aboutsummaryrefslogtreecommitdiff
path: root/lua/cmake/commandline.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/cmake/commandline.lua')
-rw-r--r--lua/cmake/commandline.lua148
1 files changed, 148 insertions, 0 deletions
diff --git a/lua/cmake/commandline.lua b/lua/cmake/commandline.lua
new file mode 100644
index 0000000..55c671c
--- /dev/null
+++ b/lua/cmake/commandline.lua
@@ -0,0 +1,148 @@
+local project = require("cmake.project")
+
+local M = {}
+
+-- from https://github.com/akinsho/toggleterm.nvim/blob/main/lua/toggleterm/commandline.lua
+
+-- Get a valid base path for a user provided path
+-- and an optional search term
+---@param typed_path string
+---@return string|nil, string|nil
+local get_path_parts = function(typed_path)
+ if vim.fn.isdirectory(typed_path ~= "" and typed_path or ".") == 1 then
+ -- The string is a valid path, we just need to drop trailing slashes to
+ -- ease joining the base path with the suggestions
+ return typed_path:gsub("/$", ""), nil
+ elseif typed_path:find("/", 2) ~= nil then
+ -- Maybe the typed path is looking for a nested directory
+ -- we need to make sure it has at least one slash in it, and that is not
+ -- from a root path
+ local base_path = vim.fn.fnamemodify(typed_path, ":h")
+ local search_term = vim.fn.fnamemodify(typed_path, ":t")
+ if vim.fn.isdirectory(base_path) then
+ return base_path, search_term
+ end
+ end
+
+ return nil, nil
+end
+
+local complete_path = function(typed_path)
+ -- Read the typed path as the base for the directory search
+ local base_path, search_term = get_path_parts(typed_path or "")
+ local safe_path = base_path ~= "" and base_path or "."
+
+ local paths = vim.fn.readdir(safe_path, function(entry)
+ return vim.fn.isdirectory(safe_path .. "/" .. entry)
+ end)
+
+ if not u.str_is_empty(search_term) then
+ paths = vim.tbl_filter(function(path)
+ return path:match("^" .. search_term .. "*") ~= nil
+ end, paths)
+ end
+
+ return vim.tbl_map(function(path)
+ return u.concat_without_empty({ base_path, path }, "/")
+ end, paths)
+end
+
+local generate_options = {
+ fresh = true,
+}
+
+local complete_value = function(values, values_opts, match)
+ return function(typed_value)
+ typed_value = typed_value or ""
+ return vim.iter(values(values_opts))
+ :filter(function(value)
+ return not typed_value or #typed_value == 0 or value[match]:match("^" .. typed_value .. "*")
+ end)
+ :map(function(value)
+ return value[match]
+ end)
+ :totable()
+ end
+end
+
+local build_options = {
+ clean = true,
+ targets = complete_value(project.current_targets, {}, "name"),
+}
+
+local install_options = {
+ explain = true,
+ -- component = complete_value(project.current_components, {}, "name"),
+ prefix = complete_path,
+}
+
+---@param options table a dictionary of key to function
+---@return fun(lead: string, command: string, _: number):table
+local function complete(options)
+ ---@param lead string the leading portion of the argument currently being completed on
+ ---@param command string the entire command line
+ ---@param _ number the cursor position in it (byte index)
+ ---@return table
+ return function(lead, command, _)
+ local parts = vim.split(lead, "=")
+ local key = parts[1]
+ local value = parts[2]
+ if options[key] then
+ if type(options[key]) == "function" then
+ return vim.iter(options[key](value))
+ :map(function(opt)
+ return key .. "=" .. opt
+ end)
+ :totable()
+ else
+ return {}
+ end
+ else
+ return vim.iter(options)
+ :filter(function(option, _)
+ return option:match(" " .. option .. "=") == nil
+ end)
+ :map(function(option, option_value)
+ if type(option_value) == "boolean" and option_value then
+ return option
+ else
+ return option .. "="
+ end
+ end)
+ :totable()
+ end
+ end
+end
+
+---Take a users command arguments in format 'key1=value key2'
+---and parse this into a table of arguments
+---@see https://stackoverflow.com/a/27007701
+---@param args string
+---@return any
+function M.parse(args)
+ local result = {}
+ if args then
+ for _, part in ipairs(vim.split(args, " ")) do
+ local arg = vim.split(part, "=")
+ local key, value = arg[1], arg[2]
+ if not value then
+ result[key] = true
+ else
+ if key == "targets" then
+ result[key] = vim.split(value, ",")
+ else
+ result[key] = value
+ end
+ end
+ end
+ end
+ return result
+end
+
+M.cmake_generate_complete = complete(generate_options)
+
+M.cmake_build_complete = complete(build_options)
+
+M.cmake_install_complete = complete(install_options)
+
+return M