BashでのEmacsスタイルのキーバインディングの混乱した動作

BashでのEmacsスタイルのキーバインディングの混乱した動作

emacs-style keybindingsBashには便利でシンプルなコマンドライン編集機能がたくさんあります。たとえば、Ctrl+wカーソルの左側にある単語を削除(「kill」)します。

他のキーバインディングは、Alt+d最初のキーバインディングの「ミラー」でなければなりません。カーソルから単語を削除する必要があります。

しかし、私はこれら2つのキーバインディングの動作が完全に対称的ではないことを発見しました。 1つの単語Ctrl+wとして扱うのではなく、2つの単語として扱います。foo.barAlt+d

もっと迷惑なのは# echo二つの単語なのにCtrl+w一つの単語という点だAlt+d

これにロジックはありますか?彼らが言葉を同じように扱わない理由はありますか?

これを変える方法はありますか?

バッシュを使っていますDebian Wheezy

答え1

異なるbashコマンドは異なる単語の概念を使用します。コマンドの各コマンドの説明を表示する手動

C-w古い空白を殺します。M-DEL(通常Alt+)単語に文字と数字のみが含まれている前の単語の境界(と同じBackSpace)を削除し、同様に前に削除します。M-bM-fM-d

BashはReadlineライブラリを使用してユーザー入力を処理し、次の方法で設定できます。~/.inputrcまたは経由bind内蔵されています~/.bashrc。あるキーを別のキーにバインドできます。ラインコマンドの読み出しあなたがしたい場合。キーを変更された変数bind -xにバインドするbash関数を使用することもできます。READLINE_LINE

M-dたとえば、Kill 単語をシェル単語にするには、次のようにバインドします。shell-kill-wordあなたの.bashrc

bind '"\M-d": shell-kill-word'

スペースで区切られた単語を削除するには組み込みM-d関数がないため、マクロまたはシェル関数を作成する必要があります。スペースで区切られた単語からなる移動コマンドがないため、少なくともその部分には機能が必要です。

delete_whitespace_word () {
  local suffix="${READLINE_LINE:$READLINE_POINT}"
  if [[ $suffix =~ ^[[:space:]]*[^[:space:]]+ ]]; then
    local -i s=READLINE_POINT+${#BASH_REMATCH[0]}
    READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}${READLINE_LINE:$s}"
  fi
}
bind -x '"\ed": delete_whitespace_word'

M-d私が知っている限り、bashコードからkillループにアクセスする方法がないので、killをスペースで区切られた単語にするのはより複雑です。そのためには、削除するセクションの終わりを見つける関数と実際の削除に続くマクロが必要です。

forward_whitespace_word () {
  local suffix="${READLINE_LINE:$READLINE_POINT}" 
  if [[ $suffix =~ ^[[:space:]]*[^[:space:]]+ ]]; then
    ((READLINE_POINT += ${#BASH_REMATCH[0]}))
  else
    READLINE_POINT=${#READLINE_LINE}
  fi
}
bind -x '"\C-xF": forward_whitespace_word'
bind '"\C-x\C-w": kill-region'
bind '"\ed": "\e \C-xF\C-x\C-w"'

これらすべてがzshでははるかに簡単です。

答え2

Readline には単語の境界としてスペースを使用するvi-fwordand が既に存在しているため、Gilles の機能は必要ありません。vi-bwordforward_whitespace_word

vi-fword後にunix-word-rubout\C-w)がある場合は、スペースで区切られた単語を後ろに削除します(末尾のスペースを含む)。

bind '"\eb":vi-bword'
bind '"\ef":vi-fword'
bind '"\ed":"\ef\C-w"'

vi-backward-wordはいエイリアスvi-bword、はいエイリアス、はいエイリアスvi-forward-word、はいエイリアス。vi-fwordvi-backward-bigwordvi-bWordvi-forward-bigwordvi-fWord

答え3

方法の結果です読書船「単語」を扱います。Altd次のショートカットは次のとおりですkill-word

現在の単語の終わりで終了するか、単語の間にある場合は、次の単語の終わりまで終了します。単語の境界は Mf で使用されるものと同じです。(これからの言葉)。

の単語境界はforward-word次のように定義されます。

単語は文字と数字で構成されています。

代わりにCtrlwショートカットunix-word-rubout:

ドットの後ろの言葉を殺すスペースを単語の境界として使用

したがって、例を使用するために、最初のfoo.barコマンドは文字列を区切りの2つの「単語」として扱います.が、2番目のコマンドはスペースをチェックせず、単一の「単語」として扱います。

関連情報