diff options
-rwxr-xr-x | conf | 213 | ||||
-rwxr-xr-x | test.sh | 28 |
2 files changed, 241 insertions, 0 deletions
@@ -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 @@ -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 |