dataframe-textual 1.9.0__py3-none-any.whl → 1.12.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataframe-textual
3
- Version: 1.9.0
3
+ Version: 1.12.0
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
@@ -62,8 +62,8 @@ 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
66
- - �📌 **Freeze Rows/Columns** - Keep important rows and columns visible while scrolling
65
+ - 📑 **Duplicate Tab** - Create a copy of the current tab with the same data
66
+ - 📌 **Freeze Rows/Columns** - Keep important rows and columns visible while scrolling
67
67
  - 🎯 **Cursor Type Cycling** - Switch between cell, row, and column selection modes
68
68
  - 🔗 **Link Column Creation** - Generate clickable URLs using template expressions with placeholder support
69
69
 
@@ -83,7 +83,7 @@ This installs an executable `dv`.
83
83
 
84
84
  Then run:
85
85
  ```bash
86
- dv <csv_file>
86
+ dv <file>
87
87
  ```
88
88
 
89
89
  ### Using [uv](https://docs.astral.sh/uv/)
@@ -97,7 +97,7 @@ cd dataframe-textual
97
97
  uv sync --extra excel # with Excel support
98
98
 
99
99
  # Run directly with uv
100
- uv run dv <csv_file>
100
+ uv run dv <file>
101
101
  ```
102
102
 
103
103
  ### Development installation
@@ -122,8 +122,8 @@ pip install -e ".[excel,dev]"
122
122
  # After pip install dataframe-textual
123
123
  dv pokemon.csv
124
124
 
125
- # Or if running from source
126
- python main.py pokemon.csv
125
+ # Or run from module
126
+ python -m dataframe-textual pokemon.csv
127
127
 
128
128
  # Or with uv
129
129
  uv run python main.py pokemon.csv
@@ -153,22 +153,23 @@ dv data1.tsv < data2.tsv
153
153
  ```
154
154
 
155
155
  When multiple files are opened:
156
- - Each file appears as a separate tab
157
- - Switch between tabs using `>` (next) or `<` (previous), or use `b` for cycling tabs
158
- - Save current tab or all tabs with `Ctrl+S`
156
+ - Each file appears as a separate tab. An Excel file may contain multiple tabs.
157
+ - Switch between tabs using `>` (next) or `<` (previous), or use `b` for cycling through tabs
158
+ - Save current tab to file with `Ctrl+T`
159
+ - Save all tabs to file with `Ctrl+A`
159
160
  - Duplicate the current tab with `Ctrl+D`
160
161
  - Open additional files with `Ctrl+O`
161
- - Each file maintains its own state (edits, sort order, selections, history, etc.)
162
+ - Each file maintains its own state (edits, sort order, selections, history, etc.) and allow undo/redo.
162
163
 
163
164
  ## Command Line Options
164
165
 
