Skip to content

Commit 299dc55

Browse files
committed
feat: init no-neck-pain.nvim
0 parents  commit 299dc55

File tree

9 files changed

+316
-0
lines changed

9 files changed

+316
-0
lines changed

.github/CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @shortcuts

.github/workflows/main.yml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: main
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
types: [opened, synchronize]
8+
9+
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
name: Lint
13+
steps:
14+
- uses: actions/checkout@v3
15+
16+
- uses: JohnnyMorganz/stylua-action@v1
17+
with:
18+
token: ${{ secrets.GITHUB_TOKEN }}
19+
version: latest
20+
args: --check .

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Clément Vannicatte
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# no-neck-pain.nvim
2+
3+
## Introduction
4+
5+
Dead simple plugin to center the current buffer to the middle of the screen.
6+
7+
## Why an other focus-zen-center-buffer plugin?
8+
9+
While there's many other (amazing!) plugins that does similar stuff, they all require some configuration or alter your NeoVim workflow.
10+
11+
In my case, I only wanted a plugin that: **center the current buffer**.
12+
13+
## Installation
14+
15+
### packer.nvim
16+
17+
```lua
18+
use {'shortcuts/no-neck-pain.nvim'}
19+
```
20+
21+
### vim-plug
22+
23+
```lua
24+
Plug 'shortcuts/no-neck-pain.nvim'
25+
```
26+
27+
## Getting started
28+
29+
### Lua
30+
31+
```lua
32+
-- values below are the default
33+
require("no-neck-pain").setup({
34+
width = 100, -- the size of the main buffer
35+
})
36+
```

lua/no-neck-pain/config.lua

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
local config = {}
2+
3+
config.options = {
4+
width = 100,
5+
}
6+
7+
function config.setup(opts)
8+
config.options = vim.tbl_deep_extend("keep", opts or {}, config.options)
9+
end
10+
11+
return config

lua/no-neck-pain/init.lua

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
local M = {}
2+
3+
function M.start()
4+
require("no-neck-pain.main").toggle()
5+
end
6+
7+
function M.setup(opts)
8+
require("no-neck-pain.config").setup(opts)
9+
end
10+
11+
return M

