ted is a tabular editor. It displays database tables as markdown table and provides spreadsheet-like editing, including mouse support for selecting cells (with Opt key) or adjust column widths.
┌──────────┬──────┬──────────┬────────────┬────────────┬─────┐
│ id │ name◂│▸email │ created_at │ updated_at │ org…│
┝━━━━━━━━━━┿━━━━━━┿━━━━━━━━━━┿━━━━━━━━━━━━┿━━━━━━━━━━━━┿━━━━━┥
│ 4 │ John…│ john.dee…│ 2021-01-01 │ 2021-01-01 │ 32 │
│ 5 │ Jane…│ jane.don…│ 2021-01-01 │ 2021-01-01 │ 4 │
└──────────┴──────┴──────────┴────────────┴────────────┴─────┘
ted [dbname] [tbl]
ted test users
dbname
can either be a database file (sqlite or duckdb) or a database name. If the file is not present, try the name with default parameters in Postgres and MySQL. The where clause lets you filter down the table.
-d
or--database
-h
or--host
-p
or--port
-u
or--username
--password
-w
or--where
-o
or--order-by
-l
or--limit
- tab
- shift+tab
- arrows
- home
- end
- page up
- page down
- cmd+arrow
- enter: edit/down/new row (if at bottom)
- esc: exit from editing, discarding changes
- shift+enter: edit/up (if at top)
- alt+del: delete row
- cmd+r: refresh data
- cmd+f: find
- alt+↑/↓: rearranges row order
- alt+←/→: rearranges column order
- ctrl+←/→: increase/decrease column width (zero hides)
- ctrl+del: hides column
Lets you interact with elements, selecting cells, resizing or unhiding columns. Selecting a range of cells lets you copy a csv to clipboard.
- opt+click
- opt+shift+click: (select range)
Get terminal size to size column widths and how many rows to display.
Focusing a cell always brings its full width into the view.
Each column has a default width of 8 characters + 2 spaces + pipe = 11 characters. 7 columns + 1 pipe = 78 characters. Column minimum width is 3 characters. …
indicates overflow. Additional columns flow off screen, just like spreadsheets. Focusing a cell minimally scrolls to fit the cell into the editor window.
When editing values with overflow, it overlays on top of the table with a light background. Overflow overlay flows to the right and below the cell. When value overflows the editor window, it word wraps. The editing overlay never exceeds the terminal window size.
Default null sentinel is \N
(configurable). \\N
to input actual string.
JSON is treated as text. JSONB is pretty printed.
Status bar in the bottom row where contextual information can be displayed, like warnings, errors, contextual information.
The status bar default shows the current database.table and the row number/total in the bottom right.
During viewing, show column data type, constraints. During editing, input-specific context, including whether input is "valid"
- run check constraints, test against unique index
- valid int, bool, float, json
- enums
- date time format
- references: preview
When highlighting or editing foreign key references, the status bar shows a logfmt preview. Say we highlight accounts.owner
, which references the users table: users: id=1 name='Eric' plan='free'…
.
If the sheet does not have a unique index with not null columns or nulls not distinct, the status bar shows a warning upon opening the file or updating data. The associated records are read-only.
If an update fails, status bar shows error message.
Use streaming to fetch results and split pipe results to display and a temporary file.
The "view" of the table is always just a cache.
Updates are run with RETURNING *
clause, attempt to update just the row and not refresh the entire table.
When updating cells, identify a table's primary keys or unique constraints (even if they are multicolumn). If none exists, warn that updates are "best effort" and are made by WHERE
'ing matching values. If the number of rows updated >1, message in the status bar.
[dbname]
is a filename (sqlite or duckdb) or a database name in the .ted.yml
config. If no matching name is found and database type flag is not set, suggest ted init
. Support for tab-completing database (from either local files or config), table and column names.
databases:
[name]: <postgres|mysql|clickhouse>
[name]:
type: <postgres|mysql|clickhouse>
host: [host] # opt
port: [port] # opt
user: [user] # optional, assumes system username
dbname: [dbname] # opt, assumes name
users: # table
frozen: [id, name]
columns: # order and width
name # default
preferences: 20
project_cache: 0
null: <null> # default is \N
.ted.yaml
can be used to store table column order and width. All columns should appear by default with a width of 8. You can only hide columns, which displays like hidden spreadsheet columns: ◂│▸
. Those unicode characters are cmd+click
-able to show column.
All columns selected by default. Extra data from table columns shouldn't matter that for this use case.
databases:
test: postgres
bloggy:
type: postgres
username: bloggy
Undo/redo with cmd+z
and cmd+shift+z
shortcuts.
If primary key does not exist, use sqlite/duckdb rowid
or postgres ctid
. This approach is vulnerable to non-exclusive access (updates) or VACUUMs. Also requires modifying update RETURNING *, rowid|ctid
. It does not work for mysql or clickhouse. Throw a warning in the status bar if using this approach.
Transactions. This is an editor, not a sql editor or a psql replacement.
Column filtering or sorting. You're re-implementing SQL at this point.
Support for views. Incredibly difficult to trace a view column to its source table. Editing via views is not useful. WHERE
, ORDER BY
and LIMIT
are supported as flags, which should cover most cases.
DDL. This is for editing data, not schemas. DDL is best done with SQL.
Real-time database updates. This is not possible without modifying the database (adding triggers). You also do not want to lock the table from external writes: this should not be necessary in local development and is never a good idea in production.
Pasting. Unclear how you'd map things, especially if focus is not on the first column.
watchexec --restart --exts go,mod,sum -- 'go install'
ted test.db users 2>/tmp/ted.log
tail -f /tmp/ted.log
`