dataframe-textual 1.3.9__tar.gz → 1.16.2__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.
Files changed (19) hide show
  1. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/PKG-INFO +331 -282
  2. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/README.md +330 -281
  3. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/pyproject.toml +1 -1
  4. dataframe_textual-1.16.2/src/dataframe_textual/__main__.py +96 -0
  5. dataframe_textual-1.16.2/src/dataframe_textual/common.py +769 -0
  6. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/src/dataframe_textual/data_frame_table.py +1980 -1177
  7. dataframe_textual-1.16.2/src/dataframe_textual/data_frame_viewer.py +598 -0
  8. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/src/dataframe_textual/sql_screen.py +50 -20
  9. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/src/dataframe_textual/table_screen.py +169 -108
  10. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/src/dataframe_textual/yes_no_screen.py +115 -30
  11. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/uv.lock +1 -1
  12. dataframe_textual-1.3.9/src/dataframe_textual/__main__.py +0 -68
  13. dataframe_textual-1.3.9/src/dataframe_textual/common.py +0 -482
  14. dataframe_textual-1.3.9/src/dataframe_textual/data_frame_viewer.py +0 -366
  15. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/.gitignore +0 -0
  16. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/LICENSE +0 -0
  17. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/main.py +0 -0
  18. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/src/dataframe_textual/__init__.py +0 -0
  19. {dataframe_textual-1.3.9 → dataframe_textual-1.16.2}/src/dataframe_textual/data_frame_help_panel.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataframe-textual
3
- Version: 1.3.9
3
+ Version: 1.16.2
4
4
  Summary: Interactive terminal viewer/editor for tabular data
5
5
  Project-URL: Homepage, https://github.com/need47/dataframe-textual
6
6
  Project-URL: Repository, https://github.com/need47/dataframe-textual.git
@@ -48,7 +48,7 @@ A powerful, interactive terminal-based viewer/editor for CSV/TSV/Excel/Parquet/J
48
48
  ### Data Viewing
49
49
  - 🚀 **Fast Loading** - Powered by Polars for efficient data handling
50
50
  - 🎨 **Rich Terminal UI** - Beautiful, color-coded columns with various data types (e.g., integer, float, string)
51
- - ⌨️ **Comprehensive Keyboard Navigation** - Intuitive controls for browsing, editing, and manipulating data
51
+ - ⌨️ **Comprehensive Keyboard Navigation** - Intuitive controls
52
52
  - 📊 **Flexible Input** - Read from files and/or stdin (pipes/redirects)
53
53
  - 🔄 **Smart Pagination** - Lazy load rows on demand for handling large datasets
54
54
 
@@ -62,8 +62,10 @@ A powerful, interactive terminal-based viewer/editor for CSV/TSV/Excel/Parquet/J
62
62
  ### Advanced Features
63
63
  - 📂 **Multi-File Support** - Open multiple files in separate tabs
64
64
  - 🔄 **Tab Management** - Seamlessly switch between open files with keyboard shortcuts
65
+ - 📑 **Duplicate Tab** - Create a copy of the current tab with the same data
65
66
  - 📌 **Freeze Rows/Columns** - Keep important rows and columns visible while scrolling
66
67
  - 🎯 **Cursor Type Cycling** - Switch between cell, row, and column selection modes
68
+ - 📸 **Take Screenshot** - Capture terminal view as a SVG image
67
69
 
68
70
  ## Installation
69
71
 
@@ -81,7 +83,7 @@ This installs an executable `dv`.
81
83
 
82
84
  Then run:
83
85
  ```bash
84
- dv <csv_file>
86
+ dv <file>
85
87
  ```
86
88
 
87
89
  ### Using [uv](https://docs.astral.sh/uv/)
@@ -95,7 +97,7 @@ cd dataframe-textual
95
97
  uv sync --extra excel # with Excel support
96
98
 
97
99
  # Run directly with uv
98
- uv run dv <csv_file>
100
+ uv run dv <file>
99
101
  ```
100
102
 
101
103
  ### Development installation
@@ -108,7 +110,10 @@ cd dataframe-textual
108
110
  # Install from local source
109
111
  pip install -e .
110
112
 
111
- # Or with development dependencies
113
+ # With Excel support
114
+ pip install -e ".[excel]"
115
+
116
+ # With development dependencies
112
117
  pip install -e ".[excel,dev]"
113
118
  ```
114
119
 
@@ -120,15 +125,21 @@ pip install -e ".[excel,dev]"
120
125
  # After pip install dataframe-textual
121
126
  dv pokemon.csv
122
127
 
123
- # Or if running from source
124
- python main.py pokemon.csv
128
+ # Or run from module
129
+ python -m dataframe-textual pokemon.csv
125
130
 
126
131
  # Or with uv
127
132
  uv run python main.py pokemon.csv
128
133
 
129
- # Read from stdin (auto-detects format; defaults to TSV if not recognized)
134
+ # Read from stdin (defaults to TSV)
130
135
  cat data.tsv | dv
131
136
  dv < data.tsv
137
+
138
+ # Specify format for gzipped stdin
139
+ zcat data.csv.gz | dv -f csv
140
+
141
+ # Gzipped files are supported
142
+ dv data.csv.gz
132
143
  ```
133
144
 
134
145
  ### Multi-File Usage - Multiple Tabs
@@ -140,16 +151,85 @@ dv file1.csv file2.csv file3.csv
140
151
  # Open multiple sheets in tabs in an Excel file
141
152
  dv file.xlsx
142
153
 
143
- # Mix files and stdin (read from stdin, then open file)
154
+ # Mix files and stdin
144
155
  dv data1.tsv < data2.tsv
145
156
  ```
146
157
 
147
158
  When multiple files are opened:
148
- - Each file appears as a separate tab at the top
149
- - Switch between tabs using `>` (next) or `<` (previous)
159
+ - Each file appears as a separate tab. An Excel file may contain multiple tabs.
160
+ - Switch between tabs using `>` (next) or `<` (previous), or use `b` for cycling through tabs
161
+ - Save current tab to file with `Ctrl+T`
162
+ - Save all tabs to file with `Ctrl+A`
163
+ - Duplicate the current tab with `Ctrl+D`
150
164
  - Open additional files with `Ctrl+O`
151
- - Close the current tab with `Ctrl+W`
152
- - Each file maintains its own state (edits, sort order, selections, history, etc.)
165
+ - Each file maintains its own state (edits, sort order, selections, history, etc.) and allow undo/redo.
166
+
167
+ ## Command Line Options
168
+
169
+ ```
170
+ usage: dv [-h] [-f {csv,excel,tsv,parquet,json,ndjson}] [-H] [-I] [-E] [-c COMMENT_PREFIX] [-q QUOTE_CHAR] [-l SKIP_LINES] [-a SKIP_ROWS_AFTER_HEADER] [-n NULL [NULL ...]] [files ...]
171
+
172
+ Interactive terminal based viewer/editor for tabular data (e.g., CSV/TSV/Excel).
173
+
174
+ positional arguments:
175
+ files Input files (or read from stdin)
176
+
177
+ options:
178
+ -h, --help show this help message and exit
179
+ -f, --format {csv,excel,tsv,parquet,json,ndjson}
180
+ Specify the format of the input files
181
+ -H, --no-header Specify that input files have no header row
182
+ -I, --no-inference Do not infer data types when reading CSV/TSV
183
+ -E, --ignore-errors Ignore errors when reading CSV/TSV
184
+ -c, --comment-prefix COMMENT_PREFIX
185
+ Comment lines are skipped when reading CSV/TSV (default: skip none)
186
+ -q, --quote-char QUOTE_CHAR
187
+ Quote character for reading CSV/TSV (default: "; use -q without argument value to disable)
188
+ -l, --skip-lines SKIP_LINES
189
+ Skip lines when reading CSV/TSV (default: 0)
190
+ -a, --skip-rows-after-header SKIP_ROWS_AFTER_HEADER
191
+ Skip rows after header when reading CSV/TSV (default: 0)
192
+ -n, --null NULL [NULL ...]
193
+ Values to interpret as null values when reading CSV/TSV
194
+ ```
195
+
196
+ ### CLI Examples
197
+
198
+ ```bash
199
+ # View headless CSV file
200
+ dv -H data_no_header.csv
201
+
202
+ # Disable type inference for faster loading
203
+ dv -I large_data.csv
204
+
205
+ # Ignore parsing errors in malformed CSV
206
+ dv -E data_with_errors.csv
207
+
208
+ # Skip first 3 lines of file (e.g., metadata)
209
+ dv -l 3 data_with_meta.csv
210
+
211
+ # Skip 1 row after header (e.g., units row)
212
+ dv -a 1 data_with_units.csv
213
+
214
+ # Skip comment lines (or just -c)
215
+ dv -c "#" commented_data.csv
216
+
217
+ # Treat specific values as null/missing (e.g., 'NA', 'N/A', '-')
218
+ dv -n NA N/A - data.csv
219
+
220
+ # Use different quote character (e.g., single quote for CSV)
221
+ dv -q "'" data.csv
222
+
223
+ # Disable quote character processing for TSV with embedded quotes
224
+ dv -q data.tsv
225
+
226
+ # Complex CSV with comments and units row
227
+ dv -l 3 -a 1 -I messy_scientific_data.csv
228
+
229
+ # Process compressed data
230
+ dv data.csv.gz
231
+ zcat compressed_data.csv.gz | dv -f csv
232
+ ```
153
233
 
154
234
  ## Keyboard Shortcuts
155
235
 
@@ -159,20 +239,28 @@ When multiple files are opened:
159
239
 
160
240
  | Key | Action |
161
241
  |-----|--------|
162
- | `Ctrl+O` | Open file in a new tab |
163
- | `Ctrl+W` | Close current tab |
164
- | `Ctrl+A` | Save all open tabs to Excel file |
165
- | `>` or `b` | Move to next tab |
242
+ | `>` | Move to next tab |
166
243
  | `<` | Move to previous tab |
244
+ | `b` | Cycle through tabs |
167
245
  | `B` | Toggle tab bar visibility |
168
- | `q` | Quit the application |
246
+ | `q` | Close current tab (prompts to save unsaved changes) |
247
+ | `Q` | Close all tabs and app (prompts to save unsaved changes) |
248
+ | `Ctrl+Q` | Force to quit app (regardless of unsaved changes) |
249
+ | `Ctrl+T` | Save current tab to file |
250
+ | `w` | Save current tab to file (overwrite without prompt) |
251
+ | `Ctrl+A` | Save all tabs to file |
252
+ | `W` | Save all tabs to file (overwrite without prompt) |
253
+ | `Ctrl+D` | Duplicate current tab |
254
+ | `Ctrl+O` | Open file in a new tab |
255
+ | `Double-click` | Rename tab |
169
256
 
170
257
  #### View & Settings
171
258
 
172
259
  | Key | Action |
173
260
  |-----|--------|
174
261
  | `F1` | Toggle help panel |
175
- | `k` | Cycle through themes |
262
+ | `k` | Cycle through dark, light and other themes |
263
+ | `Ctrl+P` -> `Screenshot` | Capture terminal view as a SVG image |
176
264
 
177
265
  ---
178
266
 
@@ -186,20 +274,34 @@ When multiple files are opened:
186
274
  | `G` | Jump to last row (loads all remaining rows) |
187
275
  | `↑` / `↓` | Move up/down one row |
188
276
  | `←` / `→` | Move left/right one column |
189
- | `Home` / `End` | Jump to first/last column in current row |
190
- | `Ctrl + Home` / `Ctrl + End` | Jump to top/bottom in current page |
277
+ | `Home` / `End` | Jump to first/last column |
278
+ | `Ctrl + Home` / `Ctrl + End` | Jump to page top/bottom |
191
279
  | `PageDown` / `PageUp` | Scroll down/up one page |
