-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdstore
executable file
·247 lines (226 loc) · 7.22 KB
/
dstore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#!/usr/bin/env bash
#
# FILE: dstore
#
# ABSTRACT: Manage manual index (index.dstore)
#
# AUTHOR: Ralf Schandl
#
# CREATED: 2020-10-08
#
script_name="$(basename "$0")"
qc_version=2.0
# Directory for qc index files
[ -z "${QC_DIR:-}" ] && QC_DIR=$HOME/.qc
QC_DIR_DATA="$QC_DIR"
QC_DIR_INDEX="$QC_DIR/index"
# Manual index file storing directory names and bookmarked directories. This
# file is managed using the command 'dstore'.
QC_DSTORE_INDEX=$QC_DIR_DATA/index.dstore
show_help()
{
echo "Manually manage content of $QC_DSTORE_INDEX for usage with 'qc'."
echo ""
echo "Usage:"
echo " dstore"
echo " store current directory"
echo " dstore dirname"
echo " store given directory"
echo " dstore -d"
echo " remove current directory from index"
echo " dstore -d dirname"
echo " remove given directory from index"
echo " dstore :lbl"
echo " store current directory with label ':lbl'"
echo " dstore :lbl dirname"
echo " store given directory with label ':lbl'"
echo " dstore -d :lbl"
echo " remove directory labeled with ':lbl' from index"
echo " dstore [-e | -l | -c]"
echo " '-e' edit directory index (using ${VISUAL:-${EDITOR:-vi}})"
echo " '-l' list directory index"
echo " '-c' clean up duplicate/none-existing entries"
echo ""
echo "Note: Labels are case-insensitive and are always stored in lower case."
echo ""
echo "See also: qc --help"
echo ""
}
# cleanup ~/.qc/index.dstore
__dstore_clean()
{
# if action is 'warn' just warn about none-existing dirs
typeset action=${1:-}
# delete duplicates
LC_ALL=C sort -u "$QC_DSTORE_INDEX" > "$QC_DSTORE_INDEX.tmp"
mv -f "$QC_DSTORE_INDEX.tmp" "$QC_DSTORE_INDEX"
# get other index files
typeset -a otherIdx
otherIdx=( "$QC_DIR_INDEX"/*.index )
if [ ${#otherIdx[@]} -eq 0 ]; then
otherIdx=( /dev/null )
elif [ ${#otherIdx[@]} -eq 1 ]; then
[ ! -e "${otherIdx[0]}" ] && otherIdx=( /dev/null )
fi
typeset IFS=$'\n'
typeset labels=""
typeset d
true > "$QC_DSTORE_INDEX.tmp"
while read -r d; do
case $d in
:*)
# remove non-existing dirs and warn on duplicate labels
lbl=$(echo "$d" | cut "-d " -f1)
dir=$(echo "$d" | cut "-d " -f2-)
if [ -d "$dir" ]; then
echo "$d" >> "$QC_DSTORE_INDEX.tmp"
if echo "$labels" | grep -ai " $lbl " >/dev/null 2>&1; then
echo >&2 "Warning: Duplicate label: '$lbl'"
fi
labels="$labels $lbl "
else
if [ "$action" = "warn" ]; then
echo "$d" >> "$QC_DSTORE_INDEX.tmp"
echo >&2 "WARNING $d: Does not exist (anymore). Use 'dstore -c' to clean up."
else
echo >&2 "Removed $d: Does not exist (anymore)."
fi
fi
;;
?*)
# ignore dirs already in another index file
if grep -a "^${d}$" "${otherIdx[@]}" >/dev/null 2>&1; then
echo >&2 "Removed $d: Already in $(grep -al "^${d}$" "${otherIdx[@]}")"
continue
fi
# remove non-existing dirs
if [ -d "$d" ]; then
echo "$d" >> "$QC_DSTORE_INDEX.tmp"
else
if [ "$action" = "warn" ]; then
echo "$d" >> "$QC_DSTORE_INDEX.tmp"
echo >&2 "WARNING $d: Does not exist (anymore). Use 'dstore -c' to clean up."
else
echo >&2 "Removed $d: Does not exist (anymore)."
fi
fi
;;
esac
done < "$QC_DSTORE_INDEX"
mv -f "$QC_DSTORE_INDEX.tmp" "$QC_DSTORE_INDEX"
}
__qc_fqname()
{
if [ -d "$1" ]; then
if ! (cd -- "$1" && pwd); then
return 1
fi
else
(cd "$(dirname -- "$1")" && echo -n "$(pwd)" && echo "/$(basename -- "$1")")
fi
}
#---------[ MAIN ]-------------------------------------------------------------
# create empty index.dstore if it does not exist.
if [ ! -e "$QC_DSTORE_INDEX" ]; then
mkdir -p "$(dirname "$QC_DSTORE_INDEX")"
touch "$QC_DSTORE_INDEX"
fi
typeset delete=''
if ! _args="$(getopt -n "$script_name" -o "elcd" --long "help,version" -- "$@")"; then
echo >&2 "Try '$script_name --help' for more information."
exit 1
fi
eval "set -- $_args"
while true; do
case $1 in
-e)
${VISUAL:-${EDITOR:-vi}} "$QC_DSTORE_INDEX"
__dstore_clean warn
exit
;;
-l)
cat "$QC_DSTORE_INDEX"
exit
;;
-c) __dstore_clean
exit
;;
-d) delete=true
;;
--help)
show_help
exit 0
;;
--version)
echo "$script_name - Quick Change Directory v$qc_version"
exit 0
;;
--)
shift
break
;;
*)
echo >&2 "Invalid option '$1'"
echo >&2 "Try '$script_name --help' for more information."
exit 1
;;
esac
shift
done
shift $((OPTIND-1))
if [ $# -eq 0 ]; then
set -- '.'
fi
/bin/cp -f "$QC_DSTORE_INDEX" "$QC_DSTORE_INDEX.org"
while [ $# -gt 0 ]; do
case $1 in
:*)
typeset -l lbl=$1
shift
if [ ${#lbl} -eq 1 ] || [ "${lbl//[-A-Za-z0-9_]/}" != ':' ]; then
echo >&2 "Invalid label '$lbl'."
exit 1
fi
if [ "$delete" = "true" ]; then
grep -avi "^$lbl " "$QC_DSTORE_INDEX" > "$QC_DSTORE_INDEX.tmp"
mv "$QC_DSTORE_INDEX.tmp" "$QC_DSTORE_INDEX"
else
typeset dir
if [ $# -lt 1 ]; then
dir=$(__qc_fqname ".")
else
dir=$(__qc_fqname "$1")
shift
fi
if [ -d "$dir" ]; then
grep -avi "^$lbl " "$QC_DSTORE_INDEX" > "$QC_DSTORE_INDEX.tmp"
mv "$QC_DSTORE_INDEX.tmp" "$QC_DSTORE_INDEX"
echo "$lbl $dir" >> "$QC_DSTORE_INDEX"
else
echo >&2 "Error: Not a directory: $dir"
fi
fi
;;
?*)
dir=$(__qc_fqname "$1")
shift
if [ "$delete" = "true" ]; then
grep -av "^${dir}$" "$QC_DSTORE_INDEX" > "$QC_DSTORE_INDEX.tmp"
mv "$QC_DSTORE_INDEX.tmp" "$QC_DSTORE_INDEX"
else
if [ -d "$dir" ]; then
echo "$dir" >> "$QC_DSTORE_INDEX"
else
echo >&2 "Error: Not a directory: $dir"
fi
fi
;;
esac
done
if cmp -s "$QC_DSTORE_INDEX.org" "$QC_DSTORE_INDEX"; then
echo "No change"
else
diff -N "$QC_DSTORE_INDEX.org" "$QC_DSTORE_INDEX" | grep -a -- "^[<>]" | sed "s/^</Removed:/;s/^>/Added: /"
fi
rm "$QC_DSTORE_INDEX.org"
__dstore_clean warn