From fbc983eb9166fdc15e5f63ec6adf043fb0124660 Mon Sep 17 00:00:00 2001 From: Luke Kershaw <35707277+l-kershaw@users.noreply.github.com> Date: Sat, 21 Aug 2021 11:44:27 +0100 Subject: [PATCH] fix(command_parser): pcall for the loadstring (#1134) --- lua/telescope/command.lua | 21 +++--- lua/tests/automated/command_spec.lua | 102 +++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 lua/tests/automated/command_spec.lua diff --git a/lua/telescope/command.lua b/lua/telescope/command.lua index 70c7b4a..db75eb1 100644 --- a/lua/telescope/command.lua +++ b/lua/telescope/command.lua @@ -68,7 +68,7 @@ local split_keywords = { -- convert command line string arguments to -- lua number boolean type and nil value -local function convert_user_opts(user_opts) +command.convert_user_opts = function(user_opts) local default_opts = config.values local _switch = { @@ -102,12 +102,15 @@ local function convert_user_opts(user_opts) if err ~= nil then -- discard invalid lua expression user_opts[key] = nil - elseif select("#", assert(eval)()) == 1 and type(assert(eval)()) == "table" then - -- allow if return a single table only - user_opts[key] = assert(eval)() - else - -- otherwise return nil (allows split check later) - user_opts[key] = nil + elseif eval ~= nil then + ok, eval = pcall(eval) + if ok and type(eval) == "table" then + -- allow if return a table only + user_opts[key] = eval + else + -- otherwise return nil (allows split check later) + user_opts[key] = nil + end end end end, @@ -129,6 +132,8 @@ local function convert_user_opts(user_opts) end elseif default_opts[key] ~= nil then _switch[type(default_opts[key])](key, val) + elseif tonumber(val) ~= nil then + _switch["number"](key, val) else _switch["string"](key, val) end @@ -157,7 +162,7 @@ local function run_command(args) local theme = user_opts.theme or "" if next(opts) ~= nil then - convert_user_opts(opts) + command.convert_user_opts(opts) end if string.len(theme) > 0 then diff --git a/lua/tests/automated/command_spec.lua b/lua/tests/automated/command_spec.lua new file mode 100644 index 0000000..9212815 --- /dev/null +++ b/lua/tests/automated/command_spec.lua @@ -0,0 +1,102 @@ +local command = require "telescope.command" + +local eq = assert.are.same + +describe("command_parser", function() + local test_parse = function(should, input, output) + it(should, function() + command.convert_user_opts(input) + eq(output, input) + end) + end + + -- Strings + test_parse("should handle cwd", { cwd = "string" }, { cwd = "string" }) + + -- Find commands + test_parse( + "should handle find_command 1", + { find_command = "rg,--ignore,--hidden,files" }, + { find_command = { "rg", "--ignore", "--hidden", "files" } } + ) + test_parse( + "should handle find_command 2", + { find_command = "fd,-t,f,-H" }, + { find_command = { "fd", "-t", "f", "-H" } } + ) + test_parse( + "should handle find_command 3", + { find_command = "fdfind,--type,f,--no-ignore" }, + { find_command = { "fdfind", "--type", "f", "--no-ignore" } } + ) + + -- Dictionaries/tables + test_parse( + "should handle layout_config viml 1", + { layout_config = "{'prompt_position':'top'}" }, + { layout_config = { prompt_position = "top" } } + ) + test_parse( + "should handle layout_config viml 2", + { layout_config = "#{prompt_position:'bottom'}" }, + { layout_config = { prompt_position = "bottom" } } + ) + test_parse( + "should handle layout_config viml 3", + { layout_config = "{'mirror':v:true}" }, + { layout_config = { mirror = true } } + ) + test_parse( + "should handle layout_config viml 4", + { layout_config = "#{mirror:v:true}" }, + { layout_config = { mirror = true } } + ) + test_parse( + "should handle layout_config lua 1", + { layout_config = "{prompt_position='bottom'}" }, + { layout_config = { prompt_position = "bottom" } } + ) + test_parse( + "should handle layout_config lua 2", + { layout_config = "{mirror=true}" }, + { layout_config = { mirror = true } } + ) + + -- Lists/tables + test_parse( + "should handle symbols commas list", + { symbols = "alpha,beta,gamma" }, + { symbols = { "alpha", "beta", "gamma" } } + ) + test_parse( + "should handle symbols viml list", + { symbols = "['alpha','beta','gamma']" }, + { symbols = { "alpha", "beta", "gamma" } } + ) + test_parse( + "should handle symbols lua list", + { symbols = "{'alpha','beta','gamma'}" }, + { symbols = { "alpha", "beta", "gamma" } } + ) + + -- Booleans + test_parse("should handle booleans 1", { hidden = "true" }, { hidden = true }) + test_parse("should handle booleans 2", { no_ignore = "false" }, { no_ignore = false }) + + -- Numbers + test_parse("should handle numbers 1", { depth = "2" }, { depth = 2 }) + test_parse("should handle numbers 2", { bufnr_width = "4" }, { bufnr_width = 4 }) + test_parse("should handle numbers 3", { severity = "27" }, { severity = 27 }) + + -- Multiple options + test_parse( + "should handle multiple options 1", + { layout_config = '{prompt_position="top"}', cwd = "/foobar", severity = "27" }, + { layout_config = { prompt_position = "top" }, cwd = "/foobar", severity = 27 } + ) + test_parse( + "should handle multiple options 2", + { symbols = "['alef','bet','gimel']", depth = "2", find_command = "rg,--ignore,files" }, + { symbols = { "alef", "bet", "gimel" }, depth = 2, find_command = { "rg", "--ignore", "files" } } + ) +end)