cli: highlight "Hint: " heading

The existing .hint() method is renamed to .hint_no_heading() to clarify that
it's not the default choice to print a hint. I'll add .hint_default() later,
which will be the shorthand for .hint_with_heading("Hint: ").
This commit is contained in:
Yuya Nishihara 2024-03-24 15:05:33 +09:00
parent 894219dd77
commit 78ce9eae65
10 changed files with 55 additions and 26 deletions

View file

@ -1602,8 +1602,8 @@ pub fn print_checkout_stats(
stats.skipped_files
)?;
writeln!(
ui.hint(),
"Hint: Inspect the changes compared to the intended target with `jj diff --from {}`.
ui.hint_with_heading("Hint: "),
"Inspect the changes compared to the intended target with `jj diff --from {}`.
Discard the conflicting changes with `jj restore --from {}`.",
short_commit_hash(new_commit.id()),
short_commit_hash(new_commit.id())
@ -1629,7 +1629,7 @@ pub fn print_trackable_remote_branches(ui: &Ui, view: &View) -> io::Result<()> {
}
writeln!(
ui.hint(),
ui.hint_no_heading(),
"The following remote branches aren't associated with the existing local branches:"
)?;
let mut formatter = ui.stderr_formatter();
@ -1639,8 +1639,8 @@ pub fn print_trackable_remote_branches(ui: &Ui, view: &View) -> io::Result<()> {
}
drop(formatter);
writeln!(
ui.hint(),
"Hint: Run `jj branch track {names}` to keep local branches updated on future pulls.",
ui.hint_with_heading("Hint: "),
"Run `jj branch track {names}` to keep local branches updated on future pulls.",
names = remote_branch_names.join(" "),
)?;
Ok(())
@ -2204,11 +2204,11 @@ fn resolve_default_command(
let args = get_string_or_array(config, "ui.default-command").optional()?;
if args.is_none() {
writeln!(
ui.hint(),
"Hint: Use `jj -h` for a list of available commands."
ui.hint_with_heading("Hint: "),
"Use `jj -h` for a list of available commands."
)?;
writeln!(
ui.hint(),
ui.hint_no_heading(),
"Run `jj config set --user ui.default-command log` to disable this message."
)?;
}

View file

@ -506,7 +506,7 @@ fn try_handle_command_result(
CommandErrorKind::Config => {
print_error(ui, "Config error", err, hints)?;
writeln!(
ui.hint(),
ui.hint_no_heading(),
"For help, see https://github.com/martinvonz/jj/blob/main/docs/config.md."
)?;
Ok(ExitCode::from(1))
@ -534,7 +534,7 @@ fn print_error(ui: &Ui, prefix: &str, err: &dyn error::Error, hints: &[String])
writeln!(ui.error(), "{prefix}: {err}")?;
print_error_sources(ui, err.source())?;
for hint in hints {
writeln!(ui.hint(), "Hint: {hint}")?;
writeln!(ui.hint_with_heading("Hint: "), "{hint}")?;
}
Ok(())
}
@ -577,7 +577,7 @@ fn handle_clap_error(ui: &mut Ui, err: &clap::Error, hints: &[String]) -> io::Re
}
write!(ui.stderr(), "{clap_str}")?;
for hint in hints {
writeln!(ui.hint(), "Hint: {hint}")?;
writeln!(ui.hint_with_heading("Hint: "), "{hint}")?;
}
Ok(ExitCode::from(2))
}

View file

@ -325,10 +325,10 @@ fn cmd_branch_rename(
"Warning: Branch {old_branch} has tracking remote branches which were not renamed."
)?;
writeln!(
ui.hint(),
"Hint: to rename the branch on the remote, you can `jj git push --branch \
{old_branch}` first (to delete it on the remote), and then `jj git push --branch \
{new_branch}`. `jj git push --all` would also be sufficient."
ui.hint_with_heading("Hint: "),
"to rename the branch on the remote, you can `jj git push --branch {old_branch}` \
first (to delete it on the remote), and then `jj git push --branch {new_branch}`. \
`jj git push --all` would also be sufficient."
)?;
}

View file

