b7e32623b0486be8937e493793b79c931f936043
[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 function ua () {
242
243     [[ "$1" ]] || ( echo "Universal unarchive: ua <file> [<file> ...]" >&2 && return 1)
244
245     while [[ "$1" ]]; do
246
247         case "$1" in
248             *.tgz|*.tar.gz|*.tbz|*.tar.bz2)
249                 tar xvf "$1"
250                 ;;
251
252             *.rar)
253                 unrar -kb x "$1"
254                 ;;
255
256             *.zip)
257                 unzip "$1"
258                 ;;
259
260             *)
261                 echo "Unknown file extension $1"
262                 ;;
263         esac
264
265         shift
266
267     done
268 }
269
270 # Create a dir and cd there
271
272 function mcd () {
273     mkdir -vp "$1"
274     cd "$1"
275 }
276
277 # Capture the screen in a dated png
278
279 function cap () {
280     if [[ $2 ]]; then
281         name=$2
282     else
283         name="capture-$(date +%s).png"
284     fi
285     echo "Waiting $1 s and saving to ${name}."
286     [[ "$1" ]] && sleep "$1"
287     echo "Please click on the window to capture."
288     xwd  | convert - ${name}
289     \ls -l ${name}
290 }
291
292 # Create and CD in a /tmp/tmp.XXXXXX directory. With the '-'
293 # arguments, do not create one and CD in the most recent instead
294
295 function cdt () {
296     if [[ "$1" ]]; then
297         if [[ "$1" == "-" ]]; then
298             cd $(\ls -td /tmp/tmp.?????? | head -1)
299         else
300             echo "USAGE: cdt [-]" >&2
301             return 1
302         fi
303     else
304         dir=$(mktemp -d /tmp/tmp.XXXXXX)
305         link=/tmp/tmp
306         if [[ -h ${link} ]]; then
307             \rm ${link}
308         fi
309         if [[ ! -a ${link} ]]; then
310             ln -s ${dir} ${link}
311         fi
312         cd ${dir}
313     fi
314 }
315
316 alias t='cd /tmp'
317
318 function trash () {
319     TRASH=$(date +/tmp/trash-%Y-%b-%d-%Hh)
320     LINK=/tmp/trash
321
322     mkdir -p ${TRASH}
323
324     [[ -h ${LINK} ]] && \rm ${LINK}
325
326     [[ ! -f ${LINK} ]] && ln -s ${TRASH} ${LINK}
327
328     mv "$@" ${TRASH}
329     echo "Trashed $@"
330 }
331
332 ######################################################################
333 ## A version of pho which stores the image numbers in environment
334 ## variables
335
336 function pho () {
337     TEMP=$(mktemp /tmp/pho.XXXXXXX)
338     $(which pho) "$@" | tee ${TEMP}
339     PHO_NOTE_1=$(grep ^"Note 1: " ${TEMP} | sed -e "s/^[^:]*: //")
340     PHO_NOTE_2=$(grep ^"Note 2: " ${TEMP} | sed -e "s/^[^:]*: //")
341     PHO_NOTE_3=$(grep ^"Note 3: " ${TEMP} | sed -e "s/^[^:]*: //")
342     PHO_NOTE_R90=$(grep ^"Rotate 90 \(CW\): " ${TEMP} | sed -e "s/^[^:]*: //")
343     PHO_NOTE_R180=$(grep ^"Rotate 180: " ${TEMP} | sed -e "s/^[^:]*: //")
344     PHO_NOTE_R270=$(grep ^"Rotate -90 \(CCW\): " ${TEMP} | sed -e "s/^[^:]*: //")
345     [[ "${PHO_NOTE_1}" ]] || unset PHO_NOTE_1
346     [[ "${PHO_NOTE_2}" ]] || unset PHO_NOTE_2
347     [[ "${PHO_NOTE_3}" ]] || unset PHO_NOTE_3
348     [[ "${PHO_NOTE_R90}" ]] || unset PHO_NOTE_R90
349     [[ "${PHO_NOTE_R180}" ]] || unset PHO_NOTE_R180
350     [[ "${PHO_NOTE_R270}" ]] || unset PHO_NOTE_R270
351     \rm ${TEMP}
352 }
353
354 ######################################################################
355 ## A version of date that shows the time at home if TZ is set
356
357 function dt () {
358     echo "Local: $(date)"
359     if [[ ${TZ} ]]; then
360         unset TZ
361         echo "Home:  $(date)"
362     fi
363 }
364
365 ######################################################################
366 ## ifup / ifdown with sudo and memorization of the network
367
368 ## When invoked without an argument netup uses the same argument as
369 ## the previous time
370
371 ## When invoked without an argument netdown removes the last interface
372 ## which was netuped
373
374 [ ${NETUP_HISTORY} ] || NETUP_HISTORY="${HOME}/.netup_history"
375
376 function netup () {
377     local upped_wifi
378
379     [[ "${WIFI_INTERFACE}" ]] || WIFI_INTERFACE=wlan0
380
381     if [[ "$1" == "--scan" ]]; then
382         if ifconfig -s | grep -v -q ${WIFI_INTERFACE}; then
383             sudo ifconfig ${WIFI_INTERFACE} up
384             upped_wifi=1
385         fi
386
387         sudo iwlist ${WIFI_INTERFACE} scan | \grep -E 'ESS|Quali|Encry' | sed -e 's/^[ \t]*//'
388
389         if [[ ${upped_wifi} ]]; then
390             sudo ifconfig ${WIFI_INTERFACE} down
391             unset upped_wifi
392         fi
393
394         return 0
395     fi
396
397     if \ifconfig -s | grep -q -v ^'(Iface|lo) '; then
398         echo "There is/are already interface(s) up." >&2
399         return 1
400     fi
401
402     if \ps h -C dhclient | grep -q .; then
403         echo "There is already a dhcp client running." >&2
404         return 1
405     fi
406
407     if \ps h -C wpa_supplicant | grep -q .; then
408         echo "There is already a wpa_supplicant running." >&2
409         return 1
410     fi
411
412     if [[ ! "$@" ]] && [[ -s ${NETUP_HISTORY} ]]; then
413         echo "netup <interface>" >&2
414         return 1
415         # # If we have no argument and there is a .netup_history, use it
416         # ARGS=$(cat ${NETUP_HISTORY})
417     else
418         # Otherwise uses the given arguments, and store them
419         ARGS="$@"
420         echo ${ARGS} > ${NETUP_HISTORY}
421     fi
422
423     if [[ "${PRIVATE_INTERFACE_DEFINITION}" ]]; then
424         ARGS="-i ${PRIVATE_INTERFACE_DEFINITION} ${ARGS}"
425     fi
426
427     echo "Executing ${VT_GREEN_FG}[sudo ifup ${ARGS}]${VT_RESET}"
428     sudo ifup ${ARGS}
429
430     # Ugly hack to remove the dsl modem dns server when we add
431     # explicitely a dns in the /etc/network/interfaces
432
433     REMOVE_LOCAL_DNS=/usr/local/bin/remove-local-dns.sh
434     # REMOVE_LOCAL_DNS=${HOME}/sources/scripts/remove-local-dns.sh
435
436     if [[ -x ${REMOVE_LOCAL_DNS} ]]; then
437         echo "Executing ${VT_GREEN_FG}[sudo ${REMOVE_LOCAL_DNS} 192.168]${VT_RESET}"
438         sudo ${REMOVE_LOCAL_DNS} 192.168
439     fi
440 }
441
442 function netdown () {
443     if [[ ! "$@" ]] && [[ -s ${NETUP_HISTORY} ]]; then
444         # If there are no arguments and there is a .netup_history, get the
445         # interface from it
446         ARGS=$(tail -1 ${NETUP_HISTORY} | sed -e "s/=.*$//")
447     else
448         # Otherwise, use the standard ifdown
449         ARGS="$@"
450     fi
451
452     [[ "${PRIVATE_INTERFACE_DEFINITION}" ]] && ARGS="-i ${PRIVATE_INTERFACE_DEFINITION} ${ARGS}"
453
454     echo "Executing sudo ${VT_GREEN_FG}[ifdown ${ARGS}]${VT_RESET}"
455     sudo ifdown ${ARGS}
456
457     # if [[ $(\ps -C dhclient | tail -n +2) ]]; then
458     # echo "There is still a dhcp client running." >&2
459     # return 1
460     # fi
461
462     # if [[ $(\ps -C wpa_supplicant | tail -n +2) ]]; then
463     # echo "There is still a wpa_supplicant running." >&2
464     # return 1
465     # fi
466 }
467
468 function checkgw () {
469     GW=$(route -n | grep ^0.0.0.0 | awk '{print $2}')
470     if [[ "${GW}" ]]; then
471         ping ${GW}
472     else
473         echo "Can not find a getaway." >&2
474         return 1
475     fi
476 }
477
478 ######################################################################
479 # Show the most recent files, no scroll
480
481 function lr () {
482     HEIGHT=$(stty size | awk '{print $1}')
483     WIDTH=$(stty size | awk '{print $2}')
484     \ls -goth --time-style="+%Y %b %d %H:%M" "$@" | \
485         head -$((HEIGHT-2)) | \
486         cut -b1-${WIDTH}
487 }
488
489 ######################################################################
490 # You can change the xterm background color on the fly!
491
492 function setxtermbg () {
493     echo -n $'\e]11;'$1$'\007'
494 }
495
496 ######################################################################
497 # Shuffle the lines from the stdin
498
499 function shuffle () {
500     SEED=$1
501     [[ $SEED ]] || SEED=0
502     awk 'BEGIN{srand('${SEED}')} { print rand()" "$0 }' | sort -g | sed -e "s/^[0-9\.e\-]* //"
503 }
504
505 ######################################################################
506 # Stores the last entered command into a file
507
508 KEPT_COMMANDS=${HOME}/.kept_bash_commands
509
510 function keep () {
511     if [[ ${KEPT_COMMANDS} ]]; then
512         TOKEEP=$(mktemp /tmp/keep.XXXXXX)
513         if [[ "$*" ]]; then
514             echo "$*" > ${TOKEEP}
515         else
516             selector -b -i -d -l ${HISTSIZE} -o "${TOKEEP}" <(history)
517         fi
518
519         if [[ -s "${TOKEEP}" ]]; then
520             echo $(date)": "$(cat ${TOKEEP}) >> ${KEPT_COMMANDS}
521             cat "${TOKEEP}"
522         else
523             echo "No command stored!"
524         fi
525
526         \rm ${TOKEEP}
527     else
528         echo "You have to set \$KEPT_COMMANDS"
529     fi
530 }
531
532 ######################################################################
533 # I sometime burn CDs and DVDs
534
535 function burn () {
536     DEVICE="/dev/cdrw1"
537     if [[ ! "$1" ]]; then
538         echo "burn <iso name | dirname>" >&2
539     elif [[ -f "$1" ]]; then
540         if [[ $(file "$1" | \grep -E 'ISO 9660|UDF filesystem data') ]]; then
541             wodim -eject -v dev=${DEVICE} "$1"
542         else
543             echo "Do not know what to do with $1" >&2
544         fi
545     elif [[ -d "$1" ]]; then
546         [[ "${TMP_ROOT}" ]] || TMP_ROOT=/tmp/
547         echo "Using ${TMP_ROOT} as temporary directory."
548         TMP=$(mktemp ${TMP_ROOT}/cdimage.XXXXXX) && \
549             genisoimage -input-charset iso8859-1 -r -o ${TMP} "$1" && \
550             wodim -eject -v dev=${DEVICE} ${TMP}
551         rm -f ${TMP}
552     else
553         echo "Can not find $1" >&2
554     fi
555 }
556
557 ######################################################################
558 # And watch DVDs too!
559
560 function dvd () {
561
562     echo
563     echo " ! @   Seek to the beginning of the previous/next chapter"
564     echo " j     Cycle through the available subtitles"
565     echo " o     Show/hide the timing"
566     echo " x z   Subtitle delay"
567     echo " / *   Volume"
568     echo
569
570     if [[ "$1" ]]; then
571         dvd_device="$1"
572         shift
573     else
574         dvd_device="/dev/dvd"
575     fi
576
577     title="1"
578
579     if [[ "$1" ]]; then
580         title=$1
581         shift
582     fi
583
584     # -vc ffmpeg12 -vf yadif
585
586     mplayer > /dev/null \
587         -stop-xscreensaver \
588         -quiet \
589         -alang en -slang en \
590         -softvol -softvol-max 1000 \
591         -dvd-device ${dvd_device} ${MPLAYER_OPTIONS} dvd://${title}
592 }
593
594 function ripdvd () {
595     if [[ -e "/dev/dvd" ]]; then
596         DVD_DEVICE="/dev/dvd"
597     elif [[ -e "/dev/dvd3" ]]; then
598         DVD_DEVICE="/dev/dvd3"
599     else
600         echo "Can not find the dvd device." >&2
601         return 1
602     fi
603
604     echo "Attemptin to rip from ${DVD_DEVICE}."
605
606     mkdir -p ${HOME}/dvds
607
608     cd ${HOME}/dvds
609     time dvdbackup -i ${DVD_DEVICE} -v -M $* && eject
610 }
611
612 alias ripcd=abcde
613
614 ######################################################################
615 # Create small images from images
616
617 function mksmall () {
618
619     PARAMS="-geometry 800x600"
620
621     # Auto-orient does not seem to work at all, hence the ugly hack
622     # with exif below
623
624     # PARAMS="-auto-orient -geometry 800x600"
625
626     echo "Using ${PARAMS}"
627
628     DEST_DIR=$1
629
630     [[ ${DEST_DIR} ]] || DEST_DIR=./small
631
632     mkdir -p ${DEST_DIR}
633
634     if [[ ! -d ${DEST_DIR} ]]; then
635         echo "Can not create ${DEST_DIR}" >&2
636         return
637     fi
638
639     NB_TOTAL=$(find -maxdepth 1 -type f | wc -l)
640     NB=0
641
642     for i in $(find -maxdepth 1 -type f); do
643         if [[ $(file $i | grep image) ]]; then
644             if [[ -e ${DEST_DIR}/$i ]]; then
645                 echo "The file ${DEST_DIR}/$i already exists."
646             else
647                 if [[ $(file ${i/%.*/}.* | grep -E movie) ]] ; then
648                     CAPTION_PARAMS="-font FreeSans-Bold -pointsize 32 -fill green -annotate +10+32 Video"
649                 else
650                     CAPTION_PARAMS=""
651                 fi
652
653                 convert ${rotation_cmd} $i ${PARAMS} ${CAPTION_PARAMS} ${DEST_DIR}/$i
654             fi
655
656             \ls -lt ${DEST_DIR}/$i
657         fi
658
659         NB=$((NB+1))
660
661         echo "$((NB*100/NB_TOTAL))% (${NB}/${NB_TOTAL})"
662     done
663 }
664
665 ######################################################################
666 # Move a file to the ~/sources/config directory and replace it where
667 # it was by a symbolic link
668
669 function mvtoconfig () {
670     CONFIGDIR=${HOME}/sources/config
671     if [[ -d ${CONFIGDIR} ]]; then
672         NEWNAME=${CONFIGDIR}/$(basename "$1" | sed -e "s/^\.//")
673         mv "$1" $NEWNAME
674         ln -s $NEWNAME $1
675     else
676         echo "Can not find ${CONFIGDIR}"
677     fi
678 }
679
680 ######################################################################
681 # The complex prompt policy
682
683 export PS1
684
685 if [[ "${CONSOLE}" == "yes" ]]; then
686     PS1=""
687 else
688
689     # If the login is a standard one (as specified in
690     # IGNORED_PROMPT_LOGIN, which is set in the private bash file), do not
691     # show it. I have IGNORED_PROMPT_LOGIN="^fleuret$".
692
693     if [[ ! ${IGNORED_PROMPT_LOGIN} ]] || [[ ! ${USER} =~ ${IGNORED_PROMPT_LOGIN} ]]; then
694         IDENT="${USER}"
695     fi
696
697     # If the display is not the main one, make the assumption that the
698     # shell is not running on the localhost, and show the hostname
699
700     [[ "${DISPLAY}" != ":0.0" ]] && IDENT="${IDENT}@\h"
701
702     # If there is the login or the hostname, add a ":" to the prompt
703
704     [[ "${IDENT}" ]] && IDENT="${IDENT}:"
705
706     # If we are root, show that in red
707
708     if [[ ${USER} == "root" ]]; then
709         PS1="\[${VT_RED_BG}${VT_WHITE_FG}\]${IDENT}\w\[${VT_RESET}\] "
710     else
711         PS1="\[${VT_WHITE_BG}${VT_BLACK_FG}\]${IDENT}\w\[${VT_RESET}\] "
712     fi
713
714     # In an xterm, show the hostname and path in the title bar, highlight
715     # the prompt
716
717     # [[ "${TERMS_WITH_BAR}" ]] || TERMS_WITH_BAR="^xterm|screen$"
718
719     # if [[ "${TERM}" =~ "${TERMS_WITH_BAR}" ]]; then
720     # PS1="\[${VT_SET_TITLE}shell@\h (\w)${VT_END_TITLE}${VT_WHITE_BG}\]${IDENT}\w\[${VT_RESET}\] "
721     # else
722     # PS1="\[${VT_WHITE_BG}\]${IDENT}\w\[${VT_RESET}\] "
723     # fi
724
725 fi
726
727 ######################################################################
728 # This implements a local history. If we are in a directory containing
729 # a writable local history file, we add the last line of the global
730 # history to it.
731
732 LOCAL_HISTORY_FILE=".local_bash_history"
733
734 function keep_local_history () {
735     if [[ -w "${LOCAL_HISTORY_FILE}" ]]; then
736         history 1 | sed -e 's/^ *[0-9]* *//' >> ${LOCAL_HISTORY_FILE}
737         TMP=$(mktemp /tmp/lh.XXXXXX)
738         \chmod 600 ${TMP}
739         uniq < ${LOCAL_HISTORY_FILE} | tail -${HISTSIZE} > ${TMP}
740         # mv would replace a symbolic link, while cp keeps it
741         \cp ${TMP} ${LOCAL_HISTORY_FILE}
742         \rm ${TMP}
743         LOCAL_HISTORY_HINT="* "
744     else
745         LOCAL_HISTORY_HINT=""
746     fi
747 }
748
749 PS1="\[${VT_WHITE_BG}\]\${LOCAL_HISTORY_HINT}\[${VT_RESET}\]${PS1}"
750
751 ######################################################################
752 # Switch off the history
753
754 function histfile_cue () {
755     if [[ ! "${HISTFILE}" == "${HOME}/.bash_history" ]]; then
756         HISTORY_CUE="[${HISTFILE}]"
757     else
758         HISTORY_CUE=""
759     fi
760 }
761
762 PS1="\[${VT_YELLOW_BG}\]\${HISTORY_CUE}\[${VT_RESET}\]${PS1}"
763
764 ######################################################################
765 # The dus command is available on my web site
766 #
767 # git clone http://fleuret.org/git/dus/
768
769 alias dus='dus -f -i'
770
771 ######################################################################
772 # The finddup command is available on my web site
773 #
774 # git clone http://fleuret.org/git/finddup/
775
776 alias finddup='finddup -p'
777
778 ######################################################################
779 # The selector command is available on my web site
780 #
781 # git clone http://fleuret.org/git/selector/
782
783 source bash-selector.sh --hist --cd
784
785 ######################################################################
786 # And we avoid to put in the history the use of the selector, which we
787 # do too often
788
789 HISTIGNORE="${HISTIGNORE}:selector-history"
790
791 ######################################################################
792
793 function selector-printer () {
794     TMP=$(mktemp /tmp/selector-printer.XXXXXX)
795     selector -o ${TMP} <(lpstat -a | awk '{print $1}')
796     export PRINTER=$(cat ${TMP})
797     echo "PRINTER=${PRINTER}"
798     rm -f ${TMP}
799     lpq
800 }
801
802 ######################################################################
803 # A ls with memory to notice what files have been added/removed from
804 # the current directory
805
806 function lsn () {
807     LSN_MEMORY=".lsn-state"
808
809     if  [[ $1 == "--mem" ]] || [[ "$1" == "-m" ]]; then
810
811         \ls -pa | sort > ${LSN_MEMORY}
812         echo "State updated." >&2
813
814     elif [[ $1 == "+" ]]; then
815
816         shift
817
818         TMP=$(mktemp /tmp/lsn.XXXXXX)
819         \ls -d $* > ${TMP}
820         cat ${LSN_MEMORY} >> ${TMP}
821         sort -u ${TMP} > ${LSN_MEMORY}
822         \rm ${TMP}
823
824     elif [[ "$1" ]]; then
825
826         echo "lsn [--mem|-m] [+ <file> ...]" >&2
827         return 1
828
829     else
830
831         if [[ -f ${LSN_MEMORY} ]]; then
832             TMP=$(mktemp /tmp/lsn.XXXXXX)
833             \ls -pa | sort > ${TMP}
834             if diff > /dev/null ${TMP} ${LSN_MEMORY}; then
835                 echo "${VT_GREEN_FG}${VT_BOLD}No change (since $(date +"%b %d, %Y" -r ${LSN_MEMORY}))${VT_RESET}"
836             else
837                 \comm -1 -3 ${LSN_MEMORY} ${TMP}
838                 \comm -2 -3 ${LSN_MEMORY} ${TMP} | while read line; do
839                     echo "${VT_RED_FG}${VT_BOLD}${line}${VT_RESET} (missing)"
840                 done
841             fi
842             \rm ${TMP}
843         else
844             echo "No lsn state here." >&2
845             return 1
846         fi
847
848     fi
849 }
850
851 ######################################################################
852
853 function prompt_command () {
854     # save the history after every command to avoid loosing some when
855     # multiple shells are open
856     history -a
857     # load the saved history
858     history -n
859     # and the local histories system defined above
860     keep_local_history
861     # and the history cue
862     histfile_cue
863 }
864
865 PROMPT_COMMAND="prompt_command"
866
867 ######################################################################
868
869 # Displaying the timezone if it is set
870
871 if [[ ${TZ} ]]; then
872     echo "${VT_BOLD}${VT_GREEN_FG}Time zone is ${TZ}.${VT_RESET}"
873 fi
874
875 ######################################################################