]> arthur.barton.de Git - ax-zsh.git/blob - bin/axzshctl
Add axzshctl subcommands "enable" and "disable"
[ax-zsh.git] / bin / axzshctl
1 #!/usr/bin/env zsh
2 #
3 # AX-ZSH: Alex' Modular ZSH Configuration
4 # Copyright (c) 2015-2016 Alexander Barton <alex@barton.de>
5 #
6
7 # Include "ax-common.sh", if available:
8 for dir ("$HOME/lib" "$HOME/.ax" /usr/local /opt/ax /usr); do
9         [[ -z "$ax_common_sourced" ]] || break
10         ax_common="${dir}/lib/ax/ax-common.sh"
11         [[ -r "$ax_common" ]] && source "$ax_common"
12 done
13 if [[ -z "$ax_common_sourced" ]]; then
14         function ax_msg {
15                 shift
16                 echo "$@"
17         }
18 fi
19 unset dir ax_common ax_common_sourced
20
21 function Usage {
22         echo "Usage: $NAME <command> [...]"
23         echo
24         echo "  enable"
25         echo "    Enable AX-ZSH altogether."
26         echo
27         echo "  disable"
28         echo "    Disable AX-ZSH altogether."
29         echo
30         echo "  enable-plugin <name|directory> [<name|directory> [...]]"
31         echo "    Enable plugin(s)."
32         echo
33         echo "  disable-plugin <name> [<name> [...]]"
34         echo "    Disable plugin(s)."
35         echo
36         echo "  reset-plugins"
37         echo "    Reset active plugins to the default set."
38         echo
39         echo "  enable-default-plugins"
40         echo "    Enable all default plugins."
41         echo
42         echo "  check-plugins"
43         echo "    Detect plugins which are \"useful\" on this system."
44         echo
45         echo "  set-theme <name>|-"
46         echo "    Set active theme to <name>, or to the default."
47         echo
48         echo "  upgrade"
49         echo "    Upgrade AX-ZSH installation (requires Git)."
50         echo
51         exit 2
52 }
53
54 function NormalizedPluginName {
55         if [[ "$1" =~ "^[[:alnum:]-]+/[[:alnum:]_-]+$" ]]; then
56                 echo "$1" | sed -e 's|/|#|g'
57         elif [[ "$1" =~ "/" ]]; then
58                 basename "$1"
59         else
60                 echo "$1"
61         fi
62 }
63
64 function EnableAXZSH {
65         for f (~/.zlogin ~/.zlogout ~/.zprofile ~/.zshrc); do
66                 ln -sv "$AXZSH/ax.zsh" "$f" \
67                         || ax_msg 2 "Failed to create symbolic link for \"$f\"!"
68         done
69 }
70
71 function DisableAXZSH {
72         for f (~/.zlogin ~/.zlogout ~/.zprofile ~/.zshrc); do
73                 if [ -h "$f" ]; then
74                         rm -v "$f" || ax_msg 2 "Failed to remove \"$f\"!"
75                 elif [ -e "$f" ]; then
76                         ax_msg 2 "Error: Not removing \"$f\", it is not a symbolic link!"
77                 else
78                         ax_msg 1 "Warning: \"$f\" already does not exist. Ok."
79                 fi
80         done
81 }
82
83 function EnablePlugin {
84         local plugin=$(NormalizedPluginName "$1")
85         local dir="$AXZSH/active_plugins"
86
87         if [[ -h "$dir/$plugin" ]]; then
88                 ax_msg 1 "Plugin \"$1\" already active!"
89                 return 1
90         fi
91
92         if [[ "$1" =~ "^[[:alnum:]-]+/[[:alnum:]_-]+$" ]]; then
93                 # GitHub plugin
94                 mkdir -p "$AXZSH/repos"
95                 if [[ ! -e "$AXZSH/repos/$plugin" ]]; then
96                         ax_msg - "Cloning plugin from GitHub ..."
97                         git clone "https://github.com/$1.git" \
98                          "$AXZSH/repos/$plugin"
99                 fi
100         fi
101
102         for dname (
103                 "$plugin:A"
104                 "$AXZSH_PLUGIN_D/$plugin"
105                 "$ZSH_CUSTOM/$plugin"
106                 "$AXZSH/custom_plugins/$plugin"
107                 "$AXZSH/repos/$plugin"
108                 "$AXZSH/plugins/$plugin"
109                 "$AXZSH/default_plugins/$plugin"
110                 "$AXZSH/core/$plugin"
111         ); do
112                 [[ ! -d "$dname" ]] && continue
113                 mkdir -p "$dir"
114                 (
115                         cd "$dir" || exit 9
116                         ln -sv "$dname" "$PWD"
117                 )
118                 return $?
119         done
120
121         ax_msg 2 "Plugin \"$1\" not found!"
122         return 1
123 }
124
125 function DisablePlugin {
126         local plugin=$(NormalizedPluginName "$1")
127         local dir="$AXZSH/active_plugins"
128
129         if [[ ! -h "$dir/$plugin" ]]; then
130                 ax_msg 1 "Plugin \"$1\" not active?"
131                 return 1
132         fi
133
134         rm -v "$dir/$plugin"; r=$?
135         [ $r -eq 0 ] && rm -fr "$AXZSH/repos/$plugin"
136         return $r
137 }
138
139 function ResetPlugins {
140         local dir="$AXZSH/active_plugins"
141         local r1=0, r2=0
142
143         if [[ -e "$dir" ]]; then
144                 ax_msg - "Removing all symbolic links in $dir ..."
145                 find "$dir" -type l -print -delete; r1=$?
146         fi
147
148         ax_msg - "Removing all external repositories in \"$AXZSH/repos\" ..."
149         rm -fr "$AXZSH/repos"; r2=$?
150
151         [[ $r1 == 0 && $r2 == 0 ]] && return 0 || return 1
152 }
153
154 function EnableDefaultPlugins {
155         local dir="$AXZSH/active_plugins"
156
157         ax_msg - "Activating (linking) default plugins ..."
158         mkdir -p "$dir"
159         (
160                 cd "$dir" || exit 9
161                 ln -sfv "$AXZSH/default_plugins/"* "$PWD"
162         )
163         return $?
164 }
165
166 function SetTheme {
167         local link_name="$AXZSH/active_theme"
168
169         if [ $# -ne 1 ]; then
170                 echo "Usage: axzsh_set_theme <name|->"
171                 return 1
172         fi
173
174         rm -f "$link_name" || return 1
175
176         if [ "$1" = "-" ]; then
177                 echo "Theme settings have been reset."
178                 return 0
179         fi
180
181         if [ -r "$1" ]; then
182                 theme="$1"
183         elif [ -r "$AXZSH/custom_themes/$1.axzshtheme" ]; then
184                 theme="$AXZSH/custom_themes/$1.axzshtheme"
185         elif [ -r "$AXZSH/themes/$1.axzshtheme" ]; then
186                 theme="$AXZSH/themes/$1.axzshtheme"
187         else
188                 echo "Theme \"$1\" not found!"
189                 return 1
190         fi
191         ln -sv "$theme" "$link_name" || return 1
192         return $?
193 }
194
195 function UpgradeAXZSH {
196         if [[ $+commands[git] -eq 0 ]]; then
197                 ax_msg 2 "The git(1) command is not available!"
198                 return 1
199         fi
200         if [[ ! -d "$AXZSH/.git" ]]; then
201                 ax_msg 2 "AX-ZSH seems not to be installed using Git. Can't upgrade!"
202                 return 1
203         fi
204
205         ax_msg - "Upgrading AX-ZSH in \"$AXZSH\" using git(1) ..."
206         ( cd "$AXZSH" && git pull --ff-only )
207 }
208
209 function UpgradeForeignPlugins {
210         if [[ $+commands[git] -eq 0 ]]; then
211                 ax_msg 2 "The git(1) command is not available!"
212                 return 1
213         fi
214
215         for dir ($AXZSH/repos/*(N)); do
216                 name=$(basename "$dir" | sed -e 's|#|/|g')
217                 if [ -d "$dir/.git" ]; then
218                         ax_msg - "Upgrading \"$name\" [git] ..."
219                         (
220                                 cd "$dir"
221                                 git pull --ff-only || ax_msg 2 "Pull failed!"
222                         )
223                 else
224                         ax_msg 2 "Unknown repository type!"
225                 fi
226         done
227 }
228
229 function CheckPlugins {
230         missing_plugins=()
231         invalid_plugins=()
232
233         ax_msg - "Checking plugins ..."
234         for dir ($AXZSH/plugins/*(N)); do
235                 plugin=$(basename "$dir")
236
237                 # Test if plugin is already enabled
238                 [[ -e "$AXZSH/active_plugins/$plugin" ]] \
239                         && enabled=" (enabled)" \
240                         || unset enabled
241
242                 # Test plugin ...
243                 printf " - \"%s\"%s ... " "$plugin" "$enabled"
244                 new_plugin=""
245                 for script ($AXZSH/plugins/$plugin/$plugin.{zshrc,zprofile}); do
246                         [[ -r "$script" ]] || continue
247                         zsh -i -c "AXZSH_PLUGIN_CHECK=1 source $script"; r=$?
248                         if [[ $r -eq 0 ]]; then
249                                 new_plugin=$plugin
250                                 break
251                         fi
252                 done
253                 if [[ -n "$new_plugin" ]]; then
254                         detected_plugins+=($new_plugin)
255                         [[ -n "$enabled" ]] || missing_plugins+=($new_plugin)
256                         ax_msg 0 "OK."
257                 elif [[ $r -eq 91 ]]; then
258                         ax_msg 1 "ignored."
259                 elif [[ $r -eq 92 ]]; then
260                         ax_msg 1 "optional."
261                 else
262                         [[ -n "$enabled" ]] && invalid_plugins+=($plugin)
263                         ax_msg 2 "failed."
264                 fi
265         done
266         echo
267
268         result=0
269         if [[ -n "$missing_plugins" ]]; then
270                 ax_msg 1 "Run the following command to enable all missing plugins:"
271                 echo "$AXZSH/bin/axzshctl enable-plugin" $missing_plugins
272                 echo
273                 result=1
274         else
275                 ax_msg 0 "All detected plugins are already enabled."
276         fi
277
278         if [[ -n "$invalid_plugins" ]]; then
279                 ax_msg 1 "Run the following command to disable all failed plugins:"
280                 echo "$AXZSH/bin/axzshctl disable-plugin" $invalid_plugins
281                 result=1
282         else
283                 ax_msg 0 "No failed plugins are enabled."
284         fi
285
286         echo
287         return $result
288 }
289
290 NAME="$0:t"
291
292 [[ $# -gt 0 ]] || Usage
293
294 if [[ -z "$AXZSH" || ! -r "$AXZSH/ax.zsh" ]]; then
295         [[ -r "$HOME/.axzsh/ax.zsh" ]] && AXZSH="$HOME/.axzsh"
296         if [[ ! -r "$AXZSH/ax.zsh" ]]; then
297                 ax_msg 2 "Oops, \"AXZSH\" is not set or invalid and can't be autodetected!"
298                 exit 3
299         fi
300 fi
301
302 cmd="$1"
303 shift
304
305 case "$cmd" in
306         "enable")
307                 [[ $# -eq 0 ]] || Usage
308                 EnableAXZSH
309                 ;;
310         "disable")
311                 [[ $# -eq 0 ]] || Usage
312                 DisableAXZSH
313                 ;;
314         "enable-plugin")
315                 [[ $# -gt 0 ]] || Usage
316                 for plugin in "$@"; do
317                         EnablePlugin "$plugin"
318                 done
319                 ;;
320         "disable-plugin")
321                 [[ $# -gt 0 ]] || Usage
322                 for plugin in "$@"; do
323                         DisablePlugin "$plugin"
324                 done
325                 ;;
326         "reset-plugins")
327                 [[ $# -eq 0 ]] || Usage
328                 ResetPlugins
329                 EnableDefaultPlugins
330                 ;;
331         "enable-default-plugins")
332                 [[ $# -eq 0 ]] || Usage
333                 EnableDefaultPlugins
334                 ;;
335         "check-plugins")
336                 [[ $# -eq 0 ]] || Usage
337                 CheckPlugins
338                 ;;
339         "set-theme")
340                 [[ $# -eq 1 ]] || Usage
341                 SetTheme "$1"
342                 ;;
343         "upgrade")
344                 [[ $# -eq 0 ]] || Usage
345                 UpgradeAXZSH
346                 UpgradeForeignPlugins
347                 ;;
348         *)
349                 Usage
350 esac