Calling a custom package/minormode with arguments in RV?

Good morning,

I was wondering if it is possible to call a minormode or custom package of another RV session with an argument. For example, if I wrote a new package/minormode that will, say, take a path to a json file that contains a huge list of sources that need to be added in, along with their names (so that I can rename the source after adding), how do I call it and pass the path as an argument?

I know that I can send events to another RV and if the minormode has a keyboard shortcut, I can call it that way, with something like send event ‘key-down–alt–j’, but I was wondering how to do it in a way that I can pass an argument.

Thank you so much for your time.

2 Likes

Hi!

Thanks for the great question!

While there are probably lots of ways of doing, there are two well-supported methods. You can either use RV’s commands.commandLineFlag, or external events.

Command Line Flags

The original method of doing this is using command line flags using the -flags argument for RV. The API call commands.commandLineFlag can obtain what flags RV was launched with, and optionally values that were passed.

A popular existing built into RV’s mode manager can be called with -flags ModeManagerVerbose. Within RV’s internal ModeManager, RV uses the commands.commandLineFlag to check if this was set. Because it is, the ModeManager outputs additional debugging information (such as what packages were loaded, from where, and how much time they took to load). The -flags approach is useful if you want an application state to exist, especially on startup. Since the flags are populated early and they are persistent, you can query them early or late in your application life cycle and RV will know what flags you launched with.

The API reference for this command looks like this:

commands.commandLineFlag( string; string flagName, string defaultValue = nil )

The RV command line has an option -flags . Arguments after -flags can have the form foo or foo=bar . commandLineFlag() will find the value of one of these name value pairs. If the argument does not have a value, then true will be returned.

For example:
 shell> rv -flags A B=foo
commandLineFlag("A") would return true

commandLineFlag("B") would return foo
Python Function Signature Note

The API is notated in Mu syntax. When converting Mu to Python, the first item in the function signature is the return type. In Python, this would be called with:

import rv
result = rv.commands.commandLineFlag("flagName", 42)

This works well, but it doesn’t have any sense of command-flow with a direct point where anything is executed. That leads us to our other option:

External Events

Since RV 6.2.8, RV supports the ability to trigger the regular event system from the command line. You can use -sendEvent <eventName> <eventContents> to call an event of your choosing in RV. To keep the event types to events intended to come from outside of the app, the event name is prepended with external-.

This allows you to handle command-line arguments similarly to how you would handle your keyboard shortcut. Where you would define something like key-down-alt-j in the event table for your mode, you could define external-my-event with a callback.

For instance, if you run:

rv -sendEvent my-event 1234

An event with the name external-my-eveent with the event.contents() of 1234 will be sent immediately after packages are loaded. The events follow the same event pattern as any other event (i.e. priority based on what modes are loaded and their sort order, and an event will no longer propagate if it isn’t rejected).

This method also works to initiate an event over OSX’s shared application URL handling (so you can send a -sendEvent using an rvlink to a running instance of RV) or cross-application with rvpush.

3 Likes

Thank you so much! This helps a lot.

Would it be too much if I asked for a simple ‘hello world’ type example wherein external-my-event is a callback to a simple package that would print ‘1234’ out to the log if that was what I passed in as an argument?

This is really good stuff, and it would be even better if there was a simple example in order to illustrate how these pieces all fit together.

Thanks again for your time!

2 Likes

I got it working on my side. Thank you

3 Likes

What got it working for me was that I used the bind command to declare a custom event. The rest is exactly as described in your solution.

4 Likes