Wie transponiert man Befehlszeilenargumente mit Emacs-Tastenkombinationen?

Wie transponiert man Befehlszeilenargumente mit Emacs-Tastenkombinationen?

Bei Verwendung von Bash mit festgelegten Emacs-Tastenkombinationen transponiert die Tastenkombination „transpose-words“ ( M-t) keine Argumente, sondern „Wörter“ (gemäß ihrer eigenen Definition von Wörtern).

Wenn ich also Folgendes habe:

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

und mein Cursor steht zwischen dem ersten und zweiten Argument, wenn ich eingebe optiont, erhalte ich stattdessen

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

was offensichtlich nicht das ist, was ich will. Wie kann ich Argumente transponieren?

Antwort1

In Bash haben verschiedene Befehle unterschiedliche Wortbedeutungen.C-wbeendet das vorherige Leerzeichen, aber die meisten anderen Befehle M-tverwenden durch Satzzeichen getrennte Wörter.

Wenn der Cursor zwischen dem ersten und zweiten Argument steht, C-w C-e SPC C-ywerden die beiden Wörter vertauscht.

Wenn Sie eine Taste an die Transposition von durch Leerzeichen getrennten Wörtern binden möchten, ist es komplizierter. Sieheverwirrendes Verhalten von Emacs-artigen Tastenkombinationen in Bash. Hier ist etwas minimal getesteter Code.

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'

In zsh ist das alles einfacher …

Antwort2

Wenn sich Ihr Cursor dort befindet:

vimdiff projectOne/Vagrantfile projectTwo/Vagrantfile
                              ^

Drücken Sie Alt + BTTBBTFTBBTT


Oder einfach:

Drücken Sie Ctrl+ W, Ctrl+ E, fügen Sie ein Leerzeichen ein und drücken Sie Ctrl+Y

Antwort3

Für eine schnelle und einfache Lösung fügen Sie Folgendes zu Ihrer inputrc hinzu (wählen Sie selbst geeignete Schlüssel aus):

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

Bei shell-*Versionen dieser FunktionenWörter werden durch Shell-Metazeichen ohne Anführungszeichen abgegrenzt.

Metazeichen

Ein Zeichen, das, wenn es nicht in Anführungszeichen gesetzt ist, Wörter trennt. Ein Metazeichen ist ein Leerzeichen, ein Tabulator, ein Zeilenumbruch oder eines der folgenden Zeichen: „|“, „&“, „;“, „(“, „)“, „<“ oder „>“.

Hinweis: Der Cursor muss sich vor dem Drücken von Ctrl+ Alt+ hinter dem zweiten Argument befinden t, sodass das Argument vor dem Cursor effektiv an den Zeilenanfang verschoben wird.

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

Hinweis: Der Cursor muss sich vor dem Drücken von Ctrl+ Alt+ hinter dem ersten Argument befinden p, damit das Argument vor dem Cursor effektiv an das Zeilenende gezogen wird.

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

Antwort4

Sie müssen BTTBBTanstelle einer einzelnen Taste drücken T.

verwandte Informationen