2012-05-12 34 views
13

Tôi muốn đặt chi nhánh git hiện tại vào lời nhắc ZSH nhiều dòng của tôi. Tuy nhiên, điều này làm rối tung hai dòng - tôi muốn chúng xếp hàng độc đáo.Đếm số lượng chuỗi hiển thị của người dùng cho lời nhắc zsh


┌─([email protected]:s000)─[master *]──────────────── 
───(~ )─┐ 
└─(127:15:44)──      ──(Sat,May12)─┘ 

nên là:


┌─([email protected]:s000)─[master *]─────────(~ )─┐ 
└─(127:15:44)──      ──(Sat,May12)─┘ 

Nhánh git được nắm lấy từ một chức năng oh-my-zsh, git_prompt_info(), mà mang lại cho tôi những chi nhánh, tình trạng bẩn thỉu, và một loạt các cửa sổ-thoát để tô màu những thứ độc đáo.

Làm cách nào để đếm các ký tự được hiển thị rõ ràng được chèn vào lời nhắc ZSH - không phải là chuỗi thoát nhanh?

Trả lời

11

Giả sử rằng chuỗi nhắc thoát được lưu trữ trong một biến FOO, điều này sẽ đếm ký tự chỉ với người sử dụng có thể nhìn thấy:

                                
FOO=$(git_prompt_info)                              
local zero='%([BSUbfksu]|([FK]|){*})' 
FOOLENGTH=${#${(S%%)FOO//$~zero/}} 

này xuất phát từ this .zshrc.

Đây là số thô giải thích lý do tại sao nó hoạt động, tự do trích dẫn từ man zshexpn, phần PARAMETER EXPANSION. Tôi không chắc chắn 100% chi tiết, vì vậy, nếu bạn đang sử dụng điều này để phát triển tương đương của riêng bạn, hãy đọc phần man zshall có liên quan.

Làm việc từ dòng FOOLENGTH=${#${(S%%)FOO//$~zero/}}, chúng tôi có một số bit. Đi từ trong ra ngoài:

  1. $~zero: Các ~ đảm bảo rằng zero, mà chúng tôi đã xác định như '%([BSUbfksu]|([FB]|){*})', được coi là một mô hình chứ không phải là một chuỗi đồng bằng.

  2. ${(S%%)FOO//$~zero/}: Đây phù hợp ${name//pattern/repl}:

    Thay thế trận đấu dài nhất có thể của mô hình trong việc mở rộng tên tham số của chuỗi repl

    Lưu ý rằng chúng tôi không có một repl; chúng tôi thay thế kết quả dài nhất có thể của pattern mà không có gì, do đó xóa nó.
    (S%%)FOO tiến hành mở rộng trên FOO với nhiều cờ được đặt. Tôi không theo kịp nó.

  3. ${#${(S%%)FOO//$~zero/}}: ${#spec} sẽ thay thế độ dài trong các ký tự của kết quả của sự thay thế spec, nếu spec là sự thay thế. Trong trường hợp của chúng tôi, spec là kết quả của việc thay thế ${(S%%)FOO//$~zero/}; do đó, điều này về cơ bản trả về độ dài của các ký tự trong kết quả của cụm từ thông dụng s/zero// trên FOO, trong đó zero là mẫu ở trên.

+4

'(S)' làm cho phù hợp không tham lam do đó chuyển "dài nhất có thể phù hợp" thành "ngắn nhất có thể phù hợp" (không có nó '{*}' trong một mô hình sẽ biến điều như '% F {xanh}% M% F {yellow}% #% f' chỉ vào'% # ', trong khi nó sẽ biến nó thành'% M% # '),' (%%) 'thực hiện mở rộng dấu nhắc trên chuỗi, sau tùy chọn PROMPT_ *. Lưu ý: phương pháp này nên tránh nếu chuỗi PROMPT chứa một lệnh với một số tác dụng phụ: ví dụ, nếu bạn muốn sử dụng nó để đếm tần suất hiển thị lời nhắc. Hầu hết thời gian bạn sẽ không phải chịu đựng điều này. – ZyX

+0

Và có, tất cả các cờ '(*)' được mô tả trong phần PARAMETER EXPANSION của 'man zshexpn'. – ZyX

+0

@ZyX Cảm ơn. Tôi thấy lời giải thích cho 'S' trong trang' zshexpn', nhưng không chắc nó được trang bị như thế nào. – simont

2

Không chắc làm thế nào để làm điều này với lệnh zsh dựng sẵn, nhưng thông tin màu sắc có thể bị tước với sed (như tài liệu here):

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" 

ví dụ

plain_str=$(git_prompt_info | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g") 

Điều này sẽ loại bỏ tất cả các chuỗi thoát khỏi chuỗi. Chiều dài bây giờ chỉ đơn giản là:

echo $#plain_str 
+0

@beardtree: cảm ơn chỉnh sửa được đề xuất. – Thor

Các vấn đề liên quan