실행 전에 Zsh/Bash의 모든 명령을 사용자 정의 명령으로 자동으로 래핑하는 방법은 무엇입니까?

실행 전에 Zsh/Bash의 모든 명령을 사용자 정의 명령으로 자동으로 래핑하는 방법은 무엇입니까?

Zsh실행 전에 Bash모든 입력에 사용자 지정 명령(예: 이름 지정)을 자동으로 추가하기 위해 셸의 동작을 수정(또는)하려고 합니다. myapp기본적으로 사용자의 입력을 가로채서 수정하고 사용자가 을 누르면 ENTER_KEY수정된 명령이 실행되어야 합니다.

셸에 입력하는 모든 명령은 다음과 같습니다.

grep -rn hello

내가 입력한 것처럼 처리되어야 합니다.

$ myapp grep -rn hello

또 다른 예를 들어, 를 입력하면 ls로 실행되어야 합니다 myapp ls.

표적

일부 cli 도구의 뷰어로 vim을 자동으로 사용해 보고 싶습니다.

# myapp
vim -c "term $*"

답변1

목표를 고려할 때 가장 간단한 해결책은 아래와 같이 명령 결과를 vim으로 파이프하는 것입니다.

$ yourcommand | vim -

예를 들어,

$ grep -rn hello | vim -

답변2

나는 당신이 이 배열에 들어오고 나가기를 원한다고 가정하고 다음을 수행했습니다. zsh의 경우 DEBUG 트랩 핸들러는 ERR_EXIT 옵션을 설정하여 제출된 명령 실행을 건너뛰고 대신 사용자 정의 명령을 실행할 수 있습니다.

# this is run before every command
debug_trap() {
    # get last submitted command
    cmd="${history[$HISTCMD]}";
    if [ "$cmd" ]; then
        # catch the unwrap command and remove the trap
        if [ "$cmd" = "unwrap" ]; then
            print 'Unwrapping command-line';
            trap - DEBUG;
            return;
        fi
        # make sure multiple trap triggers only handle this once
        if [ "$handled" != "$HISTCMD;$cmd" ]; then
            # when either history index or command text
            # changes, we can assume its a new command
            handled="$HISTCMD;$cmd";
            # do whatever with $cmd
            myapp $cmd;
        fi
        # optionally skip the raw execution
        setopt ERR_EXIT;
    fi
}

# start the debug trap
wrap() {
    print 'Wrapping command-line';
    trap 'debug_trap' DEBUG;
}

# this is just defined in order to avoid errors
# the unwrapping happens in the trap handler
unwrap() {}

Bash와 동일:

# bash requires this option in order to skip execution
# inside the debug trap
shopt -s extdebug;

# this is run before every command
debug_trap() {
    cmd="$BASH_COMMAND";
    # catch the unwrap command and remove the trap
    # notice how the alias is expanded here and
    # the command is no longer 'unwrap'
    if [[ "$cmd" == 'trap - DEBUG' ]]; then
        echo 'Unwrapping command-line';
        # the trap is unset by the submitted command
    else
        # do whatever with $cmd
        myapp $cmd;
        # optionally skip the raw execution
        return 1;
    fi
}

# start the debug trap
wrap() {
    echo 'Wrapping command-line';
    trap debug_trap DEBUG;
}

# we can't unset global traps inside a function
# so we use an alias instead
alias unwrap='trap - DEBUG';

사용 예:

> myapp() { echo "### $1"; }
> wrap
Wrapping command-line
> echo 123
### echo 123
> unwrap
Unwrapping command-line
> echo 123
123

vim 기능을 구현하려면 myapp 함수에서 "vim -c"를 사용하거나 트랩 함수에서 "myapp $cmd;" 줄을 변경하세요.

단, 사용 전 주의사항입니다. 디버깅 트랩은 매우 까다롭기 때문에 오류를 줄이기 위해 zsh 버전을 사용해 보았습니다. oh-my-*sh와 같은 플러그인을 사용하면 안정적인 구현을 달성하는 데 어려움을 크게 증가시키는 후크, 트랩 및 기타 메커니즘이 도입될 수 있습니다. zsh 버전은 oh-my-zsh에 대해 테스트되었으며 작동해야 합니다. bash 버전은 수정되지 않은 bash v4.2에서만 테스트되었습니다.

zsh의 다른 잠재적 구현: 텍스트 버퍼를 실행하기 전에 조작하는 반환 키에 바인딩된 기본 zle 위젯 "accept-line"을 재정의할 수 있으며 이는 더 깔끔한 솔루션일 수 있습니다. 유용할 수 있는 "preexec" 후크 기능도 있지만 자체적으로 명령을 변경하거나 건너뛸 수 있는 방법은 없는 것 같습니다.

기타 사용 아이디어: 하나 이상의 원격 시스템에 (ssh) 명령을 보내고, 스크립트 파일에 작성하고 실행을 연기하고, 실행 전에 정적 분석을 수행하고, 확인을 요청하거나 오타 수정을 요구하는 데 사용할 수 있습니다.

관련 정보