diff --git a/README.md b/README.md index dca3d3d..7144890 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,12 @@ A command can be run that will launch the completion UI 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 | +| 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 | +| Vertical Split | Run the completion function in a new vertical split | +| Split | Run the completion function in a new split | ## API diff --git a/lua/ivy/controller.lua b/lua/ivy/controller.lua index 306acb0..c0194eb 100644 --- a/lua/ivy/controller.lua +++ b/lua/ivy/controller.lua @@ -1,7 +1,9 @@ local window = require "ivy.window" local prompt = require "ivy.prompt" +local utils = require "ivy.utils" local controller = {} +controller.action = utils.actions controller.items = nil controller.callback = nil @@ -36,16 +38,16 @@ controller.update = function(text) end) end -controller.complete = function() +controller.complete = function(action) vim.api.nvim_set_current_win(window.origin) - controller.callback(window.get_current_selection()) + controller.callback(window.get_current_selection(), action) controller.destroy() end controller.checkpoint = function() vim.api.nvim_set_current_win(window.origin) - controller.callback(window.get_current_selection()) + controller.callback(window.get_current_selection(), controller.action.CHECKPOINT) vim.api.nvim_set_current_win(window.window) end diff --git a/lua/ivy/prompt_test.lua b/lua/ivy/prompt_test.lua index 57b0339..a99680d 100644 --- a/lua/ivy/prompt_test.lua +++ b/lua/ivy/prompt_test.lua @@ -1,14 +1,8 @@ local prompt = require "ivy.prompt" +local vim_mock = require "ivy.vim_mock" before_each(function() - -- Mock the global vim functions we are using in the prompt - _G.vim = { - notify = function() end, - api = { - nvim_echo = function() end, - }, - } - + vim_mock.reset() prompt.destroy() end) @@ -23,7 +17,7 @@ end local assert_prompt = function(t, expected) local text = prompt.text() if text ~= expected then - t.error("The promp text should be '" .. expected .. "' found '" .. text .. "'") + t.error("The prompt text should be '" .. expected .. "' found '" .. text .. "'") end end diff --git a/lua/ivy/utils.lua b/lua/ivy/utils.lua index 6fa8f67..75fc7c7 100644 --- a/lua/ivy/utils.lua +++ b/lua/ivy/utils.lua @@ -1,5 +1,22 @@ local utils = {} +-- A list of all of the actions defined by ivy. The callback function can +-- implement as many of them as necessary. As a minimum it should implement the +-- "EDIT" action that is called on the default complete. +utils.actions = { + EDIT = "EDIT", + CHECKPOINT = "CHECKPOINT", + VSPLIT = "VSPLIT", + SPLIT = "SPLIT", +} + +utils.command_map = { + [utils.actions.EDIT] = "edit", + [utils.actions.CHECKPOINT] = "edit", + [utils.actions.VSPLIT] = "vsplit", + [utils.actions.SPLIT] = "split", +} + utils.command_finder = function(command, min) if min == nil then min = 3 @@ -28,7 +45,7 @@ utils.command_finder = function(command, min) end utils.vimgrep_action = function() - return function(item) + return function(item, action) -- Match file and line form vimgrep style commands local file = item:match "([^:]+):" local line = item:match ":(%d+):" @@ -38,7 +55,7 @@ utils.vimgrep_action = function() return end - vim.cmd("edit " .. file) + utils.file_action()(file, action) if line ~= nil then vim.cmd(line) end @@ -46,11 +63,18 @@ utils.vimgrep_action = function() end utils.file_action = function() - return function(file) + return function(file, action) if file == nil then return end - vim.cmd("edit " .. file) + + local command = utils.command_map[action] + if command == nil then + vim.api.nvim_err_writeln("[IVY] The file action is unable the handel the action " .. action) + return + end + + vim.cmd(command .. " " .. file) end end diff --git a/lua/ivy/utils_line_action_test.lua b/lua/ivy/utils_line_action_test.lua new file mode 100644 index 0000000..f68810e --- /dev/null +++ b/lua/ivy/utils_line_action_test.lua @@ -0,0 +1,39 @@ +local utils = require "ivy.utils" +local line_action = utils.line_action() +local vim_mock = require "ivy.vim_mock" + +before_each(function() + vim_mock.reset() +end) + +it("will run the line command", function(t) + line_action " 4: Some text" + + if #vim_mock.commands ~= 1 then + t.error "`line_action` command length should be 1" + end + + if vim_mock.commands[1] ~= "4" then + t.error "`line_action` command should be 4" + end +end) + +it("will run with more numbers", function(t) + line_action " 44: Some text" + + if #vim_mock.commands ~= 1 then + t.error "`line_action` command length should be 1" + end + + if vim_mock.commands[1] ~= "44" then + t.error "`line_action` command should be 44" + end +end) + +it("dose not run any action if no line is found", function(t) + line_action "Some text" + + if #vim_mock.commands ~= 0 then + t.error "`line_action` command length should be 1" + end +end) diff --git a/lua/ivy/utils_vimgrep_action_test.lua b/lua/ivy/utils_vimgrep_action_test.lua new file mode 100644 index 0000000..0c08c09 --- /dev/null +++ b/lua/ivy/utils_vimgrep_action_test.lua @@ -0,0 +1,56 @@ +local utils = require "ivy.utils" +local vimgrep_action = utils.vimgrep_action() +local vim_mock = require "ivy.vim_mock" + +before_each(function() + vim_mock.reset() +end) + +local test_data = { + { + it = "will edit some file and goto the line", + completion = "some/file.lua:2: This is some text", + action = utils.actions.EDIT, + commands = { + "edit some/file.lua", + "2", + }, + }, + { + it = "will skip the line if its not matched", + completion = "some/file.lua: This is some text", + action = utils.actions.EDIT, + commands = { "edit some/file.lua" }, + }, + { + it = "will run the vsplit command", + completion = "some/file.lua: This is some text", + action = utils.actions.VSPLIT, + commands = { "vsplit some/file.lua" }, + }, + { + it = "will run the split command", + completion = "some/file.lua: This is some text", + action = utils.actions.SPLIT, + commands = { "split some/file.lua" }, + }, +} + +for i = 1, #test_data do + local data = test_data[i] + it(data.it, function(t) + vimgrep_action(data.completion, data.action) + + if #vim_mock.commands ~= #data.commands then + t.error("Incorrect number of commands run expected " .. #data.commands .. " but found " .. #vim_mock.commands) + end + + for j = 1, #data.commands do + if vim_mock.commands[j] ~= data.commands[j] then + t.error( + "Incorrect command run expected '" .. data.commands[j] .. "' but found '" .. vim_mock.commands[j] .. "'" + ) + end + end + end) +end diff --git a/lua/ivy/vim_mock.lua b/lua/ivy/vim_mock.lua new file mode 100644 index 0000000..98f03fd --- /dev/null +++ b/lua/ivy/vim_mock.lua @@ -0,0 +1,30 @@ +local mock = { + commands = {}, +} + +mock.reset = function() + mock.commands = {} + + _G.vim = { + notify = function() end, + cmd = function(cmd) + table.insert(mock.commands, cmd) + end, + api = { + nvim_echo = function() end, + nvim_get_current_win = function() + return 10 + end, + nvim_command = function() end, + nvim_win_get_buf = function() + return 10 + end, + nvim_win_set_option = function() end, + nvim_buf_set_option = function() end, + nvim_buf_set_var = function() end, + nvim_buf_set_keymap = function() end, + }, + } +end + +return mock diff --git a/lua/ivy/window.lua b/lua/ivy/window.lua index ea94ec3..87c0856 100644 --- a/lua/ivy/window.lua +++ b/lua/ivy/window.lua @@ -69,7 +69,9 @@ window.make_buffer = function() "lua vim.ivy.previous(); vim.ivy.checkpoint()", opts ) - vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.complete()", opts) + vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.complete(vim.ivy.action.EDIT)", opts) + vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.complete(vim.ivy.action.VSPLIT)", opts) + vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.complete(vim.ivy.action.SPLIT)", opts) vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.input('BACKSPACE')", opts) vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.input('LEFT')", opts) vim.api.nvim_buf_set_keymap(window.buffer, "n", "", "lua vim.ivy.input('RIGHT')", opts) diff --git a/lua/ivy/window_test.lua b/lua/ivy/window_test.lua index fff5bc4..75b9698 100644 --- a/lua/ivy/window_test.lua +++ b/lua/ivy/window_test.lua @@ -1,24 +1,8 @@ +local vim_mock = require "ivy.vim_mock" local window = require "ivy.window" before_each(function() - -- Mock the global vim functions we are using in the prompt - _G.vim = { - notify = function() end, - api = { - nvim_echo = function() end, - nvim_get_current_win = function() - return 10 - end, - nvim_command = function() end, - nvim_win_get_buf = function() - return 10 - end, - nvim_win_set_option = function() end, - nvim_buf_set_option = function() end, - nvim_buf_set_var = function() end, - nvim_buf_set_keymap = function() end, - }, - } + vim_mock.reset() end) it("can initialize", function(t)