Convert more ShellError variants to named fields (#11173)

# Description

Convert these ShellError variants to named fields:
* CreateNotPossible
* MoveNotPossibleSingle
* DirectoryNotFoundCustom
* DirectoryNotFound
* NotADirectory
* OutOfMemoryError
* PermissionDeniedError
* IOErrorSpanned
* IOError
* IOInterrupted

Also place the `span` field of `DirectoryNotFound` last to match other
errors.

Part of #10700 (almost half done!)

# User-Facing Changes

None

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

N/A
This commit is contained in:
Eric Hodel 2023-11-28 04:43:51 -08:00 committed by GitHub
parent 182b0ab4fb
commit 8386bc0919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 241 additions and 116 deletions

View File

@ -502,10 +502,10 @@ pub fn evaluate_repl(
report_error( report_error(
&working_set, &working_set,
&ShellError::DirectoryNotFound( &ShellError::DirectoryNotFound {
tokens.0[0].span, dir: path.to_string_lossy().to_string(),
path.to_string_lossy().to_string(), span: tokens.0[0].span,
), },
); );
} }
let path = nu_path::canonicalize_with(path, &cwd) let path = nu_path::canonicalize_with(path, &cwd)

View File

@ -83,10 +83,10 @@ impl Command for Cd {
let path = match nu_path::canonicalize_with(path.clone(), &cwd) { let path = match nu_path::canonicalize_with(path.clone(), &cwd) {
Ok(p) => p, Ok(p) => p,
Err(_) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
v.span, dir: path.to_string_lossy().to_string(),
path.to_string_lossy().to_string(), span: v.span,
)); });
} }
}; };
(path.to_string_lossy().to_string(), v.span) (path.to_string_lossy().to_string(), v.span)
@ -100,17 +100,17 @@ impl Command for Cd {
let path = match nu_path::canonicalize_with(path_no_whitespace, &cwd) { let path = match nu_path::canonicalize_with(path_no_whitespace, &cwd) {
Ok(p) => { Ok(p) => {
if !p.is_dir() { if !p.is_dir() {
return Err(ShellError::NotADirectory(v.span)); return Err(ShellError::NotADirectory { span: v.span });
}; };
p p
} }
// if canonicalize failed, let's check to see if it's abbreviated // if canonicalize failed, let's check to see if it's abbreviated
Err(_) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
v.span, dir: path_no_whitespace.to_string(),
path_no_whitespace.to_string(), span: v.span,
)); });
} }
}; };
(path.to_string_lossy().to_string(), v.span) (path.to_string_lossy().to_string(), v.span)
@ -135,9 +135,9 @@ impl Command for Cd {
stack.add_env_var("PWD".into(), path_value); stack.add_env_var("PWD".into(), path_value);
Ok(PipelineData::empty()) Ok(PipelineData::empty())
} }
PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError(format!( PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError {
"Cannot change directory to {path}: {reason}" msg: format!("Cannot change directory to {path}: {reason}"),
))), }),
} }
} }

View File

@ -88,10 +88,10 @@ impl Command for Cp {
let path_last_char = destination.as_os_str().to_string_lossy().chars().last(); let path_last_char = destination.as_os_str().to_string_lossy().chars().last();
let is_directory = path_last_char == Some('/') || path_last_char == Some('\\'); let is_directory = path_last_char == Some('/') || path_last_char == Some('\\');
if is_directory && !destination.exists() { if is_directory && !destination.exists() {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
dst.span, dir: destination.to_string_lossy().to_string(),
destination.to_string_lossy().to_string(), span: dst.span,
)); });
} }
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let span = call.head; let span = call.head;
@ -577,18 +577,36 @@ fn convert_io_error(error: std::io::Error, src: PathBuf, dst: PathBuf, span: Spa
ErrorKind::PermissionDenied => match std::fs::metadata(&dst) { ErrorKind::PermissionDenied => match std::fs::metadata(&dst) {
Ok(meta) => { Ok(meta) => {
if meta.permissions().readonly() { if meta.permissions().readonly() {
ShellError::PermissionDeniedError(message_dst, span) ShellError::PermissionDeniedError {
msg: message_dst,
span,
}
} else { } else {
ShellError::PermissionDeniedError(message_src, span) ShellError::PermissionDeniedError {
msg: message_src,
span,
} }
} }
Err(_) => ShellError::PermissionDeniedError(message_dst, span), }
Err(_) => ShellError::PermissionDeniedError {
msg: message_dst,
span,
},
},
ErrorKind::Interrupted => ShellError::IOInterrupted {
msg: message_src,
span,
},
ErrorKind::OutOfMemory => ShellError::OutOfMemoryError {
msg: message_src,
span,
}, },
ErrorKind::Interrupted => ShellError::IOInterrupted(message_src, span),
ErrorKind::OutOfMemory => ShellError::OutOfMemoryError(message_src, span),
// TODO: handle ExecutableFileBusy etc. when io_error_more is stabilized // TODO: handle ExecutableFileBusy etc. when io_error_more is stabilized
// https://github.com/rust-lang/rust/issues/86442 // https://github.com/rust-lang/rust/issues/86442
_ => ShellError::IOErrorSpanned(message_src, span), _ => ShellError::IOErrorSpanned {
msg: message_src,
span,
},
}; };
Value::error(shell_error, span) Value::error(shell_error, span)

