local utils = require("neo-tree.utils") local M = { FLAG = "", LIST = "", PATH = "", REF = "", } M.setup = function(all_source_names) local source_names = utils.table_copy(all_source_names) table.insert(source_names, "migrations") -- For lists, the first value is the default value. local arguments = { action = { type = M.LIST, values = { "close", "focus", "show", }, }, position = { type = M.LIST, values = { "left", "right", "top", "bottom", "float", "current", }, }, source = { type = M.LIST, values = source_names, }, dir = { type = M.PATH, stat_type = "directory" }, reveal_file = { type = M.PATH, stat_type = "file" }, git_base = { type = M.REF }, toggle = { type = M.FLAG }, reveal = { type = M.FLAG }, reveal_force_cwd = { type = M.FLAG }, } local arg_type_lookup = {} local list_args = {} local path_args = {} local ref_args = {} local flag_args = {} local reverse_lookup = {} for name, def in pairs(arguments) do arg_type_lookup[name] = def.type if def.type == M.LIST then table.insert(list_args, name) for _, vv in ipairs(def.values) do reverse_lookup[tostring(vv)] = name end elseif def.type == M.PATH then table.insert(path_args, name) elseif def.type == M.FLAG then table.insert(flag_args, name) reverse_lookup[name] = M.FLAG elseif def.type == M.REF then table.insert(ref_args, name) else error("Unknown type: " .. def.type) end end M.arguments = arguments M.list_args = list_args M.path_args = path_args M.ref_args = ref_args M.flag_args = flag_args M.arg_type_lookup = arg_type_lookup M.reverse_lookup = reverse_lookup end M.resolve_path = function(path, validate_type) local expanded = vim.fn.expand(path) local abs_path = vim.fn.fnamemodify(expanded, ":p") if validate_type then local stat = vim.loop.fs_stat(abs_path) if stat.type ~= validate_type then error("Invalid path: " .. path .. " is not a " .. validate_type) end end return abs_path end M.verify_git_ref = function(ref) local ok, _ = utils.execute_command("git rev-parse --verify " .. ref) return ok end local parse_arg = function(result, arg) if type(arg) == "string" then local eq = arg:find("=") if eq then local key = arg:sub(1, eq - 1) local value = arg:sub(eq + 1) local def = M.arguments[key] if not def.type then error("Invalid argument: " .. arg) end if def.type == M.PATH then result[key] = M.resolve_path(value, def.stat_type) elseif def.type == M.FLAG then if value == "true" then result[key] = true elseif value == "false" then result[key] = false else error("Invalid value for " .. key .. ": " .. value) end elseif def.type == M.REF then if not M.verify_git_ref(value) then error("Invalid value for " .. key .. ": " .. value) end result[key] = value else result[key] = value end else local value = arg local key = M.reverse_lookup[value] if key == nil then -- maybe it's a git ref if M.verify_git_ref(value) then result["git_base"] = value return end -- maybe it's a path local path = M.resolve_path(value) local stat = vim.loop.fs_stat(path) if stat then if stat.type == "directory" then result["dir"] = path elseif stat.type == "file" then result["reveal_file"] = path end else error("Invalid argument: " .. arg) end elseif key == M.FLAG then result[value] = true else result[key] = value end end end end M.parse = function(args, strict_checking) require("neo-tree").ensure_config() local result = {} if type(args) == "string" then args = utils.split(args, " ") end -- read args from user for _, arg in ipairs(args) do local success, err = pcall(parse_arg, result, arg) if strict_checking and not success then error(err) end end return result end return M