Skip to content

Commit

Permalink
echo-math: don't use awk, it is too fragile, use deno as bc fallback …
Browse files Browse the repository at this point in the history
  • Loading branch information
balupton committed Sep 16, 2024
1 parent 86de699 commit 35593fe
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 28 deletions.
67 changes: 42 additions & 25 deletions commands/echo-math
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,43 @@ function echo_math_test() (
echo-style --h1="TEST: $0"

local inputs=('1 - 1/2' '1 - 1/3' '1 - 1/4')
local expected=$'0.50\n0.67\n0.75'
local expected_six=$'0.500000\n0.666667\n0.750000'
local expected_two=$'0.50\n0.67\n0.75'

if command-exists -- bc; then
eval-tester --stdout="$expected" \
eval-tester --stdout="$expected_six" \
-- echo-math --tool=bc -- "${inputs[@]}"

{
__print_lines "${inputs[@]}"
} | eval-tester --stdout="$expected_six" \
-- echo-math --tool=bc --stdin

eval-tester --stdout="$expected_two" \
-- echo-math --precision=2 --tool=bc -- "${inputs[@]}"

{
__print_lines "${inputs[@]}"
} | eval-tester --stdout="$expected" \
} | eval-tester --stdout="$expected_two" \
-- echo-math --precision=2 --tool=bc --stdin
fi

if command-exists -- awk; then
eval-tester --stdout="$expected" \
-- echo-math --precision=2 --tool=awk -- "${inputs[@]}"
if command-exists -- deno; then
eval-tester --stdout="$expected_six" \
-- echo-math --tool=deno -- "${inputs[@]}"

{
__print_lines "${inputs[@]}"
} | eval-tester --stdout="$expected" \
-- echo-math --precision=2 --tool=awk --stdin
} | eval-tester --stdout="$expected_six" \
-- echo-math --tool=deno --stdin

eval-tester --stdout="$expected_two" \
-- echo-math --precision=2 --tool=deno -- "${inputs[@]}"

{
__print_lines "${inputs[@]}"
} | eval-tester --stdout="$expected_two" \
-- echo-math --precision=2 --tool=deno --stdin
fi

echo-style --g1="TEST: $0"
Expand All @@ -48,11 +65,11 @@ function echo_math() (
OPTIONS:
--precision=<precision>
The number of decimals to round to.
Defaults to [6] which is the default for [awk] for consistency.
Defaults to [6].
--tool=<tool>
The math engine to use.
Defaults to [bc] if available, otherwise [awk] if available, otherwise failure.
Defaults to [bc] if available, otherwise [deno] if available, otherwise failure.
$(stdinargs_options_help --)
EOF
Expand All @@ -77,39 +94,39 @@ function echo_math() (
shift $#
break
;;
'--'*) option_args+=("$item") ;;
*) option_args+=("$item") ;;
esac
done

if test -z "$option_tool"; then
if command-exists -- bc; then
option_tool='bc'
elif command-exists -- gawk; then
option_tool='gawk'
elif command-exists -- awk; then
option_tool='awk'
elif command-exists -- deno; then
option_tool='deno'
fi
elif ! command-exists -- "$option_tool"; then
help "Missing math <tool>: $option_tool"
fi

# =====================================
# Dependencies

# =====================================
# Action

# bc: 0 decimals by default
# bc -l: 20 decimals by default
# 0. becomes ., hence need for printf
# awk: 6 decimals by default

if test "$option_tool" = 'bc'; then
function on_line {
# bc: 0 decimals by default, bc -l: 20 decimals by default
# 0. becomes ., hence need for printf
printf "%.${option_precision}f\n" "$(bc -l <<<"$1")"
local formula="$1"
printf "%.${option_precision}f\n" "$(bc -l <<<"$formula")"
}
elif test "$option_tool" = 'awk' -o "$option_tool" = 'gawk'; then
local awk_script
awk_script="$(type -P echo-math.awk)"
elif test "$option_tool" = 'deno'; then
local deno_script
deno_script="$(type -P echo-math.ts)"
function on_line {
"$option_tool" -v option_precision="$option_precision" -v option_number="$1" -f "$awk_script"
local formula="$1"
"$deno_script" "$option_precision" "$formula"
}
else
help 'No math engine found.'
Expand Down
3 changes: 0 additions & 3 deletions commands/echo-math.awk

This file was deleted.

6 changes: 6 additions & 0 deletions commands/echo-math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env -S deno run --quiet --no-config --no-lock --no-npm --no-remote --cached-only
const precision = Number(Deno.args[0])
const formula = Deno.args[1]
const result = Number(eval(formula))
const output = result.toFixed(precision)
console.log(output)

0 comments on commit 35593fe

Please sign in to comment.