コマンドライン引数を emacs キーバインディングで転置するにはどうすればいいですか?

コマンドライン引数を emacs キーバインディングで転置するにはどうすればいいですか?

Bash を使用し、emacs キーバインディングを設定すると、transpose-words キーバインディング ( M-t) は引数を転置するのではなく、「単語」(単語の独自の定義による) を転置します。

つまり、次のような場合です:

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

カーソルが最初の引数と2番目の引数の間にある場合optiont、代わりに次のように表示されます。

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

これは明らかに私が望んでいることではありません。どうすれば引数を転置できるでしょうか?

答え1

bash では、コマンドによって単語の概念が異なります。C-wは前の空白文字までを削除しますが、他のほとんどのコマンドではM-t句読点で区切られた単語が使用されます。

最初の引数と 2 番目の引数の間にカーソルを置くと、C-w C-e SPC C-y2 つの単語が入れ替わります。

空白で区切られた単語の転置にキーをバインドしたい場合は、より複雑になります。bash における emacs スタイルのキーバインディングの紛らわしい動作以下は最小限テストされたコードです。

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+ WCtrl+を押し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+を押す前にカーソルを 2 番目の引数の後に置く必要があります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を 1 回押す代わりにを押す必要がありますT

関連情報