#!/usr/bin/env -S sh +x -v

# run this script and save its ANSI-styled results with the command
#
# sh +x -v ./commands.sh 2>&1 | cat > commands-result.ansi

######################################################################

# notes
#
# - you can add dashes anywhere in tool names, as these are all ignored;
#   letter-case is also ignored in tool names; several tools also have
#   aliases
#
# - named sources starting as either `https://` or `http://` load web
#   resources; the name `-` stands for a tool's stdin, and can appear
#   multiple times, its results cached on first use when it's needed
#   more than once
#
# - the rational-number calculator, the stack/RPN float64 calculator, and
#   all the template runner tools, arguably need their own non-trivial
#   examples/documentation, since they offer several funcs on their own
#
# - the `--` often used here is an alias for tool `compose`, which in turn
#   splits subcommands using `--` itself, hence the choice for the alias
#   itself, as it somehow seems appropriate to match the separator itself
#
# - many tools become case-insensitive when matching substrings/regexes,
#   when the leading option -i is used before the tool name(s)
#
# - some tools are experimental, and thus free to be later removed or
#   incompatibly-changed, and are only accessible via a leading `-x`


# show brief help messages for the various tools named
hat help timer pickjson pick-csv tsv2html nicecsv nosuchtool
timer                                                                           
timer
    show a live timer/chronograph on stderr until either stdin ends, or
    this app is force-quit; if stdin is feeding lines into this tool,
    the live timer will stay below the accumulated output lines being
    shown

pickjson                                                                        
pick-json [keys...]
    pick a subset of key-value pairs from either top-level objects, or
    objects which are directly part of a top-level array; like other JSON
    tools pseudo-JSON with trailing commas and/or comments is accepted as
    valid input, while its output is standard JSON

pick-csv                                                                        
pick-csv [columns...]
    pick a CSV table's columns, trying to match each argument to columns
    by exact-matching first, case-insensitive second, or as a 1-based or
    negative position, when the previous attempts fail

tsv2html                                                                        
tsv-to-html [page-title]
    render a TSV (tab-separated values) table into self-contained HTML

nicecsv                                                                         
can't find a help message for either "nicecsv" or "nicecsv1"

nosuchtool                                                                      
can't find a help message for "nosuchtool"


# args is like `echo`, but emits each argument on its own line
hat -x args 1st-line 2nd-line you-got-it... | hat style green
1st-line
2nd-line
you-got-it...


# show tool `(regular) Expressions COloring/styling LInes`, or ecoli
seq 12 | hat ecoli '[1379]$' r '[50]$' g . b
1
2
3
4
5
6
7
8
9
10
11
12


# full list of recursively-found file pathnames from all the folders given;
# also color detected extensions (alias `cext` also does the same)
hat -- files . -- colorext -- sbs 2
cadex.json           █ plain-text-example.txt
cities.csv           █ simple-html-template.txt
commands-result.ansi █ tsconfig.json
commands.sh          █ 


# get a tally on all file extensions
hat -- files . -- ext -- tally -- bt -- style blue
tally value

2 .json
2 .txt
1 .csv
1 .ansi
1 .sh


# get a tally with bullets on all file extensions
hat -x -- files . -- ext -- bully -- bt -- style blue
tally value bullets

2 .json ••
2 .txt ••
1 .csv •
1 .ansi •
1 .sh •


# get all .json and .jsonl files, searching the current folder recursively
hat -- files . -- pick-ext json jsonl -- color-ext
cadex.json
tsconfig.json


# match all file/folder names via regex, searching recursively
hat -- files . -- many comma -- cext
commands-result.ansi
commands.sh


# tool `nn` (for nice numbers) is especially handy when fractions get long
hat -- calc 'pow(2.343, 11)' -- nn
11681407506111724881718722476588572407/1000000000000000000000000000000000


# tool `nn` (for nice numbers) is especially handy when fractions get long
hat -- calc 'pow(2.343, -11)' -- nn
1000000000000000000000000000000000/11681407506111724881718722476588572407


# some combinatorics using the rational-number calculator, also available
# via the `=` alias; this calculator can also handle enormous numbers
hat -- calc 'c(419, 22)' -- nn
2479169470499515912577213060977268520/1


# the rational-number calculator can also handle enormous numbers
hat -- calc 'c(pow(48219, 234), 282)' -- count-bytes -- nn
308470


# the rational-number calculator has various funcs/aliases, such as abs,
# fac/factorial, c/choose, p/perm, pow/power, pow2/power2, pow10/power10,
# etc... and lets you call 1-arg funcs as fake-properties for convenience
hat calc 'power(5.negate.factorial, -23)'
hat  calc: 1:9: missing ',' in argument list 


# use .. or .0 due to the quirks of the expression-parser used; this example
# shows some of the error messages when misusing funcs/properties
hat calc 'power(5..negate.factorial, -23)'
hat  calc: factorial: only non-negative integers have factorials 


# you can also use an `i` suffix on integer literals, to the same effect
hat calc 'power(5i.negate.factorial, -23)'
hat  calc: factorial: only non-negative integers have factorials 


# a round-about way to get some non-sense number; `=` is an alias for `calc`
hat -- = 'power(5i.negate.abs.factorial, -23)' -- nn
1/662473726694923701112012800000000000000000000000


# show the current year and month number in orange; tool `now` gives you the
# current date, the current time, the 3-letter month name, and the 3-letter
# day of the week; the experimental tool `ymd` only gives you the YYYY-MM-DD
# part instead
hat -- now -- cap 7 -- restyle orange
2024-01


# example of various restylers: these are being used without args, so that
# they're restyling lines from stdin, but all can alternatively accept
# direct arguments instead
echo hi there | hat restyle green
hi there
echo hi there | hat restyle orange
hi there
echo hi there | hat restyle blue
hi there
echo hi there | hat restyle magenta
hi there
echo hi there | hat restyle gray
hi there
echo hi there | hat restyle red
hi there
echo hi there | hat restyle highlight
hi there
echo hi there | hat restyle underline
hi there


# an example using various CSV/table-related tools
hat -- bytes cities.csv -- first 21 \
    -- drop-csv iso3 2..4 id admin_name \
    -- nicecsv0 -- nn -- bt
 0  ■■■■■  city          country        iso2  capital  population

 1  ■■■■  Tokyo         Japan          JP    primary    39105000
 2  ■■■■  Jakarta       Indonesia      ID    primary    35362000
 3  ■■■■  Delhi         India          IN    admin      31870000
 4  ■■■■  Manila        Philippines    PH    primary    23971000
 5  ■■■■  São Paulo     Brazil         BR    admin      22495000

 6  ■■■■  Seoul         South Korea    KR    primary    22394000
 7  ■■■■  Mumbai        India          IN    admin      22186000
 8  ■■■■  Shanghai      China          CN    admin      22118000
 9  ■■■■  Mexico City   Mexico         MX    primary    21505000
10  ■■■■  Guangzhou     China          CN    admin      21489000

11  ■■■■  Cairo         Egypt          EG    primary    19787000
12  ■■■■  Beijing       China          CN    primary    19437000
13  ■■■○  New York      United States  US               18713220
14  ■■■■  Kolkāta       India          IN    admin      18698000
15  ■■■■  Moscow        Russia         RU    primary    17693000

16  ■■■■  Bangkok       Thailand       TH    primary    17573000
17  ■■■■  Dhaka         Bangladesh     BD    primary    16839000
18  ■■■■  Buenos Aires  Argentina      AR    primary    16216000
19  ■■■■  Ōsaka         Japan          JP    admin      15490000
20  ■■■■  Lagos         Nigeria        NG    minor      15487000

                      -              -     -        -   438428220


