From 874139ee0b14fedfadca396884f166fc6eb34d4a Mon Sep 17 00:00:00 2001 From: Simon Hauser Date: Sun, 22 Nov 2020 10:57:31 +0100 Subject: [PATCH] Various previewer fixes (#260) - Set env vars for previewer with set_env({ key = value } fix #228) - Set pager for git previewes (default is GIT_PAGER=less so users can scroll see #253) - Use less for people who don't have bat but less installed - Reset less env to only '-RS' because '-X' will break scrolling(fix #253, thanks @eth3lbert) - Scrolling for buffer previewer(thanks @tami5 for helping) - Also new function to create buffer previewers (which has scrolling by default). Used for tags and help_tags previewer. - Add new setting set_env to readme --- README.md | 60 +++++++++--------- lua/telescope/config.lua | 4 +- lua/telescope/previewers.lua | 118 ++++++++++++++++++++++++++++------- 3 files changed, 129 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index eb0fb46dee..bfeb398340 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ with advanced features. It is written in `lua` and is built on top of latest awesome features from `neovim` core. `Telescope.nvim` is centered around modularity so much so that each picker is its own world, (meaning it can be configured in isolation from other pickers, such presentation, algorithm, -mappings ... etc). +mappings ... etc). `Telescope.nvim` was built with the intention of becoming a library, but it has long grown to be much bigger than that. In addition to @@ -23,7 +23,7 @@ growing number of community driven [built-in pickers](#built-in-pickers), covering a wide range of use cases and tools, and offers a customizable user interface. - + @@ -44,7 +44,7 @@ This section should guide to run your first built-in pickers :smile: [Neovim Nightly (0.5)](https://github.com/neovim/neovim/releases/tag/nightly) is required for `telescope.nvim` to work. -#### Optional dependences +#### Optional dependences - [sharkdp/bat](https://github.com/sharkdp/bat) (preview) - [sharkdp/fd](https://github.com/sharkdp/fd) (finder) - [BurntSushi/ripgrep](https://github.com/BurntSushi/ripgrep) (finder) @@ -72,7 +72,7 @@ call dein#add('nvim-telescope/telescope.nvim') ``` Using [packer.nvim](https://github.com/wbthomason/packer.nvim) -```lua +```lua use { 'nvim-telescope/telescope.nvim', requires = {{'nvim-lua/popup.nvim'}, {'nvim-lua/plenary.nvim'}} @@ -108,7 +108,7 @@ This section should help you explore available options to configure and customize your `telescope.nvim`. Unlike most vim plugins, `telescope.nvim` can be customized either by applying -customizations globally or individual pre picker. +customizations globally or individual pre picker. - **Global Customization** affecting all pickers can be done through the main `setup()` method (see defaults below) @@ -125,12 +125,12 @@ As an example of using the `setup()` method, the following code configures require('telescope').setup{ defaults = { vimgrep_arguments = { - 'rg', - '--color=never', - '--no-heading', - '--with-filename', - '--line-number', - '--column', + 'rg', + '--color=never', + '--no-heading', + '--with-filename', + '--line-number', + '--column', '--smart-case' }, prompt_position = "bottom", @@ -154,6 +154,7 @@ require('telescope').setup{ borderchars = { '─', '│', '─', '│', '╭', '╮', '╯', '╰'}, color_devicons = true, use_less = true, + set_env = { ['COLORTERM'] = 'truecolor' }, -- default { }, currently unsupported for shells like cmd.exe / powershell.exe } } ``` @@ -186,9 +187,10 @@ EOF | `preview_cutoff` | TODO | NUM | | `results_height` | TODO | NUM | | `results_width` | TODO | NUM | -| `borderchars` | The border chars, it gives border telescope window | dict | +| `borderchars` | The border chars, it gives border telescope window | dict | | `color_devicons` | Whether to color devicons or not | boolean | -| `use_less` | Whether to use less of cat/bat | boolean | +| `use_less` | Whether to use less with bat or less/cat if bat not installed | boolean | +| `set_env` | Set environment variables for previewer | dict | | `scroll_strategy` | How to behave when the when there are no more item next/prev | cycle, nil | #### Options affecting Sorting @@ -198,8 +200,8 @@ EOF | `file_sorter` | The sorter for file lists. | [Sorters](#built-in-sorters) | | `generic_sorter` | The sorter for everything else. | [Sorters](#built-in-sorters) | | `vimgrep_arguments` | The command line argument for grep search ... TODO. | dict | -| `selection_strategy` | What happens to the selection if the list changes. | follow/reset/row | -| `file_ignore_patterns` | Pattern to be ignored `{ "scratch/.*", "%.env"}` | dict | +| `selection_strategy` | What happens to the selection if the list changes. | follow/reset/row | +| `file_ignore_patterns` | Pattern to be ignored `{ "scratch/.*", "%.env"}` | dict | | `shorten_path` | Whether to shorten paths or not. | boolean | #### Mappings @@ -222,7 +224,7 @@ Many familiar mapping patterns are setup as defaults. | `` | close telescope (in normal mode) | To see the full list of mappings, check out `lua/telescope/mappings.lua` and -the `default_mappings` table. +the `default_mappings` table. Much like [built-in pickers](#built-in-pickers), there are a number of @@ -273,7 +275,7 @@ require('telescope').setup{ For a [picker](#built-in-pickers) specific remapping, it can be done by setting its `attach_mappings` key to a function, like this -```lua +```lua local actions = require('telescope.actions') -- Picker specific remapping ------------------------------ @@ -382,7 +384,7 @@ Built-in function ready to be bound to any key you like :smile:. | .................................. | Your next awesome finder function here :D | -#### Built-in Sorters +#### Built-in Sorters | Sorters | Description | |------------------------------------|-----------------------------------------------------------------| @@ -406,7 +408,7 @@ return a number, which is equivalent to the "distance" between the current ## Built-in Themes Common groups of settings can be set up to allow for themes. -We have some built in themes but are looking for more cool options. +We have some built in themes but are looking for more cool options. | Themes | Description | |--------------------------|-----------------------------------------------------------------------| @@ -425,7 +427,7 @@ Themes should work with every `telescope.builtin` function. If you wish to make theme, check out `lua/telescope/themes.lua`. If you need more features, make an issue :). -## API +## API #### Finders @@ -441,9 +443,9 @@ Finder:new{ ``` #### Picker - + -This section is an overview of how custom pickers can be created any configured. +This section is an overview of how custom pickers can be created any configured. ```lua @@ -508,19 +510,19 @@ All `telescope.nvim` functions are wrapped in `vim` commands for easy access, it supports tab completions and settings options. ```viml -" Tab completion -:Telescope | +" Tab completion +:Telescope | :Telescope find_files " Setting options -:Telescope find_files prompt_prefix=🔍 +:Telescope find_files prompt_prefix=🔍 " If option is table type in lua code ,you can use `,` connect each command string eg: " find_command,vimgrep_arguments they are both table type. so config it in commandline like :Telecope find_files find_command=rg,--ignore,--hidden,--files prompt_prefix=🔍 ``` -## Media +## Media - [What is Telescope? (Video)](https://www.twitch.tv/teej_dv/clip/RichDistinctPlumberPastaThat) - [More advanced configuration (Video)](https://www.twitch.tv/videos/756229115) @@ -533,11 +535,11 @@ supports tab completions and settings options. All options available from the setup function (see [Configuration options]()) and some other functions can be easily changed in custom pickers or built-in -functions. +functions. -```lua --- Disable preview for find files +```lua +-- Disable preview for find files nnoremap ff :lua require('telescope.builtin').find_files({previewer = false}) -- Change change prompt prefix for find_files builtin function: diff --git a/lua/telescope/config.lua b/lua/telescope/config.lua index 5e3212aa2e..1d795c64e6 100644 --- a/lua/telescope/config.lua +++ b/lua/telescope/config.lua @@ -62,10 +62,12 @@ function config.set_defaults(defaults) set("use_less", true) set("color_devicons", true) + set("set_env", {}) + -- TODO: Add motions to keybindings -- To disable a keymap, put [map] = false - -- So, to not map "", just put + -- So, to not map "", just put -- -- ..., -- [""] = false, diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua index 98980790ea..01d87936df 100644 --- a/lua/telescope/previewers.lua +++ b/lua/telescope/previewers.lua @@ -20,6 +20,19 @@ Previewer.__index = Previewer -- TODO: Should play with these some more, ty @clason local bat_options = {"--style=plain", "--color=always", "--paging=always"} local has_less = (vim.fn.executable('less') == 1) and config.values.use_less +local termopen_env = vim.tbl_extend("force", { ['GIT_PAGER'] = (has_less and 'less' or ''), LESS = '-RS' }, config.values.set_env) + +-- TODO(conni2461): Workaround for neovim/neovim#11751. Add only quotes when using else branch. +local valuate_shell = function() + local shell = vim.o.shell + if string.find(shell, 'powershell.exe') or string.find(shell, 'cmd.exe') then + return '' + else + return "'" + end +end + +local add_quotes = valuate_shell() local get_file_stat = function(filename) return vim.loop.fs_stat(vim.fn.expand(filename)) or {} @@ -39,9 +52,9 @@ local bat_maker = function(filename, lnum, start, finish) if has_less then if start then - table.insert(command, {"--pager", string.format("less -RS +%s", start)}) + table.insert(command, {"--pager", string.format("%sless +%s%s", add_quotes, start, add_quotes)}) else - table.insert(command, {"--pager", "less -RS"}) + table.insert(command, {"--pager", "less"}) end else if start and finish then @@ -54,14 +67,14 @@ local bat_maker = function(filename, lnum, start, finish) end return flatten { - command, bat_options, "--", vim.fn.expand(filename) + command, bat_options, "--", add_quotes .. vim.fn.expand(filename) .. add_quotes } end -- TODO: Add other options for cat to do this better -local cat_maker = function(filename, _, _, _) +local cat_maker = function(filename, _, start, _) if get_file_stat(filename).type == 'directory' then - return { 'ls', '-la', vim.fn.expand(filename) } + return { 'ls', '-la', add_quotes .. vim.fn.expand(filename) .. add_quotes } end if 1 == vim.fn.executable('file') then @@ -72,9 +85,17 @@ local cat_maker = function(filename, _, _, _) end end - return { - "cat", "--", vim.fn.expand(filename) - } + if has_less then + if start then + return { 'less', string.format('+%s', start), add_quotes .. vim.fn.expand(filename) .. add_quotes } + else + return { 'less', add_quotes .. vim.fn.expand(filename) .. add_quotes } + end + else + return { + "cat", "--", add_quotes .. vim.fn.expand(filename) .. add_quotes + } + end end local get_maker = function(opts) @@ -167,6 +188,41 @@ previewers.new = function(...) return Previewer:new(...) end +previewers.new_buffer_previewer = function(opts) + opts = opts or {} + + assert(opts.preview_fn, "preview_fn is required function") + + if not opts.scroll_fn then + function opts.scroll_fn(self, direction) + local input = direction > 0 and "d" or "u" + local count = math.abs(direction) + + self:send_input({ count = count, input = input }) + end + end + + if not opts.send_input then + function opts.send_input(self, input) + if not self.state then + return + end + + local bufnr = vim.api.nvim_win_get_buf(self.state.hl_win) + local max_line = vim.fn.getbufinfo(bufnr)[1].linecount + local line = vim.api.nvim_win_get_cursor(self.state.hl_win)[1] + if input.input == 'u' then + line = (line - input.count) > 0 and (line - input.count) or 1 + else + line = (line + input.count) <= max_line and (line + input.count) or max_line + end + vim.api.nvim_win_set_cursor(self.state.hl_win, { line, 1 }) + end + end + + return Previewer:new(opts) +end + previewers.new_termopen_previewer = function(opts) opts = opts or {} @@ -234,13 +290,25 @@ previewers.new_termopen_previewer = function(opts) local term_opts = { cwd = opts.cwd or vim.fn.getcwd(), + env = termopen_env } + -- TODO(conni2461): Workaround for neovim/neovim#11751. + local get_cmd = function(status) + local shell = vim.o.shell + if string.find(shell, 'powershell.exe') or string.find(shell, 'cmd.exe') then + return opts.get_command(entry, status) + else + local env = {} + for k, v in pairs(termopen_env) do + table.insert(env, k .. '=' .. v) + end + return table.concat(env, ' ') .. ' ' .. table.concat(opts.get_command(entry, status), ' ') + end + end + with_preview_window(status, bufnr, function() - set_term_id( - self, - vim.fn.termopen(opts.get_command(entry, status), term_opts) - ) + set_term_id(self, vim.fn.termopen(get_cmd(status), term_opts)) end) vim.api.nvim_buf_set_name(bufnr, tostring(bufnr)) @@ -274,7 +342,7 @@ previewers.new_termopen_previewer = function(opts) end previewers.vim_buffer = defaulter(function(_) - return previewers.new { + return previewers.new_buffer_previewer { setup = function() return { last_set_bufnr = nil @@ -333,6 +401,7 @@ previewers.vim_buffer = defaulter(function(_) -- print("LNUM:", entry.lnum) end + vim.api.nvim_win_set_option(status.preview_win, 'scrolloff', 999) log.info("Previewed bufnr", bufnr) end, } @@ -342,7 +411,7 @@ previewers.git_commit_diff = defaulter(function(_) return previewers.new_termopen_previewer { get_command = function(entry) local sha = entry.value - return { 'git', '--no-pager', 'diff', sha .. '^!' } + return { 'git', '-p', 'diff', sha .. '^!' } end } end, {}) @@ -350,8 +419,8 @@ end, {}) previewers.git_branch_log = defaulter(function(_) return previewers.new_termopen_previewer { get_command = function(entry) - return { 'git', 'log', '--graph', - '--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset', + return { 'git', '-p', 'log', '--graph', + "--pretty=format:" .. add_quotes .. "%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset" .. add_quotes, '--abbrev-commit', '--date=relative', entry.value } end } @@ -360,7 +429,7 @@ end, {}) previewers.git_file_diff = defaulter(function(_) return previewers.new_termopen_previewer { get_command = function(entry) - return { 'git', '--no-pager', 'diff', entry.value } + return { 'git', '-p', 'diff', entry.value } end } end, {}) @@ -400,8 +469,8 @@ previewers.vimgrep = defaulter(function(opts) } end, {}) -previewers.ctags = defaulter(function(opts) - return previewers.new { +previewers.ctags = defaulter(function(_) + return previewers.new_buffer_previewer { setup = function() return {} end, @@ -428,10 +497,10 @@ previewers.ctags = defaulter(function(opts) vim.api.nvim_win_set_option(status.preview_win, 'winhl', 'Normal:Normal') 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) pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win) vim.fn.search(scode) - vim.cmd "norm zz" self.state.hl_win = status.preview_win self.state.hl_id = vim.fn.matchadd('Search', scode) @@ -469,7 +538,7 @@ previewers.qflist = defaulter(function(opts) end, {}) previewers.help = defaulter(function(_) - return previewers.new { + return previewers.new_buffer_previewer { setup = function() return {} end, @@ -542,9 +611,12 @@ previewers.help = defaulter(function(_) log.trace([[lua vim.fn.search("]], search_query, [[")]]) + -- Clear previous search + pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win) vim.cmd "norm! gg" vim.fn.search(search_query, "W") - vim.cmd "norm zt" + + vim.api.nvim_win_set_option(status.preview_win, 'scrolloff', 999) self.state.hl_win = status.preview_win self.state.hl_id = vim.fn.matchadd('Search', search_query) @@ -681,7 +753,7 @@ previewers.man = defaulter(function(_) end) previewers.display_content = defaulter(function(_) - return previewers.new { + return previewers.new_buffer_previewer { preview_fn = function(self, entry, status) with_preview_window(status, nil, function() local bufnr = vim.fn.bufadd("Preview command")