Update.
[scripts.git] / bashrc
1 # -*-Shell-script-*-
2
3 #########################################################################
4 # This program is free software: you can redistribute it and/or modify  #
5 # it under the terms of the version 3 of the GNU General Public License #
6 # as published by the Free Software Foundation.                         #
7 #                                                                       #
8 # This program is distributed in the hope that it will be useful, but   #
9 # WITHOUT ANY WARRANTY; without even the implied warranty of            #
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      #
11 # General Public License for more details.                              #
12 #                                                                       #
13 # You should have received a copy of the GNU General Public License     #
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.  #
15 #                                                                       #
16 # Written by and Copyright (C) Francois Fleuret                         #
17 # Contact <francois@fleuret.org> for comments & bug reports             #
18 #########################################################################
19
20 # The site-specific and confidential settings are in another file
21
22 PRIVATE_BASHRC="${HOME}/private/bashrc.perso"
23
24 # If the MANPATH is not set, set it
25
26 [ "${MANPATH}" ] || MANPATH=$(manpath)
27
28 # If the private bashrc exists, execute it
29
30 [ -f "${PRIVATE_BASHRC}" ] && source "${PRIVATE_BASHRC}"
31
32 # !!! THIS HAS TO BE HERE EVEN IN THE NON-INTERACTIVE PART OR YOU WILL
33 # LOSE YOU PREVIOUS HISTORY !!!
34
35 export HISTFILESIZE=20000
36 export HISTSIZE=${HISTFILESIZE}
37
38 export HISTIGNORE="${HISTIGNORE}:&:[ ]*"
39
40 # I want to save the command time, but I do not want to see it in
41 # history
42
43 export HISTTIMEFORMAT=""
44
45 shopt -s histappend
46
47 # I realized that most of my settings are meaningful only in
48 # interactive mode. This should maybe be done more properly through
49 # using different .bash_profile and .bash_login
50
51 [ ${TERM} == "dumb" ] || [[ ! -t 0 ]] && return
52
53 # Remove the annoying beeps in console
54
55 setterm -blength 0
56
57 ######################################################################
58 ## The interactive part
59
60 export VT_RESET=$'\e[0m'
61 export VT_BOLD=$'\e[1m'
62 export VT_UNDERLINE=$'\e[4m'
63 export VT_BLINK=$'\e[5m'
64
65 export VT_SET_TITLE=$'\e]0;'
66 export VT_END_TITLE=$'\007'
67
68 export VT_BLACK_FG=$'\e[30m'
69 export VT_RED_FG=$'\e[31m'
70 export VT_GREEN_FG=$'\e[32m'
71 export VT_YELLOW_FG=$'\e[33m'
72 export VT_BLUE_FG=$'\e[34m'
73 export VT_MAGENTA_FG=$'\e[35m'
74 export VT_CYAN_FG=$'\e[36m'
75 export VT_WHITE_FG=$'\e[37m'
76
77 export VT_BLACK_BG=$'\e[40m'
78 export VT_RED_BG=$'\e[41m'
79 export VT_GREEN_BG=$'\e[42m'
80 export VT_YELLOW_BG=$'\e[43m'
81 export VT_BLUE_BG=$'\e[44m'
82 export VT_MAGENTA_BG=$'\e[45m'
83 export VT_CYAN_BG=$'\e[46m'
84 export VT_WHITE_BG=$'\e[47m'
85
86 # Colorize man pages!
87
88 export LESS_TERMCAP_us=${VT_GREEN_FG}
89 export LESS_TERMCAP_ue=${VT_RESET}
90 export LESS_TERMCAP_md=${VT_BLUE_FG}${VT_BOLD}
91 export LESS_TERMCAP_me=${VT_RESET}
92
93 # export LESS_TERMCAP_md=$'\e[1;34;40m'
94
95 # This prevents ^S from freezing the shell
96
97 # stty -ixon
98
99 ulimit -c unlimited
100
101 alias ..='cd ..'
102 alias -- -='cd -'
103 alias rm='rm -v -i'
104 alias mv='mv -v -i'
105 alias chmod='chmod -c'
106 alias cp='cp -v -i'
107 alias rd=rmdir
108 alias md='mkdir -pv'
109 alias ps='ps uxaf'
110 alias df='df -hT'
111 # alias df='df -hT --sync'
112 alias grep='grep -i -E --color=auto'
113 alias find='ionice -c3 find'
114 alias pd=pushd
115 alias val='valgrind --leak-check=full --show-reachable=yes --db-attach=yes '
116
117 alias s='screen -d -R -U && clear'
118
119 function nh () {
120     export HISTFILE=/dev/null
121     unalias cd
122 }
123
124 function ding () {
125     if [[ $1 ]] && which winshepherd.sh; then
126         play -q ~/local/sounds/deskbell.wav &
127         unset E_APP_WINDOW
128         winshepherd.sh message green "$1"
129     else
130         play -q ~/local/sounds/deskbell.wav
131     fi
132 }
133
134 alias impressive="impressive -s -D 1000 -t Crossfade -T 100"
135
136 if [[ -e "${HOME}/.dircolors" ]]; then
137     eval $(dircolors "${HOME}/.dircolors")
138     alias ls='ls -p --group-directories-first --color'
139     alias lt='ls -p --color -gohtr --time-style="+%Y %b %d %H:%M"'
140     alias ll='ls -p --color -goh --time-style="+%Y %b %d %H:%M"'
141     alias lll='ls -p --color -lth'
142     alias l='ls -p --color -I "*~" -I "*.o"'
143     alias less='less -R'
144 else
145     alias ls='ls -p --group-directories-first'
146     alias lt='ls -p -gohtr --time-style="+%Y %b %d %H:%M"'
147     alias ll='ls -p -goh --time-style="+%Y %b %d %H:%M"'
148     alias lll='ls -p -lth'
149     alias l='ls -p -I "*~" -I "*.o"'
150 fi
151
152 export EDITOR=emacsclient
153 export GIT_EDITOR=${EDITOR}
154
155 ######################################################################
156 # Ignored extensions when completing
157
158 # export FIGNORE="CVS"
159
160 function latexdiff () {
161     wdiff -n \
162         -w $'\033[30;41m' -x $'\033[0m' \
163         -y $'\033[30;42m' -z $'\033[0m' \
164         $*
165 }
166
167 # Looks for the most recent .log and pdflatex + bibtex the
168 # corresponding tex file
169
170 function rl () {
171     RECENT_LOG=$(ls -t $(find -maxdepth 1 -name "*.log" -type f) | head -1)
172
173     if [[ ${RECENT_LOG} ]]; then
174         FILEBASE="${RECENT_LOG/.log/}"
175
176         if [[ -f "${FILEBASE}.tex" ]]; then
177
178             pdflatex "${FILEBASE}"
179             bibtex "${FILEBASE}"
180             pdflatex "${FILEBASE}"
181             pdflatex "${FILEBASE}"
182
183             if [[ "$1" ]]; then
184                 if [[ "$1" == "-v" ]] || [[ "$1" == "--view" ]]; then
185                     xpdf "${FILEBASE}.pdf"
186                 elif [[ "$1" == "-p" ]] || [[ "$1" == "--print" ]]; then
187                     lpr "${FILEBASE}.pdf"
188                 else
189                     echo "Usage: rl [-v|--view] [-p|--print]" >&2
190                     echo "Unknown option $1" >&2
191                     return 1
192                 fi
193             fi
194
195         else
196
197             echo "Can not find a tex file corresponding to the most recent log (${RECENT_LOG/.log/})." >&2
198             return 1
199
200         fi
201
202     else
203         echo "Can not find a recent log." >&2
204         return 1
205     fi
206 }
207
208
209 ######################################################################
210 # Functions
211
212 # http://www.reddit.com/r/linux/comments/2cgu5k/a_handy_little_script_for_interacting_with_your/
213 function clip () {
214     if [[ -t 0 ]] && [[ -z "$1" ]]; then
215         # output contents of clipboard
216         xclip -out -selection clipboard || exit 1
217     elif [[ "$1" ]]; then
218         # copy file contents to clipboard
219         xclip -in -selection clipboard < "$1" || exit 1
220     else
221         # copy stdin to clipboard
222         xclip -in -selection clipboard <&0 || exit 1
223     fi
224 }
225
226 # Find a file whose name contains a substring
227
228 function fn () {
229     name=$1
230     shift
231     find "$@" -name "*${name}*";
232 }
233
234 function bak () {
235     while [[ "$1" ]]; do
236         cp "$1" "$1".bak
237         shift
238     done
239 }
240
241 # Password generator
242
243 function pwgen () {
244     tr -dc A-Za-z0-9 < /dev/urandom | head -c16
245     echo
246 }
247
248 function ua () {
249
250     [[ "$1" ]] || ( echo "Universal unarchive: ua <file> [<file> ...]" >&2 && return 1)
251
252     while [[ "$1" ]]; do
253
254         case "$1" in
255             *.tgz|*.tar.gz|*.tbz|*.tar.bz2)
256                 tar xvf "$1"
257                 ;;
258
259             *.rar)
260                 unrar -kb x "$1"
261                 ;;
262
263             *.zip)
264                 unzip "$1"
265                 ;;
266
267             *)
268                 echo "Unknown file extension $1"
269                 ;;
270         esac
271
272         shift
273
274     done
275 }
276
277 # Create a dir and cd there
278
279 function mcd () {
280     mkdir -vp "$1"
281     cd "$1"
282 }
283
284 # Capture the screen in a dated png
285
286 function cap () {
287     if [[ $2 ]]; then
288         name=$2
289     else
290         name="capture-$(date +%s).png"
291     fi
292     echo "Waiting $1 s and saving to ${name}."
293     [[ "$1" ]] && sleep "$1"
294     echo "Please click on the window to capture."
295     xwd  | convert - ${name}
296     \ls -l ${name}
297 }
298
299 # Create and CD in a /tmp/tmp.XXXXXX directory. With the '-'
300 # arguments, do not create one and CD in the most recent instead
301
302 function cdt () {
303     if [[ "$1" ]]; then
304         if [[ "$1" == "-" ]]; then
305             cd $(\ls -td /tmp/tmp.?????? | head -1)
306         else
307             echo "USAGE: cdt [-]" >&2
308             return 1
309         fi
310     else
311         dir=$(mktemp -d /tmp/tmp.XXXXXX)
312         link=/tmp/tmp
313         if [[ -h ${link} ]]; then
314             \rm ${link}
315         fi
316         if [[ ! -a ${link} ]]; then
317             ln -s ${dir} ${link}
318         fi
319         cd ${dir}
320     fi
321 }
322
323 alias t='cd /tmp'
324
325 function trash () {
326     TRASH=$(date +/tmp/trash-%Y-%b-%d-%Hh)
327     LINK=/tmp/trash
328
329     mkdir -p ${TRASH}
330
331     [[ -h ${LINK} ]] && \rm ${LINK}
332
333     [[ ! -f ${LINK} ]] && ln -s ${TRASH} ${LINK}
334
335     mv "$@" ${TRASH}
336     echo "Trashed $@"
337 }
338
339 ######################################################################
340 ## A version of pho which stores the image numbers in environment
341 ## variables
342
343 function pho () {
344     TEMP=$(mktemp /tmp/pho.XXXXXXX)
345     $(which pho) "$@" | tee ${TEMP}
346     PHO_NOTE_1=$(grep ^"Note 1: " ${TEMP} | sed -e "s/^[^:]*: //")
347     PHO_NOTE_2=$(grep ^"Note 2: " ${TEMP} | sed -e "s/^[^:]*: //")
348     PHO_NOTE_3=$(grep ^"Note 3: " ${TEMP} | sed -e "s/^[^:]*: //")
349     PHO_NOTE_R90=$(grep ^"Rotate 90 \(CW\): " ${TEMP} | sed -e "s/^[^:]*: //")
350     PHO_NOTE_R180=$(grep ^"Rotate 180: " ${TEMP} | sed -e "s/^[^:]*: //")
351     PHO_NOTE_R270=$(grep ^"Rotate -90 \(CCW\): " ${TEMP} | sed -e "s/^[^:]*: //")
352     [[ "${PHO_NOTE_1}" ]] || unset PHO_NOTE_1
353     [[ "${PHO_NOTE_2}" ]] || unset PHO_NOTE_2
354     [[ "${PHO_NOTE_3}" ]] || unset PHO_NOTE_3
355     [[ "${PHO_NOTE_R90}" ]] || unset PHO_NOTE_R90
356     [[ "${PHO_NOTE_R180}" ]] || unset PHO_NOTE_R180
357     [[ "${PHO_NOTE_R270}" ]] || unset PHO_NOTE_R270
358     \rm ${TEMP}
359 }
360
361 ######################################################################
362 ## A version of date that shows the time at home if TZ is set
363
364 function dt () {
365     echo "Local: $(date)"
366     if [[ ${TZ} ]]; then
367         unset TZ
368         echo "Home:  $(date)"
369     fi
370 }
371
372 ######################################################################
373 ## ifup / ifdown with sudo and memorization of the network
374
375 ## When invoked without an argument netup uses the same argument as
376 ## the previous time
377
378 ## When invoked without an argument netdown removes the last interface
379 ## which was netuped
380
381 [ ${NETUP_HISTORY} ] || NETUP_HISTORY="${HOME}/.netup_history"
382
383 function netup () {
384     local upped_wifi
385
386     [[ "${WIFI_INTERFACE}" ]] || WIFI_INTERFACE=wlan0
387
388     if [[ "$1" == "--scan" ]]; then
389         if ifconfig -s | grep -v -q ${WIFI_INTERFACE}; then
390             sudo ifconfig ${WIFI_INTERFACE} up
391             upped_wifi=1
392         fi
393
394         sudo iwlist ${WIFI_INTERFACE} scan | \grep -E 'ESS|Quali|Encry' | sed -e 's/^[ \t]*//'
395
396         if [[ ${upped_wifi} ]]; then
397             sudo ifconfig ${WIFI_INTERFACE} down
398             unset upped_wifi
399         fi
400
401         return 0
402     fi
403
404     if \ifconfig -s | grep -q -v ^'(Iface|lo) '; then
405         echo "There is/are already interface(s) up." >&2
406         return 1
407     fi
408
409     if \ps h -C dhclient | grep -q .; then
410         echo "There is already a dhcp client running." >&2
411         return 1
412     fi
413
414     if \ps h -C wpa_supplicant | grep -q .; then
415         echo "There is already a wpa_supplicant running." >&2
416         return 1
417     fi
418
419     if [[ ! "$@" ]] && [[ -s ${NETUP_HISTORY} ]]; then
420         echo "netup <interface>" >&2
421         return 1
422         # # If we have no argument and there is a .netup_history, use it
423         # ARGS=$(cat ${NETUP_HISTORY})
424     else
425         # Otherwise uses the given arguments, and store them
426         ARGS="$@"
427         echo ${ARGS} > ${NETUP_HISTORY}
428     fi
429
430     if [[ "${PRIVATE_INTERFACE_DEFINITION}" ]]; then
431         ARGS="-i ${PRIVATE_INTERFACE_DEFINITION} ${ARGS}"
432     fi
433
434     echo "Executing ${VT_GREEN_FG}[sudo ifup ${ARGS}]${VT_RESET}"
435     sudo ifup ${ARGS}
436
437     # Ugly hack to remove the dsl modem dns server when we add
438     # explicitely a dns in the /etc/network/interfaces
439
440     REMOVE_LOCAL_DNS=/usr/local/bin/remove-local-dns.sh
441     # REMOVE_LOCAL_DNS=${HOME}/sources/scripts/remove-local-dns.sh
442
443     if [[ -x ${REMOVE_LOCAL_DNS} ]]; then
444         echo "Executing ${VT_GREEN_FG}[sudo ${REMOVE_LOCAL_DNS} 192.168]${VT_RESET}"
445         sudo ${REMOVE_LOCAL_DNS} 192.168
446     fi
447 }
448
449 function netdown () {
450     if [[ ! "$@" ]] && [[ -s ${NETUP_HISTORY} ]]; then
451         # If there are no arguments and there is a .netup_history, get the
452         # interface from it
453         ARGS=$(tail -1 ${NETUP_HISTORY} | sed -e "s/=.*$//")
454     else
455         # Otherwise, use the standard ifdown
456         ARGS="$@"
457     fi
458
459     [[ "${PRIVATE_INTERFACE_DEFINITION}" ]] && ARGS="-i ${PRIVATE_INTERFACE_DEFINITION} ${ARGS}"
460
461     echo "Executing sudo ${VT_GREEN_FG}[ifdown ${ARGS}]${VT_RESET}"
462     sudo ifdown ${ARGS}
463
464     # if [[ $(\ps -C dhclient | tail -n +2) ]]; then
465     # echo "There is still a dhcp client running." >&2
466     # return 1
467     # fi
468
469     # if [[ $(\ps -C wpa_supplicant | tail -n +2) ]]; then
470     # echo "There is still a wpa_supplicant running." >&2
471     # return 1
472     # fi
473 }
474
475 function checkgw () {
476     GW=$(route -n | grep ^0.0.0.0 | awk '{print $2}')
477     if [[ "${GW}" ]]; then
478         ping ${GW}
479     else
480         echo "Can not find a getaway." >&2
481         return 1
482     fi
483 }
484
485 ######################################################################
486 # Show the most recent files, no scroll
487
488 function lr () {
489     HEIGHT=$(stty size | awk '{print $1}')
490     WIDTH=$(stty size | awk '{print $2}')
491     \ls -goth --time-style="+%Y %b %d %H:%M" "$@" | \
492         head -$((HEIGHT-2)) | \
493         cut -b1-${WIDTH}
494 }
495
496 ######################################################################
497 # You can change the xterm background color on the fly!
498
499 function setxtermbg () {
500     echo -n $'\e]11;'$1$'\007'
501 }
502
503 ######################################################################
504 # Shuffle the lines from the stdin
505
506 function shuffle () {
507     SEED=$1
508     [[ $SEED ]] || SEED=0
509     awk 'BEGIN{srand('${SEED}')} { print rand()" "$0 }' | sort -g | sed -e "s/^[0-9\.e\-]* //"
510 }
511
512 ######################################################################
513 # Stores the last entered command into a file
514
515 KEPT_COMMANDS=${HOME}/.kept_bash_commands
516
517 function keep () {
518     if [[ ${KEPT_COMMANDS} ]]; then
519         TOKEEP=$(mktemp /tmp/keep.XXXXXX)
520         if [[ "$*" ]]; then
521             echo "$*" > ${TOKEEP}
522         else
523             selector -b -i -d -l ${HISTSIZE} -o "${TOKEEP}" <(history)
524         fi
525
526         if [[ -s "${TOKEEP}" ]]; then
527             echo $(date)": "$(cat ${TOKEEP}) >> ${KEPT_COMMANDS}
528             cat "${TOKEEP}"
529         else
530             echo "No command stored!"
531         fi
532
533         \rm ${TOKEEP}
534     else
535         echo "You have to set \$KEPT_COMMANDS"
536     fi
537 }
538
539 ######################################################################
540 # I sometime burn CDs and DVDs
541
542 function burn () {
543     DEVICE="/dev/cdrw1"
544     if [[ ! "$1" ]]; then
545         echo "burn <iso name | dirname>" >&2
546     elif [[ -f "$1" ]]; then
547         if [[ $(file "$1" | \grep -E 'ISO 9660|UDF filesystem data') ]]; then
548             wodim -eject -v dev=${DEVICE} "$1"
549         else
550             echo "Do not know what to do with $1" >&2
551         fi
552     elif [[ -d "$1" ]]; then
553         [[ "${TMP_ROOT}" ]] || TMP_ROOT=/tmp/
554         echo "Using ${TMP_ROOT} as temporary directory."
555         TMP=$(mktemp ${TMP_ROOT}/cdimage.XXXXXX) && \
556             genisoimage -input-charset iso8859-1 -r -o ${TMP} "$1" && \
557             wodim -eject -v dev=${DEVICE} ${TMP}
558         rm -f ${TMP}
559     else
560         echo "Can not find $1" >&2
561     fi
562 }
563
564 ######################################################################
565 # And watch DVDs too!
566
567 function dvd () {
568
569     echo
570     echo " ! @   Seek to the beginning of the previous/next chapter"
571     echo " j     Cycle through the available subtitles"
572     echo " o     Show/hide the timing"
573     echo " x z   Subtitle delay"
574     echo " / *   Volume"
575     echo
576
577     if [[ "$1" ]]; then
578         dvd_device="$1"
579         shift
580     else
581         dvd_device="/dev/dvd"
582     fi
583
584     title="1"
585
586     if [[ "$1" ]]; then
587         title=$1
588         shift
589     fi
590
591     # -vc ffmpeg12 -vf yadif
592
593     mplayer > /dev/null \
594         -stop-xscreensaver \
595         -quiet \
596         -alang en -slang en \
597         -softvol -softvol-max 1000 \
598         -dvd-device ${dvd_device} ${MPLAYER_OPTIONS} dvd://${title}
599 }
600
601 function ripdvd () {
602     if [[ -e "/dev/dvd" ]]; then
603         DVD_DEVICE="/dev/dvd"
604     elif [[ -e "/dev/dvd3" ]]; then
605         DVD_DEVICE="/dev/dvd3"
606     else
607         echo "Can not find the dvd device." >&2
608         return 1
609     fi
610
611     echo "Attemptin to rip from ${DVD_DEVICE}."
612
613     mkdir -p ${HOME}/dvds
614
615     cd ${HOME}/dvds
616     time dvdbackup -i ${DVD_DEVICE} -v -M $* && eject
617 }
618
619 alias ripcd=abcde
620
621 ######################################################################
622 # Create small images from images
623
624 function mksmall () {
625
626     [[ "${PARAMS}" ]] || PARAMS="-geometry 800x600"
627
628     # Auto-orient does not seem to work at all, hence the ugly hack
629     # with exif below
630
631     # PARAMS="-auto-orient -geometry 800x600"
632
633     echo "Using ${PARAMS}"
634
635     DEST_DIR=$1
636
637     [[ ${DEST_DIR} ]] || DEST_DIR=./small
638
639     mkdir -p ${DEST_DIR}
640
641     if [[ ! -d ${DEST_DIR} ]]; then
642         echo "Can not create ${DEST_DIR}" >&2
643         return
644     fi
645
646     NB_TOTAL=$(find -maxdepth 1 -type f | wc -l)
647     NB=0
648
649     for i in $(find -maxdepth 1 -type f); do
650         if [[ $(file $i | grep image) ]]; then
651             if [[ -e ${DEST_DIR}/$i ]]; then
652                 echo "The file ${DEST_DIR}/$i already exists."
653             else
654                 if [[ $(file ${i/%.*/}.* | grep -E movie) ]] ; then
655                     CAPTION_PARAMS="-font FreeSans-Bold -pointsize 32 -fill green -annotate +10+32 Video"
656                 else
657                     CAPTION_PARAMS=""
658                 fi
659
660                 convert ${rotation_cmd} $i ${PARAMS} ${CAPTION_PARAMS} ${DEST_DIR}/$i
661             fi
662
663             \ls -lt ${DEST_DIR}/$i
664         fi
665
666         NB=$((NB+1))
667
668         echo "$((NB*100/NB_TOTAL))% (${NB}/${NB_TOTAL})"
669     done
670 }
671
672 ######################################################################
673 # Move a file to the ~/sources/config directory and replace it where
674 # it was by a symbolic link
675
676 function mvtoconfig () {
677     CONFIGDIR=${HOME}/sources/config
678     if [[ -d ${CONFIGDIR} ]]; then
679         NEWNAME=${CONFIGDIR}/$(basename "$1" | sed -e "s/^\.//")
680         mv "$1" $NEWNAME
681         ln -s $NEWNAME $1
682     else
683         echo "Can not find ${CONFIGDIR}"
684     fi
685 }
686
687 ######################################################################
688 # The complex prompt policy
689
690 export PS1
691
692 if [[ "${CONSOLE}" == "yes" ]]; then
693     PS1=""
694 else
695
696     # If the login is a standard one (as specified in
697     # IGNORED_PROMPT_LOGIN, which is set in the private bash file), do not
698     # show it. I have IGNORED_PROMPT_LOGIN="^fleuret$".
699
700     if [[ ! ${IGNORED_PROMPT_LOGIN} ]] || [[ ! ${USER} =~ ${IGNORED_PROMPT_LOGIN} ]]; then
701         IDENT="${USER}"
702     fi
703
704     # If the display is not the main one, make the assumption that the
705     # shell is not running on the localhost, and show the hostname
706
707     [[ "${DISPLAY}" != ":0.0" ]] && IDENT="${IDENT}@\h"
708
709     # If there is the login or the hostname, add a ":" to the prompt
710
711     [[ "${IDENT}" ]] && IDENT="${IDENT}:"
712
713     # If we are root, show that in red
714
715     if [[ ${USER} == "root" ]]; then
716         PS1="\[${VT_RED_BG}${VT_WHITE_FG}\]${IDENT}\w\[${VT_RESET}\] "
717     else
718         PS1="\[${VT_WHITE_BG}${VT_BLACK_FG}\]${IDENT}\w\[${VT_RESET}\] "
719     fi
720
721     # In an xterm, show the hostname and path in the title bar, highlight
722     # the prompt
723
724     # [[ "${TERMS_WITH_BAR}" ]] || TERMS_WITH_BAR="^xterm|screen$"
725
726     # if [[ "${TERM}" =~ "${TERMS_WITH_BAR}" ]]; then
727     # PS1="\[${VT_SET_TITLE}shell@\h (\w)${VT_END_TITLE}${VT_WHITE_BG}\]${IDENT}\w\[${VT_RESET}\] "
728     # else
729     # PS1="\[${VT_WHITE_BG}\]${IDENT}\w\[${VT_RESET}\] "
730     # fi
731
732 fi
733
734 ######################################################################
735 # This implements a local history. If we are in a directory containing
736 # a writable local history file, we add the last line of the global
737 # history to it.
738
739 LOCAL_HISTORY_FILE=".local_bash_history"
740
741 function keep_local_history () {
742     if [[ -w "${LOCAL_HISTORY_FILE}" ]]; then
743         history 1 | sed -e 's/^ *[0-9]* *//' >> ${LOCAL_HISTORY_FILE}
744         TMP=$(mktemp /tmp/lh.XXXXXX)
745         \chmod 600 ${TMP}
746         uniq < ${LOCAL_HISTORY_FILE} | tail -${HISTSIZE} > ${TMP}
747         # mv would replace a symbolic link, while cp keeps it
748         \cp ${TMP} ${LOCAL_HISTORY_FILE}
749         \rm ${TMP}
750         LOCAL_HISTORY_HINT="* "
751     else
752         LOCAL_HISTORY_HINT=""
753     fi
754 }
755
756 PS1="\[${VT_WHITE_BG}\]\${LOCAL_HISTORY_HINT}\[${VT_RESET}\]${PS1}"
757
758 ######################################################################
759 # Switch off the history
760
761 function histfile_cue () {
762     if [[ ! "${HISTFILE}" == "${HOME}/.bash_history" ]]; then
763         HISTORY_CUE="[${HISTFILE}]"
764     else
765         HISTORY_CUE=""
766     fi
767 }
768
769 PS1="\[${VT_YELLOW_BG}\]\${HISTORY_CUE}\[${VT_RESET}\]${PS1}"
770
771 ######################################################################
772 # The dus command is available on my web site
773 #
774 # git clone http://fleuret.org/git/dus/
775
776 alias dus='dus -f -i'
777
778 ######################################################################
779 # The finddup command is available on my web site
780 #
781 # git clone http://fleuret.org/git/finddup/
782
783 alias finddup='finddup -p'
784
785 ######################################################################
786 # The selector command is available on my web site
787 #
788 # git clone http://fleuret.org/git/selector/
789
790 source bash-selector.sh --hist --cd
791
792 ######################################################################
793 # And we avoid to put in the history the use of the selector, which we
794 # do too often
795
796 HISTIGNORE="${HISTIGNORE}:selector-history"
797
798 ######################################################################
799
800 function selector-printer () {
801     TMP=$(mktemp /tmp/selector-printer.XXXXXX)
802     selector -o ${TMP} <(lpstat -a | awk '{print $1}')
803     export PRINTER=$(cat ${TMP})
804     echo "PRINTER=${PRINTER}"
805     rm -f ${TMP}
806     lpq
807 }
808
809 ######################################################################
810 # A ls with memory to notice what files have been added/removed from
811 # the current directory
812
813 function lsn () {
814     LSN_MEMORY=".lsn-state"
815
816     if  [[ $1 == "--mem" ]] || [[ "$1" == "-m" ]]; then
817
818         \ls -pa | sort > ${LSN_MEMORY}
819         echo "State updated." >&2
820
821     elif [[ $1 == "+" ]]; then
822
823         shift
824
825         TMP=$(mktemp /tmp/lsn.XXXXXX)
826         \ls -d $* > ${TMP}
827         cat ${LSN_MEMORY} >> ${TMP}
828         sort -u ${TMP} > ${LSN_MEMORY}
829         \rm ${TMP}
830
831     elif [[ "$1" ]]; then
832
833         echo "lsn [--mem|-m] [+ <file> ...]" >&2
834         return 1
835
836     else
837
838         if [[ -f ${LSN_MEMORY} ]]; then
839             TMP=$(mktemp /tmp/lsn.XXXXXX)
840             \ls -pa | sort > ${TMP}
841             if diff > /dev/null ${TMP} ${LSN_MEMORY}; then
842                 echo "${VT_GREEN_FG}${VT_BOLD}No change (since $(date +"%b %d, %Y" -r ${LSN_MEMORY}))${VT_RESET}"
843             else
844                 \comm -1 -3 ${LSN_MEMORY} ${TMP}
845                 \comm -2 -3 ${LSN_MEMORY} ${TMP} | while read line; do
846                     echo "${VT_RED_FG}${VT_BOLD}${line}${VT_RESET} (missing)"
847                 done
848             fi
849             \rm ${TMP}
850         else
851             echo "No lsn state here." >&2
852             return 1
853         fi
854
855     fi
856 }
857
858 ######################################################################
859
860 function prompt_command () {
861     # save the history after every command to avoid loosing some when
862     # multiple shells are open
863     history -a
864     # load the saved history
865     history -n
866     # and the local histories system defined above
867     keep_local_history
868     # and the history cue
869     histfile_cue
870 }
871
872 PROMPT_COMMAND="prompt_command"
873
874 ######################################################################
875
876 # Displaying the timezone if it is set
877
878 if [[ ${TZ} ]]; then
879     echo "${VT_BOLD}${VT_GREEN_FG}Time zone is ${TZ}.${VT_RESET}"
880 fi
881
882 ######################################################################