Gilles đã xác định vấn đề chính của bạn, nhưng tôi muốn thử giải thích nó theo cách khác.
Bash diễn giải lời nhắc đặc biệt chỉ thoát trước khi mở rộng bất kỳ biến nào trong dấu nhắc. Điều này có nghĩa là việc sử dụng \e
một biến được mở rộng từ dấu nhắc không hoạt động, mặc dù nó hoạt động trực tiếp PS1
.
Ví dụ: điều này hoạt động như mong đợi và đưa ra văn bản màu đỏ:
PS1='\e[1;31m this is in red '
Nhưng điều này không, nó chỉ đặt một chữ đúng nghĩa \e
:
RED='\e[1;31m'
PS1="$RED not in red "
Nếu bạn muốn lưu trữ các màu thoát trong các biến, bạn có thể sử dụng trích dẫn ANSI-C $'...'
để đặt ký tự thoát theo nghĩa đen trong biến.
Để làm điều này, bạn có thể thay đổi định nghĩa của bạn GREEN
, RED
và NONE
, vì vậy giá trị của họ là dãy thoát thực tế.
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
Nếu bạn làm điều đó, lần đầu tiên của bạn PS1
với dấu ngoặc đơn sẽ hoạt động:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
Tuy nhiên, sau đó bạn sẽ có một vấn đề thứ hai.
Hãy thử chạy nó, sau đó nhấn Up Arrow, sau đó Home, và con trỏ của bạn sẽ không quay trở lại điểm bắt đầu của dòng.
Để khắc phục điều đó, hãy thay đổi PS1
để bao gồm \[
và \]
xung quanh các chuỗi thoát màu, ví dụ:
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
Bạn không thể sử dụng get_exit_status
đúng cách ở đây, vì đầu ra của nó chứa cả in (mã thoát) và các ký tự không in (mã màu) và không có cách nào để đánh dấu chính xác trong lời nhắc. Đặt \[...\]
sẽ đánh dấu nó là không in đầy đủ, không đúng. Bạn sẽ phải thay đổi chức năng để nó chỉ in mã màu phù hợp và sau đó bao quanh nó \[...\]
trong dấu nhắc.
\[
là\1
, và\[
là\2
. Những cái đó tương ứng với một sốRL_PROMPT_{START,END}_IGNORE
thứ của readline yêu cầu nó bỏ qua các byte khi đếm độ dài dấu nhắc trên màn hình. Xem danh sách.gnu.org/archive/html/orms-bash/2015-08/msg00027.html .