프롬프트 다음에 문자열을 자동으로 삽입하는 방법

프롬프트 다음에 문자열을 자동으로 삽입하는 방법

bash실행할 수 있는 터미널 창이 있습니다.오직명령을 내리세요 foo. 그래서 나는 모든 줄(물론 프롬프트 이후)이 "foo"로 시작하여 반복되는 함수 이름 대신 함수의 옵션과 매개변수만 입력하면 되기를 원합니다. 물론 자동으로 삽입된 문자열을 변경할 수 있으면 좋겠지만, 이는필요하지 않다나를 위한.

아무 것도 입력하지 않고 터미널을 열면 내가 보고 싶은 내용은 다음과 같습니다.

user@host:~/ $ foo 

그런 다음 를 입력 --option argument하고 키를 누르면 주어진 Enter합계로 함수가 호출됩니다.foo--optionargument

내가 시도한 것

나는 이리저리 살펴보고 사용해 보았지만 $PS1놀랍게도 $PROMPT_COMMAND실제로 xdotool type "foo "작동하지만 불행히도 "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 라인 규칙이 디스플레이를 엉망으로 만든 경우 .

문자열을 삽입하여 이 문제를 해결할 수 있습니다.에코보이지 않으며(유니코드 로케일만 사용하는 경우 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)ioctl perl이전에 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명령을 사용하여 입력을 시뮬레이션 할 수 있습니다 .

관련 정보