Sử dụng biến để lưu mã màu đầu cuối cho PS1?


33

Theo tôi .bashrc, tôi sử dụng mã màu đầu cuối ANSI để tô màu các bit khác nhau. Nó trông như thế này:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

trong đó virtual_envgit_branchlà các hàm bash tạo ra các công cụ trên thiết bị xuất chuẩn.

Bây giờ, để dễ đọc và sửa đổi hơn, tôi muốn lưu trữ mã màu theo các biến và tham khảo chúng, thay vì nhúng chúng trực tiếp vào PS1. Vì vậy, tôi có một loạt các biến như thế này:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

Tôi muốn có thể viết một cái gì đó như:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

Nhưng điều này không hoạt động - mã màu hiển thị trong lời nhắc, giống như chúng đã thoát. Màu sắc hoạt động chính xác nếu tôi sử dụng dấu ngoặc kép thay thế PS1, nhưng sau đó dấu nhắc chỉ thay đổi khi tôi thực hiện source ~/.bashrc.

Tôi đã thử những thứ khác tôi đã nhìn thấy người làm - sử dụng printf, sử dụng dấu nháy đơn cho các màu sắc, đưa \[\]trong PS1thay vì biến màu sắc, nhưng không có vẻ làm việc.

Làm thế nào tôi có thể sử dụng các biến cho mã màu?


Bạn có thể cho chúng tôi .bashrc?
cuonglm

@cuonglm Tất cả .bashrc của bạn thuộc về chúng tôi? Tôi sẽ thể hiện ra ngoài.
CivilFan

Câu trả lời:


20

Giải pháp là lấy shell để thay thế các biến màu khi xác định dấu nhắc, nhưng không phải là các hàm. Để làm điều này, hãy sử dụng dấu ngoặc kép như bạn đã thử ban đầu, nhưng thoát các lệnh để chúng không được đánh giá cho đến khi lời nhắc được rút ra.

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

Lưu ý \trước $()mỗi lệnh.

Nếu chúng tôi lặp lại điều này, chúng tôi thấy:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

Như bạn có thể thấy, các biến màu đã được thay thế, nhưng không phải là các lệnh.


1
Điều này dường như không hoạt động nếu $ (git_branch) cũng đang cố in bằng $ {YELLOW}, v.v. Trong phần đó, bạn vẫn sẽ nhận được tất cả các ký tự [].
WB Sậy

7

Vấn đề là biến của bạn GREENchứa chuỗi ký tự bao gồm "dấu gạch chéo ngược dấu gạch chéo ngược zero ba ba", v.v. Ví dụ, nó không chứa ký tự thoát ASCII theo yêu cầu để thiết bị đầu cuối của bạn thay đổi màu sắc.

Bạn có thể đặt các ký tự điều khiển vào GREEN(và YELLOWRESET) theo cách thủ công, nhưng tùy chọn tốt hơn nhiều là sử dụng tputở vị trí đầu tiên để bạn không cần mã cứng bất cứ thứ gì và bạn sẽ hỗ trợ bất kỳ loại thiết bị đầu cuối nào.

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

Lý do tại sao nó xuất hiện khi bạn đặt "dấu gạch chéo ngược số ba ba" v.v ... trực tiếp vào PS1đó là việc giải thích các chuỗi dấu gạch chéo ngược nhất định là một tính năng nhắc nhở của bash (xem phần KHUYẾN MÃI trong hướng dẫn sử dụng. Thay thế này xảy ra trước khi mở rộng tham số, lệnh thay thế, mở rộng số học và loại bỏ trích dẫn, do đó, nó không được áp dụng cho kết quả của tất cả các hoạt động khác.


5
Khi thực hiện theo cách này, bạn cần bọc các biến màu \[\]bên trong $PS1. Ví dụ : PS1='\u@\h:\w\[${YELLOW}\]'. Nếu bạn không làm điều này và bạn kết thúc bằng một lệnh dài kết thúc dòng tiếp theo, bạn sẽ gặp phải tất cả các loại vấn đề. Shell sử dụng \[\]để xác định các ký tự nào không thể in được, do đó, nó không đưa chúng vào tính toán độ dài dấu nhắc. Nó cần điều này để nó có thể vẽ đúng đường khi vượt quá chiều rộng của thiết bị đầu cuối.
Patrick

Tôi không biết tput, cảm ơn. Bây giờ tôi sẽ sử dụng câu trả lời của Patrick nhưng tôi sẽ xem lại điều này khi có cơ hội.
Ismail Badawi

2

Thay đổi cách bạn điền $ XANH, $ VÀNG VÀ $ RESET:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

1
Điều này có hiệu lực thực hiện chính xác như câu trả lời của Celada. Nhưng Celada có tính di động cao hơn trong trường hợp thiết bị đầu cuối sử dụng các mã thoát khác nhau để cài đặt màu. Nó cũng sẽ có cùng một vấn đề với điều nhanh chóng đa dòng.
Patrick

2
Các \[…\]bit cần duy trì trong dấu nhắc, bạn không thể nhét nó vào một biến. Bạn đã loại bỏ nó hoàn toàn, điều này sẽ dẫn đến các vấn đề hiển thị (con trỏ không ở vị trí mà bash mong đợi).
Gilles 'SO- ngừng trở nên xấu xa'

Ngoài những lo ngại về @Patrick, echo -e không mang tính di động.
helpermethod

1
Với tính không di động đi kèm nhiều tính năng hơn - tput setafkhông cho phép bạn chọn từ bộ màu "ánh sáng", chẳng hạn như màu lục lam nhạt. @ Câu trả lời của Cyrus, tuy nhiên, không.
CivilFan
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.