Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license = "MIT"
readme = "README.md"
keywords = ["terminal", "tui", "theme", "ansi", "color-scheme"]
categories = ["command-line-utilities"]
exclude = [".github/", "samples/", "scripts/", "demo.tape", "demo.gif"]
exclude = [".github/", "scripts/", "demo.tape", "demo.gif"]

[dependencies]
ratatui = "0.29"
Expand Down
39 changes: 27 additions & 12 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
# TODO

## Done
- [x] Language panels (python, node, rust, go, c++, zig, java, c#, ruby, lua)
- [x] Fullscreen mode for individual panels
- [x] Responsive grid columns based on terminal width
- [x] Tool detection and prompt scaffolding
- [x] System and devtools panels (docker, file listing, logs, ripgrep, etc.)
- [x] CLI args (`--panel`, `--offline`, `--list`, `--no-color`)
- [x] GitHub Actions CI (clippy, fmt, test, conventions via cocogitto)
- [x] Sample capture script for real tool output (`scripts/generate-samples`)
- [x] Fixed-width fullscreen status bar (no shifting on panel cycle)
- [x] lefthook + cocogitto + Taskfile dev tooling
- [x] Publish to crates.io
- [x] Homebrew tap serving prebuilt binaries
- [x] GitHub Releases with prebuilt binaries (macOS + Linux, arm64/x86_64)
- [x] Synchronized-output rendering (no resize flicker)
- [x] NO_COLOR support (`--no-color` and the `NO_COLOR` env var)
- [x] Wire captured samples into real panels (8 languages; animated captures
flattened through tmux so pytest/vitest/etc. render as final frames)

## Short Term
- [ ] Word wrap content in fullscreen mode
- [ ] Word wrap in fullscreen (per-panel: wrap prose panels, truncate tables/art)
- [ ] Reproducible sample flattening: run the tmux flatten inside generate-samples
- [ ] Wire C# and Go captures (C# dotnet output is very long; Go has no color)
- [ ] Sanitize capture paths (temp dirs, usernames) or decide to keep them real
- [ ] Decide whether real panels replace the hand-built ones
- [ ] Detect and use real CLI tools (eza, bat, jq) when available
- [ ] Add clap for CLI argument parsing
- [ ] Add `--offline` flag to skip tool detection
- [ ] Add `--panel <name>` to jump to a specific panel

## Medium Term
- [ ] Cycle between detected tool variants in fullscreen (e.g., eza vs ls)
- [ ] Capture real tool output at wide terminal width for fullscreen
- [ ] Live embedded tool panes via PTY (tui-term) with a static fallback
- [ ] User-scriptable panes: run a command per pane, custom panels via config
- [ ] Cycle between detected tool variants in fullscreen (e.g. eza vs ls)
- [ ] Detect package managers via env vars and cache presence
- [ ] Persist user preferences in ~/.config/diorama.toml

## Distribution
- [ ] Publish to crates.io
- [ ] GitHub Releases with prebuilt binaries (macOS arm64/x86_64, Linux)
- [ ] Homebrew tap

## Ideas
- [ ] User-defined panel templates with ANSI escape codes
- [ ] More language panels
42 changes: 42 additions & 0 deletions samples/cpp-cmake-error.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
-- The CXX compiler identification is AppleClang 17.0.0.17000603
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.3s)
-- Generating done (0.0s)
-- Build files have been written to: /var/folders/t6/w423hg0j67xgrmncvf9n0d180000gn/T/diorama-capture.XXXXXX.7rD0W0gYQe/cpp/build
[ 50%] Building CXX object CMakeFiles/app.dir/src/main.cpp.o
/var/folders/t6/w423hg0j67xgrmncvf9n0d180000gn/T/diorama-capture.XXXXXX.7rD0W0gYQe/cpp/src/main.cpp:6:17: error: 
no viable conversion from 'int' to 'std::string' (aka 'basic_string<char>')
6 | std::string msg = 42; // type error
|  ^ ~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/string:1032:71: note: 
candidate constructor not viable: no known conversion from 'int' to 'const string &' for 1st argument
1032 | _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str)
|  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/string:1052:55: note: 
candidate constructor not viable: no known conversion from 'int' to 'string &&' for 1st argument
1052 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str)
|  ^ ~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/string:1092:55: note: 
candidate constructor template not viable: no known conversion from 'int' to 'const char *' for 1st argument
1092 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s) {
|  ^ ~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/string:1226:55: note: 
candidate constructor not viable: no known conversion from 'int' to 'initializer_list<char>' for 1st argument
1226 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il) {
|  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/string:1017:64: note: 
explicit constructor is not a candidate
1017 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a)
|  ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/string:1184:42: note: 
explicit constructor is not a candidate
1184 | _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) {
|  ^
1 error generated.
make[2]: *** [CMakeFiles/app.dir/src/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/app.dir/all] Error 2
make: *** [all] Error 2
218 changes: 218 additions & 0 deletions samples/csharp-dotnet.ansi

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions samples/go-test.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
=== RUN TestAddNegative
--- PASS: TestAddNegative (0.00s)
=== RUN TestDivide
--- PASS: TestDivide (0.00s)
=== RUN TestDivideByZero
--- PASS: TestDivideByZero (0.00s)
=== RUN TestFail
main_test.go:36: expected 5 but got 4
--- FAIL: TestFail (0.00s)
FAIL
FAIL github.com/example/sample-app 0.177s
FAIL
33 changes: 33 additions & 0 deletions samples/java-gradle.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
To honour the JVM settings for this build a single-use Daemon process will be forked. For more on this, please refer to
https://docs.gradle.org/9.3.1/userguide/gradle_daemon.html#sec:disabling_the_daemon in the Gradle documentation.
Daemon will be stopped at the end of the build
> Task :test FAILED

[Incubating] Problems report is available at: file:///private/var/folders/t6/w423hg0j67xgrmncvf9n0d180000gn/T/diorama-ca
pture.XXXXXX.7rD0W0gYQe/java/build/reports/problems/problems-report.html

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> Test process encountered an unexpected problem.
> Could not start Gradle Test Executor 1: Failed to load JUnit Platform. Please ensure that all JUnit Platform depen
dencies are available on the test's runtime classpath, including the JUnit Platform launcher.

* Try:
> Check common problems https://docs.gradle.org/9.3.1/userguide/java_testing.html#sec:java_testing_troubleshooting.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights from a Build Scan (powered by Develocity).
> Get more help at https://help.gradle.org.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own sc
ripts or plugins.

For more on this, please refer to https://docs.gradle.org/9.3.1/userguide/command_line_interface.html#sec:command_line_w
arnings in the Gradle documentation.

BUILD FAILED in 2s
3 actionable tasks: 3 executed
10 changes: 10 additions & 0 deletions samples/lua-busted.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
●●●●●◼
5 successes / 1 failure / 0 errors / 0 pending : 0.001749 seconds

Failure → spec/calculator_spec.lua @ 26
calculator fibonacci fails intentionally
spec/calculator_spec.lua:27: Expected objects to be equal.
Passed in:
(number) 4
Expected:
(number) 5
4 changes: 4 additions & 0 deletions samples/lua-error.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
lua: ...180000gn/T/diorama-capture.XXXXXX.7rD0W0gYQe/lua/bad.lua:2: attempt to index a nil value (local 'x')
stack traceback:
...180000gn/T/diorama-capture.XXXXXX.7rD0W0gYQe/lua/bad.lua:2: in main chunk
[C]: in ?
40 changes: 40 additions & 0 deletions samples/node-vitest.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

 RUN  v4.0.18 /private/var/folders/t6/w423hg0j67xgrmncvf9n0d180000gn/T/diorama-capture.XXXXXX.7rD0W0gYQe/node

❯ src/math.test.ts (6 tests | 1 failed) 5ms
✓ add (2)
✓ adds two positive numbers 1ms
✓ adds negative numbers 0ms
✓ divide (2)
✓ divides two numbers 0ms
 ✓ throws on zero 0ms
❯ fibonacci (2)
✓ computes fib(10) 0ms
 × intentional failure 3ms

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/math.test.ts > fibonacci > intentional failure
AssertionError: expected 4 to be 5 // Object.is equality

- Expected
+ Received

- 5
+ 4

 ❯ src/math.test.ts:27:23
 25|  });
 26|  it('intentional failure', () => {
 27|  expect(add(2, 2)).toBe(5);
 |  ^
 28|  });
 29| });

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯


 Test Files  1 failed (1)
 Tests  1 failed | 5 passed (6)
 Start at  10:25:41
 Duration  359ms (transform 272ms, setup 0ms, import 279ms, tests 5ms, environment 0ms)
34 changes: 34 additions & 0 deletions samples/python-pytest.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
================================================= test session starts ==================================================
platform darwin -- Python 3.14.3, pytest-9.0.2, pluggy-1.6.0 -- /Users/tsilenzio/.local/share/mise/installs/python/3.14.
3/bin/python3
cachedir: .pytest_cache
rootdir: /private/var/folders/t6/w423hg0j67xgrmncvf9n0d180000gn/T/diorama-capture.XXXXXX.7rD0W0gYQe/python
plugins: cov-7.0.0
collected 7 items 

tests/test_auth.py::TestLogin::test_valid_credentials PASSED [ 14%]
tests/test_auth.py::TestLogin::test_invalid_password PASSED [ 28%]
tests/test_auth.py::TestLogin::test_unknown_user PASSED [ 42%]
tests/test_auth.py::TestVerify::test_valid_token PASSED [ 57%]
tests/test_auth.py::TestVerify::test_invalid_token PASSED [ 71%]
tests/test_auth.py::TestSerialization::test_to_dict FAILED [ 85%]
tests/test_auth.py::TestSerialization::test_user_count PASSED [100%]

======================================================= FAILURES =======================================================
____________________________________________ TestSerialization.test_to_dict ____________________________________________
tests/test_auth.py:36: in test_to_dict
assert svc.to_dict() == {"users": ["alice", "charlie"]}
E AssertionError: assert {'users': ['alice', 'bob']} == {'users': ['a...', 'charlie']}
E 
E Differing items:
E {'users': ['alice', 'bob']} != {'users': ['alice', 'charlie']}
E 
E Full diff:
E   {
E   'users': [...
E 
E ...Full output truncated (5 lines hidden), use '-vv' to show
=============================================== short test summary info ================================================
FAILED tests/test_auth.py::TestSerialization::test_to_dict - AssertionError: assert {'users': ['alice', 'bob']} == {'use
rs': ['a...', 'charlie']}
============================================= 1 failed, 6 passed in 0.03s ==============================================
30 changes: 30 additions & 0 deletions samples/ruby-rspec.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

Calculator
#add
 adds two numbers
 handles negatives
#divide
 divides two numbers
 raises on zero
#fibonacci
 computes fib(10)
 fails intentionally (FAILED - 1)

Failures:

1) Calculator#fibonacci fails intentionally
Failure/Error: expect(calc.add(2, 2)).to eq(5)

 expected: 5
 got: 4

 (compared using ==)
# ./spec/calculator_spec.rb:32:in 'block (3 levels) in <top (required)>'

Finished in 0.00344 seconds (files took 0.04494 seconds to load)
6 examples, 1 failure

Failed examples:

rspec ./spec/calculator_spec.rb:31 # Calculator#fibonacci fails intentionally

31 changes: 31 additions & 0 deletions samples/rust-cargo-test.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
 Compiling sample-app v0.1.0 (/private/var/folders/t6/w423hg0j67xgrmncvf9n0d180000gn/T/diorama-capture.XXXXXX.7rD0W0gY
Qe/rust)
 Finished ]8;;https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles\`test` profile [unoptimized + debuginfo]]8;;\ target(s) in 0.15s
 Running unittests src/lib.rs (target/debug/deps/sample_app-853793f4e1db0eb3)

