ZSH tương đương với $ PROMPT_COMMAND của BASH là gì?


24

BASH hỗ trợ $PROMPT_COMMANDbiến môi trường xác định lệnh sẽ được thực thi trước bất kỳ dấu nhắc tương tác cấp đầu tiên nào. Tôi đang tìm kiếm một cân bằng ZSH về điều đó.

Các tài liệu nói rằng có một chức năng precmdtôi có thể xác định để đạt được điều đó; tuy nhiên, tôi không biết làm thế nào để xác định nó từ một biến môi trường.

Tôi đã xem xét việc chuyển một biến môi trường sẽ khiến ZSH đọc một tệp chứa định nghĩa của hàm đó, nhưng ZSH dường như không hỗ trợ những thứ như vậy : nó chỉ đọc các tệp toàn cầu và sau đó là các tệp cho mỗi người dùng. Tôi có thể thay thế chúng nhưng tôi không thể thêm vào chúng mà không sửa đổi các tệp mà tôi không thể làm được.

Vậy làm cách nào để xác định móc nối nhanh trong ZSH thông qua biến môi trường, giống như tôi đang sử dụng $PROMPT_COMMANDtrong BASH?


Sự thật mà nói, tôi cần một hook thực thi lệnh tương tác, nhưng không shell nào cung cấp một cái nên tôi phải dùng đến các hook nhắc trước - chúng dường như gần như tôi có thể nhận được.
Shnatsel

1
Hừm, tôi tự hỏi, sự khác biệt giữa thực thi lệnh sau tương tácdấu nhắc trước là gì. Ngoài một sự khác biệt về khái niệm, nơi bạn quan sát thực sự là một sự khác biệt. (Hãy bỏ qua các lệnh exitexec, ok ;))
mpy

@mpy có một sự khác biệt khi chạy một công việc nền, bởi vì các công việc nền độc lập với trình tự nhắc nhở.
Shnatsel

1
Ok, tôi đã nhận được điểm đó. Vì vậy, làm thế nào về một cái gì đó như thế: start() { eval "$@"; echo post-command-code }và sau đó sử dụng một ràng buộc zle để thực thi dòng lệnh với tiền tố start?
mpy

1
Cái DEBUGbẫy là một phát hiện hay, nhưng bạn vẫn có vấn đề làm thế nào để xác định nó. Tôi đã mở rộng câu trả lời của mình một lần nữa, nhưng tôi để bạn viết câu trả lời của riêng bạn về giải pháp bẫy DEBUG. :)
mpy

Câu trả lời:


24

Cách tiếp cận đơn giản nhất để mô phỏng bash ' $PROMPT_COMMANDmà tôi nghĩ đến là sử dụng precmdhook, như bạn đã tìm ra. Xác định nó là

precmd() { eval "$PROMPT_COMMAND" }

và bạn có thể làm một cái gì đó như thế:

$ PROMPT_COMMAND='echo Hello, it is now $(date)'
Hello, it is now Mon, Mar 31, 2014 7:08:00 PM
$ whoami      
user
Hello, it is now Mon, Mar 31, 2014 7:08:21 PM     
$

Xin lưu ý các dấu ngoặc đơn trong ví dụ đó, nếu không $(date)sẽ được mở rộng quá sớm, tức là đã được xác định $PROMPT_COMMANDvà không được gọi trước dấu nhắc.


Nếu bạn muốn giữ nguyên (và không muốn thay đổi) định nghĩa hiện có, bạn có thể sử dụng phương pháp đó:

$ prmptcmd() { eval "$PROMPT_COMMAND" }
$ precmd_functions=(prmptcmd)

Với các prmptcmdchức năng được thực hiện sau precmd()chức năng hiện có .


Cuối cùng, đây là một cách phù hợp để sử dụng trong gói chương trình, không nên sửa đổi các tệp người dùng hoặc hệ thống cũng như không thể nhập các lệnh tương tác.

Một ví dụ để sinh ra một phiên bash có thể là

PROMPT_COMMAND="echo foo" bash

Để sinh sản zsh bạn có thể sử dụng

ZDOTDIR=/program/dir zsh

mà gây ra /program/dir/.zshrcnguồn gốc. Trong tập tin này, precmd()hook có thể được định nghĩa như được giải thích ở trên. Nếu bạn muốn thiết lập của người dùng ngoài bao gồm source $HOME/.zshrcvv trong zshrc của chương trình, quá. Thiết lập này có thể duy trì được, vì không có tệp nào bên ngoài thư mục chương trình được sửa đổi.


Như là một bổ sung cuối cùng, đây là một bằng chứng về khái niệm làm thế nào để giữ cho người mới được chào đón, quá. Sử dụng mã sau đây trong /program/dir/.zshenvtập tin cấu hình RC của bạn :

