プロンプトの後に文字列を自動的に挿入する方法

プロンプトの後に文字列を自動的に挿入する方法

bash実行できる端末ウィンドウがあります。ただコマンドを発行してくださいfoo。だから私はすべての行(もちろんプロンプトの後)が「foo」で始まり、関数名の代わりに関数のオプションとパラメータを入力するだけです。もちろん、自動的に挿入された文字列を変更できればと思いますが、これは必要ない私のため。

はい

何も入力せずに端末を開くと、私が見たい内容は次のとおりです。

user@host:~/ $ foo 

次に、を入力して--option argumentキーを押すと、指定されたEnter合計で関数が呼び出されます。foo--optionargument

私が試したこと

私はあちこちを見て使ってみましたが、驚くべきことに実際に動作しますが、$PS1残念ながら「foo」も印刷されます。$PROMPT_COMMANDxdotool type "foo "今後プロンプトは非常に醜いです。

user@host:~/ $ PROMPT_COMMAND='xdotool type "foo "'
foo user@host:~/ $ foo 

私もそのpreexec機能を見つけて使ってみましたRyan Calorasのbash-preexecスクリプトしかし、まったく同じ問題があります。

行末でカーソルが点滅するようにプロンプ​​トに((実行可能)文字列)をエコーし​​ます.関連していますが、そこに答えると、--option argument実行するコマンドに何か()を追加できませんでした。まだテストしたことはありません。このように簡単なこともzsh解決策があるべきではないでしょうか?bash

答え1

の場合は、zsh次の事項に関する質問でなければなりません。

precmd() print -z 'foo '

または、ユーザーの待機中のコマンドを上書きしないようにするには、次のようにしますAlt+q

zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init

bash代わりに、xdotool次のことができますTIOCSTI ioctl

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'

これは、読み取っているデバイスの入力バッファxdotoolにこれらの文字を直接挿入するため、これが望ましいです。bashこれは、Xサーバーが実行されている場合にのみ機能します(たとえば、コンソールまたは物理端末で、またはそうでxdotoolない場合)。これは識別されたサーバーであり、対話するサーバーです。そして端末が実行するエミュレータです。実行中です。評価時に焦点が合っています。ssh-X$DISPLAYbash$PROMPT_COMMAND

これで、あなたのxdotool場合と同様に、プロンプトが表示される前にこれがioctl()完了し、ttyターミナルラインルールがモードで読み取られるので、icanon+echo次のことがわかります。エコfoottyラインルールがディスプレイを混乱させた場合。

文字列を挿入することでこの問題を解決できます。エコ表示されず(Unicodeロケールのみを使用している場合はU + 200Bと同様)、挿入されたジョブにバインドされます"foo "

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"

TIOCSTIあるいは、readlineが初期化する時間を持つようにioctlを十分に長く遅延させることもできます。

insert_with_delay() {
  perl -le 'require "sys/ioctl.ph";
            $delay = shift @ARGV;
            unless(fork) {
              select undef, undef, undef, $delay;
              ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
            }' -- "$@";
}
PROMPT_COMMAND='insert_with_delay 0.05 "foo "'

メソッドのようにzshプロンプ​​トを表示する前にユーザーがテキストを入力する状況を処理するには、次のようにします。

  • 流れるtcflush(0, TCIFLUSH)ioctlperlの前にaを実行して(オプションTIOCSTIも必要です-MPOSIX)、または
  • 同様に、zsh前(最後に移動)と後((デフォルト)編集モード)を使用すると仮定し、カーソルを行の先頭に移動してfooバッファの先頭に挿入する必要があります。^Aemacsfoo^E

    insert_with_delay 0.05 $'\1foo \5'
    

    または

    bind $'"\u200b":"\1foo \5"'
    

答え2

あなたが要求するものは一般的ではないと聞こえるので、これを行う簡単な方法がないことは驚くべきことではありません。

純粋なbashを使用すると、組み込みread関数を使用して行を読み取ってeval実行できます。模擬チップ(以下におおよそのヒントを示します)。

#!/bin/bash    
PROMPT=$'\e[1m'$USER@$HOSTNAME:$PWD$' $ \e[0m'
IFS= read -r -e -i "foo " -p "$PROMPT" line
eval "$line"
exit

これをスクリプトに入れ、端末エミュレータにスクリプトを実行するように指示します。

または、ターミナルエミュレータでScreenを実行してください。そのstuffコマンドを使用して入力をシミュレートできます。

関連情報