Skip to content

Commit 89694cc

Browse files
elifarleyclaude
andcommitted
Replace --date none with --skip-date for CLI consistency
- Add --skip-date boolean flag to skip date display entirely - Add --date-format flag for date format choices (seconds|day) - Remove --date choice-based flag entirely - Update both flat and tree renderers to use new parameters - Refactor get_column_specs() to handle skip_date boolean - Update all tests to use new flag patterns - Update README.md documentation - Achieve consistent skip-* pattern across all flags 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 363125b commit 89694cc

File tree

7 files changed

+208
-58
lines changed

7 files changed

+208
-58
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ cedarmapper ls --max-depth 2
4848
cedarmapper ls --sort -w
4949

5050
# Show dates in day format (YYYY-MM-DD)
51-
cedarmapper ls --date day
51+
cedarmapper ls --date-format day
52+
53+
# Skip date display entirely
54+
cedarmapper ls --skip-date
5255

5356
# Skip word counting for faster analysis
5457
cedarmapper ls --skip-word-count
@@ -66,7 +69,8 @@ cedarmapper ls src/ --tree --max-depth 3 --sort -s
6669
- `--tree` - Show tree-like nested output (human-friendly)
6770
- `--follow-symlinks` - Follow symbolic links during traversal
6871
- `--skip-word-count` - Skip word counting for speed
69-
- `--date` - Date display: 'seconds' (default), 'day', or 'none'
72+
- `--date-format` - Date format: 'seconds' (default) or 'day'
73+
- `--skip-date` - Skip date display entirely
7074
- `--numbered-indent` - Show depth as number prefix (tree only)
7175
- `--sort` - Sort specification using keys: w=word count, s=size, d=date, i=depth, n=name, p=path
7276

src/cedarmapper/cli/main.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def run_cli(argv: list[str] | None = None) -> tuple[int, str]:
2727
tree = False
2828
follow_symlinks = False
2929
skip_word_count = False
30-
date_mode = "seconds" # seconds | day | none
30+
date_format = "seconds" # seconds | day
31+
skip_date = False
3132
numbered_indent = False
3233
sort_spec = None
3334
skip_header = False
@@ -46,13 +47,15 @@ def run_cli(argv: list[str] | None = None) -> tuple[int, str]:
4647
follow_symlinks = True
4748
elif token == "--skip-word-count":
4849
skip_word_count = True
49-
elif token == "--date":
50+
elif token == "--skip-date":
51+
skip_date = True
52+
elif token == "--date-format":
5053
try:
51-
date_mode = next(it)
52-
if date_mode not in ("seconds", "day", "none"):
53-
return 2, "Error: --date must be one of seconds|day|none"
54+
date_format = next(it)
55+
if date_format not in ("seconds", "day"):
56+
return 2, "Error: --date-format must be one of seconds|day"
5457
except StopIteration:
55-
return 2, "Error: --date expects a value"
58+
return 2, "Error: --date-format expects a value"
5659
elif token == "--numbered-indent":
5760
numbered_indent = True
5861
elif token == "--sort":
@@ -83,20 +86,24 @@ def run_cli(argv: list[str] | None = None) -> tuple[int, str]:
8386
out = render_tree(
8487
dirinfo,
8588
max_depth=max_depth,
86-
date_mode=date_mode,
89+
date_format=date_format,
90+
skip_date=skip_date,
8791
numbered_indent=numbered_indent,
8892
sort_spec=sort_spec,
8993
skip_header=skip_header,
9094
skip_totals=skip_totals,
95+
skip_word_count=skip_word_count,
9196
)
9297
else:
9398
out = render_flat(
9499
dirinfo,
95100
max_depth=max_depth,
96-
date_mode=date_mode,
101+
date_format=date_format,
102+
skip_date=skip_date,
97103
sort_spec=sort_spec,
98104
skip_header=skip_header,
99105
skip_totals=skip_totals,
106+
skip_word_count=skip_word_count,
100107
)
101108

102109
return 0, out
@@ -127,11 +134,17 @@ def cli() -> None:
127134
"--skip-word-count", is_flag=True, default=False, help="Skip word counting for speed."
128135
)
129136
@click.option(
130-
"--date",
131-
"date_mode",
132-
type=click.Choice(["seconds", "day", "none"], case_sensitive=True),
137+
"--date-format",
138+
"date_format",
139+
type=click.Choice(["seconds", "day"], case_sensitive=True),
133140
default="seconds",
134-
help="Date display: 'seconds' (YYYY-MM-DDTHH:MM:SS), 'day' (YYYY-MM-DD), or 'none' (omit).",
141+
help="Date format: 'seconds' (YYYY-MM-DDTHH:MM:SS) or 'day' (YYYY-MM-DD).",
142+
)
143+
@click.option(
144+
"--skip-date",
145+
is_flag=True,
146+
default=False,
147+
help="Skip date display entirely.",
135148
)
136149
@click.option(
137150
"--numbered-indent",
@@ -164,7 +177,8 @@ def ls(
164177
tree: bool,
165178
follow_symlinks: bool,
166179
skip_word_count: bool,
167-
date_mode: str,
180+
date_format: str,
181+
skip_date: bool,
168182
numbered_indent: bool,
169183
sort_spec: str | None,
170184
skip_header: bool,
@@ -180,8 +194,10 @@ def ls(
180194
argv.append("--follow-symlinks")
181195
if skip_word_count:
182196
argv.append("--skip-word-count")
183-
if date_mode and date_mode != "seconds":
184-
argv.extend(["--date", date_mode])
197+
if skip_date:
198+
argv.append("--skip-date")
199+
if date_format and date_format != "seconds":
200+
argv.extend(["--date-format", date_format])
185201
if numbered_indent:
186202
argv.append("--numbered-indent")
187203
if sort_spec:

src/cedarmapper/render/flat.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,12 @@ def render_flat(
5858
root: DirInfo,
5959
max_depth: int = 0,
6060
*,
61-
date_mode: str = "seconds",
61+
date_format: str = "seconds",
62+
skip_date: bool = False,
6263
sort_spec: str | None = None,
6364
skip_header: bool = False,
6465
skip_totals: bool = False,
66+
skip_word_count: bool = False,
6567
) -> str:
6668
"""
6769
Render all nodes (dirs and files) that are at display depth <= max_depth.
@@ -129,22 +131,30 @@ def _render_node(node: DirInfo | FileInfo, depth: int, parent_path: str) -> None
129131

130132
# Add header if not skipped
131133
if not skip_header:
132-
column_specs = get_column_specs(date_mode)
134+
column_specs = get_column_specs(date_format, skip_word_count, skip_date)
133135
lines.append(format_header_row(column_specs))
134136

135137
# Add data rows
136138
for r in rows:
137-
date_str = _fmt_mtime(r.mtime, date_mode)
138-
if date_mode == "none":
139+
date_str = _fmt_mtime(r.mtime, date_format)
140+
if skip_word_count and skip_date:
141+
# Size + Path
142+
lines.append(f"{r.size_bytes:>12} {r.path}")
143+
elif skip_word_count and not skip_date:
144+
# Size + Modified + Path
145+
lines.append(f"{r.size_bytes:>12} {date_str:>19} {r.path}")
146+
elif not skip_word_count and skip_date:
147+
# Words + Size + Path
139148
lines.append(f"{_fmt_count(r.word_count):>7} {r.size_bytes:>12} {r.path}")
140149
else:
150+
# Words + Size + Modified + Path
141151
lines.append(
142152
f"{_fmt_count(r.word_count):>7} {r.size_bytes:>12} {date_str:>19} {r.path}"
143153
)
144154

145155
# Add totals footer if not skipped and we have multiple data rows
146156
if not skip_totals and len(rows) >= 2:
147-
column_specs = get_column_specs(date_mode)
157+
column_specs = get_column_specs(date_format, skip_word_count, skip_date)
148158
lines.append(format_separator_row(column_specs))
149159
lines.append(format_totals_row(column_specs, root))
150160

src/cedarmapper/render/tree.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ def render_tree(
3737
root: DirInfo,
3838
max_depth: int = 0,
3939
*,
40-
date_mode: str = "seconds",
40+
date_format: str = "seconds",
41+
skip_date: bool = False,
4142
numbered_indent: bool = False,
4243
sort_spec: str | None = None,
4344
skip_header: bool = False,
4445
skip_totals: bool = False,
46+
skip_word_count: bool = False,
4547
) -> str:
4648
"""
4749
Render tree structure with word count, bytes, mtime (per date_mode), and path.
@@ -89,28 +91,36 @@ def _render_node(
8991
prefix = "".join(prefix_parts)
9092

9193
if isinstance(node, FileInfo):
92-
date_str = _fmt_mtime(node.mtime, date_mode)
94+
date_str = _fmt_mtime(node.mtime, date_format)
9395
display_name = node.path.name
94-
if date_mode == "none":
95-
data_lines.append(
96-
f"{_fmt_count(node.word_count):>7} {node.size_bytes:>12} {prefix}{display_name}"
97-
)
96+
if skip_word_count and skip_date:
97+
# Size + Path
98+
data_lines.append(f"{node.size_bytes:>12} {prefix}{display_name}")
99+
elif skip_word_count and not skip_date:
100+
# Size + Modified + Path
101+
data_lines.append(f"{node.size_bytes:>12} {date_str:>19} {prefix}{display_name}")
102+
elif not skip_word_count and skip_date:
103+
# Words + Size + Path
104+
data_lines.append(f"{_fmt_count(node.word_count):>7} {node.size_bytes:>12} {prefix}{display_name}")
98105
else:
99-
data_lines.append(
100-
f"{_fmt_count(node.word_count):>7} {node.size_bytes:>12} {date_str:>19} {prefix}{display_name}"
101-
)
106+
# Words + Size + Modified + Path
107+
data_lines.append(f"{_fmt_count(node.word_count):>7} {node.size_bytes:>12} {date_str:>19} {prefix}{display_name}")
102108
else:
103109
# DirInfo
104-
date_str = _fmt_mtime(node.mtime, date_mode)
110+
date_str = _fmt_mtime(node.mtime, date_format)
105111
display_name = f"{node.path.name}/"
106-
if date_mode == "none":
107-
data_lines.append(
108-
f"{str(node.word_count):>7} {node.size_bytes:>12} {prefix}{display_name}"
109-
)
112+
if skip_word_count and skip_date:
113+
# Size + Path
114+
data_lines.append(f"{node.size_bytes:>12} {prefix}{display_name}")
115+
elif skip_word_count and not skip_date:
116+
# Size + Modified + Path
117+
data_lines.append(f"{node.size_bytes:>12} {date_str:>19} {prefix}{display_name}")
118+
elif not skip_word_count and skip_date:
119+
# Words + Size + Path
120+
data_lines.append(f"{str(node.word_count):>7} {node.size_bytes:>12} {prefix}{display_name}")
110121
else:
111-
data_lines.append(
112-
f"{str(node.word_count):>7} {node.size_bytes:>12} {date_str:>19} {prefix}{display_name}"
113-
)
122+
# Words + Size + Modified + Path
123+
data_lines.append(f"{str(node.word_count):>7} {node.size_bytes:>12} {date_str:>19} {prefix}{display_name}")
114124

115125
# If we are allowed to show children (display depth), iterate
116126
if depth < max_depth:
@@ -173,15 +183,15 @@ def __init__(self, obj, depth_value, parent_path):
173183

174184
# Add header if not skipped
175185
if not skip_header:
176-
column_specs = get_column_specs(date_mode)
186+
column_specs = get_column_specs(date_format, skip_word_count, skip_date)
177187
lines.append(format_header_row(column_specs))
178188

179189
# Add data rows
180190
lines.extend(data_lines)
181191

182192
# Add totals footer if not skipped and we have multiple data rows
183193
if not skip_totals and len(data_lines) >= 2:
184-
column_specs = get_column_specs(date_mode)
194+
column_specs = get_column_specs(date_format, skip_word_count, skip_date)
185195
lines.append(format_separator_row(column_specs))
186196
lines.append(format_totals_row(column_specs, root))
187197

src/cedarmapper/render/utils.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ class ColumnSpec(NamedTuple):
1515
formatter: callable
1616

1717

18-
def get_column_specs(date_mode: str) -> list[ColumnSpec]:
19-
"""Get column specifications based on date mode."""
20-
specs = [
21-
ColumnSpec("Words", 7, _fmt_count),
22-
ColumnSpec("Size", 12, lambda x: str(x)),
23-
]
24-
if date_mode != "none":
25-
specs.append(ColumnSpec("Modified", 19, lambda dt: _fmt_mtime(dt, date_mode)))
18+
def get_column_specs(date_format: str, skip_word_count: bool = False, skip_date: bool = False) -> list[ColumnSpec]:
19+
"""Get column specifications based on date format and skip preferences."""
20+
specs = []
21+
if not skip_word_count:
22+
specs.append(ColumnSpec("Words", 7, _fmt_count))
23+
specs.append(ColumnSpec("Size", 12, lambda x: str(x)))
24+
if not skip_date:
25+
specs.append(ColumnSpec("Modified", 19, lambda dt: _fmt_mtime(dt, date_format)))
2626
return specs
2727

2828

@@ -69,10 +69,9 @@ def _fmt_count(c: int | None) -> str:
6969
return "-" if c is None else str(c)
7070

7171

72-
def _fmt_mtime(dt: datetime, mode: str) -> str:
72+
def _fmt_mtime(dt: datetime, format_mode: str) -> str:
7373
"""Format modification time for display."""
74-
if mode == "none":
75-
return ""
76-
if mode == "day":
74+
if format_mode == "day":
7775
return dt.date().isoformat()
76+
# default: seconds
7877
return dt.replace(microsecond=0).isoformat()

0 commit comments

Comments
 (0)