Code Monkey home page Code Monkey logo

winshift.nvim's Introduction

WinShift.nvim

Rearrange your windows with ease.

showcase

Introduction

Window moving in vim is rather limited. You can exchange a window with any other window in the same column or row, and you can rotate the order of windows within a column or row. This doesn't grant much flexibility, and yet there are limitations to when these operations work.

WinShift lets you freely rearrange your window layouts by letting you move any window in any direction. Further, it doesn't only let you move around windows, but also lets you form new columns and rows by moving into windows horizontally or vertically respectively.

Requirements

  • Neovim ≥ 0.7.2

Installation

Install the plugin with your package manager of choice.

" Plug
Plug 'sindrets/winshift.nvim'
-- Packer
use 'sindrets/winshift.nvim'

Configuration

-- Lua
require("winshift").setup({
  highlight_moving_win = true,  -- Highlight the window being moved
  focused_hl_group = "Visual",  -- The highlight group used for the moving window
  moving_win_options = {
    -- These are local options applied to the moving window while it's
    -- being moved. They are unset when you leave Win-Move mode.
    wrap = false,
    cursorline = false,
    cursorcolumn = false,
    colorcolumn = "",
  },
  keymaps = {
    disable_defaults = false, -- Disable the default keymaps
    win_move_mode = {
      ["h"] = "left",
      ["j"] = "down",
      ["k"] = "up",
      ["l"] = "right",
      ["H"] = "far_left",
      ["J"] = "far_down",
      ["K"] = "far_up",
      ["L"] = "far_right",
      ["<left>"] = "left",
      ["<down>"] = "down",
      ["<up>"] = "up",
      ["<right>"] = "right",
      ["<S-left>"] = "far_left",
      ["<S-down>"] = "far_down",
      ["<S-up>"] = "far_up",
      ["<S-right>"] = "far_right",
    },
  },
  ---A function that should prompt the user to select a window.
  ---
  ---The window picker is used to select a window while swapping windows with
  ---`:WinShift swap`.
  ---@return integer? winid # Either the selected window ID, or `nil` to
  ---   indicate that the user cancelled / gave an invalid selection.
  window_picker = function()
    return require("winshift.lib").pick_window({
      -- A string of chars used as identifiers by the window picker.
      picker_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
      filter_rules = {
        -- This table allows you to indicate to the window picker that a window
        -- should be ignored if its buffer matches any of the following criteria.
        cur_win = true, -- Filter out the current window
        floats = true,  -- Filter out floating windows
        filetype = {},  -- List of ignored file types
        buftype = {},   -- List of ignored buftypes
        bufname = {},   -- List of vim regex patterns matching ignored buffer names
      },
      ---A function used to filter the list of selectable windows.
      ---@param winids integer[] # The list of selectable window IDs.
      ---@return integer[] filtered # The filtered list of window IDs.
      filter_func = nil,
    })
  end,
})

Optionally create some mappings for starting Win-Move mode:

" Start Win-Move mode:
nnoremap <C-W><C-M> <Cmd>WinShift<CR>
nnoremap <C-W>m <Cmd>WinShift<CR>

" Swap two windows:
nnoremap <C-W>X <Cmd>WinShift swap<CR>

" If you don't want to use Win-Move mode you can create mappings for calling the
" move commands directly:
nnoremap <C-M-H> <Cmd>WinShift left<CR>
nnoremap <C-M-J> <Cmd>WinShift down<CR>
nnoremap <C-M-K> <Cmd>WinShift up<CR>
nnoremap <C-M-L> <Cmd>WinShift right<CR>

Usage

:WinShift [direction]

When called without [direction]: starts Win-Move mode targeting the current window for moving. You can then move the window either by using hjkl or the arrow keys. You can move the window to any of the far ends of the viewport by pressing one of HJKL, or shift + any arrow key. Exit Win-Move mode by pressing q / <esc> / <C-c>.

With [direction]: perform a one-shot move operation on the current window, moving it in the given direction. [direction] can be one of:

  • left, right, up, down, far_left, far_right, far_up, far_down

The far_ variants will move the window to the far end of the viewport in the given direction.

:WinShift swap

