dataframe-textual 1.16.2__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataframe-textual
3
- Version: 1.16.2
3
+ Version: 2.2.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
@@ -247,8 +247,8 @@ zcat compressed_data.csv.gz | dv -f csv
247
247
  | `Q` | Close all tabs and app (prompts to save unsaved changes) |
248
248
  | `Ctrl+Q` | Force to quit app (regardless of unsaved changes) |
249
249
  | `Ctrl+T` | Save current tab to file |
250
+ | `Ctrl+A` | Save all tabs to a Excel file |
250
251
  | `w` | Save current tab to file (overwrite without prompt) |
251
- | `Ctrl+A` | Save all tabs to file |
252
252
  | `W` | Save all tabs to file (overwrite without prompt) |
253
253
  | `Ctrl+D` | Duplicate current tab |
254
254
  | `Ctrl+O` | Open file in a new tab |
@@ -271,7 +271,7 @@ zcat compressed_data.csv.gz | dv -f csv
271
271
  | Key | Action |
272
272
  |-----|--------|
273
273
  | `g` | Jump to first row |
274
- | `G` | Jump to last row (loads all remaining rows) |
274
+ | `G` | Jump to last row |
275
275
  | `↑` / `↓` | Move up/down one row |
276
276
  | `←` / `→` | Move left/right one column |
277
277
  | `Home` / `End` | Jump to first/last column |
@@ -295,9 +295,11 @@ zcat compressed_data.csv.gz | dv -f csv
295
295
  | `F` | Show frequency distribution for current column |
296
296
  | `s` | Show statistics for current column |
297
297
  | `S` | Show statistics for entire dataframe |
298
+ | `m` | Show metadata for row count and column count |
299
+ | `M` | Show metadata for current column |
298
300
  | `K` | Cycle cursor types: cell → row → column → cell |
299
301
  | `~` | Toggle row labels |
300
- | `_` (underscore) | Expand column to full width |
302
+ | `_` (underscore) | Toggle column full width |
301
303
  | `z` | Freeze rows and columns |
302
304
  | `,` | Toggle thousand separator for numeric display |
303
305
  | `h` | Hide current column |
@@ -318,14 +320,14 @@ zcat compressed_data.csv.gz | dv -f csv
318
320
  | `x` | Delete current row |
319
321
  | `X` | Delete current row and all those below |
320
322
  | `Ctrl+X` | Delete current row and all those above |
321
- | `d` | Duplicate current column (appends '_copy' suffix) |
323
+ | `d` | Duplicate current column |
322
324
  | `D` | Duplicate current row |
323
325
 
324
326
  #### Row Selection
325
327
 
326
328
  | Key | Action |
327
329
  |-----|--------|
328
- | `\` | Select rows that matches cursor value in current column |
330
+ | `\` | Select rows wth cell matches or those matching cursor value in current column |
329
331
  | `\|` (pipe) | Select rows by expression |
330
332
  | `{` | Go to previous selected row |
331
333
  | `}` | Go to next selected row |
@@ -349,9 +351,9 @@ zcat compressed_data.csv.gz | dv -f csv
349
351
  #### View & Filter
350
352
  | Key | Action |
351
353
  |-----|--------|
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 |
354
+ | `"` (quote) | Filter selected rows (others removed) |
355
+ | `v` | View selected rows (others hidden) |
356
+ | `V` | View selected by expression (others hidden) |
355
357
 
356
358
  #### SQL Interface
357
359
 
@@ -392,7 +394,7 @@ zcat compressed_data.csv.gz | dv -f csv
392
394
  | `c` | Copy current cell to clipboard |
393
395
  | `Ctrl+C` | Copy column to clipboard |
394
396
  | `Ctrl+R` | Copy row to clipboard (tab-separated) |
395
- | `Ctrl+S` | Save current tab to file |
397
+ | `Ctrl+S` | Save to file |
396
398
 
397
399
  ## Features in Detail
398
400
 
@@ -411,17 +413,17 @@ Press `Enter` on any row to open a modal showing all column values for that row.
411
413
  Useful for examining wide datasets where columns don't fit well on screen.
412
414
 
413
415
  **In the Row Detail Modal**:
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)
416
+ - Press `v` to **view** all rows containing the selected column value (others hidden but preserved)
417
+ - Press `"` to **filter** all rows containing the selected column value (others removed)
418
+ - Press `{` to move to the previous row
419
+ - Press `}` to move to the next row
418
420
  - Press `q` or `Escape` to close the modal
