diff --git a/lua/telescope/builtin/internal.lua b/lua/telescope/builtin/internal.lua index 7329a50..ca3b86f 100644 --- a/lua/telescope/builtin/internal.lua +++ b/lua/telescope/builtin/internal.lua @@ -321,22 +321,55 @@ internal.vim_options = function(opts) end internal.help_tags = function(opts) + local all_tag_files = {} + local all_help_files = {} + for _, v in ipairs(vim.split(vim.fn.globpath(vim.o.runtimepath, 'doc/*', 1), '\n')) do + local split_path = vim.split(v, path.separator, true) + local filename = split_path[#split_path] + if filename == 'tags' then + table.insert(all_tag_files, v) + else + all_help_files[filename] = v + end + end + + local delim = string.char(9) local tags = {} - for _, file in pairs(vim.fn.findfile('doc/tags', vim.o.runtimepath, -1)) do - local f = assert(io.open(file, "rb")) - for line in f:lines() do - table.insert(tags, line) + for _, file in ipairs(all_tag_files) do + local data = vim.split(path.read_file(file), '\n') + for _, line in ipairs(data) do + if line ~= '' then + local matches = {} + + for match in (line..delim):gmatch("(.-)" .. delim) do + table.insert(matches, match) + end + + if table.getn(matches) ~= 0 then + table.insert(tags, { + name = matches[1], + filename = all_help_files[matches[2]], + cmd = matches[3] + }) + end end - f:close() + end end pickers.new(opts, { prompt_title = 'Help', finder = finders.new_table { results = tags, - entry_maker = make_entry.gen_from_taglist(opts), + entry_maker = function(entry) + return { + value = entry.name, + display = entry.name, + ordinal = entry.name, + filename = entry.filename, + cmd = entry.cmd + } + end, }, - -- TODO: previewer for Vim help previewer = previewers.help.new(opts), sorter = conf.generic_sorter(opts), attach_mappings = function(prompt_bufnr) @@ -616,7 +649,7 @@ internal.highlights = function(opts) end) return true end, - previewer = previewers.display_content.new(opts), + previewer = previewers.highlights.new(opts), }):find() end diff --git a/lua/telescope/make_entry.lua b/lua/telescope/make_entry.lua index 04d5f3d..5d31632 100644 --- a/lua/telescope/make_entry.lua +++ b/lua/telescope/make_entry.lua @@ -391,21 +391,6 @@ function make_entry.gen_from_treesitter(opts) end end -function make_entry.gen_from_taglist(_) - local delim = string.char(9) - - return function(line) - local entry = {} - local tag = (line..delim):match("(.-)" .. delim) - entry.valid = tag ~= "" - entry.display = tag - entry.value = tag - entry.ordinal = tag - - return entry - end -end - function make_entry.gen_from_packages(opts) opts = opts or {} @@ -492,23 +477,11 @@ function make_entry.gen_from_highlights() return display, { { { 0, #display }, display } } end - local preview_command = function(entry, bufnr) - local hl = entry.value - vim.api.nvim_buf_set_option(bufnr, 'filetype', 'vim') - local output = vim.split(vim.fn.execute('hi ' .. hl), '\n') - local start = string.find(output[2], 'xxx', 1, true) - vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, output) - vim.api.nvim_buf_add_highlight(bufnr, -1, hl, 1, start - 1, start + 2) - end - return function(entry) return { value = entry, display = make_display, ordinal = entry, - - preview_command = preview_command - } end end diff --git a/lua/telescope/path.lua b/lua/telescope/path.lua index 1630ae7..972974e 100644 --- a/lua/telescope/path.lua +++ b/lua/telescope/path.lua @@ -60,6 +60,7 @@ path.read_file = function(filepath) local fd = vim.loop.fs_open(filepath, "r", 438) if fd == nil then return '' end local stat = assert(vim.loop.fs_fstat(fd)) + if stat.type ~= 'file' then return '' end local data = assert(vim.loop.fs_read(fd, stat.size, 0)) assert(vim.loop.fs_close(fd)) return data @@ -70,6 +71,7 @@ path.read_file_async = function(filepath, callback) assert(not err_open, err_open) vim.loop.fs_fstat(fd, function(err_fstat, stat) assert(not err_fstat, err_fstat) + if stat.type ~= 'file' then return callback('') end vim.loop.fs_read(fd, stat.size, 0, function(err_read, data) assert(not err_read, err_read) vim.loop.fs_close(fd, function(err_close) diff --git a/lua/telescope/pickers/entry_display.lua b/lua/telescope/pickers/entry_display.lua index a6bf8f9..4edd0ae 100644 --- a/lua/telescope/pickers/entry_display.lua +++ b/lua/telescope/pickers/entry_display.lua @@ -1,6 +1,7 @@ local entry_display = {} local function truncate(str, len) + str = tostring(str) -- We need to make sure its an actually a string and not a number -- TODO: This doesn't handle multi byte chars... if vim.fn.strdisplaywidth(str) > len then str = str:sub(1, len - 1) diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua index 2ac33c1..eb55c43 100644 --- a/lua/telescope/previewers.lua +++ b/lua/telescope/previewers.lua @@ -303,6 +303,7 @@ previewers.new_buffer_previewer = function(opts) vim.api.nvim_win_set_option(status.preview_win, 'signcolumn', 'no') vim.api.nvim_win_set_option(status.preview_win, 'foldlevel', 100) vim.api.nvim_win_set_option(status.preview_win, 'scrolloff', 999) + vim.api.nvim_win_set_option(status.preview_win, 'wrap', false) self.state.winid = status.preview_win self.state.bufname = nil @@ -525,7 +526,7 @@ end, {}) previewers.vim_buffer_cat = defaulter(function(_) return previewers.new_buffer_previewer { - get_buffer_by_name = function(self, entry) + get_buffer_by_name = function(_, entry) return from_entry.path(entry, true) end, @@ -548,12 +549,12 @@ previewers.vim_buffer_vimgrep = defaulter(function(_) end, teardown = function(self) - if self.state and self.state.hl_id then + if self.state and self.state.last_set_bufnr and vim.api.nvim_buf_is_valid(self.state.last_set_bufnr) then vim.api.nvim_buf_clear_namespace(self.state.last_set_bufnr, previewer_ns, 0, -1) end end, - get_buffer_by_name = function(self, entry) + get_buffer_by_name = function(_, entry) return from_entry.path(entry, true) end, @@ -569,7 +570,7 @@ previewers.vim_buffer_vimgrep = defaulter(function(_) if self.state.last_set_bufnr then pcall(vim.api.nvim_buf_clear_namespace, self.state.last_set_bufnr, previewer_ns, 0, -1) end - pcall(vim.api.nvim_buf_add_highlight, self.state.bufnr, previewer_ns, "Search", lnum - 1, 0, -1) + pcall(vim.api.nvim_buf_add_highlight, self.state.bufnr, previewer_ns, "TelescopePreviewLine", lnum - 1, 0, -1) pcall(vim.api.nvim_win_set_cursor, status.preview_win, {lnum, 0}) end @@ -590,7 +591,7 @@ previewers.ctags = defaulter(function(_) end end, - get_buffer_by_name = function(self, entry) + get_buffer_by_name = function(_, entry) return entry.filename end, @@ -607,7 +608,7 @@ previewers.ctags = defaulter(function(_) vim.cmd "norm! gg" vim.fn.search(scode) - self.state.hl_id = vim.fn.matchadd('Search', scode) + self.state.hl_id = vim.fn.matchadd('TelescopePreviewLine', scode) end) end } @@ -626,7 +627,7 @@ previewers.builtin = defaulter(function(_) end end, - get_buffer_by_name = function(self, entry) + get_buffer_by_name = function(_, entry) return entry.filename end, @@ -646,7 +647,7 @@ previewers.builtin = defaulter(function(_) vim.cmd "norm! gg" vim.fn.search(text) - self.state.hl_id = vim.fn.matchadd('Search', text) + self.state.hl_id = vim.fn.matchadd('TelescopePreviewLine', text) end) end } @@ -693,62 +694,24 @@ previewers.help = defaulter(function(_) end end, + get_buffer_by_name = function(_, entry) + return entry.filename + end, + define_preview = function(self, entry, status) with_preview_window(status, nil, function() - local special_chars = ":~^.?/%[%]%*" - local delim = string.char(9) + local query = entry.cmd + query = query:sub(2) + query = [[\V]] .. query - local escaped = vim.fn.escape(entry.value, special_chars) - local tags = {} - - local find_rtp_file = function(p, count) - return vim.fn.findfile(p, vim.o.runtimepath, count) - end - - for _,file in pairs(find_rtp_file('doc/tags', -1)) do - local f = assert(io.open(file, "rb")) - for line in f:lines() do - local matches = {} - - for match in (line..delim):gmatch("(.-)" .. delim) do - table.insert(matches, match) - end - - table.insert(tags, { - name = matches[1], - filename = matches[2], - cmd = matches[3] - }) - end - f:close() - end - - local search_tags = function(pattern) - local results = {} - for _, tag in pairs(tags) do - if vim.fn.match(tag.name, pattern) ~= -1 then - table.insert(results, tag) - end - end - return results - end - - local taglist = search_tags('^' .. escaped .. '$') - if taglist == {} then taglist = search_tags(escaped) end - - local best_entry = taglist[1] - file_maker_sync(find_rtp_file('doc/' .. best_entry.filename), self.state.bufnr, self.state.bufname) - -- We do no longer need to set the filetype. file_maker_ can do this now - - local search_query = best_entry.cmd - search_query = search_query:sub(2) - search_query = [[\V]] .. search_query + file_maker_sync(entry.filename, self.state.bufnr, self.state.bufname) + vim.cmd(':ownsyntax help') pcall(vim.fn.matchdelete, self.state.hl_id, self.state.winid) vim.cmd "norm! gg" - vim.fn.search(search_query, "W") + vim.fn.search(query, "W") - self.state.hl_id = vim.fn.matchadd('Search', search_query) + self.state.hl_id = vim.fn.matchadd('TelescopePreviewLine', query) end) end } @@ -784,38 +747,109 @@ end) previewers.autocommands = defaulter(function(_) return previewers.new_buffer_previewer { teardown = function(self) - if self.state and self.state.hl_id then - pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win) - self.state.hl_id = nil + if self.state and self.state.last_set_bufnr and vim.api.nvim_buf_is_valid(self.state.last_set_bufnr) then + pcall(vim.api.nvim_buf_clear_namespace, self.state.last_set_bufnr, previewer_ns, 0, -1) end end, + get_buffer_by_name = function(_, entry) + return entry.group + end, + define_preview = function(self, entry, status) local results = vim.tbl_filter(function (x) return x.group == entry.group end, status.picker.finder.results) - local display = {} - table.insert(display, string.format(" augroup: %s - [ %d entries ]", entry.group, #results)) - -- TODO: calculate banner width/string in setup() - -- TODO: get column characters to be the same HL group as border - table.insert(display, string.rep("─", vim.fn.getwininfo(status.preview_win)[1].width)) - - local selected_row - for idx, item in ipairs(results) do - if item == entry then - selected_row = idx - end - table.insert(display, - string.format(" %-14sā–%-08s %s", item.event, item.ft_pattern, item.command) - ) + if self.state.last_set_bufnr then + pcall(vim.api.nvim_buf_clear_namespace, self.state.last_set_bufnr, previewer_ns, 0, -1) end - -- TODO: set filetype in setup() - vim.api.nvim_buf_set_option(self.state.bufnr, "filetype", "vim") - vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, display) - vim.api.nvim_buf_add_highlight(self.state.bufnr, 0, "TelescopeBorder", 1, 0, -1) - vim.api.nvim_buf_add_highlight(self.state.bufnr, 0, "TelescopeSelection", selected_row + 1, 0, -1) + local selected_row = 0 + if self.state.bufname ~= entry.group then + local display = {} + table.insert(display, string.format(" augroup: %s - [ %d entries ]", entry.group, #results)) + -- TODO: calculate banner width/string in setup() + -- TODO: get column characters to be the same HL group as border + table.insert(display, string.rep("─", vim.fn.getwininfo(status.preview_win)[1].width)) + + for idx, item in ipairs(results) do + if item == entry then + selected_row = idx + end + table.insert(display, + string.format(" %-14sā–%-08s %s", item.event, item.ft_pattern, item.command) + ) + end + + vim.api.nvim_buf_set_option(self.state.bufnr, "filetype", "vim") + vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, display) + vim.api.nvim_buf_add_highlight(self.state.bufnr, 0, "TelescopeBorder", 1, 0, -1) + else + for idx, item in ipairs(results) do + if item == entry then + selected_row = idx + break + end + end + end + + vim.api.nvim_buf_add_highlight(self.state.bufnr, previewer_ns, "TelescopePreviewLine", selected_row + 1, 0, -1) + vim.api.nvim_win_set_cursor(status.preview_win, {selected_row + 1, 0}) + + self.state.last_set_bufnr = self.state.bufnr + end, + } +end, {}) + +previewers.highlights = defaulter(function(_) + return previewers.new_buffer_previewer { + teardown = function(self) + if self.state and self.state.last_set_bufnr and vim.api.nvim_buf_is_valid(self.state.last_set_bufnr) then + vim.api.nvim_buf_clear_namespace(self.state.last_set_bufnr, previewer_ns, 0, -1) + end + end, + + get_buffer_by_name = function(_, entry) + return "highlights" + end, + + define_preview = function(self, entry, status) + with_preview_window(status, nil, function() + if not self.state.bufname then + local output = vim.split(vim.fn.execute('highlight'), '\n') + local hl_groups = {} + for _, v in ipairs(output) do + if v ~= '' then + if v:sub(1, 1) == ' ' then + local part_of_old = v:match('%s+(.*)') + hl_groups[table.getn(hl_groups)] = hl_groups[table.getn(hl_groups)] .. part_of_old + else + table.insert(hl_groups, v) + end + end + end + + vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, hl_groups) + for k, v in ipairs(hl_groups) do + local startPos = string.find(v, 'xxx', 1, true) - 1 + local endPos = startPos + 3 + local hlgroup = string.match(v, '([^ ]*)%s+.*') + pcall(vim.api.nvim_buf_add_highlight, self.state.bufnr, 0, hlgroup, k - 1, startPos, endPos) + end + end + + pcall(vim.api.nvim_buf_clear_namespace, self.state.bufnr, previewer_ns, 0, -1) + vim.cmd "norm! gg" + vim.fn.search(entry.value .. ' ') + local lnum = vim.fn.line('.') + vim.api.nvim_buf_add_highlight(self.state.bufnr, + previewer_ns, + "TelescopePreviewLine", + lnum - 1, + 0, + #entry.value) + end) end, } end, {}) diff --git a/plugin/telescope.vim b/plugin/telescope.vim index 4bf165d..b9d99ee 100644 --- a/plugin/telescope.vim +++ b/plugin/telescope.vim @@ -1,4 +1,3 @@ - " Sets the highlight for selected items within the picker. highlight default link TelescopeSelection Visual highlight default link TelescopeSelectionCaret TelescopeSelection @@ -21,13 +20,16 @@ highlight default link TelescopeMatching Special " Used for the prompt prefix highlight default link TelescopePromptPrefix Identifier +" Used for highlighting the matched line inside Previewer. Works only for (vim_buffer_ previewer) +highlight default link TelescopePreviewLine Search + " This is like "" in your terminal. " To use it, do `cmap (TelescopeFuzzyCommandSearch) cnoremap (TelescopeFuzzyCommandSearch) e \ "lua require('telescope.builtin').command_history { \ default_text = [=[" . escape(getcmdline(), '"') . "]=] \ }" - + " Telescope builtin lists function! s:telescope_complete(...) return join(luaeval('vim.tbl_keys(require("telescope.builtin"))'), "\n") @@ -54,5 +56,5 @@ function! s:load_command(builtin,...) abort call telescope[a:builtin](opts) endfunction -" Telescope Commands with complete +" Telescope Commands with complete command! -nargs=+ -complete=custom,s:telescope_complete Telescope call s:load_command()