-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathncm
More file actions
executable file
·273 lines (235 loc) · 7.28 KB
/
ncm
File metadata and controls
executable file
·273 lines (235 loc) · 7.28 KB
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
#!/usr/bin/env bash
#
# Neovim Config Manager
#
# Author: @trimclain
# License: MIT
# shellcheck disable=SC2155,SC2164
# Disabled:
# "Declare and assign separately to avoid masking return values":
# https://www.shellcheck.net/wiki/SC2155
# "Use 'pushd ... || exit' or 'pushd ... || exit' in case pushd fails":
# https://www.shellcheck.net/wiki/SC2164
readonly VERSION="v0.1.0"
readonly CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}"
readonly NCM_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/ncm"
# TODO: implement
# readonly LAST_USED_CONFIG="$NCM_DIR/recent"
readonly INSTALLED_CONFIGS_DB="$NCM_DIR/configlist"
readonly BLUE="\033[1;34m"
readonly GREEN="\033[1;32m"
readonly RED="\e[1;31m"
readonly RESET="\033[0m"
info() {
printf "%b\n" "$1"
}
confirm() {
printf "${GREEN}%b${RESET}\n" "$1"
}
alert() {
printf "${RED}%b${RESET}\n" "$1"
}
error() {
alert "$1" >&2
exit 1
}
ensure_installed() {
if ! command -v "$1" > /dev/null; then
error "Dependency $1 is not installed on your system."
fi
}
display_help() {
echo "Usage: ncm [command] [configname]
COMMANDS:
h, help Show this help message
v, version Print current ncm version
a, add Add new config (dir or url)
u, use Start neovim with a config
d, del Delete config
l, list List installed configs
update Update installed configs
uninstall Remove installed configs"
}
print_configs() {
if [[ ! -s $INSTALLED_CONFIGS_DB ]]; then
info "Database is empty"
else
info "Installed Neovim Configs:\n"
cat "$INSTALLED_CONFIGS_DB"
fi
}
is_url() {
if [[ "$1" == "http://"* || "$1" == "https://"* ]]; then
return 0
else
return 1
fi
}
add_config() {
[[ -z $1 ]] && error "No config given"
if ! is_url "$1" && [[ ! -d "$1" ]]; then
error "$1 isn't a url or a directory"
fi
local confname
if is_url "$1"; then
# https://github.com/LazyVim/starter -> LazyVim
confname=$(echo "$1" | sed -E 's|https?://[^/]+/([^/]+).*|\1|')
elif [[ -d "$1" ]]; then
confname=$(basename "$1")
fi
if grep -qx "$confname" "$INSTALLED_CONFIGS_DB"; then
error "Config $confname is already in the database"
fi
# config needs to be in $CONFIG_DIR for $NVIM_APPNAME to work
if [[ ! -d "$CONFIG_DIR/$confname" ]]; then
echo -n "Installing $1 ... "
if is_url "$1"; then
if git clone --depth 1 "$1" "$CONFIG_DIR/$confname" &> /dev/null; then
confirm "Done"
else
echo -e "\e[1A\e[K❌ Failed to clone $1"
exit 1
fi
elif [[ -d "$1" ]]; then
cp -r "$1" "$CONFIG_DIR/$confname" && confirm "✅ Done"
fi
fi
echo -n "Adding $confname to the database... "
echo "$confname" >> "$INSTALLED_CONFIGS_DB"
confirm "Done"
}
##################################################
# Delete Neovim config with left-over directories
# and remove it from the list
# Globals:
# CONFIG_DIR
# INSTALLED_CONFIGS_DB
# Arguments:
# $1: config name
##################################################
delete_nvim_config() {
local data_paths=(
"$CONFIG_DIR/$1"
"${XDG_DATA_HOME:-$HOME/.local/share}/$1"
"${XDG_STATE_HOME:-$HOME/.local/state}/$1"
"${XDG_CACHE_HOME:-$HOME/.cache}/$1"
)
for dir in "${data_paths[@]}"; do
echo -n "Deleting $dir... "
rm -rf "$dir"
confirm "Done"
done
echo -n "Deleting $1 from the list... "
sed -i "/$1/d" "$INSTALLED_CONFIGS_DB"
confirm "Done"
}
remove_installed_configs() {
if [[ ! -s $INSTALLED_CONFIGS_DB ]]; then
error "Neovim configs database is empty"
fi
# Prompt for confirmation before deletion
read -p "Are you sure you want to delete ALL Neovim Configs installed with ncm? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborting..."
return
fi
local existing_lines=()
local forgotten_lines=()
while IFS= read -r line; do
if [ -d "$CONFIG_DIR/$line" ]; then
existing_lines+=("$line")
else
forgotten_lines+=("$line")
fi
done < "$INSTALLED_CONFIGS_DB"
for line in "${existing_lines[@]}"; do
delete_nvim_config "$line"
done
for line in "${forgotten_lines[@]}"; do
alert "❕ Warning: '$line' does not exist. In future use 'ncm del' to delete configs."
sed -i "/$line/d" "$INSTALLED_CONFIGS_DB"
done
}
##################################################
# Run Neovim with given config
# Arguments:
# $1: config name
##################################################
run_nvim_with_config() {
NVIM_APPNAME=$1 nvim
}
use_or_delete_config() {
if [[ ! -s $INSTALLED_CONFIGS_DB ]]; then
error "Neovim configs database is empty"
fi
if [[ -n $1 ]] && ! grep -qx "$1" "$INSTALLED_CONFIGS_DB"; then
# TODO: accept a filename
error "Config $1 is not in the database"
fi
local chosen_config
# if I trust my checks in add_config the second condition is not needed
if [[ -n $1 ]] && [[ -d ~/.config/$1 ]]; then
chosen_config="$1"
else
chosen_config=$(
fzf \
--cycle \
--bind 'tab:down,btab:up' \
--prompt "Use: " \
--height=25% \
--layout=reverse \
--border \
< "$INSTALLED_CONFIGS_DB"
)
fi
if [[ -n $chosen_config ]]; then
if [[ $2 == "--use" ]]; then
# TODO: save chosen config to $LAST_USED_CONFIG
run_nvim_with_config "$chosen_config"
elif [[ $2 == "--delete" ]]; then
delete_nvim_config "$chosen_config"
else
error "INTERNAL: you messed up"
fi
fi
}
choose_and_delete_config() {
use_or_delete_config "$1" --delete
}
choose_and_use_config() {
use_or_delete_config "$1" --use
}
update_installed_configs() {
# || part ensures the loop processes the last line,
# even if it doesn't end with a newline
while IFS="" read -r config_name || [ -n "$config_name" ]; do
local config_path="$HOME/.config/$config_name"
if git -C "$config_path" rev-parse --is-inside-work-tree &> /dev/null; then
echo -n -e "${BLUE}Updating $config_name config... ${RESET}"
git -C "$config_path" pull &> /dev/null
confirm "Done"
fi
done < "$INSTALLED_CONFIGS_DB"
}
main() {
ensure_installed nvim
ensure_installed fzf
mkdir -p "$CONFIG_DIR"
mkdir -p "$NCM_DIR"
[[ -f $INSTALLED_CONFIGS_DB ]] || touch "$INSTALLED_CONFIGS_DB"
local cmd="$1"
case $cmd in
"help" | "h" | "--help" | "-h") display_help && exit 0 ;;
"version" | "v" | "--version" | "-v" | "-V") echo "ncm $VERSION" && exit 0 ;;
"add" | "a") add_config "$2" && exit 0 ;;
"del" | "d" | "rm") choose_and_delete_config "$2" && exit 0 ;;
"use" | "u") choose_and_use_config "$2" && exit 0 ;;
"list" | "l" | "ls") print_configs && exit 0 ;;
"update") update_installed_configs && exit 0 ;;
"uninstall") remove_installed_configs && exit 0 ;;
"") choose_and_use_config && exit 0 ;;
*) error "Unknown command: $cmd" ;;
esac
}
main "$@"