miller icon indicating copy to clipboard operation
miller copied to clipboard

Support user-defined verbs

Open balki opened this issue 5 months ago • 4 comments

miller verbs are great. Easy to use, saves key strokes and easy to understand. It would be nice to extend those benefits to user-defined verbs.

Proposal

Users can create new verbs by registering them using below function. This function will be called in a miller file loaded using --[m]load.

register_verb(func, name, description, flags)
  • name is string
  • description is string for use in mlr help
  • flags is an array of flag which is a map with keys short, long, description, type, default. At least one of short or long is required. Rest are of them are optional.
  • type can be "bool", "single", or "multi". default is "single". "multi" means it can occur multiple times. e.g. verb -f arg1-f arg2 -f arg3. Accessed in the function as a list arg["f"] will be ["arg1", "arg2", "arg3"].
  • when type is bool, it can be turned off with --no- prefix. i.e. --no-longname.
  • bool flags can be coalesced. i.e. -xyz foo is same as -x -y -z foo.
  • one of the flag can have long set to [POS] which refers to positional argument. type is always single
  • func is a miller function that will be called with one argument args. It is a map with passed flags.

Example

register_verb(bconv, "bconv", "Convert bytes to KB, MB, GB or TB", [
{
"short": "s",
"long":"source",
"type":"single",
"default":"B",
"description":"Source unit. One of B, KB, MB, GB"
},
{
"short": "t",
"long":"target",
"type":"single",
"default": "auto",
"description":"Target unit. One of B, KB, MB, GB, auto. If auto, appropriate unit is chosen"
},
{
"short": "x",
"long":"suffix",
"type":"bool",
"default":true,
"description":"Add suffix after conversion. E.g. 2.4 MB"
},
{
"long":"[POS]",
"description":"comma separated list of fields to convert"
}
]
)

func bconf(args) {
if (args["suffix"]) { ... }
}

Namespace

  1. Keep user defined verbs same namespace as standard ones. (similar to user defined functions).
  2. Have user-defined verbs start with capital letter. Similar to go functions.
  3. [my choice] Prefix user-defined verbs with u: or a different prefix. E.g. mlr --l2p u:bconv Memory,Swap then head.

balki avatar Jul 17 '25 15:07 balki

@balki so the verb-implementation language would be the Miller DSL?

johnkerl avatar Jul 17 '25 16:07 johnkerl

It seems to me a great idea


Scusami per la brevità, ti sto scrivendo dal cellulare.

website: https://medium.com/tantotanto 38° 7' 48" N, 13° 21' 9" E EPSG:4326

Il gio 17 lug 2025, 17:24 Balki @.***> ha scritto:

balki created an issue (johnkerl/miller#1836) https://github.com/johnkerl/miller/issues/1836

miller verbs are great. Easy to use, saves key strokes and easy to understand. It would be nice to extend those benefits to user-defined verbs. Proposal

Users can create new verbs by registering them using below function. This function will be called in a miller file loaded using --[m]load.

register_verb(func, name, description, flags)

  • name is string
  • description is string for use in mlr help
  • flags is an array of flag which is a map with keys short, long, description, type, default. Atleast one of short or long is required. Rest are of them are optional.
  • type can be "bool", "single", or "multi". default is "single". "multi" means it can occur multiple times. e.g. verb -f arg1-f arg2 -f arg3. Accessed in the function as a list arg["f"] will be ["arg1", "arg2", "arg3"].
  • when type is bool, it can be turned off with --no- prefix. i.e. --no-longname.
  • bool flags can be coalesced. i.e. -xyz foo is same as -x -y -z foo.
  • one of the flag can have long set to [POS] which refers to positional argument. type is always single
  • func is a miller function that will be called with one argument args. It is a map with passed flags.

Example

register_verb(bconv, "bconv", "Convert bytes to KB, MB, GB or TB", [ { "short": "s", "long":"source", "type":"single", "default":"B", "description":"Source unit. One of B, KB, MB, GB" }, { "short": "t", "long":"target", "type":"single", "default": "auto", "description":"Target unit. One of B, KB, MB, GB, auto. If auto, appropriate unit is chosen" }, { "short": "x", "long":"suffix", "type":"flag", "default":true, "description":"Add suffix after conversion. E.g. 2.4 MB" }, { "long":"[POS]", "description":"comma seperated list of fields to convert" } ] )

func bconf(args) { if (args["suffix"]) { ... } }

Namespace

  1. Keep user defined verbs same namespace as standard ones. (similar to user defined functions).
  2. Have user-defined verbs start with capiltal letter. Similar to go functions.
  3. [my choice] Prefix user-defined verbs with u: or a different prefix. E.g. mlr --l2p u:bconv Memory,Swap then head.

— Reply to this email directly, view it on GitHub https://github.com/johnkerl/miller/issues/1836, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAHPD6QAVWB2EPGEQ5LR533I65ZTAVCNFSM6AAAAACBYFN5K6VHI2DSMVQWIX3LMV43ASLTON2WKOZTGIZTSOJZGE4TQMI . You are receiving this because you are subscribed to this thread.Message ID: @.***>

aborruso avatar Jul 17 '25 16:07 aborruso

@balki so the verb-implementation language would be the Miller DSL?

Yes. I think miller DSL can handle most use-cases and would be fast enough. Using golang plugin system will require to recompile and not easy for many users.

This proposal does not cover verbs that need to look across multiple records. May be we can have another register function like register_verb3(func_begin, func_process, func_end, name, desc, flags). func_end, can emit all records after aggregating.

balki avatar Jul 17 '25 16:07 balki

Using golang plugin system will require to recompile and not easy for many users.

100% agree 😎

johnkerl avatar Jul 17 '25 16:07 johnkerl