맥락과 질문
터미널 과 셸 환경 을 색칠하는 방법에는 여러 가지가 있습니다. ls
및과 같은 개별 명령의 출력 grep
도 색상을 지정할 수 있습니다. 콘솔에서 미디어를 재생 한다는 개념은 직접적으로 관련되어 있지는 않지만 흥미 롭습니다 . 다음 질문은 bash
쉘과 그 구현 에만 초점을 맞추고 있습니다. Linux 터미널 프레임 워크에서의 및 그 토대 있습니다.
2D 게임 에서 장면의 ASCII "렌더링"에 대한 다음 몽타주를 고려하십시오 .
이들은 무작위로 생성 된 장면이 아닙니다. 내가 선택한 세그먼트는 실제로 ASCII 문자를 사용하여 그러한 객체를 나타내는 게임에서 "잔디"지형 (나무, 관목 및 관목, 꽃, 잔디 등)의 일부 형태를 실제로 묘사합니다. 사용자가 타일셋을 만든 마지막 4 가지 장면 가 기본적으로 색상 사양을 가진 ASCII 문자를 다시 매핑 한 를 (세부 사항은 사소한 것입니다. 이것이 시각적 인 관점에서 "내가 달성하려는 것에 대한 시각적 인 영감"이라고 말하기에 충분합니다. 무늬").
몽타주 공유에서 이러한 장면의 일반적인 특징은 다음과 같습니다.
- 최대 5-6 개의 다른 ASCII 문자 (쉼표, 따옴표 및 기타 몇 개)
- 사용 된 2-4 색
- 캐릭터를 위해
- 경우에 따라 문자 배경의 경우-마지막 예는 패턴을 생성하기 위해 문자가 거의 또는 전혀없는 색조를 사용하는 방법을 보여줍니다.
현재 VM에서 가지고있는 것은 Arch Linux 이며 질문은 배포 관련이 아니지만 파일 을 사용자 정의하기 위해 해당 설명서 를 살펴 보았습니다 /etc/bash.bashrc
. 많은 설명이 프롬프트 의 모양 과 일반적으로 모든 전경 요소 를 구성하는 것으로 나타납니다 . 일반적으로 다음 설정 및 팁 과 같은 단색을 제외하고 배경 구성에 대한 정보는 거의 없습니다 .
# 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
나는 여전히 콘솔을 사용할 때 입력하지 않은 빈 / 빈 / 백그라운드 "공백"이 무엇인지 개념적으로 파악하지 못합니다. 말하자면. 특히 프롬프트에없고 에코되는 명령을 둘러싼 것들. 활성 라인에서 발생하는 상황과 관련하여 bash
"라인 지향"방식으로 작동하고 일부 조작이 활성 라인의 지우기를 트리거한다는 것을 증명할 수 있습니다 ( for i in $(seq 1 $(expr $(tput lines) \* $(tput cols))); do echo -n M; done; tput cup 15 1
, 프롬프트에서 문자와 백 스페이스를 입력하면-설명 됨). 기고자)-CLI의 범위에 따라 zsh에 따라 다를 수 있습니다. 또한 배경 에 관한 한 출력 모양보다 \[\033[44m\]
PS1 라인에 비슷한 것을 추가 할 때 보입니다 .bash.bashrc
너무 분명 내가 알고 있다는 것을 - 나는 떠들썩한 파티를 다시로드 한 후 파란색 배경을 얻을 일부
그러나 bash는 화면에 물건을 가져 오기 위해 TTY 하위 시스템 의 형태로 다른 시설에 의존하는 소프트웨어 조각이라는 것을 알고 있습니다. 이것은 내가 생각하는 커널 의 VT 구성 요소 로 내려갑니다 . pstree -Ap
에 아치 쇼에 systemd
연결된 login
다음에 연결 됩니다 bash
.
아치 리눅스 배포판에 의존 agetty
TTY 서비스를 위해. 단순함 echo $TERM
은 사용중인 터미널 유형 (DE 외부의 "linux")을 생성하며 infocmp[-d spec1 spec2]
매개 변수가없는 명령은 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,
그대로, 터미널 프레임 워크에서 많은 기능을 활용할 수 있으며 PS1 변수를 설정하여 프롬프트가 사용자 정의되는 한 기본적으로 bash.bashrc 구성 파일에 노출되는 기능입니다. 제어 및 이스케이프 시퀀스 는 기본적으로 터미널 정보 데이터베이스에 설명 된 커서 및 기타 기능 이동을 포함하여 기능을 제공하기 위해 터미널에 표시되는 문자 흐름을 중단하는 데 사용됩니다. 이러한 기능 중 다수는 잘 알려진 ESC[
(또는 \ 33) Control Sequence Introducer ( 여기 및 여기에 더 많은 시퀀스 및 일부 예 ) 를 사용하여 전달됩니다 . 또한,tput
일부 터미널 특성을 변경하기 위해 CLI에서 직접 유틸리티; 예를 들어 tput setab 4
파란색 배경에 bash echo 명령이 있습니다.
우리 strace bash
가 이스케이프 시퀀스와 동작을 모두 볼 수 있다면 :
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
이것은 질문에 대한 맥락을 제공합니다 . 터미널의 빈 공간 / 배경색을 임의의 (그러나 예쁜) ASCII 문자 세트로 바꿀 수 있습니까? 그러나 기능을 구현하는 방법이나 터미널에서 찾고있는 것을 알지 못합니다.
그래서 이것이 가능할 경우 최종 결과가 어떻게 보일지에 대한 예로써 조잡한 모형을 만들었습니다 (심하게 :).
기본적으로 터미널의 모든 "빈 공간"은 패턴으로 채워집니다 (여기서는 위에서 이미지 중 하나를 "타일"하지만 각 개별 "공백"에 대한 실제 구현에서 몽타주에서 문서화 한 5-6 문자 및 기능). 활성 명령 행 (예 : 물결 모양의 "물")에 대해 다른 패턴이 있지만 선이 파란색 인 것으로 설정합니다. 이것이 상상 된 바와 같이, 명령은 활성 라인에 입력 될 때 "물"을 "소거"하고, 물론 문자 패턴이 CLI에 의해 해석되지 않는다는 제약이있을 것입니다. 그렇지 않으면 쓸모가 없게됩니다.
따라서 bash
터미널 프레임 워크에 노출 된 구성 이나 문자 집합 및 색상에 대한 일부 제어를 사용하여 터미널의 bash 출력을 수정하여 배경에 다소 임의의 패턴을 생성 할 수있는 스크립트가 있습니까? (위에서 보여준 것과 비슷한 것입니까?) 아니면 단순히 전체 패턴 이미지를 tty 의 배경 으로 제공하려고하는 것과 같은 것에 정착해야 합니까?
구현
0.1-PatternOTD 버전 (로그인시 한 번의 거래)
.bashrc 파일에 추가 한 다음 표현식은 우리가 탐구 한 개념 중 일부를 모아서 표준 Linux 터미널의 비주얼에 대한 (아주) 기본 개념 증명을 구성합니다.
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
관찰
- 분명히 명령 일뿐이므로 영구적이지 않습니다. 즉 명령이 입력되면 스크롤됩니다.
- 문자 선택을 개별적으로 무작위 화하지 않기로 선택했습니다. 예
head -c 1
를 들어tput cols
줄을 곱하면 인용 된 선택에서 개별 임의 문자가 인쇄됩니다. 너무 느리기 때문입니다. 나는random
(put cols) 긴 정수를 생성 한다고 생각하지 않지만 여전히 더 빠릅니다. 확실히 이것은 모두 매우 낭비이지만 작동합니다. - 각 문자를 개별적으로 렌더링 / 처리하는 것이 너무 느리기 때문에 캐릭터 당 또는 녹색을 제외하고는 색상이나 효과를 무작위로 지정하지 않았습니다. 다시 : 프레임 버퍼?
- CLI가 해석하지 않는다는 의미에서 패턴이 CLI 사용을 방해하지 않는다는 것을 알게되어 기쁩니다! (왜 설명하지 못했지만)
- 물이 너무 빨리 사라졌습니다! ;-)
0.2-PROMPT_COMMAND 해킹 작업
변수 PROMPT_COMMAND 의 값은 Bash가 각 기본 프롬프트를 인쇄하기 직전에 검사됩니다. 나는 보통 변수를 사용하여 디스플레이 등의 요소를 처리 할 수있는 스크립트를 호출한다는 것을 알고 있지만 오히려 내 .bashrc 파일에서 직접 수행하려고합니다. 내가 함께 화면 어느 곳에서 일을 렌더링 갈 수 처음에 내가 실행 전에 커서 일부 위치 인식, 즉 구현할 수 있다고 생각 (그래서 tput
무언가 사용하여, 내가 전에 있던 위치로 돌아와 이 같은 추출 위치를 :
stty -echo; echo -n $'\e[6n'; read -d R x; stty echo; echo ${x#??} //value is in x;x format so...
값을로 파이프합니다 cut -f1 -d";"
. CLI 에서이 작업을 수행 할 수 있지만 PS1 / P_C 변수의 요소 시퀀스 에서이 작업을 수행하는 것은 현재 도달 할 수 없으며 PROMPT_COMMAND에 넣은 모든 명령이 모든 캐리지 리턴에서 평가되지 않을 수도 있습니다. 매번 실행되지만 한 번만 (?) (아래 관찰 참조)
그래서 내가 할 수있는 최선의 방법은 초기 시퀀스를 수행하고 PROMPT_COMMAND와 .bashrc의 PS1 변수 정의에 명령을 추가하는 것입니다. 이렇게 :
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
요약하면 P_C를 사용하여 지속적인 시각적 패턴을 구현하려고합니다. 즉 2 줄이 추가됩니다. 불행히도 나는 "물"트릭을 반복 하면서이 패턴을 모두 만들 수 없습니다. 즉, 활성 선이 파란색입니다 (배경색을 변경하고 명확한 선을 그린 다음 배경을 다시 검은 색으로 변경). 이것이 어떻게 작동하는지 보여주는 이미지를 모았습니다.
관찰
- 줄에 백 스페이스를 사용하면 여전히 명확한 선 동작이 트리거되고 파란색이 사라집니다.
- Enter 키를 누를 때마다 새로운 활성 라인 앞에 두 줄의 패턴이 있습니다.
- 물론 추가 라인에도 불구하고 더 아래로 볼 때 우리는 다음과 같은 명령 측면에 패턴을 배치하지 않습니다.
ls
- / dev / urandom의 랜덤 성은 여기 P_C에서 호출 될 때 그렇게 무작위 적이 지 않은 것 같습니다. 이 이미지는 2 개의 이미지로 구성되어 있지만 여분의 2 줄 패턴은 항상 동일합니다. 즉, 모든 Enter 키를 누를 때마다 임의성이 생성되지 않고 두 줄 각각에 대해 한 번만 발생합니다. time .bashrc는에 의해 읽 힙니다
bash
. - PS1 변수의 내용은
$(echo -en '\n') $(tput setab 4)
$ (tput ...) 직전에 중간에있는 공간으로 시작 합니다.이 작동하려면 반드시 있어야합니다. 그렇지 않으면 파란색 선이 프롬프트 위에 나타나지 않고 앞에 표시되며 해결할 수 없습니다. 그리고이 핵은 그 이름을 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\]"
PROMPT_COMMAND를 사용하면 프롬프트가 생성되기 전에 매번 3 줄의 패턴이 인쇄됩니다.이 3 가지 패턴 세트는 0.2에 설명 된 제한 조건 내에서 개별적으로 생성됩니다. 그런 다음을 사용하여 두 줄 위로 올라가고 tput cuu 2
PS1에 따라 중간 줄에 프롬프트가 생성됩니다. 터미널에 로그인 할 때 한 번만 실행되는 .bashrc load의 전체 화면 패턴에 대한 초기 명령 세트가 있습니다. 이제 우리는 리턴 라인이있을 때 항상 반복되는 자체 파란색 패턴을 가진 활성 라인 주위에 패딩을 가지고 있습니다. PS1 변수와 P_C의 내용이 삭제되었습니다. 이스케이프 시퀀스의 구문과 긴 색상에 포함 된 컬러 코딩echo
시퀀스는 까다로울 수 있습니다. 오류로 인해 이상한 터미널 동작이 발생합니다서로 덮어 쓰는 행, 왼쪽 여백에서 벗어난 프롬프트 또는 의도하지 않게 처리 된 항목에 대한 비정상적인 출력을 포함합니다. PS1 변수 내부에 Linux 터미널과 lxterm의 시각적 차이 (내 설정) (Arch Bang)에 시각적 차이를 없애기 위해 PS1 변수 내에 추가 공간이 필요한 조건이 있습니다. 여분의 공간이 없으면 리눅스 터미널은 마지막 줄의 끝에 프롬프트의 첫 번째 문자를 알아낼 수없는 이유로 인쇄합니다 (물론 기본 동작이 아니라 내가하는 것입니다). 또한 성능을 높이기 위해 더 긴 문자열을 생성하기로 일찍 결정되었으므로 따옴표로 묶인 문자 세트에 임의의 효과 (굵게, 역 등)를 생성하는 방법을 알 수 없습니다.
터미널이 열릴 때의 초기 패턴
clear
프롬프트에서 a 를 누르고 연속으로 Enter 키를 누른 후 동작
관찰
- 패턴을 일괄 처리하는 것 이상의 색상을 구현하도록 재 설계 또는 수정해야 함
- 훨씬 더 나아가려면 모든 것을 스크립트에 넣거나 더 높은 추상화 형식을 사용해야합니다. 그러나 터미널 기능은 최종 사용자를 위해 상당히 가능합니다 ( "로고"를 상기시킵니다)!