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