Làm cách nào để sửa lỗi gói bash màu của tôi?


9

Tôi đã xác định một dấu nhắc bash (sử dụng PROMPT_FUNCTION) như vậy:

function get_hg_prompt_prefix() {
    local APPLIED_COLOR=$1; shift
    local UNAPPLIED_COLOR=$1; shift
    local ALERT_COLOUR=$1; shift
    local TEXTCOLOR=$1; shift
    local mercurial_prompt_line="{{patches|join(:)|pre_applied(${APPLIED_COLOR})|post_applied(${TEXTCOLOR})|pre_unapplied(${UNAPPLIED_COLOR})|post_unapplied(${TEXTCOLOR})}\n\r}"
    local mercurial_status_prompt="{ ${ALERT_COLOUR}{status}${TEXTCOLOR}}"

    echo "$(hg prompt "${mercurial_prompt_line}" 2>/dev/null)$(hg prompt "${mercurial_status_prompt}" 2>/dev/null)"
}

function set_prompt() {
    bright='\[[01m\]'
    colors_reset='\[[00m\]'
    HOSTCOLOR=${colors_reset}='\[[34m\]'
    USERCOLOR=${colors_reset}='\[[01m\]'
    TEXTCOLOR=${colors_reset}='\[[32m\]'
    APPLIED_COLOR=${colors_reset}='\[[32m\]'
    UNAPPLIED_COLOR=${colors_reset}='\[[37m\]'
    ALERT_COLOUR=${colors_reset}='\[[31m\]'

    hg_status="$(get_hg_prompt_prefix $APPLIED_COLOR $UNAPPLIED_COLOR $ALERT_COLOUR $TEXTCOLOR)"
    ps1_prefix="${hg_status}$colors_reset($bright$(basename $VIRTUAL_ENV)$colors_reset) "
    PROMPTEND='$'
    PS1="${ps1_prefix}${USERCOLOR}\u${colors_reset}${TEXTCOLOR}@${colors_reset}${HOSTCOLOR}\h${colors_reset}${TEXTCOLOR} (\W) ${PROMPTEND}${colors_reset} "
}

PROMPT_COMMAND=set_prompt

Nói chung, điều này mang lại cho tôi một dấu nhắc nhiều dòng hiển thị một số thông tin trạng thái hg cũng như virtualenv hiện tại của tôi, trông (không có màu) như thế này:

buggy-wins.patch
 ! (saas) user@computer (~) $ 

Vấn đề là, đây là vấn đề khó khăn trong việc tính toán độ dài của dấu nhắc (tôi nghĩ vậy!) Và gây ra các vấn đề gói thiết bị đầu cuối kỳ lạ và vị trí con trỏ. Ví dụ: trong một thiết bị đầu cuối 80 char, đây là lời nhắc tôi thấy (ký tự ** - bao quanh là vị trí con trỏ):

~) $ **a**nis) crose@chris-rose (~

Trong các thiết bị đầu cuối đủ rộng để hiển thị dấu nhắc, việc ngắt dòng xảy ra sớm hơn nhiều so với mức cần thiết; Đây là văn bản nhiều nhất tôi có thể vừa trên dòng đầu tiên của dấu nhắc trong cửa sổ đầu cuối rộng 108 char (một lần nữa, ** đánh dấu vị trí con trỏ của tôi):

 **(**advanis) crose@chris-rose (~) $ sdkfjlskdjflksdjff

Khi dòng kết thúc, nó sẽ ghi đè lên dấu nhắc. Tuy nhiên, dòng đầu vào thứ hai chạy thẳng đến cạnh của thiết bị đầu cuối, và sau đó kết thúc chính xác.

Vì vậy, rõ ràng một cái gì đó đang gây rối với chiều rộng của dấu nhắc. Làm cách nào tôi có thể khiến bash xác định độ dài của chuỗi PS1 không theo mã thoát ANSI, nhưng theo độ dài hiển thị thực tế của dấu nhắc?

Câu trả lời:


21

bashsử dụng \[ \]để xác định "độ dài hiển thị": văn bản giữa hai lần thoát đó được coi là không thể in được và không được tính trong tổng chiều dài; mọi thứ khác

Dường như có một vấn đề với các biến của bạn: bright='\[[01m\]'không thực sự bao gồm ký tự ESC, do đó, [01mđược in dưới dạng văn bản bình thường nhưng không được tính theo độ dài. Nó phải '\[\e[01m\]'. Tương tự cho tất cả các biến khác.


Liên quan:

  • trong Bash, bạn có thể đặt \$(hg_status)để $PS1trực tiếp, mà không cần một riêng biệt PROMPT_COMMAND.

1
Điều đó cung cấp một sửa chữa một phần; bây giờ độ dài dòng được phát hiện đúng, nhưng nó không khắc phục được vấn đề với dòng ghi đầu tiên ghi trên dấu nhắc.
Chris R

1
Chris R: Tôi đã thử lời nhắc của bạn và chỉ thay thế tất cả '\[[bằng '\[\e[bash trên Ubuntu 12.04. Việc thoát màu (và một số phần không liên quan đến kích thước nhắc nhở khác) cũng \[...\]giúp tôi, nhưng tôi có PS1 phức tạp hơn nhiều so với bạn (với văn bản được căn phải trên cùng dòng với dấu nhắc và văn bản ở phía dưới bên phải góc). Nó đã sửa cả các gói đầu và các vấn đề gói chồng chéo.
TWiStErRob
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.