165
166
  ```
166
167
  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 ...]
167
168
 
168
- Interactive terminal based viewer/editor for tabular data (e.g., CSV/Excel).
169
+ Interactive terminal based viewer/editor for tabular data (e.g., CSV/TSV/Excel).
169
170
 
170
171
  positional arguments:
171
- files Files to view (or read from stdin)
172
+ files Input files (or read from stdin)
172
173
 
173
174
  options:
174
175
  -h, --help show this help message and exit
@@ -180,7 +181,7 @@ options:
180
181
  -c, --comment-prefix COMMENT_PREFIX
181
182
  Comment lines are skipped when reading CSV/TSV (default: skip none)
182
183
  -q, --quote-char QUOTE_CHAR
183
- Quote character for reading CSV/TSV (default: "; use None to disable)
184
+ Quote character for reading CSV/TSV (default: "; use -q without argument value to disable)
184
185
  -l, --skip-lines SKIP_LINES
185
186
  Skip lines when reading CSV/TSV (default: 0)
186
187
  -a, --skip-rows-after-header SKIP_ROWS_AFTER_HEADER
@@ -207,7 +208,7 @@ dv -l 3 data_with_meta.csv
207
208
  # Skip 1 row after header (e.g., units row)
208
209
  dv -a 1 data_with_units.csv
209
210
 
210
- # CSV with comment lines
211
+ # Skip comment lines
211
212
  dv -c "#" commented_data.csv
212
213
 
213
214
  # Treat specific values as null/missing (e.g., 'NA', 'N/A', '-')
@@ -241,18 +242,19 @@ zcat compressed_data.csv.gz | dv -f csv
241
242
  | `B` | Toggle tab bar visibility |
242
243
  | `q` | Close current tab (prompts to save unsaved changes) |
243
244
  | `Q` | Close all tabs and app (prompts to save unsaved changes) |
244
- | `Ctrl+Q` | Force to quit app (regardless off unsaved changes) |
245
- | `Ctrl+S` | Save current tab or all tabs to file |
245
+ | `Ctrl+Q` | Force to quit app (regardless of unsaved changes) |
246
+ | `Ctrl+T` | Save current tab to file |
247
+ | `Ctrl+A` | Save all tabs to file |
246
248
  | `Ctrl+D` | Duplicate current tab |
247
249
  | `Ctrl+O` | Open file in a new tab |
248
- | `Double-click tab` | Rename current tab |
250
+ | `Double-click tab` | Rename tab |
249
251
 
250
252
  #### View & Settings
251
253
 
252
254
  | Key | Action |
253
255
  |-----|--------|
254
256
  | `F1` | Toggle help panel |
255
- | `k` | Cycle through themes |
257
+ | `k` | Cycle through dark, light and other themes |
256
258
 
257
259
  ---
258
260
 
@@ -269,10 +271,12 @@ zcat compressed_data.csv.gz | dv -f csv
269
271
  | `Home` / `End` | Jump to first/last column |
270
272
  | `Ctrl + Home` / `Ctrl + End` | Jump to page top/bottom |
271
273
  | `PageDown` / `PageUp` | Scroll down/up one page |
272
- | `Ctrl+F` | Page down |
273
- | `Ctrl+B` | Page up |
274
+ | `Ctrl+F` | Page forward |
275
+ | `Ctrl+B` | Page backforward |
274
276
 
275
277
  #### Undo/Redo/Reset
278
+ | Key | Action |
279
+ |-----|--------|
276
280
  | `u` | Undo last action |
277
281
  | `U` | Redo last undone action |
278
282
  | `Ctrl+U` | Reset to initial state |
@@ -281,7 +285,7 @@ zcat compressed_data.csv.gz | dv -f csv
281
285
 
282
286
  | Key | Action |
283
287
  |-----|--------|
284
- | `Enter` | Record view of current row |
288
+ | `Enter` | Record view of current row transposed |
285
289
  | `F` | Show frequency distribution for current column |
286
290
  | `s` | Show statistics for current column |
287
291
  | `S` | Show statistics for entire dataframe |
@@ -290,6 +294,8 @@ zcat compressed_data.csv.gz | dv -f csv
290
294
  | `_` (underscore) | Expand column to full width |
291
295
  | `z` | Freeze rows and columns |
292
296
  | `,` | Toggle thousand separator for numeric display |
297
+ | `h` | Hide current column |
298
+ | `H` | Show all hidden rows/columns |
293
299
 
294
300
  #### Data Editing
295
301
 
@@ -298,37 +304,35 @@ zcat compressed_data.csv.gz | dv -f csv
298
304
  | `Double-click` | Edit cell or rename column header |
299
305
  | `delete` | Clear current cell (set to NULL) |
300
306
  | `e` | Edit current cell (respects data type) |
301
- | `E` | Edit entire column with expression |
307
+ | `E` | Edit entire column with value/expression |
302
308
  | `a` | Add empty column after current |
303
309
  | `A` | Add column with name and value/expression |
304
- | `@` | Add a link column from template |
310
+ | `@` | Add a link column from URL template |
305
311
  | `-` (minus) | Delete current column |
306
312
  | `x` | Delete current row |
307
313
  | `X` | Delete current row and all those below |
308
314
  | `Ctrl+X` | Delete current row and all those above |
309
315
  | `d` | Duplicate current column (appends '_copy' suffix) |
310
316
  | `D` | Duplicate current row |
311
- | `h` | Hide current column |
312
- | `H` | Show all hidden rows/columns |
313
317
 
314
318
  #### Searching & Filtering
315
319
 
316
320
  | Key | Action |
317
321
  |-----|--------|
318
- | `\` | Search in current column using cursor value and select rows |
319
- | `\|` (pipe) | Search in current column with expression and select rows |
322
+ | `\` | Search in current column using cursor value and select matching rows |
323
+ | `\|` (pipe) | Search in current column with expression and select matching rows |
320
324
  | `{` | Go to previous selected row |
321
325
  | `}` | Go to next selected row |
322
- | `/` | Find in current column with cursor value and highlight matches |
323
- | `?` | Find in current column with expression and highlight matches |
324
- | `n` | Go to next match |
325
- | `N` | Go to previous match |
326
+ | `/` | Find in current column with cursor value and highlight matching cells |
327
+ | `?` | Find in current column with expression and highlight matching cells |
328
+ | `n` | Go to next matching cell |
329
+ | `N` | Go to previous matching cell |
326
330
  | `'` | Select/deselect current row |
