Skip to content

Vim-like navigation keys (hjkl, du) require double press due to CollectionNavigator interception #188

Description

@Yuta-K19418

Description

During the investigation of key navigation behavior, it was discovered that vim-like navigation keys (h, j, k, l) and scrolling keys (d, u) do not respond on the first press and often require a second press or have a noticeable delay.

Root Cause Analysis

The issue is caused by the following factors in Terminal.Gui v2:

1. Incremental Search (CollectionNavigator) Priority

TreeView and TableView (as well as ListView) have a built-in "Type-to-navigate" feature enabled by default.

  • Behavior: Alphabetical keys (like h, j, k, l, d, u) are interpreted as "search string input" rather than "navigation commands" by the base view classes.
  • Consumption: The first key press is absorbed into the internal search buffer of the CollectionNavigator. The event is marked as Handled, preventing it from reaching the OnKeyDown override where the custom Vim logic resides.
  • Delay: There is a TypingDelay (default 500ms) during which the view waits for additional input to build the search query.

2. HotKey System Interception

If there are any controls with hotkeys defined (e.g., labels or buttons using the _ prefix), the first press of that key might be consumed to move focus to that control.

Proposed Solutions

A. Exclude specific keys from CollectionNavigator (Recommended)

Customize the ICollectionNavigatorMatcher to ensure navigation keys are not treated as search input.

public class NavigationFriendlyMatcher : DefaultCollectionNavigatorMatcher
{
    public override bool IsCompatibleKey(Key key)
    {
        // Exclude hjkl and du from search (let them be used as commands)
        if (key.MainKey == KeyCode.H || key.MainKey == KeyCode.J || 
            key.MainKey == KeyCode.K || key.MainKey == KeyCode.L ||
            key.MainKey == KeyCode.D || key.MainKey == KeyCode.U)
        {
            return false;
        }
        return base.IsCompatibleKey(key);
    }
}

// Usage in View constructors:
// this.CollectionNavigator.Matcher = new NavigationFriendlyMatcher();

B. Explicit Key Bindings

Explicitly register navigation keys in the view's KeyBindings to ensure they are routed correctly to commands.

myTreeView.KeyBindings.Add(Key.J, Command.Down);
myTreeView.KeyBindings.Add(Key.K, Command.Up);

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions