kristopolous / TickTick

JSON in your Bash scripts

Home Page:http://9ol.es/TheEmperorsNewClothes.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Portable" (no debug magic) mode using HERE-documents (<<'EOF')

Artoria2e5 opened this issue · comments

A lot of people are requesting ticktick for some other shell xsh where debug facilities may be nonexistent. A way to get that job done is to write a function that reads from its stdin, transpiles the code, and runs eval -- no caller magic needed! It's going to work in interactive shells too!

# The function should look like this...
tt() {
  eval "$(__tick_fun_tokenize_expression | __tick_fun_parse_expression)"
}
# don't ask me about disabling the rest of the magic i don't know okay?

People can then write blocks of JSON for that in here-documents and one-line here-strings. They are a bit more tedious, but that is expected. For example, instead of the example, we can say:

#!/bin/bash
TICKTICK_NOMAGIC=1
. ticktick.sh

bob=Bob
tt <<'EOF'
  people = {
    "HR" : [
      "Alice",
      $bob,
      "Carol"
    ],
    "Sales": {
      "Gale": { "profits" : 1000 },
      "Harry": { "profits" : 500 }
    }
  }
EOF

function printEmployees() {
  echo
  echo "  The $(tt <<< 'people.Engineering.length()') Employees listed are:"

  for employee in $(tt <<< 'people.Engineering.items()'); do
    printf "    - %s\n" ${!employee}
  done

  echo 
}

echo Base Assignment
tt <<< 'people.Engineering = [ "Darren", "Edith", "Frank" ]'
printEmployees

newPerson=Isaac
echo Pushed a new element by variable, $newPerson onto the array
tt <<< 'people.Engineering.push($newPerson)'
printEmployees

echo Shifted the first element off: $(tt <<< 'people.Engineering.shift()')
printEmployees

echo Popped the last value off: $(tt <<< 'people.Engineering.pop()')
printEmployees

echo Indexing an array, doing variable assignments

person0=$(tt <<< 'people.HR[0]')
echo $person0 $(tt <<< 'people.HR[1]')

(Note the quotes on EOF -- that prevents the shell from expanding $bob on its own prematurely. And the quotes on (), because when they poke out they make a syntax error. The quotes on [0] is there because it can mean a glob, and you don't want to risk having a file called people.HR0 and messing this up.)


  • If you are going interactive, you can even type tt, paste stuff in, and Ctrl-D it. The possibilties are limitless!
  • People can put positional arguments in by calling tt as tt "$@", although I don't see much use for that. If they really want that, they can make an alias tta='tt "$@"' and make it work in scripts with shopt -s expand_aliases. (Aliases are wonderful; they are like macros for bash, lmao.)
  • We can write another function ttl() { printf %s "$1" | tt "${@:2}"; }, just for typing less <<<.

hey that's pretty clever. good work.

isn't <<< a bashism?

for instance, dash, from busybox doesn't have it:
Redirection operators:
< > >| << >> <& >& <<- <>

nor does the old as dirt CSH
|| && | ^ & == != =~ !~ <= >=
< > << >> + - * / % ! ~ ( )

don't get me wrong, I love the hack but it doesn't fix the dash/csh/ksh/tcsh problem

I also don't really understand why jq and the more serious programs like that aren't alternatives ... maybe you can tell me ... what's your actual usecase?

I mean the real real real way to do this would be to just jack the interpreter as a fat wacky wrapper ... essentially have a program say, /usr/bin/crash that does all the intepreter stuff and then do this

#!/usr/bin/crash
... proceed as usual ...

Yeah, that's a bashism. printf %s "somestuff" | tt can be used to go around it though. It might be available in some version of ksh, but I am not sure.

CSH is out of the question: the syntax isn't even in the same family of POSIX/Bourne shells. And then there's that one epic rant about how awful CSH is for programming called CSH programming considered harmful.

I was in the space between sleep and awake this morning when I had more visions of the crash system ... essentially we'll need to either permanently do portable syntax (like '[' instead of '[[') or have a converter. The '[[' is sooo much faster ...

A bash-4 -> POSIX SH transpiler sounds like something that probably already exists in the world - I took enough of computer theory to know it's possible to completely make this since POSIX SH is tightly bound ... It's been around for 31 years I bet this exists. Let me look

hrmm ... "checkbashism" and "shellcheck" are the internet recommendations ... that's lame. I want to have a magic converter as part of a build script.

I dunno ... I think I'll just ask stackexchange ... https://unix.stackexchange.com/questions/588862/is-there-a-bash-to-posix-transpiler let's see what happens.

edit: Apparently the silly doofuses at stackoverflow are uninformed dorks ... I don't have time to run a shell bootcamp for the supposed experts there. I'll do it myself.

about 8 years ago, I was asked for busybox dash support in #22 and that should probably be the reference interpreter here. There's sadly quite a bit of hacks that would need to be done. bash's string substitution in a variable for instance (${//}) doesn't seem to be there.

Unless I want this thing to crawl I think I'd have to rewrite chunks of it more heavily in awk and sed

One of the things for magic-less even in bash is usability in an interactive shell. That's #20.

bash's string substitution in a variable for instance (${//}) doesn't seem to be there.

I'm just checking my busybox shell right now and this works:

$ stringZ=abcABC123ABCabc; echo ${stringZ/abc/xyz}
xyzABC123ABCabc

Does this get us any further forward? The main thing we can't do with busybox is arrays.

I would love to get this working with my busybox systems so I can use it for simple config files. Nothing more than some fields with product type, version, etc. For various reasons it's helpful to have them in json.