327
- | `t` | Toggle selected rows (invßert) |
328
- | `T` | Clear all selected rows and/or matches |
329
- | `"` (quote) | Filter to selected rows and remove others |
330
- | `v` | View only rows (and hide others) by selected rows and/or matches or cursor value |
331
- | `V` | View only rows (and hide others) by expression |
331
+ | `t` | Toggle row selections (invert) |
332
+ | `T` | Clear all row selections and/or cell matches |
333
+ | `"` (quote) | Filter to selected rows (and remove others) |
334
+ | `v` | View rows (and hide others) by row selections and/or cell matches or cursor value |
335
+ | `V` | View rows (and hide others) by expression |
332
336
 
333
337
  #### SQL Interface
334
338
 
@@ -346,7 +350,7 @@ zcat compressed_data.csv.gz | dv -f csv
346
350
  | `r` | Find and replace in current column (interactive or replace all) |
347
351
  | `R` | Find and replace across all columns (interactive or replace all) |
348
352
 
349
- #### Sorting
353
+ #### Sorting (supporting multiple columns)
350
354
 
351
355
  | Key | Action |
352
356
  |-----|--------|
@@ -386,10 +390,10 @@ zcat compressed_data.csv.gz | dv -f csv
386
390
 
387
391
  Columns are automatically styled based on their data type:
388
392
  - **integer**: Cyan text, right-aligned
389
- - **float**: Magenta text, right-aligned
393
+ - **float**: Yellow text, right-aligned
390
394
  - **string**: Green text, left-aligned
391
395
  - **boolean**: Blue text, centered
392
- - **temporal**: Yellow text, centered
396
+ - **temporal**: Magenta text, centered
393
397
 
394
398
  ### 2. Row Detail View
395
399
 
@@ -401,33 +405,37 @@ Useful for examining wide datasets where columns don't fit well on screen.
401
405
  - Press `"` to **filter** all rows containing the selected column value (and remove others)
402
406
  - Press `q` or `Escape` to close the modal
403
407
 
404
- ### 3. Search & Filtering
408
+ ### 3. Search & Select/Highlight
405
409
 
406
410
  The application provides multiple search modes for different use cases:
407
411
 
408
412
  **Search Operations** - Search by value/expression in current column and select rows:
