답변:
프롬프트를 표시하기 전에 첫 번째 행을 표시하면 원하는 작업을 쉽게 수행 할 수 있습니다. 예를 들어, 다음 \w
은 첫 번째 줄의 왼쪽에 프롬프트와 첫 번째 줄 \u@\h
의 오른쪽에 프롬프트를 표시합니다. $COLUMNS
터미널 너비를 포함 하는 변수와 $PROMPT_COMMAND
bash가 프롬프트를 표시하기 전에 평가 되는 매개 변수를 사용합니다.
print_pre_prompt ()
{
PS1L=$PWD
if [[ $PS1L/ = "$HOME"/* ]]; then PS1L=\~${PS1L#$HOME}; fi
PS1R=$USER@$HOSTNAME
printf "%s%$(($COLUMNS-${#PS1L}))s" "$PS1L" "$PS1R"
}
PROMPT_COMMAND=print_pre_prompt
.inputrc
있다 set show-mode-in-prompt on
. 모두 비 prinable의 길이를 계산하지 않는 ANSI CSI 코드를 , 제대로 묶하지 않는 \[
및 \]
@Mu 마음에서 언급 한 바와 같이. 해결책 은 이 답변 을 참조하십시오 .
여기에서 찾은 정보를 기반으로 색상에 대한 지원을 포함하여 오른쪽 또는 왼쪽의 가변 길이 내용을 수용하면서 오른쪽 정렬을위한 더 간단한 솔루션을 찾을 수있었습니다. 귀하의 편의를 위해 여기에 추가 ...
색상에 대한 참고 사항 : 그룹화 \033
없이 대안을 선호 하여 이스케이프를 사용하면 \[\]
가장 호환 가능하므로 권장됩니다.
트릭은 오른쪽을 먼저 쓴 다음 캐리지 리턴 ( \r
)을 사용 하여 줄의 시작으로 돌아가서 왼쪽 내용을 계속 덮어 씁니다.
prompt() {
PS1=$(printf "%*s\r%s\n\$ " "$(tput cols)" 'right' 'left')
}
PROMPT_COMMAND=prompt
내가 사용하고 있습니다 tput cols
에서 터미널 / 콘솔 폭을 검색하는 맥 OS X에 terminfo
내 이후 $COLUMNS
var에 채워되지 않습니다 env
하지만 당신은 교체 "대체 할 수 있습니다 *
"의 값을 %*s
제공하여, "${COLUMNS}
", 또는 다른 어떤 값 대신, 선호합니다.
다음 예제는 $RANDOM
다른 길이의 컨텐츠를 생성 하는 데 사용 하는 색상을 포함하며 구현을 재사용 가능한 함수로 리팩토링하기 위해 함수를 추출하는 방법을 보여줍니다.
function prompt_right() {
echo -e "\033[0;36m$(echo ${RANDOM})\033[0m"
}
function prompt_left() {
echo -e "\033[0;35m${RANDOM}\033[0m"
}
function prompt() {
compensate=11
PS1=$(printf "%*s\r%s\n\$ " "$(($(tput cols)+${compensate}))" "$(prompt_right)" "$(prompt_left)")
}
PROMPT_COMMAND=prompt
printf
문자열의 길이를 문자 수로 간주하여 색상을 렌더링하는 데 필요한 문자 수를 보상해야하므로 보상없이 인쇄되지 않은 ANSI 문자로 인해 항상 화면 끝보다 짧습니다. 색상에 필요한 문자는 일정하게 유지되며 printf는 다음과 같이 반환 된 길이의 변화를 고려합니다.$RANDOM
예를 들어 올바른 정렬을 유지합니다.
이것은 (예. 배쉬 프롬프트 이스케이프 시퀀스 경우가 아니라 \u
, \w
, \h
, \t
프롬프트가 표시 될 때 printf와 문자열을 렌더링 한 후 bash는 단지 그들을 변환하기 때문에이 단지 2의 길이를 기록합니다 같이)하지만. 왼쪽에는 영향을 미치지 않지만 오른쪽에는 피하는 것이 가장 좋습니다.
생성 된 컨텐츠가 일정한 길이로 유지 될 경우 아무런 결과가 없습니다. \t
24 시간 동안 항상 같은 양의 문자 (8)를 렌더링 하는 시간 옵션과 같습니다. 이 경우 인쇄시 8 자까지 계산 된 2 자 사이의 차이를 수용하기 위해 필요한 보정 만 고려하면됩니다.
\\\
문자열에 의미가있는 일부 이스케이프 시퀀스 를 세 번 이스케이프해야 할 수도 있습니다. 다음 예제와 같이 현재 작업 디렉토리 이스케이프 \w
는 다른 의미를 갖지 않으므로 예상대로 작동하지만 \t
탭 문자를 의미하는 time 은 세 번 이스케이프하지 않으면 예상대로 작동하지 않습니다.
function prompt_right() {
echo -e "\033[0;36m\\\t\033[0m"
}
function prompt_left() {
echo -e "\033[0;35m\w\033[0m"
}
function prompt() {
compensate=5
PS1=$(printf "%*s\r%s\n\$ " "$(($(tput cols)+${compensate}))" "$(prompt_right)" "$(prompt_left)")
}
PROMPT_COMMAND=prompt
조이!
다음은 터미널의 RHS에서 현재 날짜와 시간을 빨간색으로 표시합니다.
# Create a string like: "[ Apr 25 16:06 ]" with time in RED.
printf -v PS1RHS "\e[0m[ \e[0;1;31m%(%b %d %H:%M)T \e[0m]" -1 # -1 is current time
# Strip ANSI commands before counting length
# From: https://www.commandlinefu.com/commands/view/12043/remove-color-special-escape-ansi-codes-from-text-with-sed
PS1RHS_stripped=$(sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" <<<"$PS1RHS")
# Reference: https://en.wikipedia.org/wiki/ANSI_escape_code
local Save='\e[s' # Save cursor position
local Rest='\e[u' # Restore cursor to save point
# Save cursor position, jump to right hand edge, then go left N columns where
# N is the length of the printable RHS string. Print the RHS string, then
# return to the saved position and print the LHS prompt.
# Note: "\[" and "\]" are used so that bash can calculate the number of
# printed characters so that the prompt doesn't do strange things when
# editing the entered text.
PS1="\[${Save}\e[${COLUMNS:-$(tput cols)}C\e[${#PS1RHS_stripped}D${PS1RHS}${Rest}\]${PS1}"
장점 :
shellcheck
깨끗한..inputrc
있다 set show-mode-in-prompt on
.\[
하고 \]
프롬프트에서 입력 한 텍스트를 편집하면 이상하게 다시 인쇄 프롬프트가 발생하지 않습니다 그래서.참고 : 당신은 어떤 색상 시퀀스 수 있도록해야합니다 $PS1
코드 전에 제대로 묶 exeucted됩니다 \[
및 \]
그들 중 어떤 중첩이 없습니다 것을.
bash: local: can only be used in a function
. 이는 수정하기가 쉽지 않습니다. 그 후에 COLUMNS
는 정의 되어 있지 않으므로 아무것도 표시하지 않습니다 $(tput cols)
. 로 대체해야 합니다. 스 니펫이 다른 파일에 저장된 후 소스로 제공되는 경우 동일한 결과 .bashrc
.
tput cols
경우 실행할 코드를 업데이트했습니다 $COLUMNS
. 그리고 네,이 코드는 함수 안에 있어야합니다. PROMPT_COMMAND='_prompt_bash_set'
함수를 사용 하고 이름을 지정합니다 _prompt_bash_set
.
방금 여기에 내 것을 던질 줄 알았는데 GRML zsh 프롬프트와 거의 동일합니다 (zsh 업데이트를 제외하고는 줄 바꿈 및 백 스페이스에서 조금 더 나은 프롬프트가 표시됩니다-bash에서는 복제가 불가능합니다. 적어도 현재로서는 매우 어렵습니다).
나는 이것에 좋은 3 일을 보냈습니다 (아치가 달린 랩톱에서만 테스트되었습니다). 그래서 스크린 샷과 ~ / .bashrc에 들어가는 것들이 있습니다 :)
경고 -조금 미쳤어
옆 중요 -마다 ^[
(예 :가 ^[[34m
) 정말 이스케이프 문자입니다 (char)27
. 나는이를 삽입하는 방법을 알고있는 유일한 방법은 입력하는 것입니다 ctrl+ ( [v) (즉, 모두를 공격 [하고 v있는 동안 ctrl아래로 개최됩니다.
# grml battery?
GRML_DISPLAY_BATTERY=1
# battery dir
if [ -d /sys/class/power_supply/BAT0 ]; then
_PS1_bat_dir='BAT0';
else
_PS1_bat_dir='BAT1';
fi
# ps1 return and battery
_PS1_ret(){
# should be at beg of line (otherwise more complex stuff needed)
RET=$?;
# battery
if [[ "$GRML_DISPLAY_BATTERY" == "1" ]]; then
if [ -d /sys/class/power_supply/$_PS1_bat_dir ]; then
# linux
STATUS="$( cat /sys/class/power_supply/$_PS1_bat_dir/status )";
if [ "$STATUS" = "Discharging" ]; then
bat=$( printf ' v%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
elif [ "$STATUS" = "Charging" ]; then
bat=$( printf ' ^%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
elif [ "$STATUS" = "Full" ] || [ "$STATUS" = "Unknown" ] && [ "$(cat /sys/class/power_supply/$_PS1_bat_dir/capacity)" -gt "98" ]; then
bat=$( printf ' =%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
else
bat=$( printf ' ?%d%%' "$( cat /sys/class/power_supply/$_PS1_bat_dir/capacity )" );
fi;
fi
fi
if [[ "$RET" -ne "0" ]]; then
printf '\001%*s%s\r%s\002%s ' "$(tput cols)" ":( $bat " "^[[0;31;1m" "$RET"
else
printf '\001%*s%s\r\002' "$(tput cols)" "$bat "
fi;
}
_HAS_GIT=$( type 'git' &> /dev/null );
# ps1 git branch
_PS1_git(){
if ! $_HAS_GIT; then
return 1;
fi;
if [ ! "$( git rev-parse --is-inside-git-dir 2> /dev/null )" ]; then
return 2;
fi
branch="$( git symbolic-ref --short -q HEAD 2> /dev/null )"
if [ "$branch" ]; then
printf ' \001%s\002(\001%s\002git\001%s\002)\001%s\002-\001%s\002[\001%s\002%s\001%s\002]\001%s\002' "^[[0;35m" "^[[39m" "^[[35m" "^[[39m" "^[[35m" "^[[32m" "${branch}" "^[[35m" "^[[39m"
fi;
}
# grml PS1 string
PS1="\n\[\e[F\e[0m\]\$(_PS1_ret)\[\e[34;1m\]${debian_chroot:+($debian_chroot)}\u\[\e[0m\]@\h \[\e[01m\]\w\$(_PS1_git) \[\e[0m\]% "
나는 여전히 색상을 구성 할 수 있도록 노력하고 있지만 지금은 색상에 만족합니다.
현재 미친 ^[
캐릭터와 쉬운 색상 전환 에 대한 수정 작업 중입니다. :)
printf
올바른 정렬을 수행 하는 데 사용할 수 있습니다 .
$ printf "%10s\n" "hello"
hello
$ PS1='$(printf "%10s" "$somevar")\w\$ '
자일스 '답변을 추가, 더 나은 (제대로 묶여있어 제공되는 핸들 색상에 뭔가를 작성 \[
하고 \]
. 그것은 사건의 경우 별과 모든 경우를 처리하지 않습니다, 그러나 그것은 나를 PS1과 같은 구문 내 PS1L을 설정할 수 있습니다 (색이 지정되지 않은) 날짜를 PS1R로 사용합니다.
function title {
case "$TERM" in
xterm*|rxvt*)
echo -en "\033]2;$1\007"
;;
*)
;;
esac
}
print_pre_prompt() {
PS1R=$(date)
PS1L_exp="${PS1L//\\u/$USER}"
PS1L_exp="${PS1L_exp//\\h/$HOSTNAME}"
SHORT_PWD=${PWD/$HOME/~}
PS1L_exp="${PS1L_exp//\\w/$SHORT_PWD}"
PS1L_clean="$(sed -r 's:\\\[([^\\]|\\[^]])*\\\]::g' <<<$PS1L_exp)"
PS1L_exp=${PS1L_exp//\\\[/}
PS1L_exp=${PS1L_exp//\\\]/}
PS1L_exp=$(eval echo '"'$PS1L_exp'"')
PS1L_clean=$(eval echo -e $PS1L_clean)
title $PS1L_clean
printf "%b%$(($COLUMNS-${#PS1L_clean}))b\n" "$PS1L_exp" "$PS1R"
}
여기 github에 있습니다 : dbarnett / dotfiles / right_prompt.sh . 내 .bashrc에서 다음과 같이 사용합니다.
source $HOME/dotfiles/right_prompt.sh
PS1L='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]'
PS1='\[\033[01;34m\]\w\[\033[00m\]\$ '
PROMPT_COMMAND=print_pre_prompt
참고 : PS1R 이후에도 줄 바꿈을 추가하여 시각적 차이는 없지만 명령 기록에서 특정 명령을 다시 스크롤하면 프롬프트가 깨지지 않는 것 같습니다.
나는 누군가 다른 사람이 이것을 향상시킬 수 있다고 확신하고, 특별한 경우를 일반화 할 수 있습니다.
여기에 기반 솔루션 PROMPT_COMMAND
과는 tput
:
function __prompt_command() {
local EXIT="$?" # This needs to be first
history -a
local COL=$(expr `tput cols` - 8)
PS1="💻 \[$(tput setaf 196)\][\[$(tput setaf 21)\]\W\[$(tput setaf 196)\]]\[$(tput setaf 190)\]"
local DATE=$(date "+%H:%M:%S")
if [ $EXIT != 0 ]; then
PS1+="\[$(tput setaf 196)\]\$" # Add red if exit code non 0
tput sc;tput cuu1; tput cuf $COL;echo "$(tput setaf 196)$DATE"; tput rc
else
PS1+="\[$(tput setaf 118)\]\$"
tput sc;tput cuu1; tput cuf $COL;echo "$(tput setaf 118)$DATE"; tput rc
fi
PS1+="\[$(tput setaf 255)\] "
}
PROMPT_COMMAND="__prompt_command"
마법은 다음에 의해 수행됩니다.
tput sc;tput cuu1; tput cuf $COL;echo "$(tput setaf 196)$DATE"; tput rc
다음과 같이 분류됩니다.
tput sc # saved the cursor position
tput cuu1 # up one line
tput cuf $COL # move $COL characters left
echo "$(tput setaf 196)$DATE" # set the colour and print the date
tput rc # restore the cursor position
PS1에서 tput
\ [\]로 이스케이프되어 표시된 길이로 계산되지 않습니다.