diff --git a/README.md b/README.md
index fae7b8b..c333988 100644
--- a/README.md
+++ b/README.md
@@ -1,78 +1,79 @@
# ivy.nvim
An [ivy-mode](https://github.com/abo-abo/swiper#ivy) port to neovim. Ivy is a
generic completion mechanism for ~~Emacs~~ Nvim
## Installation
### Manually
```sh
git clone https://github.com/AdeAttwood/ivy.nvim ~/.config/nvim/pack/bundle/start/ivy.nvim
```
### Plugin managers
TODO: Add docs in the plugin managers I don't use any
### Compiling
For the native searching, you will need to compile the shard library. You can
do that by running the below command in the root of the plugin.
```sh
cmake -DCMAKE_BUILD_TYPE=Release -B build/Release && (cd build/Release; make -j)
```
If you are missing build dependencies, you can install them via apt.
```sh
sudo apt-get install build-essential pkg-config cmake
```
## Features
### Commands
A command can be run that will launch the completion UI
| Command | Key Map | Description |
| ---------- | ----------- | ------------------------------------------------------ |
| IvyFd | \p | Find files in your project with the fd cli file finder |
| IvyAg | \/ | Find content in files using the silver searcher |
| IvyBuffers | \b | Search though open buffers |
+| IvyLines | | Search the lines in the current buffer |
### Actions
Action can be run on selected candidates provide functionality
| Action | Description |
| -------- | ------------------------------------------------------------------------------ |
| Complete | Run the completion function, usually this will be opening a file |
| Peek | Run the completion function on a selection, but don't close the results window |
## API
```lua
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 { "One", "Two", 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
)
```
## Other stuff you might like
- [ivy-mode](https://github.com/abo-abo/swiper#ivy) - An emacs package that was the inspiration for this nvim plugin
- [Command-T](https://github.com/wincent/command-t) - Vim plugin I used before I started this one
- [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) - Another competition plugin, lots of people are using
diff --git a/lua/ivy/utils.lua b/lua/ivy/utils.lua
index c087167..6fa8f67 100644
--- a/lua/ivy/utils.lua
+++ b/lua/ivy/utils.lua
@@ -1,57 +1,64 @@
local utils = {}
utils.command_finder = function(command, min)
if min == nil then
min = 3
end
return function(input)
-- Dont run the commands unless we have somting to search that wont
-- return a ton of results or on some commands the command files with
-- no search term
if #input < min then
return "-- Please type more than " .. min .. " chars --"
end
-- TODO(ade): Think if we want to start escaping the command here. I
-- dont know if its causing issues while trying to use regex especially
-- with word boundaries `input:gsub("'", "\\'"):gsub('"', '\\"')`
local handle = io.popen(command .. " " .. input .. " 2>&1")
if handle == nil then
return {}
end
local result = handle:read "*a"
handle:close()
return result
end
end
utils.vimgrep_action = function()
return function(item)
-- Match file and line form vimgrep style commands
local file = item:match "([^:]+):"
local line = item:match ":(%d+):"
-- Cant do anything if we cant find a file to go to
if file == nil then
return
end
vim.cmd("edit " .. file)
if line ~= nil then
vim.cmd(line)
end
end
end
utils.file_action = function()
return function(file)
if file == nil then
return
end
vim.cmd("edit " .. file)
end
end
+utils.line_action = function()
+ return function(item)
+ local line = item:match "^%s+(%d+):"
+ vim.cmd(line)
+ end
+end
+
return utils
diff --git a/plugin/ivy.lua b/plugin/ivy.lua
index 92f22f6..2744c71 100644
--- a/plugin/ivy.lua
+++ b/plugin/ivy.lua
@@ -1,47 +1,69 @@
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`.
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" })
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)
if vim.api.nvim_buf_is_loaded(buffer) and #buffer_name > 0 then
local score = libivy.ivy_match(input, buffer_name)
if score > -200 or #input == 0 then
table.insert(list, { score, buffer_name })
end
end
end
table.sort(list, function(a, b)
return a[1] < b[1]
end)
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, prefix .. line })
+ end
+ end
+
+ table.sort(list, function(a, b)
+ return a[1] < b[1]
+ end)
+
+ return list
+ end, utils.line_action())
+end, { bang = true, desc = "List all of the current open buffers" })
+
vim.api.nvim_set_keymap("n", "b", "IvyBuffers", { nowait = true, silent = true })
vim.api.nvim_set_keymap("n", "p", "IvyFd", { nowait = true, silent = true })
vim.api.nvim_set_keymap("n", "/", "IvyAg", { nowait = true, silent = true })