summaryrefslogtreecommitdiff
path: root/lua/telescope/make_entry.lua
diff options
context:
space:
mode:
authorTJ DeVries <devries.timothyj@gmail.com>2020-10-07 11:35:38 -0400
committerGitHub <noreply@github.com>2020-10-07 11:35:38 -0400
commit2053a2621a56177da34032a055dffe3f7bb384d1 (patch)
treed34ae40b1c52989c16e78725b9b551e25b2f6e21 /lua/telescope/make_entry.lua
parentd32d4a6e0f0c571941f1fd37759ca1ebbdd5f488 (diff)
feat: Use metatables to use less memory (#152)
Instead of storing everything in key / value pair hashes, we store as much as possible in an array and then reference the items in the array using metatables. This provides us with a much lower memory footprint and just one level of table lookup indirection (so I think the speed will not be noticeably different)
Diffstat (limited to 'lua/telescope/make_entry.lua')
-rw-r--r--lua/telescope/make_entry.lua228
1 files changed, 142 insertions, 86 deletions
diff --git a/lua/telescope/make_entry.lua b/lua/telescope/make_entry.lua
index bca2aa1..276f149 100644
--- a/lua/telescope/make_entry.lua
+++ b/lua/telescope/make_entry.lua
@@ -7,11 +7,6 @@ local get_default = utils.get_default
local make_entry = {}
-make_entry.types = {
- GENERIC = 0,
- FILE = 1,
-}
-
local transform_devicons
if has_devicons then
transform_devicons = function(filename, display, disable_devicons)
@@ -29,88 +24,82 @@ else
end
end
-function make_entry.gen_from_string()
- return function(line)
- return {
- valid = line ~= "",
- entry_type = make_entry.types.GENERIC,
+do
+ local lookup_keys = {
+ display = 1,
+ ordinal = 1,
+ value = 1,
+ }
- value = line,
- ordinal = line,
- display = line,
- }
+ local mt_string_entry = {
+ __index = function(t, k)
+ return rawget(t, rawget(lookup_keys, k))
+ end
+ }
+
+ function make_entry.gen_from_string()
+ return function(line)
+ return setmetatable({
+ line,
+ }, mt_string_entry)
+ end
end
end
-function make_entry.gen_from_file(opts)
- -- local opts = vim.deepcopy(init_opts or {})
- opts = opts or {}
-
- local cwd = vim.fn.expand(opts.cwd or vim.fn.getcwd())
- local disable_devicons = opts.disable_devicons
- local shorten_path = opts.shorten_path
+do
+ local lookup_keys = {
+ ordinal = 1,
+ value = 1,
+ filename = 1,
+ cwd = 2,
+ }
- local make_display = function(line)
- local display = line
- if shorten_path then
- display = utils.path_shorten(line)
- end
+ function make_entry.gen_from_file(opts)
+ opts = opts or {}
- display = transform_devicons(line, display, disable_devicons)
+ local cwd = vim.fn.expand(opts.cwd or vim.fn.getcwd())
- return display
- end
+ local disable_devicons = opts.disable_devicons
+ local shorten_path = opts.shorten_path
- return function(line)
- local entry = {
- ordinal = line,
- value = line,
+ local mt_file_entry = {}
- entry_type = make_entry.types.FILE,
- filename = line,
- path = cwd .. utils.get_separator() .. line,
- }
-
- entry.display = make_display(line)
-
- return entry
- end
-end
+ mt_file_entry.cwd = cwd
+ mt_file_entry.display = function(entry)
+ local display = entry.value
+ if shorten_path then
+ display = utils.path_shorten(display)
+ end
-function make_entry.gen_from_vimgrep(opts)
- opts = opts or {}
+ return transform_devicons(entry.value, display, disable_devicons)
+ end
- local display_string = "%s:%s%s"
+ mt_file_entry.__index = function(t, k)
+ local raw = rawget(mt_file_entry, k)
+ if raw then return raw end
- local make_display = function(entry)
- local display = entry.value
+ if k == "path" then
+ return t.cwd .. path.separator .. t.value
+ end
- local display_filename
- if opts.shorten_path then
- display_filename = utils.path_shorten(entry.filename)
- else
- display_filename = entry.filename
+ return rawget(t, rawget(lookup_keys, k))
end
- local coordinates = ""
- if not opts.disable_coordinates then
- coordinates = string.format("%s:%s:", entry.lnum, entry.col)
+ return function(line)
+ return setmetatable({line}, mt_file_entry)
end
-
- display = transform_devicons(
- entry.filename,
- string.format(display_string, display_filename, coordinates, entry.text),
- opts
- )
-
- return display
end
+end
- return function(line)
- -- TODO: Consider waiting to do this string.find
- -- TODO: Is this the fastest way to get each of these?
- -- Or could we just walk the text and check for colons faster?
- local _, _, filename, lnum, col, text = string.find(line, [[([^:]+):(%d+):(%d+):(.*)]])
+do
+ local lookup_keys = {
+ value = 1,
+ ordinal = 1,
+ }
+
+ -- Gets called only once to parse everything out for the vimgrep, after that looks up directly.
+ local parse = function(t)
+ local _, _, filename, lnum, col, text = string.find(t.value, [[([^:]+):(%d+):(%d+):(.*)]])
local ok
ok, lnum = pcall(tonumber, lnum)
@@ -119,19 +108,89 @@ function make_entry.gen_from_vimgrep(opts)
ok, col = pcall(tonumber, col)
if not ok then col = nil end
- return {
- valid = line ~= "",
+ t.filename = filename
+ t.lnum = lnum
+ t.col = col
+ t.text = text
- value = line,
- ordinal = line,
- display = make_display,
+ return {filename, lnum, col, text}
+ end
- entry_type = make_entry.types.FILE,
- filename = filename,
- lnum = lnum,
- col = col,
- text = text,
- }
+ local execute_keys = {
+ path = function(t)
+ return t.cwd .. path.separator .. t.filename, false
+ end,
+
+ filename = function(t)
+ return parse(t)[1], true
+ end,
+
+ lnum = function(t)
+ return parse(t)[2], true
+ end,
+
+ col = function(t)
+ return parse(t)[3], true
+ end,
+
+ text = function(t)
+ return parse(t)[4], true
+ end,
+ }
+
+ function make_entry.gen_from_vimgrep(opts)
+ opts = opts or {}
+
+ local shorten_path = opts.shorten_path
+ local disable_coordinates = opts.disable_coordinates
+ local disable_devicons = opts.disable_devicons
+
+ local display_string = "%s:%s%s"
+
+ local mt_vimgrep_entry = {}
+
+ mt_vimgrep_entry.cwd = vim.fn.expand(opts.cwd or vim.fn.getcwd())
+ mt_vimgrep_entry.display = function(entry)
+ local display = entry.value
+
+ local display_filename
+ if shorten_path then
+ display_filename = utils.path_shorten(entry.filename)
+ else
+ display_filename = entry.filename
+ end
+
+ local coordinates = ""
+ if not disable_coordinates then
+ coordinates = string.format("%s:%s:", entry.lnum, entry.col)
+ end
+
+ display = transform_devicons(
+ entry.filename,
+ string.format(display_string, display_filename, coordinates, entry.text),
+ disable_devicons
+ )
+
+ return display
+ end
+
+ mt_vimgrep_entry.__index = function(t, k)
+ local raw = rawget(mt_vimgrep_entry, k)
+ if raw then return raw end
+
+ local executor = rawget(execute_keys, k)
+ if executor then
+ local val, save = executor(t)
+ if save then rawset(t, k, val) end
+ return val
+ end
+
+ return rawget(t, rawget(lookup_keys, k))
+ end
+
+ return function(line)
+ return setmetatable({line}, mt_vimgrep_entry)
+ end
end
end
@@ -320,10 +379,7 @@ function make_entry.gen_from_tagfile(opts)
end
return function(line)
- local entry = {
- entry_type = make_entry.types.GENERIC,
-
- }
+ local entry = {}
local d = make_display(line)
entry.valid = next(d) ~= nil
entry.display = d.display
@@ -338,8 +394,8 @@ function make_entry.gen_from_packages(opts)
opts = opts or {}
local make_display = function(module_name)
- local path = package.searchpath(module_name, package.path) or ""
- local display = string.format("%-" .. opts.column_len .. "s : %s", module_name, vim.fn.fnamemodify(path, ":~:."))
+ local p_path = package.searchpath(module_name, package.path) or ""
+ local display = string.format("%-" .. opts.column_len .. "s : %s", module_name, vim.fn.fnamemodify(p_path, ":~:."))
return display
end