lua/no-neck-pain/main.lua

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
local cfg = require("no-neck-pain.config").options
2+
local SIDES = { "left", "right" }
3+
4+
local M = {
5+
-- State of NoNeckPain
6+
state = {
7+
enabled = false,
8+
win = {
9+
-- side buffer/windows options
10+
opts = {
11+
bo = {
12+
buftype = "nofile",
13+
bufhidden = "hide",
14+
modifiable = false,
15+
buflisted = false,
16+
swapfile = false,
17+
},
18+
wo = {
19+
cursorline = false,
20+
cursorcolumn = false,
21+
number = false,
22+
relativenumber = false,
23+
foldenable = false,
24+
list = false,
25+
},
26+
},
27+
curr = nil,
28+
left = nil,
29+
right = nil,
30+
},
31+
},
32+
}
33+
34+
vim.api.nvim_create_augroup("NoNeckPain", {
35+
clear = true,
36+
})
37+
38+
-- toggle plugin and restart states
39+
function M.toggle()
40+
if M.state.enabled then
41+
M.disable()
42+
else
43+
M.enable()
44+
end
45+
end
46+
47+
local function getPadding()
48+
local width = vim.api.nvim_list_uis()[1].width
49+
50+
if cfg.width >= width then
51+
return 1
52+
end
53+
54+
local curr_width = cfg.width * 3
55+
if curr_width > width then
56+
local available_space = width - cfg.width
57+
return (available_space % 2 > 0 and ((available_space - 1) / 2) or available_space / 2)
58+
end
59+
60+
return cfg.width
61+
end
62+
63+
-- Creates a buffer for the given padding, at the given direction
64+
local function createBuf(cmd, padding, moveTo)
65+
vim.cmd(cmd)
66+
67+
local id = vim.api.nvim_get_current_win()
68+
69+
vim.api.nvim_win_set_width(0, padding)
70+
71+
for scope, _ in pairs(M.state.win.opts) do
72+
for name, value in pairs(M.state.win.opts[scope]) do
73+
vim[scope][name] = value
74+
end
75+
end
76+
77+
vim.cmd(moveTo)
78+
return id
79+
end
80+
81+
-- creates a NNP focused buffer when called with `init`. Resizes sides on `resize`
82+
local function createWin(action)
83+
local padding = getPadding()
84+
85+
if action == "init" then
86+
local splitbelow, splitright = vim.o.splitbelow, vim.o.splitright
87+
vim.o.splitbelow, vim.o.splitright = true, true
88+
89+
M.state.win = {
90+
opts = M.state.win.opts,
91+
curr = vim.api.nvim_get_current_win(),
92+
left = createBuf("leftabove vnew", padding, "wincmd l"),
93+
right = createBuf("vnew", padding, "wincmd h"),
94+
}
95+
96+
vim.o.splitbelow, vim.o.splitright = splitbelow, splitright
97+
98+
return
99+
end
100+
101+
-- resize
102+
for _, side in ipairs(SIDES) do
103+
if vim.api.nvim_win_is_valid(M.state.win[side]) then
104+
vim.api.nvim_win_set_width(M.state.win[side], padding)
105+
end
106+
end
107+
end
108+
109+
function M.enable()
110+
createWin("init")
111+
112+
vim.api.nvim_create_autocmd({ "VimResized" }, {
113+
callback = function()
114+
createWin()
115+
end,
116+
group = "NoNeckPain",
117+
desc = "Resizes side windows after resize",
118+
})
119+
120+
vim.api.nvim_create_autocmd({ "WinClosed" }, {
121+
callback = function()
122+
vim.schedule(function()
123+
-- if main window is closed, disable
124+
if M.state.enabled and vim.api.nvim_get_current_win() ~= M.state.win.curr then
125+
M.disable()
126+
end
127+
end)
128+
end,
129+
group = "NoNeckPain",
130+
desc = "Disables NoNeckPain when main window is closed",
131+
})
132+
133+
vim.api.nvim_create_autocmd({ "WinEnter", "WinClosed" }, {
134+
callback = function()
135+
vim.schedule(function()
136+
-- trigger on float window (e.g. telescope)
137+
if vim.api.nvim_win_get_config(0).relative ~= "" then
138+
createWin()
139+
140+
return
141+
end
142+
143+
-- skip if the newly focused window is a side buffer
144+
if
145+
vim.api.nvim_get_current_win() == M.state.win.left
146+
or vim.api.nvim_get_current_win() == M.state.win.right
147+
then
148+
return
149+
end
150+
151+
local padding = 0
152+
153+
-- when opening a new buffer as current, keep its padding and resize everything (e.g. side tree)
154+
if vim.api.nvim_get_current_win() ~= M.state.win.curr then
155+
padding = vim.api.nvim_win_get_width(0)
156+
end
157+
158+
local width = vim.api.nvim_list_uis()[1].width
159+
local totalSideSizes = (width - padding) - cfg.width
160+
161+
for _, side in ipairs(SIDES) do
162+
if M.state.win[side] ~= nil then
163+
if vim.api.nvim_win_is_valid(M.state.win[side]) then
164+
vim.api.nvim_win_set_width(
165+
M.state.win[side],
166+
math.floor(totalSideSizes / 2)
167+
)
168+
end
169+
end
170+
end
171+
end)
172+
end,
173+
group = "NoNeckPain",
174+
desc = "Resize to apply on Enter/Closed callbacks",
175+
})
176+
177+
M.state.enabled = true
178+
end
179+
180+
function M.disable()
181+
-- when disabling, if current isn't NNP curr, focus it
182+
if vim.api.nvim_win_is_valid(M.state.win.curr) then
183+
if M.state.win.curr ~= vim.api.nvim_get_current_win() then
184+
vim.fn.win_gotoid(M.state.win.curr)
185+
end
186+
end
187+
188+
vim.cmd("only")
189+
190+
vim.api.nvim_create_augroup("NoNeckPain", {
191+
clear = true,
192+
})
193+
194+
M.state = {
195+
enabled = false,
196+
win = {
197+
opts = M.state.win.opts,
198+
curr = nil,
199+
left = nil,
200+
right = nil,
201+
},
202+
}
203+
end
204+
205+
return M

plugin/no-neck-pain.lua

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
if vim.g.noNeckPain then
2+
return
3+
end
4+
vim.g.noNeckPain = true
5+
6+
vim.api.nvim_create_user_command("NoNeckPain", function()
7+
require("no-neck-pain").start()
8+
end, {})

stylua.toml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
indent_type = "Spaces"
2+
indent_width = 4
3+
column_width = 100

0 commit comments

Comments
 (0)