bash
실행할 수 있는 터미널 창이 있습니다.오직명령을 내리세요 foo
. 그래서 나는 모든 줄(물론 프롬프트 이후)이 "foo"로 시작하여 반복되는 함수 이름 대신 함수의 옵션과 매개변수만 입력하면 되기를 원합니다. 물론 자동으로 삽입된 문자열을 변경할 수 있으면 좋겠지만, 이는필요하지 않다나를 위한.
예
아무 것도 입력하지 않고 터미널을 열면 내가 보고 싶은 내용은 다음과 같습니다.
user@host:~/ $ foo
그런 다음 를 입력 --option argument
하고 키를 누르면 주어진 Enter합계로 함수가 호출됩니다.foo
--option
argument
내가 시도한 것
나는 이리저리 살펴보고 사용해 보았지만 $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
$DISPLAY
bash
$PROMPT_COMMAND
이제 귀하의 xdotool
경우와 마찬가지로 프롬프트가 표시되기 전에 이 ioctl()
작업이 완료되고 tty 터미널 라인 규칙이 모드에서 읽혀지므로 icanon+echo
다음을 볼 수 있습니다.에코foo
tty 라인 규칙이 디스플레이를 엉망으로 만든 경우 .
문자열을 삽입하여 이 문제를 해결할 수 있습니다.에코보이지 않으며(유니코드 로케일만 사용하는 경우 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
버퍼의 시작 부분에 삽입해야 합니다 .^A
emacs
foo
^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
명령을 사용하여 입력을 시뮬레이션 할 수 있습니다 .