# same as the previous example, ignoring the last (totals) line
hat -- bytes cities.csv -- first 21 \
    -- drop-csv iso3 2..4 id admin_name \
    -- nicecsv0 -- nn -- skip-last 1 -- bt
 0  ■■■■■  city          country        iso2  capital  population

 1  ■■■■  Tokyo         Japan          JP    primary    39105000
 2  ■■■■  Jakarta       Indonesia      ID    primary    35362000
 3  ■■■■  Delhi         India          IN    admin      31870000
 4  ■■■■  Manila        Philippines    PH    primary    23971000
 5  ■■■■  São Paulo     Brazil         BR    admin      22495000

 6  ■■■■  Seoul         South Korea    KR    primary    22394000
 7  ■■■■  Mumbai        India          IN    admin      22186000
 8  ■■■■  Shanghai      China          CN    admin      22118000
 9  ■■■■  Mexico City   Mexico         MX    primary    21505000
10  ■■■■  Guangzhou     China          CN    admin      21489000

11  ■■■■  Cairo         Egypt          EG    primary    19787000
12  ■■■■  Beijing       China          CN    primary    19437000
13  ■■■○  New York      United States  US               18713220
14  ■■■■  Kolkāta       India          IN    admin      18698000
15  ■■■■  Moscow        Russia         RU    primary    17693000

16  ■■■■  Bangkok       Thailand       TH    primary    17573000
17  ■■■■  Dhaka         Bangladesh     BD    primary    16839000
18  ■■■■  Buenos Aires  Argentina      AR    primary    16216000
19  ■■■■  Ōsaka         Japan          JP    admin      15490000
20  ■■■■  Lagos         Nigeria        NG    minor      15487000


# transform each input line as indicated by the template string: multiple
# template strings would generate separate output lines for each input line
seq 5 10 | hat template 'number {{.}}.'
number 5.
number 6.
number 7.
number 8.
number 9.
number 10.


# templates can do math and run funcs, auto-parsing strings into numbers
# when math funcs are used
seq 5 10 | hat template '2 to the {{sprintf "%2d" (int .)}} is {{pow 2 .}}'
2 to the  5 is 32
2 to the  6 is 64
2 to the  7 is 128
2 to the  8 is 256
2 to the  9 is 512
2 to the 10 is 1024


# setting up the next example
echo abc def
abc def


# isolate words/fields, emitting each into its own line
echo abc def | hat fields
abc
def


# showing a few handy number-extraction tools
echo numbers 1, 2, and 3 add to ... |
    hat -- drop-runes , -- numbers -- stats -- realign-tsv -- nn
count            3
numeric          3
negative         0
zero             0
positive         3
min       1.000000
max       3.000000
sum       6.000000
mean      2.000000
geomean   1.817121
sd        0.707107
rms       1.224745


# fun with words using tool `compose`, its alias `--` being the same symbol
# it uses to separate sub-commands apart; tool `compose` is an alternative
# to having to pipe the app with itself many times, saving some typing
hat -- get-plain https://icanhazdadjoke.com -- fields -- lower -- sbs 4
why  █ live █ water?  █ makes
do   █ in   █ because █ them
fish █ salt █ pepper  █ sneeze!


# fun with words, using tool `compose` via its `--` alias, to avoid having
# to pipe the app with itself many times, which saves you some typing
hat -x -- joke -- fields -- lower -- dedup -- sbs 4
can      █ march? █ but   █ may.
february █ no,    █ april █ 


# using a few prime numbers to show the `side-by-side` tool
hat -- primes 50 -- sbs 10
2  █ 13 █ 31 █ 53 █ 73 █ 101 █ 127 █ 151 █ 179 █ 199
3  █ 17 █ 37 █ 59 █ 79 █ 103 █ 131 █ 157 █ 181 █ 211
5  █ 19 █ 41 █ 61 █ 83 █ 107 █ 137 █ 163 █ 191 █ 223
7  █ 23 █ 43 █ 67 █ 89 █ 109 █ 139 █ 167 █ 193 █ 227
11 █ 29 █ 47 █ 71 █ 97 █ 113 █ 149 █ 173 █ 197 █ 229


# make numbers `nice`, or easier to read, by alternating colors
hat -x -- rpn '10 times rexp 54321.2345 *' -- nn
5348.816242
255504.942421
40750.226330
52636.017709
8584.449422
43770.810835
3322.737461
133232.433702
32339.545761
201427.024002


# 10 random numbers, precede them with a custom line of text, number lines
# starting from 0, adding empty lines every 5, starting from the 2nd line;
# the last tool's name `bt` stands for `breathe table`
hat -x -- rpn 10 times random -- begin 'random integers' -- enum 0 -- bt
1 random integers

2 0.055901
3 0.111463
4 0.124070
5 0.305931
6 0.678133

7 0.410237
8 0.973912
9 0.723182
10 0.436816
11 0.391175


# run `nicejson` on a non-standard JSON file, since it has comments
hat nj tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}


# forgot to show the `plain` tool, so here it is
hat -- nj tsconfig.json -- plain
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}


# tool `cgron` is like running `gron -C`, except the original `gron` app
# doesn't support trailing commas and comments in JSON, and its colors
# look much worse than this tool's colors, which admittedly take more
# bytes in contrast
hat cgron tsconfig.json
json = {};
json.compilerOptions = {};
json.compilerOptions.target = "es5";
json.compilerOptions.module = "commonjs";
json.compilerOptions.strict = true;
json.compilerOptions.esModuleInterop = true;
json.compilerOptions.skipLibCheck = true;
json.compilerOptions.forceConsistentCasingInFileNames = true;


