O que se entende por um shell está no modo "vi" ou "emacs"?

32

Esta pergunta segue diretamente da resposta . Neste caso, sou especificamente incapaz de entender a parte que diz:

Nesse sentido, seu comportamento é mais próximo do emacs do que no modo bash (readline) / ksh / zsh emacs, mas parte do editor de linha incorporado do driver do terminal (no modo canônico), onde Ctrl-Wexclui a palavra anterior (werase, também no vi )

Aqui estamos falando de shells e não de editores, que são dois programas completamente diferentes. O que significa dizer que o shell está em algum modo de editor?

PS: Você pode basear sua resposta na premissa de que eu entendo o que é um shell e como usar o vim para edição básica.

Nerd
fonte
Não se trata da funcionalidade principal do shell em si, mas da edição de linhas (o que você faz quando digita um erro e volta e se corrige).
n. 'pronomes' m.

Respostas:

27

No modo "vi", você pode editar / navegar no prompt do shell atual como uma linha no editor vi. Você pode vê-lo como um arquivo de texto de uma linha. Analogamente, no modo "emacs", você pode editar / navegar na linha de comando atual usando (alguns) os atalhos do Emacs.

Exemplo

Por exemplo, no modo vi, você pode fazer algo como (no bash):

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

Em emacs-mode você pode bater por exemplo Ctrl+ Apara saltar no início de uma linha (vi: Ctrl+ [, 0ou ESC, 0). Você pode ativar o modo emacs via set -o emacs(no bash, ksh, zsh etc.).

Leia a linha

Muitos programas interativos de linha de comando (incluindo o bash ) usam a biblioteca readline . Assim, você pode configurar qual modo de entrada usar (vi ou emacs) e outras opções em um único local, de modo que todos os programas que usam o readline tenham exatamente a mesma interface de edição / navegação.

Por exemplo, minha configuração de linha de leitura se parece com:

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

Por exemplo, zsh / ksh não usa o readline até onde eu sei, mas também suporta modos vi / emacs que são muito parecidos com o bash / readline.

Obviamente, o modo vi / emacs em um shell de linha de comando é apenas um subconjunto do conjunto completo de recursos do editor. Nem todo recurso faz sentido em um shell de linha de comando, e alguns recursos são mais complicados de oferecer suporte do que outros.

Modo canônico

Antes que os modos vi / emacs de shells interativos de linha de comando 'fossem inventados', seu shell usaria apenas o modo canônico do seu terminal, que fornece apenas um conjunto limitado de comandos de edição (por exemplo, Ctrl+ Wpara excluir a última palavra.

maxschlepzig
fonte
Suponha que eu não saiba em qual modo de entrada estou. Posso verificá-lo inserindo algum texto e pressionar [Ctrl] + [A]? se o cursor se move para iniciar seu emacs, mais ele vi?
limovala
2
@limovala, deve ser uma boa aproximação. Depende do seu shell, é claro - se o CTL + A não funcionar, outra possibilidade é que o seu shell não inclua nenhum modo de edição. Talvez algumas conchas também implementem outros modos de edição. Mas, na prática, seu método deve ser bom o suficiente. Você também pode testar com um comando vi depois disso para ter mais certeza. No bash, você também pode usar algo como set -o | grep 'emacs\|vi'. No zsh (onde eu tenho o modo vi), isso não funciona.
maxschlepzig
bind -P também dará uma boa indicação de qual é o modo em que está
Paul
23

Você notará que, quando você executa catum prompt de shell em um terminal, catdeve escrever para stdout o que lê de stdin, e pressionar a, você vê um aeco de volta pelo driver do terminal, mas catnão escreve isso a(você vê apenas um a, aquele ecoado pelo driver do terminal).

No entanto, se você digitar a Backspace b Enter, não verá a catsaída a\010b\015, mas b\012( be nova linha).

Isso ocorre porque o driver do terminal (estamos falando de software no kernel, não no emulador de terminal xterm) implementa um editor de linhas muito básico quando no modo canônico . O driver do terminal pode ser configurado usando ioctl()chamadas do sistema, como ao usar o sttycomando Por exemplo, para sair do modo canônico, você pode fazer stty -icanon. Se você fizer:

stty -icanon; cat

Em seguida, você verá o echo(com o qual você poderia ter desativado stty -echo) e a catsaída ao mesmo tempo.

Esse editor é um editor de linha. Ou seja, cabe ao usuário editar uma linha de texto até que seja enviada ao aplicativo que lê o dispositivo terminal ao pressionar Enter.

Os recursos de edição desse editor são muito limitados. Na maioria das implementações, existem apenas 4 chaves de edição (na verdade caracteres) também configuráveis ​​com stty:

  • apagar ( ^Hou ^?geralmente): apaga o caractere anterior
  • kill ( ^Ugeralmente): vazio (kill) a linha inserida até o momento
  • werase ( ^W): apaga a palavra anterior
  • lnext ( ^V): insira o próximo caractere literalmente (cancele o significado especial de todos os itens acima)

Antigamente, pensava-se que esse editor de linha de driver de terminal seria estendido com recursos mais sofisticados. É por isso que nenhum dos shells anteriores possui recursos de edição de linha de comando (você obteria os mesmos recursos de edição de linha no prompt do shell do que quando executava catcomo fizemos acima).

No entanto, isso realmente nunca aconteceu, talvez parte do motivo seja a bagunça com terminais diferentes que não enviam os mesmos caracteres em algumas teclas pressionadas, o que tornou evidente que isso não deve ser implementado no espaço do kernel.

Assim, alguns shells começaram a abandonar o modo canônico do driver do terminal e a implementar seu próprio editor de linha. Na época, emacse vieram os editores visuais de texto mais populares com ligação de teclas e modo de operação completamente diferentes. Em vi, você tem um modo para inserir texto e outro para editar. Em emacs, você está sempre entrando no modo de texto , mas a edição é feita pressionando as combinações de teclas (como ^bmover o caractere para trás).

Não havia nenhum ponto para as conchas no momento apresentarem suas próprias chaves diferentes. Isso causaria frustração para as pessoas terem que aprender outra. No entanto, escolher um ( emacsou vi) estilo sobre o outro teria sido uma maneira de alienar os usuários do outro editor.

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

Os populares recursos de edição em linha (modo vi e emacs) do ksh foram criados por desenvolvedores de software nos Laboratórios Bell; o modo de edição de linha vi, de Pat Sullivan, e o modo de edição de linha emacs, de Mike Veach. Cada um deles modificou independentemente o shell Bourne para adicionar esses recursos, e ambos estavam em organizações que queriam usar o ksh apenas se o ksh tivesse seu respectivo editor embutido. Originalmente, a idéia de adicionar edição de linha de comando ao ksh foi rejeitada na esperança de que a edição de linha passasse para o driver do terminal. No entanto, quando ficou claro que não era provável que isso acontecesse em breve, os dois modos de edição de linha foram integrados ao ksh e tornaram-se opcionais para que pudessem ser desativados em sistemas que forneciam edição como parte da interface do terminal.

Então, em vez disso, eles implementaram ambos e uma interface para os usuários escolherem entre os dois. kshfoi provavelmente o primeiro no início dos anos 80 (reutilizando código que foi escrito separadamente para adicionar um modo vi e um modo emacs ao shell Bourne, como visto acima), seguido por tcsh( tcshinicialmente só tinha emacsligação de teclas, o vimodo foi adicionado posteriormente) e mais tarde bashe zshno início dos anos 90.

Você alterna entre os dois modos em bash, zshou kshcom set -o viou set -o emacs, e com bindkey -eou bindkey -vem tcshou zsh.

O POSIX na verdade especifica o vimodo e não o emacsmodo sh(a história mostraemacssh que Richard Stallman se opôs ao POSIX especificar o modo para ).

O modo padrão para bash, as variantes de domínio público de ksh(pdksh, mksh, oksh) tcshe zshé o modo emacs (embora com zsh, seja vise você $EDITORfor vi), enquanto na AT&T kshé o modo burro , a menos que $EDITORou $VISUALmencione viou emacs.

kshposteriormente, também adicionou um gmacsmodo para acomodar os usuários de Gosling emacsque lidavam de maneira Ctrl+Tdiferente.

Agora a manipulação de ^Wem emacsou em tcshmodo de emacs, provavelmente antecede a werasepersonagem no editor de linha terminal, por isso não podemos culpá-los por isso e minha declaração sobre "partida ..." pode ser visto como enganosa. É só que eu acho que é irritante quando as coisas gostam emacs, tcshou infose comportam de maneira diferente de tudo o resto quando você digita Ctrl-W. Você pode imaginar que eu achei muito mais irritante quando alguns aplicativos começaram a fechar a janela quando você digitou Ctrl-W.

Stéphane Chazelas
fonte
1
pdkshtambém analisa $EDITORpor vie alterna modos na inicialização; Eu removi isso para mksh(especialmente porque eu realmente só mantenho o modo Emacs de qualquer maneira).
mirabilos
Muito obrigado, especialmente com a discussão detalhada do comportamento e da história de várias conchas. Como alguém regularmente solicitado a trabalhar em diferentes distros com shells que não configurei, isso é extraordinariamente útil.
BrykKan # 1/17
Obrigado pelo excelente contexto histórico. É uma pena que recursos de edição em linha mais sofisticados não tenham sido adicionados ao driver do terminal naquele momento. Não haveria necessidade de programas incluirem bibliotecas como o Readline. Também me perguntava por que o modo Emacs não é especificado pelo POSIX, para que o link para o Rationale fosse interessante. (Eu também compartilho sua frustração com o ^Wfechamento de janelas).
Anthony G - justiça para Monica
1
@AnthonyGeoghegan, ainda precisaríamos de coisas como zle / readline, pois coisas como nome de arquivo / conclusão de comando não poderiam realmente ser feitas no driver do terminal.
Stéphane Chazelas