Bối cảnh và câu hỏi
Có nhiều cách để tô màu cho môi trường thiết bị đầu cuối và vỏ. Đầu ra của các lệnh riêng lẻ, chẳng hạn như ls
và grep
, cũng có thể được tô màu. Không liên quan trực tiếp nhưng dù sao cũng thú vị là khái niệm chơi phương tiện tại bàn điều khiển nhưng điều này dường như dựa vào một số khung (thư viện) trên đầu hệ thống cửa sổ. Câu hỏi sau đây chỉ hướng đến hệ bash
vỏ và việc triển khai nó trong khung thiết bị đầu cuối Linux và nền tảng của nó.
Vui lòng xem xét cách dựng phim "kết xuất" sau đây của ASCII về một cảnh trong trò chơi 2D :
Đây không phải là những cảnh được tạo ngẫu nhiên. Các phân đoạn tôi đã chọn thực sự mô tả một số dạng địa hình "đồng cỏ" (cây, bụi rậm & cây bụi, hoa, cỏ, v.v.) từ một trò chơi sử dụng các ký tự ASCII để thể hiện các đối tượng đó. 4 cảnh cuối cùng giới thiệu sử dụng làm tilesets mà cơ bản là một remap của các ký tự ASCII với thông số kỹ thuật màu sắc (chi tiết như là tầm thường - nó đủ để nói rằng đây là nguồn cảm hứng thị giác cho những gì tôi đang cố gắng để hoàn thành ở đây về mặt hình ảnh và " mẫu").
Các đặc điểm chung của những cảnh trong phần dựng phim là:
- Tối đa 5-6 ký tự ASCII khác nhau (dấu phẩy, dấu ngoặc kép và một vài ký tự khác)
- 2-4 màu sử dụng
- cho các nhân vật
- đối với nền của nhân vật trong một số trường hợp - ví dụ cuối cùng là để hiển thị việc sử dụng các sắc thái màu với ít hoặc không có ký tự để tạo ra một mẫu, ví dụ như khảm màu
Những gì tôi có trong một máy ảo hiện tại là Arch Linux và mặc dù câu hỏi không phải là phân phối cụ thể, tôi đã xem xét tài liệu của họ để tùy chỉnh /etc/bash.bashrc
tệp. Tôi có thể thấy rằng rất nhiều giải thích đi vào cấu hình sự xuất hiện của dấu nhắc và nói chung là tất cả các yếu tố tiền cảnh. Có rất ít thông tin về bất kỳ cấu hình nào cho nền, ngoại trừ thông thường cho một màu đơn sắc, chẳng hạn như các cài đặt và mẹo này :
# Background
On_Black='\e[40m' # Black
On_Red='\e[41m' # Red
On_Green='\e[42m' # Green
On_Yellow='\e[43m' # Yellow
On_Blue='\e[44m' # Blue
On_Purple='\e[45m' # Purple
On_Cyan='\e[46m' # Cyan
On_White='\e[47m' # White
Về mặt khái niệm, tôi vẫn không nắm bắt được những "khoảng trống" trống / trống / nền nào mà tôi không gõ khi tôi sử dụng bảng điều khiển tức là "chúng được làm từ gì?" để nói Đặc biệt là những lệnh không ở dấu nhắc và bao quanh các lệnh được lặp lại. Đối với những gì xảy ra trên dòng hoạt động, có thể chứng minh rằng bash
hành động đó theo cách "định hướng theo dòng" và một số thao tác kích hoạt xóa dòng hoạt động ( for i in $(seq 1 $(expr $(tput lines) \* $(tput cols))); do echo -n M; done; tput cup 15 1
sau đó, tại dấu nhắc gõ char và xóa lùi nó - đã thể hiện một người đóng góp) - mức độ có thể thay đổi từ CLI sang khác tức là zsh. Hơn nữa, dường như khi tôi thêm một cái gì đó giống như \[\033[44m\]
dòng PS1 của tôi vào thì bash.bashrc
tôi có nền màu xanh sau khi tải lại bash - vì vậy rõ ràng tôi biết rằng có một sốđòn bẩy ở đây trên sự xuất hiện đầu ra trong chừng mực nền tảng có liên quan.
Nhưng tôi cũng biết rằng bash là một phần mềm dựa trên một số cơ sở khác dưới dạng hệ thống con TTY để đưa mọi thứ lên màn hình - và điều này đi xuống từ đó đến thành phần VT trong kernel tôi giả sử. pstree -Ap
trên Arch hiển thị systemd
liên kết đến login
và sau đó đến bash
.
Bản phân phối Arch Linux dựa trên agetty
các dịch vụ TTY. Một đơn giản echo $TERM
sẽ mang lại loại thiết bị đầu cuối đang sử dụng ("linux" ở đây bên ngoài bất kỳ DE nào) và infocmp[-d spec1 spec2]
lệnh không có tham số hiển thị các khả năng của thiết bị đầu cuối hoạt động và thông tin hồ sơ từ cơ sở dữ liệu đầu cuối terminfo (5) :
# Reconstructed via infocmp from file: /usr/share/terminfo/l/linux
linux|linux console,
am, bce, ccc, eo, mir, msgr, xenl, xon,
colors#8, it#8, ncv#18, pairs#64,
acsc=+\020\,\021-\030.^Y0\333'\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376,
bel=^G, blink=\E[5m, bold=\E[1m, civis=\E[?25l\E[?1c,
clear=\E[H\E[J, cnorm=\E[?25h\E[?0c, cr=^M,
csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
cvvis=\E[?25h\E[?8c, dch=\E[%p1%dP, dch1=\E[P, dim=\E[2m,
dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K,
el1=\E[1K, flash=\E[?5h\E[?5l$, home=\E[H,
hpa=\E[%i%p1%dG, ht=^I, hts=\EH, ich=\E[%p1%d@, ich1=\E[@,
il=\E[%p1%dL, il1=\E[L, ind=^J,
initc=\E]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x,
kb2=\E[G, kbs=\177, kcbt=\E[Z, kcub1=\E[D, kcud1=\E[B,
kcuf1=\E[C, kcuu1=\E[A, kdch1=\E[3~, kend=\E[4~, kf1=\E[[A,
kf10=\E[21~, kf11=\E[23~, kf12=\E[24~, kf13=\E[25~,
kf14=\E[26~, kf15=\E[28~, kf16=\E[29~, kf17=\E[31~,
kf18=\E[32~, kf19=\E[33~, kf2=\E[[B, kf20=\E[34~,
kf3=\E[[C, kf4=\E[[D, kf5=\E[[E, kf6=\E[17~, kf7=\E[18~,
kf8=\E[19~, kf9=\E[20~, khome=\E[1~, kich1=\E[2~,
kmous=\E[M, knp=\E[6~, kpp=\E[5~, kspd=^Z, nel=^M^J, oc=\E]R,
op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM, rmacs=\E[10m,
rmam=\E[?7l, rmir=\E[4l, rmpch=\E[10m, rmso=\E[27m,
rmul=\E[24m, rs1=\Ec\E]R, sc=\E7, setab=\E[4%p1%dm,
setaf=\E[3%p1%dm,
sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
sgr0=\E[0;10m, smacs=\E[11m, smam=\E[?7h, smir=\E[4h,
smpch=\E[11m, smso=\E[7m, smul=\E[4m, tbc=\E[3g,
u6=\E[%i%d;%dR, u7=\E[6n, u8=\E[?6c, u9=\E[c,
vpa=\E[%i%p1%dd,
Vì thế, nhiều khả năng có thể được tận dụng từ khung thiết bị đầu cuối và về cơ bản, đó là những tính năng được thể hiện trong tệp cấu hình bash.bashrc khi lời nhắc được tùy chỉnh bằng cách đặt biến PS1. Các chuỗi điều khiển và thoát được sử dụng để làm gián đoạn luồng ký tự hiển thị trong thiết bị đầu cuối nhằm cung cấp các chức năng, bao gồm di chuyển con trỏ và các khả năng khác được mô tả trong cơ sở dữ liệu thông tin đầu cuối. Nhiều trong số các chức năng đó được truyền vào bằng cách sử dụng Trình giới thiệu trình tự điều khiển nổi tiếng ESC[
(hoặc \ 33) (nhiều trình tự ở đây và ở đây , và một số ví dụ ). Hơn nữa, nó cũng có thể sử dụngtput
tiện ích trực tiếp trên CLI để thay đổi một số thuộc tính thiết bị đầu cuối; ví dụ tput setab 4
sẽ có các lệnh bash echo trên nền màu xanh.
Nếu chúng strace bash
ta có thể thấy cả chuỗi thoát và hành vi đang hoạt động:
write(2, "[il@Arch64vm1 ~]$ ", 19[il@Arch64vm1 ~]$ ) = 19 //bash starts
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, " ", 1) = 1 //pressed <space>
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, " ", 1 ) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "\177", 1) = 1 //pressed <backspace>...
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "\10\33[K", ) = 4 //triggers erasing the line
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "\33", 1) = 1 //pressed <esc> per se
Điều này cung cấp ngữ cảnh cho câu hỏi Có thể thay thế các khoảng trống / màu nền trong thiết bị đầu cuối bằng một bộ ký tự ASCII ngẫu nhiên (nhưng đẹp) không? nhưng không biết làm thế nào để thực hiện các tính năng hoặc về những gì tôi đang tìm kiếm trong thiết bị đầu cuối.
Vì vậy, tôi đã tạo ra một mockup thô sơ như một ví dụ về kết quả cuối cùng có thể trông như thế nào nếu điều này là có thể (không nghiêm túc :):
Về cơ bản, tất cả "không gian trống" trong thiết bị đầu cuối sẽ được lấp đầy bằng mẫu (ở đây tôi "xếp" một trong các hình ảnh từ trên xuống nhưng tôi muốn thực hiện thực tế cho từng "trống" riêng lẻ được tạo ngẫu nhiên từ bộ 5-6 ký tự và tính năng được ghi lại từ đoạn phim sẽ được chỉ định). Có một mẫu khác cho dòng lệnh đang hoạt động tức là "nước" lượn sóng nhưng tôi giải quyết cho dòng có màu xanh. Như điều này đã được tưởng tượng, các lệnh sẽ "xóa" "nước" khi chúng được gõ trên dòng hoạt động và tất nhiên một hạn chế là mô hình các ký tự không bao giờ được CLI giải thích nếu không nó sẽ vô dụng.
Vì vậy, có bất kỳ cấu hình nào được hiển thị trong bash
hoặc trong khung thiết bị đầu cuối, hoặc một tập lệnh cho phép sử dụng một bộ ký tự và một số điều khiển màu để sửa đổi đầu ra của bash trong terminal để tạo ra một mẫu ngẫu nhiên cho nền (sẽ tương tự như những gì tôi đã trình bày ở trên)? Hoặc tôi nên đơn giản giải quyết cho một cái gì đó như cố gắng cung cấp một hình ảnh đầy đủ mẫu làm nền cho tty ?
Triển khai
0.1 - Phiên bản PatternOTD (thỏa thuận một lần bắn khi bạn đăng nhập)
Biểu thức sau đây tôi đã thêm vào tệp .bashrc của mình kết hợp một số khái niệm chúng ta đã khám phá và tạo thành một bằng chứng cơ bản (rất) về khái niệm cho hình ảnh trong thiết bị đầu cuối linux tiêu chuẩn:
for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[32;32m'$(tr -dc '",.;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 15; tput setab 4; echo -en "\E[2K"; tput setab 0
Quan sát
- Nó rõ ràng chỉ là một lệnh nên không bền bỉ, tức là nó cuộn đi khi các lệnh được gõ
- Chọn để không riêng ngẫu nhiên việc lựa chọn nhân vật tức là
head -c 1
vớitput cols
nhân đường để bắt đầu với, mà sẽ in chars ngẫu nhiên cá nhân từ sự lựa chọn trích dẫn - bởi vì nó quá chậm. Tôi không nghĩrandom
tạo ra một số nguyên dài (tput cols) nhưng vẫn nhanh hơn. Chắc chắn điều này là rất lãng phí nhưng nó hoạt động. - Không ngẫu nhiên bất kỳ màu sắc hoặc hiệu ứng cho mỗi ký tự hoặc ngoại trừ màu xanh lá cây đó bởi vì như tôi đã giải thích kết xuất / xử lý mỗi char riêng lẻ là quá chậm. Re: bộ đệm khung?
- Tôi rất vui khi thấy rằng mô hình không can thiệp vào việc sử dụng CLI theo nghĩa không được CLI giải thích! (tại sao tôi không thể giải thích)
- Nước đi quá nhanh! ;-)
0.2 - Công việc hack PROMPT_COMMAND
Giá trị của biến PROMPT_COMMAND được kiểm tra ngay trước khi Bash in từng dấu nhắc chính. Tôi biết thông thường bạn sẽ sử dụng biến để gọi một tập lệnh trong đó bạn có thể xử lý các phần tử từ màn hình, v.v. nhưng tôi đang cố gắng thực hiện điều này trực tiếp trong tệp .bashrc của mình. Ban đầu tôi nghĩ rằng tôi có thể thực hiện một số nhận thức về vị trí, tức là con trỏ ở đâu trước khi thực hiện (vì vậy tôi có thể kết xuất mọi thứ trên màn hình ở bất cứ đâu tput
sau đó quay lại vị trí tôi trước đây, sử dụng cái gì đó như thế này để trích xuất vị trí:
stty -echo; echo -n $'\e[6n'; read -d R x; stty echo; echo ${x#??} //value is in x;x format so...
Tôi sẽ ống giá trị đến cut -f1 -d";"
. Tôi có thể thực hiện điều này trên CLI nhưng làm cho công việc này nằm trong chuỗi các yếu tố trong các biến PS1 / P_C nằm ngoài tầm với của tôi vào lúc này và có thể không có bất kỳ lệnh nào được đưa vào PROMPT_COMMAND trong mỗi lần trả về vận chuyển mà thay vào đó chỉ một lần (?) mặc dù được thực hiện mỗi lần (xem các quan sát bên dưới).
Vì vậy, điều tốt nhất tôi có thể làm là thực hiện trình tự ban đầu của mình và thêm một số lệnh vào cả PROMPT_COMMAND và định nghĩa của biến PS1 trong .bashrc. Thích như vậy:
PROMPT_COMMAND="echo -en '\E[32;32m'$(tr -dc ',.:~' < /dev/urandom | head -c $(echo "$[$(tput cols) * 2]"))"
PS1="$(echo -en '\n') $(tput setab 4)$(echo -en "\E[2K")$(tput setab 0)\[\033[7;32m\]df:\[\033[1;34m\] \W @d \[\033[0m\]\e[32m"
for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[32;32m'$(tr -dc '",.;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 1; tput setab 4; echo -en "\E[2K"; tput setab 0
Tóm lại, tôi đang sử dụng P_C để cố gắng triển khai một mẫu trực quan bền vững, tức là 2 dòng được thêm vào. Thật không may, tôi không thể thành công trong việc tạo cả hai mẫu này trong khi lặp lại thủ thuật "nước" của mình, tức là có dòng màu xanh hoạt động (chỉ thay đổi màu nền, thực hiện một đường rõ ràng, sau đó thay đổi nền trở lại màu đen). Tôi đã ghép lại một hình ảnh để cho thấy cách nó chơi với nhau:
Quan sát
- Sử dụng backspace trên một dòng vẫn kích hoạt hành vi dòng rõ ràng và màu xanh không còn nữa
- Mỗi lần nhấn phím enter, chúng ta có 2 dòng mẫu trước dòng hoạt động mới
- Tất nhiên, khi chúng ta nhìn xa hơn mặc dù các dòng bổ sung, chúng ta không gói mẫu bên cạnh các lệnh như
ls
- Tính ngẫu nhiên của / dev / urandom dường như không quá ngẫu nhiên khi được gọi ở đây trong P_C. Hình ảnh này được tạo thành từ 2 hình ảnh, nhưng thật dễ dàng để nhận ra rằng mẫu 2 dòng bổ sung luôn giống nhau, tức là tính ngẫu nhiên không được tạo ra với mỗi lần nhấn phím mà chỉ một lần cho mỗi trong hai dòng - có thể chỉ là lần đầu tiên thời gian .bashrc được đọc bởi
bash
. - Nội dung của biến PS1 bắt đầu bằng
$(echo -en '\n') $(tput setab 4)
- không gian ở giữa đó, ngay trước $ (tput ...), nó PHẢI ở đó để nó hoạt động. Nếu không, dòng màu xanh xuất hiện trên đầu dấu nhắc và không ở phía trước nó và tôi không thể giải quyết điều đó. Và hack này là những gì mang tên của nó đến 0,2. :)
0,3 - tput cuu
&tput cud
for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[0;32m'$(tr -dc '",.o;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 1
PROMPT_COMMAND="echo -en '\033[0;32m$(tr -dc ',;o.:~' < /dev/urandom | head -c $(tput cols))\n\033[36;44m$(tr -dc '~' < /dev/urandom | head -c $(tput cols))\033[0;32m$(tr -dc ',.o+;:~' < /dev/urandom | head -c $(tput cols))'$(tput cuu 2)"
PS1="\[\033[0m\] \[\033[1;32m\][1]\[\033[7;32m\]=2=:\W)\[\033[0;32m\]=3=\[\033[1;32m\]=4=@>\[\033[0;32m\]"
Điều được thực hiện với PROMPT_COMMAND là 3 dòng mẫu được in mỗi lần trước khi lời nhắc được tạo - và 3 bộ mẫu đó được tạo riêng lẻ trong các ràng buộc được giải thích trong 0,2 - vô nghĩa đối với nước là 1 char nhưng vẫn. Sau đó, chúng tôi đi lên hai dòng (sử dụng tput cuu 2
) và lời nhắc được tạo trên dòng giữa theo PS1. Chúng tôi vẫn có bộ lệnh ban đầu cho mẫu toàn màn hình khi tải .bashrc chỉ được thực thi một lần khi chúng tôi đăng nhập vào thiết bị đầu cuối. Bây giờ chúng ta có một số phần đệm xung quanh dòng hoạt động có hoa văn màu xanh của riêng nó luôn luôn được lặp lại khi có một cỗ xe trở về. Nội dung của biến PS1 và P_C đã được khử trùng. Cú pháp của các chuỗi thoát và mã hóa màu được nhúng trong dàiecho
trình tự có thể là khó khăn. Lỗi dẫn đến hành vi kỳ lạbao gồm các dòng ghi đè lên nhau, một dấu nhắc xuất hiện ở lề trái hoặc đầu ra bất thường cho những thứ đã được xử lý ngoài ý muốn. Một điều kiện tồn tại với những gì tôi đang làm, trong đó cần thêm một khoảng trống bên trong biến PS1 để chống lại sự khác biệt trực quan giữa thiết bị đầu cuối linux và lxterm với thiết lập của tôi (Arch Bang). Không có thêm dung lượng, thiết bị đầu cuối linux in ký tự đầu tiên của dấu nhắc ở cuối dòng cuối cùng vì một số lý do tôi không thể tìm ra (tất nhiên đó là điều tôi làm và không phải là hành vi mặc định). Cũng không thể tìm ra cách tạo một số hiệu ứng ngẫu nhiên (đậm, nghịch đảo, v.v.) cho tập hợp các ký tự trong dấu ngoặc kép, vì nó đã được quyết định sớm để tạo ra các chuỗi dài hơn để tăng hiệu suất.
Mẫu ban đầu khi thiết bị đầu cuối mở
Hành vi sau một clear
và nhấn enter liên tiếp tại dấu nhắc
Quan sát
- Nên được thiết kế lại hoặc sửa đổi để thực hiện tô màu cho các mẫu ngoài việc thực hiện hàng loạt
- Bắt đầu cảm thấy rằng đi xa hơn sẽ yêu cầu hoặc đưa tất cả những điều đó vào một kịch bản hoặc tận dụng một hình thức trừu tượng cao hơn. Nhưng các khả năng của thiết bị đầu cuối khá cho phép người dùng cuối (nhắc nhở tôi về "logo")!