Git Product home page Git Product logo

bufresize.nvim's Introduction

bufresize.nvim

Features

Resize Terminal Window

bufresize.mov

bufresize.nvim can keep your buffers width and height in proportion when the terminal window is resized. For example, if you have two buffers side by side, with the left buffer taking up 70% of the terminal width and the right buffer taking up 30% of the terminal width. Then if you resized the terminal window, the left buffer and right buffer will still take up 70% and 30% respectively(By default, resizing terminal window does not keep the buffers dimension in proportion).

Resize After Opening Or Closing Window

In addition, bufresize.nvim also support proportional resize when opening or closing a window.

Normally, if you close window D in the below configuration, the height of window D goes to A and C.

Without bufresize
---------------          ---------------
|      |      |          |      |      |
|      |  B   |          |      |  B   |
|  A   |------|          |  A   |------|
|      |  C   |    ->    |      |  C   |
|      |      |          |      |      |
---------------          |      |      |
|      D      |          |      |      |
---------------          ---------------

With bufresize.nvim, we can distribute the height proportionally to B and C as shown below

With bufresize
---------------          ---------------
|      |      |          |      |      |
|      |  B   |          |      |  B   |
|  A   |------|          |  A   |      |
|      |  C   |    ->    |      |------|
|      |      |          |      |      |
---------------          |      |  C   |
|      D      |          |      |      |
---------------          ---------------

The same goes for opening a new window. For example, if you open toggleterm in vertical direction (windows D in the below figure), the initial windows will go out of proportion.

Without bufresize
---------------         ---------------
|      |      |         |      | |    |
|      |  B   |         |      |B|    |
|  A   |      |         |  A   | |    |
|      |------|   ->    |      |-| D  |
|      |      |         |      | |    |
|      |  C   |         |      |C|    |
|      |      |         |      | |    |
---------------         ---------------

With bufresize.nvim, we can resize the windows A, B, and C so that their proportion remains the same after opening toggleterm windows.

With bufresize
---------------         ---------------
|      |      |         |    |   |    |
|      |  B   |         |    | B |    |
|  A   |      |         |  A |   |    |
|      |------|   ->    |    |---| D  |
|      |      |         |    |   |    |
|      |  C   |         |    | C |    |
|      |      |         |    |   |    |
---------------         ---------------

Video demonstrations are available in this pull request

Prerequistes

  • Neovim 0.5 or higher

Installing

with vim-plug

Plug 'kwkarlwang/bufresize.nvim'

with packer.nvim

use {
    "kwkarlwang/bufresize.nvim",
    config = function()
        require("bufresize").setup()
    end
}

Configuration

This section setup bufresize for resizing terminal window. To setup bufresize for opening and closing window, please see the Exported Functions section.

bufresize.nvim setup provides two options, register and resize. register and resize are tables with two keys, keys and trigger_events. keys is a list of keymappings and trigger_events are a list of vim events that will trigger the function.

register is use to register the current state of buffer windows in the vim, it records the layout, and dimension of each active buffer.

resize is use to apply the registered state to the current state so that the current buffers will have the same proportion as the registered states.

resize also has the key increment, which will round the height and width percent of a window to the nearest increment. For example, with the increment set to 5, if the neovim window now takes up 52.3% of the terminal window width, after resizing, the neovim window width percent will round to the nearest increment, which in this case is 50%. If the increment is set to 2, the neovim window width percent would be round to 52%. To disable rounding to the nearest increment, set increment to false.

Example configuration:

use({
    "kwkarlwang/bufresize.nvim",
    config = function()
        local opts = { noremap=true, silent=true }
        require("bufresize").setup({
            register = {
                keys = {
                    { "n", "<leader>w<", "30<C-w><", opts },
                    { "n", "<leader>w>", "30<C-w>>", opts },
                    { "n", "<leader>w+", "10<C-w>+", opts },
                    { "n", "<leader>w-", "10<C-w>-", opts },
                    { "n", "<leader>w_", "<C-w>_", opts },
                    { "n", "<leader>w=", "<C-w>=", opts },
                    { "n", "<leader>w|", "<C-w>|", opts },
                    { "n", "<leader>wo", "<C-w>|<C-w>_", opts },
                },
                trigger_events = { "BufWinEnter", "WinEnter" },
            },
            resize = {
                keys = {},
                trigger_events = { "VimResized" },
                increment = 5,
            },
        })
    end,
})

In this case, if I were to press <leader>w< to resize the buffer window, then the plugin will call register and record the state after the buffer is resized. Suppose I make a new split with :split, then the autocmd event WinEnter will trigger and call register to record the current state.