Swap the current window with another. When this command is called, you'll be prompted to select the window you want to swap with. A selection is made by pressing the character displayed in the statusline of the target window. The input is case-insensitive.

Caveats

Moving through windows with 'winfixwidth' and / or 'winfixheight' can be a bit wonky. It will work, but it can be a bit hard to follow the movement, and the fixed window might end up with different dimensions after. This is simply a consequence of vim being forced to resize the window due to there not being enough space to adhere to the fixed window's preferred dimensions.

winshift.nvim's People

Contributors

sindrets 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  avatar  avatar

winshift.nvim's Issues

Swapping split windows gives "Unknown option" error

Have tried this plugin today. Moving splits works fine but swapping two of three or more split windows gives an error.

I'm using Lunarvim with a bunch of plugins but also managed to reproduce this issue with this minimal config:

Minimal config
--[[
-- Usage: `nvim --clean -u winshift_mini.lua`
--]]
vim.cmd([[set runtimepath=$VIMRUNTIME]])
vim.cmd([[set packpath=/tmp/nvim/site]])
local package_root = "/tmp/nvim/site/pack"
local install_path = package_root .. "/packer/start/packer.nvim"
local function load_plugins()
  require("packer").startup({
      {
          "wbthomason/packer.nvim",
          "sindrets/winshift.nvim",
          "nvim-lualine/lualine.nvim",
          -- ADD PLUGINS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
      },
      config = {
          package_root = package_root,
          compile_path = install_path .. "/plugin/packer_compiled.lua",
          display = { non_interactive = true },
      },
  })
  require("lualine").setup()
end
_G.load_config = function()
  -- ADD INIT.LUA SETTINGS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
  vim.opt.nu = true
end
if vim.fn.isdirectory(install_path) == 0 then
  print("Installing dependencies...")
  vim.fn.system({ "git", "clone", "--depth=1", "https://github.com/wbthomason/packer.nvim", install_path })
end
load_plugins()
require("packer").sync()
vim.cmd([[autocmd User PackerComplete ++once echo "Ready!" | lua load_config()]])

Apparently there's a conflict with lualine.

Using

NVIM v0.7.2
Build type: Release

Run nvim <somefile> then <C-w>+s twice. Having two split windows is not enough since they're swapping just fine. But with three and more I'm getting this error:

...e/pack/packer/start/winshift.nvim/lua/winshift/utils.lua:286: Error executing lua: ...e/pack/packer/start/winshift.nvim/lua/winshift/utils.lua:304: Vim(setlocal):E518: Unknown option: main.go 
stack traceback:
^I[C]: in function 'cmd'
^I...e/pack/packer/start/winshift.nvim/lua/winshift/utils.lua:304: in function <...e/pack/packer/start/winshift.nvim/lua/winshift/utils.lua:286>
^I[C]: in function 'nvim_win_call'
^I...e/pack/packer/start/winshift.nvim/lua/winshift/utils.lua:286: in function 'set_local'
^I...ite/pack/packer/start/winshift.nvim/lua/winshift/lib.lua:377: in function 'window_picker'
^I...ite/pack/packer/start/winshift.nvim/lua/winshift/lib.lua:583: in function <...ite/pack/packer/start/winshift.nvim/lua/winshift/lib.lua:582>
^I[C]: in function 'pcall'
^I...ite/pack/packer/start/winshift.nvim/lua/winshift/lib.lua:582: in function 'start_swap_mode'
^I...im/site/pack/packer/start/winshift.nvim/lua/winshift.lua:48: in function 'cmd_winshift'
^I[string ":lua"]:1: in main chunk

Took a look at


in set_local function.

Changed to:

print(vim.inspect(cmd))
vim.cmd(cmd)

Got this:

"setl nowrap"
"setl nocursorline"
"setl colorcolumn="
"setl nocursorcolumn"
"setl statusline=%=A%="
"exe 'setl winhl=' . (&winhl == \"\" ? \"\" : &winhl . \",\") . 'StatusLine:WinShiftWindowPicker,StatusLineNC:WinShiftWindowPicker'"
"setl statusline=%=B%="
"exe 'setl winhl=' . (&winhl == \"\" ? \"\" : &winhl . \",\") . 'StatusLine:WinShiftWindowPicker,StatusLineNC:WinShiftWindowPicker'"
"setl statusline=%<%#lualine_c_inactive# main.go %#lualine_c_inactive#%=%#lualine_c_inactive#   1:1  "
"setl wrap"
<error message>

