# serhii.net

In the middle of the desert you can say anything you want

TL;DR: fish easy version below works, but needs quotes when expression is complex: cc 2+2 but cc 'floor(2.3)'.

I’m continuing to move my useful snippets from zsh to fish (240620-2109 Fish shell bits), and the most challenging one was the CLI python calculator I really love and depend on, since it contained arguments with parentheses (which are fish expressions as well).

Basically: cc WHATEVER runs WHATEVER inside python, can do both easy math a la 2+2 and more casual statistics-y mean([2,33,28]).

Before in zsh this was the magic function:

cc() python3 -c "from math import *; from statistics import *; print($*);" alias cc='noglob cc'  Fish, easy version: function cc command python3 -c "from math import *; from statistics import *; print($argv);"
end


Works for easy cc 2+2 bits, but as soon as functions and therefore parentheses get involved (cc floor(2.3)) it starts to error out.

[I] sh@nebra~/t $cc mean([2,4]) fish: Unknown command: '[2,4]' in command substitution fish: Unknown command cc mean([2,4]) ^~~~~~^ [I] sh@nebra~/t$ cc mean$[2,4]$

>>> mean([2,4])
3
[I] sh@nebra~/t $ (But I REALLY don’t want to do cc mean$[2, 3]$) In the zsh snippet, noglob meant basically “take this literally w/o expanding anything”, and it passed everything as-is to python, and this is what fails in my fish solution. Noglob in fish is fun: • The fish language — fish-shell 3.7.0 documentation on escaping characters • Implement the noglob modifier · Issue #3504 · fish-shell/fish-shell: If you wish to use arguments that may be expanded somehow literally, quote them. echo ‘’ and echo “” both will print the literal. • The fish language on quotes: • single quotes = no expansion of any kind • \' for literals inside single • double quotes = variable exp. ($TERM) & command substitution ($(command)) • \" for literal "s inside double • within each other, no special meaning • Let’s test: • echo (ls) = ls output, one line • echo "$(ls)" = ls output, multiline
• echo '(ls)' = (ls)
• echo "(ls)" = "(ls)"

THEN

• command python3 -c "from math import *; from statistics import *; print($argv);" • cc ceil$2$ + • cc ceil(2) - • command python3 -c “from math import *; from statistics import *; print(’$argv’);”

• literally prints the passed thing w/o python eval, w/ same rules
• OK can I do a variable then?

  set pyc $argv echo$pyc
command python3 -c "from math import *; from statistics import *; print($pyc);"  nope. ### Bruteforcing the solution (and learning to use fish loops mainly, of course there are better ways to do this.)  # list of simple, brackets, and parentheses + no, single, double quotes # no space between nums in brackets, python interpreter would add them. [2,3] — literal, [2, 3] — parsed by python set cmds \ '2+2' \ '\'2+2\'' \ '"2+2"' \ '[2,3]' \ '\'[2,3]\'' \ '"[2,3]"' \ 'floor(2.3)' \ '\'floor(2.3)\'' \ '"floor(2.3)"' function tcc set pyc$argv
# command python3 -c "from math import *; from statistics import *; print" '(' "$pyc" ');' # command python3 -c "from math import *; from statistics import *; print($pyc);"
command python3 -c "from math import *; from statistics import *; print($pyc);" end # loop through all test cases to see sth that works for all for i in$cmds
echo $i: echo "$(tcc $i)" end  At the end, no additional literal quotes + initial command didn’t error out, and we came full circle: set cmds \ '2+2' \ '[2,3]' \ 'floor(2.3)' # winner command! function tcc command python3 -c "from math import *; from statistics import *; print($argv);"
end

[I] sh@nebra~/t $./test_cc.sh 2+2: 4 [2,3]: [2, 3] floor(2.3): 2  • Double quotes in the python command mean only $pyc gets expanded
• $pyc in the working versions have no hard-coded quotes • in CLI tcc floor(2.3) still fails — because like that it’s a command, not a string. In the file it was inside single quotes, as a string. So I can do this in the CLI as well. So simple and logical at the end. #### Final solution function cc echo ">>>$argv"
command python3 -c "from math import *; from statistics import *; print($argv);" end  When using, quotes are needed only for complex bits (parentheses, * etc.). [I] sh@nebra~/t$ cc 2+2
>>> 2+2
4

[I] sh@nebra~/t $cc [2,3,4] >>> [2,3,4] [2, 3, 4] # no quotes [I] sh@nebra~/t$ cc mean([2,3,4])
fish: Unknown command: '[2,3,4]'
in command substitution
fish: Unknown command
cc mean([2,3,4])
^~~~~~~~^

# with quotes
[I] sh@nebra~/t \$ cc 'mean([2,3,4])'
>>> mean([2,3,4])
3
`