3 # redirect output to log file
8 # By default this file is sourced for ALL ssh commands. This is wonky.
9 # Normally, this file is not sourced when a script is run, but we can override
10 # that by having #!/bin/bash -l.
11 # I want something similar for ssh commands. when a local script runs an ssh command,
12 # this file should not be sourced by default, but we should be able to override that.
14 # so here we test for conditions of a script under ssh and return if so. To test
15 # for an overriding condition, we have a few options. one is to use an
16 # environment variable. env variables sent across ssh are strictly limited. ssh
17 # -t which sets $SSH_TTY, but within a script that won't work because tty
18 # allocation will fail. We could override an obscure unused LC_var, like
19 # telephone, but I don't want to run into some edge case where that messes
20 # things up. we could transfer a file which we could test for, but I can't think
21 # of a way to make that inherently limited to a single ssh command. I choose to
22 # set SendEnv and AcceptEnv ssh config vars to allow the environment variable
23 # BASH_LOGIN_SHELL to propagate across ssh.
25 # assume we want ssh commands to source this file if we are sourcing it,
26 # and we haven't specified otherwise already
27 [[ ! $BASH_LOGIN_SHELL ]] && export BASH_LOGIN_SHELL=true
29 # first conditions show that we are an ssh command without an interactive shell
30 if [[ $SSH_CONNECTION ]] \
34 && [[ ! $BASH_LOGIN_SHELL == true ]]; then
48 # remove all aliases. aliases provided by the system tend to get in the way,
49 # for example, error happens if I try to define a function the same name as an alias
52 # remove gnome keyring warning messages
53 # there is probably a more proper way, but I didn't find any easily on google
54 # now using xfce+xmonad instead of vanilla xmonad, so disabling this
55 #unset GNOME_KEYRING_CONTROL
57 # use extra globing features.
59 # include .files when globbing, but ignore files name . and ..
60 # setting this also sets dotglob
61 export GLOBIGNORE=*/.:*/..
63 # broken with bash_completion package. Saw a bug for this once. Don't anymore.
64 # still broken in wheezy
65 # still buggered in latest stable from the web, version 2.1
66 # perhaps its fixed in newer git version, which fails to make for me
67 # this note is from 6-2014
70 # make tab on an empty line do nothing
71 shopt -s no_empty_cmd_completion
74 # http://bash-completion.alioth.debian.org/
75 # might be sourced by the system already, but I've noticed it not being sourced before
76 if ! type _init_completion &> /dev/null && [[ -r "/usr/share/bash-completion/bash_completion" ]]; then
77 . /usr/share/bash-completion/bash_completion
81 # fix spelling errors for cd, only in interactive shell
83 # append history instead of overwritting it
85 # for compatibility, per gentoo/debian bashrc
87 # attempt to save multiline single commands as single history entries.
93 if [[ $INSIDE_EMACS ]]; then
94 # EMACS is used by bash on startup, but we don't need it anymore.
95 # plus I hit a bug in a makefile which inherited it
100 # scp completion does not work, but this doesn't fix it. todo, figure this out
101 complete -r scp &> /dev/null
102 # todo, remote file completion fails, figure out how to turn it off
106 if [[ $- == *i* ]]; then
107 # for readline-complete.el
108 if [[ $INSIDE_EMACS ]]; then
109 # all for readline-complete.el
111 bind 'set horizontal-scroll-mode on'
112 bind 'set print-completions-horizontally on'
113 bind '"\C-i": self-insert'
115 # arrow keys. for other terminals, see http://unix.stackexchange.com/questions/10806/how-to-change-previous-next-word-shortcut-in-bash
116 if [[ $TERM == "xterm" ]]; then
117 bind '"\e[1;5C": shell-forward-word' 2>/dev/null
118 bind '"\e[1;5D": shell-backward-word' 2>/dev/null
120 bind '"\eOc": shell-forward-word'
121 bind '"\eOd": shell-backward-word'
123 # terminal keys: C-c, C-z. the rest defined by stty -a are, at least in
124 # gnome-terminal, overridden by bash, or disabled by the system
125 stty werase undef lnext undef stop undef start undef
132 # history number. History expansion is good.
134 # history file size limit, set to unlimited.
135 # this needs to be different from the default because
136 # default HISTFILESIZE is 500 and could clobber our history
138 # max commands 1 session can append/read from history
140 # my own history size limit based on lines
141 HISTFILELINES=1000000
143 # the time format display when doing the history command
144 # also, setting this makes the history file record time
145 # of each command as seconds from the epoch
146 HISTTIMEFORMAT="%I:%M %p %m/%d "
147 # consecutive duplicate lines don't go in history
148 HISTCONTROL=ignoredups
149 # works in addition to HISTCONTROL to do more flexible things
150 # it could also do the same things as HISTCONTROL and thus replace it,
154 export BC_LINE_LENGTH=0
157 # note, if I use a machine I don't want files readable by all users, set
158 # umask 077 # If fewer than 4 digits are entered, leading zeros are assumed
169 for _x in $HOME/bin/bash-programs-by-ian/repos/*/*-function ~/opt/distro-functions/src/*; do
173 source $HOME/bin/semi-private # so I can share my bashrc
174 source $HOME/path_add-function
175 path_add --ifexists /a/opt/adt-bundle*/tools /a/opt/adt-bundle*/platform-tools
176 path_add $HOME/bin/bash-programs-by-ian/utils
183 # disabled for now, but these are generally good
184 # if [[ $- == *i* ]]; then
189 # remove any default aliases for these
190 alias ls > /dev/null 2>&1 && unalias ls
191 alias ll > /dev/null 2>&1 && unalias ll
192 alias grep > /dev/null 2>&1 && unalias grep
196 command mkdir -p "$@"
201 complete -A stopped -P '"%' -S '"' d
206 # note: gksudo is recommended for X apps because it does not set the
207 # home directory to the same.
209 if [[ $- == *i* ]]; then
210 # extra space at the end allows aliases to work
211 alias s='SUDOD="$PWD" sudo -i '
214 if [[ $EUID != 0 || $1 == -* ]]; then
215 SUDOD="$PWD" sudo -i "$@"
224 if [[ $OS == Windows_NT ]]; then
225 alias ffs='cygstart "/c/Program Files (x86)/Mozilla Firefox/firefox.exe" -P scratch'
227 alias j='command cygpath'
228 alias t='command cygstart'
229 alias cygstart='echo be quick, use the alias "t" instead :\)'
230 alias cygpath='echo be quick, use the alias "j" instead :\)'
238 #####################
240 #####################
242 # netselect-apt finds a fast mirror.
243 # but we need to replace the mirrors ourselves,
244 # because it doesn't do that. best it can do is
245 # output a basic sources file
246 # here we get the server it found, get the main server we use
247 # then substitute all instances of one for the other in the sources file
248 # and backup original to /etc/apt/sources.list-original.
250 debian_pick_mirror () {
251 local x=$(mktemp -d)/f # safe way to get file name without creating one
252 sudo netselect-apt -o "$x" || return 1
253 x=$(_debian_pick_mirror_grep stable "$x")
254 sudo cp -f /etc/apt/sources.list /etc/apt/sources.list-original
255 sudo sed -i "s/$(_debian_pick_mirror_grep wheezy)/$x/" /etc/apt/sources.list
259 _debian_pick_mirror_grep () {
260 local x="$(grep -oP "^deb [^ ]+ $1 " ${2-/etc/apt/sources.list})"
263 # replace / with \/ so we can use it with sed
267 # portable daemon, for debian & fedora
270 sudo /etc/init.d/$1 $2
272 sudo systemctl $2 $1.service
286 if type ack-grep >/dev/null 2>&1; then
292 grep -i --binary-files=without-match --color=auto "$@"
296 grep -ri --binary-files=without-match --color=auto "$@"
300 rsync -rhc /a/h/_site/ li:/var/www/iankelling.org/public_html
304 local startdir="$PWD"
307 ssh $x mkdir -p bin opt/distro-functions
308 tar cz bin/bash-programs-by-ian bin/semi-private opt/distro-functions/src | ssh $x tar xz
311 command cp /a/c/repos/bash/!(.git) ~/.gitconfig .
313 tar cz * | ssh $x tar xz
319 k() { grep -P "$@" ${HISTFILE:-~/.bash_history} | tail -n 40; }
321 calc() { echo "scale=3; $*" | bc -l; }
324 # setup for format of postfix
330 local unified="$(mktemp)"
334 _cdiff-prep "$1" "$f1"
335 _cdiff-prep "$2" "$f2"
336 cat "$f1" "$f2" | grep -Po '^[^=]+=' | sort | uniq > "$unified"
337 while IFS= read -r line; do
338 # the default bright red / blue doesn't work in emacs shell
339 dwdiff -cblue,red -A best -d " ," <(grep "^$line" "$f1" || echo ) <(grep "^$line" "$f2" || echo ) | colordiff
344 # join options which are continued to multiples lines onto one line
347 grep -vE '^([ \t]*#|^[ \t]*$)' "$1" | while IFS= read -r line; do
348 # remove leading spaces/tabs. assumes extglob
349 if [[ $line == "[ ]*" ]]; then
355 elif [[ $line == *=* ]]; then
356 echo "$pastline" >> "$2"
359 pastline="$pastline $line"
362 echo "$pastline" >> "$2"
365 # makes it so chown -R symlink affects the symlink and its target.
367 if [[ $1 == -R ]]; then
369 command chown -h "$@"
371 command chown -RH "$@"
381 if [[ $# == 0 ]]; then
382 cp /a/bin/data/COPYING .
384 cp /a/bin/data/COPYING "$@"
390 diff --strip-trailing-cr -w "$@" # diff content
395 date "+%A, %B %d, %r" "$@"
402 envload() { # load environment from a previous: export > file
403 local file=${1:-$HOME/.${USER}_env}
404 eval "$(export | sed 's/^declare -x/export -n/')"
405 while IFS= read -r line; do
406 # declare -x makes variables local to a function
407 eval ${line/#declare -x/export}
413 # havn't tested these:
414 #file cut copy and paste, like the text buffers :)
415 _fbufferinit() { # internal use by
416 ! [[ $my_f_tempdir ]] && my_f_tempdir=$(mktemp -d)
417 rm -rf "$my_f_tempdir"/*
421 cp "$@" "$my_f_tempdir"/
425 mv "$@" "$my_f_tempdir"/
427 fpst() { # file paste
428 [[ $2 ]] && { echo too many arguments; return 1; }
430 cp "$my_f_tempdir"/* "$target"
434 # find array. make an array of file names found by find into $x
435 # argument: find arguments
436 # return: find results in an array $x
438 while read -rd ''; do
440 done < <(find "$@" -print0);
444 git_empty_branch() { # start an empty git branch. carefull, it deletes untracked files.
445 [[ $# == 1 ]] || { echo 'need a branch name!'; return 1;}
447 gitroot || return 1 # function to set gitroot
448 builtin cd "$gitroot"
449 git symbolic-ref HEAD refs/heads/$1
456 if type -P firefox &>/dev/null; then
464 firefox -P default "$@" >/dev/null 2>&1
468 firefox -P alt "$@" >/dev/null 2>&1
475 # horizontal row. used to break up output
476 hr() { printf "$(tput setaf 5)â–ˆ$(tput sgr0)%.0s" $(seq $COLUMNS); }
482 # modified from ~/local/bin/git-completion.bash
483 # other completion commands are mostly taken from bash_completion package
484 complete -o bashdefault -o default -o nospace -F _git i 2>/dev/null \
485 || complete -o default -o nospace -F _git i
494 find . -iname '*'"$*"'*'
501 if [[ $PWD == /[iap] ]]; then
502 command ls -A --color=auto -I lost+found "$@"
504 command ls -A --color=auto "$@"
510 lld() { ll -d "$@"; }
513 low() { # make filenames all lowercase
516 y=$(tr "[A-Z]" "[a-z]" <<<"$x")
517 [[ $y != $x ]] && mv "$x" "$y"
522 lower() { # make first letter of filenames lowercase.
525 if [[ ${x::1} == [A-Z] ]]; then
526 y=$(tr "[A-Z]" "[a-z]" <<<"${x::1}")"${x:1}"
527 safe_rename "$x" "$y"
533 if [[ $# != 2 ]]; then
534 echo safe_rename error: $# args, need 2 >2
536 elif [[ $1 != $2 ]]; then
538 echo Cannot rename "$1" to "$2" as it already exists.
549 safe_rename "$x" "$y"
557 # test existence / exists
561 [[ -e "$x" || -L "$x" ]] || ret=1
566 # show make targets, via http://stackoverflow.com/questions/3063507/list-goals-targets-in-gnu-make
568 make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
572 # fix root file ownership for FILE argument.
573 # check if parent or grandparent is not root and if the dir of FILE is also
574 # owned by that user, and change ownership to that user
577 if [[ $EUID == 0 ]]; then
578 te "$1" || touch "$1"
579 if [[ $(stat -c "%u" "$1") == 0 ]] ; then
580 argdir=$(getdir "$1")
581 if [[ $(stat -c "%u" "$argdir") != 0 ]] ; then
582 if ! chown "--reference=$argdir" "$1"; then
583 echo failed to fix bad ownership file permissons
591 # see notes for usage
594 local dname="${PWD##*/}"
595 local m="/a/tmp/$dname-missing"
596 local d="/a/tmp/$dname-diff"
597 [[ -e $d ]] && rm "$d"
598 [[ -e $m ]] && rm "$m"
601 while read -r line; do
603 if [[ -e "$fsfile" ]]; then
604 md5diff "$line" "$fsfile" && tee -a "/a/tmp/$dname-diff" <<< "$fsfile $line"
610 done < <(find -type f )
613 (( msize <= 100 )) && cat $m
625 echo different > $x/c/d
629 # expected output, with different tmp dirs
630 # /tmp/tmp.HDPbwMqdC9/c/d ./c/d
631 # /a/tmp/tmp.qLDkYxBYPM-missing
635 # test whether missing files were renamed, generally for use with fsdiff
636 # $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir
637 # echos non-renamed files
642 { sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null
644 while read -r line; do
645 { missing_sum=$(md5sum < "$line") ; } 2>/dev/null
647 for x in "${sums[@]}"; do
648 if [[ $missing_sum == "$x" ]]; then
653 $renamed || echo "$line"
659 # get a random string
660 #par2rbase=$(head -c 50 /dev/urandom | tr -cd '[:alpha:]')
662 [[ $par2rbase ]] || { echo "set \$par2rbase first"; return 1; }
667 par2 c QDLDeDJ6z4.par2 *
675 [[ $(md5sum < "$1") != $(md5sum < "$2") ]]
679 pfind() { #find *$1* in $PATH
680 [[ $# != 1 ]] && { echo requires 1 argument; return 1; }
682 IFS=: pathArray=($PATH); unset IFS
683 find "${pathArray[@]}" -iname "*$1*"
686 # do pwd + some other info.
687 #pwd() { echo "$(ll -d "$PWD") $USER@$HOSTNAME $(date +%r)"; }
690 pwgen() { # generate a random password, with digits & punctuation and without
692 head -c 200 /dev/urandom | tr -cd '[:graph:]' | head -c "$arg"
694 head -c 200 /dev/urandom | tr -cd '[:alnum:]' | head -c "$arg"
695 head -c 5 /dev/urandom | tr -cd '[:alpha:]' | head -c "$arg"
699 q() { # start / launch a program in the backround and redir output to null
706 exit "$@" 2>/dev/null
709 # trash-restore lists everything that has been trashed at or below CWD
710 # This picks out files just in CWD, not subdirectories,
711 # which also match grep $1, usually use $1 for a time string
712 # which you get from running restore-trash once first
716 # last condition is to not ask again for ones we skipped
717 while name="$( echo | restore-trash | gr "$PWD/[^/]\+$" | gr "$1" )" \
718 && [[ $name ]] && (( $(wc -l <<<"$name") >= nth )); do
719 name="$(echo "$name" | head -n $nth | tail -n 1 )"
720 read -p "$name [Y/n] " ask
721 if [[ ! $ask || $ask == [Yy] ]]; then
722 x=$( echo "$name" | gr -o "^\s*[0-9]*" )
723 echo $x | restore-trash > /dev/null
724 elif [[ $ask == [Nn] ]]; then
732 # rsync, root is required to keep permissions right.
733 # rsync --archive --human-readable --verbose --itemize-changes --checksum \(-ahvic\) \
734 # --no-times --delete
735 # basically, make an exact copy, use checksums instead of file times to be more accurate
736 rl() { rsync -ahvic --delete "$@"; }
737 # don't delete files on the target end which do not exist on the original end:
738 rld() { rsync -ahvic "$@"; }
739 complete -F _rsync -o nospace rld rlt fl
740 # rl without preserving modification time. for some reason I had this as default before.
741 # perhaps that reason will come up again and I will document it.
742 rlt() { rsync -ahvic --delete --no-t "$@"; }
746 # use sb instead of s is for sudo redirections, eg. sb 'echo "ok fine" > /etc/file'
751 complete -F _root_command s sb
753 # use -ll, less secure but faster.
758 # sudo redo. be aware, this command may not work right on strange distros or earlier software
760 if [[ $# == 0 ]]; then
761 sudo -E bash -c -l "$(history -p '!!')"
763 echo this command redos last history item. no argument is accepted
769 # log with script. timing is $1.t and script is $1.s
770 # -l to save to ~/typescripts/
771 # -t to add a timestamp to the filenames
773 local logdir do_stamp arg_base
774 (( $# >= 1 )) || { echo "arguments wrong"; return 1; }
777 while getopts "lt" option
780 l ) arg_base=$logdir ;;
784 shift $(($OPTIND - 1))
786 [[ -e $logdir ]] || mkdir -p $logdir
787 $do_stamp && arg_base+=$(date +%F.%T%z)
788 script -t $arg_base.s 2> $arg_base.t
790 splay() { # script replay
791 #logRoot="$HOME/typescripts/"
792 #scriptreplay "$logRoot$1.t" "$logRoot$1.s"
793 scriptreplay "$1.t" "$1.s"
800 (sleep $(calc "$@ * 60") && mpv --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
804 ts() { # start editing a new file
805 [[ $# != 1 ]] && echo "I need a filename." && return 1
807 if [[ $- != *i* ]]; then
810 if [[ $1 == *.c ]]; then
811 e '#include <stdio.h>' >"$1"
812 e '#include <stdlib.h>' >>"$1"
813 e 'int main(int argc, char * argv[]) {' >>"$1"
814 e ' printf( "hello world\n");' >>"$1"
815 e ' return 0;' >>"$1"
817 e "${1%.c}: $1" > Makefile
818 e " g++ -ggdb -std=gnu99 -o ${1%.c} $<" >> Makefile
819 e "#!/bin/bash" >run.sh
820 e "./${1%.c}" >>run.sh
822 elif [[ $1 == *.java ]]; then
823 e "public class ${1%.*} {" >"$1"
824 e ' public static void main(String[] args) {' >>"$1"
825 e ' System.out.println("Hello, world!");' >>"$1"
830 echo "#!/bin/bash" > "$1"
833 [[ $quiet ]] || g "$1"
837 tx() { # toggle set -x, and the prompt so it doesn't spam
838 if [[ $- == *x* ]]; then
840 PROMPT_COMMAND=prompt_command
851 if [[ $OS == Windows_NT ]]; then
862 (( ${#x[#]} > 1 )) && { echo "warning ${#x[#]} matches found"; sleep 1; }
867 if type gvfs-open &> /dev/null ; then
872 # another alternative is run-mailcap
880 complete -F _longopt la lower low rlt rld rl lld ts ll dircp ex fcp fct fpst gr
884 hl() { # history limit. Write extra history to archive file.
885 local max_lines linecount tempfile prune_lines
886 local harchive="${HISTFILE}_archive"
887 for x in "$HISTFILE" "$harchive"; do
888 [[ -e $x ]] || { touch "$x" && echo "notice from hl(): creating $x"; }
889 if [[ ! $x || ! -e $x || ! -w $x || $(stat -c "%u" "$x") != $EUID ]]; then
890 echo "error in hl: history file \$x:$x no good"
894 history -a # save history
895 max_lines=$HISTFILELINES
896 [[ $max_lines =~ ^[0-9]+$ ]] || { echo "error in hl: failed to get max line count"; return 1; }
897 linecount=$(wc -l < $HISTFILE) # pipe so it doesn't output a filename
898 [[ $linecount =~ ^[0-9]+$ ]] || { echo "error in hl: wc failed"; return 1; }
899 if (($linecount > $max_lines)); then
900 prune_lines=$(($linecount - $max_lines))
901 head -n $prune_lines "$HISTFILE" >> "$harchive" \
902 && sed -ie "1,${prune_lines}d" $HISTFILE
906 if [[ $- == *i* ]]; then
907 # commands to run when bash exits normally
912 # temporary variables to test colorization
913 # some copied from gentoo /etc/bash/bashrc,
915 # dircolors --print-database uses its own built-in database
916 # instead of using /etc/DIR_COLORS. Try to use the external file
917 # first to take advantage of user additions.
918 safe_term=${TERM//[^[:alnum:]]/?} # sanitize TERM
920 [[ -f ~/.dir_colors ]] && match_lhs="${match_lhs}$(<~/.dir_colors)"
921 [[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(</etc/DIR_COLORS)"
922 [[ -z ${match_lhs} ]] \
923 && type -P dircolors >/dev/null \
924 && match_lhs=$(dircolors --print-database)
925 # test if our $TERM is in the TERM values in dircolor
926 [[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true
929 if ${use_color} && [[ $- == *i* ]]; then
931 if [[ $XTERM_VERSION == Cygwin* ]]; then
935 underl) echo -n $'\E[4m' ;;
936 bold) echo -n $'\E[1m' ;;
937 red) echo -n $'\E[31m' ;;
938 green) echo -n $'\E[32m' ;;
939 blue) echo -n $'\E[34m' ;;
940 cyan) echo -n $'\E[36m' ;;
941 yellow) echo -n $'\E[33m' ;;
942 purple) echo -n $'\E[35m' ;;
943 nocolor) echo -n $'\E(B\E[m' ;;
952 underl) echo -n $(tput smul) ;;
953 bold) echo -n $(tput bold) ;;
954 red) echo -n $(tput setaf 1) ;;
955 green) echo -n $(tput setaf 2) ;;
956 blue) echo -n $(tput setaf 4) ;;
957 cyan) echo -n $(tput setaf 6) ;;
958 yellow) echo -n $(tput setaf 3) ;;
959 purple) echo -n $(tput setaf 5) ;;
960 nocolor) echo -n $(tput sgr0) ;; # no font attributes
970 # Try to keep environment pollution down, EPA loves us.
971 unset safe_term match_lhs use_color
983 if [[ $- == *i* ]]; then
984 # git branch/status prompt function
985 if [[ $OS != Windows_NT ]]; then
986 GIT_PS1_SHOWDIRTYSTATE=true
988 # arch source location
989 [[ -r /usr/share/git/git-prompt.sh ]] && source /usr/share/git/git-prompt.sh
990 # fedora/debian source
991 [[ -r /usr/share/git-core/contrib/completion/git-prompt.sh ]] && source /usr/share/git-core/contrib/completion/git-prompt.sh
993 # in case we didn't source git-prompt.sh
994 if ! declare -f __git_ps1 > /dev/null; then
1000 # this needs to come before next ps1 stuff
1001 # this stuff needs bash 4, feb 2009,
1002 # old enough to no longer condition on $BASH_VERSION anymore
1006 if [[ $- == *i* ]] && [[ ! $INSIDE_EMACS ]]; then
1008 bind -m vi-command B:shell-backward-word
1009 bind -m vi-command W:shell-forward-word
1012 if [[ $SSH_CLIENT ]]; then
1017 local return=$? # this MUST COME FIRST
1019 local ps_char ps_color
1021 history -a # save history
1022 history -n # read any new history
1023 if [[ ! $DESKTOP_SESSION == xmonad && $TERM == *(screen*|xterm*|rxvt*) ]]; then
1024 # from the screen man page
1025 if [[ $TERM == screen* ]]; then
1026 local title_escape="\033]..2;"
1028 local title_escape="\033]0;"
1030 echo -ne "$title_escape${PWD/#$HOME/~} $USER@$HOSTNAME\007"
1034 0) ps_color="$(get_term_color blue)"
1037 1) ps_color="$(get_term_color green)"
1038 ps_char="$return \\$"
1040 *) ps_color="$(get_term_color yellow)"
1041 ps_char="$return \\$"
1044 if [[ ! -O . ]]; then # not owner
1045 if [[ -w . ]]; then # writable
1046 ps_color="$(get_term_color bold red)"
1048 ps_color="$(get_term_color bold green)"
1051 PS1="${PS1%"${PS1#*[wW]}"}$(__git_ps1 ' (%s)') \[$ps_color\]$ps_char\[$(get_term_color nocolor)\] "
1053 PROMPT_COMMAND=prompt_command
1060 ###########################################
1061 # stuff that makes sense to be at the end #
1062 ###########################################
1063 if [[ "$SUDOD" ]]; then
1065 elif [[ -d /a ]] && [[ $PWD == $HOME ]] && [[ $- == *i* ]]; then
1074 # if someone exported $SOE, catch errors