running 7 tests
test tests::test_add ... ok
test tests::test_divide ... ok
test tests::test_add_negative ... ok
test tests::test_divide_by_zero ... ok
test tests::test_fibonacci ... ok
test tests::test_fibonacci_zero ... ok
test tests::test_serialization_fail ... FAILED

failures:

---- tests::test_serialization_fail stdout ----

thread 'tests::test_serialization_fail' (147861) panicked at src/lib.rs:56:9:
assertion `left == right` failed
left: 4
right: 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
tests::test_serialization_fail

test result: FAILED. 6 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--lib`
4 changes: 4 additions & 0 deletions samples/zig-error.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src/bad.zig:5:19: error: use of undeclared identifier 'undefined_var'
 const y = x + undefined_var;
^~~~~~~~~~~~~

18 changes: 18 additions & 0 deletions samples/zig-test.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[3] Compile Build Script
[3] Compile Build Script
[3] Compile Build Script
[3] Compile Build Script
[3] Compile Build Script
[3] Compile Build Script
[3] Compile Build Script
[5] Compile Build Script
build.zig:6:10: error: no field named 'root_source_file' in struct 'Build.ExecutableOptions'
.root_source_file = b.path("src/main.zig"),
^~~~~~~~~~~~~~~~
/Users/tsilenzio/.local/share/mise/installs/zig/0.15.2/lib/std/Build.zig:771:31: note: struct declared here
pub const ExecutableOptions = struct {
^~~~~~
referenced by:
 runBuild__anon_21152: /Users/tsilenzio/.local/share/mise/installs/zig/0.15.2/lib/std/Build.zig:2214:33
 main: /Users/tsilenzio/.local/share/mise/installs/zig/0.15.2/lib/compiler/build_runner.zig:366:29
 4 reference(s) hidden; use '-freference-trace=6' to see all references
Loading