409
- - **`\` - Column Cursor Search**: Search cursor value
410
- - **`|` - Column Expression Search**: Opens dialog to search with custom expression
413
+ - `\` - Search cursor value
414
+ - `|` - Opens dialog to search with custom expression
411
415
 
412
- **Find Operations** - Find by value/expression and highlight matches:
413
- - **`/` - Column Find**: Find cursor value within current column
414
- - **`?` - Column Expression Find**: Open dialog to search current column with expression
415
- - **`;` - Global Find**: Find cursor value across all columns
416
- - **`:` - Global Expression Find**: Open dialog to search all columns with expression
416
+ **Find Operations** - Find by value/expression and highlight matching cells:
417
+ - `/` - Find cursor value within current column
418
+ - `?` - Open dialog to search current column with expression
419
+ - `;` - Find cursor value across all columns
420
+ - `:` - Open dialog to search all columns with expression
417
421
 
418
422
  **Selection & Filtering**:
419
- - **`'` - Toggle Row Selection**: Select/deselect current row (marks it for filtering or viewing)
420
- - **`t` - Invert Selections**: Flip selections of all rows
421
- - **`T` - Clear Selections**: Remove all row selections and matches
422
- - **`"` - Filter Selected**: View only the selected rows (others removed)
423
- - **`v` - View by Value**: View rows by selected rows or cursor value (others hidden but preserved)
424
- - **`V` - View by Expression**: View rows using custom expression (others hidden but preserved)
423
+ - `'` - Select/deselect current row (marks it for filtering or viewing)
424
+ - `t` - Flip selections of all rows
425
+ - `T` - Clear all row selections and cell matches
426
+ - `"` - **Filter** to rows that are selected and contain matching cells (removes all others permanently)
427
+ - `v` - **View** rows that are selected or contain matching cells (others hidden but preserved)
428
+ - `V` - **View** rows using custom expression (others hidden but preserved)
429
+
430
+ **Note**:
431
+ - The `"` (Filter) and `v`/`V` (View) operations appear similar but have very different effects on your data. See section 3b "Filter vs. View - Understanding the Difference" for detailed guidance on when to use each.
432
+ - If currently there are no selectet rows and no matching cells, the `"` (Filter) and `v` (View) will use cursor value for search.
425
433
 
426
434
  **Advanced Matching Options**:
427
435
 
428
436
  When searching or finding, you can use checkboxes in the dialog to enable:
