commit b764aa522417b9a44d35fe34f83bee4e8521e201
parent 068499979c701e7c847b205fe5c824d560208b86
Author: Alex Balgavy <a.balgavy@gmail.com>
Date: Mon, 4 Nov 2019 12:31:46 -0500
conf: multi-level mappings and other bells & whistles
Former-commit-id: 3815c4ee203e304531281eaca84bcee4c97e12b5
Diffstat:
2 files changed, 48 insertions(+), 13 deletions(-)
diff --git a/dot.map b/dot.map
@@ -1,3 +1,5 @@
+# Mappings for your dotfiles
+
# The format of this file is:
# - lines starting with '#' are comments
# - whitespace is ignored, except inside a mapping definition
@@ -20,6 +22,8 @@
# vim/autoload/script1.vim => ~/.vim/autoload/script1.vim
# vim/autoload/script2.vim => ~/.vim/autoload/script2.vim
# tmux/tmux.conf => ~/.tmux.conf
+#
+# (the arrows show the symbolic links)
# When linking/unlinking, names don't have to be complete.
# You can also just provide the name of the top directory, conf will figure out the rest.
diff --git a/scripts/conf b/scripts/conf
@@ -1,6 +1,5 @@
#!/usr/bin/env bash
-# TODO: handle multiple nesting levels, convert to posix shell
-
+# TODO: convert to posix shell
# Set the dir for your dotfiles, mine comes from the environment
DOTFILES="${DOTFILES}"
@@ -11,11 +10,19 @@ die() {
echo "$1" >&2
exit 1
}
+get_bash_version() {
+ echo "${BASH_VERSION}" | cut -d'.' -f1
+}
+
+[ "$(get_bash_version)" -ge 4 ] || die "Requires Bash >= 4"
# Don't want $DOTFILES expansion in the message
# shellcheck disable=SC2016
[ -z "${DOTFILES}" ] && die '$DOTFILES variable not set.'
cd "${DOTFILES}" || die "Can't read ${DOTFILES}"
+[ -f "${mapfile}" ] || die "Mapfile ${mapfile} does not exist in $(pwd)"
+
+
do_link() {
if [ -e "$2" ]; then
@@ -27,26 +34,25 @@ do_link() {
mv "$2" "$2.bak"
fi
fi
+ mkdir -vp "${2%/*}"
ln -svf "$(pwd)/$1" "$2"
}
parse_mapfile() {
- if [ ! -f "$1" ]; then
- die "Mapfile $1 does not exist."
- fi
-
local nestdir=""
local lineno=1
+ local nestlevel=0
homedir="$(echo -n "${HOME}" | tr -d '\n\r')"
while read -r map; do
if [ -n "${map}" ] && [[ ! "${map}" == "#"* ]]; then
- IFS=" " read -r -a mapping <<< "$(echo -n "${map}" | sed -e 's/^ *- /-/' -e "s:~:${homedir}:" | awk -F ': ' '{ print $1 " " $2 }')"
+ IFS=" " read -r -a mapping <<< "$(echo -n "${map}" | sed -e 's/^ *-* /-/' -e "s:~:${homedir}:" | awk -F ': ' '{ print $1 " " $2 }')"
# Top level items
if [[ ! "${mapping[0]}" == "-"* ]]; then
nestdir=""
+ nestlevel=0
if [ -z "${mapping[1]}" ]; then
# nestdir
nestdir="${mapping[0]/://}"
@@ -58,10 +64,27 @@ parse_mapfile() {
mappings["${nestdir}${mapping[0]}"]="${mapping[1]}"
fi
else
- if [ ! -e "${nestdir}${mapping[0]/-/}" ]; then
- die "error in mapfile: ${nestdir}${mapping[0]/-/} does not exist (line ${lineno})"
+ levels="$(count_nestlevels "${mapping[0]}")"
+ pth="$(echo "${mapping[0]}" | sed -e 's/^-*//g' -e 's/://')"
+ if [ "${levels}" -lt "${nestlevel}" ]; then
+ while [ "${levels}" -lt "${nestlevel}" ]; do
+ nestdir="${nestdir%/*/}/"
+ ((nestlevel--))
+ done
+ [ "${nestdir}" = "/" ] && nestdir=""
+ elif [ "${levels}" -gt "${nestlevel}" ]; then
+ while [ "${levels}" -gt "${nestlevel}" ]; do
+ ((nestlevel++))
+ done
+ fi
+ if [ -z "${mapping[1]}" ]; then
+ nestdir="${nestdir}${pth}/"
+ else
+ if [ ! -e "${nestdir}${mapping[0]/-/}" ]; then
+ die "error in mapfile: ${nestdir}${pth} does not exist (line ${lineno})"
+ fi
+ mappings["${nestdir}${pth}"]="${mapping[1]}"
fi
- mappings["${nestdir}${mapping[0]/-/}"]="${mapping[1]}"
fi
fi
((lineno++))
@@ -111,9 +134,15 @@ unlink_specific(){
fi
}
list_mappings() {
+ mapstr=""
for f in "${!mappings[@]}"; do
- echo "${f} => ${mappings[${f}]}";
+ mapstr="${mapstr}${f} => ${mappings[${f}]}\n";
done
+
+ echo -e "${mapstr}" | sort
+}
+count_nestlevels() {
+ echo -n "$1" | sed 's/^\([-]*\).*/\1/' | tr -d '\n' | wc -m | tr -d ' '
}
declare -A mappings
@@ -125,6 +154,7 @@ while (( "$#" )); do
case "$1" in
-l|--list)
parse_mapfile "./${mapfile}"
+ echo "Mappings:"
list_mappings
exit 0
;;
@@ -148,6 +178,7 @@ while (( "$#" )); do
-e|--edit)
# $EDITOR is an environment variable
# shellcheck disable=SC2154
+ echo "Opening ${mapfile} with ${EDITOR}"
"${EDITOR}" "${DOTFILES}/${mapfile}"
exit 0
;;
@@ -192,7 +223,7 @@ esac
parse_mapfile "./${mapfile}"
if [ "${link_mode}" -eq 1 ]; then
if [ $# -eq 0 ]; then
- read -srp "Link all dotfiles?" -n 1 -s conf
+ read -srp "Link all dotfiles? [Y/n]" -n 1 -s conf
case "${conf}" in
Y|y)
echo
@@ -208,7 +239,7 @@ if [ "${link_mode}" -eq 1 ]; then
fi
elif [ "${unlink_mode}" -eq 1 ]; then
if [ $# -eq 0 ]; then
- read -srp "Unlink all dotfiles?" -n 1 -s conf
+ read -srp "Unlink all dotfiles? [Y/n]" -n 1 -s conf
case "${conf}" in
Y|y)
echo