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
master
David Kebler 2020-11-06 14:24:10 -08:00
parent 8d8ade7810
commit 189ba95076
12 changed files with 311 additions and 72 deletions

View File

@ -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 <repo path>` e.g. /opt/shell
`git clone https://git.kebler.net/bashrc <repo path>` 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=<repo path>/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=<path> # will be in home/<USER>
export BASH_SHELL_MACHINE=<path> #parent directory e.g. opt/shell/machine
export BASH_SHELL_NETWORK=<path> #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/<hostname>
# 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/<hostname> 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=<some directory under $HOME>
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

1
env/00-shell.env vendored
View File

@ -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

24
env/colors.env vendored Normal file
View File

@ -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'

View File

@ -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

114
function/modules Normal file
View File

@ -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<cnt;i++)); do
DIR="${DIRS[i]}/modules"
[ -d $DIR ] && MDIRS[j]=$DIR && j+=1
done
[ $MODULE_DIRS ] && MDIRS=("$MODULE_DIRS" "${MDIRS[@]}")
# echo Module Directories ${MDIRS[@]}
for MDIR in "${MDIRS[@]}"
do
# echo mdir $MDIR name $MODULE
RES=$(module_confirm "$MDIR" "$MODULE")
[ $? -eq 0 ] && echo $RES && return 0
done
return 1
}
module_load () {
[ ! $1 ] && echo "no module specified" && return 1
local FILE
FILE=$(module_find $1)
[ $? -ne 0 ] && echo no module $1 found && return 1
# source $FILE "$0"
source $FILE
echo $FILE
return 0
}
module_loaded () {
[ ! $1 ] && echo "no module specified" && return 1
local func
local ret
local file
ret=0
# function_list | grep module
file=$(module_find $1)
[ ! $file ] && echo no module $1 found && return 1
# echo "$(function_list $file)"
for func in $(function_list $file)
do
[ ! $(function_list | grep $func) ] && echo "$func not loaded" && ret=1 || echo "$func loaded"
done
[ $ret = 0 ] && echo all functions loaded
return $ret
}
function test_modules {
RED='\033[0;31m'
NC='\033[0m' # No Color
echo module to test: $1
echo --------------------
echo -e "testing: ${RED}module_find${NC}"
FILE=$(module_find $1)
[ $? -ne 0 ] && echo no module $1 found && return 1
echo module $FILE found
# . $FILE
echo ---------------
echo -e "testing: ${RED}module_load${NC}"
module_load $1
[ $? -ne 0 ] && echo no module $1 found && return 1
echo loaded module $1
echo ----------------------
echo -e "testing: ${RED}module_loaded${NC}"
module_loaded $1
}

54
misc/00-prompt Normal file
View File

@ -0,0 +1,54 @@
#!/bin/bash
# see
# used http://bashrcgenerator.com/
# and
# https://unix.stackexchange.com/questions/148/colorizing-your-terminal-and-shell-environment/174#174
function parse_git_branch() {
git branch 2> /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

View File

@ -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)\$ "

View File

@ -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"

View File

@ -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 <path>" && 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 <file path>"
echo "no file set in which to add block, use: ${RED_COLOR}set-block -f <file path>"
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 <file-path>"
}
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

View File

@ -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).

View File

@ -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