View File

@ -69,12 +69,13 @@ impl Command for Mkdir {
let dir_res = std::fs::create_dir_all(&dir); let dir_res = std::fs::create_dir_all(&dir);
if let Err(reason) = dir_res { if let Err(reason) = dir_res {
return Err(ShellError::CreateNotPossible( return Err(ShellError::CreateNotPossible {
format!("failed to create directory: {reason}"), msg: format!("failed to create directory: {reason}"),
call.positional_nth(i) span: call
.positional_nth(i)
.expect("already checked through directories") .expect("already checked through directories")
.span, .span,
)); });
} }
if is_verbose { if is_verbose {

View File

@ -110,10 +110,14 @@ impl Command for Mktemp {
}; };
let res = match uu_mktemp::mktemp(&options) { let res = match uu_mktemp::mktemp(&options) {
Ok(res) => res Ok(res) => {
.into_os_string() res.into_os_string()
.into_string() .into_string()
.map_err(|e| ShellError::IOErrorSpanned(e.to_string_lossy().to_string(), span))?, .map_err(|e| ShellError::IOErrorSpanned {
msg: e.to_string_lossy().to_string(),
span,
})?
}
Err(e) => { Err(e) => {
return Err(ShellError::GenericError( return Err(ShellError::GenericError(
format!("{}", e), format!("{}", e),

View File

@ -260,10 +260,10 @@ fn move_file(
}; };
if !destination_dir_exists { if !destination_dir_exists {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
to_span, dir: to.to_string_lossy().to_string(),
to.to_string_lossy().to_string(), span: to_span,
)); });
} }
// This can happen when changing case on a case-insensitive filesystem (ex: changing foo to Foo on Windows) // This can happen when changing case on a case-insensitive filesystem (ex: changing foo to Foo on Windows)
@ -275,10 +275,10 @@ fn move_file(
let from_file_name = match from.file_name() { let from_file_name = match from.file_name() {
Some(name) => name, Some(name) => name,
None => { None => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
to_span, dir: from.to_string_lossy().to_string(),
from.to_string_lossy().to_string(), span: to_span,
)) })
} }
}; };

View File

@ -105,7 +105,7 @@ 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 { span },
_ => err, _ => err,
})? })?
.1 .1

View File

@ -162,9 +162,13 @@ impl Command for Save {
)?; )?;
for val in ls { for val in ls {
file.write_all(&value_to_bytes(val)?) file.write_all(&value_to_bytes(val)?)
.map_err(|err| ShellError::IOError(err.to_string()))?; .map_err(|err| ShellError::IOError {
msg: err.to_string(),
})?;
file.write_all("\n".as_bytes()) file.write_all("\n".as_bytes())
.map_err(|err| ShellError::IOError(err.to_string()))?; .map_err(|err| ShellError::IOError {
msg: err.to_string(),
})?;
} }
file.flush()?; file.flush()?;
@ -184,8 +188,9 @@ impl Command for Save {
force, force,
)?; )?;
file.write_all(&bytes) file.write_all(&bytes).map_err(|err| ShellError::IOError {
.map_err(|err| ShellError::IOError(err.to_string()))?; msg: err.to_string(),
})?;
file.flush()?; file.flush()?;
@ -453,7 +458,9 @@ fn stream_to_file(
if let Err(err) = writer.write(&buf) { if let Err(err) = writer.write(&buf) {
*process_failed_p = true; *process_failed_p = true;
return Err(ShellError::IOError(err.to_string())); return Err(ShellError::IOError {
msg: err.to_string(),
});
} }
Ok(()) Ok(())
}) })

