Skip to content

Commit

Permalink
Merge branch 'main' into peek-folded
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinhwang91 committed Jul 1, 2022
2 parents 42c2b8b + 1cf0e99 commit 9331576
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 5 deletions.
3 changes: 3 additions & 0 deletions lua/ufo.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local api = vim.api

---Export methods to the users, `require('ufo').method(...)`
---@class Ufo
local M = {}
Expand Down Expand Up @@ -33,6 +35,7 @@ end
---Inspect ufo information by bufnr
---@param bufnr? number current buffer 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)
Expand Down
11 changes: 11 additions & 0 deletions lua/ufo/fold.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ function Fold.get(bufnr)
return foldbuffer:get(bufnr)
end

function Fold.attach(bufnr)
foldbuffer.detachedBufSet[bufnr] = nil
end

function Fold.detach(bufnr)
foldbuffer.detachedBufSet[bufnr] = true
end

function Fold.setStatus(bufnr, status)
local fb = foldbuffer:get(bufnr)
local old = ''
Expand Down Expand Up @@ -147,6 +155,9 @@ end)()

local function attach(bufnr)
bufnr = bufnr or api.nvim_get_current_buf()
if foldbuffer.detachedBufSet[bufnr] then
return
end
log.debug('attach bufnr:', bufnr)
local fb = foldbuffer:get(bufnr)
if fb then
Expand Down
3 changes: 2 additions & 1 deletion lua/ufo/fold/buffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ local FoldBuffer = {
ns = nil,
hlNs = nil,
openFoldHlTimeout = 0,
pool = {}
pool = {},
detachedBufSet = {}
}

---@class UfoFoldedLine
Expand Down
2 changes: 2 additions & 0 deletions lua/ufo/lib/event.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local disposable = require('ufo.lib.disposable')
local log = require('ufo.lib.log')

---@class UfoEvent
local Event = {
Expand Down Expand Up @@ -48,6 +49,7 @@ function Event:emit(name, ...)
if not listeners then
return
end
log.trace('event:', name, 'listeners:', listeners, 'args:', ...)
for _, listener in ipairs(listeners) do
listener(...)
end
Expand Down
6 changes: 5 additions & 1 deletion lua/ufo/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ local event = require('ufo.lib.event')
local disposable = require('ufo.lib.disposable')

local enabled

---@type UfoDisposable[]
local disposables = {}

local function createEvents()
Expand Down Expand Up @@ -73,7 +75,7 @@ function M.disable()
end
deleteCommand()
for _, item in ipairs(disposables) do
item:disable()
item:dispose()
end
enabled = false
return true
Expand All @@ -99,6 +101,7 @@ end

function M.attach(bufnr)
bufnr = bufnr or api.nvim_get_current_buf()
fold.attach(bufnr)
event:emit('BufEnter', bufnr)
end

Expand All @@ -108,6 +111,7 @@ function M.detach(bufnr)
if fb then
fb:dispose()
end
fold.detach(bufnr)
end

function M.enableFold(bufnr)
Expand Down
7 changes: 5 additions & 2 deletions lua/ufo/provider.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ end
function Provider.requestFoldingRange(providers, bufnr)
local main, fallback = providers[1], providers[2]
local mainFunc = getFunction(main)
return promise.resolve(mainFunc(bufnr)):thenCall(function(value)

return promise(function(resolve)
resolve(mainFunc(bufnr))
end):thenCall(function(value)
return {main, value}
end, function(reason)
if reason == 'UfoFallbackException' then
if type(reason) == 'string' and reason:match('UfoFallbackException') then
local fallbackFunc = getFunction(fallback)
if fallbackFunc then
return {fallback, fallbackFunc(bufnr)}
Expand Down
1 change: 0 additions & 1 deletion lua/ufo/provider/lsp/nvim.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function NvimClient.requestFoldingRange(bufnr, kind)
return
end
local bt = vim.bo[bufnr].bt
-- same behavior with coc.nvim
if bt ~= '' and bt ~= 'acwrite' then
return
end
Expand Down
111 changes: 111 additions & 0 deletions lua/ufo/provider/treesitter.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
local parsers = require('nvim-treesitter.parsers')
local query = require('nvim-treesitter.query')
local utils = require('ufo.utils')

local Treesitter = {}

local function prepare_query(bufnr, parser, queryName, root, rootLang)
if not root then
local firstTree = parser:trees()[1]
if firstTree then
root = firstTree:root()
else
return
end
end

local range = {root:range()}

if not rootLang then
local langTree = parser:language_for_range(range)
if langTree then
rootLang = langTree:lang()
else
return
end
end

return query.get_query(rootLang, queryName), {
root = root,
source = bufnr,
start = range[1],
-- The end row is exclusive so we need to add 1 to it.
stop = range[3] + 1,
}
end

local function iterFoldMatches(bufnr, parser, root, rootLang)
local q, p = prepare_query(bufnr, parser, 'folds', root, rootLang)
if not q then
return function() end
end
local iter = q:iter_matches(p.root, p.source, p.start, p.stop)
return function()
local pattern, match = iter()
local matches = {}
if pattern == nil then
return pattern
end
for id, node in ipairs(match) do
local name = q.captures[id] -- name of the capture in the query
if name then
table.insert(matches, node)
end
end
return matches
end
end

local function getFoldMatches(res, bufnr, parser, root, lang)
for matches in iterFoldMatches(bufnr, parser, root, lang) do
for _, node in ipairs(matches) do
table.insert(res, node)
end
end
return res
end

local function getCpatureMatchesRecursively(bufnr, parser)
local noQuery = true
local res = {}
parser:for_each_tree(function(tree, langTree)
local lang = langTree:lang()
if query.has_folds(lang) then
noQuery = false
getFoldMatches(res, bufnr, parser, tree:root(), lang)
end
end)
if noQuery then
error('UfoFallbackException')
end
return res
end

function Treesitter.getFolds(bufnr)
if not utils.isBufLoaded(bufnr) then
return
end
local bt = vim.bo[bufnr].bt
if bt ~= '' and bt ~= 'acwrite' then
return
end
local parser = parsers.get_parser(bufnr)
if not parser then
error('UfoFallbackException')
end

local ranges = {}
local matches = getCpatureMatchesRecursively(bufnr, parser)
for _, node in ipairs(matches) do
local start, _, stop, stop_col = node:range()
if stop_col == 0 then
stop = stop - 1
end
if stop > start then
table.insert(ranges, {startLine = start, endLine = stop})
end
end
return ranges
end

return Treesitter

0 comments on commit 9331576

Please sign in to comment.