Qu'entend-on par un shell en mode «vi» ou en mode «emacs»?

32

Cette question découle directement de la réponse . Dans ce cas, je suis spécifiquement incapable de comprendre la partie qui dit:

À cet égard, son comportement est plus proche de celui d'Emacs qu'en mode bash (readline) / ksh / zsh emacs, mais s'écarte de l'éditeur de ligne intégré du pilote de terminal (en mode canonique), où Ctrl-Wsupprime le mot précédent (werase, également en vi ).

Nous parlons ici de shells et non d'éditeurs qui sont deux programmes complètement différents. Que signifie dire que le shell est dans un mode éditeur?

PS: Vous pouvez baser votre réponse sur la prémisse que je comprends ce qu'est un shell et comment utiliser vim pour l'édition de base.

Geek
la source
Il ne s'agit pas de la fonctionnalité principale du shell en soi, mais plutôt de l'édition de lignes (ce que vous faites lorsque vous faites une faute de frappe et que vous vous corrigez).
n. «pronoms» m.

Réponses:

27

En mode "vi", vous pouvez modifier / naviguer sur l'invite du shell actuel comme une ligne dans l'éditeur vi. Vous pouvez le regarder comme un fichier texte d'une ligne. De façon analogue, en mode "emacs", vous pouvez éditer / naviguer dans la ligne de commande actuelle en utilisant (certains) des raccourcis Emacs.

Exemple

Par exemple, en vi-mode, vous pouvez faire quelque chose comme (en bash):

$ set -o vi
$ ls hello world
<ESC>
bbdw # results in
$ ls world

En mode emacs, vous pouvez par exemple Ctrlappuyer Asur + pour sauter au début d'une ligne (vi: Ctrl+ [, 0ou ESC, 0). Vous pouvez activer le mode emacs via set -o emacs(en bash, ksh, zsh etc.).

Readline

De nombreux programmes de ligne de commande interactifs (y compris bash ) utilisent la bibliothèque readline . Ainsi, vous pouvez configurer le mode d'entrée à utiliser (vi ou emacs) et d'autres options en un seul endroit de sorte que chaque programme utilisant readline ait exactement la même interface d'édition / navigation.

Par exemple ma configuration readline ressemble à:

$ cat ~/.inputrc 
set editing-mode vi
set blink-matching-paren on

Par exemple, zsh / ksh n'utilise pas readline pour autant que je sache, mais prend également en charge les modes vi / emacs qui sont très similaires à celui bash / readline.

Bien sûr, le mode vi / emacs dans un shell de ligne de commande n'est qu'un sous-ensemble de l'ensemble complet des fonctionnalités de l'éditeur. Toutes les fonctionnalités n'ont pas de sens dans un shell de ligne de commande et certaines fonctionnalités sont plus compliquées à prendre en charge que d'autres.

Mode canonique

Avant que les modes vi / emacs des shells de ligne de commande interactifs «ne soient inventés», votre shell n'utilisait que le mode canonique de votre terminal qui ne fournit qu'un ensemble limité de commandes d'édition (par exemple Ctrl+ Wpour supprimer le dernier mot.