View File

@ -136,12 +136,13 @@ impl Command for Touch {
} }
if let Err(err) = OpenOptions::new().write(true).create(true).open(&item) { if let Err(err) = OpenOptions::new().write(true).create(true).open(&item) {
return Err(ShellError::CreateNotPossible( return Err(ShellError::CreateNotPossible {
format!("Failed to create file: {err}"), msg: format!("Failed to create file: {err}"),
call.positional_nth(index) span: call
.positional_nth(index)
.expect("already checked positional") .expect("already checked positional")
.span, .span,
)); });
}; };
if change_mtime { if change_mtime {

View File

@ -83,10 +83,10 @@ impl Command for Watch {
let path = match nu_path::canonicalize_with(path_no_whitespace, cwd) { let path = match nu_path::canonicalize_with(path_no_whitespace, cwd) {
Ok(p) => p, Ok(p) => p,
Err(_) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
path_arg.span, dir: path_no_whitespace.to_string(),
path_no_whitespace.to_string(), span: path_arg.span,
)) })
} }
}; };
@ -153,15 +153,15 @@ impl Command for Watch {
let mut debouncer = match new_debouncer(debounce_duration, None, tx) { let mut debouncer = match new_debouncer(debounce_duration, None, tx) {
Ok(d) => d, Ok(d) => d,
Err(e) => { Err(e) => {
return Err(ShellError::IOError(format!( return Err(ShellError::IOError {
"Failed to create watcher: {e}" msg: format!("Failed to create watcher: {e}"),
))) })
} }
}; };
if let Err(e) = debouncer.watcher().watch(&path, recursive_mode) { if let Err(e) = debouncer.watcher().watch(&path, recursive_mode) {
return Err(ShellError::IOError(format!( return Err(ShellError::IOError {
"Failed to create watcher: {e}" msg: format!("Failed to create watcher: {e}"),
))); });
} }
// need to cache to make sure that rename event works. // need to cache to make sure that rename event works.
debouncer.cache().add_root(&path, recursive_mode); debouncer.cache().add_root(&path, recursive_mode);
@ -275,14 +275,14 @@ impl Command for Watch {
} }
} }
Ok(Err(_)) => { Ok(Err(_)) => {
return Err(ShellError::IOError( return Err(ShellError::IOError {
"Unexpected errors when receiving events".into(), msg: "Unexpected errors when receiving events".into(),
)) })
} }
Err(RecvTimeoutError::Disconnected) => { Err(RecvTimeoutError::Disconnected) => {
return Err(ShellError::IOError( return Err(ShellError::IOError {
"Unexpected disconnect from file watcher".into(), msg: "Unexpected disconnect from file watcher".into(),
)); });
} }
Err(RecvTimeoutError::Timeout) => {} Err(RecvTimeoutError::Timeout) => {}
} }

View File

@ -209,9 +209,9 @@ pub fn send_request(
} }
Value::List { vals, .. } if body_type == BodyType::Form => { Value::List { vals, .. } if body_type == BodyType::Form => {
if vals.len() % 2 != 0 { if vals.len() % 2 != 0 {
return Err(ShellErrorOrRequestError::ShellError(ShellError::IOError( return Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
"unsupported body input".into(), msg: "unsupported body input".into(),
))); }));
} }
let data = vals let data = vals
@ -233,9 +233,9 @@ pub fn send_request(
let data = value_to_json_value(&body)?; let data = value_to_json_value(&body)?;
send_cancellable_request(&request_url, Box::new(|| request.send_json(data)), ctrl_c) send_cancellable_request(&request_url, Box::new(|| request.send_json(data)), ctrl_c)
} }
_ => Err(ShellErrorOrRequestError::ShellError(ShellError::IOError( _ => Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
"unsupported body input".into(), msg: "unsupported body input".into(),
))), })),
} }
} }

View File

