summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconf213
-rwxr-xr-xtest.sh28
2 files changed, 241 insertions, 0 deletions
diff --git a/conf b/conf
new file mode 100755
index 0000000..450a65c
--- /dev/null
+++ b/conf
@@ -0,0 +1,213 @@
+#!/bin/bash
+##
+# conf -- manage configuration files
+# Copyright (C) 2020 Anastasis Grammenos
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+set -e
+
+CONF_VERSION="0.1.0"
+
+#################
+# CONFIGURATION #
+#################
+
+CONF_HOME="${CONF_HOME:-$HOME/.conf}"
+DEF_GROUP="default"
+HOME_SUB="/home"
+
+########
+# VARS #
+########
+
+PROGRAM_NAME=${0}
+MODE="normal"
+
+function err {
+ echo "${1}" >&2
+ exit 1
+}
+
+function warn {
+ echo "${1}" >&2
+}
+
+function echo_if_test {
+ if [ "$MODE" == "test" ]; then
+ echo "$@"
+ fi
+}
+
+function add {
+ GROUP=${DEF_GROUP}
+
+ for arg in "$@"; do
+ [[ "$arg" == "-t" ]] && MODE="test"
+ done
+
+ while [ $# -gt 0 ]; do
+ case ${1} in
+ -g)
+ GROUP="${2}"
+ shift
+ shift
+ ;;
+ -g*)
+ GROUP="${1/-g/}"
+ shift
+ ;;
+ -t)
+ shift
+ ;;
+ *)
+ [ ! -f "${1}" ] && err "${1} is not a file"
+ [ -L "${1}" ] && err "${1} is a symlink"
+ SRC="$(realpath "${1}")"
+ shift
+ DST="${CONF_HOME}/${GROUP}${SRC/${HOME}/${HOME_SUB}}" ## CHANGE
+ echo_if_test "${SRC} -> ${DST}"
+ [ "${MODE}" != "test" ] && mkdir -p "$(dirname "${DST}")" && mv "${SRC}" "${DST}" && ln -s "${DST}" "${SRC}"
+ esac
+ done
+}
+
+function list {
+ [ $# -lt 1 ] && for group in "${CONF_HOME}"/*; do
+ [[ -e "$group" ]] || break
+ _group="$(basename "$group")"
+ echo "${_group}:"
+ find "${group}" -type f | sed -e "s#^${group}${HOME_SUB}#|- ${HOME}#"
+ done && return 0
+
+ while getopts ":lg:Gh" OPT; do
+ case ${OPT} in
+ l) #l list paths
+ for group in "${CONF_HOME}"/*; do
+ [[ -e "$group" ]] || break
+ find "${group}" -type f | sed -e "s#${group}##" -e "s#^${HOME_SUB}#${HOME}#"
+ done
+ return 0
+ ;;
+ G) #l list groups
+ for group in "${CONF_HOME}"/*; do
+ basename "$group"
+ done
+ return 0
+ ;;
+ g) #l list paths in <group>
+ [ ! -d "${CONF_HOME}/${OPTARG}" ] && err "group ${OPTARG} doesn't exist"
+ find "${CONF_HOME}/${OPTARG}" -type f | sed -e "s#${CONF_HOME}/${OPTARG}${HOME_SUB}#${HOME}#"
+ return 0
+ ;;
+ h) #l print this help
+ grep ")\ #l" "${PROGRAM_NAME}" | sed -e 's/^[[:space:]]*/-/' -e 's:) \#l: :g'
+ return 0
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+ err "wrong list argument"
+}
+
+function search {
+ [ $# -ne 1 ] && err "search requires a term"
+ # grep -HR "$@" "${CONF_HOME}"
+ find "${CONF_HOME}" -type f -exec grep -H "${1}" {} \;
+}
+
+function edit {
+ declare -A configs
+
+ for group in "${CONF_HOME}"/*; do
+ [[ -e "$group" ]] || break
+ _group="$(basename "$group")"
+ while IFS= read -r -d '' file; do
+ configs["${_group}:$(basename "$file")"]="$file"
+ done < <(find "${CONF_HOME}/${_group}" -type f -print0)
+ done
+
+ matched=()
+ for c in "${!configs[@]}"; do
+ if [ "${c/:*/}" == "$1" ]; then
+ matched+=( "${configs[$c]}" )
+ fi
+ done
+ [ ${#matched[@]} -eq 1 ] && ${EDITOR} "${matched[0]}" && return 0
+ [ ${#matched[@]} -gt 1 ] && warn "Too many files, specify" && list -g "${1}" && return 1
+
+ matched=()
+ for c in "${!configs[@]}"; do
+ if [ "${c/*:/}" == "$1" ]; then
+ matched+=( "${configs[$c]}" )
+ fi
+ done
+ [ ${#matched[@]} -eq 1 ] && ${EDITOR} "${matched[0]}" && return 0
+ [ ${#matched[@]} -gt 1 ] && warn "Too many files, specify" && list -l | grep "${1}" && return 1
+
+ matched=()
+ for c in "${!configs[@]}"; do
+ if [ "${c}" == "$1" ]; then
+ ${EDITOR} "${configs[$c]}" && return 0
+ fi
+ done
+
+ echo "${1} - no match"
+ return 1
+}
+
+function relink {
+ echo Not implemented
+}
+
+function printhelp {
+ grep ")\ ##" "${PROGRAM_NAME}" | sed -e 's/^[[:space:]]*//' -e 's:) \##: :g'
+ exit 1
+}
+
+if [ $# -lt 1 ]
+then
+ printhelp
+fi
+
+case ${1} in
+ add | a) ## add a file
+ shift
+ add "$@"
+ ;;
+ list | ls | l) ## list managed files
+ shift
+ list "$@"
+ ;;
+ search | grep | s) ## grep managed files
+ shift
+ search "$@"
+ ;;
+ edit | e) ## edit managed files
+ shift
+ edit "$@"
+ ;;
+ relink) ## relink managed files
+ relink "$@"
+ ;;
+ version | --version | -v | -V)
+ echo "version $CONF_VERSION"
+ ;;
+ *)
+ printhelp
+ ;;
+esac
diff --git a/test.sh b/test.sh
new file mode 100755
index 0000000..6dc38e6
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+CONF=$(realpath conf)
+CONF_HOME=$(mktemp -d)
+export CONF_HOME
+
+conf1=$(mktemp)
+conf2=$(mktemp)
+conf3=$(mktemp)
+conf4=$(mktemp)
+conf5=$(mktemp)
+
+echo "test config 1" > "$conf1"
+echo "test config 2" > "$conf2"
+echo "test config 3" > "$conf3"
+echo "test config 4" > "$conf4"
+echo "test config 5" > "$conf5"
+
+$CONF add "$conf1"
+$CONF add -g conf "$conf2" "$conf3"
+$CONF add -g conf "$conf4"
+$CONF add -g other "$conf5"
+
+[ "$($CONF ls -l | wc -l)" != "5" ] && echo Test failed
+[ "$($CONF ls | wc -l)" != "8" ] && echo Test failed
+
+rm -rf "$conf1" "$conf2" "$conf3" "$conf4" "$conf5" "$CONF_HOME"
+echo PASS