From 58a72f7ab2d66df597f7bdcb0669e7e4b5a2e70e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 02:39:32 +0000 Subject: [PATCH 1/4] feat: add trycmd for living documentation tests Introduce trycmd-based testing that serves dual purposes: 1. Automated regression testing for CLI behavior 2. Living documentation with real input/output examples The Markdown files in tests/examples/ can be directly used in user documentation (mdBook, etc.) as they contain actual command outputs verified by tests. --- diffx-cli/Cargo.toml | 5 ++ diffx-cli/tests/examples.rs | 15 +++++ diffx-cli/tests/examples/01_basic_json.md | 45 ++++++++++++++ .../tests/examples/02_yaml_comparison.md | 37 +++++++++++ .../tests/examples/03_help_and_version.md | 61 ++++++++++++++++++ diffx-cli/tests/examples/04_output_formats.md | 62 +++++++++++++++++++ .../tests/examples/05_toml_comparison.md | 30 +++++++++ .../tests/examples/06_filtering_options.md | 43 +++++++++++++ 8 files changed, 298 insertions(+) create mode 100644 diffx-cli/tests/examples.rs create mode 100644 diffx-cli/tests/examples/01_basic_json.md create mode 100644 diffx-cli/tests/examples/02_yaml_comparison.md create mode 100644 diffx-cli/tests/examples/03_help_and_version.md create mode 100644 diffx-cli/tests/examples/04_output_formats.md create mode 100644 diffx-cli/tests/examples/05_toml_comparison.md create mode 100644 diffx-cli/tests/examples/06_filtering_options.md diff --git a/diffx-cli/Cargo.toml b/diffx-cli/Cargo.toml index 14d41e8..337dfdc 100644 --- a/diffx-cli/Cargo.toml +++ b/diffx-cli/Cargo.toml @@ -32,6 +32,7 @@ regex = { workspace = true } assert_cmd = { workspace = true } predicates = { workspace = true } tempfile = { workspace = true } +trycmd = "0.15" [[test]] name = "cli" @@ -44,3 +45,7 @@ path = "tests/docs_examples/mod.rs" [[test]] name = "integration" path = "tests/integration/mod.rs" + +[[test]] +name = "examples" +path = "tests/examples.rs" diff --git a/diffx-cli/tests/examples.rs b/diffx-cli/tests/examples.rs new file mode 100644 index 0000000..01442c2 --- /dev/null +++ b/diffx-cli/tests/examples.rs @@ -0,0 +1,15 @@ +//! Example-based tests using trycmd +//! +//! These tests serve dual purposes: +//! 1. Automated regression testing +//! 2. Living documentation that shows real input/output examples +//! +//! The Markdown files in `tests/examples/` can be directly used +//! in user documentation (like mdBook). + +#[test] +fn cli_examples() { + trycmd::TestCases::new() + .case("tests/examples/*.md") + .run(); +} diff --git a/diffx-cli/tests/examples/01_basic_json.md b/diffx-cli/tests/examples/01_basic_json.md new file mode 100644 index 0000000..1ceaa0d --- /dev/null +++ b/diffx-cli/tests/examples/01_basic_json.md @@ -0,0 +1,45 @@ +# Basic JSON Comparison + +diffx can compare two JSON files and show semantic differences. + +## Simple Object Comparison + +Given two JSON files with different values: + +**file1.json:** +```json +{ + "name": "John", + "age": 30, + "city": "New York", + "items": ["apple", "banana"] +} +``` + +**file2.json:** +```json +{ + "name": "John", + "age": 31, + "city": "Boston", + "items": ["apple", "banana", "orange"] +} +``` + +Running diffx shows the differences: + +```console +$ diffx tests/fixtures/file1.json tests/fixtures/file2.json +? failed +~ age: 30 -> 31 +~ city: "New York" -> "Boston" + + items[2]: "orange" + +``` + +The output shows: +- `~` indicates a **modified** value +- `+` indicates an **added** value +- `-` indicates a **removed** value (not shown in this example) + +Exit code `1` means differences were found. diff --git a/diffx-cli/tests/examples/02_yaml_comparison.md b/diffx-cli/tests/examples/02_yaml_comparison.md new file mode 100644 index 0000000..94e89b6 --- /dev/null +++ b/diffx-cli/tests/examples/02_yaml_comparison.md @@ -0,0 +1,37 @@ +# YAML Comparison + +diffx supports YAML files with the same semantic comparison. + +## Basic YAML Diff + +**file1.yaml:** +```yaml +name: John +age: 30 +city: New York +items: + - apple + - banana +``` + +**file2.yaml:** +```yaml +name: John +age: 31 +city: Boston +items: + - apple + - banana + - orange +``` + +```console +$ diffx tests/fixtures/file1.yaml tests/fixtures/file2.yaml +? failed +~ age: 30 -> 31 +~ city: "New York" -> "Boston" + + items[2]: "orange" + +``` + +The format is auto-detected from the file extension. diff --git a/diffx-cli/tests/examples/03_help_and_version.md b/diffx-cli/tests/examples/03_help_and_version.md new file mode 100644 index 0000000..029266b --- /dev/null +++ b/diffx-cli/tests/examples/03_help_and_version.md @@ -0,0 +1,61 @@ +# Help and Version + +## Show Version + +```console +$ diffx --version +diffx 0.6.0 + +``` + +## Show Help + +```console +$ diffx --help +A diff tool for structured data + +Usage: diffx [OPTIONS] + +Arguments: + The first input file + The second input file + +Options: + -f, --format + Input file format (auto-detected if not specified) [possible values: json, yaml, csv, toml, ini, xml] + -o, --output + Output format + --path + Filter by path (only show differences in paths containing this string) + --ignore-keys-regex + Ignore keys matching this regex pattern + --epsilon + Numerical comparison tolerance (for floating point numbers) + --array-id-key + Array comparison by ID key (compare arrays by this field instead of index) + --ignore-whitespace + Ignore whitespace differences + --ignore-case + Ignore case differences + -q, --quiet + Suppress normal output; return only exit status + --brief + Report only whether files differ, not the differences + -v, --verbose + Show verbose processing information + --no-color + Disable colored output + --memory-optimization + Enable memory optimization for large files + --batch-size + Batch size for memory optimization + --show-unchanged + Show unchanged values as well + --show-types + Show type information in output + -h, --help + Print help + -V, --version + Print version + +``` diff --git a/diffx-cli/tests/examples/04_output_formats.md b/diffx-cli/tests/examples/04_output_formats.md new file mode 100644 index 0000000..31fe05d --- /dev/null +++ b/diffx-cli/tests/examples/04_output_formats.md @@ -0,0 +1,62 @@ +# Output Formats + +diffx can output differences in various formats for automation and integration. + +## JSON Output + +Use `--output json` to get machine-readable JSON output: + +```console +$ diffx tests/fixtures/file1.json tests/fixtures/file2.json --output json +? failed +[ + { + "Modified": [ + "age", + 30, + 31 + ] + }, + { + "Modified": [ + "city", + "New York", + "Boston" + ] + }, + { + "Added": [ + "items[2]", + "orange" + ] + } +] + +``` + +Each difference is represented as an object with: +- `Modified`: `[path, old_value, new_value]` +- `Added`: `[path, new_value]` +- `Removed`: `[path, old_value]` + +## YAML Output + +Use `--output yaml` for YAML format: + +```console +$ diffx tests/fixtures/file1.json tests/fixtures/file2.json --output yaml +? failed +- Modified: + - age + - 30 + - 31 +- Modified: + - city + - New York + - Boston +- Added: + - items[2] + - orange + + +``` diff --git a/diffx-cli/tests/examples/05_toml_comparison.md b/diffx-cli/tests/examples/05_toml_comparison.md new file mode 100644 index 0000000..6b79155 --- /dev/null +++ b/diffx-cli/tests/examples/05_toml_comparison.md @@ -0,0 +1,30 @@ +# TOML Comparison + +diffx supports TOML configuration files. + +## Basic TOML Diff + +**file1.toml:** +```toml +name = "John" +age = 30 +city = "New York" +items = ["apple", "banana"] +``` + +**file2.toml:** +```toml +name = "John" +age = 31 +city = "Boston" +items = ["apple", "banana", "orange"] +``` + +```console +$ diffx tests/fixtures/file1.toml tests/fixtures/file2.toml +? failed +~ age: 30 -> 31 +~ city: "New York" -> "Boston" + + items[2]: "orange" + +``` diff --git a/diffx-cli/tests/examples/06_filtering_options.md b/diffx-cli/tests/examples/06_filtering_options.md new file mode 100644 index 0000000..1955b0d --- /dev/null +++ b/diffx-cli/tests/examples/06_filtering_options.md @@ -0,0 +1,43 @@ +# Filtering Options + +diffx provides options to filter or ignore certain differences. + +## Ignore Keys by Regex + +Use `--ignore-keys-regex` to skip certain keys from comparison: + +```console +$ diffx tests/fixtures/file1.json tests/fixtures/file2.json --ignore-keys-regex "^age$" +? failed +~ city: "New York" -> "Boston" + + items[2]: "orange" + +``` + +The `age` field is now ignored and not shown in the output. + +## Quiet Mode + +Use `--quiet` or `-q` to suppress output and only return exit code: + +```console +$ diffx tests/fixtures/file1.json tests/fixtures/file2.json --quiet +? failed + +``` + +Exit codes: +- `0`: No differences +- `1`: Differences found +- `2`: Error occurred + +## Files with No Differences + +When comparing identical files: + +```console +$ diffx tests/fixtures/file1.json tests/fixtures/file1.json + +``` + +Exit code is `0` when files are identical. From 1e8018d0bf2db359673d8679fd092ba846d6dea2 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 03:00:29 +0000 Subject: [PATCH 2/4] refactor: move example docs to docs/examples/ Living documentation files are now in docs/examples/ where they belong as user-facing documentation. Tests still verify them via trycmd from diffx-cli/tests/examples.rs. --- diffx-cli/tests/examples.rs | 6 +++--- {diffx-cli/tests => docs}/examples/01_basic_json.md | 0 {diffx-cli/tests => docs}/examples/02_yaml_comparison.md | 0 {diffx-cli/tests => docs}/examples/03_help_and_version.md | 0 {diffx-cli/tests => docs}/examples/04_output_formats.md | 0 {diffx-cli/tests => docs}/examples/05_toml_comparison.md | 0 {diffx-cli/tests => docs}/examples/06_filtering_options.md | 0 7 files changed, 3 insertions(+), 3 deletions(-) rename {diffx-cli/tests => docs}/examples/01_basic_json.md (100%) rename {diffx-cli/tests => docs}/examples/02_yaml_comparison.md (100%) rename {diffx-cli/tests => docs}/examples/03_help_and_version.md (100%) rename {diffx-cli/tests => docs}/examples/04_output_formats.md (100%) rename {diffx-cli/tests => docs}/examples/05_toml_comparison.md (100%) rename {diffx-cli/tests => docs}/examples/06_filtering_options.md (100%) diff --git a/diffx-cli/tests/examples.rs b/diffx-cli/tests/examples.rs index 01442c2..bdb83e2 100644 --- a/diffx-cli/tests/examples.rs +++ b/diffx-cli/tests/examples.rs @@ -4,12 +4,12 @@ //! 1. Automated regression testing //! 2. Living documentation that shows real input/output examples //! -//! The Markdown files in `tests/examples/` can be directly used -//! in user documentation (like mdBook). +//! The Markdown files in `docs/examples/` are the source of truth +//! for user documentation and are verified by these tests. #[test] fn cli_examples() { trycmd::TestCases::new() - .case("tests/examples/*.md") + .case("../docs/examples/*.md") .run(); } diff --git a/diffx-cli/tests/examples/01_basic_json.md b/docs/examples/01_basic_json.md similarity index 100% rename from diffx-cli/tests/examples/01_basic_json.md rename to docs/examples/01_basic_json.md diff --git a/diffx-cli/tests/examples/02_yaml_comparison.md b/docs/examples/02_yaml_comparison.md similarity index 100% rename from diffx-cli/tests/examples/02_yaml_comparison.md rename to docs/examples/02_yaml_comparison.md diff --git a/diffx-cli/tests/examples/03_help_and_version.md b/docs/examples/03_help_and_version.md similarity index 100% rename from diffx-cli/tests/examples/03_help_and_version.md rename to docs/examples/03_help_and_version.md diff --git a/diffx-cli/tests/examples/04_output_formats.md b/docs/examples/04_output_formats.md similarity index 100% rename from diffx-cli/tests/examples/04_output_formats.md rename to docs/examples/04_output_formats.md diff --git a/diffx-cli/tests/examples/05_toml_comparison.md b/docs/examples/05_toml_comparison.md similarity index 100% rename from diffx-cli/tests/examples/05_toml_comparison.md rename to docs/examples/05_toml_comparison.md diff --git a/diffx-cli/tests/examples/06_filtering_options.md b/docs/examples/06_filtering_options.md similarity index 100% rename from diffx-cli/tests/examples/06_filtering_options.md rename to docs/examples/06_filtering_options.md From 07a94718691b35ccdde71986240b7483455157a3 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 03:10:56 +0000 Subject: [PATCH 3/4] feat: add shell completions and man page generation - Add --completions option to generate shell completions (bash, zsh, fish, powershell) - Add build.rs to generate man page at build time - Update docs/examples to reflect new CLI options Usage: diffx --completions bash > ~/.local/share/bash-completion/completions/diffx diffx --completions zsh > ~/.zfunc/_diffx --- diffx-cli/Cargo.toml | 6 + diffx-cli/build.rs | 160 +++++++++++++++++++++++++++ diffx-cli/src/main.rs | 68 ++++++++---- docs/examples/03_help_and_version.md | 8 +- 4 files changed, 217 insertions(+), 25 deletions(-) create mode 100644 diffx-cli/build.rs diff --git a/diffx-cli/Cargo.toml b/diffx-cli/Cargo.toml index 337dfdc..bd61907 100644 --- a/diffx-cli/Cargo.toml +++ b/diffx-cli/Cargo.toml @@ -18,6 +18,7 @@ rust-version.workspace = true diffx-core = { workspace = true } anyhow = { workspace = true } clap = { workspace = true } +clap_complete = "4.5" colored = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -28,6 +29,11 @@ walkdir = { workspace = true } dirs = { workspace = true } regex = { workspace = true } +[build-dependencies] +clap = { workspace = true } +clap_mangen = "0.2" +clap_complete = "4.5" + [dev-dependencies] assert_cmd = { workspace = true } predicates = { workspace = true } diff --git a/diffx-cli/build.rs b/diffx-cli/build.rs new file mode 100644 index 0000000..2800dca --- /dev/null +++ b/diffx-cli/build.rs @@ -0,0 +1,160 @@ +use clap::{Arg, Command, ValueHint}; +use clap_complete::Shell; +use clap_mangen::Man; +use std::env; +use std::fs; +use std::path::PathBuf; + +fn build_cli() -> Command { + Command::new("diffx") + .version(env!("CARGO_PKG_VERSION")) + .about("A diff tool for structured data") + .arg( + Arg::new("FILE1") + .help("The first input file") + .value_hint(ValueHint::FilePath), + ) + .arg( + Arg::new("FILE2") + .help("The second input file") + .value_hint(ValueHint::FilePath), + ) + .arg( + Arg::new("completions") + .long("completions") + .value_name("SHELL") + .value_parser(clap::value_parser!(Shell)) + .help("Generate shell completions for the specified shell"), + ) + .arg( + Arg::new("format") + .short('f') + .long("format") + .value_name("FORMAT") + .help("Input file format (auto-detected if not specified)") + .value_parser(["json", "yaml", "csv", "toml", "ini", "xml"]), + ) + .arg( + Arg::new("output") + .short('o') + .long("output") + .value_name("OUTPUT") + .help("Output format"), + ) + .arg( + Arg::new("path") + .long("path") + .value_name("PATH") + .help("Filter by path (only show differences in paths containing this string)"), + ) + .arg( + Arg::new("ignore-keys-regex") + .long("ignore-keys-regex") + .value_name("PATTERN") + .help("Ignore keys matching this regex pattern"), + ) + .arg( + Arg::new("epsilon") + .long("epsilon") + .value_name("VALUE") + .help("Numerical comparison tolerance (for floating point numbers)"), + ) + .arg( + Arg::new("array-id-key") + .long("array-id-key") + .value_name("KEY") + .help("Array comparison by ID key (compare arrays by this field instead of index)"), + ) + .arg( + Arg::new("ignore-whitespace") + .long("ignore-whitespace") + .action(clap::ArgAction::SetTrue) + .help("Ignore whitespace differences"), + ) + .arg( + Arg::new("ignore-case") + .long("ignore-case") + .action(clap::ArgAction::SetTrue) + .help("Ignore case differences"), + ) + .arg( + Arg::new("quiet") + .short('q') + .long("quiet") + .action(clap::ArgAction::SetTrue) + .help("Suppress normal output; return only exit status"), + ) + .arg( + Arg::new("brief") + .long("brief") + .action(clap::ArgAction::SetTrue) + .help("Report only whether files differ, not the differences"), + ) + .arg( + Arg::new("verbose") + .short('v') + .long("verbose") + .action(clap::ArgAction::SetTrue) + .help("Show verbose processing information"), + ) + .arg( + Arg::new("no-color") + .long("no-color") + .action(clap::ArgAction::SetTrue) + .help("Disable colored output"), + ) + .arg( + Arg::new("memory-optimization") + .long("memory-optimization") + .action(clap::ArgAction::SetTrue) + .help("Enable memory optimization for large files"), + ) + .arg( + Arg::new("batch-size") + .long("batch-size") + .value_name("SIZE") + .help("Batch size for memory optimization"), + ) + .arg( + Arg::new("show-unchanged") + .long("show-unchanged") + .action(clap::ArgAction::SetTrue) + .help("Show unchanged values as well"), + ) + .arg( + Arg::new("show-types") + .long("show-types") + .action(clap::ArgAction::SetTrue) + .help("Show type information in output"), + ) +} + +fn main() { + // Only generate man page and completions for release builds + let out_dir = match env::var_os("OUT_DIR") { + Some(dir) => PathBuf::from(dir), + None => return, + }; + + let cmd = build_cli(); + + // Generate man page + let man_dir = out_dir.join("man"); + fs::create_dir_all(&man_dir).unwrap(); + + let man = Man::new(cmd.clone()); + let mut buffer = Vec::new(); + man.render(&mut buffer).unwrap(); + fs::write(man_dir.join("diffx.1"), buffer).unwrap(); + + // Generate shell completions + let completions_dir = out_dir.join("completions"); + fs::create_dir_all(&completions_dir).unwrap(); + + for shell in [Shell::Bash, Shell::Zsh, Shell::Fish, Shell::PowerShell] { + let mut cmd = build_cli(); + clap_complete::generate_to(shell, &mut cmd, "diffx", &completions_dir).unwrap(); + } + + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/diffx-cli/src/main.rs b/diffx-cli/src/main.rs index d4057ae..3414d67 100644 --- a/diffx-cli/src/main.rs +++ b/diffx-cli/src/main.rs @@ -1,5 +1,6 @@ use anyhow::{Context, Result}; -use clap::{Parser, ValueEnum}; +use clap::{CommandFactory, Parser, ValueEnum}; +use clap_complete::{generate, Shell}; use diffx_core::{ diff, diff_paths, format_diff_output, parse_csv, parse_ini, parse_xml, value_type_name, DiffOptions, DiffResult, DiffxSpecificOptions, OutputFormat, @@ -55,12 +56,16 @@ mod color_utils { #[command(version)] struct Args { /// The first input file - #[arg(value_name = "FILE1")] - input1: PathBuf, + #[arg(value_name = "FILE1", required_unless_present = "completions")] + input1: Option, - /// The second input file - #[arg(value_name = "FILE2")] - input2: PathBuf, + /// The second input file + #[arg(value_name = "FILE2", required_unless_present = "completions")] + input2: Option, + + /// Generate shell completions for the specified shell + #[arg(long, value_enum, value_name = "SHELL")] + completions: Option, /// Input file format (auto-detected if not specified) #[arg(short, long, value_enum)] @@ -157,15 +162,28 @@ fn main() { fn run() -> Result<()> { let args = Args::parse(); + + // Handle shell completions + if let Some(shell) = args.completions { + let mut cmd = Args::command(); + let name = cmd.get_name().to_string(); + generate(shell, &mut cmd, name, &mut io::stdout()); + return Ok(()); + } + + // At this point, input1 and input2 are guaranteed to be present + let input1 = args.input1.as_ref().unwrap(); + let input2 = args.input2.as_ref().unwrap(); + let start_time = Instant::now(); // Check for stdin usage - let input1_is_stdin = args.input1.to_str() == Some("-"); - let input2_is_stdin = args.input2.to_str() == Some("-"); + let input1_is_stdin = input1.to_str() == Some("-"); + let input2_is_stdin = input2.to_str() == Some("-"); if input1_is_stdin || input2_is_stdin { // Handle stdin cases - return handle_stdin_input(&args, input1_is_stdin, input2_is_stdin); + return handle_stdin_input(&args, input1, input2, input1_is_stdin, input2_is_stdin); } // Build options from CLI arguments @@ -178,8 +196,8 @@ fn run() -> Result<()> { eprintln!("Batch size: {}", args.batch_size.unwrap_or(1000)); // Input file information - if let Ok(metadata1) = fs::metadata(&args.input1) { - if let Ok(metadata2) = fs::metadata(&args.input2) { + if let Ok(metadata1) = fs::metadata(input1) { + if let Ok(metadata2) = fs::metadata(input2) { eprintln!("Input file information:"); eprintln!(" Input 1 size: {} bytes", metadata1.len()); eprintln!(" Input 2 size: {} bytes", metadata2.len()); @@ -215,8 +233,8 @@ fn run() -> Result<()> { let mut options_no_filter = options.clone(); options_no_filter.path_filter = None; let unfiltered_results = diff_paths( - &args.input1.to_string_lossy(), - &args.input2.to_string_lossy(), + &input1.to_string_lossy(), + &input2.to_string_lossy(), Some(&options_no_filter), )?; Some(unfiltered_results.len()) @@ -225,8 +243,8 @@ fn run() -> Result<()> { }; let results = diff_paths( - &args.input1.to_string_lossy(), - &args.input2.to_string_lossy(), + &input1.to_string_lossy(), + &input2.to_string_lossy(), Some(&options), )?; let diff_time = parse_start.elapsed(); @@ -243,8 +261,8 @@ fn run() -> Result<()> { } else { println!( "Files {} and {} differ", - args.input1.display(), - args.input2.display() + input1.display(), + input2.display() ); } std::process::exit(if results.is_empty() { 0 } else { 1 }); @@ -431,22 +449,28 @@ fn parse_content(content: &str, format: Format) -> Result { } } -fn handle_stdin_input(args: &Args, input1_is_stdin: bool, input2_is_stdin: bool) -> Result<()> { +fn handle_stdin_input( + args: &Args, + input1: &PathBuf, + input2: &PathBuf, + input1_is_stdin: bool, + input2_is_stdin: bool, +) -> Result<()> { if input1_is_stdin && input2_is_stdin { // Case 2 & 3: Both inputs from stdin - read two data sets from stdin return handle_both_stdin(args); } // Case 1: One stdin, one file - let content1 = read_input(&args.input1)?; - let content2 = read_input(&args.input2)?; + let content1 = read_input(input1)?; + let content2 = read_input(input2)?; // Determine input format let input_format = if let Some(fmt) = args.format { fmt } else { - infer_format_from_path(&args.input1) - .or_else(|| infer_format_from_path(&args.input2)) + infer_format_from_path(input1) + .or_else(|| infer_format_from_path(input2)) .context("Could not infer format from file extensions. Please specify --format.")? }; diff --git a/docs/examples/03_help_and_version.md b/docs/examples/03_help_and_version.md index 029266b..5d8348c 100644 --- a/docs/examples/03_help_and_version.md +++ b/docs/examples/03_help_and_version.md @@ -14,13 +14,15 @@ diffx 0.6.0 $ diffx --help A diff tool for structured data -Usage: diffx [OPTIONS] +Usage: diffx [OPTIONS] [FILE1] [FILE2] Arguments: - The first input file - The second input file + [FILE1] The first input file + [FILE2] The second input file Options: + --completions + Generate shell completions for the specified shell [possible values: bash, elvish, fish, powershell, zsh] -f, --format Input file format (auto-detected if not specified) [possible values: json, yaml, csv, toml, ini, xml] -o, --output From 2b60fca3a1625175e651dade320d532022e11652 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 03:13:38 +0000 Subject: [PATCH 4/4] docs: update README_ja.md with shell completions and man page - Add shell completions section with installation commands for bash/zsh/fish/powershell - Add man page installation instructions - Add link to docs/examples/ (living documentation) --- README_ja.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README_ja.md b/README_ja.md index 3c72347..5b5287f 100644 --- a/README_ja.md +++ b/README_ja.md @@ -196,8 +196,37 @@ pip install diffx-python 詳細な使い方とサンプルは [ドキュメント](docs/index_ja.md) をご確認ください。 +### シェル補完 + +Tab補完を有効にしてコマンド入力を快適に: + +```bash +# Bash +diffx --completions bash > ~/.local/share/bash-completion/completions/diffx + +# Zsh +diffx --completions zsh > ~/.zfunc/_diffx + +# Fish +diffx --completions fish > ~/.config/fish/completions/diffx.fish + +# PowerShell +diffx --completions powershell >> $PROFILE +``` + +### マニュアルページ + +`man diffx` でマニュアルを参照できます。ビルド時に自動生成されます: + +```bash +# ビルド後、man pageをシステムにインストール +sudo cp target/release/build/diffx-*/out/man/diffx.1 /usr/local/share/man/man1/ +man diffx +``` + ### クイックドキュメントリンク +- **[実行例(テスト検証済み)](docs/examples/)** - 実際の入出力例 - **[はじめに](docs/user-guide/getting-started_ja.md)** - 基本を学ぶ - **[インストールガイド](docs/user-guide/installation_ja.md)** - プラットフォーム別セットアップ - **[CLIリファレンス](docs/reference/cli-reference_ja.md)** - 完全なコマンドリファレンス