196 lines
6.4 KiB
Lua

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