mrjones2014 / smart-splits.nvim

🧠 Smart, seamless, directional navigation and resizing of Neovim + terminal multiplexer splits. Supports tmux, Wezterm, and Kitty. Think about splits in terms of "up/down/left/right".
MIT License
831 stars 33 forks source link

[Bug]: wezterm .Valid for shell environments, not for neovim, valid if neovim is abnormal #212

Closed mochouaaaaa closed 1 month ago

mochouaaaaa commented 1 month ago

Similar Issues

Neovim Version

NVIM v0.10.0 Build type: Release LuaJIT 2.1.1716656478 Run "nvim -V1 -v" for more info

Multiplexer Integration

Wezterm

Multiplexer Version

wezterm 20240203-110809-5046fc22

Steps to Reproduce

  1. Edit smart-splits source code, trigger exception
  2. nvim file
  3. split window or move

Expected Behavior

  1. open nvim
  2. split window
  3. move or resize window

Actual Behavior

  1. open nvim
  2. void split window
  3. void move or resize window

Minimal Configuration to Reproduce

{
        "mrjones2014/smart-splits.nvim",
        build = "./kitty/install-kittens.bash",
        config = function()
            local smart_splits = require("smart-splits")

            smart_splits.setup {
                -- Ignored filetypes (only while resizing)
                ignored_filetypes = {
                    "nofile",
                    "quickfix",
                    "prompt",
                },
                -- when moving cursor between splits left or right,
                -- place the cursor on the same row of the *screen*
                -- regardless of line numbers. False by default.
                -- Can be overridden via function parameter, see Usage.
                move_cursor_same_row = false,
                -- whether the cursor should follow the buffer when swapping
                -- buffers by default; it can also be controlled by passing
                -- `{ move_cursor = true }` or `{ move_cursor = false }`
                -- when calling the Lua function.
                cursor_follows_swapped_bufs = false,
                -- resize mode options
                -- resize mode options
                resize_mode = {
                    -- key to exit persistent resize mode
                    quit_key = "<ESC>",
                    -- keys to use for moving in resize mode
                    -- in order of left, down, up' right
                    resize_keys = { "h", "j", "k", "l" },
                    -- set to true to silence the notifications
                    -- when entering/exiting persistent resize mode
                    silent = false,
                },
                -- Supply a Kitty remote control password if needed,
                -- or you can also set vim.g.smart_splits_kitty_password
                -- see https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.remote_control_password
                kitty_password = "kitty",
            }
            local utils = require("config.utils")
            local cmd = utils.platform_key("cmd")

            vim.keymap.set("n", cmd .. "-S-k>", function() smart_splits.resize_up() end)
            vim.keymap.set("n", cmd .. "-S-j>", function() smart_splits.resize_down() end)
            vim.keymap.set("n", cmd .. "-S-h>", function() smart_splits.resize_left() end)
            vim.keymap.set("n", cmd .. "-S-l>", function()
                vim.notify("lll")
                smart_splits.resize_right()
            end)

            vim.keymap.set("n", cmd .. "-k>", function() smart_splits.move_cursor_up() end)
            vim.keymap.set("n", cmd .. "-j>", function() smart_splits.move_cursor_down() end)
            vim.keymap.set("n", cmd .. "-h>", function() smart_splits.move_cursor_left() end)
            vim.keymap.set("n", cmd .. "-l>", function() smart_splits.move_cursor_right() end)

            local mux = require("smart-splits.mux").get()
            if mux ~= nil then
                vim.keymap.set("n", cmd .. "-C-k>", function() mux.split_pane("up") end)
                vim.keymap.set("n", cmd .. "-C-j>", function() mux.split_pane("down") end)
                vim.keymap.set("n", cmd .. "-C-h>", function() mux.split_pane("left") end)
                vim.keymap.set("n", cmd .. "-C-l>", function() mux.split_pane("right") end)
            end
        end,
    }

Additional Details and/or Screenshots

not error image

error image

mochouaaaaa commented 1 month ago

The solution I'm currently using is.


local function is_tmux(pane) return pane:get_user_vars().WEZTERM_IN_TMUX == "1" end

-- Mapping modifier keys to CSI codes
local mod_map = {
    SHIFT = 1,
    ALT = 2,
    CTRL = 4,
    CMD = 8,
}

-- Function: Generate CSI Sequence
function get_csi_sequence(key, mods)
    local mod_code = 0 -- default is 0

    for mod in string.gmatch(mods, "([^|]+)") do
        if mod_map[mod] then
            mod_code = mod_code + mod_map[mod]
        end
    end

    local csi_sequence = string.format("\x1b[%d;%du", string.byte(key), mod_code + 1)
    print(mods, key)
    print(string.format("Generated CSI sequence: \\x1b[%d;%du", string.byte(key), mod_code + 1)) 
    return csi_sequence
end

function M.wezterm_nvim(operation, key, mods)
    return {
        key = key,
        mods = mods,
        action = w.action_callback(function(win, pane)
            -- not run tmux
            if is_vim(pane) or is_tmux(pane) then
                -- pass the keys through to vim/nvim
                local csi_keymap = get_csi_sequence(key, mods)
                win:perform_action({ SendString = csi_keymap }, pane)
                -- win:perform_action({ SendKey = { key = key, mods = mods } }, pane)
            else
                if operation == "resize" then
                    win:perform_action({ AdjustPaneSize = { direction_keys[key], 3 } }, pane)
                elseif operation == "move" then
                    win:perform_action({ ActivatePaneDirection = direction_keys[key] }, pane)
                elseif operation == "split" then
                    win:perform_action({ SplitPane = { direction = direction_keys[key] } }, pane)
                elseif operation == "close_tab" then
                    win:perform_action({ CloseCurrentPane = { confirm = false } }, pane)
                end
                -- end
            end
        end),
    }
end