Как транспонировать аргументы командной строки с помощью сочетаний клавиш emacs?

Как транспонировать аргументы командной строки с помощью сочетаний клавиш emacs?

При использовании Bash с установленными сочетаниями клавиш emacs сочетание клавиш transpose-words ( M-t) переставляет не аргументы, а «слова» (согласно собственному определению слов).

Итак, если у меня есть это:

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

и мой курсор находится между первым и вторым аргументом, когда я ввожу optiont, вместо этого я получаю

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

что, очевидно, не то, что я хочу. Как мне переставить аргументы?

решение1

В bash разные команды имеют разные понятия слов.C-wудаляет предыдущий пробел, но большинство других команд M-tиспользуют слова, разделенные знаками пунктуации.

Поместив курсор между первым и вторым аргументом, C-w C-e SPC C-yможно поменять местами два слова.

Если вы хотите привязать клавишу к транспонированию слов, разделенных пробелами, то это сложнее. Смотритезапутанное поведение сочетаний клавиш в стиле emacs в bash. Вот минимально протестированный код.

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'

В zsh все это проще…

решение2

Если ваш курсор там:

vimdiff projectOne/Vagrantfile projectTwo/Vagrantfile
                              ^

Нажмите Alt + BTTBBTFTBBTT


Или просто:

Нажмите Ctrl+ W, Ctrl+ E, вставьте пробел и нажмите Ctrl+Y

решение3

Для быстрого и простого решения добавьте это в ваш inputrc (выберите подходящие для себя ключи):

"\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"

В случае shell-*версий этих функцийслова разделяются метасимволами оболочки, не заключенными в кавычки.

метасимвол

Символ, который, если не заключен в кавычки, разделяет слова. Метасимвол — это пробел, табуляция, новая строка или один из следующих символов: '|', '&', ';', '(', ')', '<' или '>'.

CtrlПримечание: перед нажатием + Alt+ курсор должен находиться после второго аргумента t, чтобы фактически переместить аргумент перед курсором в начало строки.

$ 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
                         ^

CtrlПримечание: перед нажатием + Alt+ курсор должен находиться после первого аргумента p, чтобы он фактически переместил аргумент перед курсором к концу строки.

$ 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"
                                                             ^

решение4

Вам нужно нажать BTTBBTвместо одного T.

Связанный контент