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

Extend plugin to optionally move to prev/next tab when at edge of screen. #39

Open
mwpardue opened this issue Feb 12, 2023 · 3 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@mwpardue
Copy link

mwpardue commented Feb 12, 2023

I would like to see the plugin extended so that, if you have navigated to a window at the far edge of the screen and press the kitten key in that same direction it moves to the corresponding previous or next tab. For instance, if I move to the far right window and press my "vim-kitty-navigator right" keybind again then it will activate the next_tab action instead.

I'm trying to figure out how to do this myself, but I am not much of a programmer (trying to learn) and definitely don't know python. If somebody could help me with how to determine if there are no neighboring windows in the direction pressed then I think I could do the rest, I just can't figure out that part.

Edit: edited for clarity, had wrong action in description.

@knubie knubie added help wanted Extra attention is needed enhancement New feature or request labels Feb 13, 2023
@mwpardue
Copy link
Author

mwpardue commented Feb 15, 2023

Hi! I was able to achieve this thanks to a lot of help from page-down over on the Kitty discussions page, and wanted to post what I have. Please note that I'm not even good enough at programming to call myself a novice, so I feel certain this could be polished and done more cleanly. Especially in my if/elif/else section in pass_keys.py. I'm sure it can be done more succinctly....

There is also the issue that, say you have 2 splits in grid layout (or any layout other than vertical and stacks) in tab 1 and you navigate from tab 2 to tab 1 using this modification, it will open tab 1 with the focus in the window that was last active and not necessarily the tab closest from the direction you came from. Ideally if you're coming into tab 1 from tab 2 (previous_tab) it would automatically focus on the far-right window rather than just last active. If coming in from the right (next_tab) then it should focus to the left-most window.
Edit: page-down did provide code to do this, I'll update and post changes as soon as I can. Not sure if anybody else will ever want this, but it'd be nice to contribute at least a little something.

I suppose it also needs some way to select the new behavior versus the original behavior. Not sure what the best way to do that is.

pass_keys.py

import re
from kittens.tui.handler import result_handler
from kitty.key_encoding import KeyEvent, parse_shortcut


def is_window_vim(window, vim_id):
    fp = window.child.foreground_processes
    return any(re.search(vim_id, p['cmdline'][0] if len(p['cmdline']) else '', re.I) for p in fp)


def encode_key_mapping(window, key_mapping):
    mods, key = parse_shortcut(key_mapping)
    event = KeyEvent(
        mods=mods,
        key=key,
        shift=bool(mods & 1),
        alt=bool(mods & 2),
        ctrl=bool(mods & 4),
        super=bool(mods & 8),
        hyper=bool(mods & 16),
        meta=bool(mods & 32),
    ).as_window_system_event()

    return window.encoded_key(event)


def main():
    pass


@result_handler(no_ui=True)
def handle_result(args, result, target_window_id, boss):
    tm = boss.active_tab_manager
    tab = boss.active_tab
    window = boss.window_id_map.get(target_window_id)
    direction = args[2]
    key_mapping = args[3]
    neighbor = tab.neighboring_group_id(direction)
    vim_id = args[4] if len(args) > 4 else "n?vim"
    fp = window.child.foreground_processes

    if is_window_vim(window, vim_id):
        encoded = encode_key_mapping(window, key_mapping)
        window.write_to_child(encoded)
    if neighbor is None and not is_window_vim(window, vim_id):
        if direction == 'left':
            boss.previous_tab()
        elif direction == 'right':
            boss.next_tab()
        else:
            boss.active_tab.neighboring_window(direction)
            return
    elif neighbor is not None and not is_window_vim(window, vim_id):
        boss.active_tab.neighboring_window(direction)

neighboring_window.py

def main():
    pass


def handle_result(args, result, target_window_id, boss):
    tab = boss.active_tab
    direction = args[1]
    neighbor = tab.neighboring_group_id(direction)
    if neighbor is None:
        if direction == 'left':
            boss.previous_tab()
        elif direction == 'right':
            boss.next_tab()
    else:
        boss.active_tab.neighboring_window(direction)
        return


handle_result.no_ui = True

@knubie
Copy link
Owner

knubie commented Feb 17, 2023

Hey @mwpardue , thanks for the thoughtful contribution! Please feel free to open a draft pull request with your changes.

@mwpardue
Copy link
Author

@knubie Thanks for that! Only, I assume it needs some method of selecting this behavior or original, not everybody is going to want to cycle through tabs like I do. How would you recommend that choice be handled?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants