mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-07 21:26:58 +00:00
cli: render string pattern suggestion as a hint
Templater doesn't have the one yet, but I think it belongs to the same category. For clap::Error, we could use clap's own mechanism to render suggestions as "tip: ...", but I feel "Hint: ..." looks better because our error/hint message is capitalized.
This commit is contained in:
parent
d759ba11f1
commit
a6615bf36d
4 changed files with 33 additions and 4 deletions
|
@ -30,6 +30,7 @@ use jj_lib::revset::{
|
||||||
RevsetEvaluationError, RevsetParseError, RevsetParseErrorKind, RevsetResolutionError,
|
RevsetEvaluationError, RevsetParseError, RevsetParseErrorKind, RevsetResolutionError,
|
||||||
};
|
};
|
||||||
use jj_lib::signing::SignInitError;
|
use jj_lib::signing::SignInitError;
|
||||||
|
use jj_lib::str_util::StringPatternParseError;
|
||||||
use jj_lib::working_copy::{ResetError, SnapshotError, WorkingCopyStateError};
|
use jj_lib::working_copy::{ResetError, SnapshotError, WorkingCopyStateError};
|
||||||
use jj_lib::workspace::WorkspaceInitError;
|
use jj_lib::workspace::WorkspaceInitError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -423,6 +424,9 @@ impl From<RevsetParseError> for CommandError {
|
||||||
name: _,
|
name: _,
|
||||||
candidates,
|
candidates,
|
||||||
} => format_similarity_hint(candidates),
|
} => format_similarity_hint(candidates),
|
||||||
|
RevsetParseErrorKind::InvalidFunctionArguments { .. } => {
|
||||||
|
find_source_parse_error_hint(bottom_err)
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let mut cmd_err =
|
let mut cmd_err =
|
||||||
|
@ -470,6 +474,8 @@ impl From<TemplateParseError> for CommandError {
|
||||||
| TemplateParseErrorKind::NoSuchMethod { candidates, .. } => {
|
| TemplateParseErrorKind::NoSuchMethod { candidates, .. } => {
|
||||||
format_similarity_hint(candidates)
|
format_similarity_hint(candidates)
|
||||||
}
|
}
|
||||||
|
TemplateParseErrorKind::InvalidArguments { .. }
|
||||||
|
| TemplateParseErrorKind::Expression(_) => find_source_parse_error_hint(bottom_err),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let mut cmd_err =
|
let mut cmd_err =
|
||||||
|
@ -489,7 +495,10 @@ impl From<FsPathParseError> for CommandError {
|
||||||
|
|
||||||
impl From<clap::Error> for CommandError {
|
impl From<clap::Error> for CommandError {
|
||||||
fn from(err: clap::Error) -> Self {
|
fn from(err: clap::Error) -> Self {
|
||||||
cli_error(err)
|
let hint = find_source_parse_error_hint(&err);
|
||||||
|
let mut cmd_err = cli_error(err);
|
||||||
|
cmd_err.extend_hints(hint);
|
||||||
|
cmd_err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,6 +520,24 @@ impl From<GitIgnoreError> for CommandError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_source_parse_error_hint(err: &dyn error::Error) -> Option<String> {
|
||||||
|
let source = err.source()?;
|
||||||
|
if let Some(source) = source.downcast_ref() {
|
||||||
|
string_pattern_parse_error_hint(source)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_pattern_parse_error_hint(err: &StringPatternParseError) -> Option<String> {
|
||||||
|
match err {
|
||||||
|
StringPatternParseError::InvalidKind(_) => {
|
||||||
|
Some("Try prefixing with one of `exact:`, `glob:` or `substring:`".into())
|
||||||
|
}
|
||||||
|
StringPatternParseError::GlobPattern(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const BROKEN_PIPE_EXIT_CODE: u8 = 3;
|
const BROKEN_PIPE_EXIT_CODE: u8 = 3;
|
||||||
|
|
||||||
pub(crate) fn handle_command_result(ui: &mut Ui, result: Result<(), CommandError>) -> ExitCode {
|
pub(crate) fn handle_command_result(ui: &mut Ui, result: Result<(), CommandError>) -> ExitCode {
|
||||||
|
|
|
@ -396,9 +396,10 @@ fn test_branch_delete_glob() {
|
||||||
// Unknown pattern kind
|
// Unknown pattern kind
|
||||||
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["branch", "forget", "whatever:branch"]);
|
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["branch", "forget", "whatever:branch"]);
|
||||||
insta::assert_snapshot!(stderr, @r###"
|
insta::assert_snapshot!(stderr, @r###"
|
||||||
error: invalid value 'whatever:branch' for '[NAMES]...': Invalid string pattern kind "whatever:", try prefixing with one of `exact:`, `glob:` or `substring:`
|
error: invalid value 'whatever:branch' for '[NAMES]...': Invalid string pattern kind "whatever:"
|
||||||
|
|
||||||
For more information, try '--help'.
|
For more information, try '--help'.
|
||||||
|
Hint: Try prefixing with one of `exact:`, `glob:` or `substring:`
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,8 @@ fn test_bad_function_call() {
|
||||||
| ^---------^
|
| ^---------^
|
||||||
|
|
|
|
||||||
= Function "branches": Invalid string pattern
|
= Function "branches": Invalid string pattern
|
||||||
2: Invalid string pattern kind "bad:", try prefixing with one of `exact:`, `glob:` or `substring:`
|
2: Invalid string pattern kind "bad:"
|
||||||
|
Hint: Try prefixing with one of `exact:`, `glob:` or `substring:`
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "root()::whatever()"]);
|
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "root()::whatever()"]);
|
||||||
|
|
|
@ -25,7 +25,7 @@ use thiserror::Error;
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum StringPatternParseError {
|
pub enum StringPatternParseError {
|
||||||
/// Unknown pattern kind is specified.
|
/// Unknown pattern kind is specified.
|
||||||
#[error(r#"Invalid string pattern kind "{0}:", try prefixing with one of `exact:`, `glob:` or `substring:`"#)]
|
#[error(r#"Invalid string pattern kind "{0}:""#)]
|
||||||
InvalidKind(String),
|
InvalidKind(String),
|
||||||
/// Failed to parse glob pattern.
|
/// Failed to parse glob pattern.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
Loading…
Reference in a new issue