mirror of
https://github.com/kevinhwang91/nvim-ufo
synced 2024-09-16 14:14:02 +02:00
docs: update
This commit is contained in:
parent
a9a422b2f0
commit
9569085ffd
9 changed files with 199 additions and 20 deletions
19
README.md
19
README.md
|
@ -8,6 +8,8 @@ The goal of nvim-ufo is to make Neovim's fold look modern and keep high performa
|
|||
|
||||
<https://user-images.githubusercontent.com/17562139/173796287-9842fb3a-37c2-47fb-8968-6e7600c0fcef.mp4>
|
||||
|
||||
> [setup foldcolumn like demo](https://github.com/kevinhwang91/nvim-ufo/issues/4)
|
||||
|
||||
---
|
||||
|
||||
## Table of contents
|
||||
|
@ -45,6 +47,7 @@ vim.wo.foldenable = true
|
|||
|
||||
-- option 1: coc.nvim as LSP client
|
||||
use {'neoclide/coc.nvim', branch = 'master', run = 'yarn install --frozen-lockfile'}
|
||||
--
|
||||
|
||||
-- option 2: nvim lsp as LSP client
|
||||
-- tell the sever the capability of foldingRange
|
||||
|
@ -53,6 +56,7 @@ capabilities.textDocument.foldingRange = {
|
|||
dynamicRegistration = false,
|
||||
lineFoldingOnly = true
|
||||
}
|
||||
--
|
||||
|
||||
require('ufo').setup()
|
||||
```
|
||||
|
@ -66,7 +70,7 @@ Use fold as usual.
|
|||
### How does nvim-ufo get the folds?
|
||||
|
||||
If ufo detect `foldmethod` option is not `diff` or `marker`, it will request the providers to get
|
||||
the folds, the request strategy formed by the main and the fallback. The default value of main is
|
||||
the folds, the request strategy is formed by the main and the fallback. The default value of main is
|
||||
`lsp` and the default value of fallback is `indent` which implemented by ufo.
|
||||
|
||||
Changing the text in a buffer will request the providers for folds.
|
||||
|
@ -83,11 +87,12 @@ Changing the text in a buffer will request the providers for folds.
|
|||
default = 400
|
||||
},
|
||||
provider_selector = {
|
||||
description = [[a function as a selector for fold providers, TODO]],
|
||||
description = [[a function as a selector for fold providers. For now, there are 'lsp' and 'indent'
|
||||
providers]],
|
||||
default = nil
|
||||
},
|
||||
fold_virt_text_handler = {
|
||||
description = [[a function customize fold virt text, TODO]],
|
||||
description = [[a function customize fold virt text, see ### Customize fold text]],
|
||||
default = nil
|
||||
}
|
||||
}
|
||||
|
@ -99,22 +104,24 @@ Changing the text in a buffer will request the providers for folds.
|
|||
hi default link UfoFoldedEllipsis Comment
|
||||
```
|
||||
|
||||
- `UfoFoldedEllipsis`: highlight ellipsis at the end of folded line
|
||||
- `UfoFoldedEllipsis`: highlight ellipsis at the end of folded line, invalid if
|
||||
`fold_virt_text_handler` is set.
|
||||
|
||||
## Advanced configuration
|
||||
|
||||
Configuration can be found at [example.lua](./doc/example.lua)
|
||||
|
||||
### Customize provider selector
|
||||
|
||||
```lua
|
||||
local ftMap = {
|
||||
vim = 'indent',
|
||||
c = 'indent',
|
||||
python = {'indent'},
|
||||
git = ''
|
||||
}
|
||||
require('ufo').setup({
|
||||
provider_selector = function(bufnr, filetype)
|
||||
-- return a string type use a built-in provider
|
||||
-- return a string type use internal providers
|
||||
-- return a string in a table like a string type
|
||||
-- return empty string '' will disable any providers
|
||||
-- return `nil` will use default value {'lsp', 'indent'}
|
||||
|
|
73
doc/example.lua
Normal file
73
doc/example.lua
Normal file
|
@ -0,0 +1,73 @@
|
|||
---@diagnostic disable: unused-local, unused-function
|
||||
|
||||
local function selectProviderWithFt()
|
||||
local ftMap = {
|
||||
vim = 'indent',
|
||||
python = {'indent'},
|
||||
git = ''
|
||||
}
|
||||
require('ufo').setup({
|
||||
provider_selector = function(bufnr, filetype)
|
||||
-- return a string type use ufo providers
|
||||
-- return a string in a table like a string type
|
||||
-- return empty string '' will disable any providers
|
||||
-- return `nil` will use default value {'lsp', 'indent'}
|
||||
return ftMap[filetype]
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
local function selectProviderWithFunc()
|
||||
require('ufo').setup({
|
||||
provider_selector = function(bufnr, filetype)
|
||||
-- use indent provider for c fieltype
|
||||
if filetype == 'c' then
|
||||
return function()
|
||||
return require('ufo').getFolds('indent', bufnr)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
local handler = function(virtText, lnum, endLnum, width, truncate)
|
||||
local newVirtText = {}
|
||||
local suffix = (' %d '):format(endLnum - lnum)
|
||||
local sufWidth = vim.fn.strdisplaywidth(suffix)
|
||||
local targetWidth = width - sufWidth
|
||||
local curWidth = 0
|
||||
for _, chunk in ipairs(virtText) do
|
||||
local chunkText = chunk[1]
|
||||
local chunkWidth = vim.fn.strdisplaywidth(chunkText)
|
||||
if targetWidth > curWidth + chunkWidth then
|
||||
table.insert(newVirtText, chunk)
|
||||
else
|
||||
chunkText = truncate(chunkText, targetWidth - curWidth)
|
||||
local hlGroup = chunk[2]
|
||||
table.insert(newVirtText, {chunkText, hlGroup})
|
||||
chunkWidth = vim.fn.strdisplaywidth(chunkText)
|
||||
-- text length returned from truncate() may less than 2rd argument, need padding
|
||||
if curWidth + chunkWidth < targetWidth then
|
||||
suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
|
||||
end
|
||||
break
|
||||
end
|
||||
curWidth = curWidth + chunkWidth
|
||||
end
|
||||
table.insert(newVirtText, {suffix, 'MoreMsg'})
|
||||
return newVirtText
|
||||
end
|
||||
|
||||
local function customizeFoldText()
|
||||
-- global handler
|
||||
require('ufo').setup({
|
||||
fold_virt_text_handler = handler
|
||||
}
|
||||
end
|
||||
|
||||
local function customizeBufFoldText()
|
||||
-- buffer scope handler
|
||||
-- will override global handler if it is existed
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
require('ufo').setVirtTextHandler(bufnr, handler)
|
||||
end
|
17
doc/ufo.txt
Normal file
17
doc/ufo.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
*ufo.txt*
|
||||
*nvimufo.txt*
|
||||
*nvim-ufo.txt*
|
||||
|
||||
type `gf` or `CTRL-W gf` under the PATH value :)
|
||||
|
||||
`URL`: https://github.com/kevinhwang91/nvim-ufo
|
||||
|
||||
`PATH`: ../README.md
|
||||
|
||||
`PATH`: ../lua/ufo/config.lua |nvim-ufo-default-config|
|
||||
|
||||
`PATH`: ../lua/ufo.lua |nvim-ufo-api|
|
||||
|
||||
`PATH`: ../doc/example.lua |nvim-ufo-example|
|
||||
|
||||
vim:ft=help
|
28
lua/ufo.lua
28
lua/ufo.lua
|
@ -1,9 +1,9 @@
|
|||
---Export methods to the users, `require('ufo').method(...)`
|
||||
---@class Ufo
|
||||
local M = {}
|
||||
local cmd = vim.cmd
|
||||
local fn = vim.fn
|
||||
local api = vim.api
|
||||
|
||||
|
||||
---Setup configuration and enable ufo
|
||||
---@param opts? UfoConfig
|
||||
function M.setup(opts)
|
||||
opts = opts or {}
|
||||
M._config = opts
|
||||
|
@ -14,6 +14,8 @@ function M.goPreviousStartFold()
|
|||
return require('ufo.action').goPreviousStartFold()
|
||||
end
|
||||
|
||||
---Inspect ufo information by bufnr
|
||||
---@param bufnr? number current buffer default
|
||||
function M.inspect(bufnr)
|
||||
local msg = require('ufo.main').inspectBuf(bufnr)
|
||||
if not msg then
|
||||
|
@ -23,32 +25,48 @@ function M.inspect(bufnr)
|
|||
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 current buffer default
|
||||
---@return boolean
|
||||
function M.hasAttached(bufnr)
|
||||
return require('ufo.main').inspectBuf(bufnr) ~= nil
|
||||
end
|
||||
|
||||
---Attach bufnr to enable ufo features
|
||||
---@param bufnr? number current buffer default
|
||||
function M.attach(bufnr)
|
||||
require('ufo.main').attach(bufnr)
|
||||
end
|
||||
|
||||
---Detach bufnr to disable ufo features
|
||||
---@param bufnr? number current buffer default
|
||||
function M.detach(bufnr)
|
||||
require('ufo.main').detach(bufnr)
|
||||
end
|
||||
|
||||
function M.getFoldingRange(providerName, bufnr)
|
||||
---Get foldingRange from the ufo internal providers by name
|
||||
---@param providerName string
|
||||
---@param bufnr number
|
||||
---@return UfoFoldingRange|Promise
|
||||
function M.getFolds(providerName, bufnr)
|
||||
local ok, res = pcall(require, 'ufo.provider.' .. providerName)
|
||||
assert(ok, ([[Can't find %s provider]]):format(providerName))
|
||||
return res.getFolds(bufnr)
|
||||
end
|
||||
|
||||
---Set a fold virtual text handler for a buffer, will override global handler if it's existed
|
||||
---@param bufnr number
|
||||
---@param handler UfoFoldVirtTextHandler reference to `config.fold_virt_text_handler`
|
||||
function M.setFoldVirtTextHandler(bufnr, handler)
|
||||
require('ufo.decorator').setVirtTextHandler(bufnr, handler)
|
||||
end
|
||||
|
|
|
@ -1,8 +1,57 @@
|
|||
---@class UfoConfig
|
||||
---@field open_fold_hl_timeout number
|
||||
---@field provider_selector function
|
||||
---@field fold_virt_text_handler UfoFoldVirtTextHandler
|
||||
local config = {}
|
||||
---@field fold_virt_text_handler function
|
||||
local Config = {}
|
||||
|
||||
|
||||
---@alias UfoProviderEnum
|
||||
---| 'lsp'
|
||||
---| 'indent'
|
||||
|
||||
---
|
||||
---@param bufnr number
|
||||
---@param filetype string buffer filetype
|
||||
---@return UfoProviderEnum|string[]|function|nil
|
||||
---return a string type use ufo providers
|
||||
---return a string in a table like a string type
|
||||
---return empty string '' will disable any providers
|
||||
---return `nil` will use default value {'lsp', 'indent'}
|
||||
---@diagnostic disable-next-line: unused-function, unused-local
|
||||
function Config.provider_selector(bufnr, filetype) end
|
||||
|
||||
---@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
|
||||
|
||||
---run `:h nvim_buf_set_extmark` and search `virt_text` optional parameter for details
|
||||
---@class ExtmarkVirtText
|
||||
---@field text string
|
||||
---@field highlight string|number
|
||||
|
||||
---@class UfoFoldVirtTextHandler
|
||||
---Ufo actually uses a virtual text with `nvim_buf_set_extmark` to overlap the first line of
|
||||
---closed fold
|
||||
---@param virtText ExtmarkVirtText contained text and highlight captured by Ufo, reused by 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 the 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 str's width.
|
||||
---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好'
|
||||
---truncate('1你2好', 8) return '1你2好'
|
||||
---@param ctx UfoFoldVirtTextHandlerContext context for handler
|
||||
---@return ExtmarkVirtText[]
|
||||
---@diagnostic disable-next-line: unused-function, unused-local
|
||||
function Config.fold_virt_text_handler(virtText, lnum, endLnum, width, truncate, ctx) end
|
||||
|
||||
local function init()
|
||||
local ufo = require('ufo')
|
||||
|
@ -12,10 +61,10 @@ local function init()
|
|||
provider_selector = nil,
|
||||
fold_virt_text_handler = nil,
|
||||
}
|
||||
config = vim.tbl_deep_extend('keep', ufo._config or {}, def)
|
||||
Config = vim.tbl_deep_extend('keep', ufo._config or {}, def)
|
||||
ufo._config = nil
|
||||
end
|
||||
|
||||
init()
|
||||
|
||||
return config
|
||||
return Config
|
||||
|
|
|
@ -179,7 +179,6 @@ local function onEnd(name, tick)
|
|||
fb:closeFold(lnum, endLnum, virtText, width)
|
||||
end
|
||||
end
|
||||
fb.width = width
|
||||
end)
|
||||
end
|
||||
local lnum = api.nvim_win_get_cursor(winid)[1]
|
||||
|
@ -214,7 +213,7 @@ function Decorator.defaultVirtTextHandler(virtText, lnum, endLnum, width, trunca
|
|||
local hlGroup = chunk[2]
|
||||
table.insert(newVirtText, {chunkText, hlGroup})
|
||||
chunkWidth = fn.strdisplaywidth(chunkText)
|
||||
-- text length returned from truncate() may less than 2rd argument, need padding
|
||||
-- str width returned from truncate() may less than 2rd argument, need padding
|
||||
if curWidth + chunkWidth < targetWidth then
|
||||
suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
|
||||
end
|
||||
|
|
|
@ -63,10 +63,10 @@ local function updateFold(bufnr)
|
|||
bufnr, (uv.hrtime() - s) / 1e6))
|
||||
end
|
||||
local p, ranges = res[1], res[2]
|
||||
fb.targetProvider = type(p) == 'string' and p or 'external'
|
||||
if not ranges or #ranges == 0 or not utils.isBufLoaded(bufnr) then
|
||||
return
|
||||
end
|
||||
fb.targetProvider = type(p) == 'string' and p or 'external'
|
||||
winid = fn.bufwinid(bufnr)
|
||||
local newChangedtick = api.nvim_buf_get_changedtick(bufnr)
|
||||
fb.version = newChangedtick
|
||||
|
|
|
@ -65,7 +65,8 @@ function M.inspectBuf(bufnr)
|
|||
end
|
||||
local msg = {}
|
||||
table.insert(msg, 'Buffer: ' .. bufnr)
|
||||
table.insert(msg, 'Main provider: ' .. fb.providers[1])
|
||||
local main = fb.providers[1]
|
||||
table.insert(msg, 'Main provider: ' .. (type(main) == 'function' and 'external' or main))
|
||||
if fb.providers[2] then
|
||||
table.insert(msg, 'Fallback provider: ' .. fb.providers[2])
|
||||
end
|
||||
|
@ -92,5 +93,4 @@ function M.foldtext()
|
|||
return utils.expandTab(text, vim.bo.ts)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
|
|
|
@ -15,6 +15,22 @@ local function getFunction(m)
|
|||
return type(m) == 'string' and modules[m].getFolds or m
|
||||
end
|
||||
|
||||
---@alias UfoFoldingRangeKind
|
||||
---| 'comment'
|
||||
---| 'imports'
|
||||
---| 'region'
|
||||
|
||||
---@class UfoFoldingRange
|
||||
---@field startLine number
|
||||
---@field startCharacter? number
|
||||
---@field endLine number
|
||||
---@field endCharacter? number
|
||||
---@field kind? UfoFoldingRangeKind
|
||||
|
||||
---
|
||||
---@param providers table
|
||||
---@param bufnr number
|
||||
---@return Promise
|
||||
function Provider.requestFoldingRange(providers, bufnr)
|
||||
local main, fallback = providers[1], providers[2]
|
||||
local mainFunc = getFunction(main)
|
||||
|
|
Loading…
Reference in a new issue