mirror of
https://github.com/sharkdp/fd
synced 2024-06-28 22:04:23 +00:00
Compare commits
5 Commits
ebaade5402
...
93fa7219c2
Author | SHA1 | Date | |
---|---|---|---|
|
93fa7219c2 | ||
|
f8270a6a44 | ||
|
7042dff969 | ||
|
f477c4f2c9 | ||
|
5cdf9763e4 |
25
.github/workflows/CICD.yml
vendored
25
.github/workflows/CICD.yml
vendored
|
@ -80,19 +80,19 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
- { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: aarch64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true }
|
||||
- { target: i686-pc-windows-msvc , os: windows-2019 }
|
||||
- { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: aarch64-unknown-linux-gnu , os: ubuntu-22.04, use-cross: true }
|
||||
- { target: aarch64-unknown-linux-musl , os: ubuntu-22.04, use-cross: true }
|
||||
- { target: arm-unknown-linux-gnueabihf , os: ubuntu-22.04, use-cross: true }
|
||||
- { target: arm-unknown-linux-musleabihf, os: ubuntu-22.04, use-cross: true }
|
||||
- { target: i686-pc-windows-msvc , os: windows-2022 }
|
||||
- { target: i686-unknown-linux-gnu , os: ubuntu-22.04, use-cross: true }
|
||||
- { target: i686-unknown-linux-musl , os: ubuntu-22.04, use-cross: true }
|
||||
- { target: x86_64-apple-darwin , os: macos-12 }
|
||||
- { target: aarch64-apple-darwin , os: macos-14 }
|
||||
- { target: x86_64-pc-windows-gnu , os: windows-2019 }
|
||||
- { target: x86_64-pc-windows-msvc , os: windows-2019 }
|
||||
- { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: x86_64-pc-windows-gnu , os: windows-2022 }
|
||||
- { target: x86_64-pc-windows-msvc , os: windows-2022 }
|
||||
- { target: x86_64-unknown-linux-gnu , os: ubuntu-22.04, use-cross: true }
|
||||
- { target: x86_64-unknown-linux-musl , os: ubuntu-22.04, use-cross: true }
|
||||
env:
|
||||
BUILD_CMD: cargo
|
||||
steps:
|
||||
|
@ -111,6 +111,9 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.job.target }}
|
||||
# On windows, for now build with 1.77.2, so that it works on windows 7.
|
||||
# When we update the MSRV again, we'll need to revisit this, and probably drop support for Win7
|
||||
toolchain: "${{ contains(matrix.job.target, 'windows-') && '1.77.2' || 'stable' }}"
|
||||
|
||||
- name: Install cross
|
||||
if: matrix.job.use-cross
|
||||
|
|
37
src/cli.rs
37
src/cli.rs
|
@ -167,8 +167,8 @@ pub struct Opts {
|
|||
pub regex: bool,
|
||||
|
||||
/// Treat the pattern as a literal string instead of a regular expression. Note
|
||||
/// that this also performs substring comparison. If you want to match on an
|
||||
/// exact filename, consider using '--glob'.
|
||||
/// that the pattern would still match on a substring of the input. If you want
|
||||
/// to match on an exact filename, consider adding '--anchor=input' as well.
|
||||
#[arg(
|
||||
long,
|
||||
short = 'F',
|
||||
|
@ -245,6 +245,20 @@ pub struct Opts {
|
|||
)]
|
||||
pub full_path: bool,
|
||||
|
||||
/// By default, the search pattern for --regex and --fixed-strings can match any part of the input.
|
||||
/// (See the --full-path option for what constitutes input)
|
||||
///
|
||||
/// This flag allows anchoring the pattern.
|
||||
///
|
||||
/// Conflicts with the --glob flag: globs always match the entire input
|
||||
#[arg(
|
||||
long,
|
||||
help = "Where to anchor the pattern",
|
||||
conflicts_with("glob"),
|
||||
long_help
|
||||
)]
|
||||
pub anchor: Option<Anchor>,
|
||||
|
||||
/// Separate search results by the null character (instead of newlines).
|
||||
/// Useful for piping results to 'xargs'.
|
||||
#[arg(
|
||||
|
@ -697,6 +711,17 @@ impl Opts {
|
|||
self.rg_alias_hidden_ignore > 0
|
||||
}
|
||||
|
||||
pub fn anchor(&self) -> Option<Anchor> {
|
||||
if self.glob {
|
||||
// globset has no way to use an anchor.
|
||||
// Otherwise we'd guard like this:
|
||||
// && !self.no_anchor && self.anchor.is_none()
|
||||
Some(Anchor::Input)
|
||||
} else {
|
||||
self.anchor
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_depth(&self) -> Option<usize> {
|
||||
self.max_depth.or(self.exact_depth)
|
||||
}
|
||||
|
@ -752,6 +777,14 @@ fn default_num_threads() -> NonZeroUsize {
|
|||
.min(limit)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, ValueEnum)]
|
||||
pub enum Anchor {
|
||||
InputStart,
|
||||
InputEnd,
|
||||
Input,
|
||||
Word,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, ValueEnum)]
|
||||
pub enum FileType {
|
||||
#[value(alias = "f")]
|
||||
|
|
35
src/main.rs
35
src/main.rs
|
@ -163,15 +163,36 @@ fn ensure_search_pattern_is_not_a_path(opts: &Opts) -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
fn apply_anchors(re: String, anchors: Option<cli::Anchor>) -> String {
|
||||
use cli::Anchor;
|
||||
match anchors {
|
||||
None => re,
|
||||
Some(Anchor::InputStart) => "^".to_owned() + &re,
|
||||
Some(Anchor::InputEnd) => re + "$",
|
||||
Some(Anchor::Input) => "^".to_owned() + &re + "$",
|
||||
// https://docs.rs/regex/latest/regex/#empty-matches
|
||||
Some(Anchor::Word) => r"\<".to_owned() + &re + r"\>",
|
||||
}
|
||||
}
|
||||
|
||||
fn build_pattern_regex(pattern: &str, opts: &Opts) -> Result<String> {
|
||||
Ok(if opts.glob && !pattern.is_empty() {
|
||||
let glob = GlobBuilder::new(pattern).literal_separator(true).build()?;
|
||||
glob.regex().to_owned()
|
||||
} else if opts.fixed_strings {
|
||||
// Treat pattern as literal string if '--fixed-strings' is used
|
||||
regex::escape(pattern)
|
||||
Ok(if opts.glob {
|
||||
if !pattern.is_empty() {
|
||||
let glob = GlobBuilder::new(pattern).literal_separator(true).build()?;
|
||||
glob.regex().to_owned()
|
||||
} else {
|
||||
"".to_owned()
|
||||
}
|
||||
} else {
|
||||
String::from(pattern)
|
||||
apply_anchors(
|
||||
if opts.fixed_strings {
|
||||
// Treat pattern as literal string if '--fixed-strings' is used
|
||||
regex::escape(pattern)
|
||||
} else {
|
||||
String::from(pattern)
|
||||
},
|
||||
opts.anchor(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -604,6 +604,33 @@ fn test_full_path() {
|
|||
);
|
||||
}
|
||||
|
||||
/// Anchoring (--anchor)
|
||||
#[test]
|
||||
fn test_anchors() {
|
||||
let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
|
||||
|
||||
te.assert_output(&["--anchor=input", "foo"], "");
|
||||
te.assert_output(&["--anchor=input", "b.foo"], "one/b.foo");
|
||||
te.assert_output(&["--anchor=input-start", "foo"], "");
|
||||
te.assert_output(&["--anchor=input-start", "b."], "one/b.foo");
|
||||
te.assert_output(
|
||||
&["--anchor=input-end", "oo"],
|
||||
"a.foo
|
||||
one/b.foo
|
||||
one/two/c.foo
|
||||
one/two/three/d.foo
|
||||
one/two/three/directory_foo/",
|
||||
);
|
||||
te.assert_output(&["--anchor=word", "oo"], "");
|
||||
te.assert_output(
|
||||
&["--anchor=word", "foo"],
|
||||
"a.foo
|
||||
one/b.foo
|
||||
one/two/c.foo
|
||||
one/two/three/d.foo",
|
||||
);
|
||||
}
|
||||
|
||||
/// Hidden files (--hidden)
|
||||
#[test]
|
||||
fn test_hidden() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user