From 630ec6cfb8670607ddfc67dd4e56e98c17746ca6 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Mon, 24 Feb 2020 16:40:58 +0800 Subject: API/UI: Allow UI to set PUM position and size, and pass the position to CompleteChanged --- runtime/doc/api.txt | 16 +++++++++++++ src/nvim/api/ui.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nvim/popupmnu.c | 16 +++++++++---- src/nvim/ui.c | 26 +++++++++++++++++++++ src/nvim/ui.h | 5 ++++ 5 files changed, 126 insertions(+), 4 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 39b6c6417d..c5ccf35c8e 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -2341,6 +2341,22 @@ nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()* Parameters: ~ {height} Popupmenu height, must be greater than zero. + *nvim_ui_pum_set_bounds()* +nvim_ui_pum_set_bounds({width}, {height}, {row}, {col}) + + Tells Nvim the geometry of the popumenu, to align floating + windows with an external popup menu. Note that this method + is not to be confused with |nvim_ui_pum_set_height()|, which + sets the number of visible items in the popup menu, while + this function sets the bounding box of the popup menu, + including visual decorations such as boarders and sliders. + + Parameters: ~ + {width} Popupmenu width, must be greater than zero. + {height} Popupmenu height, must be greater than zero. + {row} Popupmenu row, must be greater or equal to zero. + {height} Popupmenu height, must be greater or equal to zero. + nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()* TODO: Documentation diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 75ee05761b..d2d1355207 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -109,7 +109,12 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)width; ui->height = (int)height; + ui->pum_nlines = 0; + ui->pum_pos = false; + ui->pum_width = 0; ui->pum_height = 0; + ui->pum_row = -1; + ui->pum_col = -1; ui->rgb = true; ui->override = false; ui->grid_resize = remote_ui_grid_resize; @@ -340,7 +345,69 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) "It must support the ext_popupmenu option"); return; } + + ui->pum_nlines = (int)height; +} + +/// Tells Nvim the geometry of the popumenu, to align floating +/// windows with an external popup menu. Note that this method +/// is not to be confused with |nvim_ui_pum_set_height()|, which +/// sets the number of visible items in the popup menu, while +/// this function sets the bounding box of the popup menu, +/// including visual decorations such as boarders and sliders. +/// +/// @param channel_id +/// @param width Popupmenu width, must be greater than zero. +/// @param height Popupmenu height, must be greater than zero. +/// @param row Popupmenu row, must be greater or equal to zero. +/// @param col Popupmenu height, must be greater or equal to zero. +/// @param[out] err Error details, if any. On error, suspend pum position reporting for the current UI. +void nvim_ui_pum_set_bounds(uint64_t channel_id, Integer width, Integer height, + Integer row, Integer col, Error *err) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY +{ + if (!pmap_has(uint64_t)(connected_uis, channel_id)) { + api_set_error(err, kErrorTypeException, + "UI not attached to channel: %" PRId64, channel_id); + return; + } + + UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); + if (!ui->ui_ext[kUIPopupmenu]) { + api_set_error(err, kErrorTypeValidation, + "It must support the ext_popupmenu option"); + return; + } + + if (row < 0) { + api_set_error(err, kErrorTypeValidation, "Expected pumpos row >= 0"); + ui->pum_pos = false; + return; + } + + if (col < 0) { + api_set_error(err, kErrorTypeValidation, "Expected pumpos col >= 0"); + ui->pum_pos = false; + return; + } + + if (width <= 0) { + api_set_error(err, kErrorTypeValidation, "Expected pumpos width > 0"); + ui->pum_pos = false; + return; + } + + if (height <= 0) { + api_set_error(err, kErrorTypeValidation, "Expected pumpos height > 0"); + ui->pum_pos = false; + return; + } + + ui->pum_row = (int)row; + ui->pum_col = (int)col; + ui->pum_width = (int)width; ui->pum_height = (int)height; + ui->pum_pos = true; } /// Pushes data into UI.UIData, to be consumed later by remote_ui_flush(). diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index da34d85c00..9568f319b4 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -908,10 +908,18 @@ void pum_set_event_info(dict_T *dict) if (!pum_visible()) { return; } - tv_dict_add_nr(dict, S_LEN("height"), pum_height); - tv_dict_add_nr(dict, S_LEN("width"), pum_width); - tv_dict_add_nr(dict, S_LEN("row"), pum_row); - tv_dict_add_nr(dict, S_LEN("col"), pum_col); + int w,h,r,c; + if (!ui_pum_get_pos(&w, &h, &r, &c)){ + tv_dict_add_nr(dict, S_LEN("height"), pum_height); + tv_dict_add_nr(dict, S_LEN("width"), pum_width); + tv_dict_add_nr(dict, S_LEN("row"), pum_row); + tv_dict_add_nr(dict, S_LEN("col"), pum_col); + } else { + tv_dict_add_nr(dict, S_LEN("height"), h); + tv_dict_add_nr(dict, S_LEN("width"), w); + tv_dict_add_nr(dict, S_LEN("row"), r); + tv_dict_add_nr(dict, S_LEN("col"), c); + } tv_dict_add_nr(dict, S_LEN("size"), pum_size); tv_dict_add_special(dict, S_LEN("scrollbar"), pum_scrollbar ? kSpecialVarTrue : kSpecialVarFalse); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 3a5aa95ad3..e7cc3b4e36 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -235,6 +235,32 @@ int ui_pum_get_height(void) return pum_height; } +bool ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol) +{ + int w=0,h=0,r=-1,c=-1; + bool found = false; + for (size_t i = 1; i < ui_count; i++) { + if (!uis[i]->pum_pos) continue; + if (!found) { + w = uis[i]->pum_width; + h = uis[i]->pum_height; + r = uis[i]->pum_row; + c = uis[i]->pum_col; + found = true; + } else { + w = MIN(uis[i]->pum_width, w); + h = MIN(uis[i]->pum_height, h); + r = MIN(uis[i]->pum_row, r); + c = MIN(uis[i]->pum_col, c); + } + } + *pwidth = w; + *pheight = h; + *prow = r; + *pcol = c; + return found; +} + static void ui_refresh_event(void **argv) { ui_refresh(); diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 8867b5ee24..b3a569b0df 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -53,7 +53,12 @@ struct ui_t { bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities. int width; int height; + int pum_nlines; /// actual nr. lines shown in PUM + bool pum_pos; /// UI reports back pum position? + int pum_row; + int pum_col; int pum_height; + int pum_width; void *data; #ifdef INCLUDE_GENERATED_DECLARATIONS -- cgit From 9c85caa390ccf6295233c4201a60ccfa66417816 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 3 Mar 2020 17:43:02 +0800 Subject: ui_pum_get_pos: return internal pum position if external pum pos not found --- runtime/doc/api.txt | 8 ++++---- src/nvim/api/ui.c | 28 +++++++++------------------- src/nvim/popupmnu.c | 28 +++++++++++++++++----------- src/nvim/ui.c | 17 ++++++++++------- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index c5ccf35c8e..a2e0c56f85 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -2352,10 +2352,10 @@ nvim_ui_pum_set_bounds({width}, {height}, {row}, {col}) including visual decorations such as boarders and sliders. Parameters: ~ - {width} Popupmenu width, must be greater than zero. - {height} Popupmenu height, must be greater than zero. - {row} Popupmenu row, must be greater or equal to zero. - {height} Popupmenu height, must be greater or equal to zero. + {width} Popupmenu width. + {height} Popupmenu height. + {row} Popupmenu row. + {height} Popupmenu height. nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()* TODO: Documentation diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index d2d1355207..430be920e2 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -357,11 +357,11 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) /// including visual decorations such as boarders and sliders. /// /// @param channel_id -/// @param width Popupmenu width, must be greater than zero. -/// @param height Popupmenu height, must be greater than zero. -/// @param row Popupmenu row, must be greater or equal to zero. -/// @param col Popupmenu height, must be greater or equal to zero. -/// @param[out] err Error details, if any. On error, suspend pum position reporting for the current UI. +/// @param width Popupmenu width. +/// @param height Popupmenu height. +/// @param row Popupmenu row. +/// @param col Popupmenu height. +/// @param[out] err Error details, if any. void nvim_ui_pum_set_bounds(uint64_t channel_id, Integer width, Integer height, Integer row, Integer col, Error *err) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY @@ -375,31 +375,21 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Integer width, Integer height, UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); if (!ui->ui_ext[kUIPopupmenu]) { api_set_error(err, kErrorTypeValidation, - "It must support the ext_popupmenu option"); + "UI must support the ext_popupmenu option"); return; } if (row < 0) { api_set_error(err, kErrorTypeValidation, "Expected pumpos row >= 0"); - ui->pum_pos = false; return; - } - - if (col < 0) { + } else if (col < 0) { api_set_error(err, kErrorTypeValidation, "Expected pumpos col >= 0"); - ui->pum_pos = false; return; - } - - if (width <= 0) { + } else if (width <= 0) { api_set_error(err, kErrorTypeValidation, "Expected pumpos width > 0"); - ui->pum_pos = false; return; - } - - if (height <= 0) { + } else if (height <= 0) { api_set_error(err, kErrorTypeValidation, "Expected pumpos height > 0"); - ui->pum_pos = false; return; } diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index 9568f319b4..5f636ba847 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -902,6 +902,18 @@ int pum_get_height(void) return pum_height; } +/// Gets the internal pum geometry. +/// +/// @return the internal pum geometry. Ignores UI external pum geometry. +/// Only valid when pum_visible() returns TRUE! +void pum_get_internal_pos(int* pwidth, int* pheight, int* prow, int* pcol) +{ + *pwidth = pum_width; + *pheight = pum_height; + *prow = pum_row; + *pcol = pum_col; +} + /// Add size information about the pum to "dict". void pum_set_event_info(dict_T *dict) { @@ -909,17 +921,11 @@ void pum_set_event_info(dict_T *dict) return; } int w,h,r,c; - if (!ui_pum_get_pos(&w, &h, &r, &c)){ - tv_dict_add_nr(dict, S_LEN("height"), pum_height); - tv_dict_add_nr(dict, S_LEN("width"), pum_width); - tv_dict_add_nr(dict, S_LEN("row"), pum_row); - tv_dict_add_nr(dict, S_LEN("col"), pum_col); - } else { - tv_dict_add_nr(dict, S_LEN("height"), h); - tv_dict_add_nr(dict, S_LEN("width"), w); - tv_dict_add_nr(dict, S_LEN("row"), r); - tv_dict_add_nr(dict, S_LEN("col"), c); - } + ui_pum_get_pos(&w, &h, &r, &c); + tv_dict_add_nr(dict, S_LEN("height"), h); + tv_dict_add_nr(dict, S_LEN("width"), w); + tv_dict_add_nr(dict, S_LEN("row"), r); + tv_dict_add_nr(dict, S_LEN("col"), c); tv_dict_add_nr(dict, S_LEN("size"), pum_size); tv_dict_add_special(dict, S_LEN("scrollbar"), pum_scrollbar ? kSpecialVarTrue : kSpecialVarFalse); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index e7cc3b4e36..9ab868c78e 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -226,7 +226,7 @@ int ui_pum_get_height(void) { int pum_height = 0; for (size_t i = 1; i < ui_count; i++) { - int ui_pum_height = uis[i]->pum_height; + int ui_pum_height = uis[i]->pum_nlines; if (ui_pum_height) { pum_height = pum_height != 0 ? MIN(pum_height, ui_pum_height) : ui_pum_height; @@ -235,7 +235,7 @@ int ui_pum_get_height(void) return pum_height; } -bool ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol) +void ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol) { int w=0,h=0,r=-1,c=-1; bool found = false; @@ -254,11 +254,14 @@ bool ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol) c = MIN(uis[i]->pum_col, c); } } - *pwidth = w; - *pheight = h; - *prow = r; - *pcol = c; - return found; + if (found) { + *pwidth = w; + *pheight = h; + *prow = r; + *pcol = c; + } else { + pum_get_internal_pos(pwidth, pheight, prow, pcol); + } } static void ui_refresh_event(void **argv) -- cgit From 6da16ac931eec7be2487ee98e7f605fa12b0171d Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 3 Mar 2020 18:17:37 +0800 Subject: external pum: use floating point geometry; typval: add tv_dict_add_float --- src/nvim/api/ui.c | 29 ++++++++++++++++------------- src/nvim/eval/typval.c | 22 ++++++++++++++++++++++ src/nvim/popupmnu.c | 12 ++++++------ src/nvim/testdir/test_popup.vim | 14 +++++++------- src/nvim/ui.c | 15 +++++++++++---- src/nvim/ui.h | 12 ++++++------ 6 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 430be920e2..b10434428c 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -111,10 +111,10 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, ui->height = (int)height; ui->pum_nlines = 0; ui->pum_pos = false; - ui->pum_width = 0; - ui->pum_height = 0; - ui->pum_row = -1; - ui->pum_col = -1; + ui->pum_width = 0.0; + ui->pum_height = 0.0; + ui->pum_row = -1.0; + ui->pum_col = -1.0; ui->rgb = true; ui->override = false; ui->grid_resize = remote_ui_grid_resize; @@ -349,12 +349,15 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) ui->pum_nlines = (int)height; } -/// Tells Nvim the geometry of the popumenu, to align floating +/// Tells Nvim the geometry of the popumenu, to align floating /// windows with an external popup menu. Note that this method /// is not to be confused with |nvim_ui_pum_set_height()|, which /// sets the number of visible items in the popup menu, while -/// this function sets the bounding box of the popup menu, +/// this function sets the bounding box of the popup menu, /// including visual decorations such as boarders and sliders. +/// Floats need not use the same font size, nor be anchored to +/// exact grid corners, so one can set floating-point numbers +/// to the popup menu geometry. /// /// @param channel_id /// @param width Popupmenu width. @@ -362,9 +365,9 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) /// @param row Popupmenu row. /// @param col Popupmenu height. /// @param[out] err Error details, if any. -void nvim_ui_pum_set_bounds(uint64_t channel_id, Integer width, Integer height, - Integer row, Integer col, Error *err) - FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY +void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, + Float row, Float col, Error *err) + FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(err, kErrorTypeException, @@ -393,10 +396,10 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Integer width, Integer height, return; } - ui->pum_row = (int)row; - ui->pum_col = (int)col; - ui->pum_width = (int)width; - ui->pum_height = (int)height; + ui->pum_row = (double)row; + ui->pum_col = (double)col; + ui->pum_width = (double)width; + ui->pum_height = (double)height; ui->pum_pos = true; } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c8b5fc294c..773e493d0b 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1634,6 +1634,28 @@ int tv_dict_add_nr(dict_T *const d, const char *const key, return OK; } +/// Add a floating point number entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] nr Floating point number to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_float(dict_T *const d, const char *const key, + const size_t key_len, const float_T nr) +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_type = VAR_FLOAT; + item->di_tv.vval.v_float = nr; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + /// Add a special entry to dictionary /// /// @param[out] d Dictionary to add entry to. diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index 5f636ba847..051cd660db 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -906,7 +906,7 @@ int pum_get_height(void) /// /// @return the internal pum geometry. Ignores UI external pum geometry. /// Only valid when pum_visible() returns TRUE! -void pum_get_internal_pos(int* pwidth, int* pheight, int* prow, int* pcol) +void pum_get_internal_pos(int *pwidth, int *pheight, int *prow, int *pcol) { *pwidth = pum_width; *pheight = pum_height; @@ -920,12 +920,12 @@ void pum_set_event_info(dict_T *dict) if (!pum_visible()) { return; } - int w,h,r,c; + double w, h, r, c; ui_pum_get_pos(&w, &h, &r, &c); - tv_dict_add_nr(dict, S_LEN("height"), h); - tv_dict_add_nr(dict, S_LEN("width"), w); - tv_dict_add_nr(dict, S_LEN("row"), r); - tv_dict_add_nr(dict, S_LEN("col"), c); + tv_dict_add_float(dict, S_LEN("height"), h); + tv_dict_add_float(dict, S_LEN("width"), w); + tv_dict_add_float(dict, S_LEN("row"), r); + tv_dict_add_float(dict, S_LEN("col"), c); tv_dict_add_nr(dict, S_LEN("size"), pum_size); tv_dict_add_special(dict, S_LEN("scrollbar"), pum_scrollbar ? kSpecialVarTrue : kSpecialVarFalse); diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index e5696f4cbb..bb0ed6e00c 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -979,9 +979,9 @@ func Test_CompleteChanged() call cursor(4, 1) call feedkeys("Sf\", 'tx') - call assert_equal({'completed_item': {}, 'width': 15, - \ 'height': 2, 'size': 2, - \ 'col': 0, 'row': 4, 'scrollbar': v:false}, g:event) + call assert_equal({'completed_item': {}, 'width': 15.0, + \ 'height': 2.0, 'size': 2, + \ 'col': 0.0, 'row': 4.0, 'scrollbar': v:false}, g:event) call feedkeys("a\\\", 'tx') call assert_equal('foo', g:word) call feedkeys("a\\\\", 'tx') @@ -1009,10 +1009,10 @@ func Test_pum_getpos() setlocal completefunc=UserDefinedComplete let d = { - \ 'height': 5, - \ 'width': 15, - \ 'row': 1, - \ 'col': 0, + \ 'height': 5.0, + \ 'width': 15.0, + \ 'row': 1.0, + \ 'col': 0.0, \ 'size': 5, \ 'scrollbar': v:false, \ } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 9ab868c78e..cc9bf42bc8 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -235,12 +235,14 @@ int ui_pum_get_height(void) return pum_height; } -void ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol) +void ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol) { - int w=0,h=0,r=-1,c=-1; + double w = 0.0, h = 0.0, r = -1.0, c = -1.0; bool found = false; for (size_t i = 1; i < ui_count; i++) { - if (!uis[i]->pum_pos) continue; + if (!uis[i]->pum_pos) { + continue; + } if (!found) { w = uis[i]->pum_width; h = uis[i]->pum_height; @@ -260,7 +262,12 @@ void ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol) *prow = r; *pcol = c; } else { - pum_get_internal_pos(pwidth, pheight, prow, pcol); + int iw, ih, ir, ic; + pum_get_internal_pos(&iw, &ih, &ir, &ic); + *pwidth = (double)iw; + *pheight = (double)ih; + *prow = (double)ir; + *pcol = (double)ic; } } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index b3a569b0df..d00243d35f 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -53,12 +53,12 @@ struct ui_t { bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities. int width; int height; - int pum_nlines; /// actual nr. lines shown in PUM - bool pum_pos; /// UI reports back pum position? - int pum_row; - int pum_col; - int pum_height; - int pum_width; + int pum_nlines; /// actual nr. lines shown in PUM + bool pum_pos; /// UI reports back pum position? + double pum_row; + double pum_col; + double pum_height; + double pum_width; void *data; #ifdef INCLUDE_GENERATED_DECLARATIONS -- cgit From ed6230434b2b0a07ece03272b871412929bfcb53 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Thu, 5 Mar 2020 15:51:02 +0800 Subject: gen_api_dispatch.lua: allow msgpack int for Float args; test: add ui_pum_set_bounds and tv_dict_add_float tests --- src/nvim/generators/gen_api_dispatch.lua | 6 +++ test/functional/ui/popupmenu_spec.lua | 86 ++++++++++++++++++++++++++++++-- test/unit/eval/typval_spec.lua | 20 ++++++++ 3 files changed, 107 insertions(+), 5 deletions(-) diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index e861cfda35..6e80ad0e5c 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -237,6 +237,12 @@ for i = 1, #functions do (j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') end + if rt:match('^Float$') then + -- accept integers for Floats + output:write('\n } else if (args.items['.. + (j - 1)..'].type == kObjectTypeInteger) {') + output:write('\n '..converted..' = (Float)args.items['..(j - 1)..'].data.integer;') + end -- accept empty lua tables as empty dictionarys if rt:match('^Dictionary') then output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631 diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 11c3f4123e..9b6ca8032a 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -382,7 +382,7 @@ describe('ui/ext_popupmenu', function() end describe('pum_set_height', function() - it('can be set pum height', function() + it('can set pum height', function() source_complete_month() local month_expected = { {'January', '', '', ''}, @@ -423,23 +423,99 @@ describe('ui/ext_popupmenu', function() it('an error occurs if set 0 or less', function() local ok, err, _ ok, _ = pcall(meths.ui_pum_set_height, 1) - eq(ok, true) + eq(true, ok) ok, err = pcall(meths.ui_pum_set_height, 0) - eq(ok, false) + eq(false, ok) matches('.*: Expected pum height > 0', err) end) it('an error occurs when ext_popupmenu is false', function() local ok, err, _ ok, _ = pcall(meths.ui_pum_set_height, 1) - eq(ok, true) + eq(true, ok) screen:set_option('ext_popupmenu', false) ok, err = pcall(meths.ui_pum_set_height, 1) - eq(ok, false) + eq(false, ok) matches('.*: It must support the ext_popupmenu option', err) end) end) + describe('pum_set_bounds', function() + it('can set pum bounds', function() + source_complete_month() + local month_expected = { + {'January', '', '', ''}, + {'February', '', '', ''}, + {'March', '', '', ''}, + {'April', '', '', ''}, + {'May', '', '', ''}, + {'June', '', '', ''}, + {'July', '', '', ''}, + {'August', '', '', ''}, + {'September', '', '', ''}, + {'October', '', '', ''}, + {'November', '', '', ''}, + {'December', '', '', ''}, + } + local pum_height = 6 + feed('o=TestCompleteMonth()') + meths.ui_pum_set_height(pum_height) + -- set bounds w h r c + meths.ui_pum_set_bounds(10.5, 5.2, 6.3, 7.4) + feed('') + -- pos becomes pum_height-2 because it is subtracting 2 to keep some + -- context in ins_compl_key2count() + screen:expect{grid=[[ + | + January^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]], popupmenu={ + items=month_expected, + pos=pum_height-2, + anchor={1,1,0}, + }} + end) + + it('an error occurs if row or col set less than 0', function() + local ok, err, _ + ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) + eq(true, ok) + ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, -1.0, 0.0) + eq(false, ok) + matches('.*: Expected pumpos row >= 0', err) + ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, -1.0) + eq(false, ok) + matches('.*: Expected pumpos col >= 0', err) + end) + + it('an error occurs if width or height set 0 or less', function() + local ok, err, _ + ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) + eq(true, ok) + ok, err = pcall(meths.ui_pum_set_bounds, 0.0, 1.0, 1.0, 0.0) + eq(false, ok) + matches('.*: Expected pumpos width > 0', err) + ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 0.0, 1.0, 0.0) + eq(false, ok) + matches('.*: Expected pumpos height > 0', err) + end) + + it('an error occurs when ext_popupmenu is false', function() + local ok, err, _ + ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) + eq(true, ok) + screen:set_option('ext_popupmenu', false) + ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) + eq(false, ok) + matches('.*: UI must support the ext_popupmenu option', err) + end) + end) + it(', works without ui_pum_set_height', function() source_complete_month() local month_expected = { diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index 1651eb9bcc..ea86ccbf1c 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -2026,6 +2026,26 @@ describe('typval.c', function() alloc_log:check({}) end) end) + describe('float()', function() + itp('works', function() + local d = dict({test=10}) + alloc_log:clear() + eq({test=10}, dct2tbl(d)) + eq(OK, lib.tv_dict_add_float(d, 'testt', 3, 1.5)) + local dis = dict_items(d) + alloc_log:check({a.di(dis.tes, 'tes')}) + eq({test=10, tes=1.5}, dct2tbl(d)) + eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end, + 'E685: Internal error: hash_add()')) + alloc_log:clear() + lib.emsg_skip = lib.emsg_skip + 1 + eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end, + nil)) + lib.emsg_skip = lib.emsg_skip - 1 + alloc_log:clear_tmp_allocs() + alloc_log:check({}) + end) + end) describe('str()', function() itp('works', function() local d = dict({test=10}) -- cgit From d372c804aa33a272f6659f6d08d5dfee704d30d9 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Sun, 22 Mar 2020 17:27:49 +0800 Subject: api/ui: allow set bounds row and col to be less than 0; ui_pum_get_pos: return first extui bounds information instead of reducing --- src/nvim/api/ui.c | 12 +++--------- src/nvim/ui.c | 20 +++++++------------- test/functional/ui/popupmenu_spec.lua | 12 +++++------- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index b10434428c..300f409a0f 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -382,17 +382,11 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, return; } - if (row < 0) { - api_set_error(err, kErrorTypeValidation, "Expected pumpos row >= 0"); - return; - } else if (col < 0) { - api_set_error(err, kErrorTypeValidation, "Expected pumpos col >= 0"); - return; - } else if (width <= 0) { - api_set_error(err, kErrorTypeValidation, "Expected pumpos width > 0"); + if (width <= 0) { + api_set_error(err, kErrorTypeValidation, "Expected width > 0"); return; } else if (height <= 0) { - api_set_error(err, kErrorTypeValidation, "Expected pumpos height > 0"); + api_set_error(err, kErrorTypeValidation, "Expected height > 0"); return; } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index cc9bf42bc8..0a8474ff82 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -237,24 +237,18 @@ int ui_pum_get_height(void) void ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol) { - double w = 0.0, h = 0.0, r = -1.0, c = -1.0; + double w = 0.0, h = 0.0, r = 0.0, c = 0.0; bool found = false; for (size_t i = 1; i < ui_count; i++) { if (!uis[i]->pum_pos) { continue; } - if (!found) { - w = uis[i]->pum_width; - h = uis[i]->pum_height; - r = uis[i]->pum_row; - c = uis[i]->pum_col; - found = true; - } else { - w = MIN(uis[i]->pum_width, w); - h = MIN(uis[i]->pum_height, h); - r = MIN(uis[i]->pum_row, r); - c = MIN(uis[i]->pum_col, c); - } + w = uis[i]->pum_width; + h = uis[i]->pum_height; + r = uis[i]->pum_row; + c = uis[i]->pum_col; + found = true; + break; } if (found) { *pwidth = w; diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 9b6ca8032a..3108d21508 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -481,16 +481,14 @@ describe('ui/ext_popupmenu', function() }} end) - it('an error occurs if row or col set less than 0', function() + it('no error occurs if row or col set less than 0', function() local ok, err, _ ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) eq(true, ok) - ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, -1.0, 0.0) - eq(false, ok) - matches('.*: Expected pumpos row >= 0', err) - ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, -1.0) - eq(false, ok) - matches('.*: Expected pumpos col >= 0', err) + ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, -1.0, 0.0) + eq(true, ok) + ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, -1.0) + eq(true, ok) end) it('an error occurs if width or height set 0 or less', function() -- cgit From e34684b2ad02e759dec39c0f0958c7882120ecdc Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Sun, 22 Mar 2020 17:53:45 +0800 Subject: api/ui: simplify popup menu position get/set logic; fix test --- src/nvim/api/ui.c | 18 ++++++------ src/nvim/popupmnu.c | 19 ++++--------- src/nvim/ui.c | 29 +++++-------------- test/functional/ui/popupmenu_spec.lua | 53 ++++++++++++----------------------- 4 files changed, 40 insertions(+), 79 deletions(-) diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 300f409a0f..717713b948 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -349,15 +349,15 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) ui->pum_nlines = (int)height; } -/// Tells Nvim the geometry of the popumenu, to align floating -/// windows with an external popup menu. Note that this method -/// is not to be confused with |nvim_ui_pum_set_height()|, which -/// sets the number of visible items in the popup menu, while -/// this function sets the bounding box of the popup menu, -/// including visual decorations such as boarders and sliders. -/// Floats need not use the same font size, nor be anchored to -/// exact grid corners, so one can set floating-point numbers -/// to the popup menu geometry. +/// Tells Nvim the geometry of the popumenu, to align floating windows with an +/// external popup menu. +/// +/// Note that this method is not to be confused with |nvim_ui_pum_set_height()|, +/// which sets the number of visible items in the popup menu, while this +/// function sets the bounding box of the popup menu, including visual +/// decorations such as boarders and sliders. Floats need not use the same font +/// size, nor be anchored to exact grid corners, so one can set floating-point +/// numbers to the popup menu geometry. /// /// @param channel_id /// @param width Popupmenu width. diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index 051cd660db..532bf68190 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -902,18 +902,6 @@ int pum_get_height(void) return pum_height; } -/// Gets the internal pum geometry. -/// -/// @return the internal pum geometry. Ignores UI external pum geometry. -/// Only valid when pum_visible() returns TRUE! -void pum_get_internal_pos(int *pwidth, int *pheight, int *prow, int *pcol) -{ - *pwidth = pum_width; - *pheight = pum_height; - *prow = pum_row; - *pcol = pum_col; -} - /// Add size information about the pum to "dict". void pum_set_event_info(dict_T *dict) { @@ -921,7 +909,12 @@ void pum_set_event_info(dict_T *dict) return; } double w, h, r, c; - ui_pum_get_pos(&w, &h, &r, &c); + if (!ui_pum_get_pos(&w, &h, &r, &c)) { + w = (double)pum_width; + h = (double)pum_height; + r = (double)pum_row; + c = (double)pum_col; + } tv_dict_add_float(dict, S_LEN("height"), h); tv_dict_add_float(dict, S_LEN("width"), w); tv_dict_add_float(dict, S_LEN("row"), r); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 0a8474ff82..685da77b39 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -235,34 +235,19 @@ int ui_pum_get_height(void) return pum_height; } -void ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol) +bool ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol) { - double w = 0.0, h = 0.0, r = 0.0, c = 0.0; - bool found = false; for (size_t i = 1; i < ui_count; i++) { if (!uis[i]->pum_pos) { continue; } - w = uis[i]->pum_width; - h = uis[i]->pum_height; - r = uis[i]->pum_row; - c = uis[i]->pum_col; - found = true; - break; - } - if (found) { - *pwidth = w; - *pheight = h; - *prow = r; - *pcol = c; - } else { - int iw, ih, ir, ic; - pum_get_internal_pos(&iw, &ih, &ir, &ic); - *pwidth = (double)iw; - *pheight = (double)ih; - *prow = (double)ir; - *pcol = (double)ic; + *pwidth = uis[i]->pum_width; + *pheight = uis[i]->pum_height; + *prow = uis[i]->pum_row; + *pcol = uis[i]->pum_col; + return true; } + return false; } static void ui_refresh_event(void **argv) diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 3108d21508..c1c5d1ce2e 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -8,7 +8,7 @@ local command = helpers.command local funcs = helpers.funcs local get_pathsep = helpers.get_pathsep local eq = helpers.eq -local matches = helpers.matches +local pcall_err = helpers.pcall_err describe('ui/ext_popupmenu', function() local screen @@ -421,22 +421,16 @@ describe('ui/ext_popupmenu', function() end) it('an error occurs if set 0 or less', function() - local ok, err, _ - ok, _ = pcall(meths.ui_pum_set_height, 1) - eq(true, ok) - ok, err = pcall(meths.ui_pum_set_height, 0) - eq(false, ok) - matches('.*: Expected pum height > 0', err) + meths.ui_pum_set_height(1) + eq('Expected pum height > 0', + pcall_err(meths.ui_pum_set_height, 0)) end) it('an error occurs when ext_popupmenu is false', function() - local ok, err, _ - ok, _ = pcall(meths.ui_pum_set_height, 1) - eq(true, ok) + meths.ui_pum_set_height(1) screen:set_option('ext_popupmenu', false) - ok, err = pcall(meths.ui_pum_set_height, 1) - eq(false, ok) - matches('.*: It must support the ext_popupmenu option', err) + eq('It must support the ext_popupmenu option', + pcall_err(meths.ui_pum_set_height, 1)) end) end) @@ -482,35 +476,24 @@ describe('ui/ext_popupmenu', function() end) it('no error occurs if row or col set less than 0', function() - local ok, err, _ - ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) - eq(true, ok) - ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, -1.0, 0.0) - eq(true, ok) - ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, -1.0) - eq(true, ok) + meths.ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5) + meths.ui_pum_set_bounds(1.0, 1.0, -1.0, 0.0) + meths.ui_pum_set_bounds(1.0, 1.0, 0.0, -1.0) end) it('an error occurs if width or height set 0 or less', function() - local ok, err, _ - ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) - eq(true, ok) - ok, err = pcall(meths.ui_pum_set_bounds, 0.0, 1.0, 1.0, 0.0) - eq(false, ok) - matches('.*: Expected pumpos width > 0', err) - ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 0.0, 1.0, 0.0) - eq(false, ok) - matches('.*: Expected pumpos height > 0', err) + meths.ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5) + eq('Expected width > 0', + pcall_err(meths.ui_pum_set_bounds, 0.0, 1.0, 1.0, 0.0)) + eq('Expected height > 0', + pcall_err(meths.ui_pum_set_bounds, 1.0, -1.0, 1.0, 0.0)) end) it('an error occurs when ext_popupmenu is false', function() - local ok, err, _ - ok, _ = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) - eq(true, ok) + meths.ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5) screen:set_option('ext_popupmenu', false) - ok, err = pcall(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5) - eq(false, ok) - matches('.*: UI must support the ext_popupmenu option', err) + eq('UI must support the ext_popupmenu option', + pcall_err(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5)) end) end) -- cgit