Como especificar argumentos de comando para bind -x com base no histórico?

3

Digamos que eu tenha um comando chamado synopsis, que usa o nome de um comando como argumento e imprime sua sintaxe. Agora quero ligar a sinopse a uma sequência de teclas. Como posso passar o nome do comando na linha de comando atual para sinopse? Este é um exemplo do comportamento desejado:

1$ bind -x '"\C-h": synopsis !#:0'
2$ ls -F^H 
<ls syntax print out from synopsis> 
3$ ls -F

Sinopse é invocada em 2, mas não há expansão de histórico. Eu obtenho a string '! #: 0' em vez de 'ls'. Nada parece funcionar: - /

    
por Nelson 20.02.2017 / 20:07

2 respostas

1

Em uma função que é ligada a uma chave, você pode acessar e modificar o conteúdo atual da linha de comando através das variáveis READLINE_LINE e READLINE_POINT . Prova de conceito (código não testado):

synopsis () (
  set -f
  IFS=$'\t\n\r ;&|'
  words=($READLINE_LINE)
  while [[ "${words[1]}" == @([<>]*|[A-Za-z0-9_]##=) ]]; do
    shift words
  done
  command=${words[1]}
  "$command" --help
)
bind -x '"\C-h": synopsis'

O método que você tentou com a expansão do histórico não funciona. A expansão do histórico é executada quando uma linha de comando é executada. Ao invocar uma ligação, não há histórico para expandir.

Mas o seu problema fundamental é que sua concha não é legal o suficiente . Esse recurso já existe no zsh, chamado run-help .

bash$ echo 'autoload run-help' >~/.zshrc
bash$ zsh
darkstar% ls -FAlt+h
    
por 21.02.2017 / 02:49
1

Uma possibilidade é usar bind sem -x , inserindo synopsis no início da linha:

bind "'\C-h": "\C-asynopsis \C-j"

Isso seria ok com um argumento. Uma versão mais complexa seria:

bind '"\C-h": "\C-e !#:0\e^\e\C-] \C-usynopsis\C-j"'

Quebrando:

'\C-e '    end-of-line
' !#:0'    insert space and 1st argument of current line
'\e^'      history-expand-line
'\e\C-] '  character-search-backward (to last space)
'\C-u'     unix-line-discard (delete to beginning of line)
'synopsis' insert 'synopsis' in front of the first argument
'\C-j'     accept-line

Isso lida com uma linha com vários argumentos, executando synopsis apenas com o primeiro argumento. (Eu também talvez usaria "\C-xh" ou "\eh" em vez de "\C-h" , que já pode ser apagado / retrocesso / "backward-delete-char".)

    
por 21.02.2017 / 03:59