Powershell GUI fronted (WPF) to run categorized console scripts

⌈⌋ branch:  ClickyColoury


plugin meta data

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 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.

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)
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 variable names
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/*

param: extra, fields

Defines more input variables/fields. Now this is mostly a workaround, but with interesting by-features.

  • This 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, adds a text input or dropdown field to one of the toolblocks.
  • Comboboxes are created whenever a like-named "data/combobox.feldname.txt" file exists.
  • 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.

ToDo: future versions will probably use the same structure as config: however.

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?)

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

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.