-- TODO -- reuse existing split -- use fqcn as buffer name -- add function to convert to fqcn, with telescope dropdown if there are multiple options -- telescope window to search through all available module names, enter inserts, other key opens doc in split local ts = require('nvim-treesitter.parsers') local M = {} M.example = function() local bufnr = vim.api.nvim_get_current_buf() local file_basename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ':t') local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) local parser = ts.get_parser(bufnr, 'yaml') local tree = parser:parse()[1] local root = tree:root() local objects = {} local current_line_nr = 1 while current_line_nr <= #lines do local line = lines[current_line_nr] -- print('current_line_nr', current_line_nr) -- print('line', line) if not line or line:match("^%s*$") then -- print('empty line, continuing') current_line_nr = current_line_nr + 1 goto continue end -- if line:match("^%s*#") then -- -- print('comment, continuing') -- -- todo - how? they are currently part of the nodes, but the previous one - if anything i want them to stick to the next one -- current_line_nr = current_line_nr + 1 -- goto continue -- end local node = root:named_descendant_for_range(current_line_nr-1, 0, current_line_nr-1, #line) if node and (node:type() == 'block_mapping_pair') then -- local node_lines = vim.treesitter.get_node_text(node, bufnr) -- not using, returns string, we want a table local start_row, _, end_row, _ = node:range() local node_lines = vim.api.nvim_buf_get_lines(bufnr, start_row, end_row + 1, false) -- print('line', line) -- print('node type', node:type()) -- print('node range', node:range()) -- print('node lines', node_lines) table.insert(objects, { sort_line = line, lines = node_lines, }) -- set current line to the next line after the node's end, and accouting for 0-indexing current_line_nr = end_row + 2 goto continue end -- do not get stuck on lines that do not match above print('did not match the line, node type: ', node:type(), ', line: ', line) -- insert it anyway, we do not want to loose lines table.insert(objects, { sort_line = line, lines = {line}, }) current_line_nr = current_line_nr + 1 ::continue:: end -- print(vim.inspect(objects)) table.sort( objects, function(k1, k2) return k1.sort_line < k2.sort_line end ) -- print(vim.inspect(objects)) -- clear the buffer vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {}) -- flatten sorted objects into lines and insert back into the buffer local sorted_lines = {} local last_prefix = nil for _, obj in ipairs(objects) do -- if the prefix switches, insert an empty line before the lines local split_line = vim.split(obj.sort_line, '__') -- if we only get one element back this means the line does not contain '__' -- lets try splitting on '_' -- else the fallback is the whole line if #split_line <= 1 then split_line = vim.split(obj.sort_line, '_') end local current_prefix = split_line[1] -- special case for hosts.yml if file_basename == 'hosts.yml' then current_prefix = obj.sort_line end -- print('current_prefix', current_prefix) -- print('last_prefix', last_prefix) if last_prefix == nil then -- handle the first line last_prefix = current_prefix elseif current_prefix ~= last_prefix then -- print('inserting newline') table.insert(sorted_lines, "") last_prefix = current_prefix end -- print('obj', vim.inspect(obj)) for _, line in ipairs(obj.lines) do table.insert(sorted_lines, line) end end -- print('sorted_lines', vim.inspect(sorted_lines)) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, sorted_lines) end M.display_ansible_doc = function(keyword) local Job = require'plenary.job' -- local keyword = 'get_url' local doc = {} Job:new({ command = 'ansible-doc', args = { keyword }, on_exit = function(j, return_val) -- print(return_val) -- print(vim.inspect(j:result())) doc = j:result() end, }):sync() -- or start() -- TODO unlisted / scratch buffer? local fqcn = string.lower(vim.split(doc[1], ' ')[2]) vim.api.nvim_command('vsplit ' .. fqcn) local win_handle = vim.api.nvim_tabpage_get_win(0) local buf_handle = vim.api.nvim_win_get_buf(0) vim.api.nvim_buf_set_lines(buf_handle, 0, -1, false, doc) vim.api.nvim_buf_set_option(buf_handle, 'readonly', true) vim.api.nvim_buf_set_option(buf_handle, 'modifiable', false) -- Now we set some options for our buffer. -- nofile prevent mark buffer as modified so we never get warnings about not saved changes. -- Also some plugins treat nofile buffers different. -- For example coc.nvim don't triggers aoutcompletation for these. vim.api.nvim_buf_set_option(buf_handle, 'buftype', 'nofile') -- We do not need swapfile for this buffer. vim.api.nvim_buf_set_option(buf_handle, 'swapfile', false) -- And we would rather prefer that this buffer will be destroyed when hide. vim.api.nvim_buf_set_option(buf_handle, 'bufhidden', 'wipe') -- It's not necessary but it is good practice to set custom filetype. -- This allows users to create their own autocommand or colorschemes on filetype. -- and prevent collisions with other plugins. vim.api.nvim_buf_set_option(buf_handle, 'filetype', 'ansible-doc') -- vim.api.nvim_command('wincmd p') -- go back to previous window end M.replace_fqcn = function() local Job = require'plenary.job' -- keyword = 'get_url' doc = {} Job:new({ command = 'ansible-doc', args = { keyword }, on_exit = function(j, return_val) -- print(return_val) -- print(vim.inspect(j:result())) doc = j:result() end, }):sync() -- or start() fqcn = string.lower(vim.split(doc[1], ' ')[2]) cur_pos = vim.api.nvim_win_get_cursor(0) buf_handle = vim.api.nvim_win_get_buf(0) vim.api.nvim_buf_set_lines(buf_handle, 0, -1, false, doc) end return M