diff --git a/lua/outline/markdown.lua b/lua/outline/markdown.lua deleted file mode 100644 index 0464d35..0000000 --- a/lua/outline/markdown.lua +++ /dev/null @@ -1,91 +0,0 @@ -local M = {} - --- Parses markdown files and returns a table of SymbolInformation[] which is --- used by the plugin to show the outline. --- We do this because markdown does not have a LSP. --- Note that the headings won't have any hierarchy (as of now). ----@return table -function M.handle_markdown() - local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) - local level_symbols = { { children = {} } } - local max_level = 1 - local is_inside_code_block = false - - for line, value in ipairs(lines) do - if string.find(value, '^```') then - is_inside_code_block = not is_inside_code_block - end - if is_inside_code_block then - goto nextline - end - - local next_value = lines[line+1] - local is_emtpy_line = #value:gsub("^%s*(.-)%s*$", "%1") == 0 - - local header, title = string.match(value, '^(#+)%s+(.+)$') - if not header and next_value and not is_emtpy_line then - if string.match(next_value, '^=+%s*$') then - header = '#' - title = value - elseif string.match(next_value, '^-+%s*$') then - header = '##' - title = value - end - end - if not header or not title then - goto nextline - end - -- TODO: This is not needed and it works? - -- if #header > 6 then - -- goto nextline - -- end - - local depth = #header + 1 - - local parent - for i = depth - 1, 1, -1 do - if level_symbols[i] ~= nil then - parent = level_symbols[i].children - break - end - end - - for i = depth, max_level do - if level_symbols[i] ~= nil then - level_symbols[i].selectionRange['end'].line = line - 1 - level_symbols[i].range['end'].line = line - 1 - level_symbols[i] = nil - end - end - max_level = depth - - local entry = { - kind = 13, - name = title, - selectionRange = { - start = { character = 1, line = line - 1 }, - ['end'] = { character = 1, line = line - 1 }, - }, - range = { - start = { character = 1, line = line - 1 }, - ['end'] = { character = 1, line = line - 1 }, - }, - children = {}, - } - - parent[#parent + 1] = entry - level_symbols[depth] = entry - ::nextline:: - end - - for i = 2, max_level do - if level_symbols[i] ~= nil then - level_symbols[i].selectionRange['end'].line = #lines - level_symbols[i].range['end'].line = #lines - end - end - - return level_symbols[1].children -end - -return M diff --git a/lua/outline/providers/init.lua b/lua/outline/providers/init.lua index 1599c1b..343446a 100644 --- a/lua/outline/providers/init.lua +++ b/lua/outline/providers/init.lua @@ -3,6 +3,11 @@ local M = {} local providers = { 'outline/providers/nvim-lsp', 'outline/providers/coc', + -- NOTE: There is in fact a markdown LSP that can provide symbols. However + -- on buffer open the LSP may not be attached immediately. Before the LSP is + -- ready if the user opens the outline, our own markdown provider will be + -- used. After refreshing/reopening, the provider will then switch to the LSP + -- (if the user has a markdown LSP). 'outline/providers/markdown', } diff --git a/lua/outline/providers/markdown.lua b/lua/outline/providers/markdown.lua index 01bfa1f..3f6def2 100644 --- a/lua/outline/providers/markdown.lua +++ b/lua/outline/providers/markdown.lua @@ -1,10 +1,13 @@ -local md_parser = require 'outline.markdown' +-- Our own markdown provider is used because legacy symbols-outline considered +-- the case where markdown does not have an LSP. However, it does, so as of now +-- this module is kept for use when user opens symbols outline before the +-- markdown LSP is ready. Please also see comment in providers/init.lua local M = {} --- probably change this +---@return boolean ft_is_markdown function M.should_use_provider(bufnr) - return string.match(vim.api.nvim_buf_get_option(bufnr, 'ft'), 'markdown') + return vim.api.nvim_buf_get_option(bufnr, 'ft') == 'markdown' end function M.hover_info(_, _, on_info) @@ -16,10 +19,96 @@ function M.hover_info(_, _, on_info) }) end +-- Parses markdown files and returns a table of SymbolInformation[] which is +-- used by the plugin to show the outline. +---@return table +function M.handle_markdown() + local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) + local level_symbols = { { children = {} } } + local max_level = 1 + local is_inside_code_block = false + + for line, value in ipairs(lines) do + if string.find(value, '^```') then + is_inside_code_block = not is_inside_code_block + end + if is_inside_code_block then + goto nextline + end + + local next_value = lines[line+1] + local is_emtpy_line = #value:gsub("^%s*(.-)%s*$", "%1") == 0 + + local header, title = string.match(value, '^(#+)%s+(.+)$') + if not header and next_value and not is_emtpy_line then + if string.match(next_value, '^=+%s*$') then + header = '#' + title = value + elseif string.match(next_value, '^-+%s*$') then + header = '##' + title = value + end + end + if not header or not title then + goto nextline + end + -- TODO: This is not needed and it works? + -- if #header > 6 then + -- goto nextline + -- end + + local depth = #header + 1 + + local parent + for i = depth - 1, 1, -1 do + if level_symbols[i] ~= nil then + parent = level_symbols[i].children + break + end + end + + for i = depth, max_level do + if level_symbols[i] ~= nil then + level_symbols[i].selectionRange['end'].line = line - 1 + level_symbols[i].range['end'].line = line - 1 + level_symbols[i] = nil + end + end + max_level = depth + + local entry = { + kind = 15, + name = title, + selectionRange = { + start = { character = 1, line = line - 1 }, + ['end'] = { character = 1, line = line - 1 }, + }, + range = { + start = { character = 1, line = line - 1 }, + ['end'] = { character = 1, line = line - 1 }, + }, + children = {}, + } + + parent[#parent + 1] = entry + level_symbols[depth] = entry + ::nextline:: + end + + for i = 2, max_level do + if level_symbols[i] ~= nil then + level_symbols[i].selectionRange['end'].line = #lines + level_symbols[i].range['end'].line = #lines + end + end + + return level_symbols[1].children +end + ---@param on_symbols function ---@param opts table function M.request_symbols(on_symbols, opts) - on_symbols(md_parser.handle_markdown(), opts) + on_symbols(M.handle_markdown(), opts) end return M