Productivity macros, what do you use?

I thought it would be interesting to have a topic in which people share useful macros they already use, intend to use or would like to use if they knew how, whether for keyboard(.io) or mouse or any other input. For context, I don’t code often and I work as a medical audio typist, so typing and browsing are my main foci for efficiency.

As I mentioned in another thread, I’m intending when I get my keyboardio to have one of the thumb keys have the function full stop (period for the Americans in the audience), spacebar, one-shot shift, so when typing normal sentences, instead of typing your last word of your sentence, full stop, spacebar and holding down shift while pressing your first new letter of the sentence, you just type your last word, macro then type the first word of the new sentence. Saves keystrokes and avoids double capital errors e.g. “end of sentence. STart of new sentence” - word processors pick this up usually and autocorrect but other places you’re usually out of luck.

I’d bind that to a thumb key like I said and probably have it so with one palm key held it just does a normal full stop so I can do … and decimal places easily. I’d possibly also have it so with the other palm key held it makes a paragraph (full stop enter enter one-shot shift)

One I already use, facilitated by autohotkey, is so when I press one of the media keys on my current keyboard, it triggers shift-left, ctrl-x, right, ctrl-v which has the net effect of swapping the letters to the left and right of where your typing indicator is. Very helpful for fixing “teh” and similar mistakes, mistimed spacebars and moderately dyslexic mistakes. I also bind one of the side mouse buttons to do the same thing, but with a left mouse button click first, so you can just click between your mistakes while editing.

I’ve added these macros to my mouse through LGS, but they could also be useful for keyboards:

  • ctrl-c, ctrl-t, ctrl-v, enter. Just pastes whatever you’ve highlighted into a new tab.
  • Ctrl-c, ctrl-f, enter. Obviously, to find whatever you’ve highlighted.
  • Not really macros, but I’ve also assigned mouse buttons to
    • ctrl-shift-t to reopen closed tabs,
    • F5 for refresh
    • ctrl-click to open links in a background tab.
    • Win-d for “oh god I don’t want my boss/girlfriend/etc to see what I’ve been looking at!”
5 Likes

The “double a” thread has reminded me of my forgotten desire to make a “repeat last letter” macro which would in theory make typing better by eliminating the awkward movement of repeating a letter, if one could get used to it.

Redial key: Shift-left, ctrl-c, right, ctrl-v - repeats the last letter as mentioned above, meaning if this macro is put in a reasonable place, you can avoid using the same finger twice when typing - this key would, if used consistently, be more frequently used than the 10 least commonly used letters in english, gwybvkxjqz, at frequency of about 2% of letters. Or I guess if you’re into making ascii art and want to use a non-keyboard character lots of times in a row, you can use that macro to repeat it more easily.

I don’t suppose there’s a more direct way to redial than that macro? I certainly wouldn’t want keylogger to be part of it unless it could be hobbled to only keep a few most recent keypresses in memory, safely.

You can keep the last pressed key in memory, and replay that, yeah. You’d need a custom event handler hook for that (to capture the last pressed key), and a macro (to replay it).

Something along these lines:

static Key lastPressedKey;

Key rememberLast(Key mappedKey, byte row, byte col, uint8_t keyState) {
  if (!key_toggled_on(keyState))
    return mappedKey;

  if (mappedKey == M(REDIAL)) // Don't remember the redial key
    return mappedKey;

  lastPressedKey = mappedKey;
  return mappedKey;
}

And in the macro, you’d just inject the lastPressedKey.

2 Likes

Thanks so much for doing that! I am not a coder (beyond Human Resource Machine games) and understand only a little that you wrote, so I can’t really program this myself unfortunately. I’m fine with just doing the macro version initially, but ultimately it would be really cool it if worked in this way in situations where that macro wouldn’t work (particularly Epistory, which I can see you also enjoy from when I searched for it!)

So basically the only way this will work is if someone gets it to work for me. Hopefully it’s simple enough that asking stuff like this is not a big pain for you, and if it is a pain, no worries at all!

I imagine I’d want to disable it for anything but the letter keys in case something stupid happens like a cat steps on Redial and the last thing I pressed was Enter or something important like that. So I’m guessing I could just do what you did to ignore the redial key to ignore all non-alpha keys? Would I have to do separate lines for each key I wanted ignored, or could there be just comma-separated values? Would it be reasonable to instead have a line saying to only remember alpha keys?

You said “something along these lines”. Does that mean “exactly this, it would work perfectly as is but you might want to do little variations”? Or does that mean “this is a rough sketch, something which would actually work would be something like this but don’t put it in your code yet”?

Also where would it go in the code? Tonight’s my first night playing around with it and I don’t have the keyboard yet, so absolutely zero urgency!

1 Like

If you can upload your current sketch to GitHub, I can open a pull request to add this for you, with a fair amount of comments that will hopefully allow you to tweak it a little.

You can change the if (mappedKey == M(REDIAL)) line to if (mappedKey < Key_A || mappedKey > Key_Z), and then it will only remember alphas.

It means I have not tested the code at all, so it may or may not work =)

The snippet I showed can go anywhere before the setup() function. Then, in there, you’d need to add the handler to the active ones: Kaleidoscope.useEventLoopHook(rememberLast) (off the top of my head).

3 Likes

Thanks - when I’ve tweaked my sketch a bit more I will definitely do that!

If you can upload your current sketch to GitHub, I can open a pull request to add this for you, with a fair amount of comments that will hopefully allow you to tweak it a little.

Instead of this, maybe it could just shown added to the default firmware? Might be more useful this way as an example in case anyone wanted to add something similar to their own setup, and then I could add it to my own, more finished layout when I actually have finished it.

Had a little think about it also - the main thing is that it is able to repeat individual lower case alpha keypresses, but I’m curious about whether keys that are excluded from this interrupt the macro so it returns nothing, or whether it ignores them and would return the last valid alpha keypress? I think I would prefer the latter in case a new word starts with the same letter the last word ended with and it could ignore spacebar, but I wouldn’t lose sleep over it not working that way.

Also am I understanding it right in that it remembers keypresses, not modifier states? I’m wondering for things like Aardvark, I wouldn’t want to end up with AArdvark, but again that’s rare and I wouldn’t lose sleep if it didn’t work, but especially since letter capitalisations are often done by downshift, downletter, upletter, upshift, I wouldn’t want that to interfere if possible.

1 Like

Can do that too, yes.

It is able to repeat alphas. As it does not remember, nor do anything special about modifier keys, you can have a sequence of Shift+A REDIAL, and that’ll produce Aa, because REDIAL will repeat the last key remembered, which would be Key_A, and you have released Shift at this point, so it isn’t applied to the redial.

With the event handler I’ve shown, the macro would not be able to return nothing, because there’s no such state. There always is a lastPressedKey after pressing a non-ignored key (it remains Key_NoKey until then).

A macro that would simply repeat the last pressed key would look like this:

static void RedialMacro(uint8_t keyState) {
  if (!keyState)
    return;
  handleKeyswitchEvent(lastPressedKey, UNKNOWN_KEYSWITCH_LOCATION, keyState);
}

This also supports holding the REDIAL key, and it will keep sending the last pressed key until held, so you can have OS-side repeat with this key too.

The code shown above ignores the spacebar as far as remembering goes: it only works for keys between A and Z. :slight_smile:

Correct, it only remembers the key, not any other key or modifier pressed at the same time. When the REDIAL macro repeats the remembered key, only those modifiers will be applied that are pressed at the same time as REDIAL.

2 Likes

Come to think of it… I can turn this into a plugin with reasonable ease… And then all you’d have to do is:

Kaleidoscope.use(&Redial);
Redial.key = M(REDIAL);

…and place M(REDIAL) on the keymap somewhere. I can also make it possible to customize what keys it remembers (and default to alphas or alphanumerics).

2 Likes

Can’t like your replies more than once - thanks so much! That all sounds pretty ideal.

If you could do the pull request for adding it (either the plugin or the custom event handler hook) to the default firmware, that would be awesome, and I’ll at least have a go at adding it to my own sketch before necessarily asking for help :wink:

Maybe whatever is done with it, add a disclaimer that it does potentially make your passwords one letter easier to crack! Though the position of the letter returnable by redial is not guaranteed as last …

1 Like

There’s an example sketch in there, and a README, hopefully they’ll be enough to get you started. Turns out this is very, very lightweight to accomplish. :slight_smile:

2 Likes

Sheesh, wasn’t expecting that to happen anywhere near that quickly! Nicely done!

So this may have been enough, I certainly got it to compile based on what was in there. Few noob questions, and if it’d be easier just to see my sketch, I’ll upload it:

To compile, in the line defining Key_Redial, I had to remove “(key)” as it said

‘key’ was not declared in this scope"

So I interpreted (key) intended more as a comment, like “put your key name here” or something. Have I just compiled gobbledygook?

Also a couple of noob questions not really related to Redial in particular:

  • “” and <> are used seemingly interchangeably when including libraries, I’m assuming I don’t have to care about that?
  • Do I have to worry about the order of Kaleidoscope.setup() and Kaleidoscope.use(&this, &that, &TheOther)? Or other things in void setup? The default firmware lists setup then use, but most plugin examples seem to list them the other way around.
  • The messages I get when compiling ending in “Low memory available, stability problems may occur.”, I’m assuming they’re not relevant? Since it does that on the default firmware, I’m assuming it’s fine.

I figure the more I actually understand about this, the less I’ll have to pester people and the more I’ll be able to add unaided :wink:

1 Like

It tells the type for the compiler, in case it couldn’t guess (in this case, it can guess it). Do note that case matters here: key and Key are not the same!

Generally, you don’t have to worry. The Arduino IDE prefers "", so if you plan to use it, go with the double-quotes. Otherwise it doesn’t matter.

In other circumstances, outside of the Arduino ecosystem, there is a distinction between "" and <>, namely that the latter is for system-wide includes, the former for local ones. The difference between the two is how the compiler will search for the files to be included. In our case however, it doesn’t matter much.

Nope, the order of Kaleidoscope.setup() and Kaleidoscope.use() should not matter. If it does, I’d consider that a bug.

That is harmless, indeed. If you want to get rid of it, you can remove (or comment out) the &TestMode line from Kaleidoscope.use(). Test mode is most useful for the factory, or when you want to test your keyboard. It is of little use in one’s daily life. Removing it will free up plenty of resources, and you can always put it back, should you need it.

2 Likes

Changed, cool, cool, and commented out respectively, thank you!

Thanks for all the help, this will definitely be making my final layout of my firmware and will be something I do my best to force myself to learn to use while typing - I’ll be sure to update people about whether I’m successful and hopefully if so, others may follow! And even if for whatever reason I can’t get used to it, it’ll still stay around on my build as a curiosity at the very least!

6 posts were split to a new topic: On Kaleidoscope.use() and .setup()

Hi @algernon! Have received my keyboardio, uploaded my firmware with redial and it works as expected, thank you so much! One thing - it doesn’t seem to work while any other key is held down, and I seem to hold my keystrokes long enough for that to be a problem.

Ideally, I think it should register the new key to be redialled on downstroke and be able to be pressed before upstroke is done.

1 Like