{"id":18446943,"url":"https://github.com/nmeum/saneterm","last_synced_at":"2025-10-27T23:32:55.782Z","repository":{"id":42385255,"uuid":"372548225","full_name":"nmeum/saneterm","owner":"nmeum","description":"Modern line-oriented terminal emulator without support for TUIs","archived":false,"fork":false,"pushed_at":"2022-04-07T22:00:38.000Z","size":152,"stargazers_count":15,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-23T03:32:05.076Z","etag":null,"topics":["console","readline","terminal","terminal-emulator","unicode"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nmeum.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-31T15:14:23.000Z","updated_at":"2024-12-21T16:32:22.000Z","dependencies_parsed_at":"2022-09-21T05:44:25.169Z","dependency_job_id":null,"html_url":"https://github.com/nmeum/saneterm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmeum%2Fsaneterm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmeum%2Fsaneterm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmeum%2Fsaneterm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmeum%2Fsaneterm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nmeum","download_url":"https://codeload.github.com/nmeum/saneterm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247755412,"owners_count":20990617,"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":["console","readline","terminal","terminal-emulator","unicode"],"created_at":"2024-11-06T07:11:25.452Z","updated_at":"2025-10-27T23:32:50.740Z","avatar_url":"https://github.com/nmeum.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# saneterm\n\nModern line-oriented terminal emulator without support for TUIs.\n\n![saneterm demo](https://gist.githubusercontent.com/nmeum/51d89900c9c7beef49cace24ebc605ec/raw/14b9eeb25483c82fa3672875bb24ff33dbdf932a/saneterm.gif)\n\n## Motivation\n\nMainstream terminal emulators (urxvt, xterm, alacritty, …) support a\nstandard known as [ANSI escape sequences][wikipedia ansi]. This standard\ndefines several byte sequences to provide special control\nfunctions for terminals emulators. This includes control of the cursor,\nsupport for different colors, et cetera. They are often used to\nimplement TUIs, e.g. using the [ncurses][ncurses web] library.\n\nMany of these escape sequences operate on rows and columns and therefore\nrequire terminal emulators to be built around a character grid were\nindividual cells can be modified. Historically, this was very useful to\nimplement UIs on physical terminals like the VT100. Nowadays this\napproach feels dated and causes a variety of problems. For instance, the\nconcept of grapheme cluster as used in [Unicode][unicode web] is largely\nincompatible with fixed-size columns. For this reason, terminal\nemulator supporting the aforementioned escape sequences can never fully\nsupport Unicode [\\[1\\]][variable-width glyphs].\n\nOn the other hand, a terminal emulator not supporting ANSI escape\nsequences can never support existing TUIs. However, the idea behind\n`saneterm` is that terminals shouldn't be used to implement TUIs anyhow,\ninstead they should focus on line-based CLIs. By doing so, a variety of\nfeatures normally implemented in CLI programs themselves (like\n[readline][readline web]-keybindings) can be implemented directly in the\nterminal emulator.\n\n## Status\n\nSilly, buggy, and incomplete prototype implementation.\n\n## Features\n\nBy focusing on line-based input in the terminal emulator a variety of\nthings can be simplified and improved. `saneterm` is presently just a\nprototype and provides basic implementations of the following features:\n\n* Full Unicode support\n* Support for readline-like line editing keybindings\n* Editing history support directly in the terminal emulator\n* File name completions\n* Pager-like text handling (scrolling, searching, …)\n* Basic support for SGR escape sequences (colors, font modifiers, …)\n\n## Installation\n\nThis software has the following dependencies:\n\n* [python3][python web]\n* [PyGObject][PyGObject web] and [gtk+3.0][gtk web]\n* [setuptools][setuptools web]\n\nIf these are installed run the following command to install `saneterm`:\n\n\t$ python3 setup.py install --optimize=1\n\nYou can also run saneterm's tests (with limited coverage at the moment):\n\n\t$ python3 tests.py\n\nFor development setups just run `python3 -msaneterm`.\n\n## Usage\n\nSince many modern day shells use ANSI escape sequences heavily for\nproviding editing features, your favorite shell might not directly work\nwith `saneterm`. Simple shells like [dash][dash web] are known to work\nwell though. You might also want to consider using a clean environment,\nto do so run the following command to start `saneterm`:\n\n\t$ saneterm -- env -i dash\n\n## Configuration\n\nThe terminal appearance can be configured using [Gtk's CSS][gtk css]\nfeature. The `saneterm` window widget can be selected using the CSS\nselector `#saneterm`.\n\nFor example, to change the color scheme and employed font. Add the\nfollowing to your `gtk.css` configuration file located at\n`$XDG_CONFIG_HOME/gtk-3.0/gtk.css`:\n\n\t#saneterm textview {\n\t\tfont-family: Terminus;\n\t\tfont-size: 16px;\n\t}\n\n\t#saneterm textview text {\n\t\tbackground-color: #181818;\n\t\tcolor: #d8d8d8;\n\n\t\t/* change cursor color too */\n\t\tcaret-color: #d8d8d8;\n\t}\n\nKeybindings can be configured using the same mechanism, see `keys.py`\nfor the default keybindings.\n\n## FAQ\n\n**Q:** How do I edit text on remote machines over SSH if my terminal\nemulator doesn't support visual editors?\n\n**A:** This is an interesting problem since a lot of software\nrelies on TUIs to be used over PTYs and SSH on remote machines. This is\nmostly also an inherit flaw of Unix as it hasn't been designed with\nnetworking and GUIs in mind. Plan 9 solves this problem through 9P file\nservers, but unfortunately it has not been widely adopted and we are\nstuck with Unix. In the Unix world potential solutions include\nCLI-based editors (e.g. [ed][wikipedia ed]) or network protocols\ntunneled over SSH connections (e.g.  [Emacs Tramp Mode][emacs tramp mode]).\n\n**Q:** How do I use pagers (e.g. `less(1)`) without support for TUIs?\n\n**A:** With `saneterm` pagers are not needed as paging functionality is\nimplemented in the terminal emulator itself. For this reason, `saneterm`\noffers a scrollback buffer in which autoscrolling can be configured\nusing the Gtk context menu. Furthermore, word wrapping can also be\ndisabled using the same mechanism. A search feature is also implemented\nand can be activated using ctrl+f.\n\n**Q:** How do I paste the primary clipboard when clicking the middle\nmouse button?\n\n**A:** Configure [gtk-enable-primary-paste][gtk primary paste] in\n`$XDG_CONFIG_HOME/gtk-3.0/settings.ini`. Since most terminal emulator do\nit this way, this may become the default in future `saneterm` versions.\n\n**Q:** Why is this written in Python and not X?\n\n**A:** This software is presently just a silly prototype, Python is good\nfor prototyping. Furthermore, Python has decent, somewhat well-documented\nbindings for Gtk.\n\n## Related Work\n\nThis work is heavily inspired by the Plan 9 terminal emulator, usage of\nwhich is further described in the [`rio(1)`][rio man page] man page.\nThis terminal emulator was also [ported to Unix][9term man page] as part\nof [plan9port][plan9port web]. An (unmaintained) reimplementation using\nRuby and the Tk GUI toolkit, named [tt], is also available.\n\nThere are also a few projects which seem to share the problem statement\noutlined in the Motivation but propose different solution. Most of\nwhich include continued support for TUIs and therefore don't benefit\nfrom other line-based editing features. Non-complete list:\n\n* https://github.com/withoutboats/notty\n* https://github.com/christianparpart/contour\n* https://notcurses.com/\n\n## License\n\nThis program is free software: you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by the\nFree Software Foundation, either version 3 of the License, or (at your\noption) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\nPublic License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this program. If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\n[ncurses web]: https://invisible-island.net/ncurses/\n[wikipedia ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code\n[wikipedia zwj]: https://en.wikipedia.org/wiki/Zero-width_joiner\n[unicode web]: https://www.unicode.org/\n[readline web]: https://tiswww.case.edu/php/chet/readline/rltop.html\n[python web]: https://www.python.org/\n[PyGObject web]: https://pygobject.readthedocs.io/en/latest/\n[gtk web]: https://gtk.org/\n[setuptools web]: https://pypi.python.org/pypi/setuptools\n[wikipedia ed]: https://en.wikipedia.org/wiki/Ed_(text_editor)\n[emacs tramp mode]: https://www.emacswiki.org/emacs/TrampMode\n[variable-width glyphs]: https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/21\n[rio man page]: https://9p.io/magic/man2html/1/rio\n[9term man page]: https://9fans.github.io/plan9port/man/man1/9term.html\n[plan9port web]: https://9fans.github.io/plan9port/\n[gtk css]: https://developer.gnome.org/gtk3/stable/chap-css-overview.html\n[dash web]: http://gondor.apana.org.au/~herbert/dash/\n[gtk primary paste]: https://developer.gnome.org/gtk3/stable/GtkSettings.html#GtkSettings--gtk-enable-primary-paste\n[tt]: https://github.com/leahneukirchen/tt\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnmeum%2Fsaneterm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnmeum%2Fsaneterm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnmeum%2Fsaneterm/lists"}