maxschlepzig
la source
Supposons que je ne sache pas sur quel mode d'entrée je suis. Puis-je le vérifier en entrant du texte et en appuyant sur [Ctrl] + [A]? si le curseur se déplace pour commencer son emacs sinon il vi?
limovala
2
@limovala, devrait être une bonne approximation. Cela dépend bien sûr de votre shell - si CTL + A ne fonctionne pas, une autre possibilité est que votre shell n'inclut aucun mode d'édition. Peut-être que certains shells implémentent également d'autres modes d'édition. Mais en pratique, votre méthode devrait être assez bonne. Vous pouvez également tester avec une commande vi après cela pour être plus sûr. En bash, vous pouvez également utiliser quelque chose comme set -o | grep 'emacs\|vi'. Dans zsh (où j'ai vi-mode), cela ne fonctionne pas.
maxschlepzig
bind -P donnera également une bonne indication du mode dans lequel on se trouve
Paul
23

Vous remarquerez que lorsque vous exécutez catà l'invite du shell sur un terminal, catétant censé écrire sur stdout ce qu'il lit à partir de stdin, et appuyez sur a, vous voyez un aécho en retour par le pilote du terminal, mais catn'écrit pas cela a(vous voyez un seul a, celui repris par le pilote de terminal).

Cependant, si vous tapez a Backspace b Enter, vous ne voyez pas la catsortie a\010b\015, mais b\012( bet la nouvelle ligne).

C'est parce que le pilote de terminal (nous parlons de logiciel dans le noyau, pas dans l'émulateur de terminal comme xterm) implémente un éditeur de ligne très basique en mode canonique . Le pilote de terminal peut être configuré à l'aide d' ioctl()appels système comme lors de l'utilisation de la sttycommande. Par exemple, pour quitter le mode canonique, vous pouvez le faire stty -icanon. Si tu fais:

stty -icanon; cat

Ensuite, vous verrez à la fois le echo(que vous auriez pu désactiver stty -echo) et la catsortie en même temps.

Cet éditeur est un éditeur de ligne. C'est-à-dire qu'il appartient à l'utilisateur de modifier une ligne de texte jusqu'à ce qu'elle soit envoyée à l'application lisant le terminal en appuyant sur Enter.

Les capacités d'édition de cet éditeur sont très limitées. Dans la plupart des implémentations, il n'y a que 4 touches d'édition (en fait des caractères) également configurables avec stty:

  • effacer ( ^Hou ^?généralement): effacer le caractère précédent
  • kill ( ^Uhabituellement): vide (tue) la ligne entrée jusqu'ici
  • werase ( ^W): efface le mot précédent
  • lnext ( ^V): entrez littéralement le caractère suivant (annulez la signification spéciale de tout ce qui précède)

Dans le passé, on pensait que cet éditeur de ligne de pilote de terminal serait étendu avec des capacités plus sophistiquées. C'est pourquoi aucun des premiers shells n'a de capacités d'édition en ligne de commande (vous obtiendriez les mêmes capacités d'édition en ligne à l'invite du shell que lors de l'exécution catcomme nous l'avons fait ci-dessus).

Cependant, cela ne s'est vraiment jamais produit, peut-être en partie à cause du désordre avec différents terminaux qui n'envoient pas les mêmes caractères lors de certaines pressions sur les touches, ce qui rendait évident que cela ne devrait pas être implémenté dans l'espace du noyau.

Certains shells ont donc commencé à abandonner le mode canonique du pilote de terminal et à implémenter leur propre éditeur de ligne. À l'époque, emacset viétaient les éditeurs de texte visuel les plus populaires avec un mode de liaison et de fonctionnement des touches complètement différent. Dans vi, vous disposez d'un mode de saisie de texte et d'un mode d'édition. Dans emacs, vous êtes toujours en mode texte , mais l'édition se fait en appuyant sur des combinaisons de touches (comme ^bpour déplacer le caractère vers l'arrière).

Il n'y avait aucun intérêt pour les shells à l'époque à proposer leur propre liaison de clés différente. Cela aurait causé de la frustration pour les gens à devoir en apprendre un autre. Cependant, choisir un ( emacsou vi) style plutôt que l'autre aurait été un moyen sûr d'aliéner les utilisateurs de l' autre éditeur.

Selon https://www.usenix.org/legacy/publications/library/proceedings/vhll/full_papers/korn.ksh.a :

