Skip to content

Instantly share code, notes, and snippets.

@wcarhart
Created April 21, 2020 03:20
Show Gist options
  • Save wcarhart/72bdb7aaa082c0415e5966ddb5ae4445 to your computer and use it in GitHub Desktop.
Save wcarhart/72bdb7aaa082c0415e5966ddb5ae4445 to your computer and use it in GitHub Desktop.
Bash metaprogramming
#!/bin/bash
# list all custom BASH functions
lsf() {
if [[ ! -d ~/.bash_functions ]] ; then
if [[ ! -f ~/.bashrc ]] ; then
echo "lsf: err: no such directory ~/.bash_functions, no such file ~/.bashrc"
return 1
fi
while IFS='' read -r LINE || [[ -n $LINE ]] ; do
LET=`echo $LINE | fold -w1`
CHARS=`echo $LET | tr -d '\040\011\012\015'`
if [[ ( "${CHARS[*]: -1}" == "{" ) && ( "${CHARS: -2:1}" == ")" && "${CHARS: -3:1}" == "(" ) ]] ; then
LEN=${#CHARS}
LEN="$(( $LEN - 1 ))"
echo "${CHARS:0:$LEN}"
fi
done < ~/.bashrc
else
for FILE in ~/.bash_functions/* ; do
PARTS=( ${FILE//./ } )
if [[ "${PARTS[*]: -1}" == "sh" ]] ; then
echo "`basename ${FILE:0:${#FILE}-3}`()"
fi
done
fi
}
# make a BASH function out of the last x commands
makef() {
fc -rnl > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echo "makef: err: history is empty"
return 1
fi
if [[ $# -eq 0 ]] ; then
NUM=1
RANDO=`random 5`
NAME="function_$RANDO"
elif [[ $# -eq 1 ]] ; then
NUM=$1
RANDO=`random 5`
NAME="function_$RANDO"
elif [[ $# -eq 2 ]] ; then
NUM=$1
NAME=$2
RANDO=`random 5`
else
echo "makef: err: incorrect number of arguments"
return 1
fi
[ -n "$NUM" ] && [ "$NUM" -eq "$NUM" ] 2>/dev/null
if [ $? -ne 0 ]; then
echo "makef: err: first argument must be a number"
return 1
fi
if [[ $NUM -lt 1 ]] ; then
echo "makef: err: first argument must be a positive integer"
return 1
fi
NAMESTR=( $NAME )
if [[ ${#NAMESTR[@]} -gt 1 ]] ; then
echo "makef: err: name of function cannot contain spaces"
return 1
fi
if [[ ! -d ~/.bash_functions ]] ; then
SOURCE=~/.bashrc
else
if [[ ! -f ~/.bash_functions/$NAME.sh ]] ; then
SOURCE=~/.bash_functions/$NAME.sh
else
echo "makef: err: ~/.bash_functions/$NAME.sh already exists"
return 1
fi
fi
NUM=$(( $NUM + 1 ))
printf "\n" >> $SOURCE
printf "$NAME() {\n" >> $SOURCE
fc -rnl | head -$NUM > $RANDO
tac $RANDO > .tempfile
INDEX=0
while IFS='' read -r CMD || [[ -n "$CMD" ]] ; do
if [ $INDEX -eq 0 ] ; then
INDEX+=1
continue
fi
printf "$CMD\n" >> $SOURCE
done < ".tempfile"
printf "}\n" >> $SOURCE
rm -rf .tempfile
rm -rf $RANDO
source $SOURCE
}
# make a shell script out of the last x commands
makes() {
fc -rnl > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echo "makes: err: history is empty"
return 1
fi
if [[ $# -eq 0 ]] ; then
NUM=1
NAME="script.sh"
elif [[ $# -eq 1 ]] ; then
NUM=$1
NAME="script.sh"
elif [[ $# -eq 2 ]] ; then
NUM=$1
NAME=$2
else
echo "makes: err: incorrect number of arguments"
return 1
fi
[ -n "$NUM" ] && [ "$NUM" -eq "$NUM" ] 2>/dev/null
if [ $? -ne 0 ]; then
echo "makes: err: first argument must be a number"
return 1
fi
if [[ $NUM -lt 1 ]] ; then
echo "makes: err: first argument must be a positive integer"
return 1
fi
NAMESTR=( $NAME )
if [[ ${#NAMESTR[@]} -gt 1 ]] ; then
echo "makes: err: name of function cannot contain spaces"
return 1
fi
RANDO=`random`
fc -rnl | head -$NUM > $RANDO
tac $RANDO > $NAME
rm -rf $RANDO
}
# remove a BASH Function by name
rmf() {
if [[ $# -ne 1 ]] ; then
echo "rmf: err: incorrect number of arguments"
return 1
fi
if [[ "${1: -2:2}" == "()" ]] ; then
FUNCTION="${1:0:-2}"
else
FUNCTION="$1"
fi
if [[ -d ~/.bash_functions ]] ; then
FILENAME="$FUNCTION.sh"
if [[ ! -f ~/.bash_functions/$FILENAME ]] ; then
echo "rmf: err: $FUNCTION.sh not found in ~/.bash_functions"
return 1
fi
rm -rf ~/.bash_functions/$FILENAME
else
if [[ ! -f ~/.bashrc ]] ; then
echo "rmf: err: no such directory ~/.bash_functions, no such file ~/.bashrc"
return 1
fi
RANDO=`random`
TITLE="$FUNCTION() {"
EDIT=0
FOUND=0
COUNT=0
while IFS='' read -r LINE || [[ -n "$LINE" ]] ; do
if [[ "$TITLE" == "$LINE" ]] && [[ $EDIT -eq 0 ]] ; then
EDIT=1
FOUND=1
elif [[ "$LINE" == "}" ]] && [[ $EDIT -eq 1 ]] ; then
EDIT=0
COUNT="$(( $COUNT + 1 ))"
else
if [[ $EDIT -eq 0 ]] ; then
printf "%s\n" "$LINE" >> $RANDO
fi
fi
done < ~/.bashrc
cat $RANDO > ~/.bashrc
rm -rf $RANDO
if [[ $FOUND -eq 0 ]] ; then
echo "rmf: err: $FUNCTION not found in ~/.bashrc"
return 1
else
if [ $COUNT -eq 1 ] ; then
echo "Removed $FUNCTION from ~/.bashrc"
source ~/.bashrc
else
echo "Removed $FUNCTION $COUNT times from ~/.bashrc"
source ~/.bashrc
fi
fi
fi
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment