197 lines
7.4 KiB
Lua
197 lines
7.4 KiB
Lua
local api = vim.api
|
|
|
|
---Export methods to the users, `require('ufo').method(...)`
|
|
---@class Ufo
|
|
local M = {}
|
|
|
|
---Peek the folded line under cursor, any motions in the normal window will close the floating window.
|
|
---@param enter? boolean enter the floating window, default value is false
|
|
---@param nextLineIncluded? boolean include the next line of last line of closed fold, default is true
|
|
---@return number? winid return the winid if successful, otherwise return nil
|
|
function M.peekFoldedLinesUnderCursor(enter, nextLineIncluded)
|
|
return require('ufo.preview'):peekFoldedLinesUnderCursor(enter, nextLineIncluded)
|
|
end
|
|
|
|
---Go to previous start fold. Neovim can't go to previous start fold directly, it's an extra motion.
|
|
function M.goPreviousStartFold()
|
|
require('ufo.action').goPreviousStartFold()
|
|
end
|
|
|
|
---Go to previous closed fold. It's an extra motion.
|
|
function M.goPreviousClosedFold()
|
|
require('ufo.action').goPreviousClosedFold()
|
|
end
|
|
|
|
---Go to next closed fold. It's an extra motion.
|
|
function M.goNextClosedFold()
|
|
return require('ufo.action').goNextClosedFold()
|
|
end
|
|
|
|
---Close all folds but keep foldlevel
|
|
function M.closeAllFolds()
|
|
return M.closeFoldsWith(0)
|
|
end
|
|
|
|
---Open all folds but keep foldlevel
|
|
function M.openAllFolds()
|
|
return require('ufo.action').openFoldsExceptKinds()
|
|
end
|
|
|
|
---Close the folds with a higher level,
|
|
---Like execute `set foldlevel=level` but keep foldlevel
|
|
---@param level? number fold level, `v:count` by default
|
|
function M.closeFoldsWith(level)
|
|
return require('ufo.action').closeFolds(level or vim.v.count)
|
|
end
|
|
|
|
---Open folds except specified kinds
|
|
---@param kinds? UfoFoldingRangeKind[] kind in ranges, get default kinds from `config.close_fold_kinds_for_ft`
|
|
function M.openFoldsExceptKinds(kinds)
|
|
if not kinds then
|
|
local c = require('ufo.config')
|
|
if c.close_fold_kinds and not vim.tbl_isempty(c.close_fold_kinds) then
|
|
kinds = c.close_fold_kinds
|
|
else
|
|
kinds = c.close_fold_kinds_for_ft[vim.bo.ft] or c.close_fold_kinds_for_ft.default
|
|
end
|
|
end
|
|
return require('ufo.action').openFoldsExceptKinds(kinds)
|
|
end
|
|
|
|
---Inspect ufo information by bufnr
|
|
---@param bufnr? number buffer number, current buffer by default
|
|
function M.inspect(bufnr)
|
|
bufnr = bufnr or api.nvim_get_current_buf()
|
|
local msg = require('ufo.main').inspectBuf(bufnr)
|
|
if not msg then
|
|
vim.notify(('Buffer %d has not been attached.'):format(bufnr), vim.log.levels.ERROR)
|
|
else
|
|
vim.notify(table.concat(msg, '\n'), vim.log.levels.INFO)
|
|
end
|
|
end
|
|
|
|
---Enable ufo
|
|
function M.enable()
|
|
require('ufo.main').enable()
|
|
end
|
|
|
|
---Disable ufo
|
|
function M.disable()
|
|
require('ufo.main').disable()
|
|
end
|
|
|
|
---Check whether the buffer has been attached
|
|
---@param bufnr? number buffer number, current buffer by default
|
|
---@return boolean
|
|
function M.hasAttached(bufnr)
|
|
return require('ufo.main').hasAttached(bufnr)
|
|
end
|
|
|
|
---Attach bufnr to enable all features
|
|
---@param bufnr? number buffer number, current buffer by default
|
|
function M.attach(bufnr)
|
|
require('ufo.main').attach(bufnr)
|
|
end
|
|
|
|
---Detach bufnr to disable all features
|
|
---@param bufnr? number buffer number, current buffer by default
|
|
function M.detach(bufnr)
|
|
require('ufo.main').detach(bufnr)
|
|
end
|
|
|
|
---Enable to get folds and update them at once
|
|
---@param bufnr? number buffer number, current buffer by default
|
|
---@return string|'start'|'pending'|'stop' status
|
|
function M.enableFold(bufnr)
|
|
return require('ufo.main').enableFold(bufnr)
|
|
end
|
|
|
|
---Disable to get folds
|
|
---@param bufnr? number buffer number, current buffer by default
|
|
---@return string|'start'|'pending'|'stop' status
|
|
function M.disableFold(bufnr)
|
|
return require('ufo.main').disableFold(bufnr)
|
|
end
|
|
|
|
---Get foldingRange from the ufo internal providers by name
|
|
---@param bufnr number
|
|
---@param providerName string|'lsp'|'treesitter'|'indent'
|
|
---@return UfoFoldingRange[]|Promise
|
|
function M.getFolds(bufnr, providerName)
|
|
if type(bufnr) == 'string' and type(providerName) == 'number' then
|
|
--TODO signature is changed (swap parameters), notify deprecated in next released
|
|
---@deprecated
|
|
---@diagnostic disable-next-line: cast-local-type
|
|
bufnr, providerName = providerName, bufnr
|
|
end
|
|
local func = require('ufo.provider'):getFunction(providerName)
|
|
return func(bufnr)
|
|
end
|
|
|
|
---Apply foldingRange at once.
|
|
---ufo always apply folds asynchronously, this function can apply folds synchronously.
|
|
---Note: Get ranges from 'lsp' provider is asynchronous.
|
|
---@param bufnr number
|
|
---@param ranges UfoFoldingRange[]
|
|
---@return number winid return the winid if successful, otherwise return -1
|
|
function M.applyFolds(bufnr, ranges)
|
|
vim.validate({bufnr = {bufnr, 'number', true}, ranges = {ranges, 'table'}})
|
|
return require('ufo.fold').apply(bufnr, ranges, true)
|
|
end
|
|
|
|
---Setup configuration and enable ufo
|
|
---@param opts? UfoConfig
|
|
function M.setup(opts)
|
|
opts = opts or {}
|
|
M._config = opts
|
|
M.enable()
|
|
end
|
|
|
|
---------------------------------------setFoldVirtTextHandler---------------------------------------
|
|
|
|
---@class UfoFoldVirtTextHandlerContext
|
|
---@field bufnr number buffer for closed fold
|
|
---@field winid number window for closed fold
|
|
---@field text string text for the first line of closed fold
|
|
---@field get_fold_virt_text fun(lnum: number): UfoExtmarkVirtTextChunk[] a function to get virtual text by lnum
|
|
|
|
---@class UfoExtmarkVirtTextChunk
|
|
---@field [1] string text
|
|
---@field [2] string|number highlight
|
|
|
|
---Set a fold virtual text handler for a buffer, will override global handler if it's existed.
|
|
---Ufo actually uses a virtual text with \`nvim_buf_set_extmark\` to overlap the first line of closed fold
|
|
---run \`:h nvim_buf_set_extmark | call search('virt_text')\` for detail.
|
|
---Return `{}` will not render folded line but only keep a extmark for providers.
|
|
---@diagnostic disable: undefined-doc-param
|
|
---Detail for handler function:
|
|
---@param virtText UfoExtmarkVirtTextChunk[] contained text and highlight captured by Ufo, export to caller
|
|
---@param lnum number first line of closed fold, like \`v:foldstart\` in foldtext()
|
|
---@param endLnum number last line of closed fold, like \`v:foldend\` in foldtext()
|
|
---@param width number text area width, exclude foldcolumn, signcolumn and numberwidth
|
|
---@param truncate fun(str: string, width: number): string truncate the str to become specific width,
|
|
---return width of string is equal or less than width (2nd argument).
|
|
---For example: '1': 1 cell, '你': 2 cells, '2': 1 cell, '好': 2 cells
|
|
---truncate('1你2好', 1) return '1'
|
|
---truncate('1你2好', 2) return '1'
|
|
---truncate('1你2好', 3) return '1你'
|
|
---truncate('1你2好', 4) return '1你2'
|
|
---truncate('1你2好', 5) return '1你2'
|
|
---truncate('1你2好', 6) return '1你2好'
|
|
---truncate('1你2好', 7) return '1你2好'
|
|
---@param ctx UfoFoldVirtTextHandlerContext the context used by ufo, export to caller
|
|
|
|
---@alias UfoFoldVirtTextHandler fun(virtText: UfoExtmarkVirtTextChunk[], lnum: number, endLnum: number, width: number, truncate: fun(str: string, width: number), ctx: UfoFoldVirtTextHandlerContext): UfoExtmarkVirtTextChunk[]
|
|
|
|
---@param bufnr number
|
|
---@param handler UfoFoldVirtTextHandler
|
|
function M.setFoldVirtTextHandler(bufnr, handler)
|
|
vim.validate({bufnr = {bufnr, 'number', true}, handler = {handler, 'function'}})
|
|
require('ufo.decorator'):setVirtTextHandler(bufnr, handler)
|
|
end
|
|
|
|
---@diagnostic disable: undefined-doc-param
|
|
---------------------------------------setFoldVirtTextHandler---------------------------------------
|
|
|
|
return M
|