Skip to content

feat: add support for macOS modifier keys#159

Merged
srothgan merged 3 commits into
srothgan:mainfrom
TomasWeisss:feat/keyboard-navigation-macos
May 4, 2026
Merged

feat: add support for macOS modifier keys#159
srothgan merged 3 commits into
srothgan:mainfrom
TomasWeisss:feat/keyboard-navigation-macos

Conversation

@TomasWeisss
Copy link
Copy Markdown
Contributor

Summary

Changed the modifier key handling for text navigation, deleting, and history to work on MacOS.

Why

MacOS uses Option for skipping/deleting by words, and Command for undo/redo. The current setup didn't account for this, so the navigation didn't work on MacOS.

Validation

  • Automated: Tests modified to use MacOS modifier keys when on MacOS, all pass.
  • Manual: Verified to work on MacOS.
  • Screenshot/video (if UI changed): N/A

Notes

  • Breaking changes: N/A
  • Docs updated: N/A

@TomasWeisss TomasWeisss requested a review from srothgan as a code owner April 30, 2026 21:15
@TomasWeisss TomasWeisss force-pushed the feat/keyboard-navigation-macos branch from dddec1c to 261f0ea Compare April 30, 2026 22:01
@srothgan
Copy link
Copy Markdown
Owner

srothgan commented May 2, 2026

@TomasWeisss Thanks for the PR. This looks like a useful improvement. Since I am working on Windows, I didnt catch that.

I would just ask for two focused changes tied to the Command-key behavior added here:

  1. Can you also support standard macOS redo as Shift + Command + Z (KeyModifiers::SUPER | KeyModifiers::SHIFT with KeyCode::Char('z')). Keeping Command + Y as an extra alias is fine. This from documentation looks like the standard combination for macOs but I could be wrong.

  2. If we rely on KeyModifiers::SUPER, we should enable crossterm keyboard enhancement mode on startup and restore it on shutdown. The centralized place for that is src/app/terminal_runtime/modes.rs, where CHAT_STARTUP_ACTIONS and SHUTDOWN_RESTORE_ACTIONS are applied. The implementation would be roughly:

use crossterm::event::{KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags};

execute!(
    stdout,
    PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES)
)?;

// during terminal restore/shutdown
execute!(stdout, PopKeyboardEnhancementFlags)?;

crossterm documents that SUPER, HYPER, and META require KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES, so I think we should enable that mode here if this PR depends on Command-key shortcuts.

@TomasWeisss
Copy link
Copy Markdown
Contributor Author

TomasWeisss commented May 3, 2026

That's a good recommendation, definitely should follow system shortcuts. I've run into some issues however.

The updated shortcuts did not work without the keyboard enhancement as you predicted. However, the location you mention (rc/app/terminal_runtime/modes.rs) only exists in your refactor branch. So I explored if I could rebase the feature on it, but I found the branch is not very stable yet. I wasn't able to run it out of the box (failed to construct ratatui inline chat terminal: The cursor position could not be read within a normal duration). After adding a default cursor position fallback, it did run, but didn't position and/or overdraw the existing terminal contents correctly.

What would you advise- I finish this feature on main and you or I have to possibly re-integrate in the refactor, or wait until after the refactor?

@srothgan
Copy link
Copy Markdown
Owner

srothgan commented May 3, 2026

Sorry for that. I was fully focused on the refactor and pointed you at a file from my refactor branch.

On main branch, the keyboard enhancement setup already lives in src/app/mod.rs via resume_terminal() / suspend_terminal(), so please do not rebase this onto the refactor branch and do not spend time moving terminal setup around.

For this PR, I think the only change I would still ask for is the macOS redo shortcut: please support Shift + Command + Z (KeyModifiers::SUPER | KeyModifiers::SHIFT with KeyCode::Char('z')). Keeping Command + Y as an extra alias is fine.

After that, we can merge the PR. I will handle any refactor-branch integration later. Thank you for your help

@TomasWeisss
Copy link
Copy Markdown
Contributor Author

Modified to use the standard Command + Shift + Z for redo. I also modified the history method to always return true if the shortcut was recognized, even if it didn't perform an action, as pressing Redo and having it suddenly start typing capital Z was very strange and not standard behavior.

@srothgan
Copy link
Copy Markdown
Owner

srothgan commented May 4, 2026

Looks good, but we need to handle macOS, Windows and Linux so we can not just replace CTRL with the macOS native command. We need to make the command key OS-aware. Here is my idea for that:

#[cfg(target_os = "macos")]
const CMD_MOD: KeyModifiers = KeyModifiers::SUPER;

#[cfg(not(target_os = "macos"))]
const CMD_MOD: KeyModifiers = KeyModifiers::CONTROL;

@TomasWeisss
Copy link
Copy Markdown
Contributor Author

My apologies, I accidentally changed the key for the Windows branch. I used the opportunity to centralize the handling into a few constants at the top of keys.rs, which are exported as to be available in tests as well.

Copy link
Copy Markdown
Owner

@srothgan srothgan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, looks good 👍

@TomasWeisss
Copy link
Copy Markdown
Contributor Author

Great! Is there anything more I need to do or will you merge it?

@srothgan srothgan merged commit ca194e8 into srothgan:main May 4, 2026
8 checks passed
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

Successfully merging this pull request may close these issues.

2 participants