dirplot 0.3.3__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dirplot-0.3.3 → dirplot-0.4.0}/.claude/settings.local.json +3 -1
- dirplot-0.4.0/CHANGELOG.md +431 -0
- dirplot-0.4.0/LICENSE2 +21 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/PKG-INFO +172 -9
- {dirplot-0.3.3 → dirplot-0.4.0}/README.md +168 -5
- {dirplot-0.3.3 → dirplot-0.4.0}/TASKS.md~ +0 -1
- {dirplot-0.3.3 → dirplot-0.4.0}/docs/EXAMPLES.md +5 -5
- dirplot-0.4.0/paths.txt +17 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/pyproject.toml +21 -4
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/__init__.py +1 -1
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/archives.py +1 -1
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/display.py +21 -3
- dirplot-0.4.0/src/dirplot/git_scanner.py +309 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/github.py +30 -0
- dirplot-0.4.0/src/dirplot/main.py +1411 -0
- dirplot-0.4.0/src/dirplot/pathlist.py +154 -0
- dirplot-0.3.3/src/dirplot/render.py → dirplot-0.4.0/src/dirplot/render_png.py +297 -19
- dirplot-0.4.0/src/dirplot/replay_scanner.py +172 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/scanner.py +12 -2
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/svg_render.py +1 -1
- dirplot-0.4.0/src/dirplot/watch.py +279 -0
- dirplot-0.4.0/test_file.txt +0 -0
- dirplot-0.4.0/test_file2.txt +0 -0
- dirplot-0.4.0/tests/__init__.py +0 -0
- dirplot-0.4.0/tests/test_cli.py +483 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_drawing.py +1 -1
- dirplot-0.4.0/tests/test_git_github.py +48 -0
- dirplot-0.4.0/tests/test_git_local.py +153 -0
- dirplot-0.4.0/tests/test_pathlist.py +196 -0
- dirplot-0.3.3/tests/test_render.py → dirplot-0.4.0/tests/test_render_png.py +55 -1
- dirplot-0.4.0/tests/test_watch_animate.py +276 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/uv.lock +2 -4
- dirplot-0.3.3/CHANGELOG.md +0 -221
- dirplot-0.3.3/alpine-pod.png +0 -0
- dirplot-0.3.3/aws-lambda.png +0 -0
- dirplot-0.3.3/breadcrumbs_test.png +0 -0
- dirplot-0.3.3/demo.cast +0 -418
- dirplot-0.3.3/demo1.cast +0 -414
- dirplot-0.3.3/docs/dirplot.png +0 -0
- dirplot-0.3.3/docs/docker.png +0 -0
- dirplot-0.3.3/docs/fastapi.png +0 -0
- dirplot-0.3.3/docs/flask.png +0 -0
- dirplot-0.3.3/docs/k8s.png +0 -0
- dirplot-0.3.3/docs/pypy.png +0 -0
- dirplot-0.3.3/docs/python.png +0 -0
- dirplot-0.3.3/docs/s3.png +0 -0
- dirplot-0.3.3/foo.svg +0 -158
- dirplot-0.3.3/misc/scan/FILE-SCANNING.md +0 -72
- dirplot-0.3.3/misc/scan/compare.py +0 -58
- dirplot-0.3.3/misc/scan/scan_async.py +0 -93
- dirplot-0.3.3/misc/scan/scan_dir.py +0 -66
- dirplot-0.3.3/misc/scan/scan_rust.py +0 -33
- dirplot-0.3.3/misc/scan/scan_threaded.py +0 -90
- dirplot-0.3.3/misc/scan/scan_walk.py +0 -46
- dirplot-0.3.3/misc/watch/foo.txt +0 -2
- dirplot-0.3.3/misc/watch/watch_dir.py +0 -72
- dirplot-0.3.3/misc/watch/wordcloud1.png +0 -0
- dirplot-0.3.3/misc-watched.png +0 -0
- dirplot-0.3.3/openclaw.png +0 -0
- dirplot-0.3.3/pg.png +0 -0
- dirplot-0.3.3/scripts/animate_demo.py +0 -121
- dirplot-0.3.3/scripts/make_docs_images.sh +0 -16
- dirplot-0.3.3/scripts/make_fixtures.py +0 -340
- dirplot-0.3.3/scripts/open_terminals.sh +0 -71
- dirplot-0.3.3/src/dirplot/main.py +0 -648
- dirplot-0.3.3/src/dirplot/watch.py +0 -168
- dirplot-0.3.3/src-portrait.png +0 -0
- dirplot-0.3.3/src.pdf +0 -0
- dirplot-0.3.3/src.png +0 -0
- dirplot-0.3.3/src.svg +0 -382
- dirplot-0.3.3/test-animation.png +0 -0
- dirplot-0.3.3/tests/animation/README.md +0 -3
- dirplot-0.3.3/tests/animation/changelog.txt +0 -1
- dirplot-0.3.3/tests/animation/config.toml +0 -3
- dirplot-0.3.3/tests/animation/data/records.csv +0 -4
- dirplot-0.3.3/tests/animation/data/schema_v1.json +0 -1
- dirplot-0.3.3/tests/animation/src/lib/parser.py +0 -2
- dirplot-0.3.3/tests/animation/src/main.py +0 -7
- dirplot-0.3.3/tests/test_cli.py +0 -193
- {dirplot-0.3.3 → dirplot-0.4.0}/.dockerignore +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.github/dependabot.yml +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.github/workflows/ci.yml +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.github/workflows/publish.yml +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.gitignore +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.ipynb_checkpoints/Untitled-checkpoint.ipynb +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.pre-commit-config.yaml +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/.python-version +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/CONTRIBUTING.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/Dockerfile +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/LICENSE +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/Makefile +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/SECURITY.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/demo.yaml +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/demo.yaml~ +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/docs/ARCHIVES.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/docs/SSH_DESIGN.md +0 -0
- /dirplot-0.3.3/src/dirplot/py.typed → /dirplot-0.4.0/echo +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/gen_asciicast.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/__main__.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/colors.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/docker.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/fonts/JetBrainsMono-Bold.ttf +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/fonts/JetBrainsMono-BoldItalic.ttf +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/fonts/JetBrainsMono-Italic.ttf +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/fonts/JetBrainsMono-Regular.ttf +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/fonts/OFL.txt +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/k8s.py +0 -0
- /dirplot-0.3.3/tests/__init__.py → /dirplot-0.4.0/src/dirplot/py.typed +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/s3.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/ssh.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/src/dirplot/terminal.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/conftest.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/example/bar/bar.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/example/bar/baz.json +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/example/foo/foo.md +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.7z +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.a +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.aab +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.apk +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.cpio +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.ear +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.epub +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.ipa +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.iso +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.jar +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.nupkg +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.rar +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tar +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tar.bz2 +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tar.gz +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tar.xz +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tar.zst +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tbz2 +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tgz +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.txz +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.tzst +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.vsix +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.war +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.whl +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.xar +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.xpi +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/fixtures/sample.zip +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_archives.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_colors.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_display.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_docker.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_github.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_k8s.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_s3.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_scanner.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_ssh.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_svg_render.py +0 -0
- {dirplot-0.3.3 → dirplot-0.4.0}/tests/test_terminal.py +0 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.4.0] - 2026-03-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **MP4 video output** — all three animation commands (`watch --animate`, `git --animate`,
|
|
15
|
+
`replay`) now write MP4 video when the output path ends in `.mp4` or `.mov`. Quality is
|
|
16
|
+
controlled via `--crf` (Constant Rate Factor: 0 = lossless, 51 = worst, default 23) and
|
|
17
|
+
`--codec` (`libx264` H.264 or `libx265` H.265). MP4 files are typically 10–100× smaller
|
|
18
|
+
than equivalent APNGs. Requires `ffmpeg` on PATH.
|
|
19
|
+
```bash
|
|
20
|
+
dirplot git . -o history.mp4 --animate
|
|
21
|
+
dirplot git . -o history.mp4 --animate --crf 18 --codec libx265
|
|
22
|
+
dirplot replay events.jsonl -o replay.mp4 --total-duration 30
|
|
23
|
+
dirplot watch . -o treemap.mp4 --animate
|
|
24
|
+
```
|
|
25
|
+
- **`@ref` suffix for `dirplot git`**: local repository paths now accept an optional
|
|
26
|
+
`@ref` suffix to target a specific branch, tag, or commit SHA without needing
|
|
27
|
+
`--range` (e.g. `dirplot git .@my-branch -o out.apng --animate`). `--range` takes
|
|
28
|
+
precedence when both are provided.
|
|
29
|
+
- **`dirplot git` subcommand** — replays a git repository's commit history as an
|
|
30
|
+
animated treemap. Each commit becomes one frame; changed tiles receive the same
|
|
31
|
+
colour-coded highlight borders as `watch --animate` (green = created, blue = modified,
|
|
32
|
+
red = deleted). The commit SHA and local timestamp are shown in the root tile header,
|
|
33
|
+
and a progress bar at the top of each frame advances as the animation plays.
|
|
34
|
+
```bash
|
|
35
|
+
# Animate all commits, write APNG
|
|
36
|
+
dirplot git . --output history.apng --animate --exclude .git
|
|
37
|
+
|
|
38
|
+
# Last 50 commits on main, 30-second animation with time-proportional frame durations
|
|
39
|
+
dirplot git . --output history.apng --animate \
|
|
40
|
+
--range main~50..main --total-duration 30
|
|
41
|
+
|
|
42
|
+
# Live-updating static PNG (last frame wins; useful with an auto-refreshing viewer)
|
|
43
|
+
dirplot git /path/to/repo --output treemap.png --max-commits 100
|
|
44
|
+
```
|
|
45
|
+
- **`--range`** (`-r`): git revision range passed directly to `git log`
|
|
46
|
+
(e.g. `main~50..main`, `v1.0..HEAD`). Defaults to the full history of the current branch.
|
|
47
|
+
- **`--max-commits`** (`-n`): cap the number of commits processed.
|
|
48
|
+
- **`--frame-duration`**: fixed frame display time in ms when `--total-duration` is not set
|
|
49
|
+
(default: 1000 ms).
|
|
50
|
+
- **`--total-duration`**: target total animation length in seconds. Frame durations are
|
|
51
|
+
scaled proportionally to the real elapsed time between commits, so quiet periods in
|
|
52
|
+
development history map to longer pauses and burst activity to rapid flips. A 200 ms
|
|
53
|
+
floor prevents very fast commits from being invisible; durations are capped at 65 535 ms
|
|
54
|
+
(APNG uint16 limit). A summary line reports the actual range:
|
|
55
|
+
`Proportional timing: 200–7553 ms/frame (total ~30.1s)`.
|
|
56
|
+
- **`--workers`** (`-w`): number of parallel render workers in animate mode (default: all
|
|
57
|
+
CPU cores). Rendering is memory-bandwidth bound, so 4–8 workers is typically optimal;
|
|
58
|
+
use this flag to tune for your hardware.
|
|
59
|
+
- **Time-proportional progress bar**: a 2 px bar at the top of each frame advances in
|
|
60
|
+
proportion to animation time consumed, not frame count — so a burst of closely-spaced
|
|
61
|
+
commits produces only a small movement while a long quiet period advances it visibly.
|
|
62
|
+
With fixed `--frame-duration` the bar is linear as before.
|
|
63
|
+
|
|
64
|
+
- **Debounced watch** (`--debounce SECONDS`, default `0.5`): the `watch` subcommand now
|
|
65
|
+
collects rapid file-system event bursts and regenerates the treemap once per quiet
|
|
66
|
+
period instead of on every raw event. A `git checkout` touching 100 files triggers
|
|
67
|
+
exactly one render after the activity settles. Pass `--debounce 0` to restore the
|
|
68
|
+
old immediate-fire behaviour.
|
|
69
|
+
```bash
|
|
70
|
+
dirplot watch . --output treemap.png # 500 ms debounce (default)
|
|
71
|
+
dirplot watch . --output treemap.png --debounce 1.0 # 1 s quiet window
|
|
72
|
+
dirplot watch . --output treemap.png --debounce 0 # immediate, as before
|
|
73
|
+
```
|
|
74
|
+
- **Event log** (`--event-log FILE`): on Ctrl-C exit, all raw file-system events
|
|
75
|
+
recorded during the session are written as newline-delimited JSON (JSONL) to the
|
|
76
|
+
given file. Each line has `timestamp`, `type`, `path`, and `dest_path` fields.
|
|
77
|
+
The log is written only if there are events to record.
|
|
78
|
+
```bash
|
|
79
|
+
dirplot watch src --output treemap.png --event-log events.jsonl
|
|
80
|
+
# Ctrl-C, then:
|
|
81
|
+
cat events.jsonl | python3 -m json.tool
|
|
82
|
+
```
|
|
83
|
+
- **File-change highlights** (`--animate`): each APNG frame now draws colour-coded
|
|
84
|
+
borders around tiles that changed since the previous frame — green for created,
|
|
85
|
+
blue for modified, red for deleted, orange for moved. Deleted files are highlighted
|
|
86
|
+
retroactively on the *previous* frame (since the tile no longer exists in the current
|
|
87
|
+
one), so the animation clearly shows both the disappearance and the appearance of files.
|
|
88
|
+
Moved files appear as a deletion at the old path and a creation at the new path.
|
|
89
|
+
- **Graceful finalization**: Ctrl-C now flushes any pending debounced render before
|
|
90
|
+
stopping the observer, so the output file always reflects the final state of the
|
|
91
|
+
watched tree. A second Ctrl-C during APNG writing is ignored so the file can finish
|
|
92
|
+
being written.
|
|
93
|
+
- **Tree comment stripping**: trailing `# comments` in `tree` output are now ignored
|
|
94
|
+
by the path-list parser, so annotated tree listings (e.g. `├── config.json # app config`)
|
|
95
|
+
are parsed correctly. Filenames containing `#` without a leading space are preserved.
|
|
96
|
+
- **`scripts/apng_frames.py`**: utility script to list frame durations, dimensions, and
|
|
97
|
+
offsets in an APNG file.
|
|
98
|
+
- **`scripts/watch_events.py`**: utility script to watch directories and log filesystem
|
|
99
|
+
events to a CSV file (or stdout) in real time using watchdog.
|
|
100
|
+
- **`--depth` for `watch`**: the `watch` subcommand now accepts `--depth N` to limit
|
|
101
|
+
recursion depth, matching the behaviour of `dirplot map`.
|
|
102
|
+
```bash
|
|
103
|
+
dirplot watch . --output treemap.png --depth 3
|
|
104
|
+
```
|
|
105
|
+
- **`dirplot replay` subcommand** — replays a JSONL filesystem event log (as produced
|
|
106
|
+
by `dirplot watch --event-log`) as an animated treemap APNG. Events are grouped into
|
|
107
|
+
time buckets (one frame per bucket, default 60 s), with colour-coded highlight borders
|
|
108
|
+
matching `watch --animate`. Only files referenced in the event log appear in the
|
|
109
|
+
treemap; the common ancestor of all paths is used as the tree root. Frame durations
|
|
110
|
+
can be uniform (`--frame-duration`, default 500 ms) or proportional to the real time
|
|
111
|
+
gaps between buckets (`--total-duration`). Frames are rendered in parallel.
|
|
112
|
+
```bash
|
|
113
|
+
# Replay an event log with 60-second buckets, 30-second total animation
|
|
114
|
+
dirplot replay events.jsonl --output replay.apng --total-duration 30
|
|
115
|
+
|
|
116
|
+
# Smaller buckets for fine-grained activity, fixed frame duration
|
|
117
|
+
dirplot replay events.jsonl --output replay.apng --bucket 10 --frame-duration 200
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- **`dirplot git` accepts GitHub URLs** — pass a `github://owner/repo[@branch]` or
|
|
121
|
+
`https://github.com/owner/repo` URL directly to `dirplot git`. dirplot clones the
|
|
122
|
+
repository into a temporary directory (shallow when `--max-commits` is set, full
|
|
123
|
+
otherwise), runs the full history pipeline locally, and removes the clone on exit.
|
|
124
|
+
No permanent local copy is created.
|
|
125
|
+
```bash
|
|
126
|
+
# Animate the last 50 commits of a GitHub repo — no local clone needed
|
|
127
|
+
dirplot git github://owner/repo --output history.png --animate --max-commits 50
|
|
128
|
+
|
|
129
|
+
# Specific branch
|
|
130
|
+
dirplot git github://owner/repo@main --output history.png --animate --max-commits 50
|
|
131
|
+
```
|
|
132
|
+
- **Total commit count shown** — `dirplot git` now reports the total number of commits
|
|
133
|
+
available alongside the number being animated, so you can gauge how much history
|
|
134
|
+
exists before committing to a longer run:
|
|
135
|
+
```
|
|
136
|
+
Replaying 20 of 147 commit(s) (increase --max-commits to process more) ...
|
|
137
|
+
```
|
|
138
|
+
For GitHub URLs the count is fetched with a single cheap API request (one commit
|
|
139
|
+
object + `Link` header). For local repos `git rev-list --count HEAD` is used.
|
|
140
|
+
- **`--github-token`** (`$GITHUB_TOKEN`): added to `dirplot git` for private GitHub
|
|
141
|
+
repos or to raise the API rate limit when fetching the total commit count.
|
|
142
|
+
|
|
143
|
+
### Changed
|
|
144
|
+
|
|
145
|
+
- **`libarchive-c` is now an optional dependency.** Install it with
|
|
146
|
+
`pip install 'dirplot[libarchive]'` (plus the system library:
|
|
147
|
+
`brew install libarchive` / `apt install libarchive-dev`) to enable
|
|
148
|
+
`.iso`, `.cpio`, `.rpm`, `.cab`, `.lha`, `.xar`, `.pkg`, `.dmg`, `.a`, `.ar`,
|
|
149
|
+
and `.tar.zst` / `.tzst` support. The base install works without it; a clear
|
|
150
|
+
error is shown if you try to open one of these formats without the extra.
|
|
151
|
+
|
|
152
|
+
- **`--animate` writes the APNG once on exit** instead of reading and rewriting the
|
|
153
|
+
entire file on every render. Frames are accumulated as raw PNG bytes in memory and
|
|
154
|
+
flushed as a single multi-frame APNG when the watcher stops (Ctrl-C). This removes
|
|
155
|
+
an O(N²) disk-I/O pattern where frame K required reading a K-frame APNG just to
|
|
156
|
+
append one more frame. Status output during a session now reads `Captured frame N`;
|
|
157
|
+
the final `Wrote N-frame APNG → …` line confirms the file was written on exit.
|
|
158
|
+
|
|
159
|
+
### Fixed
|
|
160
|
+
|
|
161
|
+
- **Initial scan progress**: the `watch` subcommand now prints `Scanning <roots> …`
|
|
162
|
+
before the first render and starts the filesystem observer only after the initial
|
|
163
|
+
treemap has been generated, avoiding spurious events during the first scan.
|
|
164
|
+
- **`--animate` race condition**: the debounce timer thread was marked as daemon,
|
|
165
|
+
causing an in-progress render to be killed when the main thread exited after
|
|
166
|
+
`observer.join()`. The timer is no longer a daemon thread; `flush()` joins any
|
|
167
|
+
in-flight render before stopping.
|
|
168
|
+
- **`--animate` Pillow APNG regression**: passing `pnginfo` alongside `save_all=True`
|
|
169
|
+
caused Pillow to silently write a static PNG instead of an APNG. The `pnginfo`
|
|
170
|
+
argument is now omitted from multi-frame saves (cross-process timing metadata is
|
|
171
|
+
no longer needed since frames are held in memory for the lifetime of the process).
|
|
172
|
+
- **APNG frame duration overflow**: restoring the inter-session frame duration from
|
|
173
|
+
stored metadata could produce a value exceeding 65 535 ms — the maximum expressible
|
|
174
|
+
by APNG's uint16 `delay_num` field when `delay_den = 1000` — causing Pillow to raise
|
|
175
|
+
`cannot write duration`. Durations are now capped at 65 535 ms (≈ 65 s).
|
|
176
|
+
|
|
177
|
+
- **Path-list input from `tree` / `find`** (`--paths-from FILE` or stdin pipe): the `map`
|
|
178
|
+
subcommand now accepts a list of paths produced by `tree` or `find` — either piped via
|
|
179
|
+
stdin or read from a file with `--paths-from`. Format is auto-detected: `tree` output
|
|
180
|
+
(detected by `├──` / `└──` box-drawing characters) or `find` output (one path per line).
|
|
181
|
+
Handles `tree -s` / `tree -h` (size columns), `tree -f` (full embedded paths), and the
|
|
182
|
+
default indented name format. Ancestor/descendant duplicates are collapsed automatically
|
|
183
|
+
so only the minimal set of roots is passed to the scanner.
|
|
184
|
+
```bash
|
|
185
|
+
# Implicit stdin — no flag needed
|
|
186
|
+
tree src/ | dirplot map
|
|
187
|
+
tree -s src/ | dirplot map # with file sizes in tree output
|
|
188
|
+
find . -name "*.py" | dirplot map
|
|
189
|
+
|
|
190
|
+
# Explicit file
|
|
191
|
+
tree src/ > paths.txt && dirplot map --paths-from paths.txt
|
|
192
|
+
|
|
193
|
+
# Explicit stdin
|
|
194
|
+
tree src/ | dirplot map --paths-from -
|
|
195
|
+
```
|
|
196
|
+
Positional path arguments and path-list input are mutually exclusive — combining them
|
|
197
|
+
exits with a clear error. Only local paths are supported (remote backends such as
|
|
198
|
+
`docker://`, `s3://`, `ssh://` remain positional-arg only).
|
|
199
|
+
|
|
200
|
+
- **`dirplot watch` accepts multiple directories**: the `watch` subcommand now takes
|
|
201
|
+
one or more positional path arguments and schedules a filesystem observer for each,
|
|
202
|
+
regenerating the treemap from all roots on every change.
|
|
203
|
+
```bash
|
|
204
|
+
dirplot watch src tests --output treemap.png
|
|
205
|
+
```
|
|
206
|
+
- **`dirplot map` accepts multiple file paths as roots**: previously, multi-root mode
|
|
207
|
+
required every argument to be a directory. Individual files can now be passed as roots;
|
|
208
|
+
each is treated as a leaf node and displayed under the common parent directory.
|
|
209
|
+
```bash
|
|
210
|
+
dirplot map src/main.py src/util.py --no-show
|
|
211
|
+
```
|
|
212
|
+
- **stdout output** (`--output -`): passing `-` as the output path writes the PNG or SVG
|
|
213
|
+
bytes to stdout, enabling piping to other tools. Header and progress lines are
|
|
214
|
+
automatically redirected to stderr to keep the binary stream clean.
|
|
215
|
+
```bash
|
|
216
|
+
dirplot map . --output - --no-show | convert - -resize 50% small.png
|
|
217
|
+
dirplot map . --output - --format svg --no-show > treemap.svg
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## [0.3.3] - 2026-03-14
|
|
221
|
+
|
|
222
|
+
### Added
|
|
223
|
+
|
|
224
|
+
- **Breadcrumbs mode** (`--breadcrumbs/--no-breadcrumbs`, `-b/-B`, on by default): directories
|
|
225
|
+
that form a single-child chain (one subdirectory, no files) are collapsed into a single tile
|
|
226
|
+
whose header shows the full path separated by ` / ` (e.g. `src / dirplot / fonts`). When the
|
|
227
|
+
label is too wide, middle segments are replaced with `…` (`src / … / fonts`). The root tile
|
|
228
|
+
is never collapsed. Disable with `-B` or `--no-breadcrumbs`.
|
|
229
|
+
- **Tree depth in root label**: the root tile header now includes `depth: N` alongside the
|
|
230
|
+
file, directory, and size summary (e.g. `myproject — 124 files, 18 dirs, 4.0 MB (…), depth: 6`).
|
|
231
|
+
The depth reflects the original tree structure and is invariant to whether breadcrumbs mode
|
|
232
|
+
is active.
|
|
233
|
+
|
|
234
|
+
## [0.3.2] - 2026-03-13
|
|
235
|
+
|
|
236
|
+
### Added
|
|
237
|
+
|
|
238
|
+
- **`dirplot watch`** subcommand — watches a directory and regenerates the treemap
|
|
239
|
+
on every file-system change using watchdog (FSEvents on macOS, inotify on Linux,
|
|
240
|
+
kqueue on BSD). Requires `watchdog`, now a core dependency.
|
|
241
|
+
```bash
|
|
242
|
+
dirplot watch . --output treemap.png
|
|
243
|
+
dirplot watch . --output treemap.png --animate # APNG, one frame per change
|
|
244
|
+
```
|
|
245
|
+
- **Vertical file labels**: file tiles that are at least twice as tall as wide now
|
|
246
|
+
display their label rotated 90° CCW, letting the text span the full tile height
|
|
247
|
+
instead of being squeezed into the narrow width.
|
|
248
|
+
- **Scan and render timing** shown in header output:
|
|
249
|
+
`Found 1,414 files … [2.3s]` and `Saved dirplot to out.png [0.4s]`.
|
|
250
|
+
- **Multiple local roots**: `dirplot map src tests` accepts two or more local
|
|
251
|
+
directory paths, finds their common parent, and shows only those subtrees.
|
|
252
|
+
- **`--subtree` / `-s`** option (repeatable) — allowlist complement to `--exclude`:
|
|
253
|
+
keep only the named direct children of the root after scanning. Supports nested
|
|
254
|
+
paths such as `--subtree src/dirplot/fonts`.
|
|
255
|
+
|
|
256
|
+
### Fixed
|
|
257
|
+
|
|
258
|
+
- `--exclude` on pod and Docker backends now prunes entire subtrees — previously only
|
|
259
|
+
the exact path was matched, so all children leaked through.
|
|
260
|
+
- Clearer error for distroless pods: exit code 126 from `kubectl exec` now surfaces as
|
|
261
|
+
an actionable message explaining that the container has no shell or `find` utility.
|
|
262
|
+
- Adaptive file-label font size is now computed with a single `textbbox` measurement
|
|
263
|
+
(one call per tile) instead of stepping down one pixel at a time — eliminates an
|
|
264
|
+
O(font_size × n_tiles) bottleneck that caused near-blocking on large trees such as
|
|
265
|
+
`.venv` directories.
|
|
266
|
+
|
|
267
|
+
### Changed
|
|
268
|
+
|
|
269
|
+
- `-s` short alias reassigned from `--font-size` to `--subtree`. `--font-size` still
|
|
270
|
+
works as before; it just no longer has a single-letter alias.
|
|
271
|
+
|
|
272
|
+
## [0.3.1] - 2026-03-11
|
|
273
|
+
|
|
274
|
+
### Added
|
|
275
|
+
|
|
276
|
+
- `github://` URI now accepts an optional subpath after the repository name, letting
|
|
277
|
+
you scan a subdirectory directly:
|
|
278
|
+
- `github://owner/repo/sub/path` — subpath on the default branch
|
|
279
|
+
- `github://owner/repo@ref/sub/path` — subpath on a specific branch, tag, or commit SHA
|
|
280
|
+
- `https://github.com/owner/repo/tree/branch/sub/path` — full GitHub URL form
|
|
281
|
+
- Tags and commit SHAs are supported wherever a branch ref was previously accepted
|
|
282
|
+
(e.g. `github://torvalds/linux@v6.12`), as the GitHub trees API accepts any git ref.
|
|
283
|
+
- `--legend N` replaces the old boolean `--legend/--no-legend` flag. It now shows a
|
|
284
|
+
**file-count legend** — a sorted list of the top N extensions by number of files,
|
|
285
|
+
with a coloured swatch and the file count for each entry:
|
|
286
|
+
- Pass `--legend` alone to use the default of 20 entries.
|
|
287
|
+
- Pass `--legend 10` for a custom limit.
|
|
288
|
+
- Omit the flag entirely to show no legend.
|
|
289
|
+
- The number of rows is also capped automatically so the box never overflows the
|
|
290
|
+
image, based on available vertical space and the current `--font-size`.
|
|
291
|
+
- Extensions with the same count are sorted alphabetically as a tiebreaker.
|
|
292
|
+
- When the total number of extensions exceeds the limit, a `(+N more)` line is
|
|
293
|
+
appended at the bottom of the box.
|
|
294
|
+
|
|
295
|
+
- The root tile header now includes a summary of the scanned tree after an em-dash
|
|
296
|
+
separator: `myproject — 124 files, 18 dirs, 4.0 MB (4,231,680 bytes)`.
|
|
297
|
+
Applies to both PNG and SVG output. The label is truncated with `…` when the tile
|
|
298
|
+
is too narrow to fit the full string.
|
|
299
|
+
|
|
300
|
+
- Greatly expanded archive format support via the new `libarchive-c` core dependency
|
|
301
|
+
(wraps the system libarchive C library):
|
|
302
|
+
- **New formats**: `.iso`, `.cpio`, `.xar`, `.pkg`, `.dmg`, `.img`, `.rpm`, `.cab`,
|
|
303
|
+
`.lha`, `.lzh`, `.a`, `.ar`, `.tar.zst`, `.tzst`
|
|
304
|
+
- **New ZIP aliases**: `.nupkg` (NuGet), `.vsix` (VS Code extension), `.ipa` (iOS app),
|
|
305
|
+
`.aab` (Android App Bundle)
|
|
306
|
+
- `.tar.zst` / `.tzst` routed through libarchive for consistent behaviour across all
|
|
307
|
+
supported Python versions (stdlib `tarfile` only gained zstd support in 3.12).
|
|
308
|
+
- `libarchive-c>=5.0` added as a core dependency alongside `py7zr` and `rarfile`.
|
|
309
|
+
Requires the system libarchive library:
|
|
310
|
+
`brew install libarchive` / `apt install libarchive-dev`.
|
|
311
|
+
- See [ARCHIVES.md](docs/ARCHIVES.md) for the full format table, platform notes, and
|
|
312
|
+
intentionally unsupported formats (`.deb`, UDIF `.dmg`).
|
|
313
|
+
- Encrypted archive handling:
|
|
314
|
+
- `--password` CLI option passes a passphrase upfront.
|
|
315
|
+
- If an archive turns out to be encrypted and no password was given, dirplot prompts
|
|
316
|
+
interactively (`Password:` hidden-input prompt) and retries — no need to re-run with a flag.
|
|
317
|
+
- A wrong password exits cleanly with `Error: incorrect password.`
|
|
318
|
+
- `PasswordRequired` exception exported from `dirplot.archives` for programmatic use.
|
|
319
|
+
- **Encryption behaviour by format** (since dirplot reads metadata only, never extracts):
|
|
320
|
+
- ZIP and 7z: central directory / file list is unencrypted by default → readable without
|
|
321
|
+
a password even for encrypted archives.
|
|
322
|
+
- RAR with header encryption (`-hp`): listing is hidden without password;
|
|
323
|
+
wrong password raises `PasswordRequired`.
|
|
324
|
+
|
|
325
|
+
### Fixed
|
|
326
|
+
|
|
327
|
+
- `--version` moved back to the top-level `dirplot` command (was accidentally scoped
|
|
328
|
+
to `dirplot map` after the CLI was restructured into subcommands).
|
|
329
|
+
|
|
330
|
+
## [0.3.0] - 2026-03-10
|
|
331
|
+
|
|
332
|
+
### Added
|
|
333
|
+
|
|
334
|
+
- Kubernetes pod scanning via `pod://pod-name/path` syntax — uses `kubectl exec` and
|
|
335
|
+
`find` to build the tree without copying files out of the pod. Works on any running
|
|
336
|
+
pod that has a POSIX shell and `find` (GNU or BusyBox). No extra dependency; only
|
|
337
|
+
`kubectl` is required.
|
|
338
|
+
- Namespace can be specified inline (`pod://pod-name@namespace:/path`) or via
|
|
339
|
+
`--k8s-namespace`.
|
|
340
|
+
- Container can be selected for multi-container pods via `--k8s-container`.
|
|
341
|
+
- `-xdev` is intentionally omitted so mounted volumes (emptyDir, PVC, etc.) within
|
|
342
|
+
the scanned path are traversed — the common case in k8s where images declare
|
|
343
|
+
`VOLUME` entries that are always mounted on a separate filesystem.
|
|
344
|
+
- Automatically falls back to a portable `sh` + `stat` loop on BusyBox/Alpine pods.
|
|
345
|
+
- Docker container scanning via `docker://container:/path` syntax — uses `docker exec`
|
|
346
|
+
and `find` to build the tree without copying files out of the container. Works on any
|
|
347
|
+
running container that has a POSIX shell and `find` (GNU or BusyBox). No extra
|
|
348
|
+
dependency; only the `docker` CLI is required.
|
|
349
|
+
- Automatically detects BusyBox `find` (Alpine-based images) and falls back to a
|
|
350
|
+
portable `sh` + `stat` loop when GNU `-printf` is unavailable.
|
|
351
|
+
- Virtual filesystems (`/proc`, `/sys`, `/dev`) are skipped via `-xdev`.
|
|
352
|
+
- Supports `--exclude`, `--depth`, `--log`, and all other standard options.
|
|
353
|
+
- `Dockerfile` and `.dockerignore` added so the project itself can be used as a
|
|
354
|
+
scan target.
|
|
355
|
+
- SVG output format via `--format svg` or by saving to a `.svg`-suffixed path with `--output`.
|
|
356
|
+
The output is a fully self-contained, interactive SVG file:
|
|
357
|
+
- **CSS hover highlight** — file tiles brighten and gain a soft glow; directory headers
|
|
358
|
+
brighten on mouse-over (`.tile` / `.dir-tile` classes, no JavaScript needed).
|
|
359
|
+
- **Floating tooltip panel** — a JavaScript-driven semi-transparent panel tracks the cursor
|
|
360
|
+
and shows the file or directory name, human-readable size, and file-type / item count.
|
|
361
|
+
No external scripts or stylesheets — the panel logic is embedded in the SVG itself.
|
|
362
|
+
- **Van Wijk cushion shading** — approximated via a single diagonal `linearGradient`
|
|
363
|
+
overlay (`gradientUnits="objectBoundingBox"`), defined once and shared across all tiles.
|
|
364
|
+
Matches the ×1.20 highlight / ×0.80 shadow range of the PNG renderer.
|
|
365
|
+
Disabled with `--no-cushion`.
|
|
366
|
+
- `--format png|svg` CLI option; format is also auto-detected from the `--output` file
|
|
367
|
+
extension.
|
|
368
|
+
- `create_treemap_svg()` added to the public Python API (`from dirplot import create_treemap_svg`).
|
|
369
|
+
- `drawsvg>=2.4` added as a core dependency.
|
|
370
|
+
- Rename the treemap command to `map` (dirplot map <root>).
|
|
371
|
+
- Add `termsize` subcommand and restructure CLI as multi-command app.
|
|
372
|
+
- Add `--depht` parameter to limit the scanning of large file trees.
|
|
373
|
+
- Support for SSH remote directory scanning (`pip install dirplot[ssh]`).
|
|
374
|
+
- Support for AWS S3 buckets in the cloud (`pip install dirplot[s3]`).
|
|
375
|
+
- Support for local archive files, .zip, tgz, .tar.xz, .rar, .7z, etc.
|
|
376
|
+
- Include example archives for 17 different extentions for testing.
|
|
377
|
+
- Comprehensive documentation.
|
|
378
|
+
- `github://owner/repo[@branch]` URI scheme for GitHub repository scanning. The old
|
|
379
|
+
`github:owner/repo` shorthand has been removed.
|
|
380
|
+
- File tiles now have a 1-px dark outline (60/255 below fill colour per channel) so
|
|
381
|
+
adjacent same-coloured tiles — e.g. a directory full of extension-less files — are
|
|
382
|
+
always visually distinct rather than blending into a single flat block.
|
|
383
|
+
|
|
384
|
+
### Changed
|
|
385
|
+
|
|
386
|
+
- `docs/REMOTE-ACCESS.md` renamed to `docs/EXAMPLES.md`; Docker and Kubernetes pod
|
|
387
|
+
sections added; images with captions added for all remote backends.
|
|
388
|
+
|
|
389
|
+
### Fixed
|
|
390
|
+
|
|
391
|
+
- SVG tooltips now show the original byte count when `--log` is active, not the
|
|
392
|
+
log-transformed layout value. `Node.original_size` is populated by `apply_log_sizes`
|
|
393
|
+
for both file and directory nodes and is used by the SVG renderer for `data-size`.
|
|
394
|
+
- GitHub error messages are now clear and actionable.
|
|
395
|
+
|
|
396
|
+
## [0.2.0] - 2026-03-09
|
|
397
|
+
|
|
398
|
+
### Added
|
|
399
|
+
|
|
400
|
+
- Support for Windows, incl. full test suite
|
|
401
|
+
|
|
402
|
+
### Fixed
|
|
403
|
+
|
|
404
|
+
- Improved README, Makefile
|
|
405
|
+
|
|
406
|
+
## [0.1.2] - 2026-03-06
|
|
407
|
+
|
|
408
|
+
### Fixed
|
|
409
|
+
|
|
410
|
+
- Partly incorrect `uvx install dirplot` command
|
|
411
|
+
- Wrong version number in `uv.lock`
|
|
412
|
+
|
|
413
|
+
## [0.1.1] - 2026-03-06
|
|
414
|
+
|
|
415
|
+
### Fixed
|
|
416
|
+
|
|
417
|
+
- Typing complaints
|
|
418
|
+
- Improved README with better install/run commands
|
|
419
|
+
|
|
420
|
+
## [0.1.0] - 2026-03-06
|
|
421
|
+
|
|
422
|
+
### Added
|
|
423
|
+
|
|
424
|
+
- Nested squarified treemap rendered as a PNG at the exact pixel dimensions of the terminal window.
|
|
425
|
+
- Inline terminal display via iTerm2 and Kitty graphics protocols, auto-detected at runtime; supports iTerm2, WezTerm, Warp, Hyper, Kitty, and Ghostty.
|
|
426
|
+
- System-viewer fallback (`open` / `xdg-open`) as the default display mode.
|
|
427
|
+
- File-extension colours from the GitHub Linguist palette (~500 known extensions); unknown extensions fall back to a stable MD5-derived colour from the chosen colormap.
|
|
428
|
+
- Van Wijk quadratic cushion shading giving each tile a raised 3-D look (`--cushion`, on by default).
|
|
429
|
+
- Bundled JetBrains Mono fonts for crisp directory labels at any size.
|
|
430
|
+
- CLI options: `--output`, `--show/--no-show`, `--inline`, `--legend`, `--font-size`, `--colormap`, `--exclude`, `--size`, `--header/--no-header`, `--cushion/--no-cushion`, `--log`.
|
|
431
|
+
- Full test suite (65 tests), strict mypy, ruff linting, pre-commit hooks, and CI on Python 3.10–3.13.
|
dirplot-0.4.0/LICENSE2
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dinu Gherman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|