vim-patch:9.1.1341: cannot define completion triggers

Problem:  Cannot define completion triggers and act upon it
Solution: add the new option 'isexpand' and add the complete_match()
          function to return the completion matches according to the
          'isexpand' setting (glepnir)

Currently, completion trigger position is determined solely by the
'iskeyword' pattern (\k\+$), which causes issues when users need
different completion behaviors - such as triggering after '/' for
comments or '.' for methods. Modifying 'iskeyword' to include these
characters has undesirable side effects on other Vim functionality that
relies on keyword definitions.

Introduce a new buffer-local option 'isexpand' that allows specifying
different completion triggers and add the complete_match() function that
finds the appropriate start column for completion based on these
triggers, scanning backwards from cursor position.

This separation of concerns allows customized completion behavior
without affecting iskeyword-dependent features. The option's
buffer-local nature enables per-filetype completion triggers.

closes: vim/vim#16716

bcd5995b40

Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
glepnir
2025-04-26 13:06:43 +08:00
parent ac8ae1596c
commit fcabbc2283
13 changed files with 434 additions and 0 deletions

View File

@@ -1109,6 +1109,55 @@ function vim.fn.complete_check() end
--- @return table
function vim.fn.complete_info(what) end
--- Returns a List of matches found according to the 'isexpand'
--- option. Each match is represented as a List containing
--- [startcol, trigger_text] where:
--- - startcol: column position where completion should start,
--- or -1 if no trigger position is found. For multi-character
--- triggers, returns the column of the first character.
--- - trigger_text: the matching trigger string from 'isexpand',
--- or empty string if no match was found or when using the
--- default 'iskeyword' pattern.
---
--- When 'isexpand' is empty, uses the 'iskeyword' pattern
--- "\k\+$" to find the start of the current keyword.
---
--- When no arguments are provided, uses the current cursor
--- position.
---
--- Examples: >
--- set isexpand=.,->,/,/*,abc
--- func CustomComplete()
--- let res = complete_match()
--- if res->len() == 0 | return | endif
--- let [col, trigger] = res[0]
--- let items = []
--- if trigger == '/*'
--- let items = ['/** */']
--- elseif trigger == '/'
--- let items = ['/*! */', '// TODO:', '// fixme:']
--- elseif trigger == '.'
--- let items = ['length()']
--- elseif trigger =~ '^\->'
--- let items = ['map()', 'reduce()']
--- elseif trigger =~ '^\abc'
--- let items = ['def', 'ghk']
--- endif
--- if items->len() > 0
--- let startcol = trigger =~ '^/' ? col : col + len(trigger)
--- call complete(startcol, items)
--- endif
--- endfunc
--- inoremap <Tab> <Cmd>call CustomComplete()<CR>
--- <
---
--- Return type: list<list<any>>
---
--- @param lnum? integer?
--- @param col? integer?
--- @return table
function vim.fn.complete_match(lnum, col) end
--- confirm() offers the user a dialog, from which a choice can be
--- made. It returns the number of the choice. For the first
--- choice this is 1.