Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions ci/test-complete
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ main() {
# where a long option starting with certain letters (see `_rg`) is found.
# Occasionally we may have to handle some manually, however
help_args=( ${(f)"$(
$rg --help |
$rg -i -- '^\s+--?[a-z0-9.]|--[a-z]' |
$rg -ior '$1' -- $'[\t /\"\'`.,](-[a-z0-9.]|--[a-z0-9-]+)(,|\\b)' |
$rg -vw -- --print0 # False positives
$rg --no-config --help |
$rg --no-config -i -- '^\s+--?[a-z0-9.]|--[a-z]' |
$rg --no-config -ior '$1' -- $'[\t /\"\'`.,](-[a-z0-9.]|--[a-z0-9-]+)(,|\\b)' |
$rg --no-config -vw -- --print0 # False positives
)"} )
help_args=( ${(ou)help_args} )

Expand Down
4 changes: 4 additions & 0 deletions crates/core/flags/complete/rg.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ _rg() {
"--no-ignore-files[don't respect --ignore-file flags]"
$no'--ignore-files[respect --ignore-file files]'

+ input
'*--in=[specify text file containing paths to search]: :_files'
'*--in0=[specify binary file containing NUL-terminated paths to search]: :_files'

+ '(invert-match)'
{-v,--invert-match}'[invert matching]'
$no"--no-invert-match[don't invert matching]"
Expand Down
191 changes: 188 additions & 3 deletions crates/core/flags/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use crate::flags::{
lowargs::{
BinaryMode, BoundaryMode, BufferMode, CaseMode, ColorChoice,
ContextMode, EncodingMode, EngineChoice, GenerateMode, IndexMode,
LoggingMode, LowArgs, MmapMode, Mode, PatternSource, SearchMode,
SortMode, SortModeKind, SpecialMode, TypeChange,
InputSource, LoggingMode, LowArgs, MmapMode, Mode, PatternSource,
SearchMode, SortMode, SortModeKind, SpecialMode, TypeChange,
},
};

Expand Down Expand Up @@ -83,6 +83,8 @@ pub(super) const FLAGS: &[&dyn Flag] = &[
&IgnoreCase,
&IgnoreFile,
&IgnoreFileCaseInsensitive,
&In,
&In0,
&IncludeZero,
&Index,
&IndexCrud,
Expand Down Expand Up @@ -3402,6 +3404,186 @@ fn test_ignore_file_case_insensitive() {
assert_eq!(true, args.ignore_file_case_insensitive);
}

/// --in
#[derive(Debug)]
struct In;

impl Flag for In {
fn is_switch(&self) -> bool {
false
}
fn name_long(&self) -> &'static str {
"in"
}
fn doc_variable(&self) -> Option<&'static str> {
Some("INPUTFILE")
}
fn doc_category(&self) -> Category {
Category::Input
}
fn doc_short(&self) -> &'static str {
r"Read paths to search from the given text file."
}
fn doc_long(&self) -> &'static str {
r"
Includes paths to search from the given file, with one path per line.
.sp
When this flag is used, it behaves as if the file paths in the file provided
were passed as positional arguments in the same order as they are
in the file and relative to other positional arguments.
.sp
Newlines (both LF and CRLF) are not counted as part of the path.
The rest of the path name is taken as-is on Unix and decoded as UTF-8 on
Windows. Use the \flag{in0} flag to use \fBNUL\fP as terminator.
.sp
When \fIINPUTFILE\fP is \fB-\fP, then the paths will be read from \fBstdin\fP.
"
}
fn completion_type(&self) -> CompletionType {
CompletionType::Filename
}

fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let path = PathBuf::from(v.unwrap_value());
args.inputs.push(InputSource::LineTerminated(path));
Ok(())
}
}

/// --in0
#[derive(Debug)]
struct In0;

