प्रॉम्प्ट का दायां संरेखित भाग


27

मुझे यकीन है कि मैंने देखा है कि किसी ने अपने टर्मिनल विंडो में दाईं ओर संरेखित अपने प्रॉम्प्ट का एक हिस्सा है और फिर दूसरी पंक्ति पर वास्तविक कर्सर शुरू किया है। मुझे पता है कि मैं PS1 में "\ n" के साथ दूसरी पंक्ति को प्राप्त कर सकता हूं, लेकिन मैं यह पता नहीं लगा सकता कि इसके दायें हिस्से को कैसे संरेखित किया जाए। क्या मैंने देखा कि दोनों तारों के बीच सिर्फ व्हाट्सएप जोड़ा गया था?

जवाबों:


17

क्या आप चाहते हैं काफी आसानी से शीघ्र प्रदर्शित करने से पहले पहली पंक्ति प्रदर्शित करके किया जा सकता है। उदाहरण के लिए, निम्नलिखित \wपहली पंक्ति के बाईं ओर एक संकेत और पहली पंक्ति \u@\hके दाईं ओर एक संकेत प्रदर्शित करता है । यह का उपयोग करता है $COLUMNSचर जो टर्मिनल और की चौड़ाई शामिल $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

3
ध्यान दें कि यदि आप रंगीन बायीं ओर चाहते हैं तो चीजें बहुत अधिक जटिल हो जाती हैं, क्योंकि गैर-मुद्रण वाले वर्णों का अर्थ है कि स्ट्रिंग की लंबाई प्रदर्शित वर्णों की संख्या के समान नहीं है।
म्यू माइंड

1
दोनों इस और उच्चतम सही ढंग से काम नहीं करते हैं तो जवाब मतदान .inputrcहै set show-mode-in-prompt on। दोनों गैर prinable की अवधि की गणना नहीं है एएनएसआई सीएसआई कोड , और ठीक से उन में संलग्न नहीं है \[और \]@Mu मन से उल्लेख किया। संकल्प के लिए यह उत्तर देखें ।
टॉम हैल

26

मुझे यहां मिली जानकारी के आधार पर मैं रंग के लिए समर्थन सहित दाईं या बाईं ओर चर लंबाई सामग्री को समायोजित करते हुए दाएं संरेखित करने के लिए एक सरल समाधान खोजने में सक्षम था। आपकी सुविधा के लिए यहां जोड़ा गया ...

रंगों पर ध्यान दें:\033 विकल्पों के पक्ष में भागने का उपयोग करना , बिना \[\]समूहों के, सबसे अधिक संगत और अनुशंसित है।

ट्रिक पहले दाहिने हाथ की ओर लिखने की है, फिर \rलाइन की शुरुआत में लौटने के लिए गाड़ी वापसी ( ) का उपयोग करें और बाएं हाथ की सामग्री को उस के शीर्ष पर लिखना जारी रखें, निम्नानुसार:

prompt() {
    PS1=$(printf "%*s\r%s\n\$ " "$(tput cols)" 'right' 'left')
}
PROMPT_COMMAND=prompt

मैं tput colsटर्मिनल / कंसोल की चौड़ाई को पुनः प्राप्त करने के लिए मैक ओएस एक्स पर उपयोग कर रहा हूं terminfoक्योंकि मेरी $COLUMNSvar पॉपुलेटेड नहीं है, 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 वर्णों के बिना स्क्रीन के अंत में हमेशा कमी रहेगी। रंग के लिए आवश्यक वर्ण स्थिर रहते हैं और आप पाएंगे कि प्रिंटफ लंबाई में बदलाव को भी ध्यान में रखता है, जैसे कि $RANDOMउदाहरण के लिए '।

इस विशेष पार्टी शीघ्र भागने दृश्यों के मामले में (यानी। नहीं है \u, \w, \h, \t) हालांकि, इसलिए उन्हें ही 2 की लंबाई रिकॉर्ड करेगा क्योंकि पार्टी केवल उन्हें, जब संकेत दिखाई देने पर अनुवाद करेगा printf के बाद स्ट्रिंग प्रदान की गई है। यह बाएं हाथ की तरफ को प्रभावित नहीं करता है लेकिन दाएं से बचने के लिए सबसे अच्छा है।

कोई महत्व का है, तो द्वारा निर्मित सामग्री को हालांकि लगातार लंबाई पर बना रहेगा। समय \tविकल्प की तरह जो हमेशा 24 समय के लिए वर्णों (8) की समान राशि प्रदान करेगा। हमें इन मामलों में मुद्रित किए गए 8 वर्णों के लिए गिने गए 2 वर्णों के बीच अंतर के लिए आवश्यक मुआवजे में केवल कारक की आवश्यकता है।

ध्यान रखें कि आपको \\\कुछ भागने के क्रम को तीन गुना करने की आवश्यकता हो सकती है जो अन्यथा स्ट्रिंग के लिए अर्थ रखती है। निम्नलिखित उदाहरण के साथ वर्तमान कार्य निर्देशिका से बच निकलने \wका कोई अर्थ नहीं है, इसलिए यह अपेक्षा के अनुरूप काम करता है, लेकिन समय \t, जिसका अर्थ एक टैब वर्ण है, पहले ट्रिपल से बचने के बिना अपेक्षा के अनुरूप काम नहीं करता है।

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

एन ज्वॉय!


8

का उपयोग printfके साथ $COLUMNSकी तरह वास्तव में अच्छी तरह से काम किया, कुछ:

printf "%${COLUMNS}s\n" "hello"

इसने मेरे लिए इसे पूरी तरह से सही ठहराया।


6

निम्नलिखित टर्मिनल की आरएचएस पर RED में वर्तमान तिथि और समय डाल देगा।

# 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}"

लाभ:

  • RHS प्रॉम्प्ट में रंगों और ANSI CSI कोड के साथ सही तरीके से काम करता है
  • कोई उपप्रकार नहीं। shellcheckस्वच्छ।
  • अगर सही ढंग से काम करता .inputrcहै set show-mode-in-prompt on
  • सही तरीके से गैर-शीघ्र-लंबाई देने वाले वर्णों को इनकैप्सुलेट करता है \[और \]इसलिए कि शीघ्रता से दर्ज किए गए संपादन पाठ में संकेत को अजीब रूप से पुनर्मुद्रण करने का कारण नहीं बनता है।

नोट : आपको यह सुनिश्चित करने की आवश्यकता होगी कि $PS1इस कोड के बाहर होने से पहले किसी भी रंग अनुक्रम को ठीक से संलग्न किया गया हो \[और \]उनमें कोई घोंसला न हो।


जब मैं सिद्धांत में इस दृष्टिकोण को पसंद करता हूं, व्यवहार में यह बॉक्स से बाहर काम नहीं करता है (ubuntu 18.04, GNU bash 4.4.19): कोड को सीधे सीधे .bashrc में जोड़ना त्रुटि देता है bash: local: can only be used in a function, जिसे ठीक करने के लिए तुच्छ है, और। उसके बाद, यह कुछ भी नहीं दिखाता है क्योंकि COLUMNSपरिभाषित नहीं है: इसे प्रतिस्थापित किया जाना है $(tput cols)। एक ही परिणाम अगर स्निपेट को एक अलग फाइल पर सहेजा जाता है, और फिर इसमें खटास आ जाती है .bashrc
पोलेंटिनो

1
धन्यवाद @Polentino tput colsयदि $COLUMNSमैं परेशान है, तो मैंने उसे चलाने के लिए कोड अपडेट कर दिया है। और हाँ, यह कोड एक फंक्शन के अंदर होना चाहिए। मैं PROMPT_COMMAND='_prompt_bash_set'फ़ंक्शन का उपयोग और नाम देता हूं _prompt_bash_set
टॉम हेल

2

मैंने सिर्फ सोचा था कि मैं अपने को यहां फेंक दूंगा। यह लगभग जीआरएमएल ज़श प्रॉम्प्ट के समान ही है (ज़ीएस अपडेट को छोड़कर यह नई लाइनों और बैक स्पेस पर थोड़ा बेहतर है - जो कि बैश में दोहराने के लिए असंभव है ... इस समय में बहुत मुश्किल है, कम से कम)।

मैंने इस पर एक अच्छा तीन दिन बिताए (केवल लैपटॉप पर चलने वाले आर्च पर परीक्षण किया गया), इसलिए यहां एक स्क्रीनशॉट है और फिर सामान जो मेरे ~ / .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\]% "

मैं अभी भी रंग विन्यास बनाने पर काम कर रहा हूँ, लेकिन मैं रंग के साथ खुश हूँ के रूप में वे अब कर रहे हैं।


वर्तमान में पागल के लिए एक ठीक पर काम कर ^[चरित्र और आसान रंग स्विचिंग :)


यह Ctrl + [और वी एक साथ, यह Ctrl + V Ctrl + के बाद [नहीं है।
निएडजेककोब


0

गाइल्स के उत्तर पर जोड़ते हुए, मैंने रंगों को बेहतर ढंग से संभालने के लिए कुछ लिखा है (बशर्ते वे ठीक से संलग्न हों \[और \]यह मामला-दर-मामला है और हर मामले को नहीं संभालता, लेकिन यह मुझे 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 के बाद एक नई पंक्ति, जो कोई दृश्य फर्क नहीं पड़ता है, लेकिन अगर आप अपने आदेश के इतिहास में कुछ आदेश के माध्यम से वापस स्क्रॉल ठीक से प्रदर्शित होने से शीघ्र रखने के लिए लगता है जोड़ा।

मुझे यकीन है कि कोई और इस पर सुधार कर सकता है, और शायद कुछ विशेष-केस-इनेस को सामान्य कर सकता है।


0

यहाँ एक समाधान पर आधारित है 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\ [\] के साथ भाग जाता है ताकि इसे प्रदर्शित लंबाई में न गिना जाए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.