Auto merge of #23206 - nagisa:print-io, r=alexcrichton
r? @alexcrichton or @aturon This still needs to somehow figure out how to avoid unstable warnings arising from the use of unstable functions. I tried to use `#[allow_internal_unstable]` but it still spits out warnings as far as I can see. @huonw (I think you implemented it) does `#[allow_internal_unstable]` not work for some reason or am I using it incorrectly?
This commit is contained in:
commit
c62ae87db2
8 changed files with 62 additions and 57 deletions
|
@ -37,7 +37,7 @@
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(exit_status)]
|
#![feature(exit_status)]
|
||||||
#![feature(io)]
|
#![feature(io)]
|
||||||
#![feature(set_panic)]
|
#![feature(set_stdio)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate flate;
|
extern crate flate;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
#![feature(exit_status)]
|
#![feature(exit_status)]
|
||||||
#![feature(int_uint)]
|
#![feature(int_uint)]
|
||||||
#![feature(set_panic)]
|
#![feature(set_stdio)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(old_path)]
|
#![feature(old_path)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
|
|
@ -33,10 +33,10 @@ pub use self::buffered::IntoInnerError;
|
||||||
pub use self::cursor::Cursor;
|
pub use self::cursor::Cursor;
|
||||||
pub use self::error::{Result, Error, ErrorKind};
|
pub use self::error::{Result, Error, ErrorKind};
|
||||||
pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat};
|
pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat};
|
||||||
pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr};
|
pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr};
|
||||||
pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
|
pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
|
||||||
#[doc(no_inline, hidden)]
|
#[doc(no_inline, hidden)]
|
||||||
pub use self::stdio::set_panic;
|
pub use self::stdio::{set_panic, set_print};
|
||||||
|
|
||||||
#[macro_use] mod lazy;
|
#[macro_use] mod lazy;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use prelude::v1::*;
|
use prelude::v1::*;
|
||||||
use io::prelude::*;
|
use io::prelude::*;
|
||||||
|
|
||||||
|
use cell::RefCell;
|
||||||
use cmp;
|
use cmp;
|
||||||
use fmt;
|
use fmt;
|
||||||
use io::lazy::Lazy;
|
use io::lazy::Lazy;
|
||||||
|
@ -18,6 +19,13 @@ use io::{self, BufReader, LineWriter};
|
||||||
use sync::{Arc, Mutex, MutexGuard};
|
use sync::{Arc, Mutex, MutexGuard};
|
||||||
use sys::stdio;
|
use sys::stdio;
|
||||||
|
|
||||||
|
/// Stdout used by print! and println! macroses
|
||||||
|
thread_local! {
|
||||||
|
static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
|
||||||
|
RefCell::new(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A handle to a raw instance of the standard input stream of this process.
|
/// A handle to a raw instance of the standard input stream of this process.
|
||||||
///
|
///
|
||||||
/// This handle is not synchronized or buffered in any fashion. Constructed via
|
/// This handle is not synchronized or buffered in any fashion. Constructed via
|
||||||
|
@ -338,15 +346,15 @@ impl<'a> Write for StderrLock<'a> {
|
||||||
fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
|
fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets the task-local stdout handle to the specified writer
|
/// Resets the task-local stderr handle to the specified writer
|
||||||
///
|
///
|
||||||
/// This will replace the current task's stdout handle, returning the old
|
/// This will replace the current task's stderr handle, returning the old
|
||||||
/// handle. All future calls to `print` and friends will emit their output to
|
/// handle. All future calls to `panic!` and friends will emit their output to
|
||||||
/// this specified handle.
|
/// this specified handle.
|
||||||
///
|
///
|
||||||
/// Note that this does not need to be called for all new tasks; the default
|
/// Note that this does not need to be called for all new tasks; the default
|
||||||
/// output handle is to the process's stdout stream.
|
/// output handle is to the process's stderr stream.
|
||||||
#[unstable(feature = "set_panic",
|
#[unstable(feature = "set_stdio",
|
||||||
reason = "this function may disappear completely or be replaced \
|
reason = "this function may disappear completely or be replaced \
|
||||||
with a more general mechanism")]
|
with a more general mechanism")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -360,3 +368,37 @@ pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
|
||||||
Some(s)
|
Some(s)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resets the task-local stdout handle to the specified writer
|
||||||
|
///
|
||||||
|
/// This will replace the current task's stdout handle, returning the old
|
||||||
|
/// handle. All future calls to `print!` and friends will emit their output to
|
||||||
|
/// this specified handle.
|
||||||
|
///
|
||||||
|
/// Note that this does not need to be called for all new tasks; the default
|
||||||
|
/// output handle is to the process's stdout stream.
|
||||||
|
#[unstable(feature = "set_stdio",
|
||||||
|
reason = "this function may disappear completely or be replaced \
|
||||||
|
with a more general mechanism")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
|
||||||
|
use mem;
|
||||||
|
LOCAL_STDOUT.with(move |slot| {
|
||||||
|
mem::replace(&mut *slot.borrow_mut(), Some(sink))
|
||||||
|
}).and_then(|mut s| {
|
||||||
|
let _ = s.flush();
|
||||||
|
Some(s)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "print",
|
||||||
|
reason = "implementation detail which may disappear or be replaced at any time")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn _print(args: fmt::Arguments) {
|
||||||
|
if let Err(e) = LOCAL_STDOUT.with(|s| match s.borrow_mut().as_mut() {
|
||||||
|
Some(w) => w.write_fmt(args),
|
||||||
|
None => stdout().write_fmt(args)
|
||||||
|
}) {
|
||||||
|
panic!("failed printing to stdout: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -60,19 +60,21 @@ macro_rules! panic {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro for printing to the standard output.
|
||||||
|
///
|
||||||
/// Equivalent to the `println!` macro except that a newline is not printed at
|
/// Equivalent to the `println!` macro except that a newline is not printed at
|
||||||
/// the end of the message.
|
/// the end of the message.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[allow_internal_unstable]
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
($($arg:tt)*) => ($crate::old_io::stdio::print_args(format_args!($($arg)*)))
|
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro for printing to a task's stdout handle.
|
/// Macro for printing to the standard output.
|
||||||
///
|
///
|
||||||
/// Each task can override its stdout handle via `std::old_io::stdio::set_stdout`.
|
/// Use the `format!` syntax to write data to the standard output.
|
||||||
/// The syntax of this macro is the same as that used for `format!`. For more
|
/// See `std::fmt` for more information.
|
||||||
/// information, see `std::fmt` and `std::old_io::stdio`.
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -83,7 +85,8 @@ macro_rules! print {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
macro_rules! println {
|
macro_rules! println {
|
||||||
($($arg:tt)*) => ($crate::old_io::stdio::println_args(format_args!($($arg)*)))
|
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||||
|
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper macro for unwrapping `Result` values while returning early with an
|
/// Helper macro for unwrapping `Result` values while returning early with an
|
||||||
|
|
|
@ -535,18 +535,4 @@ mod tests {
|
||||||
stdout();
|
stdout();
|
||||||
stderr();
|
stderr();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn capture_stdout() {
|
|
||||||
use old_io::{ChanReader, ChanWriter};
|
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
|
||||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
|
||||||
let _t = thread::spawn(move|| {
|
|
||||||
set_stdout(Box::new(w));
|
|
||||||
println!("hello!");
|
|
||||||
});
|
|
||||||
assert_eq!(r.read_to_string().unwrap(), "hello!\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,12 @@
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
#![feature(int_uint)]
|
#![feature(int_uint)]
|
||||||
#![feature(old_io)]
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(std_misc)]
|
#![feature(std_misc)]
|
||||||
#![feature(io)]
|
#![feature(io)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(set_panic)]
|
#![feature(set_stdio)]
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
@ -908,7 +907,6 @@ pub fn run_test(opts: &TestOpts,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)] // set_stdout
|
|
||||||
fn run_test_inner(desc: TestDesc,
|
fn run_test_inner(desc: TestDesc,
|
||||||
monitor_ch: Sender<MonitorMsg>,
|
monitor_ch: Sender<MonitorMsg>,
|
||||||
nocapture: bool,
|
nocapture: bool,
|
||||||
|
@ -920,11 +918,6 @@ pub fn run_test(opts: &TestOpts,
|
||||||
}
|
}
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||||
}
|
}
|
||||||
impl Writer for Sink {
|
|
||||||
fn write_all(&mut self, data: &[u8]) -> std::old_io::IoResult<()> {
|
|
||||||
Writer::write_all(&mut *self.0.lock().unwrap(), data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let data = Arc::new(Mutex::new(Vec::new()));
|
let data = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
@ -936,7 +929,7 @@ pub fn run_test(opts: &TestOpts,
|
||||||
|
|
||||||
let result_guard = cfg.spawn(move || {
|
let result_guard = cfg.spawn(move || {
|
||||||
if !nocapture {
|
if !nocapture {
|
||||||
std::old_io::stdio::set_stdout(box Sink(data2.clone()));
|
io::set_print(box Sink(data2.clone()));
|
||||||
io::set_panic(box Sink(data2));
|
io::set_panic(box Sink(data2));
|
||||||
}
|
}
|
||||||
testfn.invoke(())
|
testfn.invoke(())
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::cmp::Ordering::{self, Less, Greater, Equal};
|
use std::cmp::Ordering::{self, Less, Greater, Equal};
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
|
||||||
use std::collections::hash_map;
|
|
||||||
use std::hash::Hash;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::num::{Float, FromPrimitive};
|
use std::num::{Float, FromPrimitive};
|
||||||
|
|
||||||
|
@ -330,22 +327,6 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a HashMap with the number of occurrences of every element in the
|
|
||||||
/// sequence that the iterator exposes.
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint>
|
|
||||||
where T: Iterator<Item=U>, U: Eq + Clone + Hash
|
|
||||||
{
|
|
||||||
let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
|
|
||||||
for elem in iter {
|
|
||||||
match map.entry(elem) {
|
|
||||||
Occupied(mut entry) => { *entry.get_mut() += 1; },
|
|
||||||
Vacant(entry) => { entry.insert(1); },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
map
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
|
// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue