[Question on Leader Plugin] Is it possible to pass method with argument to leader dictionnary configuration to be able to do a vi mode with leader plugin (or something to minimize the size in the eeprom using leader plugin)?

Hello,

I wrote a kind of vi mode with the leader plugin to notably do the movement like
number + movement with selection and after you can apply a command like delete (delete), cut (Ctrl+X), copy (Ctrl+C) in a classical text editor.

It is useful if you want for instance cut the next 15 lines like 15dd in vi.

Exemple of code with leader plugin :

static void moveNLinesAfter(uint8_t seq_index, int n) {
    Macros.play(MACRO(D(LeftShift)));
    for (int i = 0; i < n; i++) {
        Macros.play(MACRO(T(DownArrow)));
    }
}

static void move1LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 1);}
static void move2LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 2);}
static void move3LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 3);}
static void move4LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 4);}
static void move5LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 5);}
static void move6LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 6);}
static void move7LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 7);}
static void move8LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 8);}
static void move9LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 9);}
static void move10LinesAfter(uint8_t seq_index) { moveNLinesAfter(seq_index, 10);}

…

// moveNLinesAfter
{ LEADER_SEQ(LEAD(0), Key_K, Key_Semicolon), move1LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_A, Key_K), move1LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_S, Key_K), move2LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_D, Key_K), move3LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_F, Key_K), move4LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_G, Key_K), move5LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_H, Key_K), move6LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_J, Key_K), move7LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_K, Key_K), move8LinesAfter},
{ LEADER_SEQ(LEAD(0), Key_L, Key_K), move9LinesAfter},

It works but I need to create a lot of code configuration (not a problem) for leader plugin but it has as consequence to generate a lot of memory used in the eeprom.

I can’t manage more than 100 key sequences in leader plugin without having a full eeprom.

But if I use the same method in the configuration of leader (not correct functionally speaking), the size taken in the memory is clearly less.

So, my question, is possible in leader plugin to pass argument (in addition of uint8_t seq_index) in the configuration, something like

{ LEADER_SEQ(LEAD(0), Key_K, Key_Semicolon), moveNLinesAfter(1)},
{ LEADER_SEQ(LEAD(0), Key_A, Key_K), moveNLinesAfter(1)},
{ LEADER_SEQ(LEAD(0), Key_S, Key_K), moveNLinesAfter(2)},
{ LEADER_SEQ(LEAD(0), Key_D, Key_K), moveNLinesAfter(3)},
{ LEADER_SEQ(LEAD(0), Key_F, Key_K), moveNLinesAfter(4)},
{ LEADER_SEQ(LEAD(0), Key_G, Key_K), moveNLinesAfter(5)},
{ LEADER_SEQ(LEAD(0), Key_H, Key_K), moveNLinesAfter(6)},
{ LEADER_SEQ(LEAD(0), Key_J, Key_K), moveNLinesAfter(7)},
{ LEADER_SEQ(LEAD(0), Key_K, Key_K), moveNLinesAfter(8)},
{ LEADER_SEQ(LEAD(0), Key_L, Key_K), moveNLinesAfter(9)},

or something can permit to manage a lot of key sequences in leader plugin.

Thanks in advance,

PS : my customized firmware https://github.com/alexandrenavarro/Model01-Firmware/blob/master/Model01-Firmware.ino with vi mode around 525 lines of code if some people are interested.

1 Like

Having all the power of Vi [number] [selection] operator motion available for any other applications : Just a dream !

I don’t know if @tpope still have a Model01 but, hey, maybe The Artist would be interested :slight_smile:

Effectively, I have some really close in my vi mode.

You have to press a key (personally is fn1 which activate the Leader Plugin), after a number (it is optional, 1 by default as vi), after a movement (I defined a lot of movement in my layout, like right, next word, next line, next paragraph, next code block end, next page, end line, end file and previous), it will result a selection of the text. Then you can do you operator (like delete, cut, copy through classic delete, Ctrl+C, Ctrl+V) or Right to unselect (just to do the move).
It is not same as vi (number operator motion), closer to what you do in a classical text editor (and easier to implement it in keyboardio model 01) and you can’t do all the stuffs of course you can do in vi but it is better if you use any text editor (except vi).

Nevertheless, because of the memory of the eeprom, in can’t have more than 100 key sequences in leader key (which is not so bad but not so many) but the useful ones are available.

I didn’t experiment a lot this kind of vi mode (I thought about a long time but just implemented it), time will tell me if it is really useful or not.

Any people interested can check my repo above.
If someone have an ideas to manage more vi movements, I’m really interested.

1 Like

It is (effectively) possible to pass an extra argument to the function(s) called by Leader in its dictionary, but only by using an additional plugin to do so.

By placing this plugin before Leader in KALEIDOSCOPE_INIT_PLUGINS() and having it “listen” for LEAD(n) keys, then consume “digit” keys (which could be configurable, so you needn’t use actual number row keys), storing an integer “prefix argument” and making it available to calling code, this is doable.

I’m inspired to write this up as a custom plugin example now. It would serve as a good example of a plugin that needs to use the new onKeyswitchEvent() handler, rather than the more straightforward onKeyEvent() one, but which nevertheless has very simple logic.

1 Like

I wrote an example sketch for Kaleidoscope with a LeaderPrefix custom plugin to implement this. It’s currently PR #1044.

1 Like

Thanks, I will have a look when I will have time.

In fact, @algernon has already merged it into master!

1 Like