REPL calculator in Bash and AWK
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

147 lines
4.2 KiB

#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# Script : cawk
# Descrição: REPL calculator in bash and GNU AWK.
# Versão : 0.0.3
# Data : 09/03/2022
# Licença : GNU/GPL v3.0
# -----------------------------------------------------------------------------
# Copyright (C) 2022 Blau Araujo <blau@debxp.org>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------
# USAGE
# cawk [-f PRECISION] - Start in REPL mode.
# cawk -e EXPRESSION [-f PRECISION] - Eval EXPRESSION and quit.
# COMMAND | cawk [-f PRECISION] - Eval expressions from COMMAND output.
# -----------------------------------------------------------------------------
version="0.0.3"
error[0]="Exiting..."
error[1]="Invalid expression!"
error[2]="Invalid argument!"
bold=$'\e[1m'
reset=$'\e[m'
copy='Copyright (C) 2022 Blau Araujo <blau@debxp.org>.
License: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
'
help="${bold}cawk${reset} ($version) - REPL calculator in Bash and AWK
${bold}USAGE${reset}
${bold}cawk${reset} [-f PRECISION]
${bold}cawk${reset} -e EXPRESSION [-f PRECISION]
COMMAND | ${bold}cawk${reset} [-f PRECISION]
${bold}cawk${reset} [-f PRECISION] < FILE
${bold}OPTIONS${reset}
${bold}-e${reset} EXPRESSION Expression to evaluate.
${bold}-f${reset} PRECISION Number of positions after decimal point.
${bold}-h${reset} or ${bold}--help${reset} This help.
${bold}COMMANDS${reset}
${bold}f${reset} PRECISION Redefine precision.
${bold}h${reset} or ${bold}?${reset} Help.
${bold}q${reset} or ${bold}quit${reset} Quit.
"
# functions -------------------------------------------------------------------
shopt -s extglob
die() {
(($1)) && echo "$help"
printf '\e[33;1m%s\e[m\n' "${error[$1]}"
exit $1
}
calc() {
local exp fix res
exp="$1"
fix=$2
res=$(awk -M 'BEGIN { printf "%.'$fix'f\n", ('"$exp"') }' 2> /dev/null)
[[ $res ]] && EXPRESSION_VAL="$res" || EXPRESSION_ERROR=1
}
repl() {
while :; do
read -erp ': '
history -s -- "$REPLY"
case "${REPLY,,}" in
(f*( )+([0-9])) PRECISION=${REPLY:1}
;;
help|h|'?') echo "$help"
;;
q|quit) die 0
;;
*) eval_expression "$REPLY" $PRECISION IS_REPL || continue
;;
esac
done
}
opts() {
local param
for param; do
case $param in
-h|--help) echo "$help"; echo "$copy"; exit;;
-e) EXPRESSION=${@:2:1} ;;
-e?*) EXPRESSION=${param:2};;
-f) PRECISION=${@:2:1} ;;
-f?*) PRECISION=${param:2} ;;
esac
shift
done
}
eval_expression() {
# Reset globals...
EXPRESSION_ERROR=0
EXPRESSION_VAL=''
calc "$1" $2
if (( EXPRESSION_ERROR )); then
printf '\e[33;1m%s\e[m\n' "${error[1]}"
return 1
fi
[[ $3 = 'IS_REPL' ]] && history -s -- "$EXPRESSION_VAL"
echo "$EXPRESSION_VAL"
}
# main ------------------------------------------------------------------------
unset EXPRESSION
PRECISION=2
opts "$@"
if [[ -t 0 ]];then
if [[ $EXPRESSION ]]; then
eval_expression "$EXPRESSION" $PRECISION || exit
else
repl $PRECISION
fi
else
while read; do
eval_expression "$REPLY" $PRECISION || exit
done
fi