author | Pierre-Yves David <pierre-yves.david@octobus.net> |
Mon, 07 Nov 2022 22:12:59 -0500 | |
changeset 49677 | 05db41701ece |
parent 49513 | 467d9df98c68 |
child 49981 | 364e78389653 |
permissions | -rw-r--r-- |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
1 |
use crate::color::ColorConfig; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
2 |
use crate::color::Effect; |
45984
fada33872b5b
rhg: use `format_bytes!` for error messages
Raphaël Gomès <rgomes@octobus.net>
parents:
45528
diff
changeset
|
3 |
use format_bytes::format_bytes; |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
4 |
use format_bytes::write_bytes; |
48730
1aaf11e35aec
rhg: Pass a &Config to Ui::new
Simon Sapin <simon.sapin@octobus.net>
parents:
48729
diff
changeset
|
5 |
use hg::config::Config; |
49513
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
6 |
use hg::config::PlainInfo; |
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
7 |
use hg::errors::HgError; |
45528
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
8 |
use std::borrow::Cow; |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
9 |
use std::io; |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
10 |
use std::io::{ErrorKind, Write}; |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
11 |
|
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
12 |
pub struct Ui { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
13 |
stdout: std::io::Stdout, |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
14 |
stderr: std::io::Stderr, |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
15 |
colors: Option<ColorConfig>, |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
16 |
} |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
17 |
|
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
18 |
/// The kind of user interface error |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
19 |
pub enum UiError { |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
20 |
/// The standard output stream cannot be written to |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
21 |
StdoutError(io::Error), |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
22 |
/// The standard error stream cannot be written to |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
23 |
StderrError(io::Error), |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
24 |
} |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
25 |
|
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
26 |
/// The commandline user interface |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
27 |
impl Ui { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
28 |
pub fn new(config: &Config) -> Result<Self, HgError> { |
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
29 |
Ok(Ui { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
30 |
// If using something else, also adapt `isatty()` below. |
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
31 |
stdout: std::io::stdout(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
32 |
|
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
33 |
stderr: std::io::stderr(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
34 |
colors: ColorConfig::new(config)?, |
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
35 |
}) |
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
36 |
} |
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
37 |
|
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
38 |
/// Default to no color if color configuration errors. |
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
39 |
/// |
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
40 |
/// Useful when we’re already handling another error. |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
41 |
pub fn new_infallible(config: &Config) -> Self { |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
42 |
Ui { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
43 |
// If using something else, also adapt `isatty()` below. |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
44 |
stdout: std::io::stdout(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
45 |
|
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
46 |
stderr: std::io::stderr(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
47 |
colors: ColorConfig::new(config).unwrap_or(None), |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
48 |
} |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
49 |
} |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
50 |
|
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
51 |
/// Returns a buffered handle on stdout for faster batch printing |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
52 |
/// operations. |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
53 |
pub fn stdout_buffer(&self) -> StdoutBuffer<std::io::StdoutLock> { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
54 |
StdoutBuffer::new(self.stdout.lock()) |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
55 |
} |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
56 |
|
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
57 |
/// Write bytes to stdout |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
58 |
pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> { |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
59 |
let mut stdout = self.stdout.lock(); |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
60 |
|
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
61 |
stdout.write_all(bytes).or_else(handle_stdout_error)?; |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
62 |
|
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
63 |
stdout.flush().or_else(handle_stdout_error) |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
64 |
} |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
65 |
|
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
66 |
/// Write bytes to stderr |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
67 |
pub fn write_stderr(&self, bytes: &[u8]) -> Result<(), UiError> { |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
68 |
let mut stderr = self.stderr.lock(); |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
69 |
|
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
70 |
stderr.write_all(bytes).or_else(handle_stderr_error)?; |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
71 |
|
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
72 |
stderr.flush().or_else(handle_stderr_error) |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
73 |
} |
48176
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
74 |
|
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
75 |
/// Write bytes to stdout with the given label |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
76 |
/// |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
77 |
/// Like the optional `label` parameter in `mercurial/ui.py`, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
78 |
/// this label influences the color used for this output. |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
79 |
pub fn write_stdout_labelled( |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
80 |
&self, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
81 |
bytes: &[u8], |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
82 |
label: &str, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
83 |
) -> Result<(), UiError> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
84 |
if let Some(colors) = &self.colors { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
85 |
if let Some(effects) = colors.styles.get(label.as_bytes()) { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
86 |
if !effects.is_empty() { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
87 |
return self |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
88 |
.write_stdout_with_effects(bytes, effects) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
89 |
.or_else(handle_stdout_error); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
90 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
91 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
92 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
93 |
self.write_stdout(bytes) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
94 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
95 |
|
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
96 |
fn write_stdout_with_effects( |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
97 |
&self, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
98 |
bytes: &[u8], |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
99 |
effects: &[Effect], |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
100 |
) -> io::Result<()> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
101 |
let stdout = &mut self.stdout.lock(); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
102 |
let mut write_line = |line: &[u8], first: bool| { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
103 |
// `line` does not include the newline delimiter |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
104 |
if !first { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
105 |
stdout.write_all(b"\n")?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
106 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
107 |
if line.is_empty() { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
108 |
return Ok(()); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
109 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
110 |
/// 0x1B == 27 == 0o33 |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
111 |
const ASCII_ESCAPE: &[u8] = b"\x1b"; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
112 |
write_bytes!(stdout, b"{}[0", ASCII_ESCAPE)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
113 |
for effect in effects { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
114 |
write_bytes!(stdout, b";{}", effect)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
115 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
116 |
write_bytes!(stdout, b"m")?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
117 |
stdout.write_all(line)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
118 |
write_bytes!(stdout, b"{}[0m", ASCII_ESCAPE) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
119 |
}; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
120 |
let mut lines = bytes.split(|&byte| byte == b'\n'); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
121 |
if let Some(first) = lines.next() { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
122 |
write_line(first, true)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
123 |
for line in lines { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
124 |
write_line(line, false)? |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
125 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
126 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
127 |
stdout.flush() |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
128 |
} |
48729
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
129 |
} |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
130 |
|
49513
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
131 |
// TODO: pass the PlainInfo to call sites directly and |
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
132 |
// delete this function |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
133 |
pub fn plain(opt_feature: Option<&str>) -> bool { |
49513
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
134 |
let plain_info = PlainInfo::from_env(); |
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
135 |
match opt_feature { |
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
136 |
None => plain_info.is_plain(), |
467d9df98c68
rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49512
diff
changeset
|
137 |
Some(feature) => plain_info.is_feature_plain(feature), |
48176
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
138 |
} |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
139 |
} |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
140 |
|
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
141 |
/// A buffered stdout writer for faster batch printing operations. |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
142 |
pub struct StdoutBuffer<W: Write> { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
143 |
buf: io::BufWriter<W>, |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
144 |
} |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
145 |
|
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
146 |
impl<W: Write> StdoutBuffer<W> { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
147 |
pub fn new(writer: W) -> Self { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
148 |
let buf = io::BufWriter::new(writer); |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
149 |
Self { buf } |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
150 |
} |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
151 |
|
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
152 |
/// Write bytes to stdout buffer |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
153 |
pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), UiError> { |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
154 |
self.buf.write_all(bytes).or_else(handle_stdout_error) |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
155 |
} |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
156 |
|
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
157 |
/// Flush bytes to stdout |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
158 |
pub fn flush(&mut self) -> Result<(), UiError> { |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
159 |
self.buf.flush().or_else(handle_stdout_error) |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
160 |
} |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
161 |
} |
45366
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
162 |
|
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
163 |
/// Sometimes writing to stdout is not possible, try writing to stderr to |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
164 |
/// signal that failure, otherwise just bail. |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
165 |
fn handle_stdout_error(error: io::Error) -> Result<(), UiError> { |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
166 |
if let ErrorKind::BrokenPipe = error.kind() { |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
167 |
// This makes `| head` work for example |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
168 |
return Ok(()); |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
169 |
} |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
170 |
let mut stderr = io::stderr(); |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
171 |
|
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
172 |
stderr |
45984
fada33872b5b
rhg: use `format_bytes!` for error messages
Raphaël Gomès <rgomes@octobus.net>
parents:
45528
diff
changeset
|
173 |
.write_all(&format_bytes!( |
fada33872b5b
rhg: use `format_bytes!` for error messages
Raphaël Gomès <rgomes@octobus.net>
parents:
45528
diff
changeset
|
174 |
b"abort: {}\n", |
fada33872b5b
rhg: use `format_bytes!` for error messages
Raphaël Gomès <rgomes@octobus.net>
parents:
45528
diff
changeset
|
175 |
error.to_string().as_bytes() |
fada33872b5b
rhg: use `format_bytes!` for error messages
Raphaël Gomès <rgomes@octobus.net>
parents:
45528
diff
changeset
|
176 |
)) |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
177 |
.map_err(UiError::StderrError)?; |
45366
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
178 |
|
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
179 |
stderr.flush().map_err(UiError::StderrError)?; |
45366
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
180 |
|
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
181 |
Err(UiError::StdoutError(error)) |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
182 |
} |
45367
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
183 |
|
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
184 |
/// Sometimes writing to stderr is not possible. |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
185 |
fn handle_stderr_error(error: io::Error) -> Result<(), UiError> { |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
186 |
// A broken pipe should not result in a error |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
187 |
// like with `| head` for example |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
188 |
if let ErrorKind::BrokenPipe = error.kind() { |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
189 |
return Ok(()); |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
190 |
} |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
191 |
Err(UiError::StdoutError(error)) |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
192 |
} |
45528
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
193 |
|
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
194 |
/// Encode rust strings according to the user system. |
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
195 |
pub fn utf8_to_local(s: &str) -> Cow<[u8]> { |
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
196 |
// TODO encode for the user's system // |
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
197 |
let bytes = s.as_bytes(); |
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
198 |
Cow::Borrowed(bytes) |
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
199 |
} |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
200 |
|
48770
f19be290756a
rhg: signal when falling back in logs
Raphaël Gomès <rgomes@octobus.net>
parents:
48734
diff
changeset
|
201 |
/// Decode user system bytes to Rust string. |
f19be290756a
rhg: signal when falling back in logs
Raphaël Gomès <rgomes@octobus.net>
parents:
48734
diff
changeset
|
202 |
pub fn local_to_utf8(s: &[u8]) -> Cow<str> { |
f19be290756a
rhg: signal when falling back in logs
Raphaël Gomès <rgomes@octobus.net>
parents:
48734
diff
changeset
|
203 |
// TODO decode from the user's system |
f19be290756a
rhg: signal when falling back in logs
Raphaël Gomès <rgomes@octobus.net>
parents:
48734
diff
changeset
|
204 |
String::from_utf8_lossy(s) |
f19be290756a
rhg: signal when falling back in logs
Raphaël Gomès <rgomes@octobus.net>
parents:
48734
diff
changeset
|
205 |
} |
f19be290756a
rhg: signal when falling back in logs
Raphaël Gomès <rgomes@octobus.net>
parents:
48734
diff
changeset
|
206 |
|
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
207 |
/// Should formatted output be used? |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
208 |
/// |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
209 |
/// Note: rhg does not have the formatter mechanism yet, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
210 |
/// but this is also used when deciding whether to use color. |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
211 |
pub fn formatted(config: &Config) -> Result<bool, HgError> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
212 |
if let Some(formatted) = config.get_option(b"ui", b"formatted")? { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
213 |
Ok(formatted) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
214 |
} else { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
215 |
isatty(config) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
216 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
217 |
} |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
218 |
|
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
219 |
fn isatty(config: &Config) -> Result<bool, HgError> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
220 |
Ok(if config.get_bool(b"ui", b"nontty")? { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
221 |
false |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
222 |
} else { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
223 |
atty::is(atty::Stream::Stdout) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
224 |
}) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
225 |
} |