echo define precmd, traps, etc.

autoload -Uz zsh-newuser-install

if [[ ! -e "$HOME/.zshrc" ]]; then
  zsh-newuser-install -f
  mv $ZDOTDIR/.zshrc $HOME/.zshrc
else
  builtin source $HOME/.zshrc
fi

Điều đó nhiều tôi đã tìm ra. Vấn đề là - làm thế nào để tôi xác định hook premd thông qua một biến môi trường? Có một cơ chế để thêm hook hoặc code mà không sửa đổi các tập tin? Hoặc làm thế nào để tôi làm điều đó ít nhất mà không cần ghi vào ".zprofile" toàn cầu và toàn cầu? Giống như, tôi có thể thêm .zprofile của riêng mình mà sẽ không thay thế những cái hiện có không?
Shnatsel

1
Ngoài ra, việc bạn sử dụng hook premd ở đây sẽ thay thế bất kỳ hook premd nào đã đọc; Tài liệu zsh đề cập Tôi có thể tạo ra một loạt các hàm sẽ cùng tồn tại nhưng tôi không biết làm thế nào để làm điều đó.
Shnatsel

1
(1) Ý của bạn là làm thế nào để tôi xác định hook premd thông qua một biến môi trường? Ví dụ tôi đã trình bày IMHO giống như cơ chế bash. (2) Bạn có thể thêm hook thông qua dòng lệnh, nhưng sau đó nó không vĩnh viễn. Có vấn đề gì với việc sửa đổi của bạn .zshrc? (3) Một ví dụ: foo() { echo foo }; bar() { echo bar }; precmd_functions=(foo bar)Đây thực thi foo()bar() ngoài tới precmd().
mpy

2
Ok, điều đó làm rõ rất nhiều - một ví dụ tối thiểu cho bash sau đó sẽ là PROMPT_COMMAND="echo foo" bash, phải không? Đây có phải là một khả năng để sinh sản zsh : ZDOTDIR=/program/dir zsh. Sau đó, /program/dir/.zshrccó nguồn gốc khi bắt đầu nơi bạn có thể xác định hook premd (). Nếu bạn muốn người dùng thêm vào, bao gồm source $HOME/.zshrcvv trong zshrc của chương trình. Điều này phải dễ bảo trì, vì không có tệp nào bên ngoài thư mục chương trình được sửa đổi.
mpy

1
@Shnatsel: Tôi mở rộng câu trả lời của mình. Có lẽ bạn cũng có thể chỉnh sửa câu hỏi của mình để bao gồm thông tin bổ sung từ ý kiến ​​của bạn.
mpy

5

Như @mypy tuyên bố, Zsh precmdhoạt động tương tự như Bash PROMPT_COMMAND.

Đây là một ví dụ hoạt động cho Bash hoặc Zsh và không sử dụng eval:

## ~/myprompt.sh

# 'ZSH_VERSION' only defined in Zsh
# 'precmd' is a special function name known to Zsh

[ ${ZSH_VERSION} ] && precmd() { myprompt; }

# 'BASH_VERSION' only defined in Bash
# 'PROMPT_COMMAND' is a special environment variable name known to Bash

[ ${BASH_VERSION} ] && PROMPT_COMMAND=myprompt

# function called every time shell is about to draw prompt
myprompt() {
  if [ ${ZSH_VERSION} ]; then
    # Zsh prompt expansion syntax
    PS1='%{%F{red}%}%n%{%f%}@%{%F{red}%}%m %{%F{cyan}%}%~ %{%F{white}%}%# %{%f%}'
  elif [ ${BASH_VERSION} ]; then
    # Bash prompt expansion syntax
    PS1='\[\e[31m\]\u\[\e[0m\]@\[\e[31m\]\h \[\e[36m\]\w \[\e[37m\]\$ \[\e[0m\]'
  fi
}

Chạy từ shell init script:

## ~/.bashrc
. ~/myprompt.sh

và:

## ~/.zshrc
. ~/myprompt.sh

Các gợi ý ở đây chỉ là ví dụ. Một người chắc chắn có thể làm nhiều thứ khó khăn hơn.

Để biết chi tiết về cài đặt các chức năng nhắc nhở, hãy xem: http://zsh.sourceforge.net/Doc/Release/Fiances.html#index-precmdhttp://www.gnu.org/software/bash/manual/bashref.html # In-a-Nhắc .

Để biết chi tiết về việc mở rộng nhanh chóng, hãy xem http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.htmlhttp://www.gnu.org/software/bash/manual/bashref.html#Printing-a -Prompt .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.