280
+ | `Ctrl+F` | Page forward |
281
+ | `Ctrl+B` | Page backforward |
282
+
283
+ #### Undo/Redo/Reset
284
+ | Key | Action |
285
+ |-----|--------|
286
+ | `u` | Undo last action |
287
+ | `U` | Redo last undone action |
288
+ | `Ctrl+U` | Reset to initial state |
192
289
 
193
- #### Viewing & Display
290
+ #### Display
194
291
 
195
292
  | Key | Action |
196
293
  |-----|--------|
197
- | `Enter` | View full details of current row in modal |
198
- | `F` | Show frequency distribution for column |
294
+ | `Enter` | Record view of current row transposed |
295
+ | `F` | Show frequency distribution for current column |
199
296
  | `s` | Show statistics for current column |
200
297
  | `S` | Show statistics for entire dataframe |
201
- | `K` | Cycle cursor type: cell → row → column → cell |
298
+ | `K` | Cycle cursor types: cell → row → column → cell |
202
299
  | `~` | Toggle row labels |
300
+ | `_` (underscore) | Expand column to full width |
301
+ | `z` | Freeze rows and columns |
302
+ | `,` | Toggle thousand separator for numeric display |
303
+ | `h` | Hide current column |
304
+ | `H` | Show all hidden rows/columns |
203
305
 
204
306
  #### Data Editing
205
307
 
@@ -208,56 +310,57 @@ When multiple files are opened:
208
310
  | `Double-click` | Edit cell or rename column header |
209
311
  | `delete` | Clear current cell (set to NULL) |
210
312
  | `e` | Edit current cell (respects data type) |
211
- | `E` | Edit entire column with expression |
313
+ | `E` | Edit entire column with value/expression |
212
314
  | `a` | Add empty column after current |
213
315
  | `A` | Add column with name and value/expression |
316
+ | `@` | Add a link column from URL template |
214
317
  | `-` (minus) | Delete current column |
215
- | `_` (underscore) | Delete current column and all columns after |
216
- | `Ctrl+_` | Delete current column and all columns before |
217
318
  | `x` | Delete current row |
218
- | `X` | Delete current row and all rows below |
219
- | `Ctrl+X` | Delete current row and all rows above |
319
+ | `X` | Delete current row and all those below |
320
+ | `Ctrl+X` | Delete current row and all those above |
220
321
  | `d` | Duplicate current column (appends '_copy' suffix) |
221
322
  | `D` | Duplicate current row |
222
- | `h` | Hide current column |
223
- | `H` | Show all hidden rows/columns |
224
323
 
225
- #### Searching & Filtering
324
+ #### Row Selection
226
325
 
227
326
  | Key | Action |
228
327
  |-----|--------|
229
- | `\` | Search in current column using cursor value and select rows |
230
- | `\|` (pipe) | Search in current column with expression and select rows |
231
- | `/` | Find in current column with cursor value and highlight matches |
232
- | `?` | Find in current column with expression and highlight matches |
233
- | `n` | Go to next match |
234
- | `N` | Go to previous match |
328
+ | `\` | Select rows that matches cursor value in current column |
329
+ | `\|` (pipe) | Select rows by expression |
235
330
  | `{` | Go to previous selected row |
236
331
  | `}` | Go to next selected row |
237
332
  | `'` | Select/deselect current row |
238
- | `t` | Toggle selected rows (invert) |
239
- | `T` | Clear all selected rows and/or matches |
240
- | `"` (quote) | Filter to selected rows only |
241
- | `v` | View only rows by selected rows and/or matches or cursor value |
242
- | `V` | View only rows by expression |
333
+ | `t` | Toggle row selections (invert) |
334
+ | `T` | Clear all row selections and/or cell matches |
243
335
 
244
- #### SQL Interface
336
+ #### Find & Replace
245
337
 
246
338
  | Key | Action |
247
339
  |-----|--------|
248
- | `l` | Simple SQL interface (select columns & WHERE clause) |
249
- | `L` | Advanced SQL interface (full SQL queries) |
340
+ | `/` | Find in current column with cursor value and highlight matching cells |
341
+ | `?` | Find in current column with expression and highlight matching cells |
342
+ | `n` | Go to next matching cell |
343
+ | `N` | Go to previous matching cell |
344
+ | `;` | Find across all columns with cursor value |
345
+ | `:` | Find across all columns with expression |
346
+ | `r` | Find and replace in current column (interactive or replace all) |
347
+ | `R` | Find and replace across all columns (interactive or replace all) |
250
348
 
251
- #### Find & Replace
349
+ #### View & Filter
350
+ | Key | Action |
351
+ |-----|--------|
352
+ | `"` (quote) | Filter to rows that are selected or contain matching cells (and remove others) |
353
+ | `v` | View rows (and hide others) by row selections and cell matches or cursor value |
354
+ | `V` | View rows (and hide others) by expression |
355
+
356
+ #### SQL Interface
252
357
 
253
358
  | Key | Action |
254
359
  |-----|--------|
255
- | `f` | Find across all columns with cursor value |
256
- | `Ctrl+F` | Find across all columns with expression |
257
- | `r` | Find and replace in current column (interactive or replace all) |
258
- | `R` | Find and replace across all columns (interactive or replace all) |
360
+ | `l` | Simple SQL interface (select columns & where clause) |
361
+ | `L` | Advanced SQL interface (full SQL query with syntax highlight) |
259
362
 
260
- #### Sorting
363
+ #### Sorting (supporting multiple columns)
261
364
 
262
365
  | Key | Action |
263
366
  |-----|--------|
@@ -273,7 +376,7 @@ When multiple files are opened:
273
376
  | `Shift+←` | Move current column left |
274
377
  | `Shift+→` | Move current column right |
275
378
 
276
- #### Type Conversion
379
+ #### Type Casting
277
380
 
278
381
  | Key | Action |
279
382
  |-----|--------|