Problem is here:

"setl statusline=%<%#lualine_c_inactive# main.go %#lualine_c_inactive#%=%#lualine_c_inactive#   1:1  "

Changed code on line 300 from

{ option = option, value = tostring(value):gsub("'", "''") }

To

{ option = option, value = tostring(value):gsub("'", "''"):gsub(" ", "\\ ") }

Solution is to escape spaces or quote option's value setl statusline="..."

That was a quickfix from my side. I don't even know if it's the right fix or if it even WinShift's fault or lualine's. Could you please take a look?

Colour name or number not recognised when in tty

When in a tty, i.e. $TTY == /dev/tty*, an error involving unrecognised colours occurs. This is the error message:

Error detected while processing /home/bmr/.config/nvim/init.lua:
E5113: Error while calling lua chunk: /home/bmr/.config/nvim/init.lua:71: /home/bmr/.config/nvim/init.lua..ColorScheme Autocommands for "*": Vim(lua):E5108: Error executing lua vim/_editor.lua:0: /home/bmr/.config/nvim/init.lua..ColorScheme Autocommands for "*"..script nvim_exec2() called at ColorScheme Autocommands for "*":0: Vim(highlight):E421: Colour name or number not recognised: ctermfg=#45403d ctermbg=#45403d
stack traceback:
	[C]: in function 'nvim_exec2'
	vim/_editor.lua: in function 'cmd'
	...al/share/nvim/lazy/winshift.nvim/lua/winshift/colors.lua:126: in function 'hi'
	...al/share/nvim/lazy/winshift.nvim/lua/winshift/colors.lua:192: in function 'setup'
	[string ":lua"]:1: in main chunk
	[C]: in function 'colorscheme'
	/home/bmr/.config/nvim/init.lua:71: in main chunk
stack traceback:
	[C]: in function 'colorscheme'
	/home/bmr/.config/nvim/init.lua:71: in main chunk

Winshift commit: 37468ed
Neovim version: 0.9.1

Visual highlighting of current window doesn't work

I'm on neovim v0.8.2 and, as the title says, the highlighting of the current window doesn't change when going into WinShift mode. Other setting are being implemented correctly (such as turning on/off line wrapping), but the highlighting is not. My config is default right now.

Running :hi WinShiftNormal shows WinShiftNormal xxx cleared. It looks like you simply toggle linking the "normal" highlight groups to WinShift* highlight to get the effect. If that's true, I believe the result of :hi WinShiftNormal should actually display some the visual highlight settings, but it currently doesn't. Any ideas as to why, or debugging?

Question on expected window movement

First of all I want to thank you for this amazing plugin, I was just looking for something like this yesterday and luky me, this came like a saving grace

I have one question thou, why when there is only vertical windows calling WinShift left or right first moves the window to the top of the adjacent window and you need to input a subsequent WinShift left or right to move it to the "correct position". It feels a little counterintuitive when you need to call left or right twice if you want to move the window left or right. I would understand this behavior when there are multiple windows and positioning gets wonky, but for only vertical windows it seems rather odd.

So I was wondering why we get this behavior and if there is any way to fix it or if there is nothing that can be currently done about it

Thanks

"Invalid argument" when calling WinShift

Howdy! Thanks for the plugin, it seems quite helpful.

I just set it up according to the README, copy/pasting the mappings and configuration exactly. I installed with vim-plug and I'm at commit cf436bd which seems to be the latest in the repo. I'm using neovim 0.5.0 on Linux.

If I open neovim with a few windows on different files, and then hit the mapping for WinShift, I get:

E5108: Error executing lua ...al/share/nvim/plugged/winshift.nvim/lua/winshift/lib.lua:623: E474: Invalid argument

That seems to point to:

I'm not very familiar with Vim's use of Lua, so I don't understand what's wrong, but naively that seems like a valid table.concat call..?