impl Flag for In0 {
fn is_switch(&self) -> bool {
false
}
fn name_long(&self) -> &'static str {
"in0"
}
fn doc_variable(&self) -> Option<&'static str> {
Some("INPUTFILE")
}
fn doc_category(&self) -> Category {
Category::Input
}
fn doc_short(&self) -> &'static str {
r"Read paths to search from the given binary file."
}
fn doc_long(&self) -> &'static str {
r"
Includes paths to search from the given file, terminated by \fBNUL\fP bytes.
.sp
When this flag is used, it behaves as if the file paths in the file provided
were passed as positional arguments in the same order as they are
in the file and relative to other positional arguments.
.sp
The path names are taken as-is on Unix, and decoded as UTF-8 on Windows.
.sp
When \fIINPUTFILE\fP is \fB-\fP, then the paths will be read from \fBstdin\fP.
"
}
fn completion_type(&self) -> CompletionType {
CompletionType::Filename
}

fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let path = PathBuf::from(v.unwrap_value());
args.inputs.push(InputSource::NulTerminated(path));
Ok(())
}
}

#[cfg(test)]
#[test]
fn test_in_in0() {
let args = parse_low_raw(None::<&str>).unwrap();
assert_eq!(Vec::<InputSource>::new(), args.inputs);

let args = parse_low_raw(["--in", "foo"]).unwrap();
assert_eq!(
vec![InputSource::LineTerminated(PathBuf::from("foo"))],
args.inputs
);

let args = parse_low_raw(["--in0", "foo"]).unwrap();
assert_eq!(
vec![InputSource::NulTerminated(PathBuf::from("foo"))],
args.inputs
);

let args = parse_low_raw(["--in=foo"]).unwrap();
assert_eq!(
vec![InputSource::LineTerminated(PathBuf::from("foo"))],
args.inputs
);

let args = parse_low_raw(["--in0=foo"]).unwrap();
assert_eq!(
vec![InputSource::NulTerminated(PathBuf::from("foo"))],
args.inputs
);

let args = parse_low_raw(["--in", "-foo"]).unwrap();
assert_eq!(
vec![InputSource::LineTerminated(PathBuf::from("-foo"))],
args.inputs
);

let args = parse_low_raw(["--in0", "-foo"]).unwrap();
assert_eq!(
vec![InputSource::NulTerminated(PathBuf::from("-foo"))],
args.inputs
);

let args = parse_low_raw(["--in=-foo"]).unwrap();
assert_eq!(
vec![InputSource::LineTerminated(PathBuf::from("-foo"))],
args.inputs
);

let args = parse_low_raw(["--in0=-foo"]).unwrap();
assert_eq!(
vec![InputSource::NulTerminated(PathBuf::from("-foo"))],
args.inputs
);

let args =
parse_low_raw(["--in=foo", "--in0", "bar", "--in", "baz"]).unwrap();
assert_eq!(
vec![
InputSource::LineTerminated(PathBuf::from("foo")),
InputSource::NulTerminated(PathBuf::from("bar")),
InputSource::LineTerminated(PathBuf::from("baz")),
],
args.inputs
);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add tests that mingle --in, --in0 and other positional paths?


let args = parse_low_raw(["--in=-"]).unwrap();
assert_eq!(
vec![InputSource::LineTerminated(PathBuf::from("-")),],
args.inputs
);

let args = parse_low_raw(["--in", "-"]).unwrap();
assert_eq!(
vec![InputSource::LineTerminated(PathBuf::from("-")),],
args.inputs
);

let args = parse_low_raw(["--in0=-"]).unwrap();
assert_eq!(
vec![InputSource::NulTerminated(PathBuf::from("-")),],
args.inputs
);

let args = parse_low_raw(["--in0", "-"]).unwrap();
assert_eq!(
vec![InputSource::NulTerminated(PathBuf::from("-")),],
args.inputs
);
}

/// --include-zero
#[derive(Debug)]
struct IncludeZero;
Expand Down Expand Up @@ -3640,7 +3822,10 @@ fn test_index_crud() {

let args = parse_low_raw(["--files", "--x-crud", "foo"]).unwrap();
assert_eq!(Mode::Index(IndexMode::Crud), args.mode);
assert_eq!(vec![std::ffi::OsString::from("foo")], args.positional);
assert_eq!(
vec![InputSource::PositionalArgument(std::ffi::OsString::from("foo"))],
args.inputs
);

let args = parse_low_raw(["--x-crud", "--files"]).unwrap();
assert_eq!(Mode::Files, args.mode);
Expand Down
Loading
Loading