# show a few lines to emphasize JSON file has (non-standard) comments
hat -- bytes tsconfig.json -- first 10 -- cap 70
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file

    /* Basic Options */
    // "incremental": true,                         /* Enable incremen
    "target": "es5",                                /* Specify ECMAScr
    "module": "commonjs",                           /* Specify module 
    // "lib": [],                                   /* Specify library
    // "allowJs": true,                             /* Allow javascrip


# focus on exchange rates from the latest day from the saved online data
cat cadex.json | hat -- zoom-json observations -1 -- nicejson -- sbs 3
{                    █     "v": "0.000100" █     "v": "0.04150"
  "d": "2017-01-03", █   },                █   },
  "FXAUDCAD": {      █   "FXSARCAD": {     █   "FXJPYCAD": {
    "v": "0.9702"    █     "v": "0.3582"   █     "v": "0.01140"
  },                 █   },                █   },
  "FXTHBCAD": {      █   "FXBRLCAD": {     █   "FXSGDCAD": {
    "v": "0.03739"   █     "v": "0.4121"   █     "v": "0.9264"
  },                 █   },                █   },
  "FXMYRCAD": {      █   "FXTRYCAD": {     █   "FXCNYCAD": {
    "v": "0.2991"    █     "v": "0.3744"   █     "v": "0.1930"
  },                 █   },                █   },
  "FXZARCAD": {      █   "FXMXNCAD": {     █   "FXGBPCAD": {
    "v": "0.09740"   █     "v": "0.06439"  █     "v": "1.6459"
  },                 █   },                █   },
  "FXEURCAD": {      █   "FXKRWCAD": {     █   "FXNZDCAD": {
    "v": "1.3973"    █     "v": "0.001112" █     "v": "0.9295"
  },                 █   },                █   },
  "FXUSDCAD": {      █   "FXHKDCAD": {     █   "FXSEKCAD": {
    "v": "1.3435"    █     "v": "0.1732"   █     "v": "0.1465"
  },                 █   },                █   },
  "FXNOKCAD": {      █   "FXVNDCAD": {     █   "FXINRCAD": {
    "v": "0.1551"    █     "v": "0.000059" █     "v": "0.01965"
  },                 █   },                █   },
  "FXCHFCAD": {      █   "FXPENCAD": {     █   "FXRUBCAD": {
    "v": "1.3064"    █     "v": "0.3976"   █     "v": "0.02210"
  },                 █   },                █   }
  "FXIDRCAD": {      █   "FXTWDCAD": {     █ }


# ... too many currencies, so focus on a few; the key-picker tool being
# used is case-insensitive, so it doesn't force screaming the key names
# out to match the original ones exactly, which are all uppercase
cat cadex.json | hat -i -- zoom-json observations -1 -- \
    pick-json d fxusdcad fxeurcad -- nicejson
{
  "d": "2017-01-03",
  "FXEURCAD": {
    "v": "1.3973"
  },
  "FXUSDCAD": {
    "v": "1.3435"
  }
}


# show a few integers along with their base-10 logarithm; tool `skiplast`
# is used to ignore the last ugly line showing a final empty stack form
# `rpn`, the stack-based calculator used to do the math
seq 5 12 | hat -x -- template '{{.}} d p0 log10 print' \
    -- with-args rpn -- line-up 2 -- nn
5 0.698970
6 0.778151
7 0.845098
8 0.903090
9 0.954243
10 1.000000
11 1.041393
12 1.079181


# example similar to the previous one, but looks even better, by rounding
# the calculated logarithms to 3 decimals
seq 10 | hat -x -- template '{{.}} d p0 log10 p3' \
    -- with-args rpn -- lineup 2 \
    -- begin-tsv n log10 -- nice-tsv-0
 0  ■■  n   log10
 1     1  0.000
 2     2  0.301
 3     3  0.477
 4     4  0.602
 5     5  0.699
 6     6  0.778
 7     7  0.845
 8     8  0.903
 9     9  0.954
10    10  1.000
        55  6.559


# another way to get the previous example's results, also letting the
# table `breathe`
seq 10 | hat -- template '{{.}}' '{{sprintf "%.3f" (log10 .)}}' \
    -- lineup 2 -- begin-tsv n log10 \
    -- nice-tsv-0 -- bt
 0  ■■  n   log10

 1     1  0.000
 2     2  0.301
 3     3  0.477
 4     4  0.602
 5     5  0.699

 6     6  0.778
 7     7  0.845
 8     8  0.903
 9     9  0.954
10    10  1.000

        55  6.559


# show own LAN IP address... better not
# hat lanip | hat gsub '[0-9]+' '*'
(ifconfig || ipconfig) 2>&1 | hat -- any 192. -- gsub '\.[0-9]+' '.*'
   IPv4 Address. . . . . . . . . . . : 192.*.*.*
                                       192.*.*.*
   IPv4 Address. . . . . . . . . . . : 192.*.*.*


# show the html template file used in the next example
echo | hat -- template '{{repeat "-" 80}}' \
    -- bytes - simple-html-template.txt
--------------------------------------------------------------------------------
{{- $abc := "123" -}}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="data:,">
    <title>Document {{$abc}}</title>
</head>

<body>
    <p>2 &times; ({{$abc}} + 5) = {{mul 2 (add $abc 5)}}</p>
</body>

</html>


# run an html/svg template file
hat -x template-html simple-html-template.txt
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="data:,">
    <title>Document 123</title>
</head>

<body>
    <p>2 &times; (123 + 5) = 256</p>
</body>

</html>


# run an html/svg template file
# hat template-svg simple-svg-template.txt


# run a text-template file, as opposed to an html/svg-specific one
# hat template-file example-template.txt


# tool `get` autocompletes the `http` protocol part; tool `size` counts
# bytes, a result which is piped into a template, then also passed on to
# `nicenums` (nn) to alternate groups of 3 digits, to improve readability
hat -- get wsj.com -- count-bytes \
    -- template 'wsj.com responded with {{.}} bytes' -- nn
wsj.com responded with 759362 bytes


# change foreign money into CAD, using the latest official exchange rates
# for a few select currencies; notice how column names can often be picked
# without matching letter-case; last line with column sums is ignored,
# since with only 1 data row, the totals line isn't needed
hat -x -- cadex 123.456 -- picktsv usd mxn eur -- nicetsv0 -- skiplast 1
0  ■■■  USD       MXN     EUR
1    164.7767  9.7407  180.4186


# show a colored symbol-tally of e truncated after its 1000th decimal
echo 'scale=1000; e(1)' | bc -l | tr -d '\n' |
hat -- drop-runes \\ -- shquote -- gotron in.tally -- nj
{
  "2": 98,
  ".": 1,
  "7": 99,
  "1": 96,
  "8": 103,
  "4": 100,
  "5": 85,
  "9": 112,
  "0": 100,
  "3": 109,
  "6": 99
}


# another joke; the site's response is random, so the joke keeps changing
# hat -- getjson https://icanhazdadjoke.com -- nj | fold -s | hat trim
hat -- getjson https://icanhazdadjoke.com -- drop-json joke -- nj
{
  "id": "iV0DQ7pjGlb",
  "status": 200
}


# the next joke is to show `zooming-into` JSON data
hat -- get-json https://icanhazdadjoke.com -- zj joke -- cap 80 -- plain
"I’ve just been reading a book about anti-gravity, it’s impossible to put down!"


# one more joke, but this time shown as a nicely word-wrapped paragraph
hat getplain https://icanhazdadjoke.com | fold -s | hat \
    -- trim-trail -- style green
What do bees do after they are married? They go on a honeymoon.


# show a (hopefully) good random joke, putting it in a colored box
(echo; hat -x joke; echo) | fold -s -w 76 | hat -- trim -- \
    template '{{sprintf "  %-76s  " .}}' -- indent 1 -- style highlight
                                                                                 
   Where did Captain Hook get his hook? From a second hand store.                
                                                                                 


# lookup words using dict://dict.org, dimming the response-metadata lines;
# you can use `curl -s dict://dict.org/d:chair` for the same input data
hat -- define chair -- cap 80 -- ecoli '^[0-9]+ ' gray '^ ' green . blue
220 dict.dict.org dictd 1.12.1/rf on Linux 4.19.0-10-amd64 <auth.mime> <24513746
150 1 definitions retrieved
151 "chair" wn "WordNet (r) 3.0 (2006)"
chair
    n 1: a seat for one person, with a support for the back; "he put
         his coat over the back of the chair and sat down"
    2: the position of professor; "he was awarded an endowed chair
       in economics" [syn: {professorship}, {chair}]
    3: the officer who presides at the meetings of an organization;
       "address your remarks to the chairperson" [syn: {president},
       {chairman}, {chairwoman}, {chair}, {chairperson}]
    4: an instrument of execution by electrocution; resembles an
       ordinary seat for one person; "the murderer was sentenced to
       die in the chair" [syn: {electric chair}, {chair}, {death
       chair}, {hot seat}]
    5: a particular seat in an orchestra; "he is second chair
       violin"
    v 1: act or preside as chair, as of an academic department in a
         university; "She chaired the department for many years"
         [syn: {chair}, {chairman}]
    2: preside over; "John moderated the discussion" [syn:
       {moderate}, {chair}, {lead}]


# ping a site, ignore empty lines, color lines by regex, show timestamped
# lines, and finally remove the time part of the timestamp; try piping all
# of this to command `hat timer` to also track progress with a live timer
ping www.bing.ca | hat -- many . -- ecoli Reply gray Ping g . b \
    -- timestamp -- gsub ' ..:..:..' ''
2024-01-06 Pinging www.bing.ca [204.79.197.219] with 32 bytes of data:
2024-01-06 Reply from 204.79.197.219: bytes=32 time=2ms TTL=121
2024-01-06 Reply from 204.79.197.219: bytes=32 time=3ms TTL=121
2024-01-06 Reply from 204.79.197.219: bytes=32 time=3ms TTL=121
2024-01-06 Reply from 204.79.197.219: bytes=32 time=3ms TTL=121
2024-01-06 Ping statistics for 204.79.197.219:
2024-01-06     Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
2024-01-06 Approximate round trip times in milli-seconds:
2024-01-06     Minimum = 2ms, Maximum = 3ms, Average = 2ms


# make only a few data from the ping output stand out
ping www.bing.ca | hat -- many . -- coma \
    'Minimum = [0-9]+ms' green \
    'Maximum = [0-9]+ms' red \
    'Average = [0-9]+ms' orange \
    '([0-9\.]+){3}[0-9]' mag
Pinging www.bing.ca [204.79.197.219] with 32 bytes of data:
Reply from 204.79.197.219: bytes=32 time=12ms TTL=121
Reply from 204.79.197.219: bytes=32 time=3ms TTL=121
Reply from 204.79.197.219: bytes=32 time=13ms TTL=121
Reply from 204.79.197.219: bytes=32 time=2ms TTL=121
Ping statistics for 204.79.197.219:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 2msMaximum = 13msAverage = 7ms


# wondering how long float64 mantissas will work as unix-style timestamps...
# are those in millionths or billionths of a second?
hat -- gj '_{52, 53, 64}.pow2() / _{1e6, 1e9} / day / 365.25 + 1970' \
    -- nj -- nn
{
  "52": {
    "1000000": 2112.7104604713445,
    "1000000000": 1970.1427104604713
  },
  "53": {
    "1000000": 2255.4209209426886,
    "1000000000": 1970.2854209209427
  },
  "64": {
    "1000000": 586512.0460906264,
    "1000000000": 2554.5420460906266
  }
}


# you say about 1500 each day, what range is that a year?
hat -- gj '1500i.fuzz * _{365, 366}' -- nj -- nn
{
  "1450": {
    "365": 529250,
    "366": 530700
  },
  "1500": {
    "365": 547500,
    "366": 549000
  },
  "1550": {
    "365": 565750,
    "366": 567300
  }
}


# now you tell me about 1400-1500 a day, so between 1400 and 1500 a day...
hat -- gj '_{1400, 1500} * _{365, 366}' -- nj -- nn
{
  "1400": {
    "365": 511000,
    "366": 512400
  },
  "1500": {
    "365": 547500,
    "366": 549000
  }
}


# calculate PCM time-durations of 4GB, the `max` size for .wav files
hat -- gj '(4*gb / (_{44_100, 48_000} * 2*_{mono: 1, stereo: 2})).hms()' \
    -- nj
{
  "44100": {
    "mono": "13:31:35.77",
    "stereo": "06:45:47.89"
  },
  "48000": {
    "mono": "12:25:39.24",
    "stereo": "06:12:49.62"
  }
}


# given the next example, open web-browser tab for http://127.0.0.1:8080
# hat open :8080


# webserve the current folder on local TCP/HTTP port 8080
# hat serve . 8080


# pop GUI window to navigate/explore the current folder's contents
# hat open .


# pop GUI windows to explore folders abc, def, the current folder, open
# the default web-browser for http://127.0.0.1:1234, play video file
# video.mp4 using the default video-player app for mp4 files, and finally
# open the default web-browser on the website given as well
# hat open abc def :1234 . video.mp4 https://duckduckgo.com


# color-code results from golang unit-tester command; using tool `time`
# separately, gives you a live timer/chronograph right below the output
# go test ./... | hat ecoli ^ok green ^fail red '^\?' gray | hat -x timer


# example of composing/piping hat with itself and standard cmd-line tools
# hat now ; hat -- pscan -- nn -- timestamp |
# awk '{ $3=""; $4=""; gsub(/ +/, " "); print; fflush() }' | hat -x timer