私は誰かが彼らのプロンプトの一部を彼らのターミナルウィンドウで右に揃えているのを見て、それから実際のカーソルが2行目から始まるようにしたと確信しています。 PS1で「\ n」を使用して2行目を達成できることはわかっていますが、その一部を右に揃える方法がわかりません。 2つの文字列の間に空白を追加しただけですか。
プロンプトを表示する前に最初の行を表示することで、必要なことをかなり簡単に行うことができます。たとえば、次の例では、最初の行の左側に\w
のプロンプトが表示され、最初の行の右側に\u@\h
のプロンプトが表示されます。これは、ターミナルの幅を含む$COLUMNS
変数と、bashがプロンプトを表示する前に評価される$Prompt_COMMAND
パラメータを使用します。
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
printf
を$COLUMNS
とともに使用すると、次のように非常にうまく機能します。
printf "%${COLUMNS}s\n" "hello"
それは私にとってそれを完全に正当化しました。
次の例では、端末の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
内のすべてのカラーシーケンスが\[
および\]
で適切に囲まれ、存在しないことを確認する必要があります。それらのネスト。
私はここに私を投げ入れようと思っただけです。これは、GRML zshプロンプトとほぼ同じです(zshの更新を除いて、新しい行とバックスペースではプロンプトが少し良くなります-これは、bashで複製することは不可能です...少なくとも現時点では非常に困難です)。
私はこれに良い3日間を費やしました(Archを実行しているラップトップでのみテストされています)。ここにスクリーンショットと、〜/ .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\$ '
以下は、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
は\ [\]でエスケープされているため、表示される長さでカウントされません。
Gilesの回答に加えて、色をより適切に処理するために何かを書きました(それらが\[
と\]
で適切に囲まれている場合)。ケースバイケースですべてのケースを処理するわけではありませんが、 PS1LをPS1と同じ構文で設定し、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の後に改行を追加しました。これは視覚的な違いはありませんが、コマンド履歴で特定のコマンドをスクロールして戻った場合にプロンプトが文字化けしないように思われます。
他の誰かがこれを改善でき、おそらく特殊なケースのいくつかを一般化できると思います。