##  punkshell - an alternative Tcl Shell

BSD license

2023-08  Note: this is **alpha** level software and still highly experimental.


### Features
- default ansi color output - toggle with 'colour on' and 'colour off' (or set NO_COLOR environment variable)
- rendering of old-school Ansi art (cp437) in the terminal 
  ![Ansi art courtesy of roy-sac.com](hype_roysac.png?raw=true "Ansi art")
- Relatively easy compositing of text blocks containing Ansi colour codes - (or rendered versions of ansi containing movement and other controls)
``` 
    proc welcome_test {} {
        package require textblock
        package require punk::ansi
        package require overtype
        set ansi        [textblock::join -- " " [punk::ansi::ansicat src/testansi/publicdomain/roysac/roy-welc.ans 80x8]]
        # Ansi art courtesy of Carsten Cumbrowski aka Roy/SAC - roysac.com
        set table       [[textblock::spantest] print]
        set punks       [a+ web-lawngreen][>punk . lhs][a]\n\n[a+ rgb#FFFF00][>punk . rhs][a]
        set ipunks      [overtype::renderspace -width [textblock::width $punks] [punk::ansi::enable_inverse]$punks]
        set testblock   [textblock::testblock 15 rainbow]
        set contents    $ansi\n[textblock::join -- "  " $table "  " $punks " " $testblock " " $ipunks " " $punks] 
        set framed      [textblock::frame -type arc -title [a+ cyan]Compositing[a] -subtitle [a+ red]ANSI[a] -ansiborder [a+ web-orange] $contents]
    } 
```
  ![textblock composition of Ansi strings](compositing_ansi.png?raw=true "Compositing Ansi")

- experimental functional/pattern-matching language features. (will not be performant until more work is done on script compilation)   
    e.g.1 basic pipeline with 2 segments   
    `var_pipe_output.=  var_list.= list a b c |> string toupper`   
    e.g.2 basic pattern-match multi-assignment to variables x y & z   
    `x@0,y@1,z@2.= list a b c`  equivalently: `x@,y@,z@.= list a b c`  or even `x@,y@,z@= {a b c}`  
    `x/0,y/1,z/2,zz/3.= list a b c` is similar - but the use of forward-slash instead of @ will not produce a mismatch if an index is out of range.   
     where .= indicates following arguments form a command, and a plain = accepts only a single argument as a value   
     The diminutive case of this is `x= "something"`  as equivalent to `set x "something"`   
     Assignment operations and pattern-matches are slightly optimised to bytecompile, but are unlikely to compete with raw Tcl commands performance-wise.   
    e.g.3 destructuring pattern-match. Get value of key 'k1' from last item in a list of dicts.   
    `x@end/@@k1.= list {k1 aaa} {k1 bb}`  returns bbb   
    
    There are many more pattern-matching features yet to be documented.
- easy execution of externals commands with return of stdout, stderr and the exitcode of the process   
    The run... commands use a very basic repl-telemetry system to output more information to the console than just the return value,   
    but in a way which makes the return value clear. The telemetry only outputs if the command is the first word on the commandline.  
    - `run <comand> ...`   
       (return exitcode of process - and allows process writes to stderr/stdout to appear in console as they occur)
    - `runout [-n] <command> ...`   
       (return stdout of process - no output until completion)
    - `runerr [-n] <command> ...`   
       (return stderr of process - no output until completion)
    - `runx [-n] <command> ...`
       (return a dict of stdout stderr exitcode - no output until completion)
       
    The run... commands attempt to make it clear if a called process outputs a trailing newline by displaying a trailing blank line.   
    The optional `-n` argument can be used to suppress a trailing newline.
    `runout -n pwd` is thus **similar** to Tcl's `exec pwd`   
    For simple cases `exec <command>` is fine - but the equivalent `runout -n <command>` when used in the shell will display exitcode and stderr separately (whilst returning only stdout)
    exec will return stdout and stderr together.  
    If you are on a unix-like platform, or a windows platform which has something like msys2 to provide commands like 'which' and 'grep' in the path:   
    Try `runx -n which grep nonexistant` vs `exec which grep nonexistant`  to see the difference in terms of easy access to what was written to stderr vs stdout.   
    The run... commands are intended as a supplement for rather than a replacement for Tcl's exec/open.   
- namespace browser (contextual - allowing running of commands within the active namespace - analogous to 'cd' for directories)
    -  `n/`  - display child namespaces of current namespace  (alias `:/`)   
         also `n/ <globpattern>` to restrict output
    -  `n/ <childns>`  - if the argument doesn't contain glob chars '*' or '?' - attempt to switch to a child namespace of that name. Analogous to `cd <dir>`   
         list any sub namespaces of the namespace we just switched to.
    -  `n//` - display child namespaces and commands  (alias `://`)   
        with colourised indication of type such as proc,alias,ensemble,oo object,oo class,imported,exported where possible.   
        (renamed aliases and builtins and commands loaded from binaries will appear unmarked)
    -  `nn/` - move up one namespace towards root namespace '::'  analogous to `cd ..`   (alias `::/`)
    -  `n/new <somename>` - create a child namespace called 'somename' and switch to it in one operation.  (alias `:/new`)
- cross-platform alternative to cd & ls/dir without invoking child processes. Display colourised listing of dirs and folders - with vfs indication.
    -  `d/` - list current directory (alias `./`)   
        also `d/ <globpattern>` to restrict output
    -  `d/ <subdir>` - switch to subdir and list contents in one operation 
    -  `dd/` - move up one directory and output listing. Roughly equivalent to `cd ..` followed by dir or ls  (alias `../`)
    -  `d/new <folder>` - create a child directory and switch to it in one operation. (alias `./new <folder>`)

#### missing
- raw mode REPL (read-eval-print-loop) to allow commandline completion etc. Initial version is linemode. (intention is to allow different REPLs to be plugged)
- documentation!
- tests
- signal handling on unix-like platforms (ctrl-c implemented on windows only)


#### very unripe parts:
- commandline options - in need of urgent work to document and lock down specifics - in particular: punkshell somescript.tcl needs a fix to emit errors.
- shellfilter - api is clumsy
- scriptlib - will likely be reorganised/pruned significantly