A TUI paging application with enhanced support for tabular data and real-time streaming
Project description
Nothing-less (nless)
Nless is a TUI paging application (based on the awesome Textual library) with vi-like keybindings. Nless has enhanced functionality for parsing tabular data:
- inferring file delimiters
- delimiter swapping on the fly
- regex-based parsing of raw logs into tabular data using Python's regex engine
- filtering
- sorting
- searching
- real-time event parsing.
Getting started
Dependencies
- python>=3.13
OR - brew
Installation
pip install nothing-less
OR
brew install mpryor/tap/nless
Usage
- pipe the output of a command to nless to parse the output
$COMMAND | nless - read a file with nless
nless $FILE_NAME - redirect a file into nless
nless < $FILE_NAME - Once output is loaded, press
?to view the keybindings
Why?
As a kubernetes engineer, I frequently need to interact with streaming tabular data. k get pods -w, k get events -w, etc. I want a TUI tool to quickly dissect and analyze this data - and none of the existing alternatives had exactly what I wanted:
- streaming support
- delimiter inference - I don't want to do a bunch of work to tell the program what type of data it's viewing, I want it to infer it if possible
- vi-like keybindings So I decided to build my own tool, integrating some of my favorite features that I've seen in other similar tools.
Goals
This project is not meant to be a replacement/competitor for any of the tools mentioned in the alternatives section at the end. Instead, it's meant to bring its own unique set of features to compliment your workflow.
- UX:
- vi-like keybindings, familiar to any VIM user
- minimize the number of keypresses to analyze a dataset
- Kubernetes support:
- support for K8s usecases out of the box - such as parsing data streams from kubectl
- Tabular data toolkit:
- broad support for a variety of use-cases analyzing,filtering,sorting, and searching tabular data
- converting data streams into tabular data, such as JSON log parsing
Demos
Basic functionality
The below demo shows basic functionality:
- starting with a search
/ - applying that search
& - filtering the selected column by the value within the selected cell
F - swapping the delimiter
D(rawand,)
Streaming functionality
The below demo showcases some of nless's features for handling streaming input, and interacting with unknown delimitation:
- The nless view stays up-to-date as new log lines arrive on stdin (allows pipeline commands, or redirecting a file into nless)
- Showcases using a custom (Python engine) regex, example -
{(?P<severity>.*)}\((?P<user>.*)\) - (?P<message>.*)- to parse raw logs into tabular fields. - Sorts, filters, and searches on those fields.
- Flips the delimiter back to raw, sorts, searches, and filters on the raw logs
Features & Functionality
Buffers:
- All mutating actions will apply the action by replicating the current "buffer". This allows you to jump up and down the stack to see how you've analyzed your data.
[1-9]- will select the buffer at the index corresponding to the input numberL- selects the next bufferH- select the previous bufferq- closes the current active buffer, or the program if all buffers are closedN- creates a new buffer from the original data
Navigation:
h- move cursor leftl- move cursor rightj- move cursor downk- move cursor up0- jump to first column$- jump to final columng- jump to first rowG- jump to final roww- move cursor rightb/B- move cursor leftctrl+u- page upctrl+d- page downc- to select a column to jump the cursor to
Column visibility
C- will prompt for a regex filter to selectively display columns, orallto see all columns. TIP: use a non-existing column (none, for example) to only see the current pivots/count>- will move the current column one to the right<- will move the current column one to the left
Pivoting
U- will mark the selected column as part of a composite key to group records by, adding acountcolumn pinned to the leftenter- pressing enter while the cursor is over one of the composite key columns will "dive in" to the data set behind the pivot - applying the composite key as a filter in a new buffer
Filtering:
f- will filter the current column and prompt for a filterF- will filter the current column by the highlighted cell|- will filter ALL columns and prompt for a filter&- applies the current search as a filter across all columns
Searching:
/- will prompt for a search value and jump to the first match*- will search all columns for the current highlighted cell valuen- jump to the next matchp- jump to previous match
Output:
W- will prompt for a file to write the current buffer to.-can be used to write tostdout, allowing you to usenlessinside of a command chaincat $MY_FILE.txt | nless | grep -i activefor example.y- copies the contents of the currently highlighted cell to the clipboard
Shell Commands:
!- run a shell command and pipe its output into a new buffer for analysis
Tail Mode:
t- toggle tail mode, which keeps the cursor at the bottom as new data arrives (useful for streaming input)
Unparsed Logs:
~- view logs that did not match the current delimiter, useful for spotting malformed or unexpected lines
Help:
?- show the help screen with all keybindings
Sorting:
s- toggles ascending/descending sort on the current column
json:
- in addition to the
jsondelimiter that can be set per session or per column, there's also support for json actions: J- will prompt you to select a json field, under the current cell, to add as a column for further filtering/sorting/etc
Delimiter/file parsing:
-
By default,
nlesswill attempt to infer a file delimiter from the first few rows sent through stdin. It uses common delimiters to start -,,,|,\t, etc. -
D- you can useDto explicitly swap the delimiter on the fly. Just type in one of the common delimiters above, and the rows will be re-parsed into a tabular format. -
D- alternatively, you can pass in a regex with named capture groups. Those named groups will become the tabular columns, and each row will be parsed and split across those groups. Example{(?P<severity>.*)}\((?P<user>.*)\) - (?P<message>.*) -
D- additionally you can just pass the wordrawto see the raw lines behind the data. You can still sort, filter, and search the raw lines. -
D- pass the wordjsonto parse the first set of keys from each JSON line (or read the whole buffer in as a JSON object/list) -
D- last, you can pass a delimiter value of(two spaces). This will parse text that has been delimited utilizing multiple spaces, while preserving values that have a single space. This is most commonly useful for parsing kubernetes output (kubectl get pods -w), for example. -
d- transforms a column into more columns using a columnar delimiter. Supports three modes:json— extracts keys from JSON objects in the selected column into new columns- A regex with named capture groups — each group becomes a new column (e.g.
(?P<host>[^:]+):(?P<port>\d+)) - Any string delimiter — splits the column's values by the given string (e.g.
:,-, etc.)
Contributing
Contributions are welcome! Please open an issue or a pull request - check out the contributing guidelines for more information.
Alternatives
Shout-outs to all of the below wonderful tools! If my tool doesn't have what you need, they likely will:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nothing_less-1.0.0.tar.gz.
File metadata
- Download URL: nothing_less-1.0.0.tar.gz
- Upload date:
- Size: 39.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d9e227e9fae04e429fcfcda203052f4cc036e89f90dc126ccd448efca60db69
|
|
| MD5 |
4c184351773d8675fe79bb1b603f67b5
|
|
| BLAKE2b-256 |
f22be3c20c5abcca161204f0d182beb5e3c30904d3cc2d77a9fc7df00451566e
|
File details
Details for the file nothing_less-1.0.0-py3-none-any.whl.
File metadata
- Download URL: nothing_less-1.0.0-py3-none-any.whl
- Upload date:
- Size: 41.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7e4b835a6464d46e1002d870d30d2f1c64089d2960373caa340d4362770fbec
|
|
| MD5 |
3e6ff5b1a8dc715aa1d15e2d9abfa8fd
|
|
| BLAKE2b-256 |
1450b9d096242b9e1437d4394364bd87443479bd5d7360f2b2a8446e1f46043e
|