Modern line-oriented terminal emulator without support for TUIs
git clone https://git.8pit.net/saneterm.git
1# saneterm 2 3Modern line-oriented terminal emulator without support for TUIs. 4 5![saneterm demo](https://gist.githubusercontent.com/nmeum/51d89900c9c7beef49cace24ebc605ec/raw/14b9eeb25483c82fa3672875bb24ff33dbdf932a/saneterm.gif) 6 7## Motivation 8 9Mainstream terminal emulators (urxvt, xterm, alacritty, …) support a 10standard known as [ANSI escape sequences][wikipedia ansi]. This standard 11defines several byte sequences to provide special control 12functions for terminals emulators. This includes control of the cursor, 13support for different colors, et cetera. They are often used to 14implement TUIs, e.g. using the [ncurses][ncurses web] library. 15 16Many of these escape sequences operate on rows and columns and therefore 17require terminal emulators to be built around a character grid were 18individual cells can be modified. Historically, this was very useful to 19implement UIs on physical terminals like the VT100. Nowadays this 20approach feels dated and causes a variety of problems. For instance, the 21concept of grapheme cluster as used in [Unicode][unicode web] is largely 22incompatible with fixed-size columns. For this reason, terminal 23emulator supporting the aforementioned escape sequences can never fully 24support Unicode [\[1\]][variable-width glyphs]. 25 26On the other hand, a terminal emulator not supporting ANSI escape 27sequences can never support existing TUIs. However, the idea behind 28`saneterm` is that terminals shouldn't be used to implement TUIs anyhow, 29instead they should focus on line-based CLIs. By doing so, a variety of 30features normally implemented in CLI programs themselves (like 31[readline][readline web]-keybindings) can be implemented directly in the 32terminal emulator. 33 34## Status 35 36Silly, buggy, and incomplete prototype implementation. 37 38## Features 39 40By focusing on line-based input in the terminal emulator a variety of 41things can be simplified and improved. `saneterm` is presently just a 42prototype and provides basic implementations of the following features: 43 44* Full Unicode support 45* Support for readline-like line editing keybindings 46* Editing history support directly in the terminal emulator 47* File name completions 48* Pager-like text handling (scrolling, searching, …) 49* Basic support for SGR escape sequences (colors, font modifiers, …) 50 51## Installation 52 53This software has the following dependencies: 54 55* [python3][python web] 56* [PyGObject][PyGObject web] and [gtk+3.0][gtk web] 57* [setuptools][setuptools web] 58 59If these are installed run the following command to install `saneterm`: 60 61 $ python3 setup.py install --optimize=1 62 63You can also run saneterm's tests (with limited coverage at the moment): 64 65 $ python3 tests.py 66 67For development setups just run `python3 -msaneterm`. 68 69## Usage 70 71Since many modern day shells use ANSI escape sequences heavily for 72providing editing features, your favorite shell might not directly work 73with `saneterm`. Simple shells like [dash][dash web] are known to work 74well though. You might also want to consider using a clean environment, 75to do so run the following command to start `saneterm`: 76 77 $ saneterm -- env -i dash 78 79## Configuration 80 81The terminal appearance can be configured using [Gtk's CSS][gtk css] 82feature. The `saneterm` window widget can be selected using the CSS 83selector `#saneterm`. 84 85For example, to change the color scheme and employed font. Add the 86following to your `gtk.css` configuration file located at 87`$XDG_CONFIG_HOME/gtk-3.0/gtk.css`: 88 89 #saneterm textview { 90 font-family: Terminus; 91 font-size: 16px; 92 } 93 94 #saneterm textview text { 95 background-color: #181818; 96 color: #d8d8d8; 97 98 /* change cursor color too */ 99 caret-color: #d8d8d8;100 }101102Keybindings can be configured using the same mechanism, see `keys.py`103for the default keybindings.104105## FAQ106107**Q:** How do I edit text on remote machines over SSH if my terminal108emulator doesn't support visual editors?109110**A:** This is an interesting problem since a lot of software111relies on TUIs to be used over PTYs and SSH on remote machines. This is112mostly also an inherit flaw of Unix as it hasn't been designed with113networking and GUIs in mind. Plan 9 solves this problem through 9P file114servers, but unfortunately it has not been widely adopted and we are115stuck with Unix. In the Unix world potential solutions include116CLI-based editors (e.g. [ed][wikipedia ed]) or network protocols117tunneled over SSH connections (e.g. [Emacs Tramp Mode][emacs tramp mode]).118119**Q:** How do I use pagers (e.g. `less(1)`) without support for TUIs?120121**A:** With `saneterm` pagers are not needed as paging functionality is122implemented in the terminal emulator itself. For this reason, `saneterm`123offers a scrollback buffer in which autoscrolling can be configured124using the Gtk context menu. Furthermore, word wrapping can also be125disabled using the same mechanism. A search feature is also implemented126and can be activated using ctrl+f.127128**Q:** How do I paste the primary clipboard when clicking the middle129mouse button?130131**A:** Configure [gtk-enable-primary-paste][gtk primary paste] in132`$XDG_CONFIG_HOME/gtk-3.0/settings.ini`. Since most terminal emulator do133it this way, this may become the default in future `saneterm` versions.134135**Q:** Why is this written in Python and not X?136137**A:** This software is presently just a silly prototype, Python is good138for prototyping. Furthermore, Python has decent, somewhat well-documented139bindings for Gtk.140141## Related Work142143This work is heavily inspired by the Plan 9 terminal emulator, usage of144which is further described in the [`rio(1)`][rio man page] man page.145This terminal emulator was also [ported to Unix][9term man page] as part146of [plan9port][plan9port web]. An (unmaintained) reimplementation using147Ruby and the Tk GUI toolkit, named [tt], is also available.148149There are also a few projects which seem to share the problem statement150outlined in the Motivation but propose different solution. Most of151which include continued support for TUIs and therefore don't benefit152from other line-based editing features. Non-complete list:153154* https://github.com/withoutboats/notty155* https://github.com/christianparpart/contour156* https://notcurses.com/157158## License159160This program is free software: you can redistribute it and/or modify it161under the terms of the GNU General Public License as published by the162Free Software Foundation, either version 3 of the License, or (at your163option) any later version.164165This program is distributed in the hope that it will be useful, but166WITHOUT ANY WARRANTY; without even the implied warranty of167MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General168Public License for more details.169170You should have received a copy of the GNU General Public License along171with this program. If not, see <http://www.gnu.org/licenses/>.172173[ncurses web]: https://invisible-island.net/ncurses/174[wikipedia ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code175[wikipedia zwj]: https://en.wikipedia.org/wiki/Zero-width_joiner176[unicode web]: https://www.unicode.org/177[readline web]: https://tiswww.case.edu/php/chet/readline/rltop.html178[python web]: https://www.python.org/179[PyGObject web]: https://pygobject.readthedocs.io/en/latest/180[gtk web]: https://gtk.org/181[setuptools web]: https://pypi.python.org/pypi/setuptools182[wikipedia ed]: https://en.wikipedia.org/wiki/Ed_(text_editor)183[emacs tramp mode]: https://www.emacswiki.org/emacs/TrampMode184[variable-width glyphs]: https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/21185[rio man page]: https://9p.io/magic/man2html/1/rio186[9term man page]: https://9fans.github.io/plan9port/man/man1/9term.html187[plan9port web]: https://9fans.github.io/plan9port/188[gtk css]: https://developer.gnome.org/gtk3/stable/chap-css-overview.html189[dash web]: http://gondor.apana.org.au/~herbert/dash/190[gtk primary paste]: https://developer.gnome.org/gtk3/stable/GtkSettings.html#GtkSettings--gtk-enable-primary-paste191[tt]: https://github.com/leahneukirchen/tt