summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorTJ DeVries <devries.timothyj@gmail.com>2020-08-31 16:44:47 -0400
committerTJ DeVries <devries.timothyj@gmail.com>2020-08-31 17:32:31 -0400
commite38589f265a276d431113efcef6fdb157120ce68 (patch)
treebd3203a976f3e349875184f03d3199d79fb7303f /lua
parent0af8a911b4b5d3eefa6518a804ddadefefd65e19 (diff)
feat: Combine configuration into picker.new()
Diffstat (limited to 'lua')
-rw-r--r--lua/telescope/_private/NGRam.lua109
-rw-r--r--lua/telescope/builtin.lua196
-rw-r--r--lua/telescope/finders.lua48
-rw-r--r--lua/telescope/pickers.lua90
-rw-r--r--lua/telescope/utils.lua142
5 files changed, 275 insertions, 310 deletions
diff --git a/lua/telescope/_private/NGRam.lua b/lua/telescope/_private/NGRam.lua
new file mode 100644
index 0000000..15006c6
--- /dev/null
+++ b/lua/telescope/_private/NGRam.lua
@@ -0,0 +1,109 @@
+local NGram = {}
+NGram.__index = NGram
+
+function NGram:new(opts)
+ -- TODO: Add padding
+ opts = opts or {}
+ return setmetatable({
+ N = opts.N or 2,
+ split = opts.split or "/",
+ _depth = 5,
+ _grams = setmetatable({}, utils.default_table_mt)
+ }, self)
+end
+
+local min = math.min
+
+function NGram:_split(word)
+ local word_len = #word
+
+ local result = {}
+ for i = 1, word_len - 1 do
+ -- for j = i + (self.N - 1), min(i + self._depth - 1, word_len) do
+ -- table.insert(result, string.sub(word, i, j))
+ -- end
+ table.insert(result, string.sub(word, i, i + self.N - 1))
+ end
+
+ return result
+end
+
+-- local function pairsByKeys (t, f)
+-- local a = {}
+-- for n in pairs(t) do table.insert(a, n) end
+-- table.sort(a, f)
+-- local i = 0 -- iterator variable
+-- local iter = function () -- iterator function
+-- i = i + 1
+-- if a[i] == nil then return nil
+-- else return a[i], t[a[i]]
+-- end
+-- end
+-- return iter
+-- end
+
+function NGram:add(word)
+ local split_word = self:_split(word)
+
+ for _, k in ipairs(split_word) do
+ local counts = self._grams[k]
+ if counts[word] == nil then
+ counts[word] = 0
+ end
+
+ counts[word] = counts[word] + 1
+ end
+end
+
+function NGram:_items_sharing_ngrams(query)
+ local split_query = self:_split(query)
+
+ -- Matched string to number of N-grams shared with the query string.
+ local shared = {}
+
+ local remaining = {}
+
+ for _, ngram in ipairs(split_query) do
+ remaining = {}
+ for match, count in pairs(self._grams[ngram] or {}) do
+ remaining[match] = remaining[match] or count
+
+ if remaining[match] > 0 then
+ remaining[match] = remaining[match] - 1
+ shared[match] = (shared[match] or 0) + 1
+ end
+ end
+ end
+
+ return shared
+end
+
+function NGram:search(query, show_values)
+ local sharing_ngrams = self:_items_sharing_ngrams(query)
+
+ local results = {}
+ for name, count in pairs(sharing_ngrams) do
+ local allgrams = #query + #name - (2 * self.N) - count + 2
+ table.insert(results, {name, count / allgrams})
+ end
+
+ table.sort(results, function(left, right)
+ return left[2] > right[2]
+ end)
+
+ if not show_values then
+ for k, v in ipairs(results) do
+ results[k] = v[1]
+ end
+ end
+
+ return results
+end
+
+function NGram:find(query)
+ return self:search(query)[1]
+end
+
+function NGram:score(query)
+ return (self:search(query, true)[1] or {})[2] or 0
+end
diff --git a/lua/telescope/builtin.lua b/lua/telescope/builtin.lua
index cd7e4ab..43e57fc 100644
--- a/lua/telescope/builtin.lua
+++ b/lua/telescope/builtin.lua
@@ -8,50 +8,20 @@ local finders = require('telescope.finders')
local previewers = require('telescope.previewers')
local pickers = require('telescope.pickers')
local sorters = require('telescope.sorters')
+local utils = require('telescope.utils')
local builtin = {}
-local ifnil = function(x, was_nil, was_not_nil) if x == nil then return was_nil else return was_not_nil end end
-
builtin.git_files = function(opts)
- opts = opts or {}
-
- local show_preview = ifnil(opts.show_preview, true, opts.show_preview)
-
- local file_finder = finders.new {
- static = true,
-
- fn_command = function(self)
- return {
- command = 'git',
- args = {'ls-files'}
- }
- end,
- }
-
- local file_previewer = previewers.cat
-
- local file_picker = pickers.new {
- previewer = show_preview and file_previewer,
-
- selection_strategy = opts.selection_strategy,
- }
-
- -- local file_sorter = telescope.sorters.get_ngram_sorter()
- -- local file_sorter = require('telescope.sorters').get_levenshtein_sorter()
- local file_sorter = sorters.get_norcalli_sorter()
-
- file_picker:find {
- prompt = 'Simple File',
- finder = file_finder,
- sorter = file_sorter,
-
- border = opts.border,
- borderchars = opts.borderchars,
- }
+ pickers.new(opts, {
+ prompt = 'Git File',
+ finder = finders.new_oneshot_job({ "git", "ls-files" }),
+ previewer = previewers.cat,
+ sorter = sorters.get_norcalli_sorter(),
+ }):find()
end
-builtin.live_grep = function()
+builtin.live_grep = function(opts)
local live_grepper = finders.new {
maximum_results = 1000,
@@ -68,15 +38,13 @@ builtin.live_grep = function()
end
}
- local file_previewer = previewers.vimgrep
- local file_picker = pickers.new {
- previewer = file_previewer
- }
-
- -- local file_sorter = telescope.sorters.get_ngram_sorter()
- -- local file_sorter = require('telescope.sorters').get_levenshtein_sorter()
- -- local file_sorter = sorters.get_norcalli_sorter()
+ pickers.new(opts, {
+ prompt = 'Live Grep',
+ finder = live_grepper,
+ previewer = previewers.vimgrep,
+ }):find()
+ -- TODO: Incorporate this.
-- Weight the results somehow to be more likely to be the ones that you've opened.
-- local old_files = {}
-- for _, f in ipairs(vim.v.oldfiles) do
@@ -102,15 +70,9 @@ builtin.live_grep = function()
-- end
-- end
-- }
-
- file_picker:find {
- prompt = 'Live Grep',
- finder = live_grepper,
- sorter = oldfiles_sorter,
- }
end
-builtin.lsp_references = function()
+builtin.lsp_references = function(opts)
local params = vim.lsp.util.make_position_params()
params.context = { includeDeclaration = true }
@@ -120,87 +82,34 @@ builtin.lsp_references = function()
vim.list_extend(locations, vim.lsp.util.locations_to_items(server_results.result) or {})
end
- local results = {}
- for _, entry in ipairs(locations) do
- local vimgrep_str = string.format(
- "%s:%s:%s: %s",
- vim.fn.fnamemodify(entry.filename, ":."),
- entry.lnum,
- entry.col,
- entry.text
- )
-
- table.insert(results, {
- valid = true,
- value = entry,
- ordinal = vimgrep_str,
- display = vimgrep_str,
- })
- end
+ local results = utils.quickfix_items_to_entries(locations)
if vim.tbl_isempty(results) then
return
end
- local lsp_reference_finder = finders.new {
- results = results
- }
-
- local reference_previewer = previewers.qflist
- local reference_picker = pickers.new {
- previewer = reference_previewer
- }
-
- reference_picker:find {
- prompt = 'LSP References',
- finder = lsp_reference_finder,
- sorter = sorters.get_norcalli_sorter(),
- }
+ local reference_picker = pickers.new(opts, {
+ prompt = 'LSP References',
+ finder = finders.new_table(results),
+ previewer = previewers.qflist,
+ sorter = sorters.get_norcalli_sorter(),
+ }):find()
end
-builtin.quickfix = function()
+builtin.quickfix = function(opts)
local locations = vim.fn.getqflist()
-
- local results = {}
- for _, entry in ipairs(locations) do
- if not entry.filename then
- entry.filename = vim.api.nvim_buf_get_name(entry.bufnr)
- end
-
- local vimgrep_str = string.format(
- "%s:%s:%s: %s",
- vim.fn.fnamemodify(entry.filename, ":."),
- entry.lnum,
- entry.col,
- entry.text
- )
-
- table.insert(results, {
- valid = true,
- value = entry,
- ordinal = vimgrep_str,
- display = vimgrep_str,
- })
- end
+ local results = utils.quickfix_items_to_entries(locations)
if vim.tbl_isempty(results) then
return
end
- local quickfix_finder = finders.new {
- results = results
- }
-
- local quickfix_previewer = previewers.qflist
- local quickfix_picker = pickers.new {
- previewer = quickfix_previewer
- }
-
- quickfix_picker:find {
- prompt = 'Quickfix',
- finder = quickfix_finder,
- sorter = sorters.get_norcalli_sorter(),
- }
+ pickers.new(opts, {
+ prompt = 'Quickfix',
+ finder = finders.new_table(results),
+ previewer = previewers.qflist,
+ sorter = sorters.get_norcalli_sorter(),
+ }):find()
end
builtin.grep_string = function(opts)
@@ -208,42 +117,23 @@ builtin.grep_string = function(opts)
local search = opts.search or vim.fn.expand("<cword>")
- local grepper = finders.new {
- maximum_results = 10000,
-
- -- TODO: We can optimize these.
- -- static = true,
-
- fn_command = function()
- return {
- command = 'rg',
- args = {"--vimgrep", search},
- }
- end
- }
-
- local file_picker = pickers.new {
- previewer = previewers.vimgrep
- }
-
- file_picker:find {
- prompt = 'Live Grep',
- finder = grepper,
+ local file_picker = pickers.new(opts, {
+ prompt = 'Find Word',
+ finder = finders.new_oneshot_job {'rg', '--vimgrep', search},
+ previewer = previewers.vimgrep,
sorter = sorters.get_norcalli_sorter(),
- }
+ }):find()
end
-builtin.oldfiles = function()
- local oldfiles_finder = finders.new {
- results = vim.v.oldfiles
- }
- local file_picker = pickers.new{}
-
- file_picker:find {
+builtin.oldfiles = function(opts)
+ pickers.new(opts, {
prompt = 'Oldfiles',
- finder = oldfiles_finder,
- sorter = sorters.get_norcalli_sorter()
- }
+ finder = finders.new_table(vim.tbl_filter(function(val)
+ return 0 ~= vim.fn.filereadable(val)
+ end, vim.v.oldfiles)),
+ sorter = sorters.get_norcalli_sorter(),
+ previewer = previewers.cat,
+ }):find()
end
return builtin
diff --git a/lua/telescope/finders.lua b/lua/telescope/finders.lua
index 7866c87..ae32370 100644
--- a/lua/telescope/finders.lua
+++ b/lua/telescope/finders.lua
@@ -1,17 +1,19 @@
local Job = require('plenary.job')
local log = require('telescope.log')
+local utils = require('telescope.utils')
local finders = {}
-
-- TODO: We should make a few different "FinderGenerators":
-- SimpleListFinder(my_list)
-- FunctionFinder(my_func)
-- JobFinder(my_job_args)
---@class Finder
-local Finder = {}
+local Finder = {
+ hello = "world"
+}
Finder.__index = Finder
Finder.__call = function(t, ... ) return t:_find(...) end
@@ -35,7 +37,7 @@ function Finder:new(opts)
-- string
-- list
-- ...
- return setmetatable({
+ local obj = setmetatable({
results = opts.results,
fn_command = opts.fn_command,
@@ -45,7 +47,9 @@ function Finder:new(opts)
-- Maximum number of results to process.
-- Particularly useful for live updating large queries.
maximum_results = opts.maximum_results,
- }, Finder)
+ }, self)
+
+ return obj
end
-- Probably should use the word apply here, since we're apply the callback passed to us by
@@ -145,8 +149,38 @@ end
--- Return a new Finder
--
--@return Finder
-finders.new = function(...)
- return Finder:new(...)
+finders.new = function(opts)
+ return Finder:new(opts)
+end
+
+-- TODO: Is this worth making?
+-- finders.new_responsive_job = function(opts)
+-- return finders.new {
+-- maximum_results = get_default(opts.maximum_results, 2000),
+-- }
+-- end
+
+finders.new_oneshot_job = function(command_list)
+ command_list = vim.deepcopy(command_list)
+
+ local command = table.remove(command_list, 1)
+
+ return finders.new {
+ static = true,
+
+ fn_command = function()
+ return {
+ command = command,
+ args = command_list,
+ }
+ end,
+ }
+end
+
+finders.new_table = function(t)
+ return finders.new {
+ results = t
+ }
end
-- We should add a few utility functions here...
@@ -155,6 +189,6 @@ end
-- finders.new_one_shot_job
-- finders.new_table
-finders.Finder = Finder
+-- finders.Finder = Finder
return finders
diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua
index ce01f23..e75f43e 100644
--- a/lua/telescope/pickers.lua
+++ b/lua/telescope/pickers.lua
@@ -1,5 +1,6 @@
local a = vim.api
local popup = require('popup')
+local has_devicons, devicons = pcall(require, 'nvim-web-devicons')
local actions = require('telescope.actions')
local log = require('telescope.log')
@@ -8,14 +9,22 @@ local state = require('telescope.state')
local utils = require('telescope.utils')
local Entry = require('telescope.entry')
-local Sorter = require('telescope.sorters').Sorter
-local Previewer = require('telescope.previewers').Previewer
-local has_devicons, devicons = pcall(require, 'nvim-web-devicons')
+local get_default = utils.get_default
-local pickers = {}
+-- TODO: Make this work with deep extend I think.
+local extend = function(opts, defaults)
+ local result = vim.deepcopy(opts or {})
+ for k, v in pairs(defaults or {}) do
+ if result[k] == nil then
+ result[k] = v
+ end
+ end
-local ifnil = function(x, was_nil, was_not_nil) if x == nil then return was_nil else return was_not_nil end end
+ return result
+end
+
+local pickers = {}
local default_mappings = {
i = {
@@ -42,58 +51,60 @@ local default_mappings = {
local Picker = {}
Picker.__index = Picker
-assert(Sorter)
-assert(Previewer)
-
----@class PickOpts
----@field filter Sorter
----@field maps table
----@field unseen string
-
--- Create new picker
---- @param opts PickOpts
function Picker:new(opts)
opts = opts or {}
return setmetatable({
- filter = opts.filter,
+ prompt = opts.prompt,
+
+ finder = opts.finder,
+ sorter = opts.sorter,
previewer = opts.previewer,
- maps = opts.maps,
- get_window_options = opts.get_window_options,
+ mappings = get_default(opts.mappings, default_mappings),
+ get_window_options = opts.get_window_options,
selection_strategy = opts.selection_strategy,
+
+ window = {
+ border = get_default(opts.border, {}),
+ borderchars = get_default(opts.borderchars, { '─', '│', '─', '│', '┌', '┐', '┘', '└'}),
+ },
+
+ preview_cutoff = get_default(opts.preview_cutoff, 120),
}, Picker)
end
-function Picker:get_window_options(max_columns, max_lines, prompt_title, find_options)
-
- local popup_border = ifnil(find_options.border, {}, find_options.border)
+function Picker:get_window_options(max_columns, max_lines, prompt_title)
+ local popup_border = self.window.border
+ local popup_borderchars = self.window.borderchars
local preview = {
border = popup_border,
- borderchars = find_options.borderchars or nil,
+ borderchars = popup_borderchars,
enter = false,
highlight = false
}
local results = {
border = popup_border,
- borderchars = find_options.borderchars or nil,
+ borderchars = popup_borderchars,
enter = false,
}
local prompt = {
title = prompt_title,
border = popup_border,
- borderchars = find_options.borderchars or nil,
+ borderchars = popup_borderchars,
enter = true
}
-- TODO: Test with 120 width terminal
local width_padding = 10
- if not self.previewer or max_columns < find_options.preview_cutoff then
+ if not self.previewer or max_columns < self.preview_cutoff then
+ width_padding = 2
preview.width = 0
elseif max_columns < 150 then
width_padding = 5
@@ -110,7 +121,7 @@ function Picker:get_window_options(max_columns, max_lines, prompt_title, find_op
local base_height
if max_lines < 40 then
- base_height = math.floor(max_lines * 0.5)
+ base_height = math.min(math.floor(max_lines * 0.8), max_lines - 8)
else
base_height = math.floor(max_lines * 0.8)
end
@@ -143,21 +154,10 @@ function Picker:get_window_options(max_columns, max_lines, prompt_title, find_op
}
end
--- opts.preview_cutoff = 120
-function Picker:find(opts)
- opts = opts or {}
-
- if opts.preview_cutoff == nil then
- opts.preview_cutoff = 120
- end
-
- opts.borderchars = opts.borderchars or { '─', '│', '─', '│', '┌', '┐', '┘', '└'}
-
- local finder = opts.finder
- assert(finder, "Finder is required to do picking")
-
- local sorter = opts.sorter
- local prompt_string = opts.prompt
+function Picker:find()
+ local prompt_string = assert(self.prompt, "Prompt is required.")
+ local finder = assert(self.finder, "Finder is required to do picking")
+ local sorter = self.sorter
self.original_win_id = a.nvim_get_current_win()
@@ -165,7 +165,7 @@ function Picker:find(opts)
-- 1. Prompt window
-- 2. Options window
-- 3. Preview window
- local popup_opts = self:get_window_options(vim.o.columns, vim.o.lines, prompt_string, opts)
+ local popup_opts = self:get_window_options(vim.o.columns, vim.o.lines, prompt_string)
-- TODO: Add back the borders after fixing some stuff in popup.nvim
local results_win, results_opts = popup.create('', popup_opts.results)
@@ -338,8 +338,7 @@ function Picker:find(opts)
finder = finder,
})
- -- mappings.set_keymap(prompt_bufnr, results_bufnr)
- mappings.apply_keymap(prompt_bufnr, opts.mappings or default_mappings)
+ mappings.apply_keymap(prompt_bufnr, self.mappings)
vim.cmd [[startinsert]]
end
@@ -462,8 +461,9 @@ function Picker:set_selection(row)
end
end
-pickers.new = function(...)
- return Picker:new(...)
+pickers.new = function(opts, defaults)
+ opts = extend(opts, defaults)
+ return Picker:new(opts)
end
-- TODO: We should consider adding `process_bulk` or `bulk_entry_manager` for things
diff --git a/lua/telescope/utils.lua b/lua/telescope/utils.lua
index 7ddc428..eba24a6 100644
--- a/lua/telescope/utils.lua
+++ b/lua/telescope/utils.lua
@@ -1,5 +1,25 @@
local utils = {}
+utils.if_nil = function(x, was_nil, was_not_nil)
+ if x == nil then
+ return was_nil
+ else
+ return was_not_nil
+ end
+end
+
+utils.get_default = function(x, default)
+ return utils.if_nil(x, default, x)
+end
+
+utils.get_lazy_default = function(x, defaulter, ...)
+ if x == nil then
+ return defaulter(...)
+ else
+ return x
+ end
+end
+
local function reversedipairsiter(t, i)
i = i - 1
if i ~= 0 then
@@ -27,119 +47,31 @@ utils.repeated_table = function(n, val)
return empty_lines
end
-
-local NGram = {}
-NGram.__index = NGram
-
-function NGram:new(opts)
- -- TODO: Add padding
- opts = opts or {}
- return setmetatable({
- N = opts.N or 2,
- split = opts.split or "/",
- _depth = 5,
- _grams = setmetatable({}, utils.default_table_mt)
- }, self)
-end
-
-local min = math.min
-
-function NGram:_split(word)
- local word_len = #word
-
- local result = {}
- for i = 1, word_len - 1 do
- -- for j = i + (self.N - 1), min(i + self._depth - 1, word_len) do
- -- table.insert(result, string.sub(word, i, j))
- -- end
- table.insert(result, string.sub(word, i, i + self.N - 1))
- end
-
- return result
-end
-
--- local function pairsByKeys (t, f)
--- local a = {}
--- for n in pairs(t) do table.insert(a, n) end
--- table.sort(a, f)
--- local i = 0 -- iterator variable
--- local iter = function () -- iterator function
--- i = i + 1
--- if a[i] == nil then return nil
--- else return a[i], t[a[i]]
--- end
--- end
--- return iter
--- end
-
-function NGram:add(word)
- local split_word = self:_split(word)
-
- for _, k in ipairs(split_word) do
- local counts = self._grams[k]
- if counts[word] == nil then
- counts[word] = 0
- end
-
- counts[word] = counts[word] + 1
- end
-end
-
-function NGram:_items_sharing_ngrams(query)
- local split_query = self:_split(query)
-
- -- Matched string to number of N-grams shared with the query string.
- local shared = {}
-
- local remaining = {}
-
- for _, ngram in ipairs(split_query) do
- remaining = {}
- for match, count in pairs(self._grams[ngram] or {}) do
- remaining[match] = remaining[match] or count
-
- if remaining[match] > 0 then
- remaining[match] = remaining[match] - 1
- shared[match] = (shared[match] or 0) + 1
- end
- end
- end
-
- return shared
-end
-
-function NGram:search(query, show_values)
- local sharing_ngrams = self:_items_sharing_ngrams(query)
-
+utils.quickfix_items_to_entries = function(locations)
local results = {}
- for name, count in pairs(sharing_ngrams) do
- local allgrams = #query + #name - (2 * self.N) - count + 2
- table.insert(results, {name, count / allgrams})
- end
-
- table.sort(results, function(left, right)
- return left[2] > right[2]
- end)
- if not show_values then
- for k, v in ipairs(results) do
- results[k] = v[1]
- end
+ for _, entry in ipairs(locations) do
+ local vimgrep_str = string.format(
+ "%s:%s:%s: %s",
+ vim.fn.fnamemodify(entry.filename, ":."),
+ entry.lnum,
+ entry.col,
+ entry.text
+ )
+
+ table.insert(results, {
+ valid = true,
+ value = entry,
+ ordinal = vimgrep_str,
+ display = vimgrep_str,
+ })
end
return results
end
-function NGram:find(query)
- return self:search(query)[1]
-end
-
-function NGram:score(query)
- return (self:search(query, true)[1] or {})[2] or 0
-end
-
utils.new_ngram = function()
- return NGram:new()
+ return require("telescope._private.NGram"):new()
end
return utils