Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F132250
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Fri, May 8, 4:58 PM (1 w, 12 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
8989
Default Alt Text
(14 KB)
Attached To
Mode
R1 ivy.nvim
Attached
Detach File
Event Timeline
Log In to Comment