feat: add replace subcommand with multi-pattern support

This commit is contained in:
Rogee
2025-10-29 17:46:54 +08:00
parent fa57af8a26
commit ceea09f7be
42 changed files with 1848 additions and 14 deletions

View File

@@ -0,0 +1,115 @@
# Feature Specification: Replace Command with Multi-Pattern Support
**Feature Branch**: `002-add-replace-command`
**Created**: 2025-10-29
**Status**: Draft
**Input**: User description: "添加 替换replace命令用于替换指定的字符串支持同时对多个字符串进行替换为一个 示例: renamer replace pattern1 pattern2 with space pattern3 <replacement>"
## Clarifications
### Session 2025-10-29
- Q: What syntax separates patterns from the replacement value? → A: The final positional argument is the replacement; no delimiter keyword is used.
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Normalize Naming with One Command (Priority: P1)
As a CLI user cleaning messy filenames, I want to run `renamer replace` with multiple source
patterns so I can normalize all variants to a single replacement in one pass.
**Why this priority**: Unlocks the main value proposition—batch consolidation of inconsistent
substrings without writing custom scripts.
**Independent Test**: Execute `renamer list` to confirm scope, then `renamer replace foo bar Baz`
and verify preview shows every `foo` and `bar` occurrence replaced with `Baz` before confirming.
**Acceptance Scenarios**:
1. **Given** files containing `draft`, `Draft`, and `DRAFT`, **When** the user runs `renamer replace draft Draft DRAFT final`, **Then** the preview lists every filename replaced with `final`, and execution applies the same mapping.
2. **Given** filenames where patterns appear multiple times, **When** the user runs `renamer replace beta gamma release`, **Then** each occurrence within a single filename is substituted, and the summary highlights total replacements per file.
---
### User Story 2 - Script-Friendly Replacement Workflows (Priority: P2)
As an operator embedding renamer in automation, I want deterministic exit codes and reusable
profiles for replace operations so scripts can preview, apply, and undo safely.
**Why this priority**: Ensures pipelines can rely on the command without interactive ambiguity.
**Independent Test**: In a CI script, run `renamer replace ... --dry-run` (preview), assert exit code
0, then run with `--yes` and check ledger entry plus `renamer undo` restores originals.
**Acceptance Scenarios**:
1. **Given** a non-interactive environment, **When** the user passes `--yes` to apply replacements after a successful preview, **Then** the command exits 0 on success and writes a ledger entry capturing all mappings.
2. **Given** an invalid argument (e.g., only one token supplied), **When** the command executes, **Then** it exits with a non-zero code and explains that the final positional argument becomes the replacement value.
---
### User Story 3 - Validate Complex Pattern Input (Priority: P3)
As a power user handling patterns with spaces or special characters, I want clear syntax guidance
and validation feedback so I can craft replacements confidently.
**Why this priority**: Prevents user frustration when patterns require quoting or escaping.
**Independent Test**: Run `renamer replace "Project X" "Project-X" ProjectX` and confirm preview
resolves both variants, while invalid quoting produces actionable guidance.
**Acceptance Scenarios**:
1. **Given** a pattern containing whitespace, **When** it is provided in quotes, **Then** the preview reflects the intended substring and documentation shows identical syntax describing the final argument as replacement.
2. **Given** duplicate patterns in the same command, **When** the command runs, **Then** duplicates are deduplicated with a warning so replacements remain idempotent.
---
### Edge Cases
- Replacement produces duplicate target filenames; command must surface conflicts before confirmation.
- Patterns overlap within the same filename (e.g., `aaa` replaced via `aa`); order of application must be deterministic and documented.
- Case-sensitivity opt-in: default literal matching is case-sensitive, but a future `--ignore-case` option is deferred; command must warn that matches are case-sensitive.
- Replacement string empty (aka deletion); preview must show empty substitution clearly and require explicit confirmation.
- No files match any pattern; command exits 0 with "No entries matched" messaging and no ledger entry.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: The CLI MUST expose `renamer replace <pattern...> <replacement>` and treat all but the final token as literal patterns (quotes support whitespace).
- **FR-002**: Replace operations MUST integrate with the existing preview → confirm workflow; previews list old and new names with highlighted substrings.
- **FR-003**: Executions MUST append detailed entries to `.renamer` including original names, replacements performed, patterns supplied, and timestamps so undo remains possible.
- **FR-004**: Users MUST be able to undo the most recent replace batch via existing undo mechanics without orphaned files.
- **FR-005**: Command MUST respect global scope flags (`--recursive`, `--include-dirs`, `--hidden`, `--extensions`, `--path`) identical to `list` / `preview` behavior.
- **FR-006**: Command MUST accept two or more patterns and collapse them into a single replacement string applied to every filename in scope.
- **FR-007**: Command MUST preserve idempotence by deduplicating patterns and reporting the number of substitutions per pattern in summary output.
- **FR-008**: Invalid invocations (fewer than two arguments, empty pattern list after deduplication, missing replacement) MUST fail with exit code ≠0 and actionable usage guidance.
- **FR-009**: CLI help MUST document quoting rules for patterns containing spaces or shell special characters.
### Key Entities *(include if feature involves data)*
- **ReplaceRequest**: Captures working directory, scope flags, ordered pattern list, replacement string, and preview/apply options.
- **ReplaceSummary**: Aggregates per-pattern match counts, per-file changes, and conflict warnings for preview and ledger output.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: Users complete a multi-pattern replacement across 100 files with preview + apply in under 2 minutes end-to-end.
- **SC-002**: 95% of usability test participants interpret the final positional replacement argument correctly after reading `renamer replace --help`.
- **SC-003**: Automated regression tests confirm replace + undo leave the filesystem unchanged in 100% of scripted scenarios.
- **SC-004**: Support tickets related to manual string normalization drop by 40% within the first release cycle after launch.
## Assumptions
- Patterns are treated as literal substrings; regex support is out of scope for this increment.
- Case-sensitive matching aligns with current rename semantics; advanced matching can be added later.
- Replacement applies to filenames (and directories when `-d`/`--include-dirs` is set), not file contents.
- Existing infrastructure for preview, ledger, and undo can be extended without architectural changes.
## Dependencies & Risks
- Requires updates to shared traversal/filter utilities so replace respects global scope flags.
- Help/quickstart documentation must be updated alongside the command to prevent misuse.
- Potential filename conflicts must be detected pre-apply to avoid data loss; conflict handling relies on existing validation pipeline.