diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
commit | 9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch) | |
tree | 607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/api/win_config.c | |
parent | 9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff) | |
parent | 3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff) | |
download | rneovim-usermarks.tar.gz rneovim-usermarks.tar.bz2 rneovim-usermarks.zip |
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/api/win_config.c')
-rw-r--r-- | src/nvim/api/win_config.c | 158 |
1 files changed, 145 insertions, 13 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 6c37df6af8..0ffeac1bff 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -1,19 +1,27 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <assert.h> #include <stdbool.h> -#include <stddef.h> -#include <stdint.h> +#include <string.h> +#include "klib/kvec.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/win_config.h" #include "nvim/ascii.h" +#include "nvim/buffer_defs.h" +#include "nvim/decoration.h" #include "nvim/drawscreen.h" +#include "nvim/extmark_defs.h" +#include "nvim/globals.h" +#include "nvim/grid_defs.h" #include "nvim/highlight_group.h" +#include "nvim/macros.h" +#include "nvim/mbyte.h" +#include "nvim/memory.h" #include "nvim/option.h" -#include "nvim/strings.h" +#include "nvim/pos.h" #include "nvim/syntax.h" #include "nvim/ui.h" #include "nvim/window.h" @@ -47,13 +55,13 @@ /// this should not be used to specify arbitrary WM screen positions. /// /// Example (Lua): window-relative float -/// <pre> +/// <pre>lua /// vim.api.nvim_open_win(0, false, /// {relative='win', row=3, col=3, width=12, height=3}) /// </pre> /// /// Example (Lua): buffer-relative float (travels as buffer is scrolled) -/// <pre> +/// <pre>lua /// vim.api.nvim_open_win(0, false, /// {relative='win', width=12, height=3, bufpos={100,10}}) /// </pre> @@ -66,6 +74,7 @@ /// - "editor" The global editor grid /// - "win" Window given by the `win` field, or current window. /// - "cursor" Cursor position in current window. +/// - "mouse" Mouse position /// - win: |window-ID| for relative="win". /// - anchor: Decides which corner of the float to place at (row,col): /// - "NW" northwest (default) @@ -106,10 +115,11 @@ /// 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. The -/// end-of-buffer region is hidden by setting `eob` flag of +/// 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 -/// |EndOfBuffer| region in 'winhighlight'. +/// |hl-EndOfBuffer| region in 'winhighlight'. /// - border: Style of (optional) window border. This can either be a string /// or an array. The string values are /// - "none": No border (default). @@ -133,7 +143,12 @@ /// will only make vertical borders but not horizontal ones. /// By default, `FloatBorder` highlight is used, which links to `WinSeparator` /// when not defined. It could also be specified by character: -/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ]. +/// [ ["+", "MyCorner"], ["x", "MyBorder"] ]. +/// - title: Title (optional) in window border, String or list. +/// List is [text, highlight] tuples. if is string the default +/// highlight group is `FloatTitle`. +/// - title_pos: Title position must set with title option. +/// value can be of `left` `center` `right` default is left. /// - noautocmd: If true then no buffer-related autocommand events such as /// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from /// calling this function. @@ -202,7 +217,7 @@ void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err) if (!win_new_float(win, false, fconfig, err)) { return; } - redraw_later(win, NOT_VALID); + redraw_later(win, UPD_NOT_VALID); } else { win_config_float(win, fconfig); win->w_pos_changed = true; @@ -263,7 +278,7 @@ Dictionary nvim_win_get_config(Window window, Error *err) String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T)); int hi_id = config->border_hl_ids[i]; - char *hi_name = (char *)syn_id2name(hi_id); + char *hi_name = syn_id2name(hi_id); if (hi_name[0]) { ADD(tuple, STRING_OBJ(s)); ADD(tuple, STRING_OBJ(cstr_to_string((const char *)hi_name))); @@ -273,6 +288,29 @@ Dictionary nvim_win_get_config(Window window, Error *err) } } PUT(rv, "border", ARRAY_OBJ(border)); + if (config->title) { + Array titles = ARRAY_DICT_INIT; + VirtText title_datas = config->title_chunks; + for (size_t i = 0; i < title_datas.size; i++) { + Array tuple = ARRAY_DICT_INIT; + ADD(tuple, CSTR_TO_OBJ((const char *)title_datas.items[i].text)); + if (title_datas.items[i].hl_id > 0) { + ADD(tuple, + STRING_OBJ(cstr_to_string((const char *)syn_id2name(title_datas.items[i].hl_id)))); + } + ADD(titles, ARRAY_OBJ(tuple)); + } + PUT(rv, "title", ARRAY_OBJ(titles)); + char *title_pos; + if (config->title_pos == kAlignLeft) { + title_pos = "left"; + } else if (config->title_pos == kAlignCenter) { + title_pos = "center"; + } else { + title_pos = "right"; + } + PUT(rv, "title_pos", CSTR_TO_OBJ(title_pos)); + } } } @@ -312,6 +350,8 @@ static bool parse_float_relative(String relative, FloatRelative *out) *out = kFloatRelativeWindow; } else if (striequal(str, "cursor")) { *out = kFloatRelativeCursor; + } else if (striequal(str, "mouse")) { + *out = kFloatRelativeMouse; } else { return false; } @@ -330,7 +370,74 @@ static bool parse_float_bufpos(Array bufpos, lpos_T *out) return true; } -static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) +static void parse_border_title(Object title, Object title_pos, FloatConfig *fconfig, Error *err) +{ + if (!parse_title_pos(title_pos, fconfig, err)) { + return; + } + + if (title.type == kObjectTypeString) { + if (title.data.string.size == 0) { + fconfig->title = false; + return; + } + int hl_id = syn_check_group(S_LEN("FloatTitle")); + kv_push(fconfig->title_chunks, ((VirtTextChunk){ .text = xstrdup(title.data.string.data), + .hl_id = hl_id })); + fconfig->title_width = (int)mb_string2cells(title.data.string.data); + fconfig->title = true; + return; + } + + if (title.type != kObjectTypeArray) { + api_set_error(err, kErrorTypeValidation, "title must be string or array"); + return; + } + + if (title.data.array.size == 0) { + api_set_error(err, kErrorTypeValidation, "title cannot be an empty array"); + return; + } + + fconfig->title_width = 0; + fconfig->title_chunks = parse_virt_text(title.data.array, err, &fconfig->title_width); + + fconfig->title = true; +} + +static bool parse_title_pos(Object title_pos, FloatConfig *fconfig, Error *err) +{ + if (!HAS_KEY(title_pos)) { + fconfig->title_pos = kAlignLeft; + return true; + } + + if (title_pos.type != kObjectTypeString) { + api_set_error(err, kErrorTypeValidation, "title_pos must be string"); + return false; + } + + if (title_pos.data.string.size == 0) { + fconfig->title_pos = kAlignLeft; + return true; + } + + char *pos = title_pos.data.string.data; + + if (strequal(pos, "left")) { + fconfig->title_pos = kAlignLeft; + } else if (strequal(pos, "center")) { + fconfig->title_pos = kAlignCenter; + } else if (strequal(pos, "right")) { + fconfig->title_pos = kAlignRight; + } else { + api_set_error(err, kErrorTypeValidation, "invalid title_pos value"); + return false; + } + return true; +} + +static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) { struct { const char *name; @@ -414,6 +521,8 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) String str = style.data.string; if (str.size == 0 || strequal(str.data, "none")) { fconfig->border = false; + // title does not work with border equal none + fconfig->title = false; return; } for (size_t i = 0; defaults[i].name; i++) { @@ -603,6 +712,29 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, return false; } + if (HAS_KEY(config->title_pos)) { + if (!HAS_KEY(config->title)) { + api_set_error(err, kErrorTypeException, "title_pos requires title to be set"); + return false; + } + } + + if (HAS_KEY(config->title)) { + // title only work with border + if (!HAS_KEY(config->border) && !fconfig->border) { + api_set_error(err, kErrorTypeException, "title requires border to be set"); + return false; + } + + if (fconfig->title) { + clear_virttext(&fconfig->title_chunks); + } + parse_border_title(config->title, config->title_pos, fconfig, err); + if (ERROR_SET(err)) { + return false; + } + } + if (HAS_KEY(config->border)) { parse_border_style(config->border, fconfig, err); if (ERROR_SET(err)) { |