mirror of https://github.com/neovim/neovim.git
Compare commits
3 Commits
48e88f7dd4
...
cd240d085b
Author | SHA1 | Date |
---|---|---|
glepnir | cd240d085b | |
dundargoc | c18d7941ef | |
glepnir | 20a5ba6796 |
|
@ -50,11 +50,6 @@ file(GLOB DOCFILES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt)
|
|||
set_directory_properties(PROPERTIES
|
||||
EP_PREFIX "${DEPS_BUILD_DIR}")
|
||||
|
||||
find_program(CCACHE_PRG ccache)
|
||||
if(CCACHE_PRG)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env CCACHE_SLOPPINESS=pch_defines,time_macros ${CCACHE_PRG})
|
||||
endif()
|
||||
|
||||
if(NOT CI_BUILD)
|
||||
set(CMAKE_INSTALL_MESSAGE NEVER)
|
||||
endif()
|
||||
|
|
|
@ -23,6 +23,12 @@ if(POLICY CMP0092)
|
|||
list(APPEND DEPS_CMAKE_ARGS -D CMAKE_POLICY_DEFAULT_CMP0092=NEW)
|
||||
endif()
|
||||
|
||||
find_program(CACHE_PRG NAMES ccache sccache)
|
||||
if(CACHE_PRG)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env CCACHE_SLOPPINESS=pch_defines,time_macros ${CACHE_PRG})
|
||||
list(APPEND DEPS_CMAKE_CACHE_ARGS -DCMAKE_C_COMPILER_LAUNCHER:STRING=${CMAKE_C_COMPILER_LAUNCHER})
|
||||
endif()
|
||||
|
||||
# MAKE_PRG
|
||||
if(UNIX)
|
||||
find_program(MAKE_PRG NAMES gmake make)
|
||||
|
@ -58,7 +64,8 @@ function(get_externalproject_options name DEPS_IGNORE_SHA)
|
|||
|
||||
set(EXTERNALPROJECT_OPTIONS
|
||||
DOWNLOAD_NO_PROGRESS TRUE
|
||||
EXTERNALPROJECT_OPTIONS URL ${${name_allcaps}_URL})
|
||||
EXTERNALPROJECT_OPTIONS URL ${${name_allcaps}_URL}
|
||||
CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
|
||||
|
||||
if(NOT ${DEPS_IGNORE_SHA})
|
||||
list(APPEND EXTERNALPROJECT_OPTIONS URL_HASH SHA256=${${name_allcaps}_SHA256})
|
||||
|
|
|
@ -386,6 +386,10 @@ The following new APIs and features were added.
|
|||
using the OSC 8 control sequence, enabling clickable text in supporting
|
||||
terminals.
|
||||
|
||||
• |extmarks| can be associated with a URL and URLs are included as a new
|
||||
highlight attribute. The TUI will display URLs using the OSC 8 control
|
||||
sequence, enabling clickable text in supporting terminals.
|
||||
|
||||
• Added |nvim_tabpage_set_win()| to set the current window of a tabpage.
|
||||
|
||||
• Clicking on a tabpage in the tabline with the middle mouse button closes it.
|
||||
|
@ -399,6 +403,8 @@ The following new APIs and features were added.
|
|||
• |vim.fs.root()| finds project root directories from a list of "root
|
||||
markers".
|
||||
|
||||
• Added 'previewpopup' option.
|
||||
|
||||
==============================================================================
|
||||
CHANGED FEATURES *news-changed*
|
||||
|
||||
|
|
|
@ -4609,6 +4609,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
Default height for a preview window. Used for |:ptag| and associated
|
||||
commands. Used for |CTRL-W_}| when no count is given.
|
||||
|
||||
*'previewpopup'* *'pvp'*
|
||||
'previewpopup' 'pvp' string (default "")
|
||||
global
|
||||
When not empty a floating window is used for commands that would open
|
||||
a preview window. See |preview-popup|.
|
||||
Not used for the insert completion info, add "popup" to
|
||||
'completeopt' for that.
|
||||
|
||||
*'previewwindow'* *'pvw'* *'nopreviewwindow'* *'nopvw'* *E590*
|
||||
'previewwindow' 'pvw' boolean (default off)
|
||||
local to window |local-noglobal|
|
||||
|
|
|
@ -590,7 +590,6 @@ These legacy Vim features are not yet implemented:
|
|||
- *:gui*
|
||||
- *:gvim*
|
||||
- *'completepopup'*
|
||||
- *'previewpopup'*
|
||||
|
||||
==============================================================================
|
||||
Removed legacy features *nvim-removed*
|
||||
|
|
|
@ -922,6 +922,26 @@ set in the preview window to be able to recognize it. The 'winfixheight'
|
|||
option is set to have it keep the same height when opening/closing other
|
||||
windows.
|
||||
|
||||
*preview-popup*
|
||||
Alternatively, a floating window can be used by setting the 'previewpopup'
|
||||
option. When set, it overrules the 'previewwindow' and 'previewheight'
|
||||
settings. The option is a comma-separated list of values:
|
||||
height maximum height of the popup
|
||||
width maximum width of the popup
|
||||
border string values are one of none, single, double, rounded,
|
||||
solid, shadow.
|
||||
Example: >vim
|
||||
:set previewpopup=border:double,height:10,width:60
|
||||
|
||||
A few peculiarities:
|
||||
- If the file is in a buffer already, it will be re-used. This will allow for
|
||||
editing the file while it's visible in the popup window.
|
||||
- No ATTENTION dialog will be used, since you can't edit the file in the popup
|
||||
window. However, if you later open the same buffer in a normal window, you
|
||||
may not notice it's edited elsewhere. And when then using ":edit" to
|
||||
trigger the ATTENTION and responding "A" for Abort, the preview window will
|
||||
become empty.
|
||||
|
||||
*:pta* *:ptag*
|
||||
:pta[g][!] [tagname]
|
||||
Does ":tag[!] [tagname]" and shows the found tag in a
|
||||
|
|
|
@ -4801,6 +4801,17 @@ vim.o.pvh = vim.o.previewheight
|
|||
vim.go.previewheight = vim.o.previewheight
|
||||
vim.go.pvh = vim.go.previewheight
|
||||
|
||||
--- When not empty a floating window is used for commands that would open
|
||||
--- a preview window. See `preview-popup`.
|
||||
--- Not used for the insert completion info, add "popup" to
|
||||
--- 'completeopt' for that.
|
||||
---
|
||||
--- @type string
|
||||
vim.o.previewpopup = ""
|
||||
vim.o.pvp = vim.o.previewpopup
|
||||
vim.go.previewpopup = vim.o.previewpopup
|
||||
vim.go.pvp = vim.go.previewpopup
|
||||
|
||||
--- Identifies the preview window. Only one window can have this option
|
||||
--- set. It's normally not set directly, but by using one of the commands
|
||||
--- `:ptag`, `:pedit`, etc.
|
||||
|
|
|
@ -835,8 +835,8 @@ static bool parse_float_bufpos(Array bufpos, lpos_T *out)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, WinConfig *fconfig,
|
||||
Error *err)
|
||||
void parse_bordertext(Object bordertext, BorderTextType bordertext_type, WinConfig *fconfig,
|
||||
Error *err)
|
||||
{
|
||||
if (bordertext.type != kObjectTypeString && bordertext.type != kObjectTypeArray) {
|
||||
api_set_error(err, kErrorTypeValidation, "title/footer must be string or array");
|
||||
|
@ -893,8 +893,8 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type,
|
|||
*is_present = true;
|
||||
}
|
||||
|
||||
static bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertext_type,
|
||||
WinConfig *fconfig, Error *err)
|
||||
bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertext_type, WinConfig *fconfig,
|
||||
Error *err)
|
||||
{
|
||||
AlignTextPos *align;
|
||||
switch (bordertext_type) {
|
||||
|
@ -933,7 +933,7 @@ static bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertex
|
|||
return true;
|
||||
}
|
||||
|
||||
static void parse_border_style(Object style, WinConfig *fconfig, Error *err)
|
||||
void parse_border_style(Object style, WinConfig *fconfig, Error *err)
|
||||
{
|
||||
struct {
|
||||
const char *name;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "nvim/api/keysets_defs.h" // IWYU pragma: keep
|
||||
#include "nvim/api/private/defs.h" // IWYU pragma: keep
|
||||
#include "nvim/buffer_defs.h" // IWYU pragma: keep
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "api/win_config.h.generated.h"
|
||||
|
|
|
@ -904,6 +904,11 @@ typedef enum {
|
|||
kFloatRelativeMouse = 3,
|
||||
} FloatRelative;
|
||||
|
||||
typedef enum {
|
||||
kFloatInfo = 0,
|
||||
kFloatPreview = 1,
|
||||
} FloatType;
|
||||
|
||||
/// Keep in sync with win_split_str[] in nvim_win_get_config() (api/win_config.c)
|
||||
typedef enum {
|
||||
kWinSplitLeft = 0,
|
||||
|
@ -1295,7 +1300,7 @@ struct window_S {
|
|||
ScreenGrid w_grid_alloc; // the grid specific to the window
|
||||
bool w_pos_changed; // true if window position changed
|
||||
bool w_floating; ///< whether the window is floating
|
||||
bool w_float_is_info; // the floating window is info float
|
||||
FloatType w_float_is; // the floating window is info float
|
||||
WinConfig w_config;
|
||||
|
||||
// w_fraction is the fractional row of the cursor within the window, from
|
||||
|
|
|
@ -98,6 +98,7 @@
|
|||
#include "nvim/undo.h"
|
||||
#include "nvim/vim_defs.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/winfloat.h"
|
||||
|
||||
/// Case matching style to use for :substitute
|
||||
typedef enum {
|
||||
|
@ -2617,6 +2618,10 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
|
|||
changed_line_abv_curs();
|
||||
|
||||
maketitle();
|
||||
if (curwin->w_floating && curwin->w_p_pvw) {
|
||||
win_float_set_title(curwin, false);
|
||||
win_float_adjust_position(curwin);
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the diff stuff that this buffer is new and/or needs updating.
|
||||
|
@ -4551,24 +4556,40 @@ void free_old_sub(void)
|
|||
/// @param undo_sync sync undo when leaving the window
|
||||
///
|
||||
/// @return true when it was created.
|
||||
bool prepare_tagpreview(bool undo_sync)
|
||||
bool prepare_tagpreview(bool undo_sync, bool use_float)
|
||||
{
|
||||
if (curwin->w_p_pvw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is already a preview window open, use that one.
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_p_pvw) {
|
||||
if (use_float) {
|
||||
win_T *wp = win_float_find_preview(false);
|
||||
if (wp) {
|
||||
win_enter(wp, undo_sync);
|
||||
return false;
|
||||
} else {
|
||||
wp = win_float_create(false, true, kFloatPreview);
|
||||
if (!wp) {
|
||||
return false;
|
||||
}
|
||||
win_enter(wp, undo_sync);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// If there is already a preview window open, use that one.
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_p_pvw) {
|
||||
win_enter(wp, undo_sync);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There is no preview window open yet. Create one.
|
||||
if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
|
||||
== FAIL) {
|
||||
return false;
|
||||
if (!use_float) {
|
||||
// There is no preview window open yet. Create one.
|
||||
if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
|
||||
== FAIL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
curwin->w_p_pvw = true;
|
||||
curwin->w_p_wfh = true;
|
||||
|
|
|
@ -4834,6 +4834,10 @@ static void ex_pclose(exarg_T *eap)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p_pvp != NUL) {
|
||||
win_float_close(kFloatPreview);
|
||||
}
|
||||
}
|
||||
|
||||
/// Close window "win" and take care of handling closing the last window for a
|
||||
|
@ -6790,7 +6794,7 @@ static void ex_pedit(exarg_T *eap)
|
|||
|
||||
// Open the preview window or popup and make it the current window.
|
||||
g_do_tagpreview = (int)p_pvh;
|
||||
prepare_tagpreview(true);
|
||||
prepare_tagpreview(true, *p_pvp != NUL);
|
||||
|
||||
// Edit the file.
|
||||
do_exedit(eap, NULL);
|
||||
|
@ -7565,7 +7569,7 @@ static void ex_terminal(exarg_T *eap)
|
|||
/// ":fclose"
|
||||
static void ex_fclose(exarg_T *eap)
|
||||
{
|
||||
win_float_remove(eap->forceit, eap->line1);
|
||||
win_float_remove_by_zindex(eap->forceit, eap->line1);
|
||||
}
|
||||
|
||||
void verify_command(char *cmd)
|
||||
|
|
|
@ -2821,7 +2821,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
|
|||
}
|
||||
if (ret == OK && (what_flag & CI_WHAT_SELECTED)) {
|
||||
ret = tv_dict_add_nr(retdict, S_LEN("selected"), selected_idx);
|
||||
win_T *wp = win_float_find_preview();
|
||||
win_T *wp = win_float_find_preview(true);
|
||||
if (wp != NULL) {
|
||||
tv_dict_add_nr(retdict, S_LEN("preview_winid"), wp->handle);
|
||||
tv_dict_add_nr(retdict, S_LEN("preview_bufnr"), wp->w_buffer->handle);
|
||||
|
|
|
@ -596,6 +596,7 @@ EXTERN unsigned rdb_flags;
|
|||
EXTERN OptInt p_rdt; ///< 'redrawtime'
|
||||
EXTERN OptInt p_re; ///< 'regexpengine'
|
||||
EXTERN OptInt p_report; ///< 'report'
|
||||
EXTERN char *p_pvp; ///< 'previewpopup'
|
||||
EXTERN OptInt p_pvh; ///< 'previewheight'
|
||||
EXTERN int p_ari; ///< 'allowrevins'
|
||||
EXTERN int p_ri; ///< 'revins'
|
||||
|
|
|
@ -6034,6 +6034,24 @@ return {
|
|||
type = 'number',
|
||||
varname = 'p_pvh',
|
||||
},
|
||||
{
|
||||
abbreviation = 'pvp',
|
||||
cb = 'did_set_previewpopup',
|
||||
expand_cb = 'expand_set_popupoption',
|
||||
defaults = { if_true = '' },
|
||||
desc = [=[
|
||||
When not empty a floating window is used for commands that would open
|
||||
a preview window. See |preview-popup|.
|
||||
Not used for the insert completion info, add "popup" to
|
||||
'completeopt' for that.
|
||||
]=],
|
||||
full_name = 'previewpopup',
|
||||
list = 'commacolon',
|
||||
scope = { 'global' },
|
||||
short_desc = N_('use a flaoting window for preview'),
|
||||
type = 'string',
|
||||
varname = 'p_pvp',
|
||||
},
|
||||
{
|
||||
abbreviation = 'pvw',
|
||||
cb = 'did_set_previewwindow',
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nvim/types_defs.h"
|
||||
#include "nvim/vim_defs.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/winfloat.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "optionstr.c.generated.h"
|
||||
|
@ -142,6 +143,11 @@ static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelt
|
|||
"flush", NULL };
|
||||
static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL };
|
||||
|
||||
// Note: Keep this in sync with parse_float_option()
|
||||
static char *(p_popup_option_values[]) = { "height:", "width:", "border:", NULL };
|
||||
static char *(p_popup_option_border_values[]) = { "single", "double", "none", "rounded", "solid",
|
||||
"shadow", NULL };
|
||||
|
||||
/// All possible flags for 'shm'.
|
||||
/// the literal chars before 0 are removed flags. these are safely ignored
|
||||
static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_LINES,
|
||||
|
@ -2881,3 +2887,41 @@ const char *check_chars_options(void)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *did_set_previewpopup(optset_T *args)
|
||||
{
|
||||
win_T *wp = win_float_find_preview(kFloatPreview);
|
||||
WinConfig fconfig = wp ? wp->w_config : WIN_CONFIG_INIT;
|
||||
if (!parse_float_option(&fconfig)) {
|
||||
return e_invarg;
|
||||
}
|
||||
|
||||
if (wp) {
|
||||
win_config_float(wp, fconfig);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int expand_set_popupoption(optexpand_T *args, int *numMatches, char ***matches)
|
||||
{
|
||||
expand_T *xp = args->oe_xp;
|
||||
|
||||
if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern - 1) == ':') {
|
||||
int arg_len = (int)(xp->xp_pattern - args->oe_set_arg);
|
||||
|
||||
// match border:
|
||||
if (arg_len >= 7 && strncmp(xp->xp_pattern - 7, "border:", 7) == 0) {
|
||||
return expand_set_opt_string(args, p_popup_option_border_values,
|
||||
ARRAY_SIZE(p_popup_option_border_values) - 1, numMatches,
|
||||
matches);
|
||||
}
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
return expand_set_opt_string(args,
|
||||
p_popup_option_values,
|
||||
ARRAY_SIZE(p_popup_option_values) - 1,
|
||||
numMatches,
|
||||
matches);
|
||||
}
|
||||
|
|
|
@ -745,9 +745,9 @@ win_T *pum_set_info(int selected, char *info)
|
|||
block_autocmds();
|
||||
RedrawingDisabled++;
|
||||
no_u_sync++;
|
||||
win_T *wp = win_float_find_preview();
|
||||
win_T *wp = win_float_find_preview(kFloatInfo);
|
||||
if (wp == NULL) {
|
||||
wp = win_float_create(false, true);
|
||||
wp = win_float_create(false, true, kFloatInfo);
|
||||
if (!wp) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -797,7 +797,7 @@ static bool pum_set_selected(int n, int repeat)
|
|||
bool use_float = strstr(p_cot, "popup") != NULL;
|
||||
// when new leader add and info window is shown and no selected we still
|
||||
// need use the first index item to update the info float window position.
|
||||
bool force_select = use_float && pum_selected < 0 && win_float_find_preview();
|
||||
bool force_select = use_float && pum_selected < 0 && win_float_find_preview(kFloatInfo);
|
||||
if (force_select) {
|
||||
pum_selected = 0;
|
||||
}
|
||||
|
@ -881,13 +881,13 @@ static bool pum_set_selected(int n, int repeat)
|
|||
no_u_sync++;
|
||||
|
||||
if (!use_float) {
|
||||
resized = prepare_tagpreview(false);
|
||||
resized = prepare_tagpreview(false, false);
|
||||
} else {
|
||||
win_T *wp = win_float_find_preview();
|
||||
win_T *wp = win_float_find_preview(kFloatInfo);
|
||||
if (wp) {
|
||||
win_enter(wp, false);
|
||||
} else {
|
||||
wp = win_float_create(true, true);
|
||||
wp = win_float_create(true, true, kFloatInfo);
|
||||
if (wp) {
|
||||
resized = true;
|
||||
}
|
||||
|
@ -898,7 +898,7 @@ static bool pum_set_selected(int n, int repeat)
|
|||
RedrawingDisabled--;
|
||||
g_do_tagpreview = 0;
|
||||
|
||||
if (curwin->w_p_pvw || curwin->w_float_is_info) {
|
||||
if (curwin->w_p_pvw || (curwin->w_float_is == kFloatInfo)) {
|
||||
int res = OK;
|
||||
if (!resized
|
||||
&& (curbuf->b_nwindows == 1)
|
||||
|
@ -1054,9 +1054,8 @@ void pum_check_clear(void)
|
|||
}
|
||||
pum_is_drawn = false;
|
||||
pum_external = false;
|
||||
win_T *wp = win_float_find_preview();
|
||||
if (wp != NULL) {
|
||||
win_close(wp, false, false);
|
||||
if (strstr(p_cot, "popup") != NULL) {
|
||||
win_float_close(kFloatInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4012,7 +4012,7 @@ search_line:
|
|||
// ":psearch" uses the preview window
|
||||
if (l_g_do_tagpreview != 0) {
|
||||
curwin_save = curwin;
|
||||
prepare_tagpreview(true);
|
||||
prepare_tagpreview(true, *p_pvp != NUL);
|
||||
}
|
||||
if (action == ACTION_SPLIT) {
|
||||
if (win_split(0, 0) == FAIL) {
|
||||
|
|
|
@ -2868,7 +2868,7 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
|
|||
|
||||
// Make the preview window the current window.
|
||||
// Open a preview window when needed.
|
||||
prepare_tagpreview(true);
|
||||
prepare_tagpreview(true, *p_pvp != NUL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,20 +7,32 @@
|
|||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/vim.h"
|
||||
#include "nvim/api/win_config.h"
|
||||
#include "nvim/ascii_defs.h"
|
||||
#include "nvim/autocmd.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/decoration.h"
|
||||
#include "nvim/decoration_defs.h"
|
||||
#include "nvim/drawscreen.h"
|
||||
#include "nvim/gettext_defs.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/grid.h"
|
||||
#include "nvim/grid_defs.h"
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_defs.h"
|
||||
#include "nvim/highlight_group.h"
|
||||
#include "nvim/macros_defs.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/mouse.h"
|
||||
#include "nvim/move.h"
|
||||
#include "nvim/option.h"
|
||||
#include "nvim/option_defs.h"
|
||||
#include "nvim/option_vars.h"
|
||||
#include "nvim/optionstr.h"
|
||||
#include "nvim/plines.h"
|
||||
#include "nvim/pos_defs.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/types_defs.h"
|
||||
|
@ -271,7 +283,7 @@ static int float_zindex_cmp(const void *a, const void *b)
|
|||
return za == zb ? 0 : za < zb ? 1 : -1;
|
||||
}
|
||||
|
||||
void win_float_remove(bool bang, int count)
|
||||
void win_float_remove_by_zindex(bool bang, int count)
|
||||
{
|
||||
kvec_t(win_T *) float_win_arr = KV_INITIAL_VALUE;
|
||||
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
|
||||
|
@ -330,10 +342,123 @@ bool win_float_valid(const win_T *win)
|
|||
return false;
|
||||
}
|
||||
|
||||
win_T *win_float_find_preview(void)
|
||||
/// Parses the 'border' style configuration and updates WinConfig.
|
||||
///
|
||||
/// @param fconfig Configuration storage.
|
||||
/// @param dup_val Value text to parse.
|
||||
/// @param len Length of the text.
|
||||
/// @param err Pointer to the Error structure for error handling.
|
||||
///
|
||||
/// @return true if parsing is successful, otherwise false.
|
||||
static bool parse_opt_border(WinConfig *config, char *dup_val, size_t len, Error *err)
|
||||
{
|
||||
Object style = CSTR_AS_OBJ(dup_val);
|
||||
parse_border_style(style, config, err);
|
||||
api_free_object(style);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
int border_attr = syn_name2attr("FloatBorder");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
config->border_attr[i] = config->border_hl_ids[i]
|
||||
? hl_get_ui_attr(0, HLF_BORDER, config->border_hl_ids[i], false)
|
||||
: border_attr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Parses numeric keys for 'height' and 'width' options and updates WinConfig.
|
||||
///
|
||||
/// @param fconfig Configuration storage.
|
||||
/// @param dig Digits representing the numeric value.
|
||||
/// @param len Length of the digits.
|
||||
/// @param err Pointer to the Error structure for error handling.
|
||||
///
|
||||
/// @return true if parsing is successful, otherwise false.
|
||||
static bool parse_opt_dig_key(WinConfig *config, char *dig, size_t len, Error *err)
|
||||
{
|
||||
int val = getdigits_int(&dig, false, 0);
|
||||
if (len == 6) {
|
||||
config->width = val;
|
||||
} else {
|
||||
config->height = val;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Parses options for configuring floating windows for completion popups or preview popups.
|
||||
/// Supports setting border style, title, title position, footer, footer position, height, and width.
|
||||
/// Only processes height and width options if `preview` is true.
|
||||
///
|
||||
/// @param fconfig The floating window configuration to modify.
|
||||
/// @param preview Indicates if the configuration is for a preview popup.
|
||||
///
|
||||
/// @return True if options are successfully parsed, otherwise false.
|
||||
bool parse_float_option(WinConfig *config)
|
||||
{
|
||||
char *p = p_pvp;
|
||||
Error err = ERROR_INIT;
|
||||
|
||||
struct {
|
||||
char *key;
|
||||
bool (*parser_func)(WinConfig *, char *, size_t, Error *);
|
||||
} parsers[] = {
|
||||
{ "border:", parse_opt_border },
|
||||
{ "height:", parse_opt_dig_key },
|
||||
{ "width:", parse_opt_dig_key },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
for (; *p != NUL; p += (*p == ',' ? 1 : 0)) {
|
||||
char *s = p;
|
||||
|
||||
char *e = strchr(p, ':');
|
||||
if (e == NULL || e[1] == NUL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
p = strchr(e, ',');
|
||||
if (p == NULL) {
|
||||
p = e + strlen(e);
|
||||
}
|
||||
|
||||
bool parsed = false;
|
||||
for (size_t i = 0; parsers[i].key; i++) {
|
||||
size_t len = strlen(parsers[i].key);
|
||||
if (strncmp(s, parsers[i].key, len) == 0) {
|
||||
// when is width or height use e + 1
|
||||
char *val = s[0] == 'w' || s[0] == 'h' ? e + 1 : NULL;
|
||||
if (!val) {
|
||||
val = xmemdupz(s + len, (p ? (size_t)(p - s) - len : (size_t)(s - len)));
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!parsers[i].parser_func(config, val, len, &err)) {
|
||||
return false;
|
||||
}
|
||||
parsed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parsed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Searches for a floating window matching given criteria.
|
||||
///
|
||||
/// @param find_info Search for info window if true, else preview window.
|
||||
///
|
||||
/// @return A pointer to the a floating window structure.
|
||||
win_T *win_float_find_preview(FloatType float_type)
|
||||
{
|
||||
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
|
||||
if (wp->w_float_is_info) {
|
||||
if (wp->w_float_is == float_type) {
|
||||
return wp;
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +489,7 @@ win_T *win_float_find_altwin(const win_T *win, const tabpage_T *tp)
|
|||
/// @param[in] bool create a new buffer for window.
|
||||
///
|
||||
/// @return win_T
|
||||
win_T *win_float_create(bool enter, bool new_buf)
|
||||
win_T *win_float_create(bool enter, bool new_buf, FloatType float_type)
|
||||
{
|
||||
WinConfig config = WIN_CONFIG_INIT;
|
||||
config.col = curwin->w_wcol;
|
||||
|
@ -375,8 +500,11 @@ win_T *win_float_create(bool enter, bool new_buf)
|
|||
config.noautocmd = true;
|
||||
config.hide = true;
|
||||
config.style = kWinStyleMinimal;
|
||||
if (float_type == kFloatPreview && !parse_float_option(&config)) {
|
||||
emsg(_(e_invarg));
|
||||
return NULL;
|
||||
}
|
||||
Error err = ERROR_INIT;
|
||||
|
||||
block_autocmds();
|
||||
win_T *wp = win_new_float(NULL, false, config, &err);
|
||||
if (!wp) {
|
||||
|
@ -400,9 +528,144 @@ win_T *win_float_create(bool enter, bool new_buf)
|
|||
}
|
||||
unblock_autocmds();
|
||||
wp->w_p_diff = false;
|
||||
wp->w_float_is_info = true;
|
||||
wp->w_float_is = float_type;
|
||||
if (wp->w_float_is == kFloatPreview) {
|
||||
wp->w_p_pvw = true;
|
||||
wp->w_p_wrap = true;
|
||||
wp->w_p_so = 0;
|
||||
}
|
||||
|
||||
if (enter) {
|
||||
win_enter(wp, false);
|
||||
}
|
||||
return wp;
|
||||
}
|
||||
|
||||
/// Closes a specified floating window used for previews or popups.
|
||||
/// Searches for and closes a floating window based on given criteria.
|
||||
///
|
||||
/// @param find_info Flag to determine search criteria for the floating window.
|
||||
///
|
||||
/// @return True if the window is successfully closed, otherwise false.
|
||||
bool win_float_close(FloatType float_type)
|
||||
{
|
||||
win_T *wp = win_float_find_preview(float_type);
|
||||
return wp && win_close(wp, false, false) != FAIL;
|
||||
}
|
||||
|
||||
/// Set bufname as title for a floating window.
|
||||
/// Title position is center.
|
||||
///
|
||||
/// @param wp A pointer of win_T
|
||||
/// @param redraw bool
|
||||
/// @return
|
||||
void win_float_set_title(win_T *wp, bool redraw)
|
||||
{
|
||||
if (!wp->w_floating || !wp->w_config.border) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wp->w_config.title) {
|
||||
clear_virttext(&wp->w_config.title_chunks);
|
||||
}
|
||||
int title_id = syn_check_group(S_LEN("FloatTitle"));
|
||||
wp->w_config.title = true;
|
||||
wp->w_config.title_pos = kAlignCenter;
|
||||
wp->w_config.title_width = (int)mb_string2cells(wp->w_buffer->b_fname);
|
||||
kv_push(*(&wp->w_config.title_chunks), ((VirtTextChunk){ .text = xstrdup(wp->w_buffer->b_fname),
|
||||
.hl_id = title_id }));
|
||||
if (redraw) {
|
||||
win_config_float(wp, wp->w_config);
|
||||
}
|
||||
}
|
||||
|
||||
/// adjust a preview floating window postion to fit screen and buffer in wp.
|
||||
///
|
||||
/// @param wp A pointer of win_T
|
||||
/// @return
|
||||
void win_float_adjust_position(win_T *wp)
|
||||
{
|
||||
if (!wp->w_floating) {
|
||||
return;
|
||||
}
|
||||
|
||||
int border_extra = wp->w_config.border ? 2 : 0;
|
||||
int right_extra = Columns - curwin->w_wincol - curwin->w_wcol - border_extra;
|
||||
int left_extra = curwin->w_wincol + curwin->w_wcol - border_extra;
|
||||
int below_height = Rows - curwin->w_winrow - curwin->w_wrow - border_extra;
|
||||
int above_height = curwin->w_winrow + curwin->w_wrow - border_extra;
|
||||
|
||||
// fit screen
|
||||
bool west = false;
|
||||
if (wp->w_config.width < right_extra) { // placed in right
|
||||
west = true;
|
||||
} else if (wp->w_config.width < left_extra) { // placed in left
|
||||
west = false;
|
||||
} else { // eighter width not enough to placed the preview window use the largest onw.
|
||||
if (right_extra > left_extra) {
|
||||
west = true;
|
||||
wp->w_config.width = right_extra;
|
||||
} else {
|
||||
wp->w_config.width = left_extra;
|
||||
}
|
||||
}
|
||||
|
||||
if (wp->w_config.height < below_height) { // below is enough to placed preview window
|
||||
wp->w_config.anchor = west ? 0 : kFloatAnchorEast; // NW or NE
|
||||
} else if (wp->w_config.height < above_height) {
|
||||
// SW or SE
|
||||
wp->w_config.anchor = west ? kFloatAnchorSouth : kFloatAnchorSouth | kFloatAnchorEast;
|
||||
} else { // either height value smaller than max height use the largest one
|
||||
if (below_height > above_height) {
|
||||
wp->w_config.height = below_height;
|
||||
wp->w_config.anchor = west ? 0 : kFloatAnchorEast; // NW or NE
|
||||
} else {
|
||||
wp->w_config.height = above_height;
|
||||
// SW or SE
|
||||
wp->w_config.anchor = west ? kFloatAnchorSouth : kFloatAnchorSouth | kFloatAnchorEast;
|
||||
}
|
||||
}
|
||||
|
||||
if (wp->w_topline < 1) {
|
||||
wp->w_topline = 1;
|
||||
} else if (wp->w_topline > wp->w_buffer->b_ml.ml_line_count) {
|
||||
wp->w_topline = wp->w_buffer->b_ml.ml_line_count;
|
||||
}
|
||||
|
||||
// fit buffer preview window it's wrap always
|
||||
if (wp->w_p_wrap) {
|
||||
// actually height of preview window
|
||||
int actual_height = 0;
|
||||
// max width of lines in preview window
|
||||
int max_width = 0;
|
||||
int lnum = wp->w_topline;
|
||||
int height = wp->w_config.height;
|
||||
while (height) {
|
||||
actual_height += plines_win(wp, lnum, false);
|
||||
int len = linetabsize(wp, lnum);
|
||||
if (len > max_width) {
|
||||
max_width = len;
|
||||
}
|
||||
lnum++;
|
||||
if (lnum > wp->w_buffer->b_ml.ml_line_count) {
|
||||
break;
|
||||
}
|
||||
height--;
|
||||
}
|
||||
|
||||
if (actual_height > 0) {
|
||||
wp->w_config.height = MIN(wp->w_config.height, actual_height);
|
||||
}
|
||||
|
||||
if (max_width > 0) {
|
||||
wp->w_config.width = MIN(wp->w_config.width, max_width);
|
||||
}
|
||||
}
|
||||
|
||||
if ((wp->w_config.anchor & kFloatAnchorSouth) == 0) {
|
||||
wp->w_config.row += 1;
|
||||
wp->w_config.col += 1;
|
||||
}
|
||||
wp->w_config.hide = false;
|
||||
win_config_float(wp, wp->w_config);
|
||||
}
|
||||
|
|
|
@ -9316,6 +9316,207 @@ describe('float window', function()
|
|||
]]
|
||||
})
|
||||
end
|
||||
end)
|
||||
it('#previewpopup option', function()
|
||||
command('call writefile(["bar"], "foo", "a")')
|
||||
finally(function()
|
||||
os.remove('foo')
|
||||
end)
|
||||
command('set previewpopup=height:2,width:5,border:single | pedit foo')
|
||||
|
||||
if multigrid then
|
||||
screen:expect({grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
^ |
|
||||
{0:~ }|*5
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{5:┌}{11:foo}{5:┐}|
|
||||
{5:│}{1:bar}{5:│}|
|
||||
{5:└───┘}|
|
||||
]], float_pos={
|
||||
[4] = {1001, "NW", 1, 1, 1, false, 50};
|
||||
}, win_viewport={
|
||||
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
[4] = {win = 1001, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
}, win_viewport_margins={
|
||||
[2] = {
|
||||
bottom = 0,
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
win = 1000
|
||||
},
|
||||
[4] = {
|
||||
bottom = 1,
|
||||
left = 1,
|
||||
right = 1,
|
||||
top = 1,
|
||||
win = 1001
|
||||
}
|
||||
}
|
||||
})
|
||||
else
|
||||
screen:expect({
|
||||
grid = [[
|
||||
^ |
|
||||
{0:~}{5:┌}{11:foo}{5:┐}{0: }|
|
||||
{0:~}{5:│}{1:bar}{5:│}{0: }|
|
||||
{0:~}{5:└───┘}{0: }|
|
||||
{0:~ }|*2
|
||||
|
|
||||
]]
|
||||
})
|
||||
end
|
||||
|
||||
--refconfig it by using set
|
||||
command('set previewpopup=height:2,width:5,border:double')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
^ |
|
||||
{0:~ }|*5
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{5:╔═}{11:foo}{5:═╗}|
|
||||
{5:║}{1:bar }{5:║}|
|
||||
{5:║}{1: }{5:║}|
|
||||
{5:╚═════╝}|
|
||||
]], float_pos={
|
||||
[4] = {1001, "NW", 1, 1, 1, false, 50};
|
||||
}, win_viewport={
|
||||
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
[4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
}, win_viewport_margins={
|
||||
[2] = {
|
||||
bottom = 0,
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
win = 1000
|
||||
},
|
||||
[4] = {
|
||||
bottom = 1,
|
||||
left = 1,
|
||||
right = 1,
|
||||
top = 1,
|
||||
win = 1001
|
||||
}
|
||||
}
|
||||
})
|
||||
else
|
||||
screen:expect({
|
||||
grid = [[
|
||||
^ |
|
||||
{0:~}{5:╔═}{11:foo}{5:═╗}{0: }|
|
||||
{0:~}{5:║}{1:bar }{5:║}{0: }|
|
||||
{0:~}{5:║}{1: }{5:║}{0: }|
|
||||
{0:~}{5:╚═════╝}{0: }|
|
||||
{0:~ }|
|
||||
|
|
||||
]]
|
||||
})
|
||||
end
|
||||
--can close by pclose command
|
||||
command('pclose')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
^ |
|
||||
{0:~ }|*5
|
||||
## grid 3
|
||||
|
|
||||
]], win_viewport={
|
||||
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
}, win_viewport_margins={
|
||||
[2] = {
|
||||
bottom = 0,
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
win = 1000
|
||||
}
|
||||
}
|
||||
})
|
||||
else
|
||||
screen:expect({
|
||||
grid = [[
|
||||
^ |
|
||||
{0:~ }|*5
|
||||
|
|
||||
]]
|
||||
})
|
||||
end
|
||||
|
||||
--when open an empty buffer/file will use max width and height
|
||||
command('set previewpopup=height:2,width:7,border:double | pedit unexist')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
^ |
|
||||
{0:~ }|*5
|
||||
## grid 3
|
||||
|
|
||||
## grid 5
|
||||
{5:╔}{11:unexist}{5:╗}|
|
||||
{5:║}{1: }{5:║}|
|
||||
{5:╚═══════╝}|
|
||||
]], float_pos={
|
||||
[5] = {1002, "NW", 1, 1, 1, false, 50};
|
||||
}, win_viewport={
|
||||
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
[5] = {win = 1002, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||
}, win_viewport_margins={
|
||||
[2] = {
|
||||
bottom = 0,
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
win = 1000
|
||||
},
|
||||
[5] = {
|
||||
bottom = 1,
|
||||
left = 1,
|
||||
right = 1,
|
||||
top = 1,
|
||||
win = 1002
|
||||
}
|
||||
}
|
||||
})
|
||||
else
|
||||
screen:expect({
|
||||
grid = [[
|
||||
^ |
|
||||
{0:~}{5:╔}{11:unexist}{5:╗}{0: }|
|
||||
{0:~}{5:║}{1: }{5:║}{0: }|
|
||||
{0:~}{5:╚═══════╝}{0: }|
|
||||
{0:~ }|*2
|
||||
|
|
||||
]]
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
it('invalid argument in previewpopup', function ()
|
||||
local err = pcall_err(n.exec_capture, 'set previewpopup=height:10,border:nonexist')
|
||||
eq('nvim_exec2(): Vim(set):E474: Invalid argument: previewpopup=height:10,border:nonexist', err)
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue