rust/rhg/src/ui.rs
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--
find-delta: pass the cache-delta usage policy alongside the cache-delta The idea is to give higher level code more control to what will happens with the cache delta passed. This should help with controling how we treat delta's from different sources. The final goal of this change is to allow for server modes where the client can blindly accept any server delta without regards to any local constraints. This will be implemented in later changesets.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
}