wezterm icon indicating copy to clipboard operation
wezterm copied to clipboard

A way for user to create custom cli options

Open MuhammedZakir opened this issue 3 years ago • 4 comments

Note: whenever I mention cli args in this post, unless explicitly specified, all of them is in the namespace wezterm cli, i.e. for instance, if I mention workspace switch-by name <name>, the command to execute will be wezterm cli workspace switch-by-name <name>.

Is your feature request related to a problem? Please describe.

I wanted some cli flags related workspace like workspace switch-by-name <name>, workspace switch-by-index [--relative] <index>, etc. When I thought about it, I realised that for most cli options, there are corresponding Lua functions, which made me think it would be cool if we users can create custom cli options. This way, user can create cli options instead of asking for it to be added here. Of course, for cli options like spawn, it is better to implement them by default.

Describe the solution you'd like

A way to let user create new cli options. It could be called as, e.g. wezterm cli user_command <options>.

Describe alternatives you've considered

NIL.

Additional context

I could think of two ways to implement this:

  1. A callback function, which will be passed a table of arguments.
    • Easy to make mistakes when parsing args.
  2. A table of options, with option-names as keys and corresponding callback functions as values.
    • An important benefit is "automatic validation", which should avoid some common mistakes.
    • Using the table, WezTerm will
      • generate hierarchical cli options, including boolean flags.
      • generate help messages.
      • validate argument count.
    • The callback function may return an optional exit code along with optional output.
      • If output is a string, it will be printed to stdout.
      • If it is a table with keys stdout and/or stderr, the values will be printed to corresponding file descriptor.

An example for #2 (api, names, etc. can be different; this is more to show the sub-features I am hoping for):

custom_cli_ops = {
   workspace = {
      switch = {
         name = {
            _help_ = "Switch to given workspace name.",
            _arg_count_ = 1,
            _call_ = function(ws_name)
               if does_workspace_name_exist(ws_name) then
                  mux.set_active_workspace(ws_name)
                  return
               else
                  return 3, { stderr = "error: no workspace named, " .. ws_name }
               end
            end
         },
         index = {
            _help_ = "Switch to given workspace index.",
            _flags_ = { 
               relative = "The given index is relative to the current workspace. See `SwitchWorkspaceRelative` for details."
            },
            _arg_count_ = 1,
            _call_ = function(flags, ws_index)
               if flags.relative then
                  wezterm.action_callback(function(win)
                     win:perform_action(act.SwitchWorkspaceRelative(ws_index))
                  end)
               else
                  if does_workspace_index_exist(ws_index) then
                     mux.set_active_workspace(mux.get_workspace_names()[ws_index])
                  else
                     return 3, { stderr = "error: wrong workspace index, " .. ws_index }
                  end
               end
               return
            end
         }
      }
   }
}

With the above code, the generated valid commands will be (assuming these will be in user_command):

wezterm cli user_command workspace name <name>
wezterm cli user_command workspace index [--relative] <index>

MuhammedZakir avatar Jul 12 '22 19:07 MuhammedZakir

I was thinking earlier today that it would be nice to allow running a lua script against the internal lua runtime and set of modules. For example, the new color processing functions are quite powerful and can be used on the fly, but might be useful to pre-compute stuff and share it out beyond just wezterm. That's awkward if it is all embedded in the main config file.

What I had in mind was something like wezterm eval-lua -- "inline lua code" and wezterm run-lua /path/to/file.lua args.

Regarding the specific use case and examples you mentioned, there are some complexities and potential for mismatched expectations:

  • Spawning something via the CLI will start a new process, which means that the lua code will run in a different process/address space than the currently running GUI(s) or mux server(s)
  • There is logic in wezterm cli to resolve a running mux server (including the GUI), and use that as the target of wezterm's mux protocol, but that is scoped to things that are expressable by the mux protocol
  • The lua wezterm.mux module operates on the in-process Mux, and doesn't communicate via the mux protocol
  • The lua wezterm.gui and gui window and pane objects operate on the in-gui-process equivalent objects and have no equivalents in the remote mux protocol
  • There is no lua binding for the remote mux protocol

The result of that is, even with the ability to run a lua script, I think it would be quite frustrating to try to use mux/window management functions in it, because it would be difficult to map the right things in the right places.

wez avatar Jul 12 '22 19:07 wez

That's what I feared, but thought I might as well post it as I really don't know the internals of WezTerm.

As the config will be evaluated when WezTerm is started, I thought that wezterm cli user_command could be implemented kind of like emitting event using key assignment and triggering/executing the registered function. I was hoping that whatever is possible in event callbacks are possible here.

MuhammedZakir avatar Jul 12 '22 20:07 MuhammedZakir

Sorry to bump old thread, but I found myself also wanting what OP suggest.

I understand the limitations You mentioned about how Mux's LUA is independent from GUI's LUA, so here is my idea: Since there already is a "Send Text" command that is implemented, couldn't we simply add another one, ie. "Send lua [to eval]", that would be nothing more then a 'send text' wrapper with some flag to tell the client to interpret it differently. I imagine this should be fairly straighforward thing to implement? Then the client would run it in it's context normally just as if it was triggered from the GUI, with keybinds for example.

While this isn't 100% what OP suggests (It wouldn't allow to write a cross mux-gui lua code that could access multiple windows at once), I think it's fair to say that 'remote' access to even single GUI client, would still give us most of functionalities that relates to this problem.

I hope this makes sense, and it's not just me completely misunderstanding the problem.

GusIG avatar Apr 15 '24 15:04 GusIG