@@ -281,21 +384,15 @@ When multiple files are opened:
281
384
  | `%` | Cast current column to float (Float64) |
282
385
  | `!` | Cast current column to boolean |
283
386
  | `$` | Cast current column to string |
284
- | `@` | Make URLs in current column clickable with Ctrl/Cmd + click|
285
387
 
286
- #### Data Management
388
+ #### Copy & Save
287
389
 
288
390
  | Key | Action |
289
391
  |-----|--------|
290
- | `z` | Freeze rows and columns |
291
- | `,` | Toggle thousand separator for numeric display |
292
392
  | `c` | Copy current cell to clipboard |
293
393
  | `Ctrl+C` | Copy column to clipboard |
294
394
  | `Ctrl+R` | Copy row to clipboard (tab-separated) |
295
395
  | `Ctrl+S` | Save current tab to file |
296
- | `u` | Undo last action |
297
- | `U` | Redo last undone action |
298
- | `Ctrl+U` | Reset to initial state |
299
396
 
300
397
  ## Features in Detail
301
398
 
@@ -303,155 +400,108 @@ When multiple files are opened:
303
400
 
304
401
  Columns are automatically styled based on their data type:
305
402
  - **integer**: Cyan text, right-aligned
306
- - **float**: Magenta text, right-aligned
403
+ - **float**: Yellow text, right-aligned
307
404
  - **string**: Green text, left-aligned
308
405
  - **boolean**: Blue text, centered
309
- - **temporal**: Yellow text, centered
406
+ - **temporal**: Magenta text, centered
310
407
 
311
408
  ### 2. Row Detail View
312
409
 
313
410
  Press `Enter` on any row to open a modal showing all column values for that row.
314
- Useful for examining wide datasets where columns don't fit on screen.
411
+ Useful for examining wide datasets where columns don't fit well on screen.
315
412
 
316
413
  **In the Row Detail Modal**:
317
- - Press `v` to **view** the main table to show only rows with the selected column value
318
- - Press `"` to **filter** all rows containing the selected column value
414
+ - Press `v` to **view** all rows containing the selected column value (and hide others)
415
+ - Press `"` to **filter** all rows containing the selected column value (and remove others)
416
+ - Press `{` to move to the **previous row** (respects hidden rows)
417
+ - Press `}` to move to the **next row** (respects hidden rows)
319
418
  - Press `q` or `Escape` to close the modal
320
419
 
321
- ### 3. Search & Filtering
420
+ ### 3. Row Selection
322
421
 
323
- The application provides multiple search modes for different use cases:
422
+ The application provides multiple modes for selecting rows (marks it for filtering or viewing):
324
423
 
325
- **Search Operations** - Direct value/expression matching in current column:
326
- - **`|` - Column Expression Search**: Opens dialog to search current column with custom expression
327
- - **`\` - Column Cursor Search**: Instantly search current column using the cursor value
328
-
329
- **Find Operations** - Find by value/expression:
330
- - **`/` - Column Find**: Find cursor value within current column
331
- - **`?` - Column Expression Find**: Open dialog to search current column with expression
332
- - **`f` - Global Find**: Find cursor value across all columns
333
- - **`Ctrl+f` - Global Expression Find**: Open dialog to search all columns with expression
334
-
335
- **Selection & Filtering**:
336
- - **`'` - Toggle Row Selection**: Select/deselect current row (marks it for filtering)
337
- - **`t` - Invert Selections**: Flip selection state of all rows at once
338
- - **`T` - Clear Selections**: Remove all row selections and matches
339
- - **`"` - Filter Selected**: Display only the selected rows and remove others
340
- - **`v` - View by Value**: Filter/view rows by selected rows or cursor value (others hidden but preserved)
341
- - **`V` - View by Expression**: Filter/view rows using custom Polars expression (others hidden but preserved)
424
+ - `\` - Select rows that match cursor value in current column (respects data type)
425
+ - `|` - Opens dialog to select rows with custom expression
426
+ - `'` - Select/deselect current row
427
+ - `t` - Flip selections of all rows
428
+ - `T` - Clear all row selections and cell matches
429
+ - `{` - Go to previous selected row
430
+ - `}` - Go to next selected row
342
431
 
343
432
  **Advanced Matching Options**:
344
433
 
345
434
  When searching or finding, you can use checkboxes in the dialog to enable:
