cli-tutor 0.4.1

Interactive terminal app for learning Unix command-line tools
Documentation
[module]
name = "diff"
description = "Compare two files and show what changed"
version = 1

[intro]
text = """
## Why diff matters

`diff` is the foundation of code review and configuration management. Every `git diff`, every patch file, every pull request review is built on what `diff` produces. When you need to verify that a deployment changed only the intended lines, audit what changed between two generated config files, or prove that two build artifacts are identical, `diff` is the right tool.

Learning to read diff output makes you faster at reviewing changes, diagnosing regressions, and constructing patches. It's also a building block for pipelines: `diff ... | grep '^>'` to extract additions, or `diff ... | wc -l` to count changes.

## Output format

Standard diff output uses **change codes** to describe what transformed the first file into the second:

- `NcN` — a line was **changed** (e.g. `1c1` means line 1 in file 1 changed to line 1 in file 2)
- `NaN` — a line was **added** (present in file 2 but not file 1)
- `NdN` — a line was **deleted** (present in file 1 but not file 2)

Lines prefixed with `<` come from the **first** file. Lines prefixed with `>` come from the **second** file. `---` separates the two sides.

## Key Flags

- `-u` — unified format: shows context lines around changes, the same format `git diff` uses
- `-i` — case-insensitive comparison
- `-w` — ignore all whitespace differences

## Real-world workflows

- **Config promotion**: compare staging config to production config before deploying
- **Output validation**: verify a code generator's output matches the expected golden file
- **Patch review**: extract only the added lines (`grep '^>'`) or only the removed lines (`grep '^<'`) for focused review
"""

[[examples]]
title = "Compare two config files"
description = "Show all differences between a staging and production config"
command = "diff staging.conf prod.conf"
output = "2c2\n< debug=true\n---\n> debug=false\n"

[[examples]]
title = "Unified diff (git-style)"
description = "Show differences with context lines, like git diff output"
command = "diff -u old.txt new.txt"
output = "--- old.txt\n+++ new.txt\n@@ -1,3 +1,3 @@\n host=localhost\n-port=5432\n+port=5433\n debug=false\n"

[[exercises]]
id = "diff.1"
difficulty = "beginner"
question = """Before deploying a config update, verify that `a.txt` and `b.txt` are exactly identical. Print "files are identical" if they match."""
expected_output = "files are identical\n"
hints = [
  "diff exits with code 0 if files are identical, non-zero if they differ",
  "Use && to run the echo only when diff succeeds (no differences found)",
  "Try: diff a.txt b.txt && echo \"files are identical\"",
]
solution = "diff a.txt b.txt && echo \"files are identical\""
match_mode = "exact"

[[exercises.fixtures]]
filename = "a.txt"
content = "hello\nworld\n"

[[exercises.fixtures]]
filename = "b.txt"
content = "hello\nworld\n"

[[exercises]]
id = "diff.2"
difficulty = "beginner"
question = """You're promoting a config from staging to production. Show the differences between `v1.txt` (staging) and `v2.txt` (production) using standard diff format."""
expected_output = "1c1\n< host=localhost\n---\n> host=db.prod.internal\n3c3\n< debug=true\n---\n> debug=false\n"
hints = [
  "diff FILE1 FILE2 shows what must change in FILE1 to produce FILE2",
  "Try: diff v1.txt v2.txt",
]
solution = "diff v1.txt v2.txt"
match_mode = "exact"

[[exercises.fixtures]]
filename = "v1.txt"
content = "host=localhost\nport=5432\ndebug=true\n"

[[exercises.fixtures]]
filename = "v2.txt"
content = "host=db.prod.internal\nport=5432\ndebug=false\n"

[[exercises]]
id = "diff.3"
difficulty = "intermediate"
question = """Compare `old.txt` and `new.txt` and print ONLY the changed lines — lines removed (starting with `<`) and lines added (starting with `>`)."""
expected_output = "< bob 87\n> bob 91\n< diana 90\n> diana 88\n"
hints = [
  "diff output has lines starting with <, >, ---, and change codes like 2c2",
  "Use grep to keep only the lines starting with < or >",
  "Try: diff old.txt new.txt | grep '^[<>]'",
]
solution = "diff old.txt new.txt | grep '^[<>]'"
match_mode = "exact"

[[exercises.fixtures]]
filename = "old.txt"
content = "alice 95\nbob 87\ncharlie 72\ndiana 90\n"

[[exercises.fixtures]]
filename = "new.txt"
content = "alice 95\nbob 91\ncharlie 72\ndiana 88\n"

[[exercises]]
id = "diff.4"
difficulty = "intermediate"
question = """Count the total number of changed lines between `file1.txt` and `file2.txt`. Both removed lines (starting with `<`) and added lines (starting with `>`) count toward the total."""
expected_output = "4\n"
hints = [
  "Filter diff output to lines starting with < or >, then count them",
  "grep -c counts matching lines directly",
  "Try: diff file1.txt file2.txt | grep -c '^[<>]'",
]
solution = "diff file1.txt file2.txt | grep -c '^[<>]'"
match_mode = "normalized"

[[exercises.fixtures]]
filename = "file1.txt"
content = "apple\nbanana\ncherry\nmango\n"

[[exercises.fixtures]]
filename = "file2.txt"
content = "apple\nblueberry\ncherry\nmelon\n"

[[exercises]]
id = "diff.5"
difficulty = "advanced"
question = """You're reviewing a config change. Extract only the NEW values (lines present in `new_config.txt` but not `old_config.txt`), with the `> ` prefix removed."""
expected_output = "timeout=60\nlog_level=info\nmetrics=true\n"
hints = [
  "Lines added in the second file are prefixed with '> ' in diff output",
  "Use grep '^>' to isolate them, then sed to strip the prefix",
  "Try: diff old_config.txt new_config.txt | grep '^>' | sed 's/^> //'",
]
solution = "diff old_config.txt new_config.txt | grep '^>' | sed 's/^> //'"
match_mode = "exact"

[[exercises.fixtures]]
filename = "old_config.txt"
content = "timeout=30\nretries=3\nlog_level=warn\n"

[[exercises.fixtures]]
filename = "new_config.txt"
content = "timeout=60\nretries=3\nlog_level=info\nmetrics=true\n"