@ -135,7 +135,13 @@ fn exists(path: &Path, span: Span, args: &Arguments) -> Value {
match path.try_exists() { match path.try_exists() {
Ok(exists) => exists, Ok(exists) => exists,
Err(err) => { Err(err) => {
return Value::error(ShellError::IOErrorSpanned(err.to_string(), span), span) return Value::error(
ShellError::IOErrorSpanned {
msg: err.to_string(),
span,
},
span,
)
} }
}, },
span, span,

View File

@ -36,7 +36,10 @@ impl Command for Clear {
CommandSys::new("cmd") CommandSys::new("cmd")
.args(["/C", "cls"]) .args(["/C", "cls"])
.status() .status()
.map_err(|e| ShellError::IOErrorSpanned(e.to_string(), span))?; .map_err(|e| ShellError::IOErrorSpanned {
msg: e.to_string(),
span,
})?;
} else if cfg!(unix) { } else if cfg!(unix) {
let mut cmd = CommandSys::new("/bin/sh"); let mut cmd = CommandSys::new("/bin/sh");
@ -46,7 +49,10 @@ impl Command for Clear {
cmd.args(["-c", "clear"]) cmd.args(["-c", "clear"])
.status() .status()
.map_err(|e| ShellError::IOErrorSpanned(e.to_string(), span))?; .map_err(|e| ShellError::IOErrorSpanned {
msg: e.to_string(),
span,
})?;
} }
Ok(Value::nothing(span).into_pipeline_data()) Ok(Value::nothing(span).into_pipeline_data())

View File

@ -110,7 +110,9 @@ impl Command for Input {
{ {
if k.modifiers == KeyModifiers::CONTROL && c == 'c' { if k.modifiers == KeyModifiers::CONTROL && c == 'c' {
crossterm::terminal::disable_raw_mode()?; crossterm::terminal::disable_raw_mode()?;
return Err(ShellError::IOError("SIGINT".to_string())); return Err(ShellError::IOError {
msg: "SIGINT".to_string(),
});
} }
continue; continue;
} }

View File

@ -196,7 +196,9 @@ impl Command for InputList {
.items(&options) .items(&options)
.report(false) .report(false)
.interact_on_opt(&Term::stderr()) .interact_on_opt(&Term::stderr())
.map_err(|err| ShellError::IOError(format!("{}: {}", INTERACT_ERROR, err)))?, .map_err(|err| ShellError::IOError {
msg: format!("{}: {}", INTERACT_ERROR, err),
})?,
) )
} else if call.has_flag("fuzzy") { } else if call.has_flag("fuzzy") {
let fuzzy_select = FuzzySelect::new(); //::with_theme(&theme); let fuzzy_select = FuzzySelect::new(); //::with_theme(&theme);
@ -211,7 +213,9 @@ impl Command for InputList {
.default(0) .default(0)
.report(false) .report(false)
.interact_on_opt(&Term::stderr()) .interact_on_opt(&Term::stderr())
.map_err(|err| ShellError::IOError(format!("{}: {}", INTERACT_ERROR, err)))?, .map_err(|err| ShellError::IOError {
msg: format!("{}: {}", INTERACT_ERROR, err),
})?,
) )
} else { } else {
let select = Select::new(); //::with_theme(&theme); let select = Select::new(); //::with_theme(&theme);
@ -225,7 +229,9 @@ impl Command for InputList {
.default(0) .default(0)
.report(false) .report(false)
.interact_on_opt(&Term::stderr()) .interact_on_opt(&Term::stderr())
.map_err(|err| ShellError::IOError(format!("{}: {}", INTERACT_ERROR, err)))?, .map_err(|err| ShellError::IOError {
msg: format!("{}: {}", INTERACT_ERROR, err),
})?,
) )
}; };

View File

