ฉันจะแก้ไขการตัดคำพร้อมรับคำทุบตีสีได้อย่างไร


9

ฉันได้กำหนดพรอมต์ bash (โดยใช้ PROMPT_FUNCTION) ดังนี้:

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

โดยทั่วไปจะให้พรอมต์หลายบรรทัดที่แสดงข้อมูลสถานะ hg รวมถึง virtualenv ปัจจุบันของฉันดู (ไม่มีสี) ดังนี้:

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

ปัญหาคือสิ่งนี้กำลังเกิดขึ้นกับการคำนวณความยาวของพรอมต์ (ฉันคิดว่า!) และทำให้เกิดปัญหาการตัดขั้วและการวางเคอร์เซอร์ที่แปลก ตัวอย่างเช่นในเทอร์มินัล 80-char ต่อไปนี้เป็นพรอมต์ที่ฉันเห็น (อักขระ ** - ล้อมรอบคือตำแหน่งเคอร์เซอร์):

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

ในเทอร์มินัลกว้างพอที่จะแสดงพรอมต์การตัดบรรทัดเกิดขึ้นเร็วกว่าที่ควรจะเป็น; นี่คือข้อความส่วนใหญ่ที่ฉันสามารถใส่ในบรรทัดแรกของพรอมต์ในหน้าต่างเทอร์มินัล 108-char-wide (อีกครั้งเครื่องหมาย ** ทำเครื่องหมายตำแหน่งเคอร์เซอร์ของฉัน):

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

เมื่อบรรทัดถูกทับจะเป็นการเขียนทับพร้อมต์ อย่างไรก็ตามบรรทัดที่สองของอินพุตวิ่งไปทางขอบของเทอร์มินัลแล้วทำการห่ออย่างถูกต้อง

ดังนั้นสิ่งที่ชัดเจนกับความกว้างของพรอมต์ ฉันจะทำให้ bash กำหนดความยาวของสตริง PS1 ไม่ได้ตามรหัสการหลบหนี ANSI แต่ตามความยาวที่ปรากฏจริงของพรอมต์?

คำตอบ:


21

bashใช้\[ \]เพื่อกำหนด "ความยาวที่แสดง": ข้อความระหว่างสอง escapes นั้นถือว่าไม่สามารถพิมพ์ได้และไม่นับในความยาวทั้งหมด ทุกอย่างอื่นคือ

ดูเหมือนว่าจะมีปัญหากับตัวแปรของคุณ: bright='\[[01m\]'จริง ๆ แล้วไม่รวมอักขระ ESC ดังนั้น[01mได้รับการพิมพ์เป็นข้อความปกติ แต่ไม่นับในความยาว '\[\e[01m\]'มันควรจะเป็น เหมือนกันสำหรับตัวแปรอื่น ๆ ทั้งหมด


ที่เกี่ยวข้อง:

  • ในทุบตีคุณสามารถใส่\$(hg_status)ไปโดยตรงโดยไม่จำเป็นที่จะต้องแยกจากกัน$PS1PROMPT_COMMAND

1
ที่ให้การแก้ไขบางส่วน; ตรวจพบความยาวของเส้นอย่างถูกต้องในตอนนี้ แต่ไม่สามารถแก้ไขปัญหาด้วยการเขียนบรรทัดคำสั่งแรกผ่านทางพรอมต์
Chris R

1
Chris R: ฉันได้ลองพรอมต์ของคุณและแทนที่ทั้งหมด'\[[ด้วยการ'\[\e[ทำงานใน bash บน Ubuntu 12.04 การหลบหนีสี (และส่วนอื่น ๆ ที่ไม่เกี่ยวข้องกับขนาดพร้อมรับคำ) \[...\]ช่วยด้วยเช่นกัน แต่ฉันมี PS1 ที่ซับซ้อนมากขึ้นกว่าคุณมาก (พร้อมข้อความชิดขอบขวาบนบรรทัดเดียวกันกับข้อความและขวาที่ด้านล่างขวา มุม). มันแก้ไขทั้งปัญหาการห่อเร็วและปัญหาการห่อทับซ้อนกัน
TWiStErRob
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.