2011-10-08 7 views

risposta

0

Un modo potrebbe essere quello di utilizzare tput per contare i colonne del vostro terminale, e sottotraccia il numero di caratteri che stanno per essere stampati a destra ea sinistra, quindi utilizzare questo numero come il numero di spazi tra il testo sinistro e destro. Utilizzare printf per costruire la linea.

esempio veloce:

left="[${status}]\[email protected]\h:\w\$ " 
right="$(git symbolic-ref HEAD) $(date +%T)" 
spaces="$(($(tput cols) - ${#left} - ${#right}))" 
export PS1="$(printf "%s%${spaces}s\n" "$left" "$right")" 
+0

mmm completato, ho appena visto questo è il line_ _same. Non penso che^funzionerà. Sembra più che tu abbia bisogno di mettere le mani di più sulla roba di "[n] curses". – c00kiemon5ter

9

Prova il seguente:

PS1='$(printf "%*s\r%s" $((COLUMNS-1)) "[$(git branch 2>/dev/null | grep '^*' | sed s/..//)] $(date +%H:%M:%S)" "[email protected]:$PWD$ ")' 

Si noti che non avrete mai un comportamento che corrisponde esattamente un zsh solo con bash. Nel caso di cui sopra compaiono i seguenti differenze:

  1. parte destra del prompt non viene cancellato quando si esegue un comando (accept-line evento in termini di zsh).
  2. La parte destra del prompt verrà cancellata se si digita qualcosa e quindi si preme <C-u> o <BS>.
  3. La parte destra del prompt non verrà ripristinata se si digita qualcosa su di esso e quindi si elimina il testo.
  4. La parte destra del prompt non scomparirà se si digita qualcosa su di esso, anche se il testo in questa parte verrà sovrascritto.
1

Oggi ho costruito qualcosa del genere nel modo seguente. la prova completa non è stato ancora reso ...

preprompt() { 
    rc=$? 
    c=31 
    [ $rc -eq 0 ] && c=32 

    PS1="\[$(color $c)\]$rc\[$(color 0)\] \t \w \$ " 
    # right "prompt" 
    # We cannot use $COLUMNS here, since in new shells the first prompt 
    # will get garbled then. Seems like the correct value of COLUMNS is 
    # in the shell init. 
    printf "%`tput cols`s`tput cr`" "${USER}@${HOST}" 
} 

PROMPT_COMMAND=preprompt 
1

Il codice di seguito creerà un prompt che assomiglia a:

bash prompt with git status on right

E 'non banale di fare questo in bash a causa di:

  • Readline mode string takes up characters before the prompt is printed, il che significa che le soluzioni printf non funzioneranno in alcuni casi.A causa di questo:
  • Rimozione tutti (ad esempio i colori) per calcolare correttamente la lunghezza della stampa di destra-lato pronta
  • necessità di utilizzare __git_ps1 per affrontare git casi limite
  • __git_ps1 solo output di colore in alcuni circostanze, e solo all'interno $PS1
  • Permettere colore nel __git_ps1 uscita durante la rimozione dei \[ e \] personaggi sua uscita (che non possono essere nidificate)
  • Avvolgendo tutta pronta RHS in \[ e \] per far sì che la richiesta non fa cose strane quando la navigazione/editing/comandi

#!/bin/bash 
# _options=$(shopt -op); set -exu # Save and set shell options for testing 
################## 
# Set the prompt # Sourced from .bashrc 
################## 

# Select git info displayed, see /usr/lib/git-core/git-sh-prompt for more 
export GIT_PS1_SHOWCOLORHINTS=1   # Make pretty colours inside $PS1 
export GIT_PS1_SHOWDIRTYSTATE=1   # '*'=unstaged, '+'=staged 
export GIT_PS1_SHOWSTASHSTATE=1   # '$'=stashed 
export GIT_PS1_SHOWUNTRACKEDFILES=1  # '%'=untracked 
export GIT_PS1_SHOWUPSTREAM="verbose"  # 'u='=no difference, 'u+1'=ahead by 1 commit 
export GIT_PS1_STATESEPARATOR=''   # No space between branch and index status 
export GIT_PS1_DESCRIBE_STYLE="describe" # Detached HEAD style: 
# describe  relative to older annotated tag (v1.6.3.1-13-gdd42c2f) 
# contains  relative to newer annotated tag (v1.6.3.2~35) 
# branch  relative to newer tag or branch (master~4) 
# default  exactly eatching tag 


# Sets prompt like: 
# [email protected]:~/prj/sample_app[exit]$     master*% u= | 30 Apr 22:27 
_set_bash_prompt() { 
    # Set left hand side of the prompt 
    PS1="\[email protected]\h:\w\$ " 

    # 
    # Git status 
    # 

    # Save current state of user shopt settings promptvars and extglob 
    local user_shopt 
    user_shopt=$(shopt -p promptvars extglob) 
    # __git_ps1 usually returns literal text "${__git_ps1_branch_name}" rather 
    # than the contained branch name, eg "master". This prevents calculating 
    # the length of the printable characers in the RHS string (used to move the 
    # cursor that many columns left from the terminal's right edge.) However if 
    # "shopt promptvars" is unset, __git_ps1 it will include the dereferenced 
    # branch name instead. 
    shopt -qu promptvars 
    # extglob is required for the ${variable//@(pattern)/} replacements 
    shopt -qs extglob 

    # Allow disabling git status and no error if __git_ps1 undefined 
    if [[ ! -v _disable_git_prompt && $(type -t __git_ps1 2>/dev/null) == function ]]; then 
    # __git_ps1 will only make pretty colours inside $PS1 
    local old_PS1=$PS1 
    __git_ps1 "" "" "%s" # force colour; no default round bracket (decorations) 

    # Strip "\[" and "\[": non-printable character markers. __git_ps1 outputs 
    # them however the whole of the RHS prompt needs to be included in these 
    # markers, and they can't be nested. 
    git=${PS1//@(\\@(\[|\]))/} 
    PS1=$old_PS1 
    fi 

    # 
    # Right hand side of prompt 
    # 
    local rhs="" # String to be printed on the right hand side of terminal 

    # Create a string like: "25 Apr 13:15" 
    local date_time 
    printf -v date_time "%(%e %b %H:%M)T" -1 # -1 is current time 

    # Format the RHS prompt 
    [[ -n $git ]] && rhs="$git | " #" 
    rhs+="\e[0;1;31m${date_time}" 

    # Strip ANSI CSI commands (eg colours) to enble counting the length of 
    # printable characters, giving offset of cursor from terminal RHS edge (from 
    # https://www.commandlinefu.com/commands/view/12043/remove-color-special-escape-ansi-codes-from-text-with-sed) 
    # Neither bash not sed support lookbehind zero-length assertions, so it's not 
    # possible to ignore "\\e", (ie a literal '\' followed by a literal 'e'), yet 
    # still remove "\e" (ie ESC) 
    local rhs_printable=${rhs//@(\\@(\[|]|[Ee]\[*([0-9;])[a-zA-Z]))/} 
    # or, in using sed (but requires exec): 
    # local rhs_printable=$(sed -e 's,\\[][]\|\\[Ee]\[\([0-9;]\)*[A-Za-z],,g' <<< "$rhs") 

    # 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 minus 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 
    # command line editing/browsing/completion. Ensure that these are not nested. 
    PS1="\[\e[0m${Save}\e[$((COLUMNS - ${#rhs_printable}))G${rhs}${Rest}\]${PS1}" 

    eval "$user_shopt" 
} 

# eval "$_options"; unset _options # Restore previous shell options from line 2