Skip to content

Commit

Permalink
replace: add --literal option
Browse files Browse the repository at this point in the history
to be consistent with the `--literal` option in `search` & `searchset`
  • Loading branch information
jqnatividad committed Aug 17, 2024
1 parent 70c171d commit 7196053
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
23 changes: 18 additions & 5 deletions src/cmd/replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ replace arguments:
replace options:
-i, --ignore-case Case insensitive search. This is equivalent to
prefixing the regex with '(?i)'.
--literal Treat the regex pattern as a literal string. This allows
you to search for exact matches that even contain special
regex characters without escaping them.
-s, --select <arg> Select the columns to search. See 'qsv select -h'
for the full syntax.
-u, --unicode Enable unicode support. When enabled, character classes
Expand All @@ -50,7 +53,7 @@ Common options:
"#;

use std::{borrow::Cow, collections::HashSet, env};
use std::{borrow::Cow, collections::HashSet};

#[cfg(any(feature = "feature_capable", feature = "lite"))]
use indicatif::{HumanCount, ProgressBar, ProgressDrawTarget};
Expand All @@ -75,6 +78,7 @@ struct Args {
flag_no_headers: bool,
flag_delimiter: Option<Delimiter>,
flag_ignore_case: bool,
flag_literal: bool,
flag_size_limit: usize,
flag_dfa_size_limit: usize,
flag_progressbar: bool,
Expand All @@ -85,11 +89,20 @@ const NULL_VALUE: &str = "<null>";

pub fn run(argv: &[&str]) -> CliResult<()> {
let args: Args = util::get_args(USAGE, argv)?;
let regex_unicode = match env::var("QSV_REGEX_UNICODE") {
Ok(_) => true,
Err(_) => args.flag_unicode,

let regex_unicode = if util::get_envvar_flag("QSV_REGEX_UNICODE") {
true
} else {
args.flag_unicode
};

let arg_pattern = if args.flag_literal {
regex::escape(&args.arg_pattern)
} else {
args.arg_pattern.clone()
};
let pattern = RegexBuilder::new(&args.arg_pattern)

let pattern = RegexBuilder::new(&arg_pattern)
.case_insensitive(args.flag_ignore_case)
.unicode(regex_unicode)
.size_limit(args.flag_size_limit * (1 << 20))
Expand Down
28 changes: 28 additions & 0 deletions tests/test_replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@ fn replace() {
wrk.assert_success(&mut cmd);
}

#[test]
fn replace_regex_literal() {
let wrk = Workdir::new("replace");
wrk.create(
"data.csv",
vec![
svec!["identifier", "color"],
svec!["164.0", "yel$low^"],
svec!["165.0", "yellow"],
svec!["166.0", "yellow"],
svec!["167.0", "yel$low^.0"],
],
);
let mut cmd = wrk.command("replace");
cmd.arg("$low^").arg("low").arg("--literal").arg("data.csv");

let got: Vec<Vec<String>> = wrk.read_stdout(&mut cmd);
let expected = vec![
svec!["identifier", "color"],
svec!["164.0", "yellow"],
svec!["165.0", "yellow"],
svec!["166.0", "yellow"],
svec!["167.0", "yellow.0"],
];
assert_eq!(got, expected);
wrk.assert_success(&mut cmd);
}

#[test]
fn replace_match() {
let wrk = Workdir::new("replace_match");
Expand Down

0 comments on commit 7196053

Please sign in to comment.