@ -597,9 +597,8 @@ fn get_default_fetch_remotes(
// if nothing was explicitly configured, try to guess
if remote != DEFAULT_REMOTE {
writeln!(
ui.hint(),
"Fetching from the only existing remote: {}",
remote
ui.hint_no_heading(),
"Fetching from the only existing remote: {remote}"
)?;
}
Ok(vec![remote])
@ -1040,7 +1039,10 @@ fn get_default_push_remote(
} else if let Some(remote) = get_single_remote(git_repo)? {
// similar to get_default_fetch_remotes
if remote != DEFAULT_REMOTE {
writeln!(ui.hint(), "Pushing to the only existing remote: {}", remote)?;
writeln!(
ui.hint_no_heading(),
"Pushing to the only existing remote: {remote}"
)?;
}
Ok(remote)
} else {
@ -1058,7 +1060,7 @@ impl RejectedBranchUpdateReason {
fn print(&self, ui: &Ui) -> io::Result<()> {
writeln!(ui.warning(), "{}", self.message)?;
if let Some(hint) = &self.hint {
writeln!(ui.hint(), "Hint: {hint}")?;
writeln!(ui.hint_with_heading("Hint: "), "{hint}")?;
}
Ok(())
}

View file

@ -134,7 +134,10 @@ fn cmd_util_completion(
"Warning: `jj util completion --{shell}` will be removed in a future version, and \
this will be a hard error"
)?;
writeln!(ui.hint(), "Hint: Use `jj util completion {shell}` instead")
writeln!(
ui.hint_with_heading("Hint: "),
"Use `jj util completion {shell}` instead"
)
};
let shell = match (args.shell, args.fish, args.zsh, args.bash) {
(Some(s), false, false, false) => s,

View file

@ -2,6 +2,7 @@
"error" = "red"
"warning" = "yellow"
"hint" = "cyan"
"hint heading" = { bold = true }
"conflict_description" = "yellow"
"conflict_description difficult" = "red"

View file

@ -408,8 +408,8 @@ pub fn print_failed_git_export(
.any(|failed| matches!(failed.reason, FailedRefExportReason::FailedToSet(_)))
{
writeln!(
ui.hint(),
r#"Hint: Git doesn't allow a branch name that looks like a parent directory of
ui.hint_with_heading("Hint: "),
r#"Git doesn't allow a branch name that looks like a parent directory of
another (e.g. `foo` and `foo/bar`). Try to rename the branches that failed to
export or their "parent" branches."#,
)?;

View file

@ -124,7 +124,7 @@ fn editor_args_from_settings(
} else {
let default_editor = BUILTIN_EDITOR_NAME;
writeln!(
ui.hint(),
ui.hint_no_heading(),
"Using default editor '{default_editor}'; run `jj config set --user {key} :builtin` \
to disable this message."
)

View file

@ -23,7 +23,7 @@ use tracing::instrument;
use crate::command_error::{config_error_with_message, CommandError};
use crate::config::CommandNameAndArgs;
use crate::formatter::{Formatter, FormatterFactory, LabeledWriter};
use crate::formatter::{Formatter, FormatterFactory, HeadingLabeledWriter, LabeledWriter};
const BUILTIN_PAGER_NAME: &str = ":builtin";
@ -373,10 +373,19 @@ impl Ui {
})
}
pub fn hint(&self) -> LabeledWriter<Box<dyn Formatter + '_>, &'static str> {
/// Writer to print hint without the "Hint: " heading.
pub fn hint_no_heading(&self) -> LabeledWriter<Box<dyn Formatter + '_>, &'static str> {
LabeledWriter::new(self.stderr_formatter(), "hint")
}
/// Writer to print hint with the given heading.
pub fn hint_with_heading<H: fmt::Display>(
&self,
heading: H,
) -> HeadingLabeledWriter<Box<dyn Formatter + '_>, &'static str, H> {
HeadingLabeledWriter::new(self.stderr_formatter(), "hint", heading)
}
pub fn warning(&self) -> LabeledWriter<Box<dyn Formatter + '_>, &'static str> {
LabeledWriter::new(self.stderr_formatter(), "warning")
}

View file

@ -385,6 +385,20 @@ fn test_color_config() {
"###);
}
#[test]
fn test_color_ui_messages() {
let test_env = TestEnvironment::default();
test_env.add_config("ui.color = 'always'");
// hint and error
let stderr = test_env.jj_cmd_failure(test_env.env_root(), &["-R."]);
insta::assert_snapshot!(stderr, @r###"
Hint: Use `jj -h` for a list of available commands.
Run `jj config set --user ui.default-command log` to disable this message.
Error: There is no jj repo in "."
"###);
}
#[test]
fn test_early_args() {
// Test that help output parses early args