zmkfirmware / zmk

ZMK Firmware Repository
https://zmk.dev/
MIT License
2.81k stars 2.83k forks source link

Feature request: Option to make Caps Word behave like QMK #1706

Open chalop opened 1 year ago

chalop commented 1 year ago

On QMK's caps word, when you press the minus key it automatically converts it to an underscore (https://docs.qmk.fm/#/feature_caps_word). I was happy to see this key on ZMK too, but it doesn't behave the same.

How feasible would be to make the minus key is pressed it "shifts" it to underscore and caps word remains active? I posted on the discord if there was a way to make it but the post didn't gain any traction.

jjangga0214 commented 1 year ago

@chalop For now, as a workaround, you can duplicate the layer which has all the same settings but the MINUS key is UNDERSCORE. And you replace &caps_word with a new macro &new_caps_word, like the below example.

        new_caps_word: new_caps_word {
            label = "new_caps_word";
            compatible = "zmk,behavior-macro";
            #binding-cells = <0>;
            bindings
                = <&macro_tap &caps_word &tog DUPLICATED_LAYER>; /* Going to another layer */
        };

And on the DUPLICATED_LAYER, you activate macro instead of space, esc, and etc.

        new_space: new_space {
            label = "new_space";
            compatible = "zmk,behavior-macro";
            #binding-cells = <0>;
            bindings
                = <&macro_tap &kp SPACE &tog DUPLICATED_LAYER>; /* Going back to the original layer */
        };
chalop commented 1 year ago

It's not an ideal solution, but it works really great! It also has the added benefit of turning on a status led on the adv 360 (since its technically just another layer)

As for what the ideal solution would look like, I would need to get more familiar with zmk's syntax in order to suggest an api for it. I'll leave the issue open in case someone has a need to implement the qmk behavior on zmk.

Thank you!

jjangga0214 commented 1 year ago

In my humble opinion, it'd be better to let users configure this for their taste instead of just letting MINUS and UNDERSCORE the only special exception. For example, while &caps_word activates, I want to input ':' over ';'.

(For those who wonder the reason: It's because I use Colemak layout. For input source language layout reasons, I can't but let ZMK-level layout be QWERTY and OS layout be Colemak, not the opposite way. So the OS does remapping under the hood, which means OS remaps ';' to 'o' and ':' to 'O'. That is why ':', not ';', should be inputted when using &caps_word. This problem appears to many people using alternative layouts with multiple input sources.)

joelspadin commented 1 year ago

I'm working on a PR to improve caps word which will add

jjangga0214 commented 1 year ago

@joelspadin I think it's a great idea 👍 🎉

It would be elegant if, by no-default-keys, #1712 can be smoothly supported with Multiple Caps Breaks. Would it be possible? Or another property should be added? (e.g. break_on_twice: if set to true, &caps_word breaks when non continue-list input is given continuously. For example, when alphanumeric keys are not continue-list but backspace is, &kp A &kp B &kp C would result in "Abc", while &kp A &kp BSPC &kp B &kp C would become "Bc". This is great for preventing a mistake when inputting the first letter of the sentence.)

joelspadin commented 1 year ago

I don't think that's really in scope for my set of changes. I'm just aiming for feature parity with QMK, which lets you fully customize which keys break a word and which keys are shifted. If you set no-default-keys and don't manually include any alphanumeric keys in continue-list, then &caps_word &kp A would immediately break and print "a".

urob commented 1 year ago

I'm working on a PR to improve caps word which will add

* `shift-list`: a list of additional key codes to be shifted (defaults to `MINUS`)

* `no-default-keys`: if set to true, alphanumeric keys are not automatically added to `continue-list` and `shift-list`, so you can fully customize the lists in case you're using an OS layout where the standard alphanumeric keys aren't actually alphanumeric.

Two quick thoughts:

1/ #1451 already provides full control over the continue-list (the PR defaults it to empty, and then provides shortcuts to quickly add all alphas, numbers or mods)

2/ I am wondering whether it would make sense to consolidate capsword with the approach taken in #1366 to provide a more general backend. See this comment for details: https://github.com/zmkfirmware/zmk/pull/1366#issuecomment-1473051776

joelspadin commented 1 year ago

I'm not sure I like changing the default to be empty and adding flags to get back to the original behavior, because that would break any existing "zmk,behavior-caps-word" behaviors in people's config repos.

The layer activation thing seems odd to add to caps word, but maybe I'm not understanding the use case. I think it would probably be easier to maintain multiple, focused behaviors rather than one behavior that tries to do everything. Some of the changes I have locally could be pulled out into common utility code for multiple "do this thing as long as I only press these keys" behaviors though.

urob commented 1 year ago

I'm not sure I like changing the default to be empty and adding flags to get back to the original behavior, because that would break any existing "zmk,behavior-caps-word" behaviors in people's config repos.

I figured that changes to the backend "zmk,behavior-caps-word" are fine as long as the frontend &caps-word does the same thing. But you are probably right.

The layer activation thing seems odd to add to caps word, but maybe I'm not understanding the use case. I think it would probably be easier to maintain multiple, focused behaviors rather than one behavior that tries to do everything.

The layer stuff is useful, e.g., to get a numword that activates a numbers layer and automatically deactivates it once a non-number is pressed.

I agree that it's not really related to caps-word. But given that its implementation overlaps 99% with the caps-word backend, I thought it would be more code efficient to re-use the backend (which then should probably be renamed to something other than zmk,behavior-caps-word), and then just provide &caps-word as a frontend.

That said, I actually prefer @nickconway's tri-state over my approach. So if there were to be a more general backend, I would advocate for it to be based on his PR. But I see your point about maintaince being easier for more focused behaviors. (And in either case, you are the far better judge for what's most code efficient/easy to maintain).

Andrew15-5 commented 7 months ago
  • in case you're using an OS layout where the standard alphanumeric keys aren't actually alphanumeric.

What is "an OS layout"?

Another (?) reason for modifying existing or creating a separate caps word macro is to add a proper support for other languages. For example, in Russian these keys should work with caps word, but don't (i.e., Russian support is currently broken):

`;',.[]
ёжэбюхъ

And since using caps in general is rare, especially with some of those letters, I previously didn't even know that some letters don't work.

So I'm also interested in this feature.

joelspadin commented 7 months ago

What is "an OS layout"?

That should have been "OS keyboard layout"

Andrew15-5 commented 7 months ago

Well, that I understand. But what does this mean? Is it just any keyboard layout that you add in the OS settings? Which are usually just different languages. I was probably confused because I didn't encounter "OS" before, when talking about "keyboard layouts".

example ![image](https://github.com/zmkfirmware/zmk/assets/37143421/596cb319-fbcf-4af1-9bff-1dd16bc126f9)
caksoylar commented 7 months ago

They are called "OS keyboard layouts" because they are provided by your operating system. Usually they correspond to different languages, but you can have multiple layouts for the same language/locale, like US English and US International.

Prepending "OS" helps to distinguish from firmware-based keyboard layouts, i.e. your keymap.