Note: that the WinShift swap and WinShift left/down/up/right mappings work fine and show no errors, it's just the main WinShift mode that fails. I assume that's because the error is coming from the highlight_win function, and swapping and moving directly don't highlight windows.

[edit] Same error with neovim 0.5.1.

allow ignoring certain filetypes in the config

I think filter_func is meant to be the more extensive alternative to ignoring filetypes, but I can't seem to get it to work with NvimTree (and Alpha, which just blinks the screen).

Perhaps we could have a config option to ignore certain filetypes directly, without a filter?

feat: Support for 256-color cterm highlights

Howdy! I have a sort of graphical issue that I'm not sure how to debug.

When I use WinShift, the moving window's contents aren't highlighted, even though I'm using the config from the README that uses highlight_moving_win = true and focused_hl_group = "Visual". (I tried some other highlight groups and saw no difference.) What I actually see is that the gutter changes color, so line numbers turn white instead of my default grey, and the gutter is the same color as the rest of the window, instead of being a lighter grey like I usually have. I can still move the window around as expected, though.

When I use WinShift swap, I get the same effect in the gutter of the window I was in. No change in the other windows, except for the status bar being replaced by the window picker chars.

I've tried removing all my config, so init.vim just has the winshift plug line and its configuration, but it makes no difference. (I have no gutter in that case, so there's no change in appearance when I call WinShift, but it does still move windows around correctly.

I'm using Neovim 0.5.1 on Linux with the latest winshift, b5f5ac0. Any tips on what might be wrong would be appreciated!

don't resize on swap

window swaps resize the windows. It would be ideal if this resizing could be switched on or off.

actively looking into the code right now to understand/try a fix/perhaps open a PR but you might understand how to implement this more easily.

WinShift repeats message when pressing other keys

If I call :WinShift and press any key other than h, j, k, l, q, and Esc, the prompt duplicates itself like this:

-- WIN MOVE MODE -- press 'q' to exit
-- WIN MOVE MODE -- press 'q' to exit

I'd also like to thank you for this plugin. It's very nice! ❤️

Window resizing

Because this plugin already replaces some of the functionality of https://github.com/simeji/winresizer, I think it would be great to have the window resizing feature of that plugin.

While window resizing could be easily mapped to key mappings, that lacks the context awareness that winresizer provides.
The great thing that winresizer does is that the functionality of using hjkl to expand/reduce the size of a window changes depending on the orientation of that window compared to others. For example, if you have two vertical splits in front of you, and the right window has focus, h will expand the window's width, and l will collapse it. If the left window has focus, the keys swap functionality.

support for floating windows

I currently use the standard vim movements <C-w> L / <C-W> R to move a floating window into a split.

It'd be nice if winshift.nvim could support the same movements, but when I try :WinShift left etc or :WinShift then an arrow, I'm seeing the following error:

../winshift.nvim/lua/winshift/lib.lua:458 attempt to index local 'target_leaf' (a nil value)

The line in question is here:

https://github.com/sindrets/winshift.nvim/blob/main/lua/winshift/lib.lua#L458

If I try a :WinShift swap, I get a similar error on line 99, attempt to index local 'a' (a nil value):

https://github.com/sindrets/winshift.nvim/blob/main/lua/winshift/lib.lua#L99

For background, I'm using the goto-preview plugin which presents me with floating windows which I'd like to convert to 'norma' windows. It is a bit unusual, but I figure there may be other use cases for this.

Feature Request: Modern looking Window Hints

Hello!
Thanks for your plugin! I've found it particularly useful in my workflow. However, the feature I use the most is swapping windows and window hints are barely visible which leads to an eyestrain during the day.
image

Would you be so kind to implement custom callback option for showing hints / make some options for their customization?

As for me, the best way is to completely reimplement it using newer vim features - floating windows. It would look like this:
image
(screenshot using complementary plugin nvim-window)

Don't toggle switching when only one window open

Hi,

First of all, thanks for this extension. It's great!

I just noticed that if there's only one window open, I can still enter WIN MOVE MODE. Maybe it would be better to just flash a message or something in this case instead of having to press q/ESC ?

This is such a minor nitpick detail, so probably doesn't matter at all. But just thought I'd mention it 😄

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.