feat: v1 options menu (#133)
Still has a bunch of improvements that can be done, but wanted to merge in some of the related changes. * options parser * wip: vimoptions finder * feat: pre-populate ex-command line with `:set foo=` * use options current value when populating command line * fix: use result.raw_value to store original option value * . * options: Continue work on option finder * [WIP]: Tue 27 Oct 2020 10:34:09 PM EDT * [WIP]: Mon 02 Nov 2020 08:20:13 PM EST * [WIP]: Mon 02 Nov 2020 09:04:23 PM EST Co-authored-by: TJ DeVries <devries.timothyj@gmail.com>
This commit is contained in:
@@ -24,14 +24,13 @@ if 2 > vim.o.report then
|
||||
end
|
||||
|
||||
|
||||
-- TODO: Give some bonus weight to files we've picked before
|
||||
-- TODO: Give some bonus weight to oldfiles
|
||||
|
||||
local actions = require('telescope.actions')
|
||||
local finders = require('telescope.finders')
|
||||
local log = require('telescope.log')
|
||||
local make_entry = require('telescope.make_entry')
|
||||
local previewers = require('telescope.previewers')
|
||||
local path = require('telescope.path')
|
||||
local pickers = require('telescope.pickers')
|
||||
local previewers = require('telescope.previewers')
|
||||
local sorters = require('telescope.sorters')
|
||||
local utils = require('telescope.utils')
|
||||
|
||||
@@ -46,11 +45,17 @@ local builtin = {}
|
||||
builtin.git_files = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local show_untracked = utils.get_default(opts.show_untracked, true)
|
||||
|
||||
if opts.cwd then
|
||||
opts.cwd = vim.fn.expand(opts.cwd)
|
||||
else
|
||||
--- Find root of git directory and remove trailing newline characters
|
||||
opts.cwd = string.gsub(vim.fn.system("git rev-parse --show-toplevel"), '[\n\r]+', '')
|
||||
opts.cwd = vim.fn.systemlist("git rev-parse --show-toplevel")[1]
|
||||
|
||||
if not vim.fn.isdirectory(opts.cwd) then
|
||||
error("Not a working directory for git_files:", opts.cwd)
|
||||
end
|
||||
end
|
||||
|
||||
-- By creating the entry maker after the cwd options,
|
||||
@@ -60,7 +65,7 @@ builtin.git_files = function(opts)
|
||||
pickers.new(opts, {
|
||||
prompt_title = 'Git File',
|
||||
finder = finders.new_oneshot_job(
|
||||
{ "git", "ls-tree", "--full-tree", "-r", "--name-only", "HEAD" },
|
||||
{ "git", "ls-files", "--exclude-standard", "--cached", show_untracked and "--others" },
|
||||
opts
|
||||
),
|
||||
previewer = previewers.cat.new(opts),
|
||||
@@ -412,6 +417,72 @@ builtin.command_history = function(opts)
|
||||
}):find()
|
||||
end
|
||||
|
||||
builtin.vim_options = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
-- Load vim options.
|
||||
local vim_opts = loadfile(utils.data_directory() .. path.separator .. 'options' .. path.separator .. 'options.lua')().options
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt = 'options',
|
||||
finder = finders.new_table {
|
||||
results = vim_opts,
|
||||
entry_maker = make_entry.gen_from_vimoptions(opts),
|
||||
},
|
||||
-- TODO: previewer for Vim options
|
||||
-- previewer = previewers.help.new(opts),
|
||||
sorter = sorters.get_fzy_sorter(),
|
||||
attach_mappings = function(prompt_bufnr, map)
|
||||
local edit_option = function()
|
||||
local selection = actions.get_selected_entry(prompt_bufnr)
|
||||
local esc = ""
|
||||
|
||||
|
||||
if vim.fn.mode() == "i" then
|
||||
-- TODO: don't make this local
|
||||
esc = vim.api.nvim_replace_termcodes("<esc>", true, false, true)
|
||||
end
|
||||
|
||||
-- TODO: Make this actually work.
|
||||
|
||||
-- actions.close(prompt_bufnr)
|
||||
-- vim.api.nvim_win_set_var(vim.fn.nvim_get_current_win(), "telescope", 1)
|
||||
-- print(prompt_bufnr)
|
||||
-- print(vim.fn.bufnr())
|
||||
-- vim.cmd([[ autocmd BufEnter <buffer> ++nested ++once startinsert!]])
|
||||
-- print(vim.fn.winheight(0))
|
||||
|
||||
-- local prompt_winnr = vim.fn.getbufinfo(prompt_bufnr)[1].windows[1]
|
||||
-- print(prompt_winnr)
|
||||
|
||||
-- local float_opts = {}
|
||||
-- float_opts.relative = "editor"
|
||||
-- float_opts.anchor = "sw"
|
||||
-- float_opts.focusable = false
|
||||
-- float_opts.style = "minimal"
|
||||
-- float_opts.row = vim.api.nvim_get_option("lines") - 2 -- TODO: include `cmdheight` and `laststatus` in this calculation
|
||||
-- float_opts.col = 2
|
||||
-- float_opts.height = 10
|
||||
-- float_opts.width = string.len(selection.last_set_from)+15
|
||||
-- local buf = vim.fn.nvim_create_buf(false, true)
|
||||
-- vim.fn.nvim_buf_set_lines(buf, 0, 0, false, {"default value: abcdef", "last set from: " .. selection.last_set_from})
|
||||
-- local status_win = vim.fn.nvim_open_win(buf, false, float_opts)
|
||||
-- -- vim.api.nvim_win_set_option(status_win, "winblend", 100)
|
||||
-- vim.api.nvim_win_set_option(status_win, "winhl", "Normal:PmenuSel")
|
||||
-- -- vim.api.nvim_set_current_win(status_win)
|
||||
-- vim.cmd[[redraw!]]
|
||||
-- vim.cmd("autocmd CmdLineLeave : ++once echom 'beep'")
|
||||
vim.api.nvim_feedkeys(string.format("%s:set %s=%s", esc, selection.name, selection.current_value), "m", true)
|
||||
end
|
||||
|
||||
map('i', '<CR>', edit_option)
|
||||
map('n', '<CR>', edit_option)
|
||||
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
end
|
||||
|
||||
builtin.help_tags = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local has_devicons, devicons = pcall(require, 'nvim-web-devicons')
|
||||
|
||||
local conf = require('telescope.config').values
|
||||
local entry_display = require('telescope.pickers.entry_display')
|
||||
local path = require('telescope.path')
|
||||
local utils = require('telescope.utils')
|
||||
|
||||
@@ -465,4 +466,110 @@ function make_entry.gen_from_marks(_)
|
||||
end
|
||||
end
|
||||
|
||||
function make_entry.gen_from_vimoptions(opts)
|
||||
-- TODO: Can we just remove this from `options.lua`?
|
||||
function N_(s)
|
||||
return s
|
||||
end
|
||||
|
||||
local process_one_opt = function(o)
|
||||
local ok, value_origin
|
||||
|
||||
local option = {
|
||||
name = "",
|
||||
description = "",
|
||||
current_value = "",
|
||||
default_value = "",
|
||||
value_type = "",
|
||||
set_by_user = false,
|
||||
last_set_from = "",
|
||||
}
|
||||
|
||||
local is_global = false
|
||||
for _, v in ipairs(o.scope) do
|
||||
if v == "global" then
|
||||
is_global = true
|
||||
end
|
||||
end
|
||||
|
||||
if not is_global then
|
||||
return
|
||||
end
|
||||
|
||||
if is_global then
|
||||
option.name = o.full_name
|
||||
|
||||
ok, option.current_value = pcall(vim.api.nvim_get_option, o.full_name)
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
|
||||
local str_funcname = o.short_desc()
|
||||
option.description = assert(loadstring("return " .. str_funcname))()
|
||||
-- if #option.description > opts.desc_col_length then
|
||||
-- opts.desc_col_length = #option.description
|
||||
-- end
|
||||
|
||||
if o.defaults ~= nil then
|
||||
option.default_value = o.defaults.if_true.vim or o.defaults.if_true.vi
|
||||
end
|
||||
|
||||
if type(option.default_value) == "function" then
|
||||
option.default_value = "Macro: " .. option.default_value()
|
||||
end
|
||||
|
||||
option.value_type = (type(option.current_value) == "boolean" and "bool" or type(option.current_value))
|
||||
|
||||
if option.current_value ~= option.default_value then
|
||||
option.set_by_user = true
|
||||
value_origin = vim.fn.execute("verbose set " .. o.full_name .. "?")
|
||||
if string.match(value_origin, "Last set from") then
|
||||
-- TODO: parse file and line number as separate items
|
||||
option.last_set_from = value_origin:gsub("^.*Last set from ", "")
|
||||
end
|
||||
end
|
||||
|
||||
return option
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: don't call this 'line'
|
||||
local displayer = entry_display.create {
|
||||
separator = "│",
|
||||
items = {
|
||||
{ width = 25 },
|
||||
{ width = 50 },
|
||||
{ remaining = true },
|
||||
},
|
||||
}
|
||||
|
||||
local make_display = function(entry)
|
||||
|
||||
return displayer {
|
||||
entry.name,
|
||||
string.format(
|
||||
"[%s] %s",
|
||||
entry.value_type,
|
||||
utils.display_termcodes(tostring(entry.current_value))),
|
||||
entry.description,
|
||||
}
|
||||
end
|
||||
|
||||
return function(line)
|
||||
local entry = process_one_opt(line)
|
||||
if not entry then
|
||||
return
|
||||
end
|
||||
|
||||
entry.valid = true
|
||||
entry.display = make_display
|
||||
entry.value = line
|
||||
entry.ordinal = line.full_name
|
||||
-- entry.raw_value = d.raw_value
|
||||
-- entry.last_set_from = d.last_set_from
|
||||
|
||||
return entry
|
||||
end
|
||||
end
|
||||
|
||||
return make_entry
|
||||
|
||||
@@ -7,12 +7,14 @@ local actions = require('telescope.actions')
|
||||
local config = require('telescope.config')
|
||||
local debounce = require('telescope.debounce')
|
||||
local resolve = require('telescope.config.resolve')
|
||||
local layout_strategies = require('telescope.pickers.layout_strategies')
|
||||
local log = require('telescope.log')
|
||||
local mappings = require('telescope.mappings')
|
||||
local state = require('telescope.state')
|
||||
local utils = require('telescope.utils')
|
||||
|
||||
local layout_strategies = require('telescope.pickers.layout_strategies')
|
||||
local entry_display = require('telescope.pickers.entry_display')
|
||||
|
||||
local EntryManager = require('telescope.entry_manager')
|
||||
|
||||
local get_default = utils.get_default
|
||||
@@ -307,7 +309,9 @@ function Picker:find()
|
||||
|
||||
local results_win, results_opts = popup.create('', popup_opts.results)
|
||||
local results_bufnr = a.nvim_win_get_buf(results_win)
|
||||
|
||||
self.results_bufnr = results_bufnr
|
||||
self.results_win = results_win
|
||||
|
||||
-- TODO: Should probably always show all the line for results win, so should implement a resize for the windows
|
||||
a.nvim_win_set_option(results_win, 'wrap', false)
|
||||
@@ -785,13 +789,8 @@ function Picker:entry_adder(index, entry, score)
|
||||
return
|
||||
end
|
||||
|
||||
local display, display_highlights
|
||||
if type(entry.display) == 'function' then
|
||||
self:_increment("display_fn")
|
||||
display, display_highlights = entry:display()
|
||||
elseif type(entry.display) == 'string' then
|
||||
display = entry.display
|
||||
else
|
||||
local display, display_highlights = entry_display.resolve(self, entry)
|
||||
if not display then
|
||||
log.info("Weird entry", entry)
|
||||
return
|
||||
end
|
||||
|
||||
100
lua/telescope/pickers/entry_display.lua
Normal file
100
lua/telescope/pickers/entry_display.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
local log = require('telescope.log')
|
||||
|
||||
local entry_display = {}
|
||||
|
||||
-- index are used to determine the correct order
|
||||
-- elements = {
|
||||
-- [1] = { element, max width }, -- max width should be greater than 0
|
||||
-- [2] = { a, 0 } -- Use 0 to disable max width
|
||||
-- [3] = { b, 0 } -- If b is nil, skip this column, should skip column for all rows
|
||||
-- },
|
||||
-- separator = " " -- either arbitrary string, when you wanna use the same separator between all elements
|
||||
-- separator = { " ", ":" } -- or table, where [1] is separator between elements[1] and elements[2], etc
|
||||
|
||||
-- TODO: Remove this and move ONLY to create method.
|
||||
|
||||
local table_format = function(picker, elements, separator)
|
||||
-- TODO: Truncate...
|
||||
local win_width = vim.api.nvim_win_get_width(picker.results_win)
|
||||
|
||||
local output = ""
|
||||
for k, v in ipairs(elements) do
|
||||
local text = v[1]
|
||||
local width = v[2]
|
||||
if text ~= nil then
|
||||
if k > 1 then
|
||||
output = output .. (type(separator) == "table" and separator[k - 1] or separator)
|
||||
end
|
||||
if width then
|
||||
if width == 0 then
|
||||
output = output .. string.format("%s", text)
|
||||
elseif width < 1 then
|
||||
output = output .. string.format("%-" .. math.floor(width * win_width) .. "s", text)
|
||||
else
|
||||
output = output .. string.format("%-" .. width .."s", text)
|
||||
end
|
||||
else
|
||||
output = output .. text
|
||||
end
|
||||
end
|
||||
end
|
||||
return output
|
||||
end
|
||||
|
||||
local function truncate(str, len)
|
||||
-- TODO: This doesn't handle multi byte chars...
|
||||
if vim.fn.strdisplaywidth(str) > len - 1 then
|
||||
str = str:sub(1, len)
|
||||
str = str .. "…"
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
entry_display.create = function(configuration)
|
||||
local generator = {}
|
||||
for _, v in ipairs(configuration.items) do
|
||||
if v.width then
|
||||
local justify = not v.right_justify and "-" or ""
|
||||
local format_str = "%" .. justify .. v.width .. "s"
|
||||
table.insert(generator, function(item)
|
||||
return string.format(format_str, truncate(item, v.width))
|
||||
end)
|
||||
else
|
||||
table.insert(generator, function(item)
|
||||
return item
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
return function(self, picker)
|
||||
local results = {}
|
||||
for k, v in ipairs(self) do
|
||||
table.insert(results, generator[k](v, picker))
|
||||
end
|
||||
|
||||
return table.concat(results, configuration.separator or "│")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
entry_display.resolve = function(self, entry)
|
||||
local display, display_highlights
|
||||
if type(entry.display) == 'function' then
|
||||
self:_increment("display_fn")
|
||||
display, display_highlights = entry:display(self)
|
||||
|
||||
if type(display) == 'string' then
|
||||
return display, display_highlights
|
||||
end
|
||||
else
|
||||
display = entry.display
|
||||
end
|
||||
|
||||
if type(display) == 'string' then
|
||||
return display, display_highlights
|
||||
elseif type(display) == 'table' then
|
||||
return table_format(self, display, "│"), display_highlights
|
||||
end
|
||||
end
|
||||
|
||||
return entry_display
|
||||
@@ -178,4 +178,16 @@ function utils.max_split(s, pattern, maxsplit)
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
function utils.data_directory()
|
||||
local sourced_file = require('plenary.debug_utils').sourced_filepath()
|
||||
local base_directory = vim.fn.fnamemodify(sourced_file, ":h:h:h")
|
||||
|
||||
return base_directory .. pathlib.separator .. 'data' .. pathlib.separator
|
||||
end
|
||||
|
||||
function utils.display_termcodes(str)
|
||||
return str:gsub(string.char(9), "<TAB>"):gsub("", "<C-F>"):gsub(" ", "<Space>")
|
||||
end
|
||||
|
||||
return utils
|
||||
|
||||
Reference in New Issue
Block a user