aboutsummaryrefslogblamecommitdiff
path: root/pdksh/pdkshrc.d/prompt.pdksh
blob: f9dfa584762d70067d6766d82ccb150d43dc4c92 (plain) (tree)
1
2
3
4
5
6
7
8
9


                                                              




                                                           
                                                                 







                                                                    

                                                                               
                          
                                   
                                   



                                      
                                    
                             




                                      
                         




                                                                        
                          




                                                                  
                                               









                                                              
                                              


















                                                                               
                                

              

















                                                               



                                                                 
                         









                                                                        
                                     


                                  
                                                   


                                                          

                                                                   

                                       
                                                                   
                                
 

                                                                           
                                                                                 

              

                                              





                     









                                                                              

                                                                          
                           
                                         






                                     
                                                          







                                
# All of this is only known to work on OpenBSD's fork of pdksh
[[ $(uname -s) == OpenBSD ]] || return

# Frontend to controlling prompt
prompt() {

    # If no arguments, print the prompt strings as they are
    if ! (($#)) ; then
        printf '%s\n' PS1="$PS1" PS2="$PS2" PS3="$PS3" PS4="$PS4"
        return
    fi

    # What's done next depends on the first argument to the function
    case $1 in

        # Turn complex, colored PS1 and debugging PS4 prompts on
        on)
            # Set up prompt, including optional PROMPT_PREFIX and PROMPT_SUFFIX
            # variables
            PS1='\u@\h:\w'
            PS1=$PS1'$(prompt vcs)'
            PS1=$PS1'$(prompt job)'
            PS1='${PROMPT_PREFIX}'$PS1
            PS1=$PS1'${PROMPT_SUFFIX}'
            PS1=$PS1'\$'

            # Count available colors
            typeset -i colors
            colors=$( {
                tput Co || tput colors
            } 2>/dev/null )

            # Prepare reset code
            typeset reset
            reset=$( {
                tput me || tput sgr0
            } 2>/dev/null )

            # Decide prompt color formatting based on color availability
            typeset format
            case $colors in

                # Check if we have non-bold bright green available
                256)
                    format=$( {
                        : "${PROMPT_COLOR:=12}"
                        tput AF "$PROMPT_COLOR" ||
                        tput setaf "$PROMPT_COLOR" ||
                        tput AF "$PROMPT_COLOR" 0 0  ||
                        tput setaf "$PROMPT_COLOR" 0 0
                    } 2>/dev/null )
                    ;;

                # If we have only eight colors, use bold green
                8)
                    format=$( {
                        : "${PROMPT_COLOR:=4}"
                        tput AF "$PROMPT_COLOR" ||
                        tput setaf "$PROMPT_COLOR"
                        tput md || tput bold
                    } 2>/dev/null )
                    ;;

                # For all other terminals, we assume non-color (!), and we just
                # use bold
                *)
                    format=$( {
                        tput md || tput bold
                    } 2>/dev/null )
                    ;;
            esac

            # String it all together
            PS1='\['"$format"'\]'"$PS1"'\['"$reset"'\] '
            PS2='> '
            PS3='? '
            PS4='+<$?> $LINENO:'
            ;;

        # Git prompt function
        git)
            # Bail if we have no git(1)
            if ! hash git 2>/dev/null ; then
                return 1
            fi

            # Attempt to determine git branch, bail if we can't
            typeset branch
            branch=$( {
                git symbolic-ref --quiet HEAD ||
                git rev-parse --short HEAD
            } 2>/dev/null )
            if [[ ! -n $branch ]] ; then
                return 1
            fi
            branch=${branch##*/}

            # Refresh index so e.g. git-diff-files(1) is accurate
            git update-index --refresh >/dev/null

            # Collect symbols representing repository state
            typeset state

            # Upstream HEAD has commits after local HEAD; we're "behind"
            (($(git rev-list --count 'HEAD..@{u}' 2>/dev/null) > 0)) &&
                state=${state}\<

            # Local HEAD has commits after upstream HEAD; we're "ahead"
            (($(git rev-list --count '@{u}..HEAD' 2>/dev/null) > 0)) &&
                state=${state}\>

            # Tracked files are modified
            git diff-files --quiet ||
                state=${state}'!!'

            # Changes are staged
            git diff-index --cached --quiet HEAD ||
                state=${state}\+

            # There are some untracked and unignored files
            [[ -n $(git ls-files --others --exclude-standard) ]] &&
                state=${state}\?

            # There are stashed changes
            git rev-parse --quiet --verify refs/stash >/dev/null &&
                state=${state}\^

            # Print the status in brackets; add a git: prefix only if there
            # might be another VCS prompt (because PROMPT_VCS is set)
            printf '(%s%s%s)' "${PROMPT_VCS:+git:}" "${branch:-unknown}" "$state"
            ;;

        # Revert to simple inexpensive prompts
        off)
            PS1='\$ '
            PS2='> '
            PS3='? '
            PS4='+ '
            ;;

        # VCS wrapper prompt function; print the first relevant prompt, if any
        vcs)
            typeset vcs
            for vcs in "${PROMPT_VCS[@]:-git}" ; do
                if prompt "$vcs" ; then
                    return
                fi
            done
            ;;

        # Show the count of background jobs in curly brackets, if not zero
        job)
            typeset -i jobc
            jobc=$(jobs -p | sed -n '$=')
            if ((jobc > 0)) ; then
                printf '{%u}' "$jobc"
            fi
            ;;

        # Print error
        *)
            printf 'prompt: Unknown command %s\n' "$1" >&2
            return 2
            ;;

    esac
}

# Start with full-fledged prompt
prompt on