summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua')
-rw-r--r--lua/telescope/finders.lua11
-rw-r--r--lua/telescope/log.lua85
-rw-r--r--lua/telescope/pickers.lua179
-rw-r--r--lua/telescope/previewers.lua2
-rw-r--r--lua/telescope/sorters.lua13
-rw-r--r--lua/telescope/utils.lua9
-rw-r--r--lua/tests/telescope_spec.lua76
7 files changed, 229 insertions, 146 deletions
diff --git a/lua/telescope/finders.lua b/lua/telescope/finders.lua
index e5a601e..10716d0 100644
--- a/lua/telescope/finders.lua
+++ b/lua/telescope/finders.lua
@@ -29,6 +29,7 @@ function Finder:new(opts)
-- list
-- ...
return setmetatable({
+ results = opts.results,
fn_command = opts.fn_command,
static = opts.static,
state = {},
@@ -46,6 +47,16 @@ end
-- do_your_job
-- process_plz
function Finder:_find(prompt, process_result, process_complete)
+ if self.results then
+ assert(type(self.results) == 'table', "self.results must be a table")
+ for _, v in ipairs(self.results) do
+ process_result(v)
+ end
+
+ process_complete()
+ return
+ end
+
if (self.state.job_id or 0) > 0 then
vim.fn.jobstop(self.job_id)
end
diff --git a/lua/telescope/log.lua b/lua/telescope/log.lua
index fb3d712..a9bc2b0 100644
--- a/lua/telescope/log.lua
+++ b/lua/telescope/log.lua
@@ -1,83 +1,4 @@
--- https://raw.githubusercontent.com/rxi/log.lua/master/log.lua
--- log.lua
---
--- Copyright (c) 2016 rxi
---
--- This library is free software; you can redistribute it and/or modify it
--- under the terms of the MIT license. See LICENSE for details.
---
-
-local log = { _version = "0.1.0" }
-
-log.usecolor = true
-log.outfile = vim.fn.stdpath('data') .. '/telescope.log'
-log.console = false
-log.level = "trace"
-
-
-local modes = {
- { name = "trace", color = "\27[34m", },
- { name = "debug", color = "\27[36m", },
- { name = "info", color = "\27[32m", },
- { name = "warn", color = "\27[33m", },
- { name = "error", color = "\27[31m", },
- { name = "fatal", color = "\27[35m", },
+return require('plenary.log').new {
+ plugin = 'telescope',
+ level = 'debug',
}
-
-
-local levels = {}
-for i, v in ipairs(modes) do
- levels[v.name] = i
-end
-
-
-local round = function(x, increment)
- increment = increment or 1
- x = x / increment
- return (x > 0 and math.floor(x + .5) or math.ceil(x - .5)) * increment
-end
-
-for i, x in ipairs(modes) do
- local nameupper = x.name:upper()
- log[x.name] = function(...)
- -- Return early if we're below the log level
- if i < levels[log.level] then
- return
- end
-
- local passed = {...}
- local fmt = table.remove(passed, 1)
- local inspected = {}
- for _, v in ipairs(passed) do
- table.insert(inspected, vim.inspect(v))
- end
- local msg = string.format(fmt, unpack(inspected))
- local info = debug.getinfo(2, "Sl")
- local lineinfo = info.short_src .. ":" .. info.currentline
-
- -- Output to console
- if log.console then
- print(string.format("%s[%-6s%s]%s %s: %s",
- log.usecolor and x.color or "",
- nameupper,
- os.date("%H:%M:%S"),
- log.usecolor and "\27[0m" or "",
- lineinfo,
- msg))
- end
-
- -- Output to log file
- if log.outfile then
- local fp = io.open(log.outfile, "a")
- local str = string.format("[%-6s%s] %s: %s\n",
- nameupper, os.date(), lineinfo, msg)
- fp:write(str)
- fp:close()
- end
-
- end
-end
-
-log.info("Logger Succesfully Loaded")
-
-return log
diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua
index db5ec7d..f2acfac 100644
--- a/lua/telescope/pickers.lua
+++ b/lua/telescope/pickers.lua
@@ -1,11 +1,7 @@
local a = vim.api
-local fun = require('fun')
local popup = require('popup')
-local zip = fun.zip
-local tomap = fun.tomap
-
local log = require('telescope.log')
local mappings = require('telescope.mappings')
local state = require('telescope.state')
@@ -13,6 +9,8 @@ local utils = require('telescope.utils')
local pickers = {}
+--- Picker is the main UI that shows up to interact w/ your results.
+-- Takes a filter & a previewr
local Picker = {}
Picker.__index = Picker
@@ -133,98 +131,77 @@ function Picker:find(opts)
local on_lines = function(_, _, _, first_line, last_line)
local prompt = vim.api.nvim_buf_get_lines(prompt_bufnr, first_line, last_line, false)[1]
-
-- Create a closure that has all the data we need
-- We pass a function called "newResult" to get_results
-- get_results calles "newResult" every time it gets a new result
-- picker then (if available) calls sorter
-- and then appropriately places new result in the buffer.
-
- -- Sorted table by scores.
- -- Lowest score gets lowest index.
- self.line_scores = {}
-
-- TODO: We need to fix the sorting
-- TODO: We should provide a simple fuzzy matcher in Lua for people
-- TODO: We should get all the stuff on the bottom line directly, not floating around
-- TODO: We need to handle huge lists in a good way, cause currently we'll just put too much stuff in the buffer
-- TODO: Stop having things crash if we have an error.
- local replace_line = function(score, row, line)
- log.trace("Replacing @ %s w/ text '%s' (%s)", row, line, score)
- vim.api.nvim_buf_set_lines(results_bufnr, row, row + 1, false, {line})
- end
-
- local insert_line = function(score, row, line)
- log.trace("Inserting @ %s w/ text '%s' (%s)", row, line, score)
- vim.api.nvim_buf_set_lines(results_bufnr, row, row, false, {line})
- end
+ local line_manager = pickers.line_manager(
+ self.max_results,
+ function(index, line)
+ local row = self.max_results - index + 1
+ log.trace("Setting row", row, "with value", line)
+ vim.api.nvim_buf_set_lines(results_bufnr, row, row + 1, false, {line})
+ end
+ )
local process_result = function(line)
if vim.trim(line) == "" then
return
end
+ log.trace("Processing result... ", line)
+
+ local sort_score = 0
if sorter then
- local sort_score = sorter:score(prompt, line)
+ sort_score = sorter:score(prompt, line)
if sort_score == -1 then
+ log.trace("Filtering out result: ", line)
return
end
+ end
- -- { 7, 3, 1, 1 }
- -- 2
- for row, row_score in utils.reversed_ipairs(self.line_scores) do
- if row_score > sort_score then
- -- Insert line at row
- insert_line(sort_score, self.max_results - row, line)
-
- -- Insert current score in the table
- table.insert(self.line_scores, row + 1, sort_score)
-
- -- All done :)
- return
- end
+ line_manager:add_result(sort_score, line)
+ end
- -- Don't keep inserting stuff
- if row > self.max_results then
- return
- end
- end
+ local process_complete = function()
+ local worst_line = self.max_results - line_manager.num_results()
+ local empty_lines = utils.repeated_table(worst_line, "")
+ -- vim.api.nvim_buf_set_lines(results_bufnr, 0, worst_line + 1, false, empty_lines)
- -- Worst score so far, so add to end
+ log.debug("Worst Line after process_complete: %s", worst_line, results_bufnr)
- -- example: 5 max results, 8
- local worst_line = self.max_results - #self.line_scores
- replace_line(sort_score, worst_line, line)
- table.insert(self.line_scores, sort_score)
- else
- -- Just always append to the end of the buffer if this is all you got.
- vim.api.nvim_buf_set_lines(results_bufnr, -1, -1, false, {line})
- end
- end
+ -- local fun = require('fun')
+ -- local zip = fun.zip
+ -- local tomap = fun.tomap
- local process_complete = function()
- local worst_line = self.max_results - #self.line_scores
- local empty_lines = {}
- for _ = 1, worst_line do table.insert(empty_lines, "") end
- vim.api.nvim_buf_set_lines(results_bufnr, 0, worst_line, false, empty_lines)
-
- log.info("Worst Line after process_complete: %s", worst_line)
- log.trace("%s", tomap(zip(
- a.nvim_buf_get_lines(results_bufnr, worst_line, self.max_results, false),
- self.line_scores
- )))
+ -- log.trace("%s", tomap(zip(
+ -- a.nvim_buf_get_lines(results_bufnr, worst_line, self.max_results, false),
+ -- self.line_scores
+ -- )))
end
- pcall(function()
+ local ok, msg = pcall(function()
return finder(prompt, process_result, process_complete)
end)
+
+ if not ok then
+ log.warn("Failed with msg: ", msg)
+ end
end
- -- Call this once to pre-populate if it makes sense
- -- vim.schedule_wrap(on_lines(nil, nil, nil, 0, 1))
+ -- TODO: Uncomment
+ vim.schedule(function()
+ on_lines(nil, nil, nil, 0, 1)
+ end)
-- Register attach
vim.api.nvim_buf_attach(prompt_bufnr, true, {
@@ -359,4 +336,82 @@ pickers.new = function(...)
return Picker:new(...)
end
+-- TODO: We should consider adding `process_bulk` or `bulk_line_manager` for things
+-- that we always know the items and can score quickly, so as to avoid drawing so much.
+pickers.line_manager = function(max_results, set_line)
+ log.debug("Creating line_manager...")
+
+ -- state contains list of
+ -- {
+ -- score = ...
+ -- line = ...
+ -- metadata ? ...
+ -- }
+ local state = {}
+
+ set_line = set_line or function() end
+
+ return setmetatable({
+ add_result = function(self, score, line)
+ score = score or 0
+
+ for index, item in ipairs(state) do
+ if item.score > score then
+ return self:insert(index, {
+ score = score,
+ line = line,
+ })
+ end
+
+ -- Don't add results that are too bad.
+ if index >= max_results then
+ return self
+ end
+ end
+
+ return self:insert({
+ score = score,
+ line = line,
+ })
+ end,
+
+ insert = function(self, index, item)
+ if item == nil then
+ item = index
+ index = #state + 1
+ end
+
+ -- To insert something, we place at the next available index (or specified index)
+ -- and then shift all the corresponding items one place.
+ local next_item
+ repeat
+ next_item = state[index]
+
+ set_line(index, item.line)
+ state[index] = item
+
+ index = index + 1
+ item = next_item
+ until not next_item
+ end,
+
+ num_results = function()
+ return #state
+ end,
+
+ _get_state = function()
+ return state
+ end,
+ }, {
+ -- insert =
+
+ -- __index = function(_, line)
+ -- end,
+
+ -- __newindex = function(_, index, line)
+ -- end,
+ })
+end
+
+
return pickers
diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua
index 31ea364..ee99d11 100644
--- a/lua/telescope/previewers.lua
+++ b/lua/telescope/previewers.lua
@@ -29,7 +29,7 @@ previewers.vim_buffer = previewers.new {
end
local file_name = vim.split(line, ":")[1]
- log.info("Previewing File: %s", file_name)
+ log.trace("Previewing File: %s", file_name)
-- vim.fn.termopen(
-- string.format("bat --color=always --style=grid %s"),
diff --git a/lua/telescope/sorters.lua b/lua/telescope/sorters.lua
index c97a1a9..0299c91 100644
--- a/lua/telescope/sorters.lua
+++ b/lua/telescope/sorters.lua
@@ -1,3 +1,4 @@
+local log = require('telescope.log')
local util = require('telescope.utils')
local sorters = {}
@@ -12,7 +13,7 @@ Sorter.__index = Sorter
---
--- Lower number is better (because it's like a closer match)
--- But, any number below 0 means you want that line filtered out.
---- @param scoring_function function Function that has the interface:
+--- @field scoring_function function Function that has the interface:
-- (sorter, prompt, line): number
function Sorter:new(opts)
opts = opts or {}
@@ -59,4 +60,14 @@ sorters.get_ngram_sorter = function()
}
end
+sorters.get_levenshtein_sorter = function()
+ return Sorter:new {
+ scoring_function = function(_, prompt, line)
+ local result = require('telescope.algos.string_distance')(prompt, line)
+ log.info("Sorting result for", prompt, line, " = ", result)
+ return result
+ end
+ }
+end
+
return sorters
diff --git a/lua/telescope/utils.lua b/lua/telescope/utils.lua
index e758ed0..7ddc428 100644
--- a/lua/telescope/utils.lua
+++ b/lua/telescope/utils.lua
@@ -19,6 +19,15 @@ utils.default_table_mt = {
end
}
+utils.repeated_table = function(n, val)
+ local empty_lines = {}
+ for _ = 1, n do
+ table.insert(empty_lines, val)
+ end
+ return empty_lines
+end
+
+
local NGram = {}
NGram.__index = NGram
diff --git a/lua/tests/telescope_spec.lua b/lua/tests/telescope_spec.lua
index 692f469..c671579 100644
--- a/lua/tests/telescope_spec.lua
+++ b/lua/tests/telescope_spec.lua
@@ -1,5 +1,6 @@
require('plenary.test_harness'):setup_busted()
+local pickers = require('telescope.pickers')
local utils = require('telescope.utils')
--[[
@@ -13,6 +14,81 @@ describe('Picker', function()
end)
end)
+ describe('process_result', function()
+ it('works with one entry', function()
+ local lines_manager = pickers.line_manager(5, nil)
+
+ lines_manager:add_result(1, "hello")
+
+ assert.are.same(1, lines_manager:_get_state()[1].score)
+ end)
+
+ it('works with two entries', function()
+ local lines_manager = pickers.line_manager(5, nil)
+
+ lines_manager:add_result(1, "hello")
+ lines_manager:add_result(2, "later")
+
+ assert.are.same("hello", lines_manager:_get_state()[1].line)
+ assert.are.same("later", lines_manager:_get_state()[2].line)
+ end)
+
+ it('calls functions when inserting', function()
+ local called_count = 0
+ local lines_manager = pickers.line_manager(5, function() called_count = called_count + 1 end)
+
+ assert(called_count == 0)
+ lines_manager:add_result(1, "hello")
+ assert(called_count == 1)
+ end)
+
+ it('calls functions when inserting twice', function()
+ local called_count = 0
+ local lines_manager = pickers.line_manager(5, function() called_count = called_count + 1 end)
+
+ assert(called_count == 0)
+ lines_manager:add_result(1, "hello")
+ lines_manager:add_result(2, "world")
+ assert(called_count == 2)
+ end)
+
+ it('correctly sorts lower scores', function()
+ local called_count = 0
+ local lines_manager = pickers.line_manager(5, function() called_count = called_count + 1 end)
+ lines_manager:add_result(5, "worse result")
+ lines_manager:add_result(2, "better result")
+
+ assert.are.same("better result", lines_manager:_get_state()[1].line)
+ assert.are.same("worse result", lines_manager:_get_state()[2].line)
+
+ -- once to insert "worse"
+ -- once to insert "better"
+ -- and then to move "worse"
+ assert.are.same(3, called_count)
+ end)
+
+ it('respects max results', function()
+ local called_count = 0
+ local lines_manager = pickers.line_manager(1, function() called_count = called_count + 1 end)
+ lines_manager:add_result(2, "better result")
+ lines_manager:add_result(5, "worse result")
+
+ assert.are.same("better result", lines_manager:_get_state()[1].line)
+
+ -- once to insert "worse"
+ -- once to insert "better"
+ -- and then to move "worse"
+ assert.are.same(1, called_count)
+ end)
+
+ -- TODO: We should decide if we want to add this or not.
+ -- it('should handle no scores', function()
+ -- local lines_manager = pickers.line_manager(5, nil)
+
+ -- lines_manager:add_result(nil,
+ -- end)
+ end)
+
describe('ngrams', function()
it('should capture intself in the ngram', function()
local n = utils.new_ngram()