From 999801876bcca90e6b8aa34a8de319e60e8c9a7e Mon Sep 17 00:00:00 2001 From: rootiest Date: Thu, 8 Aug 2024 22:36:04 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(smart-splits):=20integrate=20w?= =?UTF-8?q?ith=20smart-splits=20in=20neovim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows smart-splits in neovim to control certain keymaps for seamless integration These changes are necessary for the functionality in smart-splits --- keymaps.conf | 46 ++++++++++++++++----- neighboring_window.py | 35 ++++++++++++++++ relative_resize.py | 94 +++++++++++++++++++++++++++++++++++++++++++ split_window.py | 49 ++++++++++++++++++++++ 4 files changed, 215 insertions(+), 9 deletions(-) create mode 100644 neighboring_window.py create mode 100644 relative_resize.py create mode 100644 split_window.py diff --git a/keymaps.conf b/keymaps.conf index bd28702..60add5f 100644 --- a/keymaps.conf +++ b/keymaps.conf @@ -82,11 +82,32 @@ map shift+left move_window left map shift+right move_window right map shift+down move_window down -# Switch focus to the neighboring window in the indicated direction -map alt+left neighboring_window left -map alt+right neighboring_window right -map alt+up neighboring_window up -map alt+down neighboring_window down +map alt+shift+k move_window up +map alt+shift+h move_window left +map alt+shift+l move_window right +map alt+shift+j move_window down + +map --when-focus-on var:IS_NVIM alt+shift+j +map --when-focus-on var:IS_NVIM alt+shift+k +map --when-focus-on var:IS_NVIM alt+shift+h +map --when-focus-on var:IS_NVIM alt+shift+l + +# the 3 here is the resize amount, adjust as needed +map alt+j kitten relative_resize.py down 3 +map alt+k kitten relative_resize.py up 3 +map alt+h kitten relative_resize.py left 3 +map alt+l kitten relative_resize.py right 3 + +map --when-focus-on var:IS_NVIM alt+j +map --when-focus-on var:IS_NVIM alt+k +map --when-focus-on var:IS_NVIM alt+h +map --when-focus-on var:IS_NVIM alt+l + +### Smart Resize ### + +map alt+r start_resizing_window + +map --when-focus-on var:IS_NVIM alt+r # Detach Windows # moves the window into a new OS window @@ -101,10 +122,17 @@ map ctrl+f4 detach_window tab-prev map kitty_mod+/ launch --location=hsplit --allow-remote-control kitty +kitten kitty_search/search.py @active-kitty-window-id ### NVim Plugins -map ctrl+shift+j kitten pass_keys.py neighboring_window bottom ctrl+shift+j -map ctrl+shift+k kitten pass_keys.py neighboring_window top ctrl+shift+k -map ctrl+shift+h kitten pass_keys.py neighboring_window left ctrl+shift+h -map ctrl+shift+l kitten pass_keys.py neighboring_window right ctrl+shift+l + +map ctrl+shift+j neighboring_window down +map ctrl+shift+k neighboring_window up +map ctrl+shift+h neighboring_window left +map ctrl+shift+l neighboring_window right + +# Unset the mapping to pass the keys to neovim +map --when-focus-on var:IS_NVIM ctrl+shift+j +map --when-focus-on var:IS_NVIM ctrl+shift+k +map --when-focus-on var:IS_NVIM ctrl+shift+h +map --when-focus-on var:IS_NVIM ctrl+shift+l ## NVim Kitty Scrollback # Browse scrollback buffer in nvim diff --git a/neighboring_window.py b/neighboring_window.py new file mode 100644 index 0000000..91db694 --- /dev/null +++ b/neighboring_window.py @@ -0,0 +1,35 @@ +from kitty.key_encoding import KeyEvent, parse_shortcut +from kittens.tui.handler import result_handler + + +def main(): + pass + + +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) + + +@result_handler(no_ui=True) +def handle_result(args, result, target_window_id, boss): + window = boss.window_id_map.get(target_window_id) + + cmd = window.child.foreground_cmdline[0] + if cmd == 'tmux': + keymap = args[2] + encoded = encode_key_mapping(window, keymap) + window.write_to_child(encoded) + else: + boss.active_tab.neighboring_window(args[1]) diff --git a/relative_resize.py b/relative_resize.py new file mode 100644 index 0000000..75dfd8b --- /dev/null +++ b/relative_resize.py @@ -0,0 +1,94 @@ +# Based on MIT licensed code at https://github.com/chancez/dotfiles/blob/badc69d3895a6a942285amount26b8c372a55d77533eamount/kitty/.config/kitty/relative_resize.py +from kittens.tui.handler import result_handler +from kitty.key_encoding import KeyEvent, parse_shortcut + + +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(args): + pass + + +def relative_resize_window(direction, amount, target_window_id, boss): + window = boss.window_id_map.get(target_window_id) + if window is None: + return + + neighbors = boss.active_tab.current_layout.neighbors_for_window( + window, boss.active_tab.windows + ) + current_window_id = boss.active_tab.active_window + + left_neighbors = neighbors.get('left') + right_neighbors = neighbors.get('right') + top_neighbors = neighbors.get('top') + bottom_neighbors = neighbors.get('bottom') + + # has a neighbor on both sides + if direction == 'left' and (left_neighbors and right_neighbors): + boss.active_tab.resize_window('narrower', amount) + # only has left neighbor + elif direction == 'left' and left_neighbors: + boss.active_tab.resize_window('wider', amount) + # only has right neighbor + elif direction == 'left' and right_neighbors: + boss.active_tab.resize_window('narrower', amount) + + # has a neighbor on both sides + elif direction == 'right' and (left_neighbors and right_neighbors): + boss.active_tab.resize_window('wider', amount) + # only has left neighbor + elif direction == 'right' and left_neighbors: + boss.active_tab.resize_window('narrower', amount) + # only has right neighbor + elif direction == 'right' and right_neighbors: + boss.active_tab.resize_window('wider', amount) + + # has a neighbor above and below + elif direction == 'up' and (top_neighbors and bottom_neighbors): + boss.active_tab.resize_window('shorter', amount) + # only has top neighbor + elif direction == 'up' and top_neighbors: + boss.active_tab.resize_window('taller', amount) + # only has bottom neighbor + elif direction == 'up' and bottom_neighbors: + boss.active_tab.resize_window('shorter', amount) + + # has a neighbor above and below + elif direction == 'down' and (top_neighbors and bottom_neighbors): + boss.active_tab.resize_window('taller', amount) + # only has top neighbor + elif direction == 'down' and top_neighbors: + boss.active_tab.resize_window('shorter', amount) + # only has bottom neighbor + elif direction == 'down' and bottom_neighbors: + boss.active_tab.resize_window('taller', amount) + + +@result_handler(no_ui=True) +def handle_result(args, result, target_window_id, boss): + direction = args[1] + amount = int(args[2]) + window = boss.window_id_map.get(target_window_id) + + cmd = window.child.foreground_cmdline[0] + if cmd == 'tmux': + keymap = args[3] + encoded = encode_key_mapping(window, keymap) + window.write_to_child(encoded) + else: + relative_resize_window(direction, amount, target_window_id, boss) diff --git a/split_window.py b/split_window.py new file mode 100644 index 0000000..24d6cd6 --- /dev/null +++ b/split_window.py @@ -0,0 +1,49 @@ +from kittens.tui.handler import result_handler +from kitty.key_encoding import KeyEvent, parse_shortcut + + +def main(args): + pass + + +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 split_window(boss, direction): + if direction == 'up' or direction == 'down': + boss.launch('--cwd=current', '--location=hsplit') + else: + boss.launch('--cwd=current', '--location=vsplit') + + if direction == 'up' or direction == 'left': + boss.active_tab.move_window(direction) + + +@result_handler(no_ui=True) +def handle_result(args, result, target_window_id, boss): + window = boss.window_id_map.get(target_window_id) + + if window is None: + return + + direction = args[1] + cmd = window.child.foreground_cmdline[0] + if cmd == 'tmux': + keymap = args[2] + encoded = encode_key_mapping(window, keymap) + window.write_to_child(encoded) + else: + split_window(boss, direction) \ No newline at end of file