Repository navigation
v1.8.0
Thank you 🙏
v1.8.0 is here, with patches from 17 community contributors.
ttt grows thanks to the support of its community, and every report, review and patch is truly appreciated.
This release brings editable diffs, pull diagnostics for language servers that need them, image support for plugin system, and much faster editing of very large files.
I aim to release every two weeks, but with this many contributions coming in, holding them that long stopped making sense, so this release ships a week early. Thank you all for the support that made that happen.
Highlights
Edit your changes right in the diff
"Open Changes" opens the file itself in diff mode: edit, save and undo as in any tab while the diff follows each keystroke. Every diff view is now a real editor pane, staged and unstaged changes open separately like in VS Code, and git changes are marked on the scrollbar.
Language servers
ttt pulls diagnostics from servers that support it, so TypeScript 7's tsc --lsp now shows errors. Completion, hover and protocol handling got a round of fixes.
Performance
Redraws allocate up to 80% less, jumping to the end of a long file no longer stalls on highlighting, and very large files open, wrap and take typing much faster with less memory. A 256 MiB log opens in 127 ms instead of 201 ms, and word wrap on it takes 1.3 s instead of 3.1 s.
Plugins can open binary files and draw images
Plugins can register handlers for binary file types and draw images on terminals with the Kitty graphics protocol. ttt-pdf uses both to show PDF pages. See the plugin authoring guide.
Also in this release
- Extensionless scripts get highlighting from their shebang line.
editor.diffColorGutterNumbersis off by default, so line numbers on changed rows are now plain.- Replace in Files no longer overwrites unsaved edits.
- Many git fixes: permalinks, blame of unsaved edits, special-character paths, and gutter marks in CRLF and gitignored files.
- Windows install with Scoop.
More
What's Changed (98 pull requests)
- feat(tabs): add Reveal in Explorer to the tab context menu by @omar3903 in #747
- ci: fail when Go code isn't gofmt-formatted by @eugenioenko in #746
- test(plugin): run the SSRF protection test without DNS lookups by @eugenioenko in #753
- chore(plugins): remove cheat sheet from community registry by @eugenioenko in #754
- fix(ui): use ✕ for the editor tab close button by @Detoy in #752
- plugin: no-op Replace on identical text; reject invalid ranges by @eugenioenko in #538
- ci(bench): benchmark diff views alongside the editor by @eugenioenko in #764
- test(e2e): time open changes without git's process time by @eugenioenko in #765
- refactor(buffer): record line changes from every write by @eugenioenko in #771
- perf: cut per-frame allocations in editor rendering by @eugenioenko in #773
- fix(diff): drop the stray trailing row and cut diff allocations by @eugenioenko in #776
- feat(app): open staged and unstaged changes like VS Code by @eugenioenko in #777
- docs(readme): replace contributor lists with avatars by @eugenioenko in #780
- refactor(ui): one incremental row layout for wrap and folds by @eugenioenko in #781
- feat(editor): ctrl+home/ctrl+end go to the start/end of the file by @eugenioenko in #783
- perf(highlight): shared and background highlighting for diff sides by @eugenioenko in #788
- feat(ui): diff overlay for the editor by @eugenioenko in #789
- fix(editor): replace untouched untitled tab when opening files by @bet4it in #784
- docs(readme): shorten architecture and exhaustive lists by @eugenioenko in #787
- feat(ui): diff tabs on a DiffEditorWidget built from editor panes by @eugenioenko in #791
- refactor(ui): remove DiffViewWidget by @eugenioenko in #793
- feat: edit working-tree changes in a live diff by @eugenioenko in #795
- chore(deps): bump textmate-go to v0.2.1; fix flaky highlighting test by @eugenioenko in #798
- chore: update vendorHash by @github-actions in #799
- refactor(ui): Commit Details on the diff widget; remove the old diff renderer by @eugenioenko in #797
- perf(highlight): one event-loop scheduler for background highlighting by @eugenioenko in #801
- fix(ui): route editor commands to the diff pane that has the keys by @eugenioenko in #803
- perf(term): write cells with Put and cached ASCII strings by @eugenioenko in #805
- feat(diff): add editor.diffColorGutterNumbers setting by @AnushreeKasturi in #807
- feat(fold): add explicit open and close commands by @EuanTop in #808
- chore(ci): turn off CodeRabbit's docstring coverage check by @eugenioenko in #809
- fix(terminal): don't hang on close when the shell has background jobs by @eugenioenko in #806
- fix(terminal): scope the SIGHUP takeover to starting the shell by @eugenioenko in #810
- fix(editor): collapse multi-cursors on Select All by @eugenioenko in #811
- fix(git): make Copy GitHub Permalink produce links that open by @jayhemnani9910 in #814
- fix(lsp): accept string ids and answer server requests by @aahoughton in #816
- feat(highlight): detect script language from shebang by @rafjaf in #822
- fix(plugin): allow filesystem access under a symlinked workspace root by @sercanatalik in #818
- feat(plugin): add file handlers for binary file types by @sercanatalik in #819
- feat(widgets): add an image widget backed by the Kitty layer by @sercanatalik in #820
- feat(plugin): add image widget and ttt.graphics by @sercanatalik in #821
- refactor(ui): build ImageViewWidget on widgets.ImageWidget by @eugenioenko in #828
- fix(plugin): destroy and init plugins on the UI goroutine by @eugenioenko in #829
- fix(widgets): run one image decode at a time and cache the fallback info by @sercanatalik in #831
- fix(plugin): release file handler tabs when a plugin is disabled by errors by @sercanatalik in #830
- fix(git): blame the cursor line of unsaved edits, not the line on disk by @jayhemnani9910 in #815
- chore(plugins): remove HTTP Client from community registry by @eugenioenko in #838
- test(bench): measure log opening and scrolling by @eugenioenko in #841
- perf(buffer): read a file straight into its string by @eugenioenko in #842
- ci(lsp): allow manual runs of pinned server tests by @eugenioenko in #843
- test(bench): open logs in the built binary and report peak RSS by @eugenioenko in #845
- perf(lsp): join buffer text only when a server handles the file by @eugenioenko in #844
- test(bench): open logs with word wrap on as well by @eugenioenko in #847
- perf(ui): count wrapped rows without copying each line to runes by @eugenioenko in #846
- test(bench): edit a log committed to git by @eugenioenko in #848
- perf(git): blame unsaved contents off the UI thread and cancel stale runs by @eugenioenko in #849
- perf(git): read blobs into a string sized from the blob by @eugenioenko in #850
- fix(git): show no gutter markers for gitignored files by @eugenioenko in #851
- refactor(async): add shared debounced task API by @eugenioenko in #835
- perf(ui): compute an opened file's folds after its first frame by @eugenioenko in #852
- refactor(git): migrate gutter refreshes to shared async task by @eugenioenko in #853
- fix(ui): keep background folds that typing did not invalidate by @eugenioenko in #854
- fix(statusbar): refresh blame after edits with shared tasks by @eugenioenko in #855
- test(bench): open and type in a large Go file by @eugenioenko in #856
- perf(highlight): replay buffer edits into the document by @eugenioenko in #857
- chore: update vendorHash by @github-actions in #858
- fix(lsp): keep the completion popup closed after accepting or escaping by @eugenioenko in #861
- refactor(lsp): migrate hover to shared async tasks by @eugenioenko in #859
- refactor(lsp): migrate completion and signature help to shared tasks by @eugenioenko in #862
- feat(lsp): pull diagnostics from servers that advertise them by @aahoughton in #839
- refactor(lsp): migrate outline refreshes to shared tasks by @eugenioenko in #863
- fix(lsp): replace characters typed after a completion request by @eugenioenko in #867
- test(bench): press Enter in a large Go file by @eugenioenko in #868
- docs(lsp): document TypeScript 7's tsc --lsp server by @aahoughton in #870
- perf(folds): recompute a large file's folds off the keystroke by @eugenioenko in #869
- fix(git): treat file paths literally when staging, discarding and diffing by @jayhemnani9910 in #877
- fix(explorer): recognize gitignored paths with non-ASCII characters by @jayhemnani9910 in #878
- fix(lsp): apply workspace edits sent as documentChanges by @eugenioenko in #879
- fix(autocomplete): rank exact-case matches above other items with the same sortText by @cestercian in #871
- fix(lsp): skip auto-suggest when the cursor left the word being typed by @eugenioenko in #880
- fix(lsp): map mouse hover through the pane's row and column layout by @eugenioenko in #881
- read references line text from buffer when file has unsaved changes by @ibraah007 in #882
- fix(watcher): report changes at least once a second while a file keeps changing by @eugenioenko in #884
- fix(lsp): send an empty diagnostics array in code action requests by @Yami066 in #885
- fix(lsp): render hover diagnostics as plain text by @KeuqS in #886
- fix(lsp): keep a change from before a restart off the new server by @aahoughton in #887
- fix(markdown): drop blank lines around dividers and at the end by @eugenioenko in #888
- test(ui): set terminal OnUpdate before starting the read loop by @eugenioenko in #889
- feat(lsp): pull diagnostics for open background documents by @aahoughton in #890
- fix(search): keep unsaved edits and moved text safe from Replace in Files by @jayhemnani9910 in #891
- fix(git): don't mark unchanged lines of CRLF files in the gutter by @jayhemnani9910 in #892
- fix(git): split blobs with the buffer's line splitter by @wzd8888 in #894
- test(e2e): benchmark editor frames on a file with git changes by @eugenioenko in #898
- feat(editor): mark git changes on the vertical scrollbar by @risixdzn in #895
- Added Windows scoop install instructions to README.md by @vincentmathis in #901
- fix(editor): scroll to the change when clicking a scrollbar git mark by @mahirhir in #900
- perf(editor): place scrollbar git marks from change runs by @eugenioenko in #903
- test: disable git auto-maintenance in test repositories by @eugenioenko in #905
Full Changelog: v1.7.1...v1.8.0
New Contributors
- @omar3903 made their first contribution in #747
- @AnushreeKasturi made their first contribution in #807
- @EuanTop made their first contribution in #808
- @jayhemnani9910 made their first contribution in #814
- @aahoughton made their first contribution in #816
- @rafjaf made their first contribution in #822
- @sercanatalik made their first contribution in #818
- @cestercian made their first contribution in #871
- @ibraah007 made their first contribution in #882
- @Yami066 made their first contribution in #885
- @KeuqS made their first contribution in #886
- @wzd8888 made their first contribution in #894
- @vincentmathis made their first contribution in #901
- @mahirhir made their first contribution in #900
Full Changelog: v1.7.1...v1.8.0