419
421
 
420
422
  ### 3. Row Selection
421
423
 
422
424
  The application provides multiple modes for selecting rows (marks it for filtering or viewing):
423
425
 
424
- - `\` - Select rows that match cursor value in current column (respects data type)
426
+ - `\` - Select rows with cell matches or those matching cursor value in current column (respects data type)
425
427
  - `|` - Opens dialog to select rows with custom expression
426
428
  - `'` - Select/deselect current row
427
429
  - `t` - Flip selections of all rows
@@ -429,7 +431,7 @@ The application provides multiple modes for selecting rows (marks it for filteri
429
431
  - `{` - Go to previous selected row
430
432
  - `}` - Go to next selected row
431
433
 
432
- **Advanced Matching Options**:
434
+ **Advanced Options**:
433
435
 
434
436
  When searching or finding, you can use checkboxes in the dialog to enable:
435
437
  - **Match Nocase**: Ignore case differences
@@ -445,7 +447,7 @@ These options work with plain text searches. Use Polars regex patterns in expres
445
447
  - Use `u` to undo any search or filter
446
448
 
447
449
  ### 4. Find & Replace
448
- **Find Operations** - Find by value/expression and highlight matching cells:
450
+ Find by value/expression and highlight matching cells:
449
451
  - `/` - Find cursor value within current column (respects data type)
450
452
  - `?` - Open dialog to search current column with expression
451
453
  - `;` - Find cursor value across all columns
@@ -469,10 +471,10 @@ When you press `r` or `R`, enter:
469
471
 
470
472
  **Replace Interactive**:
471
473
  - Review each match one at a time (confirm, skip, or cancel)
472
- - Shows progress: `X of Y`
474
+ - Shows progress
473
475
 
474
476
  **Tips:**
475
- - Search are done by string value (i.e. ignoring data type)
477
+ - Search are done by string value (i.e., ignoring data type)
476
478
  - Type `NULL` to replace null/missing values
477
479
  - Use `Match Nocase` for case-insensitive matching
478
480
  - Use `Match Whole` to avoid partial replacements
@@ -480,7 +482,7 @@ When you press `r` or `R`, enter:
480
482
 
481
483
  ### 5. Filter vs. View
482
484
 
483
- Both operations show rows that are selected or contain matching cells, but with fundamentally different effects:
485
+ Both operations show selected rows but with fundamentally different effects:
484
486
 
485
487
  | Operation | Keyboard | Effect | Data Preserved |
486
488
  |-----------|----------|--------|-----------------|
@@ -571,8 +573,8 @@ View quick metadata about your dataframe and columns to understand their structu
571
573
 
572
574
  **Dataframe Metadata** (`m`):
573
575
  - 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
576
+ - **Row** - Total number of rows in the dataframe
577
+ - **Column** - Total number of columns in the dataframe
576
578
 
577
579
  **Column Metadata** (`M`):
578
580
  - Press `M` to open a modal displaying details for all columns:
@@ -591,8 +593,8 @@ Press `F` to see value distributions of the current column. The modal shows:
591
593
 
592
594
  **In the Frequency Table**:
593
595
  - Press `[` and `]` to sort by any column (value, count, or percentage)
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)
596
+ - Press `v` to **view** all rows containing the selected value (others hidden but preserved)
597
+ - Press `"` to **filter** all rows containing the selected value (others removed)
596
598
  - Press `q` or `Escape` to close the frequency table
597
599
 
598
600
  This is useful for:
@@ -751,7 +753,6 @@ SELECT specific columns and apply WHERE conditions without writing full SQL:
751
753
  #### Advanced SQL Interface (`L`)
752
754
  Execute complete SQL queries for advanced data manipulation:
753
755
  - Write full SQL queries with standard [SQL syntax](https://docs.pola.rs/api/python/stable/reference/sql/index.html)
754
- - Support for JOINs, GROUP BY, aggregations, and more
755
756
  - Access to all SQL capabilities for complex transformations
756
757
  - Always use `self` as the table name
757
758
  - Syntax highlighted
@@ -773,7 +774,7 @@ WHERE `product id` = 7
773
774
 
774
775
  Copies value to system clipboard with `pbcopy` on macOS and `xclip` on Linux.
775
776
 
776
- **Note** May require a X server to work.
777
+ **Note**: may require a X server to work.
777
778
 
778
779
  - Press `c` to copy cursor value
779
780
  - Press `Ctrl+C` to copy column values
@@ -815,8 +816,8 @@ Manage multiple files and dataframes simultaneously with tabs.
815
816
  - **`Double-click`** - Rename the tab
816
817
  - **`Ctrl+D`** - Duplicate current tab (creates a copy with same data and state)
817
818
  - **`Ctrl+T`** - Save current tab to file
818
- - **`w`** - Save current tab to file (overwrite without prompt)
819
819
  - **`Ctrl+A`** - Save all tabs in a single Excel file
820
+ - **`w`** - Save current tab to file (overwrite without prompt)
820
821
  - **`W`** - Save all tabs to file (overwrite without prompt)
821
822
  - **`q`** - Close current tab (closes tab, prompts to save if unsaved changes)
822
823
  - **`Q`** - Close all tabs and exit app (prompts to save tabs with unsaved changes)
@@ -208,8 +208,8 @@ zcat compressed_data.csv.gz | dv -f csv
208
208
  | `Q` | Close all tabs and app (prompts to save unsaved changes) |
209
209
  | `Ctrl+Q` | Force to quit app (regardless of unsaved changes) |
210
210
  | `Ctrl+T` | Save current tab to file |
211
+ | `Ctrl+A` | Save all tabs to a Excel file |
211
212
  | `w` | Save current tab to file (overwrite without prompt) |
212
- | `Ctrl+A` | Save all tabs to file |
213
213
  | `W` | Save all tabs to file (overwrite without prompt) |
214
214
  | `Ctrl+D` | Duplicate current tab |
215
215
  | `Ctrl+O` | Open file in a new tab |
@@ -232,7 +232,7 @@ zcat compressed_data.csv.gz | dv -f csv
232
232
  | Key | Action |
233
233
  |-----|--------|
234
234
  | `g` | Jump to first row |
235
- | `G` | Jump to last row (loads all remaining rows) |
235
+ | `G` | Jump to last row |
236
236
  | `↑` / `↓` | Move up/down one row |
237
237
  | `←` / `→` | Move left/right one column |
238
238
  | `Home` / `End` | Jump to first/last column |
@@ -256,9 +256,11 @@ zcat compressed_data.csv.gz | dv -f csv
256
256
  | `F` | Show frequency distribution for current column |
257
257
  | `s` | Show statistics for current column |
258
258
  | `S` | Show statistics for entire dataframe |
259
+ | `m` | Show metadata for row count and column count |
260
+ | `M` | Show metadata for current column |
259
261
  | `K` | Cycle cursor types: cell → row → column → cell |
260
262
  | `~` | Toggle row labels |
261
- | `_` (underscore) | Expand column to full width |
263
+ | `_` (underscore) | Toggle column full width |
262
264
  | `z` | Freeze rows and columns |
263
265
  | `,` | Toggle thousand separator for numeric display |
264
266
  | `h` | Hide current column |
@@ -279,14 +281,14 @@ zcat compressed_data.csv.gz | dv -f csv
279
281
  | `x` | Delete current row |
280
282
  | `X` | Delete current row and all those below |
281
283
  | `Ctrl+X` | Delete current row and all those above |
282
- | `d` | Duplicate current column (appends '_copy' suffix) |
284
+ | `d` | Duplicate current column |
283
285
  | `D` | Duplicate current row |
284
286
 
285
287
  #### Row Selection
286
288
 
287
289
  | Key | Action |
288
290
  |-----|--------|
289
- | `\` | Select rows that matches cursor value in current column |
291
+ | `\` | Select rows wth cell matches or those matching cursor value in current column |
290
292
  | `\|` (pipe) | Select rows by expression |
291
293
  | `{` | Go to previous selected row |
292
294
  | `}` | Go to next selected row |
@@ -310,9 +312,9 @@ zcat compressed_data.csv.gz | dv -f csv
310
312
  #### View & Filter
311
313
  | Key | Action |
312
314
  |-----|--------|
313
- | `"` (quote) | Filter to rows that are selected or contain matching cells (and remove others) |
314
- | `v` | View rows (and hide others) by row selections and cell matches or cursor value |
315
- | `V` | View rows (and hide others) by expression |
315
+ | `"` (quote) | Filter selected rows (others removed) |
316
+ | `v` | View selected rows (others hidden) |
317
+ | `V` | View selected by expression (others hidden) |
316
318
 
317
319
  #### SQL Interface
318
320
 
@@ -353,7 +355,7 @@ zcat compressed_data.csv.gz | dv -f csv
353
355
  | `c` | Copy current cell to clipboard |
354
356
  | `Ctrl+C` | Copy column to clipboard |
355
357
  | `Ctrl+R` | Copy row to clipboard (tab-separated) |
356
- | `Ctrl+S` | Save current tab to file |
358
+ | `Ctrl+S` | Save to file |
357
359
 
358
360
  ## Features in Detail
359
361
 
@@ -372,17 +374,17 @@ Press `Enter` on any row to open a modal showing all column values for that row.
372
374
  Useful for examining wide datasets where columns don't fit well on screen.
373
375
 
374
376
  **In the Row Detail Modal**:
375
- - Press `v` to **view** all rows containing the selected column value (and hide others)
376
- - Press `"` to **filter** all rows containing the selected column value (and remove others)
377
- - Press `{` to move to the **previous row** (respects hidden rows)
378
- - Press `}` to move to the **next row** (respects hidden rows)
377
+ - Press `v` to **view** all rows containing the selected column value (others hidden but preserved)
378
+ - Press `"` to **filter** all rows containing the selected column value (others removed)
379
+ - Press `{` to move to the previous row
380
+ - Press `}` to move to the next row
379
381
  - Press `q` or `Escape` to close the modal
380
382
 
381
383
  ### 3. Row Selection
382
384
 
383
385
  The application provides multiple modes for selecting rows (marks it for filtering or viewing):
384
386
 
385
- - `\` - Select rows that match cursor value in current column (respects data type)
387
+ - `\` - Select rows with cell matches or those matching cursor value in current column (respects data type)
386
388
  - `|` - Opens dialog to select rows with custom expression
387
389
  - `'` - Select/deselect current row
388
390
  - `t` - Flip selections of all rows
@@ -390,7 +392,7 @@ The application provides multiple modes for selecting rows (marks it for filteri
390
392
  - `{` - Go to previous selected row
391
393
  - `}` - Go to next selected row
392
394
 
393
- **Advanced Matching Options**:
395
+ **Advanced Options**:
394
396
 
395
397
  When searching or finding, you can use checkboxes in the dialog to enable:
396
398
  - **Match Nocase**: Ignore case differences
@@ -406,7 +408,7 @@ These options work with plain text searches. Use Polars regex patterns in expres
406
408
  - Use `u` to undo any search or filter
407
409
 
408
410
  ### 4. Find & Replace
409
- **Find Operations** - Find by value/expression and highlight matching cells:
411
+ Find by value/expression and highlight matching cells:
410
412
  - `/` - Find cursor value within current column (respects data type)
411
413
  - `?` - Open dialog to search current column with expression
412
414
  - `;` - Find cursor value across all columns
@@ -430,10 +432,10 @@ When you press `r` or `R`, enter:
430
432
 
431
433
  **Replace Interactive**:
432
434
  - Review each match one at a time (confirm, skip, or cancel)
433
- - Shows progress: `X of Y`
435
+ - Shows progress
434
436
 
435
437
  **Tips:**
436
- - Search are done by string value (i.e. ignoring data type)
438
+ - Search are done by string value (i.e., ignoring data type)
437
439
  - Type `NULL` to replace null/missing values
438
440
  - Use `Match Nocase` for case-insensitive matching
439
441
  - Use `Match Whole` to avoid partial replacements
@@ -441,7 +443,7 @@ When you press `r` or `R`, enter:
441
443
 
442
444
  ### 5. Filter vs. View
443
445
 
444
- Both operations show rows that are selected or contain matching cells, but with fundamentally different effects:
446
+ Both operations show selected rows but with fundamentally different effects:
445
447
 
446
448
  | Operation | Keyboard | Effect | Data Preserved |
447
449
  |-----------|----------|--------|-----------------|
@@ -532,8 +534,8 @@ View quick metadata about your dataframe and columns to understand their structu
532
534
 
533
535
  **Dataframe Metadata** (`m`):
534
536
  - Press `m` to open a modal displaying:
535
- - **Rows** - Total number of rows in the dataframe
536
- - **Columns** - Total number of columns in the dataframe
537
+ - **Row** - Total number of rows in the dataframe
538
+ - **Column** - Total number of columns in the dataframe
537
539
 
538
540
  **Column Metadata** (`M`):
539
541
  - Press `M` to open a modal displaying details for all columns:
@@ -552,8 +554,8 @@ Press `F` to see value distributions of the current column. The modal shows:
552
554
 
553
555
  **In the Frequency Table**:
554
556
  - Press `[` and `]` to sort by any column (value, count, or percentage)
555
- - Press `v` to **filter** all rows with the selected value (others hidden but preserved)
556
- - Press `"` to **exclude** all rows containing the selected value (others removed)
557
+ - Press `v` to **view** all rows containing the selected value (others hidden but preserved)
558
+ - Press `"` to **filter** all rows containing the selected value (others removed)
557
559
  - Press `q` or `Escape` to close the frequency table
558
560
 
559
561
  This is useful for:
@@ -712,7 +714,6 @@ SELECT specific columns and apply WHERE conditions without writing full SQL:
712
714
  #### Advanced SQL Interface (`L`)
713
715
  Execute complete SQL queries for advanced data manipulation:
714
716
  - Write full SQL queries with standard [SQL syntax](https://docs.pola.rs/api/python/stable/reference/sql/index.html)
715
- - Support for JOINs, GROUP BY, aggregations, and more
716
717
  - Access to all SQL capabilities for complex transformations
717
718
  - Always use `self` as the table name
718
719
  - Syntax highlighted
@@ -734,7 +735,7 @@ WHERE `product id` = 7
734
735
 
735
736
  Copies value to system clipboard with `pbcopy` on macOS and `xclip` on Linux.
736
737
 
737
- **Note** May require a X server to work.
738
+ **Note**: may require a X server to work.
738
739
 
739
740
  - Press `c` to copy cursor value
740
741
  - Press `Ctrl+C` to copy column values
@@ -776,8 +777,8 @@ Manage multiple files and dataframes simultaneously with tabs.
776
777
  - **`Double-click`** - Rename the tab
777
778
  - **`Ctrl+D`** - Duplicate current tab (creates a copy with same data and state)
778
779
  - **`Ctrl+T`** - Save current tab to file
779
- - **`w`** - Save current tab to file (overwrite without prompt)
780
780
  - **`Ctrl+A`** - Save all tabs in a single Excel file
781
+ - **`w`** - Save current tab to file (overwrite without prompt)
781
782
  - **`W`** - Save all tabs to file (overwrite without prompt)
782
783
  - **`q`** - Close current tab (closes tab, prompts to save if unsaved changes)
783
784
  - **`Q`** - Close all tabs and exit app (prompts to save tabs with unsaved changes)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dataframe-textual"
7
- version = "1.16.2"
7
+ version = "2.2.0"
8
8
  description = "Interactive terminal viewer/editor for tabular data"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,15 +1,32 @@
1
1
  """DataFrame Viewer - Interactive CSV/Excel viewer for the terminal."""
2
2
 
3
+ from importlib.metadata import version
4
+
5
+ __version__ = version("dataframe-textual")
6
+
3
7
  from .data_frame_help_panel import DataFrameHelpPanel
4
8
  from .data_frame_table import DataFrameTable, History
5
9
  from .data_frame_viewer import DataFrameViewer
6
- from .table_screen import FrequencyScreen, RowDetailScreen, TableScreen
10
+ from .table_screen import (
11
+ FrequencyScreen,
12
+ MetaColumnScreen,
13
+ MetaShape,
14
+ RowDetailScreen,
15
+ StatisticsScreen,
16
+ TableScreen,
17
+ )
7
18
  from .yes_no_screen import (
19
+ AddColumnScreen,
20
+ AddLinkScreen,
8
21
  ConfirmScreen,
9
22
  EditCellScreen,
23
+ EditColumnScreen,
10
24
  FilterScreen,
25
+ FindReplaceScreen,
11
26
  FreezeScreen,
12
27
  OpenFileScreen,
28
+ RenameColumnScreen,
29
+ RenameTabScreen,
13
30
  SaveFileScreen,
14
31
  SearchScreen,
15
32
  YesNoScreen,
@@ -23,6 +40,9 @@ __all__ = [
23
40
  "TableScreen",
24
41
  "RowDetailScreen",
25
42
  "FrequencyScreen",
43
+ "StatisticsScreen",
44
+ "MetaShape",
45
+ "MetaColumnScreen",
26
46
  "YesNoScreen",
27
47
  "SaveFileScreen",
28
48
  "ConfirmScreen",
@@ -31,4 +51,10 @@ __all__ = [
31
51
  "FilterScreen",
32
52
  "FreezeScreen",
33
53
  "OpenFileScreen",
54
+ "RenameColumnScreen",
55
+ "EditColumnScreen",
56
+ "AddColumnScreen",
57
+ "AddLinkScreen",
58
+ "FindReplaceScreen",
59
+ "RenameTabScreen",
34
60
  ]
@@ -4,6 +4,7 @@ import argparse
4
4
  import sys
5
5
  from pathlib import Path
6
6
 
7
+ from . import __version__
7
8
  from .common import SUPPORTED_FORMATS, load_dataframe
8
9
  from .data_frame_viewer import DataFrameViewer
9
10
 
@@ -24,6 +25,12 @@ def cli() -> argparse.Namespace:
24
25
  " cat data.csv | %(prog)s --format csv\n",
25
26
  )
26
27
  parser.add_argument("files", nargs="*", help="Files to view (or read from stdin)")
28
+ parser.add_argument(
29
+ "-V",
30
+ "--version",
31
+ action="version",
32
+ version=f"%(prog)s {__version__}",
33
+ )
27
34
  parser.add_argument(
28
35
  "-f",
29
36
  "--format",
@@ -39,6 +46,9 @@ def cli() -> argparse.Namespace:
39
46
  parser.add_argument(
40
47
  "-I", "--no-inference", action="store_true", help="Do not infer data types when reading CSV/TSV"
41
48
  )
49
+ parser.add_argument(
50
+ "-t", "--truncate-ragged-lines", action="store_true", help="Truncate ragged lines when reading CSV/TSV"
51
+ )
42
52
  parser.add_argument("-E", "--ignore-errors", action="store_true", help="Ignore errors when reading CSV/TSV")
43
53
  parser.add_argument(
44
54
  "-c", "--comment-prefix", nargs="?", const="#", help="Comment lines are skipped when reading CSV/TSV"
@@ -87,6 +97,7 @@ def main() -> None:
87
97
  skip_rows_after_header=args.skip_rows_after_header,
88
98
  null_values=args.null,
89
99
  ignore_errors=args.ignore_errors,
100
+ truncate_ragged_lines=args.truncate_ragged_lines,
90
101
  )
91
102
  app = DataFrameViewer(*sources)
92
103
  app.run()
@@ -152,8 +152,8 @@ SUBSCRIPT_DIGITS = {
152
152
  # Cursor types ("none" removed)
153
153
  CURSOR_TYPES = ["row", "column", "cell"]
154
154
 
155
- # For row index column
156
- RIDX = "^_ridx_^"
155
+ # Row index mapping between filtered and original dataframe
156
+ RID = "^_RID_^"
157
157
 
158
158
 
159
159
  @dataclass
@@ -224,7 +224,7 @@ def format_row(vals, dtypes, styles: list[str | None] | None = None, thousand_se
224
224
  return formatted_row
225
225
 
226
226
 
227
- def rindex(lst: list, value) -> int:
227
+ def rindex(lst: list, value, pos: int | None = None) -> int:
228
228
  """Return the last index of value in a list. Return -1 if not found.
229
229
 
230
230
  Searches through the list in reverse order to find the last occurrence
@@ -237,9 +237,12 @@ def rindex(lst: list, value) -> int:
237
237
  Returns:
238
238
  The index (0-based) of the last occurrence, or -1 if not found.
239
239
  """
240
+ n = len(lst)
240
241
  for i, item in enumerate(reversed(lst)):
242
+ if pos is not None and (n - 1 - i) > pos:
243
+ continue
241
244
  if item == value:
242
- return len(lst) - 1 - i
245
+ return n - 1 - i
243
246
  return -1
244
247
 
245
248
 
@@ -272,7 +275,7 @@ def parse_placeholders(template: str, columns: list[str], current_cidx: int) ->
272
275
 
273
276
  Supports multiple placeholder types:
274
277
  - `$_` - Current column (based on current_cidx parameter)
275
- - `$#` - Row index (1-based, requires '^__ridx__^' column to be present)
278
+ - `$#` - Row index (1-based)
276
279
  - `$1`, `$2`, etc. - Column index (1-based)
277
280
  - `$name` - Column name (e.g., `$product_id`)
278
281
  - `` $`col name` `` - Column name with spaces (e.g., `` $`product id` ``)
@@ -323,7 +326,7 @@ def parse_placeholders(template: str, columns: list[str], current_cidx: int) ->
323
326
  parts.append(pl.col(col_name))
324
327
  elif placeholder == "#":
325
328
  # $# refers to row index (1-based)
326
- parts.append((pl.col(RIDX)))
329
+ parts.append(pl.col(RID))
327
330
  elif placeholder.isdigit():
328
331
  # $1, $2, etc. refer to columns by 1-based position index
329
332
  col_idx = int(placeholder) - 1 # Convert to 0-based
@@ -364,14 +367,14 @@ def parse_polars_expression(expression: str, columns: list[str], current_cidx: i
364
367
 
365
368
  Replaces column references with Polars col() expressions:
366
369
  - $_ - Current selected column
367
- - $# - Row index (1-based, requires '^__ridx__^' column to be present)
370
+ - $# - Row index (1-based)
368
371
  - $1, $2, etc. - Column index (1-based)
369
372
  - $col_name - Column name (valid identifier starting with _ or letter)
370
373
  - $`col name` - Column name with spaces (backtick quoted)
371
374
 
372
375
  Examples:
373
376
  - "$_ > 50" -> "pl.col('current_col') > 50"
374
- - "$# > 10" -> "pl.col('^__ridx__^') > 10"
377
+ - "$# > 10" -> "pl.col('^_RID_^') > 10"
375
378
  - "$1 > 50" -> "pl.col('col0') > 50"
376
379
  - "$name == 'Alex'" -> "pl.col('name') == 'Alex'"
377
380
  - "$age < $salary" -> "pl.col('age') < pl.col('salary')"
@@ -404,7 +407,10 @@ def parse_polars_expression(expression: str, columns: list[str], current_cidx: i
404
407
  if isinstance(part, pl.Expr):
405
408
  col = part.meta.output_name()
406
409
 
407
- result.append(f"pl.col('{col}')")
410
+ if col == RID: # Convert to 1-based
411
+ result.append(f"(pl.col('{col}') + 1)")
412
+ else:
413
+ result.append(f"pl.col('{col}')")
408
414
  else:
409
415
  result.append(part)
410
416
 
@@ -478,6 +484,7 @@ def load_dataframe(
478
484
  skip_rows_after_header: int = 0,
479
485
  null_values: list[str] | None = None,
480
486
  ignore_errors: bool = False,
487
+ truncate_ragged_lines: bool = False,
481
488
  ) -> list[Source]:
482
489
  """Load DataFrames from file specifications.
483
490
 
@@ -542,6 +549,7 @@ def load_dataframe(
542
549
  skip_rows_after_header=skip_rows_after_header,
543
550
  null_values=null_values,
544
551
  ignore_errors=ignore_errors,
552
+ truncate_ragged_lines=truncate_ragged_lines,
545
553
  )
546
554
  )
547
555
 
@@ -618,6 +626,7 @@ def load_file(
618
626
  schema_overrides: dict[str, pl.DataType] | None = None,
619
627
  null_values: list[str] | None = None,
620
628
  ignore_errors: bool = False,
629
+ truncate_ragged_lines: bool = False,
621
630
  ) -> list[Source]:
622
631
  """Load a single file.
623
632
 
@@ -672,6 +681,7 @@ def load_file(
672
681
  schema_overrides=schema_overrides,
673
682
  null_values=null_values,
674
683
  ignore_errors=ignore_errors,
684
+ truncate_ragged_lines=truncate_ragged_lines,
675
685
  )
676
686
  data.append(Source(lf, filename, filepath.stem))
677
687
  elif file_format in ("xlsx", "xls", "excel"):
@@ -74,9 +74,6 @@ class DataFrameHelpPanel(Widget):
74
74
 
75
75
  Initializes the help panel by setting up a watcher for focused widget changes
76
76
  to dynamically update help text based on which widget has focus.
77
-
78
- Returns:
79
- None
80
77
  """
81
78
 
82
79
  # def update_help(focused_widget: Widget | None):