Cosa si intende per shell in modalità "vi" o "emacs"?


32

Questa domanda segue direttamente la risposta . In questo caso non sono specificamente in grado di comprendere la parte che dice:

A tale proposito, il suo comportamento è più vicino a emacs 'che con la modalità emacs bash (readline) / ksh / zsh, ma si discosta dall'editor di linea incorporato del driver terminale (in modalità canonica), dove Ctrl-Wcancella la parola precedente (werase, anche in vi ).

Qui stiamo parlando di shell e non di editor che sono due programmi completamente diversi. Cosa significa dire che la shell è in una modalità editor?

PS: Puoi basare la tua risposta sul presupposto che capisco cos'è una shell e come usare vim per l'editing di base.


Non si tratta della funzionalità della shell principale in sé, ma piuttosto della modifica della linea (cosa fai quando fai un refuso e torni indietro e correggi te stesso).
n. 'pronomi' m.

Risposte:


27

In modalità "vi" è possibile modificare / navigare sul prompt della shell corrente come una riga nell'editor vi. Puoi vederlo come un file di testo a una riga. Analogamente in modalità "emacs" puoi modificare / navigare nella riga di comando corrente usando (alcune) le scorciatoie di Emacs.

Esempio

Ad esempio in vi-mode puoi fare qualcosa del tipo (in bash):

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

In modalità emacs puoi premere ad es. Ctrl+ APer saltare all'inizio di una linea (vi: Ctrl+ [, 0o ESC, 0). Puoi attivare la modalità emacs tramite set -o emacs(in bash, ksh, zsh ecc.).

Linea di lettura

Molti programmi interattivi da riga di comando (incluso bash ) usano la libreria readline . Pertanto, è possibile configurare quale modalità di input utilizzare (vi o emacs) e altre opzioni in un unico posto in modo tale che ogni programma che utilizza readline abbia la stessa identica interfaccia di modifica / navigazione.

Ad esempio la mia configurazione readline assomiglia a:

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

Ad esempio zsh / ksh non usa readline per quanto ne so, ma supporta anche modalità vi / emacs che sono molto simili a quella bash / readline.

Naturalmente, la modalità vi / emacs in una shell della riga di comando è solo un sottoinsieme del set completo di funzioni dell'editor. Non tutte le funzionalità hanno senso in una shell della riga di comando e alcune funzionalità sono più complicate da supportare rispetto ad altre.

Modalità canonica

Prima che le modalità vi / emacs delle shell interattive della riga di comando "venissero inventate", la shell usava solo la modalità canonica del terminale che fornisce solo un numero limitato di comandi di modifica (ad es. Ctrl+ WPer eliminare l'ultima parola.


Supponiamo di non sapere su quale modalità di input sono attivo. Posso verificarlo inserendo del testo e premere [Ctrl] + [A]? se il cursore si sposta all'inizio dei suoi emacs altrimenti vi?
limovala,

2
@limovala, dovrebbe essere una buona approssimazione. Dipende ovviamente dalla shell: se CTL + A non funziona, un'altra possibilità è che la shell non includa alcuna modalità di modifica. Forse alcune shell implementano anche altre modalità di modifica. Ma in pratica il tuo metodo dovrebbe essere abbastanza buono. Puoi anche provare con un comando vi dopo quello per essere più sicuro. In bash puoi anche usare qualcosa di simile set -o | grep 'emacs\|vi'. In zsh (dove ho vi-mode), tuttavia, non funziona.
maxschlepzig,

bind -P fornirà anche una buona indicazione della modalità in cui ci si trova
Paul

23

Noterai che quando esegui catun prompt della shell su un terminale, catdovendo scrivere a stdout ciò che legge da stdin, e premi a, vedi un aeco restituito dal driver del terminale, ma catnon lo scrive a(vedi solo uno a, quello echeggiato dal driver del terminale).

Tuttavia, se digiti a Backspace b Enter, non vedi l' catoutput a\010b\015, ma b\012( be la nuova riga).

Questo perché il driver del terminale (stiamo parlando di software nel kernel, non nell'emulatore di terminale come xterm) implementa un editor di linee molto semplice quando è in modalità canonica . Il driver del terminale può essere configurato utilizzando ioctl()le chiamate di sistema come quando si utilizza il sttycomando. Ad esempio, per uscire dalla modalità canonica, puoi farlo stty -icanon. Se fate:

stty -icanon; cat

Quindi vedrai sia l' output echo(con il quale potresti aver disabilitato stty -echo) sia l' catoutput.

Quell'editor è un editor di linee. Cioè, spetta all'utente modificare una riga di testo fino a quando non viene inviato all'applicazione leggendo il dispositivo terminale dopo aver premuto Enter.

Le capacità di modifica di quell'editor sono molto limitate. Nella maggior parte delle implementazioni, ci sono solo 4 chiavi di modifica (in realtà caratteri) configurabili anche con stty:

  • cancella ( ^Ho di ^?solito): cancella il carattere precedente
  • kill (di ^Usolito): svuota (uccide) la riga inserita finora
  • werase ( ^W): cancella la parola precedente
  • lnext ( ^V): inserisci il carattere successivo letteralmente (annulla il significato speciale di tutto quanto sopra)

Ai vecchi tempi, si pensava che quell'editor di linea del driver terminale sarebbe stato esteso con funzionalità più elaborate. Questo è il motivo per cui nessuna delle prime shell ha funzionalità di modifica della riga di comando (al prompt della shell si otterrebbero le stesse funzionalità di modifica della riga rispetto a quando si esegue catcome descritto sopra).

Tuttavia, ciò non è mai accaduto, forse parte del motivo è che il caos con terminali diversi non ha inviato gli stessi caratteri su alcune pressioni di tasti, il che ha reso evidente che non dovrebbe essere implementato nello spazio del kernel.

Quindi alcune shell hanno iniziato a abbandonare la modalità canonica del driver del terminale e ad implementare il proprio editor di linee. A quel tempo, emacse visono stati i più popolari editor di testo visivo con la modalità di rilegatura chiave e il funzionamento completamente diverso. In vi, hai una modalità per l'immissione del testo e una per la modifica. In emacs, stai sempre entrando in modalità testo , ma la modifica viene effettuata premendo le combinazioni di tasti (come ^bspostare il personaggio all'indietro).

All'epoca non aveva senso che le shell trovassero il loro diverso key binding. Ciò avrebbe causato frustrazione alle persone che dovevano imparare qualcosa di diverso. Tuttavia, scegliere uno ( emacso vi) stile rispetto all'altro sarebbe stato un modo sicuro per alienare gli utenti dell'altro editor.

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

Le popolari funzionalità di modifica in linea (modalità vi ed emacs) di ksh sono state create dagli sviluppatori software dei Bell Laboratories; la modalità di modifica della linea vi di Pat Sullivan e la modalità di modifica della linea emacs di Mike Veach. Ognuno aveva modificato in modo indipendente la shell Bourne per aggiungere queste funzionalità, ed entrambi facevano parte delle organizzazioni che volevano usare ksh solo se ksh aveva il loro rispettivo editor inline. Inizialmente l'idea di aggiungere la modifica della riga di comando a ksh è stata respinta nella speranza che la modifica della riga si spostasse nel driver del terminale. Tuttavia, quando è diventato chiaro che ciò non sarebbe successo presto, entrambe le modalità di modifica della linea sono state integrate in ksh e rese opzionali in modo da poter essere disabilitate sui sistemi che fornivano l'editing come parte dell'interfaccia del terminale.

Quindi, invece, hanno implementato entrambi e un'interfaccia per gli utenti di scegliere tra i due. kshfu probabilmente il primo nei primi anni '80 (riutilizzando il codice che era stato scritto separatamente per aggiungere una modalità vi e una modalità emacs alla shell Bourne come visto sopra) seguito da tcsh( tcshinizialmente aveva solo l' emacsassociazione delle chiavi, la vimodalità fu aggiunta in seguito) e successivamente bashe zshnei primi anni '90.

Si passa tra le due modalità in bash, zsho kshcon set -o vio set -o emacs, e con bindkey -eo bindkey -vin tcsho zsh.

POSIX in realtà specifica la vimodalità e non la emacsmodalità per sh(la storia ha che Richard Stallman si è opposto a POSIX specificando la emacsmodalità persh ).

La modalità predefinita per bash, le varianti di dominio pubblico di ksh(pdksh, mksh, oksh), tcshed zshè la modalità emacs (sebbene con zsh, è vise lo $EDITORè vi), mentre in AT&T ksh, è la modalità stupida a meno che $EDITORo $VISUALmenzioni vio emacs.

kshinoltre in seguito ha aggiunto una gmacsmodalità per soddisfare gli utenti di Gosling emacsche ha gestito in modo Ctrl+Tdiverso.

Ora la gestione della modalità ^Win emacso in tcshemacs probabilmente precede il werasecarattere nell'editor della linea terminale, quindi non possiamo davvero biasimarli per questo e la mia affermazione su "partire ..." può essere vista come fuorviante. E 'solo che trovo irritante quando le cose come emacs, tcsho infocomportarsi in modo diverso da tutto il resto quando si digita Ctrl-W. Puoi immaginare che l'ho trovato molto più irritante quando alcune applicazioni hanno iniziato a chiudere la finestra quando hai digitato Ctrl-W.


1
pdkshanalizza anche $EDITORper vie commuta le modalità su avvio; L'ho rimosso per mksh(specialmente perché mantengo la modalità Emacs solo in ogni caso).
mirabilos,

Grazie mille aggiunta, soprattutto con la discussione dettagliata del comportamento e della storia di varie conchiglie. Come qualcuno che è regolarmente tenuto a lavorare in diverse distribuzioni con shell non ho configurato, questo è straordinariamente utile.
BryKKan,

Grazie per l'ottimo contesto storico. È un peccato che le funzioni di modifica in linea più sofisticate non siano state aggiunte al driver del terminale in quel momento. Non sarebbe necessario che i programmi includessero librerie come Readline. Mi ero anche chiesto perché la modalità Emacs non è stata specificata da POSIX, quindi quel collegamento alla Rationale era interessante. (Condivido anche la tua frustrazione con la ^Wchiusura di Windows).
Anthony G - giustizia per Monica il

1
@AnthonyGeoghegan, avremmo ancora bisogno di cose come zle / readline poiché cose come il completamento del nome file / comando non potevano davvero essere eseguite nel driver del terminale.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.