@ -301,7 +301,9 @@ fn heuristic_parse_file(
} }
} }
} else { } else {
Err(ShellError::IOError("Can not read input".to_string())) Err(ShellError::IOError {
msg: "Can not read input".to_string(),
})
} }
} else { } else {
Err(ShellError::NotFound { span: call.head }) Err(ShellError::NotFound { span: call.head })
@ -402,7 +404,9 @@ fn parse_file_script(
call.head, call.head,
) )
} else { } else {
Err(ShellError::IOError("Can not read path".to_string())) Err(ShellError::IOError {
msg: "Can not read path".to_string(),
})
} }
} else { } else {
Err(ShellError::NotFound { span: call.head }) Err(ShellError::NotFound { span: call.head })
@ -425,7 +429,9 @@ fn parse_file_module(
if let Ok(contents) = std::fs::read(path) { if let Ok(contents) = std::fs::read(path) {
parse_module(working_set, Some(filename), &contents, is_debug, call.head) parse_module(working_set, Some(filename), &contents, is_debug, call.head)
} else { } else {
Err(ShellError::IOError("Can not read path".to_string())) Err(ShellError::IOError {
msg: "Can not read path".to_string(),
})
} }
} else { } else {
Err(ShellError::NotFound { span: call.head }) Err(ShellError::NotFound { span: call.head })

View File

@ -72,10 +72,10 @@ pub fn glob_from(
let path = if let Ok(p) = canonicalize_with(path.clone(), cwd) { let path = if let Ok(p) = canonicalize_with(path.clone(), cwd) {
p p
} else { } else {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound {
pattern.span, dir: path.to_string_lossy().to_string(),
path.to_string_lossy().to_string(), span: pattern.span,
)); });
}; };
(path.parent().map(|parent| parent.to_path_buf()), path) (path.parent().map(|parent| parent.to_path_buf()), path)
} }

View File

@ -12,13 +12,17 @@ pub fn run_command_with_value(
stack: &mut Stack, stack: &mut Stack,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
if is_ignored_command(command) { if is_ignored_command(command) {
return Err(ShellError::IOError(String::from("the command is ignored"))); return Err(ShellError::IOError {
msg: String::from("the command is ignored"),
});
} }
let pipeline = PipelineData::Value(input.clone(), None); let pipeline = PipelineData::Value(input.clone(), None);
let pipeline = run_nu_command(engine_state, stack, command, pipeline)?; let pipeline = run_nu_command(engine_state, stack, command, pipeline)?;
if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline { if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline {
Err(ShellError::IOError(error.to_string())) Err(ShellError::IOError {
msg: error.to_string(),
})
} else { } else {
Ok(pipeline) Ok(pipeline)
} }
@ -63,7 +67,9 @@ fn eval_source2(
); );
if let Some(err) = working_set.parse_errors.first() { if let Some(err) = working_set.parse_errors.first() {
return Err(ShellError::IOError(err.to_string())); return Err(ShellError::IOError {
msg: err.to_string(),
});
} }
(output, working_set.render()) (output, working_set.render())
@ -71,7 +77,9 @@ fn eval_source2(
// We need to merge different info other wise things like PIPEs etc will not work. // We need to merge different info other wise things like PIPEs etc will not work.
if let Err(err) = engine_state.merge_delta(delta) { if let Err(err) = engine_state.merge_delta(delta) {
return Err(ShellError::IOError(err.to_string())); return Err(ShellError::IOError {
msg: err.to_string(),
});
} }
// eval_block outputs all expressions except the last to STDOUT; // eval_block outputs all expressions except the last to STDOUT;

View File

@ -32,7 +32,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(path.to_string_lossy(), span) Value::string(path.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not get config directory".into()), ShellError::IOError {
msg: "Could not get config directory".into(),
},
span, span,
) )
}, },
@ -49,7 +51,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(path.to_string_lossy(), span) Value::string(path.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not get config directory".into()), ShellError::IOError {
msg: "Could not get config directory".into(),
},
span, span,
) )
}, },
@ -66,7 +70,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(path.to_string_lossy(), span) Value::string(path.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not find environment path".into()), ShellError::IOError {
msg: "Could not find environment path".into(),
},
span, span,
) )
}, },
@ -88,7 +94,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(canon_hist_path.to_string_lossy(), span) Value::string(canon_hist_path.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not find history path".into()), ShellError::IOError {
msg: "Could not find history path".into(),
},
span, span,
) )
}, },
@ -103,7 +111,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(canon_login_path.to_string_lossy(), span) Value::string(canon_login_path.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not find login shell path".into()), ShellError::IOError {
msg: "Could not find login shell path".into(),
},
span, span,
) )
}, },
@ -123,7 +133,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(plugin_path.to_string_lossy(), span) Value::string(plugin_path.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not get plugin signature location".into()), ShellError::IOError {
msg: "Could not get plugin signature location".into(),
},
span, span,
) )
}, },
@ -136,7 +148,12 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
let canon_home_path = canonicalize_path(engine_state, &path); let canon_home_path = canonicalize_path(engine_state, &path);
Value::string(canon_home_path.to_string_lossy(), span) Value::string(canon_home_path.to_string_lossy(), span)
} else { } else {
Value::error(ShellError::IOError("Could not get home path".into()), span) Value::error(
ShellError::IOError {
msg: "Could not get home path".into(),
},
span,
)
}, },
); );
@ -178,7 +195,9 @@ pub fn create_nu_constant(engine_state: &EngineState, span: Span) -> Result<Valu
Value::string(current_exe.to_string_lossy(), span) Value::string(current_exe.to_string_lossy(), span)
} else { } else {
Value::error( Value::error(
ShellError::IOError("Could not get current executable path".to_string()), ShellError::IOError {
msg: "Could not get current executable path".to_string(),
},
span, span,
) )
}, },

