Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 73536b848f | |||
| df6b58bc7d | |||
| 47193a0f4f | |||
| c930fb1594 | |||
| 2188552724 |
8 changed files with 229 additions and 67 deletions
65
README.md
65
README.md
|
|
@ -51,11 +51,12 @@ error: linker `cc` not found
|
|||
A command can be run that will launch the completion UI
|
||||
|
||||
| Command | Key Map | Description |
|
||||
| ---------- | ----------- | ------------------------------------------------------ |
|
||||
| IvyFd | \<leader\>p | Find files in your project with the fd cli file finder |
|
||||
| ------------------ | ----------- | ----------------------------------------------------------- |
|
||||
| IvyFd | \<leader\>p | Find files in your project with a custom rust file finder |
|
||||
| IvyAg | \<leader\>/ | Find content in files using the silver searcher |
|
||||
| IvyBuffers | \<leader\>b | Search though open buffers |
|
||||
| IvyLines | | Search the lines in the current buffer |
|
||||
| IvyWorkspaceSymbol | | Search for workspace symbols using the lsp workspace/symbol |
|
||||
|
||||
### Actions
|
||||
|
||||
|
|
@ -70,6 +71,41 @@ Action can be run on selected candidates provide functionality
|
|||
|
||||
## API
|
||||
|
||||
### ivy.run
|
||||
|
||||
The `ivy.run` function is the core function in the plugin, it will launch the
|
||||
completion window and display the items from your items function. When the
|
||||
users accept one of the candidates with an [action](#actions), it will call the
|
||||
callback function to in most cases open the item in the desired location.
|
||||
|
||||
```lua
|
||||
---@param name string
|
||||
---@param items fun(input: string): { content: string }[] | string
|
||||
---@param callback fun(result: string, action: string)
|
||||
vim.ivy.run = function(name, items, callback) end
|
||||
```
|
||||
|
||||
#### Name `string`
|
||||
|
||||
The name is the display name for the command and will be the name of the buffer
|
||||
in the completion window
|
||||
|
||||
#### Items `fun(input: string): { content: string }[] | string`
|
||||
|
||||
The items function is a function that will return the candidates to display in
|
||||
the completion window. This can return a string where each line will be a
|
||||
completion item. Or an array of tables where the `content` will be the
|
||||
completion item.
|
||||
|
||||
#### Callback `fun(result: string, action: string)`
|
||||
|
||||
The function that will run when the user selects a completion item. Generally
|
||||
this will open the item in the desired location. For example, in the file
|
||||
finder with will open the file in a new buffer. If the user selects the
|
||||
vertical split action it will open the buffer in a new `vsplit`
|
||||
|
||||
#### Example
|
||||
|
||||
```lua
|
||||
vim.ivy.run(
|
||||
-- The name given to the results window and displayed to the user
|
||||
|
|
@ -77,7 +113,30 @@ Action can be run on selected candidates provide functionality
|
|||
-- Call back function to get all the candidates that will be displayed in
|
||||
-- the results window, The `input` will be passed in, so you can filter
|
||||
-- your results with the value from the prompt
|
||||
function(input) return { "One", "Two", Three } end,
|
||||
function(input)
|
||||
vim.ivy.run(
|
||||
-- The name given to the results window and displayed to the user
|
||||
"Title",
|
||||
-- Call back function to get all the candidates that will be displayed in
|
||||
-- the results window, The `input` will be passed in, so you can filter
|
||||
-- your results with the value from the prompt
|
||||
function(input)
|
||||
return {
|
||||
{ content = "One" },
|
||||
{ content = "Two" },
|
||||
{ content = "Three" },
|
||||
}
|
||||
end,
|
||||
-- Action callback that will be called on the completion or peek actions.
|
||||
-- The currently selected item is passed in as the result.
|
||||
function(result) vim.cmd("edit " .. result) end
|
||||
)
|
||||
return {
|
||||
{ content = "One" },
|
||||
{ content = "Two" },
|
||||
{ content = "Three" },
|
||||
}
|
||||
end,
|
||||
-- Action callback that will be called on the completion or peek actions.
|
||||
-- The currently selected item is passed in as the result.
|
||||
function(result) vim.cmd("edit " .. result) end
|
||||
|
|
|
|||
12
lua/ivy/backends/ag.lua
Normal file
12
lua/ivy/backends/ag.lua
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
local utils = require "ivy.utils"
|
||||
|
||||
local ag = {
|
||||
name = "AG",
|
||||
command = "IvyAg",
|
||||
description = "Run ag to search for content in files",
|
||||
keymap = "<leader>/",
|
||||
items = utils.command_finder "ag",
|
||||
callback = utils.vimgrep_action(),
|
||||
}
|
||||
|
||||
return ag
|
||||
38
lua/ivy/backends/buffers.lua
Normal file
38
lua/ivy/backends/buffers.lua
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
local libivy = require "ivy.libivy"
|
||||
local utils = require "ivy.utils"
|
||||
|
||||
local function items(input)
|
||||
local list = {}
|
||||
local buffers = vim.api.nvim_list_bufs()
|
||||
for index = 1, #buffers do
|
||||
local buffer = buffers[index]
|
||||
-- Get the relative path from the current working directory. We need to
|
||||
-- substring +2 to remove the `/` from the start of the path to give us a
|
||||
-- true relative path
|
||||
local buffer_name = vim.api.nvim_buf_get_name(buffer):sub(#vim.fn.getcwd() + 2, -1)
|
||||
local file_type = vim.api.nvim_buf_get_option(buffer, "filetype")
|
||||
if vim.api.nvim_buf_is_loaded(buffer) and file_type ~= "ivy" and #buffer_name > 0 then
|
||||
local score = libivy.ivy_match(input, buffer_name)
|
||||
if score > -200 or #input == 0 then
|
||||
table.insert(list, { score = score, content = buffer_name })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(list, function(a, b)
|
||||
return a.score < b.score
|
||||
end)
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
local buffers = {
|
||||
name = "Buffers",
|
||||
command = "IvyBuffers",
|
||||
description = "List all of the current open buffers",
|
||||
keymap = "<leader>b",
|
||||
items = items,
|
||||
callback = utils.file_action(),
|
||||
}
|
||||
|
||||
return buffers
|
||||
17
lua/ivy/backends/files.lua
Normal file
17
lua/ivy/backends/files.lua
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
local libivy = require "ivy.libivy"
|
||||
local utils = require "ivy.utils"
|
||||
|
||||
local function items(term)
|
||||
return libivy.ivy_files(term, vim.fn.getcwd())
|
||||
end
|
||||
|
||||
local files = {
|
||||
name = "Files",
|
||||
command = "IvyFd",
|
||||
description = "Find files in the project",
|
||||
keymap = "<leader>p",
|
||||
items = items,
|
||||
callback = utils.file_action(),
|
||||
}
|
||||
|
||||
return files
|
||||
32
lua/ivy/backends/lines.lua
Normal file
32
lua/ivy/backends/lines.lua
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
local utils = require "ivy.utils"
|
||||
local libivy = require "ivy.libivy"
|
||||
|
||||
local function items(input)
|
||||
local list = {}
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(vim.ivy.origin(), 0, -1, false)
|
||||
for index = 1, #lines do
|
||||
local line = lines[index]
|
||||
local score = libivy.ivy_match(input, line)
|
||||
if score > -200 then
|
||||
local prefix = string.rep(" ", 4 - #tostring(index)) .. index .. ": "
|
||||
table.insert(list, { score = score, content = prefix .. line })
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(list, function(a, b)
|
||||
return a.score < b.score
|
||||
end)
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
local lines = {
|
||||
name = "Lines",
|
||||
command = "IvyLines",
|
||||
description = "Search though the lines in the current buffer",
|
||||
items = items,
|
||||
callback = utils.line_action(),
|
||||
}
|
||||
|
||||
return lines
|
||||
40
lua/ivy/backends/lsp-workspace-symbols.lua
Normal file
40
lua/ivy/backends/lsp-workspace-symbols.lua
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
local window = require "ivy.window"
|
||||
local utils = require "ivy.utils"
|
||||
|
||||
local previous_results = {}
|
||||
local function set_items(items)
|
||||
window.set_items(items)
|
||||
previous_results = items
|
||||
end
|
||||
|
||||
local function items(input)
|
||||
local buffer_number = window.origin_buffer
|
||||
local cwd = vim.fn.getcwd()
|
||||
local results = {}
|
||||
vim.lsp.buf_request(buffer_number, "workspace/symbol", { query = input }, function(err, server_result, _, _)
|
||||
if err ~= nil then
|
||||
set_items { content = "-- There was an error with workspace/symbol --" }
|
||||
return
|
||||
end
|
||||
local locations = vim.lsp.util.symbols_to_items(server_result or {}, buffer_number) or {}
|
||||
for index = 1, #locations do
|
||||
local item = locations[index]
|
||||
local relative_path = item.filename:sub(#cwd + 2, -1)
|
||||
table.insert(results, { content = relative_path .. ":" .. item.lnum .. ": " .. item.text })
|
||||
end
|
||||
|
||||
set_items(results)
|
||||
end)
|
||||
|
||||
return previous_results
|
||||
end
|
||||
|
||||
local lsp_workspace_symbols = {
|
||||
name = "WorkspaceSymbols",
|
||||
command = "IvyWorkspaceSymbols",
|
||||
description = "Search for workspace symbols using the lsp workspace/symbol",
|
||||
items = items,
|
||||
callback = utils.vimgrep_action(),
|
||||
}
|
||||
|
||||
return lsp_workspace_symbols
|
||||
|
|
@ -27,6 +27,7 @@ window.index = 0
|
|||
window.origin = nil
|
||||
window.window = nil
|
||||
window.buffer = nil
|
||||
window.origin_buffer = nil
|
||||
|
||||
window.initialize = function()
|
||||
window.make_buffer()
|
||||
|
|
@ -34,6 +35,7 @@ end
|
|||
|
||||
window.make_buffer = function()
|
||||
window.origin = vim.api.nvim_get_current_win()
|
||||
window.origin_buffer = vim.api.nvim_win_get_buf(0)
|
||||
|
||||
vim.api.nvim_command "botright split new"
|
||||
window.buffer = vim.api.nvim_win_get_buf(0)
|
||||
|
|
@ -138,6 +140,7 @@ window.destroy = function()
|
|||
window.buffer = nil
|
||||
window.window = nil
|
||||
window.origin = nil
|
||||
window.origin_buffer = nil
|
||||
window.index = 0
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,73 +1,34 @@
|
|||
local controller = require "ivy.controller"
|
||||
local utils = require "ivy.utils"
|
||||
local libivy = require "ivy.libivy"
|
||||
|
||||
-- Put the controller in to the vim global so we can access it in mappings
|
||||
-- better without requires. You can call controller commands like `vim.ivy.xxx`.
|
||||
-- luacheck: ignore
|
||||
vim.ivy = controller
|
||||
|
||||
vim.api.nvim_create_user_command("IvyAg", function()
|
||||
vim.ivy.run("AG", utils.command_finder "ag", utils.vimgrep_action())
|
||||
end, { bang = true, desc = "Run ag to search for content in files" })
|
||||
local register_backend = function(backend)
|
||||
assert(backend.command, "The backend must have a command")
|
||||
assert(backend.items, "The backend must have a items function")
|
||||
assert(backend.callback, "The backend must have a callback function")
|
||||
|
||||
vim.api.nvim_create_user_command("IvyFd", function()
|
||||
vim.ivy.run("Files", function(term)
|
||||
return libivy.ivy_files(term, vim.fn.getcwd())
|
||||
end, utils.file_action())
|
||||
end, { bang = true, desc = "Find files in the project" })
|
||||
|
||||
vim.api.nvim_create_user_command("IvyBuffers", function()
|
||||
vim.ivy.run("Buffers", function(input)
|
||||
local list = {}
|
||||
local buffers = vim.api.nvim_list_bufs()
|
||||
for index = 1, #buffers do
|
||||
local buffer = buffers[index]
|
||||
-- Get the relative path from the current working directory. We need to
|
||||
-- substring +2 to remove the `/` from the start of the path to give us a
|
||||
-- true relative path
|
||||
local buffer_name = vim.api.nvim_buf_get_name(buffer):sub(#vim.fn.getcwd() + 2, -1)
|
||||
local file_type = vim.api.nvim_buf_get_option(buffer, "filetype")
|
||||
if vim.api.nvim_buf_is_loaded(buffer) and file_type ~= "ivy" and #buffer_name > 0 then
|
||||
local score = libivy.ivy_match(input, buffer_name)
|
||||
if score > -200 or #input == 0 then
|
||||
table.insert(list, { score = score, content = buffer_name })
|
||||
end
|
||||
end
|
||||
local user_command_options = { bang = true }
|
||||
if backend.description ~= nil then
|
||||
user_command_options.desc = backend.description
|
||||
end
|
||||
|
||||
table.sort(list, function(a, b)
|
||||
return a.score < b.score
|
||||
end)
|
||||
local name = backend.name or backend.command
|
||||
vim.api.nvim_create_user_command(backend.command, function()
|
||||
vim.ivy.run(name, backend.items, backend.callback)
|
||||
end, user_command_options)
|
||||
|
||||
return list
|
||||
end, utils.file_action())
|
||||
end, { bang = true, desc = "List all of the current open buffers" })
|
||||
|
||||
vim.api.nvim_create_user_command("IvyLines", function()
|
||||
vim.ivy.run("Lines", function(input)
|
||||
local list = {}
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(vim.ivy.origin(), 0, -1, false)
|
||||
for index = 1, #lines do
|
||||
local line = lines[index]
|
||||
local score = libivy.ivy_match(input, line)
|
||||
if score > -200 then
|
||||
local prefix = string.rep(" ", 4 - #tostring(index)) .. index .. ": "
|
||||
table.insert(list, { score = score, content = prefix .. line })
|
||||
end
|
||||
if backend.keymap ~= nil then
|
||||
vim.api.nvim_set_keymap("n", backend.keymap, "<cmd>" .. backend.command .. "<CR>", { nowait = true, silent = true })
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(list, function(a, b)
|
||||
return a.score < b.score
|
||||
end)
|
||||
|
||||
return list
|
||||
end, utils.line_action())
|
||||
end, { bang = true, desc = "List all of the current open buffers" })
|
||||
|
||||
vim.api.nvim_set_keymap("n", "<leader>b", "<cmd>IvyBuffers<CR>", { nowait = true, silent = true })
|
||||
vim.api.nvim_set_keymap("n", "<leader>p", "<cmd>IvyFd<CR>", { nowait = true, silent = true })
|
||||
vim.api.nvim_set_keymap("n", "<leader>/", "<cmd>IvyAg<CR>", { nowait = true, silent = true })
|
||||
register_backend(require "ivy.backends.ag")
|
||||
register_backend(require "ivy.backends.buffers")
|
||||
register_backend(require "ivy.backends.files")
|
||||
register_backend(require "ivy.backends.lines")
|
||||
register_backend(require "ivy.backends.lsp-workspace-symbols")
|
||||
|
||||
vim.cmd "highlight IvyMatch cterm=bold gui=bold"
|
||||
|
|
|
|||
Loading…
Reference in a new issue