Les fonctions d'édition en ligne populaires (mode vi et emacs) de ksh ont été créées par les développeurs de logiciels des Laboratoires Bell; le mode d'édition de ligne vi par Pat Sullivan, et le mode d'édition de ligne emacs par Mike Veach. Chacun avait indépendamment modifié le shell Bourne pour ajouter ces fonctionnalités, et tous deux faisaient partie d'organisations qui ne voulaient utiliser ksh que si ksh avait leur éditeur en ligne respectif. À l'origine, l'idée d'ajouter l'édition de ligne de commande à ksh a été rejetée dans l'espoir que l'édition de ligne se déplacerait dans le pilote du terminal. Cependant, lorsqu'il est devenu clair que cela ne se produirait probablement pas bientôt, les deux modes d'édition de ligne ont été intégrés dans ksh et rendus facultatifs afin qu'ils puissent être désactivés sur les systèmes qui fournissaient l'édition dans le cadre de l'interface du terminal.

Au lieu de cela, ils ont implémenté les deux et une interface permettant aux utilisateurs de choisir entre les deux. kshétait très probablement le premier au début des années 80 (réutilisation de code qui avait été écrit séparément pour ajouter un mode vi et un mode emacs au shell Bourne comme vu ci-dessus) suivi par tcsh( tcshinitialement, il n'y avait qu'une emacsliaison de clé, le vimode a été ajouté plus tard) et plus tard bashet zshau début des années 90.

Vous basculez entre les deux modes dans bash, zshou kshavec set -o viou set -o emacs, et avec bindkey -eou bindkey -vdans tcshou zsh.

POSIX spécifie en fait le vimode et non le emacsmode pour sh(l'histoire raconte que Richard Stallman s'est opposé à ce que POSIX spécifie le emacsmode poursh ).

Le mode par défaut bash, le domaine public variantes de ksh(pdksh, mksh, oksh), tcshet zshest le mode emacs (mais avec zsh, il est visi votre $EDITORest - vi), tandis que dans le AT & T ksh, il est le muet mode à moins $EDITORou les $VISUALmentions viou emacs.

ksha également ajouté plus tard un gmacsmode pour accueillir les utilisateurs de Gosling emacsqui géraient Ctrl+Tdifféremment.

Maintenant, la gestion de ^Win emacsou en tcshmode emacs est probablement antérieure au werasecaractère dans l'éditeur de ligne de terminal, donc nous ne pouvons pas vraiment leur en vouloir et ma déclaration sur le "départ ..." peut être considérée comme trompeuse. C'est juste que je trouve ça irritant quand des choses comme emacs, tcshou infose comportent différemment de tout le reste lorsque vous tapez Ctrl-W. Vous pouvez imaginer que je l'ai trouvé beaucoup plus irritant lorsque certaines applications ont commencé à fermer leur fenêtre lorsque vous avez tapé Ctrl-W.

Stéphane Chazelas
la source
1
pdkshparse également $EDITORpour viet commutateurs modes sur le démarrage; J'ai supprimé cela pour mksh(d'autant plus que je ne maintiens vraiment le mode Emacs de toute façon).
mirabilos
Merci beaucoup de plus, en particulier avec la discussion détaillée du comportement et de l'histoire des différents obus. En tant que personne qui doit régulièrement travailler dans différentes distributions avec des coques que je n'ai pas configurées, cela est extrêmement utile.
BryKKan
Merci pour l'excellent contexte historique. Il est dommage que des fonctionnalités d'édition en ligne plus sophistiquées n'aient pas été ajoutées au pilote de terminal à ce moment-là. Il ne serait pas nécessaire que les programmes incluent des bibliothèques telles que Readline. Je m'étais également demandé pourquoi le mode Emacs n'était pas spécifié par POSIX, donc ce lien vers la justification était intéressant. (Je partage également votre frustration de ^Wfermer des fenêtres).
Anthony G - justice pour Monica
1
@AnthonyGeoghegan, nous aurions encore besoin de choses comme zle / readline car des choses comme le nom de fichier / la complétion de commande ne pouvaient pas vraiment être faites dans le pilote du terminal.
Stéphane Chazelas