In the example above, only the event VimResized will trigger the resize function, which take the registered states and apply the proportion of the layout to the current terminal width and height.

Default configuration:

use({
    "kwkarlwang/bufresize.nvim",
    config = function()
        local opts = { noremap=true, silent=true }
        require("bufresize").setup({
            register = {
                keys = {
                    { "n", "<C-w><", "<C-w><", opts },
                    { "n", "<C-w>>", "<C-w>>", opts },
                    { "n", "<C-w>+", "<C-w>+", opts },
                    { "n", "<C-w>-", "<C-w>-", opts },
                    { "n", "<C-w>_", "<C-w>_", opts },
                    { "n", "<C-w>=", "<C-w>=", opts },
                    { "n", "<C-w>|", "<C-w>|", opts },
                    { "", "<LeftRelease>", "<LeftRelease>", opts },
                    { "i", "<LeftRelease>", "<LeftRelease><C-o>", opts },
                },
                trigger_events = { "BufWinEnter", "WinEnter" },
            },
            resize = {
                keys = {},
                trigger_events = { "VimResized" },
                increment = false,
            },
        })
    end,
})

Alternative configuration:

If you don't want to call the setup function, you can also bind register and resize as followed.

use({
    "kwkarlwang/bufresize.nvim",
    config = function()
        local opts = { noremap=true, silent=true }
        vim.api.nvim_set_keymap("n", "<C-w><", "<C-w><<cmd>lua require('bufresize').register()<cr>", opts)
        vim.api.nvim_set_keymap("n", "<C-w>>", "<C-w>><cmd>lua require('bufresize').register()<cr>", opts)
        vim.cmd([[
                augroup Resize
                    autocmd!
                    autocmd VimResized * lua require('bufresize').resize()
                augroup END
                ]])
    end,
})

Exported Functions

bufresize export the following functions

  1. register: record the current windows layout and dimensions. This function is called internally by resize, resize_open, and resize_close
  2. resize: apply resize using the registered state, then register the state after resizing. Should be use with VimResized event
  3. resize_open: find the newly opened window that is in the current state but not in the registered state, adjust the proportion of registered windows accordingly, then apply resize to the registered windows. Should be use with block_register to prevent race condition
  4. resize_close: find the newly closed window that is not in the registered state but not in the current state, adjust the proportion of registered windows accordingly, then apply resize to the registered windows. Should be use with block_register to prevent race condition
  5. setup: setup the proportional resize functionality for resizing terminal window. Please see Configuration section for how to setup
  6. block_register: prevent register from recording the state. This is useful for resize_open and resize_close if WinEnter and BufWinEnter is in the trigger_events for register. If we don't use block_register, when opening a new window, register might be called before resize_open, which will make resize_open unable to find the newly opened window
  7. unblock_register: allow register to record the state. This function is called internally by resize, resize_open, and resize_close after applying the resize and before calling register

Configuration for resize_open and resize_close

My personal usage for resize_open and resize_close is using with toggleterm.

Assuming you have the default configuration for setup, below is my configuration for toggleterm to not mess up the proportion when toggling.

opts = { noremap = true, silent = true }
map = vim.api.nvim_set_keymap
ToggleTerm = function(direction)
    local command = "ToggleTerm"
    if direction == "horizontal" then
        command = command .. " direction=horizontal"
    elseif direction == "vertical" then
        command = command .. " direction=vertical"
    end
    if vim.bo.filetype == "toggleterm" then
        require("bufresize").block_register()
        vim.api.nvim_command(command)
        require("bufresize").resize_close()
    else
        require("bufresize").block_register()
        vim.api.nvim_command(command)
        require("bufresize").resize_open()
        cmd([[execute "normal! i"]])
    end
end
map("n", "<C-s>", ":lua ToggleTerm()<cr>", opts)
map("n", "<leader>ot", [[:lua ToggleTerm("horizontal")<cr>]], opts)
map("n", "<leader>ol", [[:lua ToggleTerm("vertical")<cr>]], opts)
map("i", "<C-s>", "<esc>:lua ToggleTerm()<cr>", opts)
map("t", "<C-s>", "<C-\\><C-n>:lua ToggleTerm()<cr>", opts)

Here is the configuration for applying resize_close for closing windows.

