##// END OF EJS Templates
rhg: extract function handle_stdout_error...
Antoine Cezar -
r45925:10c36ead default
parent child Browse files
Show More
@@ -1,109 +1,96 b''
1 1 use std::io;
2 2 use std::io::{ErrorKind, Write};
3 3
4 4 #[derive(Debug)]
5 5 pub struct Ui {
6 6 stdout: std::io::Stdout,
7 7 stderr: std::io::Stderr,
8 8 }
9 9
10 10 /// The kind of user interface error
11 11 pub enum UiError {
12 12 /// The standard output stream cannot be written to
13 13 StdoutError(io::Error),
14 14 /// The standard error stream cannot be written to
15 15 StderrError(io::Error),
16 16 }
17 17
18 18 /// The commandline user interface
19 19 impl Ui {
20 20 pub fn new() -> Self {
21 21 Ui {
22 22 stdout: std::io::stdout(),
23 23 stderr: std::io::stderr(),
24 24 }
25 25 }
26 26
27 27 /// Returns a buffered handle on stdout for faster batch printing
28 28 /// operations.
29 29 pub fn stdout_buffer(&self) -> StdoutBuffer<std::io::StdoutLock> {
30 30 StdoutBuffer::new(self.stdout.lock())
31 31 }
32 32
33 33 /// Write bytes to stdout
34 34 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> {
35 35 let mut stdout = self.stdout.lock();
36 36
37 self.write_stream(&mut stdout, bytes)
38 .or_else(|e| self.handle_stdout_error(e))?;
39
40 stdout.flush().or_else(|e| self.handle_stdout_error(e))
41 }
37 stdout
38 .write_all(bytes)
39 .or_else(|e| handle_stdout_error(e))?;
42 40
43 /// Sometimes writing to stdout is not possible, try writing to stderr to
44 /// signal that failure, otherwise just bail.
45 fn handle_stdout_error(&self, error: io::Error) -> Result<(), UiError> {
46 self.write_stderr(
47 &[b"abort: ", error.to_string().as_bytes(), b"\n"].concat(),
48 )?;
49 Err(UiError::StdoutError(error))
41 stdout.flush().or_else(|e| handle_stdout_error(e))
50 42 }
51 43
52 44 /// Write bytes to stderr
53 45 pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> {
54 46 let mut stderr = self.stderr.lock();
55 47
56 self.write_stream(&mut stderr, bytes)
57 .or_else(|e| Err(UiError::StderrError(e)))?;
48 stderr
49 .write_all(bytes)
50 .or_else(|e| handle_stderr_error(e))?;
58 51
59 52 stderr.flush().or_else(|e| Err(UiError::StderrError(e)))
60 53 }
61
62 fn write_stream(
63 &self,
64 stream: &mut impl Write,
65 bytes: &[u8],
66 ) -> Result<(), io::Error> {
67 stream.write_all(bytes)
68 }
69 54 }
70 55
71 56 /// A buffered stdout writer for faster batch printing operations.
72 57 pub struct StdoutBuffer<W: Write> {
73 58 buf: io::BufWriter<W>,
74 59 }
75 60
76 61 impl<W: Write> StdoutBuffer<W> {
77 62 pub fn new(writer: W) -> Self {
78 63 let buf = io::BufWriter::new(writer);
79 64 Self { buf }
80 65 }
81 66
82 67 /// Write bytes to stdout buffer
83 68 pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), UiError> {
84 self.buf.write_all(bytes).or_else(|e| self.io_err(e))
69 self.buf
70 .write_all(bytes)
71 .or_else(|e| handle_stdout_error(e))
85 72 }
86 73
87 74 /// Flush bytes to stdout
88 75 pub fn flush(&mut self) -> Result<(), UiError> {
89 self.buf.flush().or_else(|e| self.io_err(e))
76 self.buf.flush().or_else(|e| handle_stdout_error(e))
77 }
90 78 }
91 79
92 fn io_err(&self, error: io::Error) -> Result<(), UiError> {
80 /// Sometimes writing to stdout is not possible, try writing to stderr to
81 /// signal that failure, otherwise just bail.
82 fn handle_stdout_error(error: io::Error) -> Result<(), UiError> {
93 83 if let ErrorKind::BrokenPipe = error.kind() {
94 84 // This makes `| head` work for example
95 85 return Ok(());
96 86 }
97 87 let mut stderr = io::stderr();
98 88
99 89 stderr
100 .write_all(
101 &[b"abort: ", error.to_string().as_bytes(), b"\n"].concat(),
102 )
90 .write_all(&[b"abort: ", error.to_string().as_bytes(), b"\n"].concat())
103 91 .map_err(|e| UiError::StderrError(e))?;
104 92
105 93 stderr.flush().map_err(|e| UiError::StderrError(e))?;
106 94
107 95 Err(UiError::StdoutError(error))
108 96 }
109 }
General Comments 0
You need to be logged in to leave comments. Login now