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