1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 07:10:06 +08:00

feat(zettelkasten): improve zettelkasten layer

This commit is contained in:
Wang Shidong 2022-10-25 18:35:51 +08:00 committed by GitHub
parent 1c1d63d923
commit ac74bffee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 5053 additions and 6986 deletions

View File

@ -29,12 +29,17 @@ endfunction
function! SpaceVim#layers#zettelkasten#config() abort
let g:_spacevim_mappings_space.m.z = {'name' : '+zettelkasten'}
call SpaceVim#mapping#space#def('nnoremap', ['m', 'z', 'n'], 'ZkNew', 'create-new-zettel-note', 1)
call SpaceVim#mapping#space#def('nnoremap', ['m', 'z', 't'], 'Telescope zettelkasten_template', 'zettel-template', 1)
call SpaceVim#mapping#space#def('nnoremap', ['m', 'z', 'b'], 'ZkBrowse', 'open-zettelkasten-browse', 1)
endfunction
function! SpaceVim#layers#zettelkasten#set_variable(var) abort
let g:zettelkasten_directory = get(a:var,
\ 'zettel_dir',
\ '')
let g:zettelkasten_template_directory = get(a:var,
\ 'zettel_template_dir',
\ '')
endfunction
function! SpaceVim#layers#zettelkasten#get_options() abort

View File

@ -1 +1 @@
github: [tjdevries, Conni2461]
github: [tjdevries, Conni2461, fdschmidt93]

View File

@ -29,6 +29,12 @@ body:
placeholder: "macOS 11.5"
validations:
required: true
- type: input
attributes:
label: "Telescope version / branch / rev"
placeholder: "telescope 0.1.0"
validations:
required: true
- type: textarea
attributes:
label: "checkhealth telescope"

View File

@ -0,0 +1,33 @@
# Description
Please include a summary of the change and which issue is fixed. Please also
include relevant motivation and context
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- This change requires a documentation update
# How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list relevant details about your configuration
- [ ] Test A
- [ ] Test B
**Configuration**:
* Neovim version (nvim --version):
* Operating system and version:
# Checklist:
- [ ] My code follows the style guidelines of this project (stylua)
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation (lua annotations)

View File

@ -13,19 +13,19 @@ jobs:
- os: ubuntu-20.04
url: https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.tar.gz
manager: sudo apt-get
packages: -y fd-find
packages: -y ripgrep
- os: ubuntu-20.04
url: https://github.com/neovim/neovim/releases/download/v0.7.0/nvim-linux64.tar.gz
manager: sudo apt-get
packages: -y fd-find
packages: -y ripgrep
- os: macos-10.15
url: https://github.com/neovim/neovim/releases/download/nightly/nvim-macos.tar.gz
manager: brew
packages: fd
packages: ripgrep
- os: macos-10.15
url: https://github.com/neovim/neovim/releases/download/v0.7.0/nvim-macos.tar.gz
manager: brew
packages: fd
packages: ripgrep
steps:
- uses: actions/checkout@v2
- run: date +%F > todays-date

View File

@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: JohnnyMorganz/stylua-action@1.0.0
- uses: JohnnyMorganz/stylua-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
# CLI arguments

View File

@ -51,7 +51,7 @@ latest neovim nightly commit is required for `telescope.nvim` to work.
### Suggested dependencies
- [BurntSushi/ripgrep](https://github.com/BurntSushi/ripgrep) is required for
`live_grep` and `grep_string`
`live_grep` and `grep_string` and is the first priority for `find_files`.
We also suggest you install one native telescope sorter to significantly improve
sorting performance. Take a look at either
@ -71,24 +71,34 @@ wiki.
### Installation
It is suggested to either use the latest release
[tag](https://github.com/nvim-telescope/telescope.nvim/tags) or our release
branch (which will get consistent updates)
[0.1.x](https://github.com/nvim-telescope/telescope.nvim/tree/0.1.x).
It is not suggested to run latest master.
Using [vim-plug](https://github.com/junegunn/vim-plug)
```viml
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-telescope/telescope.nvim'
Plug 'nvim-telescope/telescope.nvim', { 'tag': '0.1.0' }
" or , { 'branch': '0.1.x' }
```
Using [dein](https://github.com/Shougo/dein.vim)
```viml
call dein#add('nvim-lua/plenary.nvim')
call dein#add('nvim-telescope/telescope.nvim')
call dein#add('nvim-telescope/telescope.nvim', { 'rev': '0.1.0' })
" or , { 'rev': '0.1.x' })
```
Using [packer.nvim](https://github.com/wbthomason/packer.nvim)
```lua
use {
'nvim-telescope/telescope.nvim',
'nvim-telescope/telescope.nvim', tag = '0.1.0',
-- or , branch = '0.1.x',
requires = { {'nvim-lua/plenary.nvim'} }
}
```
@ -96,7 +106,7 @@ use {
### checkhealth
Make sure you call `:checkhealth telescope` after installing telescope to ensure
everything is setup correctly.
everything is set up correctly.
After this setup you can continue reading here or switch to `:help telescope`
to get an understanding of how to use Telescope and how to configure it.
@ -106,6 +116,8 @@ to get an understanding of how to use Telescope and how to configure it.
Try the command `:Telescope find_files<cr>`
to see if `telescope.nvim` is installed correctly.
Using VimL:
```viml
" Find files using Telescope command-line sugar.
nnoremap <leader>ff <cmd>Telescope find_files<cr>
@ -120,6 +132,16 @@ nnoremap <leader>fb <cmd>lua require('telescope.builtin').buffers()<cr>
nnoremap <leader>fh <cmd>lua require('telescope.builtin').help_tags()<cr>
```
Using Lua:
```lua
local builtin = require('telescope.builtin')
vim.keymap.set('n', '<leader>ff', builtin.find_files, {})
vim.keymap.set('n', '<leader>fg', builtin.live_grep, {})
vim.keymap.set('n', '<leader>fb', builtin.buffers, {})
vim.keymap.set('n', '<leader>fh', builtin.help_tags, {})
```
See [builtin pickers](#pickers) for a list of all builtin functions.
## Customization
@ -192,7 +214,7 @@ EOF
## Default Mappings
Mappings are fully customizable.
Many familiar mapping patterns are setup as defaults.
Many familiar mapping patterns are set up as defaults.
| Mappings | Action |
|----------------|------------------------------------------------------|
@ -200,7 +222,7 @@ Many familiar mapping patterns are setup as defaults.
| `<C-p>/<Up>` | Previous item |
| `j/k` | Next/previous (in normal mode) |
| `H/M/L` | Select High/Middle/Low (in normal mode) |
| 'gg/G' | Select the first/last item (in normal mode) |
| `gg/G` | Select the first/last item (in normal mode) |
| `<CR>` | Confirm selection |
| `<C-x>` | Go to file selection as a split |
| `<C-v>` | Go to file selection as a vsplit |
@ -260,9 +282,9 @@ Built-in functions. Ready to be bound to any key you like.
| Functions | Description |
|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `builtin.find_files` | Lists files in your current working directory, respects .gitignore |
| `builtin.git_files` | Fuzzy search through the output of `git ls-files` command, respects .gitignore, optionally ignores untracked files |
| `builtin.git_files` | Fuzzy search through the output of `git ls-files` command, respects .gitignore |
| `builtin.grep_string` | Searches for the string under your cursor in your current working directory |
| `builtin.live_grep` | Search for a string in your current working directory and get results live as you type (respecting .gitignore) |
| `builtin.live_grep` | Search for a string in your current working directory and get results live as you type, respects .gitignore |
### Vim Pickers
@ -299,6 +321,8 @@ Built-in functions. Ready to be bound to any key you like.
| Functions | Description |
|---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `builtin.lsp_references` | Lists LSP references for word under the cursor |
| `builtin.lsp_incoming_calls` | Lists LSP incoming calls for word under the cursor |
| `builtin.lsp_outgoing_calls` | Lists LSP outgoing calls for word under the cursor |
| `builtin.lsp_document_symbols` | Lists LSP document symbols in the current buffer |
| `builtin.lsp_workspace_symbols` | Lists LSP document symbols in the current workspace |
| `builtin.lsp_dynamic_workspace_symbols` | Dynamically Lists LSP for all workspace symbols |

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
- [Oneshot job](#oneshot-job)
- [Previewer](#previewer)
- [More examples](#more-examples)
- [Bundling as Extension](#bundling-as-extension)
- [Technical](#technical)
- [picker](#picker)
- [finders](#finders)
@ -163,7 +164,7 @@ needs to return either `true` or `false`. If it returns false it means that only
the actions defined in the function should be attached. In this case it would
remove the default actions to move the selected item in the picker,
`move_selection_{next,previous}`. So in most cases you'll want to return `true`.
If the function does not return anything then an error is thrown.
If the function does not return anything then an error is thrown.
The `attach_mappings` function has two parameters, `prompt_bufnr` is the buffer number
of the prompt buffer, which we can use to get the pickers object and `map` is a function
@ -228,7 +229,7 @@ where `tbl` is the table returned by `entry_maker`. So in this example `tbl` wou
give our `display` function access to `value` and `ordinal`.
If our picker will have a lot of values it's suggested to use a function for `display`,
especially if you are modifying the text to display. This way the function will only be executed
especially if you are modifying the text to display. This way the function will only be executed
for the entries being displayed. For an example of an entry maker take a look at
`lua/telescope/make_entry.lua`.
@ -238,7 +239,7 @@ function `gen_from_git_commits` in `make_entry.lua`.
The `ordinal` is also required, which is used for sorting. As already mentioned
this allows us to have different display and sorting values. This allows `display`
to be more complex with icons and special indicators but `ordinal` could be a simpler
to be more complex with icons and special indicators but `ordinal` could be a simpler
sorting key.
There are other important keys which can be set, but do not make sense in the
@ -250,7 +251,7 @@ current context as we are not dealing with files:
### Previewer
We will not write a previewer for this picker because it isn't required for
We will not write a previewer for this picker because it isn't required for
basic colors and is a more advanced topic. It's already well documented in `:help
telescope.previewers` so you can read this section if you want to write your
own `previewer`. If you want a file previewer without columns you should
@ -263,7 +264,7 @@ find results and call `entry_maker` for each entry. An example usage would be
`find`.
```lua
finder = finders.new_oneshot_job { "find", opts },
finder = finders.new_oneshot_job({ "find" }, opts ),
```
### More examples
@ -278,6 +279,51 @@ more information on [gitter](https://gitter.im/nvim-telescope/community?utm_sour
and we will happily answer your questions and hopefully allow us to improve this guide. You can also
help us to improve this guide by sending a PR.
### Bundling as extension
If you now want to bundle your picker as extension, so it is available as
picker via the `:Telescope` command, the following has to be done.
Structure your plugin as follows, so it can be found by telescope:
```
.
└── lua
├── plugin_name # Your actual plugin code
│ ├── init.lua
│ └── some_file.lua
└── telescope
└── _extensions # The underscore is significant
└─ plugin_name.lua # Init and register your extension
```
The `lua/telescope/_extensions/plugin_name.lua` file needs to return the
following: (see `:help telescope.register_extension`)
```lua
return require("telescope").register_extension {
setup = function(ext_config, config)
-- access extension config and user config
end,
exports = {
stuff = require("plugin_name").stuff
},
}
```
The setup function can be used to access the extension config and setup
extension specific global configuration. You also have access to the user
telescope default config, so you can override specific internal function. For
example sorters if you have an extension that provides a replacement sorter,
like
[telescope-fzf-native](https://github.com/nvim-telescope/telescope-fzf-native.nvim).
The exports table declares the exported pickers that can then be accessed via
`Telescope plugin_name stuff`. If you only provide one export it is suggested
that you name the key like the plugin, so you can access it with `Telescope
plugin_name`.
## Technical
### Picker

File diff suppressed because it is too large Load Diff

View File

@ -195,5 +195,64 @@ https://github.com/stevearc/dressing.nvim which has support for multiple
different backends including telescope.
*telescope.changelog-1945*
Date: July 01, 2022
PR: https://github.com/nvim-telescope/telescope.nvim/pull/1945
This is our dev branch which contains a lot of PRs, a lot of fixes,
refactoring and general quality of life improvements. It also contains new
features, the most noteworthy are the following (mostly developed by the
community):
- feat: none strategy & control attachment (#1867)
- feat: force buffer delete for terminal and improvements for
Picker:delete_selection (#1943)
- feat(tags): process tagfiles on the fly (#1989)
- feat(builtin.lsp): implement builtin handlers for
lsp.(incoming|outgoing)_calls (#1484)
- feat: clear previewer if no item is selected (#2004)
- feat: add min max boundary to width, height resolver (#2002)
- feat: Add entry_index for entry_makers (#1850)
- feat: refine with new_table (#1115)
The last one is one of the most exciting new features, because it allows you
to go from live_grep into a fuzzy environment with the following mapping
`<C-Space>`. It's a general interface we now implemented for `live_grep` and
`lsp_dynamic_workspace_symbols` but it could also be easily implemented for
other builtins, by us or the user. It's now available for extension developers.
We will add documentation in the next couple of days and improve it by adding
more options to configure it after the initial 0.1 release.
But as with all longer development phases, there are also some breaking
changes. This is the main reason we moved development to a separate branch, for
the past two months. We can't promise that there won't be more breaking
changes, but it is the plan that this is the last set of breaking changes prior
to the 0.1 release on July, 12. We are deeply sorry for the inconvenience. The
following breaking changes are included in this PR:
- break(git_files): change `show_untracked` default to false. Can be changed
back with `:Telescope git_files show_untracked=true`
- break: deprecate `utils.get_default` `utils.if_nil`, will be removed prior
to 0.1, so if you use it in your config, please move to `vim.F.if_nil`
- break: drops `ignore_filename` option, use `path_display= { "hidden" }`
instead
- break: prefix internal interfaces with __ so
`require("telescope.builtin.files").find_files` will show a notify error but
still works for now. The error will be removed prior to 0.1! You should use
`require("telescope.builtin").find_files` because we wrap all the functions
that are exposed in this module.
- break: defaults.preview.treesitter rework that allows you to either enable a
list of languages, or enable all and disable some. Please read
`:help telescope.defaults.preview` for more information.
Something like this is now possible:
>
treesitter = {
enable = false,
-- or
enable = { "c" },
-- disable can be set if enable isn't set
disable = { "perl", "javascript" },
},
<
vim:tw=78:ts=8:ft=help:norl:

View File

@ -1,5 +1,5 @@
---@tag telescope.actions.generate
---@config { ["module"] = "telescope.actions.generate" }
---@config { ["module"] = "telescope.actions.generate", ["name"] = "ACTIONS_GENERATE" }
---@brief [[
--- Module for convenience to override defaults of corresponding |telescope.actions| at |telescope.setup()|.
@ -24,6 +24,10 @@
---@brief ]]
local actions = require "telescope.actions"
local config = require "telescope.config"
local action_state = require "telescope.actions.state"
local finders = require "telescope.finders"
local action_generate = {}
--- Display the keymaps of registered actions similar to which-key.nvim.<br>
@ -54,4 +58,60 @@ action_generate.which_key = function(opts)
end
end
action_generate.refine = function(prompt_bufnr, opts)
opts = opts or {}
opts.prompt_to_prefix = vim.F.if_nil(opts.prompt_to_prefix, false)
opts.prefix_hl_group = vim.F.if_nil(opts.prompt_hl_group, "TelescopePromptPrefix")
opts.prompt_prefix = vim.F.if_nil(opts.promt_prefix, config.values.prompt_prefix)
opts.reset_multi_selection = vim.F.if_nil(opts.reset_multi_selection, false)
opts.reset_prompt = vim.F.if_nil(opts.reset_prompt, true)
opts.sorter = vim.F.if_nil(opts.sorter, config.values.generic_sorter {})
local push_history = vim.F.if_nil(opts.push_history, true)
local current_picker = action_state.get_current_picker(prompt_bufnr)
local current_line = action_state.get_current_line()
if push_history then
action_state.get_current_history():append(current_line, current_picker)
end
-- title
if opts.prompt_title then
current_picker.prompt_border:change_title(opts.prompt_title)
end
if opts.results_title then
current_picker.results_border:change_title(opts.results_title)
end
local results = {}
for entry in current_picker.manager:iter() do
table.insert(results, entry)
end
-- if opts.sorter == false, keep older sorter
if opts.sorter then
current_picker.sorter:_destroy()
current_picker.sorter = opts.sorter
current_picker.sorter:_init()
end
local new_finder = finders.new_table {
results = results,
entry_maker = function(x)
return x
end,
}
if not opts.reset_multi_selection and current_line ~= "" then
opts.multi = current_picker._multi
end
if opts.prompt_to_prefix then
local current_prefix = current_picker.prompt_prefix
local suffix = current_prefix ~= opts.prompt_prefix and current_prefix or ""
opts.new_prefix = suffix .. current_line .. " " .. opts.prompt_prefix
end
current_picker:refresh(new_finder, opts)
end
return action_generate

View File

@ -54,7 +54,7 @@
local a = vim.api
local config = require "telescope.config"
local conf = require("telescope.config").values
local state = require "telescope.state"
local utils = require "telescope.utils"
local popup = require "plenary.popup"
@ -242,10 +242,9 @@ end
---@param prompt_bufnr number: The prompt bufnr
actions.select_default = {
pre = function(prompt_bufnr)
action_state.get_current_history():append(
action_state.get_current_line(),
action_state.get_current_picker(prompt_bufnr)
)
action_state
.get_current_history()
:append(action_state.get_current_line(), action_state.get_current_picker(prompt_bufnr))
end,
action = function(prompt_bufnr)
return action_set.select(prompt_bufnr, "default")
@ -259,10 +258,9 @@ actions.select_default = {
---@param prompt_bufnr number: The prompt bufnr
actions.select_horizontal = {
pre = function(prompt_bufnr)
action_state.get_current_history():append(
action_state.get_current_line(),
action_state.get_current_picker(prompt_bufnr)
)
action_state
.get_current_history()
:append(action_state.get_current_line(), action_state.get_current_picker(prompt_bufnr))
end,
action = function(prompt_bufnr)
return action_set.select(prompt_bufnr, "horizontal")
@ -276,10 +274,9 @@ actions.select_horizontal = {
---@param prompt_bufnr number: The prompt bufnr
actions.select_vertical = {
pre = function(prompt_bufnr)
action_state.get_current_history():append(
action_state.get_current_line(),
action_state.get_current_picker(prompt_bufnr)
)
action_state
.get_current_history()
:append(action_state.get_current_line(), action_state.get_current_picker(prompt_bufnr))
end,
action = function(prompt_bufnr)
return action_set.select(prompt_bufnr, "vertical")
@ -293,16 +290,47 @@ actions.select_vertical = {
---@param prompt_bufnr number: The prompt bufnr
actions.select_tab = {
pre = function(prompt_bufnr)
action_state.get_current_history():append(
action_state.get_current_line(),
action_state.get_current_picker(prompt_bufnr)
)
action_state
.get_current_history()
:append(action_state.get_current_line(), action_state.get_current_picker(prompt_bufnr))
end,
action = function(prompt_bufnr)
return action_set.select(prompt_bufnr, "tab")
end,
}
--- Perform 'drop' action on selection, usually something like<br>
---`:drop <selection>`
---
--- i.e. open the selection in a window
---@param prompt_bufnr number: The prompt bufnr
actions.select_drop = {
pre = function(prompt_bufnr)
action_state
.get_current_history()
:append(action_state.get_current_line(), action_state.get_current_picker(prompt_bufnr))
end,
action = function(prompt_bufnr)
return action_set.select(prompt_bufnr, "drop")
end,
}
--- Perform 'tab drop' action on selection, usually something like<br>
---`:tab drop <selection>`
---
--- i.e. open the selection in a new tab
---@param prompt_bufnr number: The prompt bufnr
actions.select_tab_drop = {
pre = function(prompt_bufnr)
action_state
.get_current_history()
:append(action_state.get_current_line(), action_state.get_current_picker(prompt_bufnr))
end,
action = function(prompt_bufnr)
return action_set.select(prompt_bufnr, "tab drop")
end,
}
-- TODO: consider adding float!
-- https://github.com/nvim-telescope/telescope.nvim/issues/365
@ -343,14 +371,17 @@ end
--- Close the Telescope window, usually used within an action
---@param prompt_bufnr number: The prompt bufnr
actions.close = function(prompt_bufnr)
action_state.get_current_history():reset()
local picker = action_state.get_current_picker(prompt_bufnr)
local original_win_id = picker.original_win_id
local cursor_valid, original_cursor = pcall(a.nvim_win_get_cursor, original_win_id)
actions.close_pum(prompt_bufnr)
require("telescope.pickers").on_close_prompt(prompt_bufnr)
pcall(a.nvim_set_current_win, original_win_id)
if cursor_valid and a.nvim_get_mode().mode == "i" and picker._original_mode ~= "i" then
pcall(a.nvim_win_set_cursor, original_win_id, { original_cursor[1], original_cursor[2] + 1 })
end
end
--- Close the Telescope window, usually used within an action<br>
@ -428,6 +459,8 @@ actions.edit_register = function(prompt_bufnr)
end
--- Paste the selected register into the buffer
---
--- Note: only meant to be used inside builtin.registers
---@param prompt_bufnr number: The prompt bufnr
actions.paste_register = function(prompt_bufnr)
local selection = action_state.get_selected_entry()
@ -559,6 +592,7 @@ actions.git_checkout = function(prompt_bufnr)
msg = string.format("Checked out: %s", selection.value),
level = "INFO",
})
vim.cmd "checktime"
else
utils.notify("actions.git_checkout", {
msg = string.format(
@ -601,7 +635,7 @@ actions.git_switch_branch = function(prompt_bufnr)
selection.value,
table.concat(stderr, " ")
),
level = "ERORR",
level = "ERROR",
})
end
end
@ -748,6 +782,7 @@ actions.git_checkout_current_buffer = function(prompt_bufnr)
end
actions.close(prompt_bufnr)
utils.get_os_command_output({ "git", "checkout", selection.value, "--", selection.file }, cwd)
vim.cmd "checktime"
end
--- Stage/unstage selected file
@ -1017,7 +1052,9 @@ end
actions.delete_buffer = function(prompt_bufnr)
local current_picker = action_state.get_current_picker(prompt_bufnr)
current_picker:delete_selection(function(selection)
vim.api.nvim_buf_delete(selection.bufnr, { force = false })
local force = vim.api.nvim_buf_get_option(selection.bufnr, "buftype") == "terminal"
local ok = pcall(vim.api.nvim_buf_delete, selection.bufnr, { force = force })
return ok
end)
end
@ -1056,22 +1093,22 @@ end
---@param prompt_bufnr number: The prompt bufnr
actions.which_key = function(prompt_bufnr, opts)
opts = opts or {}
opts.max_height = utils.get_default(opts.max_height, 0.4)
opts.only_show_current_mode = utils.get_default(opts.only_show_current_mode, true)
opts.mode_width = utils.get_default(opts.mode_width, 1)
opts.keybind_width = utils.get_default(opts.keybind_width, 7)
opts.name_width = utils.get_default(opts.name_width, 30)
opts.line_padding = utils.get_default(opts.line_padding, 1)
opts.separator = utils.get_default(opts.separator, " -> ")
opts.close_with_action = utils.get_default(opts.close_with_action, true)
opts.normal_hl = utils.get_default(opts.normal_hl, "TelescopePrompt")
opts.border_hl = utils.get_default(opts.border_hl, "TelescopePromptBorder")
opts.winblend = utils.get_default(opts.winblend, config.values.winblend)
opts.column_padding = utils.get_default(opts.column_padding, " ")
opts.max_height = vim.F.if_nil(opts.max_height, 0.4)
opts.only_show_current_mode = vim.F.if_nil(opts.only_show_current_mode, true)
opts.mode_width = vim.F.if_nil(opts.mode_width, 1)
opts.keybind_width = vim.F.if_nil(opts.keybind_width, 7)
opts.name_width = vim.F.if_nil(opts.name_width, 30)
opts.line_padding = vim.F.if_nil(opts.line_padding, 1)
opts.separator = vim.F.if_nil(opts.separator, " -> ")
opts.close_with_action = vim.F.if_nil(opts.close_with_action, true)
opts.normal_hl = vim.F.if_nil(opts.normal_hl, "TelescopePrompt")
opts.border_hl = vim.F.if_nil(opts.border_hl, "TelescopePromptBorder")
opts.winblend = vim.F.if_nil(opts.winblend, conf.winblend)
opts.column_padding = vim.F.if_nil(opts.column_padding, " ")
-- Assigning into 'opts.column_indent' would override a number with a string and
-- cause issues with subsequent calls, keep a local copy of the string instead
local column_indent = table.concat(utils.repeated_table(utils.get_default(opts.column_indent, 4), " "))
local column_indent = table.concat(utils.repeated_table(vim.F.if_nil(opts.column_indent, 4), " "))
-- close on repeated keypress
local km_bufs = (function()
@ -1100,7 +1137,7 @@ actions.which_key = function(prompt_bufnr, opts)
local displayer = entry_display.create {
separator = opts.separator,
items = {
{ width = opts.mode_with },
{ width = opts.mode_width },
{ width = opts.keybind_width },
{ width = opts.name_width },
},
@ -1108,9 +1145,9 @@ actions.which_key = function(prompt_bufnr, opts)
local make_display = function(mapping)
return displayer {
{ mapping.mode, utils.get_default(opts.mode_hl, "TelescopeResultsConstant") },
{ mapping.keybind, utils.get_default(opts.keybind_hl, "TelescopeResultsVariable") },
{ mapping.name, utils.get_default(opts.name_hl, "TelescopeResultsFunction") },
{ mapping.mode, vim.F.if_nil(opts.mode_hl, "TelescopeResultsConstant") },
{ mapping.keybind, vim.F.if_nil(opts.keybind_hl, "TelescopeResultsVariable") },
{ mapping.name, vim.F.if_nil(opts.name_hl, "TelescopeResultsFunction") },
}
end
@ -1125,7 +1162,7 @@ actions.which_key = function(prompt_bufnr, opts)
name = name == "" and action or name .. " + " .. action
end
end
if name and name ~= "which_key" then
if name and name ~= "which_key" and name ~= "nop" then
if not opts.only_show_current_mode or mode == v.mode then
table.insert(mappings, { mode = v.mode, keybind = v.keybind, name = name })
end
@ -1168,10 +1205,8 @@ actions.which_key = function(prompt_bufnr, opts)
+ opts.name_width
+ (3 * #opts.separator)
local num_total_columns = math.floor((vim.o.columns - #column_indent) / entry_width)
opts.num_rows = math.min(
math.ceil(#mappings / num_total_columns),
resolver.resolve_height(opts.max_height)(_, _, vim.o.lines)
)
opts.num_rows =
math.min(math.ceil(#mappings / num_total_columns), resolver.resolve_height(opts.max_height)(_, _, vim.o.lines))
local total_available_entries = opts.num_rows * num_total_columns
local winheight = opts.num_rows + 2 * opts.line_padding
@ -1266,6 +1301,30 @@ actions.which_key = function(prompt_bufnr, opts)
end
end
--- Move from a none fuzzy search to a fuzzy one<br>
--- This action is meant to be used in live_grep and lsp_dynamic_workspace_symbols
---@param prompt_bufnr number: The prompt bufnr
actions.to_fuzzy_refine = function(prompt_bufnr)
local line = action_state.get_current_line()
local prefix = (function()
local title = action_state.get_current_picker(prompt_bufnr).prompt_title
if title == "Live Grep" then
return "Find Word"
elseif title == "LSP Dynamic Workspace Symbols" then
return "LSP Workspace Symbols"
else
return "Fuzzy over"
end
end)()
require("telescope.actions.generate").refine(prompt_bufnr, {
prompt_title = string.format("%s (%s)", prefix, line),
sorter = conf.generic_sorter {},
})
end
actions.nop = function(_) end
-- ==================================================
-- Transforms modules and sets the correct metatables.
-- ==================================================

View File

@ -1,5 +1,5 @@
---@tag telescope.actions.layout
---@config { ["module"] = "telescope.actions.layout" }
---@config { ["module"] = "telescope.actions.layout", ["name"] = "ACTIONS_LAYOUT" }
---@brief [[
--- The layout actions are actions to be used to change the layout of a picker.

View File

@ -1,5 +1,5 @@
---@tag telescope.actions.set
---@config { ["module"] = "telescope.actions.set" }
---@config { ["module"] = "telescope.actions.set", ["name"] = "ACTIONS_SET" }
---@brief [[
--- Telescope action sets are used to provide an interface for managing
@ -67,6 +67,8 @@ end
local edit_buffer
do
local map = {
drop = "drop",
["tab drop"] = "tab drop",
edit = "buffer",
new = "sbuffer",
vnew = "vert sbuffer",
@ -78,7 +80,11 @@ do
if command == nil then
error "There was no associated buffer command"
end
vim.cmd(string.format("%s %d", command, bufnr))
if command ~= "drop" and command ~= "tab drop" then
vim.cmd(string.format("%s %d", command, bufnr))
else
vim.cmd(string.format("%s %s", command, vim.api.nvim_buf_get_name(bufnr)))
end
end
end
@ -104,7 +110,7 @@ action_set.edit = function(prompt_bufnr, command)
-- TODO: Check for off-by-one
row = entry.row or entry.lnum
col = entry.col
col = vim.F.if_nil(entry.col, 1)
elseif not entry.bufnr then
-- TODO: Might want to remove this and force people
-- to put stuff into `filename`
@ -131,12 +137,24 @@ action_set.edit = function(prompt_bufnr, command)
local entry_bufnr = entry.bufnr
local picker = action_state.get_current_picker(prompt_bufnr)
require("telescope.actions").close(prompt_bufnr)
require("telescope.pickers").on_close_prompt(prompt_bufnr)
pcall(vim.api.nvim_set_current_win, picker.original_win_id)
local win_id = picker.get_selection_window(picker, entry)
if picker.push_cursor_on_edit then
vim.cmd "normal! m'"
end
if picker.push_tagstack_on_edit then
local from = { vim.fn.bufnr "%", vim.fn.line ".", vim.fn.col ".", 0 }
local items = { { tagname = vim.fn.expand "<cword>", from = from } }
vim.fn.settagstack(vim.fn.win_getid(), { items = items }, "t")
end
if win_id ~= 0 and a.nvim_get_current_win() ~= win_id then
vim.api.nvim_set_current_win(win_id)
end
if entry_bufnr then
if not vim.api.nvim_buf_get_option(entry_bufnr, "buflisted") then
vim.api.nvim_buf_set_option(entry_bufnr, "buflisted", true)
@ -167,13 +185,13 @@ end
-- Valid directions include: "1", "-1"
action_set.scroll_previewer = function(prompt_bufnr, direction)
local previewer = action_state.get_current_picker(prompt_bufnr).previewer
local status = state.get_status(prompt_bufnr)
-- Check if we actually have a previewer
if type(previewer) ~= "table" or previewer.scroll_fn == nil then
-- Check if we actually have a previewer and a preview window
if type(previewer) ~= "table" or previewer.scroll_fn == nil or status.preview_win == nil then
return
end
local status = state.get_status(prompt_bufnr)
local default_speed = vim.api.nvim_win_get_height(status.preview_win) / 2
local speed = status.picker.layout_config.scroll_speed or default_speed

View File

@ -1,5 +1,5 @@
---@tag telescope.actions.state
---@config { ["module"] = "telescope.actions.state" }
---@config { ["module"] = "telescope.actions.state", ["name"] = "ACTIONS_STATE" }
---@brief [[
--- Functions to be used to determine the current state of telescope.
@ -33,6 +33,8 @@ local select_to_edit_map = {
horizontal = "new",
vertical = "vnew",
tab = "tabedit",
drop = "drop",
["tab drop"] = "tab drop",
}
function action_state.select_key_to_edit_key(type)
return select_to_edit_map[type]

View File

@ -1,5 +1,5 @@
---@tag telescope.actions.utils
---@config { ["module"] = "telescope.actions.utils" }
---@config { ["module"] = "telescope.actions.utils", ["name"] = "ACTIONS_UTILS" }
---@brief [[
--- Utilities to wrap functions around picker selections and entries.
@ -13,7 +13,7 @@ local utils = {}
--- Apply `f` to the entries of the current picker.
--- - Notes:
--- - Mapped entries may include results not visible in the results popup.
--- - Mapped entries include all currently filtered results, not just the visible onces.
--- - Indices are 1-indexed, whereas rows are 0-indexed.
--- - Warning: `map_entries` has no return value.
--- - The below example showcases how to collect results
@ -96,8 +96,11 @@ function utils.get_registered_mappings(prompt_bufnr)
for _, mode in ipairs { "n", "i" } do
local mode_mappings = vim.api.nvim_buf_get_keymap(prompt_bufnr, mode)
for _, mapping in ipairs(mode_mappings) do
local funcid = findnth(mapping.rhs, 2)
table.insert(ret, { mode = mode, keybind = mapping.lhs, func = __TelescopeKeymapStore[prompt_bufnr][funcid] })
-- ensure only telescope mappings
if mapping.rhs and string.find(mapping.rhs, [[require%('telescope.mappings'%).execute_keymap]]) then
local funcid = findnth(mapping.rhs, 2)
table.insert(ret, { mode = mode, keybind = mapping.lhs, func = __TelescopeKeymapStore[prompt_bufnr][funcid] })
end
end
end
return ret

View File

@ -122,18 +122,20 @@ diagnostics.get = function(opts)
end
opts.path_display = vim.F.if_nil(opts.path_display, "hidden")
pickers.new(opts, {
prompt_title = opts.bufnr == nil and "Workspace Diagnostics" or "Document Diagnostics",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_diagnostics(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "type",
sorter = conf.generic_sorter(opts),
},
}):find()
pickers
.new(opts, {
prompt_title = opts.bufnr == nil and "Workspace Diagnostics" or "Document Diagnostics",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_diagnostics(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "type",
sorter = conf.generic_sorter(opts),
},
})
:find()
end
local function apply_checks(mod)

View File

@ -1,5 +1,6 @@
local action_state = require "telescope.actions.state"
local action_set = require "telescope.actions.set"
local actions = require "telescope.actions"
local finders = require "telescope.finders"
local make_entry = require "telescope.make_entry"
local pickers = require "telescope.pickers"
@ -35,6 +36,29 @@ local escape_chars = function(string)
})
end
local get_open_filelist = function(grep_open_files, cwd)
if not grep_open_files then
return nil
end
local bufnrs = filter(function(b)
if 1 ~= vim.fn.buflisted(b) then
return false
end
return true
end, vim.api.nvim_list_bufs())
if not next(bufnrs) then
return
end
local filelist = {}
for _, bufnr in ipairs(bufnrs) do
local file = vim.api.nvim_buf_get_name(bufnr)
table.insert(filelist, Path:new(file):make_relative(cwd))
end
return filelist
end
-- Special keys:
-- opts.search_dirs -- list of directory to search in
-- opts.grep_open_files -- boolean to restrict search to open files
@ -44,40 +68,32 @@ files.live_grep = function(opts)
local grep_open_files = opts.grep_open_files
opts.cwd = opts.cwd and vim.fn.expand(opts.cwd) or vim.loop.cwd()
local filelist = {}
if grep_open_files then
local bufnrs = filter(function(b)
if 1 ~= vim.fn.buflisted(b) then
return false
end
return true
end, vim.api.nvim_list_bufs())
if not next(bufnrs) then
return
end
for _, bufnr in ipairs(bufnrs) do
local file = vim.api.nvim_buf_get_name(bufnr)
table.insert(filelist, Path:new(file):make_relative(opts.cwd))
end
elseif search_dirs then
local filelist = get_open_filelist(grep_open_files, opts.cwd)
if search_dirs then
for i, path in ipairs(search_dirs) do
search_dirs[i] = vim.fn.expand(path)
end
end
local additional_args = {}
if opts.additional_args ~= nil and type(opts.additional_args) == "function" then
additional_args = opts.additional_args(opts)
if opts.additional_args ~= nil then
if type(opts.additional_args) == "function" then
additional_args = opts.additional_args(opts)
elseif type(opts.additional_args) == "table" then
additional_args = opts.additional_args
end
end
if opts.type_filter then
additional_args[#additional_args + 1] = "--type=" .. opts.type_filter
end
if opts.glob_pattern then
if type(opts.glob_pattern) == "string" then
additional_args[#additional_args + 1] = "--glob=" .. opts.glob_pattern
elseif type(opts.glob_pattern) == "table" then
for i = 1, #opts.glob_pattern do
additional_args[#additional_args + 1] = "--glob=" .. opts.glob_pattern[i]
end
end
local live_grepper = finders.new_job(function(prompt)
@ -89,80 +105,95 @@ files.live_grep = function(opts)
local search_list = {}
if search_dirs then
table.insert(search_list, search_dirs)
end
if grep_open_files then
search_list = filelist
elseif search_dirs then
search_list = search_dirs
end
return flatten { vimgrep_arguments, additional_args, "--", prompt, search_list }
end, opts.entry_maker or make_entry.gen_from_vimgrep(opts), opts.max_results, opts.cwd)
pickers.new(opts, {
prompt_title = "Live Grep",
finder = live_grepper,
previewer = conf.grep_previewer(opts),
-- TODO: It would be cool to use `--json` output for this
-- and then we could get the highlight positions directly.
sorter = sorters.highlighter_only(opts),
}):find()
pickers
.new(opts, {
prompt_title = "Live Grep",
finder = live_grepper,
previewer = conf.grep_previewer(opts),
-- TODO: It would be cool to use `--json` output for this
-- and then we could get the highlight positions directly.
sorter = sorters.highlighter_only(opts),
attach_mappings = function(_, map)
map("i", "<c-space>", actions.to_fuzzy_refine)
return true
end,
})
:find()
end
-- Special keys:
-- opts.search -- the string to search.
-- opts.search_dirs -- list of directory to search in
-- opts.use_regex -- special characters won't be escaped
files.grep_string = function(opts)
-- TODO: This should probably check your visual selection as well, if you've got one
local vimgrep_arguments = opts.vimgrep_arguments or conf.vimgrep_arguments
local search_dirs = opts.search_dirs
local word = opts.search or vim.fn.expand "<cword>"
opts.cwd = opts.cwd and vim.fn.expand(opts.cwd) or vim.loop.cwd()
local vimgrep_arguments = vim.F.if_nil(opts.vimgrep_arguments, conf.vimgrep_arguments)
local word = vim.F.if_nil(opts.search, vim.fn.expand "<cword>")
local search = opts.use_regex and word or escape_chars(word)
local word_match = opts.word_match
opts.entry_maker = opts.entry_maker or make_entry.gen_from_vimgrep(opts)
local additional_args = {}
if opts.additional_args ~= nil and type(opts.additional_args) == "function" then
additional_args = opts.additional_args(opts)
if opts.additional_args ~= nil then
if type(opts.additional_args) == "function" then
additional_args = opts.additional_args(opts)
elseif type(opts.additional_args) == "table" then
additional_args = opts.additional_args
end
end
if search == "" then
search = { "-v", "--", "^[[:space:]]*$" }
opts.__inverted = true
else
search = { "--", search }
end
local args = flatten {
vimgrep_arguments,
additional_args,
word_match,
"--",
opts.word_match,
search,
}
if search_dirs then
for _, path in ipairs(search_dirs) do
if opts.grep_open_files then
for _, file in ipairs(get_open_filelist(opts.grep_open_files, opts.cwd)) do
table.insert(args, file)
end
elseif opts.search_dirs then
for _, path in ipairs(opts.search_dirs) do
table.insert(args, vim.fn.expand(path))
end
end
pickers.new(opts, {
prompt_title = "Find Word (" .. word .. ")",
finder = finders.new_oneshot_job(args, opts),
previewer = conf.grep_previewer(opts),
sorter = conf.generic_sorter(opts),
}):find()
opts.entry_maker = opts.entry_maker or make_entry.gen_from_vimgrep(opts)
pickers
.new(opts, {
prompt_title = "Find Word (" .. word:gsub("\n", "\\n") .. ")",
finder = finders.new_oneshot_job(args, opts),
previewer = conf.grep_previewer(opts),
sorter = conf.generic_sorter(opts),
})
:find()
end
-- TODO: Maybe just change this to `find`.
-- TODO: Support `find` and maybe let people do other stuff with it as well.
files.find_files = function(opts)
local find_command = (function()
if opts.find_command then
if type(opts.find_command) == "function" then
return opts.find_command(opts)
end
return opts.find_command
elseif 1 == vim.fn.executable "fd" then
return { "fd", "--type", "f" }
elseif 1 == vim.fn.executable "fdfind" then
return { "fdfind", "--type", "f" }
elseif 1 == vim.fn.executable "rg" then
return { "rg", "--files" }
return { "rg", "--files", "--color", "never" }
elseif 1 == vim.fn.executable "fd" then
return { "fd", "--type", "f", "--color", "never" }
elseif 1 == vim.fn.executable "fdfind" then
return { "fdfind", "--type", "f", "--color", "never" }
elseif 1 == vim.fn.executable "find" and vim.fn.has "win32" == 0 then
return { "find", ".", "-type", "f" }
elseif 1 == vim.fn.executable "where" then
@ -181,8 +212,10 @@ files.find_files = function(opts)
local command = find_command[1]
local hidden = opts.hidden
local no_ignore = opts.no_ignore
local no_ignore_parent = opts.no_ignore_parent
local follow = opts.follow
local search_dirs = opts.search_dirs
local search_file = opts.search_file
if search_dirs then
for k, v in pairs(search_dirs) do
@ -192,21 +225,30 @@ files.find_files = function(opts)
if command == "fd" or command == "fdfind" or command == "rg" then
if hidden then
table.insert(find_command, "--hidden")
find_command[#find_command + 1] = "--hidden"
end
if no_ignore then
table.insert(find_command, "--no-ignore")
find_command[#find_command + 1] = "--no-ignore"
end
if no_ignore_parent then
find_command[#find_command + 1] = "--no-ignore-parent"
end
if follow then
table.insert(find_command, "-L")
find_command[#find_command + 1] = "-L"
end
if search_file then
if command == "rg" then
find_command[#find_command + 1] = "-g"
find_command[#find_command + 1] = "*" .. search_file .. "*"
else
find_command[#find_command + 1] = search_file
end
end
if search_dirs then
if command ~= "rg" then
table.insert(find_command, ".")
end
for _, v in pairs(search_dirs) do
table.insert(find_command, v)
if command ~= "rg" and not search_file then
find_command[#find_command + 1] = "."
end
vim.list_extend(find_command, search_dirs)
end
elseif command == "find" then
if not hidden then
@ -216,9 +258,16 @@ files.find_files = function(opts)
if no_ignore ~= nil then
log.warn "The `no_ignore` key is not available for the `find` command in `find_files`."
end
if no_ignore_parent ~= nil then
log.warn "The `no_ignore_parent` key is not available for the `find` command in `find_files`."
end
if follow then
table.insert(find_command, 2, "-L")
end
if search_file then
table.insert(find_command, "-name")
table.insert(find_command, "*" .. search_file .. "*")
end
if search_dirs then
table.remove(find_command, 2)
for _, v in pairs(search_dirs) do
@ -232,12 +281,18 @@ files.find_files = function(opts)
if no_ignore ~= nil then
log.warn "The `no_ignore` key is not available for the Windows `where` command in `find_files`."
end
if no_ignore_parent ~= nil then
log.warn "The `no_ignore_parent` key is not available for the Windows `where` command in `find_files`."
end
if follow ~= nil then
log.warn "The `follow` key is not available for the Windows `where` command in `find_files`."
end
if search_dirs ~= nil then
log.warn "The `search_dirs` key is not available for the Windows `where` command in `find_files`."
end
if search_file ~= nil then
log.warn "The `search_file` key is not available for the Windows `where` command in `find_files`."
end
end
if opts.cwd then
@ -246,12 +301,14 @@ files.find_files = function(opts)
opts.entry_maker = opts.entry_maker or make_entry.gen_from_file(opts)
pickers.new(opts, {
prompt_title = "Find Files",
finder = finders.new_oneshot_job(find_command, opts),
previewer = conf.file_previewer(opts),
sorter = conf.file_sorter(opts),
}):find()
pickers
.new(opts, {
prompt_title = "Find Files",
finder = finders.new_oneshot_job(find_command, opts),
previewer = conf.file_previewer(opts),
sorter = conf.file_sorter(opts),
})
:find()
end
local function prepare_match(entry, kind)
@ -270,7 +327,7 @@ end
-- TODO: finish docs for opts.show_line
files.treesitter = function(opts)
opts.show_line = utils.get_default(opts.show_line, true)
opts.show_line = vim.F.if_nil(opts.show_line, true)
local has_nvim_treesitter, _ = pcall(require, "nvim-treesitter")
if not has_nvim_treesitter then
@ -304,18 +361,20 @@ files.treesitter = function(opts)
return
end
pickers.new(opts, {
prompt_title = "Treesitter Symbols",
finder = finders.new_table {
results = results,
entry_maker = opts.entry_maker or make_entry.gen_from_treesitter(opts),
},
previewer = conf.grep_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "kind",
sorter = conf.generic_sorter(opts),
},
}):find()
pickers
.new(opts, {
prompt_title = "Treesitter Symbols",
finder = finders.new_table {
results = results,
entry_maker = opts.entry_maker or make_entry.gen_from_treesitter(opts),
},
previewer = conf.grep_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "kind",
sorter = conf.generic_sorter(opts),
},
})
:find()
end
files.current_buffer_fuzzy_find = function(opts)
@ -356,8 +415,12 @@ files.current_buffer_fuzzy_find = function(opts)
return obj
end,
})
-- update to changes on Neovim master, see https://github.com/neovim/neovim/pull/19931
-- TODO(clason): remove when dropping support for Neovim 0.7
local on_nvim_master = vim.fn.has "nvim-0.8" == 1
for id, node in query:iter_captures(root, opts.bufnr, 0, -1) do
local hl = highlighter_query:_get_hl_from_capture(id)
local hl = on_nvim_master and query.captures[id] or highlighter_query:_get_hl_from_capture(id)
if hl and type(hl) ~= "number" then
local row1, col1, row2, col2 = node:range()
@ -387,29 +450,34 @@ files.current_buffer_fuzzy_find = function(opts)
opts.line_highlights = line_highlights
end
pickers.new(opts, {
prompt_title = "Current Buffer Fuzzy",
finder = finders.new_table {
results = lines_with_numbers,
entry_maker = opts.entry_maker or make_entry.gen_from_buffer_lines(opts),
},
sorter = conf.generic_sorter(opts),
previewer = conf.grep_previewer(opts),
attach_mappings = function()
action_set.select:enhance {
post = function()
local selection = action_state.get_selected_entry()
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
end,
}
pickers
.new(opts, {
prompt_title = "Current Buffer Fuzzy",
finder = finders.new_table {
results = lines_with_numbers,
entry_maker = opts.entry_maker or make_entry.gen_from_buffer_lines(opts),
},
sorter = conf.generic_sorter(opts),
previewer = conf.grep_previewer(opts),
attach_mappings = function()
action_set.select:enhance {
post = function()
local selection = action_state.get_selected_entry()
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
end,
}
return true
end,
}):find()
return true
end,
})
:find()
end
files.tags = function(opts)
local tagfiles = opts.ctags_file and { opts.ctags_file } or vim.fn.tagfiles()
for i, ctags_file in ipairs(tagfiles) do
tagfiles[i] = vim.fn.expand(ctags_file, true)
end
if vim.tbl_isempty(tagfiles) then
utils.notify("builtin.tags", {
msg = "No tags file found. Create one with ctags -R",
@ -417,46 +485,42 @@ files.tags = function(opts)
})
return
end
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_ctags(opts))
local results = {}
for _, ctags_file in ipairs(tagfiles) do
for line in Path:new(vim.fn.expand(ctags_file, true)):iter() do
results[#results + 1] = line
end
end
pickers
.new(opts, {
prompt_title = "Tags",
finder = finders.new_oneshot_job(flatten { "cat", tagfiles }, opts),
previewer = previewers.ctags.new(opts),
sorter = conf.generic_sorter(opts),
attach_mappings = function()
action_set.select:enhance {
post = function()
local selection = action_state.get_selected_entry()
if not selection then
return
end
pickers.new(opts, {
prompt_title = "Tags",
finder = finders.new_table {
results = results,
entry_maker = opts.entry_maker or make_entry.gen_from_ctags(opts),
},
previewer = previewers.ctags.new(opts),
sorter = conf.generic_sorter(opts),
attach_mappings = function()
action_set.select:enhance {
post = function()
local selection = action_state.get_selected_entry()
if selection.scode then
-- un-escape / then escape required
-- special chars for vim.fn.search()
-- ] ~ *
local scode = selection.scode:gsub([[\/]], "/"):gsub("[%]~*]", function(x)
return "\\" .. x
end)
if selection.scode then
-- un-escape / then escape required
-- special chars for vim.fn.search()
-- ] ~ *
local scode = selection.scode:gsub([[\/]], "/"):gsub("[%]~*]", function(x)
return "\\" .. x
end)
vim.cmd "norm! gg"
vim.fn.search(scode)
vim.cmd "norm! zz"
else
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
end
end,
}
return true
end,
}):find()
vim.cmd "norm! gg"
vim.fn.search(scode)
vim.cmd "norm! zz"
else
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
end
end,
}
return true
end,
})
:find()
end
files.current_buffer_tags = function(opts)

View File

@ -0,0 +1,427 @@
local actions = require "telescope.actions"
local action_state = require "telescope.actions.state"
local finders = require "telescope.finders"
local make_entry = require "telescope.make_entry"
local pickers = require "telescope.pickers"
local previewers = require "telescope.previewers"
local utils = require "telescope.utils"
local entry_display = require "telescope.pickers.entry_display"
local strings = require "plenary.strings"
local Path = require "plenary.path"
local conf = require("telescope.config").values
local git = {}
git.files = function(opts)
if opts.is_bare then
utils.notify("builtin.git_files", {
msg = "This operation must be run in a work tree",
level = "ERROR",
})
return
end
local show_untracked = vim.F.if_nil(opts.show_untracked, false)
local recurse_submodules = vim.F.if_nil(opts.recurse_submodules, false)
if show_untracked and recurse_submodules then
utils.notify("builtin.git_files", {
msg = "Git does not support both --others and --recurse-submodules",
level = "ERROR",
})
return
end
-- By creating the entry maker after the cwd options,
-- we ensure the maker uses the cwd options when being created.
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_file(opts))
local git_command = vim.F.if_nil(opts.git_command, { "git", "ls-files", "--exclude-standard", "--cached" })
pickers
.new(opts, {
prompt_title = "Git Files",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
git_command,
show_untracked and "--others" or nil,
recurse_submodules and "--recurse-submodules" or nil,
},
opts
),
previewer = conf.file_previewer(opts),
sorter = conf.file_sorter(opts),
})
:find()
end
git.commits = function(opts)
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
local git_command = vim.F.if_nil(opts.git_command, { "git", "log", "--pretty=oneline", "--abbrev-commit", "--", "." })
pickers
.new(opts, {
prompt_title = "Git Commits",
finder = finders.new_oneshot_job(git_command, opts),
previewer = {
previewers.git_commit_diff_to_parent.new(opts),
previewers.git_commit_diff_to_head.new(opts),
previewers.git_commit_diff_as_was.new(opts),
previewers.git_commit_message.new(opts),
},
sorter = conf.file_sorter(opts),
attach_mappings = function(_, map)
actions.select_default:replace(actions.git_checkout)
map("i", "<c-r>m", actions.git_reset_mixed)
map("n", "<c-r>m", actions.git_reset_mixed)
map("i", "<c-r>s", actions.git_reset_soft)
map("n", "<c-r>s", actions.git_reset_soft)
map("i", "<c-r>h", actions.git_reset_hard)
map("n", "<c-r>h", actions.git_reset_hard)
return true
end,
})
:find()
end
git.stash = function(opts)
opts.show_branch = vim.F.if_nil(opts.show_branch, true)
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_stash(opts))
pickers
.new(opts, {
prompt_title = "Git Stash",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
"git",
"--no-pager",
"stash",
"list",
},
opts
),
previewer = previewers.git_stash_diff.new(opts),
sorter = conf.file_sorter(opts),
attach_mappings = function()
actions.select_default:replace(actions.git_apply_stash)
return true
end,
})
:find()
end
local get_current_buf_line = function(winnr)
local lnum = vim.api.nvim_win_get_cursor(winnr)[1]
return vim.trim(vim.api.nvim_buf_get_lines(vim.api.nvim_win_get_buf(winnr), lnum - 1, lnum, false)[1])
end
git.bcommits = function(opts)
opts.current_line = (opts.current_file == nil) and get_current_buf_line(opts.winnr) or nil
opts.current_file = vim.F.if_nil(opts.current_file, vim.api.nvim_buf_get_name(opts.bufnr))
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
local git_command =
vim.F.if_nil(opts.git_command, { "git", "log", "--pretty=oneline", "--abbrev-commit", "--follow" })
pickers
.new(opts, {
prompt_title = "Git BCommits",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
git_command,
opts.current_file,
},
opts
),
previewer = {
previewers.git_commit_diff_to_parent.new(opts),
previewers.git_commit_diff_to_head.new(opts),
previewers.git_commit_diff_as_was.new(opts),
previewers.git_commit_message.new(opts),
},
sorter = conf.file_sorter(opts),
attach_mappings = function()
actions.select_default:replace(actions.git_checkout_current_buffer)
local transfrom_file = function()
return opts.current_file and Path:new(opts.current_file):make_relative(opts.cwd) or ""
end
local get_buffer_of_orig = function(selection)
local value = selection.value .. ":" .. transfrom_file()
local content = utils.get_os_command_output({ "git", "--no-pager", "show", value }, opts.cwd)
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, content)
vim.api.nvim_buf_set_name(bufnr, "Original")
return bufnr
end
local vimdiff = function(selection, command)
local ft = vim.bo.filetype
vim.cmd "diffthis"
local bufnr = get_buffer_of_orig(selection)
vim.cmd(string.format("%s %s", command, bufnr))
vim.bo.filetype = ft
vim.cmd "diffthis"
vim.api.nvim_create_autocmd("WinClosed", {
buffer = bufnr,
nested = true,
once = true,
callback = function()
vim.api.nvim_buf_delete(bufnr, { force = true })
end,
})
end
actions.select_vertical:replace(function(prompt_bufnr)
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
vimdiff(selection, "leftabove vert sbuffer")
end)
actions.select_horizontal:replace(function(prompt_bufnr)
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
vimdiff(selection, "belowright sbuffer")
end)
actions.select_tab:replace(function(prompt_bufnr)
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
vim.cmd("tabedit " .. transfrom_file())
vimdiff(selection, "leftabove vert sbuffer")
end)
return true
end,
})
:find()
end
git.branches = function(opts)
local format = "%(HEAD)"
.. "%(refname)"
.. "%(authorname)"
.. "%(upstream:lstrip=2)"
.. "%(committerdate:format-local:%Y/%m/%d %H:%M:%S)"
local output =
utils.get_os_command_output({ "git", "for-each-ref", "--perl", "--format", format, opts.pattern }, opts.cwd)
local results = {}
local widths = {
name = 0,
authorname = 0,
upstream = 0,
committerdate = 0,
}
local unescape_single_quote = function(v)
return string.gsub(v, "\\([\\'])", "%1")
end
local parse_line = function(line)
local fields = vim.split(string.sub(line, 2, -2), "''", true)
local entry = {
head = fields[1],
refname = unescape_single_quote(fields[2]),
authorname = unescape_single_quote(fields[3]),
upstream = unescape_single_quote(fields[4]),
committerdate = fields[5],
}
local prefix
if vim.startswith(entry.refname, "refs/remotes/") then
prefix = "refs/remotes/"
elseif vim.startswith(entry.refname, "refs/heads/") then
prefix = "refs/heads/"
else
return
end
local index = 1
if entry.head ~= "*" then
index = #results + 1
end
entry.name = string.sub(entry.refname, string.len(prefix) + 1)
for key, value in pairs(widths) do
widths[key] = math.max(value, strings.strdisplaywidth(entry[key] or ""))
end
if string.len(entry.upstream) > 0 then
widths.upstream_indicator = 2
end
table.insert(results, index, entry)
end
for _, line in ipairs(output) do
parse_line(line)
end
if #results == 0 then
return
end
local displayer = entry_display.create {
separator = " ",
items = {
{ width = 1 },
{ width = widths.name },
{ width = widths.authorname },
{ width = widths.upstream_indicator },
{ width = widths.upstream },
{ width = widths.committerdate },
},
}
local make_display = function(entry)
return displayer {
{ entry.head },
{ entry.name, "TelescopeResultsIdentifier" },
{ entry.authorname },
{ string.len(entry.upstream) > 0 and "=>" or "" },
{ entry.upstream, "TelescopeResultsIdentifier" },
{ entry.committerdate },
}
end
pickers
.new(opts, {
prompt_title = "Git Branches",
finder = finders.new_table {
results = results,
entry_maker = function(entry)
entry.value = entry.name
entry.ordinal = entry.name
entry.display = make_display
return make_entry.set_default_entry_mt(entry, opts)
end,
},
previewer = previewers.git_branch_log.new(opts),
sorter = conf.file_sorter(opts),
attach_mappings = function(_, map)
actions.select_default:replace(actions.git_checkout)
map("i", "<c-t>", actions.git_track_branch)
map("n", "<c-t>", actions.git_track_branch)
map("i", "<c-r>", actions.git_rebase_branch)
map("n", "<c-r>", actions.git_rebase_branch)
map("i", "<c-a>", actions.git_create_branch)
map("n", "<c-a>", actions.git_create_branch)
map("i", "<c-s>", actions.git_switch_branch)
map("n", "<c-s>", actions.git_switch_branch)
map("i", "<c-d>", actions.git_delete_branch)
map("n", "<c-d>", actions.git_delete_branch)
map("i", "<c-y>", actions.git_merge_branch)
map("n", "<c-y>", actions.git_merge_branch)
return true
end,
})
:find()
end
git.status = function(opts)
if opts.is_bare then
utils.notify("builtin.git_status", {
msg = "This operation must be run in a work tree",
level = "ERROR",
})
return
end
local gen_new_finder = function()
local expand_dir = vim.F.if_nil(opts.expand_dir, true)
local git_cmd = { "git", "status", "-s", "--", "." }
if expand_dir then
table.insert(git_cmd, #git_cmd - 1, "-u")
end
local output = utils.get_os_command_output(git_cmd, opts.cwd)
if #output == 0 then
print "No changes found"
utils.notify("builtin.git_status", {
msg = "No changes found",
level = "WARN",
})
return
end
return finders.new_table {
results = output,
entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_status(opts)),
}
end
local initial_finder = gen_new_finder()
if not initial_finder then
return
end
pickers
.new(opts, {
prompt_title = "Git Status",
finder = initial_finder,
previewer = previewers.git_file_diff.new(opts),
sorter = conf.file_sorter(opts),
attach_mappings = function(prompt_bufnr, map)
actions.git_staging_toggle:enhance {
post = function()
action_state.get_current_picker(prompt_bufnr):refresh(gen_new_finder(), { reset_prompt = true })
end,
}
map("i", "<tab>", actions.git_staging_toggle)
map("n", "<tab>", actions.git_staging_toggle)
return true
end,
})
:find()
end
local set_opts_cwd = function(opts)
if opts.cwd then
opts.cwd = vim.fn.expand(opts.cwd)
else
opts.cwd = vim.loop.cwd()
end
-- Find root of git directory and remove trailing newline characters
local git_root, ret = utils.get_os_command_output({ "git", "rev-parse", "--show-toplevel" }, opts.cwd)
local use_git_root = vim.F.if_nil(opts.use_git_root, true)
if ret ~= 0 then
local in_worktree = utils.get_os_command_output({ "git", "rev-parse", "--is-inside-work-tree" }, opts.cwd)
local in_bare = utils.get_os_command_output({ "git", "rev-parse", "--is-bare-repository" }, opts.cwd)
if in_worktree[1] ~= "true" and in_bare[1] ~= "true" then
utils.notify("builtin.git", {
msg = opts.cwd .. " is not a git directory",
level = "ERROR",
})
return false
elseif in_worktree[1] ~= "true" and in_bare[1] == "true" then
opts.is_bare = true
end
else
if use_git_root then
opts.cwd = git_root[1]
end
end
return true
end
local function apply_checks(mod)
for k, v in pairs(mod) do
mod[k] = function(opts)
opts = vim.F.if_nil(opts, {})
local ok = set_opts_cwd(opts)
if ok then
v(opts)
end
end
end
return mod
end
return apply_checks(git)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
local channel = require("plenary.async.control").channel
local actions = require "telescope.actions"
local sorters = require "telescope.sorters"
local conf = require("telescope.config").values
local finders = require "telescope.finders"
local make_entry = require "telescope.make_entry"
@ -24,7 +25,7 @@ lsp.references = function(opts)
local locations = {}
if result then
local results = vim.lsp.util.locations_to_items(result, vim.lsp.get_client_by_id(ctx.client_id).offset_encoding)
if include_current_line then
if not include_current_line then
locations = vim.tbl_filter(function(v)
-- Remove current line from result
return not (v.filename == filepath and v.lnum == lnum)
@ -38,22 +39,111 @@ lsp.references = function(opts)
return
end
pickers.new(opts, {
prompt_title = "LSP References",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.generic_sorter(opts),
push_cursor_on_edit = true,
}):find()
pickers
.new(opts, {
prompt_title = "LSP References",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.generic_sorter(opts),
push_cursor_on_edit = true,
push_tagstack_on_edit = true,
})
:find()
end)
end
local function list_or_jump(action, title, opts)
opts = opts or {}
local function call_hierarchy(opts, method, title, direction, item)
vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
if err then
vim.api.nvim_err_writeln("Error handling " .. title .. ": " .. err.message)
return
end
if not result or vim.tbl_isempty(result) then
return
end
local locations = {}
for _, ch_call in pairs(result) do
local ch_item = ch_call[direction]
for _, range in pairs(ch_call.fromRanges) do
table.insert(locations, {
filename = vim.uri_to_fname(ch_item.uri),
text = ch_item.name,
lnum = range.start.line + 1,
col = range.start.character + 1,
})
end
end
pickers
.new(opts, {
prompt_title = title,
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.generic_sorter(opts),
push_cursor_on_edit = true,
push_tagstack_on_edit = true,
})
:find()
end)
end
local function pick_call_hierarchy_item(call_hierarchy_items)
if not call_hierarchy_items then
return
end
if #call_hierarchy_items == 1 then
return call_hierarchy_items[1]
end
local items = {}
for i, item in pairs(call_hierarchy_items) do
local entry = item.detail or item.name
table.insert(items, string.format("%d. %s", i, entry))
end
local choice = vim.fn.inputlist(items)
if choice < 1 or choice > #items then
return
end
return choice
end
local function calls(opts, direction)
local params = vim.lsp.util.make_position_params()
vim.lsp.buf_request(opts.bufnr, "textDocument/prepareCallHierarchy", params, function(err, result)
if err then
vim.api.nvim_err_writeln("Error when preparing call hierarchy: " .. err)
return
end
local call_hierarchy_item = pick_call_hierarchy_item(result)
if not call_hierarchy_item then
return
end
if direction == "from" then
call_hierarchy(opts, "callHierarchy/incomingCalls", "LSP Incoming Calls", direction, call_hierarchy_item)
else
call_hierarchy(opts, "callHierarchy/outgoingCalls", "LSP Outgoing Calls", direction, call_hierarchy_item)
end
end)
end
lsp.incoming_calls = function(opts)
calls(opts, "from")
end
lsp.outgoing_calls = function(opts)
calls(opts, "to")
end
local function list_or_jump(action, title, opts)
local params = vim.lsp.util.make_position_params(opts.winnr)
vim.lsp.buf_request(opts.bufnr, action, params, function(err, result, ctx, _)
if err then
@ -85,15 +175,19 @@ local function list_or_jump(action, title, opts)
vim.lsp.util.jump_to_location(flattened_results[1], offset_encoding)
else
local locations = vim.lsp.util.locations_to_items(flattened_results, offset_encoding)
pickers.new(opts, {
prompt_title = title,
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.generic_sorter(opts),
}):find()
pickers
.new(opts, {
prompt_title = title,
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.generic_sorter(opts),
push_cursor_on_edit = true,
push_tagstack_on_edit = true,
})
:find()
end
end)
end
@ -141,20 +235,23 @@ lsp.document_symbols = function(opts)
return
end
opts.ignore_filename = opts.ignore_filename or true
pickers.new(opts, {
prompt_title = "LSP Document Symbols",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "symbol_type",
sorter = conf.generic_sorter(opts),
},
push_cursor_on_edit = true,
}):find()
opts.path_display = { "hidden" }
pickers
.new(opts, {
prompt_title = "LSP Document Symbols",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "symbol_type",
sorter = conf.generic_sorter(opts),
},
push_cursor_on_edit = true,
push_tagstack_on_edit = true,
})
:find()
end)
end
@ -182,20 +279,22 @@ lsp.workspace_symbols = function(opts)
return
end
opts.ignore_filename = utils.get_default(opts.ignore_filename, false)
opts.ignore_filename = vim.F.if_nil(opts.ignore_filename, false)
pickers.new(opts, {
prompt_title = "LSP Workspace Symbols",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "symbol_type",
sorter = conf.generic_sorter(opts),
},
}):find()
pickers
.new(opts, {
prompt_title = "LSP Workspace Symbols",
finder = finders.new_table {
results = locations,
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.prefilter_sorter {
tag = "symbol_type",
sorter = conf.generic_sorter(opts),
},
})
:find()
end)
end
@ -220,15 +319,21 @@ local function get_workspace_symbols_requester(bufnr, opts)
end
lsp.dynamic_workspace_symbols = function(opts)
pickers.new(opts, {
prompt_title = "LSP Dynamic Workspace Symbols",
finder = finders.new_dynamic {
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
fn = get_workspace_symbols_requester(opts.bufnr, opts),
},
previewer = conf.qflist_previewer(opts),
sorter = conf.generic_sorter(opts),
}):find()
pickers
.new(opts, {
prompt_title = "LSP Dynamic Workspace Symbols",
finder = finders.new_dynamic {
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
fn = get_workspace_symbols_requester(opts.bufnr, opts),
},
previewer = conf.qflist_previewer(opts),
sorter = sorters.highlighter_only(opts),
attach_mappings = function(_, map)
map("i", "<c-space>", actions.to_fuzzy_refine)
return true
end,
})
:find()
end
local function check_capabilities(feature, bufnr)
@ -267,6 +372,8 @@ local feature_map = {
["type_definitions"] = "typeDefinitionProvider",
["implementations"] = "implementationProvider",
["workspace_symbols"] = "workspaceSymbolProvider",
["incoming_calls"] = "callHierarchyProvider",
["outgoing_calls"] = "callHierarchyProvider",
}
local function apply_checks(mod)

View File

@ -1,409 +0,0 @@
local actions = require "telescope.actions"
local action_state = require "telescope.actions.state"
local finders = require "telescope.finders"
local make_entry = require "telescope.make_entry"
local pickers = require "telescope.pickers"
local previewers = require "telescope.previewers"
local utils = require "telescope.utils"
local entry_display = require "telescope.pickers.entry_display"
local strings = require "plenary.strings"
local Path = require "plenary.path"
local conf = require("telescope.config").values
local git = {}
git.files = function(opts)
if opts.is_bare then
utils.notify("builtin.git_files", {
msg = "This operation must be run in a work tree",
level = "ERROR",
})
return
end
local show_untracked = utils.get_default(opts.show_untracked, true)
local recurse_submodules = utils.get_default(opts.recurse_submodules, false)
if show_untracked and recurse_submodules then
utils.notify("builtin.git_files", {
msg = "Git does not support both --others and --recurse-submodules",
level = "ERROR",
})
return
end
-- By creating the entry maker after the cwd options,
-- we ensure the maker uses the cwd options when being created.
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_file(opts))
local git_command = vim.F.if_nil(opts.git_command, { "git", "ls-files", "--exclude-standard", "--cached" })
pickers.new(opts, {
prompt_title = "Git Files",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
git_command,
show_untracked and "--others" or nil,
recurse_submodules and "--recurse-submodules" or nil,
},
opts
),
previewer = conf.file_previewer(opts),
sorter = conf.file_sorter(opts),
}):find()
end
git.commits = function(opts)
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
local git_command = vim.F.if_nil(opts.git_command, { "git", "log", "--pretty=oneline", "--abbrev-commit", "--", "." })
pickers.new(opts, {
prompt_title = "Git Commits",
finder = finders.new_oneshot_job(git_command, opts),
previewer = {
previewers.git_commit_diff_to_parent.new(opts),
previewers.git_commit_diff_to_head.new(opts),
previewers.git_commit_diff_as_was.new(opts),
previewers.git_commit_message.new(opts),
},
sorter = conf.file_sorter(opts),
attach_mappings = function(_, map)
actions.select_default:replace(actions.git_checkout)
map("i", "<c-r>m", actions.git_reset_mixed)
map("n", "<c-r>m", actions.git_reset_mixed)
map("i", "<c-r>s", actions.git_reset_soft)
map("n", "<c-r>s", actions.git_reset_soft)
map("i", "<c-r>h", actions.git_reset_hard)
map("n", "<c-r>h", actions.git_reset_hard)
return true
end,
}):find()
end
git.stash = function(opts)
opts.show_branch = vim.F.if_nil(opts.show_branch, true)
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_stash(opts))
pickers.new(opts, {
prompt_title = "Git Stash",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
"git",
"--no-pager",
"stash",
"list",
},
opts
),
previewer = previewers.git_stash_diff.new(opts),
sorter = conf.file_sorter(opts),
attach_mappings = function()
actions.select_default:replace(actions.git_apply_stash)
return true
end,
}):find()
end
local get_current_buf_line = function(winnr)
local lnum = vim.api.nvim_win_get_cursor(winnr)[1]
return vim.trim(vim.api.nvim_buf_get_lines(vim.api.nvim_win_get_buf(winnr), lnum - 1, lnum, false)[1])
end
git.bcommits = function(opts)
opts.current_line = (opts.current_file == nil) and get_current_buf_line(opts.winnr) or nil
opts.current_file = vim.F.if_nil(opts.current_file, vim.api.nvim_buf_get_name(opts.bufnr))
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
local git_command = vim.F.if_nil(opts.git_command, { "git", "log", "--pretty=oneline", "--abbrev-commit" })
pickers.new(opts, {
prompt_title = "Git BCommits",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
git_command,
opts.current_file,
},
opts
),
previewer = {
previewers.git_commit_diff_to_parent.new(opts),
previewers.git_commit_diff_to_head.new(opts),
previewers.git_commit_diff_as_was.new(opts),
previewers.git_commit_message.new(opts),
},
sorter = conf.file_sorter(opts),
attach_mappings = function()
actions.select_default:replace(actions.git_checkout_current_buffer)
local transfrom_file = function()
return opts.current_file and Path:new(opts.current_file):make_relative(opts.cwd) or ""
end
local get_buffer_of_orig = function(selection)
local value = selection.value .. ":" .. transfrom_file()
local content = utils.get_os_command_output({ "git", "--no-pager", "show", value }, opts.cwd)
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, content)
vim.api.nvim_buf_set_name(bufnr, "Original")
return bufnr
end
local vimdiff = function(selection, command)
local ft = vim.bo.filetype
vim.cmd "diffthis"
local bufnr = get_buffer_of_orig(selection)
vim.cmd(string.format("%s %s", command, bufnr))
vim.bo.filetype = ft
vim.cmd "diffthis"
vim.api.nvim_create_autocmd("WinClosed", {
event = "WinClosed",
buffer = bufnr,
nested = true,
once = true,
function()
vim.api.nvim_buf_delete(bufnr, { force = true })
end,
})
end
actions.select_vertical:replace(function(prompt_bufnr)
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
vimdiff(selection, "leftabove vert sbuffer")
end)
actions.select_horizontal:replace(function(prompt_bufnr)
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
vimdiff(selection, "belowright sbuffer")
end)
actions.select_tab:replace(function(prompt_bufnr)
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
vim.cmd("tabedit " .. transfrom_file())
vimdiff(selection, "leftabove vert sbuffer")
end)
return true
end,
}):find()
end
git.branches = function(opts)
local format = "%(HEAD)"
.. "%(refname)"
.. "%(authorname)"
.. "%(upstream:lstrip=2)"
.. "%(committerdate:format-local:%Y/%m/%d %H:%M:%S)"
local output = utils.get_os_command_output(
{ "git", "for-each-ref", "--perl", "--format", format, opts.pattern },
opts.cwd
)
local results = {}
local widths = {
name = 0,
authorname = 0,
upstream = 0,
committerdate = 0,
}
local unescape_single_quote = function(v)
return string.gsub(v, "\\([\\'])", "%1")
end
local parse_line = function(line)
local fields = vim.split(string.sub(line, 2, -2), "''", true)
local entry = {
head = fields[1],
refname = unescape_single_quote(fields[2]),
authorname = unescape_single_quote(fields[3]),
upstream = unescape_single_quote(fields[4]),
committerdate = fields[5],
}
local prefix
if vim.startswith(entry.refname, "refs/remotes/") then
prefix = "refs/remotes/"
elseif vim.startswith(entry.refname, "refs/heads/") then
prefix = "refs/heads/"
else
return
end
local index = 1
if entry.head ~= "*" then
index = #results + 1
end
entry.name = string.sub(entry.refname, string.len(prefix) + 1)
for key, value in pairs(widths) do
widths[key] = math.max(value, strings.strdisplaywidth(entry[key] or ""))
end
if string.len(entry.upstream) > 0 then
widths.upstream_indicator = 2
end
table.insert(results, index, entry)
end
for _, line in ipairs(output) do
parse_line(line)
end
if #results == 0 then
return
end
local displayer = entry_display.create {
separator = " ",
items = {
{ width = 1 },
{ width = widths.name },
{ width = widths.authorname },
{ width = widths.upstream_indicator },
{ width = widths.upstream },
{ width = widths.committerdate },
},
}
local make_display = function(entry)
return displayer {
{ entry.head },
{ entry.name, "TelescopeResultsIdentifier" },
{ entry.authorname },
{ string.len(entry.upstream) > 0 and "=>" or "" },
{ entry.upstream, "TelescopeResultsIdentifier" },
{ entry.committerdate },
}
end
pickers.new(opts, {
prompt_title = "Git Branches",
finder = finders.new_table {
results = results,
entry_maker = function(entry)
entry.value = entry.name
entry.ordinal = entry.name
entry.display = make_display
return entry
end,
},
previewer = previewers.git_branch_log.new(opts),
sorter = conf.file_sorter(opts),
attach_mappings = function(_, map)
actions.select_default:replace(actions.git_checkout)
map("i", "<c-t>", actions.git_track_branch)
map("n", "<c-t>", actions.git_track_branch)
map("i", "<c-r>", actions.git_rebase_branch)
map("n", "<c-r>", actions.git_rebase_branch)
map("i", "<c-a>", actions.git_create_branch)
map("n", "<c-a>", actions.git_create_branch)
map("i", "<c-s>", actions.git_switch_branch)
map("n", "<c-s>", actions.git_switch_branch)
map("i", "<c-d>", actions.git_delete_branch)
map("n", "<c-d>", actions.git_delete_branch)
map("i", "<c-y>", actions.git_merge_branch)
map("n", "<c-y>", actions.git_merge_branch)
return true
end,
}):find()
end
git.status = function(opts)
if opts.is_bare then
utils.notify("builtin.git_status", {
msg = "This operation must be run in a work tree",
level = "ERROR",
})
return
end
local gen_new_finder = function()
local expand_dir = utils.if_nil(opts.expand_dir, true, opts.expand_dir)
local git_cmd = { "git", "status", "-s", "--", "." }
if expand_dir then
table.insert(git_cmd, #git_cmd - 1, "-u")
end
local output = utils.get_os_command_output(git_cmd, opts.cwd)
if #output == 0 then
print "No changes found"
utils.notify("builtin.git_status", {
msg = "No changes found",
level = "WARN",
})
return
end
return finders.new_table {
results = output,
entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_status(opts)),
}
end
local initial_finder = gen_new_finder()
if not initial_finder then
return
end
pickers.new(opts, {
prompt_title = "Git Status",
finder = initial_finder,
previewer = previewers.git_file_diff.new(opts),
sorter = conf.file_sorter(opts),
attach_mappings = function(prompt_bufnr, map)
actions.git_staging_toggle:enhance {
post = function()
action_state.get_current_picker(prompt_bufnr):refresh(gen_new_finder(), { reset_prompt = true })
end,
}
map("i", "<tab>", actions.git_staging_toggle)
map("n", "<tab>", actions.git_staging_toggle)
return true
end,
}):find()
end
local set_opts_cwd = function(opts)
if opts.cwd then
opts.cwd = vim.fn.expand(opts.cwd)
else
opts.cwd = vim.loop.cwd()
end
-- Find root of git directory and remove trailing newline characters
local git_root, ret = utils.get_os_command_output({ "git", "rev-parse", "--show-toplevel" }, opts.cwd)
local use_git_root = utils.get_default(opts.use_git_root, true)
if ret ~= 0 then
local in_worktree = utils.get_os_command_output({ "git", "rev-parse", "--is-inside-work-tree" }, opts.cwd)
local in_bare = utils.get_os_command_output({ "git", "rev-parse", "--is-bare-repository" }, opts.cwd)
if in_worktree[1] ~= "true" and in_bare[1] ~= "true" then
error(opts.cwd .. " is not a git directory")
elseif in_worktree[1] ~= "true" and in_bare[1] == "true" then
opts.is_bare = true
end
else
if use_git_root then
opts.cwd = git_root[1]
end
end
end
local function apply_checks(mod)
for k, v in pairs(mod) do
mod[k] = function(opts)
opts = vim.F.if_nil(opts, {})
set_opts_cwd(opts)
v(opts)
end
end
return mod
end
return apply_checks(git)

View File

@ -26,11 +26,6 @@
--- </code>
---@brief ]]
if 1 ~= vim.fn.has "nvim-0.7.0" then
vim.api.nvim_err_writeln "Telescope.nvim requires at least nvim-0.7.0. See `:h telescope.changelog-1851`"
return
end
local builtin = {}
-- Ref: https://github.com/tjdevries/lazy.nvim
@ -50,39 +45,42 @@ end
--
--
--- Search for a string and get results live as you type (respecting .gitignore)
--- Search for a string and get results live as you type, respects .gitignore
---@param opts table: options to pass to the picker
---@field cwd string: root dir to search from (default: cwd, use utils.buffer_dir() to search relative to open buffer)
---@field grep_open_files boolean: if true, restrict search to open files only, mutually exclusive with `search_dirs`
---@field search_dirs table: directory/directories to search in, mutually exclusive with `grep_open_files`
---@field glob_pattern string: argument to be used with `--glob`, e.g. "*.toml", can use the opposite "!*.toml"
---@field search_dirs table: directory/directories/files to search, mutually exclusive with `grep_open_files`
---@field glob_pattern string|table: argument to be used with `--glob`, e.g. "*.toml", can use the opposite "!*.toml"
---@field type_filter string: argument to be used with `--type`, e.g. "rust", see `rg --type-list`
---@field additional_args function: function(opts) which returns a table of additional arguments to be passed on
---@field additional_args function|table: additional arguments to be passed on. Can be fn(opts) -> tbl
---@field max_results number: define a upper result value
---@field disable_coordinates boolean: don't show the line & row numbers (default: false)
builtin.live_grep = require_on_exported_call("telescope.builtin.files").live_grep
builtin.live_grep = require_on_exported_call("telescope.builtin.__files").live_grep
--- Searches for the string under your cursor in your current working directory
---@param opts table: options to pass to the picker
---@field cwd string: root dir to search from (default: cwd, use utils.buffer_dir() to search relative to open buffer)
---@field search string: the query to search
---@field search_dirs table: directory/directories to search in
---@field grep_open_files boolean: if true, restrict search to open files only, mutually exclusive with `search_dirs`
---@field search_dirs table: directory/directories/files to search, mutually exclusive with `grep_open_files`
---@field use_regex boolean: if true, special characters won't be escaped, allows for using regex (default: false)
---@field word_match string: can be set to `-w` to enable exact word matches
---@field additional_args function: function(opts) which returns a table of additional arguments to be passed on
---@field additional_args function|table: additional arguments to be passed on. Can be fn(opts) -> tbl
---@field disable_coordinates boolean: don't show the line and row numbers (default: false)
---@field sort_only_text boolean: only sort the text, not the file, line or row (default: false)
builtin.grep_string = require_on_exported_call("telescope.builtin.files").grep_string
---@field only_sort_text boolean: only sort the text, not the file, line or row (default: false)
builtin.grep_string = require_on_exported_call("telescope.builtin.__files").grep_string
--- Search for files (respecting .gitignore)
---@param opts table: options to pass to the picker
---@field cwd string: root dir to search from (default: cwd, use utils.buffer_dir() to search relative to open buffer)
---@field find_command table: command line arguments for `find_files` to use for the search, overrides default: config
---@field find_command function|table: cmd to use for the search. Can be a fn(opts) -> tbl (default: autodetect)
---@field follow boolean: if true, follows symlinks (i.e. uses `-L` flag for the `find` command)
---@field hidden boolean: determines whether to show hidden files or not (default: false)
---@field no_ignore boolean: show files ignored by .gitignore, .ignore, etc. (default: false)
---@field search_dirs table: directory/directories to search in
builtin.find_files = require_on_exported_call("telescope.builtin.files").find_files
---@field no_ignore_parent boolean: show files ignored by .gitignore, .ignore, etc. in parent dirs. (default: false)
---@field search_dirs table: directory/directories/files to search
---@field search_file string: specify a filename to search for
builtin.find_files = require_on_exported_call("telescope.builtin.__files").find_files
--- This is an alias for the `find_files` picker
builtin.fd = builtin.find_files
@ -93,12 +91,12 @@ builtin.fd = builtin.find_files
---@field show_line boolean: if true, shows the row:column that the result is found at (default: true)
---@field bufnr number: specify the buffer number where treesitter should run. (default: current buffer)
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
builtin.treesitter = require_on_exported_call("telescope.builtin.files").treesitter
builtin.treesitter = require_on_exported_call("telescope.builtin.__files").treesitter
--- Live fuzzy search inside of the currently open buffer
---@param opts table: options to pass to the picker
---@field skip_empty_lines boolean: if true we dont display empty lines (default: false)
builtin.current_buffer_fuzzy_find = require_on_exported_call("telescope.builtin.files").current_buffer_fuzzy_find
builtin.current_buffer_fuzzy_find = require_on_exported_call("telescope.builtin.__files").current_buffer_fuzzy_find
--- Lists tags in current directory with tag location file preview (users are required to run ctags -R to generate tags
--- or update when introducing new changes)
@ -108,7 +106,7 @@ builtin.current_buffer_fuzzy_find = require_on_exported_call("telescope.builtin.
---@field show_line boolean: if true, shows the content of the line the tag is found on in the picker (default: true)
---@field only_sort_tags boolean: if true we will only sort tags (default: false)
---@field fname_width number: defines the width of the filename section (default: 30)
builtin.tags = require_on_exported_call("telescope.builtin.files").tags
builtin.tags = require_on_exported_call("telescope.builtin.__files").tags
--- Lists all of the tags for the currently open buffer, with a preview
---@param opts table: options to pass to the picker
@ -117,7 +115,7 @@ builtin.tags = require_on_exported_call("telescope.builtin.files").tags
---@field show_line boolean: if true, shows the content of the line the tag is found on in the picker (default: true)
---@field only_sort_tags boolean: if true we will only sort tags (default: false)
---@field fname_width number: defines the width of the filename section (default: 30)
builtin.current_buffer_tags = require_on_exported_call("telescope.builtin.files").current_buffer_tags
builtin.current_buffer_tags = require_on_exported_call("telescope.builtin.__files").current_buffer_tags
--
--
@ -125,17 +123,17 @@ builtin.current_buffer_tags = require_on_exported_call("telescope.builtin.files"
--
--
--- Fuzzy search for files tracked by Git. This command lists the output of the `git ls-files` command, respects
--- .gitignore, and optionally ignores untracked files
--- Fuzzy search for files tracked by Git. This command lists the output of the `git ls-files` command,
--- respects .gitignore
--- - Default keymaps:
--- - `<cr>`: opens the currently selected file
---@param opts table: options to pass to the picker
---@field cwd string: specify the path of the repo
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
---@field show_untracked boolean: if true, adds `--others` flag to command and shows untracked files (default: true)
---@field show_untracked boolean: if true, adds `--others` flag to command and shows untracked files (default: false)
---@field recurse_submodules boolean: if true, adds the `--recurse-submodules` flag to command (default: false)
---@field git_command table: command that will be exectued. {"git","ls-files","--exclude-standard","--cached"}
builtin.git_files = require_on_exported_call("telescope.builtin.git").files
builtin.git_files = require_on_exported_call("telescope.builtin.__git").files
--- Lists commits for current directory with diff preview
--- - Default keymaps:
@ -147,7 +145,7 @@ builtin.git_files = require_on_exported_call("telescope.builtin.git").files
---@field cwd string: specify the path of the repo
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
---@field git_command table: command that will be exectued. {"git","log","--pretty=oneline","--abbrev-commit","--","."}
builtin.git_commits = require_on_exported_call("telescope.builtin.git").commits
builtin.git_commits = require_on_exported_call("telescope.builtin.__git").commits
--- Lists commits for current buffer with diff preview
--- - Default keymaps or your overriden `select_` keys:
@ -160,7 +158,7 @@ builtin.git_commits = require_on_exported_call("telescope.builtin.git").commits
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
---@field current_file string: specify the current file that should be used for bcommits (default: current buffer)
---@field git_command table: command that will be exectued. {"git","log","--pretty=oneline","--abbrev-commit"}
builtin.git_bcommits = require_on_exported_call("telescope.builtin.git").bcommits
builtin.git_bcommits = require_on_exported_call("telescope.builtin.__git").bcommits
--- List branches for current directory, with output from `git log --oneline` shown in the preview window
--- - Default keymaps:
@ -174,7 +172,7 @@ builtin.git_bcommits = require_on_exported_call("telescope.builtin.git").bcommit
---@field cwd string: specify the path of the repo
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
---@field pattern string: specify the pattern to match all refs
builtin.git_branches = require_on_exported_call("telescope.builtin.git").branches
builtin.git_branches = require_on_exported_call("telescope.builtin.__git").branches
--- Lists git status for current directory
--- - Default keymaps:
@ -184,7 +182,7 @@ builtin.git_branches = require_on_exported_call("telescope.builtin.git").branche
---@field cwd string: specify the path of the repo
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
---@field git_icons table: string -> string. Matches name with icon (see source code, make_entry.lua git_icon_defaults)
builtin.git_status = require_on_exported_call("telescope.builtin.git").status
builtin.git_status = require_on_exported_call("telescope.builtin.__git").status
--- Lists stash items in current repository
--- - Default keymaps:
@ -193,7 +191,7 @@ builtin.git_status = require_on_exported_call("telescope.builtin.git").status
---@field cwd string: specify the path of the repo
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
---@field show_branch boolean: if we should display the branch name for git stash entries (default: true)
builtin.git_stash = require_on_exported_call("telescope.builtin.git").stash
builtin.git_stash = require_on_exported_call("telescope.builtin.__git").stash
--
--
@ -204,14 +202,15 @@ builtin.git_stash = require_on_exported_call("telescope.builtin.git").stash
--- Lists all of the community maintained pickers built into Telescope
---@param opts table: options to pass to the picker
---@field include_extensions boolean: if true will show the pickers of the installed extensions (default: false)
builtin.builtin = require_on_exported_call("telescope.builtin.internal").builtin
---@field use_default_opts boolean: if the selected picker should use its default options (default: false)
builtin.builtin = require_on_exported_call("telescope.builtin.__internal").builtin
--- Opens the previous picker in the identical state (incl. multi selections)
--- - Notes:
--- - Requires `cache_picker` in setup or when having invoked pickers, see |telescope.defaults.cache_picker|
---@param opts table: options to pass to the picker
---@field cache_index number: what picker to resume, where 1 denotes most recent (default: 1)
builtin.resume = require_on_exported_call("telescope.builtin.internal").resume
builtin.resume = require_on_exported_call("telescope.builtin.__internal").resume
--- Opens a picker over previously cached pickers in their preserved states (incl. multi selections)
--- - Default keymaps:
@ -219,12 +218,13 @@ builtin.resume = require_on_exported_call("telescope.builtin.internal").resume
--- - Notes:
--- - Requires `cache_picker` in setup or when having invoked pickers, see |telescope.defaults.cache_picker|
---@param opts table: options to pass to the picker
builtin.pickers = require_on_exported_call("telescope.builtin.internal").pickers
builtin.pickers = require_on_exported_call("telescope.builtin.__internal").pickers
--- Use the telescope...
---@param opts table: options to pass to the picker
---@field show_pluto boolean: we love pluto (default: false, because its a hidden feature)
builtin.planets = require_on_exported_call("telescope.builtin.internal").planets
---@field show_moon boolean: we love the moon (default: false, because its a hidden feature)
builtin.planets = require_on_exported_call("telescope.builtin.__internal").planets
--- Lists symbols inside of `data/telescope-sources/*.json` found in your runtime path
--- or found in `stdpath("data")/telescope/symbols/*.json`. The second path can be customized.
@ -234,69 +234,71 @@ builtin.planets = require_on_exported_call("telescope.builtin.internal").planets
---@param opts table: options to pass to the picker
---@field symbol_path string: specify the second path. Default: `stdpath("data")/telescope/symbols/*.json`
---@field sources table: specify a table of sources you want to load this time
builtin.symbols = require_on_exported_call("telescope.builtin.internal").symbols
builtin.symbols = require_on_exported_call("telescope.builtin.__internal").symbols
--- Lists available plugin/user commands and runs them on `<cr>`
---@param opts table: options to pass to the picker
---@field show_buf_command boolean: show buf local command (Default: true)
builtin.commands = require_on_exported_call("telescope.builtin.internal").commands
builtin.commands = require_on_exported_call("telescope.builtin.__internal").commands
--- Lists items in the quickfix list, jumps to location on `<cr>`
---@param opts table: options to pass to the picker
---@field ignore_filename boolean: dont show filenames (default: true)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field nr number: specify the quickfix list number
builtin.quickfix = require_on_exported_call("telescope.builtin.internal").quickfix
builtin.quickfix = require_on_exported_call("telescope.builtin.__internal").quickfix
--- Lists all quickfix lists in your history and open them with `builtin.quickfix`. It seems that neovim
--- only keeps the full history for 10 lists
---@param opts table: options to pass to the picker
builtin.quickfixhistory = require_on_exported_call("telescope.builtin.internal").quickfixhistory
builtin.quickfixhistory = require_on_exported_call("telescope.builtin.__internal").quickfixhistory
--- Lists items from the current window's location list, jumps to location on `<cr>`
---@param opts table: options to pass to the picker
---@field ignore_filename boolean: dont show filenames (default: true)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.loclist = require_on_exported_call("telescope.builtin.internal").loclist
---@field fname_width number: defines the width of the filename section (default: 30)
builtin.loclist = require_on_exported_call("telescope.builtin.__internal").loclist
--- Lists previously open files, opens on `<cr>`
---@param opts table: options to pass to the picker
---@field only_cwd boolean: show only files in the cwd (default: false)
---@field cwd_only boolean: alias for only_cwd
builtin.oldfiles = require_on_exported_call("telescope.builtin.internal").oldfiles
builtin.oldfiles = require_on_exported_call("telescope.builtin.__internal").oldfiles
--- Lists commands that were executed recently, and reruns them on `<cr>`
--- - Default keymaps:
--- - `<C-e>`: open the command line with the text of the currently selected result populated in it
---@param opts table: options to pass to the picker
builtin.command_history = require_on_exported_call("telescope.builtin.internal").command_history
builtin.command_history = require_on_exported_call("telescope.builtin.__internal").command_history
--- Lists searches that were executed recently, and reruns them on `<cr>`
--- - Default keymaps:
--- - `<C-e>`: open a search window with the text of the currently selected search result populated in it
---@param opts table: options to pass to the picker
builtin.search_history = require_on_exported_call("telescope.builtin.internal").search_history
builtin.search_history = require_on_exported_call("telescope.builtin.__internal").search_history
--- Lists vim options, allows you to edit the current value on `<cr>`
---@param opts table: options to pass to the picker
builtin.vim_options = require_on_exported_call("telescope.builtin.internal").vim_options
builtin.vim_options = require_on_exported_call("telescope.builtin.__internal").vim_options
--- Lists available help tags and opens a new window with the relevant help info on `<cr>`
---@param opts table: options to pass to the picker
---@field lang string: specify language (default: vim.o.helplang)
---@field fallback boolean: fallback to en if language isn't installed (default: true)
builtin.help_tags = require_on_exported_call("telescope.builtin.internal").help_tags
builtin.help_tags = require_on_exported_call("telescope.builtin.__internal").help_tags
--- Lists manpage entries, opens them in a help window on `<cr>`
---@param opts table: options to pass to the picker
---@field sections table: a list of sections to search, use `{ "ALL" }` to search in all sections (default: { "1" })
---@field man_cmd function: that returns the man command. (Default: `apropos ""` on linux, `apropos " "` on macos)
builtin.man_pages = require_on_exported_call("telescope.builtin.internal").man_pages
builtin.man_pages = require_on_exported_call("telescope.builtin.__internal").man_pages
--- Lists lua modules and reloads them on `<cr>`
---@param opts table: options to pass to the picker
---@field column_len number: define the max column len for the module name (default: dynamic, longest module name)
builtin.reloader = require_on_exported_call("telescope.builtin.internal").reloader
builtin.reloader = require_on_exported_call("telescope.builtin.__internal").reloader
--- Lists open buffers in current neovim instance, opens selected buffer on `<cr>`
---@param opts table: options to pass to the picker
@ -307,56 +309,58 @@ builtin.reloader = require_on_exported_call("telescope.builtin.internal").reload
---@field sort_lastused boolean: Sorts current and last buffer to the top and selects the lastused (default: false)
---@field sort_mru boolean: Sorts all buffers after most recent used. Not just the current and last one (default: false)
---@field bufnr_width number: Defines the width of the buffer numbers in front of the filenames (default: dynamic)
builtin.buffers = require_on_exported_call("telescope.builtin.internal").buffers
builtin.buffers = require_on_exported_call("telescope.builtin.__internal").buffers
--- Lists available colorschemes and applies them on `<cr>`
---@param opts table: options to pass to the picker
---@field enable_preview boolean: if true, will preview the selected color
builtin.colorscheme = require_on_exported_call("telescope.builtin.internal").colorscheme
builtin.colorscheme = require_on_exported_call("telescope.builtin.__internal").colorscheme
--- Lists vim marks and their value, jumps to the mark on `<cr>`
---@param opts table: options to pass to the picker
builtin.marks = require_on_exported_call("telescope.builtin.internal").marks
builtin.marks = require_on_exported_call("telescope.builtin.__internal").marks
--- Lists vim registers, pastes the contents of the register on `<cr>`
--- - Default keymaps:
--- - `<C-e>`: edit the contents of the currently selected register
---@param opts table: options to pass to the picker
builtin.registers = require_on_exported_call("telescope.builtin.internal").registers
builtin.registers = require_on_exported_call("telescope.builtin.__internal").registers
--- Lists normal mode keymappings, runs the selected keymap on `<cr>`
---@param opts table: options to pass to the picker
---@field modes table: a list of short-named keymap modes to search (default: { "n", "i", "c", "x" })
---@field show_plug boolean: if true, the keymaps for which the lhs contains "<Plug>" are also shown (default: true)
builtin.keymaps = require_on_exported_call("telescope.builtin.internal").keymaps
builtin.keymaps = require_on_exported_call("telescope.builtin.__internal").keymaps
--- Lists all available filetypes, sets currently open buffer's filetype to selected filetype in Telescope on `<cr>`
---@param opts table: options to pass to the picker
builtin.filetypes = require_on_exported_call("telescope.builtin.internal").filetypes
builtin.filetypes = require_on_exported_call("telescope.builtin.__internal").filetypes
--- Lists all available highlights
---@param opts table: options to pass to the picker
builtin.highlights = require_on_exported_call("telescope.builtin.internal").highlights
builtin.highlights = require_on_exported_call("telescope.builtin.__internal").highlights
--- Lists vim autocommands and goes to their declaration on `<cr>`
---@param opts table: options to pass to the picker
builtin.autocommands = require_on_exported_call("telescope.builtin.internal").autocommands
builtin.autocommands = require_on_exported_call("telescope.builtin.__internal").autocommands
--- Lists spelling suggestions for the current word under the cursor, replaces word with selected suggestion on `<cr>`
---@param opts table: options to pass to the picker
builtin.spell_suggest = require_on_exported_call("telescope.builtin.internal").spell_suggest
builtin.spell_suggest = require_on_exported_call("telescope.builtin.__internal").spell_suggest
--- Lists the tag stack for the current window, jumps to tag on `<cr>`
---@param opts table: options to pass to the picker
---@field ignore_filename boolean: dont show filenames (default: true)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.tagstack = require_on_exported_call("telescope.builtin.internal").tagstack
---@field fname_width number: defines the width of the filename section (default: 30)
builtin.tagstack = require_on_exported_call("telescope.builtin.__internal").tagstack
--- Lists items from Vim's jumplist, jumps to location on `<cr>`
---@param opts table: options to pass to the picker
---@field ignore_filename boolean: dont show filenames (default: true)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.jumplist = require_on_exported_call("telescope.builtin.internal").jumplist
---@field fname_width number: defines the width of the filename section (default: 30)
builtin.jumplist = require_on_exported_call("telescope.builtin.__internal").jumplist
--
--
@ -368,64 +372,83 @@ builtin.jumplist = require_on_exported_call("telescope.builtin.internal").jumpli
---@param opts table: options to pass to the picker
---@field include_declaration boolean: include symbol declaration in the lsp references (default: true)
---@field include_current_line boolean: include current line (default: false)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.lsp_references = require_on_exported_call("telescope.builtin.lsp").references
builtin.lsp_references = require_on_exported_call("telescope.builtin.__lsp").references
--- Lists LSP incoming calls for word under the cursor, jumps to reference on `<cr>`
---@param opts table: options to pass to the picker
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.lsp_incoming_calls = require_on_exported_call("telescope.builtin.__lsp").incoming_calls
--- Lists LSP outgoing calls for word under the cursor, jumps to reference on `<cr>`
---@param opts table: options to pass to the picker
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.lsp_outgoing_calls = require_on_exported_call("telescope.builtin.__lsp").outgoing_calls
--- Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope
---@param opts table: options to pass to the picker
---@field jump_type string: how to goto definition if there is only one, values: "tab", "split", "vsplit", "never"
---@field ignore_filename boolean: dont show filenames (default: true)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.lsp_definitions = require_on_exported_call("telescope.builtin.lsp").definitions
builtin.lsp_definitions = require_on_exported_call("telescope.builtin.__lsp").definitions
--- Goto the definition of the type of the word under the cursor, if there's only one,
--- otherwise show all options in Telescope
---@param opts table: options to pass to the picker
---@field jump_type string: how to goto definition if there is only one, values: "tab", "split", "vsplit", "never"
---@field ignore_filename boolean: dont show filenames (default: true)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.lsp_type_definitions = require("telescope.builtin.lsp").type_definitions
builtin.lsp_type_definitions = require("telescope.builtin.__lsp").type_definitions
--- Goto the implementation of the word under the cursor if there's only one, otherwise show all options in Telescope
---@param opts table: options to pass to the picker
---@field jump_type string: how to goto implementation if there is only one, values: "tab", "split", "vsplit", "never"
---@field ignore_filename boolean: dont show filenames (default: true)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: show results text (default: true)
---@field trim_text boolean: trim results text (default: false)
builtin.lsp_implementations = require_on_exported_call("telescope.builtin.lsp").implementations
builtin.lsp_implementations = require_on_exported_call("telescope.builtin.__lsp").implementations
--- Lists LSP document symbols in the current buffer
--- - Default keymaps:
--- - `<C-l>`: show autocompletion menu to prefilter your query by type of symbol you want to see (i.e. `:variable:`)
---@param opts table: options to pass to the picker
---@field ignore_filename boolean: dont show filenames (default: true)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: if true, shows the content of the line the tag is found on (default: false)
---@field symbols string|table: filter results by symbol kind(s)
---@field ignore_symbols string|table: list of symbols to ignore
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
builtin.lsp_document_symbols = require_on_exported_call("telescope.builtin.lsp").document_symbols
builtin.lsp_document_symbols = require_on_exported_call("telescope.builtin.__lsp").document_symbols
--- Lists LSP document symbols in the current workspace
--- - Default keymaps:
--- - `<C-l>`: show autocompletion menu to prefilter your query by type of symbol you want to see (i.e. `:variable:`)
---@param opts table: options to pass to the picker
---@field query string: for what to query the workspace (default: "")
---@field ignore_filename boolean: dont show filenames (default: false)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: if true, shows the content of the line the tag is found on (default: false)
---@field symbols string|table: filter results by symbol kind(s)
---@field ignore_symbols string|table: list of symbols to ignore
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
builtin.lsp_workspace_symbols = require_on_exported_call("telescope.builtin.lsp").workspace_symbols
builtin.lsp_workspace_symbols = require_on_exported_call("telescope.builtin.__lsp").workspace_symbols
--- Dynamically lists LSP for all workspace symbols
--- - Default keymaps:
--- - `<C-l>`: show autocompletion menu to prefilter your query by type of symbol you want to see (i.e. `:variable:`)
---@param opts table: options to pass to the picker
---@field ignore_filename boolean: dont show filenames (default: false)
---@field fname_width number: defines the width of the filename section (default: 30)
---@field show_line boolean: if true, shows the content of the line the symbol is found on (default: false)
---@field symbols string|table: filter results by symbol kind(s)
---@field ignore_symbols string|table: list of symbols to ignore
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.builtin.lsp").dynamic_workspace_symbols
builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.builtin.__lsp").dynamic_workspace_symbols
--
--
@ -439,7 +462,7 @@ builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.buil
--- - Default keymaps:
--- - `<C-l>`: show autocompletion menu to prefilter your query with the diagnostic you want to see (i.e. `:warning:`)
---@param opts table: options to pass to the picker
---@field bufnr string|number: if nil get diagnostics for all open buffers. Use 0 for current buffer
---@field bufnr number|nil: Buffer number to get diagnostics from. Use 0 for current buffer or nil for all buffers
---@field severity string|number: filter diagnostics by severity name (string) or id (number)
---@field severity_limit string|number: keep diagnostics equal or more severe wrt severity name (string) or id (number)
---@field severity_bound string|number: keep diagnostics equal or less severe wrt severity name (string) or id (number)
@ -448,7 +471,7 @@ builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.buil
---@field no_sign boolean: hide DiagnosticSigns from Results (default: false)
---@field line_width number: set length of diagnostic entry text in Results
---@field namespace number: limit your diagnostics to a specific namespace
builtin.diagnostics = require_on_exported_call("telescope.builtin.diagnostics").get
builtin.diagnostics = require_on_exported_call("telescope.builtin.__diagnostics").get
local apply_config = function(mod)
local pickers_conf = require("telescope.config").pickers

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
local strings = require "plenary.strings"
local deprecated = require "telescope.deprecated"
local sorters = require "telescope.sorters"
local if_nil = vim.F.if_nil
local os_sep = require("plenary.path").path.sep
local has_win = vim.fn.has "win32" == 1
@ -69,7 +68,7 @@ config.descriptions = {}
config.pickers = _TelescopeConfigurationPickers
function config.set_pickers(pickers)
pickers = if_nil(pickers, {})
pickers = vim.F.if_nil(pickers, {})
for k, v in pairs(pickers) do
config.pickers[k] = v
@ -153,25 +152,6 @@ append(
- "ascending"]]
)
append(
"tiebreak",
function(current_entry, existing_entry, _)
return #current_entry.ordinal < #existing_entry.ordinal
end,
[[
A function that determines how to break a tie when two entries have
the same score.
Having a function that always returns false would keep the entries in
the order they are found, so existing_entry before current_entry.
Vice versa always returning true would place the current_entry
before the existing_entry.
Signature: function(current_entry, existing_entry, prompt) -> boolean
Default: function that breaks the tie based on the length of the
entry's ordinal]]
)
append(
"selection_strategy",
"reset",
@ -182,7 +162,8 @@ append(
- "reset" (default)
- "follow"
- "row"
- "closest"]]
- "closest"
- "none"]]
)
append(
@ -442,6 +423,28 @@ append(
Default: "Prompt"]]
)
append(
"mappings",
{},
[[
Your mappings to override telescope's default mappings.
See: ~
|telescope.mappings|
]]
)
append(
"default_mappings",
nil,
[[
Not recommended to use except for advanced users.
Will allow you to completely remove all of telescope's default maps
and use your own.
]]
)
append(
"history",
{
@ -593,8 +596,17 @@ append(
highlighting, which falls back to regex-based highlighting.
`true`: treesitter highlighting for all available filetypes
`false`: regex-based highlighting for all filetypes
`table`: table of filetypes for which to attach treesitter
highlighting
`table`: following nvim-treesitters highlighting options:
It contains two keys:
- enable boolean|table: if boolean, enable all ts
highlighing with that flag,
disable still considered.
Containing a list of filetypes,
that are enabled, disabled
ignored because it doesnt make
any sense in this case.
- disable table: containing a list of filetypes
that are disabled
Default: true
- msg_bg_fillchar: Character to fill background of unpreviewable buffers with
Default: ""
@ -653,91 +665,12 @@ append(
true,
[[
Boolean if devicons should be enabled or not. If set to false, the
"TelescopeResultsFileIcon" highlight group is used.
text highlight group is used.
Hint: Coloring only works if |termguicolors| is enabled.
Default: true]]
)
append(
"mappings",
{},
[[
Your mappings to override telescope's default mappings.
Format is:
{
mode = { ..keys }
}
where {mode} is the one character letter for a mode
('i' for insert, 'n' for normal).
For example:
mappings = {
i = {
["<esc>"] = require('telescope.actions').close,
},
}
To disable a keymap, put [map] = false
So, to not map "<C-n>", just put
...,
["<C-n>"] = false,
...,
Into your config.
otherwise, just set the mapping to the function that you want it to
be.
...,
["<C-i>"] = require('telescope.actions').select_default,
...,
If the function you want is part of `telescope.actions`, then you can
simply give a string.
For example, the previous option is equivalent to:
...,
["<C-i>"] = "select_default",
...,
You can also add other mappings using tables with `type = "command"`.
For example:
...,
["jj"] = { "<esc>", type = "command" },
["kk"] = { "<cmd>echo \"Hello, World!\"<cr>", type = "command" },)
...,
You can also add additional options for mappings of any type
("action" and "command"). For example:
...,
["<C-j>"] = {
action = actions.move_selection_next,
opts = { nowait = true, silent = true }
},
...,
]]
)
append(
"default_mappings",
nil,
[[
Not recommended to use except for advanced users.
Will allow you to completely remove all of telescope's default maps
and use your own.
]]
)
append(
"file_sorter",
sorters.get_fzy_sorter,
@ -774,6 +707,25 @@ append(
Default: require("telescope.sorters").prefilter]]
)
append(
"tiebreak",
function(current_entry, existing_entry, _)
return #current_entry.ordinal < #existing_entry.ordinal
end,
[[
A function that determines how to break a tie when two entries have
the same score.
Having a function that always returns false would keep the entries in
the order they are found, so existing_entry before current_entry.
Vice versa always returning true would place the current_entry
before the existing_entry.
Signature: function(current_entry, existing_entry, prompt) -> boolean
Default: function that breaks the tie based on the length of the
entry's ordinal]]
)
append(
"file_ignore_patterns",
nil,
@ -783,10 +735,35 @@ append(
Example: { "%.npz" } -- ignore all npz files
See: https://www.lua.org/manual/5.1/manual.html#5.4.1 for more
information about lua regex
Note: `file_ignore_patterns` will be used in all pickers that have a
file associated. This might lead to the problem that lsp_ pickers
aren't displaying results because they might be ignored by
`file_ignore_patterns`. For example, setting up node_modules as ignored
will never show node_modules in any results, even if you are
interested in lsp_ results.
If you only want `file_ignore_patterns` for `find_files` and
`grep_string`/`live_grep` it is suggested that you setup `gitignore`
and have fd and or ripgrep installed because both tools will not show
`gitignore`d files on default.
Default: nil]]
)
append(
"get_selection_window",
function()
return 0
end,
[[
Function that takes function(picker, entry) and returns a window id.
The window ID will be used to decide what window the chosen file will
be opened in and the cursor placed in upon leaving the picker.
Default: `function() return 0 end`
]]
)
append(
"file_previewer",
function(...)
@ -851,8 +828,8 @@ append(
-- @param tele_defaults table: (optional) a table containing all of the defaults
-- for telescope [defaults to `telescope_defaults`]
function config.set_defaults(user_defaults, tele_defaults)
user_defaults = if_nil(user_defaults, {})
tele_defaults = if_nil(tele_defaults, telescope_defaults)
user_defaults = vim.F.if_nil(user_defaults, {})
tele_defaults = vim.F.if_nil(tele_defaults, telescope_defaults)
-- Check if using layout keywords outside of `layout_config`
deprecated.options(user_defaults)
@ -860,18 +837,21 @@ function config.set_defaults(user_defaults, tele_defaults)
local function get(name, default_val)
if name == "layout_config" then
return smarter_depth_2_extend(
if_nil(user_defaults[name], {}),
vim.tbl_deep_extend("keep", if_nil(config.values[name], {}), if_nil(default_val, {}))
vim.F.if_nil(user_defaults[name], {}),
vim.tbl_deep_extend("keep", vim.F.if_nil(config.values[name], {}), vim.F.if_nil(default_val, {}))
)
end
if name == "history" or name == "cache_picker" or name == "preview" then
if user_defaults[name] == false or config.values[name] == false then
return false
end
if user_defaults[name] == true then
return vim.F.if_nil(config.values[name], {})
end
return smarter_depth_2_extend(
if_nil(user_defaults[name], {}),
vim.tbl_deep_extend("keep", if_nil(config.values[name], {}), if_nil(default_val, {}))
vim.F.if_nil(user_defaults[name], {}),
vim.tbl_deep_extend("keep", vim.F.if_nil(config.values[name], {}), vim.F.if_nil(default_val, {}))
)
end
return first_non_null(user_defaults[name], config.values[name], default_val)
@ -881,9 +861,7 @@ function config.set_defaults(user_defaults, tele_defaults)
assert(description, "Config values must always have a description")
config.values[name] = get(name, default_val)
if description then
config.descriptions[name] = strings.dedent(description)
end
config.descriptions[name] = strings.dedent(description)
end
for key, info in pairs(tele_defaults) do

View File

@ -91,8 +91,6 @@ That's the next step to scrolling.
--]]
local get_default = require("telescope.utils").get_default
local resolver = {}
local _resolve_map = {}
@ -129,9 +127,6 @@ end] = function(selector, val)
end
end
-- Tables TODO:
-- ... {70, max}
-- function:
-- Function must have same signature as get_window_layout
-- function(self, max_columns, max_lines): number
@ -143,6 +138,26 @@ end] = function(_, val)
return val
end
_resolve_map[function(val)
return type(val) == "table" and val["max"] ~= nil and val[1] ~= nil and val[1] >= 0 and val[1] < 1
end] =
function(selector, val)
return function(...)
local selected = select(selector, ...)
return math.min(math.floor(val[1] * selected), val["max"])
end
end
_resolve_map[function(val)
return type(val) == "table" and val["min"] ~= nil and val[1] ~= nil and val[1] >= 0 and val[1] < 1
end] =
function(selector, val)
return function(...)
local selected = select(selector, ...)
return math.max(math.floor(val[1] * selected), val["min"])
end
end
-- Add padding option
_resolve_map[function(val)
return type(val) == "table" and val["padding"] ~= nil
@ -164,7 +179,7 @@ end] = function(selector, val)
end
--- Converts input to a function that returns the height.
--- The input must take one of four forms:
--- The input must take one of five forms:
--- 1. 0 <= number < 1 <br>
--- This means total height as a percentage.
--- 2. 1 <= number <br>
@ -172,7 +187,10 @@ end
--- 3. function <br>
--- Must have signature:
--- function(self, max_columns, max_lines): number
--- 4. table of the form: {padding = `foo`} <br>
--- 4. table of the form: { val, max = ..., min = ... } <br>
--- val has to be in the first form 0 <= val < 1 and only one is given,
--- `min` or `max` as fixed number
--- 5. table of the form: {padding = `foo`} <br>
--- where `foo` has one of the previous three forms. <br>
--- The height is then set to be the remaining space after padding.
--- For example, if the window has height 50, and the input is {padding = 5},
@ -190,7 +208,7 @@ resolver.resolve_height = function(val)
end
--- Converts input to a function that returns the width.
--- The input must take one of four forms:
--- The input must take one of five forms:
--- 1. 0 <= number < 1 <br>
--- This means total width as a percentage.
--- 2. 1 <= number <br>
@ -198,7 +216,10 @@ end
--- 3. function <br>
--- Must have signature:
--- function(self, max_columns, max_lines): number
--- 4. table of the form: {padding = `foo`} <br>
--- 4. table of the form: { val, max = ..., min = ... } <br>
--- val has to be in the first form 0 <= val < 1 and only one is given,
--- `min` or `max` as fixed number
--- 5. table of the form: {padding = `foo`} <br>
--- where `foo` has one of the previous three forms. <br>
--- The width is then set to be the remaining space after padding.
--- For example, if the window has width 100, and the input is {padding = 5},
@ -286,9 +307,9 @@ resolver.win_option = function(val, default)
end
return {
preview = get_default(val.preview, val_to_set),
results = get_default(val.results, val_to_set),
prompt = get_default(val.prompt, val_to_set),
preview = vim.F.if_nil(val.preview, val_to_set),
results = vim.F.if_nil(val.results, val_to_set),
prompt = vim.F.if_nil(val.prompt, val_to_set),
}
end
end

View File

@ -44,7 +44,7 @@ function JobFinder:new(opts)
assert(not opts.static, "`static` should be used with finder.new_oneshot_job")
local obj = setmetatable({
entry_maker = opts.entry_maker or make_entry.gen_from_string,
entry_maker = opts.entry_maker or make_entry.gen_from_string(opts),
fn_command = opts.fn_command,
cwd = opts.cwd,
writer = opts.writer,
@ -122,7 +122,7 @@ function DynamicFinder:new(opts)
local obj = setmetatable({
curr_buf = opts.curr_buf,
fn = opts.fn,
entry_maker = opts.entry_maker or make_entry.gen_from_string,
entry_maker = opts.entry_maker or make_entry.gen_from_string(opts),
}, self)
return obj
@ -180,7 +180,7 @@ finders.new_oneshot_job = function(command_list, opts)
local command = table.remove(command_list, 1)
return async_oneshot_finder {
entry_maker = opts.entry_maker or make_entry.gen_from_string(),
entry_maker = opts.entry_maker or make_entry.gen_from_string(opts),
cwd = opts.cwd,
maximum_results = opts.maximum_results,

View File

@ -6,7 +6,7 @@ local log = require "telescope.log"
return function(opts)
log.trace("Creating async_job:", opts)
local entry_maker = opts.entry_maker or make_entry.gen_from_string()
local entry_maker = opts.entry_maker or make_entry.gen_from_string(opts)
local fn_command = function(prompt)
local command_list = opts.command_generator(prompt)

View File

@ -9,7 +9,7 @@ local await_count = 1000
return function(opts)
opts = opts or {}
local entry_maker = opts.entry_maker or make_entry.gen_from_string
local entry_maker = opts.entry_maker or make_entry.gen_from_string(opts)
local cwd = opts.cwd
local env = opts.env
local fn_command = assert(opts.fn_command, "Must pass `fn_command`")
@ -30,6 +30,7 @@ return function(opts)
end
end,
results = results,
entry_maker = entry_maker,
}, {
__call = function(_, prompt, process_result, process_complete)
if not job_started then

View File

@ -10,7 +10,7 @@ return function(opts)
input_results = opts.results
end
local entry_maker = opts.entry_maker or make_entry.gen_from_string()
local entry_maker = opts.entry_maker or make_entry.gen_from_string(opts)
local results = {}
for k, v in ipairs(input_results) do
@ -24,6 +24,7 @@ return function(opts)
return setmetatable({
results = results,
entry_maker = entry_maker,
close = function() end,
}, {
__call = function(_, _, process_result, process_complete)

View File

@ -12,13 +12,7 @@ local from_entry = {}
function from_entry.path(entry, validate, escape)
escape = vim.F.if_nil(escape, true)
local path
if escape then
path = entry.path and vim.fn.fnameescape(entry.path) or nil
else
path = entry.path
end
local path = entry.path
if path == nil then
path = entry.filename
end
@ -30,10 +24,20 @@ function from_entry.path(entry, validate, escape)
return
end
if validate and not vim.fn.filereadable(path) then
return
-- only 0 if neither filereadable nor directory
if validate then
-- We need to expand for filereadable and isdirectory
-- TODO(conni2461): we are not going to return the expanded path because
-- this would lead to cache misses in the perviewer.
-- Requires overall refactoring in previewer interface
local expanded = vim.fn.expand(path)
if (vim.fn.filereadable(expanded) + vim.fn.isdirectory(expanded)) == 0 then
return
end
end
if escape then
return vim.fn.fnameescape(path)
end
return path
end

View File

@ -1,4 +1,4 @@
local health = require "health"
local health = vim.health or require "health"
local extension_module = require "telescope._extensions"
local extension_info = require("telescope").extensions
local is_win = vim.api.nvim_call_function("has", { "win32" }) == 1

View File

@ -13,7 +13,7 @@ local telescope = {}
---
--- Getting started with telescope:
--- 1. Run `:checkhealth telescope` to make sure everything is installed.
--- 2. Evalulate it working with
--- 2. Evaluate it working with
--- `:Telescope find_files` or
--- `:lua require("telescope.builtin").find_files()`
--- 3. Put a `require("telescope").setup() call somewhere in your neovim config.
@ -90,6 +90,7 @@ local telescope = {}
---@brief ]]
---@tag telescope.nvim
---@config { ["name"] = "INTRODUCTION" }
--- Setup function to be run by user. Configures the defaults, pickers and
--- extensions of telescope.
@ -134,12 +135,6 @@ function telescope.setup(opts)
_extensions.set_config(opts.extensions)
end
--- Register an extension. To be used by plugin authors.
---@param mod table: Module
function telescope.register_extension(mod)
return _extensions.register(mod)
end
--- Load an extension.
--- - Notes:
--- - Loading triggers ext setup via the config passed in |telescope.setup|
@ -148,6 +143,12 @@ function telescope.load_extension(name)
return _extensions.load(name)
end
--- Register an extension. To be used by plugin authors.
---@param mod table: Module
function telescope.register_extension(mod)
return _extensions.register(mod)
end
--- Use telescope.extensions to reference any extensions within your configuration. <br>
--- While the docs currently generate this as a function, it's actually a table. Sorry.
telescope.extensions = require("telescope._extensions").manager

View File

@ -1,3 +1,40 @@
---@tag telescope.make_entry
---@brief [[
---
--- Each picker has a finder made up of two parts, the results which are the
--- data to be displayed, and the entry_maker. These entry_makers are functions
--- returned from make_entry functions. These will be referrd to as
--- entry_makers in the following documentation.
---
--- Every entry maker returns a function which accepts the data to be used for
--- an entry. This function will return an entry table (or nil, meaning skip
--- this entry) which contains of the - following important keys:
--- - value any: value key can be anything but still required
--- - valid bool: is an optional key because it defaults to true but if the key
--- is set to false it will not be displayed by the picker. (optional)
--- - ordinal string: is the text that is used for filtering (required)
--- - display string|function: is either a string of the text that is being
--- displayed or a function receiving the entry at a later stage, when the entry
--- is actually being displayed. A function can be useful here if complex
--- calculation have to be done. `make_entry` can also return a second value
--- a highlight array which will then apply to the line. Highlight entry in
--- this array has the following signature `{ { start_col, end_col }, hl_group }`
--- (required).
--- - filename string: will be interpreted by the default `<cr>` action as
--- open this file (optional)
--- - bufnr number: will be interpreted by the default `<cr>` action as open
--- this buffer (optional)
--- - lnum number: lnum value which will be interpreted by the default `<cr>`
--- action as a jump to this line (optional)
--- - col number: col value which will be interpreted by the default `<cr>`
--- action as a jump to this column (optional)
---
--- More information on easier displaying, see |telescope.pickers.entry_display|
---
--- TODO: Document something we call `entry_index`
---@brief ]]
local entry_display = require "telescope.pickers.entry_display"
local utils = require "telescope.utils"
local strings = require "plenary.strings"
@ -26,8 +63,55 @@ local lsp_type_highlight = {
["Variable"] = "TelescopeResultsVariable",
}
local get_filename_fn = function()
local bufnr_name_cache = {}
return function(bufnr)
bufnr = vim.F.if_nil(bufnr, 0)
local c = bufnr_name_cache[bufnr]
if c then
return c
end
local n = vim.api.nvim_buf_get_name(bufnr)
bufnr_name_cache[bufnr] = n
return n
end
end
local handle_entry_index = function(opts, t, k)
local override = ((opts or {}).entry_index or {})[k]
if not override then
return
end
local val, save = override(t, opts)
if save then
rawset(t, k, val)
end
return val
end
local make_entry = {}
make_entry.set_default_entry_mt = function(tbl, opts)
return setmetatable({}, {
__index = function(t, k)
local override = handle_entry_index(opts, t, k)
if override then
return override
end
-- Only hit tbl once
local val = tbl[k]
if val then
rawset(t, k, val)
end
return val
end,
})
end
do
local lookup_keys = {
display = 1,
@ -35,13 +119,18 @@ do
value = 1,
}
local mt_string_entry = {
__index = function(t, k)
return rawget(t, rawget(lookup_keys, k))
end,
}
function make_entry.gen_from_string(opts)
local mt_string_entry = {
__index = function(t, k)
local override = handle_entry_index(opts, t, k)
if override then
return override
end
return rawget(t, rawget(lookup_keys, k))
end,
}
function make_entry.gen_from_string()
return function(line)
return setmetatable({
line,
@ -82,6 +171,11 @@ do
end
mt_file_entry.__index = function(t, k)
local override = handle_entry_index(opts, t, k)
if override then
return override
end
local raw = rawget(mt_file_entry, k)
if raw then
return raw
@ -111,7 +205,7 @@ do
}
-- Gets called only once to parse everything out for the vimgrep, after that looks up directly.
local parse = function(t)
local parse_with_col = function(t)
local _, _, filename, lnum, col, text = string.find(t.value, [[(..-):(%d+):(%d+):(.*)]])
local ok
@ -133,14 +227,32 @@ do
return { filename, lnum, col, text }
end
--- Special options:
--- - disable_coordinates: Don't show the line & row numbers
--- - only_sort_text: Only sort via the text. Ignore filename and other items
function make_entry.gen_from_vimgrep(opts)
local mt_vimgrep_entry
local parse_without_col = function(t)
local _, _, filename, lnum, text = string.find(t.value, [[(..-):(%d+):(.*)]])
local ok
ok, lnum = pcall(tonumber, lnum)
if not ok then
lnum = nil
end
t.filename = filename
t.lnum = lnum
t.col = nil
t.text = text
return { filename, lnum, nil, text }
end
function make_entry.gen_from_vimgrep(opts)
opts = opts or {}
local mt_vimgrep_entry
local parse = parse_with_col
if opts.__inverted == true then
parse = parse_without_col
end
local disable_devicons = opts.disable_devicons
local disable_coordinates = opts.disable_coordinates
local only_sort_text = opts.only_sort_text
@ -188,7 +300,11 @@ do
local coordinates = ""
if not disable_coordinates then
coordinates = string.format("%s:%s:", entry.lnum, entry.col)
if entry.col then
coordinates = string.format("%s:%s:", entry.lnum, entry.col)
else
coordinates = string.format("%s:", entry.lnum)
end
end
local display, hl_group = utils.transform_devicons(
@ -205,6 +321,11 @@ do
end,
__index = function(t, k)
local override = handle_entry_index(opts, t, k)
if override then
return override
end
local raw = rawget(mt_vimgrep_entry, k)
if raw then
return raw
@ -257,13 +378,13 @@ function make_entry.gen_from_git_stash(opts)
local _, branch_name = string.match(splitted[2], "^([WIP on|On]+) (.+)")
local commit_info = splitted[3]
return {
return make_entry.set_default_entry_mt({
value = stash_idx,
ordinal = commit_info,
branch_name = branch_name,
commit_info = commit_info,
display = make_display,
}
}, opts)
end
end
@ -297,52 +418,61 @@ function make_entry.gen_from_git_commits(opts)
msg = "<empty commit message>"
end
return {
return make_entry.set_default_entry_mt({
value = sha,
ordinal = sha .. " " .. msg,
msg = msg,
display = make_display,
current_file = opts.current_file,
}
}, opts)
end
end
function make_entry.gen_from_quickfix(opts)
opts = opts or {}
local show_line = vim.F.if_nil(opts.show_line, true)
local displayer = entry_display.create {
separator = "",
items = {
{ width = 8 },
{ width = 0.45 },
{ remaining = true },
},
local hidden = utils.is_path_hidden(opts)
local items = {
{ width = vim.F.if_nil(opts.fname_width, 30) },
{ remaining = true },
}
local make_display = function(entry)
local filename = utils.transform_path(opts, entry.filename)
local line_info = { table.concat({ entry.lnum, entry.col }, ":"), "TelescopeResultsLineNr" }
if opts.trim_text then
entry.text = entry.text:gsub("^%s*(.-)%s*$", "%1")
end
return displayer {
line_info,
entry.text:gsub(".* | ", ""),
filename,
}
if hidden then
items[1] = { width = 8 }
end
if not show_line then
table.remove(items, 1)
end
local displayer = entry_display.create { separator = "", items = items }
local make_display = function(entry)
local input = {}
if not hidden then
table.insert(input, string.format("%s:%d:%d", utils.transform_path(opts, entry.filename), entry.lnum, entry.col))
else
table.insert(input, string.format("%4d:%2d", entry.lnum, entry.col))
end
if show_line then
local text = entry.text
if opts.trim_text then
text = text:gsub("^%s*(.-)%s*$", "%1")
end
text = text:gsub(".* | ", "")
table.insert(input, text)
end
return displayer(input)
end
local get_filename = get_filename_fn()
return function(entry)
local filename = entry.filename or vim.api.nvim_buf_get_name(entry.bufnr)
return {
valid = true,
local filename = vim.F.if_nil(entry.filename, get_filename(entry.bufnr))
return make_entry.set_default_entry_mt({
value = entry,
ordinal = (not opts.ignore_filename and filename or "") .. " " .. entry.text,
ordinal = (not hidden and filename or "") .. " " .. entry.text,
display = make_display,
bufnr = entry.bufnr,
@ -352,7 +482,7 @@ function make_entry.gen_from_quickfix(opts)
text = entry.text,
start = entry.start,
finish = entry.finish,
}
}, opts)
end
end
@ -361,14 +491,22 @@ function make_entry.gen_from_lsp_symbols(opts)
local bufnr = opts.bufnr or vim.api.nvim_get_current_buf()
-- Default we have two columns, symbol and type(unbound)
-- If path is not hidden then its, filepath, symbol and type(still unbound)
-- If show_line is also set, type is bound to len 8
local display_items = {
{ width = opts.symbol_width or 25 }, -- symbol
{ width = opts.symbol_type_width or 8 }, -- symbol type
{ remaining = true }, -- filename{:optional_lnum+col} OR content preview
{ width = opts.symbol_width or 25 },
{ remaining = true },
}
if opts.ignore_filename and opts.show_line then
table.insert(display_items, 2, { width = 6 })
local hidden = utils.is_path_hidden(opts)
if not hidden then
table.insert(display_items, 1, { width = vim.F.if_nil(opts.fname_width, 30) })
end
if opts.show_line then
-- bound type to len 8 or custom
table.insert(display_items, #display_items, { width = opts.symbol_type_width or 8 })
end
local displayer = entry_display.create {
@ -376,51 +514,42 @@ function make_entry.gen_from_lsp_symbols(opts)
hl_chars = { ["["] = "TelescopeBorder", ["]"] = "TelescopeBorder" },
items = display_items,
}
local type_highlight = vim.F.if_nil(opts.symbol_highlights or lsp_type_highlight)
local make_display = function(entry)
local msg
-- what to show in the last column: filename or symbol information
if opts.ignore_filename then -- ignore the filename and show line preview instead
-- TODO: fixme - if ignore_filename is set for workspace, bufnr will be incorrect
msg = vim.api.nvim_buf_get_lines(bufnr, entry.lnum - 1, entry.lnum, false)[1] or ""
msg = vim.trim(msg)
if opts.show_line then
msg = vim.trim(vim.F.if_nil(vim.api.nvim_buf_get_lines(bufnr, entry.lnum - 1, entry.lnum, false)[1], ""))
end
if hidden then
return displayer {
entry.symbol_name,
{ entry.symbol_type:lower(), type_highlight[entry.symbol_type] },
msg,
}
else
local filename = utils.transform_path(opts, entry.filename)
if opts.show_line then -- show inline line info
filename = filename .. " [" .. entry.lnum .. ":" .. entry.col .. "]"
end
msg = filename
return displayer {
utils.transform_path(opts, entry.filename),
entry.symbol_name,
{ entry.symbol_type:lower(), type_highlight[entry.symbol_type] },
msg,
}
end
local type_highlight = opts.symbol_highlights or lsp_type_highlight
local display_columns = {
entry.symbol_name,
{ entry.symbol_type:lower(), type_highlight[entry.symbol_type], type_highlight[entry.symbol_type] },
msg,
}
if opts.ignore_filename and opts.show_line then
table.insert(display_columns, 2, { entry.lnum .. ":" .. entry.col, "TelescopeResultsLineNr" })
end
return displayer(display_columns)
end
local get_filename = get_filename_fn()
return function(entry)
local filename = entry.filename or vim.api.nvim_buf_get_name(entry.bufnr)
local filename = vim.F.if_nil(entry.filename, get_filename(entry.bufnr))
local symbol_msg = entry.text
local symbol_type, symbol_name = symbol_msg:match "%[(.+)%]%s+(.*)"
local ordinal = ""
if not opts.ignore_filename and filename then
if not hidden and filename then
ordinal = filename .. " "
end
ordinal = ordinal .. symbol_name .. " " .. (symbol_type or "unknown")
return {
valid = true,
return make_entry.set_default_entry_mt({
value = entry,
ordinal = ordinal,
display = make_display,
@ -432,7 +561,7 @@ function make_entry.gen_from_lsp_symbols(opts)
symbol_type = symbol_type,
start = entry.start,
finish = entry.finish,
}
}, opts)
end
end
@ -460,8 +589,9 @@ function make_entry.gen_from_buffer(opts)
local cwd = vim.fn.expand(opts.cwd or vim.loop.cwd())
local make_display = function(entry)
-- bufnr_width + modes + icon + 3 spaces + : + lnum
opts.__prefix = opts.bufnr_width + 4 + icon_width + 3 + 1 + #tostring(entry.lnum)
local display_bufname = utils.transform_path(opts, entry.filename)
local icon, hl_group = utils.get_devicons(entry.filename, disable_devicons)
return displayer {
@ -483,9 +613,7 @@ function make_entry.gen_from_buffer(opts)
local indicator = entry.flag .. hidden .. readonly .. changed
local line_count = vim.api.nvim_buf_line_count(entry.bufnr)
return {
valid = true,
return make_entry.set_default_entry_mt({
value = bufname,
ordinal = entry.bufnr .. " : " .. bufname,
display = make_display,
@ -495,7 +623,7 @@ function make_entry.gen_from_buffer(opts)
-- account for potentially stale lnum as getbufinfo might not be updated or from resuming buffers picker
lnum = entry.info.lnum ~= 0 and math.max(math.min(entry.info.lnum, line_count), 1) or 1,
indicator = indicator,
}
}, opts)
end
end
@ -537,13 +665,12 @@ function make_entry.gen_from_treesitter(opts)
return displayer(display_columns)
end
local get_filename = get_filename_fn()
return function(entry)
local ts_utils = require "nvim-treesitter.ts_utils"
local start_row, start_col, end_row, _ = ts_utils.get_node_range(entry.node)
local node_text = vim.treesitter.get_node_text(entry.node, bufnr)
return {
valid = true,
return make_entry.set_default_entry_mt({
value = entry.node,
kind = entry.kind,
ordinal = node_text .. " " .. (entry.kind or "unknown"),
@ -551,14 +678,14 @@ function make_entry.gen_from_treesitter(opts)
node_text = node_text,
filename = vim.api.nvim_buf_get_name(bufnr),
filename = get_filename(bufnr),
-- need to add one since the previewer substacts one
lnum = start_row + 1,
col = start_col,
text = node_text,
start = start_row,
finish = end_row,
}
}, opts)
end
end
@ -573,14 +700,12 @@ function make_entry.gen_from_packages(opts)
end
return function(module_name)
local entry = {
return make_entry.set_default_entry_mt({
valid = module_name ~= "",
value = module_name,
ordinal = module_name,
}
entry.display = make_display(module_name)
return entry
display = make_display(module_name),
}, opts)
end
end
@ -622,38 +747,33 @@ function make_entry.gen_from_apropos(opts)
cmd = vim.split(cmd, ",")[1]
return keyword
and sections[section]
and {
and make_entry.set_default_entry_mt({
value = cmd,
description = desc,
ordinal = cmd,
display = make_display,
section = section,
keyword = keyword,
}
}, opts)
or nil
end
end
function make_entry.gen_from_marks(_)
return function(line)
local split_value = utils.max_split(line, "%s+", 4)
local mark_value = split_value[1]
local cursor_position = vim.fn.getpos("'" .. mark_value)
return {
value = line,
ordinal = line,
display = line,
lnum = cursor_position[2],
col = cursor_position[3],
start = cursor_position[2],
filename = vim.api.nvim_buf_get_name(cursor_position[1]),
}
function make_entry.gen_from_marks(opts)
return function(item)
return make_entry.set_default_entry_mt({
value = item.line,
ordinal = item.line,
display = item.line,
lnum = item.lnum,
col = item.col,
start = item.lnum,
filename = item.filename,
}, opts)
end
end
function make_entry.gen_from_registers(_)
function make_entry.gen_from_registers(opts)
local displayer = entry_display.create {
separator = " ",
hl_chars = { ["["] = "TelescopeBorder", ["]"] = "TelescopeBorder" },
@ -672,13 +792,13 @@ function make_entry.gen_from_registers(_)
end
return function(entry)
return {
valid = true,
local contents = vim.fn.getreg(entry)
return make_entry.set_default_entry_mt({
value = entry,
ordinal = entry,
content = vim.fn.getreg(entry),
ordinal = string.format("%s %s", entry, contents),
content = contents,
display = make_display,
}
}, opts)
end
end
@ -711,7 +831,7 @@ function make_entry.gen_from_keymaps(opts)
end
return function(entry)
return {
return make_entry.set_default_entry_mt({
mode = entry.mode,
lhs = get_lhs(entry),
desc = get_desc(entry),
@ -720,22 +840,22 @@ function make_entry.gen_from_keymaps(opts)
value = entry,
ordinal = entry.mode .. " " .. get_lhs(entry) .. " " .. get_desc(entry),
display = make_display,
}
}, opts)
end
end
function make_entry.gen_from_highlights()
function make_entry.gen_from_highlights(opts)
local make_display = function(entry)
local display = entry.value
return display, { { { 0, #display }, display } }
end
return function(entry)
return {
return make_entry.set_default_entry_mt({
value = entry,
display = make_display,
ordinal = entry,
}
}, opts)
end
end
@ -756,12 +876,12 @@ function make_entry.gen_from_picker(opts)
end
return function(entry)
return {
return make_entry.set_default_entry_mt({
value = entry,
text = entry.prompt_title,
ordinal = string.format("%s %s", entry.prompt_title, utils.get_default(entry.default_text, "")),
ordinal = string.format("%s %s", entry.prompt_title, vim.F.if_nil(entry.default_text, "")),
display = make_display,
}
}, opts)
end
end
@ -804,117 +924,61 @@ function make_entry.gen_from_buffer_lines(opts)
return
end
return {
valid = true,
return make_entry.set_default_entry_mt({
ordinal = entry.text,
display = make_display,
filename = entry.filename,
lnum = entry.lnum,
text = entry.text,
}
}, opts)
end
end
function make_entry.gen_from_vimoptions()
local process_one_opt = function(o)
local ok, value_origin
local option = {
name = "",
description = "",
current_value = "",
default_value = "",
value_type = "",
set_by_user = false,
last_set_from = "",
}
local is_global = false
for _, v in ipairs(o.scope) do
if v == "global" then
is_global = true
end
end
if not is_global then
return
end
if is_global then
option.name = o.full_name
ok, option.current_value = pcall(vim.api.nvim_get_option, o.full_name)
if not ok then
return
end
local str_funcname = o.short_desc()
option.description = assert(loadstring(str_funcname))()
-- if #option.description > opts.desc_col_length then
-- opts.desc_col_length = #option.description
-- end
if o.defaults ~= nil then
option.default_value = o.defaults.if_true.vim or o.defaults.if_true.vi
end
if type(option.default_value) == "function" then
option.default_value = "Macro: " .. option.default_value()
end
option.value_type = (type(option.current_value) == "boolean" and "bool" or type(option.current_value))
if option.current_value ~= option.default_value then
option.set_by_user = true
value_origin = vim.fn.execute("verbose set " .. o.full_name .. "?")
if string.match(value_origin, "Last set from") then
-- TODO: parse file and line number as separate items
option.last_set_from = value_origin:gsub("^.*Last set from ", "")
end
end
return option
end
end
function make_entry.gen_from_vimoptions(opts)
local displayer = entry_display.create {
separator = "",
hl_chars = { ["["] = "TelescopeBorder", ["]"] = "TelescopeBorder" },
items = {
{ width = 25 },
{ width = 12 },
{ width = 11 },
{ remaining = true },
},
}
local make_display = function(entry)
return displayer {
{ entry.name, "Keyword" },
{ "[" .. entry.value_type .. "]", "Type" },
utils.display_termcodes(tostring(entry.current_value)),
entry.description,
{ entry.value.name, "Keyword" },
{ "[" .. entry.value.type .. "]", "Type" },
{ "[" .. entry.value.scope .. "]", "Identifier" },
utils.display_termcodes(tostring(entry.value.value)),
}
end
return function(line)
local entry = process_one_opt(line)
if not entry then
return
return function(o)
local entry = {
display = make_display,
value = {
name = o.name,
value = o.default,
type = o.type,
scope = o.scope,
},
ordinal = string.format("%s %s %s", o.name, o.type, o.scope),
}
local ok, value = pcall(vim.api.nvim_get_option, o.name)
if ok then
entry.value.value = value
entry.ordinal = entry.ordinal .. " " .. utils.display_termcodes(tostring(value))
else
entry.ordinal = entry.ordinal .. " " .. utils.display_termcodes(tostring(o.default))
end
entry.valid = true
entry.display = make_display
entry.value = line
entry.ordinal = line.full_name
-- entry.raw_value = d.raw_value
-- entry.last_set_from = d.last_set_from
return entry
return make_entry.set_default_entry_mt(entry, opts)
end
end
--- Special options:
--- - only_sort_tags: Only sort via tag name. Ignore filename and other items
function make_entry.gen_from_ctags(opts)
opts = opts or {}
@ -965,6 +1029,11 @@ function make_entry.gen_from_ctags(opts)
local mt = {}
mt.__index = function(t, k)
local override = handle_entry_index(opts, t, k)
if override then
return override
end
if k == "path" then
local retpath = Path:new({ t.filename }):absolute()
if not vim.loop.fs_access(retpath, "R", nil) then
@ -974,6 +1043,7 @@ function make_entry.gen_from_ctags(opts)
end
end
local current_file_cache = {}
return function(line)
if line == "" or line:sub(1, 1) == "!" then
return nil
@ -991,8 +1061,14 @@ function make_entry.gen_from_ctags(opts)
file = string.gsub(file, "/", "\\")
end
if opts.only_current_file and file ~= current_file then
return nil
if opts.only_current_file then
if current_file_cache[file] == nil then
current_file_cache[file] = Path:new(file):normalize(cwd) == current_file
end
if current_file_cache[file] == false then
return nil
end
end
local tag_entry = {}
@ -1036,11 +1112,12 @@ function make_entry.gen_from_diagnostics(opts)
end)()
local display_items = {
{ width = utils.if_nil(signs, 8, 10) },
{ width = signs ~= nil and 10 or 8 },
{ remaining = true },
}
local line_width = vim.F.if_nil(opts.line_width, 0.5)
if not utils.is_path_hidden(opts) then
local hidden = utils.is_path_hidden(opts)
if not hidden then
table.insert(display_items, 2, { width = line_width })
end
local displayer = entry_display.create {
@ -1055,13 +1132,9 @@ function make_entry.gen_from_diagnostics(opts)
local pos = string.format("%4d:%2d", entry.lnum, entry.col)
local line_info = {
(signs and signs[entry.type] .. " " or "") .. pos,
"Diagnostic" .. entry.type,
"DiagnosticSign" .. entry.type,
}
--TODO(conni2461): I dont like that this is symbol lnum:col | msg | filename
-- i want: symbol filename:lnum:col | msg
-- or : symbol lnum:col | msg
-- I think this is more natural
return displayer {
line_info,
entry.text,
@ -1070,20 +1143,20 @@ function make_entry.gen_from_diagnostics(opts)
end
return function(entry)
return {
return make_entry.set_default_entry_mt({
value = entry,
ordinal = ("%s %s"):format(not opts.ignore_filename and entry.filename or "", entry.text),
ordinal = ("%s %s"):format(not hidden and entry.filename or "", entry.text),
display = make_display,
filename = entry.filename,
type = entry.type,
lnum = entry.lnum,
col = entry.col,
text = entry.text,
}
}, opts)
end
end
function make_entry.gen_from_autocommands(_)
function make_entry.gen_from_autocommands(opts)
local displayer = entry_display.create {
separator = "",
items = {
@ -1096,32 +1169,37 @@ function make_entry.gen_from_autocommands(_)
local make_display = function(entry)
return displayer {
{ entry.event, "vimAutoEvent" },
{ entry.group, "vimAugroup" },
{ entry.ft_pattern, "vimAutoCmdSfxList" },
entry.command,
{ entry.value.event, "vimAutoEvent" },
{ entry.value.group_name, "vimAugroup" },
{ entry.value.pattern, "vimAutoCmdSfxList" },
entry.value.command,
}
end
-- TODO: <action> dump current filtered items to buffer
return function(entry)
return {
event = entry.event,
group = entry.group,
ft_pattern = entry.ft_pattern,
command = entry.command,
value = string.format("+%d %s", entry.source_lnum, entry.source_file),
source_file = entry.source_file,
source_lnum = entry.source_lnum,
local group_name = vim.F.if_nil(entry.group_name, "<anonymous>")
local command = entry.command
if entry.desc and (entry.callback or vim.startswith(command, "<lua: ")) then
command = entry.desc
end
if command == nil or command == "" then
command = "<lua function>"
end
return make_entry.set_default_entry_mt({
value = {
event = entry.event,
group_name = group_name,
pattern = entry.pattern,
command = command,
},
--
valid = true,
ordinal = entry.event .. " " .. entry.group .. " " .. entry.ft_pattern .. " " .. entry.command,
ordinal = entry.event .. " " .. group_name .. " " .. entry.pattern .. " " .. entry.command,
display = make_display,
}
}, opts)
end
end
function make_entry.gen_from_commands(_)
function make_entry.gen_from_commands(opts)
local displayer = entry_display.create {
separator = "",
items = {
@ -1154,7 +1232,7 @@ function make_entry.gen_from_commands(_)
end
return function(entry)
return {
return make_entry.set_default_entry_mt({
name = entry.name,
bang = entry.bang,
nargs = entry.nargs,
@ -1162,10 +1240,9 @@ function make_entry.gen_from_commands(_)
definition = entry.definition,
--
value = entry,
valid = true,
ordinal = entry.name,
display = make_display,
}
}, opts)
end
end
@ -1224,13 +1301,13 @@ function make_entry.gen_from_git_status(opts)
end
local mod, file = string.match(entry, "(..).*%s[->%s]?(.+)")
return {
return setmetatable({
value = file,
status = mod,
ordinal = entry,
display = make_display,
path = Path:new({ opts.cwd, file }):absolute(),
}
}, opts)
end
end

View File

@ -1,4 +1,125 @@
-- TODO: Customize keymap
---@tag telescope.mappings
---@brief [[
--- |telescope.mappings| is used to configure the keybindings within
--- a telescope picker. These keybinds are only local to the picker window
--- and will be cleared once you exit the picker.
---
--- We provide multiple different ways of configuring, as described below,
--- to provide an easy to use experience for changing the default behavior
--- of telescope or extending for your own purposes.
---
--- To see many of the builtin actions that you can use as values for this
--- table, see |telescope.actions|
---
--- Format is:
--- <code>
--- {
--- mode = { ..keys }
--- }
--- </code>
---
--- where {mode} is the one character letter for a mode ('i' for insert, 'n' for normal).
---
--- For example:
--- <code>
--- mappings = {
--- i = {
--- ["<esc>"] = require('telescope.actions').close,
--- },
--- }
--- </code>
---
--- To disable a keymap, put `[map] = false`<br>
--- For example:
--- <code>
--- {
--- ...,
--- ["<C-n>"] = false,
--- ...,
--- }
--- </code>
--- Into your config.
---
--- To override behavior of a key, simply set the value
--- to be a function (either by requiring an action or by writing
--- your own function)
--- <code>
--- {
--- ...,
--- ["<C-i>"] = require('telescope.actions').select_default,
--- ...,
--- }
--- </code>
---
--- If the function you want is part of `telescope.actions`, then you can
--- simply give a string.
--- For example, the previous option is equivalent to:
--- <code>
--- {
--- ...,
--- ["<C-i>"] = "select_default",
--- ...,
--- }
--- </code>
---
--- You can also add other mappings using tables with `type = "command"`.
--- For example:
--- <code>
--- {
--- ...,
--- ["jj"] = { "<esc>", type = "command" },
--- ["kk"] = { "<cmd>echo \"Hello, World!\"<cr>", type = "command" },)
--- ...,
--- }
--- </code>
---
--- You can also add additional options for mappings of any type ("action" and "command").
--- For example:
--- <code>
--- {
--- ...,
--- ["<C-j>"] = {
--- actions.move_selection_next, type = "action",
--- opts = { nowait = true, silent = true }
--- },
--- ...,
--- }
--- </code>
---
--- There are three main places you can configure |telescope.mappings|. These are
--- ordered from the lowest priority to the highest priority.
---
--- 1. |telescope.defaults.mappings|
--- 2. In the |telescope.setup()| table, inside a picker with a given name, use the `mappings` key
--- <code>
--- require("telescope").setup {
--- pickers = {
--- find_files = {
--- mappings = {
--- n = {
--- ["kj"] = "close",
--- },
--- },
--- },
--- },
--- }
--- </code>
--- 3. `attach_mappings` function for a particular picker.
--- <code>
--- require("telescope.builtin").find_files {
--- attach_mappings = function(_, map)
--- map("i", "asdf", function(_prompt_bufnr)
--- print "You typed asdf"
--- end)
--- -- needs to return true if you want to map default_mappings and
--- -- false if not
--- return true
--- end,
--- }
--- </code>
---@brief ]]
local a = vim.api
local actions = require "telescope.actions"
@ -33,8 +154,12 @@ mappings.default_mappings = config.values.default_mappings
["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
["<C-l>"] = actions.complete_tag,
["<C-/>"] = actions.which_key,
["<C-_>"] = actions.which_key, -- keys from pressing <C-/>
["<C-w>"] = { "<c-s-w>", type = "command" },
-- disable c-j because we dont want to allow new lines #2123
["<C-j>"] = actions.nop,
},
n = {
@ -95,25 +220,6 @@ local assign_function = function(prompt_bufnr, func)
return func_id
end
--[[
Usage:
mappings.apply_keymap(42, <function>, {
n = {
["<leader>x"] = "just do this string",
["<CR>"] = function(picker, prompt_bufnr)
actions.close_prompt()
> local filename = ...
vim.cmd(string.format(":e %s", filename))
end,
},
i = {
}
})
--]]
local telescope_map = function(prompt_bufnr, mode, key_bind, key_func, opts)
if not key_func then
return
@ -147,11 +253,8 @@ local telescope_map = function(prompt_bufnr, mode, key_bind, key_func, opts)
local map_string
if opts.expr then
map_string = string.format(
[[luaeval("require('telescope.mappings').execute_keymap(%s, %s)")]],
prompt_bufnr,
key_id
)
map_string =
string.format([[luaeval("require('telescope.mappings').execute_keymap(%s, %s)")]], prompt_bufnr, key_id)
else
if mode == "i" and not opts.expr then
prefix = "<cmd>"
@ -161,12 +264,8 @@ local telescope_map = function(prompt_bufnr, mode, key_bind, key_func, opts)
prefix = ":"
end
map_string = string.format(
"%slua require('telescope.mappings').execute_keymap(%s, %s)<CR>",
prefix,
prompt_bufnr,
key_id
)
map_string =
string.format("%slua require('telescope.mappings').execute_keymap(%s, %s)<CR>", prefix, prompt_bufnr, key_id)
end
a.nvim_buf_set_keymap(prompt_bufnr, mode, key_bind, map_string, opts)

View File

@ -24,8 +24,6 @@ local p_window = require "telescope.pickers.window"
local EntryManager = require "telescope.entry_manager"
local MultiSelect = require "telescope.pickers.multi"
local get_default = utils.get_default
local truncate = require("plenary.strings").truncate
local strdisplaywidth = require("plenary.strings").strdisplaywidth
@ -65,25 +63,27 @@ function Picker:new(opts)
-- pcall(v.clear)
-- end
local layout_strategy = get_default(opts.layout_strategy, config.values.layout_strategy)
local layout_strategy = vim.F.if_nil(opts.layout_strategy, config.values.layout_strategy)
local obj = setmetatable({
prompt_title = get_default(opts.prompt_title, config.values.prompt_title),
results_title = get_default(opts.results_title, config.values.results_title),
prompt_title = vim.F.if_nil(opts.prompt_title, config.values.prompt_title),
results_title = vim.F.if_nil(opts.results_title, config.values.results_title),
-- either whats passed in by the user or whats defined by the previewer
preview_title = opts.preview_title,
prompt_prefix = get_default(opts.prompt_prefix, config.values.prompt_prefix),
wrap_results = get_default(opts.wrap_results, config.values.wrap_results),
selection_caret = get_default(opts.selection_caret, config.values.selection_caret),
entry_prefix = get_default(opts.entry_prefix, config.values.entry_prefix),
multi_icon = get_default(opts.multi_icon, config.values.multi_icon),
prompt_prefix = vim.F.if_nil(opts.prompt_prefix, config.values.prompt_prefix),
wrap_results = vim.F.if_nil(opts.wrap_results, config.values.wrap_results),
selection_caret = vim.F.if_nil(opts.selection_caret, config.values.selection_caret),
entry_prefix = vim.F.if_nil(opts.entry_prefix, config.values.entry_prefix),
multi_icon = vim.F.if_nil(opts.multi_icon, config.values.multi_icon),
initial_mode = get_default(opts.initial_mode, config.values.initial_mode),
debounce = get_default(tonumber(opts.debounce), nil),
initial_mode = vim.F.if_nil(opts.initial_mode, config.values.initial_mode),
_original_mode = vim.api.nvim_get_mode().mode,
debounce = vim.F.if_nil(tonumber(opts.debounce), nil),
_finder_attached = true,
default_text = opts.default_text,
get_status_text = get_default(opts.get_status_text, config.values.get_status_text),
get_status_text = vim.F.if_nil(opts.get_status_text, config.values.get_status_text),
_on_input_filter_cb = opts.on_input_filter_cb or function() end,
finder = assert(opts.finder, "Finder is required."),
@ -94,6 +94,8 @@ function Picker:new(opts)
default_selection_index = opts.default_selection_index,
get_selection_window = vim.F.if_nil(opts.get_selection_window, config.values.get_selection_window),
cwd = opts.cwd,
_find_id = 0,
@ -103,37 +105,40 @@ function Picker:new(opts)
and opts._multi
or MultiSelect:new(),
track = get_default(opts.track, false),
track = vim.F.if_nil(opts.track, false),
stats = {},
attach_mappings = opts.attach_mappings,
file_ignore_patterns = get_default(opts.file_ignore_patterns, config.values.file_ignore_patterns),
file_ignore_patterns = vim.F.if_nil(opts.file_ignore_patterns, config.values.file_ignore_patterns),
scroll_strategy = get_default(opts.scroll_strategy, config.values.scroll_strategy),
sorting_strategy = get_default(opts.sorting_strategy, config.values.sorting_strategy),
tiebreak = get_default(opts.tiebreak, config.values.tiebreak),
selection_strategy = get_default(opts.selection_strategy, config.values.selection_strategy),
scroll_strategy = vim.F.if_nil(opts.scroll_strategy, config.values.scroll_strategy),
sorting_strategy = vim.F.if_nil(opts.sorting_strategy, config.values.sorting_strategy),
tiebreak = vim.F.if_nil(opts.tiebreak, config.values.tiebreak),
selection_strategy = vim.F.if_nil(opts.selection_strategy, config.values.selection_strategy),
push_cursor_on_edit = get_default(opts.push_cursor_on_edit, false),
push_cursor_on_edit = vim.F.if_nil(opts.push_cursor_on_edit, false),
push_tagstack_on_edit = vim.F.if_nil(opts.push_tagstack_on_edit, false),
layout_strategy = layout_strategy,
layout_config = config.smarter_depth_2_extend(opts.layout_config or {}, config.values.layout_config or {}),
__cycle_layout_list = get_default(opts.cycle_layout_list, config.values.cycle_layout_list),
__cycle_layout_list = vim.F.if_nil(opts.cycle_layout_list, config.values.cycle_layout_list),
window = {
winblend = get_default(
winblend = vim.F.if_nil(
opts.winblend,
type(opts.window) == "table" and opts.window.winblend or config.values.winblend
),
border = get_default(opts.border, type(opts.window) == "table" and opts.window.border or config.values.border),
borderchars = get_default(
border = vim.F.if_nil(opts.border, type(opts.window) == "table" and opts.window.border or config.values.border),
borderchars = vim.F.if_nil(
opts.borderchars,
type(opts.window) == "table" and opts.window.borderchars or config.values.borderchars
),
},
cache_picker = config.resolve_table_opts(opts.cache_picker, vim.deepcopy(config.values.cache_picker)),
__scrolling_limit = tonumber(vim.F.if_nil(opts.temp__scrolling_limit, 250)),
}, self)
obj.get_window_options = opts.get_window_options or p_window.get_window_options
@ -369,11 +374,8 @@ function Picker:find()
popup_opts.preview.titlehighlight = "TelescopePreviewTitle"
end
local results_win, results_opts, results_border_win = self:_create_window(
"",
popup_opts.results,
not self.wrap_results
)
local results_win, results_opts, results_border_win =
self:_create_window("", popup_opts.results, not self.wrap_results)
local results_bufnr = a.nvim_win_get_buf(results_win)
pcall(a.nvim_buf_set_option, results_bufnr, "tabstop", 1) -- #1834
@ -411,7 +413,7 @@ function Picker:find()
-- want to scroll through more than 10,000 items.
--
-- This just lets us stop doing stuff after tons of things.
self.max_results = 1000
self.max_results = self.__scrolling_limit
vim.api.nvim_buf_set_lines(results_bufnr, 0, self.max_results, false, utils.repeated_table(self.max_results, ""))
@ -501,10 +503,12 @@ function Picker:find()
-- Register attach
vim.api.nvim_buf_attach(prompt_bufnr, false, {
on_lines = function(...)
find_id = self:_next_find_id()
if self._finder_attached then
find_id = self:_next_find_id()
status_updater { completed = false }
self._on_lines(...)
status_updater { completed = false }
self._on_lines(...)
end
end,
on_detach = function()
@ -527,7 +531,6 @@ function Picker:find()
buffer = prompt_bufnr,
group = "PickerInsert",
nested = true,
once = true,
callback = function()
require("telescope.pickers").on_resize_window(prompt_bufnr)
end,
@ -688,7 +691,7 @@ end
---
--- Example usage in telescope:
--- - `actions.delete_buffer()`
---@param delete_cb function: called with each deleted selection
---@param delete_cb function: called for each selection fn(s) -> bool|nil (true|nil removes the entry from the results)
function Picker:delete_selection(delete_cb)
vim.validate { delete_cb = { delete_cb, "f" } }
local original_selection_strategy = self.selection_strategy
@ -714,8 +717,10 @@ function Picker:delete_selection(delete_cb)
return x > y
end)
for _, index in ipairs(selection_index) do
local selection = table.remove(self.finder.results, index)
delete_cb(selection)
local delete_cb_return = delete_cb(self.finder.results[index])
if delete_cb_return == nil or delete_cb_return == true then
table.remove(self.finder.results, index)
end
end
if used_multi_select then
@ -904,7 +909,7 @@ function Picker:refresh(finder, opts)
local handle = type(opts.new_prefix) == "table" and unpack or function(x)
return x
end
self:change_prompt_prefix(handle(opts.new_prefix))
self:change_prompt_prefix(handle(opts.new_prefix), opts.prefix_hl_group)
end
if finder then
@ -958,6 +963,9 @@ function Picker:set_selection(row)
state.set_global_key("selected_entry", entry)
if not entry then
-- also refresh previewer when there is no entry selected, so the preview window is cleared
self._selection_entry = entry
self:refresh_previewer()
return
end
@ -1039,7 +1047,7 @@ function Picker:update_prefix(entry, row)
local line = vim.api.nvim_buf_get_lines(self.results_bufnr, row, row + 1, false)[1]
if not line then
log.warn(string.format("no line found at row %d in buffer %d", row, self.results_bufnr))
log.trace(string.format("no line found at row %d in buffer %d", row, self.results_bufnr))
return
end
@ -1061,10 +1069,6 @@ end
--- Refresh the previewer based on the current `status` of the picker
function Picker:refresh_previewer()
local status = state.get_status(self.prompt_bufnr)
if not self._selection_entry then
-- if selection_entry is nil there is nothing to be previewed
return
end
if self.previewer and status.preview_win and a.nvim_win_is_valid(status.preview_win) then
self:_increment "previewed"
@ -1361,6 +1365,16 @@ function Picker:_do_selection(prompt)
else
self:set_selection(self:get_reset_row())
end
elseif selection_strategy == "none" then
if self._selection_entry then
local old_entry, old_row = self._selection_entry, self._selection_row
self:reset_selection() -- required to reset selection before updating prefix
if old_row >= 0 then
self:update_prefix(old_entry, old_row)
self.highlighter:hi_multiselect(old_row, self:is_multi_selected(old_entry))
end
end
return
else
error("Unknown selection strategy: " .. selection_strategy)
end
@ -1413,6 +1427,7 @@ end
function pickers.on_close_prompt(prompt_bufnr)
local status = state.get_status(prompt_bufnr)
local picker = status.picker
require("telescope.actions.state").get_current_history():reset()
if type(picker.cache_picker) == "table" then
local cached_pickers = state.get_global_key "cached_pickers" or {}
@ -1490,6 +1505,11 @@ function Picker:_reset_highlights()
vim.api.nvim_buf_clear_namespace(self.results_bufnr, ns_telescope_matching, 0, -1)
end
-- Toggles whether finder is attached to prompt buffer input
function Picker:_toggle_finder_attach()
self._finder_attached = not self._finder_attached
end
function Picker:_detach()
self.finder:close()

View File

@ -1,3 +1,63 @@
---@tag telescope.pickers.entry_display
---@brief [[
--- Entry Display is used to format each entry shown in the result panel.
---
--- Entry Display create() will give us a function based on the configuration
--- of column widths we pass into it. We then can use this function n times to
--- return a string based on structured input.
---
--- Note that if you call `create()` inside `make_display` it will be called for
--- every single entry. So it is suggested to do this outside of `make_display`
--- for the best performance.
---
--- The create function will use the column widths passed to it in
--- configaration.items. Each item in that table is the number of characters in
--- the column. It's also possible for the final column to not have a fixed
--- width, this will be shown in the configuartion as 'remaining = true'.
---
--- An example of this configuration is shown for the buffers picker
--- <code>
--- local displayer = entry_display.create {
--- separator = " ",
--- items = {
--- { width = opts.bufnr_width },
--- { width = 4 },
--- { width = icon_width },
--- { remaining = true },
--- },
--- }
--- </code>
---
--- This shows 4 columns, the first is defined in the opts as the width we'll
--- use when display_string the number of the buffer. The second has a fixed
--- width of 4 and the 3rd column's widht will be decided by the width of the
--- icons we use. The fourth column will use the remaining space. Finally we
--- have also defined the seperator between each column will be the space " ".
---
--- An example of how the display reference will be used is shown, again for
--- the buffers picker:
--- <code>
--- return displayer {
--- { entry.bufnr, "TelescopeResultsNumber" },
--- { entry.indicator, "TelescopeResultsComment" },
--- { icon, hl_group },
--- display_bufname .. ":" .. entry.lnum,
--- }
--- </code>
---
--- There are two types of values each column can have. Either a simple String
--- or a table containing the String as well as the hl_group.
---
--- The displayer can return values, string and an optional highlights.
--- String is all the text to be displayed for this entry as a single string. If
--- parts of the string are to be highlighted they will be described in the
--- highlights table.
---
--- For better understanding of how create() and displayer are used it's best to look
--- at the code in make_entry.lua.
---@brief ]]
local strings = require "plenary.strings"
local state = require "telescope.state"
local resolve = require "telescope.config.resolve"

View File

@ -53,7 +53,6 @@
local resolve = require "telescope.config.resolve"
local p_window = require "telescope.pickers.window"
local if_nil = vim.F.if_nil
local get_border_size = function(opts)
if opts.window.border == false then
@ -125,7 +124,7 @@ local function validate_layout_config(strategy_name, configuration, values, defa
local valid_configuration_keys = get_valid_configuration_keys(configuration)
-- If no default_layout_config provided, check Telescope's config values
default_layout_config = if_nil(default_layout_config, require("telescope.config").values.layout_config)
default_layout_config = vim.F.if_nil(default_layout_config, require("telescope.config").values.layout_config)
local result = {}
local get_value = function(k)
@ -263,7 +262,7 @@ local function make_documented_layout(name, layout_config, layout)
validate_layout_config(
name,
layout_config,
vim.tbl_deep_extend("keep", if_nil(override_layout, {}), if_nil(self.layout_config, {}))
vim.tbl_deep_extend("keep", vim.F.if_nil(override_layout, {}), vim.F.if_nil(self.layout_config, {}))
)
)
end
@ -320,7 +319,7 @@ layout_strategies.horizontal = make_documented_layout(
-- Cap over/undersized width (with previewer)
width, w_space = calc_size_and_spacing(width, max_columns, bs, 2, 4, 1)
preview.width = resolve.resolve_width(if_nil(layout_config.preview_width, function(_, cols)
preview.width = resolve.resolve_width(vim.F.if_nil(layout_config.preview_width, function(_, cols)
if cols < 150 then
return math.floor(cols * 0.4)
elseif cols < 200 then
@ -588,7 +587,7 @@ layout_strategies.cursor = make_documented_layout(
-- Cap over/undersized width (with preview)
width, w_space = calc_size_and_spacing(width, max_columns, bs, 2, 4, 0)
preview.width = resolve.resolve_width(if_nil(layout_config.preview_width, 2 / 3))(self, width, max_lines)
preview.width = resolve.resolve_width(vim.F.if_nil(layout_config.preview_width, 2 / 3))(self, width, max_lines)
prompt.width = width - preview.width - w_space
results.width = prompt.width
else
@ -601,8 +600,14 @@ layout_strategies.cursor = make_documented_layout(
end
local position = vim.api.nvim_win_get_position(0)
local winbar = (function()
if vim.fn.exists "&winbar" == 1 then
return vim.o.winbar == "" and 0 or 1
end
return 0
end)()
local top_left = {
line = vim.fn.winline() + position[1] + bs,
line = vim.fn.winline() + position[1] + bs + winbar,
col = vim.fn.wincol() + position[2],
}
local bot_right = {
@ -694,7 +699,8 @@ layout_strategies.vertical = make_documented_layout(
-- Cap over/undersized height (with previewer)
height, h_space = calc_size_and_spacing(height, max_lines, bs, 3, 6, 2)
preview.height = resolve.resolve_height(if_nil(layout_config.preview_height, 0.5))(self, max_columns, height)
preview.height =
resolve.resolve_height(vim.F.if_nil(layout_config.preview_height, 0.5))(self, max_columns, height)
else
-- Cap over/undersized height (without previewer)
height, h_space = calc_size_and_spacing(height, max_lines, bs, 2, 4, 1)
@ -764,8 +770,8 @@ layout_strategies.flex = make_documented_layout(
horizontal = "Options to pass when switching to horizontal layout",
}),
function(self, max_columns, max_lines, layout_config)
local flip_columns = if_nil(layout_config.flip_columns, 100)
local flip_lines = if_nil(layout_config.flip_lines, 20)
local flip_columns = vim.F.if_nil(layout_config.flip_columns, 100)
local flip_lines = vim.F.if_nil(layout_config.flip_lines, 20)
if max_columns < flip_columns and max_lines > flip_lines then
self.__flex_strategy = "vertical"
@ -851,7 +857,7 @@ layout_strategies.bottom_pane = make_documented_layout(
local tbln
max_lines, tbln = calc_tabline(max_lines)
local height = if_nil(resolve.resolve_height(layout_config.height)(self, max_columns, max_lines), 25)
local height = vim.F.if_nil(resolve.resolve_height(layout_config.height)(self, max_columns, max_lines), 25)
if type(layout_config.height) == "table" and type(layout_config.height.padding) == "number" then
-- Since bottom_pane only has padding at the top, we only need half as much padding in total
-- This doesn't match the vim help for `resolve.resolve_height`, but it matches expectations
@ -874,7 +880,7 @@ layout_strategies.bottom_pane = make_documented_layout(
-- Cap over/undersized width (with preview)
local width, w_space = calc_size_and_spacing(max_columns, max_columns, bs, 2, 4, 0)
preview.width = resolve.resolve_width(if_nil(layout_config.preview_width, 0.5))(self, width, max_lines)
preview.width = resolve.resolve_width(vim.F.if_nil(layout_config.preview_width, 0.5))(self, width, max_lines)
results.width = width - preview.width - w_space
else
results.width = prompt.width

View File

@ -152,11 +152,13 @@ local scroll_fn = function(self, direction)
end
previewers.file_maker = function(filepath, bufnr, opts)
opts = opts or {}
opts.preview = opts.preview or {}
opts = vim.F.if_nil(opts, {})
-- TODO(conni2461): here shouldn't be any hardcoded magic numbers ...
opts.preview = vim.F.if_nil(opts.preview, {})
opts.preview.timeout = vim.F.if_nil(opts.preview.timeout, 250) -- in ms
opts.preview.filesize_limit = vim.F.if_nil(opts.preview.filesize_limit, 25) -- in mb
opts.preview.msg_bg_fillchar = vim.F.if_nil(opts.preview.msg_bg_fillchar, "") -- in mb
opts.preview.treesitter = vim.F.if_nil(opts.preview.treesitter, true)
if opts.use_ft_detect == nil then
opts.use_ft_detect = true
end
@ -333,7 +335,7 @@ previewers.new_buffer_previewer = function(opts)
-- Push in another buffer so the last one will not be cleaned up
if preview_window_id then
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(preview_window_id, bufnr)
utils.win_set_buf_noautocmd(preview_window_id, bufnr)
end
end
@ -358,14 +360,14 @@ previewers.new_buffer_previewer = function(opts)
if opts.get_buffer_by_name and get_bufnr_by_bufname(self, opts.get_buffer_by_name(self, entry)) then
self.state.bufname = opts.get_buffer_by_name(self, entry)
self.state.bufnr = get_bufnr_by_bufname(self, self.state.bufname)
vim.api.nvim_win_set_buf(status.preview_win, self.state.bufnr)
utils.win_set_buf_noautocmd(status.preview_win, self.state.bufnr)
else
local bufnr = vim.api.nvim_create_buf(false, true)
set_bufnr(self, bufnr)
vim.schedule(function()
if vim.api.nvim_buf_is_valid(bufnr) then
vim.api.nvim_win_set_buf(status.preview_win, bufnr)
utils.win_set_buf_noautocmd(status.preview_win, bufnr)
end
end)
@ -385,8 +387,16 @@ previewers.new_buffer_previewer = function(opts)
opts.define_preview(self, entry, status)
putils.with_preview_window(status, nil, function()
vim.cmd "do User TelescopePreviewerLoaded"
vim.schedule(function()
if not self or not self.state or not self.state.bufnr then
return
end
if vim.api.nvim_buf_is_valid(self.state.bufnr) then
vim.api.nvim_buf_call(self.state.bufnr, function()
vim.cmd "do User TelescopePreviewerLoaded"
end)
end
end)
if opts.get_buffer_by_name then
@ -407,11 +417,11 @@ previewers.cat = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "File Preview",
dyn_title = function(_, entry)
return Path:new(from_entry.path(entry, true)):normalize(cwd)
return Path:new(from_entry.path(entry, false, false)):normalize(cwd)
end,
get_buffer_by_name = function(_, entry)
return from_entry.path(entry, true)
return from_entry.path(entry, false)
end,
define_preview = function(self, entry, status)
@ -446,21 +456,26 @@ previewers.vimgrep = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "Grep Preview",
dyn_title = function(_, entry)
return Path:new(from_entry.path(entry, true)):normalize(cwd)
return Path:new(from_entry.path(entry, false, false)):normalize(cwd)
end,
get_buffer_by_name = function(_, entry)
return from_entry.path(entry, true)
return from_entry.path(entry, false)
end,
define_preview = function(self, entry, status)
local p = from_entry.path(entry, true)
if p == nil or p == "" then
return
-- builtin.buffers: bypass path validation for terminal buffers that don't have appropriate path
local has_buftype = entry.bufnr and vim.api.nvim_buf_get_option(entry.bufnr, "buftype") ~= "" or false
local p
if not has_buftype then
p = from_entry.path(entry, true)
if p == nil or p == "" then
return
end
end
-- Workaround for unnamed buffer when using builtin.buffer
if entry.bufnr and (p == "[No Name]" or vim.api.nvim_buf_get_option(entry.bufnr, "buftype") ~= "") then
if entry.bufnr and (p == "[No Name]" or has_buftype) then
local lines = vim.api.nvim_buf_get_lines(entry.bufnr, 0, -1, false)
vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, lines)
jump_to_line(self, self.state.bufnr, entry.lnum)
@ -711,8 +726,12 @@ previewers.git_stash_diff = defaulter(function(opts)
value = entry.value,
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
if vim.api.nvim_buf_is_valid(bufnr) then
putils.regex_highlighter(bufnr, "diff")
end
end,
})
putils.regex_highlighter(self.state.bufnr, "diff")
end,
}
end, {})
@ -737,10 +756,12 @@ previewers.git_commit_diff_to_parent = defaulter(function(opts)
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
search_cb_jump(self, bufnr, opts.current_line)
if vim.api.nvim_buf_is_valid(bufnr) then
search_cb_jump(self, bufnr, opts.current_line)
putils.regex_highlighter(bufnr, "diff")
end
end,
})
putils.regex_highlighter(self.state.bufnr, "diff")
end,
}
end, {})
@ -766,10 +787,12 @@ previewers.git_commit_diff_to_head = defaulter(function(opts)
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
search_cb_jump(self, bufnr, opts.current_line)
if vim.api.nvim_buf_is_valid(bufnr) then
search_cb_jump(self, bufnr, opts.current_line)
putils.regex_highlighter(bufnr, "diff")
end
end,
})
putils.regex_highlighter(self.state.bufnr, "diff")
end,
}
end, {})
@ -795,10 +818,12 @@ previewers.git_commit_diff_as_was = defaulter(function(opts)
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
search_cb_jump(self, bufnr, opts.current_line)
if vim.api.nvim_buf_is_valid(bufnr) then
search_cb_jump(self, bufnr, opts.current_line)
putils.regex_highlighter(bufnr, ft)
end
end,
})
putils.highlighter(self.state.bufnr, ft)
end,
}
end, {})
@ -860,8 +885,12 @@ previewers.git_file_diff = defaulter(function(opts)
value = entry.value,
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
if vim.api.nvim_buf_is_valid(bufnr) then
putils.regex_highlighter(bufnr, "diff")
end
end,
})
putils.regex_highlighter(self.state.bufnr, "diff")
end
end,
}
@ -877,12 +906,12 @@ previewers.autocommands = defaulter(function(_)
end,
get_buffer_by_name = function(_, entry)
return entry.group
return entry.value.group_name
end,
define_preview = function(self, entry, status)
local results = vim.tbl_filter(function(x)
return x.group == entry.group
return x.value.group_name == entry.value.group_name
end, status.picker.finder.results)
if self.state.last_set_bufnr then
@ -890,9 +919,9 @@ previewers.autocommands = defaulter(function(_)
end
local selected_row = 0
if self.state.bufname ~= entry.group then
if self.state.bufname ~= entry.value.group_name then
local display = {}
table.insert(display, string.format(" augroup: %s - [ %d entries ]", entry.group, #results))
table.insert(display, string.format(" augroup: %s - [ %d entries ]", entry.value.group_name, #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))
@ -901,7 +930,10 @@ previewers.autocommands = defaulter(function(_)
if item == entry then
selected_row = idx
end
table.insert(display, string.format(" %-14s▏%-08s %s", item.event, item.ft_pattern, item.command))
table.insert(
display,
string.format(" %-14s▏%-08s %s", item.value.event, item.value.pattern, item.value.command)
)
end
vim.api.nvim_buf_set_option(self.state.bufnr, "filetype", "vim")

View File

@ -1,3 +1,5 @@
local utils = require "telescope.utils"
local Previewer = {}
Previewer.__index = Previewer
@ -25,11 +27,19 @@ function Previewer:new(opts)
_send_input = opts.send_input,
_scroll_fn = opts.scroll_fn,
preview_fn = opts.preview_fn,
_empty_bufnr = nil,
}, Previewer)
end
function Previewer:preview(entry, status)
if not entry then
if not self._empty_bufnr then
self._empty_bufnr = vim.api.nvim_create_buf(false, true)
end
if vim.api.nvim_buf_is_valid(self._empty_bufnr) then
vim.api.nvim_win_set_buf(status.preview_win, self._empty_bufnr)
end
return
end
@ -47,7 +57,11 @@ end
function Previewer:title(entry, dynamic)
if dynamic == true and self._dyn_title_fn ~= nil then
if entry == nil then
return nil
if self._title_fn ~= nil then
return self:_title_fn()
else
return ""
end
end
return self:_dyn_title_fn(entry)
end
@ -57,6 +71,9 @@ function Previewer:title(entry, dynamic)
end
function Previewer:teardown()
if self._empty_bufnr then
utils.buf_delete(self._empty_bufnr)
end
if self._teardown_func then
self:_teardown_func()
end

View File

@ -192,12 +192,12 @@ previewers.new_termopen_previewer = function(opts)
local prev_bufnr = get_bufnr_by_bufentry(self, entry)
if prev_bufnr then
self.state.termopen_bufnr = prev_bufnr
vim.api.nvim_win_set_buf(status.preview_win, self.state.termopen_bufnr)
utils.win_set_buf_noautocmd(status.preview_win, self.state.termopen_bufnr)
self.state.termopen_id = term_ids[self.state.termopen_bufnr]
else
local bufnr = vim.api.nvim_create_buf(false, true)
set_bufnr(self, bufnr)
vim.api.nvim_win_set_buf(status.preview_win, bufnr)
utils.win_set_buf_noautocmd(status.preview_win, bufnr)
local term_opts = {
cwd = opts.cwd or vim.loop.cwd(),
@ -250,11 +250,11 @@ previewers.cat = defaulter(function(opts)
return previewers.new_termopen_previewer {
title = "File Preview",
dyn_title = function(_, entry)
return Path:new(from_entry.path(entry, true)):normalize(cwd)
return Path:new(from_entry.path(entry, false, false)):normalize(cwd)
end,
get_command = function(entry)
local p = from_entry.path(entry, true)
local p = from_entry.path(entry, true, false)
if p == nil or p == "" then
return
end
@ -273,14 +273,14 @@ previewers.vimgrep = defaulter(function(opts)
return previewers.new_termopen_previewer {
title = "Grep Preview",
dyn_title = function(_, entry)
return Path:new(from_entry.path(entry, true)):normalize(cwd)
return Path:new(from_entry.path(entry, false, false)):normalize(cwd)
end,
get_command = function(entry, status)
local win_id = status.preview_win
local height = vim.api.nvim_win_get_height(win_id)
local p = from_entry.path(entry, true)
local p = from_entry.path(entry, true, false)
if p == nil or p == "" then
return
end
@ -308,14 +308,14 @@ previewers.qflist = defaulter(function(opts)
return previewers.new_termopen_previewer {
title = "Grep Preview",
dyn_title = function(_, entry)
return Path:new(from_entry.path(entry, true)):normalize(cwd)
return Path:new(from_entry.path(entry, false, false)):normalize(cwd)
end,
get_command = function(entry, status)
local win_id = status.preview_win
local height = vim.api.nvim_win_get_height(win_id)
local p = from_entry.path(entry, true)
local p = from_entry.path(entry, true, false)
if p == nil or p == "" then
return
end

View File

@ -45,28 +45,26 @@ utils.job_maker = function(cmd, bufnr, opts)
end
end)()
Job
:new({
command = command,
args = cmd,
env = opts.env,
cwd = opts.cwd,
writer = writer,
on_exit = vim.schedule_wrap(function(j)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
if opts.mode == "append" then
vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, j:result())
elseif opts.mode == "insert" then
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, j:result())
end
if opts.callback then
opts.callback(bufnr, j:result())
end
end),
})
:start()
Job:new({
command = command,
args = cmd,
env = opts.env,
cwd = opts.cwd,
writer = writer,
on_exit = vim.schedule_wrap(function(j)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
if opts.mode == "append" then
vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, j:result())
elseif opts.mode == "insert" then
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, j:result())
end
if opts.callback then
opts.callback(bufnr, j:result())
end
end),
}):start()
else
if opts.callback then
opts.callback(bufnr)
@ -80,14 +78,41 @@ end
--- Attach default highlighter which will choose between regex and ts
utils.highlighter = function(bufnr, ft, opts)
opts = opts or {}
opts.preview = opts.preview or {}
opts.preview.treesitter = vim.F.if_nil(
opts.preview.treesitter,
type(conf.preview) == "table" and conf.preview.treesitter
)
local ts_highlighting = opts.preview.treesitter == true
or type(opts.preview.treesitter) == "table" and vim.tbl_contains(opts.preview.treesitter, ft)
opts = vim.F.if_nil(opts, {})
opts.preview = vim.F.if_nil(opts.preview, {})
opts.preview.treesitter = (function()
if type(opts.preview) == "table" and opts.preview.treesitter then
return opts.preview.treesitter
end
if type(conf.preview) == "table" and conf.preview.treesitter then
return conf.preview.treesitter
end
if type(conf.preview) == "boolean" then
return conf.preview
end
-- We should never get here
return false
end)()
if type(opts.preview.treesitter) == "boolean" then
local temp = { enable = opts.preview.treesitter }
opts.preview.treesitter = temp
end
local ts_highlighting = (function()
if type(opts.preview.treesitter.enable) == "table" then
if vim.tbl_contains(opts.preview.treesitter.enable, ft) then
return true
end
return false
end
if vim.tbl_contains(vim.F.if_nil(opts.preview.treesitter.disable, {}), ft) then
return false
end
return opts.preview.treesitter.enable == nil or opts.preview.treesitter.enable == true
end)()
local ts_success
if ts_highlighting then
@ -114,9 +139,6 @@ local treesitter_attach = function(bufnr, ft)
end
local config = ts_configs.get_module "highlight"
for k, v in pairs(config.custom_captures) do
vim.treesitter.highlighter.hl_map[k] = v
end
vim.treesitter.highlighter.new(ts_parsers.get_parser(bufnr, lang))
local is_table = type(config.additional_vim_regex_highlighting) == "table"
if

View File

@ -291,17 +291,17 @@ sorters.get_fuzzy_file = function(opts)
end
local denominator = (
(10 * match_count / #prompt_lower_ngrams)
-- biases for shorter strings
+ 3 * match_count * ngram_len / #line
+ consecutive_matches
+ N / (contains_string or (2 * #line))
-- + 30/(c1 or 2*N)
-- TODO: It might be possible that this too strongly correlates,
-- but it's unlikely for people to type capital letters without actually
-- wanting to do something with a capital letter in it.
+ uppers_matching
) * tail_modifier
(10 * match_count / #prompt_lower_ngrams)
-- biases for shorter strings
+ 3 * match_count * ngram_len / #line
+ consecutive_matches
+ N / (contains_string or (2 * #line))
-- + 30/(c1 or 2*N)
-- TODO: It might be possible that this too strongly correlates,
-- but it's unlikely for people to type capital letters without actually
-- wanting to do something with a capital letter in it.
+ uppers_matching
) * tail_modifier
if denominator == 0 or denominator ~= denominator then
return -1
@ -430,6 +430,7 @@ sorters.fuzzy_with_index_bias = function(opts)
return math.min(math.pow(entry.index, 0.25), 2) * base_score
end
end,
highlighter = fuzzy_sorter.highlighter,
}
end
@ -602,7 +603,7 @@ end
sorters.prefilter = function(opts)
local sorter = opts.sorter
opts.delimiter = util.get_default(opts.delimiter, ":")
opts.delimiter = vim.F.if_nil(opts.delimiter, ":")
sorter._delimiter = opts.delimiter
sorter.tags = create_tag_set(opts.tag)
sorter.filter_function = filter_function(opts)

View File

@ -0,0 +1,112 @@
local assert = require "luassert"
local Path = require "plenary.path"
local tester = {}
tester.debug = false
local get_results_from_contents = function(content)
local nvim = vim.fn.jobstart(
{ "nvim", "--noplugin", "-u", "scripts/minimal_init.vim", "--headless", "--embed" },
{ rpc = true }
)
local result = vim.fn.rpcrequest(nvim, "nvim_exec_lua", content, {})
assert.are.same(true, result[1], vim.inspect(result))
local count = 0
while
vim.fn.rpcrequest(nvim, "nvim_exec_lua", "return require('telescope.testharness.runner').state.done", {}) ~= true
do
count = count + 1
vim.wait(100)
-- TODO: Could maybe wait longer, but it's annoying to wait if the test is going to timeout.
if count > 100 then
break
end
end
local state = vim.fn.rpcrequest(nvim, "nvim_exec_lua", "return require('telescope.testharness.runner').state", {})
vim.fn.jobstop(nvim)
assert.are.same(true, state.done, vim.inspect(state))
local result_table = {}
for _, v in ipairs(state.results) do
table.insert(result_table, v)
end
return result_table, state
end
local check_results = function(results, state)
assert(state, "Must pass state")
for _, v in ipairs(results) do
local assertion
if not v._type or v._type == "are" or v._type == "_default" then
assertion = assert.are.same
else
assertion = assert.are_not.same
end
-- TODO: I think it would be nice to be able to see the state,
-- but it clutters up the test output so much here.
--
-- So we would have to consider how to do that I think.
assertion(v.expected, v.actual, string.format("Test Case: %s // %s", v.location, v.case))
end
end
tester.run_string = function(contents)
contents = [[
return (function()
local tester = require('telescope.testharness')
local runner = require('telescope.testharness.runner')
local helper = require('telescope.testharness.helpers')
helper.make_globals()
local ok, msg = pcall(function()
runner.log("Loading Test")
]] .. contents .. [[
end)
return {ok, msg or runner.state}
end)()
]]
check_results(get_results_from_contents(contents))
end
tester.run_file = function(filename)
local file = "./lua/tests/pickers/" .. filename .. ".lua"
local path = Path:new(file)
if not path:exists() then
assert.are.same("<An existing file>", file)
end
local contents = string.format(
[[
return (function()
local runner = require('telescope.testharness.runner')
local helper = require('telescope.testharness.helpers')
helper.make_globals()
local ok, msg = pcall(function()
runner.log("Loading Test")
return loadfile("%s")()
end)
return {ok, msg or runner.state}
end)()
]],
path:absolute()
)
check_results(get_results_from_contents(contents))
end
tester.not_ = function(val)
val._type = "are_not"
return val
end
return tester

View File

@ -0,0 +1,156 @@
local builtin = require "telescope.builtin"
local DELAY = vim.g.telescope_test_delay or 50
local runner = {}
-- State is test variable
runner.state = {
done = false,
results = {},
msgs = {},
}
local writer = function(val)
table.insert(runner.state.results, val)
end
local invalid_test_case = function(k)
error { case = k, expected = "<a valid key>", actual = k }
end
local _VALID_KEYS = {
post_typed = true,
post_close = true,
}
local replace_terms = function(input)
return vim.api.nvim_replace_termcodes(input, true, false, true)
end
runner.nvim_feed = function(text, feed_opts)
feed_opts = feed_opts or "m"
vim.api.nvim_feedkeys(text, feed_opts, true)
end
local end_test_cases = function()
runner.state.done = true
end
local execute_test_case = function(location, key, spec)
local ok, actual = pcall(spec[2])
if not ok then
writer {
location = "Error: " .. location,
case = key,
expected = "To succeed and return: " .. tostring(spec[1]),
actual = actual,
_type = spec._type,
}
end_test_cases()
else
writer {
location = location,
case = key,
expected = spec[1],
actual = actual,
_type = spec._type,
}
end
return ok
end
runner.log = function(msg)
table.insert(runner.state.msgs, msg)
end
runner.picker = function(picker_name, input, test_cases, opts)
opts = opts or {}
for k, _ in pairs(test_cases) do
if not _VALID_KEYS[k] then
return invalid_test_case(k)
end
end
opts.on_complete = {
runner.create_on_complete(input, test_cases),
}
opts._on_error = function(self, msg)
runner.state.done = true
writer {
location = "Error while running on complete",
expected = "To Work",
actual = msg,
}
end
runner.log "Starting picker"
builtin[picker_name](opts)
runner.log "Called picker"
end
runner.create_on_complete = function(input, test_cases)
input = replace_terms(input)
local actions = {}
for i = 1, #input do
local char = input:sub(i, i)
table.insert(actions, {
cb = function()
runner.log("Inserting char: " .. char)
runner.nvim_feed(char, "")
end,
char = char,
})
end
return function()
local action
repeat
action = table.remove(actions, 1)
if action then
action.cb()
end
until not action or string.match(action.char, "%g")
if #actions > 0 then
return
end
vim.defer_fn(function()
if test_cases.post_typed then
for k, v in ipairs(test_cases.post_typed) do
if not execute_test_case("post_typed", k, v) then
return
end
end
end
vim.defer_fn(function()
runner.nvim_feed(replace_terms "<CR>", "")
vim.defer_fn(function()
if test_cases.post_close then
for k, v in ipairs(test_cases.post_close) do
if not execute_test_case("post_close", k, v) then
return
end
end
end
vim.defer_fn(end_test_cases, DELAY)
end, DELAY)
end, DELAY)
end, DELAY)
end
end
return runner

View File

@ -1,3 +1,10 @@
---@tag telescope.utils
---@config { ["module"] = "telescope.utils" }
---@brief [[
--- Utilities for writing telescope pickers
---@brief ]]
local Path = require "plenary.path"
local Job = require "plenary.job"
@ -12,18 +19,6 @@ utils.get_separator = function()
return Path.path.sep
end
utils.if_nil = function(x, was_nil, was_not_nil)
if x == nil then
return was_nil
else
return was_not_nil
end
end
utils.get_default = function(x, default)
return utils.if_nil(x, default, x)
end
utils.cycle = function(i, n)
return i % n == 0 and n or i % n
end
@ -179,21 +174,23 @@ end)()
utils.path_tail = (function()
local os_sep = utils.get_separator()
local match_string = "[^" .. os_sep .. "]*$"
return function(path)
return string.match(path, match_string)
for i = #path, 1, -1 do
if path:sub(i, i) == os_sep then
return path:sub(i + 1, -1)
end
end
return path
end
end)()
utils.is_path_hidden = function(opts, path_display)
path_display = path_display or utils.get_default(opts.path_display, require("telescope.config").values.path_display)
path_display = path_display or vim.F.if_nil(opts.path_display, require("telescope.config").values.path_display)
return path_display == nil
or path_display == "hidden"
or type(path_display) ~= "table"
or vim.tbl_contains(path_display, "hidden")
or path_display.hidden
or type(path_display) == "table" and (vim.tbl_contains(path_display, "hidden") or path_display.hidden)
end
local is_uri = function(filename)
@ -206,6 +203,16 @@ local calc_result_length = function(truncate_len)
return type(truncate_len) == "number" and len - truncate_len or len
end
--- Transform path is a util function that formats a path based on path_display
--- found in `opts` or the default value from config.
--- It is meant to be used in make_entry to have a uniform interface for
--- builtins as well as extensions utilizing the same user configuration
--- Note: It is only supported inside `make_entry`/`make_display` the use of
--- this function outside of telescope might yield to undefined behavior and will
--- not be addressed by us
---@param opts table: The opts the users passed into the picker. Might contains a path_display key
---@param path string: The path that should be formated
---@return string: The transformed path ready to be displayed
utils.transform_path = function(opts, path)
if path == nil then
return
@ -214,7 +221,7 @@ utils.transform_path = function(opts, path)
return path
end
local path_display = utils.get_default(opts.path_display, require("telescope.config").values.path_display)
local path_display = vim.F.if_nil(opts.path_display, require("telescope.config").values.path_display)
local transformed_path = path
@ -253,7 +260,10 @@ utils.transform_path = function(opts, path)
if opts.__length == nil then
opts.__length = calc_result_length(path_display.truncate)
end
transformed_path = truncate(transformed_path, opts.__length, nil, -1)
if opts.__prefix == nil then
opts.__prefix = 0
end
transformed_path = truncate(transformed_path, opts.__length - opts.__prefix, nil, -1)
end
end
@ -393,19 +403,24 @@ function utils.get_os_command_output(cmd, cwd)
end
local command = table.remove(cmd, 1)
local stderr = {}
local stdout, ret = Job
:new({
command = command,
args = cmd,
cwd = cwd,
on_stderr = function(_, data)
table.insert(stderr, data)
end,
})
:sync()
local stdout, ret = Job:new({
command = command,
args = cmd,
cwd = cwd,
on_stderr = function(_, data)
table.insert(stderr, data)
end,
}):sync()
return stdout, ret, stderr
end
function utils.win_set_buf_noautocmd(win, buf)
local save_ei = vim.o.eventignore
vim.o.eventignore = "all"
vim.api.nvim_win_set_buf(win, buf)
vim.o.eventignore = save_ei
end
local load_once = function(f)
local resolved = nil
return function(...)
@ -431,13 +446,13 @@ utils.transform_devicons = load_once(function()
return display
end
local icon, icon_highlight = devicons.get_icon(filename, string.match(filename, "%a+$"), { default = true })
local icon, icon_highlight = devicons.get_icon(utils.path_tail(filename), nil, { default = true })
local icon_display = (icon or " ") .. " " .. (display or "")
if conf.color_devicons then
return icon_display, icon_highlight
else
return icon_display, "TelescopeResultsFileIcon"
return icon_display, nil
end
end
else
@ -461,11 +476,11 @@ utils.get_devicons = load_once(function()
return ""
end
local icon, icon_highlight = devicons.get_icon(filename, string.match(filename, "%a+$"), { default = true })
local icon, icon_highlight = devicons.get_icon(utils.path_tail(filename), nil, { default = true })
if conf.color_devicons then
return icon, icon_highlight
else
return icon, "TelescopeResultsFileIcon"
return icon, nil
end
end
else

View File

@ -488,7 +488,7 @@ describe("actions", function()
eq("replaced:vnew", actions.file_vsplit())
end)
it("handles backwards compat with select and edit files", function()
pending("handles backwards compat with select and edit files", function()
-- Reproduce steps:
-- In config, we have { ["<CR>"] = actions.select, ... }
-- In caller, we have actions._goto:replace(...)

View File

@ -1,6 +1,9 @@
require("plenary.reload").reload_module "telescope"
-- Just skip on mac, it has flaky CI for some reason
if vim.fn.has "mac" == 1 then
return
end
local tester = require "telescope.pickers._test"
local tester = require "telescope.testharness"
local disp = function(val)
return vim.inspect(val, { newline = " ", indent = "" })
@ -11,10 +14,6 @@ describe("builtin.find_files", function()
tester.run_file "find_files__readme"
end)
it("should be able to move selections", function()
tester.run_file "find_files__with_ctrl_n"
end)
for _, configuration in ipairs {
{ sorting_strategy = "descending" },
{ sorting_strategy = "ascending" },
@ -24,7 +23,7 @@ describe("builtin.find_files", function()
[[
local max_results = 5
tester.builtin_picker('find_files', 'README.md', {
runner.picker('find_files', 'README.md', {
post_typed = {
{ "> README.md", GetPrompt },
{ "> README.md", GetBestResult },
@ -41,56 +40,24 @@ describe("builtin.find_files", function()
height = max_results + 1,
width = 0.9,
},
border = false,
}, vim.json.decode([==[%s]==])))
]],
vim.json.encode(configuration)
))
end)
it("should only save one line for ascending, but many for descending", function()
local expected
if configuration.sorting_strategy == "descending" then
expected = 5
else
expected = 1
end
tester.run_string(string.format(
[[
local max_results = 5
tester.builtin_picker('find_files', 'README.md', {
post_typed = {
{ %s, function() return #GetResults() end },
},
}, vim.tbl_extend("force", {
disable_devicons = true,
sorter = require('telescope.sorters').get_fzy_sorter(),
layout_strategy = 'center',
layout_config = {
height = max_results + 1,
width = 0.9,
},
border = false,
}, vim.json.decode([==[%s]==])))
]],
expected,
vim.json.encode(configuration)
))
end)
it("use devicons, if it has it when enabled", function()
pending("use devicons, if it has it when enabled", function()
if not pcall(require, "nvim-web-devicons") then
return
end
local md = require("nvim-web-devicons").get_icon "md"
tester.run_string(string.format(
[[
tester.builtin_picker('find_files', 'README.md', {
runner.picker('find_files', 'README.md', {
post_typed = {
{ "> README.md", GetPrompt },
{ "> README.md", GetBestResult }
{ "> %s README.md", GetBestResult }
},
post_close = {
{ 'README.md', GetFile },
@ -101,6 +68,7 @@ describe("builtin.find_files", function()
sorter = require('telescope.sorters').get_fzy_sorter(),
}, vim.json.decode([==[%s]==])))
]],
md,
vim.json.encode(configuration)
))
end)
@ -108,7 +76,7 @@ describe("builtin.find_files", function()
it("should find the readme, using lowercase", function()
tester.run_string [[
tester.builtin_picker('find_files', 'readme.md', {
runner.picker('find_files', 'readme.md', {
post_close = {
{ 'README.md', GetFile },
}
@ -118,7 +86,7 @@ describe("builtin.find_files", function()
it("should find the pickers.lua, using lowercase", function()
tester.run_string [[
tester.builtin_picker('find_files', 'pickers.lua', {
runner.picker('find_files', 'pickers.lua', {
post_close = {
{ 'pickers.lua', GetFile },
}
@ -128,7 +96,7 @@ describe("builtin.find_files", function()
it("should find the pickers.lua", function()
tester.run_string [[
tester.builtin_picker('find_files', 'pickers.lua', {
runner.picker('find_files', 'pickers.lua', {
post_close = {
{ 'pickers.lua', GetFile },
{ 'pickers.lua', GetFile },
@ -139,20 +107,13 @@ describe("builtin.find_files", function()
it("should be able to c-n the items", function()
tester.run_string [[
tester.builtin_picker('find_files', 'fixtures/file<c-p>', {
runner.picker('find_files', 'fixtures/file<c-n>', {
post_typed = {
{
{
" lua/tests/fixtures/file_abc.txt",
"> lua/tests/fixtures/file_a.txt",
}, function()
local res = GetResults()
return {
res[#res - 1],
res[#res],
}
end
" lua/tests/fixtures/file_a.txt",
"> lua/tests/fixtures/file_abc.txt",
}, GetResults
},
},
post_close = {
@ -160,6 +121,7 @@ describe("builtin.find_files", function()
},
}, {
sorter = require('telescope.sorters').get_fzy_sorter(),
sorting_strategy = "ascending",
disable_devicons = true,
})
]]
@ -167,7 +129,7 @@ describe("builtin.find_files", function()
it("should be able to get the current selection", function()
tester.run_string [[
tester.builtin_picker('find_files', 'fixtures/file_abc', {
runner.picker('find_files', 'fixtures/file_abc', {
post_typed = {
{ 'lua/tests/fixtures/file_abc.txt', GetSelectionValue },
}

View File

@ -75,6 +75,14 @@ describe("telescope.config.resolve", function()
end
end)
it("should handle percentages with min/max boundary", function()
eq(20, resolve.resolve_width { 0.1, min = 20 }(nil, 40, 120))
eq(30, resolve.resolve_height { 0.1, min = 20 }(nil, 40, 300))
eq(24, resolve.resolve_width { 0.4, max = 80 }(nil, 60, 60))
eq(80, resolve.resolve_height { 0.4, max = 80 }(nil, 60, 300))
end)
it("should handle fixed size", function()
local fixed = { 5, 8, 13, 21, 34 }
for _, s in ipairs(test_sizes) do

View File

@ -1,7 +1,7 @@
local tester = require "telescope.pickers._test"
local helper = require "telescope.pickers._test_helpers"
local helper = require "telescope.testharness.helpers"
local runner = require "telescope.testharness.runner"
tester.builtin_picker("find_files", "README.md", {
runner.picker("find_files", "README.md", {
post_close = {
{ "README.md", helper.get_file },
},

View File

@ -1,10 +1,8 @@
require("plenary.reload").reload_module "plenary"
require("plenary.reload").reload_module "telescope"
local tester = require "telescope.testharness"
local helper = require "telescope.testharness.helpers"
local runner = require "telescope.testharness.runner"
local tester = require "telescope.pickers._test"
local helper = require "telescope.pickers._test_helpers"
tester.builtin_picker("find_files", "telescope<c-n>", {
runner.picker("find_files", "telescope<c-n>", {
post_close = {
tester.not_ { "plugin/telescope.vim", helper.get_file },
},

View File

@ -1,8 +0,0 @@
local tester = require "telescope.pickers._test"
local helper = require "telescope.pickers._test_helpers"
tester.builtin_picker("find_files", "fixtures/file<c-p>", {
post_close = {
{ "lua/tests/fixtures/file_abc.txt", helper.get_selection_value },
},
})

View File

@ -1,47 +0,0 @@
local finders = require('telescope.finders')
local previewers = require('telescope.previewers')
local pickers = require('telescope.pickers')
local sorters = require('telescope.sorters')
-- Get all the items from v:oldfiles that are valid files
local valid_oldfiles = vim.tbl_filter(function(val)
return 0 ~= vim.fn.filereadable(val)
end, vim.v.oldfiles)
-- print(vim.inspect(valid_oldfiles))
-- => {
-- "/home/tj/blah.txt",
-- "/home/tj/another_dir/file.py",
-- ...
-- }
-- Create a finder from a Lua list.
local oldfiles_finder = finders.new_table(valid_oldfiles)
-- Get a pre-defined sorter.
-- Sorters return a "score" for each "Entry" found by a finder.
--
-- This sorter is optimized to best find files in a fuzzy manner.
local oldfiles_sorter = sorters.get_fuzzy_file()
-- Get a pre-defined previewer.
-- Previewers take the currently selected entry,
-- and put a preview of it in a floating window
local oldfiles_previewer = previewers.cat
-- Create and run a Picker.
-- Pickers are the main entry point to telescope.
-- They manage the interactions between:
-- Finder,
-- Sorter,
-- Previewer
--
-- And provide the UI for the user.
pickers.new {
prompt = 'Oldfiles',
finder = oldfiles_finder,
sorter = oldfiles_sorter,
previewer = oldfiles_previewer,
}:find()

View File

@ -1,30 +0,0 @@
local finders = require('telescope.finders')
local previewers = require('telescope.previewers')
local pickers = require('telescope.pickers')
-- Create a new finder.
-- This finder, rather than taking a Lua list,
-- generates a shell command that should be run.
--
-- Each line of the shell command is converted to an entry,
-- and is possible to preview with builtin previews.
--
-- In this example, we use ripgrep to search over your entire directory
-- live as you type.
local live_grepper = finders.new_job(function(prompt)
if not prompt or prompt == "" then
return nil
end
return { 'rg', "--vimgrep", prompt}
end)
-- Create and run the Picker.
--
-- NOTE: No sorter is needed to be passed.
-- Results will be returned in the order they are received.
pickers.new({
prompt = 'Live Grep',
finder = live_grepper,
previewer = previewers.vimgrep,
}):find()

View File

@ -1,34 +0,0 @@
### Simple demo to show the rg stuff
## key_delay 1
## feed_full
:e! ./scratch/simple_rg.lua\<CR>
:set foldlevel=100\<CR>
:luafile %\<CR>
## pause
## key_delay 80
Finder
## key_delay 150
\<c-n>
## pause
\<c-n>
## pause
\<c-n>
## pause
\<cr>
## pause
\<esc>
:" Went to the file!\<esc>
## pause
## feed_full
:qa!\<CR>

View File

@ -1,26 +0,0 @@
+-------------------------------------------------------------------+
| Picker:find()--------------------+ +------>Picker |
| | ^ | | |
| | | v | |
| | +----------------+ +----------------+ |
| +->| Finder + | Sorter | |
| +----------------+ +----------------+ |
| [1] |
| |
| |
| |
| |
| |
| |
+-------------------------------------------------------------------+
Picker starts a `finder`.
Finder returns a list of `entries` to Picker.
Picker can optionally sort w/ `Sorter`.
Picker can optionally preview selected with `Previewer`
Then you can map stuff in the picker to decide what to do next.

View File

@ -82,7 +82,6 @@ local highlights = {
TelescopeResultsNumber = { default = true, link = "Number" },
TelescopeResultsComment = { default = true, link = "Comment" },
TelescopeResultsSpecialComment = { default = true, link = "SpecialComment" },
TelescopeResultsFileIcon = { default = true, link = "Normal" },
-- Used for git status Results highlighting
TelescopeResultsDiffChange = { default = true, link = "DiffChange" },

View File

@ -1,55 +0,0 @@
local actions = require('telescope.actions')
local finders = require('telescope.finders')
local previewers = require('telescope.previewers')
local pickers = require('telescope.pickers')
local sorters = require('telescope.sorters')
local utils = require('telescope.utils')
local Job = require('plenary.job')
-- local live_grepper = finders.new {
-- fn_command = function(_, prompt)
-- -- TODO: Make it so that we can start searching on the first character.
-- if not prompt or prompt == "" then
-- return nil
-- end
-- return {
-- command = 'rg',
-- args = {"--vimgrep", prompt},
-- }
-- end
-- }
local f = function(prompt, process_result, process_complete)
local fzf = Job:new {
command = 'fzf';
writer = Job:new {
command = "fdfind",
args = nil,
cwd = "/home/tj/build/neovim",
enable_handlers = false,
},
-- Still doesn't work if you don't pass these args and just run `fzf`
args = {'--no-sort', '--filter', prompt};
}
local start = vim.fn.reltime()
print(vim.inspect(fzf:sync()), vim.fn.reltimestr(vim.fn.reltime(start)))
end
-- Process all the files
-- f("", nil, nil)
-- Filter on nvimexec
f("nvim/executor", nil, nil)
-- pickers.new({}, {
-- prompt = 'Live Grep',
-- finder = f,
-- previewer = previewers.vimgrep,
-- }):find()

View File

@ -1,33 +0,0 @@
RELOAD('telescope')
RELOAD('plenary')
local finders = require('telescope.finders')
local make_entry = require('telescope.make_entry')
local pickers = require('telescope.pickers')
local sorters = require('telescope.sorters')
local Job = require('plenary.job')
pickers.new {
prompt = "Piped FZF",
finder = finders._new {
fn_command = function(_, prompt)
return {
command = 'fzf',
args = {'--no-sort', '--filter', prompt or ''},
writer = Job:new {
command = 'rg',
args = {'--files'},
cwd = '/home/tj/',
enable_handlers = false,
},
}
end,
entry_maker = make_entry.gen_from_file(),
sorter = sorters.get_fuzzy_file(),
},
}:find()

View File

@ -1,11 +0,0 @@
echo "hello"
sleep 1
echo "help"
sleep 1
echo "hi"
sleep 1
echo "husband"
sleep 1
echo "helper"

View File

@ -15,8 +15,12 @@ docs.test = function()
"./lua/telescope/command.lua",
"./lua/telescope/builtin/init.lua",
"./lua/telescope/themes.lua",
"./lua/telescope/mappings.lua",
"./lua/telescope/pickers/layout_strategies.lua",
"./lua/telescope/config/resolve.lua",
"./lua/telescope/make_entry.lua",
"./lua/telescope/pickers/entry_display.lua",
"./lua/telescope/utils.lua",
"./lua/telescope/actions/init.lua",
"./lua/telescope/actions/state.lua",
"./lua/telescope/actions/set.lua",

View File

@ -4,3 +4,6 @@ set rtp+=../tree-sitter-lua/
runtime! plugin/plenary.vim
runtime! plugin/telescope.lua
runtime! plugin/ts_lua.vim
let g:telescope_test_delay = 100

View File

@ -1,55 +1,58 @@
if vim.b.did_ftp == true then
return
return
end
vim.opt_local.cursorline = true
vim.opt_local.modifiable = true
vim.opt_local.buflisted = true
vim.opt_local.syntax = "zkbrowser"
vim.opt_local.buftype = "nofile"
vim.opt_local.modifiable = false
vim.opt_local.buflisted = false
vim.opt_local.syntax = 'zkbrowser'
vim.opt_local.buftype = 'nofile'
vim.opt_local.swapfile = false
vim.opt_local.iskeyword:append(":")
vim.opt_local.iskeyword:append("-")
vim.opt_local.suffixesadd:append(".md")
vim.opt_local.errorformat = "%f:%l: %m"
vim.opt_local.iskeyword:append(':')
vim.opt_local.iskeyword:append('-')
vim.opt_local.suffixesadd:append('.md')
vim.opt_local.errorformat = '%f:%l: %m'
if vim.opt_local.keywordprg:get() == "" then
vim.opt_local.keywordprg = ":ZkHover -preview"
if vim.opt_local.keywordprg:get() == '' then
vim.opt_local.keywordprg = ':ZkHover -preview'
end
if vim.opt_local.tagfunc:get() == "" then
vim.opt_local.tagfunc = "v:lua.zettelkasten.tagfunc"
if vim.opt_local.tagfunc:get() == '' then
vim.opt_local.tagfunc = 'v:lua.zettelkasten.tagfunc'
end
require("zettelkasten").add_hover_command()
require('zettelkasten').add_hover_command()
if vim.fn.mapcheck("[I", "n") == "" then
vim.api.nvim_buf_set_keymap(
0,
"n",
"[I",
'<CMD>lua require("zettelkasten").show_back_references(vim.fn.expand("<cword>"))<CR>',
{ noremap = true, silent = true, nowait = true }
)
if vim.fn.mapcheck('[I', 'n') == '' then
vim.api.nvim_buf_set_keymap(
0,
'n',
'[I',
'<CMD>lua require("zettelkasten").show_back_references(vim.fn.expand("<cword>"))<CR>',
{ noremap = true, silent = true, nowait = true }
)
vim.api.nvim_buf_set_keymap(
0,
'n',
'q',
':bd!<cr>',
{ noremap = true, silent = true, nowait = true }
)
end
local config = require("zettelkasten.config").get()
if config.notes_path ~= "" then
vim.cmd("lcd " .. config.notes_path)
local config = require('zettelkasten.config')
if config.zettel_dir ~= '' then
vim.cmd('lcd ' .. config.zettel_dir)
end
vim.api.nvim_create_autocmd({ "BufEnter" }, {
group = vim.api.nvim_create_augroup("zettelkasten_browser_events", { clear = true }),
buffer = vim.api.nvim_get_current_buf(),
callback = function(opts)
vim.opt_local.syntax = ""
vim.api.nvim_buf_set_lines(
0,
vim.fn.line("$") - 1,
-1,
true,
require("zettelkasten").get_note_browser_content()
)
vim.opt_local.syntax = "zkbrowser"
end,
vim.api.nvim_create_autocmd({ 'BufEnter' }, {
group = vim.api.nvim_create_augroup('zettelkasten_browser_events', { clear = true }),
buffer = vim.api.nvim_get_current_buf(),
callback = function(opts)
vim.opt_local.syntax = ''
vim.opt_local.modifiable = true
vim.api.nvim_buf_set_lines(0, 0, -1, false, require('zettelkasten').get_note_browser_content())
vim.opt_local.syntax = 'zkbrowser'
vim.opt_local.modifiable = false
end,
})

View File

@ -1,314 +1,337 @@
--=============================================================================
-- zettelkasten.lua --- zk plugin
-- Copyright (c) 2016-2022 Wang Shidong & Contributors
-- Author: Wang Shidong < wsdjeg@outlook.com >
-- URL: https://spacevim.org
-- License: GPLv3
--=============================================================================
local M = {}
local api = vim.api
local fn = vim.fn
local log_levels = vim.log.levels
local log = require("zettelkasten.log")
local config = require("zettelkasten.config")
local formatter = require("zettelkasten.formatter")
local browser = require("zettelkasten.browser")
local log = require('zettelkasten.log')
local config = require('zettelkasten.config')
local formatter = require('zettelkasten.formatter')
local browser = require('zettelkasten.browser')
local NOTE_ID_STRFTIME_FORMAT = "%Y-%m-%d-%H-%M-%S"
local NOTE_ID_STRFTIME_FORMAT = '%Y-%m-%d-%H-%M-%S'
local function set_qflist(lines, action, bufnr, use_loclist, what)
what = what or {}
local _, local_efm = pcall(vim.api.nvim_buf_get_option, bufnr, "errorformat")
what.efm = what.efm or local_efm
if use_loclist then
fn.setloclist(bufnr, lines, action, what)
else
fn.setqflist(lines, action, what)
end
what = what or {}
local _, local_efm = pcall(vim.api.nvim_buf_get_option, bufnr, 'errorformat')
what.efm = what.efm or local_efm
if use_loclist then
fn.setloclist(bufnr, lines, action, what)
else
fn.setqflist(lines, action, what)
end
end
local function read_note(file_path, line_count)
local file = io.open(file_path, "r")
assert(file ~= nil)
assert(file:read(0) ~= nil)
local file = io.open(file_path, 'r')
assert(file ~= nil)
assert(file:read(0) ~= nil)
if line_count == nil then
return file:read("*all")
if line_count == nil then
return file:read('*all')
end
local lines = {}
while #lines < line_count do
local line = file:read('*line')
if line == nil then
break
end
local lines = {}
while #lines < line_count do
local line = file:read("*line")
if line == nil then
break
end
table.insert(lines, line)
end
table.insert(lines, line)
end
return lines
return lines
end
local function get_all_tags(lookup_tag)
if lookup_tag ~= nil and #lookup_tag > 0 then
lookup_tag = string.gsub(lookup_tag, "\\<", "")
lookup_tag = string.gsub(lookup_tag, "\\>", "")
end
if lookup_tag ~= nil and #lookup_tag > 0 then
lookup_tag = string.gsub(lookup_tag, '\\<', '')
lookup_tag = string.gsub(lookup_tag, '\\>', '')
end
local tags = browser.get_tags()
if lookup_tag ~= nil and #lookup_tag > 0 then
tags = vim.tbl_filter(function(tag)
return string.match(tag.name, lookup_tag) ~= nil
end, tags)
end
local tags = browser.get_tags()
if lookup_tag ~= nil and #lookup_tag > 0 then
tags = vim.tbl_filter(function(tag)
return string.match(tag.name, lookup_tag) ~= nil
end, tags)
end
return tags
return tags
end
local function generate_note_id()
return fn.strftime(NOTE_ID_STRFTIME_FORMAT)
return fn.strftime(NOTE_ID_STRFTIME_FORMAT)
end
function M.completefunc(find_start, base)
if find_start == 1 and base == "" then
local pos = api.nvim_win_get_cursor(0)
local line = api.nvim_get_current_line()
local line_to_cursor = line:sub(1, pos[2])
return fn.match(line_to_cursor, "\\k*$")
end
if find_start == 1 and base == '' then
local pos = api.nvim_win_get_cursor(0)
local line = api.nvim_get_current_line()
local line_to_cursor = line:sub(1, pos[2])
return fn.match(line_to_cursor, '\\k*$')
end
local notes = vim.tbl_filter(function(note)
return string.match(note.title, base)
end, browser.get_notes())
local notes = vim.tbl_filter(function(note)
-- here the note sometimes do not have title, then it is nil
return string.match(note.title, base)
end, browser.get_notes())
local words = {}
for _, ref in ipairs(notes) do
table.insert(words, {
word = ref.id,
abbr = ref.title,
dup = 0,
empty = 0,
kind = "[zettelkasten]",
icase = 1,
})
end
local words = {}
for _, ref in ipairs(notes) do
table.insert(words, {
word = ref.id,
abbr = ref.title,
dup = 0,
empty = 0,
kind = '[zettelkasten]',
icase = 1,
})
end
return words
return words
end
function M.set_note_id(bufnr)
local first_line = vim.api.nvim_buf_get_lines(bufnr, 0, 1, true)[1]
local zk_id = generate_note_id()
if #zk_id > 0 then
first_line, _ = string.gsub(first_line, "# ", "")
api.nvim_buf_set_lines(bufnr, 0, 1, true, { "# " .. zk_id .. " " .. first_line })
vim.cmd("file " .. zk_id .. ".md")
else
log.notify("There's already a note with the same ID.", log_levels.ERROR, {})
end
local first_line = vim.api.nvim_buf_get_lines(bufnr, 0, 1, true)[1]
local zk_id = generate_note_id()
if #zk_id > 0 then
first_line, _ = string.gsub(first_line, '# ', '')
api.nvim_buf_set_lines(bufnr, 0, 1, true, { '# ' .. zk_id .. ' ' .. first_line })
vim.cmd('file ' .. zk_id .. '.md')
else
log.notify("There's already a note with the same ID.", log_levels.ERROR, {})
end
end
function M.tagfunc(pattern, flags, info)
local in_insert = string.match(flags, "i") ~= nil
local pattern_provided = pattern ~= "\\<\\k\\k" or pattern == "*"
local all_tags = {}
if pattern_provided then
all_tags = get_all_tags(pattern)
else
all_tags = get_all_tags()
end
local in_insert = string.match(flags, 'i') ~= nil
local pattern_provided = pattern ~= '\\<\\k\\k' or pattern == '*'
local all_tags = {}
if pattern_provided then
all_tags = get_all_tags(pattern)
else
all_tags = get_all_tags()
end
local tags = {}
for _, tag in ipairs(all_tags) do
local tags = {}
for _, tag in ipairs(all_tags) do
table.insert(tags, {
name = string.gsub(tag.name, '#', ''),
filename = tag.file_name,
cmd = tostring(tag.linenr),
kind = 'zettelkasten',
})
end
if not in_insert then
local notes = browser.get_notes()
for _, note in ipairs(notes) do
if string.find(note.id, pattern, 1, true) or not pattern_provided then
table.insert(tags, {
name = string.gsub(tag.name, "#", ""),
filename = tag.file_name,
cmd = tostring(tag.linenr),
kind = "zettelkasten",
name = note.id,
filename = note.file_name,
cmd = '1',
kind = 'zettelkasten',
})
end
end
end
if not in_insert then
local notes = browser.get_notes()
for _, note in ipairs(notes) do
if string.find(note.id, pattern, 1, true) or not pattern_provided then
table.insert(tags, {
name = note.id,
filename = note.file_name,
cmd = "1",
kind = "zettelkasten",
})
end
end
end
if #tags > 0 then
return tags
end
if #tags > 0 then
return tags
end
return nil
return nil
end
function M.keyword_expr(word, opts)
if not word then
return {}
end
if not word then
return {}
end
opts = opts or {}
opts.preview_note = opts.preview_note or false
opts.return_lines = opts.return_lines or false
opts = opts or {}
opts.preview_note = opts.preview_note or false
opts.return_lines = opts.return_lines or false
local note = browser.get_note(word)
if note == nil then
log.notify("Cannot find note.", log_levels.ERROR, {})
return {}
end
local note = browser.get_note(word)
if note == nil then
log.notify('Cannot find note.', log_levels.ERROR, {})
return {}
end
local lines = {}
if opts.preview_note and not opts.return_lines then
vim.cmd(config.get().preview_command .. " " .. note.file_name)
elseif opts.preview_note and opts.return_lines then
vim.list_extend(lines, read_note(note.file_name))
else
table.insert(lines, note.title)
end
local lines = {}
if opts.preview_note and not opts.return_lines then
vim.cmd(config.preview_command .. ' ' .. note.file_name)
elseif opts.preview_note and opts.return_lines then
vim.list_extend(lines, read_note(note.file_name))
else
table.insert(lines, note.title)
end
return lines
return lines
end
function M.get_back_references(note_id)
local note = browser.get_note(note_id)
if note == nil then
return {}
local note = browser.get_note(note_id)
if note == nil then
return {}
end
local title_cache = {}
local get_title = function(id)
if title_cache[id] ~= nil then
return title_cache[id]
end
local title_cache = {}
local get_title = function(id)
if title_cache[id] ~= nil then
return title_cache[id]
end
title_cache[id] = browser.get_note(id).title
return title_cache[id]
end
title_cache[id] = browser.get_note(id).title
return title_cache[id]
end
local references = {}
for _, back_reference in ipairs(note.back_references) do
table.insert(references, {
id = back_reference.id,
linenr = back_reference.linenr,
title = back_reference.title,
file_name = back_reference.file_name,
})
end
local references = {}
for _, back_reference in ipairs(note.back_references) do
table.insert(references, {
id = back_reference.id,
linenr = back_reference.linenr,
title = back_reference.title,
file_name = back_reference.file_name,
})
end
return references
return references
end
function M.show_back_references(cword, use_loclist)
use_loclist = use_loclist or false
local references = M.get_back_references(cword)
if #references == 0 then
log.notify("No back references found.", log_levels.ERROR, {})
return
end
use_loclist = use_loclist or false
local references = M.get_back_references(cword)
if #references == 0 then
log.notify('No back references found.', log_levels.ERROR, {})
return
end
local lines = {}
for _, ref in ipairs(references) do
local line = {}
table.insert(line, fn.fnamemodify(ref.file_name, ":."))
table.insert(line, ":")
table.insert(line, ref.linenr)
table.insert(line, ": ")
table.insert(line, ref.title)
local lines = {}
for _, ref in ipairs(references) do
local line = {}
table.insert(line, fn.fnamemodify(ref.file_name, ':.'))
table.insert(line, ':')
table.insert(line, ref.linenr)
table.insert(line, ': ')
table.insert(line, ref.title)
table.insert(lines, table.concat(line, ""))
end
table.insert(lines, table.concat(line, ''))
end
set_qflist(
{},
" ",
vim.api.nvim_get_current_buf(),
use_loclist,
{ title = "[[" .. cword .. "]] References", lines = lines }
)
set_qflist(
{},
' ',
vim.api.nvim_get_current_buf(),
use_loclist,
{ title = '[[' .. cword .. ']] References', lines = lines }
)
if use_loclist then
vim.cmd([[botright lopen | wincmd p]])
else
vim.cmd([[botright copen | wincmd p]])
end
if use_loclist then
vim.cmd([[botright lopen | wincmd p]])
else
vim.cmd([[botright copen | wincmd p]])
end
end
function M.get_toc(note_id, format)
format = format or "- [%h](%d)"
local references = M.get_back_references(note_id)
local lines = {}
for _, note in ipairs(references) do
table.insert(lines, {
file_name = note.file_name,
id = note.id,
title = note.title,
})
end
format = format or '- [%h](%d)'
local references = M.get_back_references(note_id)
local lines = {}
for _, note in ipairs(references) do
table.insert(lines, {
file_name = note.file_name,
id = note.id,
title = note.title,
})
end
return formatter.format(lines, format)
return formatter.format(lines, format)
end
function M.get_note_browser_content()
if config.get().notes_path == "" then
log.notify("'notes_path' option is required for note browsing.", log_levels.WARN, {})
return {}
end
if config.zettel_dir == '' then
log.notify("'notes_path' option is required for note browsing.", log_levels.WARN, {})
return {}
end
local all_notes = browser.get_notes()
local lines = {}
for _, note in ipairs(all_notes) do
table.insert(lines, {
file_name = note.file_name,
id = note.id,
references = note.references,
back_references = note.back_references,
tags = note.tags,
title = note.title,
})
end
local all_notes = browser.get_notes()
local lines = {}
for _, note in ipairs(all_notes) do
table.insert(lines, {
file_name = note.file_name,
id = note.id,
references = note.references,
back_references = note.back_references,
tags = note.tags,
title = note.title,
})
end
return formatter.format(lines, config.get().browseformat)
return formatter.format(lines, config.browseformat)
end
function M.add_hover_command()
if fn.exists(":ZkHover") == 2 then
return
end
if fn.exists(':ZkHover') == 2 then
return
end
vim.cmd(
[[command -buffer -nargs=1 ZkHover :lua require"zettelkasten"._internal_execute_hover_cmd(<q-args>)]]
)
vim.cmd(
[[command -buffer -nargs=1 ZkHover :lua require"zettelkasten"._internal_execute_hover_cmd(<q-args>)]]
)
end
function M._internal_execute_hover_cmd(args)
if args ~= nil and type(args) == "string" then
args = vim.split(args, " ", true)
else
args = {}
end
if args ~= nil and type(args) == 'string' then
args = vim.split(args, ' ', true)
else
args = {}
end
local cword = ""
if #args == 1 then
cword = fn.expand("<cword>")
else
cword = args[#args]
end
local cword = ''
if #args == 1 then
cword = fn.expand('<cword>')
else
cword = args[#args]
end
local lines = M.keyword_expr(cword, {
preview_note = vim.tbl_contains(args, "-preview"),
return_lines = vim.tbl_contains(args, "-return-lines"),
})
if #lines > 0 then
log.notify(table.concat(lines, "\n"), log_levels.INFO, {})
end
local lines = M.keyword_expr(cword, {
preview_note = vim.tbl_contains(args, '-preview'),
return_lines = vim.tbl_contains(args, '-return-lines'),
})
if #lines > 0 then
log.notify(table.concat(lines, '\n'), log_levels.INFO, {})
end
end
function M.setup(opts)
opts = opts or {}
opts.notes_path = opts.notes_path or ""
function M.zknew(opt) -- {{{
vim.cmd([[new | setlocal filetype=markdown]])
if config.zettel_dir ~= '' then
if vim.fn.isdirectory(config.zettel_dir) == 0 then
vim.fn.mkdir(vim.fn.expand(config.zettel_dir), 'p', '0700')
end
vim.cmd('lcd ' .. config.zettel_dir)
end
config._set(opts)
vim.cmd('normal ggI# New Note')
require('zettelkasten').set_note_id(vim.api.nvim_get_current_buf())
vim.cmd('normal $')
end
-- }}}
function M.setup(opts)
opts = opts or {}
opts.notes_path = opts.notes_path or ''
config._set(opts)
end
return M

View File

@ -1,215 +1,219 @@
local M = {}
local fn = vim.fn
local config = require("zettelkasten.config")
local config = require('zettelkasten.config')
local ZK_FULL_TITLE_PATTERN = "# %d+-%d+-%d+-%d+-%d+-%d+ .+"
local ZK_ID_PATTERN = "%d+-%d+-%d+-%d+-%d+-%d+"
local ZK_FILE_NAME_PATTERN = "%d+-%d+-%d+-%d+-%d+-%d+.md"
local ZK_FULL_TITLE_PATTERN = '# %d+-%d+-%d+-%d+-%d+-%d+ .+'
local ZK_ID_PATTERN = '%d+-%d+-%d+-%d+-%d+-%d+'
local ZK_FILE_NAME_PATTERN = '%d+-%d+-%d+-%d+-%d+-%d+.md'
local s_note_cache_with_file_path = {}
local s_note_cache_with_id = {}
local function get_files(folder)
local files = fn.split(fn.globpath(folder, "*.md"), "\\n")
files = vim.tbl_filter(function(file)
return string.match(file, ZK_FILE_NAME_PATTERN) ~= nil
end, files)
local files = fn.split(fn.globpath(folder, '*.md'), '\\n')
files = vim.tbl_filter(function(file)
return string.match(file, ZK_FILE_NAME_PATTERN) ~= nil
end, files)
return files
return files
end
local function extract_id_and_title(line)
local zk_id = string.match(line, ZK_FULL_TITLE_PATTERN)
if zk_id == nil then
return nil
end
local zk_id = string.match(line, ZK_FULL_TITLE_PATTERN)
if zk_id == nil then
return nil
end
zk_id = string.gsub(zk_id, "# ", "")
local note_id = string.match(zk_id, ZK_ID_PATTERN)
local title = vim.trim(string.gsub(zk_id, ZK_ID_PATTERN, ""))
zk_id = string.gsub(zk_id, '# ', '')
local note_id = string.match(zk_id, ZK_ID_PATTERN)
local title = vim.trim(string.gsub(zk_id, ZK_ID_PATTERN, ''))
return { id = note_id, title = string.gsub(title, "\r", "") }
return { id = note_id, title = string.gsub(title, '\r', '') }
end
local function extract_references(line, linenr)
assert(line ~= nil)
assert(line ~= nil)
local references = {}
for ref in string.gmatch(line, "(%[%[" .. ZK_ID_PATTERN .. "%]%])") do
ref = string.gsub(ref, "%[%[", "")
ref = string.gsub(ref, "%]%]", "")
table.insert(references, { id = ref, linenr = linenr })
end
local references = {}
for ref in string.gmatch(line, '(%[%[' .. ZK_ID_PATTERN .. '%]%])') do
ref = string.gsub(ref, '%[%[', '')
ref = string.gsub(ref, '%]%]', '')
table.insert(references, { id = ref, linenr = linenr })
end
return references
return references
end
local function extract_back_references(notes, note_id)
assert(note_id ~= nil)
assert(note_id ~= nil)
local back_references = {}
for _, note in ipairs(notes) do
if note.id == note_id then
goto continue
end
local references = note.references
for _, ref in ipairs(references) do
if ref.id == note_id then
table.insert(back_references, {
id = note.id,
title = note.title,
file_name = note.file_name,
linenr = ref.linenr,
})
break
end
end
::continue::
local back_references = {}
for _, note in ipairs(notes) do
if note.id == note_id then
goto continue
end
return back_references
local references = note.references
for _, ref in ipairs(references) do
if ref.id == note_id then
table.insert(back_references, {
id = note.id,
title = note.title,
file_name = note.file_name,
linenr = ref.linenr,
})
break
end
end
::continue::
end
return back_references
end
local function extract_tags(line, linenr)
assert(line ~= nil)
assert(line ~= nil)
local tags = {}
for tag in string.gmatch(line, "(%#%a[%w-]+)") do
local start_pos, _ = string.find(line, tag, 1, true)
local previous_char = string.sub(line, start_pos - 1, start_pos - 1)
if previous_char == "" or previous_char == " " then
table.insert(tags, { linenr = linenr, name = tag })
end
local tags = {}
for tag in string.gmatch(line, '(%#%a[%w-]+)') do
local start_pos, _ = string.find(line, tag, 1, true)
local previous_char = string.sub(line, start_pos - 1, start_pos - 1)
if previous_char == '' or previous_char == ' ' then
table.insert(tags, { linenr = linenr, name = tag })
end
end
return tags
return tags
end
local function get_note_information(file_path)
local last_modified = fn.strftime("%Y-%m-%d.%H:%M:%S", fn.getftime(file_path))
if
s_note_cache_with_file_path[file_path] ~= nil
and s_note_cache_with_file_path[file_path].last_modified == last_modified
then
return s_note_cache_with_file_path[file_path]
local last_modified = fn.strftime('%Y-%m-%d.%H:%M:%S', fn.getftime(file_path))
if
s_note_cache_with_file_path[file_path] ~= nil
and s_note_cache_with_file_path[file_path].last_modified == last_modified
then
return s_note_cache_with_file_path[file_path]
end
local file = io.open(file_path, 'r')
if file:read(0) == nil then
return nil
end
local info = {
id = '',
title = '',
file_name = file_path,
last_modified = last_modified,
tags = {},
references = {},
back_references = {},
}
local linenr = 0
while true do
linenr = linenr + 1
local line = file:read('*line')
if line == nil then
break
end
local file = io.open(file_path, "r")
if file:read(0) == nil then
return nil
if line == '' then
goto continue
end
local info = {
file_name = file_path,
last_modified = last_modified,
tags = {},
references = {},
back_references = {},
}
local linenr = 0
while true do
linenr = linenr + 1
local line = file:read("*line")
if line == nil then
break
end
if line == "" then
goto continue
end
if info.id == nil then
local id_title = extract_id_and_title(line)
if id_title then
info = vim.tbl_extend("error", info, id_title)
goto continue
end
end
local refs = extract_references(line, linenr)
if refs then
vim.list_extend(info.references, refs)
end
local tags = extract_tags(line, linenr)
if tags then
vim.list_extend(info.tags, tags)
end
::continue::
if info.id == '' then
local id_title = extract_id_and_title(line)
if id_title then
info = vim.tbl_extend('force', info, id_title)
goto continue
end
end
local refs = extract_references(line, linenr)
if refs then
vim.list_extend(info.references, refs)
end
local tags = extract_tags(line, linenr)
if tags then
vim.list_extend(info.tags, tags)
end
::continue::
end
if info.id ~= nil then
s_note_cache_with_file_path[file_path] = info
s_note_cache_with_id[info.id] = info
return info
end
return info
end
function M.get_note(id)
if s_note_cache_with_id[id] ~= nil then
return s_note_cache_with_id[id]
end
if s_note_cache_with_id[id] ~= nil then
return s_note_cache_with_id[id]
end
local _ = M.get_notes()
local _ = M.get_notes()
if s_note_cache_with_id[id] ~= nil then
return s_note_cache_with_id[id]
end
if s_note_cache_with_id[id] ~= nil then
return s_note_cache_with_id[id]
end
return nil
return nil
end
function M.get_notes()
local folder = config.get().notes_path
local files = get_files(folder)
local all_notes = {}
for _, file in ipairs(files) do
table.insert(all_notes, get_note_information(file))
local folder = config.zettel_dir
local files = get_files(folder)
local all_notes = {}
for _, file in ipairs(files) do
table.insert(all_notes, get_note_information(file))
end
for _, note in ipairs(all_notes) do
if note.id == nil then
goto continue
end
for _, note in ipairs(all_notes) do
if note.id == nil then
goto continue
end
local back_references = extract_back_references(all_notes, note.id)
if back_references then
-- When notes are cached, `back_references` field will have the references from before.
-- Since the files that refer to this one might have changed, we'll overwrite it here.
-- extract_back_references() already re-processes the references.
note.back_references = back_references
end
::continue::
local back_references = extract_back_references(all_notes, note.id)
if back_references then
-- When notes are cached, `back_references` field will have the references from before.
-- Since the files that refer to this one might have changed, we'll overwrite it here.
-- extract_back_references() already re-processes the references.
note.back_references = back_references
end
return all_notes
::continue::
end
return all_notes
end
function M.get_tags()
local notes = M.get_notes()
local tags = {}
for _, note in ipairs(notes) do
if #note.tags == 0 then
goto continue
end
for _, tag in ipairs(note.tags) do
table.insert(tags, {
linenr = tag.linenr,
name = tag.name,
file_name = note.file_name,
})
end
::continue::
local notes = M.get_notes()
local tags = {}
for _, note in ipairs(notes) do
if #note.tags == 0 then
goto continue
end
return tags
for _, tag in ipairs(note.tags) do
table.insert(tags, {
linenr = tag.linenr,
name = tag.name,
file_name = note.file_name,
})
end
::continue::
end
return tags
end
return M

View File

@ -14,18 +14,17 @@ else
M.zettel_dir = '~/.zettelkasten/'
end
local s_config = {
notes_path = "",
preview_command = "pedit",
browseformat = "%f - %h [%r Refs] [%b B-Refs] %t",
}
M.get = function()
return s_config
if vim.g.zettelkasten_template_directory and vim.g.zettelkasten_template_directory ~= '' then
M.templete_dir = vim.g.zettelkasten_template_directory
else
M.templete_dir = '~/.zettelkasten_template'
end
M._set = function(new_config)
s_config = vim.tbl_extend("force", s_config, new_config)
M.browseformat = "%f - %h [%r Refs] [%b B-Refs] %t"
M.preview_command = "pedit"
M.get = function()
return nil
end
return M

View File

@ -1,54 +1,55 @@
local M = {}
local s_formatters = {
["%r"] = function(line)
return #line.references
end,
["%b"] = function(line)
return #line.back_references
end,
["%f"] = function(line)
return vim.fn.fnamemodify(line.file_name, ":t")
end,
["%h"] = function(line)
return line.title
end,
["%d"] = function(line)
return line.id
end,
["%t"] = function(line)
local tags = {}
for _, tag in ipairs(line.tags) do
if vim.tbl_contains(tags, tag.name) == false then
table.insert(tags, tag.name)
end
end
['%r'] = function(line)
return #line.references
end,
['%b'] = function(line)
return #line.back_references
end,
['%f'] = function(line)
return vim.fn.fnamemodify(line.file_name, ':t')
end,
['%h'] = function(line)
return line.title
end,
['%d'] = function(line)
return line.id
end,
['%t'] = function(line)
local tags = {}
for _, tag in ipairs(line.tags) do
if vim.tbl_contains(tags, tag.name) == false then
table.insert(tags, tag.name)
end
end
return table.concat(tags, " ")
end,
return table.concat(tags, ' ')
end,
}
local function get_format_keys(format)
local matches = {}
for w in string.gmatch(format, "%%%a") do
table.insert(matches, w)
end
local matches = {}
for w in string.gmatch(format, '%%%a') do
table.insert(matches, w)
end
return matches
return matches
end
function M.format(lines, format)
local formatted_lines = {}
local modifiers = get_format_keys(format)
for _, line in ipairs(lines) do
local cmps = format
for _, modifier in ipairs(modifiers) do
cmps = string.gsub(cmps, "%" .. modifier, s_formatters[modifier](line))
end
table.insert(formatted_lines, cmps)
local formatted_lines = {}
local modifiers = get_format_keys(format)
for _, line in ipairs(lines) do
local cmps = format
for _, modifier in ipairs(modifiers) do
local rst = s_formatters[modifier](line) or ''
cmps = string.gsub(cmps, '%' .. modifier, rst)
end
return formatted_lines
table.insert(formatted_lines, cmps)
end
return formatted_lines
end
return M

View File

@ -1,8 +1,12 @@
local api = vim.api
local s_config = require("zettelkasten.config")
--=============================================================================
-- zettelkasten.lua --- init plugin for zk
-- Copyright (c) 2016-2022 Wang Shidong & Contributors
-- Author: Wang Shidong < wsdjeg@outlook.com >
-- URL: https://spacevim.org
-- License: GPLv3
--=============================================================================
if vim.fn.exists(":ZkNew") == 0 then
vim.cmd([[command ZkNew :lua _G.zettelkasten.zknew()]])
vim.api.nvim_create_user_command("ZkNew", ":lua require('zettelkasten').zknew({})", {})
end
if vim.fn.exists(":ZkBrowse") == 0 then
@ -12,19 +16,7 @@ end
_G.zettelkasten = {
tagfunc = require("zettelkasten").tagfunc,
completefunc = require("zettelkasten").completefunc,
zknew = function()
vim.cmd([[new | setlocal filetype=markdown]])
if s_config.zettel_dir ~= "" then
if vim.fn.isdirectory(s_config.zettel_dir) == 0 then
vim.fn.mkdir(vim.fn.expand(s_config.zettel_dir), 'p', '0700')
end
vim.cmd("lcd " .. s_config.zettel_dir)
end
vim.cmd("normal ggI# New Note")
require("zettelkasten").set_note_id(vim.api.nvim_get_current_buf())
vim.cmd("normal $")
end,
zknew = require("zettelkasten").zknew,
zkbrowse = function()
vim.cmd("edit zk://browser")
end,

View File

@ -1,2 +1,6 @@
indent_type = "Spaces"
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
call_parentheses = "Always"

View File

@ -3,6 +3,7 @@ lua require('telescope').load_extension('messages')
lua require('telescope').load_extension('project')
lua require('telescope').load_extension('scriptnames')
lua require('telescope').load_extension('neoyank')
lua require('telescope').load_extension('zettelkasten_template')
if filereadable(g:_spacevim_root_dir . 'bundle/telescope-fzf-native.nvim/build/libfzf.so')
\ || filereadable(g:_spacevim_root_dir . 'bundle/telescope-fzf-native.nvim/build/libfzf.dll')
lua require('telescope').load_extension('fzf')

View File

@ -20,19 +20,33 @@ This layer adds support for zettelkasten in neovim.
## Install
To use this configuration layer, update your custom configuration file with:
This layer also requires `telescope` layer, so to use this configuration layer,
update your custom configuration file with:
```toml
# load the zettelkasten layer
[[layers]]
name = "zettelkasten"
# load the fuzzy finder layer: telescope
[[layers]]
name = "telescope"
```
## Layer options
- `zettel_dir`: set the default zettelkasten directory
- `zettel_dir`: set the zettelkasten directory, default is `~/.zettelkasten/`
- `zettel_template_dir`: set the zettelkasten template directory, default is `~/.zettelkasten_template`
## Key bindings
| Key bindings | description |
| ------------ | --------------- |
| `SPC m z n` | create new note |
| Key bindings | description |
| ------------ | ----------------------------- |
| `SPC m z n` | create new note |
| `SPC m z t` | create new note with template |
| `SPC m z b` | open zettelkasten browse |
In the zettelkasten browse buffer:
| key bindings | description |
| ------------ | ---------------- |
| `K` | preview the note |

View File

@ -0,0 +1,53 @@
local action_state = require("telescope.actions.state")
local actions = require("telescope.actions")
local conf = require("telescope.config").values
local entry_display = require("telescope.pickers.entry_display")
local finders = require("telescope.finders")
local pickers = require("telescope.pickers")
local zk_config = require("zettelkasten.config")
local function prepare_output_table()
local lines = {}
local result = vim.fn.globpath(zk_config.templete_dir, '**/*', 0, 1)
for _, templete in ipairs(result) do
table.insert(lines, templete)
end
return lines
end
local function show_script_names(opts)
opts = opts or {}
pickers.new(opts, {
prompt_title = "ZettelKasten Templete",
finder = finders.new_table {
results = prepare_output_table()
},
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
local entry = action_state.get_selected_entry()
actions.close(prompt_bufnr)
-- the file name is entry.value
-- do something with the file
vim.cmd('ZkNew')
local templete_context = vim.fn.readfile(entry.value, '')
vim.api.nvim_buf_set_lines(0, 0, -1, false, templete_context)
-- maybe this is a bug, the mode is insert mode.
vim.cmd('stopinsert')
end)
return true
end,
}):find()
end
local function run()
show_script_names()
end
return require("telescope").register_extension({
exports = {
-- Default when to argument is given, i.e. :Telescope scriptnames
zettelkasten_template = run,
},
})