web-dev-qa-db-ja.com

Zshは、現在の引数リストの最後の要素を参照して展開します

私が次のようなことをしたとしましょう:

ln a_file_with_a_long_filename.pdf ~/path/to/a/new/hardlink/a_file_with_a_long_filename_slightly_modified.pdf

カーソルがzshの文字列a_file_with_a_long_filename.pdfの末尾にある場合、ln a_file_with_a_long_filename.pdf ~/path/to/a/new/hardlink/を参照して展開する方法はありますか?

そうでない場合、タイピング作業を減らすために何を提案しますか?

3
student

これは楽しいコードゴルフチャレンジのように聞こえます。 1つのオプションがあります:

  1. ファイル名を使用して無害なコマンドを実行します。 TAB補完を可能にするのに十分なファイル名を入力します。

    : a_file<TAB>
    
  2. !!$を使用して、前のコマンドの最後の引数を参照します。

    ln !!$ ~/path/to/a/new/hardlink/!!$
    

Zshの便利な引用のおかげで、これはIFSを含むファイル名に直面しても安全です。最初の!!$の後にスペースを入れるとすぐに、zshがファイル名を展開することに気付くでしょう。コマンドの最後に無償のスペースを追加した場合も同様です。

必要な文字数は次のとおりです。

  • 2つの場合は3x 2 = 6 !!$
  • :<SPACE>の場合は2

8 +プラス、最初のタブ補完に十分です。

1
Jeff Schaller

デフォルトのEmacsバインディングでは、それはたった2つのキーコードです:ESC-2 ESC-^_(つまり、 Esc2EscCtrl+_ または Alt+2Ctrl+Alt+_)。これがコマンド copy-prev-Word で、数値引数2を使用します(デフォルトの引数1は~/path/to/a/new/hardlink/をコピーします)。ファイル名に(引用符で囲まれた)スペースが含まれている場合は、ESC-2 ESC-x copy-prev-Shell-Word RETが必要になります。特にキーボードレイアウトで必要な場合は、このコマンドをより便利なキーにバインドすることをお勧めします Shift にとって _。これらのコマンドはviモードでも使用できますが、デフォルトではどちらもキーにバインドされていません。

数値引数を間違えた場合は、 Ctrl+_ 元に戻すには、もう一度やり直してください。

copy-earlier-Word があります。これらの行を~/.zshrcに追加して使用する前に、お気に入りのキーバインドにバインドできます。

autoload -Uz copy-earlier-Word
zle -N copy-earlier-Word
bindkey "^[," copy-earlier-Word

したがって、コマンドラインで次のように使用できます。

% ln a_file_with_a_long_filename.pdf ~/path/to/a/new/hardlink/<Esc-,><Esc-,>

(の最初のキー押下 Esc-,(または Alt+,)は copy-prev-Shell-Word のように「〜/ path/to/new/hardlink /」を生成し、2回目は新しく挿入されたWordを「a_file_with_a_long_filename.pdf」に置き換えます。


参考までに copy-earlier-Word ドキュメントのコピーを次に示します。

このウィジェットは、 insert-last-Wordcopy-prev-Shell-Word の組み合わせのように機能します。ウィジェットを繰り返し呼び出すと、関連する履歴行の以前の単語が取得されます。数値引数[〜#〜] n [〜#〜]を使用して、[〜#〜]を挿入しますn [〜#〜]th履歴行からの単語。 [〜#〜] n [〜#〜]は、行の終わりから数えると負になる場合があります。

insert-last-Word を使用して前の履歴行の最後の単語を取得した場合、呼び出しを繰り返すと、その単語が同じ行の前の単語に置き換えられます。

それ以外の場合、ウィジェットは現在編集中の行の単語に適用されます。ウィジェットスタイルは、単語を取得するために呼び出す必要がある別のウィジェットの名前に設定できます。このウィジェットは、 insert-last-Word と同じ3つの引数を受け入れる必要があります。

- copy-earlier-Word ZLE関数、ウィジェット、zshcontrib(1)

1
hchbaw

viモードでは、これは<esc>0wyt $pになり、コマンドモードになります。0行の先頭、wは次の単語になります(ファイル名の前に)yt yank to space(ファイル名にスペースがないと仮定して、長いファイル名を取得するため)、次に$pを使用して、ヤンクされたばかりのものを行の最後に配置します。これは、viモーションを覚えたら説明するよりもはるかに高速です。

bindkeyを設定して2番目の引数をヤンクすることもできますが、これはそのようなユースケースのかなり具体的なコードであり、ここでは control+t しかし、それはあなたが望むものなら何でもかまいません。

function yank-put {
  local -a words
  words=(${(z)LBUFFER})
  if (( $#words > 1 )); then
    BUFFER+=$words[2]
    CURSOR+=${#words[2]}
  fi
}
zle -N yank-put
autoload -U yank-put compinit
compinit
set -o vi
bindkey -M viins "^t" yank-put
0
thrig