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)
This commit is contained in:
@@ -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
|
||||
|
||||
do
|
||||
local lookup_keys = {
|
||||
display = 1,
|
||||
ordinal = 1,
|
||||
value = 1,
|
||||
}
|
||||
|
||||
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 {
|
||||
valid = line ~= "",
|
||||
entry_type = make_entry.types.GENERIC,
|
||||
return setmetatable({
|
||||
line,
|
||||
}, mt_string_entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
value = line,
|
||||
ordinal = line,
|
||||
display = line,
|
||||
do
|
||||
local lookup_keys = {
|
||||
ordinal = 1,
|
||||
value = 1,
|
||||
filename = 1,
|
||||
cwd = 2,
|
||||
}
|
||||
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
|
||||
|
||||
local make_display = function(line)
|
||||
local display = line
|
||||
local mt_file_entry = {}
|
||||
|
||||
mt_file_entry.cwd = cwd
|
||||
mt_file_entry.display = function(entry)
|
||||
local display = entry.value
|
||||
if shorten_path then
|
||||
display = utils.path_shorten(line)
|
||||
display = utils.path_shorten(display)
|
||||
end
|
||||
|
||||
display = transform_devicons(line, display, disable_devicons)
|
||||
return transform_devicons(entry.value, display, disable_devicons)
|
||||
end
|
||||
|
||||
return display
|
||||
mt_file_entry.__index = function(t, k)
|
||||
local raw = rawget(mt_file_entry, k)
|
||||
if raw then return raw end
|
||||
|
||||
if k == "path" then
|
||||
return t.cwd .. path.separator .. t.value
|
||||
end
|
||||
|
||||
return rawget(t, rawget(lookup_keys, k))
|
||||
end
|
||||
|
||||
return function(line)
|
||||
local entry = {
|
||||
ordinal = line,
|
||||
value = line,
|
||||
return setmetatable({line}, mt_file_entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
entry_type = make_entry.types.FILE,
|
||||
filename = line,
|
||||
path = cwd .. utils.get_separator() .. line,
|
||||
do
|
||||
local lookup_keys = {
|
||||
value = 1,
|
||||
ordinal = 1,
|
||||
}
|
||||
|
||||
entry.display = make_display(line)
|
||||
|
||||
return entry
|
||||
end
|
||||
end
|
||||
|
||||
function make_entry.gen_from_vimgrep(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local display_string = "%s:%s%s"
|
||||
|
||||
local make_display = function(entry)
|
||||
local display = entry.value
|
||||
|
||||
local display_filename
|
||||
if opts.shorten_path then
|
||||
display_filename = utils.path_shorten(entry.filename)
|
||||
else
|
||||
display_filename = entry.filename
|
||||
end
|
||||
|
||||
local coordinates = ""
|
||||
if not opts.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),
|
||||
opts
|
||||
)
|
||||
|
||||
return display
|
||||
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+):(.*)]])
|
||||
-- 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
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
-- require('plenary.reload').reload_module('telescope')
|
||||
require('plenary.reload').reload_module('telescope')
|
||||
|
||||
local finders = require('telescope.finders')
|
||||
local pickers = require('telescope.pickers')
|
||||
local sorters = require('telescope.sorters')
|
||||
local previewers = require('telescope.previewers')
|
||||
local make_entry = require('telescope.make_entry')
|
||||
|
||||
local my_list = {
|
||||
'lua/telescope/WIP.lua',
|
||||
|
||||
Reference in New Issue
Block a user