From f67d3e883d7afafa93428a27cb1ba1c4144d9d4c Mon Sep 17 00:00:00 2001 From: Luke Kershaw <35707277+l-kershaw@users.noreply.github.com> Date: Wed, 18 Aug 2021 10:05:04 +0100 Subject: [PATCH] feat: allow tables in vimscript command parser (#1075) --- doc/telescope.txt | 35 ++++++++++++++++ lua/telescope/command.lua | 88 +++++++++++++++++++++++++++++++++------ scripts/gendocs.lua | 1 + 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/doc/telescope.txt b/doc/telescope.txt index 55c3466..20b3984 100644 --- a/doc/telescope.txt +++ b/doc/telescope.txt @@ -271,6 +271,41 @@ telescope.extensions() *telescope.extensions()* +================================================================================ + *telescope.command* + +Telescope commands can be called through two apis, the lua api and the viml +api. + +The lua api is the more direct way to interact with Telescope, as you directly +call the lua functions that Telescope defines. It can be called in a lua file +using commands like: +`require("telescope.builtin").find_files({hidden=true, layout_config={prompt_position="top"}})` +If you want to use this api from a vim file you should prepend `lua` to the +command, as below: +`lua require("telescope.builtin").find_files({hidden=true, layout_config={prompt_position="top"}})` +If you want to use this api from a neovim command line you should prepend +`:lua` to the command, as below: +`:lua require("telescope.builtin").find_files({hidden=true, layout_config={prompt_position="top"}})` + +The viml api is more indirect, as first the command must be parsed to the +relevant lua equivalent, which brings some limitations. The viml api can be +called using commands like: +`:Telescope find_files hidden=true layout_config={"prompt_position":"top"}` +This involves setting options using an `=` and using viml syntax for lists and +dictionaries when the corresponding lua function requires a table. + +One limitation of the viml api is that there can be no spaces in any of the +options. For example, if you want to use the `cwd` option for `find_files` to +specify that you only want to search within the folder `/foo bar/subfolder/` +you could not do that using the viml api, as the path name contains a space. +Similarly, you could NOT set the `prompt_position` to `"top"` using the +following command: +`:Telescope find_files layout_config={ "prompt_position" : "top" }` +as there are spaces in the option. + + + ================================================================================ *telescope.builtin* diff --git a/lua/telescope/command.lua b/lua/telescope/command.lua index c123b7b..01ed3c6 100644 --- a/lua/telescope/command.lua +++ b/lua/telescope/command.lua @@ -1,3 +1,46 @@ +---@tag telescope.command + +---@brief [[ +--- +--- Telescope commands can be called through two apis, +--- the lua api and the viml api. +--- +--- The lua api is the more direct way to interact with Telescope, as you directly call the +--- lua functions that Telescope defines. +--- It can be called in a lua file using commands like: +---
+--- `require("telescope.builtin").find_files({hidden=true, layout_config={prompt_position="top"}})`
+--- 
+--- If you want to use this api from a vim file you should prepend `lua` to the command, as below: +---
+--- `lua require("telescope.builtin").find_files({hidden=true, layout_config={prompt_position="top"}})`
+--- 
+--- If you want to use this api from a neovim command line you should prepend `:lua` to +--- the command, as below: +---
+--- `:lua require("telescope.builtin").find_files({hidden=true, layout_config={prompt_position="top"}})`
+--- 
+--- +--- The viml api is more indirect, as first the command must be parsed to the relevant lua +--- equivalent, which brings some limitations. +--- The viml api can be called using commands like: +---
+--- `:Telescope find_files hidden=true layout_config={"prompt_position":"top"}`
+--- 
+--- This involves setting options using an `=` and using viml syntax for lists and +--- dictionaries when the corresponding lua function requires a table. +--- +--- One limitation of the viml api is that there can be no spaces in any of the options. +--- For example, if you want to use the `cwd` option for `find_files` to specify that you +--- only want to search within the folder `/foo bar/subfolder/` you could not do that using the +--- viml api, as the path name contains a space. +--- Similarly, you could NOT set the `prompt_position` to `"top"` using the following command: +---
+--- `:Telescope find_files layout_config={ "prompt_position" : "top" }`
+--- 
+--- as there are spaces in the option. +--- +---@brief ]] local themes = require "telescope.themes" local builtin = require "telescope.builtin" local extensions = require("telescope._extensions").manager @@ -15,6 +58,14 @@ local bool_type = { ["true"] = true, } +local split_keywords = { + ["find_command"] = true, + ["vimgrep_arguments"] = true, + ["sections"] = true, + ["search_dirs"] = true, + ["symbols"] = true, +} + -- convert command line string arguments to -- lua number boolean type and nil value local function convert_user_opts(user_opts) @@ -41,6 +92,19 @@ local function convert_user_opts(user_opts) user_opts[key] = bool_type[val] end end, + ["table"] = function(key, val) + local ok, eval = pcall(vim.fn.eval, val) + if ok then + user_opts[key] = eval + else + eval = assert(loadstring("return " .. val))() + if type(eval) == "table" then + user_opts[key] = eval + else + user_opts[key] = nil + end + end + end, } local _switch_metatable = { @@ -52,7 +116,12 @@ local function convert_user_opts(user_opts) setmetatable(_switch, _switch_metatable) for key, val in pairs(user_opts) do - if default_opts[key] ~= nil then + if split_keywords[key] then + _switch["table"](key, val) + if user_opts[key] == nil then + user_opts[key] = vim.split(val, ",") + end + elseif default_opts[key] ~= nil then _switch[type(default_opts[key])](key, val) else _switch["string"](key, val) @@ -123,13 +192,6 @@ function command.get_extensions_subcommand() return complete_ext_table end -local split_keywords = { - ["find_command"] = true, - ["vimgrep_arguments"] = true, - ["sections"] = true, - ["search_dirs"] = true, -} - function command.register_keyword(keyword) split_keywords[keyword] = true end @@ -150,12 +212,12 @@ function command.load_command(cmd, ...) user_opts["extension_type"] = arg else local param = vim.split(arg, "=") - if param[1] == "theme" then - user_opts["theme"] = param[2] - elseif split_keywords[param[1]] then - user_opts.opts[param[1]] = vim.split(param[2], ",") + local key = table.remove(param, 1) + param = table.concat(param, "=") + if key == "theme" then + user_opts["theme"] = param else - user_opts.opts[param[1]] = param[2] + user_opts.opts[key] = param end end end diff --git a/scripts/gendocs.lua b/scripts/gendocs.lua index 5f04727..6972b21 100644 --- a/scripts/gendocs.lua +++ b/scripts/gendocs.lua @@ -10,6 +10,7 @@ docs.test = function() -- TODO: Fix the other files so that we can add them here. local input_files = { "./lua/telescope/init.lua", + "./lua/telescope/command.lua", "./lua/telescope/builtin/init.lua", "./lua/telescope/themes.lua", "./lua/telescope/pickers/layout_strategies.lua",