Add argument rendering in passive matches
This commit is contained in:
parent
0eb58704a9
commit
6378aa3bcc
|
@ -55,7 +55,8 @@ fn default_word_separators() -> Vec<char> { vec![' ', ',', '.', '\r', '\n', 22u8
|
||||||
fn default_toggle_interval() -> u32 { 230 }
|
fn default_toggle_interval() -> u32 { 230 }
|
||||||
fn default_preserve_clipboard() -> bool {false}
|
fn default_preserve_clipboard() -> bool {false}
|
||||||
fn default_passive_match_regex() -> String{ "(?P<name>:\\p{L}+)(/(?P<args>.*)/)?".to_owned() }
|
fn default_passive_match_regex() -> String{ "(?P<name>:\\p{L}+)(/(?P<args>.*)/)?".to_owned() }
|
||||||
fn default_passive_arg_regex() -> String{ "((\\\\/)|[^/])+".to_owned() }
|
fn default_passive_arg_delimiter() -> char { '/' }
|
||||||
|
fn default_passive_arg_escape() -> char { '\\' }
|
||||||
fn default_backspace_limit() -> i32 { 3 }
|
fn default_backspace_limit() -> i32 { 3 }
|
||||||
fn default_exclude_default_matches() -> bool {false}
|
fn default_exclude_default_matches() -> bool {false}
|
||||||
fn default_matches() -> Vec<Match> { Vec::new() }
|
fn default_matches() -> Vec<Match> { Vec::new() }
|
||||||
|
@ -107,8 +108,11 @@ pub struct Configs {
|
||||||
#[serde(default = "default_passive_match_regex")]
|
#[serde(default = "default_passive_match_regex")]
|
||||||
pub passive_match_regex: String,
|
pub passive_match_regex: String,
|
||||||
|
|
||||||
#[serde(default = "default_passive_arg_regex")]
|
#[serde(default = "default_passive_arg_delimiter")]
|
||||||
pub passive_arg_regex: String,
|
pub passive_arg_delimiter: char,
|
||||||
|
|
||||||
|
#[serde(default = "default_passive_arg_escape")]
|
||||||
|
pub passive_arg_escape: char,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub paste_shortcut: PasteShortcut,
|
pub paste_shortcut: PasteShortcut,
|
||||||
|
@ -159,7 +163,8 @@ impl Configs {
|
||||||
validate_field!(result, self.use_system_agent, default_use_system_agent());
|
validate_field!(result, self.use_system_agent, default_use_system_agent());
|
||||||
validate_field!(result, self.preserve_clipboard, default_preserve_clipboard());
|
validate_field!(result, self.preserve_clipboard, default_preserve_clipboard());
|
||||||
validate_field!(result, self.passive_match_regex, default_passive_match_regex());
|
validate_field!(result, self.passive_match_regex, default_passive_match_regex());
|
||||||
validate_field!(result, self.passive_arg_regex, default_passive_arg_regex());
|
validate_field!(result, self.passive_arg_delimiter, default_passive_arg_delimiter());
|
||||||
|
validate_field!(result, self.passive_arg_escape, default_passive_arg_escape());
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl super::Extension for DateExtension {
|
||||||
String::from("date")
|
String::from("date")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate(&self, params: &Mapping) -> Option<String> {
|
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> {
|
||||||
let now: DateTime<Local> = Local::now();
|
let now: DateTime<Local> = Local::now();
|
||||||
|
|
||||||
let format = params.get(&Value::from("format"));
|
let format = params.get(&Value::from("format"));
|
||||||
|
|
|
@ -26,7 +26,7 @@ mod random;
|
||||||
|
|
||||||
pub trait Extension {
|
pub trait Extension {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
fn calculate(&self, params: &Mapping) -> Option<String>;
|
fn calculate(&self, params: &Mapping, args: &Vec<String>) -> Option<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_extensions() -> Vec<Box<dyn Extension>> {
|
pub fn get_extensions() -> Vec<Box<dyn Extension>> {
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl super::Extension for RandomExtension {
|
||||||
String::from("random")
|
String::from("random")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate(&self, params: &Mapping) -> Option<String> {
|
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> { // TODO: add argument handling
|
||||||
let choices = params.get(&Value::from("choices"));
|
let choices = params.get(&Value::from("choices"));
|
||||||
if choices.is_none() {
|
if choices.is_none() {
|
||||||
warn!("No 'choices' parameter specified for random variable");
|
warn!("No 'choices' parameter specified for random variable");
|
||||||
|
@ -82,7 +82,7 @@ mod tests {
|
||||||
params.insert(Value::from("choices"), Value::from(choices.clone()));
|
params.insert(Value::from("choices"), Value::from(choices.clone()));
|
||||||
|
|
||||||
let extension = RandomExtension::new();
|
let extension = RandomExtension::new();
|
||||||
let output = extension.calculate(¶ms);
|
let output = extension.calculate(¶ms, &vec![]);
|
||||||
|
|
||||||
assert!(output.is_some());
|
assert!(output.is_some());
|
||||||
|
|
||||||
|
@ -90,4 +90,6 @@ mod tests {
|
||||||
|
|
||||||
assert!(choices.iter().any(|x| x == &output));
|
assert!(choices.iter().any(|x| x == &output));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add test with arguments
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ impl super::Extension for ScriptExtension {
|
||||||
String::from("script")
|
String::from("script")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate(&self, params: &Mapping) -> Option<String> {
|
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> { // TODO: add argument handling
|
||||||
let args = params.get(&Value::from("args"));
|
let args = params.get(&Value::from("args"));
|
||||||
if args.is_none() {
|
if args.is_none() {
|
||||||
warn!("No 'args' parameter specified for script variable");
|
warn!("No 'args' parameter specified for script variable");
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl super::Extension for ShellExtension {
|
||||||
String::from("shell")
|
String::from("shell")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate(&self, params: &Mapping) -> Option<String> {
|
fn calculate(&self, params: &Mapping, _: &Vec<String>) -> Option<String> { // TODO: add argument handling
|
||||||
let cmd = params.get(&Value::from("cmd"));
|
let cmd = params.get(&Value::from("cmd"));
|
||||||
if cmd.is_none() {
|
if cmd.is_none() {
|
||||||
warn!("No 'cmd' parameter specified for shell variable");
|
warn!("No 'cmd' parameter specified for shell variable");
|
||||||
|
@ -90,7 +90,7 @@ mod tests {
|
||||||
params.insert(Value::from("cmd"), Value::from("echo hello world"));
|
params.insert(Value::from("cmd"), Value::from("echo hello world"));
|
||||||
|
|
||||||
let extension = ShellExtension::new();
|
let extension = ShellExtension::new();
|
||||||
let output = extension.calculate(¶ms);
|
let output = extension.calculate(¶ms, &vec![]);
|
||||||
|
|
||||||
assert!(output.is_some());
|
assert!(output.is_some());
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ mod tests {
|
||||||
params.insert(Value::from("trim"), Value::from(true));
|
params.insert(Value::from("trim"), Value::from(true));
|
||||||
|
|
||||||
let extension = ShellExtension::new();
|
let extension = ShellExtension::new();
|
||||||
let output = extension.calculate(¶ms);
|
let output = extension.calculate(¶ms, &vec![]);
|
||||||
|
|
||||||
assert!(output.is_some());
|
assert!(output.is_some());
|
||||||
assert_eq!(output.unwrap(), "hello world");
|
assert_eq!(output.unwrap(), "hello world");
|
||||||
|
@ -126,7 +126,7 @@ mod tests {
|
||||||
params.insert(Value::from("trim"), Value::from(true));
|
params.insert(Value::from("trim"), Value::from(true));
|
||||||
|
|
||||||
let extension = ShellExtension::new();
|
let extension = ShellExtension::new();
|
||||||
let output = extension.calculate(¶ms);
|
let output = extension.calculate(¶ms, &vec![]);
|
||||||
|
|
||||||
assert!(output.is_some());
|
assert!(output.is_some());
|
||||||
assert_eq!(output.unwrap(), "hello world");
|
assert_eq!(output.unwrap(), "hello world");
|
||||||
|
@ -139,7 +139,7 @@ mod tests {
|
||||||
params.insert(Value::from("trim"), Value::from("error"));
|
params.insert(Value::from("trim"), Value::from("error"));
|
||||||
|
|
||||||
let extension = ShellExtension::new();
|
let extension = ShellExtension::new();
|
||||||
let output = extension.calculate(¶ms);
|
let output = extension.calculate(¶ms, &vec![]);
|
||||||
|
|
||||||
assert!(output.is_some());
|
assert!(output.is_some());
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
|
@ -157,9 +157,11 @@ mod tests {
|
||||||
params.insert(Value::from("trim"), Value::from(true));
|
params.insert(Value::from("trim"), Value::from(true));
|
||||||
|
|
||||||
let extension = ShellExtension::new();
|
let extension = ShellExtension::new();
|
||||||
let output = extension.calculate(¶ms);
|
let output = extension.calculate(¶ms, &vec![]);
|
||||||
|
|
||||||
assert!(output.is_some());
|
assert!(output.is_some());
|
||||||
assert_eq!(output.unwrap(), "hello world");
|
assert_eq!(output.unwrap(), "hello world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add tests with arguments
|
||||||
}
|
}
|
|
@ -36,9 +36,6 @@ pub struct DefaultRenderer {
|
||||||
|
|
||||||
// Regex used to identify matches (and arguments) in passive expansions
|
// Regex used to identify matches (and arguments) in passive expansions
|
||||||
passive_match_regex: Regex,
|
passive_match_regex: Regex,
|
||||||
|
|
||||||
// Regex used to separate arguments in passive expansions
|
|
||||||
passive_arg_regex: Regex,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefaultRenderer {
|
impl DefaultRenderer {
|
||||||
|
@ -54,15 +51,10 @@ impl DefaultRenderer {
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
panic!("Invalid passive match regex");
|
panic!("Invalid passive match regex");
|
||||||
});
|
});
|
||||||
let passive_arg_regex = Regex::new(&config.passive_arg_regex)
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
panic!("Invalid passive arg regex");
|
|
||||||
});
|
|
||||||
|
|
||||||
DefaultRenderer{
|
DefaultRenderer{
|
||||||
extension_map,
|
extension_map,
|
||||||
passive_match_regex,
|
passive_match_regex,
|
||||||
passive_arg_regex
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +121,7 @@ impl super::Renderer for DefaultRenderer {
|
||||||
// TODO: pass the arguments to the extension
|
// TODO: pass the arguments to the extension
|
||||||
let extension = self.extension_map.get(&variable.var_type);
|
let extension = self.extension_map.get(&variable.var_type);
|
||||||
if let Some(extension) = extension {
|
if let Some(extension) = extension {
|
||||||
let ext_out = extension.calculate(&variable.params);
|
let ext_out = extension.calculate(&variable.params, &args);
|
||||||
if let Some(output) = ext_out {
|
if let Some(output) = ext_out {
|
||||||
output_map.insert(variable.name.clone(), output);
|
output_map.insert(variable.name.clone(), output);
|
||||||
}else{
|
}else{
|
||||||
|
@ -142,11 +134,6 @@ impl super::Renderer for DefaultRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace the arguments
|
|
||||||
// the idea is that every param placeholder, such as $1$, is replaced with
|
|
||||||
// an ArgExtension when loading a match, which renders the argument as output
|
|
||||||
// this is only used as syntactic sugar
|
|
||||||
|
|
||||||
// Replace the variables
|
// Replace the variables
|
||||||
let result = VAR_REGEX.replace_all(&content.replace, |caps: &Captures| {
|
let result = VAR_REGEX.replace_all(&content.replace, |caps: &Captures| {
|
||||||
let var_name = caps.name("name").unwrap().as_str();
|
let var_name = caps.name("name").unwrap().as_str();
|
||||||
|
@ -159,6 +146,9 @@ impl super::Renderer for DefaultRenderer {
|
||||||
content.replace.clone()
|
content.replace.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Render any argument that may be present
|
||||||
|
let target_string = utils::render_args(&target_string, &args);
|
||||||
|
|
||||||
RenderResult::Text(target_string)
|
RenderResult::Text(target_string)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -202,9 +192,9 @@ impl super::Renderer for DefaultRenderer {
|
||||||
}else{
|
}else{
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
let args : Vec<String> = self.passive_arg_regex.split(match_args).into_iter().map(
|
let args : Vec<String> = utils::split_args(match_args,
|
||||||
|arg| arg.to_owned()
|
config.passive_arg_delimiter,
|
||||||
).collect();
|
config.passive_arg_escape);
|
||||||
|
|
||||||
let m = m.unwrap();
|
let m = m.unwrap();
|
||||||
// Render the actual match
|
// Render the actual match
|
||||||
|
@ -242,7 +232,6 @@ mod tests {
|
||||||
fn verify_render(rendered: RenderResult, target: &str) {
|
fn verify_render(rendered: RenderResult, target: &str) {
|
||||||
match rendered {
|
match rendered {
|
||||||
RenderResult::Text(rendered) => {
|
RenderResult::Text(rendered) => {
|
||||||
println!("{}", rendered);
|
|
||||||
assert_eq!(rendered, target);
|
assert_eq!(rendered, target);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -326,4 +315,97 @@ mod tests {
|
||||||
|
|
||||||
verify_render(rendered, result);
|
verify_render(rendered, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_passive_nested_matches_no_args() {
|
||||||
|
let text = ":greet";
|
||||||
|
|
||||||
|
let config = get_config_for(r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ':greet'
|
||||||
|
replace: "hi {{name}}"
|
||||||
|
vars:
|
||||||
|
- name: name
|
||||||
|
type: match
|
||||||
|
params:
|
||||||
|
trigger: ":name"
|
||||||
|
|
||||||
|
- trigger: ':name'
|
||||||
|
replace: john
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let renderer = get_renderer(config.clone());
|
||||||
|
|
||||||
|
let rendered = renderer.render_passive(text, &config);
|
||||||
|
|
||||||
|
verify_render(rendered, "hi john");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_passive_simple_match_with_args() {
|
||||||
|
let text = ":greet/Jon/";
|
||||||
|
|
||||||
|
let config = get_config_for(r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ':greet'
|
||||||
|
replace: "Hi $0$"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let renderer = get_renderer(config.clone());
|
||||||
|
|
||||||
|
let rendered = renderer.render_passive(text, &config);
|
||||||
|
|
||||||
|
verify_render(rendered, "Hi Jon");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_passive_simple_match_with_multiple_args() {
|
||||||
|
let text = ":greet/Jon/Snow/";
|
||||||
|
|
||||||
|
let config = get_config_for(r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ':greet'
|
||||||
|
replace: "Hi $0$, there is $1$ outside"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let renderer = get_renderer(config.clone());
|
||||||
|
|
||||||
|
let rendered = renderer.render_passive(text, &config);
|
||||||
|
|
||||||
|
verify_render(rendered, "Hi Jon, there is Snow outside");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_passive_simple_match_with_escaped_args() {
|
||||||
|
let text = ":greet/Jon/10\\/12/";
|
||||||
|
|
||||||
|
let config = get_config_for(r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ':greet'
|
||||||
|
replace: "Hi $0$, today is $1$"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let renderer = get_renderer(config.clone());
|
||||||
|
|
||||||
|
let rendered = renderer.render_passive(text, &config);
|
||||||
|
|
||||||
|
verify_render(rendered, "Hi Jon, today is 10/12");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_passive_simple_match_with_args_not_closed() {
|
||||||
|
let text = ":greet/Jon/Snow";
|
||||||
|
|
||||||
|
let config = get_config_for(r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ':greet'
|
||||||
|
replace: "Hi $0$"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let renderer = get_renderer(config.clone());
|
||||||
|
|
||||||
|
let rendered = renderer.render_passive(text, &config);
|
||||||
|
|
||||||
|
verify_render(rendered, "Hi JonSnow");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ use crate::matcher::{Match};
|
||||||
use crate::config::Configs;
|
use crate::config::Configs;
|
||||||
|
|
||||||
pub(crate) mod default;
|
pub(crate) mod default;
|
||||||
|
pub(crate) mod utils;
|
||||||
|
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
// Render a match output
|
// Render a match output
|
||||||
|
|
130
src/render/utils.rs
Normal file
130
src/render/utils.rs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use regex::{Regex, Captures};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref ARG_REGEX: Regex = Regex::new("\\$(?P<pos>\\d+)\\$").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_args(text: &str, args: &Vec<String>) -> String {
|
||||||
|
let result = ARG_REGEX.replace_all(text, |caps: &Captures| {
|
||||||
|
let position_str = caps.name("pos").unwrap().as_str();
|
||||||
|
let position = position_str.parse::<i32>().unwrap_or(-1);
|
||||||
|
|
||||||
|
if position >= 0 && position < args.len() as i32 {
|
||||||
|
args[position as usize].to_owned()
|
||||||
|
}else{
|
||||||
|
"".to_owned()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn split_args(text: &str, delimiter: char, escape: char) -> Vec<String> {
|
||||||
|
let mut output = vec![];
|
||||||
|
|
||||||
|
// Make sure the text is not empty
|
||||||
|
if text.is_empty() {
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut last = String::from("");
|
||||||
|
let mut previous : char = char::from(0);
|
||||||
|
text.chars().into_iter().for_each(|c| {
|
||||||
|
if c == delimiter {
|
||||||
|
if previous != escape {
|
||||||
|
output.push(last.clone());
|
||||||
|
last = String::from("");
|
||||||
|
}else{
|
||||||
|
last.push(c);
|
||||||
|
}
|
||||||
|
}else if c == escape {
|
||||||
|
if previous == escape {
|
||||||
|
last.push(c);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
last.push(c);
|
||||||
|
}
|
||||||
|
previous = c;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the last one
|
||||||
|
output.push(last);
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
// TESTS
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_args_no_args() {
|
||||||
|
let args = vec!("hello".to_owned());
|
||||||
|
assert_eq!(render_args("no args", &args), "no args")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_args_one_arg() {
|
||||||
|
let args = vec!("jon".to_owned());
|
||||||
|
assert_eq!(render_args("hello $0$", &args), "hello jon")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_args_one_multiple_args() {
|
||||||
|
let args = vec!("jon".to_owned(), "snow".to_owned());
|
||||||
|
assert_eq!(render_args("hello $0$, the $1$ is white", &args), "hello jon, the snow is white")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_render_args_out_of_range() {
|
||||||
|
let args = vec!("jon".to_owned());
|
||||||
|
assert_eq!(render_args("hello $10$", &args), "hello ")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_split_args_one_arg() {
|
||||||
|
assert_eq!(split_args("jon", '/', '\\'), vec!["jon"])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_split_args_two_args() {
|
||||||
|
assert_eq!(split_args("jon/snow", '/', '\\'), vec!["jon", "snow"])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_split_args_escaping() {
|
||||||
|
assert_eq!(split_args("jon\\/snow", '/', '\\'), vec!["jon/snow"])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_split_args_escaping_escape() {
|
||||||
|
assert_eq!(split_args("jon\\\\snow", '/', '\\'), vec!["jon\\snow"])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_split_args_empty() {
|
||||||
|
let empty_vec : Vec<String> = vec![];
|
||||||
|
assert_eq!(split_args("", '/', '\\'), empty_vec)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user