Configurando aliases para um padrão de expansão de histórico

Configurando aliases para um padrão de expansão de histórico

semelhante ao existente $_que aprendi significa !-1:$, gostaria de criar aliases para $__, $___e assim por diante, que se refiram ao 2º ou 3º comando -último. Eu tentei adicionar

alias "$__"='!-2:$'

no meu .zshrc.local. Se possível, gostaria de escrever uma função zsh que devolva o primeiro argumento do enésimo último comando com base na quantidade de sublinhados.

arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)

Responder1

Esta funcionalidade já existe

Você não precisa de nada complicado para acessar a última palavra dos comandos anteriores. Basta pressionar ESC-.(ou seja Alt, + .) ou ESC-_(ou seja, Alt+ _). Isso invoca o comando do editorinsert-last-word, que insere a última palavra da linha de comando anterior. Pressione a tecla novamente para obter a última palavra da linha de comando antes disso e assim por diante. Se você pressionar ESC-.uma vez a mais, use C-_(desfazer) para voltar à palavra que você tinha antes.

Este comando não está vinculado a uma chave por padrão no modo vi, mas você pode vinculá-lo com bindkey.

Você pode passar um argumento numérico para obter uma palavra diferente: positivo para começar à direita (1 é a última palavra), zero ou negativo para começar à esquerda (0 é a primeira palavra que geralmente é o nome do comando, 1 é o palavra depois daquela que é o primeiro argumento, etc.). Por exemplo ESC . ESC - ESC 1 ESC ., insere o primeiro argumento do penúltimo comando.

Muitas variações deste comando são possíveis definindo seu próprio widget em torno de zle insert-last-word. Zsh vem comcopy-earlier-wordesmart-insert-last-wordque você pode achar útil para usar como está ou como exemplos de código.

Se você realmente deseja $__expandir para a última palavra do comando anterior, darei algumas soluções abaixo, mas primeiro preciso explicar o que está acontecendo.

Por que sua tentativa não está funcionando

Primeiro, você não está definindo o que pensa que está definindo. alias "$__"=…define um alias cujo nome é o valor atual da variável __no momento em que a definição do alias é executada. Provavelmente está vazio, então você está executando alias ='!-2:$'o que procura por um comando chamado '!-2:$'no caminho de pesquisa (o=expansãoparte da expansão do nome do arquivo). Para definir um alias chamado $__, você precisa passar $__para o comando alias, por exemplo, com alias '$__'=…ou alias \$__=….

Em segundo lugar, um alias só é expandido na posição de comando, ou seja, como a primeira palavra de um comando (após quaisquer atribuições e redirecionamentos de variáveis ​​iniciais). Para que esse alias seja útil, ele precisaria ser umapelido global:alias -g '$__'=…

Terceiro, esse alias não faria nada de útil, porque a expansão do alias ocorre após a expansão do histórico.

darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$

$_não “representa” !-1:$. $_e !-1:$são duas maneiras de acessar as mesmas informações em casos comuns. Você pode dizer que $_“é um alias” de !-1:$, ou inversamente, que !-1:$“é um alias” de $_, mas isso é usar “alias” em seu sentido geral em inglês, não no sentido técnico de aliases de shell, e é impreciso porque os dois não t sempre o mesmo valor. !-1:$é umexpansão da história( !) construção que se expande para oúltima palavra( :$) dolinha de comando anterior( -1). $_é umparameter expansionusando o parâmetro_que o shell define como o último argumento do comando anterior. Faz diferença se você executar linhas de comando que não sejam exatamente um comando simples, por exemplo:

darkstar% for x in 1 2 3; do echo $x; done
1
2
3
darkstar% echo $_ is not !-1:$
echo $_ is not done
3 is not done
darkstar% echo $_ and !-1:$ are different; echo $_ and !-1:$ are different
echo $_ and done are different; echo $_ and done are different
done and done are different
different and done are different

Definindo $__por comando

Você pode definir umfunção de armadilhachamadoTRAPDEBUGque é executado antes de executar cada comando. Lembre-se do valor atual de $_(observe que você deve fazer isso primeiro, porque o primeiro comando dentro do trap irá sobrescrever _) e, em seguida, “desloque” as variáveis ​​com múltiplos sublinhados.

darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one        
one
darkstar% echo two        
two
darkstar% echo three      
three
darkstar% echo $_,$__,$___
three,two,one

$_1nem sempre será o mesmo que $_, porque a armadilha de depuração não é executada exatamente nas mesmas circunstâncias que a definem _, mas é bem próxima.

Definindo $__por linha de comando

Você pode registrar umfunção de ganchopara ser executado antes ou depois de inserir uma linha de comando. Neste caso, ouprecmdoupreexec. Eles são executados antes e depois da execução de um comando, respectivamente.

preexec_set_underscore_variables () {
  ___=$__
  __=$_1
  _1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)

eu usohistorywordspara obter a última palavra da linha de comando. Eu guardo _1porque _já está levado. E a função “desloca” as variáveis ​​do histórico da última palavra em um.

darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one

informação relacionada