1 Punkte von GN⁺ 2024-07-09 | 1 Kommentare | Auf WhatsApp teilen
  • Text auf der Kommandozeile zu korrigieren wirkt wie eine Grundfunktion, doch Programme verarbeiten Eingaben unterschiedlich, sodass dieselbe Taste völlig anders reagieren kann
  • Die Eingabeerfahrung im Terminal lässt sich grob in vier Strömungen einteilen: kein Eingabesystem, GNU readline, alternative Bibliotheken wie libedit und eigene Eingabesysteme
  • In einfachen Tools wie cat, nc oder dash können Pfeiltasten als ^[[D erscheinen, aber vom Terminal bereitgestellte Funktionen wie Ctrl+W, Ctrl+U, Ctrl+C und Ctrl+Z lassen sich weiterhin nutzen
  • Readline-basierte Tools wie bash, psql, irb und python3 bieten Verlauf, Pfeiltasten, Suche mit Ctrl+R sowie Navigation mit Ctrl+A/Ctrl+E; mit rlwrap lässt sich eine ähnliche Erfahrung nachrüsten
  • Wenn man das aktuelle Eingabesystem erkennt, versteht man schneller, warum Pfeiltasten oder Ctrl+R unterschiedlich aussehen, und kann bei Bedarf in der Dokumentation nachsehen oder Workarounds wie rlwrap wählen

Unterschiedliche Eingabeerfahrung je nach Programm

  • Wie man im Terminal Text eingibt und bearbeitet, unterscheidet sich stark von Programm zu Programm
  • Die wichtigsten Typen lassen sich wie folgt einteilen
    • cat, nc, git commit --interactive usw. unterstützen keine Pfeiltasten, sodass Zeichenketten wie ^[[D^[[D^[[C^[[C^ sichtbar werden können
    • irb, python3 unter Linux usw. bieten über die readline-Bibliothek grundlegende Bearbeitungsfunktionen wie Verlauf und Pfeiltasten
    • In manchen Fällen, etwa bei /usr/bin/python3 auf dem Mac, funktionieren Pfeiltasten, aber Ctrl+left oder die Rückwärtssuche mit Ctrl+R werden nicht unterstützt
    • fish, ipython3, micro, vim usw. verwenden eigene Eingabesysteme

Modus 1: Grundzustand ohne Eingabesystem

  • Wenn ein Programm Text nur über Aufrufe wie fgets() entgegennimmt und keine eigenen Bearbeitungsfunktionen bereitstellt, können Pfeiltasten nicht als Bearbeitungsbefehle, sondern als Escape-Sequenzen ausgegeben werden
  • Drückt man zum Beispiel in dash die linke Pfeiltaste, erscheint im Terminal ^[[D wie folgt
$ ls l-^[[D^[[D^[[D
  • Dennoch bleiben die vom Terminal standardmäßig bereitgestellten Steuerfunktionen erhalten
    • Texteingabe
    • Backspace
    • Ctrl+W: vorheriges Wort löschen
    • Ctrl+U: gesamte Zeile löschen
    • Ctrl+C: Prozess unterbrechen
    • Ctrl+Z: Prozess anhalten
  • Auch in einer solchen Umgebung kann man mit Ctrl+W wortweise löschen, statt mehrfach Backspace zu drücken
  • Welche Steuerzeichen das Terminal unterstützt, lässt sich mit stty -a prüfen

Modus 2: Tools, die readline verwenden

  • readline ist eine GNU-Bibliothek, die Texteingabe komfortabler macht und in vielen interaktiven Tools verwendet wird
  • Häufig genutzte readline-Shortcuts sind:
    • Ctrl+E oder End: ans Zeilenende springen
    • Ctrl+A oder Home: an den Zeilenanfang springen
    • Ctrl+left/right arrow: wortweise vor- und zurückspringen
    • Pfeil nach oben: zum vorherigen Befehl wechseln
    • Ctrl+R: Verlauf durchsuchen
  • Ctrl+W und Ctrl+U aus dem Grundmodus lassen sich ebenfalls verwenden, aber in readline löscht Ctrl+U nicht die gesamte Zeile, sondern vom Cursor bis zum Zeilenanfang
  • Die Verlaufssuche mit Ctrl+R in bash ist eine von readline bereitgestellte Funktion
  • psql, irb, python3 usw. sind ebenfalls Beispiele für Programme, die readline verwenden
  • Eine vollständige Liste der readline-Bearbeitungsbefehle findet sich im readline-Handbuch

rlwrap an Tools ohne readline anhängen

  • Auch Programme ohne readline-Unterstützung, etwa nc, lassen sich mit rlwrap nc so ausführen, dass sie sich wie Programme mit readline-Unterstützung nutzen lassen
  • rlwrap kann die Benutzbarkeit von Tools ohne readline deutlich verbessern
  • Benutzerdefinierte Autovervollständigung lässt sich ebenfalls konfigurieren, wurde hier aber nicht praktisch ausprobiert

Warum Tools readline nicht verwenden

  • Es gibt mehrere Gründe, warum manche Tools readline nicht verwenden
    • Sehr einfache Programme wie cat oder nc möchten möglicherweise keine relativ große Abhängigkeit hinzufügen
    • readline steht nicht unter der LGPL, sondern unter der GPL-Lizenz, was möglicherweise nicht zur Lizenz des Programms passt
    • Wenn nur Teile eines Programms interaktiv sind und die Eingabe eher aus einzelnen Zeichen wie y oder n besteht, kann readline-Unterstützung eine geringe Priorität haben
  • git hat interaktive Funktionen wie git add -p, startet aber bei sinnvollen längeren Eingaben normalerweise einen Texteditor
  • idris2 verwendet readline nicht, um Abhängigkeiten zu minimieren, und empfiehlt rlwrap, wenn bessere interaktive Funktionen benötigt werden

Prüfen, ob gerade readline verwendet wird

  • Die einfachste Prüfung ist, Ctrl+R zu drücken
  • Wenn der folgende Prompt erscheint, ist die Wahrscheinlichkeit hoch, dass readline verwendet wird
(reverse-i-search)`':
  • Auch andere Bibliotheken könnten denselben Begriff verwenden, daher ist es kein absoluter Nachweis; es sind jedoch keine anderen Systeme bekannt, die für die Verlaufssuche den Ausdruck reverse-i-search verwenden

Readline-Shortcuts und Emacs

  • Die Shortcuts Ctrl+A für den Zeilenanfang und Ctrl+E für das Zeilenende kann man als von Emacs stammend betrachten
  • Auch in Emacs haben Ctrl+A und Ctrl+E dasselbe Verhalten wie in readline
  • Ctrl+W und Ctrl+U hingegen verhalten sich in Emacs und im Terminal nicht gleich
  • Mehr zur Geschichte des readline-Projekts findet sich unter Geschichte des Readline-Projekts

Modus 3: Alternative Eingabebibliotheken wie libedit

  • /usr/bin/python3 auf dem Mac ist eher ein Zwischenzustand, der nur einige readline-Funktionen unterstützt
  • Drückt man zum Beispiel Ctrl+left arrow, kann statt einer Wortbewegung ;5D ausgegeben werden
$ python3
>>> importt subprocess;5D
  • In der standardmäßigen Python-Installation von Mac OS basiert das Python-Modul readline tatsächlich auf libedit
  • Vermutlich liegt das daran, dass readline unter der GPL-Lizenz steht
  • Mit dem folgenden Befehl lässt sich prüfen, ob dieses Python libedit verwendet
$ python3 -c "import readline; print(readline.__doc__)"
Importing this module enables command line editing using libedit readline.
  • Python-Installationen unter Linux oder über Homebrew verwenden in der Regel readline
  • Python 3.13 soll die readline-Abhängigkeit entfernen und eine eigene Bibliothek verwenden; daher ist die Aussage „Python verwendet readline“ künftig möglicherweise nicht immer richtig

Modus 4: Eigene Eingabesysteme

  • Manche Programme verwenden eigene Systeme zur Textbearbeitung und bieten mitunter mehr Funktionen als readline
  • Beispiele für eigene Eingabesysteme sind:
    • die meisten Terminal-Texteditoren wie nano, micro, vim, emacs
    • Shells wie fish
    • der Zeileneditor zle von zsh
    • REPLs wie ipython
    • Tools wie atuin
  • In solchen Systemen findet man Funktionen wie:
    • stärker auf das Tool zugeschnittene Autovervollständigung
    • bessere Verlaufsverwaltung einschließlich Syntax-Highlighting
    • mehr Tastatur-Shortcuts

Von readline inspirierte eigene Eingabesysteme

  • Atuin ist ein Tool zur Shell-Verlaufssuche; seine Eingabeimplementierung ist zwar eigenständig, aber von readline inspiriert
  • Atuin nutzt aus, dass Nutzer mit readline-Keybindings vertraut sind, und sorgt dafür, dass diese Keybindings funktionieren, ohne readline direkt zu verwenden
  • Auch das von IPython verwendete prompt_toolkit unterstützt viele Optionen, darunter Keybindings im vi-Stil
  • Die Standardeinstellung von prompt_toolkit unterstützt Keybindings im readline-Stil
  • Das ähnelt der Tatsache, dass viele Programme grundlegende vim-Keybindings unterstützen, bei denen j nach unten und k nach oben bedeutet
  • Fastmail unterstützt zum Beispiel j und k, auch wenn die meisten seiner Shortcuts wenig mit vim zu tun haben
  • Von readline inspirierte eigene Eingabesysteme können auf subtile Weise inkompatibel zu readline sein, für Nutzer, die nur einige grundlegende Shortcuts verwenden, ist das aber möglicherweise kein großes Problem
  • Solche eigenen Systeme können oft eine bessere Autovervollständigung bieten als die reine Nutzung von readline

Shells mit vi-Modus

  • bash, zsh und fish unterstützen alle einen vi-Modus für Texteingabe
  • In einer unwissenschaftlichen Umfrage auf Mastodon gaben 12 % an, den vi-Modus zu verwenden
  • readline selbst besitzt ebenfalls einen vi-Modus; die vi-Modus-Unterstützung in bash funktioniert darüber
  • Auch viele andere Programme, die readline verwenden, können einen vi-Modus haben

Ablauf zur Diagnose des Eingabezustands

  • Wenn man weiß, welches Eingabesystem verwendet wird, lässt sich das Verhalten der Kommandozeile leichter vorhersagen
  • An einem Eingabeprompt kann man in dieser Reihenfolge urteilen:
    • Wenn die Pfeiltasten nicht funktionieren, ist wahrscheinlich kein Eingabesystem vorhanden; Ctrl+W und Ctrl+U lassen sich trotzdem verwenden, und bei Bedarf kann man rlwrap vorschalten
    • Wenn bei Ctrl+R reverse-i-search erscheint, ist es wahrscheinlich readline; dann lassen sich vertraute readline-Shortcuts und grundlegende Verlaufsfunktionen nutzen
    • Wenn Ctrl+R etwas anderes tut, handelt es sich wahrscheinlich um eine eigene Eingabebibliothek; sie kann sich meist ähnlich wie readline verhalten, und bei Bedarf sollte man in die Dokumentation schauen
  • Es bleiben weitere Komplexitäten rund um Eingaben, die hier nicht behandelt wurden
    • Probleme im Zusammenhang mit ssh und tmux
    • die Umgebungsvariable TERM
    • Unterschiede bei der Unterstützung von Kopieren und Einfügen zwischen Terminals wie GNOME Terminal, iTerm und xterm
    • Unicode
    • weitere diverse Eingabeprobleme

1 Kommentare

 
GN⁺ 2024-07-09
Hacker-News-Kommentare
  • Julias Artikel sind immer gut. Was noch fehlt: Mit stty in Shell-Skripten kann man viele Verhaltensweisen des Terminals ändern, einschließlich der Art der Eingabeverarbeitung.
    Ein früheres Experiment von mir mit sh und stty: https://gist.github.com/alganet/63f1dbc97b8fd35f7bb14ec30f79...
    In VT100-kompatiblen Terminals (mintty, xterm, Terminal.app, vscode usw.) lassen sich die meisten Tastenkombinationen und sogar Mausgesten (Drücken/Ziehen/Loslassen) in der Shell erfassen und interpretieren.
    Die ausführbare Demo ist bash -c "$(curl -L https://git.io/fjToH)"; danach einfach Tasten drücken oder die Maus bewegen. Beenden mit Ctrl+W. zsh und ksh werden ebenfalls unterstützt, dash und ähnliche Shells ohne read -rn1 jedoch nicht.
    Außerdem kann man interaktive Programme wie vi | cat -v nach cat -v pipen, um die VT100-Escapes zu sehen, die das Programm verwendet; ich habe viel gelernt, indem ich mir angesehen habe, wie vi das macht.

    • Wenn nach dem Ausführen eines Befehls das Terminal kaputt wirkt, keine Ausgabe mehr erscheint oder merkwürdige Zeichen angezeigt werden, hat der Befehl möglicherweise das tty-Cleanup nicht korrekt erledigt. Statt das Terminal zu schließen, kann man stty sane eingeben, um es zurückzusetzen.
    • Als ich den Anfang von Kernighans UNIX Programming Environment las, kam ich in ähnlichem Geist auf diese absonderliche Methode, um das Ein-/Ausgabeverhalten des Terminals zu erkunden.
      Drei Terminals öffnen und darin 1) man ascii, 2) nc -lvp 9001 | xxd -c1, 3) stty raw -echo; nc -nv 127.0.0.1 9001 ausführen; dann im dritten Terminal die gesamte „Hex“-Spalte der Manpage der Reihe nach nachbilden.
      Dabei lässt sich beobachten, dass manche Werte auf mehrere Arten erzeugt werden können und dass einige andere Tasten Payloads aus mehreren Bytes senden.
    • Auch dieser Artikel über die Implementierung eines Terminal-Texteditors war hilfreich, um stty und Raw Mode zu verstehen: https://viewsourcecode.org/snaptoken/kilo/, https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode...
      Die magisch wirkenden stty-Parameter und Symbole stammen aus vor langer Zeit definierten Steuersequenzen. In unklaren Standards aus den 1970er-Jahren wie ECMA-48 gibt es viele schwer verständliche Begriffe, die heute kaum noch verwendet werden.
      Select Graphic Rendition (SGR) ist zum Beispiel grob so etwas wie ein HTML-Tag der 1970er: Zum Setzen der Vordergrundfarbe verwendet man etwa ESC[38;2;R;G;BmTextESC[0m. ESC[ ist CSI, m ist SGR, 38 steht für Vordergrundfarbe, 2 für den RGB-Farbraum und 0 setzt den Stil zurück.
      Weil die Parameter vor dem Befehl stehen, fühlt sich die Struktur etwas verkehrt herum an. Wie bei Browsern unterschieden und unterscheiden sich Terminals darin, was sie implementieren und wie sie es implementieren. Farben werden recht gut unterstützt, andere Funktionen dagegen nicht. SGR<7> ist zum Beispiel angeblich der Modus „negative image“, aber der Standard erklärt das nicht detailliert; manche Terminals zeigen es invertiert an, andere behandeln es anders, was bis heute Probleme verursacht.
    • Bevor man Code aus dem Internet direkt in bash hineinzieht, sollte man ihn immer prüfen. Diese Demo scheint meine nicht standardmäßige Konfiguration auf seltsame Weise beschädigt zu haben, und ich hatte nicht vor, das genauer zu dokumentieren.
    • Unter Sonoma erscheint „The invoked shell does not support interactive features“.
  • Vor mehr als 20 Jahren habe ich auf readline eine Zustandsmaschine gebaut, sodass man es nicht nur als umbrechende einzelne Zeile, sondern als echten mehrzeiligen Editor verwenden konnte, in dem man nach oben und unten navigieren kann.
    Video: https://github.com/colmmacc/jot/raw/master/jot-demo.mp4
    CVS-Repository des Unix-Terminal-IM-Clients, in dem diese Funktion enthalten war: https://c-hey.redbrick.dcu.ie/src/c-hey_cvs_latest/
    Beim Wechseln zwischen Zeilen nach oben und unten verfolgt und zeichnet er den Cursor neu; wenn sich die Terminalgröße ändert, erkennt er SIGWINCH und zeichnet erneut. Ich würde das gern in Rust neu schreiben und als kleine Bibliothek veröffentlichen, hatte aber keine Zeit. Es hat mich immer überrascht, dass niemand etwas Ähnliches gemacht hat.

    • Ziemlich cool; die Idee würde ich gern aufgreifen. Für einen bestimmten Fall ließe sich das in zsh vermutlich mit ein paar Zeilen umsetzen.
      Nach autoload -Uz zed kann man mit zed eine temporäre Datei bearbeiten und sie an git commit -F übergeben; so startet man einen Inline-Editor mit allen Funktionen von ZLE. Mit C-x C-w speichern und committen, mit C-c abbrechen.
      Der Vorteil dieser Grundimplementierung ist, dass zed ein neues ZLE-Widget ist und man die Keymap vollständig kontrollieren kann. Emacs-Modus oder vi-Modus funktionieren sofort und lassen sich weiter anpassen.
      Wenn man ein eigenes ZLE-Widget schreibt, kann man es direkt aus dem Zeileneditor heraus aufrufen und muss den Befehl nicht wie oben einhüllen.
      https://github.com/zsh-users/zsh/blob/master/Functions/Misc/...
    • Bis ich das Video gesehen hatte, wusste ich nicht, wie viel besser sich diese Editiererfahrung anfühlt, und ich stimme dem Vorteil zu, dass man keinen Kontextwechsel braucht, ähnlich wie beim interaktiven Modus von git commit. Auch der Effekt einer „Inline-Schreibmaschine“ ist cool.
    • Das Textfenster von rio sieht im Hold-Modus ähnlich aus. Das Design ist allerdings viel einfacher und die Mausunterstützung besser: https://p9f.org/magic/man2html/1/rio
    • Ich frage mich, ob die aktuelle Version des Programms stabil ist.
  • Zu den Dingen, die im Artikel fehlen, gehören breite Zeichen, das Problem, dass dieselbe Tasteneingabe wegen unterschiedlicher Tastaturmodi als unterschiedliche ANSI-Escape-Sequenzen dargestellt wird, Unterschiede im TTY-Zustand wie lokales Echo sowie die Tatsache, dass Systemaufrufe zum Ändern des TTY-Zustands je nach Betriebssystem leicht unterschiedlich sind.
    Auch die Unterstützung für Terminal-Emulation ist sehr uneinheitlich. Heutzutage wird meist xterm nachgeahmt, aber selbst dabei zielt niemand wirklich auf 100%ige Kompatibilität ab.
    Auch darüber, wie man die vom Terminal bereitgestellten Funktionen ermittelt, gibt es wenig Einigkeit. Die einen schicken ANSI-Escape-Sequenzen und warten auf eine Antwort, die anderen schauen auf $TERM, und manche Terminals geben sich als xterm aus, ignorieren aber VT-Funktionssequenzen und setzen andere Umgebungsvariablen. Ehrlich gesagt ist das noch chaotischer als User-Agent-Strings.
    All das gilt unter der Annahme eines POSIX-Systems; wenn man Windows noch dazunimmt, wird es doppelt interessant.

  • Wenn man in bash $EDITOR auf seinen bevorzugten Editor setzt, kann man mit Ctrl-X Ctrl-E die aktuelle Zeile an $EDITOR schicken. Nachdem man den Befehl bearbeitet, gespeichert und den Editor beendet hat, wird er ausgeführt.

    • Alte Unix-Hasen, die in ksh den vi-Modus verwenden, können einfach v drücken.
    • Das Built-in fc macht dasselbe. Man kann einfach fc eingeben, ohne eine Ctrl-Tastensequenz zu verwenden.
      Man kann den vorherigen Befehl auch mit einem bestimmten Editor statt mit dem Standard-$EDITOR öffnen. Wenn etwa EDITOR=vi gesetzt ist und man den letzten Befehl mit ed bearbeiten möchte, verwendet man fc -e ed.
      Im vi-Modus kann man aus der Befehlshistorie auch schnell ein Shell-Skript erstellen. Wenn der gewünschte Befehl der 15. Eintrag in der Historie ist, geht das etwa mit fc 15 und anschließend w1.sh, %d, wq.
    • In fish ist es Alt-e.
    • Ich mag solche Shortcuts, aber genau dann, wenn ich sie brauche, fallen sie mir nicht ein.
    • Ich verwende in Neovim EDITOR=nvim zusammen mit copilot.vim wie eine KI-Shell-Autovervollständigung. Das ist ziemlich gut.
      Hier gesehen: https://twitter.com/arjie/status/1575201117595926530?s=46&t=...
  • Aus Sicht eines Linux-Anfängers ist interessant, warum ein Programm, selbst wenn es nur Text mit etwas wie fgets() liest, Funktionen wie Backspace, Ctrl+W und Ctrl+U gratis dazubekommt.
    In der Dokumentation zu fgets() steht, dass gelesen wird, bis ein Zeilenumbruch oder EOF kommt. Bedeutet das, dass es standardmäßig blockiert, bis der Benutzer einen Zeilenumbruch eingibt, und dass das Terminal davor den Zeilenpuffer mit Backspace oder Ctrl+W/Ctrl+U bearbeiten lässt?
    Allerdings ist nicht garantiert, dass das Programm immer eine ganze Zeile liest; wenn man count auf 2 setzt, könnte es auch zeichenweise lesen. Dann könnte man bei einem Backspace bereits gelesene Zeichen nicht mehr „zurücknehmen“. Ich frage mich, ob es im internen Puffer von fgets() irgendeine Magie gibt oder ob in solchen Fällen die Zeilenbearbeitung kaputtgeht.
    https://en.cppreference.com/w/c/io/fgets

    • zsh, bash, ksh, fish und die meisten Terminal-UI-Programme lassen das Terminal im cooked mode und verwalten das Terminalverhalten selbst. Im cooked mode puffert das Terminal nicht bis zum Zeilenumbruch, sondern liest alle Zeichen.
      Dass es so aussieht, als würde nach Zeilenumbrüchen gepuffert, liegt tatsächlich daran, dass die Shell das verwaltet. Deshalb können Entwickler Funktionen zur Manipulation des Textpuffers einbauen, etwa Tab-Completion oder das Voranstellen von sudo am Zeilenanfang.
    • Standardmäßig arbeitet ein Terminal im kanonischen Modus (canonical mode). Ein- und Ausgabe finden erst statt, wenn der Benutzer eine vollständige Zeile eingegeben hat.
      Die Zeichen auf dem Bildschirm vor dem Drücken von Enter befinden sich nur im Speicher des Terminals, und der read-Systemaufruf der Anwendung blockiert auf dem Terminal-File-Descriptor. Bevor die Zeile vollständig ist, schreibt das Terminal keine Daten.
      Auch die Bearbeitung der aktuell eingegebenen Zeile wird dabei normalerweise vom Terminal selbst bereitgestellt. Dass Zeichen auf dem Bildschirm erscheinen, ist ebenfalls eine Terminalfunktion namens Echo; dasselbe gilt für Backspace, Delete, Ctrl+C für SIGINT und Ctrl+D für EOF.
      Zeileneditoren und Texteditoren schalten solche Funktionen ab und setzen das Terminal in den Raw Mode. Alles, was eingegeben wird, wird sofort an die Anwendung übertragen und dort direkt verarbeitet. Ein häufiges Beispiel ist ein Passwort-Prompt, der nur Echo abschaltet, um Zeichen zu verbergen.
      Auch das traditionelle Unix-Zeilenende \n ist eigentlich eine Terminalfunktion. Aus Sicht des Terminals bewegt \n den Cursor nur eine Zeile nach unten; um zum Zeilenanfang zurückzukehren, braucht man auch \r. Das echte Zeilenende ist \r\n, und das Terminal wandelt \n unsichtbar in \r\n um. Auch das kann deaktiviert werden.
    • Diese Funktion wird vom Terminal-Emulator im „cooked“ mode bereitgestellt: https://en.wikipedia.org/wiki/Terminal_mode
      Im raw mode funktioniert es nicht so.
    • Eine meiner ersten bezahlten Aufgaben als Programmierer war es, das help-Programm von VMS nach SunOS zu portieren. Die erste Hürde war herauszufinden, wie man auf jeden Tastendruck reagiert, ohne auf Enter/Return zu warten.
      Mein Chef half mir absichtlich kaum, und 1986, ohne Web und fast ohne O’Reilly-Bücher, ließ er mich das weitgehend allein herausfinden. Für diese Entscheidung bin ich ihm bis heute unendlich dankbar.
  • Auch die dash-Shell unterstützt einen Editiermodus, wenn sie mit libedit kompiliert wird. Debian-basierte Distributionen tun das vermutlich aus Platzgründen nicht, aber meiner Meinung nach sollte es unterstützt werden, damit Leute, die mit bash angefangen haben, später weniger umlernen müssen.
    Auch der POSIX-Standard definiert set -o vi als optionale Erweiterung. Wenn eine Shell, die POSIX-Kompatibilität beansprucht, diesen Editiermodus implementiert, muss sie set -o vi unterstützen.
    „[set -o] vi: Erlaubt die Bearbeitung von Shell-Befehlszeilen mit dem eingebauten vi-Editor. Wird der vi-Modus aktiviert, müssen alle anderen Befehlszeilen-Editiermodi, die als Implementierungserweiterungen bereitgestellt werden, deaktiviert werden.“
    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V...

    • Debians dash ist als leichtgewichtiges POSIX-sh zum Ausführen von Shell-Skripten gedacht. Es ist nicht als Login-Shell oder für interaktive Nutzung gedacht; in diesem Kontext ist es sinnvoll, die Abhängigkeiten schlank zu halten.
  • Ich habe weiterhin gedacht, dass das Terminal der einzelne Faktor ist, der Linux für immer bei unter 5 % Marktanteil festhält.
    Nicht nur Texteingabe ist das Problem, die gesamte Experience ist komplex. 95 % der Bevölkerung wollen einfach nur eine Drohne fliegen, und man setzt ihnen ein Concorde-Cockpit ohne Beschriftungen vor.
    https://qph.cf2.quoracdn.net/main-qimg-2566f4c91b894e4169d77..., https://media.thedroningcompany.com/images/tincy/WQZpC56vqMp...

    • Wenn es nur Distributionen im Stil von LFS, Gentoo und Arch gäbe, würde das stimmen; aber solange es Ubuntu, Mint, OpenSUSE, Fedora, Manjaro und zahllose benutzerfreundliche Distributionen gibt, ist das wenig überzeugend.
      Dass hinter Ubuntu ein Concorde-Cockpit steckt und ich auf meinem Ubuntu-Arbeitslaptop darauf zugreifen kann, finde ich eher erfreulich. Ohne dieses Maß an Kontrolle würde es mir wohl nicht gefallen.
      Andererseits läuft auf dem Laptop meiner Mutter ebenfalls Ubuntu und auf dem Laptop meiner Freundin Manjaro; beide setzen keinen Fuß ins Concorde-Cockpit, sondern „fliegen nur Drohnen“ und kommen gut damit zurecht. Natürlich nutze ich Arch.
    • Einen Linux-Kernel ohne Terminal und Teile des Userspace verwendet die Mehrheit bereits in Form von Android und Chromebooks.
      Das Terminal ist ein Werkzeug für Entwickler und Systemadministratoren. Es wirkt nur so, weil die meisten Desktop-GNU/Linux-Nutzer Entwickler und Systemadministratoren sind, und die machen nur ein paar Prozent der Bevölkerung aus.
    • In Ubuntus Gnome Terminal oder Windows’ Windows Terminal kommt man mit Home an den Zeilenanfang und mit End ans Zeilenende, und die leicht einzugebenden Dinge scheinen überall ähnlich einfach zu sein.
      Wo man tatsächlich viele seltsame Tastenkürzel kennen muss, ist eher das macOS-Terminal, dort ist alles so wenig intuitiv wie möglich gestaltet.
    • Was den geringen Marktanteil von Linux verursacht, ist fehlende Vorinstallation. Auch Windows wurde praktisch von niemandem genutzt, bevor Microsoft in der 3.x-Ära OEM-Bundles und Vorinstallationen beinahe erzwang.
    • Umgekehrt könnte die im Vergleich zu Unix bessere Terminal-Experience von GNU/Linux einer der Gründe gewesen sein, warum es Unix überholt hat. Wenn man sich auf einer BSD-Kiste einloggt, fühlt es sich an wie eine Zeitreise in die 1980er.
  • Vermutlich eine unpopuläre Meinung, aber ich habe in iTerm2 auf das Preset Natural text editing umgestellt, damit es zu den traditionellen macOS-Shortcuts zum Bearbeiten passt.
    Weil innerhalb der Terminal-App normalerweise wieder auf Steuersequenzen gemappt wird, hat das den Vorteil, dass man die Funktion fast überall bekommt, ohne an mehreren Stellen etwas ändern oder sich um readline-Unterstützung sorgen zu müssen.
    Perfekt ist es nicht: Gelegentlich wurden Sequenzen, die ich manuell eingeben musste, erneut remappt. Aber weil es zu meinem Muskelgedächtnis passt, bearbeite ich Befehle nun deutlich häufiger.
    https://pliszko.com/blog/post/2021-10-31-natural-text-editin...

    • Das ist eines der ersten Dinge, die ich einstelle, wenn ich iTerm installiere. Cmd+Pfeiltasten, Option+Pfeiltasten, Cmd+Delete und Option+Delete natürlich verwenden zu können, ist sehr wichtig.
      Ich möchte nicht, dass Textbearbeitung im Terminal besonders anders funktioniert.
  • Drei grundlegende readline-Keybindings, die das Leben der Leute verbessern würden, wenn sie sie kennen würden, sind Ctrl+W, Ctrl+O und Ctrl+R.
    Ctrl+W löscht, wie Julia im Artikel erwähnt, das letzte Wort.
    Ctrl+O führt eine aus der History geladene Zeile aus und lädt anschließend wieder die nächste History-Zeile. Wenn man in der History zum ersten Befehl geht und fünfmal Ctrl+O drückt, kann man fünf Befehle der Reihe nach ausführen.
    Ctrl+R durchsucht die History rückwärts, während man den Suchstring eingibt. Drückt man erneut Ctrl+R, geht es zum vorherigen Treffer; Ctrl+S bewegt sich zeitlich nach vorn. Ausgeführt wird mit Enter oder Ctrl+O.

    • Ich habe mich immer gefragt, warum Ctrl+S gewählt wurde. Meiner Erfahrung nach kollidiert es fast überall mit dem standardmäßigen XOFF-Pause.
      Wenn man diese Tastenkombination für die Vorwärtssuche verwenden will, muss man wissen, warum es nicht funktioniert, und bereit sein, XOFF abzuschalten.
    • Die letzte Funktion habe ich, wie Shift+Tab in einer GUI, immer mit Ctrl+Shift+R verwendet. Gut, jetzt auch Ctrl+S zu kennen, aber wegen des Muskelgedächtnisses werde ich es wohl nicht nutzen können.
  • In Windows Terminal funktioniert Ctrl+C immer passend: Wenn Text ausgewählt ist, wird kopiert, andernfalls wird der laufende Prozess beendet.
    Die Terminal-Apps unter Linux kopieren nicht mit Ctrl+C, sondern verlangen Ctrl+Shift+C. Auch beim Einfügen landen mit Ctrl+V seltsame Zeichen im Terminal, und weil in allen anderen Apps Ctrl+V gilt, fällt man wegen des Muskelgedächtnisses ständig darauf herein.
    Ich frage mich, ob es eine Linux-Terminal-App gibt, die sich wie Windows Terminal verhält und einem nicht wegen „unsachgemäßer Teletype-Nutzung“ auf die Finger klopft.

    • Ich stelle Terminals immer so ein, dass beim Auswählen automatisch kopiert wird. Ctrl+C drücke ich nicht. Warum sollte man überhaupt Text auswählen, wenn man ihn nicht kopieren will?
    • Dass Kopieren und Beenden im Terminal in Command-C und Ctrl-C getrennt sind, ist einer der wichtigsten Gründe, warum ich beim Mac bleibe.
    • Kopieren innerhalb und außerhalb des Terminals macht man mit der mittleren Maustaste. Einfach Text auswählen und an der Einfügestelle mit der mittleren Taste klicken.
      Diese Methode nutzt einen separaten Xorg-Puffer. Wenn man also mit Ctrl+C etwas kopiert und danach anderen Text auswählt, fügt Ctrl+V das Erste ein, während ein Mittelklick das Zweite einfügt.
      Unter Windows oder auf Smartphones ist es manchmal nervig, wenn man etwas nur ausgewählt hat und dann vergisst, noch so etwas wie Ctrl+C zu drücken.
      Ich glaube nicht, dass es unter den Linux-Terminals eines gibt, das es wie Windows Terminal macht. Der Grund ist, dass ein im Terminal laufendes Programm Ctrl+C vielleicht selbst verarbeiten möchte. Texteditoren sind ein Beispiel dafür, und das Terminal weiß nicht einmal, welches Programm gerade läuft. Job Control ist schließlich Sache der Shell.
    • Bei den meisten guten Linux-Terminals lässt sich das konfigurieren. In kitty reicht zum Beispiel map ctrl+c copy_or_interrupt.
      https://sw.kovidgoyal.net/kitty/actions/#action-copy_or_inte...
    • In WezTerm, das sich per Lua konfigurieren lässt, dürfte das wohl auch gehen. Da ich schon mit anderen Key Bindings bestimmte Lua-Funktionen ausführe, will ich es ausprobieren, sobald ich wieder vor dem Laptop sitze.