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.
It seems a bit invasive that RepoPath constructor processes an environment
like cwd, but we need an unmodified input string to build a readable error.
The error could be rewrapped at cli boundary, but I don't think it would
worth inserting indirection just for that.
I made s/file_path/fs_path/ change because there's already to_fs_path()
function, and "file path" in RepoPath context may be ambiguous.
This patch addresses TODOs described in parse_file_path_wc_in_cwd() test.
Since the input string is considered a filesystem path, I think it makes
sense to normalize the cwd + input path first.
These utility functions will probably be moved to lib to implement file()
revset resolution.
Let the test harness suppress uninteresting output. Anyway, these tests
would print nothing.
I think Ui::with_cwd() can also be removed after refactoring file path
handling.
This should help to create a temporary ColorFormatter instantly.
A cached_colors table could also be shared across formatters, but doing that
would require some locking mechanism. Since commands like cmd_log/diff()
use a single formatter instance, I don't think shared mutable cache would be
needed for the moment.
This allows callers to instantiate long-lived formatter. ui.write() can't
be invoked while formatter is borrowed. My plan is to make Ui directly hold
output streams so the color settings can be easily reset.
ui.stdout/stderr_formatter() will create a temporary formatter there.
write_commit_summary() could be hosted by WorkspaceCommandHelper to eliminate
some of the function arguments, but that would make the source RepoRef unclear
while transaction is in progress.
I had missed that `Ui::write_commit_summary()` still shows open
commits in green even when open commits are disabled (as they are by
default these days). This patch fixes that.
The user can still override templates to format open commits
differently, but I'm not sure it's worth fixing that.
This allows us to reconfigure ui with the parsed --color option.
I tried if implementing formatter.into_output() would make sense, and it
turned out to be a bit mess as the Formatter trait doesn't know the lifetime
of the underlying output. Ui could own the formatter behind Color|Plain enum
variant in place of Box<dyn>, but that seemed to unnecessarily change the
Ui interface with little benefit.
Since we just want to reinitialize the ui at very early stage, I think
recreating the formatters is the simplest way to go.
Regarding the formatter API, I have a feeling that Ui should keep the
underlying stdout/stderr/color_map instead of the stateful formatters.
ui.stdout_formatter() will return a temporary formatter, and maybe dropping
it will automatically clear labels. This would also means the temporary
formatter could be created with stdout.lock().
ColorChoice implements FromStr so it can be a clap argument. It could
leverage the ArgEnum derive macro, but I don't think the ui is the layer
which can depend on clap.
According to the NO_COLOR FAQ, "user-level configuration files [...] should
override $NO_COLOR." https://no-color.org/
Unfortunately this makes it harder to test the $NO_COLOR behavior since the
test environment isn't attached to a tty. We could allocate a pty or
LD_PRELOAD shim to intercept isatty(), but I feel it would be too much to do.
https://github.com/assert-rs/assert_cmd/issues/138