Specify which file not found in error (#11868)

# Description
Currently, `ShellError::FileNotFound` shows the span where the error
occurred but doesn't say which file wasn't found. This PR makes it so
the help includes that (like the `DirectoryNotFound` error).

# User-Facing Changes
No breaking changes, it's just that when a file can't be found, the help
will say which file couldn't be found:


![image](https://github.com/nushell/nushell/assets/45539777/e52f1e65-55c1-4cd2-8108-a4ccc334a66f)
This commit is contained in:
Yash Thakur 2024-02-21 08:27:13 -05:00 committed by GitHub
parent 1058707a29
commit 6ff3a4180b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 39 additions and 16 deletions

View File

@ -72,7 +72,7 @@ impl Command for History {
} else { } else {
let history_reader: Option<Box<dyn ReedlineHistory>> = match history.file_format { let history_reader: Option<Box<dyn ReedlineHistory>> = match history.file_format {
HistoryFileFormat::Sqlite => { HistoryFileFormat::Sqlite => {
SqliteBackedHistory::with_file(history_path, None, None) SqliteBackedHistory::with_file(history_path.clone(), None, None)
.map(|inner| { .map(|inner| {
let boxed: Box<dyn ReedlineHistory> = Box::new(inner); let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
boxed boxed
@ -80,14 +80,15 @@ impl Command for History {
.ok() .ok()
} }
HistoryFileFormat::PlainText => { HistoryFileFormat::PlainText => FileBackedHistory::with_file(
FileBackedHistory::with_file(history.max_size as usize, history_path) history.max_size as usize,
.map(|inner| { history_path.clone(),
let boxed: Box<dyn ReedlineHistory> = Box::new(inner); )
boxed .map(|inner| {
}) let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
.ok() boxed
} })
.ok(),
}; };
match history.file_format { match history.file_format {
@ -107,7 +108,10 @@ impl Command for History {
) )
}) })
}) })
.ok_or(ShellError::FileNotFound { span: head })? .ok_or(ShellError::FileNotFound {
file: history_path.display().to_string(),
span: head,
})?
.into_pipeline_data(ctrlc)), .into_pipeline_data(ctrlc)),
HistoryFileFormat::Sqlite => Ok(history_reader HistoryFileFormat::Sqlite => Ok(history_reader
.and_then(|h| { .and_then(|h| {
@ -119,12 +123,18 @@ impl Command for History {
create_history_record(idx, entry, long, head) create_history_record(idx, entry, long, head)
}) })
}) })
.ok_or(ShellError::FileNotFound { span: head })? .ok_or(ShellError::FileNotFound {
file: history_path.display().to_string(),
span: head,
})?
.into_pipeline_data(ctrlc)), .into_pipeline_data(ctrlc)),
} }
} }
} else { } else {
Err(ShellError::FileNotFound { span: head }) Err(ShellError::FileNotFound {
file: "history file".into(),
span: head,
})
} }
} }

View File

@ -56,6 +56,7 @@ impl Command for SourceEnv {
PathBuf::from(&path) PathBuf::from(&path)
} else { } else {
return Err(ShellError::FileNotFound { return Err(ShellError::FileNotFound {
file: source_filename.item,
span: source_filename.span, span: source_filename.span,
}); });
}; };

View File

@ -81,6 +81,7 @@ impl Command for Mv {
if sources.is_empty() { if sources.is_empty() {
return Err(ShellError::FileNotFound { return Err(ShellError::FileNotFound {
file: spanned_source.item.to_string(),
span: spanned_source.span, span: spanned_source.span,
}); });
} }

View File

@ -92,7 +92,10 @@ impl Command for Open {
for path in nu_engine::glob_from(&path, &cwd, call_span, None) for path in nu_engine::glob_from(&path, &cwd, call_span, None)
.map_err(|err| match err { .map_err(|err| match err {
ShellError::DirectoryNotFound { span, .. } => ShellError::FileNotFound { span }, ShellError::DirectoryNotFound { span, .. } => ShellError::FileNotFound {
file: path.item.to_string(),
span,
},
_ => err, _ => err,
})? })?
.1 .1

View File

@ -205,7 +205,10 @@ impl Command for UCp {
.map(|f| f.1)? .map(|f| f.1)?
.collect(); .collect();
if exp_files.is_empty() { if exp_files.is_empty() {
return Err(ShellError::FileNotFound { span: p.span }); return Err(ShellError::FileNotFound {
file: p.item.to_string(),
span: p.span,
});
}; };
let mut app_vals: Vec<PathBuf> = Vec::new(); let mut app_vals: Vec<PathBuf> = Vec::new();
for v in exp_files { for v in exp_files {

View File

@ -121,7 +121,10 @@ impl Command for UMv {
.map(|f| f.1)? .map(|f| f.1)?
.collect(); .collect();
if exp_files.is_empty() { if exp_files.is_empty() {
return Err(ShellError::FileNotFound { span: p.span }); return Err(ShellError::FileNotFound {
file: p.item.to_string(),
span: p.span,
});
}; };
let mut app_vals: Vec<PathBuf> = Vec::new(); let mut app_vals: Vec<PathBuf> = Vec::new();
for v in exp_files { for v in exp_files {

View File

@ -120,6 +120,7 @@ impl Command for NuCheck {
path path
} else { } else {
return Err(ShellError::FileNotFound { return Err(ShellError::FileNotFound {
file: path_str.item,
span: path_str.span, span: path_str.span,
}); });
} }

View File

@ -727,8 +727,9 @@ pub enum ShellError {
/// ///
/// Does the file in the error message exist? Is it readable and accessible? Is the casing right? /// Does the file in the error message exist? Is it readable and accessible? Is the casing right?
#[error("File not found")] #[error("File not found")]
#[diagnostic(code(nu::shell::file_not_found))] #[diagnostic(code(nu::shell::file_not_found), help("{file} does not exist"))]
FileNotFound { FileNotFound {
file: String,
#[label("file not found")] #[label("file not found")]
span: Span, span: Span,
}, },