map(
	"t",
	"<leader>wd",
	"<C-\\><C-n>"
		.. ":lua require('bufresize').block_register()<cr>"
		.. "<C-w>c"
		.. ":lua require('bufresize').resize_close()<cr>",
	opts
)
map(
	"n",
	"<leader>wd",
	":lua require('bufresize').block_register()<cr>" .. "<C-w>c" .. ":lua require('bufresize').resize_close()<cr>",
	opts
)

bufresize.nvim's People

Contributors

disrupted avatar kwkarlwang avatar leixb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

bufresize.nvim's Issues

[Enhancement] block resize

I am using bufresize in conjunction with smart-splits, but if I set bufresize to trigger on WinResized, which is more useful than VimResized in my case, each resize in resize mode triggers bufresize and undoes my manual resizing. Just as there is a way to block registering, please add a way to block resizing temporarily.

`VimResized` should be added by default in the `trigget_events` for the `register`

Hello :) First off, I really love this plugin! not only because of how useful it is, but also because it's all I ever needed to close this issue in a repo of mine.

Now, why should VimResized be added by default? Here is an example:

Without VimResized

without_resized.mp4

With VimResized

with_resized.mp4

Explanation

Basically what's going on here is that I have tmux open, with 3 splits, and the one in the left is being focused at the beginning and then unfocused. Without that event, after one moves the cursor (in my case), the text "shifts" (I have wrap set), however with VimResized it does not happens, for obvious reasons.

Notice that this isn't like a tmux-only thing, you can test this by simply using any other terminal multiplexer or by resizing the terminal.

Perhaps it'd be good it add it by default?

Question: allow persistent size for defined buffers?

Hey, there. I hope a quick question is okay here.

I couldn't find out how or if it's possible to prevent a buffer from being resized / allow persistent size for it.
E.g., when there is a split with nvimtree while UI resizing happens and this split should keep its size while others will be relatively sized.

Already thank you for the development m8 ๐Ÿ‘

Can this plugin maintain window sizes when opening new windows?

Hi, great plugin. It works well when I resize Vim itself, but I'm having an issue when opening/closing windows.

Background

Vim has this annoying default behavior where when you open a new window or close an existing window, the rest of the windows resize themselves (as if you pressed <C-w>=). This is a default behavior of Vim, but I would like to see if this plugin can fix it.

Close an existing window

You can see in this video that when I make a bunch of splits and resize them, then close one window, they all resize.

subtract.mp4

Open a new window

You can see in this video that when I make some splits and resize them, then open a new window, the existing windows resize.

add.mp4

Fix for closing windows

I was able to fix this behavior using this plugin for closing windows only, but I want to fix it for opening windows as well. Here is my code that fixes the behavior while closing windows:

vim.api.nvim_create_autocmd(
    { 'WinClosed' },
    {
        callback = function()
            require('bufresize').register()
            require('bufresize').block_register()
        end
    }
)
vim.api.nvim_create_autocmd(
    { 'WinEnter' },
    {
        callback = function()
            require('bufresize').resize_close()
        end
    }
)

Since WinClosed is fired right before the window is removed, I can save the window layout with register() right before it closes. Then when I hit WinEnter after the window is closed, I can restore the saved layout with resize_close().

Here is a video of this fix working. You can see in the video that when I make a bunch of splits, resize them, and then close one, the other windows maintain their sizes. So this plugin is working here :)

subtract-fix.mp4

Fix for opening windows?

I can't get this to work. I tried the same method using WinNew instead of WinClosed. I used a variable to keep track of whether the WinEnter event was triggered after a close vs. an open.

local lastAction = ''
vim.api.nvim_create_autocmd(
    { 'WinClosed' },
    {
        pattern = '*',
        callback = function()
            lastAction = 'close'
            require('bufresize').register()
            require('bufresize').block_register()
        end
    }
)
vim.api.nvim_create_autocmd(
    { 'WinNew' },
    {
        pattern = '*',
        callback = function()
            lastAction = 'open'
            require('bufresize').register()
            require('bufresize').block_register()
        end
    }
)
vim.api.nvim_create_autocmd(
    { 'WinEnter' },
    {
        pattern = { '*' },
        callback = function()
            if lastAction == 'close' then
                vim.notify('doing a close')
                require('bufresize').resize_close()
            elseif lastAction == 'open' then
                vim.notify('doing an open')
                require('bufresize').resize_open()
            end
            lastAction = ''
        end
    }
)

As you can see, if the last action is 'close', then I call resize_close(), which works. When the last action is 'open', then I call resize_open(), but it doesn't seem to work the same way.

Is there a configuration that will fix this behavior in the way that I want? Thanks very much in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.