Como transpor argumentos de linha de comando com atalhos de teclado do emacs?

Como transpor argumentos de linha de comando com atalhos de teclado do emacs?

Usando o Bash, com os atalhos de teclado do emacs definidos, o atalho de teclado transpose-words ( M-t) não transpõe argumentos, mas "palavras" (por sua própria definição de palavras).

Então, se eu tiver isso:

vimdiff project-number-One/Vagrantfile project-number-Two/Vagrantfile.old

e meu cursor está entre o primeiro e o segundo argumento quando eu entro optiont, acabo com

vimdiff project-number-One/project Vagrantfile-number-Two/Vagrantfile.old

o que obviamente não é o que eu quero. Como posso transpor argumentos?

Responder1

No bash, comandos diferentes têm noções diferentes de palavras.C-wmata para o espaço em branco anterior, mas a maioria dos outros comandos, incluindo, M-tusam palavras delimitadas por pontuação.

Com o cursor entre o primeiro e o segundo argumento, C-w C-e SPC C-yirá transpor as duas palavras.

Se você quiser vincular uma chave à transposição de palavras delimitadas por espaços em branco, é mais complicado. Vercomportamento confuso de atalhos de teclado no estilo emacs no bash. Aqui está um código minimamente testado.

transpose_whitespace_words () {
  local prefix=${READLINE_LINE:0:$READLINE_POINT} suffix=${READLINE_LINE:$READLINE_POINT}
  if [[ $suffix =~ ^[^[:space:]] ]] && [[ $prefix =~ [^[:space:]]+$ ]]; then
    prefix=${prefix%${BASH_REMATCH[0]}}
    suffix=${BASH_REMATCH[0]}${suffix}
  fi
  if [[ $suffix =~ ^[[:space:]]+ ]]; then
    prefix=${prefix}${BASH_REMATCH[0]}
    suffix=${suffix#${BASH_REMATCH[0]}}
  fi
  if [[ $prefix =~ ([^[:space:]]+)([[:space:]]+)$ ]]; then
    local word1=${BASH_REMATCH[1]} space=${BASH_REMATCH[2]}
    prefix=${prefix%${BASH_REMATCH[0]}}
    if [[ $suffix =~ [^[:space:]]+ ]]; then
      suffix=${suffix#${BASH_REMATCH[0]}}
      READLINE_LINE=${prefix}${BASH_REMATCH[0]}$space$word1$suffix
      READLINE_POINT=$((${#READLINE_LINE} - ${#suffix}))
    fi
  fi
}
bind -x '"\e\C-t": transpose_whitespace_words'

Tudo isso é mais fácil no zsh…

Responder2

Se o seu cursor estiver lá:

vimdiff projectOne/Vagrantfile projectTwo/Vagrantfile
                              ^

Pressione Alt + BTTBBTFTBBTT


Ou simples:

Pressione Ctrl+ W, Ctrl+ E, insira um espaço em branco e pressione Ctrl+Y

Responder3

Para uma solução rápida e simples, adicione isto ao seu inputrc (escolha as teclas adequadas para você):

"\e\C-b": shell-backward-kill-word
"\eh": shell-backward-word
"\e\C-f": shell-forward-word
# Swap the preceding two arguments (control + alt + t)
"\e\C-t": "\e\C-b\eh\C-y"
# Swap the preceding argument with the next (control + alt + p)
"\e\C-p": "\e\C-b\e\C-f\C-y"

No caso de shell-*versões destas funçõesas palavras são delimitadas por metacaracteres de shell não citados.

metacaractere

Um caractere que, quando não citado, separa palavras. Um metacaractere é um espaço, tabulação, nova linha ou um dos seguintes caracteres: '|', '&', ';', '(', ')', '<' ou '>'.

Nota: O cursor deve estar após o segundo argumento antes de pressionar Ctrl+ Alt+ t, para que ele efetivamente empurre o argumento antes do cursor em direção ao início da linha.

$ true foo/bar.xyz even/without\ quotes.ok "too/too far.away"
                                                             ^
$ true foo/bar.xyz "too/too far.away" even/without\ quotes.ok
                                     ^
$ true "too/too far.away" foo/bar.xyz even/without\ quotes.ok
                         ^

Nota: O cursor deve estar após o primeiro argumento antes de pressionar Ctrl+ Alt+ p, portanto, ele efetivamente puxa o argumento antes do cursor para o final da linha.

$ true "too/too far.away" foo/bar.xyz even/without\ quotes.ok
                         ^
$ true foo/bar.xyz "too/too far.away" even/without\ quotes.ok
                                     ^
$ true foo/bar.xyz even/without\ quotes.ok "too/too far.away"
                                                             ^

Responder4

Você precisa pressionar BTTBBTem vez de um único T.

informação relacionada