zsh의 기존 기능 재정의 및 재사용

zsh의 기존 기능 재정의 및 재사용

zsh 완성 기능을 약간 확장하고 싶습니다.

전체 함수 본문을 내 홈 디렉터리에 넣는 것을 피하고 한 줄만 변경하고 싶습니다. 대신 호출을 가로채서 원래 함수를 직접 호출하고 싶습니다. 베어 코드에서:

<make sure _the_original_function is loaded>
_backup_of_original_function=_the_original_function

_the_original_function() {
   _arguments "-superduper[that one option I always need]"
   _backup_of_originial_function $@
}

제 경우에는 거의 모든 프로젝트에 cmake 속성이 있으므로 cmake 완성을 수정하고 싶습니다. 완료 시 이 옵션이 없으면 옵션이 아닌 프로젝트에 이 옵션이 있는 것보다 더 짜증납니다. 따라서 _cmake어딘가에 복사하지 않고 _cmake_define_common_property_names()내 위치에 복사하겠습니다 .zshrc.

_cmake_define_common_property_names() {
  local properties; properties=(
    'MY_GREAT_OPTION:be awesome'
  )                    

  _describe -t 'my-property-names' 'my property name' properties $@

  **call original _cmake_define_common_property_names here
}  

그래서 빠진 것은 _cmake_define_common_property_names새로운 함수 이름을 로드하고 할당하는 것입니다.

~에서여기나는 노력했다

autoload -Uz +X _cmake_define_common_property_names

그러나 이는 실패합니다(함수는 자체 파일에 정의되어 있지 않지만 _cmake.

참고: 원래 버전에서 함수가 호출된 위치를 수정할 필요가 없도록 새 함수 이름을 지정하지 않았습니다.

부분적으로는 yes 작동 autoload -Uz +X _cmake하지만 이는 _cmake로드된 것만 확인합니다(를 호출하여 확인했습니다 functions _cmake). 도우미 함수를 로드하지 않습니다 _cmake_define_common_property_names.

그래서 내 두 가지 질문은

  1. $fpath파일에서 함수를 로드하는 방법
  2. 일단 함수를 로드합니다. 이것을 스크립트에 복사하거나 새 함수 이름을 할당하려면 어떻게 해야 합니까?

답변1

기능을 패치하는 방법

함수의 코드는 연관 배열에 저장됩니다 functions. 다음은 정규화된 공백이 있고 주석이 없는 소스 코드입니다(zsh가 어휘 분석을 수행하고 마크업을 보기 좋게 인쇄했습니다). 배열의 항목을 수정하여 함수의 코드를 변경할 수 있습니다 functions. 예를 들어 시작 부분에 추가 코드를 추가하려면 다음을 수행하세요.

functions[_cmake_define_common_property_names]="
    … # your extra code here
    $functions[_cmake_define_common_property_names]"

변경하려는 내용이 단순히 원래 코드 앞과 뒤의 코드 실행과 관련된 경우(또는 더 일반적으로는 조건에 넣는 것과 같이) 함수를 새 이름으로 복사하고 해당 새 이름을 호출하도록 함수를 재정의할 수 있습니다. zsh 5.8부터는 다음 명령을 사용하여 쉽게 이 작업을 수행할 수 있습니다.functions -c.

functions -c _cmake_define_common_property_names _cmake_define_common_property_names_orig
_cmake_define_common_property_names () {
    _cmake_define_common_property_names_orig "$@"
}

또는 모든 zsh 버전에서 배열을 사용하여 functions함수를 다른 이름으로 복사할 수도 있습니다.

functions[_cmake_define_common_property_names_orig]=$functions[_cmake_define_common_property_names]
_cmake_define_common_property_names () {
    _cmake_define_common_property_names_orig "$@"
}

모든 기능 로드

자동 로드 파일에서 모든 기능을 로드하는 신뢰할 수 있는 유일한 방법은 기능을 실행하는 것입니다(부작용 없이 기능을 실행하도록 준비할 수 있는 경우). 완료 함수의 경우 함수를 실행하고 오류를 비트버킷으로 리디렉션하면 됩니다. 완료 컨텍스트에서 실행되지 않는다고 불평하고 아무 작업도 수행하지 않습니다.

_cmake 2>/dev/null
# Now _cmake_xxx is defined

autoload -Uz +X _cmake작동하지 않는 이유는 도우미 함수가 _cmake함수 자체에 정의되어 있기 때문입니다.

% echo $functions[_cmake]
builtin autoload -XU
% autoload -Uz +X _cmake
% echo $functions[_cmake]
        (( $+functions[_cmake_define_property_names] )) || _cmake_define_property_names () {
}
        local cmake_command_actions
        cmake_command_actions=('-E[CMake command mode]:*:command') 
        _cmake_command () {
                _arguments -C -s - command "$cmake_command_actions[@]"
        }
        local cmake_suggest_build
        cmake_suggest_build=('--build[build]') 
        if [ $CURRENT -eq 2 ]
        then
                _arguments -C -s - help "$cmake_help_actions[@]" - command "$cmake_command_actions[@]" - build_opts "$cmake_build_options[@]" - build_cmds "$cmake_suggest_build[@]" && return 0
        elif [[ $words[2] = --help* ]]
        then
                _cmake_help
        elif [[ $words[2] != -E ]]
        then
                _cmake_on_build
        else
                _cmake_command
        fi

최상위 기능을 실제로 실행하고 싶지 않은 경우 몇 가지 옵션이 있습니다.

  • _cmake_define_common_property_names정의 내의 정의를 패치합니다 _cmake.

  • _cmake_define_common_property_names의 정의에서 정의를 추출 _cmake하고 이를 사용하여 _cmake_define_common_property_names_orig또는 을 정의합니다 _cmake_define_common_property_names.

  • _cmake함수 정의 이외의 부분을 제거하려면 정의를 패치한 후 실행합니다. 실제로는 작동하지 않지만 _cmake작업을 더 잘 수행하는 다른 구조가 있습니다. 예를 들어 _cvs순전히 조건부 함수 정의(예: (( $+functions[_cvs_command] )) || _cvs_command () { … }), 제목 함수 정의, 마지막으로 제목 함수 호출로 구성되므로 모든 함수를 정의할 수 있지만 아무것도 할 수는 없습니다. 마지막 줄을 제거하여.

      autoload -Uz +X _cvs
      functions[_cvs]=${functions_cvs%'$\n'*}
      _cvs
      # Patch auxiliary functions here
    

관련 정보