Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve layer activation specification, for momentary or toggled activators #158

Open
caksoylar opened this issue Feb 18, 2025 · 6 comments

Comments

@caksoylar
Copy link
Owner

Currently, we have two visualization tools that link keys to layers that they activate:

  1. held key type, which indicates a held-down key while a layer is active
  2. the hyperlink to the layer header on the activator field in a key, added by draw_config.style_layer_activators

The first one is determined by keymap parse (when it can, it fails for custom behaviors and customizations using raw_binding_map, see #113 and #157) and is reflected in the keymap YAML with the type: held field.

The second one on the other hand, is determined by keymap draw through a simple string match: it only checks if the legend field is exactly equal to one of the layer names. This cannot be specified in any way in keymap YAML or customized with draw_config. For instance, the detection doesn't work when you use parse_config.layer_legend_map to customize layer legends (#148).

I think it is inelegant and not good design to have this incongruency, where at the end of the day, both features are tying layers to the keys they activate from. Both 1. and 2. should be able to be configured in keymap YAML or draw_config.

Implementation alternatives: TBD

@urob
Copy link

urob commented Feb 18, 2025

I like adding an activates field as you mentioned in #148. A few more thoughts on that.

What about nesting activates inside a "legends" dictionary to track which key type does the activation? For instance,

layers:
  Base:
    # Key types map to dictionaries with a 'title' (or 'legend'?) and an optional `activates` field
    - {t: {title: StickySym, activates: Sym}, h: {title: Nav, activates: Nav}}
    
    # The current simpler syntax could be remapped internally
    - {t: Q, h: Ctrl}   # Same as {t: {title: Q}, h: {title: Ctrl}}
    - W                 # Same as {t: {title: W}}

It would make the keymap YAML the only source of truth rather than parts of the logic being implicit in keymap draw. And as you said, all the activation config could be done in raw_binding_map without needing additional config options, which would be both cleaner and more powerful.

In terms of backwards compatibility, the current string matching logic could be moved to the parse step (if there is no raw_binding_map for a key)1. Then the change would only be breaking for folks who map hold to a layer in raw_binding_map.

Regarding the held key type, it seems it would be redundant from an informational perspective (in most cases). One alternative could be to remove it from the keymap YAML and replace it with a draw_config option that specifies for which key types, layers linked in activates are automatically highlighted in the drawing step.2

Similarly, the hyperlinking of layers could be based of activates, too, and both the linking and highlighting could be configured via a shared key in draw_config. For instance,

draw_config:
  layer_activators:
    add_links: true               # Replaces existing 'style_layer_activators' setting.
    add_highlights: true          # The analog for highlighting activators.
    enabled_for_key_types: [hold] # Add 'tap' or set to 'all' to also highlight sticky layers etc.
                                  # Not sure whether this setting should be shared for links and
                                  # highlights or just apply to the latter.

Footnotes

  1. For maximum backward compatibility, one could default to only match layer strings in hold key types, though doing this for all key types seems a more sensible default to me.

  2. This would be breaking in case anyone is manually using held to customize things. Not sure if that warrants keeping around an otherwise redundant field in the keymap YAML.

@caksoylar
Copy link
Owner Author

I think that plan seems good in general, thanks for writing it up! I hadn't thought about putting activator inside the legend field, rather than key. This solves the issue of how we do links only for a certain legend (like the current implementation), not the full key.

In terms of backwards compatibility, the current string matching logic could be moved to the parse step (if there is no raw_binding_map for a key).
[...] Similarly, the hyperlinking of layers could be based of activates, too, and both the linking and highlighting could be configured via a shared key in draw_config.

The latter makes sense, in the parse step we don't need string matching, because we know (through parsing the behavior type, or are told via raw_bindings_map) semantically that a key is a layer activator (resulting in activates: layer).

Regarding the held key type, it seems it would be redundant from an informational perspective (in most cases).

We'd remove it in the parse output in favor of activates, but they can still make use of the held CSS class which'd preserve backwards compatibility in draw.

The only question I have is, how do we signify whether a key is hold or tap in the keymap YAML? Say you have &mo NAV and &tog NAV and they resolve to {t: {title: NAV, activates: NAV}[, h: toggle]}, how do we know whether {title: NAV, activates: NAV} is held or just tapped, for highlighting purposes? I guess we can add an additional field, or use e.g. momentary: NAV vs. toggled: NAV, instead. But I am curious if I am missing something from your proposal.

@urob
Copy link

urob commented Feb 19, 2025

The only question I have is, how do we signify whether a key is hold or tap in the keymap YAML? Say you have &mo NAV and &tog NAV and they resolve to {t: {title: NAV, activates: NAV}[, h: toggle]}, how do we know whether {title: NAV, activates: NAV} is held or just tapped, for highlighting purposes? I guess we can add an additional field, or use e.g. momentary: NAV vs. toggled: NAV, instead. But I am curious if I am missing something from your proposal.

There might be some conceptual misunderstanding of mine here. I am thinking of key types (tap, hold, etc) as fancy alias for legend positions (center, bottom, etc). What I suggested takes the assignment to key types as given (either explicitly set in raw_binding_map or determined via the parsing logic). Whether or not a key is highlighted then just depends on the value of enabled_for_key_types in draw_config.

In your example, suppose &mo NAV resolves to {t: {title: NAV, activates: NAV}. In this case, it would trigger the highlighting only if t label position (aka tap aka center) is in the enabled_for_key_types list.

Adding additional fields to differentiate between label position and tap/hold for highlighting purposes would be (slightly) more flexible but might not be worth the added complexity? In fact, ignoring the hyperlinking for a moment, it seems that by setting enabled_for_key_types to all one could obtain any desired highlighting behavior using just the activates setting. So the only benefit of adding additional config options (e.g., by splitting activates to activates_highlights and activates_links) would be to have separate control over the hyperlinking.

@urob
Copy link

urob commented Feb 19, 2025

Adding to the previous, how about the following:

  • Use activates to control the highlighting
  • Have an optional activates_links which if omitted defaults to activates (to keep the keymap YAML clean, I would omit it there unless it's different from activates)
  • By default link and highlight everything in activates
  • No need for enabled_for_key_types since it's redundant to overwriting activates in raw_binding_map
  • Keep two global draw_config flags for link_layer_activators and highlight_layer_activators so one doesn't need to overwrite all default parses if one wants to disable them

@caksoylar
Copy link
Owner Author

caksoylar commented Feb 20, 2025

The crux of my problem is that I want to highlight(==mark held) only the layer activators that are momentary(==held), like &mo NAV, and not toggled(==tapped), like &tog NAV1. This is why I was thinking if the activates should be separated by being momentary or not.

I was initially thinking that your enabled_for_key_types values might be related to above, but I understand now it was for legend types (tap/center, hold/bottom etc.). Unfortunately &mo NAV and &tog NAV both result in the same "tap"/center legend, so it doesn't help with above.

I think you are proposing to not make this distinction at all, at least by default, given the added complexity. I guess that's possible, but it'd be a breaking change as well without an easy way to restore the old behavior. Other than this point, your suggestions broadly makes sense to me.

Footnotes

  1. Both can always link to the NAV layer, so a separate setting for that like activates_links doesn't seem necessary to me, other than a global config like link_layer_activators.

@urob
Copy link

urob commented Feb 20, 2025

I think you are proposing to not make this distinction at all, at least by default, given the added complexity. I guess that's possible, but it'd be a breaking change as well without an easy way to restore the old behavior. Other than this point, your suggestions broadly makes sense to me.

I didn't realize that would have been a regression. Agreed that wouldn't be great.

Both can always link to the NAV layer, so a separate setting for that like activates_links doesn't seem necessary to me, other than a global config like link_layer_activators.

I think you are right, both would be functionally equivalent. And using flags here seems cleaner. I'd probably use something more related to the functionality though, e.g., no_highlight and no_link (both defaulting to false)1:

- {t: {title: NAV, activates: NAV}}                           # &mo NAV
- {t: {title: NAV, activates: NAV, no_highlight}, h: toggle}  # &tog NAV

(This would be in addition to the global draw_config flags to turn off highlighting or linking for all legends.)

Footnotes

  1. momentary and persistent are great too. My only quarrel is that for someone wanting to tweak the highlighting / linking, it's less obvious what are the relevant settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants