From 189ba9507621a7cf56fadeab2eb4744d61b78d46 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Fri, 6 Nov 2020 14:24:10 -0800 Subject: [PATCH] add modules function to find and load modules refactored functions_list to assist with finding functions within a script file refactored prompt PS1 setup and added colors variables added block module to base which will write and edit a block of lines to any text file improve setup.sh, now can be reused for other shell repos to default source --- README.md | 38 +++++++++-- env/00-shell.env | 1 + env/colors.env | 24 +++++++ function/00-basic | 36 +++++++++- function/modules | 114 +++++++++++++++++++++++++++++++ misc/00-prompt | 54 +++++++++++++++ misc/prompt | 27 -------- misc/{xterm => xterm.off} | 0 modules/bind-mount/bind-mount.sh | 4 +- modules/editing/block/block.sh | 57 ++++++++++------ options | 3 +- setup.sh | 25 ++++--- 12 files changed, 311 insertions(+), 72 deletions(-) create mode 100644 env/colors.env create mode 100644 function/modules create mode 100644 misc/00-prompt delete mode 100644 misc/prompt rename misc/{xterm => xterm.off} (100%) diff --git a/README.md b/README.md index 01be26e..8f9023a 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,19 @@ -# Bash Shell Setup Repo -A better way to keep organized and share interactive (.bashrc) environment, aliases, functions, modules +# Bash Shell Organizer +A better way to keep your shell setup organized, clean, and useful + + interactive (.bashrc) environment, aliases, functions, modules ## Install Clone to a directory -`git clone https://git.kebler.net/bashrc ` e.g. /opt/shell +`git clone https://git.kebler.net/bashrc ` suggestion: /opt/shell/base now edit your `~/.bashrc` with nano or other available editor add this ``` +# BASH_SHELL is a common parent directory that should be set in /etc/bash.bashrc export BASH_SHELL_REPO=/setup. source $BASH_SHELL_REPO/setup.sh ``` @@ -25,10 +28,33 @@ The sourced files in this repo should be NOT be user/machine/network specific if you include any of these environment variables all files in there directories will be sourced where -export BASH_SHELL_USER= # will be in home/ -export BASH_SHELL_MACHINE= #parent directory e.g. opt/shell/machine -export BASH_SHELL_NETWORK= #parent directory e.g. opt/shell/network +# unless below specific directories are set +# shell files are sourced in this order +# sourced via /etc/bash.bashrc so for all machine users +# $BASH_SHELL_BASE # this MUST be set in /etc/bash.bashrc +# $BASH_SHELL_NETWORK/all +# $BASH_SHELL_NETWORK/$NETWORKNAME +# $BASH_SHELL_HOST/all +# $BASH_SHELL_HOST/ +# sourced via $HOME/.bashrc +# $HOME/shell or $HOME/BASH_SHELL_USER +# within each of those directories if setup.sh exits it will be run +# otherwise files will be sourced exactly like in the base + +# identify a network name that this host resides on +# like hostname but for the LAN network +# if unset then only /all will be sourced +export NETWORKNAME=238 +# will use $BASH_SHELL_NETWORK/$NETWORKNAME under this directory unless specifically set +export BASH_SHELL_NETWORK=$BASH_SHELL/network + +# will use $BASH_SHELL_HOST/ unless specifically set +export BASH_SHELL_HOST=$BASH_SHELL/host + +# by default SHELL sources will be looked for under $HOME/bash/shell +# but can be user set below to $HOME/$BASH_SHELL_USER +# export BASH_SHELL_USER= if there is a script setup.sh in the root of these directoies it will be run. If not then all files no matter how deep will be sourced in alpha order order. For those diff --git a/env/00-shell.env b/env/00-shell.env index 093bf4a..773c84f 100644 --- a/env/00-shell.env +++ b/env/00-shell.env @@ -4,6 +4,7 @@ # shell files are sourced in this order # sourced via /etc/bash.bashrc so for all machine users # $BASH_SHELL_BASE # this MUST be set in /etc/bash.bashrc + # $BASH_SHELL_NETWORK/all # $BASH_SHELL_NETWORK/$NETWORKNAME # $BASH_SHELL_HOST/all diff --git a/env/colors.env b/env/colors.env new file mode 100644 index 0000000..b224f68 --- /dev/null +++ b/env/colors.env @@ -0,0 +1,24 @@ +#!/bin/bash +export TERM=xterm-color +export GREP_OPTIONS='--color=auto' GREP_COLOR='1;32' +export CLICOLOR=1 +export LSCOLORS=ExFxCxDxBxegedabagacad + + +export COLOR_NC='\e[0m' # No Color +export COLOR_BLACK='\e[0;30m' +export COLOR_GRAY='\e[1;30m' +export COLOR_RED='\e[0;31m' +export COLOR_LIGHT_RED='\e[1;31m' +export COLOR_GREEN='\e[0;32m' +export COLOR_LIGHT_GREEN='\e[1;32m' +export COLOR_BROWN='\e[0;33m' +export COLOR_YELLOW='\e[1;33m' +export COLOR_BLUE='\e[0;34m' +export COLOR_LIGHT_BLUE='\e[1;34m' +export COLOR_PURPLE='\e[0;35m' +export COLOR_LIGHT_PURPLE='\e[1;35m' +export COLOR_CYAN='\e[0;36m' +export COLOR_LIGHT_CYAN='\e[1;36m' +export COLOR_LIGHT_GRAY='\e[0;37m' +export COLOR_WHITE='\e[1;37m' diff --git a/function/00-basic b/function/00-basic index bd863af..e25951c 100644 --- a/function/00-basic +++ b/function/00-basic @@ -4,11 +4,28 @@ ##-- functions which may be used by any of the alias file --# function function_list() { + if [ $1 ]; then + local STR + local func + declare -a FUNCS + STR=$(grep '() {\|(){\|function' $1) + readarray -t LIST <<<"$STR" + for func in "${LIST[@]}" + do + if [[ ! $func =~ ^# ]]; then + func=${func#function } + func=${func%()?( ){} + [[ ! $func =~ ^_ ]] && FUNCS+=($func) + fi + done + echo "${FUNCS[@]}" + else echo echo -e "\033[1;4;32m""Functions:""\033[0;34m" declare -F | grep -v "declare -f\s_" | awk {'print $3'} echo echo -e "\033[0m" + fi } function alias_list() { @@ -22,10 +39,23 @@ function alias_list() { rsynchc() { rsync --help | grep "\-$1"; } alias rsynch="rsynchc" -change-ext() { -shopt -s globstar -rename -n 's/.'+$1+'/.'+$2+'/' ** +get_shopt () { + echo $([ "$(shopt -p $1 | grep '\-s')" ] && echo on || echo off) } + +change-ext() { +local depth +local d +d=${3:-0} +let d+=1 +[ $d -lt 1 ] && depth="" || depth=" -maxdepth $d " +find . $depth -name '*.'$1 -exec rename -n 's/\.'$1'/.'$2'/' \{} \; +read -p "do REALLY want to change the extensions? " -n 1 -r +echo +[[ ! $REPLY =~ ^[Yy]$ ]] && return 1 +find . $depth -name '*.'$1 -exec rename 's/\.'$1'/.'$2'/' \{} \; +} + alias chext=change-ext # find in any file diff --git a/function/modules b/function/modules new file mode 100644 index 0000000..c2a8229 --- /dev/null +++ b/function/modules @@ -0,0 +1,114 @@ +#!/bin/bash + +module_confirm () { +local FILE +local DIR +local NAME +DIR=$1 +NAME=$2 +# echo finding $NAME in $DIR +FILE="$(find ${DIR} -type f -name "${NAME}.mod" -o -name "${NAME}".sh)" +# echo files found $FILE +COUNT=0 +if [ "$FILE" ]; then + COUNT=$(echo $FILE | xargs -n 1 | wc -l) +fi +# echo Number: $COUNT +if [ $COUNT -gt 1 ]; then + echo two or more modules of same name found, aborting + echo $FILE | xargs -n 1 + return 1 +fi +[ $COUNT == 1 ] && echo $FILE && return 0 +return 1 +} + +# if succesfull returns the path +function module_find () { + +[ ! $1 ] && echo "no module specified" && return 1 + +local MDIRS +local MDIR +local DIRS +local MODULE=$1 +DIRS=( \ +$([ $BASH_SHELL_USER ] && echo $HOME/$BASH_SHELL_USER || echo $HOME/bash/shell) \ +$BASH_SHELL_HOST/$(hostname) +$BASH_SHELL_HOST/all \ +$BASH_SHELL_NETWORK/$NETWORKNAME \ +$BASH_SHELL_NETWORK/all \ +$BASH_SHELL_BASE \ +) + +# echo ${DIRS[@]} + +MDIRS=() +j=0 +cnt=${#DIRS[@]} +for ((i=0;i /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' +} + +function fancy_prompt () { + + # if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + + function c () { + local color + name=COLOR_$1 + color=${!name} + echo '\['$color'\]' + } + +case $TERM in + xterm*|rxvt*) + # local TITLEBAR='\[\033]0;\u ${NEW_PWD}\007\]' + local PARENTBASE='${PWD#"${PWD%/*/*}/"}' + ;; + *) + local PARENTBASE='' + # local TITLEBAR="" + ;; + esac + +local UC=WHITE # user's color +[ $UID -eq "0" ] && UC=RED # root's color + +# PS1="$PARENTBASE\[${UC}\]\u@\h: \[${COLOR_LIGHT_GREEN}\]→\[${COLOR_NC}\] " + +local user +local machine +local dir +local branch +local promptc +user="$(c $UC)\u$(c GREY)@$(c NC)" +machine="$(c CYAN)\h$(c GREY):$(c NC)" +dir="$(c YELLOW)[${PARENTBASE}]$(c NC)" +branch=$(c LIGHT_BLUE)'$(parse_git_branch)'$(c NC) +promptc=$(c GREEN)' $ '$(c NC) + +PS1=$(echo "$user$machine$dir$branch$promptc") +# echo $PS1 +} + +# fancy prompt is on by default comment out to disable default +fancy_prompt diff --git a/misc/prompt b/misc/prompt deleted file mode 100644 index 6da9535..0000000 --- a/misc/prompt +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# uncomment for a colored prompt, if the terminal has the capability; turned -# off by default to not distract the user: the focus in a terminal window -# should be on the output of commands, not on the prompt -#force_color_prompt=yes - -if [ -n "$force_color_prompt" ]; then - if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then - # We have color support; assume it's compliant with Ecma-48 - # (ISO/IEC-6429). (Lack of such support is extremely rare, and such - # a case would tend to support setf rather than setaf.) - color_prompt=yes - else - color_prompt= - fi -fi - - -# use http://bashrcgenerator.com/ -PARENTBASE='${PWD#"${PWD%/*/*}/"}' -PS1="\[\033[38;5;11m\]\u\[$(tput sgr0)\]@\h:\[$(tput sgr0)\]\[\033[38;5;6m\][\[$(tput sgr0)\]\[\033[38;5;14m\]${PARENTBASE}\[$(tput sgr0)\]\[\033[38;5;6m\]]\[$(tput sgr0)\]\[$(tput sgr0)\]" - -parse_git_branch() { - git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' -} -PS1="$PS1\[\033[00m\]\$(parse_git_branch)\$ " diff --git a/misc/xterm b/misc/xterm.off similarity index 100% rename from misc/xterm rename to misc/xterm.off diff --git a/modules/bind-mount/bind-mount.sh b/modules/bind-mount/bind-mount.sh index fddd6c3..ad163fe 100755 --- a/modules/bind-mount/bind-mount.sh +++ b/modules/bind-mount/bind-mount.sh @@ -1,6 +1,6 @@ #!/bin/bash # must have fuser and bindfs installed -function bmount(){ +function bmount () { if [ "$1" == "-mp" ]; then MOUNTED=$(mountpoint "$2" | grep not) if [ -z "$MOUNTED" ]; then @@ -17,7 +17,7 @@ function bmount(){ fi } -function bumount(){ +bumount () { echo "removing bind mount at $1" notify-send "removing bind mount at ${1}" --icon=dialog-information -t 2000 fusermount -u "$1" diff --git a/modules/editing/block/block.sh b/modules/editing/block/block.sh index bc8b52b..bc3767b 100755 --- a/modules/editing/block/block.sh +++ b/modules/editing/block/block.sh @@ -6,7 +6,7 @@ BLOCK_COMMENT_CHAR="#" # a comment added before the block BLOCK_DESCRIPTION="" -function __update () { +function __update_block () { if [ ! -z "$BLOCK_FILE" ]; then touch $BLOCK_FILE tail -c1 $BLOCK_FILE | read -r _ || echo >> $BLOCK_FILE @@ -19,10 +19,11 @@ function __update () { } -__update +# set block to defaults +__update_block # echo -e "default block template follows use: block-set before block-add to change>\n" $BLOCK -function set-block () { +function set_block () { declare OPTION declare OPTARG @@ -52,7 +53,7 @@ done shift $(( OPTIND - 1 )) -__update +__update_block echo -e "new block template follows use: block-add >\n" $BLOCK echo ---- echo $([ -e "$BLOCK_FILE" ] || echo "Warning: No output file set yet, use block-set -f " && echo "block will be placed in $BLOCK_FILE") @@ -60,7 +61,7 @@ __update } -function add-block () { +function add_block () { # only add if it doesn't exist, existance is only based on block begin local ADD ADD=$(echo "${BLOCK}" | sed 's/\//\\\//g') @@ -68,14 +69,29 @@ if [ -e "$BLOCK_FILE" ]; then sed -n '/^[ \t]*'"${BLOCK_BEGIN}"'/{q50}' "${BLOCK_FILE}" [ $? == 50 ] && return WHERE=${1-${BLOCK_BEGIN}} # default is end -echo Where $WHERE +# echo Where $WHERE sed -i '/'"${WHERE}"'/{s/.*/&\n'"${ADD}"'/;h};${x;/^$/{s//'"$ADD"'/;H};x}' "${BLOCK_FILE}" else - echo "no file set in which to add block, use: set-block -f " + echo "no file set in which to add block, use: ${RED_COLOR}set-block -f " fi } -modify-block () { +get_block () { +if [[ $1 =~ -?r(aw)? ]]; then + echo $BLOCK +else + local block + block=${BLOCK##'\n'}'\n' + printf "$block" +fi +} + +get_block_file () { + [ $BLOCK_FILE ] && echo ${BLOCK_FILE} + [[ $1 = -v ]] && echo "no output file set, use set_block -f " +} + +modify_block () { sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { /'"${BLOCK_BEGIN}"'/b /'"${BLOCK_END}"'/b @@ -83,20 +99,21 @@ modify-block () { }' "${BLOCK_FILE}" } -remove-block () { - [ -z "$BLOCK_DESCRIPTION" ] || sed -ni '/'"${BLOCK_BEGIN}"'/{x;d;};1h;1!{x;p;};${x;p;}' "${BLOCK_FILE}" - remove-block-leading +block_remove_leading () { + printf "%s\n" "$(tac $BLOCK_FILE \ + | sed '/'"${BLOCK_BEGIN}"'/,/^./{ /^[ \t]*$/d}' | tac)" > $BLOCK_FILE +} + +remove_block () { + [[ "$BLOCK_DESCRIPTION" ]] || sed -ni '/'"${BLOCK_BEGIN}"'/{x;d;};1h;1!{x;p;};${x;p;}' "${BLOCK_FILE}" + block_remove_leading sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { d }' "${BLOCK_FILE}" } -remove-block-leading () { - printf "%s\n" "$(tac $BLOCK_FILE \ - | sed '/'"${BLOCK_BEGIN}"'/,/^./{ /^[ \t]*$/d}' | tac)" > $BLOCK_FILE -} -block-remove-content () { +block_remove_content () { sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { /'"${BLOCK_BEGIN}"'/b /'"${BLOCK_END}"'/b @@ -105,7 +122,7 @@ block-remove-content () { } -block-add-line () { +block_add_line () { # echo argument count $#, $1, $2, $3 local ADD ADD="/^${BLOCK_BEGIN}/a\\${1}" @@ -126,19 +143,19 @@ sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { }' "${BLOCK_FILE}" } -block-remove-line () { +block_remove_line () { sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { /'"${1}"'/d }' "${BLOCK_FILE}" } -block-change-line () { +block_change_line () { sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { /'"${1}"'/c\'"${2}"' }' "${BLOCK_FILE}" } -block-modify-line () { +block_modify_line () { sed -i '/^'"${BLOCK_BEGIN}"'/,/^'"${BLOCK_END}"$'/ { /'"${BLOCK_BEGIN}"'/b /'"${BLOCK_END}"'/b diff --git a/options b/options index 9a39225..685bf4d 100644 --- a/options +++ b/options @@ -7,7 +7,8 @@ shopt -s checkwinsize # If set, the pattern "**" used in a pathname expansion context will # match all files and zero or more directories and subdirectories. #shopt -s globstar - +# if expanding aliases in all non-interactive shell is desired then uncomment +shopt -s expand_aliases # enable programmable completion features (you don't need to enable # if it's already enabled in /etc/bash.bashrc and /etc/profile # sources /etc/bash.bashrc). diff --git a/setup.sh b/setup.sh index 8bb8e2d..8b7e5c1 100755 --- a/setup.sh +++ b/setup.sh @@ -15,17 +15,18 @@ else local DSUBDIRS DIR=${1:-$BASH_SHELL_BASE} - echo $DIR + # echo soucring directory $DIR if [ -d "$DIR" ]; then - if [ "$DIR" = "$BASH_SHELL_BASE" ] && [ $BASH_SHELL_BASE_SOURCED ]; then + if [ "$DIR" = "$BASH_SHELL_BASE" ] && [ "$BASH_SHELL_BASE_SOURCED" = "true" ]; then if [ -v PS1 ]; then echo base directory already sourced read -p "do you want to re-source the base (not recommended)? " -n 1 -r echo [[ ! $REPLY =~ ^[Yy]$ ]] && return 1 - else - return 1 + # else + # echo non-interactive shell + # return 1 fi fi @@ -43,21 +44,19 @@ else for SUBDIR in "${SUBDIRS[@]}" do if [ -e "$DIR/$SUBDIR" ]; then - echo processing subdirectory $DIR/$SUBDIR + # echo processing subdirectory $DIR/$SUBDIR # must quote all globs to avoid bash glob expansion which is likely on source_dir -p "archive" -x '"*.off" "*.md"' -d 0 $DIR/$SUBDIR - else - echo no subdirectory $DIR/$SUBDIR to process, ignorning + # else + # echo no subdirectory $DIR/$SUBDIR to process, ignorning fi done fi - echo "done sourcing directory $DIR" - else - echo $DIR does not exist nothing to source + # echo "done sourcing directory $DIR" + # else + # echo $DIR does not exist nothing to source fi - - } # process the base directory by default @@ -73,6 +72,6 @@ shell_process_directory "$BASH_SHELL_HOST/$(hostname)" # process user # Note: $HOME/shell or $HOME/BASH_SHELL_USER are sourced via $HOME/.bashrc -echo $(envg BASH) | xargs -n 1 +# echo $(envg BASH) | xargs -n 1 fi