feat(float): 'statusline' in floating windows #36521

Problem:
Can't show 'statusline' in floating windows.

Solution:
Use window-local 'statusline' to control floating window statusline visibility.
This commit is contained in:
glepnir
2025-11-27 01:10:45 +08:00
committed by GitHub
parent 23d0d4c92a
commit 8a626e5c4a
13 changed files with 414 additions and 254 deletions
+70 -70
View File
@@ -3781,70 +3781,12 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
• {enter} (`boolean`) Enter the window (make it the current window)
• {config} (`vim.api.keyset.win_config`) Map defining the window
configuration. Keys:
• relative: Sets the window layout to "floating", placed at
(row,col) coordinates relative to:
• "cursor" Cursor position in current window.
• "editor" The global editor grid.
• "laststatus" 'laststatus' if present, or last row.
• "mouse" Mouse position.
• "tabline" Tabline if present, or first row.
• "win" Window given by the `win` field, or current
window.
• win: |window-ID| window to split, or relative window when
creating a float (relative="win").
• anchor: Decides which corner of the float to place at
(row,col):
• "NW" northwest (default)
• "NE" northeast
• "SW" southwest
• "SE" southeast
• width: Window width (in character cells). Minimum of 1.
• height: Window height (in character cells). Minimum of 1.
• bufpos: Places float relative to buffer text (only when
relative="win"). Takes a tuple of zero-indexed
`[line, column]`. `row` and `col` if given are applied
relative to this position, else they default to:
• `row=1` and `col=0` if `anchor` is "NW" or "NE"
• `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
like a tooltip near the buffer text).
• row: Row position in units of "screen cell height", may be
fractional.
• col: Column position in units of screen cell width, may be
fractional.
• focusable: Enable focus by user actions (wincmds, mouse
events). Defaults to true. Non-focusable windows can be
entered by |nvim_set_current_win()|, or, when the `mouse`
field is set to true, by mouse events. See |focusable|.
• mouse: Specify how this window interacts with mouse
events. Defaults to `focusable` value.
• If false, mouse events pass through this window.
• If true, mouse events interact with this window
normally.
• external: GUI should display the window as an external
top-level window. Currently accepts no other positioning
configuration together with this.
• zindex: Stacking order. floats with higher `zindex` go on
top on floats with lower indices. Must be larger than
zero. The following screen elements have hard-coded
z-indices:
• 100: insert completion popupmenu
• 200: message scrollback
• 250: cmdline completion popupmenu (when
wildoptions+=pum) The default value for floats are 50.
In general, values below 100 are recommended, unless
there is a good reason to overshadow builtin elements.
• style: (optional) Configure the appearance of the window.
Currently only supports one value:
• "minimal" Nvim will display the window with many UI
options disabled. This is useful when displaying a
temporary float where the text should not be edited.
Disables 'number', 'relativenumber', 'cursorline',
'cursorcolumn', 'foldcolumn', 'spell' and 'list'
options. 'signcolumn' is changed to `auto` and
'colorcolumn' is cleared. 'statuscolumn' is changed to
empty. The end-of-buffer region is hidden by setting
`eob` flag of 'fillchars' to a space char, and clearing
the |hl-EndOfBuffer| region in 'winhighlight'.
• border: (`string|string[]`) (defaults to 'winborder'
option) Window border. The string form accepts the same
values as the 'winborder' option. The array form must have
@@ -3870,13 +3812,24 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
side can specify an optional highlight: >
[ ["+", "MyCorner"], ["x", "MyBorder"] ].
<
title: (optional) Title in window border, string or list.
List should consist of `[text, highlight]` tuples. If
string, or a tuple lacks a highlight, the default
highlight group is `FloatTitle`.
• title_pos: Title position. Must be set with `title`
option. Value can be one of "left", "center", or "right".
Default is `"left"`.
bufpos: Places float relative to buffer text (only when
relative="win"). Takes a tuple of zero-indexed
`[line, column]`. `row` and `col` if given are applied
relative to this position, else they default to:
• `row=1` and `col=0` if `anchor` is "NW" or "NE"
• `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
like a tooltip near the buffer text).
• col: Column position in units of screen cell width, may be
fractional.
• external: GUI should display the window as an external
top-level window. Currently accepts no other positioning
configuration together with this.
• fixed: If true when anchor is NW or SW, the float window
would be kept fixed even if the window would be truncated.
• focusable: Enable focus by user actions (wincmds, mouse
events). Defaults to true. Non-focusable windows can be
entered by |nvim_set_current_win()|, or, when the `mouse`
field is set to true, by mouse events. See |focusable|.
• footer: (optional) Footer in window border, string or
list. List should consist of `[text, highlight]` tuples.
If string, or a tuple lacks a highlight, the default
@@ -3884,14 +3837,61 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
• footer_pos: Footer position. Must be set with `footer`
option. Value can be one of "left", "center", or "right".
Default is `"left"`.
noautocmd: Block all autocommands for the duration of the
call. Cannot be changed by |nvim_win_set_config()|.
• fixed: If true when anchor is NW or SW, the float window
would be kept fixed even if the window would be truncated.
height: Window height (in character cells). Minimum of 1.
• hide: If true the floating window will be hidden and the
cursor will be invisible when focused on it.
vertical: Split vertically |:vertical|.
mouse: Specify how this window interacts with mouse
events. Defaults to `focusable` value.
• If false, mouse events pass through this window.
• If true, mouse events interact with this window
normally.
• noautocmd: Block all autocommands for the duration of the
call. Cannot be changed by |nvim_win_set_config()|.
• relative: Sets the window layout to "floating", placed at
(row,col) coordinates relative to:
• "cursor" Cursor position in current window.
• "editor" The global editor grid.
• "laststatus" 'laststatus' if present, or last row.
• "mouse" Mouse position.
• "tabline" Tabline if present, or first row.
• "win" Window given by the `win` field, or current
window.
• row: Row position in units of "screen cell height", may be
fractional.
• split: Split direction: "left", "right", "above", "below".
• style: (optional) Configure the appearance of the window.
Currently only supports one value:
• "minimal" Nvim will display the window with many UI
options disabled. This is useful when displaying a
temporary float where the text should not be edited.
Disables 'number', 'relativenumber', 'cursorline',
'cursorcolumn', 'foldcolumn', 'spell' and 'list'
options. 'signcolumn' is changed to `auto` and
'colorcolumn' is cleared. 'statuscolumn' is changed to
empty. The end-of-buffer region is hidden by setting
`eob` flag of 'fillchars' to a space char, and clearing
the |hl-EndOfBuffer| region in 'winhighlight'.
• title: (optional) Title in window border, string or list.
List should consist of `[text, highlight]` tuples. If
string, or a tuple lacks a highlight, the default
highlight group is `FloatTitle`.
• title_pos: Title position. Must be set with `title`
option. Value can be one of "left", "center", or "right".
Default is `"left"`.
• vertical: Split vertically |:vertical|.
• width: Window width (in character cells). Minimum of 1.
• win: |window-ID| window to split, or relative window when
creating a float (relative="win").
• zindex: Stacking order. floats with higher `zindex` go on
top on floats with lower indices. Must be larger than
zero. The following screen elements have hard-coded
z-indices:
• 100: insert completion popupmenu
• 200: message scrollback
• 250: cmdline completion popupmenu (when
wildoptions+=pum) The default value for floats are 50.
In general, values below 100 are recommended, unless
there is a good reason to overshadow builtin elements.
• _cmdline_offset: (EXPERIMENTAL) When provided, anchor the
|cmdline-completion| popupmenu to this window, with an
offset in screen cell width.
+2
View File
@@ -151,6 +151,8 @@ API
escape sequences to the terminal when Nvim is running in the |TUI|.
• |nvim_echo()| can set the |ui-messages| kind with which to emit the message.
• |nvim_echo()| can create |Progress| messages
• |nvim_open_win()| floating windows can show a 'statusline'. Plugins can use
`style='minimal'` or `:setlocal statusline=` to hide the statusline.
BUILD
+2
View File
@@ -127,6 +127,8 @@ You can change the contents of the status line with the 'statusline' option.
This option can be local to the window, so that you can have a different
status line in each window.
Note: |floating-windows| 'statusline' is not affected by 'laststatus'.
Normally, inversion is used to display the status line. This can be changed
with the |hl-StatusLine| highlight group. If no highlighting is used for the
status line, the '^' character is used for the current window, and '=' for
+69 -69
View File
@@ -1758,64 +1758,11 @@ function vim.api.nvim_open_term(buffer, opts) end
--- @param buffer integer Buffer to display, or 0 for current buffer
--- @param enter boolean Enter the window (make it the current window)
--- @param config vim.api.keyset.win_config Map defining the window configuration. Keys:
--- - relative: Sets the window layout to "floating", placed at (row,col)
--- coordinates relative to:
--- - "cursor" Cursor position in current window.
--- - "editor" The global editor grid.
--- - "laststatus" 'laststatus' if present, or last row.
--- - "mouse" Mouse position.
--- - "tabline" Tabline if present, or first row.
--- - "win" Window given by the `win` field, or current window.
--- - win: `window-ID` window to split, or relative window when creating a
--- float (relative="win").
--- - anchor: Decides which corner of the float to place at (row,col):
--- - "NW" northwest (default)
--- - "NE" northeast
--- - "SW" southwest
--- - "SE" southeast
--- - width: Window width (in character cells). Minimum of 1.
--- - height: Window height (in character cells). Minimum of 1.
--- - bufpos: Places float relative to buffer text (only when
--- relative="win"). Takes a tuple of zero-indexed `[line, column]`.
--- `row` and `col` if given are applied relative to this
--- position, else they default to:
--- - `row=1` and `col=0` if `anchor` is "NW" or "NE"
--- - `row=0` and `col=0` if `anchor` is "SW" or "SE"
--- (thus like a tooltip near the buffer text).
--- - row: Row position in units of "screen cell height", may be fractional.
--- - col: Column position in units of screen cell width, may be fractional.
--- - focusable: Enable focus by user actions (wincmds, mouse events).
--- Defaults to true. Non-focusable windows can be entered by
--- `nvim_set_current_win()`, or, when the `mouse` field is set to true,
--- by mouse events. See `focusable`.
--- - mouse: Specify how this window interacts with mouse events.
--- Defaults to `focusable` value.
--- - If false, mouse events pass through this window.
--- - If true, mouse events interact with this window normally.
--- - external: GUI should display the window as an external
--- top-level window. Currently accepts no other positioning
--- configuration together with this.
--- - zindex: Stacking order. floats with higher `zindex` go on top on
--- floats with lower indices. Must be larger than zero. The
--- following screen elements have hard-coded z-indices:
--- - 100: insert completion popupmenu
--- - 200: message scrollback
--- - 250: cmdline completion popupmenu (when wildoptions+=pum)
--- The default value for floats are 50. In general, values below 100 are
--- recommended, unless there is a good reason to overshadow builtin
--- elements.
--- - style: (optional) Configure the appearance of the window. Currently
--- only supports one value:
--- - "minimal" Nvim will display the window with many UI options
--- disabled. This is useful when displaying a temporary
--- float where the text should not be edited. Disables
--- 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
--- 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
--- is changed to `auto` and 'colorcolumn' is cleared.
--- 'statuscolumn' is changed to empty. The end-of-buffer
--- region is hidden by setting `eob` flag of
--- 'fillchars' to a space char, and clearing the
--- `hl-EndOfBuffer` region in 'winhighlight'.
--- - border: (`string|string[]`) (defaults to 'winborder' option) Window border. The string form
--- accepts the same values as the 'winborder' option. The array form must have a length of
--- eight or any divisor of eight, specifying the chars that form the border in a clockwise
@@ -1839,30 +1786,83 @@ function vim.api.nvim_open_term(buffer, opts) end
--- [ "", "", "", ">", "", "", "", "<" ]
--- ```
--- By default, `hl-FloatBorder` highlight is used, which links to `hl-WinSeparator` when not
--- defined. Each border side can specify an optional highlight:
--- defined. Each border side can specify an optional highlight:
--- ```
--- [ ["+", "MyCorner"], ["x", "MyBorder"] ].
--- ```
--- - title: (optional) Title in window border, string or list.
--- List should consist of `[text, highlight]` tuples.
--- If string, or a tuple lacks a highlight, the default highlight group is `FloatTitle`.
--- - title_pos: Title position. Must be set with `title` option.
--- Value can be one of "left", "center", or "right".
--- Default is `"left"`.
--- - footer: (optional) Footer in window border, string or list.
--- List should consist of `[text, highlight]` tuples.
--- If string, or a tuple lacks a highlight, the default highlight group is `FloatFooter`.
--- - footer_pos: Footer position. Must be set with `footer` option.
--- Value can be one of "left", "center", or "right".
--- Default is `"left"`.
--- - noautocmd: Block all autocommands for the duration of the call. Cannot be changed by
--- `nvim_win_set_config()`.
--- - bufpos: Places float relative to buffer text (only when
--- relative="win"). Takes a tuple of zero-indexed `[line, column]`.
--- `row` and `col` if given are applied relative to this
--- position, else they default to:
--- - `row=1` and `col=0` if `anchor` is "NW" or "NE"
--- - `row=0` and `col=0` if `anchor` is "SW" or "SE"
--- (thus like a tooltip near the buffer text).
--- - col: Column position in units of screen cell width, may be fractional.
--- - external: GUI should display the window as an external
--- top-level window. Currently accepts no other positioning
--- configuration together with this.
--- - fixed: If true when anchor is NW or SW, the float window
--- would be kept fixed even if the window would be truncated.
--- - focusable: Enable focus by user actions (wincmds, mouse events).
--- Defaults to true. Non-focusable windows can be entered by
--- `nvim_set_current_win()`, or, when the `mouse` field is set to true,
--- by mouse events. See `focusable`.
--- - footer: (optional) Footer in window border, string or list.
--- List should consist of `[text, highlight]` tuples.
--- If string, or a tuple lacks a highlight, the default highlight group is `FloatFooter`.
--- - footer_pos: Footer position. Must be set with `footer` option.
--- Value can be one of "left", "center", or "right".
--- Default is `"left"`.
--- - height: Window height (in character cells). Minimum of 1.
--- - hide: If true the floating window will be hidden and the cursor will be invisible when
--- focused on it.
--- - vertical: Split vertically `:vertical`.
--- - mouse: Specify how this window interacts with mouse events.
--- Defaults to `focusable` value.
--- - If false, mouse events pass through this window.
--- - If true, mouse events interact with this window normally.
--- - noautocmd: Block all autocommands for the duration of the call. Cannot be changed by
--- `nvim_win_set_config()`.
--- - relative: Sets the window layout to "floating", placed at (row,col)
--- coordinates relative to:
--- - "cursor" Cursor position in current window.
--- - "editor" The global editor grid.
--- - "laststatus" 'laststatus' if present, or last row.
--- - "mouse" Mouse position.
--- - "tabline" Tabline if present, or first row.
--- - "win" Window given by the `win` field, or current window.
--- - row: Row position in units of "screen cell height", may be fractional.
--- - split: Split direction: "left", "right", "above", "below".
--- - style: (optional) Configure the appearance of the window. Currently
--- only supports one value:
--- - "minimal" Nvim will display the window with many UI options
--- disabled. This is useful when displaying a temporary
--- float where the text should not be edited. Disables
--- 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
--- 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
--- is changed to `auto` and 'colorcolumn' is cleared.
--- 'statuscolumn' is changed to empty. The end-of-buffer
--- region is hidden by setting `eob` flag of
--- 'fillchars' to a space char, and clearing the
--- `hl-EndOfBuffer` region in 'winhighlight'.
--- - title: (optional) Title in window border, string or list.
--- List should consist of `[text, highlight]` tuples.
--- If string, or a tuple lacks a highlight, the default highlight group is `FloatTitle`.
--- - title_pos: Title position. Must be set with `title` option.
--- Value can be one of "left", "center", or "right".
--- Default is `"left"`.
--- - vertical: Split vertically `:vertical`.
--- - width: Window width (in character cells). Minimum of 1.
--- - win: `window-ID` window to split, or relative window when creating a
--- float (relative="win").
--- - zindex: Stacking order. floats with higher `zindex` go on top on
--- floats with lower indices. Must be larger than zero. The
--- following screen elements have hard-coded z-indices:
--- - 100: insert completion popupmenu
--- - 200: message scrollback
--- - 250: cmdline completion popupmenu (when wildoptions+=pum)
--- The default value for floats are 50. In general, values below 100 are
--- recommended, unless there is a good reason to overshadow builtin
--- elements.
--- - _cmdline_offset: (EXPERIMENTAL) When provided, anchor the `cmdline-completion`
--- popupmenu to this window, with an offset in screen cell width.
--- @return integer # |window-ID|, or 0 on error
+17 -17
View File
@@ -440,29 +440,29 @@ error('Cannot require a meta file')
--- @field register? boolean
--- @class vim.api.keyset.win_config
--- @field row? number
--- @field col? number
--- @field width? integer
--- @field height? integer
--- @field anchor? "NW"|"NE"|"SW"|"SE"
--- @field relative? "cursor"|"editor"|"laststatus"|"mouse"|"tabline"|"win"
--- @field split? "left"|"right"|"above"|"below"
--- @field win? integer
--- @field bufpos? integer[]
--- @field external? boolean
--- @field fixed? boolean
--- @field focusable? boolean
--- @field mouse? boolean
--- @field vertical? boolean
--- @field zindex? integer
--- @field border? string[]|"none"|"single"|"double"|"rounded"|"solid"|"shadow"
--- @field title? any
--- @field title_pos? "center"|"left"|"right"
--- @field footer? any
--- @field footer_pos? "center"|"left"|"right"
--- @field hide? boolean
--- @field height? integer
--- @field mouse? boolean
--- @field relative? "cursor"|"editor"|"laststatus"|"mouse"|"tabline"|"win"
--- @field row? number
--- @field style? "minimal"
--- @field noautocmd? boolean
--- @field fixed? boolean
--- @field hide? boolean
--- @field vertical? boolean
--- @field win? integer
--- @field width? integer
--- @field zindex? integer
--- @field anchor? "NW"|"NE"|"SW"|"SE"
--- @field border? string[]|"none"|"single"|"double"|"rounded"|"solid"|"shadow"
--- @field bufpos? integer[]
--- @field col? number
--- @field split? "left"|"right"|"above"|"below"
--- @field title? any
--- @field title_pos? "center"|"left"|"right"
--- @field _cmdline_offset? integer
--- @class vim.api.keyset.win_text_height
+17 -17
View File
@@ -116,29 +116,29 @@ typedef struct {
typedef struct {
OptionalKeys is_set__win_config_;
Float row;
Float col;
Integer width;
Integer height;
Enum("NW", "NE", "SW", "SE") anchor;
Enum("cursor", "editor", "laststatus", "mouse", "tabline", "win") relative;
Enum("left", "right", "above", "below") split;
Window win;
ArrayOf(Integer) bufpos;
Boolean external;
Boolean fixed;
Boolean focusable;
Boolean mouse;
Boolean vertical;
Integer zindex;
Union(ArrayOf(String), Enum("none", "single", "double", "rounded", "solid", "shadow")) border;
Object title;
Enum("center", "left", "right") title_pos;
Object footer;
Enum("center", "left", "right") footer_pos;
Boolean hide;
Integer height;
Boolean mouse;
Enum("cursor", "editor", "laststatus", "mouse", "tabline", "win") relative;
Float row;
Enum("minimal") style;
Boolean noautocmd;
Boolean fixed;
Boolean hide;
Boolean vertical;
Window win;
Integer width;
Integer zindex;
Enum("NW", "NE", "SW", "SE") anchor;
Union(ArrayOf(String), Enum("none", "single", "double", "rounded", "solid", "shadow")) border;
ArrayOf(Integer) bufpos;
Float col;
Enum("left", "right", "above", "below") split;
Object title;
Enum("center", "left", "right") title_pos;
Integer _cmdline_offset;
} Dict(win_config);
+69 -69
View File
@@ -94,64 +94,11 @@
/// @param buffer Buffer to display, or 0 for current buffer
/// @param enter Enter the window (make it the current window)
/// @param config Map defining the window configuration. Keys:
/// - relative: Sets the window layout to "floating", placed at (row,col)
/// coordinates relative to:
/// - "cursor" Cursor position in current window.
/// - "editor" The global editor grid.
/// - "laststatus" 'laststatus' if present, or last row.
/// - "mouse" Mouse position.
/// - "tabline" Tabline if present, or first row.
/// - "win" Window given by the `win` field, or current window.
/// - win: |window-ID| window to split, or relative window when creating a
/// float (relative="win").
/// - anchor: Decides which corner of the float to place at (row,col):
/// - "NW" northwest (default)
/// - "NE" northeast
/// - "SW" southwest
/// - "SE" southeast
/// - width: Window width (in character cells). Minimum of 1.
/// - height: Window height (in character cells). Minimum of 1.
/// - bufpos: Places float relative to buffer text (only when
/// relative="win"). Takes a tuple of zero-indexed `[line, column]`.
/// `row` and `col` if given are applied relative to this
/// position, else they default to:
/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
/// (thus like a tooltip near the buffer text).
/// - row: Row position in units of "screen cell height", may be fractional.
/// - col: Column position in units of screen cell width, may be fractional.
/// - focusable: Enable focus by user actions (wincmds, mouse events).
/// Defaults to true. Non-focusable windows can be entered by
/// |nvim_set_current_win()|, or, when the `mouse` field is set to true,
/// by mouse events. See |focusable|.
/// - mouse: Specify how this window interacts with mouse events.
/// Defaults to `focusable` value.
/// - If false, mouse events pass through this window.
/// - If true, mouse events interact with this window normally.
/// - external: GUI should display the window as an external
/// top-level window. Currently accepts no other positioning
/// configuration together with this.
/// - zindex: Stacking order. floats with higher `zindex` go on top on
/// floats with lower indices. Must be larger than zero. The
/// following screen elements have hard-coded z-indices:
/// - 100: insert completion popupmenu
/// - 200: message scrollback
/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
/// The default value for floats are 50. In general, values below 100 are
/// recommended, unless there is a good reason to overshadow builtin
/// elements.
/// - style: (optional) Configure the appearance of the window. Currently
/// only supports one value:
/// - "minimal" Nvim will display the window with many UI options
/// disabled. This is useful when displaying a temporary
/// float where the text should not be edited. Disables
/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
/// 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
/// is changed to `auto` and 'colorcolumn' is cleared.
/// 'statuscolumn' is changed to empty. The end-of-buffer
/// region is hidden by setting `eob` flag of
/// 'fillchars' to a space char, and clearing the
/// |hl-EndOfBuffer| region in 'winhighlight'.
/// - border: (`string|string[]`) (defaults to 'winborder' option) Window border. The string form
/// accepts the same values as the 'winborder' option. The array form must have a length of
/// eight or any divisor of eight, specifying the chars that form the border in a clockwise
@@ -175,30 +122,83 @@
/// [ "", "", "", ">", "", "", "", "<" ]
/// ```
/// By default, |hl-FloatBorder| highlight is used, which links to |hl-WinSeparator| when not
/// defined. Each border side can specify an optional highlight:
/// defined. Each border side can specify an optional highlight:
/// ```
/// [ ["+", "MyCorner"], ["x", "MyBorder"] ].
/// ```
/// - title: (optional) Title in window border, string or list.
/// List should consist of `[text, highlight]` tuples.
/// If string, or a tuple lacks a highlight, the default highlight group is `FloatTitle`.
/// - title_pos: Title position. Must be set with `title` option.
/// Value can be one of "left", "center", or "right".
/// Default is `"left"`.
/// - footer: (optional) Footer in window border, string or list.
/// List should consist of `[text, highlight]` tuples.
/// If string, or a tuple lacks a highlight, the default highlight group is `FloatFooter`.
/// - footer_pos: Footer position. Must be set with `footer` option.
/// Value can be one of "left", "center", or "right".
/// Default is `"left"`.
/// - noautocmd: Block all autocommands for the duration of the call. Cannot be changed by
/// |nvim_win_set_config()|.
/// - bufpos: Places float relative to buffer text (only when
/// relative="win"). Takes a tuple of zero-indexed `[line, column]`.
/// `row` and `col` if given are applied relative to this
/// position, else they default to:
/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
/// (thus like a tooltip near the buffer text).
/// - col: Column position in units of screen cell width, may be fractional.
/// - external: GUI should display the window as an external
/// top-level window. Currently accepts no other positioning
/// configuration together with this.
/// - fixed: If true when anchor is NW or SW, the float window
/// would be kept fixed even if the window would be truncated.
/// - focusable: Enable focus by user actions (wincmds, mouse events).
/// Defaults to true. Non-focusable windows can be entered by
/// |nvim_set_current_win()|, or, when the `mouse` field is set to true,
/// by mouse events. See |focusable|.
/// - footer: (optional) Footer in window border, string or list.
/// List should consist of `[text, highlight]` tuples.
/// If string, or a tuple lacks a highlight, the default highlight group is `FloatFooter`.
/// - footer_pos: Footer position. Must be set with `footer` option.
/// Value can be one of "left", "center", or "right".
/// Default is `"left"`.
/// - height: Window height (in character cells). Minimum of 1.
/// - hide: If true the floating window will be hidden and the cursor will be invisible when
/// focused on it.
/// - vertical: Split vertically |:vertical|.
/// - mouse: Specify how this window interacts with mouse events.
/// Defaults to `focusable` value.
/// - If false, mouse events pass through this window.
/// - If true, mouse events interact with this window normally.
/// - noautocmd: Block all autocommands for the duration of the call. Cannot be changed by
/// |nvim_win_set_config()|.
/// - relative: Sets the window layout to "floating", placed at (row,col)
/// coordinates relative to:
/// - "cursor" Cursor position in current window.
/// - "editor" The global editor grid.
/// - "laststatus" 'laststatus' if present, or last row.
/// - "mouse" Mouse position.
/// - "tabline" Tabline if present, or first row.
/// - "win" Window given by the `win` field, or current window.
/// - row: Row position in units of "screen cell height", may be fractional.
/// - split: Split direction: "left", "right", "above", "below".
/// - style: (optional) Configure the appearance of the window. Currently
/// only supports one value:
/// - "minimal" Nvim will display the window with many UI options
/// disabled. This is useful when displaying a temporary
/// float where the text should not be edited. Disables
/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
/// 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
/// is changed to `auto` and 'colorcolumn' is cleared.
/// 'statuscolumn' is changed to empty. The end-of-buffer
/// region is hidden by setting `eob` flag of
/// 'fillchars' to a space char, and clearing the
/// |hl-EndOfBuffer| region in 'winhighlight'.
/// - title: (optional) Title in window border, string or list.
/// List should consist of `[text, highlight]` tuples.
/// If string, or a tuple lacks a highlight, the default highlight group is `FloatTitle`.
/// - title_pos: Title position. Must be set with `title` option.
/// Value can be one of "left", "center", or "right".
/// Default is `"left"`.
/// - vertical: Split vertically |:vertical|.
/// - width: Window width (in character cells). Minimum of 1.
/// - win: |window-ID| window to split, or relative window when creating a
/// float (relative="win").
/// - zindex: Stacking order. floats with higher `zindex` go on top on
/// floats with lower indices. Must be larger than zero. The
/// following screen elements have hard-coded z-indices:
/// - 100: insert completion popupmenu
/// - 200: message scrollback
/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
/// The default value for floats are 50. In general, values below 100 are
/// recommended, unless there is a good reason to overshadow builtin
/// elements.
/// - _cmdline_offset: (EXPERIMENTAL) When provided, anchor the |cmdline-completion|
/// popupmenu to this window, with an offset in screen cell width.
///
+1
View File
@@ -111,6 +111,7 @@
#include "nvim/undo_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
#include "nvim/winfloat.h"
#ifdef BACKSLASH_IN_FILENAME
# include "nvim/arglist.h"
+8 -1
View File
@@ -54,6 +54,7 @@
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
#include "nvim/winfloat.h"
#include "optionstr.c.generated.h"
@@ -1898,9 +1899,10 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf
}
const char *errmsg = NULL;
char *s = *varp;
bool is_stl = args->os_idx == kOptStatusline;
// reset statusline to default when setting global option and empty string is being set
if (args->os_idx == kOptStatusline
if (is_stl
&& ((args->os_flags & OPT_GLOBAL) || !(args->os_flags & OPT_LOCAL))
&& s[0] == NUL) {
xfree(*varp);
@@ -1908,6 +1910,11 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf
s = *varp;
}
// handle floating window statusline changes
if (is_stl && win && win->w_floating) {
win_config_float(win, win->w_config);
}
if (rulerformat && *s == '%') {
// set ru_wid if 'ruf' starts with "%99("
if (*++s == '-') { // ignore a '-'
+17 -6
View File
@@ -76,9 +76,14 @@ void win_redr_status(win_T *wp)
|| (wild_menu_showing != 0 && !ui_has(kUIWildmenu))) {
return;
}
wp->w_redr_status = false;
if (wp->w_floating && is_stl_global) {
return;
}
busy = true;
wp->w_redr_status = false;
if (wp->w_status_height == 0 && !(is_stl_global && wp == curwin)) {
// no status line, either global statusline is enabled or the window is a last window
redraw_cmdline = true;
@@ -229,7 +234,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool u
StlClickRecord *tabtab;
bool is_stl_global = global_stl_height() > 0;
ScreenGrid *grid = &default_grid;
ScreenGrid *grid = wp && wp->w_floating ? &wp->w_grid_alloc : &default_grid;
// There is a tiny chance that this gets called recursively: When
// redrawing a status line triggers redrawing the ruler or tabline.
@@ -269,10 +274,16 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool u
wp->w_winbar_click_defs = stl_alloc_click_defs(wp->w_winbar_click_defs, maxwidth,
&wp->w_winbar_click_defs_size);
} else {
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
fillchar = fillchar_status(&group, wp);
const bool in_status_line = wp->w_status_height != 0 || is_stl_global;
maxwidth = in_status_line && !is_stl_global ? wp->w_width : Columns;
if (wp->w_floating && !draw_ruler) {
row = wp->w_winrow_off + wp->w_view_height;
col = wp->w_wincol_off;
maxwidth = wp->w_view_width;
} else {
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
maxwidth = in_status_line && !is_stl_global ? wp->w_width : Columns;
}
fillchar = fillchar_status(&group, wp);
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
wp->w_status_click_defs = stl_alloc_click_defs(wp->w_status_click_defs, maxwidth,
&wp->w_status_click_defs_size);
@@ -310,7 +321,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool u
}
attr = win_hl_attr(wp, (int)group);
if (in_status_line && !is_stl_global) {
if (!wp->w_floating && in_status_line && !is_stl_global) {
col += wp->w_wincol;
}
}
+6 -3
View File
@@ -4542,6 +4542,7 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
prevwin = next_prevwin;
last_status(false); // status line may appear or disappear
win_float_update_statusline();
win_comp_pos(); // recompute w_winrow for all windows
diff_need_scrollbind = true;
@@ -6787,7 +6788,9 @@ void win_set_inner_size(win_T *wp, bool valid_cursor)
terminal_check_size(wp->w_buffer->terminal);
}
wp->w_height_outer = (wp->w_view_height + win_border_height(wp) + wp->w_winbar_height);
int float_stl_height = wp->w_floating && wp->w_status_height ? STATUS_HEIGHT : 0;
wp->w_height_outer = (wp->w_view_height + win_border_height(wp) + wp->w_winbar_height +
float_stl_height);
wp->w_width_outer = (wp->w_view_width + win_border_width(wp));
wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height;
wp->w_wincol_off = wp->w_border_adj[3];
@@ -6907,13 +6910,13 @@ void last_status(bool morewin)
}
// Remove status line from window, replacing it with a horizontal separator if needed.
static void win_remove_status_line(win_T *wp, bool add_hsep)
void win_remove_status_line(win_T *wp, bool add_hsep)
{
wp->w_status_height = 0;
if (add_hsep) {
wp->w_hsep_height = 1;
} else {
win_new_height(wp, wp->w_height + STATUS_HEIGHT);
win_new_height(wp, (wp->w_floating ? wp->w_view_height : wp->w_height) + STATUS_HEIGHT);
}
comp_col();
+30 -2
View File
@@ -104,7 +104,7 @@ win_T *win_new_float(win_T *wp, bool last, WinConfig fconfig, Error *err)
win_append(lastwin_nofloating(), wp, NULL);
}
wp->w_floating = true;
wp->w_status_height = 0;
wp->w_status_height = *wp->w_p_stl != NUL ? STATUS_HEIGHT : 0;
wp->w_winbar_height = 0;
wp->w_hsep_height = 0;
wp->w_vsep_width = 0;
@@ -166,6 +166,15 @@ void win_set_minimal_style(win_T *wp)
free_string_option(wp->w_p_stc);
wp->w_p_stc = xstrdup("");
}
// statusline: cleared (for floating windows)
if (wp->w_floating && wp->w_p_stl != NULL && *wp->w_p_stl != NUL) {
free_string_option(wp->w_p_stl);
wp->w_p_stl = xstrdup("");
if (wp->w_status_height > 0) {
win_config_float(wp, wp->w_config);
}
}
}
int win_border_height(win_T *wp)
@@ -180,6 +189,14 @@ int win_border_width(win_T *wp)
void win_config_float(win_T *wp, WinConfig fconfig)
{
// Process statusline changes before applying new height from config
bool show_stl = *wp->w_p_stl != NUL;
if (wp->w_status_height && !show_stl) {
win_remove_status_line(wp, false);
} else if (wp->w_status_height == 0 && show_stl) {
wp->w_status_height = STATUS_HEIGHT;
}
wp->w_width = MAX(fconfig.width, 1);
wp->w_height = MAX(fconfig.height, 1);
@@ -225,7 +242,7 @@ void win_config_float(win_T *wp, WinConfig fconfig)
win_set_inner_size(wp, true);
set_must_redraw(UPD_VALID);
wp->w_redr_status = wp->w_status_height;
wp->w_pos_changed = true;
if (change_external || change_border) {
wp->w_hl_needs_update = true;
@@ -308,6 +325,17 @@ void win_check_anchored_floats(win_T *win)
}
}
void win_float_update_statusline(void)
{
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
bool has_status = wp->w_status_height > 0;
bool should_show = *wp->w_p_stl != NUL;
if (should_show != has_status) {
win_config_float(wp, wp->w_config);
}
}
}
void win_float_anchor_laststatus(void)
{
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
+106
View File
@@ -892,3 +892,109 @@ describe('default statusline', function()
]])
end)
end)
describe("'statusline' in floatwin", function()
local screen
before_each(function()
clear()
screen = Screen.new(30, 20)
screen:add_extra_attr_ids({
[101] = { foreground = Screen.colors.Magenta1, bold = true },
[102] = {
foreground = Screen.colors.Magenta1,
underline = true,
background = Screen.colors.LightGray,
bold = true,
},
})
end)
it('controlled by ":setlocal statusline" and "style"', function()
local buf = api.nvim_create_buf(false, false)
api.nvim_buf_set_lines(buf, 0, -1, false, { '1', '2', '3', '4' })
local cfg = {
relative = 'editor',
row = 1,
col = 1,
height = 4,
width = 10,
border = 'single',
}
local win = api.nvim_open_win(buf, true, cfg)
local set_stl = [[setlocal stl=%f\ %m]]
command('set laststatus=2')
command(set_stl)
local has_stl = [[
|
{1:~}{1: }|
{1:~}{4:^1 }{1: }|
{1:~}{4:2 }{1: }|
{1:~}{4:3 }{1: }|
{1:~}{4:4 }{1: }|
{1:~}{3:<Name] [+]}{1: }|
{1:~}{1: }|
{1:~ }|*10
{2:[No Name] }|
|
]]
screen:expect(has_stl)
-- setting the style will clear the statusline expression for floating windows
api.nvim_win_set_config(win, { style = 'minimal' })
local without_stl = [[
|
{1:~}{1: }|
{1:~}{4:^1 }{1: }|
{1:~}{4:2 }{1: }|
{1:~}{4:3 }{1: }|
{1:~}{4:4 }{1: }|
{1:~}{1: }|
{1:~ }|*11
{2:[No Name] }|
|
]]
screen:expect(without_stl)
-- no statusline is displayed because the statusline option was cleared
api.nvim_win_set_config(win, cfg)
screen:expect(without_stl)
-- displayed after the option is reset
command(set_stl)
screen:expect(has_stl)
-- Show in a new window in a new tab, then return to the previous tab;
-- remove the statusline of the new window, When re-entering this new tab,
-- the statusline of the new window is cleared
command('tabnew')
local win2 = api.nvim_open_win(buf, false, cfg)
command(set_stl)
screen:expect([[
{24: }{102:2}{24:+ [No Name] }{5: }{101:2}{5:+ [No Name] }{2: }{24:X}|
^ |
{1:~}{4:1 }{1: }|
{1:~}{4:2 }{1: }|
{1:~}{4:3 }{1: }|
{1:~}{4:4 }{1: }|
{1:~}{1: }|
{1:~ }|*11
{3:[No Name] }|
|
]])
command('tabfirst')
api.nvim_win_set_config(win2, { style = 'minimal' })
command('tabnext')
screen:expect([[
{24: }{102:2}{24:+ [No Name] }{5: }{101:2}{5:+ [No Name] }{2: }{24:X}|
^ |
{1:~}{4:1 }{1: }|
{1:~}{4:2 }{1: }|
{1:~}{4:3 }{1: }|
{1:~}{4:4 }{1: }|
{1:~}{1: }|
{1:~ }|*11
{3:[No Name] }|
|
]])
end)
end)