mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
feat(cli): agent-native output, stdin symbols, and exit-code classes
Phase 1 of docs/DESIGN.md: - Output format resolves -o > IDX_OUTPUT > general.output > auto; auto is a table on a terminal and JSON when stdout is piped or captured. `config init` now writes output = "auto". - JSON is pretty only on a terminal and compact otherwise. New `-o jsonl` prints one array item per line with the same key order. - No ANSI color when stdout is not a terminal (direct owo-colors calls now go through output::style). - `stocks quote -` and `stocks compare -` read symbols from stdin. - Exit codes by class: 2 invalid input/config, 3 not found or cache miss, 4 upstream unavailable, 5 unsupported, 1 other. Golden changes are limited to those documented kinds and were verified mechanically: JSON goldens are semantically identical, tables differ only by removed ANSI codes and the column padding comfy-table had reserved for them (cell contents identical), exit codes match each error's class, and help/completions only gain the new --output values. 17 new golden cases cover auto, jsonl, stdin, and the new errors. tests/cli.rs now pins IDX_OUTPUT=table in its harness (its tests assert table text and run piped) and parses discover JSON instead of matching pretty-printed whitespace. Live A/B against main: 16/16 stocks cases identical; ownership discover got IDX 403 on both binaries, now exiting 4 instead of 1 as intended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fe627496dd
commit
22b6dabaeb
119 changed files with 920 additions and 1896 deletions
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
|
@ -40,6 +41,9 @@ struct Case {
|
|||
/// Commands run first in the same environment; their output is ignored.
|
||||
#[serde(default)]
|
||||
before: Vec<Vec<String>>,
|
||||
/// Text piped to the command's stdin.
|
||||
#[serde(default)]
|
||||
stdin: Option<String>,
|
||||
}
|
||||
|
||||
fn default_formats() -> Vec<String> {
|
||||
|
|
@ -56,6 +60,15 @@ fn work_dir() -> PathBuf {
|
|||
|
||||
/// Runs idx with an isolated home under `root` and only the given IDX_* env.
|
||||
fn idx(root: &Path, args: &[String], env: &BTreeMap<String, String>) -> std::process::Output {
|
||||
idx_with_stdin(root, args, env, None)
|
||||
}
|
||||
|
||||
fn idx_with_stdin(
|
||||
root: &Path,
|
||||
args: &[String],
|
||||
env: &BTreeMap<String, String>,
|
||||
stdin: Option<&str>,
|
||||
) -> std::process::Output {
|
||||
let mut cmd = Command::new(IDX);
|
||||
cmd.current_dir(REPO).args(args);
|
||||
for (key, _) in std::env::vars_os() {
|
||||
|
|
@ -68,8 +81,17 @@ fn idx(root: &Path, args: &[String], env: &BTreeMap<String, String>) -> std::pro
|
|||
.env("XDG_CACHE_HOME", root.join("cache"))
|
||||
.env("XDG_DATA_HOME", root.join("data"))
|
||||
.env("IDX_USE_MOCK_PROVIDER", "1")
|
||||
.envs(env);
|
||||
cmd.output().expect("run idx")
|
||||
.envs(env)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
let mut child = cmd.spawn().expect("spawn idx");
|
||||
let mut pipe = child.stdin.take().expect("stdin pipe");
|
||||
if let Some(input) = stdin {
|
||||
pipe.write_all(input.as_bytes()).expect("write stdin");
|
||||
}
|
||||
drop(pipe);
|
||||
child.wait_with_output().expect("run idx")
|
||||
}
|
||||
|
||||
/// Fixture ownership DB: the above-1% XLSX (2026-08-31) plus two KSEI archive
|
||||
|
|
@ -161,7 +183,8 @@ fn cli_output_matches_golden_files() {
|
|||
idx(&root, before, &case.env);
|
||||
}
|
||||
|
||||
let actual = render(&root, &idx(&root, &args, &case.env));
|
||||
let output = idx_with_stdin(&root, &args, &case.env, case.stdin.as_deref());
|
||||
let actual = render(&root, &output);
|
||||
let path = golden_dir().join(format!("{name}.golden"));
|
||||
if update {
|
||||
fs::write(&path, &actual).expect("write golden");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue