Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,31 @@ return {
'nvim-telescope/telescope.nvim', -- or, 'folke/snacks.nvim'
},
cmd = { 'ApidocsSearch', 'ApidocsInstall', 'ApidocsOpen', 'ApidocsSelect', 'ApidocsUninstall' },
-- If using ensure_installed (see below), uncomment the next line to trigger the
-- installation when Neovim is opened
-- lazy = false
config = function()
require('apidocs').setup()
-- Picker will be auto-detected. To select a picker of your choice explicitly you can set picker by the configuration option 'picker':
-- require('apidocs').setup({picker = "snacks"})
-- Possible options are 'ui_select', 'telescope', and 'snacks'
local opts = {
-- Picker will be auto-detected. To select a picker of your choice explicitly you can set picker by the configuration option 'picker':
-- Possible options are 'ui_select', 'telescope', and 'snacks'
picker = "telescope",
-- Use the below to make sure documentations for your languages are installed
-- Note: best used with `lazy = false` (see above)
-- ensure_installed = { "lua~5.4" }

}
require('apidocs').setup(opts)
end,
keys = {
{ '<leader>sad', '<cmd>ApidocsOpen<cr>', desc = 'Search Api Doc' },
{
'<leader>sac',
function()
local lang = vim.bo.filetype
require("apidocs").apidocs_search({ restrict_sources = { lang } })
end,
desc = 'Search Api Doc (restricted to current file type)'
},
},
}
```
Expand Down
62 changes: 46 additions & 16 deletions lua/apidocs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,50 @@ local install = require("apidocs.install")

Config = {}

local function get_installed_docs(fs, opts)
local installed_docs = {}
if fs == nil then
return installed_docs
end
while true do
local name, type = vim.uv.fs_scandir_next(fs)
if not name then
break
end
if type == "directory" then
if opts and opts.restrict_sources then
for _, source in ipairs(opts.restrict_sources) do
if name:match("^" .. source) then
table.insert(installed_docs, name)
end
end
else
table.insert(installed_docs, name)
end
end
end
return installed_docs
end

local function ensure_installed(opts)
local docs_path = common.data_folder()
local fs = vim.uv.fs_scandir(docs_path)
local installed_docs = get_installed_docs(fs, opts)
if opts and opts.ensure_installed then
for _, source in ipairs(opts.ensure_installed) do
if not vim.tbl_contains(installed_docs, source) then
if slugs_to_mtimes == nil then
install.fetch_slugs_and_mtimes_and_then(function(slugs_to_mtimes)
install.apidoc_install(source, slugs_to_mtimes)
end)
else
install.apidoc_install(source, slugs_to_mtimes)
end
end
end
end
end

local function set_picker(opts)
if opts and (opts.picker == "snacks" or opts.picker == "telescope" or opts.picker == "ui_select") then
return opts
Expand Down Expand Up @@ -31,22 +75,7 @@ local function apidocs_open(opts)
local docs_path = common.data_folder()
local fs = vim.uv.fs_scandir(docs_path)
local candidates = {}
local installed_docs = {}
while true do
local name, type = vim.uv.fs_scandir_next(fs)
if not name then
break
end
if type == "directory" then
if opts and opts.restrict_sources then
if vim.tbl_contains(opts.restrict_sources, name) then
table.insert(installed_docs, name)
end
else
table.insert(installed_docs, name)
end
end
end
local installed_docs = get_installed_docs(fs, opts)

if opts and opts.ensure_installed then
for _, source in ipairs(opts.ensure_installed) do
Expand Down Expand Up @@ -129,6 +158,7 @@ end

local function setup(conf)
set_config(conf)
ensure_installed(conf)
vim.api.nvim_create_user_command("ApidocsInstall", install.apidocs_install, {})
vim.api.nvim_create_user_command("ApidocsOpen", apidocs_open, {})
vim.api.nvim_create_user_command("ApidocsSearch", apidocs_search, {})
Expand Down
13 changes: 10 additions & 3 deletions lua/apidocs/snacks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ local function get_data_dirs(opts)
return { data_dir }
end
local dirs = {}
local install_dirs = vim.fn.readdir(data_dir)
for _, source in ipairs(opts.restrict_sources) do
local dir = data_dir .. source .. "/"
if vim.fn.isdirectory(dir) == 1 then
table.insert(dirs, dir)
for _, entry in ipairs(install_dirs) do
if vim.fn.isdirectory(data_dir .. entry) == 1 then
if entry == source then
table.insert(dirs, data_dir .. entry .. "/")
elseif entry:match("^" .. source) then
-- no exact match found, check for a partial match
table.insert(dirs, data_dir .. entry .. "/")
end
end
end
end
return dirs
Expand Down
139 changes: 76 additions & 63 deletions lua/apidocs/telescope.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ local common = require("apidocs.common")
local install = require("apidocs.install")

local function telescope_attach_mappings(prompt_bufnr, map)
local actions = require('telescope.actions')
map('i', '<cr>', function(nr)
local actions = require("telescope.actions")
map("i", "<cr>", function(nr)
actions.close(prompt_bufnr)
local entry = require("telescope.actions.state").get_selected_entry(prompt_bufnr)
common.open_doc_in_new_window(entry.filename or entry.value)
if entry.lnum then
vim.cmd(":" .. entry.lnum)
vim.cmd("norm! zz")
end
end, {buffer = true})
end, { buffer = true })
return true
end

local function apidocs_open(params, slugs_to_mtimes, candidates)
local docs_path = common.data_folder()
local pickers = require "telescope.pickers"
local finders = require "telescope.finders"
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local previewers = require("telescope.previewers")
local conf = require("telescope.config").values

Expand All @@ -31,75 +31,88 @@ local function apidocs_open(params, slugs_to_mtimes, candidates)
}
end

pickers.new({}, {
prompt_title = "API docs",
finder = finders.new_table {
results = candidates,
entry_maker = entry_maker
},
previewer = previewers.new_buffer_previewer({
-- messy because of the conceal
setup = function(self)
vim.schedule(function()
local winid = self.state.winid
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "n"
local augroup = vim.api.nvim_create_augroup('TelescopeApiDocsResumeConceal', { clear = true })
vim.api.nvim_create_autocmd({"User"}, {
group = augroup,
pattern = "TelescopeResumePost",
callback = function()
local action_state = require("telescope.actions.state")
local current_picker = action_state.get_current_picker(vim.api.nvim_get_current_buf())
if current_picker.prompt_title == "API docs" or current_picker.prompt_title == "API docs search" then
local winid = current_picker.all_previewers[1].state.winid
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "n"
end
end
})
end)
return {}
end,
define_preview = function(self, entry)
common.load_doc_in_buffer(self.state.bufnr, entry.value)
end,
}),
sorter = conf.generic_sorter({}),
attach_mappings = telescope_attach_mappings,
}):find()
pickers
.new({}, {
prompt_title = "API docs",
finder = finders.new_table({
results = candidates,
entry_maker = entry_maker,
}),
previewer = previewers.new_buffer_previewer({
-- messy because of the conceal
setup = function(self)
vim.schedule(function()
local winid = self.state.winid
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "n"
local augroup = vim.api.nvim_create_augroup("TelescopeApiDocsResumeConceal", { clear = true })
vim.api.nvim_create_autocmd({ "User" }, {
group = augroup,
pattern = "TelescopeResumePost",
callback = function()
local action_state = require("telescope.actions.state")
local current_picker = action_state.get_current_picker(vim.api.nvim_get_current_buf())
if current_picker.prompt_title == "API docs" or current_picker.prompt_title == "API docs search" then
local winid = current_picker.all_previewers[1].state.winid
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "n"
end
end,
})
end)
return {}
end,
define_preview = function(self, entry)
common.load_doc_in_buffer(self.state.bufnr, entry.value)
end,
}),
sorter = conf.generic_sorter({}),
attach_mappings = telescope_attach_mappings,
})
:find()
end

local function apidocs_search(opts)
local previewers = require("telescope.previewers")
local make_entry = require "telescope.make_entry"
local make_entry = require("telescope.make_entry")
local folder = common.data_folder()
if opts and opts.source then
folder = folder .. opts.source .. "/"
end
local search_dirs = {folder}
local search_dirs = {}
if opts and opts.restrict_sources then
search_dirs = vim.tbl_map(function(d) return folder .. d end, opts.restrict_sources)
local install_dirs = vim.fn.readdir(folder)
for _, source in ipairs(opts.restrict_sources) do
for _, entry in ipairs(install_dirs) do
if vim.fn.isdirectory(folder .. entry) == 1 then
if entry == source then
table.insert(search_dirs, folder .. entry .. "/")
elseif entry:match("^" .. source) then
-- no exact match found, check for a partial match
table.insert(search_dirs, folder .. entry .. "/")
end
end
end
end
end


local default_entry_maker = make_entry.gen_from_vimgrep()
local function entry_maker(entry)
local r = default_entry_maker(entry)
r.display = function(entry)
local entry_components = vim.split(entry.filename:sub(#folder+1), "#")
local source_length = entry_components[1]:find("/")
local hl_group = {
{ {0, source_length}, "TelescopeResultsTitle"},
{ {source_length, #entry_components[1]}, "TelescopeResultsMethod" },
{ {#entry_components[1], #entry_components[1] + #(tostring(entry.lnum))+2}, "TelescopeResultsLineNr" },
}
return string.format("%s:%d: %s", entry_components[1], entry.lnum, entry.text), hl_group
end
r.display = function(entry)
local entry_components = vim.split(entry.filename:sub(#folder + 1), "#")
local source_length = entry_components[1]:find("/")
local hl_group = {
{ { 0, source_length }, "TelescopeResultsTitle" },
{ { source_length, #entry_components[1] }, "TelescopeResultsMethod" },
{ { #entry_components[1], #entry_components[1] + #(tostring(entry.lnum)) + 2 }, "TelescopeResultsLineNr" },
}
return string.format("%s:%d: %s", entry_components[1], entry.lnum, entry.text), hl_group
end
return r
end

require('telescope.builtin').live_grep({
require("telescope.builtin").live_grep({
cwd = folder,
search_dirs = search_dirs,
prompt_title = "API docs search",
Expand All @@ -111,8 +124,8 @@ local function apidocs_search(opts)
local winid = self.state.winid
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "n"
local augroup = vim.api.nvim_create_augroup('TelescopeApiDocsResumeConceal', { clear = true })
vim.api.nvim_create_autocmd({"User"}, {
local augroup = vim.api.nvim_create_augroup("TelescopeApiDocsResumeConceal", { clear = true })
vim.api.nvim_create_autocmd({ "User" }, {
group = augroup,
pattern = "TelescopeResumePost",
callback = function()
Expand All @@ -123,18 +136,18 @@ local function apidocs_search(opts)
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "n"
end
end
end,
})
end)
return {}
end,
define_preview = function(self, entry)
common.load_doc_in_buffer(self.state.bufnr, entry.filename)

local ns = vim.api.nvim_create_namespace('my_highlights')
vim.api.nvim_buf_set_extmark(self.state.bufnr, ns, entry.lnum-1, 0, {
local ns = vim.api.nvim_create_namespace("my_highlights")
vim.api.nvim_buf_set_extmark(self.state.bufnr, ns, entry.lnum - 1, 0, {
end_line = entry.lnum,
hl_group = 'TelescopePreviewMatch',
hl_group = "TelescopePreviewMatch",
strict = false,
})
vim.schedule(function()
Expand Down