Skip to content

Commit eb897a7

Browse files
committed
pick_or_create
filter out floats (or any other window configs) window id filter fix: center hint should be drawn always I dont know why I thought it doesnt Cleaner code with nvim_win_call()
1 parent d3e26ba commit eb897a7

File tree

9 files changed

+201
-25
lines changed

9 files changed

+201
-25
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ use {
3939

4040
```lua
4141
local picked_window_id = require('window-picker').pick_window()
42+
local picked_window_id = require('window-picker').pick_or_create()
4243
```
4344

44-
You can put the picked window id to good use
45+
You can put the picked window id to good use.
46+
`pick_or_create` will create a new split if you use the prefix keys shown on the edges of windows.
4547

4648
## Configuration
4749

lua/window-picker/config.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ local config = {
99

1010
-- when you go to window selection mode, status bar will show one of
1111
-- following letters on them so you can use that letter to select the window
12-
selection_chars = 'FJDKSLA;CMRUEIWOQP',
12+
selection_chars = 'FDSACMRUEIWOQP',
13+
14+
-- when creation mode is enabled, the following will be shown (only in floating window mode for now)
15+
create_chars = 'HJKL',
1316

1417
-- This section contains picker specific configurations
1518
picker_config = {
@@ -79,6 +82,11 @@ local config = {
7982
-- filter using window options
8083
wo = {},
8184

85+
-- filter using window config
86+
window_configs = {
87+
relative = true, -- checks if this key exists and nonempty (checks for floating windows)
88+
},
89+
8290
-- if the file path contains one of following names, the window
8391
-- will be ignored
8492
file_path_contains = {},

lua/window-picker/configurer.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ end
1818

1919
function M._basic_config_manipulations(config)
2020
config.chars = M._str_to_char_list(config.selection_chars)
21+
config.create_chars = M._str_to_char_list(config.create_chars)
2122
return config
2223
end
2324

lua/window-picker/filters/default-window-filter.lua

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ local util = require('window-picker.util')
33
--- @class DefaultWindowFilter
44
--- @field filter_stack function[]
55
--- @field window_options table<string, any> window options to filter
6+
--- @field window_configs table<string, any> window configs to filter
7+
--- @field window_ids table<string, any> window ids to include
8+
--- @field not_window_ids table<string, any> window ids to exclude
69
--- @field buffer_options table<string, any> buffer options to filter
710
--- @field file_name_contains string[] file names to filter
811
--- @field file_path_contains string[] file paths to filter
@@ -15,10 +18,13 @@ function M:new()
1518
self.__index = self
1619

1720
o.filter_stack = {
21+
o._window_config_filter,
1822
o._window_option_filter,
1923
o._buffer_options_filter,
2024
o._file_path_contains_filter,
2125
o._file_path_contains_filter,
26+
o._window_id_filter,
27+
o._not_window_id_filter,
2228
o._current_window_filter,
2329
}
2430

@@ -28,8 +34,11 @@ end
2834
function M:set_config(config)
2935
self.window_options = config.wo or {}
3036
self.buffer_options = config.bo or {}
37+
self.window_configs = config.window_configs or {}
3138
self.file_name_contains = config.file_name_contains or {}
3239
self.file_path_contains = config.file_path_contains or {}
40+
self.window_ids = config.window_ids or {}
41+
self.not_window_ids = config.not_window_ids or {}
3342
self.include_current_win = config.include_current_win
3443
end
3544

@@ -43,6 +52,33 @@ function M:filter_windows(windows)
4352
return filtered_windows
4453
end
4554

55+
function M:_window_config_filter(windows)
56+
if self.window_configs and vim.tbl_count(self.window_configs) > 0 then
57+
return util.tbl_filter(windows, function(winid)
58+
local config = vim.api.nvim_win_get_config(winid)
59+
for cfg_key, cfg_values in pairs(self.window_configs) do
60+
local actual_opt = config[cfg_key]
61+
62+
local has_value = false
63+
64+
if type(cfg_values) == 'table' then
65+
has_value = vim.tbl_contains(cfg_values, actual_opt)
66+
elseif cfg_values == true then
67+
has_value = actual_opt ~= '' and actual_opt ~= nil
68+
end
69+
70+
if has_value then
71+
return false
72+
end
73+
end
74+
75+
return true
76+
end)
77+
else
78+
return windows
79+
end
80+
end
81+
4682
function M:_window_option_filter(windows)
4783
if self.window_options and vim.tbl_count(self.window_options) > 0 then
4884
return util.tbl_filter(windows, function(winid)
@@ -63,6 +99,24 @@ function M:_window_option_filter(windows)
6399
end
64100
end
65101

102+
function M:_window_id_filter(windows)
103+
if self.window_ids and vim.tbl_count(self.window_ids) > 0 then
104+
windows = util.tbl_filter(windows, function(winid)
105+
return vim.tbl_contains(self.window_ids, winid)
106+
and not vim.tbl_contains(self.not_window_ids, winid)
107+
end)
108+
end
109+
return windows
110+
end
111+
function M:_not_window_id_filter(windows)
112+
if self.not_window_ids and vim.tbl_count(self.not_window_ids) > 0 then
113+
windows = util.tbl_filter(windows, function(winid)
114+
return not vim.tbl_contains(self.not_window_ids, winid)
115+
end)
116+
end
117+
return windows
118+
end
119+
66120
function M:_buffer_options_filter(windows)
67121
if self.buffer_options and vim.tbl_count(self.buffer_options) > 0 then
68122
return util.tbl_filter(windows, function(winid)

lua/window-picker/hints/floating-big-letter-hint.lua

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local utf8 = require('window-picker.utf-8')
33
--- @class FloatingBigLetterHint
44
--- @field win { width: number, height: number } window options
55
--- @field windows number[] list of window ids
6+
--- @field prefix_windows number[][] list of window ids for the prefix characters
67
local M = {}
78

89
local border = {
@@ -30,6 +31,7 @@ function M:new()
3031
height = 8,
3132
},
3233
windows = {},
34+
prefix_windows = { {}, {}, {}, {} },
3335
}
3436

3537
setmetatable(o, self)
@@ -40,6 +42,7 @@ end
4042

4143
function M:set_config(config)
4244
self.chars = config.chars
45+
self.create_chars = config.create_chars
4346
local font = config.picker_config.floating_big_letter.font
4447

4548
if type(font) == 'string' then
@@ -51,13 +54,25 @@ function M:set_config(config)
5154
end
5255
end
5356

54-
function M:_get_float_win_pos(window)
57+
local positioning_params = {
58+
m = { 0.5, 0.5, 0.5, 0.5, 'NW' }, -- Middle
59+
h = { 0, 0, 0.5, 0.5, 'NW' }, -- Middle-left
60+
j = { 0.5, 0.5, 1, 0, 'SW' }, -- Bottom-middle
61+
k = { 0.5, 0.5, 0, 0, 'NW' }, -- Top-middle
62+
l = { 1, 0, 0.5, 0.5, 'NE' }, -- Middle-right
63+
}
64+
local create_win_positions = { 'h', 'j', 'k', 'l' }
65+
66+
function M:_get_float_win_pos(window, position)
67+
position = position or 'm'
5568
local width = vim.api.nvim_win_get_width(window)
5669
local height = vim.api.nvim_win_get_height(window)
70+
local params = positioning_params[position]
5771

5872
local point = {
59-
x = ((width - self.win.width) / 2),
60-
y = ((height - self.win.height) / 2),
73+
x = width * params[1] - self.win.width * params[2],
74+
y = height * params[3] - self.win.height * params[4],
75+
anchor = params[5],
6176
}
6277

6378
return point
@@ -79,7 +94,7 @@ function M._add_big_char_margin(lines)
7994
--bottom padding
8095
table.insert(lines, #lines + 1, '')
8196

82-
--left & right padding
97+
--left & right paddin
8398

8499
for _, line in ipairs(lines) do
85100
local new_line = string.format(
@@ -95,8 +110,8 @@ function M._add_big_char_margin(lines)
95110
return centered_lines
96111
end
97112

98-
function M:_show_letter_in_window(window, char)
99-
local point = self:_get_float_win_pos(window)
113+
function M:_show_letter_in_window(window, char, position)
114+
local point = self:_get_float_win_pos(window, position)
100115

101116
local lines = self._add_big_char_margin(vim.split(char, '\n'))
102117

@@ -107,37 +122,67 @@ function M:_show_letter_in_window(window, char)
107122
local window_id = vim.api.nvim_open_win(buffer_id, false, {
108123
relative = 'win',
109124
win = window,
110-
focusable = true,
125+
focusable = false,
111126
row = point.y,
112127
col = point.x,
113128
width = width,
114129
height = height,
115130
style = 'minimal',
116131
border = border,
132+
anchor = point.anchor,
117133
})
118134

119135
vim.api.nvim_buf_set_lines(buffer_id, 0, 0, true, lines)
120136

121137
return window_id
122138
end
123139

124-
function M:draw(windows)
140+
function M:draw(windows, or_create)
125141
for index, window in ipairs(windows) do
126-
local char = self.chars[index]
127-
local big_char = self.big_chars[char:lower()]
128-
local window_id = self:_show_letter_in_window(window, big_char)
129-
table.insert(self.windows, window_id)
142+
do
143+
local char = self.chars[index]
144+
local big_char = self.big_chars[char:lower()]
145+
local window_id = self:_show_letter_in_window(window, big_char)
146+
table.insert(self.windows, window_id)
147+
end
148+
149+
if or_create then
150+
for i = 1, 4 do
151+
local char = self.create_chars[i]
152+
local big_char = self.big_chars[char:lower()]
153+
local dir = create_win_positions[i]
154+
local window_id =
155+
self:_show_letter_in_window(window, big_char, dir)
156+
table.insert(self.prefix_windows[i], window_id)
157+
end
158+
end
130159
end
131160
end
132161

133-
function M:clear()
134-
for _, window in ipairs(self.windows) do
162+
local function clear_list_of_windows(windows)
163+
for _, window in ipairs(windows) do
135164
if vim.api.nvim_win_is_valid(window) then
136165
local buffer = vim.api.nvim_win_get_buf(window)
137166
vim.api.nvim_win_close(window, true)
138167
vim.api.nvim_buf_delete(buffer, { force = true })
139168
end
140169
end
170+
end
171+
172+
function M:clear_prefixes(index)
173+
for prefix, windows in ipairs(self.prefix_windows) do
174+
-- Clear all prefixes except the one that was chosen
175+
if prefix ~= index then
176+
clear_list_of_windows(windows)
177+
self.prefix_windows[prefix] = {}
178+
end
179+
end
180+
end
181+
182+
function M:clear()
183+
clear_list_of_windows(self.windows)
184+
185+
self:clear_prefixes()
141186

142187
self.windows = {}
143188
end

lua/window-picker/hints/statusline-hint.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ end
2020

2121
function M:set_config(config)
2222
self.chars = config.chars
23-
self.selection_display = config.picker_config.statusline_winbar_picker.selection_display
23+
self.selection_display =
24+
config.picker_config.statusline_winbar_picker.selection_display
2425

2526
vim.api.nvim_set_hl(0, 'WindowPickerStatusLine', {
2627
fg = '#ededed',
@@ -69,7 +70,6 @@ function M:draw(windows)
6970
for index, window in ipairs(windows) do
7071
local char = self.chars[index]
7172

72-
7373
local display_text = self.selection_display
7474
and self.selection_display(char, window)
7575
or '%=' .. char .. '%='
@@ -83,6 +83,8 @@ function M:draw(windows)
8383
vim.cmd.redraw()
8484
end
8585

86+
function M:clear_prefixes(char) end
87+
8688
--- clear the screen after print
8789
function M:clear()
8890
for window, options in pairs(self.window_options) do

lua/window-picker/init.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ local dconfig = require('window-picker.config')
33

44
local M = {}
55

6+
local default_pick, default_pick_or_create
7+
68
function M.pick_window(custom_config)
79
local config = dconfig
810

@@ -39,6 +41,14 @@ function M.pick_window(custom_config)
3941
return builder:new():set_config(config):set_hint(hint):build():pick_window()
4042
end
4143

44+
function M.pick_or_create(custom_config)
45+
custom_config = custom_config or {}
46+
custom_config.or_create = true
47+
custom_config.include_current_win = custom_config.include_current_win
48+
or true
49+
50+
return M.pick_window(custom_config)
51+
end
4252
function M.setup() end
4353

4454
return M

0 commit comments

Comments
 (0)