mirror of
https://github.com/nushell/nushell.git
synced 2024-12-23 15:39:06 +01:00
Clean up some unwraps (#1147)
This commit is contained in:
parent
25298d35e4
commit
aa577bf9bf
@ -13,10 +13,10 @@ lazy_static! {
|
||||
|
||||
// got from https://github.com/mitsuhiko/insta/blob/b113499249584cb650150d2d01ed96ee66db6b30/src/runtime.rs#L67-L88
|
||||
|
||||
fn get_cargo_workspace(manifest_dir: &str) -> Option<&Path> {
|
||||
let mut workspaces = WORKSPACES.lock().unwrap();
|
||||
fn get_cargo_workspace(manifest_dir: &str) -> Result<Option<&Path>, Box<dyn std::error::Error>> {
|
||||
let mut workspaces = WORKSPACES.lock()?;
|
||||
if let Some(rv) = workspaces.get(manifest_dir) {
|
||||
Some(rv)
|
||||
Ok(Some(rv))
|
||||
} else {
|
||||
#[derive(Deserialize)]
|
||||
struct Manifest {
|
||||
@ -26,12 +26,11 @@ fn get_cargo_workspace(manifest_dir: &str) -> Option<&Path> {
|
||||
.arg("metadata")
|
||||
.arg("--format-version=1")
|
||||
.current_dir(manifest_dir)
|
||||
.output()
|
||||
.unwrap();
|
||||
let manifest: Manifest = serde_json::from_slice(&output.stdout).unwrap();
|
||||
.output()?;
|
||||
let manifest: Manifest = serde_json::from_slice(&output.stdout)?;
|
||||
let path = Box::leak(Box::new(PathBuf::from(manifest.workspace_root)));
|
||||
workspaces.insert(manifest_dir.to_string(), path.as_path());
|
||||
workspaces.get(manifest_dir).cloned()
|
||||
Ok(workspaces.get(manifest_dir).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +42,7 @@ struct Feature {
|
||||
}
|
||||
|
||||
pub fn build() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let input = env::var("CARGO_MANIFEST_DIR")?;
|
||||
|
||||
let all_on = env::var("NUSHELL_ENABLE_ALL_FLAGS").is_ok();
|
||||
let flags: HashSet<String> = env::var("NUSHELL_ENABLE_FLAGS")
|
||||
@ -56,7 +55,7 @@ pub fn build() -> Result<(), Box<dyn std::error::Error>> {
|
||||
);
|
||||
}
|
||||
|
||||
let workspace = match get_cargo_workspace(&input) {
|
||||
let workspace = match get_cargo_workspace(&input)? {
|
||||
// If the crate is being downloaded from crates.io, it won't have a workspace root, and that's ok
|
||||
None => return Ok(()),
|
||||
Some(workspace) => workspace,
|
||||
|
@ -3,14 +3,14 @@ use crate::parse::token_tree_builder::TokenTreeBuilder as b;
|
||||
use crate::Span;
|
||||
|
||||
#[test]
|
||||
fn supplies_tokens() {
|
||||
fn supplies_tokens() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let tokens = b::token_list(vec![b::var("it"), b::op("."), b::bare("cpu")]);
|
||||
let (tokens, _) = b::build(tokens);
|
||||
|
||||
let tokens = tokens.expect_list();
|
||||
let mut iterator = TokensIterator::all(tokens, Span::unknown());
|
||||
|
||||
iterator.next().unwrap().expect_var();
|
||||
iterator.next().unwrap().expect_dot();
|
||||
iterator.next().unwrap().expect_bare();
|
||||
iterator.next()?.expect_var();
|
||||
iterator.next()?.expect_dot();
|
||||
iterator.next()?.expect_bare();
|
||||
}
|
||||
|
@ -195,40 +195,32 @@ struct RawImageBuffer {
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
fn load_from_png_buffer(buffer: &[u8]) -> Option<RawImageBuffer> {
|
||||
fn load_from_png_buffer(buffer: &[u8]) -> Result<RawImageBuffer, Box<dyn std::error::Error>> {
|
||||
use image::ImageDecoder;
|
||||
|
||||
let decoder = image::png::PNGDecoder::new(buffer);
|
||||
if decoder.is_err() {
|
||||
return None;
|
||||
}
|
||||
let decoder = decoder.unwrap();
|
||||
let decoder = image::png::PNGDecoder::new(buffer)?;
|
||||
|
||||
let dimensions = decoder.dimensions();
|
||||
let colortype = decoder.colortype();
|
||||
let buffer = decoder.read_image().unwrap();
|
||||
let buffer = decoder.read_image()?;
|
||||
|
||||
Some(RawImageBuffer {
|
||||
Ok(RawImageBuffer {
|
||||
dimensions,
|
||||
colortype,
|
||||
buffer,
|
||||
})
|
||||
}
|
||||
|
||||
fn load_from_jpg_buffer(buffer: &[u8]) -> Option<RawImageBuffer> {
|
||||
fn load_from_jpg_buffer(buffer: &[u8]) -> Result<RawImageBuffer, Box<dyn std::error::Error>> {
|
||||
use image::ImageDecoder;
|
||||
|
||||
let decoder = image::jpeg::JPEGDecoder::new(buffer);
|
||||
if decoder.is_err() {
|
||||
return None;
|
||||
}
|
||||
let decoder = decoder.unwrap();
|
||||
let decoder = image::jpeg::JPEGDecoder::new(buffer)?;
|
||||
|
||||
let dimensions = decoder.dimensions();
|
||||
let colortype = decoder.colortype();
|
||||
let buffer = decoder.read_image().unwrap();
|
||||
let buffer = decoder.read_image()?;
|
||||
|
||||
Some(RawImageBuffer {
|
||||
Ok(RawImageBuffer {
|
||||
dimensions,
|
||||
colortype,
|
||||
buffer,
|
||||
@ -242,16 +234,16 @@ pub fn view_contents(
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut raw_image_buffer = load_from_png_buffer(buffer);
|
||||
|
||||
if raw_image_buffer.is_none() {
|
||||
if raw_image_buffer.is_err() {
|
||||
raw_image_buffer = load_from_jpg_buffer(buffer);
|
||||
}
|
||||
|
||||
if raw_image_buffer.is_none() {
|
||||
if raw_image_buffer.is_err() {
|
||||
//Not yet supported
|
||||
outln!("{:?}", buffer.hex_dump());
|
||||
return Ok(());
|
||||
}
|
||||
let raw_image_buffer = raw_image_buffer.unwrap();
|
||||
let raw_image_buffer = raw_image_buffer?;
|
||||
|
||||
let mut render_context: RenderContext = RenderContext::blank(lores_mode);
|
||||
let _ = render_context.update();
|
||||
@ -264,7 +256,7 @@ pub fn view_contents(
|
||||
raw_image_buffer.dimensions.1 as u32,
|
||||
raw_image_buffer.buffer,
|
||||
)
|
||||
.unwrap();
|
||||
.ok_or("Cannot convert image data")?;
|
||||
|
||||
let resized_img = image::imageops::resize(
|
||||
&img,
|
||||
@ -287,7 +279,7 @@ pub fn view_contents(
|
||||
raw_image_buffer.dimensions.1 as u32,
|
||||
raw_image_buffer.buffer,
|
||||
)
|
||||
.unwrap();
|
||||
.ok_or("Cannot convert image data")?;
|
||||
|
||||
let resized_img = image::imageops::resize(
|
||||
&img,
|
||||
@ -374,8 +366,8 @@ pub fn view_contents_interactive(
|
||||
let image_buffer = nes.image_buffer();
|
||||
|
||||
let slice = unsafe { std::slice::from_raw_parts(image_buffer, 256 * 240 * 4) };
|
||||
let img =
|
||||
image::ImageBuffer::<image::Rgba<u8>, &[u8]>::from_raw(256, 240, slice).unwrap();
|
||||
let img = image::ImageBuffer::<image::Rgba<u8>, &[u8]>::from_raw(256, 240, slice)
|
||||
.ok_or("Cannot convert image data")?;
|
||||
let resized_img = image::imageops::resize(
|
||||
&img,
|
||||
render_context.width as u32,
|
||||
|
@ -63,7 +63,13 @@ impl Plugin for Fetch {
|
||||
|
||||
fn filter(&mut self, value: Value) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
Ok(vec![block_on(fetch_helper(
|
||||
&self.path.clone().unwrap(),
|
||||
&self.path.clone().ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
"internal error: path not set",
|
||||
"path not set",
|
||||
&value.tag,
|
||||
)
|
||||
})?,
|
||||
self.has_raw,
|
||||
value,
|
||||
))])
|
||||
@ -93,7 +99,7 @@ async fn fetch_helper(path: &Value, has_raw: bool, row: Value) -> ReturnValue {
|
||||
if let Err(e) = result {
|
||||
return Err(e);
|
||||
}
|
||||
let (file_extension, contents, contents_tag) = result.unwrap();
|
||||
let (file_extension, contents, contents_tag) = result?;
|
||||
|
||||
let file_extension = if has_raw {
|
||||
None
|
||||
@ -131,7 +137,13 @@ pub async fn fetch(
|
||||
match response {
|
||||
Ok(mut r) => match r.headers().get("content-type") {
|
||||
Some(content_type) => {
|
||||
let content_type = Mime::from_str(content_type).unwrap();
|
||||
let content_type = Mime::from_str(content_type).map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
format!("MIME type unknown: {}", content_type),
|
||||
"given unknown MIME type",
|
||||
span,
|
||||
)
|
||||
})?;
|
||||
match (content_type.type_(), content_type.subtype()) {
|
||||
(mime::APPLICATION, mime::XML) => Ok((
|
||||
Some("xml".to_string()),
|
||||
@ -225,7 +237,13 @@ pub async fn fetch(
|
||||
)),
|
||||
(mime::TEXT, mime::PLAIN) => {
|
||||
let path_extension = url::Url::parse(location)
|
||||
.unwrap()
|
||||
.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
format!("Cannot parse URL: {}", location),
|
||||
"cannot parse",
|
||||
span,
|
||||
)
|
||||
})?
|
||||
.path_segments()
|
||||
.and_then(|segments| segments.last())
|
||||
.and_then(|name| if name.is_empty() { None } else { Some(name) })
|
||||
|
@ -152,24 +152,27 @@ mod tests {
|
||||
use nu_plugin::test_helpers::value::string;
|
||||
|
||||
#[test]
|
||||
fn major() {
|
||||
fn major() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Major);
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), string("1.0.0").value);
|
||||
assert_eq!(inc.apply("0.1.3")?, string("1.0.0").value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minor() {
|
||||
fn minor() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Minor);
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), string("0.2.0").value);
|
||||
assert_eq!(inc.apply("0.1.3")?, string("0.2.0").value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn patch() {
|
||||
fn patch() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Patch);
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), string("0.1.4").value);
|
||||
assert_eq!(inc.apply("0.1.3")?, string("0.1.4").value);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ struct Match {
|
||||
|
||||
impl Match {
|
||||
#[allow(clippy::trivial_regex)]
|
||||
fn new() -> Self {
|
||||
Match {
|
||||
fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
||||
Ok(Match {
|
||||
column: String::new(),
|
||||
regex: Regex::new("").unwrap(),
|
||||
}
|
||||
regex: Regex::new("")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,14 +49,20 @@ impl Plugin for Match {
|
||||
match &args[1] {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||
..
|
||||
tag,
|
||||
} => {
|
||||
self.regex = Regex::new(s).unwrap();
|
||||
self.regex = Regex::new(s).map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
"Internal error while creating regex",
|
||||
"internal error created by pattern",
|
||||
tag,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
Value { tag, .. } => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Unrecognized type in params",
|
||||
"value",
|
||||
"unexpected value",
|
||||
tag,
|
||||
));
|
||||
}
|
||||
@ -102,6 +108,7 @@ impl Plugin for Match {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
serve_plugin(&mut Match::new());
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
serve_plugin(&mut Match::new()?);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ struct Post {
|
||||
user: Option<String>,
|
||||
password: Option<String>,
|
||||
headers: Vec<HeaderKind>,
|
||||
tag: Tag,
|
||||
}
|
||||
|
||||
impl Post {
|
||||
@ -37,6 +38,7 @@ impl Post {
|
||||
user: None,
|
||||
password: None,
|
||||
headers: vec![],
|
||||
tag: Tag::unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,15 +63,20 @@ impl Post {
|
||||
file => Some(file.clone()),
|
||||
};
|
||||
|
||||
self.user = call_info.args.get("user").map(|x| x.as_string().unwrap());
|
||||
self.user = match call_info.args.get("user") {
|
||||
Some(user) => Some(user.as_string()?),
|
||||
None => None,
|
||||
};
|
||||
|
||||
self.password = call_info
|
||||
.args
|
||||
.get("password")
|
||||
.map(|x| x.as_string().unwrap());
|
||||
self.password = match call_info.args.get("password") {
|
||||
Some(password) => Some(password.as_string()?),
|
||||
None => None,
|
||||
};
|
||||
|
||||
self.headers = get_headers(&call_info)?;
|
||||
|
||||
self.tag = call_info.name_tag;
|
||||
|
||||
ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value())
|
||||
}
|
||||
}
|
||||
@ -107,9 +114,13 @@ impl Plugin for Post {
|
||||
|
||||
fn filter(&mut self, row: Value) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
Ok(vec![block_on(post_helper(
|
||||
&self.path.clone().unwrap(),
|
||||
&self.path.clone().ok_or_else(|| {
|
||||
ShellError::labeled_error("expected a 'path'", "expected a 'path'", &self.tag)
|
||||
})?,
|
||||
self.has_raw,
|
||||
&self.body.clone().unwrap(),
|
||||
&self.body.clone().ok_or_else(|| {
|
||||
ShellError::labeled_error("expected a 'body'", "expected a 'body'", &self.tag)
|
||||
})?,
|
||||
self.user.clone(),
|
||||
self.password.clone(),
|
||||
&self.headers.clone(),
|
||||
@ -154,9 +165,7 @@ async fn post_helper(
|
||||
};
|
||||
|
||||
let (file_extension, contents, contents_tag) =
|
||||
post(&path_str, &body, user, password, &headers, path_tag.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
post(&path_str, &body, user, password, &headers, path_tag.clone()).await?;
|
||||
|
||||
let file_extension = if has_raw {
|
||||
None
|
||||
@ -252,7 +261,13 @@ pub async fn post(
|
||||
match response {
|
||||
Ok(mut r) => match r.headers().get("content-type") {
|
||||
Some(content_type) => {
|
||||
let content_type = Mime::from_str(content_type).unwrap();
|
||||
let content_type = Mime::from_str(content_type).map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
format!("Unknown MIME type: {}", content_type),
|
||||
"unknown MIME type",
|
||||
&tag,
|
||||
)
|
||||
})?;
|
||||
match (content_type.type_(), content_type.subtype()) {
|
||||
(mime::APPLICATION, mime::XML) => Ok((
|
||||
Some("xml".to_string()),
|
||||
@ -332,7 +347,13 @@ pub async fn post(
|
||||
)),
|
||||
(mime::TEXT, mime::PLAIN) => {
|
||||
let path_extension = url::Url::parse(location)
|
||||
.unwrap()
|
||||
.map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
format!("could not parse URL: {}", location),
|
||||
"could not parse URL",
|
||||
&tag,
|
||||
)
|
||||
})?
|
||||
.path_segments()
|
||||
.and_then(|segments| segments.last())
|
||||
.and_then(|name| if name.is_empty() { None } else { Some(name) })
|
||||
@ -412,7 +433,13 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
|
||||
serde_json::Number::from_f64(
|
||||
f.to_f64().expect("TODO: What about really big decimals?"),
|
||||
)
|
||||
.unwrap(),
|
||||
.ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
"Can not convert big decimal to f64",
|
||||
"cannot convert big decimal to f64",
|
||||
&v.tag,
|
||||
)
|
||||
})?,
|
||||
),
|
||||
UntaggedValue::Primitive(Primitive::Int(i)) => {
|
||||
serde_json::Value::Number(serde_json::Number::from(CoerceInto::<i64>::coerce_into(
|
||||
@ -448,13 +475,22 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
|
||||
UntaggedValue::Block(_) | UntaggedValue::Primitive(Primitive::Range(_)) => {
|
||||
serde_json::Value::Null
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Binary(b)) => serde_json::Value::Array(
|
||||
b.iter()
|
||||
.map(|x| {
|
||||
serde_json::Value::Number(serde_json::Number::from_f64(*x as f64).unwrap())
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
UntaggedValue::Primitive(Primitive::Binary(b)) => {
|
||||
let mut output = vec![];
|
||||
|
||||
for item in b.iter() {
|
||||
output.push(serde_json::Value::Number(
|
||||
serde_json::Number::from_f64(*item as f64).ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
"Cannot create number from from f64",
|
||||
"cannot created number from f64",
|
||||
&v.tag,
|
||||
)
|
||||
})?,
|
||||
));
|
||||
}
|
||||
serde_json::Value::Array(output)
|
||||
}
|
||||
UntaggedValue::Row(o) => {
|
||||
let mut m = serde_json::Map::new();
|
||||
for (k, v) in o.entries.iter() {
|
||||
|
@ -52,7 +52,7 @@ impl Plugin for Str {
|
||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||
..
|
||||
} => {
|
||||
self.for_substring(s.to_string());
|
||||
self.for_substring(s.to_string())?;
|
||||
}
|
||||
_ => {
|
||||
return Err(ShellError::labeled_error(
|
||||
@ -77,12 +77,30 @@ impl Plugin for Str {
|
||||
if args.has("find-replace") {
|
||||
if let Some(Value {
|
||||
value: UntaggedValue::Table(arguments),
|
||||
..
|
||||
tag,
|
||||
}) = args.get("find-replace")
|
||||
{
|
||||
self.for_replace(ReplaceAction::FindAndReplace(
|
||||
arguments.get(0).unwrap().as_string()?,
|
||||
arguments.get(1).unwrap().as_string()?,
|
||||
arguments
|
||||
.get(0)
|
||||
.ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
"expected file and replace strings eg) [find replace]",
|
||||
"missing find-replace values",
|
||||
tag,
|
||||
)
|
||||
})?
|
||||
.as_string()?,
|
||||
arguments
|
||||
.get(1)
|
||||
.ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
"expected file and replace strings eg) [find replace]",
|
||||
"missing find-replace values",
|
||||
tag,
|
||||
)
|
||||
})?
|
||||
.as_string()?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -112,15 +112,21 @@ impl Str {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_substring(&mut self, s: String) {
|
||||
pub fn for_substring(&mut self, s: String) -> Result<(), ShellError> {
|
||||
let v: Vec<&str> = s.split(',').collect();
|
||||
let start: usize = match v[0] {
|
||||
"" => 0,
|
||||
_ => v[0].trim().parse().unwrap(),
|
||||
_ => v[0]
|
||||
.trim()
|
||||
.parse()
|
||||
.map_err(|_| ShellError::untagged_runtime_error("Could not perform substring"))?,
|
||||
};
|
||||
let end: usize = match v[1] {
|
||||
"" => usize::max_value(),
|
||||
_ => v[1].trim().parse().unwrap(),
|
||||
_ => v[1]
|
||||
.trim()
|
||||
.parse()
|
||||
.map_err(|_| ShellError::untagged_runtime_error("Could not perform substring"))?,
|
||||
};
|
||||
if start > end {
|
||||
self.log_error("End must be greater than or equal to Start");
|
||||
@ -129,6 +135,8 @@ impl Str {
|
||||
} else {
|
||||
self.log_error("can only apply one");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn for_replace(&mut self, mode: ReplaceAction) {
|
||||
@ -206,35 +214,39 @@ pub mod tests {
|
||||
use nu_plugin::test_helpers::value::{int, string};
|
||||
|
||||
#[test]
|
||||
fn downcases() {
|
||||
fn downcases() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_downcase();
|
||||
assert_eq!(strutils.apply("ANDRES").unwrap(), string("andres").value);
|
||||
assert_eq!(strutils.apply("ANDRES")?, string("andres").value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upcases() {
|
||||
fn upcases() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_upcase();
|
||||
assert_eq!(strutils.apply("andres").unwrap(), string("ANDRES").value);
|
||||
assert_eq!(strutils.apply("andres")?, string("ANDRES").value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn converts_to_int() {
|
||||
fn converts_to_int() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_to_int();
|
||||
assert_eq!(strutils.apply("9999").unwrap(), int(9999 as i64).value);
|
||||
assert_eq!(strutils.apply("9999")?, int(9999 as i64).value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces() {
|
||||
fn replaces() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_replace(ReplaceAction::Direct("robalino".to_string()));
|
||||
assert_eq!(strutils.apply("andres").unwrap(), string("robalino").value);
|
||||
assert_eq!(strutils.apply("andres")?, string("robalino").value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_and_replaces() {
|
||||
fn find_and_replaces() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut strutils = Str::new();
|
||||
|
||||
strutils.for_replace(ReplaceAction::FindAndReplace(
|
||||
@ -242,9 +254,7 @@ pub mod tests {
|
||||
"jotandrehuda".to_string(),
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
strutils.apply("wykittens").unwrap(),
|
||||
string("wyjotandrehuda").value
|
||||
);
|
||||
assert_eq!(strutils.apply("wykittens")?, string("wyjotandrehuda").value);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -422,9 +422,11 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
};
|
||||
|
||||
let prompt = {
|
||||
let bytes = strip_ansi_escapes::strip(&colored_prompt).unwrap();
|
||||
|
||||
String::from_utf8_lossy(&bytes).to_string()
|
||||
if let Ok(bytes) = strip_ansi_escapes::strip(&colored_prompt) {
|
||||
String::from_utf8_lossy(&bytes).to_string()
|
||||
} else {
|
||||
"> ".to_string()
|
||||
}
|
||||
};
|
||||
|
||||
rl.helper_mut().expect("No helper").colored_prompt = colored_prompt;
|
||||
|
Loading…
Reference in New Issue
Block a user