Mercurial > public > mercurial-scm > hg
annotate rust/rhg/src/ui.rs @ 48733:39c447e03dbc
rhg: Add support for colored output
The same "label" system is used as in Python code
Differential Revision: https://phab.mercurial-scm.org/D12167
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Thu, 10 Feb 2022 12:59:32 +0100 |
parents | f591b377375f |
children | 3e2b4bb286e7 |
rev | line source |
---|---|
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; |
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
6 use hg::errors::HgError; |
48729
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
7 use hg::utils::files::get_bytes_from_os_string; |
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; |
48176
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
9 use std::env; |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
10 use std::io; |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
11 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
|
12 |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
13 pub struct Ui { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
14 stdout: std::io::Stdout, |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
15 stderr: std::io::Stderr, |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
16 colors: Option<ColorConfig>, |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
17 } |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
18 |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
19 /// 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
|
20 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
|
21 /// 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
|
22 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
|
23 /// 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
|
24 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
|
25 } |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
26 |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
27 /// 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
|
28 impl Ui { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
29 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
|
30 Ok(Ui { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
31 // 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
|
32 stdout: std::io::stdout(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
33 |
48731
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
34 stderr: std::io::stderr(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
35 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
|
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 |
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
39 /// 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
|
40 /// |
f591b377375f
rhg: Make Ui::new falliable, add Ui::new_infallible
Simon Sapin <simon.sapin@octobus.net>
parents:
48730
diff
changeset
|
41 /// 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
|
42 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
|
43 Ui { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
44 // 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
|
45 stdout: std::io::stdout(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
46 |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
47 stderr: std::io::stderr(), |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
48 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
|
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 |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
52 /// 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
|
53 /// operations. |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
54 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
|
55 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
|
56 } |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
57 |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
58 /// 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
|
59 pub fn write_stdout(&self, bytes: &[u8]) -> Result<(), UiError> { |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
60 // Hack to silence "unused" warnings |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
61 if false { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
62 return self.write_stdout_labelled(bytes, ""); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
63 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
64 |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
65 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
|
66 |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
67 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
|
68 |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
69 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
|
70 } |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
71 |
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
72 /// 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
|
73 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
|
74 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
|
75 |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
76 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
|
77 |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
78 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
|
79 } |
48176
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
80 |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
81 /// 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
|
82 /// |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
83 /// 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
|
84 /// 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
|
85 pub fn write_stdout_labelled( |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
86 &self, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
87 bytes: &[u8], |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
88 label: &str, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
89 ) -> Result<(), UiError> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
90 if let Some(colors) = &self.colors { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
91 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
|
92 if !effects.is_empty() { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
93 return self |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
94 .write_stdout_with_effects(bytes, effects) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
95 .or_else(handle_stdout_error); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
96 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
97 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
98 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
99 self.write_stdout(bytes) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
100 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
101 |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
102 fn write_stdout_with_effects( |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
103 &self, |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
104 bytes: &[u8], |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
105 effects: &[Effect], |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
106 ) -> io::Result<()> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
107 let stdout = &mut self.stdout.lock(); |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
108 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
|
109 // `line` does not include the newline delimiter |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
110 if !first { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
111 stdout.write_all(b"\n")?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
112 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
113 if line.is_empty() { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
114 return Ok(()); |
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 /// 0x1B == 27 == 0o33 |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
117 const ASCII_ESCAPE: &[u8] = b"\x1b"; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
118 write_bytes!(stdout, b"{}[0", ASCII_ESCAPE)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
119 for effect in effects { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
120 write_bytes!(stdout, b";{}", effect)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
121 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
122 write_bytes!(stdout, b"m")?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
123 stdout.write_all(line)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
124 write_bytes!(stdout, b"{}[0m", ASCII_ESCAPE) |
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 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
|
127 if let Some(first) = lines.next() { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
128 write_line(first, true)?; |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
129 for line in lines { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
130 write_line(line, false)? |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
131 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
132 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
133 stdout.flush() |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
134 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
135 |
48513
47f2a82ae3e4
rhg: Fall back to Python if verbose status is requested by config
Simon Sapin <simon.sapin@octobus.net>
parents:
48176
diff
changeset
|
136 /// Return whether plain mode is active. |
48176
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
137 /// |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
138 /// Plain mode means that all configuration variables which affect |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
139 /// the behavior and output of Mercurial should be |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
140 /// ignored. Additionally, the output should be stable, |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
141 /// reproducible and suitable for use in scripts or applications. |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
142 /// |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
143 /// The only way to trigger plain mode is by setting either the |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
144 /// `HGPLAIN' or `HGPLAINEXCEPT' environment variables. |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
145 /// |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
146 /// The return value can either be |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
147 /// - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
148 /// - False if feature is disabled by default and not included in HGPLAIN |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
149 /// - True otherwise |
48729
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
150 pub fn plain(&self, feature: Option<&str>) -> bool { |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
151 plain(feature) |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
152 } |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
153 } |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
154 |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
155 pub fn plain(opt_feature: Option<&str>) -> bool { |
48729
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
156 if let Some(except) = env::var_os("HGPLAINEXCEPT") { |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
157 opt_feature.map_or(true, |feature| { |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
158 get_bytes_from_os_string(except) |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
159 .split(|&byte| byte == b',') |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
160 .all(|exception| exception != feature.as_bytes()) |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
161 }) |
99b1dfc06571
rhg: Add support for HGPLAINEXPECT
Simon Sapin <simon.sapin@octobus.net>
parents:
48513
diff
changeset
|
162 } else { |
48176
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
163 env::var_os("HGPLAIN").is_some() |
38deb65d4441
rhg: add ui.plain() and check it before showing relative paths in status
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46591
diff
changeset
|
164 } |
45049
513b3ef277a3
rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
165 } |
45362
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
166 |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
167 /// 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
|
168 pub struct StdoutBuffer<W: Write> { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
169 buf: io::BufWriter<W>, |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
170 } |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
171 |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
172 impl<W: Write> StdoutBuffer<W> { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
173 pub fn new(writer: W) -> Self { |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
174 let buf = io::BufWriter::new(writer); |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
175 Self { buf } |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
176 } |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
177 |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
178 /// Write bytes to stdout buffer |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
179 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
|
180 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
|
181 } |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
182 |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
183 /// Flush bytes to stdout |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
184 pub fn flush(&mut self) -> Result<(), UiError> { |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
185 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
|
186 } |
eb55274d3650
rhg: add buffered stdout writing possibility
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45049
diff
changeset
|
187 } |
45366
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
188 |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
189 /// 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
|
190 /// signal that failure, otherwise just bail. |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
191 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
|
192 if let ErrorKind::BrokenPipe = error.kind() { |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
193 // This makes `| head` work for example |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
194 return Ok(()); |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
195 } |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
196 let mut stderr = io::stderr(); |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
197 |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
198 stderr |
45984
fada33872b5b
rhg: use `format_bytes!` for error messages
Rapha?l Gom?s <rgomes@octobus.net>
parents:
45528
diff
changeset
|
199 .write_all(&format_bytes!( |
fada33872b5b
rhg: use `format_bytes!` for error messages
Rapha?l Gom?s <rgomes@octobus.net>
parents:
45528
diff
changeset
|
200 b"abort: {}\n", |
fada33872b5b
rhg: use `format_bytes!` for error messages
Rapha?l Gom?s <rgomes@octobus.net>
parents:
45528
diff
changeset
|
201 error.to_string().as_bytes() |
fada33872b5b
rhg: use `format_bytes!` for error messages
Rapha?l Gom?s <rgomes@octobus.net>
parents:
45528
diff
changeset
|
202 )) |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
203 .map_err(UiError::StderrError)?; |
45366
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
204 |
45439
fbc373b7cbc3
rhg: fix `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45367
diff
changeset
|
205 stderr.flush().map_err(UiError::StderrError)?; |
45366
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
206 |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
207 Err(UiError::StdoutError(error)) |
10c36ead86f8
rhg: extract function handle_stdout_error
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45362
diff
changeset
|
208 } |
45367
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
209 |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
210 /// 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
|
211 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
|
212 // 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
|
213 // like with `| head` for example |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
214 if let ErrorKind::BrokenPipe = error.kind() { |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
215 return Ok(()); |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
216 } |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
217 Err(UiError::StdoutError(error)) |
53af26aa5951
rhg: handle broken pipe error for stderr
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45366
diff
changeset
|
218 } |
45528
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
219 |
66756b34c06e
rhg: add a `DebugData` `Command` to prepare the `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45440
diff
changeset
|
220 /// 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
|
221 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
|
222 // 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
|
223 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
|
224 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
|
225 } |
48733
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
226 |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
227 /// Should formatted output be used? |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
228 /// |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
229 /// 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
|
230 /// 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
|
231 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
|
232 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
|
233 Ok(formatted) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
234 } else { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
235 isatty(config) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
236 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
237 } |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
238 |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
239 fn isatty(config: &Config) -> Result<bool, HgError> { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
240 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
|
241 false |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
242 } else { |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
243 atty::is(atty::Stream::Stdout) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
244 }) |
39c447e03dbc
rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents:
48731
diff
changeset
|
245 } |