346
- - **Match Nocase**: Ignore case differences (e.g., "john", "John", "JOHN" all match)
347
- - **Match Whole**: Match complete value, not partial substrings or words (e.g., "cat" won't match in "catfish")
435
+ - **Match Nocase**: Ignore case differences
436
+ - **Match Whole**: Match complete value, not partial substrings or words
348
437
 
349
- These options work with plain text searches. Use Polars regex patterns in expressions for more control:
350
- - **Case-insensitive matching in expressions**: Use `(?i)` prefix in regex (e.g., `(?i)john`)
351
- - **Word boundaries in expressions**: Use `\b` in regex (e.g., `\bjohn\b` matches whole word)
438
+ These options work with plain text searches. Use Polars regex patterns in expressions for more control. For example, use `(?i)` prefix in regex (e.g., `(?i)john`) for case-insensitive matching.
352
439
 
353
440
  **Quick Tips:**
354
- - Search results highlight matching rows/cells in **red**
355
- - Multiple searches **accumulate selections** - each new search adds to the selections
441
+ - Search results highlight matching rows in **red**
442
+ - Use expression for advanced selection (e.g., $attack > $defense)
443
+ - Multiple searches **accumulate** - each new search adds to the selections or matches
356
444
  - Type-aware matching automatically converts values. Resort to string comparison if conversion fails
357
445
  - Use `u` to undo any search or filter
358
446
 
359
- ### 3b. Find & Replace
360
-
361
- The application provides powerful find and replace functionality for both single-column and global replacements.
447
+ ### 4. Find & Replace
448
+ **Find Operations** - Find by value/expression and highlight matching cells:
449
+ - `/` - Find cursor value within current column (respects data type)
450
+ - `?` - Open dialog to search current column with expression
451
+ - `;` - Find cursor value across all columns
452
+ - `:` - Open dialog to search all columns with expression
453
+ - `n` - Go to next matching cell
454
+ - `N` - Go to previous matching cell
362
455
 
363
- **Replace Operations**:
364
- - **`r` - Column Replace**: Replace values in the current column
365
- - **`R` - Global Replace**: Replace values across all columns
456
+ Replace values in current column (`r`) or across all columns (`R`).
366
457
 
367
458
  **How It Works:**
368
459
 
369
- When you press `r` or `R`, a dialog opens where you can enter:
370
- 1. **Find term**: The value or expression to search for
371
- 2. **Replace term**: What to replace matches with
372
- 3. **Matching options**:
373
- - **Match Nocase**: Ignore case differences when matching (unchecked by default)
374
- - **Match Whole**: Match complete words only, not partial words (unchecked by default)
375
- 4. **Replace option**:
376
- - Choose **"Replace All"** to replace all matches at once (with confirmation)
377
- - Otherwise, review and confirm each match individually
378
-
379
- **Replace All** (`r` or `R` → Choose "Replace All"):
380
- - Shows a confirmation dialog with the number of matches and replacements
381
- - Replaces all matches with a single operation
382
- - Full undo support with `u`
383
- - Useful for bulk replacements when you're confident about the change
384
-
385
- **Replace Interactive** (`r` or `R` → Choose "Replace Interactive"):
386
- - Shows each match one at a time with a preview of the replacement
387
- - For each match, press:
388
- - `Enter` or press the `Yes` button - **Replace this occurrence** and move to next
389
- - Press the `Skip` button - **Skip this occurrence** and move to next
390
- - `Escape` or press the `No` button - **Cancel** remaining replacements (but keep already-made replacements)
391
- - Displays progress: `Occurrence X of Y` (Y = total matches, X = current)
392
- - Shows the value that will be replaced and what it will become
393
- - Useful for careful replacements where you want to review each change
394
-
395
- **Search Term Types:**
396
- - **Plain text**: Exact string match (e.g., "John" finds "John")
397
- - Use **Match Nocase** checkbox to match regardless of case (e.g., find "john", "John", "JOHN")
398
- - Use **Match Whole** checkbox to match complete words only (e.g., find "cat" but not in "catfish")
399
- - **NULL**: Replace null/missing values (type `NULL`)
400
- - **Expression**: Polars expressions for complex matching (e.g., `$_ > 50` for column replace)
401
- - **Regex patterns**: Use Polars regex syntax for advanced matching
402
- - Case-insensitive: Use `(?i)` prefix (e.g., `(?i)john`)
403
- - Whole word: Use `\b` boundary markers (e.g., `\bjohn\b`)
460
+ When you press `r` or `R`, enter:
461
+ 1. **Find term**: Value or expression to search for (done by string value)
462
+ 2. **Replace term**: Replacement value
463
+ 3. **Matching options**: Match Nocase (ignore case), Match Whole (complete match only)
464
+ 4. **Replace mode**: All at once or interactive review
404
465
 
405
- **Examples:**
466
+ **Replace All**:
467
+ - Replaces all matches with one operation
468
+ - Shows confirmation with match count
406
469
 
407
- ```
408
- Find: "John"
409
- Replace: "Jane"
410
- → All occurrences of "John" become "Jane"
411
-
412
- Find: "john"
413
- Replace: "jane"
414
- Match Nocase: ✓ (checked)
415
- → "John", "JOHN", "john" all become "jane"
416
-
417
- Find: "cat"
418
- Replace: "dog"
419
- Match Whole: ✓ (checked)
420
- → "cat" becomes "dog", but "catfish" is not matched
421
-
422
- Find: "NULL"
423
- Replace: "Unknown"
424
- → All null/missing values become "Unknown"
425
-
426
- Find: "(?i)active" # Case-insensitive
427
- Replace: "inactive"
428
- → "Active", "ACTIVE", "active" all become "inactive"
429
- ```
470
+ **Replace Interactive**:
471
+ - Review each match one at a time (confirm, skip, or cancel)
472
+ - Shows progress: `X of Y`
430
473
 
431
- **For Global Replace (`R`)**:
432
- - Searches and replaces across all columns simultaneously
433
- - Each column can have different matching behavior (string matching for text, numeric for numbers)
434
- - Preview shows which columns contain matches before replacement
435
- - Useful for standardizing values across multiple columns
474
+ **Tips:**
475
+ - Search are done by string value (i.e. ignoring data type)
476
+ - Type `NULL` to replace null/missing values
477
+ - Use `Match Nocase` for case-insensitive matching
478
+ - Use `Match Whole` to avoid partial replacements
479
+ - Support undo (`u`)
436
480
 
437
- **Features:**
438
- - **Full history support**: Use `u` (undo) to revert any replacement
439
- - **Visual feedback**: Matching cells are highlighted before you choose replacement mode
440
- - **Safe operations**: Requires confirmation before replacing
441
- - **Progress tracking**: Shows how many replacements have been made during interactive mode
442
- - **Type-aware**: Respects column data types when matching and replacing
443
- - **Flexible matching**: Support for case-insensitive and whole-word matching
481
+ ### 5. Filter vs. View
444
482
 
445
- **Tips:**
446
- - Use interactive mode for one-time replacements to be absolutely sure
447
- - Use "Replace All" for routine replacements (e.g., fixing typos, standardizing formats)
448
- - Use **Match Nocase** for matching variations of names or titles
449
- - Use **Match Whole** to avoid unintended partial replacements
450
- - Use `u` immediately if you accidentally replace something wrong
451
- - For complex replacements, use Polars expressions or regex patterns in the find term
452
- - Test with a small dataset first before large replacements
483
+ Both operations show rows that are selected or contain matching cells, but with fundamentally different effects:
453
484
 
454
- ### 4. [Polars Expressions](https://docs.pola.rs/api/python/stable/reference/expressions/index.html)
485
+ | Operation | Keyboard | Effect | Data Preserved |
486
+ |-----------|----------|--------|-----------------|
487
+ | **View** | `v`, `V` | Hides non-matching rows | Yes (hidden, can be restored by `H`) |
488
+ | **Filter** | `"` | Removes non-matching rows | No (permanently deleted) |
489
+
490
+ **When to use View** (`v` or `V`):
491
+ - Exploring or analyzing data safely
492
+ - Switching between different perspectives
493
+ - Press `H` to restore hidden rows (and hidden columns)
494
+
495
+ **When to use Filter** (`"`):
496
+ - Cleaning data (removing unwanted rows)
497
+ - Creating a trimmed dataset for export
498
+ - Permanent row removal from your dataframe
499
+
500
+ **Note**:
501
+ - If currently there are no selected rows and no matching cells, the `"` (Filter) and `v` (View) will use cursor value for search.
502
+ - Both support full undo with `u`.
503
+
504
+ ### 6. [Polars Expressions](https://docs.pola.rs/api/python/stable/reference/expressions/index.html)
455
505
 
456
506
  Complex values or filters can be specified via Polars expressions, with the following adaptions for convenience:
457
507
 
@@ -459,6 +509,7 @@ Complex values or filters can be specified via Polars expressions, with the foll
459
509
  - `$_` - Current column (based on cursor position)
460
510
  - `$1`, `$2`, etc. - Column by 1-based index
461
511
  - `$age`, `$salary` - Column by name (use actual column names)
512
+ - `` $`col name` `` - Column by name with spaces (backtick quoted)
462
513
 
463
514
  **Row References:**
464
515
  - `$#` - Current row index (1-based)
@@ -469,6 +520,7 @@ Complex values or filters can be specified via Polars expressions, with the foll
469
520
  - `$age < 30` - Age less than 30
470
521
  - `$status == 'active'` - Status exactly matches 'active'
471
522
  - `$name != 'Unknown'` - Name is not 'Unknown'
523
+ - `$# <= 10` - Top 10 rows
472
524
 
473
525
  **Logical Operators:**
474
526
  - `&` - AND
@@ -483,8 +535,9 @@ Complex values or filters can be specified via Polars expressions, with the foll
483
535
  - `($score >= 80) & ($score <= 90)` - Score between 80 and 90
484
536
  - `~($status == 'inactive')` - Status is not inactive
485
537
  - `$revenue > $expenses` - Revenue exceeds expenses
538
+ - ``$`product id` > 100`` - Product ID with spaces in column name greater than 100
486
539
 
487
- **String Matching:**
540
+ **String Matching:** ([Polars string API reference](https://docs.pola.rs/api/python/stable/reference/series/string.html))
488
541
  - `$name.str.contains("John")` - Name contains "John" (case-sensitive)
489
542
  - `$name.str.contains("(?i)john")` - Name contains "john" (case-insensitive)
490
543
  - `$email.str.ends_with("@company.com")` - Email ends with domain
@@ -505,26 +558,41 @@ Complex values or filters can be specified via Polars expressions, with the foll
505
558
  - Use column names that match exactly (case-sensitive)
506
559
  - Use parentheses to clarify complex expressions: `($a & $b) | ($c & $d)`
507
560
 
508
- ### 5. Sorting
561
+ ### 7. Sorting
509
562
 
510
563
  - Press `[` to sort current column ascending
511
564
  - Press `]` to sort current column descending
512
565
  - Multi-column sorting supported (press multiple times on different columns)
513
566
  - Press same key twice to remove the column from sorting
514
567
 
515
- ### 6. Frequency Distribution
568
+ ### 8. Dataframe & Column Metadata
569
+
570
+ View quick metadata about your dataframe and columns to understand their structure and content.
571
+
572
+ **Dataframe Metadata** (`m`):
573
+ - Press `m` to open a modal displaying:
574
+ - **Rows** - Total number of rows in the dataframe
575
+ - **Columns** - Total number of columns in the dataframe
516
576
 
517
- Press `F` to see how many times each value appears in the current column. The modal shows:
518
- - Value
519
- - Count
520
- - Percentage
521
- - Histogram
577
+ **Column Metadata** (`M`):
578
+ - Press `M` to open a modal displaying details for all columns:
579
+ - **ID** - 1-based column index
580
+ - **Name** - Column name
581
+ - **Type** - Data type (e.g., Int64, String, Float64, Boolean)
582
+
583
+ **In Metadata Modals**:
584
+ - Press `q` or `Escape` to close
585
+
586
+ ### 9. Frequency Distribution
587
+
588
+ Press `F` to see value distributions of the current column. The modal shows:
589
+ - Value, Count, Percentage, Histogram
522
590
  - **Total row** at the bottom
523
591
 
524
592
  **In the Frequency Table**:
525
593
  - Press `[` and `]` to sort by any column (value, count, or percentage)
526
- - Press `v` to **filter** the main table to show only rows with the selected value
527
- - Press `"` to **exclude** all rows except those containing the selected value
594
+ - Press `v` to **filter** all rows with the selected value (others hidden but preserved)
595
+ - Press `"` to **exclude** all rows containing the selected value (others removed)
528
596
  - Press `q` or `Escape` to close the frequency table
529
597
 
530
598
  This is useful for:
@@ -533,19 +601,11 @@ This is useful for:
533
601
  - Identifying rare or common values
534
602
  - Finding the most/least frequent entries
535
603
 
536
- ### 7. Column & Dataframe Statistics
604
+ ### 10. Column & Dataframe Statistics
537
605
 
538
- Press `s` to see summary statistics for the current column, or press `S` for statistics across the entire dataframe.
539
-
540
- **Column Statistics** (`s`):
541
- - Shows calculated statistics using Polars' `describe()` method
542
- - Displays: count, null count, mean, median, std, min, max, etc.
543
- - Values are color-coded according to their data type
544
- - Statistics label column has no styling for clarity
545
-
546
- **Dataframe Statistics** (`S`):
547
- - Shows statistics for all numeric and applicable columns simultaneously
548
- - Data columns are color-coded by their data type (integer, float, string, etc.)
606
+ Show summary statistics (count, null count, mean, median, std, min, max, etc.) using Polars' `describe()` method.
607
+ - `s` for the current column
608
+ - `S` for all columns across the entire dataframe
549
609
 
550
610
  **In the Statistics Modal**:
551
611
  - Press `q` or `Escape` to close the statistics table
@@ -559,7 +619,7 @@ This is useful for:
559
619
  - Quick statistical summaries without external tools
560
620
  - Comparing statistics across columns
561
621
 
562
- ### 8. Data Editing
622
+ ### 11. Data Editing
563
623
 
564
624
  **Edit Cell** (`e` or **Double-click**):
565
625
  - Opens modal for editing current cell
@@ -581,53 +641,31 @@ This is useful for:
581
641
  - Useful for removing leading rows or the beginning of a dataset
582
642
 
583
643
  **Delete Column** (`-`):
584
- - Removes the entire column from view and dataframe
585
-
586
- **Delete Column and After** (`_`):
587
- - Deletes the current column and all columns to the right
588
- - Useful for removing trailing columns or the end of a dataset
644
+ - Removes the entire column from display and dataframe
589
645
 
590
- **Delete Column and Before** (`Ctrl+-`):
591
- - Deletes the current column and all columns to the left
592
- - Useful for removing leading columns or the beginning of a dataset
646
+ **Add Empty Column** (`a`):
647
+ - Adds a new empty column after the current column
648
+ - Column is initialized with NULL values for all rows
593
649
 
594
- ### 9. Hide & Show Columns
650
+ **Add Column with Value/Expression** (`A`):
651
+ - Opens dialog to specify column name and initial value/expression
652
+ - Value can be a constant (e.g., `0`, `"text"`) or a Polars expression (e.g., `$age * 2`)
653
+ - Expression can reference other columns and perform calculations
654
+ - Useful for creating derived columns or adding data with formulas
595
655
 
596
- **Hide Column** (`h`):
597
- - Temporarily hides the current column from display
598
- - Column data is preserved in the dataframe
599
- - Hidden columns are included in saves
600
-
601
- **Show Hidden Rows/Columns** (`H`):
602
- - Restores all previously hidden rows/columns to the display
603
-
604
- This is useful for:
605
- - Focusing on specific columns without deleting data
606
- - Temporarily removing cluttered or unnecessary columns
607
-
608
- ### 10. Duplicate Column
609
-
610
- Press `d` to duplicate the current column:
656
+ **Duplicate Column** (`d`):
611
657
  - Creates a new column immediately after the current column
612
658
  - New column has '_copy' suffix (e.g., 'price' → 'price_copy')
613
- - Duplicate preserves all data from original column
614
- - New column is inserted into the dataframe
615
-
616
- This is useful for:
617
- - Creating backup copies of columns before transformation
618
- - Working with alternative versions of column data
619
- - Comparing original vs. processed column values side-by-side
620
-
621
- ### 11. Duplicate Row
659
+ - Useful for creating backups before transformation
622
660
 
623
- Press `D` to duplicate the current row:
661
+ **Duplicate Row** (`D`):
624
662
  - Creates a new row immediately after the current row
625
663
  - Duplicate preserves all data from original row
626
- - New row is inserted into the dataframe
664
+ - Useful for batch adding similar records
627
665
 
628
- This is useful for:
629
- - Creating variations of existing data records
630
- - Batch adding similar rows with modifications
666
+ **Hide/Show Columns** (`h` / `H`):
667
+ - `h` - Temporarily hide current column (data preserved)
668
+ - `H` - Restore all hidden columns and rows
631
669
 
632
670
  ### 12. Column & Row Reordering
633
671
 
@@ -644,7 +682,7 @@ This is useful for:
644
682
  Press `z` to open the dialog:
645
683
  - Enter number of fixed rows and/or columns to keep top rows/columns visible while scrolling
646
684
 
647
- ### 13.5. Thousand Separator Toggle
685
+ ### 14. Thousand Separator Toggle
648
686
 
649
687
  Press `,` to toggle thousand separator formatting for numeric data:
650
688
  - Applies to **integer** and **float** columns
@@ -654,14 +692,11 @@ Press `,` to toggle thousand separator formatting for numeric data:
654
692
  - Display-only: does not modify underlying data in the dataframe
655
693
  - State persists during the session
656
694
 
657
- ### 14. Save File
695
+ ### 15. Save File
658
696
 
659
- Press `Ctrl+S` to save:
660
- - Save filtered, edited, or sorted data back to file
661
- - Choose filename in modal dialog
662
- - Confirm if file already exists
697
+ Press `Ctrl+S` to save filtered, edited, or sorted data back to file
663
698
 
664
- ### 15. Undo/Redo/Reset
699
+ ### 16. Undo/Redo/Reset
665
700
 
666
701
  **Undo** (`u`):
667
702
  - Reverts last action with full state restoration
@@ -679,7 +714,7 @@ Press `Ctrl+S` to save:
679
714
  - Clears all edits, deletions, selections, filters, and sorts
680
715
  - Useful for starting fresh without reloading the file
681
716
 
682
- ### 16. Column Type Conversion
717
+ ### 17. Column Type Conversion
683
718
 
684
719
  Press the type conversion keys to instantly cast the current column to a different data type:
685
720
 
@@ -696,26 +731,19 @@ Press the type conversion keys to instantly cast the current column to a differe
696
731
 
697
732
  **Note**: Type conversion attempts to preserve data where possible. Conversions may lose data (e.g., float to int rounding).
698
733
 
699
- ### 17. Cursor Type Cycling
734
+ ### 18. Cursor Type Cycling
700
735
 
701
736
  Press `K` to cycle through selection modes:
702
737
  1. **Cell mode**: Highlight individual cell (and its row/column headers)
703
738
  2. **Row mode**: Highlight entire row
704
739
  3. **Column mode**: Highlight entire column
705
740
 
706
- ### 18. URL Handling
707
-
708
- Press `@` to make URLs in the current column clickable:
709
- - **Ctrl/Cmd + click** on URLs to open them in your default browser
710
- - **Scans** all cells in the current column for URLs starting with `http://` or `https://`
711
- - **Applies** link styling to make them clickable and dataframe remains unchanged
712
-
713
741
  ### 19. SQL Interface
714
742
 
715
743
  The SQL interface provides two modes for querying your dataframe:
716
744
 
717
745
  #### Simple SQL Interface (`l`)
718
- Select specific columns and apply WHERE conditions without writing full SQL:
746
+ SELECT specific columns and apply WHERE conditions without writing full SQL:
719
747
  - Choose which columns to include in results
720
748
  - Specify WHERE clause for filtering
721
749
  - Ideal for quick filtering and column selection
@@ -726,56 +754,77 @@ Execute complete SQL queries for advanced data manipulation:
726
754
  - Support for JOINs, GROUP BY, aggregations, and more
727
755
  - Access to all SQL capabilities for complex transformations
728
756
  - Always use `self` as the table name
757
+ - Syntax highlighted
729
758
 
730
759
  **Examples:**
731
760
  ```sql
732
761
  -- Filter and select specific rows and/or columns
733
- SELECT name, age FROM self WHERE age > 30
734
-
735
- -- Aggregate with GROUP BY
736
- SELECT department, COUNT(*) as count, AVG(salary) as avg_salary
762
+ SELECT name, age
737
763
  FROM self
738
- GROUP BY department
764
+ WHERE age > 30
739
765
 
740
- -- Complex filtering with multiple conditions
766
+ -- Use backticks (`) for column names with spaces
741
767
  SELECT *
742
768
  FROM self
743
- WHERE (age > 25 AND salary > 50000) OR department = 'Management'
769
+ WHERE `product id` = 7
744
770
  ```
745
771
 
746
772
  ### 20. Clipboard Operations
747
773
 
748
- Copies value to system clipboard with `pbcopy` on macOS and `xclip` on Linux
774
+ Copies value to system clipboard with `pbcopy` on macOS and `xclip` on Linux.
775
+
776
+ **Note** May require a X server to work.
749
777
 
750
- Press `Ctrl+C` to copy:
751
778
  - Press `c` to copy cursor value
752
779
  - Press `Ctrl+C` to copy column values
753
780
  - Press `Ctrl+R` to copy row values (delimited by tab)
781
+ - Hold `Shift` to select with mouse
754
782
 
755
- ## Examples
783
+ ### 21. Link Column Creation
756
784
 
757
- ### Single File Examples
785
+ Press `@` to create a new column containing dynamically generated URLs using template.
758
786
 
759
- ```bash
760
- # View Pokemon dataset
761
- dv pokemon.csv
787
+ **Template Placeholders:**
762
788
 
763
- # Chain with other command and specify input file format
764
- cut -d',' -f1,2,3 pokemon.csv | dv -f csv
765
- ```
789
+ The link template supports multiple placeholder types for maximum flexibility:
766
790
 
767
- ### Multi-File/Tab Examples
791
+ - **`$_`** - Current column (the column where cursor was when `@` was pressed), e.g., `https://example.com/search/$_` - Uses values from the current column
768
792
 
769
- ```bash
770
- # Open multiple sheets as tabs in a single Excel
771
- dv sales.xlsx
793
+ - **`$1`, `$2`, `$3`, etc.** - Column by 1-based position index, e.g., `https://example.com/product/$1/details/$2` - Uses 1st and 2nd columns
772
794
 
773
- # Open multiple files as tabs
774
- dv pokemon.csv titanic.csv
795
+ - **`$name`** - Column by name (use actual column names), e.g., `https://example.com/$region/$city/data` - Uses `region` and `city` columns
775
796
 
776
- # Start with one file, then open others using Ctrl+O
777
- dv initial_data.csv
778
- ```
797
+ **Features:**
798
+ - **Multiple Placeholders**: Mix and match placeholders in a single template
799
+ - **URL Prefix**: Automatically prepends `https://` if URL doesn't start with `http://` or `https://`
800
+
801
+ **Tips:**
802
+ - Use full undo (`u`) if template produces unexpected URLs
803
+ - For complex multi-column URLs, use column names (`$name`) for clarity over positions (`$1`)
804
+
805
+ ### 22. Tab Management
806
+
807
+ Manage multiple files and dataframes simultaneously with tabs.
808
+
809
+ **Tab Operations:**
810
+ - **`Ctrl+O`** - Open file in a new tab
811
+ - **`>`** - Move to next tab
812
+ - **`<`** - Move to previous tab
813
+ - **`b`** - Cycle through tabs
814
+ - **`B`** - Toggle tab bar visibility
815
+ - **`Double-click`** - Rename the tab
816
+ - **`Ctrl+D`** - Duplicate current tab (creates a copy with same data and state)
817
+ - **`Ctrl+T`** - Save current tab to file
818
+ - **`w`** - Save current tab to file (overwrite without prompt)
819
+ - **`Ctrl+A`** - Save all tabs in a single Excel file
820
+ - **`W`** - Save all tabs to file (overwrite without prompt)
821
+ - **`q`** - Close current tab (closes tab, prompts to save if unsaved changes)
822
+ - **`Q`** - Close all tabs and exit app (prompts to save tabs with unsaved changes)
823
+ - **`Ctrl+Q`** - Force to quit app regardless of unsaved changes
824
+
825
+ **Tips:**
826
+ - Tabs with unsaved changes are indicated with a bright background
827
+ - Closing or quitting a tab with unsaved changes triggers a save prompt
779
828
 
780
829
  ## Dependencies
781
830