-
Notifications
You must be signed in to change notification settings - Fork 1
/
env.sh
536 lines (435 loc) · 11.2 KB
/
env.sh
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
#!/bin/sh
################################################################################
# Personalized Shell Environment Manager #
# #
# This script is responsible for modifying the shell environment and for #
# providing the user an interface with which to control what options are #
# enabled. Some option scaffolding is also provided to provide a consistent #
# option development experience. #
################################################################################
# shellcheck disable=SC1090
# shellcheck disable=SC3043
################################################################################
# Internal #
################################################################################
###
# Reads the value of a configuration setting from a file.
#
# @param $1 The name of the setting.
#
# @stdout The value of the setting.
#
# @return 0|1 If the value was read, `0`. Otherwise, `1`.
##
__env_config_get()
{
local NAME="$1"
if [ -f "$__ENV_CONFIG/$NAME" ]; then
if ! cat "$__ENV_CONFIG/$NAME"; then
__env_err "env: could not read configuration setting"
return 1
fi
fi
}
###
# Sets the value of a configuration setting to a file.
#
# @param $1 The name of the setting.
# @param $2 The value of the setting.
#
# @return 0|1 If the value was set, `0`. Otherwise, `1`.
##
__env_config_set()
{
local FILE="$__ENV_CONFIG/$1"
local NAME="$1"
local VALUE="$2"
# Read value from STDIN.
if [ "$VALUE" = '-' ]; then
VALUE="$(cat -)"
fi
if [ "$VALUE" = '' ]; then
if [ -f "$FILE" ] && ! rm "$FILE"; then
__env_err "could not delete configuration setting"
return 1
fi
elif ! echo "$VALUE" > "$FILE"; then
__env_err "env: could not write configuration setting"
return 1
fi
}
###
# Prints to STDERR if DEBUG is `1`.
##
__env_debug()
{
if [ "$DEBUG" = '1' ]; then
echo "env [debug]:" "$@" >&2
fi
}
###
# Prints to STDERR.
#
# @param $@ The message to print.
##
__env_err()
{
echo env: "$@" >&2
}
###
# Adds an option to the enabled list.
#
# @param $1 The name of the option.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
__env_option_add()
{
__env_debug "adding option..."
local ENABLED
local NAME="$1"
if ! ENABLED="$(__env_config_get enabled)"; then
return 1
fi
if [ "$__ENV_PRIORITY" = '' ]; then
__env_debug "using default priority"
__ENV_PRIORITY=50
fi
if [ "$ENABLED" = '' ]; then
ENABLED="$__ENV_PRIORITY|$NAME"
else
ENABLED="$ENABLED
$__ENV_PRIORITY|$NAME"
ENABLED="$(echo "$ENABLED" | sort)"
fi
__env_debug "added $NAME, priority $__ENV_PRIORITY"
unset __ENV_PRIORITY
if ! __env_config_set enabled "$ENABLED"; then
return 1
fi
}
###
# Invokes the disabler for an option.
#
# @param $1 The name of the option.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
__env_option_disable()
{
__env_debug "disabling option..."
local DISABLER="__env_option_${1}_disable"
local FILE="$__ENV_DIR/options/$1.sh"
local NAME="$1"
if [ ! -f "$FILE" ]; then
__env_err "$NAME: option does not exist"
return 1
fi
if ! . "$FILE"; then
__env_err "$NAME: option could not be loaded"
return 1
fi
if type "$DISABLER" > /dev/null 2>&1; then
__env_debug "disabler defined"
if ! "$DISABLER"; then
return 1
fi
else
__env_debug "disabler not defined"
fi
unset "__env_option_${NAME}_activate"
unset "__env_option_${NAME}_enable"
unset "__env_option_${NAME}_disable"
}
###
# Checks if the option is disabled.
#
# @param $1 The name of the option.
#
# @return 0|1 If disabled, `0`. Otherwise, `1`.
##
__env_option_disabled()
{
if __env_option_enabled "$1"; then
return 1
fi
return 0
}
###
# Invokes the enabler for an option.
#
# @param $1 The name of the option.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
__env_option_enable()
{
__env_debug "enabling option..."
local ACTIVATOR="__env_option_${1}_activate"
local ENABLER="__env_option_${1}_enable"
local FILE="$__ENV_DIR/options/$1.sh"
local NAME="$1"
if [ ! -f "$FILE" ]; then
__env_err "$NAME: option does not exist"
return 1
fi
if ! . "$FILE"; then
__env_err "$NAME: option could not be loaded"
return 1
fi
if type "$ENABLER" > /dev/null 2>&1; then
__env_debug "enabler defined"
if ! "$ENABLER"; then
return 1
fi
else
__env_debug "enabler not defined"
fi
if ! type "$ACTIVATOR" > /dev/null 2>&1; then
__env_err "option does not have an activator"
return 1
fi
if ! "$ACTIVATOR"; then
__env_err "$NAME: option could not be activated"
return 1
fi
unset "__env_option_${NAME}_activate"
unset "__env_option_${NAME}_enable"
unset "__env_option_${NAME}_disable"
}
###
# Checks if an option is enabled.
#
# @param $1 The name of the option.
#
# @return 0|1 If enabled, `0`. Otherwise, `1`.
##
__env_option_enabled()
{
__env_debug "checking if enabled..."
local CONFIG="$__ENV_CONFIG/enabled"
if [ -f "$CONFIG" ]; then
if grep "|$1" "$CONFIG" > /dev/null; then
__env_debug "option is enabled"
return 0
fi
fi
__env_debug "option is not enabled"
return 1
}
###
# Removes an option from the enabled list.
#
# @param $1 The name of the option.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
__env_option_remove()
{
__env_debug "removing option..."
local ENABLED
local NAME="$1"
if ! ENABLED="$(__env_config_get enabled)"; then
return 1
fi
ENABLED="$(echo "$ENABLED" | grep -v "|$NAME")"
__env_debug "option removed"
if ! __env_config_set enabled "$ENABLED"; then
return 1
fi
}
################################################################################
# Interface #
################################################################################
###
# Disables an option.
#
# @param $1 The name of the option.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
option_disable()
{
__env_debug "option_disable()"
if __env_option_enabled "$1"; then
if __env_option_disable "$1"; then
if __env_option_remove "$1"; then
return 0
fi
fi
return 1
fi
}
###
# Enables an option.
#
# @param $1 The name of the option.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
option_enable()
{
__env_debug "option_enable()"
if __env_option_disabled "$1"; then
if __env_option_enable "$1"; then
if __env_option_add "$1"; then
return 0
fi
fi
return 1
fi
}
###
# Displays the help screen.
##
option_help()
{
__env_debug "option_help()"
cat - >&2 <<"HELP"
Usage: option [OPTION]
Manages shell personalization options.
OPTION
-e Enables an option.
-d Disables an option.
-h Displays this help message.
-l Lists available options.
HELP
}
###
# Lists all available options.
##
option_list()
{
__env_debug "option_list()"
local FILE
local NAME
echo "Available options:"
echo
find "$__ENV_DIR/options" -name '*.txt' | \
sort | \
while read -r FILE; do
NAME="$(basename "$FILE" .txt)"
if grep "|$NAME" "$__ENV_CONFIG/enabled" > /dev/null 2>&1; then
echo " (enabled)"
else
echo " (disabled)"
fi
cat "$FILE"
echo
done
}
###
# Provides the user with a way of customizing their environment.
#
# @param $@ The command arguments.
#
# @return 0|1 If successful, `0`. Otherwise, `1`.
##
option()
{
__env_debug arguments: "$@"
local OPTARG
local OPTIND
local OPTION
while getopts d:e:hl OPTION; do
__env_debug "option: $OPTION"
case "$OPTION" in
e) option_enable "$OPTARG";;
d) option_disable "$OPTARG";;
h) option_help;;
l) option_list;;
*) return 1;;
esac
done
}
################################################################################
# Initialize #
################################################################################
###
# Loads an enabled option.
#
# @param $1 The name of the option.
#
# @return 0|1 If successfully loaded, `0`. Otherwise, `1`.
##
__env_load()
{
local ACTIVATOR="__env_option_$1_activate"
local FILE="$__ENV_DIR/options/$1.sh"
local NAME="$1"
local STATUS=0
if [ ! -f "$FILE" ]; then
__env_err "$NAME: option does not exist"
fi
if ! . "$FILE"; then
__env_err "$NAME: option could not be loaded"
fi
if ! type "$ACTIVATOR" > /dev/null 2>&1; then
__env_err "$NAME: option does not have an activator"
fi
"$ACTIVATOR"
STATUS=$?
if [ $STATUS -ne 0 ]; then
__env_err "$NAME [$STATUS]: option could not be activated"
fi
unset "__env_option_${NAME}_activate"
unset "__env_option_${NAME}_enable"
unset "__env_option_${NAME}_disable"
}
###
# Initializes the environment.
##
__env_init()
{
# Configure the directory path to here.
__ENV_DIR="$1"
if [ "$__ENV_DIR" = '' ] && [ "$ENV_DIR" != '' ]; then
__ENV_DIR="$ENV_DIR"
fi
if [ "$__ENV_DIR" = '' ]; then
echo "env: no path set" >&2
return 1
fi
# Discover the configuration settings path.
if [ "$XDG_CONFIG_HOME" = '' ]; then
export __ENV_CONFIG="$HOME/.config/env"
else
export __ENV_CONFIG="$XDG_CONFIG_HOME/env"
fi
# Make sure the directory exists.
if [ ! -d "$__ENV_CONFIG" ]; then
if ! mkdir -p "$__ENV_CONFIG"; then
__env_err "could not create configuration directory"
return 1
fi
fi
# Load enabled options.
local ENABLED
local OPTION
if [ -f "$__ENV_CONFIG/enabled" ]; then
while read -r ENABLED; do
if [ "$ENABLED" != '' ]; then
OPTION="$(echo "$ENABLED" | cut -d\| -f2)"
if [ "$ALLOW" != '' ]; then
if echo "$ALLOW" | grep -F "+$OPTION" > /dev/null; then
__env_load "$OPTION"
else
__env_debug "$OPTION not allowed to be loaded"
fi
else
__env_load "$OPTION"
fi
fi
done < "$__ENV_CONFIG/enabled"
fi
unset __env_init
}
# Run the initializer.
__env_init "$1"
# Activate options in the wishlist.
if [ -f "$__ENV_CONFIG/wishlist" ]; then
cat "$__ENV_CONFIG/wishlist" | while read -r OPTION; do
option -e "$OPTION"
done
rm "$__ENV_CONFIG/wishlist"
fi