Skip to content

Not UFO in the sky, but an ultra fold in Neovim.

License

Notifications You must be signed in to change notification settings

jaschenb/nvim-ufo

 
 

Repository files navigation

nvim-ufo

The goal of nvim-ufo is to make Neovim's fold look modern and keep high performance.

ufo-demo.mp4

setup foldcolumn like demo


Table of contents

Features

  • Penetrate color for folded lines like other modern editors/IDEs
  • Never block Neovim
  • Adding folds high accuracy with Folding Range in LSP
  • Support Fallback and customize strategy for fold provider

Quickstart

Requirements

Installation

Install with Packer.nvim:

use {'kevinhwang91/nvim-ufo', requires = 'kevinhwang91/promise-async'}

Minimal configuration

use {'kevinhwang91/nvim-ufo', requires = 'kevinhwang91/promise-async'}

vim.wo.foldcolumn = '1'
vim.wo.foldlevel = 99 -- feel free to decrease the value
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 server the capability of foldingRange
-- nvim hasn't added foldingRange to default capabilities, users must add it manually
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.foldingRange = {
    dynamicRegistration = false,
    lineFoldingOnly = true
}
local language_servers = {} -- like {'gopls', 'clangd'}
for _, ls in ipairs(language_servers) do
    require('lspconfig')[ls].setup({
        capabilities = capabilities,
        other_fields = ...
    })
end
--

require('ufo').setup()

Usage

Use fold as usual.

Documentation

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 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.

foldmethod option will finally become manual if ufo are working.

Setup and description

{
    open_fold_hl_timeout = {
        description = [[time in millisecond between the range to be highlgihted and to be cleared
                    while opening the folded line, `0` value will disable the highlight]],
        default = 400
    },
    provider_selector = {
        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, see ### Customize fold text]],
        default = nil
    }
}

Commands

TODO main.lua

API

TODO ufo.lua

Highlight groups

hi default link UfoFoldedEllipsis Comment
  • 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

Customize provider selector

local ftMap = {
    vim = 'indent',
    python = {'indent'},
    git = ''
}
require('ufo').setup({
    provider_selector = function(bufnr, filetype)
        -- 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'}
        return ftMap[filetype]
    end
})

Customize fold text

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)
            -- str width returned from truncate() may less than 2nd 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

-- global handler
require('ufo').setup({
    fold_virt_text_handler = handler
})

-- buffer scope handler
-- will override global handler if it is existed
local bufnr = vim.api.nvim_get_current_buf()
require('ufo').setFoldVirtTextHandler(bufnr, handler)

Feedback

  • If you get an issue or come up with an awesome idea, don't hesitate to open an issue in github.
  • If you think this plugin is useful or cool, consider rewarding it a star.

License

The project is licensed under a BSD-3-clause license. See LICENSE file for details.

About

Not UFO in the sky, but an ultra fold in Neovim.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Lua 97.7%
  • JavaScript 2.3%