github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/docs/commands/autocomplete.md (about)

     1  # `autocomplete`
     2  
     3  > Set definitions for tab-completion in the command line
     4  
     5  ## Description
     6  
     7  `autocomplete` digests a JSON schema and uses that to define the tab-
     8  completion rules for suggestions in the interactive command line.
     9  
    10  ## Usage
    11  
    12  ```
    13  autocomplete get [ command ] -> <stdout>
    14  
    15  autocomplete set command { mxjson }
    16  ```
    17  
    18  ## Flags
    19  
    20  * `get`
    21      output all autocompletion schemas
    22  * `set`
    23      define a new autocompletion schema
    24  
    25  ## Detail
    26  
    27  ### Undefining autocomplete
    28  
    29  Currently there is no support for undefining an autocompletion rule however
    30  you can overwrite existing rules.
    31  
    32  ## Directives
    33  
    34  The directives are listed below.
    35  
    36  <div id="toc">
    37  
    38  - [Alias](#alias)
    39  - [AllowAny](#allowany)
    40  - [AllowMultiple](#allowmultiple)
    41  - [AnyValue](#anyvalue)
    42  - [AutoBranch](#autobranch)
    43  - [CacheTTL](#cachettl)
    44  - [Dynamic](#dynamic)
    45  - [DynamicDesc](#dynamicdesc)
    46  - [DynamicPreview](#dynamicpreview)
    47  - [ExecCmdline](#execcmdline)
    48  - [FileRegexp](#fileregexp)
    49  - [FlagValues](#flagvalues)
    50    - [Defaults for matched flags](#defaults-for-matched-flags)
    51    - [Defaults for any flags (including unmatched)](#defaults-for-any-flags-including-unmatched)
    52  - [Flags](#flags)
    53  - [FlagsDesc](#flagsdesc)
    54  - [Goto](#goto)
    55  - [IgnorePrefix](#ignoreprefix)
    56  - [ImportCompletion](#importcompletion)
    57  - [IncDirs](#incdirs)
    58  - [IncExeAll](#incexeall)
    59  - [IncExePath](#incexepath)
    60  - [IncFiles](#incfiles)
    61  - [IncManPage](#incmanpage)
    62  - [ListView](#listview)
    63  - [NestedCommand](#nestedcommand)
    64  - [Optional](#optional)
    65  
    66  </div>
    67  
    68  ### Alias
    69  
    70  > Value: `str` (default: empty)
    71  
    72  Aliases are used inside **FlagValues** as a way of pointing one flag to another
    73  without duplicating code. eg `-v` and `--version` might be the same flag. Or
    74  `-?`, `-h` and `--help`. With **Alias** you can write the definitions for one
    75  flag and then point all the synonyms as an alias to that definition.
    76  
    77  ### AllowAny
    78  
    79  > Value: `bool` (default: `false`)
    80  
    81  The way autocompletion works in Murex is the suggestion engine looks for
    82  matches and if it fines one, it then moves onto the next index in the JSON
    83  schema. This means unexpected values typed in the interactive terminal will
    84  break the suggestion engine's ability to predict what the next expected
    85  parameter should be. Setting **AllowAny** to `true` tells the suggestion
    86  engine to accept any value as the next parameter thus allowing it to then
    87  predict the next parameter afterwards.
    88  
    89  This directive isn't usually necessary because such fields are often the last
    90  parameter or most parameters can be detectable with a reasonable amount of
    91  effort. However **AllowAny** is often required for more complex command line
    92  tools.
    93  
    94  ### AllowMultiple
    95  
    96  > Value: `bool` (default: `false`)
    97  
    98  Set to `true` to enable multiple parameters following the same rules as defined
    99  in this index. For example the following will suggest directories on each tab
   100  for multiple parameters:
   101  
   102  ```
   103  autocomplete set example %[{
   104      IncDirs: true
   105      AllowMultiple: true
   106  }]
   107  ```
   108  
   109  ### AnyValue
   110  
   111  Deprecated. Please use **AllowAny** instead.
   112  
   113  ### AutoBranch
   114  
   115  > Value `bool` (default: `false`)
   116  
   117  Use this in conjunction with **Dynamic**. If the return is an array of paths,
   118  for example `[ "/home/foo", "/home/bar" ]` then **AutoBranch** will return
   119  the following patterns in the command line:
   120  
   121  ```
   122  » example [tab]
   123  # suggests "/home/"
   124  
   125  » example /home/[tab]
   126  # suggests "/home/foo" and "/home/bar"
   127  ```
   128  
   129  Please note that **AutoBranch**'s behavior is also dependant on a "shell"
   130  `config` setting, "recursive-enabled":
   131  
   132  ```
   133  » config get shell recursive-enabled
   134  true
   135  ```
   136  
   137  ### CacheTTL
   138  
   139  > Value: `int` (default: `5`)
   140  
   141  Dynamic autocompletions (via **Dynamic** or **DynamicDesc**) are cached to
   142  improve interactivity performance. By default the cache is very small but you
   143  can increase that cache or even disable it entirely. Setting this value will
   144  define the duration (in seconds) to cache that autocompletion.
   145  
   146  If you wish to disable this then set **CacheTTL** to `-1`.
   147  
   148  This directive needs to live in the very first definition and affects all
   149  autocompletes within the rest of the command. For example
   150  
   151  ```
   152  autocomplete set foobar %[
   153      {
   154          Flags: [ --foo, --bar ]
   155          CacheTTL: 60
   156      }
   157      {
   158          Dynamic: '{
   159              a [Monday..Friday]
   160              sleep 3
   161          }'
   162      }
   163  ]
   164  ```
   165  
   166  Here the days of the week take 3 seconds to show up as autocompletion
   167  suggestions the first time and instantly for the next 60 seconds after.
   168  
   169  ### Dynamic
   170  
   171  > Value: code block as a `str` (default: empty)
   172  
   173  This is a Murex block which returns an array of suggestions.
   174  
   175  Code inside that block are executed like a function and the parameters will
   176  mirror the same as those parameters entered in the interactive terminal.
   177  
   178  Two variables are created for each **Dynamic** function:
   179  
   180  - `ISMETHOD`: `true` if the command being autocompleted is going to run as a
   181    pipelined method. `false` if it isn't.
   182  
   183  - `PREFIX`: contains the partial term. For example if you typed `hello wor[tab]`
   184    then `$PREFIX` would be set to **wor** for **hello**'s
   185    autocompletion.
   186  
   187  The expected STDOUT should be an array (list) of any data type. For example:
   188  
   189  ```
   190  [
   191      "Monday",
   192      "Tuesday",
   193      "Wednesday",
   194      "Thursday",
   195      "Friday"
   196  ]
   197  ```
   198  
   199  You can additionally include suggestions if any of the array items exactly
   200  matches any of the following strings:
   201  
   202  * `@IncFiles`   ([read more](#incfiles-boolean-false))
   203  * `@IncDirs`    ([read more](#incdirs-boolean-false))
   204  * `@IncExePath` ([read more](#incexepath-boolean-false))
   205  * `@IncExeAll`  ([read more](#incexeall-boolean-false))
   206  * `@IncManPage` ([read more](#incmanpage-boolean-false))
   207  
   208  ### DynamicDesc
   209  
   210  > Value: code block as a `str` (default: empty)
   211  
   212  This is very similar to **Dynamic** except your function should return a
   213  map instead of an array. Where each key is the suggestion and the value is
   214  a description.
   215  
   216  The description will appear either in the hint text or alongside the
   217  suggestion - depending on which suggestion "popup" you define (see
   218  **ListView**).
   219  
   220  Two variables are created for each **Dynamic** function:
   221  
   222  - `ISMETHOD`: `true` if the command being autocompleted is going to run as a
   223    pipelined method. `false` if it isn't.
   224  
   225  - `PREFIX`: contains the partial term. For example if you typed `hello wor[tab]`
   226    then `$PREFIX` would be set to **wor** for **hello**'s
   227    autocompletion.
   228  
   229  The expected STDOUT should be an object (map) of any data type. The key is the
   230  autocompletion suggestion, with the value being the description. For example:
   231  
   232  ```
   233  {
   234      "Monday": "First day of the week",
   235      "Tuesday": "Second day of the week",
   236      "Wednesday": "Third day of the week"
   237      "Thursday": "Forth day of the week",
   238      "Friday": "Fifth day of the week",
   239  }
   240  ```
   241  
   242  ### DynamicPreview
   243  
   244  > Value: code block as a `str` (default: empty)
   245  
   246  The **DynamicPreview** directive is used to populate the `[f1]` preview screen.
   247  
   248  STDOUT and STDERR are passed directly to the preview frame.
   249  
   250  ### ExecCmdline
   251  
   252  > Value: `bool` (default: `false`)
   253  
   254  Sometimes you'd want your autocomplete suggestions to aware of the output
   255  returned from the commands that preceded it. For example the suggestions
   256  for `[` (index) will depend entirely on what data is piped into it.
   257  
   258  **ExecCmdline** tells Murex to run the commandline up until the command
   259  which your cursor is editing and pipe that output to the STDIN of that
   260  commands **Dynamic** or **DynamicDesc** code block.
   261  
   262  > This is a dangerous feature to enable so **ExecCmdline** is only honoured
   263  > if the commandline is considered "safe". **Dynamic** / **DynamicDesc**
   264  > will still be executed however if the commandline is "unsafe" then your
   265  > dynamic autocompletion blocks will have no STDIN.
   266  
   267  Because this is a dangerous feature, your partial commandline will only
   268  execute if the following conditions are met:
   269  
   270  - the commandline must be one pipeline (eg `;` tokens are not allowed)
   271  - the commandline must not have any new line characters
   272  - there must not be any redirection, including named pipes
   273    (eg `cmd <namedpipe>`) and the STDOUT/STDERR switch token (`?`)
   274  - the commandline doesn't inline any variables (`$strings`, `@arrays`) or
   275    functions (`${subshell}`, `$[index]`)
   276  - lastly all commands are whitelisted in "safe-commands"
   277    (`config get shell safe-commands`)
   278  
   279  If these criteria are met, the commandline is considered "safe"; if any of
   280  those conditions fail then the commandline is considered "unsafe".
   281  
   282  Murex will come with a number of sane commands already included in its
   283  `safe-commands` whitelist however you can add or remove them using `config`
   284  
   285  ```
   286  » function foobar { -> match foobar }
   287  » config eval shell safe-commands { -> append foobar }
   288  ```
   289  
   290  Remember that **ExecCmdline** is designed to be included with either
   291  **Dynamic** or **DynamicDesc** and those code blocks would need to read
   292  from STDIN:
   293  
   294  ```
   295  autocomplete set "[" %[{
   296      AnyValue: true
   297      AllowMultiple: true
   298      ExecCmdline: true
   299      Dynamic: '{
   300          switch ${ get-type stdin } {
   301              case * {
   302                  <stdin> -> [ 0: ] -> format json -> [ 0 ]
   303              }
   304  
   305              catch {
   306                  <stdin> -> formap k v { out $k } -> cast str -> append "]"
   307              }
   308          }
   309      }'
   310  }]
   311  ```
   312  
   313  ### FileRegexp
   314  
   315  > Value: `str` (default: empty)
   316  
   317  When set in conjunction with **IncFiles**, this directive will filter on files
   318  files which match the regexp string. eg to only show ".txt" extensions you can
   319  use the following:
   320  
   321  ```
   322  autocomplete set notepad.exe %[{
   323      IncFiles: true
   324      FileRegexp: (\.txt)
   325  }]
   326  ```
   327  
   328  > Please note that you may need to double escape any regexp strings: escaping
   329  > the `.` match and then also escaping the escape character in JSON. It is
   330  > recommended you use the `mxjson` method of quoting using parentheses as this
   331  > will compile that string into JSON, automatically adding additional escaping
   332  > where required.
   333  
   334  ### FlagValues
   335  
   336  > Value: map of arrays (default: empty)
   337  
   338  This is a map of the flags with the values being the same array of directive
   339  as the top level.
   340  
   341  This allows you to nest operations by flags. eg when a flag might accept
   342  multiple parameters.
   343  
   344  **FlagValues** takes a map of arrays, eg
   345  
   346  ```
   347  autocomplete set example %[{
   348      Flags: [ add, delete ]
   349      FlagValues: {
   350          add: [{
   351              Flags: [ foo ]
   352          }]
   353          delete: [{
   354              Flags: [ bar ]
   355          }]
   356      }
   357  }]
   358  ```
   359  
   360  ...will provide "foo" as a suggestion to `example add`, and "bar" as a
   361  suggestion to `example delete`.
   362  
   363  #### Defaults for matched flags
   364  
   365  You can set default properties to all matched flags by using `*` as a
   366  **FlagValues** value. To expand the above example...
   367  
   368  ```
   369  autocomplete set example %[{
   370      Flags: [ add, delete ]
   371      FlagValues: {
   372          add: [{
   373              Flags: [ foo ]
   374          }]
   375          delete: [{
   376              Flags: [ bar ]
   377          }]
   378          "*": [{
   379              IncFiles
   380          }]
   381      }
   382  }]
   383  ```
   384  
   385  ...in this code we are saying not only does "add" support "foo" and "delete"
   386  supports "bar", but both "add" and "delete" also supports any filesystem files.
   387  
   388  This default only applies if there is a matched **Flags** or **FlagValues**.
   389  
   390  #### Defaults for any flags (including unmatched)
   391  
   392  If you wanted a default which applied to all **FlagValues**, even when the flag
   393  wasn't matched, then you can use a zero length string (""). For example
   394  
   395  ```
   396  autocomplete set example %[{
   397      Flags: [ add, delete ]
   398      FlagValues: {
   399          add: [{
   400              Flags: [ foo ]
   401          }],
   402          delete: [{
   403              Flags: [ bar ]
   404          }],
   405          "": [{
   406              IncFiles: true
   407          }]
   408      }
   409  }]
   410  ```
   411  
   412  ### Flags
   413  
   414  > Value: array of strings (default is auto-populated from man pages)
   415  
   416  Setting **Flags** is the fastest and easiest way to populate suggestions
   417  because it is just an array of strings. eg
   418  
   419  ```
   420  autocomplete set example %[{
   421      Flags: [ foo, bar ]
   422  }]
   423  ```
   424  
   425  If a command doesn't **Flags** already defined when you request a completion
   426  suggestion but that command does have a man page, then **Flags** will be
   427  automatically populated with any flags identified from an a quick parse of
   428  the man page. However because man pages are written to be human readable
   429  rather than machine parsable, there may not be a 100% success rate with the
   430  automatic man page parsing.
   431  
   432  ### FlagsDesc
   433  
   434  > Value: map of strings (default: empty)
   435  
   436  This is the same concept as **Flags** except it is a map with the suggestion
   437  as a key and description as a value. This distinction is the same as the
   438  difference between **Dynamic** and **DynamicDesc**.
   439  
   440  Please note that currently man page parsing cannot provide a description so
   441  only **Flags** get auto-populated.
   442  
   443  ### Goto
   444  
   445  > Value: `str` (default: empty)
   446  
   447  This is a `goto` in programming terms. While "ugly" it does allow for quick and
   448  easy structural definitions without resorting to writing the entire
   449  autocomplete in code.
   450  
   451  **Goto** takes a string which represents the path to jump to from the top level
   452  of that autocomplete definition. The path should look something like:
   453  `/int/string/int/string....` where
   454  
   455  - the first character is the separator,
   456  
   457  - the first value is an integer that relates to the index in your autocomplete
   458    array,
   459  
   460  - the second value is a string which points to the flag value map (if you
   461    defined **FlagValues**),
   462  
   463  - the third value is the integer of the autocomplete array inside that
   464    **FlagValues** map,
   465  
   466  - ...and so on as necessary.
   467  
   468  An example of a really simple **Goto**:
   469  
   470  ```
   471  autocomplete set dd %[
   472      {
   473          Flags: [ "if=", "of=", "bs=", "iflag=", "oflag=", "count=", "status=" ]
   474          FlagValues: {
   475              "if": [{
   476                  IncFiles: true
   477              }]
   478              "of": [{
   479                  IncFiles: true
   480              }]
   481              "*": [{
   482                  AllowAny: true
   483              }]
   484          }
   485      },
   486      {
   487          Goto: "/0"
   488      }
   489  ]
   490  ```
   491  
   492  **Goto** is given precedence over any other directive. So ensure it's the only
   493  directive in it's group.
   494  
   495  ### IgnorePrefix
   496  
   497  > Value: `bool` (default: `false`)
   498  
   499  When set to `true`, this allows **Dynamic** and **DynamicDesc** functions to
   500  return every result and not just those that match the partial term (as would
   501  normally be the default).
   502  
   503  ### ImportCompletion
   504  
   505  > Value: `str` (default: empty)
   506  
   507  This allows you to import autocompletion config from another command. Similar
   508  in purpose to **NestedCommand** except where **NestedCommand** will dynamically
   509  select the command name, **ImportCompletion** hardcodes it. For example:
   510  
   511  ```
   512  autocomplete set murex-package %[{
   513      FlagsDesc: {
   514          # ...cropped out...
   515          git: "Run `git` against a package"
   516      }
   517      FlagValues: {
   518          # ...cropped out...
   519          git: [
   520              {
   521                  # list packages to run `git` against
   522                  Dynamic: %({ murex-package list packages })
   523              }
   524              {
   525                  # include `git` autocompletions as the next set of parameters
   526                  ImportCompletion: git
   527              }
   528          ]
   529      }
   530  }]
   531  ```
   532  
   533  The above code allows you to type `murex-package git package-name [tab]`, where
   534  `[tab]` will be the completions for `git`.
   535  
   536  ### IncDirs
   537  
   538  > Value: `bool` (default: `false`)
   539  
   540  Enable to include directories.
   541  
   542  Not needed if **IncFiles** is set to `true`.
   543  
   544  Behavior of this directive can be altered with `config set shell
   545  recursive-enabled`
   546  
   547  ### IncExeAll
   548  
   549  > Value: `bool` (default: `false`)
   550  
   551  Enable this to any executables. Suggestions will include aliases, functions
   552  builtins and any executables in `$PATH`. It will not include private functions.
   553  
   554  ### IncExePath
   555  
   556  > Value: `bool` (default: `false`)
   557  
   558  Enable this to include any executables in `$PATH`. Suggestions will not include
   559  aliases, functions nor privates.
   560  
   561  ### IncFiles
   562  
   563  > Value: `bool` (default: `true`)
   564  
   565  Include files and directories. This is enabled by default for any commands
   566  that don't have autocomplete defined but you will need to manually enable
   567  it in any `autocomplete` schemas you create and want files as part of the
   568  suggestions.
   569  
   570  If you want to filter files based on file name then you can set a regexp
   571  string to match to using **FileRegexp**.
   572  
   573  ### IncManPage
   574  
   575  > Value: `bool` (default: `false`)
   576  
   577  The default behavior for commands with no autocomplete defined is to parse the
   578  man page and use those results. If a custom autocomplete is defined then that
   579  man page parser is disabled by default. You can re-enable it and include its
   580  results with other flags and behaviors you define by using this directive.
   581  
   582  ### ListView
   583  
   584  > Value: `bool` (default: `false`)
   585  
   586  This alters the appearance of the autocompletion suggestions "popup". Rather
   587  than suggestions being in a grid layout (with descriptions overwriting the
   588  hint text) the suggestions are in a list view with the descriptions next to
   589  them on the same row (similar to how an IDE might display it's suggestions).
   590  
   591  ### NestedCommand
   592  
   593  > Value: `bool` (default: `false`)
   594  
   595  Only enable this if the command you are autocompleting is a nested parameter
   596  of the parent command you have types. For example with `sudo`, once you've
   597  typed the command name you wish to elivate, then you would want suggestions
   598  for that command rather than for `sudo` itself.
   599  
   600  ### Optional
   601  
   602  > Value: `bool` (default: `false`)
   603  
   604  Specifies if a match is required for the index in this schema. ie optional
   605  flags.
   606  
   607  ## See Also
   608  
   609  * [`<stdin>`](../commands/stdin.md):
   610    Read the STDIN belonging to the parent code block
   611  * [`[ Index ]`](../parser/item-index.md):
   612    Outputs an element from an array, map or table
   613  * [`alias`](../commands/alias.md):
   614    Create an alias for a command
   615  * [`config`](../commands/config.md):
   616    Query or define Murex runtime settings
   617  * [`function`](../commands/function.md):
   618    Define a function block
   619  * [`get-type`](../commands/get-type.md):
   620    Returns the data-type of a variable or pipe
   621  * [`private`](../commands/private.md):
   622    Define a private function block
   623  * [`summary` ](../commands/summary.md):
   624    Defines a summary help text for a command
   625  * [`switch`](../commands/switch.md):
   626    Blocks of cascading conditionals
   627  * [mxjson](../types/mxjson.md):
   628    Murex-flavoured JSON (deprecated)
   629  
   630  <hr/>
   631  
   632  This document was generated from [builtins/core/autocomplete/autocomplete_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/autocomplete/autocomplete_doc.yaml).