Decide: should `mado check` read standard input when it is not a terminal?
- 主要语言
- Rust
- 星标
- 409
- 派生
- 12
- 平均合并
- 5 小时 45 分钟
- 30 天内合并 PR
- 30
描述
## Context
`Checker::new` asks for standard input before it looks at anything else
(`src/command/check.rs`):
```rust
let runner = match stdin_input() {
Some(input) => LintRunner::String(...),
None => LintRunner::Parallel(...),
};
```
and `stdin_input` reads to EOF whenever standard input is not a terminal:
```rust
fn stdin_input() -> Option {
let stdin = io::stdin();
if stdin.is_terminal() {
return None;
}
let mut buffer = String::new();
io::stdin().lock().read_to_string(&mut buffer).ok()?;
...
}
```
`is_terminal()` is the only thing asked. Whether the command was given files to
check is not, and a pipe that nobody writes to and nobody closes is not a
terminal.
This is not new in #436 — `main` and 0.3.2 behave the same. It was found while
running `cargo test` from a shell whose standard input was an open pipe: every
`mado check` the tests spawned inherited it and stopped there, and the run had
to be killed.
## Observed behaviour
```console
$ mado check docs < /dev/null # stdin at EOF
Found 6 errors. # docs is linted
$ printf '' | mado check docs # empty pipe
Found 6 errors. # docs is linted
$ printf '#Hello.\n' | mado check docs # pipe with content
(stdin):1:1: MD041 First line in file should be a top level header
Found 2 errors. # docs is NOT linted, and nothing says so
$ mado check docs < <(sleep 30) # pipe held open
# nothing, until the pipe closes
```
So two things sit here:
- **a run that never starts.** `mado check .` with standard input open and
silent waits for EOF that may never come. A CI step, a test harness, an
editor integration or a task runner that leaves a pipe open is enough, and
mado says nothing while it waits.
- **files given and not looked at.** Where standard input carries something,
the paths on the command line are dropped without a word.
## What would have to be decided
- Should standard input be read only where no files were named? `files` carries
`#[arg(default_value = ".")]`, so "nothing given" and "`.` given" arrive the
same; telling them apart means `ArgMatches::value_source` or dropping the
default and answering for it elsewhere.
- Should it be asked for rather than guessed at — `mado check -`, the way many
tools spell it, or a flag?
- Should anything be said where both are given, rather than one of them being
dropped quietly?
- Whatever is decided, standard input is undocumented: neither `mado check
--help` nor the README mentions that it is read at all.
## Related
- #436
贡献指南
调研方向
Start with src/command/check.rs, especially Checker::new and stdin_input, then reproduce the inherited-open-pipe hang with cargo test. Resolve the intended interaction between stdin and the files argument, including whether to use mado check - or a flag. Done means the behavior is explicit, files are not silently dropped, and --help and the README document stdin handling.
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- markdown, rust
- 领域
- cli, documentation
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 活跃
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100