Skip to content

Commit 4ca840b

Browse files
committed
chore: add --stdin-paths and -stdin-paths0
1 parent 2b7af0e commit 4ca840b

File tree

18 files changed

+157
-4
lines changed

18 files changed

+157
-4
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/typos-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ colorchoice-clap = "1.0.3"
7878
serde_regex = "1.1.0"
7979
regex = "1.9.6"
8080
encoding_rs = "0.8.33"
81+
os_str_bytes = "6.5.1"
8182

8283
[dev-dependencies]
8384
assert_fs = "1.0"

crates/typos-cli/src/bin/typos-cli/args.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,17 @@ impl Format {
3939
#[command(group = clap::ArgGroup::new("mode").multiple(false))]
4040
pub(crate) struct Args {
4141
/// Paths to check with `-` for stdin
42-
#[arg(default_value = ".")]
42+
#[arg(default_value = ".", group = "source")]
4343
pub(crate) path: Vec<std::path::PathBuf>,
4444

45+
/// Read the list of newline separated paths from stdin
46+
#[arg(long, group = "source")]
47+
pub(crate) stdin_paths: bool,
48+
49+
/// Read the list of '\0' separated paths from stdin
50+
#[arg(long, group = "source")]
51+
pub(crate) stdin_paths0: bool,
52+
4553
/// The approximate number of threads to use.
4654
#[arg(short = 'j', long = "threads", default_value = "0")]
4755
pub(crate) threads: usize,
@@ -110,6 +118,12 @@ pub(crate) struct Args {
110118
pub(crate) verbose: clap_verbosity_flag::Verbosity,
111119
}
112120

121+
impl Args {
122+
pub fn is_using_stdin_paths(&self) -> bool {
123+
self.stdin_paths || self.stdin_paths0
124+
}
125+
}
126+
113127
#[derive(Debug, Clone, clap::Args)]
114128
#[command(rename_all = "kebab-case")]
115129
pub(crate) struct FileArgs {

crates/typos-cli/src/bin/typos-cli/main.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use std::io::Write;
1+
use std::ffi::OsString;
2+
use std::io::{Read as _, Write as _};
3+
use std::path::PathBuf;
24

35
use clap::Parser;
46

@@ -167,8 +169,29 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
167169

168170
let mut typos_found = false;
169171
let mut errors_found = false;
170-
for path in args.path.iter() {
172+
173+
let stdin_paths = if args.stdin_paths {
174+
Some(
175+
std::io::stdin()
176+
.lines()
177+
.map(|res| res.map(PathBuf::from))
178+
.collect::<Result<_, _>>()
179+
.with_code(proc_exit::sysexits::IO_ERR)?,
180+
)
181+
} else if args.stdin_paths0 {
182+
Some(unix_read_paths_from_stdin()?)
183+
} else {
184+
None
185+
};
186+
187+
// Note: stdin_paths and args.path are mutually exclusive, enforced by clap
188+
for path in stdin_paths.as_ref().unwrap_or(&args.path) {
189+
// Note paths are passed through stdin, `-` is treated like a normal path
171190
let cwd = if path == std::path::Path::new("-") {
191+
if args.is_using_stdin_paths() {
192+
return Err(proc_exit::sysexits::USAGE_ERR
193+
.with_message("Can't use `-` (stdin) while using stdin provided paths"));
194+
};
172195
global_cwd.clone()
173196
} else if path.is_file() {
174197
let mut cwd = path
@@ -293,6 +316,48 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
293316
}
294317
}
295318

319+
#[cfg(target_family = "unix")]
320+
fn os_str_from_bytes(bytes: Vec<u8>) -> Result<OsString, proc_exit::Exit> {
321+
use std::os::unix::ffi::OsStringExt;
322+
323+
Ok(OsString::from_vec(bytes))
324+
}
325+
326+
#[cfg(not(target_family = "unix"))]
327+
fn os_str_from_bytes(bytes: Vec<u8>) -> Result<OsString, proc_exit::Exit> {
328+
use os_str_bytes::RawOsString;
329+
330+
Ok(RawOsString::from_raw_vec(bytes).map_err(|_e| {
331+
proc_exit::sysexits::USAGE_ERR
332+
.with_message("Invalid encoding")?
333+
.into_os_string()
334+
}))
335+
}
336+
337+
fn unix_read_paths_from_stdin() -> Result<Vec<PathBuf>, proc_exit::Exit> {
338+
let mut buf = Vec::new();
339+
std::io::stdin()
340+
.read_to_end(&mut buf)
341+
.with_code(proc_exit::sysexits::IO_ERR)?;
342+
343+
let (mut paths, rest) = buf.into_iter().try_fold(
344+
(vec![], vec![]),
345+
|(mut paths, mut cur_path): (Vec<PathBuf>, Vec<u8>), byte| {
346+
if byte == 0 {
347+
paths.push(PathBuf::from(os_str_from_bytes(cur_path)?));
348+
Ok((paths, vec![]))
349+
} else {
350+
cur_path.push(byte);
351+
Ok((paths, cur_path))
352+
}
353+
},
354+
)?;
355+
if !rest.is_empty() {
356+
paths.push(PathBuf::from(os_str_from_bytes(rest)?));
357+
}
358+
Ok(paths)
359+
}
360+
296361
fn init_logging(level: Option<log::Level>) {
297362
if let Some(level) = level {
298363
let mut builder = env_logger::Builder::new();

crates/typos-cli/tests/cli_tests.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#[test]
22
#[cfg(feature = "dict")]
33
fn cli_tests() {
4-
trycmd::TestCases::new().case("tests/cmd/*.toml");
4+
trycmd::TestCases::new()
5+
.case("tests/cmd/*.toml")
6+
.case("tests/cmd/*.trycmd");
57
}

crates/typos-cli/tests/cmd/help.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Arguments:
99
[PATH]... Paths to check with `-` for stdin [default: .]
1010
1111
Options:
12+
--stdin-paths Read the list of newline separated paths from stdin
13+
--stdin-paths0 Read the list of '/0' separated paths from stdin
1214
-j, --threads <THREADS> The approximate number of threads to use [default: 0]
1315
--force-exclude Respect excluded files even for paths passed explicitly
1416
-h, --help Print help
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[files]
2+
extend-exclude = ["_typos.toml"]
3+
4+
[default.extend-identifiers]
5+
hello = "goodbye"
6+
7+
[type.fail]
8+
extend-glob = ["*.fail"]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello

0 commit comments

Comments
 (0)