429
- - **Match Nocase**: Ignore case differences (e.g., "john", "John", "JOHN" all match)
430
- - **Match Whole**: Match complete value, not partial substrings or words (e.g., "cat" won't match in "catfish")
437
+ - **Match Nocase**: Ignore case differences
438
+ - **Match Whole**: Match complete value, not partial substrings or words
431
439
 
432
440
  These options work with plain text searches. Use Polars regex patterns in expressions for more control:
433
441
  - **Case-insensitive matching in expressions**: Use `(?i)` prefix in regex (e.g., `(?i)john`)
@@ -439,66 +447,55 @@ These options work with plain text searches. Use Polars regex patterns in expres
439
447
  - Type-aware matching automatically converts values. Resort to string comparison if conversion fails
440
448
  - Use `u` to undo any search or filter
441
449
 
442
- ### 3b. Find & Replace
450
+ ### 3b. Filter vs. View
451
+
452
+ Both operations show selected rows, but with fundamentally different effects:
453
+
454
+ | Operation | Keyboard | Effect | Data Preserved |
455
+ |-----------|----------|--------|-----------------|
456
+ | **View** | `v`, `V` | Hides non-matching rows | Yes (hidden, can be restored by `H`) |
457
+ | **Filter** | `"` | Removes non-matching rows | No (permanently deleted) |
443
458
 
444
- The application provides powerful find and replace functionality for both single-column and global replacements.
459
+ **When to use View** (`v` or `V`):
460
+ - Exploring or analyzing data safely
461
+ - Switching between different perspectives
462
+ - Press `H` to restore hidden rows (and hidden columns)
445
463
 
446
- **Replace Operations**:
447
- - **`r` - Column Replace**: Replace values in the current column
448
- - **`R` - Global Replace**: Replace values across all columns
464
+ **When to use Filter** (`"`):
465
+ - Cleaning data (removing unwanted rows)
466
+ - Creating a trimmed dataset for export
467
+ - Permanent row removal from your dataframe
468
+
469
+ Both support full undo with `u`.
470
+
471
+ ### 4. Replace
472
+
473
+ Replace values in current column (`r`) or across all columns (`R`).
449
474
 
450
475
  **How It Works:**
451
476
 
452
- When you press `r` or `R`, a dialog opens where you can enter:
453
- 1. **Find term**: The value or expression to search for
454
- 2. **Replace term**: What to replace matches with
455
- 3. **Matching options**:
456
- - **Match Nocase**: Ignore case differences when matching (unchecked by default)
457
- - **Match Whole**: Match complete words only, not partial words (unchecked by default)
458
- 4. **Replace option**:
459
- - Choose **"Replace All"** to replace all matches at once (with confirmation)
460
- - Otherwise, review and confirm each match individually
461
-
462
- **Replace All** (`r` or `R` → Choose "Replace All"):
463
- - Shows a confirmation dialog with the number of matches and replacements
464
- - Replaces all matches with a single operation
465
- - Full undo support with `u`
466
- - Useful for bulk replacements when you're confident about the change
467
-
468
- **Replace Interactive** (`r` or `R` → Choose "Replace Interactive"):
469
- - Shows each match one at a time with a preview of the replacement
470
- - For each match, press:
471
- - `Enter` or press the `Yes` button - **Replace this occurrence** and move to next
472
- - Press the `Skip` button - **Skip this occurrence** and move to next
473
- - `Escape` or press the `No` button - **Cancel** remaining replacements (but keep already-made replacements)
474
- - Displays progress: `Occurrence X of Y` (Y = total occurrences, X = current)
475
- - Useful for careful replacements where you want to review each change
476
-
477
- **For Global Replace (`R`)**:
478
- - Searches and replaces across all columns simultaneously
479
- - Each column can have different matching behavior (string matching for text, numeric for numbers)
480
- - Preview shows which columns contain matches before replacement
481
- - Useful for standardizing values across multiple columns
477
+ When you press `r` or `R`, enter:
478
+ 1. **Find term**: Value or expression to search for (done by string value)
479
+ 2. **Replace term**: Replacement value
480
+ 3. **Matching options**: Match Nocase (ignore case), Match Whole (complete match only)
481
+ 4. **Replace mode**: All at once or interactive review
482
482
 
483
- **Features:**
484
- - **Full history support**: Use `u` (undo) to revert any replacement
485
- - **Visual feedback**: Matching cells are highlighted before you choose replacement mode
486
- - **Safe operations**: Requires confirmation before replacing
487
- - **Progress tracking**: Shows how many replacements have been made during interactive mode
488
- - **Type-aware**: Respects column data types when matching and replacing
489
- - **Flexible matching**: Support for case-insensitive and whole-word matching
483
+ **Replace All**:
484
+ - Replaces all matches with one operation
485
+ - Shows confirmation with match count
486
+
487
+ **Replace Interactive**:
488
+ - Review each match one at a time (confirm, skip, or cancel)
489
+ - Shows progress: `X of Y`
490
490
 
491
491
  **Tips:**
492
- - **NULL**: Replace null/missing values (type `NULL`)
493
- - Use interactive mode for one-time replacements to be absolutely sure
494
- - Use "Replace All" for routine replacements (e.g., fixing typos, standardizing formats)
495
- - Use **Match Nocase** for matching variations of names or titles
496
- - Use **Match Whole** to avoid unintended partial replacements
497
- - Use `u` immediately if you accidentally replace something wrong
498
- - For complex replacements, use Polars expressions or regex patterns in the find term
499
- - Test with a small dataset first before large replacements
492
+ - Search are done by string value (i.e. ignoring data type)
493
+ - Type `NULL` to replace null/missing values
494
+ - Use `Match Nocase` for case-insensitive matching
495
+ - Use `Match Whole` to avoid partial replacements
496
+ - Supprot undo (`u`)
500
497
 
501
- ### 4. [Polars Expressions](https://docs.pola.rs/api/python/stable/reference/expressions/index.html)
498
+ ### 5. [Polars Expressions](https://docs.pola.rs/api/python/stable/reference/expressions/index.html)
502
499
 
503
500
  Complex values or filters can be specified via Polars expressions, with the following adaptions for convenience:
504
501
 
@@ -516,6 +513,7 @@ Complex values or filters can be specified via Polars expressions, with the foll
516
513
  - `$age < 30` - Age less than 30
517
514
  - `$status == 'active'` - Status exactly matches 'active'
518
515
  - `$name != 'Unknown'` - Name is not 'Unknown'
516
+ - `$# <= 10` - Top 10 rows
519
517
 
520
518
  **Logical Operators:**
521
519
  - `&` - AND
@@ -552,14 +550,14 @@ Complex values or filters can be specified via Polars expressions, with the foll
552
550
  - Use column names that match exactly (case-sensitive)
553
551
  - Use parentheses to clarify complex expressions: `($a & $b) | ($c & $d)`
554
552
 
555
- ### 5. Sorting
553
+ ### 6. Sorting
556
554
 
557
555
  - Press `[` to sort current column ascending
558
556
  - Press `]` to sort current column descending
559
557
  - Multi-column sorting supported (press multiple times on different columns)
560
558
  - Press same key twice to remove the column from sorting
561
559
 
562
- ### 6. Frequency Distribution
560
+ ### 7. Frequency Distribution
563
561
 
564
562
  Press `F` to see value distributions of the current column. The modal shows:
565
563
  - Value, Count, Percentage, Histogram
@@ -577,7 +575,7 @@ This is useful for:
577
575
  - Identifying rare or common values
578
576
  - Finding the most/least frequent entries
579
577
 
580
- ### 7. Column & Dataframe Statistics
578
+ ### 8. Column & Dataframe Statistics
581
579
 
582
580
  Press `s` to see summary statistics for the current column, or press `S` for statistics across the entire dataframe.
583
581
 
@@ -601,7 +599,7 @@ This is useful for:
601
599
  - Quick statistical summaries without external tools
602
600
  - Comparing statistics across columns
603
601
 
604
- ### 8. Data Editing
602
+ ### 9. Data Editing
605
603
 
606
604
  **Edit Cell** (`e` or **Double-click**):
607
605
  - Opens modal for editing current cell
@@ -625,17 +623,17 @@ This is useful for:
625
623
  **Delete Column** (`-`):
626
624
  - Removes the entire column from display and dataframe
627
625
 
628
- ### 9. Hide & Show Columns
626
+ ### 10. Hide & Show Columns
629
627
 
630
628
  **Hide Column** (`h`):
631
629
  - Temporarily hides the current column from display
632
630
  - Column data is preserved in the dataframe
633
631
  - Hidden columns are included in saves
634
632
 
635
- **Show Hidden Rows/Columns** (`H`):
636
- - Restores all previously hidden rows/columns to the display
633
+ **Show Hidden Columns** (`H`):
634
+ - Restores all previously hidden columns (and hidden rows) to the display
637
635
 
638
- ### 10. Duplicate Column
636
+ ### 11. Duplicate Column
639
637
 
640
638
  Press `d` to duplicate the current column:
641
639
  - Creates a new column immediately after the current column
@@ -648,7 +646,7 @@ This is useful for:
648
646
  - Working with alternative versions of column data
649
647
  - Comparing original vs. processed column values side-by-side
650
648
 
651
- ### 11. Duplicate Row
649
+ ### 12. Duplicate Row
652
650
 
653
651
  Press `D` to duplicate the current row:
654
652
  - Creates a new row immediately after the current row
@@ -659,7 +657,7 @@ This is useful for:
659
657
  - Creating variations of existing data records
660
658
  - Batch adding similar rows with modifications
661
659
 
662
- ### 12. Column & Row Reordering
660
+ ### 13. Column & Row Reordering
663
661
 
664
662
  **Move Columns**: `Shift+←` and `Shift+→`
665
663
  - Swaps adjacent columns
@@ -669,12 +667,12 @@ This is useful for:
669
667
  - Swaps adjacent rows
670
668
  - Reorder is preserved when saving
671
669
 
672
- ### 13. Freeze Rows and Columns
670
+ ### 14. Freeze Rows and Columns
673
671
 
674
672
  Press `z` to open the dialog:
675
673
  - Enter number of fixed rows and/or columns to keep top rows/columns visible while scrolling
676
674
 
677
- ### 13.5. Thousand Separator Toggle
675
+ ### 14.5. Thousand Separator Toggle
678
676
 
679
677
  Press `,` to toggle thousand separator formatting for numeric data:
680
678
  - Applies to **integer** and **float** columns
@@ -684,14 +682,14 @@ Press `,` to toggle thousand separator formatting for numeric data:
684
682
  - Display-only: does not modify underlying data in the dataframe
685
683
  - State persists during the session
686
684
 
687
- ### 14. Save File
685
+ ### 15. Save File
688
686
 
689
687
  Press `Ctrl+S` to save:
690
688
  - Save filtered, edited, or sorted data back to file
691
689
  - Choose filename in modal dialog
692
690
  - Confirm if file already exists
693
691
 
694
- ### 15. Undo/Redo/Reset
692
+ ### 16. Undo/Redo/Reset
695
693
 
696
694
  **Undo** (`u`):
697
695
  - Reverts last action with full state restoration
@@ -709,7 +707,7 @@ Press `Ctrl+S` to save:
709
707
  - Clears all edits, deletions, selections, filters, and sorts
710
708
  - Useful for starting fresh without reloading the file
711
709
 
712
- ### 16. Column Type Conversion
710
+ ### 17. Column Type Conversion
713
711
 
714
712
  Press the type conversion keys to instantly cast the current column to a different data type:
715
713
 
@@ -726,14 +724,14 @@ Press the type conversion keys to instantly cast the current column to a differe
726
724
 
727
725
  **Note**: Type conversion attempts to preserve data where possible. Conversions may lose data (e.g., float to int rounding).
728
726
 
729
- ### 17. Cursor Type Cycling
727
+ ### 18. Cursor Type Cycling
730
728
 
731
729
  Press `K` to cycle through selection modes:
732
730
  1. **Cell mode**: Highlight individual cell (and its row/column headers)
733
731
  2. **Row mode**: Highlight entire row
734
732
  3. **Column mode**: Highlight entire column
735
733
 
736
- ### 18. SQL Interface
734
+ ### 19. SQL Interface
737
735
 
738
736
  The SQL interface provides two modes for querying your dataframe:
739
737
 
@@ -767,7 +765,7 @@ FROM self
767
765
  WHERE (age > 25 AND salary > 50000) OR department = 'Management'
768
766
  ```
769
767
 
770
- ### 19. Clipboard Operations
768
+ ### 20. Clipboard Operations
771
769
 
772
770
  Copies value to system clipboard with `pbcopy` on macOS and `xclip` on Linux
773
771
  **Note** May require a X server to work
@@ -777,7 +775,7 @@ Copies value to system clipboard with `pbcopy` on macOS and `xclip` on Linux
777
775
  - Press `Ctrl+R` to copy row values (delimited by tab)
778
776
  - Hold `Shift` to select with mouse
779
777
 
780
- ### 20. Link Column Creation
778
+ ### 21. Link Column Creation
781
779
 
782
780
  Press `@` to create a new column containing dynamically generated URLs using template.
783
781
 
@@ -804,7 +802,7 @@ The link template supports multiple placeholder types for maximum flexibility:
804
802
  - Use full undo (`u`) if template produces unexpected URLs
805
803
  - For complex multi-column URLs, use column names (`$name`) for clarity over positions (`$1`)
806
804
 
807
- ### 21. Tab Management
805
+ ### 22. Tab Management
808
806
 
809
807
  Manage multiple files and dataframes simultaneously with tabs.
810
808
 
@@ -816,17 +814,14 @@ Manage multiple files and dataframes simultaneously with tabs.
816
814
  - **`B`** - Toggle tab bar visibility
817
815
  - **`Double-click tab`** - Rename the tab
818
816
  - **`Ctrl+D`** - Duplicate current tab (creates a copy with same data and state)
819
- - **`Ctrl+S`** - Save current tab to file or all tabs in a single Excel file
817
+ - **`Ctrl+T`** - Save current tab to file
818
+ - **`Ctrl+A`** - Save all tabs in a single Excel file
820
819
  - **`q`** - Close current tab (closes tab, prompts to save if unsaved changes)
821
820
  - **`Q`** - Close all tabs and exit app (prompts to save tabs with unsaved changes)
822
821
  - **`Ctrl+Q`** - Force to quit app regardless of unsaved changes
823
822
 
824
- **Tab Operations:**
825
-
826
- **Saving & Quitting:**
827
-
828
823
  **Tips:**
829
- - Tabs with unsaved changes are highlighted with a bright border
824
+ - Tabs with unsaved changes are indicated with a bright background
830
825
  - Closing or quitting a tab with unsaved changes triggers a save prompt
831
826
 
832
827
  ## Dependencies
@@ -0,0 +1,14 @@
1
+ dataframe_textual/__init__.py,sha256=IFPb8RMUgghw0eRomehkkC684Iny_gs1VkiZMQ5ZpFk,813
2
+ dataframe_textual/__main__.py,sha256=VRH80gWJGLxfURg1GiN3cwWI7O_TQM5PqhqXbUCC1bg,3253
3
+ dataframe_textual/common.py,sha256=g_kMgph84ush-FLgclxYKL9PF9l9hRPMk-AVfZEWGSo,25416
4
+ dataframe_textual/data_frame_help_panel.py,sha256=iEKaur-aH1N_oqHu-vMwEEjfkjQiThK24UO5izsOiW0,3416
5
+ dataframe_textual/data_frame_table.py,sha256=hAbqT3m8BAtanPOS2Wk_1YelynT1-y50oVXyHNY5gmE,128235
6
+ dataframe_textual/data_frame_viewer.py,sha256=3r7vy3zlcqxcqzDafMK22Rcw_3mkdHmNit3avXXgXlI,21246
7
+ dataframe_textual/sql_screen.py,sha256=Pk2ENyDVkOXBLcsEMeXOEMkdzRH_NJ3T1biVUcY8j4Q,7411
8
+ dataframe_textual/table_screen.py,sha256=IhaGAWjzXaLvvc4JLBlAM6_Hl3t7du7vuHQYhrvW_5o,18055
9
+ dataframe_textual/yes_no_screen.py,sha256=qbuhywLIGBL52zQfSGVZQCfsdSmDz9JH6C4YFLrLYKU,26233
10
+ dataframe_textual-1.12.0.dist-info/METADATA,sha256=tNT_ZtTFSKkEJFjXcC9inRozV0mSL8k5s213VEqJmu4,29313
11
+ dataframe_textual-1.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ dataframe_textual-1.12.0.dist-info/entry_points.txt,sha256=R_GoooOxcq6ab4RaHiVoZ4zrZJ-phMcGmlL2rwqncW8,107
13
+ dataframe_textual-1.12.0.dist-info/licenses/LICENSE,sha256=AVTg0gk1X-LHI-nnHlAMDQetrwuDZK4eypgSMDO46Yc,1069
14
+ dataframe_textual-1.12.0.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- dataframe_textual/__init__.py,sha256=IFPb8RMUgghw0eRomehkkC684Iny_gs1VkiZMQ5ZpFk,813
2
- dataframe_textual/__main__.py,sha256=VRH80gWJGLxfURg1GiN3cwWI7O_TQM5PqhqXbUCC1bg,3253
3
- dataframe_textual/common.py,sha256=fh5dkN06VgFMItgFMlB7BMdiBjalc24jdqaGTJI7yCM,25409
4
- dataframe_textual/data_frame_help_panel.py,sha256=iEKaur-aH1N_oqHu-vMwEEjfkjQiThK24UO5izsOiW0,3416
5
- dataframe_textual/data_frame_table.py,sha256=GfjknW0xzjEyz6syIW_BvCLBjGdEZpn1jW87PefBlOo,127408
6
- dataframe_textual/data_frame_viewer.py,sha256=WI6e6AujRQkfCk2yerIRhuiTwtn86y1yWg3WesqdmAs,21315
7
- dataframe_textual/sql_screen.py,sha256=9s9V-pcyYvXoaqsW_85hs-JSsllzayqhENC6ETGq7Xw,7464
8
- dataframe_textual/table_screen.py,sha256=t2eNYS4a-G95qxRU9CFSM8kFjm-STIzkcP_o998ilqY,18135
9
- dataframe_textual/yes_no_screen.py,sha256=HF2Z1WgOEof7NdA_u0s3pCxP26n69Kr6sQWwQvjK-YE,26247
10
- dataframe_textual-1.9.0.dist-info/METADATA,sha256=bE00p7b3HACIwJzqeHRt28F99qMyruWKNEaxzm8wGVk,30380
11
- dataframe_textual-1.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- dataframe_textual-1.9.0.dist-info/entry_points.txt,sha256=R_GoooOxcq6ab4RaHiVoZ4zrZJ-phMcGmlL2rwqncW8,107
13
- dataframe_textual-1.9.0.dist-info/licenses/LICENSE,sha256=AVTg0gk1X-LHI-nnHlAMDQetrwuDZK4eypgSMDO46Yc,1069
14
- dataframe_textual-1.9.0.dist-info/RECORD,,