{"id":13468975,"url":"https://github.com/alexhallam/tv","last_synced_at":"2025-05-13T17:13:08.219Z","repository":{"id":37487249,"uuid":"363146690","full_name":"alexhallam/tv","owner":"alexhallam","description":"📺(tv) Tidy Viewer is a cross-platform CLI csv pretty printer that uses column styling to maximize viewer enjoyment.","archived":false,"fork":false,"pushed_at":"2025-01-05T23:45:33.000Z","size":34827,"stargazers_count":2093,"open_issues_count":15,"forks_count":40,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-24T02:01:45.642Z","etag":null,"topics":["cli","column","command-line","command-line-tool","csv","csv-cat","csv-column","csv-pretty-print","csv-viewer","csv-visualization","data-science","dataframe","datatable","pretty-print","pretty-printer","rust","tabular-data","terminal","tibble"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexhallam.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-30T13:18:16.000Z","updated_at":"2025-04-22T16:20:19.000Z","dependencies_parsed_at":"2024-03-29T13:28:05.575Z","dependency_job_id":"fd8a364c-6375-44d5-8745-beca4346e126","html_url":"https://github.com/alexhallam/tv","commit_stats":{"total_commits":229,"total_committers":21,"mean_commits":"10.904761904761905","dds":0.1353711790393013,"last_synced_commit":"204a2320de90c36141514526e0afb11b4c11540b"},"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexhallam%2Ftv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexhallam%2Ftv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexhallam%2Ftv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexhallam%2Ftv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexhallam","download_url":"https://codeload.github.com/alexhallam/tv/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253990483,"owners_count":21995775,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","column","command-line","command-line-tool","csv","csv-cat","csv-column","csv-pretty-print","csv-viewer","csv-visualization","data-science","dataframe","datatable","pretty-print","pretty-printer","rust","tabular-data","terminal","tibble"],"created_at":"2024-07-31T15:01:23.198Z","updated_at":"2025-05-13T17:13:03.191Z","avatar_url":"https://github.com/alexhallam.png","language":"Rust","funding_links":[],"categories":["Rust","cli","\u003ca name=\"data-management-tabular\"\u003e\u003c/a\u003eData management - Tabular data","Other"],"sub_categories":[],"readme":"[![Rust](https://github.com/alexhallam/tv/actions/workflows/rust.yml/badge.svg)](https://github.com/alexhallam/tv/actions/workflows/rust.yml)\n[![Crate](https://img.shields.io/crates/v/tidy-viewer.svg)](https://crates.io/crates/tidy-viewer)\n![Crates.io](https://img.shields.io/crates/d/tidy-viewer?label=creates.io%20downloads)\n![GitHub all releases](https://img.shields.io/github/downloads/alexhallam/tv/total?label=github%20release%20downloads)\n[![tidy-viewer](https://snapcraft.io/tidy-viewer/badge.svg)](https://snapcraft.io/tidy-viewer)\n\n\u003ch1 align=\"center\"\u003eTidy Viewer (tv)\u003c/h1\u003e\n\u003cp align=\"center\"\u003eTidy Viewer (tv) is a cross-platform csv pretty printer that uses column styling to maximize viewer enjoyment.\u003c/p\u003e\n\n![logo](img/TVBlue.png)\n\n# Pretty Printing\n\n![example](img/starwars.png)\n\n# Contents\n* [Features](#features)\n* [Installation](#installation)\n* [Examples](#examples)\n* [Significant Figure Definitions \u0026 Rules](#significant-figure-definitions-and-rules)\n* [Tools to pair with `tv`](#tools-to-pair-with-tv)\n* [Configuration Dotfile](#configuration-dotfile)\n* [FAQ](#faq)\n* [Help](#help)\n* [Inspiration](#inspiration)\n\n# Features\n\n1. Nice colors out of the box\n2. Significant digit printing (no more decimal dust taking valuable terminal space)\n3. NA comprehension and coloring (no more misaligned data cells due to missing data)\n4. Dimensions printed first (no more guessing how many rows and columns are in the data)\n5. Column overflow logic (no more misalignment due to terminal dimensions)\n6. Long string/Unicode truncation (no more long strings pushing other data around)\n7. Customizable with a dotfile config (bring your own theme)\n\n# Installation\n\nThe following install options are available via package managers:\n\n* [Cargo](#cargo)\n* [Debian](#debian)\n* [AUR](#aur)\n* [Snap](#snap)\n* [Homebrew](#homebrew)\n\nWe currently cut releases for the following architectures. Download from the [release page](https://github.com/alexhallam/tv/releases).\n\n* **MacOS**\n* **ARM**\n* **Windows**\n* **Build from source (Most general)**\n\nThe instructions for all of the above are very similar with the following general steps.\n\n1. Download your desired release from the [release page](https://github.com/alexhallam/tv/releases)\n2. `tar -xvzf \u003cRELEASE_FILE_NAME\u003e`\n3. `cd` into uncompressed folder\n4. Find binary `tidy-viewer`\n\nAfter the above steps I would highly recommend you make an alias for `tidy-viewer` as shown for other builds.\n\n### Cargo\n\nThe following will install from the [crates.io](https://crates.io/crates/tidy-viewer) source. For convenience add the alas `alias tv='tidy-viewer'` to `.bashrc`.\n\n```sh\ncargo install tidy-viewer\nsudo cp /home/$USER/.cargo/bin/tidy-viewer /usr/local/bin/.\necho \"alias tv='tidy-viewer'\" \u003e\u003e ~/.bashrc\nsource ~/.bashrc\n```\n\n### Debian\n\nThe below instructions work with the most recent release `\u003cVERSION\u003e` found here [release page](https://github.com/alexhallam/tv/releases).\n\n```sh\nwget https://github.com/alexhallam/tv/releases/download/\u003cVERSION\u003e/tidy-viewer_\u003cVERSION\u003e_amd64.deb\nsudo dpkg -i tidy-viewer_\u003cVERSION\u003e_amd64.deb\necho \"alias tv='tidy-viewer'\" \u003e\u003e ~/.bashrc\nsource ~/.bashrc\n```\n\n### AUR\n\nKindly maintained by @yigitsever\n\n```sh\nparu -S tidy-viewer\n```\n\n### Snap\n\n```\nsudo snap install --edge tidy-viewer\n```\n\n### Homebrew\n\n```\nbrew install tidy-viewer\n```\n\n# Examples\n\nHave some fun with the following datasets!\n\n### Diamonds\n```sh\n# Download the diamonds data\nwget https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/diamonds.csv\n\n# pipe to tv\ncat diamonds.csv | tv\n```\n\n### Starwars\n```sh\nwget https://raw.githubusercontent.com/tidyverse/dplyr/master/data-raw/starwars.csv\n\n# Pass as argument\ntv starwars.csv\n```\n\n### Pigeon Racing\n```sh\nwget https://raw.githubusercontent.com/joanby/python-ml-course/master/datasets/pigeon-race/pigeon-racing.csv\ncat pigeon-racing.csv | tv\n```\n\n### Titanic\n```sh\nwget https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv\n# send to pager with color\n# less \ntv titanic.csv -ea | less -R\n# bat\ntv titanic.csv -a -n 1000 | bat -p\n```\n\n# Significant Figure Definitions And Rules\n\n![example](img/sigs.png)\n\n![example](img/long_double.png)\n\n\u003e The first three digits represent \u003e 99.9% the value of a number. -- GNU-R Pillar\n\nChoosing the sigfigs amounts to how much of the value of a number is desired. The table below shows an example calculation with variable sigfigs.\n\n| sigfigs | value  | sigfiged_value | %value_of_the_number_explained_by_sigfiged_vale |\n| ------- | ------ | -------------- | :---------------------------------------------: |\n| 1       | 0.1119 | 0.1            |                      \u003e89%                       |\n| 2       | 0.1119 | 0.11           |                      \u003e98%                       |\n| 3       | 0.1119 | 0.111          |                      \u003e99%                       |\n\n`tv` uses the same significant figure (sigfig) rules that the R package `pillar` uses.\n\nThe purpose of the sigfig rules in `tv` is to guide the eye to the most important information in a number. This section defines terms and the decision tree used in the calculation of the final value displayed.\n\n## Definitions\n\n```text\n     ┌─────┐      ┌─────┐     ─┐\n     │     │      │     │      │\n     │     │      │     │      │\n     │     │      │     │      │\n     │     │      │     │      │\n     │     │  ┌┐  │     │      │\n     └─────┘  └┘  └─────┘    ──┴─\n   │        │    │                │\n   └────────┘  ▲ └────────────────┘\nleft hand side │  right hand side\n     (lhs)     │       (rhs)\n\n            decimal\n```\n\n**left hand side (lhs)**: digits on the left hand side of the decimal.\n\n**right hand side (rhs)**: digits on the right hand side of the decimal.\n\n```text\n\n ┌─────┐      ┌─────┐     ─┐     ┌─────┐\n │     │      │     │      │     │     │\n │     │      │     │      │     │     │\n │     │      │     │      │     │     │\n │     │      │     │      │     │     │\n │     │  ┌┐  │     │      │     │     │\n └─────┘  └┘  └─────┘    ──┴─    └─────┘\n\n│                     │         │       │\n└─────────────────────┘         └───────┘\n       leading 0s              trailing 0s\n```\n**leading 0s**: 0s to the left of a non-zero.\n\n**trailing 0s**: 0s to the right of a non-zero. The zeros in 500m are trailing as well as the 0s in 0.500km. \n\n\n```text\n ─┐     ┌─────┐       ─┐\n  │     │     │        │\n  │     │     │        │\n  │     │     │        │\n  │     │     │        │\n  │     │     │  ┌┐    │\n──┴─    └─────┘  └┘  ──┴─\n\n                   │        │\n                   └────────┘\n              fractional digit(s)\n```\n\n**fractional digits**: Digits on the rhs of the decimal. The represent the non-integer part of a number.\n\n## Rules\n\nThere are only 4 outputs possible. The significant figures to display are set by the user. Assume `sigfig = 3`:\n\n1. **lhs only (`12345.0 -\u003e 12345`)**: If no fractional digits are present and lhs \u003e= sigfig then return lhs\n2. **lhs + point (`1234.5 -\u003e 1234.`)**: If fractional digits are present and lhs \u003e= sigfig then return lhs with point. This is to let the user know that some decimal dust is beyond the main mass of the number.\n3. **lhs + point + rhs (`1.2345 -\u003e 1.23`)**: If fractional digits are present and lhs \u003c sigfig return the first three digits of the number.\n4. **long rhs (`0.00001 -\u003e 0.00001`)**: This is reserved for values with leading 0s in the rhs.\n\n\n\n```text\n# Pseudo Code: Sigfig logic assuming sigfig = 3\nif lhs == 0:\n    n = ((floor(log10(abs(x))) + 1 - sigfig)\n    r =(10^n) * round(x / (10^n))\n    return r\n    // (0.12345 -\u003e 0.123)\nelse:\n    if log10(lhs) + 1 \u003e sigfig:\n        if rhs \u003e 0:\n            //concatenate:\n            //(lhs)\n            //(point)\n            //(123.45 -\u003e 123.)\n        else:\n            //concatenate:\n            //(lhs)\n            //(1234.0 -\u003e 1234)\n            //(100.0 -\u003e 100)\n    else:\n        //concatenate:\n        //(lhs)\n        //(point)\n        //sigfig - log10(lhs) from rhs\n        //(12.345 -\u003e 12.3)\n        //(1.2345 -\u003e 1.23)\n```\n\n# Tools to pair with tv\n\n`tv` is a good complement to command line data manipulation tools. I have listed some tools that I like to use with tv.\n\n[qsv](https://github.com/jqnatividad/qsv) - Fork of `xsv`. Has more commands/subcommands and allows users to evaluate lua/python on data. [Rust | CLI]\n\n[xsv](https://github.com/BurntSushi/xsv) - Command line csv data manipulation. [Rust | CLI]\n\n[SQLite](https://www.sqlite.org/index.html) - Database engine with CLU, shell, and library interfaces . [C | CLI/shell/lib]\n\n[DuckDB](https://duckdb.org/) - Database engine with CLU, shell, and library interfaces . [C++ | CLI/shell/lib]\n\n[csvtk](https://bioinf.shenwei.me/csvtk/) - Command line csv data manipulation. [Go | CLI]\n\n[tsv-utils](https://github.com/eBay/tsv-utils) - Command line csv data manipulation toolkit. [D | CLI]\n\n[q](https://github.com/harelba/q) - Command line csv data manipulation query-like. [Python | CLI]\n\n[miller](https://github.com/johnkerl/miller) - Command line data manipulation, statistics, and more. [C | CLI]\n\n[VisiData](https://www.visidata.org/) - An interactive terminal user interface that is built to explore and wrangle data. [Python | TUI]\n\n# Tools similar to tv\n\n`column` Comes standard with Linux. To get similar functionality run `column file.csv -ts,`\n\nThough `column` is similar I do think there are some reasons `tv` is a better tool.\n\n## 1. NA comprehension\n\n`NA` values are very important! Viewers should have their attention drawn to these empty cells. In the image below `NA` values are not only invisible, but it seems to be causing incorrect alignment in other columns.\n\n![na_comp](img/na_comprehension.png)\n\nThere are many ways that programs will designate missing values. Some use `none`, others use `NaN`, and many more `\"\"`, `NA`, `null`, `n/a` etc. `tv` searches for these strings and replaces them with `NA`. This is similar in spirit to the significant digit calculations and the truncation of columns with long strings. The purpose of `tv` is not to show the complete literal value, but to guide the eye.\n\n![na_comp](img/na_cases.png)\n\n## 2. Column Overflow Logic\n\nIn cases where the terminal width can't fit all of the columns in a dataframe, `column` will try to smush data on the rows below. This results in an unpleasant viewing experience. \n\n`tv` can automatically tell when there will be too many columns to print. When this occurs it will only print the columns that fit in the terminal and mention the extras in the footer below the table.\n\n![overflow](img/pigeon-racing.png)\n\n# Configuration Dotfile\n\nFor information on dotfile configuration see `tv --help`. This allows users to set their own color palette, rows to print, max column width, etc.\n\n# FAQ\n\n* Does `tv` have a light theme?\n\n\u003e Yes, solorized light is added out of the box. This was added in version `1.4.6`. You may also define your own themes in the config.\n\n* The `~/.config/tv.toml` file is having no effect on the output. What am I doing wrong?\n\n\u003e Every key/value pair must exist or the toml will not be read. If even one key/value is missing then the config will not work.\n\n* It would be nice to be able to scroll vertically/horizontally through tall/wide csv file. Does `tv` allow for this functionality?\n\n\u003e Yes, pipe the output to `less` or `bat`. `tv` allows for this with the `-e` flag. \n\u003e To extend to the full csv width and length and keep color try the following `tv diamonds.csv -ea | less -SR`\n\u003e To extend to the full csv width and length and remove all color try the following `tv diamonds.csv -e | less -S`\n\n# Help\n\n`tv --help`\n\n```txt\ntv 1.5.2\nTidy Viewer (tv) is a csv pretty printer that uses column styling to maximize viewer enjoyment.✨✨📺✨✨\n\n    Example Usage:\n    wget https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/diamonds.csv\n    cat diamonds.csv | head -n 35 | tv\n    tv diamonds.csv\n\n    Configuration File Support:\n    An example config is printed to make it easy to copy/paste to `tv.toml`.\n    Check the parameters you have changed with `tv --config-details`.\n    The config (tv.toml) location is dependent on OS:\n        * Linux: $XDG_CONFIG_HOME or $HOME/.config/tv.toml\n        * macOS: $HOME/Library/Application Support/tv.toml\n        * Windows: {FOLDERID_RoamingAppData}\\tv.toml\n\n        ## ==Tidy-Viewer Config Example==\n        ## Remove the first column of comments for valid toml file\n        ## All fields must be defined. Partial files will not be read.\n        ## The delimiter separating the columns. [default: ,]\n        #delimiter = \",\"\n        ## Add a title to your tv. Example 'Test Data' [default: NA (\"\")]\n        #title = \"\"\n        ## Add a footer to your tv. Example 'footer info' [default: NA (\"\")]\n        #footer = \"\"\n        ## The upper (maximum) width of columns. [default: 20]\n        #upper_column_width = 20\n        ## The minimum width of columns. Must be 2 or larger. [default: 2]\n        #lower_column_width = 2\n        ## head number of rows to output \u003crow-display\u003e [default: 25]\n        #number = 35\n        ## extend width and length in terms of the number of rows and columns displayed beyond term width [default: false]\n        # extend_width_length = true\n        ## meta_color = [R,G,B] color for row index and \"tv dim: rows x cols\"\n        #meta_color = [64, 179, 162]\n        ## header_color = [R,G,B] color for column headers\n        #header_color = [232, 168, 124]\n        ## std_color = [R,G,B] color for standard cell data values\n        #std_color = [133, 205, 202]\n        ## na_color = [R,G,B] color for NA values\n        #na_color = [226, 125, 95]\n        ## neg_num_color = [R,G,B] color for negative values\n        #neg_num_color = [226, 125, 95]\n\nUSAGE:\n    tidy-viewer [FLAGS] [OPTIONS] [FILE]\n\nFLAGS:\n    -C, --config-details             Show the current config details\n    -d, --debug-mode                 Print object details to make it easier for the maintainer to find and resolve bugs.\n    -e, --extend-width-and-length    Extended width beyond term width (do not truncate). Useful with `less -S`.\n    -f, --force-all-rows             Print all rows in file. May be piped to 'less -S'. Example `tidy-viewer\n                                     data/diamonds.csv -f -a | less -R`\n    -a, --color-always               Always force color output. Example `tv -a starwars.csv | less -R` or `tv -a\n                                     starwars.csv | bat -p`. The `less` cli has the `-R` flag to parse colored output.\n    -h, --help                       Prints help information\n    -D, --no-dimensions              Turns off dimensions of the data\n    -R, --no-row-numbering           Turns off row numbering\n    -V, --version                    Prints version information\n\nOPTIONS:\n    -c, --color \u003ccolor\u003e\n            There are 5 preconfigured color palettes (Defaults to nord):\n                            (1)nord\n                            (2)one_dark\n                            (3)gruvbox\n                            (4)dracula\n                            (5)solarized light [default: 0]\n    -s, --delimiter \u003cdelimiter\u003e                      The delimiter separating the columns.\n    -F, --footer \u003cfooter\u003e                            Add a footer to your tv. Example 'footer info' [default: NA]\n    -l, --lower-column-width \u003clower-column-width\u003e\n            The lower (minimum) width of columns. Must be 2 or larger. [default: 2]\n\n    -n, --number-of-rows-to-output \u003crow-display\u003e     Show how many rows to display. [default: 25]\n    -g, --sigfig \u003csigfig\u003e                            Significant Digits. Default 3. Max is 7 [default: 3]\n    -t, --title \u003ctitle\u003e                              Add a title to your tv. Example 'Test Data' [default: NA]\n    -u, --upper-column-width \u003cupper-column-width\u003e    The upper (maximum) width of columns. [default: 20]\n\nARGS:\n    \u003cFILE\u003e    File to process\n```\n\n# Use With Database Engines\n\nHere I show how to use `tv` with a couple of database engines (SQLite, DuckDB).\n\n## Use With SQLite\n\n[Sqlite](https://www.sqlite.org/index.html) is a fantastic program! If it is not the most deployed software it is probably close to it. For more info on SQLite see their [Executive Summary](https://www.sqlite.org/about.html)\n\nFor this example you will need to download and uncompress taxi data\n\n```bash\nwget https://github.com/multiprocessio/dsq/blob/43e72ff1d2c871082fed0ae401dd59e2ff9f6cfe/testdata/taxi.csv.7z?raw=true -O taxi.csv.7z\n7z x taxi.csv.7z\ncd testdata\nls -l --block-size=M # the data is farily large at 192MB\n```\n\n### SQLite One-liner\n```bash\nsqlite3 :memory: -csv -header -cmd '.import taxi.csv taxi' 'SELECT passenger_count, COUNT(*), AVG(total_amount) FROM taxi GROUP BY passenger_count' | tv\n```\n\nThe above one-liner queries a csv as an in-memory database. It is also possible to query an *existing* `sqlite` database and pipe the output as a csv for `tv` to pick up. A one-liner is shown below.\n\n```bash \nsqlite3 -csv -header \u003cfile_name.sqlite\u003e 'select * from \u003ctable\u003e;' | tv\n```\n\n## Use With DuckDB\n\n[DuckDB](https://duckdb.org/why_duckdb) has a lot in common with SQLite. As personal anecdotes I do like that fewer CLI flags are needed to run on csvs. I also like the speed. Though it is not as universal as SQLite I think that it is a good fit for command line data manipulation.\n\nFor this example you will need to download and uncompress taxi data\n\n```bash\nwget https://github.com/multiprocessio/dsq/blob/43e72ff1d2c871082fed0ae401dd59e2ff9f6cfe/testdata/taxi.csv.7z?raw=true -O taxi.csv.7z\n7z x taxi.csv.7z\ncd testdata\nls -l --block-size=M # the data is fairly large at 192MB\n```\n\n## Fun With `tv`\n\nUsing `duckdb` with `tv` and `less` to manipulate data with SQL grammar and view results in a scrolling window.\n\n```sh\nduckdb --csv -c \"select norm1 from norms.csv\" | ../target/release/tidy-viewer -f -a | less -R\n```\n\n### DuckDB One-liner\n```bash\nduckdb --csv -c \"SELECT passenger_count, COUNT(*), AVG(total_amount) FROM taxi.csv GROUP BY passenger_count ORDER BY passenger_count\" | tv\n```\n\n# Inspiration\n\n[pillar](https://pillar.r-lib.org/dev/articles/digits.html#trailing-dot-1) - R's tibble like formatting. Fantastic original work by [Kirill Müller](https://github.com/krlmlr) and [Hadley Wickham](http://hadley.nz/). `tv` makes an attempt to port their ideas to the terminal.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexhallam%2Ftv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexhallam%2Ftv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexhallam%2Ftv/lists"}