mirror of
https://github.com/nushell/nushell
synced 2024-11-10 15:14:14 +00:00
removed unwraps (#430)
This commit is contained in:
parent
eed22605ef
commit
8a06ea133b
24 changed files with 233 additions and 159 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -39,4 +39,4 @@ jobs:
|
|||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: -- -D warnings
|
||||
args: -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
|
||||
|
|
|
@ -114,11 +114,13 @@ fn into_int(
|
|||
None => 10,
|
||||
};
|
||||
|
||||
if !(2..=36).contains(&radix) {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Radix must lie in the range [2, 36]".to_string(),
|
||||
options.radix.unwrap().span().unwrap(),
|
||||
));
|
||||
if let Some(val) = &options.radix {
|
||||
if !(2..=36).contains(&radix) {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Radix must lie in the range [2, 36]".to_string(),
|
||||
val.span()?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
input.map(
|
||||
|
|
|
@ -139,11 +139,13 @@ fn string_helper(
|
|||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let config = stack.get_config()?;
|
||||
|
||||
if decimals && decimals_value.is_some() && decimals_value.unwrap().is_negative() {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Cannot accept negative integers for decimals arguments".to_string(),
|
||||
head,
|
||||
));
|
||||
if let Some(decimal_val) = decimals_value {
|
||||
if decimals && decimal_val.is_negative() {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Cannot accept negative integers for decimals arguments".to_string(),
|
||||
head,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
input.map(
|
||||
|
@ -192,7 +194,7 @@ pub fn action(
|
|||
}
|
||||
Value::Float { val, .. } => {
|
||||
if decimals {
|
||||
let decimal_value = digits.unwrap() as usize;
|
||||
let decimal_value = digits.unwrap_or(2) as usize;
|
||||
Value::String {
|
||||
val: format!("{:.*}", decimal_value, val),
|
||||
span,
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Command for Cp {
|
|||
let interactive = call.has_flag("interactive");
|
||||
let force = call.has_flag("force");
|
||||
|
||||
let path: PathBuf = current_dir().unwrap();
|
||||
let path = current_dir()?;
|
||||
let source = path.join(source.as_str());
|
||||
let destination = path.join(destination.as_str());
|
||||
|
||||
|
@ -83,12 +83,36 @@ impl Command for Cp {
|
|||
let prompt = format!(
|
||||
"Are you shure that you want to copy {} to {}?",
|
||||
file.as_ref()
|
||||
.unwrap()
|
||||
.map_err(|err| ShellError::LabeledError(
|
||||
"Reference error".into(),
|
||||
err.to_string(),
|
||||
call.head
|
||||
))?
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"File name error".into(),
|
||||
"Unable to get file name".into(),
|
||||
call.head
|
||||
))?
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
destination.file_name().unwrap().to_str().unwrap()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
call.head
|
||||
))?,
|
||||
destination
|
||||
.file_name()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"File name error".into(),
|
||||
"Unable to get file name".into(),
|
||||
call.head
|
||||
))?
|
||||
.to_str()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
call.head
|
||||
))?,
|
||||
);
|
||||
|
||||
let input = get_interactive_confirmation(prompt)?;
|
||||
|
|
|
@ -55,7 +55,13 @@ impl Command for Ls {
|
|||
};
|
||||
|
||||
let call_span = call.head;
|
||||
let glob = glob::glob(&pattern).unwrap();
|
||||
let glob = glob::glob(&pattern).map_err(|err| {
|
||||
nu_protocol::ShellError::LabeledError(
|
||||
"Error extracting glob pattern".into(),
|
||||
err.to_string(),
|
||||
call.head,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(glob
|
||||
.into_iter()
|
||||
|
|
|
@ -5,7 +5,7 @@ use super::util::get_interactive_confirmation;
|
|||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape};
|
||||
use nu_protocol::{Category, PipelineData, ShellError, Signature, Spanned, SyntaxShape};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Mv;
|
||||
|
@ -45,22 +45,20 @@ impl Command for Mv {
|
|||
_input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||
// TODO: handle invalid directory or insufficient permissions when moving
|
||||
let source: String = call.req(engine_state, stack, 0)?;
|
||||
let spanned_source: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let destination: String = call.req(engine_state, stack, 1)?;
|
||||
let interactive = call.has_flag("interactive");
|
||||
let force = call.has_flag("force");
|
||||
|
||||
let path: PathBuf = current_dir().unwrap();
|
||||
let source = path.join(source.as_str());
|
||||
let path: PathBuf = current_dir()?;
|
||||
let source = path.join(spanned_source.item.as_str());
|
||||
let destination = path.join(destination.as_str());
|
||||
|
||||
let mut sources =
|
||||
glob::glob(&source.to_string_lossy()).map_or_else(|_| Vec::new(), Iterator::collect);
|
||||
|
||||
if sources.is_empty() {
|
||||
return Err(ShellError::FileNotFound(
|
||||
call.positional.first().unwrap().span,
|
||||
));
|
||||
return Err(ShellError::FileNotFound(spanned_source.span));
|
||||
}
|
||||
|
||||
if interactive && !force {
|
||||
|
@ -69,12 +67,36 @@ impl Command for Mv {
|
|||
let prompt = format!(
|
||||
"Are you shure that you want to move {} to {}?",
|
||||
file.as_ref()
|
||||
.unwrap()
|
||||
.map_err(|err| ShellError::LabeledError(
|
||||
"Reference error".into(),
|
||||
err.to_string(),
|
||||
call.head
|
||||
))?
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"File name error".into(),
|
||||
"Unable to get file name".into(),
|
||||
call.head
|
||||
))?
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
destination.file_name().unwrap().to_str().unwrap()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
call.head
|
||||
))?,
|
||||
destination
|
||||
.file_name()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"File name error".into(),
|
||||
"Unable to get file name".into(),
|
||||
call.head
|
||||
))?
|
||||
.to_str()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
call.head
|
||||
))?,
|
||||
);
|
||||
|
||||
let input = get_interactive_confirmation(prompt)?;
|
||||
|
|
|
@ -84,23 +84,6 @@ fn rm(
|
|||
"Can't use \"--trash\" with \"--permanent\"".to_string(),
|
||||
call.head,
|
||||
));
|
||||
|
||||
// let trash_span = call.get_flag_expr("trash").unwrap().span;
|
||||
// let perm_span = call.get_flag_expr("permanent").unwrap().span;
|
||||
|
||||
// let left_message = "cannot use".to_string();
|
||||
// let right_message = "with".to_string();
|
||||
// let (left_span, right_span) = match trash_span.start < perm_span.start {
|
||||
// true => (trash_span, perm_span),
|
||||
// false => (perm_span, trash_span),
|
||||
// };
|
||||
|
||||
// return Err(ShellError::IncompatibleParameters {
|
||||
// left_message,
|
||||
// left_span,
|
||||
// right_message,
|
||||
// right_span,
|
||||
// });
|
||||
}
|
||||
|
||||
let current_path = current_dir()?;
|
||||
|
@ -141,7 +124,19 @@ fn rm(
|
|||
for (index, file) in targets.iter().enumerate() {
|
||||
let prompt: String = format!(
|
||||
"Are you sure that you what to delete {}?",
|
||||
file.1.file_name().unwrap().to_str().unwrap()
|
||||
file.1
|
||||
.file_name()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"File name error".into(),
|
||||
"Unable to get file name".into(),
|
||||
call.head
|
||||
))?
|
||||
.to_str()
|
||||
.ok_or_else(|| ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
call.head
|
||||
))?,
|
||||
);
|
||||
|
||||
let input = get_interactive_confirmation(prompt)?;
|
||||
|
@ -192,9 +187,18 @@ fn rm_helper(call: &Call, args: RmArgs) -> Vec<Value> {
|
|||
#[cfg(not(feature = "trash-support"))]
|
||||
{
|
||||
if trash {
|
||||
return vec![Value::Error {
|
||||
error: ShellError::FeatureNotEnabled(call.get_flag_expr("trash").unwrap().span),
|
||||
}];
|
||||
let error = match call.get_flag_expr("trash").ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"Flag not found".into(),
|
||||
"trash flag not found".into(),
|
||||
call.head,
|
||||
)
|
||||
}) {
|
||||
Ok(expr) => ShellError::FeatureNotEnabled(expr.span),
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
return vec![Value::Error { error }];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ use nu_protocol::{
|
|||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Drop;
|
||||
|
@ -90,7 +89,7 @@ impl Command for Drop {
|
|||
vlen - rows_to_drop
|
||||
};
|
||||
|
||||
let iter = v.into_iter().take(k.try_into().unwrap());
|
||||
let iter = v.into_iter().take(k as usize);
|
||||
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,17 @@ fn first_helper(
|
|||
|
||||
let mut input_peek = input.into_iter().peekable();
|
||||
if input_peek.peek().is_some() {
|
||||
match input_peek.peek().unwrap().get_type() {
|
||||
match input_peek
|
||||
.peek()
|
||||
.ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"Error in first".into(),
|
||||
"unable to pick on next value".into(),
|
||||
call.head,
|
||||
)
|
||||
})?
|
||||
.get_type()
|
||||
{
|
||||
Type::Binary => {
|
||||
match &mut input_peek.next() {
|
||||
Some(v) => match &v {
|
||||
|
|
|
@ -6,7 +6,6 @@ use nu_protocol::{
|
|||
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Last;
|
||||
|
@ -53,9 +52,7 @@ impl Command for Last {
|
|||
let vlen: i64 = v.len() as i64;
|
||||
let beginning_rows_to_skip = rows_to_skip(vlen, rows);
|
||||
|
||||
let iter = v
|
||||
.into_iter()
|
||||
.skip(beginning_rows_to_skip.try_into().unwrap());
|
||||
let iter = v.into_iter().skip(beginning_rows_to_skip as usize);
|
||||
|
||||
Ok(iter.into_pipeline_data(engine_state.ctrlc.clone()))
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use crate::math::avg::average;
|
||||
use crate::math::utils::run_with_function;
|
||||
use nu_protocol::ast::Call;
|
||||
|
@ -72,14 +74,14 @@ pub fn median(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
|||
rhs_span: elem[1].span()?,
|
||||
});
|
||||
}
|
||||
Ok(elem[0].partial_cmp(&elem[1]).unwrap())
|
||||
Ok(elem[0].partial_cmp(&elem[1]).unwrap_or(Ordering::Equal))
|
||||
})
|
||||
.find(|elem| elem.is_err())
|
||||
{
|
||||
return Err(values);
|
||||
}
|
||||
|
||||
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
|
||||
|
||||
match take {
|
||||
Pick::Median => {
|
||||
|
|
|
@ -78,7 +78,7 @@ pub fn mode(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
|||
rhs_span: elem[1].span()?,
|
||||
});
|
||||
}
|
||||
Ok(elem[0].partial_cmp(&elem[1]).unwrap())
|
||||
Ok(elem[0].partial_cmp(&elem[1]).unwrap_or(Ordering::Equal))
|
||||
})
|
||||
.find(|elem| elem.is_err())
|
||||
{
|
||||
|
@ -87,7 +87,7 @@ pub fn mode(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
|||
//In e-q, Value doesn't implement Hash or Eq, so we have to get the values inside
|
||||
// But f64 doesn't implement Hash, so we get the binary representation to use as
|
||||
// key in the HashMap
|
||||
let hashable_values: Result<Vec<HashableType>, ShellError> = values
|
||||
let hashable_values = values
|
||||
.iter()
|
||||
.map(|val| match val {
|
||||
Value::Int { val, .. } => Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Int)),
|
||||
|
@ -102,16 +102,13 @@ pub fn mode(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
|||
}
|
||||
other => Err(ShellError::UnsupportedInput(
|
||||
"Unable to give a result with this input".to_string(),
|
||||
other.span().unwrap(),
|
||||
other.span()?,
|
||||
)),
|
||||
})
|
||||
.collect::<Result<Vec<HashableType>, ShellError>>();
|
||||
if let Err(not_hashable) = hashable_values {
|
||||
return Err(not_hashable);
|
||||
}
|
||||
.collect::<Result<Vec<HashableType>, ShellError>>()?;
|
||||
|
||||
let mut frequency_map = std::collections::HashMap::new();
|
||||
for v in hashable_values.unwrap() {
|
||||
for v in hashable_values {
|
||||
let counter = frequency_map.entry(v).or_insert(0);
|
||||
*counter += 1;
|
||||
}
|
||||
|
@ -132,7 +129,7 @@ pub fn mode(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
|||
}
|
||||
}
|
||||
|
||||
modes.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
modes.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
|
||||
Ok(Value::List {
|
||||
vals: modes,
|
||||
span: *head,
|
||||
|
|
|
@ -84,10 +84,27 @@ impl Command for Kill {
|
|||
{
|
||||
return Err(ShellError::IncompatibleParameters {
|
||||
left_message: "force".to_string(),
|
||||
left_span: call.get_named_arg("force").unwrap().span,
|
||||
left_span: call
|
||||
.get_named_arg("force")
|
||||
.ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"Flag error".into(),
|
||||
"flag force not found".into(),
|
||||
call.head,
|
||||
)
|
||||
})?
|
||||
.span,
|
||||
right_message: "signal".to_string(),
|
||||
right_span: span(&[
|
||||
call.get_named_arg("signal").unwrap().span,
|
||||
call.get_named_arg("signal")
|
||||
.ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"Flag error".into(),
|
||||
"flag signal not found".into(),
|
||||
call.head,
|
||||
)
|
||||
})?
|
||||
.span,
|
||||
signal_span,
|
||||
]),
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ impl Command for Format {
|
|||
match specified_pattern {
|
||||
Err(e) => Err(e),
|
||||
Ok(pattern) => {
|
||||
let string_pattern = pattern.as_string().unwrap();
|
||||
let string_pattern = pattern.as_string()?;
|
||||
let ops = extract_formatting_operations(string_pattern);
|
||||
format(input, &ops, call.head)
|
||||
}
|
||||
|
@ -184,9 +184,7 @@ fn format_record(
|
|||
val: col_name.clone(),
|
||||
span: Span::unknown(),
|
||||
}]) {
|
||||
Ok(value_at_column) => {
|
||||
output.push_str(value_at_column.as_string().unwrap().as_str())
|
||||
}
|
||||
Ok(value_at_column) => output.push_str(value_at_column.as_string()?.as_str()),
|
||||
Err(se) => return Err(se),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ fn action(
|
|||
span: head,
|
||||
}
|
||||
} else {
|
||||
let c = character.as_ref().unwrap(); // we already know this flag needs to exist because the command is type checked before we call the action function
|
||||
let c = character.as_ref().expect("we already know this flag needs to exist because the command is type checked before we call the action function");
|
||||
let mut res = c.repeat(s - val.chars().count());
|
||||
res += val;
|
||||
Value::String {
|
||||
|
|
|
@ -143,7 +143,7 @@ fn action(
|
|||
}
|
||||
} else {
|
||||
let mut res = val.to_string();
|
||||
res += &character.as_ref().unwrap().repeat(s - val.chars().count());
|
||||
res += &character.as_ref().expect("we already know this flag needs to exist because the command is type checked before we call the action function").repeat(s - val.chars().count());
|
||||
Value::String {
|
||||
val: res,
|
||||
span: head,
|
||||
|
|
|
@ -143,7 +143,7 @@ where
|
|||
input,
|
||||
);
|
||||
let to_trim = match options.character.as_ref() {
|
||||
Some(v) => v.as_string().unwrap().chars().next(),
|
||||
Some(v) => v.as_string()?.chars().next(),
|
||||
None => None,
|
||||
};
|
||||
|
||||
|
|
|
@ -59,19 +59,21 @@ impl Command for External {
|
|||
args,
|
||||
last_expression,
|
||||
env_vars,
|
||||
call,
|
||||
};
|
||||
command.run_with_input(engine_state, input, config)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExternalCommand {
|
||||
pub struct ExternalCommand<'call> {
|
||||
pub name: Spanned<String>,
|
||||
pub args: Vec<String>,
|
||||
pub last_expression: bool,
|
||||
pub env_vars: HashMap<String, String>,
|
||||
pub call: &'call Call,
|
||||
}
|
||||
|
||||
impl ExternalCommand {
|
||||
impl<'call> ExternalCommand<'call> {
|
||||
pub fn run_with_input(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
|
@ -84,7 +86,8 @@ impl ExternalCommand {
|
|||
|
||||
// TODO. We don't have a way to know the current directory
|
||||
// This should be information from the EvaluationContex or EngineState
|
||||
let path = env::current_dir().unwrap();
|
||||
let path = env::current_dir()?;
|
||||
|
||||
process.current_dir(path);
|
||||
|
||||
process.envs(&self.env_vars);
|
||||
|
@ -145,16 +148,12 @@ impl ExternalCommand {
|
|||
// If this external is not the last expression, then its output is piped to a channel
|
||||
// and we create a ValueStream that can be consumed
|
||||
if !last_expression {
|
||||
let stdout = child
|
||||
.stdout
|
||||
.take()
|
||||
.ok_or_else(|| {
|
||||
ShellError::ExternalCommand(
|
||||
"Error taking stdout from external".to_string(),
|
||||
span,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
let stdout = child.stdout.take().ok_or_else(|| {
|
||||
ShellError::ExternalCommand(
|
||||
"Error taking stdout from external".to_string(),
|
||||
span,
|
||||
)
|
||||
})?;
|
||||
|
||||
// Stdout is read using the Buffer reader. It will do so until there is an
|
||||
// error or there are no more bytes to read
|
||||
|
|
|
@ -5,7 +5,8 @@ use nu_engine::CallExt;
|
|||
use nu_protocol::{
|
||||
ast::{Call, PathMember},
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Config, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value,
|
||||
Category, Config, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions};
|
||||
use terminal_size::{Height, Width};
|
||||
|
@ -76,7 +77,7 @@ prints out the list properly."#
|
|||
separator_param,
|
||||
env_str,
|
||||
use_grid_icons,
|
||||
))
|
||||
)?)
|
||||
} else {
|
||||
Ok(PipelineData::new(call.head))
|
||||
}
|
||||
|
@ -93,7 +94,7 @@ prints out the list properly."#
|
|||
separator_param,
|
||||
env_str,
|
||||
use_grid_icons,
|
||||
))
|
||||
)?)
|
||||
} else {
|
||||
// dbg!(data);
|
||||
Ok(PipelineData::new(call.head))
|
||||
|
@ -115,7 +116,7 @@ prints out the list properly."#
|
|||
separator_param,
|
||||
env_str,
|
||||
use_grid_icons,
|
||||
))
|
||||
)?)
|
||||
}
|
||||
x => {
|
||||
// dbg!("other value");
|
||||
|
@ -142,7 +143,7 @@ fn create_grid_output(
|
|||
separator_param: Option<String>,
|
||||
env_str: Option<String>,
|
||||
use_grid_icons: bool,
|
||||
) -> PipelineData {
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let ls_colors = match env_str {
|
||||
Some(s) => LsColors::from_string(&s),
|
||||
None => LsColors::default(),
|
||||
|
@ -173,7 +174,7 @@ fn create_grid_output(
|
|||
if use_grid_icons {
|
||||
let no_ansi = strip_ansi(&value);
|
||||
let path = std::path::Path::new(&no_ansi);
|
||||
let icon = icon_for_file(path);
|
||||
let icon = icon_for_file(path)?;
|
||||
let ls_colors_style = ls_colors.style_for_path(path);
|
||||
// eprintln!("ls_colors_style: {:?}", &ls_colors_style);
|
||||
|
||||
|
@ -212,18 +213,20 @@ fn create_grid_output(
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(grid_display) = grid.fit_into_width(cols as usize) {
|
||||
Value::String {
|
||||
val: grid_display.to_string(),
|
||||
span: call.head,
|
||||
Ok(
|
||||
if let Some(grid_display) = grid.fit_into_width(cols as usize) {
|
||||
Value::String {
|
||||
val: grid_display.to_string(),
|
||||
span: call.head,
|
||||
}
|
||||
} else {
|
||||
Value::String {
|
||||
val: format!("Couldn't fit grid into {} columns!", cols),
|
||||
span: call.head,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Value::String {
|
||||
val: format!("Couldn't fit grid into {} columns!", cols),
|
||||
span: call.head,
|
||||
}
|
||||
}
|
||||
.into_pipeline_data()
|
||||
.into_pipeline_data(),
|
||||
)
|
||||
}
|
||||
|
||||
fn convert_to_list(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use lazy_static::lazy_static;
|
||||
use nu_protocol::{ShellError, Span};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
|
@ -129,23 +130,47 @@ lazy_static! {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn icon_for_file(file_path: &Path) -> char {
|
||||
pub fn icon_for_file(file_path: &Path) -> Result<char, ShellError> {
|
||||
let extensions = Box::new(FileExtensions);
|
||||
let fp = format!("{}", file_path.display());
|
||||
|
||||
if let Some(icon) = MAP_BY_NAME.get(&fp[..]) {
|
||||
*icon
|
||||
Ok(*icon)
|
||||
} else if file_path.is_dir() {
|
||||
match file_path.file_name().unwrap().to_str().unwrap() {
|
||||
let str = file_path
|
||||
.file_name()
|
||||
.ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"File name error".into(),
|
||||
"Unable to get file name".into(),
|
||||
Span::unknown(),
|
||||
)
|
||||
})?
|
||||
.to_str()
|
||||
.ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
Span::unknown(),
|
||||
)
|
||||
})?;
|
||||
Ok(match str {
|
||||
"bin" => '\u{e5fc}', //
|
||||
".git" => '\u{f1d3}', //
|
||||
".idea" => '\u{e7b5}', //
|
||||
_ => '\u{f115}', //
|
||||
}
|
||||
})
|
||||
} else if let Some(icon) = extensions.icon_file(file_path) {
|
||||
icon
|
||||
Ok(icon)
|
||||
} else if let Some(ext) = file_path.extension().as_ref() {
|
||||
match ext.to_str().unwrap() {
|
||||
let str = ext.to_str().ok_or_else(|| {
|
||||
ShellError::LabeledError(
|
||||
"Unable to get str error".into(),
|
||||
"Unable to convert to str file name".into(),
|
||||
Span::unknown(),
|
||||
)
|
||||
})?;
|
||||
Ok(match str {
|
||||
"ai" => '\u{e7b4}', //
|
||||
"android" => '\u{e70e}', //
|
||||
"apk" => '\u{e70e}', //
|
||||
|
@ -372,9 +397,9 @@ pub fn icon_for_file(file_path: &Path) -> char {
|
|||
"zsh-theme" => '\u{f489}', //
|
||||
"zshrc" => '\u{f489}', //
|
||||
_ => '\u{f15b}', //
|
||||
}
|
||||
})
|
||||
} else {
|
||||
'\u{f016}'
|
||||
Ok('\u{f016}')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ impl Value {
|
|||
let (cols, vals) = value.as_record()?;
|
||||
let mut hm = HashMap::new();
|
||||
for (k, v) in cols.iter().zip(vals) {
|
||||
hm.insert(k.to_string(), v.as_string().unwrap());
|
||||
hm.insert(k.to_string(), v.as_string()?);
|
||||
}
|
||||
config.color_config = hm;
|
||||
}
|
||||
|
|
|
@ -227,13 +227,14 @@ impl EngineState {
|
|||
let path = decl.is_plugin().expect("plugin should have file name");
|
||||
let file_name = path.to_str().expect("path should be a str");
|
||||
|
||||
let line = serde_json::to_string_pretty(&decl.signature())
|
||||
serde_json::to_string_pretty(&decl.signature())
|
||||
.map(|signature| format!("register {} {}\n\n", file_name, signature))
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
|
||||
plugin_file
|
||||
.write_all(line.as_bytes())
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))
|
||||
.and_then(|line| {
|
||||
plugin_file
|
||||
.write_all(line.as_bytes())
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -248,40 +249,6 @@ impl EngineState {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn update_plugin_file_1(&self) -> Result<(), ShellError> {
|
||||
use std::io::Write;
|
||||
|
||||
// Updating the signatures plugin file with the added signatures
|
||||
if let Some(plugin_path) = &self.plugin_signatures {
|
||||
// Always creating the file which will erase previous signatures
|
||||
let mut plugin_file = std::fs::File::create(plugin_path.as_path())
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
|
||||
// Plugin definitions with parsed signature
|
||||
for decl in self.plugin_decls() {
|
||||
// A successful plugin registration already includes the plugin filename
|
||||
// No need to check the None option
|
||||
let path = decl.is_plugin().expect("plugin should have file name");
|
||||
let file_name = path.to_str().expect("path should be a str");
|
||||
|
||||
let line = serde_json::to_string_pretty(&decl.signature())
|
||||
.map(|signature| format!("register {} {}\n\n", file_name, signature))
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
|
||||
plugin_file
|
||||
.write_all(line.as_bytes())
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ShellError::PluginFailedToLoad(
|
||||
"Plugin file not found".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_files(&self) -> usize {
|
||||
self.files.len()
|
||||
}
|
||||
|
|
|
@ -875,7 +875,7 @@ impl WrappedTable {
|
|||
break;
|
||||
}
|
||||
|
||||
writeln!(&mut total_output, "{}", output).unwrap();
|
||||
writeln!(&mut total_output, "{}", output).expect("writing should be done to buffer");
|
||||
}
|
||||
total_output
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ impl CompletionActionHandler for FuzzyCompletion {
|
|||
.default(0)
|
||||
.items(&selections[..])
|
||||
.interact_on_opt(&Term::stdout())
|
||||
.unwrap();
|
||||
.expect("Fuzzy completion interact on operation");
|
||||
let _ = crossterm::terminal::enable_raw_mode();
|
||||
|
||||
if let Some(result) = result {
|
||||
|
@ -85,7 +85,7 @@ fn main() -> Result<()> {
|
|||
// miette::set_panic_hook();
|
||||
let miette_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |x| {
|
||||
crossterm::terminal::disable_raw_mode().unwrap();
|
||||
crossterm::terminal::disable_raw_mode().expect("unable to disable raw mode");
|
||||
miette_hook(x);
|
||||
}));
|
||||
|
||||
|
|
Loading…
Reference in a new issue