[shell] Extend powerful cd and move it to its own file
[mina86-dot-files.git] / update
blobc1060f3d822f1a4f3155122fb0027eeb1a80f592
1 #! /bin/sh
3 set -eu
6 ##
7 ## Usage
8 ##
9 usage () {
10 cat <<EOF
11 usage: $0 [ <options> ] [ <files> ]
12 <options>:
13 -f Update files in current directory from configuration files in home.
14 -t Update configuration files from files in current directory; make backups.
15 -T Like ‘-t’ but don’t make any backups.
16 -y Assume ‘y’ to all questions, i.e. overwrite any changed files w/o asking.
17 -n Assume ‘n’ to all questions, i.e. only copy new files; leave existing be.
18 EOF
19 exit 1
24 ## Parse arguments
26 direction=
27 ask=ask
29 for arg in "$@"; do
30 case $arg in
31 -) usage;;
32 -?*) : ;;
33 *) break
34 esac
35 shift
36 while arg=${arg#?}; [ -n "$arg" ]; do
37 case "$arg" in
38 f*) direction=from ; backup=false;;
39 t*) direction=to ; backup=true ;;
40 T*) direction=to ; backup=false;;
41 y*) ask=if_different ;;
42 n*) ask=false ;;
43 *) usage ;;
44 esac
45 done
46 done
50 ## Color handling
52 if ! which tput >/dev/null 2>&1; then
53 tput () {
54 return 0
60 ## Print info
63 case "$direction" in
64 from)
65 tput bold
66 tput setaf 7
67 echo 'Updating files in current directory from configuration files'
68 tput sgr0
70 to)
71 tput bold
72 tput setaf 7
73 echo 'Updating configuration files from files in current directory'
74 tput sgr0
77 usage
78 esac
82 ## File arguments
84 if [ $# -eq 0 ]; then
85 match () {
86 return 0
88 else
89 match () {
90 for f in "$@"; do
91 case "$file" in "$f")
92 return 0
93 esac
94 done
95 return 1
101 ## Interactive asking
103 if diff=$(which cdiff 2>&1); then
104 cdiff=$diff
105 else
106 diff=diff
107 cdiff=cat
110 equal() {
111 set -- "$@" "$(readlink "$2")" "$(readlink "$3")"
113 if [ x"$4" = x"$5" ]; then
114 if [ -n "$4" ] || cmp -s "$2" "$3"; then
115 return 0
119 if [ x"$1" != x-v ]; then
120 return 1
121 elif [ -z "$4$5" ]; then
122 "$diff" -u -- "$3" "$2"
123 return 1
127 printf '%s\n' "--- $3"
128 printf '%s\n' "+++ $2"
130 if [ -z "$5" ]; then
131 sed s/^/-/ <$3
132 else
133 printf %s\\n "-→ $5"
136 if [ -z "$4" ]; then
137 sed s/^/+/ <$2
138 else
139 printf %s\\n "+→ $4"
141 ) | "$cdiff"
142 return 1
145 ask() {
146 if equal -v "$1" "$2"; then
147 return 1
150 while :; do
151 tput bold
152 tput setaf 7
153 tput setab 4
154 printf '%s:' "$2"
155 tput sgr0
156 tput setaf 7
157 tput setab 4
158 printf ' [yn] '
159 tput sgr0
160 read answer || exit 0
161 case "$answer" in
162 [yY]) return 0 ;;
163 [nN]) return 1 ;;
164 esac
165 done
168 if_different() {
169 ! equal -s "$1" "$2"
174 ## Emacs files handling
176 compile_el() {
177 if [ -n "$(which emacs 2>/dev/null)" ]; then
178 tput bold
179 tput setaf 7
180 echo "Compiling $1"
181 tput sgr0
182 emacs --batch -f batch-byte-compile "$1"
188 ## Do the job
190 handle() {
191 case $3 in *@) set -- "$1" "$2" "${3%@}${2##*/}"; esac
193 case $1 in from)
194 [ -d "${3%/*}" ] || return 0
195 set -- "$1" "$3" "$2"
196 esac
198 if [ -h "$3" ] || [ -e "$3" ]; then
199 if ! $ask "$2" "$3" <&3; then
200 return 0
201 elif $backup; then
202 mv -- "$3" "$3~"
206 case $3 in */*)
207 mkdir -p -- "${3%/*}"
208 esac
209 cp -dv -- "$2" "$3"
211 case "$direction:$3" in to:*.el)
212 compile_el "$3"
213 esac
216 while read pattern destination; do
217 for file in $pattern; do
218 case "$file" in *\~|*/\#*|*\#|*/.*)
219 continue
220 esac
221 if ! match "$@"; then
223 elif [ -h "$file" ] || [ -f "$file" ]; then
224 handle "$direction" "$file" "$HOME/$destination"
225 elif ! [ -e "$file" ]; then
226 echo "update: $file: missing, skipping" >&2
228 done
229 done 3<&1 <<EOF
230 aspell.en.pws .@
231 bin/* .local/bin/@
232 emacs/* .config/emacs/@
233 git/* .config/git/@
234 inputrc .@
235 irssi.theme .irssi/mina.theme
236 libexec/* .local/libexec/@
237 mail/* .mail/@
238 mpv/* .config/mpv/@
239 sawfishrc .sawfish/rc
240 sh/* .@
241 statuses .irssi/@
242 x/80-char.png .urxvt/@
243 x/Xresources .config/@
244 x/gtk-3.0.ini .config/gtk-3.0/settings.ini
245 x/gtkrc-2.0 .@
246 x/local.keymap .config/xkb/keymap/local
247 x/local.symbols .config/xkb/symbols/local
248 x/xinitrc .@
249 x/xserverrc .@
250 x/xsettingsd .@