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
|
# -*-eselect-*-
# Copyright 2005-2014 Gentoo Foundation
# Distributed under the terms of the GNU GPL version 2 or later
#
# DOCUMENTATION
# Following actions possible
# * show do_show()
# * list do_list()
# * set do_set()
# * update do_update()
#
# Behaviour:
# do_show():
# Checks if /usr/bin/ctags is a link and if the target exists,
# if yes, it outputs the currently linked ctags implementation.
# If it is no symlink, the user is told so, the same if there is
# no /usr/bin/ctags or the target does not exist.
# do_list(): List all available ctags implementations.
# do_set(): Set a version to be target of the symlink.
# do_update(): Set the target to the "best" available version. See below.
# This module is used for ctags and etags.
# Determine our name from ESELECT_MODULE_NAME, with BASH_SOURCE as fallback.
#CTAGS=${ESELECT_MODULE_NAME:-$(basename "${BASH_SOURCE[0]%.*}")}
CTAGS=ctags
DESCRIPTION="Manage /usr/bin/${CTAGS} implementations"
MAINTAINER="emacs@gentoo.org"
VERSION="1.17"
find_targets() {
# Return the list of available ctags implementations
# (X)Emacs: offer only one ctags implementation, namely for the
# currently active Emacs version (selected by emacs.eselect)
# The logic here is the same as in emacs.eselect, don't change it!
local emacs
if [[ -L ${EROOT}/usr/bin/emacs && -e ${EROOT}/usr/bin/emacs ]]; then
emacs=$(basename "$(readlink "${EROOT}/usr/bin/emacs")")
[[ -f ${EROOT}/usr/bin/${CTAGS}-${emacs} ]] && echo "${CTAGS}-${emacs}"
elif [[ -f ${EROOT}/usr/bin/xemacs ]]; then
[[ -f ${EROOT}/usr/bin/${CTAGS}-xemacs ]] && echo "${CTAGS}-xemacs"
elif [[ ${CTAGS} = etags ]]; then
# We are called as etags module, but no (X)Emacs is installed.
# Return an empty list in this case, because we don't want
# exuberant-ctags as default for etags (for ctags it's fine).
# Also, vi purists wouldn't want an etags symlink.
return
fi
# Exuberant ctags
[[ -f ${EROOT}/usr/bin/exuberant-ctags ]] && echo exuberant-ctags
}
remove_symlinks() {
# Remove existing symlinks to binary and man page
rm -f "${EROOT}/usr/bin/${CTAGS}" "${EROOT}"/usr/share/man/man1/${CTAGS}.1*
}
set_bin_symlinks() {
# Set symlink to binary
local target=$1
ln -s "${target}" "${EROOT}/usr/bin/${CTAGS}" \
|| die "Couldn't set ${target} ${EROOT}/usr/bin/${CTAGS} symlink"
}
set_man_symlinks() {
# Set symlink to man page
local target=$1 suffix i
for i in "${EROOT}/usr/share/man/man1/${target}.1"*; do
if [[ -f ${i} ]]; then
# target file exists; determine compression suffix
suffix=${i##*/"${target}.1"}
ln -s "${target}.1${suffix}" \
"${EROOT}/usr/share/man/man1/${CTAGS}.1${suffix}"
fi
done
}
set_symlinks() {
# Set symlinks to binary and man page
local target=$1 targets
# target may be specified by its name or its index
if is_number "${target}"; then
# numeric index, find the target's name
targets=( $(find_targets) )
[[ ${target} -ge 1 && ${target} -le ${#targets[@]} ]] \
|| die -q "Number out of range: $1"
target=${targets[target-1]}
fi
# is the target valid, i.e. does a ctags binary with this name exist?
[[ -f ${EROOT}/usr/bin/${target} ]] \
|| die -q "Target \"$1\" doesn't appear to be valid!"
echo "Switching ${CTAGS} to ${target} ..."
remove_symlinks || die -q "Couldn't remove existing symlink"
set_bin_symlinks "${target}"
set_man_symlinks "${target}"
return 0
}
test_for_root() {
# checks if the user has rights to modify /usr/bin/
[[ -w ${EROOT}/usr/bin ]] || die -q "You need root privileges!"
}
### show action ###
describe_show() {
echo "Show the current target of the ${CTAGS} symlink"
}
do_show() {
[[ $# -gt 0 ]] && die -q "Too many parameters"
write_list_start "Current target of ${CTAGS} symlink:"
if [[ -L ${EROOT}/usr/bin/${CTAGS} && -e ${EROOT}/usr/bin/${CTAGS} ]]
then
write_kv_list_entry \
"$(basename "$(readlink "${EROOT}/usr/bin/${CTAGS}")")" ""
elif [[ -e ${EROOT}/usr/bin/${CTAGS} ]]; then
write_kv_list_entry \
"(not a symlink or target of symlink does not exist)" ""
else
write_kv_list_entry "(unset)" ""
fi
}
### list action ###
describe_list() {
echo "List available ${CTAGS} symlink targets"
}
do_list() {
[[ $# -gt 0 ]] && die -q "Too many parameters"
local i targets
targets=( $(find_targets) )
for (( i = 0; i < ${#targets[@]}; i++ )); do
# Highlight the currently chosen version
[[ ${targets[i]} = \
"$(basename "$(readlink "${EROOT}/usr/bin/${CTAGS}")")" ]] \
&& targets[i]=$(highlight_marker "${targets[i]}")
done
write_list_start "Available ${CTAGS} symlink targets:"
write_numbered_list -m "(none found)" "${targets[@]}"
}
### set action ###
describe_set() {
echo "Set a new ${CTAGS} symlink"
}
describe_set_options() {
echo "target : Target name or number (from 'list' action)"
}
describe_set_parameters() {
echo "<target>"
}
do_set() {
[[ -z $1 ]] && die -q "You didn't tell me what to set the symlink to"
[[ $# -gt 1 ]] && die -q "Too many parameters"
test_for_root
if [[ -e ${EROOT}/usr/bin/${CTAGS} && ! -L ${EROOT}/usr/bin/${CTAGS} ]]
then
die -q "${EROOT}/usr/bin/${CTAGS} exists but is not a symlink"
fi
set_symlinks "$1" || die -q "Couldn't set a new symlink"
}
### update action ###
describe_update() {
echo "Automatically update the ${CTAGS} symlink"
}
describe_update_options() {
echo "ifunset : Do not override currently set version"
}
do_update() {
[[ -z $1 || $1 = ifunset || $1 = --if-unset ]] || die -q "Usage error"
[[ -z $2 || $2 = norecursion ]] || die -q "Usage error"
[[ $# -gt 2 ]] && die -q "Too many parameters"
test_for_root
if ! [[ $1 = *if*unset \
&& -L ${EROOT}/usr/bin/${CTAGS} && -e ${EROOT}/usr/bin/${CTAGS} ]]
then
local current=""
if [[ -L ${EROOT}/usr/bin/${CTAGS} ]]; then
current=$(basename "$(readlink "${EROOT}/usr/bin/${CTAGS}")")
if [[ ! -e ${EROOT}/usr/bin/${CTAGS} ]]; then
# clean up dead symlinks
remove_symlinks || die -q "Couldn't remove existing symlink"
fi
elif [[ -e ${EROOT}/usr/bin/${CTAGS} ]]; then
if ! [[ ${CTAGS} = ctags && $(uname) = FreeBSD ]]; then
die -q "${EROOT}/usr/bin/${CTAGS} exists but is not a symlink"
fi
# On FreeBSD ctags is a real file, installed by freebsd-ubin
current=nolink
fi
# For an "update" only the version should be changed, but not the
# provider (i.e. Emacs vs Exuberant). At the moment only (X)Emacs
# offers several concurrent versions.
local i target targets=( $(find_targets) )
if [[ ${#targets[@]} -gt 0 && ${current} != nolink ]]; then
target=${targets[0]}
[[ ${current} = ${CTAGS}-*emacs* ]] && current=${CTAGS}-*emacs*
for i in ${targets[@]}; do
[[ ${i} = ${current} ]] && target=${i}
done
set_symlinks "${target}" || die -q "Couldn't set a new symlink"
fi
fi
# Call "eselect etags update" from the ctags module and vice versa
[[ $2 = norecursion ]] && return
case ${CTAGS} in
ctags) CTAGS=etags do_update "$1" norecursion ;;
etags) CTAGS=ctags do_update "$1" norecursion ;;
esac
}
|