Skip to content

Commit 28ad86d

Browse files
feat: add fixed position support for floating windows (neoclide#5217)
1 parent 6a338ca commit 28ad86d

File tree

5 files changed

+112
-4
lines changed

5 files changed

+112
-4
lines changed

autoload/coc/float.vim

+46
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,52 @@ function! coc#float#create_float_win(winid, bufnr, config) abort
127127
" happens when using getchar() #3921
128128
return []
129129
endtry
130+
131+
" Calculate position when relative is editor
132+
if get(a:config, 'relative', '') ==# 'editor'
133+
let top = get(a:config, 'top', v:null)
134+
let bottom = get(a:config, 'bottom', v:null)
135+
let left = get(a:config, 'left', v:null)
136+
let right = get(a:config, 'right', v:null)
137+
138+
if top isnot v:null || bottom isnot v:null || left isnot v:null || right isnot v:null
139+
let height = &lines
140+
let width = &columns
141+
142+
" Calculate row
143+
let calc_row = a:config.row
144+
if bottom isnot v:null
145+
let calc_row = height - bottom - a:config.height - 2
146+
elseif top isnot v:null
147+
let calc_row = top
148+
endif
149+
150+
" Calculate col
151+
let calc_col = a:config.col
152+
if right isnot v:null
153+
let calc_col = width - right - a:config.width - 3
154+
elseif left isnot v:null
155+
let calc_col = left
156+
endif
157+
158+
" Check if window would overlap cursor position
159+
let pos = screenpos(0, line('.'), col('.'))
160+
let currow = pos.row - 1
161+
let curcol = pos.col - 1
162+
let win_top = calc_row
163+
let win_bottom = win_top + a:config.height + 2
164+
let win_left = calc_col
165+
let win_right = win_left + a:config.width + 3
166+
167+
" If window would overlap cursor, switch to cursor relative
168+
if currow >= win_top && currow <= win_bottom && curcol >= win_left && curcol <= win_right
169+
let a:config.relative = 'cursor'
170+
else
171+
let a:config.row = calc_row
172+
let a:config.col = calc_col
173+
endif
174+
endif
175+
endif
130176
let lnum = max([1, get(a:config, 'index', 0) + 1])
131177
let zindex = get(a:config, 'zindex', 50)
132178
" use exists

data/schema.json

+46-4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,28 @@
6060
"minimum": 0,
6161
"maximum": 100,
6262
"description": "Enables pseudo-transparency by set 'winblend' option of window, neovim only."
63+
},
64+
"position": {
65+
"type": "string",
66+
"default": "auto",
67+
"description": "Controls how floating windows are positioned. When set to `'fixed'`, the window will be positioned according to the `top`, `bottom`, `left`, and `right` settings. When set to `'auto'`, the window follows the default position.",
68+
"enum": ["fixed", "auto"]
69+
},
70+
"top": {
71+
"type": "number",
72+
"description": "Distance from the top of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Will be ignored if `bottom` is set."
73+
},
74+
"bottom": {
75+
"type": "number",
76+
"description": "Distance from the bottom of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Takes precedence over `top` if both are set."
77+
},
78+
"left": {
79+
"type": "number",
80+
"description": "Distance from the left edge of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Will be ignored if `right` is set."
81+
},
82+
"right": {
83+
"type": "number",
84+
"description": "Distance from the right edge of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Takes precedence over `left` if both are set."
6385
}
6486
}
6587
},
@@ -970,7 +992,12 @@
970992
"maxWidth": {},
971993
"winblend": {},
972994
"focusable": {},
973-
"shadow": {}
995+
"shadow": {},
996+
"position": {},
997+
"top": {},
998+
"bottom": {},
999+
"left": {},
1000+
"right": {}
9741001
}
9751002
},
9761003
"diagnostic.format": {
@@ -1242,7 +1269,12 @@
12421269
"maxHeight": {},
12431270
"winblend": {},
12441271
"focusable": {},
1245-
"shadow": {}
1272+
"shadow": {},
1273+
"position": {},
1274+
"top": {},
1275+
"bottom": {},
1276+
"left": {},
1277+
"right": {}
12461278
}
12471279
},
12481280
"hover.autoHide": {
@@ -1268,7 +1300,12 @@
12681300
"maxWidth": {},
12691301
"winblend": {},
12701302
"focusable": {},
1271-
"shadow": {}
1303+
"shadow": {},
1304+
"position": {},
1305+
"top": {},
1306+
"bottom": {},
1307+
"left": {},
1308+
"right": {}
12721309
}
12731310
},
12741311
"hover.previewMaxHeight": {
@@ -1861,7 +1898,12 @@
18611898
"maxWidth": {},
18621899
"winblend": {},
18631900
"focusable": {},
1864-
"shadow": {}
1901+
"shadow": {},
1902+
"position": {},
1903+
"top": {},
1904+
"bottom": {},
1905+
"left": {},
1906+
"right": {}
18651907
}
18661908
},
18671909
"signature.hideOnTextChange": {

doc/coc-config.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,11 @@ supported:
17231723
`0`.
17241724
- "focusable": Set to false to make window not focusable, neovim only.
17251725
- "shadow": Set to true to enable shadow, neovim only.
1726+
- "position": Controls how floating windows are positioned. When set to `'fixed'`, the window will be positioned according to the `top`, `bottom`, `left`, and `right` settings. When set to `'auto'`, the window follows the default position.
1727+
- "top": Distance from the top of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Will be ignored if `bottom` is set.
1728+
- "bottom": Distance from the bottom of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Takes precedence over `top` if both are set.
1729+
- "left": Distance from the left edge of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Will be ignored if `right` is set.
1730+
- "right": "Distance from the right edge of the editor window in characters. Only takes effect when `position` is set to `'fixed'`. Takes precedence over `left` if both are set."
17261731

17271732
------------------------------------------------------------------------------
17281733
Languageserver~

src/model/floatFactory.ts

+10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ export interface FloatWinConfig extends FloatConfig {
3434
cursorline?: boolean
3535
modes?: string[]
3636
excludeImages?: boolean
37+
position?: "fixed" | "auto";
38+
top?: number;
39+
bottom?: number;
40+
left?: number;
41+
right?: number;
3742
}
3843

3944
/**
@@ -155,6 +160,11 @@ export default class FloatFactoryImpl implements Disposable {
155160
if (opts.highlight) config.highlight = opts.highlight
156161
if (opts.borderhighlight) config.borderhighlight = opts.borderhighlight
157162
if (opts.cursorline) config.cursorline = 1
163+
if (opts.position) config.relative = opts.position === "fixed" ? config.relative = "editor" : "cursor"
164+
if (typeof opts.top === 'number' && opts.top >= 0) config.top = opts.top
165+
if (typeof opts.left === 'number' && opts.left >= 0) config.left = opts.left
166+
if (typeof opts.bottom === 'number' && opts.bottom >= 0) config.bottom = opts.bottom
167+
if (typeof opts.right === 'number' && opts.right >= 0) config.right = opts.right
158168
let autoHide = opts.autoHide === false ? false : true
159169
if (autoHide) config.autohide = 1
160170
this.unbind()

typings/index.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -9829,6 +9829,11 @@ declare module 'coc.nvim' {
98299829
cursorline?: boolean
98309830
modes?: string[]
98319831
excludeImages?: boolean
9832+
position?: "fixed" | "auto";
9833+
top?: number;
9834+
bottom?: number;
9835+
left?: number;
9836+
right?: number;
98329837
}
98339838

98349839
export interface FloatFactory {

0 commit comments

Comments
 (0)