diff options
| -rw-r--r-- | src/nvim/api/ui.c | 33 | ||||
| -rw-r--r-- | src/nvim/popupmnu.c | 11 | ||||
| -rw-r--r-- | src/nvim/ui.c | 13 | ||||
| -rw-r--r-- | src/nvim/ui.h | 1 | ||||
| -rw-r--r-- | test/functional/ui/popupmenu_spec.lua | 121 | 
5 files changed, 178 insertions, 1 deletions
| diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 7e45abb897..9ff2a529ae 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -109,6 +109,7 @@ 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_height = 0;    ui->rgb = true;    ui->override = false;    ui->grid_resize = remote_ui_grid_resize; @@ -313,6 +314,38 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width,    ui_grid_resize((handle_T)grid, (int)width, (int)height, err);  } +/// Tell Nvim the number of element displayed in popumenu. The amount of +/// movement by <PageUp> or <PageDown> is determined by the value set by this. +/// +/// If the ext_popupmenu option is false or the height is 0 or less, fails +/// with error. +/// +/// @param channel_id +/// @param height  The popupmenu height. +/// @param[out] err Error details, if any +void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, 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; +  } + +  if (height <= 0) { +    api_set_error(err, kErrorTypeValidation, "Expected pum height > 0"); +    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; +  } +  ui->pum_height = (int)height; +} +  /// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().  static void push_call(UI *ui, const char *name, Array args)  { diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index ce40bc15e0..8e554cbc1d 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -135,8 +135,8 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed,          ui_call_popupmenu_show(arr, selected, row, col, pum_anchor_grid);        } else {          ui_call_popupmenu_select(selected); +        return;        } -      return;      }      def_width = PUM_DEF_WIDTH; @@ -237,6 +237,9 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed,          pum_height = row - above_row;        }      } +    if (pum_external) { +      return; +    }      // Compute the width of the widest match and the widest extra.      for (i = 0; i < size; i++) { @@ -852,6 +855,12 @@ void pum_recompose(void)  /// Only valid when pum_visible() returns TRUE!  int pum_get_height(void)  { +  if (pum_external) { +    int ui_pum_height = ui_pum_get_height(); +    if (ui_pum_height) { +      return ui_pum_height; +    } +  }    return pum_height;  } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 94fae0a774..265b343f0d 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -221,6 +221,19 @@ void ui_refresh(void)    ui_cursor_shape();  } +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; +    if (ui_pum_height) { +      pum_height = +        pum_height != 0 ? MIN(pum_height, ui_pum_height) : ui_pum_height; +    } +  } +  return pum_height; +} +  static void ui_refresh_event(void **argv)  {    ui_refresh(); diff --git a/src/nvim/ui.h b/src/nvim/ui.h index e1dd18a289..2e2cdf9ad1 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -53,6 +53,7 @@ struct ui_t {    bool ui_ext[kUIExtCount];  ///< Externalized UI capabilities.    int width;    int height; +  int pum_height;    void *data;  #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 1db6a5150e..3b4b281c81 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -7,6 +7,8 @@ local meths = helpers.meths  local command = helpers.command  local funcs = helpers.funcs  local get_pathsep = helpers.get_pathsep +local eq = helpers.eq +local matches = helpers.matches  describe('ui/ext_popupmenu', function()    local screen @@ -368,6 +370,125 @@ describe('ui/ext_popupmenu', function()      ]])    end) +  local function source_complete_month() +    source([[ +    function! TestCompleteMonth() abort +    call complete(1, ['January', 'February', 'March', 'April', +    \ 'May', 'June', 'July', 'August', +    \ 'September', 'October', 'November', 'December']) +    return '' +    endfunction +    ]]) +  end + +  describe('pum_set_height', function() +    it('can be set pum height', 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<C-r>=TestCompleteMonth()<CR>') +      meths.ui_pum_set_height(pum_height) +      feed('<PageDown>') +      -- 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 set 0 or less', function() +      local ok, err, _ +      ok, _ = pcall(meths.ui_pum_set_height, 1) +      eq(ok, true) +      ok, err = pcall(meths.ui_pum_set_height, 0) +      eq(ok, false) +      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) +      screen:set_option('ext_popupmenu', false) +      ok, err = pcall(meths.ui_pum_set_height, 1) +      eq(ok, false) +      matches('.*: It must support the ext_popupmenu option', err) +    end) +  end) + +  it('<PageUP>, <PageDown> works without ui_pum_set_height', function() +    source_complete_month() +    local month_expected = { +      {'January', '', '', ''}, +      {'February', '', '', ''}, +      {'March', '', '', ''}, +      {'April', '', '', ''}, +      {'May', '', '', ''}, +      {'June', '', '', ''}, +      {'July', '', '', ''}, +      {'August', '', '', ''}, +      {'September', '', '', ''}, +      {'October', '', '', ''}, +      {'November', '', '', ''}, +      {'December', '', '', ''}, +    } +    feed('o<C-r>=TestCompleteMonth()<CR>') +    feed('<PageDown>') +    screen:expect{grid=[[ +                                                                | +    January^                                                     | +    {1:~                                                           }| +    {1:~                                                           }| +    {1:~                                                           }| +    {1:~                                                           }| +    {1:~                                                           }| +    {2:-- INSERT --}                                                | +    ]], popupmenu={ +      items=month_expected, +      pos=3, +      anchor={1,1,0}, +    }} +    feed('<PageUp>') +    screen:expect{grid=[[ +                                                                | +    January^                                                     | +    {1:~                                                           }| +    {1:~                                                           }| +    {1:~                                                           }| +    {1:~                                                           }| +    {1:~                                                           }| +    {2:-- INSERT --}                                                | +    ]], popupmenu={ +      items=month_expected, +      pos=0, +      anchor={1,1,0}, +    }} +  end) +    it('works with wildoptions=pum', function()      screen:try_resize(32,10)      command('set wildmenu') | 
