I'm going to redirect progress message to stderr, but the current Ui API
makes it less clear whether the underlying streams of .write*()/.flush()/
.output_guard() are related or not.
Since stdout is wrapped with LineWriter, we need to explicitly flush the
output. Otherwise the snapshot progress would persist until newline character
is printed.
It might also be better to send progress to stderr?
If you set e.g.`ui.pager = 5`, we currently ignore that and fall back
to the default. It seems better to let the user know that their config
is invalid, as we generally do. This commit does that. With this
change, the error message will look like this:
```
Config error: Invalid `ui.pager`: data did not match any variant of untagged enum CommandNameAndArgs
```
Maybe the key name will be redundant once the `config` crate releases
a version including https://github.com/mehcode/config-rs/pull/413
(thanks, Yuya).
We need 1.64 to bump `clap` to `4.1`. We don't really need to upgrade
to that, but being on an older version causes minor confusions like
#1393. Rust 1.64 is very close to 6 months old at this point.
I'm going to add $COLUMNS override, and it should work even if ioctl() on tty
failed. This means that the return type has to be (Option<u16>, Option<u16>).
Since we don't use the row count, I decided to drop it.
It turned out bad idea because EPIPE (or SIGPIPE) is kind of a successful
termination. We could show some warning based on pager exit code, but let's
avoid messing up again.
io::Error occurred in handle_command_result() is still mapped to a BrokenPipe.
panic()-ing there should be wrong.
Without a pager configured (in `ui.pager` or `$PAGER`), running
`LC_CTYPE=foo jj log` would replace the Unicode characters in our
(Sapling's) "curved" graph style by escapes, like this:
```
@ 1d4ae2372dd2 martinvonz@google.com 2023-02-11 14:56:00.000 -08:00 a8eac1f9efe8
<E2><94><82> (no description set)
```
This fixes that by including the `LESSCHARSET=utf-8` environment
variable in our default `ui.pager` value.
This partially reverts the change in d7f64c07e0 "cli: handle last-minute
ui.write() error." In this commit, I tried to handle the case when the pager
process goes through env/sh, and exits immediately with "command not found".
However, I missed EPIPE could also occur when the pager was closed by user.
Apparently, hg is killed by SIGPIPE in that case (exits with 141), and chg
exits with 255. With this change, jj will silently exits with 3.
This works if the pager exits instantly and jj is slow enough to notice
EPIPE. If the pager exits late, no error would be reported.
Since the pager process is asynchronous, EPIPE could occur in
handle_command_result(). That's why I made it not panic.
This makes us sanitize ANSI escape bytes in the output if it goes to
the terminal, even when it's not colored (by us), such as when using
`--color=never`. That means that e.g. `jj cat
tests/test_commit_template.rs` will not be colored, but `jj cat
tests/test_commit_template.rs | cat` will be. Sanitizing output sent
to the terminal might help reduce some security threats based on
hiding content by using ANSI escapes.
We could add a config option for sanitizing the output, but I'm not
sure it'll be useful.
UserSettings will be instantiated after both user and repo configs are
loaded. We might want to add a wrapper for CLI settings, but I have no idea
how that should be structured. Let's use bare config::Config until then.
Still UserSettings is cloned to WorkspaceCommandHelper, but I think this is
slightly better since CommandHelper and WorkspaceCommandHelper are scoped
based on call stack. Perhaps, UserSettings can be shared by Arc or immutable
reference.
I'm going to remove owned UserSettings from Ui so that UserSettings can be
instantiated after both user and repo configs are loaded. ui.cwd() belongs
to the same category (random environment stuff), and Ui doesn't depend on it,
so let's remove it first from Ui.
I'm not pretty sure if CommandHelper and WorkspaceCommandHelper should be
a permanent home for cwd and settings, but it works for now as CommandHelper
is immutable.
Since ui object is needed to report read_config() error, it makes sense to
create ui first without fallible user configuration. Ui::for_terminal() will
be replaced with this function and ui.reset(read_config()?).
Default::default() is also added to silence clippy. If we prefer, Ui::new()
can be replaced with Ui::default().
I ran an upgraded Clippy on the codebase. All the changes seem to be
about using variables directly in format strings instead of passing
them as separate arguments.
As dbarnett@ reported on #9, our default of `less`, combined with our
default of enabling color on TTYs, means that we print ANSI codes to
`less` by default. Unless the user has set e.g. `$LESS=R`, `less` is
going to escape those codes, resulting in garbage like this:
```
@ ESC[1;35mbb39c26a29feESC[0m ESC[1;33m(no email configured)ESC[0m ESC[1;36m2022-12-03....
```
I guess most of us didn't notice because we have something like
`$LESS=FRX` set.
This patch changes our default from `less` to `less -FRX`. Those are
the flags we're using for our internal hg distribution at Google, and
that has seemed quite uncontroversial.
I added a pointer from the changelog to the tracking issue while at
it.
Teach Ui's writing functions to write to a pager without touching the
process's file descriptors. This is done by introducing UiOutput::Paged,
which spawns a pager that Ui's functions can write to.
The pager program can be chosen via `ui.pager`. (defaults to Defaults to
$PAGER, and 'less' if that is unset (falling back to 'less' also makes
the tests pass).
Currently, commands are paginated if:
- they have "long" output (as defined by jj developers)
- jj is invoked in a terminal
The next commit will allow pagination to be turned off via a CLI option.
More complex pagination toggling (e.g. showing a pager even if the
output doesn't look like a terminal, using a pager for shorter ouput) is
left for a future PR.
We'll add a variant that isn't a pair. Also add a function to create a
new UiOutput::Terminal, we will create this variant in a few places
because we want to fall back to it.
Let's acknowledge everyone's contributions by replacing "Google LLC"
in the copyright header by "The Jujutsu Authors". If I understand
correctly, it won't have any legal effect, but maybe it still helps
reduce concerns from contributors (though I haven't heard any
concerns).
Google employees can read about Google's policy at
go/releasing/contributions#copyright.
The `atty` crate seems unmaintained. There's
https://rustsec.org/advisories/RUSTSEC-2021-0145 filed against it,
which `cargo-deny` complains about. A fix for that has been open for
well over a year without being fixed
(https://github.com/softprops/atty/pull/51). It turns out the
functionality is also available via the `crossterm` crate (thanks,
@yuja), which we already depend on.
Since we also depend on `atty` via `clap`, I also added an exception
to the `cargo-deny` config.
Unfortunately, TOML requires quotes around the argument. So, the
usage is `jj --config-toml ui.color=\"always\"` in bash. The plan is
to eventually have a `--config` option with simpler syntax for
simple cases.
As discussed in https://github.com/martinvonz/jj/discussions/688.
This lets us write to stderr, but unlike write_error(), this won't write
with formatting. This will be used for preformatted strings, e.g. those
coming from clap.