ecstacy-tui 0.1.1__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.
- ecstacy_tui-0.1.1/.gitignore +8 -0
- ecstacy_tui-0.1.1/.python-version +1 -0
- ecstacy_tui-0.1.1/CHANGELOG.md +36 -0
- ecstacy_tui-0.1.1/LICENSE +21 -0
- ecstacy_tui-0.1.1/PKG-INFO +234 -0
- ecstacy_tui-0.1.1/README.md +182 -0
- ecstacy_tui-0.1.1/assets/home.png +0 -0
- ecstacy_tui-0.1.1/assets/json.png +0 -0
- ecstacy_tui-0.1.1/assets/sparkline.png +0 -0
- ecstacy_tui-0.1.1/assets/splash.png +0 -0
- ecstacy_tui-0.1.1/dashboards/ops.yaml +15 -0
- ecstacy_tui-0.1.1/dashboards/sample.csv +501 -0
- ecstacy_tui-0.1.1/pyproject.toml +97 -0
- ecstacy_tui-0.1.1/src/ecstacy/__init__.py +3 -0
- ecstacy_tui-0.1.1/src/ecstacy/__main__.py +4 -0
- ecstacy_tui-0.1.1/src/ecstacy/app.py +130 -0
- ecstacy_tui-0.1.1/src/ecstacy/cli.py +203 -0
- ecstacy_tui-0.1.1/src/ecstacy/config/__init__.py +11 -0
- ecstacy_tui-0.1.1/src/ecstacy/config/defaults.py +15 -0
- ecstacy_tui-0.1.1/src/ecstacy/config/loader.py +83 -0
- ecstacy_tui-0.1.1/src/ecstacy/config/schema.py +91 -0
- ecstacy_tui-0.1.1/src/ecstacy/core/__init__.py +1 -0
- ecstacy_tui-0.1.1/src/ecstacy/core/dataset.py +90 -0
- ecstacy_tui-0.1.1/src/ecstacy/core/registry.py +36 -0
- ecstacy_tui-0.1.1/src/ecstacy/core/scheduler.py +48 -0
- ecstacy_tui-0.1.1/src/ecstacy/core/store.py +28 -0
- ecstacy_tui-0.1.1/src/ecstacy/core/transforms.py +78 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/__init__.py +7 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/chart.py +67 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/dashboard.py +245 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/help.py +62 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/home.py +187 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/modals.py +49 -0
- ecstacy_tui-0.1.1/src/ecstacy/screens/splash.py +118 -0
- ecstacy_tui-0.1.1/src/ecstacy/sources/__init__.py +4 -0
- ecstacy_tui-0.1.1/src/ecstacy/sources/base.py +63 -0
- ecstacy_tui-0.1.1/src/ecstacy/sources/file.py +124 -0
- ecstacy_tui-0.1.1/src/ecstacy/sources/rest.py +102 -0
- ecstacy_tui-0.1.1/src/ecstacy/sources/socket.py +124 -0
- ecstacy_tui-0.1.1/src/ecstacy/sources/sql.py +35 -0
- ecstacy_tui-0.1.1/src/ecstacy/theming/__init__.py +3 -0
- ecstacy_tui-0.1.1/src/ecstacy/theming/ecstacy.tcss +185 -0
- ecstacy_tui-0.1.1/src/ecstacy/theming/themes.py +44 -0
- ecstacy_tui-0.1.1/src/ecstacy/util/__init__.py +1 -0
- ecstacy_tui-0.1.1/src/ecstacy/util/timeparse.py +16 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/__init__.py +30 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/base.py +79 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/charts.py +216 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/gauge.py +80 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/json_tree.py +44 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/spark.py +29 -0
- ecstacy_tui-0.1.1/src/ecstacy/widgets/table.py +135 -0
- ecstacy_tui-0.1.1/tests/__init__.py +1 -0
- ecstacy_tui-0.1.1/tests/conftest.py +50 -0
- ecstacy_tui-0.1.1/tests/data/duplicate.csv +3 -0
- ecstacy_tui-0.1.1/tests/data/empty.csv +0 -0
- ecstacy_tui-0.1.1/tests/data/sample.csv +5 -0
- ecstacy_tui-0.1.1/tests/data/sample.json +6 -0
- ecstacy_tui-0.1.1/tests/data/sample.ndjson +4 -0
- ecstacy_tui-0.1.1/tests/data/sample.parquet +0 -0
- ecstacy_tui-0.1.1/tests/test_app_dashboard.py +20 -0
- ecstacy_tui-0.1.1/tests/test_charts.py +117 -0
- ecstacy_tui-0.1.1/tests/test_config.py +58 -0
- ecstacy_tui-0.1.1/tests/test_dashboard.py +98 -0
- ecstacy_tui-0.1.1/tests/test_dataset.py +12 -0
- ecstacy_tui-0.1.1/tests/test_file_source.py +65 -0
- ecstacy_tui-0.1.1/tests/test_rest_source.py +115 -0
- ecstacy_tui-0.1.1/tests/test_socket_source.py +106 -0
- ecstacy_tui-0.1.1/tests/test_sql_source.py +19 -0
- ecstacy_tui-0.1.1/tests/test_table_widget.py +59 -0
- ecstacy_tui-0.1.1/tests/test_transforms.py +44 -0
- ecstacy_tui-0.1.1/uv.lock +1999 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
## [0.1.1] - 2026-07-27
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- README images now use absolute GitHub URLs so they render on PyPI.
|
|
12
|
+
|
|
13
|
+
## [0.1.0] - 2026-07-27
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- First public release.
|
|
17
|
+
- Textual TUI for terminal data visualization.
|
|
18
|
+
- Sources: file (CSV, TSV, JSON, NDJSON, Parquet, log), REST, SQL (DuckDB),
|
|
19
|
+
WebSocket.
|
|
20
|
+
- Visualizations: table (sortable and searchable), line, bar, histogram,
|
|
21
|
+
scatter, sparkline, gauge, heatmap, JSON tree.
|
|
22
|
+
- Multi-panel dashboards from YAML with grid and single-panel layouts (`m` to
|
|
23
|
+
toggle) and live refresh.
|
|
24
|
+
- Layered configuration: defaults, user YAML, project YAML, environment
|
|
25
|
+
variables, CLI overrides (validated with Pydantic).
|
|
26
|
+
- Two built-in themes (ecstacy-dark, ecstacy-light) with `t` to toggle.
|
|
27
|
+
- Splash screen, home screen, help screen.
|
|
28
|
+
- `--max-rows` CLI option to cap rows loaded from file and REST sources.
|
|
29
|
+
- Config validation with Pydantic, friendly error messages via `SourceError`,
|
|
30
|
+
`ConfigError`, `TransformError`.
|
|
31
|
+
- Plugin registry for sources and visualizations.
|
|
32
|
+
|
|
33
|
+
### Known limitations
|
|
34
|
+
- No export to file yet (CSV/JSON/Markdown/PNG).
|
|
35
|
+
- No Excel, SQLite, clipboard, or stdin source yet.
|
|
36
|
+
- Live refresh applies to dashboards only (not single-source views).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Abhishek Dobliyal
|
|
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.
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ecstacy-tui
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A Textual TUI for beautiful terminal data visualization from files, REST endpoints and more.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Abhishek-Dobliyal/ecstacy
|
|
6
|
+
Project-URL: Repository, https://github.com/Abhishek-Dobliyal/ecstacy
|
|
7
|
+
Project-URL: Issues, https://github.com/Abhishek-Dobliyal/ecstacy/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Abhishek-Dobliyal/ecstacy/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Abhishek Dobliyal <abhishek.dobliyal1512@gmail.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: charts,csv,data,dataframe,duckdb,sql,terminal,textual,tui,visualization
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Environment :: Console :: Curses
|
|
16
|
+
Classifier: Framework :: AsyncIO
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Intended Audience :: Science/Research
|
|
19
|
+
Classifier: Intended Audience :: System Administrators
|
|
20
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Classifier: Programming Language :: Python :: 3
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
27
|
+
Classifier: Topic :: Terminals
|
|
28
|
+
Classifier: Topic :: Terminals :: Terminal Emulators/X Terminals
|
|
29
|
+
Classifier: Topic :: Utilities
|
|
30
|
+
Requires-Python: >=3.11
|
|
31
|
+
Requires-Dist: duckdb<2,>=1.0.0
|
|
32
|
+
Requires-Dist: httpx<1,>=0.27.0
|
|
33
|
+
Requires-Dist: numpy<3,>=1.26.0
|
|
34
|
+
Requires-Dist: orjson<4,>=3.10.0
|
|
35
|
+
Requires-Dist: pandas<3,>=2.2.0
|
|
36
|
+
Requires-Dist: plotext<6,>=5.2.8
|
|
37
|
+
Requires-Dist: pyarrow<20,>=15.0.0
|
|
38
|
+
Requires-Dist: pydantic<3,>=2.0.0
|
|
39
|
+
Requires-Dist: pyfiglet<2,>=1.0.2
|
|
40
|
+
Requires-Dist: pyyaml<7,>=6.0.2
|
|
41
|
+
Requires-Dist: textual-plotext<2,>=1.0.1
|
|
42
|
+
Requires-Dist: textual<1,>=0.86.2
|
|
43
|
+
Requires-Dist: typer<1,>=0.12.0
|
|
44
|
+
Requires-Dist: websockets<15,>=12.0
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
49
|
+
Requires-Dist: ruff>=0.5.0; extra == 'dev'
|
|
50
|
+
Requires-Dist: textual-dev>=1.5.1; extra == 'dev'
|
|
51
|
+
Description-Content-Type: text/markdown
|
|
52
|
+
|
|
53
|
+
# Ecstacy
|
|
54
|
+
|
|
55
|
+
Beautiful data, right in your terminal.
|
|
56
|
+
|
|
57
|
+
Ecstacy is a Textual TUI for visualizing data from local files, REST endpoints,
|
|
58
|
+
SQL, and WebSockets -- with charts, tables, sparklines, gauges, heatmaps and a
|
|
59
|
+
JSON explorer. Any source feeds any visualization through a typed `DataSet`
|
|
60
|
+
contract, and dashboards compose multiple panels from a single YAML file.
|
|
61
|
+
|
|
62
|
+
<table>
|
|
63
|
+
<tr>
|
|
64
|
+
<td align="center" width="50%"><b>Splash screen</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/splash.png" alt="Splash screen"></td>
|
|
65
|
+
<td align="center" width="50%"><b>Home screen</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/home.png" alt="Home screen"></td>
|
|
66
|
+
</tr>
|
|
67
|
+
<tr>
|
|
68
|
+
<td align="center" width="50%"><b>Sparkline chart</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/sparkline.png" alt="Sparkline chart"></td>
|
|
69
|
+
<td align="center" width="50%"><b>JSON explorer</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/json.png" alt="JSON explorer"></td>
|
|
70
|
+
</tr>
|
|
71
|
+
</table>
|
|
72
|
+
|
|
73
|
+
## Install
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
pip install ecstacy
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then launch it:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
ecstacy
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You can also run it directly with [uv](https://docs.astral.sh/uv/) from a clone
|
|
86
|
+
of this repo:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
uv sync
|
|
90
|
+
uv run ecstacy
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Quick start
|
|
94
|
+
|
|
95
|
+
Open a file directly:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
ecstacy file sample.csv --chart line
|
|
99
|
+
ecstacy file data.csv --chart bar --x region --y value
|
|
100
|
+
ecstacy file metrics.parquet --chart table --max-rows 1000
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Query a REST endpoint:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
ecstacy rest https://api.example.com/items --json-path data.items --chart table
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Run a DuckDB SQL query:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
ecstacy sql "select 1 as a, 2 as b" --chart table
|
|
113
|
+
ecstacy sql "select * from 'data.csv'" --db :memory: --chart line
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Stream from a WebSocket:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
ecstacy socket ws://localhost:8765 --chart table
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Open a multi-panel dashboard:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
ecstacy dashboard ops.yaml
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Inspect available themes, charts, or your config path:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
ecstacy themes
|
|
132
|
+
ecstacy charts
|
|
133
|
+
ecstacy config path
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Sources
|
|
137
|
+
|
|
138
|
+
| Source | Formats / protocol |
|
|
139
|
+
|----------|-------------------------------------------------|
|
|
140
|
+
| file | CSV, TSV, JSON, NDJSON, Parquet, log/text |
|
|
141
|
+
| rest | HTTP/HTTPS JSON endpoints with dotted json-path |
|
|
142
|
+
| sql | DuckDB queries (in-memory or file-backed) |
|
|
143
|
+
| socket | WebSocket streaming JSON records |
|
|
144
|
+
|
|
145
|
+
## Visualizations
|
|
146
|
+
|
|
147
|
+
table (sortable and searchable), line, bar, histogram, scatter, sparkline,
|
|
148
|
+
gauge, heatmap (correlation matrix), json tree.
|
|
149
|
+
|
|
150
|
+
## Keys
|
|
151
|
+
|
|
152
|
+
Home: `o` open, `d` dashboard, `t` theme, `?` help, `q` quit.
|
|
153
|
+
Chart: `n`/`right` next chart, `p`/`left` previous chart, `t` theme, `esc` back.
|
|
154
|
+
Table: `s` sort by column, `/` focus search, type to filter, `esc` clear.
|
|
155
|
+
Dashboard: `m` toggle grid/single layout, `n`/`p` cycle panels, `esc` back.
|
|
156
|
+
|
|
157
|
+
## Configuration
|
|
158
|
+
|
|
159
|
+
Ecstacy layers configuration in this order (later wins):
|
|
160
|
+
|
|
161
|
+
1. Built-in defaults.
|
|
162
|
+
2. User config: `$XDG_CONFIG_HOME/ecstacy/config.yaml` (or `~/.config/ecstacy/config.yaml`).
|
|
163
|
+
3. Project config: `./ecstacy.yaml` in the current directory.
|
|
164
|
+
4. Environment variables prefixed `ECSTACY_` (e.g. `ECSTACY_THEME=ecstacy-light`).
|
|
165
|
+
5. CLI flags.
|
|
166
|
+
|
|
167
|
+
Example `config.yaml`:
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
theme: ecstacy-dark
|
|
171
|
+
refresh: 0s
|
|
172
|
+
splash: true
|
|
173
|
+
max_rows: 1000
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Dashboards
|
|
177
|
+
|
|
178
|
+
A dashboard YAML describes sources and panels. Each panel binds a source to a
|
|
179
|
+
visualization with an optional column mapping. Source paths are resolved
|
|
180
|
+
relative to the dashboard file, so dashboards are portable.
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
theme: ecstacy-dark
|
|
184
|
+
refresh: 5s
|
|
185
|
+
sources:
|
|
186
|
+
- id: metrics
|
|
187
|
+
kind: file
|
|
188
|
+
path: ./sample.csv
|
|
189
|
+
panels:
|
|
190
|
+
- source: metrics
|
|
191
|
+
viz: line
|
|
192
|
+
x: timestamp
|
|
193
|
+
y: [revenue, margin]
|
|
194
|
+
- source: metrics
|
|
195
|
+
viz: bar
|
|
196
|
+
category: region
|
|
197
|
+
value: revenue
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
When `refresh` is set, dashboard panels re-fetch on that interval. Press `m` to
|
|
201
|
+
switch between grid and single-panel layouts.
|
|
202
|
+
|
|
203
|
+
## Architecture
|
|
204
|
+
|
|
205
|
+
- `core` -- `DataSet` contract, plugin registry, transforms, store, scheduler.
|
|
206
|
+
- `sources` -- file, rest, sql, socket -- all registered plugins.
|
|
207
|
+
- `widgets` -- visualization widgets, registered plugins.
|
|
208
|
+
- `screens` -- splash, home, chart, dashboard, modal, help.
|
|
209
|
+
- `config` -- defaults, Pydantic schema, layered config loader.
|
|
210
|
+
- `theming` -- Textual themes and the global stylesheet.
|
|
211
|
+
|
|
212
|
+
Sources resolve to a typed `DataSet` (DataFrame + schema + meta). Widgets bind
|
|
213
|
+
to a `DataSet` and a column mapping, so any source can feed any visualization.
|
|
214
|
+
|
|
215
|
+
## Extending
|
|
216
|
+
|
|
217
|
+
Add a source by subclassing `Source` and decorating it with
|
|
218
|
+
`@registry.sources.register("name")`. Add a visualization by creating a widget
|
|
219
|
+
with a `set_data(dataset, mapping)` method and decorating it with
|
|
220
|
+
`@registry.viz.register("name")`.
|
|
221
|
+
|
|
222
|
+
## Known limitations
|
|
223
|
+
|
|
224
|
+
- No export to file yet (CSV/JSON/Markdown/PNG).
|
|
225
|
+
- No Excel, SQLite, clipboard, or stdin source yet.
|
|
226
|
+
- Live refresh applies to dashboards only (not single-source views).
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
MIT. See [LICENSE](LICENSE).
|
|
231
|
+
|
|
232
|
+
## Changelog
|
|
233
|
+
|
|
234
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Ecstacy
|
|
2
|
+
|
|
3
|
+
Beautiful data, right in your terminal.
|
|
4
|
+
|
|
5
|
+
Ecstacy is a Textual TUI for visualizing data from local files, REST endpoints,
|
|
6
|
+
SQL, and WebSockets -- with charts, tables, sparklines, gauges, heatmaps and a
|
|
7
|
+
JSON explorer. Any source feeds any visualization through a typed `DataSet`
|
|
8
|
+
contract, and dashboards compose multiple panels from a single YAML file.
|
|
9
|
+
|
|
10
|
+
<table>
|
|
11
|
+
<tr>
|
|
12
|
+
<td align="center" width="50%"><b>Splash screen</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/splash.png" alt="Splash screen"></td>
|
|
13
|
+
<td align="center" width="50%"><b>Home screen</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/home.png" alt="Home screen"></td>
|
|
14
|
+
</tr>
|
|
15
|
+
<tr>
|
|
16
|
+
<td align="center" width="50%"><b>Sparkline chart</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/sparkline.png" alt="Sparkline chart"></td>
|
|
17
|
+
<td align="center" width="50%"><b>JSON explorer</b><br><br><img src="https://raw.githubusercontent.com/Abhishek-Dobliyal/ecstacy/main/assets/json.png" alt="JSON explorer"></td>
|
|
18
|
+
</tr>
|
|
19
|
+
</table>
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
pip install ecstacy
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then launch it:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
ecstacy
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You can also run it directly with [uv](https://docs.astral.sh/uv/) from a clone
|
|
34
|
+
of this repo:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
uv sync
|
|
38
|
+
uv run ecstacy
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
Open a file directly:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
ecstacy file sample.csv --chart line
|
|
47
|
+
ecstacy file data.csv --chart bar --x region --y value
|
|
48
|
+
ecstacy file metrics.parquet --chart table --max-rows 1000
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Query a REST endpoint:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
ecstacy rest https://api.example.com/items --json-path data.items --chart table
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Run a DuckDB SQL query:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
ecstacy sql "select 1 as a, 2 as b" --chart table
|
|
61
|
+
ecstacy sql "select * from 'data.csv'" --db :memory: --chart line
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Stream from a WebSocket:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
ecstacy socket ws://localhost:8765 --chart table
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Open a multi-panel dashboard:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
ecstacy dashboard ops.yaml
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Inspect available themes, charts, or your config path:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
ecstacy themes
|
|
80
|
+
ecstacy charts
|
|
81
|
+
ecstacy config path
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Sources
|
|
85
|
+
|
|
86
|
+
| Source | Formats / protocol |
|
|
87
|
+
|----------|-------------------------------------------------|
|
|
88
|
+
| file | CSV, TSV, JSON, NDJSON, Parquet, log/text |
|
|
89
|
+
| rest | HTTP/HTTPS JSON endpoints with dotted json-path |
|
|
90
|
+
| sql | DuckDB queries (in-memory or file-backed) |
|
|
91
|
+
| socket | WebSocket streaming JSON records |
|
|
92
|
+
|
|
93
|
+
## Visualizations
|
|
94
|
+
|
|
95
|
+
table (sortable and searchable), line, bar, histogram, scatter, sparkline,
|
|
96
|
+
gauge, heatmap (correlation matrix), json tree.
|
|
97
|
+
|
|
98
|
+
## Keys
|
|
99
|
+
|
|
100
|
+
Home: `o` open, `d` dashboard, `t` theme, `?` help, `q` quit.
|
|
101
|
+
Chart: `n`/`right` next chart, `p`/`left` previous chart, `t` theme, `esc` back.
|
|
102
|
+
Table: `s` sort by column, `/` focus search, type to filter, `esc` clear.
|
|
103
|
+
Dashboard: `m` toggle grid/single layout, `n`/`p` cycle panels, `esc` back.
|
|
104
|
+
|
|
105
|
+
## Configuration
|
|
106
|
+
|
|
107
|
+
Ecstacy layers configuration in this order (later wins):
|
|
108
|
+
|
|
109
|
+
1. Built-in defaults.
|
|
110
|
+
2. User config: `$XDG_CONFIG_HOME/ecstacy/config.yaml` (or `~/.config/ecstacy/config.yaml`).
|
|
111
|
+
3. Project config: `./ecstacy.yaml` in the current directory.
|
|
112
|
+
4. Environment variables prefixed `ECSTACY_` (e.g. `ECSTACY_THEME=ecstacy-light`).
|
|
113
|
+
5. CLI flags.
|
|
114
|
+
|
|
115
|
+
Example `config.yaml`:
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
theme: ecstacy-dark
|
|
119
|
+
refresh: 0s
|
|
120
|
+
splash: true
|
|
121
|
+
max_rows: 1000
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Dashboards
|
|
125
|
+
|
|
126
|
+
A dashboard YAML describes sources and panels. Each panel binds a source to a
|
|
127
|
+
visualization with an optional column mapping. Source paths are resolved
|
|
128
|
+
relative to the dashboard file, so dashboards are portable.
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
theme: ecstacy-dark
|
|
132
|
+
refresh: 5s
|
|
133
|
+
sources:
|
|
134
|
+
- id: metrics
|
|
135
|
+
kind: file
|
|
136
|
+
path: ./sample.csv
|
|
137
|
+
panels:
|
|
138
|
+
- source: metrics
|
|
139
|
+
viz: line
|
|
140
|
+
x: timestamp
|
|
141
|
+
y: [revenue, margin]
|
|
142
|
+
- source: metrics
|
|
143
|
+
viz: bar
|
|
144
|
+
category: region
|
|
145
|
+
value: revenue
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
When `refresh` is set, dashboard panels re-fetch on that interval. Press `m` to
|
|
149
|
+
switch between grid and single-panel layouts.
|
|
150
|
+
|
|
151
|
+
## Architecture
|
|
152
|
+
|
|
153
|
+
- `core` -- `DataSet` contract, plugin registry, transforms, store, scheduler.
|
|
154
|
+
- `sources` -- file, rest, sql, socket -- all registered plugins.
|
|
155
|
+
- `widgets` -- visualization widgets, registered plugins.
|
|
156
|
+
- `screens` -- splash, home, chart, dashboard, modal, help.
|
|
157
|
+
- `config` -- defaults, Pydantic schema, layered config loader.
|
|
158
|
+
- `theming` -- Textual themes and the global stylesheet.
|
|
159
|
+
|
|
160
|
+
Sources resolve to a typed `DataSet` (DataFrame + schema + meta). Widgets bind
|
|
161
|
+
to a `DataSet` and a column mapping, so any source can feed any visualization.
|
|
162
|
+
|
|
163
|
+
## Extending
|
|
164
|
+
|
|
165
|
+
Add a source by subclassing `Source` and decorating it with
|
|
166
|
+
`@registry.sources.register("name")`. Add a visualization by creating a widget
|
|
167
|
+
with a `set_data(dataset, mapping)` method and decorating it with
|
|
168
|
+
`@registry.viz.register("name")`.
|
|
169
|
+
|
|
170
|
+
## Known limitations
|
|
171
|
+
|
|
172
|
+
- No export to file yet (CSV/JSON/Markdown/PNG).
|
|
173
|
+
- No Excel, SQLite, clipboard, or stdin source yet.
|
|
174
|
+
- Live refresh applies to dashboards only (not single-source views).
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT. See [LICENSE](LICENSE).
|
|
179
|
+
|
|
180
|
+
## Changelog
|
|
181
|
+
|
|
182
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
theme: ecstacy-dark
|
|
2
|
+
refresh: 5s
|
|
3
|
+
sources:
|
|
4
|
+
- id: metrics
|
|
5
|
+
kind: file
|
|
6
|
+
path: ./dashboards/sample.csv
|
|
7
|
+
panels:
|
|
8
|
+
- source: metrics
|
|
9
|
+
viz: line
|
|
10
|
+
x: timestamp
|
|
11
|
+
y: [revenue, margin]
|
|
12
|
+
- source: metrics
|
|
13
|
+
viz: bar
|
|
14
|
+
category: region
|
|
15
|
+
value: revenue
|