Powershell GUI fronted (WPF) to run categorized console scripts

⌈⌋ ⎇ branch:  ClickyColoury


Artifact [cea107d9c0]

Artifact cea107d9c07006489d1c1fd4c164cd7008b0a71f:

Wiki page [plugin meta data] by mario 2018-04-09 20:28:49.
D 2018-04-09T20:28:49.007
L plugin\smeta\sdata
N text/x-markdown
P 7ada2e3b7b3fda155f90ea11b2e9da23f8a5d67c
U mario
W 7960
## plugin meta data

This summary explains the cross-language comment format for **feature management** as used within ClickyColoury.  
See also [https://pypi.python.org/pypi/pluginconf](https://pypi.python.org/pypi/pluginconf) for a Python variant.

Its purpose for ClickyColoury is to simplify script/plugin organization. Menu-structuring is a rather trivial use case for "plugin meta data".
Incidentally it enforces proper documentation however.

 * Which is particular interesting for PowerShell, as a common scheme
   is largely absent. (ASCII-art code comments are somewhat rampant.)
 * Like in other languages, the built-in PowerShell DocBlock scheme is
   largely unsuitable: no custom fields via `Get-Help` supported.
 * The `menu.psm1` implements a rather crude extractor however;
   only looks for `#`-comment blocks, not `<#` (as it should) yet.
 * `Extract-PluginMeta` is public domain however.


## meta block

Each tools/* script should have a top-level comment with meta fields:

    # api: multitool
    # version: 0.1
    # title: TITLE/INFO
    # description: WELL, DESCRIPTION
    # type: inline
    # category: BETA
    # key: x5|name|dsquery
    # keycode: Ctl+F7
    # config: -
    # 
    # More comments here …

This is basically a YAML structure in a comment. Which in some form
or another is already used by most programmers. This spec just defines
a few standard and custom fields.


<style>
 main .content table tr:nth-child(odd) { background: #f3f3f3; }
</style>

## meta fields

Well, most of those are pretty self-explanatory:

| key           | usage / defaults                                |
-------------------------------------------------------------------
|**api:**       | always "multitool" here (original project name) |
|**version:**   | mostly decoration    |
|**title:**     | Used as button / menu inscription   |
|**description:**| short summary of what the plugin does   |
|**type:**      | script execution mode (implied default is "inline") |
|**category:**  | menu category, alphanumeric only, |
| status:       | mostly decoration |
| author:       | mostly decoration |
| license:      | mostly decoration / unused |
| src:          | mostly decoration (source code origin) |
| config:       | list of config options (pseudo JSOL format) |
| vars:         | list of extra script parameters (like config:) |
| depends:      | ought to list prerequired plugins, e.g. depends: funcs_base |
| encoding:     | "utf-8" if Unicode used (this field is used like in Ruby/Python; though entirely decorative for Powershell) |
| key:          | regex for the CLI mode |
| keycode:      | shortcut for the GUI mode (unimplemented) |
| param:        | additional input / obsolete: use vars: {} dict now |
| hidden: 0     | if set, omits the toolblock area |
| nomenu: 1     | hide menut entry (see `hidden:`) |
| repeat: 1     | for CLI version: asks if script should be repeated |
| clipboard: auto | add script output to clipboard automatically (not enabled) |
| shortcut: 7   | add icon to shortcut toolbar/ribbon (custom sorting) |
| sort: 123     | largely unused, but can influence script ordering |

Normally the display and menu arrangement of scripts is driven by key: and title: -
both grouped by category: of course. In specific cases `sort:` might be used to
override it.


### type:

The execution mode influences how scripts are run:

| type:inline | runs within CC output pane (default) |
| type:window | starts script in standalone CLI powershell window |
| type:cli    | equivalent to type:window, but for the CLI version (which interprets it as "inline") |
| type:init   | run once during initialization |
| type:init-gui | run once during GUI construction (in WPF runspace) |
| type:main   | internal functions (this is decoration for the modules/* |



### config:

The `config:` field is the only structured plugin meta data entry. It allows to
describe/predefine some `$cfg.vars`. It follows the JSOL-style scheme:

    # config:
    #     { name: threaded, type: bool, value: 0, title: GUI runspace? }
    #     { name: domain, type: str, value: WORKWORK }

It's not used much, but for the configedit.ps1 script and the %APPDATA% file.
Most default options are preset in the starter.ps1 still.

Purpose is to have *plugins* define custom global settings. Tools/scripts may
use them still. (Because; why not?)


### vars:

`vars:` is now used to enlist extra script/tool input variables. It's structured like `config:` now, as the scheme is nearly identical. It supports following types:

    # vars:
    #     { name: hosty, type: str, value: $machine, title: host name }
    #     { name: use_ping, type: bool, value: 1, description: ... }
    #     { name: csv, type: text, value: "long text...", description: multiline input }
    #     { name: flag, type: select, value: "abc|def|xyz", description: combobox }

There's also a `type: button` which effectively behaves like a boolean. Note that there's no decided implementation for text/multiline parameter passing to external scripts yet.

The older **`# param: extra, vars`** list is still supported, but obsolete now. Just to elaborate on the purpose of both:

 * The `vars:`/`param:` meta field is primarily meant for scripts that run in `window`/`cli` mode, so the vars can be passed per cmdline.
 * Standard field and variable names are: machine, username, bulkcsv.
   Those become $machine, $username vars autoamtically in the GUI. (But not in the CLI version...)
 * Listing an unknown field name here, <s>adds a text input or dropdown field to one of the toolblocks</s> brings up an input box now.
 * Comboboxes are created whenever a like-named  "data/combobox.fieldname.txt"
   file exists. (Or better with a predefined `select:` type and list now.)
 * For `inline` scripts any extra field becomes available as `$extra` or `$var3` etc.
 * The GUI `Read-Host` wrapper interprets the field names from `Param($x=(Read-Host "extravar"), …)`
   to return the right GUI text field value.
 * For CLI (type:window) scripts, the standard+extraneous field names are passed as CMD arguments. = Which is the whole point of the `#param:` field.

</blockquote>


### key: a1|b2|c3

The `key:` field defines an entry for the CLI interface. The prompt there expects a shortcut to invoke scripts with. If a tool/ doesn't have one, it won't be available.

Mainly it just lists one or two alternatives to invoke a script:

    # key: s5|start5

So the prompt would allow you to enter "s5" or "s5" for example.  
Most scripts that expect input like a username or hostname can be started with "s5 localhost" or "s5 user123" as well. (The prompt supports arguments, yes.)

But back to the key: **regex**. You can define more complex alternatives like: 
    s5|sta?r?t|or-?else|teee+st

It's sometimes convenient to add more flexibility and typo support, but avoid listing a hundred spellings or aliases of course.


## Repo scan:

This fossil setup already provides the means to implement a full plugin/update system later on:  
[http://fossil.include-once.org/repo.json/clickycoloury/tools/\*/\*.ps1](http://fossil.include-once.org/repo.json/clickycoloury/tools/*/*.ps1)  


## alternative: $menu list

CC does not strictly depend on PMD comments. However, the alternative
would be to manually manage a script array:

    $menu = @(
        @{
           title = "Locked out users"
           description = "do some stuff"
           category = "cmd"
           fn = "tools\script5.ps1'
           type = "inline"
        },
        @{
           title = "Other tool"
           description = "do some stuff"
           category = "extras"
           fn = "tools\other_scr.ps1'
           type = "inline"
        },
    )

Which, let's be honest, is enticing to noone.


Z 0f8dd1d6a60a58bc78c626b84f21e02e