From c34d0afa71eadd459d34b88bd75d427eef0d25d9 Mon Sep 17 00:00:00 2001 From: Martin Larsson Date: Mon, 3 Jun 2024 00:07:14 +0200 Subject: [PATCH] [WIP] Start work on a simple windows swapping feature, much like how tiling window managers work --- home/.config/nvim/init.lua | 102 +++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/home/.config/nvim/init.lua b/home/.config/nvim/init.lua index fa5e6ce..f25cb55 100644 --- a/home/.config/nvim/init.lua +++ b/home/.config/nvim/init.lua @@ -33,3 +33,105 @@ require("terminal").setup() -- See ":help vim.highlight.on_yank()" setup_yank_highlight() + +-- Extract to plugin later +local function is_floating_window(window) + return vim.api.nvim_win_get_config(window).relative ~= "" +end + +local function is_window_resizable(window) + local config = vim.api.nvim_win_get_config(window) + return not config.winfixwidth and not config.winfixheight +end + +local function get_total_num_windows_open() + return #vim.api.nvim_tabpage_list_wins(0) +end + +local function get_adjacent_window(dir_char) + assert(dir_char == "h" or dir_char == "j" or dir_char == "k" or dir_char == "l", "Invalid direction character") + local current_window = vim.api.nvim_get_current_win() + assert(current_window, "Current window is nil") + + vim.cmd("wincmd " .. dir_char) + local new_window = vim.api.nvim_get_current_win() + vim.api.nvim_set_current_win(current_window) + + assert(vim.api.nvim_get_current_win() == current_window, "Cursor moved to a different window") + return new_window +end + +local function is_current_window_at_edge(dir_char) + return vim.api.nvim_get_current_win() == get_adjacent_window(dir_char) +end + +local function swap_buffer_between_windows(window_a, window_b) + assert(window_a and window_b, "Invalid window") + + local buffer_a = vim.api.nvim_win_get_buf(window_a) + local buffer_b = vim.api.nvim_win_get_buf(window_b) + vim.api.nvim_win_set_buf(window_a, buffer_b) + vim.api.nvim_win_set_buf(window_b, buffer_a) + + assert(vim.api.nvim_win_get_buf(window_a) == buffer_b and vim.api.nvim_win_get_buf(window_b) == buffer_a, + "Failed to swap buffers") +end + +local function swap_window(dir_char) + assert(dir_char == "h" or dir_char == "j" or dir_char == "k" or dir_char == "l", "Invalid direction character") + local current_window = vim.api.nvim_get_current_win() + assert(current_window, "Current window is nil") + + local required_num_windows = 2 + if get_total_num_windows_open() < required_num_windows then + return + end + + if is_floating_window(current_window) then + return + end + + if is_current_window_at_edge(dir_char) then + return + end + + if not is_window_resizable(current_window) then + return + end + + local adjacent_window = get_adjacent_window(dir_char) + if not is_window_resizable(adjacent_window) then + return + end + + swap_buffer_between_windows(current_window, adjacent_window) +end + +require("utils").add_keymaps({ + n = { + -- ["Left"] = { + ["h"] = { + cmd = function() + swap_window("h") + end + }, + -- ["Down"] = { + ["j"] = { + cmd = function() + swap_window("j") + end + }, + -- ["Up"] = { + ["k"] = { + cmd = function() + swap_window("k") + end + }, + -- ["Right"] = { + ["l"] = { + cmd = function() + swap_window("l") + end + }, + }, +})