Page MenuHomePhorge

No OneTemporary

diff --git a/.luacheckrc b/.luacheckrc
index 337ac8e..2d46e75 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -1,18 +1,21 @@
-- Rerun tests only if their modification time changed.
cache = true
std = luajit
codes = true
self = false
-- Global objects defined by the C code
read_globals = {
"vim",
- "it",
"after",
"after_each",
+ "assert",
"before",
"before_each",
+ "describe",
+ "it",
+ "spy",
}
diff --git a/lua/ivy/controller_spec.lua b/lua/ivy/controller_spec.lua
new file mode 100644
index 0000000..6556cee
--- /dev/null
+++ b/lua/ivy/controller_spec.lua
@@ -0,0 +1,57 @@
+local window = require "ivy.window"
+local controller = require "ivy.controller"
+
+describe("controller", function()
+ before_each(function()
+ vim.cmd "highlight IvyMatch cterm=bold gui=bold"
+ window.initialize()
+ end)
+
+ after_each(function()
+ controller.destroy()
+ end)
+
+ it("will run the completion", function()
+ controller.run("Testing", function()
+ return { { content = "Some content" } }
+ end, function()
+ return {}
+ end)
+
+ -- Run all the scheduled tasks
+ vim.wait(0)
+
+ local lines = vim.api.nvim_buf_get_lines(0, 0, -1, true)
+ assert.is_equal(#lines, 1)
+ assert.is_equal(lines[1], "Some content")
+ end)
+
+ it("will not try and highlight the buffer if there is nothing to highlight", function()
+ spy.on(vim, "cmd")
+
+ controller.items = function()
+ return { { content = "Hello" } }
+ end
+
+ controller.update ""
+
+ vim.wait(0)
+
+ assert.spy(vim.cmd).was_called_with "syntax clear IvyMatch"
+ assert.spy(vim.cmd).was_not_called_with "syntax match IvyMatch '[H]'"
+ end)
+
+ it("will escape a - when passing it to be highlighted", function()
+ spy.on(vim, "cmd")
+
+ controller.items = function()
+ return { { content = "Hello" } }
+ end
+
+ controller.update "some-file"
+
+ vim.wait(0)
+
+ assert.spy(vim.cmd).was_called_with "syntax match IvyMatch '[some\\-file]'"
+ end)
+end)
diff --git a/lua/ivy/libivy_spec.lua b/lua/ivy/libivy_spec.lua
new file mode 100644
index 0000000..8faf503
--- /dev/null
+++ b/lua/ivy/libivy_spec.lua
@@ -0,0 +1,36 @@
+require "busted.runner"()
+
+local libivy = require "ivy.libivy"
+
+describe("libivy", function()
+ it("should run a simple match", function()
+ local score = libivy.ivy_match("term", "I am a serch term")
+
+ assert.is_true(score > 0)
+ end)
+
+ it("should find a dot file", function()
+ local current_dir = libivy.ivy_cwd()
+ local results = libivy.ivy_files(".github/workflows/ci.yml", current_dir)
+
+ assert.is_equal(2, results.length, "Incorrect number of results found")
+ assert.is_equal(".github/workflows/ci.yml", results[2].content, "Invalid matches")
+ end)
+
+ it("will allow you to access the length via the metatable", function()
+ local current_dir = libivy.ivy_cwd()
+ local results = libivy.ivy_files(".github/workflows/ci.yml", current_dir)
+
+ local mt = getmetatable(results)
+
+ assert.is_equal(results.length, mt.__len(results), "The `length` property does not match the __len metamethod")
+ end)
+
+ it("will create an iterator", function()
+ local iter = libivy.ivy_files(".github/workflows/ci.yml", libivy.ivy_cwd())
+ local mt = getmetatable(iter)
+
+ assert.is_equal(type(mt["__index"]), "function")
+ assert.is_equal(type(mt["__len"]), "function")
+ end)
+end)
diff --git a/lua/ivy/matcher_spec.lua b/lua/ivy/matcher_spec.lua
new file mode 100644
index 0000000..7128a2c
--- /dev/null
+++ b/lua/ivy/matcher_spec.lua
@@ -0,0 +1,29 @@
+local libivy = require "ivy.libivy"
+
+-- Helper function to test a that string `one` has a higher match score than
+-- string `two`. If string `one` has a lower score than string `two` a string
+-- will be returned that can be used in body of an error. If not then `nil` is
+-- returned and all is good.
+local match_test = function(term, one, two)
+ local score_one = libivy.ivy_match(term, one)
+ local score_two = libivy.ivy_match(term, two)
+
+ assert.is_true(
+ score_one > score_two,
+ ("The score of %s (%d) ranked higher than %s (%d)"):format(one, score_one, two, score_two)
+ )
+end
+
+describe("ivy matcher", function()
+ it("should match path separator", function()
+ match_test("file", "some/file.lua", "somefile.lua")
+ end)
+
+ -- it("should match pattern with spaces", function()
+ -- match_test("so fi", "some/file.lua", "somefile.lua")
+ -- end)
+
+ it("should match the start of a string", function()
+ match_test("file", "file.lua", "somefile.lua")
+ end)
+end)
diff --git a/lua/ivy/prompt_spec.lua b/lua/ivy/prompt_spec.lua
new file mode 100644
index 0000000..452a091
--- /dev/null
+++ b/lua/ivy/prompt_spec.lua
@@ -0,0 +1,91 @@
+local prompt = require "ivy.prompt"
+
+-- Input a list of strings into the prompt
+local input = function(input_table)
+ for index = 1, #input_table do
+ prompt.input(input_table[index])
+ end
+end
+
+describe("prompt", function()
+ before_each(function()
+ prompt.destroy()
+ end)
+
+ it("starts with empty text", function()
+ assert.is_same(prompt.text(), "")
+ end)
+
+ it("can input some text", function()
+ input { "A", "d", "e" }
+ assert.is_same(prompt.text(), "Ade")
+ end)
+
+ it("can delete a char", function()
+ input { "A", "d", "e", "BACKSPACE" }
+ assert.is_same(prompt.text(), "Ad")
+ end)
+
+ it("will reset the text", function()
+ input { "A", "d", "e" }
+ prompt.set "New"
+ assert.is_same(prompt.text(), "New")
+ end)
+
+ it("can move around the a word", function()
+ input { "P", "r", "o", "p", "t", "LEFT", "LEFT", "LEFT", "RIGHT", "m" }
+ assert.is_same(prompt.text(), "Prompt")
+ end)
+
+ it("can delete a word", function()
+ prompt.set "Ade Attwood"
+ input { "DELETE_WORD" }
+
+ assert.is_same(prompt.text(), "Ade ")
+ end)
+
+ it("can delete a word in the middle and leave the cursor at that word", function()
+ prompt.set "Ade middle A"
+ input { "LEFT", "LEFT", "DELETE_WORD", "a" }
+
+ assert.is_same(prompt.text(), "Ade a A")
+ end)
+
+ it("will delete the space and the word if the last word is single space", function()
+ prompt.set "some.thing "
+ input { "DELETE_WORD" }
+
+ assert.is_same(prompt.text(), "some.")
+ end)
+
+ it("will only delete one word from path", function()
+ prompt.set "some/nested/path"
+ input { "DELETE_WORD" }
+
+ assert.is_same(prompt.text(), "some/nested/")
+ end)
+
+ it("will delete tailing space", function()
+ prompt.set "word "
+ input { "DELETE_WORD" }
+
+ assert.is_same(prompt.text(), "")
+ end)
+
+ it("will leave a random space", function()
+ prompt.set "some word "
+ input { "DELETE_WORD" }
+
+ assert.is_same(prompt.text(), "some ")
+ end)
+
+ local special_characters = { ".", "/", "^" }
+ for _, char in ipairs(special_characters) do
+ it(string.format("will stop at a %s", char), function()
+ prompt.set(string.format("key%sValue", char))
+ input { "DELETE_WORD" }
+
+ assert.is_same(prompt.text(), string.format("key%s", char))
+ end)
+ end
+end)
diff --git a/lua/ivy/utils.lua b/lua/ivy/utils.lua
index 910e57f..40489a8 100644
--- a/lua/ivy/utils.lua
+++ b/lua/ivy/utils.lua
@@ -1,111 +1,113 @@
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.existing_command_map = {
[utils.actions.EDIT] = "buffer",
[utils.actions.CHECKPOINT] = "buffer",
[utils.actions.VSPLIT] = "vsplit | buffer",
[utils.actions.SPLIT] = "split | buffer",
}
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 || true")
if handle == nil then
return {}
end
local results = {}
for line in handle:lines() do
table.insert(results, { content = line })
end
handle:close()
return results
end
end
utils.vimgrep_action = function()
return function(item, action)
-- 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
utils.file_action()(file, action)
if line ~= nil then
vim.cmd(line)
end
end
end
utils.file_action = function()
return function(file, action)
if file == nil then
return
end
local buffer_number = vim.fn.bufnr(file)
local command
if buffer_number > -1 then
command = utils.existing_command_map[action]
else
command = utils.command_map[action]
end
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 .. " " .. utils.escape_file_name(file))
end
end
utils.line_action = function()
return function(item)
local line = item:match "^%s+(%d+):"
- vim.cmd(line)
+ if line ~= nil then
+ vim.cmd(line)
+ end
end
end
utils.escape_file_name = function(input)
local file, _ = string.gsub(input, "([$%]\\[])", "\\%1")
return file
end
return utils
diff --git a/lua/ivy/utils_escape_spec.lua b/lua/ivy/utils_escape_spec.lua
new file mode 100644
index 0000000..7a47331
--- /dev/null
+++ b/lua/ivy/utils_escape_spec.lua
@@ -0,0 +1,11 @@
+local utils = require "ivy.utils"
+
+it("will escape a dollar in the file name", function()
+ local result = utils.escape_file_name "/path/to/$file/$name.lua"
+ assert.is_same(result, "/path/to/\\$file/\\$name.lua")
+end)
+
+it("will escape a brackets in the file name", function()
+ local result = utils.escape_file_name "/path/to/[file]/[name].lua"
+ assert.is_same(result, "/path/to/\\[file\\]/\\[name\\].lua")
+end)
diff --git a/lua/ivy/utils_line_action_spec.lua b/lua/ivy/utils_line_action_spec.lua
new file mode 100644
index 0000000..8e4484e
--- /dev/null
+++ b/lua/ivy/utils_line_action_spec.lua
@@ -0,0 +1,28 @@
+local utils = require "ivy.utils"
+local line_action = utils.line_action()
+
+describe("utils line_action", function()
+ before_each(function()
+ spy.on(vim, "cmd")
+ end)
+
+ it("will run the line command", function()
+ line_action " 4: Some text"
+
+ assert.is_equal(#vim.cmd.calls, 1, "The `vim.cmd` function should be called once")
+ assert.spy(vim.cmd).was_called_with "4"
+ end)
+
+ it("will run with more numbers", function()
+ line_action " 44: Some text"
+
+ assert.is_equal(#vim.cmd.calls, 1, "The `vim.cmd` function should be called once")
+ assert.spy(vim.cmd).was_called_with "44"
+ end)
+
+ it("dose not run any action if no line is found", function()
+ line_action "Some text"
+
+ assert.spy(vim.cmd).was_not_called()
+ end)
+end)
diff --git a/lua/ivy/utils_vimgrep_action_spec.lua b/lua/ivy/utils_vimgrep_action_spec.lua
new file mode 100644
index 0000000..51cb55d
--- /dev/null
+++ b/lua/ivy/utils_vimgrep_action_spec.lua
@@ -0,0 +1,56 @@
+local utils = require "ivy.utils"
+local vimgrep_action = utils.vimgrep_action()
+
+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 = { "buffer some/file.lua" },
+ },
+ {
+ it = "will run the vsplit command",
+ completion = "some/file.lua: This is some text",
+ action = utils.actions.VSPLIT,
+ commands = { "vsplit | buffer some/file.lua" },
+ },
+ {
+ it = "will run the split command",
+ completion = "some/file.lua: This is some text",
+ action = utils.actions.SPLIT,
+ commands = { "split | buffer some/file.lua" },
+ },
+}
+
+describe("utils vimgrep_action", function()
+ before_each(function()
+ spy.on(vim, "cmd")
+ end)
+
+ after_each(function()
+ vim.cmd:revert()
+ end)
+
+ for i = 1, #test_data do
+ local data = test_data[i]
+ it(data.it, function()
+ assert.is_true(#data.commands > 0, "You must assert that at least one command is run")
+
+ vimgrep_action(data.completion, data.action)
+ assert.is_equal(#vim.cmd.calls, #data.commands, "The `vim.cmd` function should be called once")
+
+ for j = 1, #data.commands do
+ assert.spy(vim.cmd).was_called_with(data.commands[j])
+ end
+ end)
+ end
+end)
diff --git a/lua/ivy/window_spec.lua b/lua/ivy/window_spec.lua
new file mode 100644
index 0000000..873504a
--- /dev/null
+++ b/lua/ivy/window_spec.lua
@@ -0,0 +1,32 @@
+local window = require "ivy.window"
+local controller = require "ivy.controller"
+
+describe("window", function()
+ before_each(function()
+ vim.cmd "highlight IvyMatch cterm=bold gui=bold"
+ window.initialize()
+ end)
+
+ after_each(function()
+ controller.destroy()
+ end)
+
+ it("can initialize and destroy the window", function()
+ assert.is_equal(vim.api.nvim_get_current_buf(), window.buffer)
+
+ window.destroy()
+ assert.is_equal(nil, window.buffer)
+ end)
+
+ it("can set items", function()
+ window.set_items { { content = "Line one" } }
+ assert.is_equal("Line one", window.get_current_selection())
+ end)
+
+ it("will set the items when a string is passed in", function()
+ local items = table.concat({ "One", "Two", "Three" }, "\n")
+ window.set_items(items)
+
+ assert.is_equal(items, table.concat(vim.api.nvim_buf_get_lines(window.buffer, 0, -1, true), "\n"))
+ end)
+end)
diff --git a/scripts/busted.lua b/scripts/busted.lua
new file mode 100755
index 0000000..753c0e6
--- /dev/null
+++ b/scripts/busted.lua
@@ -0,0 +1,8 @@
+-- Script to run the busted cli tool. You can use this under nvim using be
+-- below command. Any arguments can be passed in the same as the busted cli.
+--
+-- ```bash
+-- nvim -l scripts/busted.lua
+-- ```
+vim.opt.rtp:append(vim.fn.getcwd())
+require "busted.runner" { standalone = false }

File Metadata

Mime Type
text/x-diff
Expires
Fri, May 8, 4:58 PM (1 w, 10 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
8989
Default Alt Text
(14 KB)

Event Timeline