commit 3b465c8a762a88b30a302cffc598a8ae860bc070 Author: Charles D Date: Mon Apr 17 14:43:13 2023 +0000 re-initialize repo without old history :( diff --git a/prompt.sh b/prompt.sh new file mode 100644 index 0000000..f23aedb --- /dev/null +++ b/prompt.sh @@ -0,0 +1,440 @@ +#!/bin/bash + +# Charles Danesi, 2022. +# parts taken from https://gist.github.com/loudambiance/a41b42a4295bce6e7304 + +# TODO git merge status +# TODO git isLocalOnly to check if there are remotes or if this is only a local repo) +# TODO number of pushes pending +# TODO display number of modified files (maybe number of untracked as well) +# TODO display current tag +# TODO display that files are staged +# TODO display a 'ready to commit' status +# TODO display file deleted +# TODO status to display detached HEAD +# TODO status icon to indicate stash + +#========================================================= +#Terminal Color Codes +#========================================================= +WHITE='\[\033[1;37m\]' +LIGHTGRAY='\[\033[0;37m\]' +GRAY='\[\033[1;49;90m\]' +BLACK='\[\033[0;30m\]' +RED='\[\033[0;31m\]' +LIGHTRED='\[\033[1;31m\]' +GREEN='\[\033[0;32m\]' +LIGHTGREEN='\[\033[1;32m\]' +ORANGE='\[\033[0;33m\]' +YELLOW='\[\033[1;33m\]' +BLUE="\[\033[0;34m\]" +LIGHTBLUE='\[\033[1;34m\]' +PURPLE='\[\033[0;35m\]' +PINK='\[\033[1;35m\]' +CYAN='\[\033[0;36m\]' +LIGHTCYAN='\[\033[1;36m\]' +DEFAULT='\[\033[0m\]' +CDNET1="\[\e[38;5;27m\]" +CDNET2="\[\e[38;5;32m\]" +DARKGRAY="\[\e[38;5;237m\]" +DARKGRAY2="\[\e[90m\]" + +#========================================================= +# User Configuration +#========================================================= +# TODO refactor colors and config options. +# Configuration +#todoDir = "$HOME/code/todo.txt/" # This MUST be set for todo.txt to work! + +# Colors +clrLines=$GRAY # Lines and Arrow +clrBrackets=$GRAY # Brackets around each data item +clrError=$RED # Error displays when previous command did not return 0 +clrClock=$DARKGRAY # The current time +clrScreenLabel=$CYAN # Color for terminal multiplexer label +cMPX1=$YELLOW # Color for terminal multiplexer threshold 1 +cMPX2=$RED # Color for terminal multiplexer threshold 2 +cBGJ=$PURPLE # Color for background job label +cBGJ1=$YELLOW # Color for background job threshold 1 +cBGJ2=$RED # Color for background job threshold 2 +cSTJ=$RED # Color for stopped job label +cSTJ1=$YELLOW # Color for background job threshold 1 +cSTJ2=$RED # Color for background job threshold 2 +clrTaskLabel=$PURPLE # Color for todo.txt tasks label +clrTasks=$YELLOW # Color for the number of todo.txt tasks +clrSSH=$PINK # Color for brackets if session is an SSH session +clrUsername=$CDNET2 # Color of user +clrHostname=$CDNET2 # Color of hostname +clrWarnAsRoot=$RED # Color of root warning +clrWorkingDirectory=$CDNET1 # Color of current directory +clrCommand=$DEFAULT # Color of the command you type +clrSeparator=$WHITE # Color for separator for screen/jobs +clrUserSeperator=$GRAY # Color of the user and hostname separator, probably '@' +clrDefaultLines=$clrLines # default color +clrDefaultBrackets=$clrBrackets # default color +clrGitBranch=$LIGHTGREEN +clrGitHash=$CDNET1 +clrCmdRunTime=$CYAN +GITBG1="\[\e[47m\]" +GITBG2="\[\e[100m\]" + +# Features +fBlankLine=1 # Have a newline between previous command output and new prompt +fGitRepo=1 # Show git status +fGitStatusBar=1 # Show the git status bar above the main prompt (3 lines) NOTE: currently unused +fGitAfterCWD=1 # Show git status on 2-line prompt NOTE: currently unused +fReturnErrors=1 # Previous command return status tracker +fWindowTitle=1 # show uptime/load in titlebar +fClock=1 +fShowHostname=1 +fScreenTracker=1 # Terminal multiplexer tracker enabled +fSSHSession=0 # Track if session is SSH +fBackgroundJobTracker=1 # Track background jobs +fStoppedJobsTracker=1 # Track stopped jobs +fShowUserHost=1 # Show user and host #### NOTE: CURRENTLY UNUSED #### +fWorkingDirectory=1 # Show current directory +fPathShortening=1 # Enable directory shortening (configurable) +fLastCmdRunTime=1 # Display last cmd wall time + +fShowTaskCount=1 # Show task count from todo.txt, if installed + +# Settings +# TODO: add thresholds for cmd wall time +# TODO: add settings for customizing todo.txt (project/context/priority display only) +shortDirectoryThreshold="2" # How many folders deep before we start trimming the path +mpxThresholdMid="0" # Terminal multiplexer threshold 1 value +mpxThresholdHigh="2" # Terminal multiplexer threshold 2 value +bgJobThresholdMid="0" # Background job threshold 1 value +bgJobThresholdHigh="2" # Background job threshold 2 value +stoppedJobThresholdMid="0" # Stopped job threshold 1 value +stoppedJobThresholdHigh="2" # Stopped job threshold 2 value + +# Symbols/Indicators +userHostSeparator="@" +symScreen="s" +gitBranch="" #  +gitUntrackedFiles="?" +gitFilesAdded="A" +gitFilesRemoved="D" +gitFilesModified="M" +gitStagedChanges="" +gitUnstagedChanges="Δ" +gitStashedChanges="*" #  +gitMerging="‼" #   +gitUncommittedChanges="✘" # staged, but not committed +gitClean="✓" +gitDirty="✘" +gitPushReady="" #  +gitBehindRemote="" +gitLocalOnly="" +gitLocalRemote="" +taskLabel="☑" + +# if user-specific config exists, override default values +if [ -f $HOME/.cdprc ]; then + . $HOME/.cdprc +fi + +function promptcmd() { + prevReturnCode=$? + timer_stop + + # check if we're in an SSH session + if [[ $SSH_CLIENT ]] || [[ $SSH2_CLIENT ]]; then + lSSH_FLAG=1 + else + lSSH_FLAG=0 + fi + + # insert newline to clear space from previous cmd + if [ $fBlankLine -eq 1 ]; then + PS1="\n" + else + PS1= + fi + + # previous command error + if [ $fReturnErrors -eq 1 ]; then + if [ $prevReturnCode -ne 0 ]; then + clrLines=$clrError + clrBrackets=$clrError + else + clrLines=$clrDefaultLines + clrBrackets=$clrDefaultBrackets + fi + fi + + # set window title + if [ $fWindowTitle -eq 1 ]; then + if [ "$STY" != "" ]; then + PS1="\[\e]0;(`echo $STY|cut -d . -f 2`)`uptime`\a\]${PS1}" + else + PS1="\[\e]0;`uptime -p`, `uptime | cut -d " " -f 12-`\a\]${PS1}" + fi + fi + + # beginning of first line (if in a git repo) +# if [ $fGitRepo -eq 1 ] && [ "$(is_git_repo)" == "true" ]; then +# PS1="${PS1} ${WHITE} ${clrGitBranch}$(git_branch)$(git_hash) $(git_untracked)\n" +# fi + + # first line if not in a git repo + PS1="${PS1}${debian_chroot:+($debian_chroot)}${clrLines}\342\224\214\342\224\200" + + # last cmd runtime + if [ $fLastCmdRunTime -eq 1 ]; then + PS1="${PS1}${clrBrackets}[${clrCmdRunTime}$timer_show${clrBrackets}]${clrLines}\342\224\200" + fi + + # current time + if [ $fClock -eq 1 ] ; then + PS1="${PS1}${clrBrackets}[${clrClock}\t${clrBrackets}]${clrLines}\342\224\200" + fi + + # detached screen sessions + if [ $fScreenTracker -eq 1 ] ; then + hTMUX=0 + hSCREEN=0 + mpxCounter=0 + hash tmux --help 2>/dev/null || hTMUX=1 + hash screen --version 2>/dev/null || hSCREEN=1 + if [ $hTMUX -eq 1 ] && [ $hSCREEN -eq 1 ]; then + mpxCounter=$(echo "$(screen -ls|grep -c -i detach) + $(tmux ls 2> /dev/null | grep -c -i -v attach)" | bc) + elif [ $hTMUX -eq 0 ] && [ $hSCREEN -eq 1 ] ; then + mpxCounter=$(tmux ls 2>/dev/null | grep -c -i -v attach) + elif [ $hTMUX -eq 1 ] && [ $hSCREEN -eq 0 ] ; then + mpxCounter=$(screen -ls | grep -c -i detach) + fi + if [[ $mpxCounter -gt $mpxThresholdHigh ]] ; then + PS1="${PS1}${clrBrackets}[${clrScreenLabel}${symScreen}${clrSeparator}:${cMPX2}${mpxCounter}${clrBrackets}]${clrLines}\342\224\200" + elif [[ $mpxCounter -gt $mpxThresholdMid ]] ; then + PS1="${PS1}${clrBrackets}[${clrScreenLabel}${symScreen}${clrSeparator}:${cMPX1}${mpxCounter}${clrBrackets}]${clrLines}\342\224\200" + fi + fi + + # background tasks + if [ $fBackgroundJobTracker -eq 1 ] ; then + BGJC=$(jobs -r|wc -l) + if [ $BGJC -gt $bgJobThresholdHigh ] ; then + PS1="${PS1}${clrBrackets}[${cBGJ2}&${clrSeparator}:${cBGJ2}${BGJC}${clrBrackets}]${clrLines}\342\224\200" + elif [ $BGJC -gt $bgJobThresholdMid ] ; then + PS1="${PS1}${clrBrackets}[${cBGJ1}&${clrSeparator}:${cBGJ2}${BGJC}${clrBrackets}]${clrLines}\342\224\200" + fi + fi + + # stopped jobs + if [ $fStoppedJobsTracker -eq 1 ] ; then + STJC=$(jobs -s | wc -l ) + if [ $STJC -gt $stoppedJobThresholdHigh ] ; then + PS1="${PS1}${clrBrackets}[${cSTJ2}\342\234\227${clrSeparator}:${cSTJ2}${STJC}${clrBrackets}]${clrLines}\342\224\200" + elif [ $STJC -gt $stoppedJobThresholdMid ] ; then + PS1="${PS1}${clrBrackets}[${cSTJ1}\342\234\227${clrSeparator}:${cSTJ1}${STJC}${clrBrackets}]${clrLines}\342\224\200" + fi + fi + + # todo.txt task count + if [ $fShowTaskCount -eq 1 ] ; then + PS1="${PS1}${clrTaskLabel}" + fi + + # user@host + # set bracket color if in ssh session + if [ $fSSHSession -eq 1 ] && [ $lSSH_FLAG -eq 1 ]; then + clrSes="$clrSSH" + else + clrSes="$clrBrackets" + fi + + # don't display user if root + if [ $EUID -eq 0 ]; then + PS1="${PS1}${clrSes}[${clrWarnAsRoot}!" + else + PS1="${PS1}${clrSes}[${clrUsername}\u" + fi + + # Host Section + if [ $fShowHostname -eq 1 ] || [ $lSSH_FLAG -eq 1 ] ; then # Host is optional only without SSH + PS1="${PS1}${clrUserSeperator}${userHostSeparator}${clrHostname}\h${clrSes}]${clrLines}\342\224\200" + else + PS1="${PS1}${clrSes}]${clrLines}\342\224\200" + fi + #PS1="${PS1}${userHostSeparator}${LIGHTGREEN}\h${clrSes}]${GRAY}\342\224\200" + + # current directory + if [ $fWorkingDirectory -eq 1 ]; then + PS1="${PS1}[${clrWorkingDirectory}\w" + if [ $fGitRepo -eq 1 ] && [ "$(is_git_repo)" == "true" ]; then + PS1="${PS1}${clrBrackets}]${clrLines}\342\224\200${clrBrackets}[${WHITE}${gitBranch} ${clrGitBranch}$(git_branch)$(git_hash) $(git_untracked)${clrBrackets}]" + else + PS1="${PS1}${clrBrackets}]" + fi + fi + + # prompt + PS1="${PS1}\n${clrLines}\342\224\224\342\224\200\342\224\200> ${clrCommand}" +} + +function timer_now { + date +%s%3N +} + +function timer_start { + timer=${timer:-$(timer_now)} +} + +function timer_stop { + local d_ms=$(($(timer_now) - $timer)) + local d_s=$((d_ms / 1000)) + local ms=$((d_ms % 1000)) + local s=$((d_s % 60)) + local m=$(((d_s / 60) % 60)) + local h=$((d_s / 3600)) + if ((h > 0)); then timer_show=${h}h${m}m + elif ((m > 0)); then timer_show=${m}m${s}s + elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s + elif ((s > 0)); then timer_show=${s}.$((ms / 10))s + else timer_show=${ms}ms + fi + unset timer +} + +function is_git_repo { + # TODO: can do this without saving as a variable + local isREPO="$(git rev-parse --is-inside-work-tree 2>/dev/null)" + #if [ ! $(git remote 2>/dev/null) ]; then echo "no remote"; else echo "remote available";fi + echo -e $isREPO +} + +function git_hash { + local current_hash="$(git log --oneline --max-count=1 2>/dev/null|cut -b -7)" + if [ "$current_hash" != "" ]; then + # TODO: change these to configurable variable + echo -e "${YELLOW}@${clrGitHash}$current_hash" + fi +} + +# might be able to include untracked/unmerged/unstaged in one function +function git_untracked { + local git_icons="" + local git_status="$(git status 2>/dev/null)" + local git_shortStatus="$(git status --porcelain|cut -b 1-2 2>/dev/null)" +# local git_stash="$(git stash list 2>/dev/null)" + # M modified + # A added + # D deleted + # R renamed + # C copied + # byte 1 is staged, byte 2 unstaged + # ↑1 ↓10 + + # has stash present + # NOTE: IDK why this only works with the first '!' + if ! git stash list &>/dev/null != ""; then + git_icons="${git_icons}${LIGHTBLUE}${gitStashedChanges}" + fi + + # untracked files + # if git status --porcelain|cut -b 1-2|grep "??" &>/dev/null ; then + # NOTE: this is probably the better way to chain these... + if [[ $git_shortStatus =~ "??" ]]; then + git_icons="${git_icons}${RED}${gitUntrackedFiles}" + fi + # added files + if [[ $git_shortStatus =~ "A" ]]; then + git_icons="${git_icons}${DEFAULT}${gitFilesAdded}" + fi + # deleted files + if [[ $git_shortStatus =~ "D" ]]; then + git_icons="${git_icons}${DEFAULT}${gitFilesRemoved}" + fi + + # modified/renamed/copied files + for i in $git_shortStatus; do + case $i in + R) + ;& + C) + ;& + M) + #echo -n "${RED}${gitFilesModified}" + git_icons="${git_icons}${DEFAULT}${gitFilesModified}" + break; + ;; + esac + done + + # unmerged ( ‼ ) + + # FIXME: should not include this all in the same function + + # unstaged changes + if git status --porcelain|cut -b 2|grep 'M\|A\|D\|R\|C' &>/dev/null; then + git_icons="${git_icons}${LIGHTBLUE}${gitUnstagedChanges}" + fi + + if [ "$git_icons" != "" ]; then + git_icons="${git_icons} " + fi +# if git status --porcelain|cut -b 1|grep 'M\|A\|D\|R\|C' &>/dev/null; then +# git_icons="${git_icons} ${YELLOW}✘" +# if [[ !$git_status =~ "working tree clean" ]] ; then +# git_icons="${git_icons}${RED}✘" + if [[ $git_status =~ "Changes to be committed" ]]; then + git_icons="${git_icons}${GREEN}✘" # NOTE: staged but not committed + elif [[ $git_status =~ "Changes not staged" ]]; then + git_icons="${git_icons}${LIGHTBLUE}✘" + elif [[ $git_status =~ "branch is ahead" ]]; then + git_icons="${git_icons}${YELLOW}✘" #NOTE: ahead of origin + elif [[ $git_status =~ "nothing to commit" ]]; then + git_icons="${git_icons}${LIGHTGREEN}${gitClean}" #NOTE: working + else + git_icons="${git_icons}${RED}${gitDirty}" # NOTE: working + fi + +# if [ "$git_icons" != "" ]; then +# echo -e " ${git_icons}" +# fi + echo -e $git_icons +} + +function git_branch { + local git_status="$(git status 2>/dev/null)" + local on_branch="On branch ([^${IFS}]*)" + local on_commit="HEAD detached at ([^${IFS}]*)" + + if [[ $git_status =~ $on_branch ]]; then + local branch=${BASH_REMATCH[1]} + echo "$branch" + elif [[ $git_status =~ $on_commit ]]; then + local commit=${BASH_REMATCH[1]} + echo "($commit)" + fi +} + +function load_prompt() { + # Get PIDs + local parent_process=$(tr -d '\0' < /proc/$PPID/cmdline | cut -d \. -f 1) + local my_process=$(tr -d '\0' < /proc/$$/cmdline | cut -d \. -f 1) + + if [[ $parent_process == script* ]]; then + PROMPT_COMMAND="" + PS1="\t - \# - \u@\H { \w }\$ " + elif [[ $parent_process == emacs* || $parent_process == xemacs* ]]; then + PROMPT_COMMAND="" + PS1="\u@\h { \w }\$ " + else + export DAY=$(date +%A) + PROMPT_COMMAND="promptcmd" + fi + + if [ $fPathShortening -eq 1 ]; then + export PROMPT_DIRTRIM=$shortDirectoryThreshold + else + export PROMPT_DIRTRIM= + fi + + trap 'timer_start' DEBUG + export PS1 PROMPT_COMMAND +} + +load_prompt diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..0684f37 --- /dev/null +++ b/readme.md @@ -0,0 +1,21 @@ +Charles' Bash Prompt (needs renamed) + +Parts taken from: (credits) + +Features: +1. etc +2. todo.txt task count display + +How to install: + +1. `git clone (repo)` +2. edit bashrc + +How to install systemwide: + +1. clone repo +2. edit /etc/bash.bashrc + +~/.cdprc + +defaults