View File

@ -765,7 +765,11 @@ pub enum ShellError {
/// This is a generic error. Refer to the specific error message for further details. /// This is a generic error. Refer to the specific error message for further details.
#[error("I/O interrupted")] #[error("I/O interrupted")]
#[diagnostic(code(nu::shell::io_interrupted))] #[diagnostic(code(nu::shell::io_interrupted))]
IOInterrupted(String, #[label("{0}")] Span), IOInterrupted {
msg: String,
#[label("{msg}")]
span: Span,
},
/// An I/O operation failed. /// An I/O operation failed.
/// ///
@ -773,8 +777,8 @@ pub enum ShellError {
/// ///
/// This is a generic error. Refer to the specific error message for further details. /// This is a generic error. Refer to the specific error message for further details.
#[error("I/O error")] #[error("I/O error")]
#[diagnostic(code(nu::shell::io_error), help("{0}"))] #[diagnostic(code(nu::shell::io_error), help("{msg}"))]
IOError(String), IOError { msg: String },
/// An I/O operation failed. /// An I/O operation failed.
/// ///
@ -783,7 +787,11 @@ pub enum ShellError {
/// This is a generic error. Refer to the specific error message for further details. /// This is a generic error. Refer to the specific error message for further details.
#[error("I/O error")] #[error("I/O error")]
#[diagnostic(code(nu::shell::io_error))] #[diagnostic(code(nu::shell::io_error))]
IOErrorSpanned(String, #[label("{0}")] Span), IOErrorSpanned {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Permission for an operation was denied. /// Permission for an operation was denied.
/// ///
@ -792,7 +800,11 @@ pub enum ShellError {
/// This is a generic error. Refer to the specific error message for further details. /// This is a generic error. Refer to the specific error message for further details.
#[error("Permission Denied")] #[error("Permission Denied")]
#[diagnostic(code(nu::shell::permission_denied))] #[diagnostic(code(nu::shell::permission_denied))]
PermissionDeniedError(String, #[label("{0}")] Span), PermissionDeniedError {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Out of memory. /// Out of memory.
/// ///
@ -801,7 +813,11 @@ pub enum ShellError {
/// This is a generic error. Refer to the specific error message for further details. /// This is a generic error. Refer to the specific error message for further details.
#[error("Out of memory")] #[error("Out of memory")]
#[diagnostic(code(nu::shell::out_of_memory))] #[diagnostic(code(nu::shell::out_of_memory))]
OutOfMemoryError(String, #[label("{0}")] Span), OutOfMemoryError {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Tried to `cd` to a path that isn't a directory. /// Tried to `cd` to a path that isn't a directory.
/// ///
@ -810,7 +826,10 @@ pub enum ShellError {
/// Make sure the path is a directory. It currently exists, but is of some other type, like a file. /// Make sure the path is a directory. It currently exists, but is of some other type, like a file.
#[error("Cannot change to directory")] #[error("Cannot change to directory")]
#[diagnostic(code(nu::shell::cannot_cd_to_directory))] #[diagnostic(code(nu::shell::cannot_cd_to_directory))]
NotADirectory(#[label("is not a directory")] Span), NotADirectory {
#[label("is not a directory")]
span: Span,
},
/// Attempted to perform an operation on a directory that doesn't exist. /// Attempted to perform an operation on a directory that doesn't exist.
/// ///
@ -818,8 +837,12 @@ pub enum ShellError {
/// ///
/// Make sure the directory in the error message actually exists before trying again. /// Make sure the directory in the error message actually exists before trying again.
#[error("Directory not found")] #[error("Directory not found")]
#[diagnostic(code(nu::shell::directory_not_found), help("{1} does not exist"))] #[diagnostic(code(nu::shell::directory_not_found), help("{dir} does not exist"))]
DirectoryNotFound(#[label("directory not found")] Span, String), DirectoryNotFound {
dir: String,
#[label("directory not found")]
span: Span,
},
/// Attempted to perform an operation on a directory that doesn't exist. /// Attempted to perform an operation on a directory that doesn't exist.
/// ///
@ -828,7 +851,11 @@ pub enum ShellError {
/// Make sure the directory in the error message actually exists before trying again. /// Make sure the directory in the error message actually exists before trying again.
#[error("Directory not found")] #[error("Directory not found")]
#[diagnostic(code(nu::shell::directory_not_found_custom))] #[diagnostic(code(nu::shell::directory_not_found_custom))]
DirectoryNotFoundCustom(String, #[label("{0}")] Span), DirectoryNotFoundCustom {
msg: String,
#[label("{msg}")]
span: Span,
},
/// The requested move operation cannot be completed. This is typically because both paths exist, /// The requested move operation cannot be completed. This is typically because both paths exist,
/// but are of different types. For example, you might be trying to overwrite an existing file with /// but are of different types. For example, you might be trying to overwrite an existing file with
@ -858,7 +885,11 @@ pub enum ShellError {
#[error("Move not possible")] #[error("Move not possible")]
#[diagnostic(code(nu::shell::move_not_possible_single))] #[diagnostic(code(nu::shell::move_not_possible_single))]
// NOTE: Currently not actively used. // NOTE: Currently not actively used.
MoveNotPossibleSingle(String, #[label("{0}")] Span), MoveNotPossibleSingle {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Failed to create either a file or directory. /// Failed to create either a file or directory.
/// ///
@ -867,7 +898,11 @@ pub enum ShellError {
/// This is a fairly generic error. Refer to the specific error message for further details. /// This is a fairly generic error. Refer to the specific error message for further details.
#[error("Create not possible")] #[error("Create not possible")]
#[diagnostic(code(nu::shell::create_not_possible))] #[diagnostic(code(nu::shell::create_not_possible))]
CreateNotPossible(String, #[label("{0}")] Span), CreateNotPossible {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Changing the access time ("atime") of this file is not possible. /// Changing the access time ("atime") of this file is not possible.
/// ///
@ -1201,19 +1236,25 @@ impl ShellError {
impl From<std::io::Error> for ShellError { impl From<std::io::Error> for ShellError {
fn from(input: std::io::Error) -> ShellError { fn from(input: std::io::Error) -> ShellError {
ShellError::IOError(format!("{input:?}")) ShellError::IOError {
msg: format!("{input:?}"),
}
} }
} }
impl std::convert::From<Box<dyn std::error::Error>> for ShellError { impl std::convert::From<Box<dyn std::error::Error>> for ShellError {
fn from(input: Box<dyn std::error::Error>) -> ShellError { fn from(input: Box<dyn std::error::Error>) -> ShellError {
ShellError::IOError(input.to_string()) ShellError::IOError {
msg: input.to_string(),
}
} }
} }
impl From<Box<dyn std::error::Error + Send + Sync>> for ShellError { impl From<Box<dyn std::error::Error + Send + Sync>> for ShellError {
fn from(input: Box<dyn std::error::Error + Send + Sync>) -> ShellError { fn from(input: Box<dyn std::error::Error + Send + Sync>) -> ShellError {
ShellError::IOError(format!("{input:?}")) ShellError::IOError {
msg: format!("{input:?}"),
}
} }
} }

View File

@ -30,7 +30,7 @@ impl<R: Read> Iterator for BufferedReader<R> {
Some(Ok(result)) Some(Ok(result))
} }
} }
Err(e) => Some(Err(ShellError::IOError(e.to_string()))), Err(e) => Some(Err(ShellError::IOError { msg: e.to_string() })),
} }
} }
} }