feat: add list command with global filters
This commit is contained in:
34
specs/001-list-command-filters/checklists/requirements.md
Normal file
34
specs/001-list-command-filters/checklists/requirements.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Specification Quality Checklist: Cobra List Command with Global Filters
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2025-10-29
|
||||
**Feature**: [spec.md](../spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined
|
||||
- [x] Edge cases are identified
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria
|
||||
- [x] User scenarios cover primary flows
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`
|
||||
59
specs/001-list-command-filters/contracts/list-command.md
Normal file
59
specs/001-list-command-filters/contracts/list-command.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# CLI Contract: `renamer list`
|
||||
|
||||
## Command Synopsis
|
||||
|
||||
```bash
|
||||
renamer list [--path <dir>] [-r] [-d] [-e .ext|.ext2] [--format table|plain]
|
||||
```
|
||||
|
||||
## Description
|
||||
Enumerates filesystem entries that match the active global filters without applying any rename
|
||||
operations. Output supports human-friendly table view and automation-friendly plain mode. Results
|
||||
mirror the candidate set used by `renamer preview` and `renamer rename`.
|
||||
|
||||
## Arguments & Flags
|
||||
|
||||
| Flag | Type | Default | Required | Applies To | Description |
|
||||
|------|------|---------|----------|------------|-------------|
|
||||
| `--path` | string | current directory | No | root command | Directory to operate on; must exist and be readable |
|
||||
| `-r`, `--recursive` | bool | `false` | No | root command | Enable depth-first traversal through subdirectories |
|
||||
| `-d`, `--include-dirs` | bool | `false` | No | root command | Include directories in output alongside files |
|
||||
| `-e`, `--extensions` | string | (none) | No | root command | `|`-delimited list of `.`-prefixed extensions used to filter files |
|
||||
| `--format` | enum (`table`, `plain`) | `table` | No | list subcommand | Controls output rendering style |
|
||||
| `--limit` | int | 0 (no limit) | No | list subcommand | Optional cap on number of entries returned; 0 means unlimited |
|
||||
| `--no-progress` | bool | `false` | No | list subcommand | Suppress progress indicators for scripting |
|
||||
|
||||
## Exit Codes
|
||||
|
||||
| Code | Meaning | Example Trigger |
|
||||
|------|---------|-----------------|
|
||||
| `0` | Success | Listing completed even if zero entries matched |
|
||||
| `2` | Validation error | Duplicate/empty extension token, unreadable path |
|
||||
| `3` | Traversal failure | I/O error during directory walk |
|
||||
|
||||
## Output Formats
|
||||
|
||||
### Table (default)
|
||||
```
|
||||
PATH TYPE SIZE
|
||||
photos/2024/event.jpg file 3.2 MB
|
||||
photos/2024 directory —
|
||||
```
|
||||
|
||||
### Plain (`--format plain`)
|
||||
```
|
||||
photos/2024/event.jpg
|
||||
photos/2024
|
||||
```
|
||||
|
||||
Both formats MUST include a trailing summary line:
|
||||
```
|
||||
Total: 42 entries (files: 38, directories: 4)
|
||||
```
|
||||
|
||||
## Validation Rules
|
||||
- Extensions MUST begin with `.` and be deduplicated case-insensitively.
|
||||
- When no entries remain after filtering, the command prints `No entries matched the provided
|
||||
filters.` and exits with code `0`.
|
||||
- Symlinks MUST be reported with type `symlink` and NOT followed recursively unless future scope
|
||||
explicitly enables it.
|
||||
40
specs/001-list-command-filters/data-model.md
Normal file
40
specs/001-list-command-filters/data-model.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Data Model: Cobra List Command with Global Filters
|
||||
|
||||
## Entities
|
||||
|
||||
### ListingRequest
|
||||
- **Description**: Captures the user’s desired listing scope and presentation options.
|
||||
- **Fields**:
|
||||
- `workingDir` (string): Absolute or relative path where traversal begins. Default: current dir.
|
||||
- `includeDirectories` (bool): Mirrors `-d` flag; when true, directories appear in results.
|
||||
- `recursive` (bool): Mirrors `-r` flag; enables depth-first traversal of subdirectories.
|
||||
- `extensions` ([]string): Parsed, normalized list of `.`-prefixed extensions from `-e`.
|
||||
- `format` (enum): Output format requested (`table`, `plain`).
|
||||
- `maxDepth` (int, optional): Future-safe guard to prevent runaway recursion; defaults to unlimited.
|
||||
- **Validations**:
|
||||
- `extensions` MUST NOT contain empty strings or duplicates after normalization.
|
||||
- `format` MUST be one of the supported enum values; invalid values trigger validation errors.
|
||||
- `workingDir` MUST resolve to an accessible directory before traversal begins.
|
||||
|
||||
### ListingEntry
|
||||
- **Description**: Represents a single filesystem node returned by the list command.
|
||||
- **Fields**:
|
||||
- `path` (string): Relative path from `workingDir`.
|
||||
- `type` (enum): `file`, `directory`, or `symlink`.
|
||||
- `sizeBytes` (int64): File size in bytes; directories report aggregated size only if available.
|
||||
- `depth` (int): Depth level from the root directory (root = 0).
|
||||
- `matchedExtension` (string, optional): Extension that satisfied the filter when applicable.
|
||||
- **Validations**:
|
||||
- `path` MUST be unique within a single command invocation.
|
||||
- `type` MUST align with actual filesystem metadata; symlinks MUST be flagged to avoid confusion.
|
||||
|
||||
## Relationships
|
||||
- `ListingRequest` produces a stream of `ListingEntry` items based on traversal rules.
|
||||
- `ListingEntry` items may reference parent directories implicitly via `path` hierarchy; no explicit
|
||||
parent pointer is stored to keep payload lightweight.
|
||||
|
||||
## State Transitions
|
||||
1. **Initialization**: CLI parses flags into `ListingRequest` and validates inputs.
|
||||
2. **Traversal**: Request feeds traversal engine, emitting raw filesystem metadata.
|
||||
3. **Filtering**: Raw entries filtered against `includeDirectories`, `recursive`, and `extensions`.
|
||||
4. **Formatting**: Filtered entries passed to output renderer selecting table or plain layout.
|
||||
99
specs/001-list-command-filters/plan.md
Normal file
99
specs/001-list-command-filters/plan.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Implementation Plan: Cobra List Command with Global Filters
|
||||
|
||||
**Branch**: `001-list-command-filters` | **Date**: 2025-10-29 | **Spec**: [spec.md](./spec.md)
|
||||
**Input**: Feature specification from `/specs/001-list-command-filters/spec.md`
|
||||
|
||||
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
|
||||
|
||||
## Summary
|
||||
|
||||
Introduce a Cobra `list` subcommand that enumerates filesystem entries using the same global filter
|
||||
flags (`-r`, `-d`, `-e`) shared with preview/rename flows. The command will reuse traversal and
|
||||
validation utilities to guarantee consistent candidate sets, provide table/plain output formats, and
|
||||
surface clear messaging for empty results or invalid filters.
|
||||
|
||||
## Technical Context
|
||||
|
||||
<!--
|
||||
ACTION REQUIRED: Replace the content in this section with the technical details
|
||||
for the project. The structure here is presented in advisory capacity to guide
|
||||
the iteration process.
|
||||
-->
|
||||
|
||||
**Language/Version**: Go 1.24
|
||||
**Primary Dependencies**: `spf13/cobra`, `spf13/pflag`
|
||||
**Storage**: Local filesystem (read-only listing)
|
||||
**Testing**: Go `testing` package with CLI-focused integration tests
|
||||
**Target Platform**: Cross-platform CLI (Linux, macOS, Windows)
|
||||
**Project Type**: Single CLI project
|
||||
**Performance Goals**: First page of 5k entries within 2 seconds via streaming output
|
||||
**Constraints**: Deterministic ordering, no filesystem mutations, filters shared across commands
|
||||
**Scale/Scope**: Operates on directories with tens of thousands of entries per invocation
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
- Preview flow MUST show deterministic rename mappings and require explicit confirmation (Preview-First Safety).
|
||||
- Undo strategy MUST describe how the `.renamer` ledger entry is written and reversed (Persistent Undo Ledger).
|
||||
- Planned rename rules MUST document their inputs, validations, and composing order (Composable Rule Engine).
|
||||
- Scope handling MUST cover files vs directories (`-d`), recursion (`-r`), and extension filtering via `-e` without escaping the requested path (Scope-Aware Traversal).
|
||||
- CLI UX plan MUST confirm Cobra usage, flag naming, help text, and automated tests for preview/undo flows (Ergonomic CLI Stewardship).
|
||||
|
||||
**Gate Alignment**:
|
||||
- Listing command will remain a read-only helper; preview/rename confirmation flow stays unchanged.
|
||||
- Ledger logic untouched; plan maintains append-only guarantees by reusing existing history modules.
|
||||
- Filters, traversal, and rule composition will be centralized to avoid divergence between commands.
|
||||
- Root-level flags (`-r`, `-d`, `-e`) will configure shared traversal services so all subcommands honor identical scope rules.
|
||||
- Cobra command UX will include consistent help text, validation errors, and integration tests for list/preview parity.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/001-list-command-filters/
|
||||
├── plan.md # This file (/speckit.plan command output)
|
||||
├── research.md # Phase 0 output (/speckit.plan command)
|
||||
├── data-model.md # Phase 1 output (/speckit.plan command)
|
||||
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
||||
├── contracts/ # Phase 1 output (/speckit.plan command)
|
||||
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
<!--
|
||||
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
|
||||
for this feature. Delete unused options and expand the chosen structure with
|
||||
real paths (e.g., apps/admin, packages/something). The delivered plan must
|
||||
not include Option labels.
|
||||
-->
|
||||
|
||||
```text
|
||||
cmd/
|
||||
├── root.go # Cobra root command with global flags
|
||||
├── list.go # New list subcommand entry point
|
||||
└── preview.go # Existing preview wiring (to be reconciled with shared filters)
|
||||
|
||||
internal/
|
||||
├── traversal/ # Scope walking utilities (files, directories, recursion)
|
||||
├── filters/ # Extension parsing/validation shared across commands
|
||||
├── listing/ # New package composing traversal + formatting
|
||||
└── output/ # Shared renderers for table/plain display
|
||||
|
||||
tests/
|
||||
├── contract/
|
||||
│ └── list_command_test.go
|
||||
├── integration/
|
||||
│ └── list_and_preview_parity_test.go
|
||||
└── fixtures/ # Sample directory trees for CLI tests
|
||||
```
|
||||
|
||||
**Structure Decision**: Single CLI repository rooted at `cmd/` with supporting packages under
|
||||
`internal/`. Shared traversal and filter logic will move into dedicated packages to ensure the
|
||||
global flags are consumed identically by `list`, `preview`, and rename workflows. Tests live under
|
||||
`tests/` mirroring contract vs integration coverage.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
No constitution gate violations identified; no additional complexity justifications required.
|
||||
60
specs/001-list-command-filters/quickstart.md
Normal file
60
specs/001-list-command-filters/quickstart.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Quickstart: Cobra List Command with Global Filters
|
||||
|
||||
## Goal
|
||||
Learn how to preview rename scope safely by using the new `renamer list` subcommand with global
|
||||
filter flags that apply across all commands.
|
||||
|
||||
## Prerequisites
|
||||
- Go toolchain installed (>= 1.24) for building the CLI locally.
|
||||
- Sample directory containing mixed file types to exercise filters.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Build the CLI**
|
||||
```bash
|
||||
go build -o renamer ./...
|
||||
```
|
||||
|
||||
2. **Inspect available commands and global flags**
|
||||
```bash
|
||||
./renamer --help
|
||||
./renamer list --help
|
||||
```
|
||||
Confirm `-r`, `-d`, and `-e` are listed as global flags.
|
||||
|
||||
3. **List JPEG assets recursively**
|
||||
```bash
|
||||
./renamer list -r -e .jpg
|
||||
```
|
||||
Verify output shows a table with relative paths, types, and sizes. The summary line should report
|
||||
total entries found.
|
||||
|
||||
4. **Produce automation-friendly output**
|
||||
```bash
|
||||
./renamer list --format plain -e .mov|.mp4 > media-files.txt
|
||||
```
|
||||
Inspect `media-files.txt` to confirm one path per line.
|
||||
|
||||
5. **Validate filter parity with preview**
|
||||
```bash
|
||||
./renamer list -r -d -e .txt|.md
|
||||
./renamer preview -r -d -e .txt|.md
|
||||
```
|
||||
Ensure both commands report the same number of directories, since `-d` suppresses files.
|
||||
|
||||
6. **Handle empty results gracefully**
|
||||
```bash
|
||||
./renamer list -e .doesnotexist
|
||||
```
|
||||
Expect a friendly message explaining that no entries matched the filters.
|
||||
|
||||
7. **Inspect hidden files when needed**
|
||||
```bash
|
||||
./renamer list --hidden -e .env
|
||||
```
|
||||
Hidden entries are excluded by default, so `--hidden` opts in explicitly when you need to audit dotfiles.
|
||||
|
||||
## Next Steps
|
||||
- Integrate the list command into scripts that currently run `preview` to guard against unintended
|
||||
rename scopes.
|
||||
- Extend automated tests to cover new filters plus list/preview parity checks.
|
||||
33
specs/001-list-command-filters/research.md
Normal file
33
specs/001-list-command-filters/research.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Phase 0 Research: Cobra List Command with Global Filters
|
||||
|
||||
## Decision: Promote scope flags to Cobra root command persistent flags
|
||||
- **Rationale**: Persistent flags defined on the root command automatically apply to all
|
||||
subcommands, ensuring a single source of truth for recursion (`-r`), directory inclusion (`-d`),
|
||||
and extension filters (`-e`). This prevents divergence between `list`, `preview`, and future
|
||||
rename commands.
|
||||
- **Alternatives considered**:
|
||||
- *Duplicate flag definitions per subcommand*: rejected because it risks inconsistent validation
|
||||
and requires keeping help text in sync.
|
||||
- *Environment variables for shared filters*: rejected because CLI users expect flag-driven scope
|
||||
control and env vars complicate scripting.
|
||||
|
||||
## Decision: Stream directory traversal using `filepath.WalkDir` with early emission
|
||||
- **Rationale**: `WalkDir` supports depth-first traversal with built-in symlink detection and allows
|
||||
emitting entries as they are encountered, keeping memory usage bounded even for directories with
|
||||
>10k items.
|
||||
- **Alternatives considered**:
|
||||
- *Preloading all entries into slices before formatting*: rejected because it inflates memory and
|
||||
delays first output, violating the 2-second responsiveness goal.
|
||||
- *Shelling out to `find` or OS-specific tools*: rejected due to portability concerns and reduced
|
||||
testability inside Go.
|
||||
|
||||
## Decision: Provide dual output renderers (table + plain) via shared formatter interface
|
||||
- **Rationale**: Implementing a small formatter interface allows easy expansion of output modes and
|
||||
keeps the list command decoupled from presentation details. A table renderer can rely on
|
||||
text/tabwriter, while the plain renderer writes newline-delimited paths to satisfy scripting use
|
||||
cases.
|
||||
- **Alternatives considered**:
|
||||
- *Hard-coding formatted strings inside the command*: rejected because it complicates testing and
|
||||
future format additions (JSON, CSV).
|
||||
- *Introducing a heavy templating library*: rejected as unnecessary overhead for simple CLI
|
||||
output.
|
||||
151
specs/001-list-command-filters/spec.md
Normal file
151
specs/001-list-command-filters/spec.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Feature Specification: Cobra List Command with Global Filters
|
||||
|
||||
**Feature Branch**: `001-list-command-filters`
|
||||
**Created**: 2025-10-29
|
||||
**Status**: Draft
|
||||
**Input**: User description: "实现文件列表遍历展示cobra 子命令(list),支持当前系统要求的过滤参数(过滤参数为全局生效,所以应该指定到root command上)。"
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Discover Filtered Files Before Renaming (Priority: P1)
|
||||
|
||||
As a command-line user preparing a batch rename, I want to run `renamer list` with the same filters
|
||||
that the rename command will honor so I can preview the exact files that will be affected.
|
||||
|
||||
**Why this priority**: Prevents accidental renames by making scope explicit before any destructive
|
||||
action.
|
||||
|
||||
**Independent Test**: Execute `renamer list -e .jpg|.png` in a sample directory and verify the output
|
||||
lists only matching files without performing any rename.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a directory containing mixed file types, **When** the user runs `renamer list -e .jpg`,
|
||||
**Then** the output only includes `.jpg` files and reports the total count.
|
||||
2. **Given** a directory tree with nested folders, **When** the user runs `renamer list -r`,
|
||||
**Then** results include files from subdirectories with each entry showing the relative path.
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - Apply Global Filters Consistently (Priority: P2)
|
||||
|
||||
As an operator scripting renamer commands, I want filter flags (`-r`, `-d`, `-e`) to be defined on
|
||||
the root command so they apply consistently to `list`, `preview`, and future subcommands without
|
||||
redundant configuration.
|
||||
|
||||
**Why this priority**: Ensures a single source of truth for scope filters, reducing user error and
|
||||
documentation complexity.
|
||||
|
||||
**Independent Test**: Run `renamer list` and `renamer preview` with the same global flags in a
|
||||
script, confirming both commands interpret scope identically.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** the root command defines global filter flags, **When** the user specifies `--extensions
|
||||
.mov|.mp4` with `renamer list`, **Then** running `renamer preview` in the same shell session with
|
||||
identical flags produces the same candidate set.
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - Review Listing Output Comfortably (Priority: P3)
|
||||
|
||||
As a user reviewing large directories, I want the `list` output to provide human-readable columns
|
||||
and an optional machine-friendly format so I can spot issues quickly or pipe results into other
|
||||
tools.
|
||||
|
||||
**Why this priority**: Good ergonomics encourage the list command to become part of every workflow,
|
||||
increasing safety and adoption.
|
||||
|
||||
**Independent Test**: Run `renamer list --format table` and `renamer list --format plain` to confirm
|
||||
both modes display the same entries in different formats without extra configuration.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** the list command is executed with default settings, **When** multiple files are
|
||||
returned, **Then** the output presents aligned columns containing path, type (file/directory),
|
||||
and size.
|
||||
2. **Given** the user supplies `--format plain`, **When** the command runs, **Then** the output
|
||||
emits one path per line suitable for piping into other commands.
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- Directory contains no items after filters are applied; command must exit gracefully with zero
|
||||
results and a clear message.
|
||||
- Filters include duplicate or malformed extensions (e.g., `-e .jpg||.png`); command must reject the
|
||||
input and surface a descriptive validation error.
|
||||
- Listing directories requires read permissions; command must skip unreadable paths, log warnings,
|
||||
and continue scanning allowed paths.
|
||||
- File system contains symbolic links or junctions; traversal must avoid infinite loops and clearly
|
||||
mark symlinked entries.
|
||||
- Large directories (>10k entries); command must stream results without excessive memory usage and
|
||||
display progress feedback when execution exceeds a user-friendly threshold.
|
||||
- Hidden files may be unintentionally included; unless `--hidden` is provided, they must remain
|
||||
excluded and the help text should explain how to opt in.
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: The root Cobra command MUST expose global filter flags for recursion (`-r`), directory
|
||||
inclusion (`-d`), and extension filtering (`-e .ext|.ext2`) that apply to all subcommands.
|
||||
- **FR-002**: The `list` subcommand MUST enumerate files and directories matching the active filters
|
||||
within the current (or user-specified) working directory without modifying the filesystem.
|
||||
- **FR-003**: Listing results MUST be deterministic: entries sorted lexicographically by relative
|
||||
path with directories identified distinctly from files.
|
||||
- **FR-004**: The command MUST support at least two output formats: a human-readable table (default)
|
||||
and a plain-text list (`--format plain`) for automation.
|
||||
- **FR-005**: When filters exclude all entries, the CLI MUST communicate that zero results were
|
||||
found and suggest reviewing filter parameters.
|
||||
- **FR-006**: The `list` subcommand MUST share validation and traversal utilities with preview and
|
||||
rename flows to guarantee identical scope resolution across commands.
|
||||
- **FR-007**: The command MUST return a non-zero exit code when input validation fails and zero when
|
||||
execution completes successfully, enabling scripting.
|
||||
- **FR-008**: Hidden files and directories MUST be excluded by default and only included when users
|
||||
explicitly pass a `--hidden` flag.
|
||||
|
||||
### Key Entities *(include if feature involves data)*
|
||||
|
||||
- **ListingRequest**: Captures active filters (recursion, directory inclusion, extensions, path) and
|
||||
desired output format for a listing invocation.
|
||||
- **ListingEntry**: Represents a single file or directory discovered during traversal, including its
|
||||
relative path, type, size (bytes), and depth.
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: Users can execute `renamer list` with filters on a directory containing up to 5,000
|
||||
entries and receive the first page of results within 2 seconds.
|
||||
- **SC-002**: In usability testing, 90% of participants correctly predict which files will be renamed
|
||||
after reviewing `renamer list` output.
|
||||
- **SC-003**: Automated regression tests confirm that `list`, `preview`, and `rename` commands return
|
||||
identical candidate counts for the same filter combinations in 100% of tested scenarios.
|
||||
- **SC-004**: Support requests related to "unexpected files being renamed" decrease by 30% in the
|
||||
first release cycle following launch.
|
||||
|
||||
## Assumptions
|
||||
|
||||
- Default output format is a table suitable for terminals with ANSI support; plain text is available
|
||||
for scripting without additional flags beyond `--format`.
|
||||
- Users run commands from the directory they intend to operate on; specifying alternative roots will
|
||||
follow existing conventions (e.g., `--path`) if already provided by the tool.
|
||||
- Existing preview and rename workflows already rely on shared traversal utilities that can be
|
||||
extended for the list command.
|
||||
|
||||
## Dependencies & Risks
|
||||
|
||||
- Requires traversal utilities to handle large directories efficiently; performance optimizations may
|
||||
be needed if current implementation does not stream results.
|
||||
- Depends on existing validation logic for extension filtering and directory scopes; any divergence
|
||||
introduces inconsistency between commands.
|
||||
- Risk of confusing users if help documentation is not updated to emphasize using `list` before
|
||||
running rename operations.
|
||||
|
||||
## Clarifications
|
||||
|
||||
### Session 2025-10-29
|
||||
|
||||
- Q: Should the list command include hidden files by default or require an explicit opt-in? → A:
|
||||
Exclude hidden files by default; add a `--hidden` flag to include them.
|
||||
175
specs/001-list-command-filters/tasks.md
Normal file
175
specs/001-list-command-filters/tasks.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Tasks: Cobra List Command with Global Filters
|
||||
|
||||
**Input**: Design documents from `/specs/001-list-command-filters/`
|
||||
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
|
||||
|
||||
**Tests**: Tests are optional; include them only where they support the user story’s independent validation.
|
||||
|
||||
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
- **[P]**: Can run in parallel (different files, no dependencies)
|
||||
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
||||
- Include exact file paths in descriptions
|
||||
|
||||
## Phase 1: Setup (Shared Infrastructure)
|
||||
|
||||
**Purpose**: Prepare Cobra project for new subcommand and tests
|
||||
|
||||
- [X] T001 Normalize root command metadata and remove placeholder toggle flag in `cmd/root.go`
|
||||
- [X] T002 Scaffold listing service package with stub struct in `internal/listing/service.go`
|
||||
- [X] T003 Add fixture guidance for sample directory trees in `tests/fixtures/README.md`
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: Core utilities shared across list, preview, and rename flows
|
||||
|
||||
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
||||
|
||||
- [X] T004 Define `ListingRequest`/`ListingEntry` structs with validators in `internal/listing/types.go`
|
||||
- [X] T005 [P] Implement extension filter parser/normalizer in `internal/filters/extensions.go`
|
||||
- [X] T006 [P] Implement streaming traversal walker with symlink guard in `internal/traversal/walker.go`
|
||||
- [X] T007 [P] Declare formatter interface and summary helpers in `internal/output/formatter.go`
|
||||
- [X] T008 Document global filter contract expectations in `docs/cli-flags.md`
|
||||
|
||||
**Checkpoint**: Foundation ready—user story implementation can now begin in parallel
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Discover Filtered Files Before Renaming (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: Provide a read-only `renamer list` command that mirrors rename scope
|
||||
|
||||
**Independent Test**: Run `renamer list -e .jpg|.png` against fixtures and verify results/summary without filesystem changes
|
||||
|
||||
### Tests for User Story 1 (OPTIONAL - included for confidence)
|
||||
|
||||
- [X] T009 [P] [US1] Add contract test for filtered listing summary in `tests/contract/list_command_test.go`
|
||||
- [X] T010 [P] [US1] Add integration test covering recursive listing in `tests/integration/list_recursive_test.go`
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [X] T011 [US1] Implement listing pipeline combining traversal, filters, and summary in `internal/listing/service.go`
|
||||
- [X] T012 [US1] Implement zero-result messaging helper in `internal/listing/summary.go`
|
||||
- [X] T013 [US1] Add Cobra `list` command entry point in `cmd/list.go`
|
||||
- [X] T014 [US1] Register `list` command and write help text in `cmd/root.go`
|
||||
- [X] T015 [US1] Update quickstart usage section for `renamer list` workflow in `specs/001-list-command-filters/quickstart.md`
|
||||
|
||||
**Checkpoint**: User Story 1 delivers a safe, filter-aware listing command
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - Apply Global Filters Consistently (Priority: P2)
|
||||
|
||||
**Goal**: Ensure scope flags (`-r`, `-d`, `-e`) live on the root command and hydrate shared request builders
|
||||
|
||||
**Independent Test**: Execute `renamer list` twice—once via command parsing, once via helper—and confirm identical candidate counts
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [X] T016 [P] [US2] Promote scope flags to persistent flags on the root command in `cmd/root.go`
|
||||
- [X] T017 [US2] Create shared flag extraction helper returning `ListingRequest` in `internal/listing/options.go`
|
||||
- [X] T018 [US2] Refactor `cmd/list.go` to consume shared helper and root-level flags
|
||||
- [X] T019 [P] [US2] Add integration test validating flag parity in `tests/integration/global_flag_parity_test.go`
|
||||
- [X] T020 [US2] Expand CLI flag documentation for global usage patterns in `docs/cli-flags.md`
|
||||
|
||||
**Checkpoint**: User Story 2 guarantees consistent scope interpretation across commands
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 - Review Listing Output Comfortably (Priority: P3)
|
||||
|
||||
**Goal**: Offer table and plain output modes for human review and scripting
|
||||
|
||||
**Independent Test**: Run `renamer list --format table` vs `--format plain` and ensure entries match across formats
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [X] T021 [P] [US3] Implement table renderer using `text/tabwriter` in `internal/output/table.go`
|
||||
- [X] T022 [P] [US3] Implement plain renderer emitting newline-delimited paths in `internal/output/plain.go`
|
||||
- [X] T023 [US3] Wire format selection into listing service dispatcher in `internal/listing/service.go`
|
||||
- [X] T024 [US3] Extend contract tests to verify format output parity in `tests/contract/list_command_test.go`
|
||||
- [X] T025 [US3] Update quickstart to demonstrate `--format` options in `specs/001-list-command-filters/quickstart.md`
|
||||
|
||||
**Checkpoint**: User Story 3 delivers ergonomic output formats for all audiences
|
||||
|
||||
---
|
||||
|
||||
## Phase N: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Final validation, documentation, and release notes
|
||||
|
||||
- [X] T026 Update agent guidance with list command summary in `AGENTS.md`
|
||||
- [X] T027 Add release note entry describing new list command in `docs/CHANGELOG.md`
|
||||
- [X] T028 Create smoke-test script exercising list + preview parity in `scripts/smoke-test-list.sh`
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Setup (Phase 1)**: Complete before foundational utilities to ensure project scaffolding exists.
|
||||
- **Foundational (Phase 2)**: Depends on Setup; blocks all user stories because shared utilities power every command.
|
||||
- **User Story 1 (Phase 3)**: Depends on Foundational; delivers MVP list command.
|
||||
- **User Story 2 (Phase 4)**: Depends on User Story 1 (reuses command structure) and Foundational.
|
||||
- **User Story 3 (Phase 5)**: Depends on User Story 1 (listing pipeline) and Foundational (formatter interface).
|
||||
- **Polish (Final Phase)**: Runs after desired user stories finish.
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **User Story 1 (P1)**: Requires Foundational utilities; no other story prerequisites.
|
||||
- **User Story 2 (P2)**: Requires User Story 1 to expose list command behaviors before sharing flags.
|
||||
- **User Story 3 (P3)**: Requires User Story 1 to deliver base listing plus Foundational formatter interface.
|
||||
|
||||
### Within Each User Story
|
||||
|
||||
- Tests marked [P] should be authored before or alongside implementation; ensure they fail prior to feature work.
|
||||
- Service implementations depend on validated request structs and traversal utilities.
|
||||
- CLI command wiring depends on service implementation and helper functions.
|
||||
- Documentation tasks finalize once command behavior is stable.
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- Foundational tasks T005–T007 operate on different packages and can proceed in parallel after T004 validates data structures.
|
||||
- User Story 1 tests (T009, T010) can be developed in parallel before implementation tasks T011–T014.
|
||||
- User Story 3 renderers (T021, T022) can be implemented concurrently, converging at T023 for integration.
|
||||
|
||||
---
|
||||
|
||||
## Parallel Example: User Story 1
|
||||
|
||||
```bash
|
||||
# In one terminal: author contract test
|
||||
go test ./tests/contract -run TestListCommandFilters
|
||||
|
||||
# In another terminal: implement listing service
|
||||
go test ./internal/listing -run TestService
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 1 Only)
|
||||
|
||||
1. Complete Setup + Foundational phases.
|
||||
2. Implement User Story 1 tasks (T009–T015) to deliver a working `renamer list`.
|
||||
3. Validate with contract/integration tests and quickstart instructions.
|
||||
|
||||
### Incremental Delivery
|
||||
|
||||
1. Deliver MVP (User Story 1).
|
||||
2. Add User Story 2 to guarantee global flag consistency.
|
||||
3. Add User Story 3 to enhance output ergonomics.
|
||||
4. Finalize polish tasks for documentation and smoke testing.
|
||||
|
||||
### Parallel Team Strategy
|
||||
|
||||
- Developer A handles Foundational tasks (T004–T007) while Developer B updates documentation (T008).
|
||||
- After Foundational checkpoint, Developer A implements listing service (T011–T014), Developer B authors tests (T009–T010).
|
||||
- Once MVP ships, Developer A tackles global flag refactor (T016–T018) while Developer B extends integration tests (T019) and docs (T020).
|
||||
- For User Story 3, split renderer work (T021 vs T022) before merging at T023.
|
||||
Reference in New Issue
Block a user