aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--lua/cmake/actions.lua315
-rw-r--r--lua/cmake/autocmds.lua72
-rw-r--r--lua/cmake/capabilities.lua70
-rw-r--r--lua/cmake/commandline.lua209
-rw-r--r--lua/cmake/commands.lua142
-rw-r--r--lua/cmake/config.lua106
-rw-r--r--lua/cmake/constants.lua4
-rw-r--r--lua/cmake/fileapi.lua148
-rw-r--r--lua/cmake/init.lua39
-rw-r--r--lua/cmake/lazy.lua16
-rw-r--r--lua/cmake/lyaml.lua980
-rw-r--r--lua/cmake/telescope/pickers.lua164
-rw-r--r--lua/cmake/terminal.lua169
-rw-r--r--lua/cmake/utils.lua156
-rw-r--r--lua/cmake/variants.lua252
16 files changed, 1421 insertions, 1422 deletions
diff --git a/README.md b/README.md
index a660a32..7ab7183 100644
--- a/README.md
+++ b/README.md
@@ -35,3 +35,4 @@ Since the plugin is asynchronous, you don't have to lazily load it. Loading time
and go to it's definitions, depentent target and other possible entities in any meaningful relations
- [ ] quickfix
+- [ ] Ability to keep one runner terminal per project or target
diff --git a/lua/cmake/actions.lua b/lua/cmake/actions.lua
index 230e1e3..b910a2c 100644
--- a/lua/cmake/actions.lua
+++ b/lua/cmake/actions.lua
@@ -10,42 +10,43 @@ local uv = vim.uv
local M = {}
local default_generate_exe_opts = {
- notify = {
- ok_message = "CMake generate finished",
- err_message = function(code)
- return "CMake generate failed with code " .. tostring(code)
- end,
- },
+ notify = {
+ ok_message = "CMake generate finished",
+ err_message = function(code)
+ return "CMake generate failed with code " .. tostring(code)
+ end,
+ },
}
local default_build_exe_opts = {
- notify = {
- ok_message = "CMake build finished",
- err_message = function(code)
- return "CMake build failed with code " .. tostring(code)
- end,
- },
+ notify = {
+ ok_message = "CMake build finished",
+ err_message = function(code)
+ return "CMake build failed with code " .. tostring(code)
+ end,
+ },
}
local _explain = function(command)
- vim.notify(
- table.concat({
- table.concat(
- vim.iter(command.env or {})
- :map(function(k, v)
- if v:find(" ") then
- return k .. '="' .. v .. '"'
- end
- return k .. "=" .. v
- end)
- :totable(),
- " "
- ),
- command.cmd,
- command.args,
- }, " "),
- vim.log.levels.INFO
- )
+ vim.notify(
+ table.concat({
+ table.concat(
+ vim
+ .iter(command.env or {})
+ :map(function(k, v)
+ if v:find(" ") then
+ return k .. '="' .. v .. '"'
+ end
+ return k .. "=" .. v
+ end)
+ :totable(),
+ " "
+ ),
+ command.cmd,
+ command.args,
+ }, " "),
+ vim.log.levels.INFO
+ )
end
--- Extends generate command by given options
@@ -53,9 +54,9 @@ end
---@param opts GenerateOpts
---@return table
local _extend_generate_command = function(command, opts)
- opts = opts or {}
- local new = vim.deepcopy(command)
- return new
+ opts = opts or {}
+ local new = vim.deepcopy(command)
+ return new
end
--- Extends build command by given options
@@ -63,41 +64,41 @@ end
---@param opts BuildOpts
---@return table
local _extend_build_command = function(command, opts)
- local new = vim.deepcopy(command)
- if opts.j then
- new.args = new.args .. " -j " .. tostring(opts.j)
- end
- if opts.clean then
- new.args = new.args .. " --clean-first"
- end
- if opts.target and #opts.target ~= 0 then
- new.args = new.args .. " --target " .. table.concat(opts.target, " ")
- end
- return new
+ local new = vim.deepcopy(command)
+ if opts.j then
+ new.args = new.args .. " -j " .. tostring(opts.j)
+ end
+ if opts.clean then
+ new.args = new.args .. " --clean-first"
+ end
+ if opts.target and #opts.target ~= 0 then
+ new.args = new.args .. " --target " .. table.concat(opts.target, " ")
+ end
+ return new
end
local _generate = function(option, opts)
- opts = opts or {}
- local main_path = function()
- pr.create_fileapi_query({}, function()
- vim.schedule(function()
- t.cmake_execute(_extend_generate_command(option.generate_command, opts), default_generate_exe_opts)
- end)
- end)
- end
- if opts.fresh then
- pr.clear_cache()
- end
- main_path()
+ opts = opts or {}
+ local main_path = function()
+ pr.create_fileapi_query({}, function()
+ vim.schedule(function()
+ t.cmake_execute(_extend_generate_command(option.generate_command, opts), default_generate_exe_opts)
+ end)
+ end)
+ end
+ if opts.fresh then
+ pr.clear_cache()
+ end
+ main_path()
end
local _for_current_generate_option = function(func)
- local idx = pr.current_generate_option_idx()
- if not idx then
- vim.notify("CMake: no configuration to generate", vim.log.levels.WARN)
- else
- func(pr.current_generate_option())
- end
+ local idx = pr.current_generate_option_idx()
+ if not idx then
+ vim.notify("CMake: no configuration to generate", vim.log.levels.WARN)
+ else
+ func(pr.current_generate_option())
+ end
end
---@class GenerateOpts
@@ -106,55 +107,55 @@ end
--- Generate project with current generate option
--- @param opts GenerateOpts
M.generate = function(opts)
- opts = opts or {}
- _for_current_generate_option(function(option)
- _generate(option, opts)
- end)
+ opts = opts or {}
+ _for_current_generate_option(function(option)
+ _generate(option, opts)
+ end)
end
--- Generate project with current generate option
--- @param opts GenerateOpts
M.generate_explain = function(opts)
- opts = opts or {}
- _for_current_generate_option(function(option)
- _explain(_extend_generate_command(option.generate_command, opts))
- end)
+ opts = opts or {}
+ _for_current_generate_option(function(option)
+ _explain(_extend_generate_command(option.generate_command, opts))
+ end)
end
--- Generate project with current generate option
--- @param opts table|nil
M.generate_select = function(opts)
- opts = opts or {}
- local items = pr.generate_options(opts)
- vim.ui.select(items, {
- prompt = "Select configuration to generate:",
- format_item = function(item)
- return table.concat(item.name, config.variants_display.short.sep)
- end,
- }, function(_, idx)
- if not idx then
- return
- end
- pr.set_current_generate_option(idx)
- end)
+ opts = opts or {}
+ local items = pr.generate_options(opts)
+ vim.ui.select(items, {
+ prompt = "Select configuration to generate:",
+ format_item = function(item)
+ return table.concat(item.name, config.variants_display.short.sep)
+ end,
+ }, function(_, idx)
+ if not idx then
+ return
+ end
+ pr.set_current_generate_option(idx)
+ end)
end
local _for_current_build_option = function(func)
- local idx = pr.current_build_option()
- if not idx then
- vim.notify("CMake: no build configuration to generate", vim.log.levels.WARN)
- else
- func(pr.current_build_option())
- end
+ local idx = pr.current_build_option()
+ if not idx then
+ vim.notify("CMake: no build configuration to generate", vim.log.levels.WARN)
+ else
+ func(pr.current_build_option())
+ end
end
local _build = function(option, opts)
- opts = opts or {}
- pr.create_fileapi_query({}, function()
- vim.schedule(function()
- t.cmake_execute(_extend_build_command(option.command, opts), default_build_exe_opts)
- end)
- end)
+ opts = opts or {}
+ pr.create_fileapi_query({}, function()
+ vim.schedule(function()
+ t.cmake_execute(_extend_build_command(option.command, opts), default_build_exe_opts)
+ end)
+ end)
end
---@class BuildOpts
@@ -165,44 +166,44 @@ end
--- Build project with current build option
--- @param opts BuildOpts
M.build = function(opts)
- opts = opts or {}
- _for_current_build_option(function(option)
- _build(option, opts)
- end)
+ opts = opts or {}
+ _for_current_build_option(function(option)
+ _build(option, opts)
+ end)
end
--- Build project with current build option
--- @param opts BuildOpts
M.build_explain = function(opts)
- opts = opts or {}
- _for_current_build_option(function(option)
- _explain(_extend_build_command(option.command, opts))
- end)
+ opts = opts or {}
+ _for_current_build_option(function(option)
+ _explain(_extend_build_command(option.command, opts))
+ end)
end
---Change current build option
---@param opts any|nil
M.build_select = function(opts)
- local items = pr.current_generate_option().build_options
- vim.ui.select(items, {
- prompt = "Select build option to generate:",
- format_item = function(item)
- return table.concat(item.name, config.variants_display.short.sep)
- end,
- }, function(_, idx)
- if not idx then
- return
- end
- pr.set_current_build_option(idx)
- end)
+ local items = pr.current_generate_option().build_options
+ vim.ui.select(items, {
+ prompt = "Select build option to generate:",
+ format_item = function(item)
+ return table.concat(item.name, config.variants_display.short.sep)
+ end,
+ }, function(_, idx)
+ if not idx then
+ return
+ end
+ pr.set_current_build_option(idx)
+ end)
end
local _run_target = function(opts)
- local command = {
- cmd = opts.path,
- cwd = pr.current_directory(),
- }
- t.target_execute(command)
+ local command = {
+ cmd = opts.path,
+ cwd = pr.current_directory(),
+ }
+ t.target_execute(command)
end
---@class RunTargetOpts
@@ -211,58 +212,58 @@ end
--- Run target
--- @param opts RunTargetOpts
M.run_target = function(opts)
- opts = opts or {}
- local _curr_exe_cmd = pr.current_executable_target()
- if not _curr_exe_cmd then
- M.run_target_select(opts)
- else
- _run_target({ path = _curr_exe_cmd.path })
- end
+ opts = opts or {}
+ local _curr_exe_cmd = pr.current_executable_target()
+ if not _curr_exe_cmd then
+ M.run_target_select(opts)
+ else
+ _run_target({ path = _curr_exe_cmd.path })
+ end
end
--- Select target to run
M.run_target_select = function(opts)
- opts = opts or {}
- opts.type = "EXECUTABLE"
- local items = pr.current_targets(opts)
- vim.ui.select(items, {
- prompt = "Select tagret to run:",
- format_item = function(item)
- return item.name
- end,
- }, function(_, idx)
- if not idx then
- return
- end
- pr.set_current_executable_target(idx)
- end)
+ opts = opts or {}
+ opts.type = "EXECUTABLE"
+ local items = pr.current_targets(opts)
+ vim.ui.select(items, {
+ prompt = "Select tagret to run:",
+ format_item = function(item)
+ return item.name
+ end,
+ }, function(_, idx)
+ if not idx then
+ return
+ end
+ pr.set_current_executable_target(idx)
+ end)
end
---Toggle CMake terminal window
M.toggle = function()
- t.cmake_toggle()
+ t.cmake_toggle()
end
---Edit `.cmake-variants.yaml` file
M.edit_variants = function()
- utils.file_exists(constants.variants_yaml_filename, function(variants_exists)
- if variants_exists then
- vim.schedule(function()
- vim.cmd(string.format("e %s", constants.variants_yaml_filename))
- end)
- else
- local default_yaml = require("cmake.lyaml").dump(config.variants)
- utils.write_file(constants.variants_yaml_filename, default_yaml, function()
- vim.schedule(function()
- vim.cmd(string.format("e %s", constants.variants_yaml_filename))
- end)
- end)
- end
- end)
+ utils.file_exists(constants.variants_yaml_filename, function(variants_exists)
+ if variants_exists then
+ vim.schedule(function()
+ vim.cmd(string.format("e %s", constants.variants_yaml_filename))
+ end)
+ else
+ local default_yaml = require("cmake.lyaml").dump(config.variants)
+ utils.write_file(constants.variants_yaml_filename, default_yaml, function()
+ vim.schedule(function()
+ vim.cmd(string.format("e %s", constants.variants_yaml_filename))
+ end)
+ end)
+ end
+ end)
end
M.reset_project = function(opts)
- require("cmake.project").setup(opts)
+ require("cmake.project").setup(opts)
end
return M
diff --git a/lua/cmake/autocmds.lua b/lua/cmake/autocmds.lua
index 5bbfbe8..a584b52 100644
--- a/lua/cmake/autocmds.lua
+++ b/lua/cmake/autocmds.lua
@@ -7,45 +7,45 @@ local autocmds = {}
local cmake_nvim_augroup = vim.api.nvim_create_augroup("CMake", {})
function autocmds.set_on_variants()
- vim.api.nvim_create_autocmd({ "BufWritePost" }, {
- group = cmake_nvim_augroup,
- pattern = constants.variants_yaml_filename,
- callback = function(args)
- actions.reset_project()
- end,
- desc = "Setup project after saving variants",
- })
+ vim.api.nvim_create_autocmd({ "BufWritePost" }, {
+ group = cmake_nvim_augroup,
+ pattern = constants.variants_yaml_filename,
+ callback = function(args)
+ actions.reset_project()
+ end,
+ desc = "Setup project after saving variants",
+ })
end
function autocmds.setup()
- if config.generate_after_save then
- vim.api.nvim_create_autocmd({ "BufWritePost" }, {
- group = cmake_nvim_augroup,
- pattern = constants.cmakelists,
- callback = function(args)
- actions.generate()
- end,
- desc = "Generate project after saving CMakeLists.txt",
- })
- end
- --NOTE: this autocmd was written only to handle very rare case when inside directory
- --without CMakeLists.txt neovim starts like `nvim CMakeLists.txt`. In this case initial
- --setup will not make the affect and to correctry process the file save, we need to create
- --this autocommand so it reinitializes the project if it has not been done before. IMHO this
- --is not the best way to do this. Also, if newly buffer associated with CMakeLists.txt will not
- --be saved and just closed, but user will continue to use nvim, CMake commands still will be
- --able while it sholdn't. Two options is give up or handle all this corner cases
- --
- -- if config.generate_after_save then
- -- vim.api.nvim_create_autocmd({ "BufEnter" }, {
- -- group = cmake_nvim_augroup,
- -- pattern = constants.cmakelists,
- -- callback = function(args)
- -- actions.reset_project({ first_time_only = true })
- -- end,
- -- desc = "Set up project on open CMakeLists.txt if not set before",
- -- })
- -- end
+ if config.generate_after_save then
+ vim.api.nvim_create_autocmd({ "BufWritePost" }, {
+ group = cmake_nvim_augroup,
+ pattern = constants.cmakelists,
+ callback = function(args)
+ actions.generate()
+ end,
+ desc = "Generate project after saving CMakeLists.txt",
+ })
+ end
+ --NOTE: this autocmd was written only to handle very rare case when inside directory
+ --without CMakeLists.txt neovim starts like `nvim CMakeLists.txt`. In this case initial
+ --setup will not make the affect and to correctry process the file save, we need to create
+ --this autocommand so it reinitializes the project if it has not been done before. IMHO this
+ --is not the best way to do this. Also, if newly buffer associated with CMakeLists.txt will not
+ --be saved and just closed, but user will continue to use nvim, CMake commands still will be
+ --able while it sholdn't. Two options is give up or handle all this corner cases
+ --
+ -- if config.generate_after_save then
+ -- vim.api.nvim_create_autocmd({ "BufEnter" }, {
+ -- group = cmake_nvim_augroup,
+ -- pattern = constants.cmakelists,
+ -- callback = function(args)
+ -- actions.reset_project({ first_time_only = true })
+ -- end,
+ -- desc = "Set up project on open CMakeLists.txt if not set before",
+ -- })
+ -- end
end
return autocmds
diff --git a/lua/cmake/capabilities.lua b/lua/cmake/capabilities.lua
index 0b76fc0..5cc3f21 100644
--- a/lua/cmake/capabilities.lua
+++ b/lua/cmake/capabilities.lua
@@ -1,56 +1,56 @@
local config = require("cmake.config")
local multiconfig_generators = {
- "Ninja Multi-Config",
- "Xcode",
- "Visual Studio 12 2013",
- "Visual Studio 14 2015",
- "Visual Studio 15 2017",
- "Visual Studio 16 2019",
- "Visual Studio 17 2022",
- "Green Hills MULTI",
+ "Ninja Multi-Config",
+ "Xcode",
+ "Visual Studio 12 2013",
+ "Visual Studio 14 2015",
+ "Visual Studio 15 2017",
+ "Visual Studio 16 2019",
+ "Visual Studio 17 2022",
+ "Green Hills MULTI",
}
local Capabilities = {
- json = nil,
+ json = nil,
}
function Capabilities.generators()
- local ret = {}
- if not Capabilities then
- return ret
- end
- for k, v in pairs(Capabilities.json.generators) do
- table.insert(ret, v.name)
- end
- return vim.fn.reverse(ret)
+ local ret = {}
+ if not Capabilities then
+ return ret
+ end
+ for k, v in pairs(Capabilities.json.generators) do
+ table.insert(ret, v.name)
+ end
+ return vim.fn.reverse(ret)
end
function Capabilities.is_multiconfig_generator(generator)
- -- if generator is nil, assume is is not multiconifg
- if not generator then
- return
- end
- return vim.tbl_contains(multiconfig_generators, generator)
+ -- if generator is nil, assume is is not multiconifg
+ if not generator then
+ return
+ end
+ return vim.tbl_contains(multiconfig_generators, generator)
end
function Capabilities.has_fileapi()
- return vim.tbl_get(Capabilities.json, "fileApi") ~= nil
+ return vim.tbl_get(Capabilities.json, "fileApi") ~= nil
end
Capabilities.setup = function(callback)
- vim.schedule(function()
- vim.system({ config.cmake.cmake_path, "-E", "capabilities" }, { text = true }, function(obj)
- if obj.code == 0 then
- Capabilities.json = vim.json.decode(obj.stdout)
- if type(callback) == "function" then
- callback()
- end
- else
- vim.notify("error " .. tostring(obj.code) .. ". 'cmake -E capabilities'", vim.log.levels.ERROR)
- end
- end)
- end)
+ vim.schedule(function()
+ vim.system({ config.cmake.cmake_path, "-E", "capabilities" }, { text = true }, function(obj)
+ if obj.code == 0 then
+ Capabilities.json = vim.json.decode(obj.stdout)
+ if type(callback) == "function" then
+ callback()
+ end
+ else
+ vim.notify("error " .. tostring(obj.code) .. ". 'cmake -E capabilities'", vim.log.levels.ERROR)
+ end
+ end)
+ end)
end
return Capabilities
diff --git a/lua/cmake/commandline.lua b/lua/cmake/commandline.lua
index c3d0ef1..06577d5 100644
--- a/lua/cmake/commandline.lua
+++ b/lua/cmake/commandline.lua
@@ -9,112 +9,115 @@ local M = {}
---@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
+ 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)
+ -- 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,
+ 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
+ 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,
- j = function()
- return {}
- end,
- target = complete_value(project.current_targets, {}, "name"),
+ clean = true,
+ j = function()
+ return {}
+ end,
+ target = complete_value(project.current_targets, {}, "name"),
}
local install_options = {
- explain = true,
- -- component = complete_value(project.current_components, {}, "name"),
- prefix = complete_path,
+ 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
+ ---@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'
@@ -123,23 +126,23 @@ end
---@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 == "target" then
- result[key] = vim.split(value, ",")
- else
- result[key] = value
- end
- end
- end
- end
- return result
+ 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 == "target" then
+ result[key] = vim.split(value, ",")
+ else
+ result[key] = value
+ end
+ end
+ end
+ end
+ return result
end
M.cmake_generate_complete = complete(generate_options)
diff --git a/lua/cmake/commands.lua b/lua/cmake/commands.lua
index 03b20a3..8275fc8 100644
--- a/lua/cmake/commands.lua
+++ b/lua/cmake/commands.lua
@@ -9,80 +9,80 @@ local cmd = vim.api.nvim_create_user_command
local prefix = "CMake"
local commands = {
- ["Generate"] = {
- command = actions.generate,
- parse = true,
- default_opts = { fresh = false },
- cmd_opts = {
- desc = "Generate with last configuration",
- nargs = "*",
- complete = commandline.cmake_generate_complete,
- },
- },
- ["GenerateExplain"] = {
- command = actions.generate_explain,
- parse = true,
- default_opts = { fresh = false },
- cmd_opts = {
- desc = "Explain current generate command",
- nargs = "*",
- complete = commandline.cmake_generate_complete,
- },
- },
- ["GenerateSelect"] = {
- command = actions.generate_select,
- cmd_opts = { desc = "Select generate configuration" },
- },
- ["Build"] = {
- command = actions.build,
- parse = true,
- cmd_opts = {
- desc = "Build with last configuration",
- nargs = "*",
- complete = commandline.cmake_build_complete,
- },
- },
- ["BuildExplain"] = {
- command = actions.build_explain,
- parse = true,
- cmd_opts = {
- desc = "Explain current build command",
- nargs = "*",
- complete = commandline.cmake_build_complete,
- },
- },
- ["BuildSelect"] = {
- command = actions.build_select,
- cmd_opts = { desc = "Select build configuration" },
- },
- ["Run"] = {
- command = actions.run_target,
- cmd_opts = { desc = "Run current executable target", nargs = "*" },
- },
- ["RunSelect"] = {
- command = actions.run_target_select,
- cmd_opts = { desc = "Select executable target" },
- },
- ["Toggle"] = {
- command = actions.toggle,
- cmd_opts = { desc = "Toggle cmake terminal" },
- },
- ["EditVariants"] = {
- command = actions.edit_variants,
- cmd_opts = { desc = "Edit variants" },
- },
+ ["Generate"] = {
+ command = actions.generate,
+ parse = true,
+ default_opts = { fresh = false },
+ cmd_opts = {
+ desc = "Generate with last configuration",
+ nargs = "*",
+ complete = commandline.cmake_generate_complete,
+ },
+ },
+ ["GenerateExplain"] = {
+ command = actions.generate_explain,
+ parse = true,
+ default_opts = { fresh = false },
+ cmd_opts = {
+ desc = "Explain current generate command",
+ nargs = "*",
+ complete = commandline.cmake_generate_complete,
+ },
+ },
+ ["GenerateSelect"] = {
+ command = actions.generate_select,
+ cmd_opts = { desc = "Select generate configuration" },
+ },
+ ["Build"] = {
+ command = actions.build,
+ parse = true,
+ cmd_opts = {
+ desc = "Build with last configuration",
+ nargs = "*",
+ complete = commandline.cmake_build_complete,
+ },
+ },
+ ["BuildExplain"] = {
+ command = actions.build_explain,
+ parse = true,
+ cmd_opts = {
+ desc = "Explain current build command",
+ nargs = "*",
+ complete = commandline.cmake_build_complete,
+ },
+ },
+ ["BuildSelect"] = {
+ command = actions.build_select,
+ cmd_opts = { desc = "Select build configuration" },
+ },
+ ["Run"] = {
+ command = actions.run_target,
+ cmd_opts = { desc = "Run current executable target", nargs = "*" },
+ },
+ ["RunSelect"] = {
+ command = actions.run_target_select,
+ cmd_opts = { desc = "Select executable target" },
+ },
+ ["Toggle"] = {
+ command = actions.toggle,
+ cmd_opts = { desc = "Toggle cmake terminal" },
+ },
+ ["EditVariants"] = {
+ command = actions.edit_variants,
+ cmd_opts = { desc = "Edit variants" },
+ },
}
M.register_commands = function()
- for k, v in pairs(commands) do
- cmd(prefix .. k, function(opts)
- local action_opts = v.default_opts or {}
- if v.parse then
- action_opts = vim.tbl_deep_extend("keep", commandline.parse(opts.args) or {}, action_opts)
- end
- v.command(action_opts)
- end, v.cmd_opts)
- end
+ for k, v in pairs(commands) do
+ cmd(prefix .. k, function(opts)
+ local action_opts = v.default_opts or {}
+ if v.parse then
+ action_opts = vim.tbl_deep_extend("keep", commandline.parse(opts.args) or {}, action_opts)
+ end
+ v.command(action_opts)
+ end, v.cmd_opts)
+ end
end
return M
diff --git a/lua/cmake/config.lua b/lua/cmake/config.lua
index 6ac5856..b4b2bf7 100644
--- a/lua/cmake/config.lua
+++ b/lua/cmake/config.lua
@@ -51,55 +51,55 @@
---@type CMakeConfig
local default_config = {
- cmake = {
- cmake_path = "cmake",
- ctest_path = "ctest",
- cpack_path = "cpack",
- environment = {},
- configure_environment = {},
- build_directory = "${workspaceFolder}/build-${buildType}",
- build_environment = {},
- build_args = {},
- build_tool_args = {},
- generator = nil,
- parallel_jobs = nil,
- },
- variants = {
- buildType = {
- default = "debug",
- description = "Build type",
- choices = {
- debug = { short = "Debug", buildType = "Debug" },
- release = { short = "Release", buildType = "Release" },
- relWithDebInfo = { short = "RelWithDebInfo", buildType = "RelWithDebInfo" },
- minSizeRel = { short = "MinSizeRel", buildType = "MinSizeRel" },
- },
- },
- },
- save_before_build = true,
- generate_after_save = true,
- cmake_terminal = {
- split = "below",
- size = 15,
- close_on_exit = "success",
- open_on_start = true,
- clear_env = false,
- enter = false,
- },
- target_terminal = {
- split = "below",
- size = 15,
- enter = true,
- immediately = true,
- },
- notification = {
- after = "success",
- },
- variants_display = {
- short = { sep = " × ", show = true },
- long = { sep = " ❄ ", show = false },
- },
- keybinds = {},
+ cmake = {
+ cmake_path = "cmake",
+ ctest_path = "ctest",
+ cpack_path = "cpack",
+ environment = {},
+ configure_environment = {},
+ build_directory = "${workspaceFolder}/build-${buildType}",
+ build_environment = {},
+ build_args = {},
+ build_tool_args = {},
+ generator = nil,
+ parallel_jobs = nil,
+ },
+ variants = {
+ buildType = {
+ default = "debug",
+ description = "Build type",
+ choices = {
+ debug = { short = "Debug", buildType = "Debug" },
+ release = { short = "Release", buildType = "Release" },
+ relWithDebInfo = { short = "RelWithDebInfo", buildType = "RelWithDebInfo" },
+ minSizeRel = { short = "MinSizeRel", buildType = "MinSizeRel" },
+ },
+ },
+ },
+ save_before_build = true,
+ generate_after_save = true,
+ cmake_terminal = {
+ split = "below",
+ size = 15,
+ close_on_exit = "success",
+ open_on_start = true,
+ clear_env = false,
+ enter = false,
+ },
+ target_terminal = {
+ split = "below",
+ size = 15,
+ enter = true,
+ immediately = true,
+ },
+ notification = {
+ after = "success",
+ },
+ variants_display = {
+ short = { sep = " × ", show = true },
+ long = { sep = " ❄ ", show = false },
+ },
+ keybinds = {},
}
local M = vim.deepcopy(default_config)
@@ -107,11 +107,11 @@ local M = vim.deepcopy(default_config)
---Setup configs
---@param opts CMakeConfig
M.setup = function(opts)
- local newconf = vim.tbl_deep_extend("force", default_config, opts or {})
+ local newconf = vim.tbl_deep_extend("force", default_config, opts or {})
- for k, v in pairs(newconf) do
- M[k] = v
- end
+ for k, v in pairs(newconf) do
+ M[k] = v
+ end
end
return M
diff --git a/lua/cmake/constants.lua b/lua/cmake/constants.lua
index 95f15b3..5fb836e 100644
--- a/lua/cmake/constants.lua
+++ b/lua/cmake/constants.lua
@@ -1,4 +1,4 @@
return {
- variants_yaml_filename = "cmake-variants.yaml",
- cmakelists = "CMakeLists.txt",
+ variants_yaml_filename = "cmake-variants.yaml",
+ cmakelists = "CMakeLists.txt",
}
diff --git a/lua/cmake/fileapi.lua b/lua/cmake/fileapi.lua
index 612fd59..70e19c8 100644
--- a/lua/cmake/fileapi.lua
+++ b/lua/cmake/fileapi.lua
@@ -18,89 +18,89 @@ local FileApi = {}
---@field path string|nil Path to executable associated with target
function FileApi.create(path, callback)
- local query = vim.fs.joinpath(path, unpack(query_path_suffix))
- utils.file_exists(query, function(exists)
- if not exists then
- if capabilities.json.fileApi then
- vim.schedule(function()
- vim.fn.mkdir(vim.fs.dirname(query), "p")
- utils.write_file(query, vim.json.encode(capabilities.json.fileApi), callback)
- end)
- else
- vim.notify("Bad fileApi ", vim.log.levels.ERROR)
- end
- else
- callback()
- end
- end)
+ local query = vim.fs.joinpath(path, unpack(query_path_suffix))
+ utils.file_exists(query, function(exists)
+ if not exists then
+ if capabilities.json.fileApi then
+ vim.schedule(function()
+ vim.fn.mkdir(vim.fs.dirname(query), "p")
+ utils.write_file(query, vim.json.encode(capabilities.json.fileApi), callback)
+ end)
+ else
+ vim.notify("Bad fileApi ", vim.log.levels.ERROR)
+ end
+ else
+ callback()
+ end
+ end)
end
function FileApi.read_reply(path, callback)
- local reply_dir = vim.fs.joinpath(path, unpack(reply_dir_suffix))
- utils.file_exists(reply_dir, function(exists)
- if not exists then
- return
- end
- local ret = { targets = {} }
- --TODO: replace with uv scandir
- scan.scan_dir_async(reply_dir, {
- search_pattern = "index*",
- on_exit = function(results)
- if #results == 0 then
- return
- end
- utils.read_file(results[1], function(index_data)
- local index = vim.json.decode(index_data)
- for _, object in ipairs(index.objects) do
- if object.kind == "codemodel" then
- utils.read_file(vim.fs.joinpath(reply_dir, object.jsonFile), function(codemodel_data)
- local codemodel = vim.json.decode(codemodel_data)
- for _, target in ipairs(codemodel.configurations[1].targets) do
- local work = vim.uv.new_work(utils.read_file_sync, function(target_data)
- local target_json = vim.json.decode(target_data)
- ---@type CMakeTarget
- local _target = {
- id = target_json.id,
- name = target_json.name,
- type = target_json.type,
- path = nil,
- }
- if target_json.artifacts then
- --NOTE: add_library(<name> OBJECT ...) could contain more than ohe object in artifacts
- -- so maybe in future it will be useful to handle not only first one. Current behaviour
- -- aims to get path for only EXECUTABLE targets
- _target.path = target_json.artifacts[1].path
- end
- callback(_target)
- end)
- vim.uv.queue_work(work, vim.fs.joinpath(reply_dir, target.jsonFile))
- end
- end)
- end
- end
- end)
- end,
- })
- return ret
- end)
+ local reply_dir = vim.fs.joinpath(path, unpack(reply_dir_suffix))
+ utils.file_exists(reply_dir, function(exists)
+ if not exists then
+ return
+ end
+ local ret = { targets = {} }
+ --TODO: replace with uv scandir
+ scan.scan_dir_async(reply_dir, {
+ search_pattern = "index*",
+ on_exit = function(results)
+ if #results == 0 then
+ return
+ end
+ utils.read_file(results[1], function(index_data)
+ local index = vim.json.decode(index_data)
+ for _, object in ipairs(index.objects) do
+ if object.kind == "codemodel" then
+ utils.read_file(vim.fs.joinpath(reply_dir, object.jsonFile), function(codemodel_data)
+ local codemodel = vim.json.decode(codemodel_data)
+ for _, target in ipairs(codemodel.configurations[1].targets) do
+ local work = vim.uv.new_work(utils.read_file_sync, function(target_data)
+ local target_json = vim.json.decode(target_data)
+ ---@type CMakeTarget
+ local _target = {
+ id = target_json.id,
+ name = target_json.name,
+ type = target_json.type,
+ path = nil,
+ }
+ if target_json.artifacts then
+ --NOTE: add_library(<name> OBJECT ...) could contain more than ohe object in artifacts
+ -- so maybe in future it will be useful to handle not only first one. Current behaviour
+ -- aims to get path for only EXECUTABLE targets
+ _target.path = target_json.artifacts[1].path
+ end
+ callback(_target)
+ end)
+ vim.uv.queue_work(work, vim.fs.joinpath(reply_dir, target.jsonFile))
+ end
+ end)
+ end
+ end
+ end)
+ end,
+ })
+ return ret
+ end)
end
function FileApi.query_exists(path, callback)
- utils.file_exists(vim.fs.joinpath(path, unpack(query_path_suffix)), function(query_exists)
- callback(query_exists)
- end)
+ utils.file_exists(vim.fs.joinpath(path, unpack(query_path_suffix)), function(query_exists)
+ callback(query_exists)
+ end)
end
function FileApi.exists(path, callback)
- FileApi.query_exists(path, function(query_exists)
- if not query_exists then
- callback(false)
- else
- utils.file_exists(vim.fs.joinpath(path, unpack(reply_dir_suffix)), function(reply_exists)
- callback(reply_exists)
- end)
- end
- end)
+ FileApi.query_exists(path, function(query_exists)
+ if not query_exists then
+ callback(false)
+ else
+ utils.file_exists(vim.fs.joinpath(path, unpack(reply_dir_suffix)), function(reply_exists)
+ callback(reply_exists)
+ end)
+ end
+ end)
end
return FileApi
diff --git a/lua/cmake/init.lua b/lua/cmake/init.lua
index 6d7843c..5cff2dc 100644
--- a/lua/cmake/init.lua
+++ b/lua/cmake/init.lua
@@ -9,27 +9,24 @@ local uv = vim.uv
local M = {}
function M.setup(opts)
- opts = opts or {}
- config.setup(opts)
- if vim.fn.executable(config.cmake.cmake_path) then
- autocmds.setup()
- utils.file_exists(vim.fs.joinpath(uv.cwd(), constants.cmakelists), function(cmake_lists_exists)
- if cmake_lists_exists then
- --TODO: init autocommands needs to be related with project setup
- vim.schedule(function()
- autocmds.set_on_variants()
- commands.register_commands()
- end)
- require("cmake.project").setup()
- else
- end
- end)
- else
- vim.notify(
- "CMake: " .. config.cmake.cmake_path .. " is not executable. Plugin is unavailable",
- vim.log.levels.WARN
- )
- end
+ opts = opts or {}
+ config.setup(opts)
+ if vim.fn.executable(config.cmake.cmake_path) then
+ autocmds.setup()
+ utils.file_exists(vim.fs.joinpath(uv.cwd(), constants.cmakelists), function(cmake_lists_exists)
+ if cmake_lists_exists then
+ --TODO: init autocommands needs to be related with project setup
+ vim.schedule(function()
+ autocmds.set_on_variants()
+ commands.register_commands()
+ end)
+ require("cmake.project").setup()
+ else
+ end
+ end)
+ else
+ vim.notify("CMake: " .. config.cmake.cmake_path .. " is not executable. Plugin is unavailable", vim.log.levels.WARN)
+ end
end
return M
diff --git a/lua/cmake/lazy.lua b/lua/cmake/lazy.lua
index 7669dcd..c9b4a2f 100644
--- a/lua/cmake/lazy.lua
+++ b/lua/cmake/lazy.lua
@@ -7,15 +7,15 @@ local lazy = {}
---@param require_path string
---@return table
lazy.require = function(require_path)
- return setmetatable({}, {
- __index = function(_, key)
- return require(require_path)[key]
- end,
+ return setmetatable({}, {
+ __index = function(_, key)
+ return require(require_path)[key]
+ end,
- __newindex = function(_, key, value)
- require(require_path)[key] = value
- end,
- })
+ __newindex = function(_, key, value)
+ require(require_path)[key] = value
+ end,
+ })
end
return lazy
diff --git a/lua/cmake/lyaml.lua b/lua/cmake/lyaml.lua
index 3a17cc1..cf558c5 100644
--- a/lua/cmake/lyaml.lua
+++ b/lua/cmake/lyaml.lua
@@ -18,478 +18,478 @@
local table_print_value
table_print_value = function(value, indent, done)
- indent = indent or 0
- done = done or {}
- if type(value) == "table" then
- -- done[value] = true
-
- local rep = "\n"
- for key, val in pairs(value) do
- local keyRep
- if type(key) == "number" then
- keyRep = "-"
- else
- keyRep = string.format("%s:", tostring(key))
- end
- local child_indent = indent + 2
- rep = rep
- .. string
- .format("%s%s %s\n", string.rep(" ", indent), keyRep, table_print_value(val, child_indent, done))
- :gsub("\n\n", "\n")
- end
-
- -- rep = rep .. string.rep(" ", indent) -- indent it
-
- -- done[value] = false
- return rep
- elseif type(value) == "string" then
- return string.format("%q", value)
- else
- return tostring(value)
- end
+ indent = indent or 0
+ done = done or {}
+ if type(value) == "table" then
+ -- done[value] = true
+
+ local rep = "\n"
+ for key, val in pairs(value) do
+ local keyRep
+ if type(key) == "number" then
+ keyRep = "-"
+ else
+ keyRep = string.format("%s:", tostring(key))
+ end
+ local child_indent = indent + 2
+ rep = rep
+ .. string
+ .format("%s%s %s\n", string.rep(" ", indent), keyRep, table_print_value(val, child_indent, done))
+ :gsub("\n\n", "\n")
+ end
+
+ -- rep = rep .. string.rep(" ", indent) -- indent it
+
+ -- done[value] = false
+ return rep
+ elseif type(value) == "string" then
+ return string.format("%q", value)
+ else
+ return tostring(value)
+ end
end
local table_print = function(tt)
- return vim.trim(table_print_value(tt))
+ return vim.trim(table_print_value(tt))
end
local table_clone = function(t)
- local clone = {}
- for k, v in pairs(t) do
- clone[k] = v
- end
- return clone
+ local clone = {}
+ for k, v in pairs(t) do
+ clone[k] = v
+ end
+ return clone
end
local string_trim = function(s, what)
- what = what or " "
- return s:gsub("^[" .. what .. "]*(.-)[" .. what .. "]*$", "%1")
+ what = what or " "
+ return s:gsub("^[" .. what .. "]*(.-)[" .. what .. "]*$", "%1")
end
local push = function(stack, item)
- stack[#stack + 1] = item
+ stack[#stack + 1] = item
end
local pop = function(stack)
- local item = stack[#stack]
- stack[#stack] = nil
- return item
+ local item = stack[#stack]
+ stack[#stack] = nil
+ return item
end
local context = function(str)
- if type(str) ~= "string" then
- return ""
- end
+ if type(str) ~= "string" then
+ return ""
+ end
- str = str:sub(0, 25):gsub("\n", "\\n"):gsub('"', '\\"')
- return ', near "' .. str .. '"'
+ str = str:sub(0, 25):gsub("\n", "\\n"):gsub('"', '\\"')
+ return ', near "' .. str .. '"'
end
local Parser = {}
function Parser.new(self, tokens)
- self.tokens = tokens
- self.parse_stack = {}
- self.refs = {}
- self.current = 0
- return self
+ self.tokens = tokens
+ self.parse_stack = {}
+ self.refs = {}
+ self.current = 0
+ return self
end
local exports = { version = "1.2" }
local word = function(w)
- return "^(" .. w .. ")([%s$%c])"
+ return "^(" .. w .. ")([%s$%c])"
end
local tokens = {
- { "comment", "^#[^\n]*" },
- { "indent", "^\n( *)" },
- { "space", "^ +" },
- {
- "true",
- word("enabled"),
- const = true,
- value = true,
- },
- {
- "true",
- word("true"),
- const = true,
- value = true,
- },
- {
- "true",
- word("yes"),
- const = true,
- value = true,
- },
- {
- "true",
- word("on"),
- const = true,
- value = true,
- },
- {
- "false",
- word("disabled"),
- const = true,
- value = false,
- },
- {
- "false",
- word("false"),
- const = true,
- value = false,
- },
- {
- "false",
- word("no"),
- const = true,
- value = false,
- },
- {
- "false",
- word("off"),
- const = true,
- value = false,
- },
- {
- "null",
- word("null"),
- const = true,
- value = nil,
- },
- {
- "null",
- word("Null"),
- const = true,
- value = nil,
- },
- {
- "null",
- word("NULL"),
- const = true,
- value = nil,
- },
- {
- "null",
- word("~"),
- const = true,
- value = nil,
- },
- { "id", '^"([^"]-)" *(:[%s%c])' },
- { "id", "^'([^']-)' *(:[%s%c])" },
- { "string", '^"([^"]-)"', force_text = true },
- { "string", "^'([^']-)'", force_text = true },
- { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d):(%d%d)%s+(%-?%d%d?):(%d%d)" },
- { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d):(%d%d)%s+(%-?%d%d?)" },
- { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d):(%d%d)" },
- { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d)" },
- { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?)" },
- { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)" },
- { "doc", "^%-%-%-[^%c]*" },
- { ",", "^," },
- { "string", "^%b{} *[^,%c]+", noinline = true },
- { "{", "^{" },
- { "}", "^}" },
- { "string", "^%b[] *[^,%c]+", noinline = true },
- { "[", "^%[" },
- { "]", "^%]" },
- { "-", "^%-", noinline = true },
- { ":", "^:" },
- { "pipe", "^(|)(%d*[+%-]?)", sep = "\n" },
- { "pipe", "^(>)(%d*[+%-]?)", sep = " " },
- { "id", "^([%w][%w %-_]*)(:[%s%c])" },
- { "string", "^[^%c]+", noinline = true },
- { "string", "^[^,%]}%c ]+" },
+ { "comment", "^#[^\n]*" },
+ { "indent", "^\n( *)" },
+ { "space", "^ +" },
+ {
+ "true",
+ word("enabled"),
+ const = true,
+ value = true,
+ },
+ {
+ "true",
+ word("true"),
+ const = true,
+ value = true,
+ },
+ {
+ "true",
+ word("yes"),
+ const = true,
+ value = true,
+ },
+ {
+ "true",
+ word("on"),
+ const = true,
+ value = true,
+ },
+ {
+ "false",
+ word("disabled"),
+ const = true,
+ value = false,
+ },
+ {
+ "false",
+ word("false"),
+ const = true,
+ value = false,
+ },
+ {
+ "false",
+ word("no"),
+ const = true,
+ value = false,
+ },
+ {
+ "false",
+ word("off"),
+ const = true,
+ value = false,
+ },
+ {
+ "null",
+ word("null"),
+ const = true,
+ value = nil,
+ },
+ {
+ "null",
+ word("Null"),
+ const = true,
+ value = nil,
+ },
+ {
+ "null",
+ word("NULL"),
+ const = true,
+ value = nil,
+ },
+ {
+ "null",
+ word("~"),
+ const = true,
+ value = nil,
+ },
+ { "id", '^"([^"]-)" *(:[%s%c])' },
+ { "id", "^'([^']-)' *(:[%s%c])" },
+ { "string", '^"([^"]-)"', force_text = true },
+ { "string", "^'([^']-)'", force_text = true },
+ { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d):(%d%d)%s+(%-?%d%d?):(%d%d)" },
+ { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d):(%d%d)%s+(%-?%d%d?)" },
+ { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d):(%d%d)" },
+ { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?):(%d%d)" },
+ { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)%s+(%d%d?)" },
+ { "timestamp", "^(%d%d%d%d)-(%d%d?)-(%d%d?)" },
+ { "doc", "^%-%-%-[^%c]*" },
+ { ",", "^," },
+ { "string", "^%b{} *[^,%c]+", noinline = true },
+ { "{", "^{" },
+ { "}", "^}" },
+ { "string", "^%b[] *[^,%c]+", noinline = true },
+ { "[", "^%[" },
+ { "]", "^%]" },
+ { "-", "^%-", noinline = true },
+ { ":", "^:" },
+ { "pipe", "^(|)(%d*[+%-]?)", sep = "\n" },
+ { "pipe", "^(>)(%d*[+%-]?)", sep = " " },
+ { "id", "^([%w][%w %-_]*)(:[%s%c])" },
+ { "string", "^[^%c]+", noinline = true },
+ { "string", "^[^,%]}%c ]+" },
}
exports.tokenize = function(str)
- local token
- local row = 0
- local ignore
- local indents = 0
- local lastIndents
- local stack = {}
- local indentAmount = 0
- local inline = false
- str = str:gsub("\r\n", "\010")
-
- while #str > 0 do
- for i in ipairs(tokens) do
- local captures = {}
- if not inline or tokens[i].noinline == nil then
- captures = { str:match(tokens[i][2]) }
- end
-
- if #captures > 0 then
- captures.input = str:sub(0, 25)
- token = table_clone(tokens[i])
- token[2] = captures
- local str2 = str:gsub(tokens[i][2], "", 1)
- token.raw = str:sub(1, #str - #str2)
- str = str2
-
- if token[1] == "{" or token[1] == "[" then
- inline = true
- elseif token.const then
- -- Since word pattern contains last char we're re-adding it
- str = token[2][2] .. str
- token.raw = token.raw:sub(1, #token.raw - #token[2][2])
- elseif token[1] == "id" then
- -- Since id pattern contains last semi-colon we're re-adding it
- str = token[2][2] .. str
- token.raw = token.raw:sub(1, #token.raw - #token[2][2])
- -- Trim
- token[2][1] = string_trim(token[2][1])
- elseif token[1] == "string" then
- -- Finding numbers
- local snip = token[2][1]
- if not token.force_text then
- if snip:match("^(-?%d+%.%d+)$") or snip:match("^(-?%d+)$") then
- token[1] = "number"
- end
- end
- elseif token[1] == "comment" then
- ignore = true
- elseif token[1] == "indent" then
- row = row + 1
- inline = false
- lastIndents = indents
- if indentAmount == 0 then
- indentAmount = #token[2][1]
- end
-
- if indentAmount ~= 0 then
- indents = (#token[2][1] / indentAmount)
- else
- indents = 0
- end
-
- if indents == lastIndents then
- ignore = true
- elseif indents > lastIndents + 2 then
- error(
- "SyntaxError: invalid indentation, got "
- .. tostring(indents)
- .. " instead of "
- .. tostring(lastIndents)
- .. context(token[2].input)
- )
- elseif indents > lastIndents + 1 then
- push(stack, token)
- elseif indents < lastIndents then
- local input = token[2].input
- token = { "dedent", { "", input = "" } }
- token.input = input
- while lastIndents > indents + 1 do
- lastIndents = lastIndents - 1
- push(stack, token)
- end
- end
- end -- if token[1] == XXX
- token.row = row
- break
- end -- if #captures > 0
- end
-
- if not ignore then
- if token then
- push(stack, token)
- token = nil
- else
- error("SyntaxError " .. context(str))
- end
- end
-
- ignore = false
- end
-
- return stack
+ local token
+ local row = 0
+ local ignore
+ local indents = 0
+ local lastIndents
+ local stack = {}
+ local indentAmount = 0
+ local inline = false
+ str = str:gsub("\r\n", "\010")
+
+ while #str > 0 do
+ for i in ipairs(tokens) do
+ local captures = {}
+ if not inline or tokens[i].noinline == nil then
+ captures = { str:match(tokens[i][2]) }
+ end
+
+ if #captures > 0 then
+ captures.input = str:sub(0, 25)
+ token = table_clone(tokens[i])
+ token[2] = captures
+ local str2 = str:gsub(tokens[i][2], "", 1)
+ token.raw = str:sub(1, #str - #str2)
+ str = str2
+
+ if token[1] == "{" or token[1] == "[" then
+ inline = true
+ elseif token.const then
+ -- Since word pattern contains last char we're re-adding it
+ str = token[2][2] .. str
+ token.raw = token.raw:sub(1, #token.raw - #token[2][2])
+ elseif token[1] == "id" then
+ -- Since id pattern contains last semi-colon we're re-adding it
+ str = token[2][2] .. str
+ token.raw = token.raw:sub(1, #token.raw - #token[2][2])
+ -- Trim
+ token[2][1] = string_trim(token[2][1])
+ elseif token[1] == "string" then
+ -- Finding numbers
+ local snip = token[2][1]
+ if not token.force_text then
+ if snip:match("^(-?%d+%.%d+)$") or snip:match("^(-?%d+)$") then
+ token[1] = "number"
+ end
+ end
+ elseif token[1] == "comment" then
+ ignore = true
+ elseif token[1] == "indent" then
+ row = row + 1
+ inline = false
+ lastIndents = indents
+ if indentAmount == 0 then
+ indentAmount = #token[2][1]
+ end
+
+ if indentAmount ~= 0 then
+ indents = (#token[2][1] / indentAmount)
+ else
+ indents = 0
+ end
+
+ if indents == lastIndents then
+ ignore = true
+ elseif indents > lastIndents + 2 then
+ error(
+ "SyntaxError: invalid indentation, got "
+ .. tostring(indents)
+ .. " instead of "
+ .. tostring(lastIndents)
+ .. context(token[2].input)
+ )
+ elseif indents > lastIndents + 1 then
+ push(stack, token)
+ elseif indents < lastIndents then
+ local input = token[2].input
+ token = { "dedent", { "", input = "" } }
+ token.input = input
+ while lastIndents > indents + 1 do
+ lastIndents = lastIndents - 1
+ push(stack, token)
+ end
+ end
+ end -- if token[1] == XXX
+ token.row = row
+ break
+ end -- if #captures > 0
+ end
+
+ if not ignore then
+ if token then
+ push(stack, token)
+ token = nil
+ else
+ error("SyntaxError " .. context(str))
+ end
+ end
+
+ ignore = false
+ end
+
+ return stack
end
Parser.peek = function(self, offset)
- offset = offset or 1
- return self.tokens[offset + self.current]
+ offset = offset or 1
+ return self.tokens[offset + self.current]
end
Parser.advance = function(self)
- self.current = self.current + 1
- return self.tokens[self.current]
+ self.current = self.current + 1
+ return self.tokens[self.current]
end
Parser.advanceValue = function(self)
- return self:advance()[2][1]
+ return self:advance()[2][1]
end
Parser.accept = function(self, type)
- if self:peekType(type) then
- return self:advance()
- end
+ if self:peekType(type) then
+ return self:advance()
+ end
end
Parser.expect = function(self, type, msg)
- return self:accept(type) or error(msg .. context(self:peek()[1].input))
+ return self:accept(type) or error(msg .. context(self:peek()[1].input))
end
Parser.expectDedent = function(self, msg)
- return self:accept("dedent") or (self:peek() == nil) or error(msg .. context(self:peek()[2].input))
+ return self:accept("dedent") or (self:peek() == nil) or error(msg .. context(self:peek()[2].input))
end
Parser.peekType = function(self, val, offset)
- return self:peek(offset) and self:peek(offset)[1] == val
+ return self:peek(offset) and self:peek(offset)[1] == val
end
Parser.ignore = function(self, items)
- local advanced
- repeat
- advanced = false
- for _, v in pairs(items) do
- if self:peekType(v) then
- self:advance()
- advanced = true
- end
- end
- until advanced == false
+ local advanced
+ repeat
+ advanced = false
+ for _, v in pairs(items) do
+ if self:peekType(v) then
+ self:advance()
+ advanced = true
+ end
+ end
+ until advanced == false
end
Parser.ignoreSpace = function(self)
- self:ignore({ "space" })
+ self:ignore({ "space" })
end
Parser.ignoreWhitespace = function(self)
- self:ignore({ "space", "indent", "dedent" })
+ self:ignore({ "space", "indent", "dedent" })
end
Parser.parse = function(self)
- local ref = nil
- if self:peekType("string") and not self:peek().force_text then
- local char = self:peek()[2][1]:sub(1, 1)
- if char == "&" then
- ref = self:peek()[2][1]:sub(2)
- self:advanceValue()
- self:ignoreSpace()
- elseif char == "*" then
- ref = self:peek()[2][1]:sub(2)
- return self.refs[ref]
- end
- end
-
- local result
- local c = {
- indent = self:accept("indent") and 1 or 0,
- token = self:peek(),
- }
- push(self.parse_stack, c)
-
- if c.token[1] == "doc" then
- result = self:parseDoc()
- elseif c.token[1] == "-" then
- result = self:parseList()
- elseif c.token[1] == "{" then
- result = self:parseInlineHash()
- elseif c.token[1] == "[" then
- result = self:parseInlineList()
- elseif c.token[1] == "id" then
- result = self:parseHash()
- elseif c.token[1] == "string" then
- result = self:parseString("\n")
- elseif c.token[1] == "timestamp" then
- result = self:parseTimestamp()
- elseif c.token[1] == "number" then
- result = tonumber(self:advanceValue())
- elseif c.token[1] == "pipe" then
- result = self:parsePipe()
- elseif c.token.const == true then
- self:advanceValue()
- result = c.token.value
- else
- error("ParseError: unexpected token '" .. c.token[1] .. "'" .. context(c.token.input))
- end
-
- pop(self.parse_stack)
- while c.indent > 0 do
- c.indent = c.indent - 1
- local term = "term " .. c.token[1] .. ": '" .. c.token[2][1] .. "'"
- self:expectDedent("last " .. term .. " is not properly dedented")
- end
-
- if ref then
- self.refs[ref] = result
- end
- return result
+ local ref = nil
+ if self:peekType("string") and not self:peek().force_text then
+ local char = self:peek()[2][1]:sub(1, 1)
+ if char == "&" then
+ ref = self:peek()[2][1]:sub(2)
+ self:advanceValue()
+ self:ignoreSpace()
+ elseif char == "*" then
+ ref = self:peek()[2][1]:sub(2)
+ return self.refs[ref]
+ end
+ end
+
+ local result
+ local c = {
+ indent = self:accept("indent") and 1 or 0,
+ token = self:peek(),
+ }
+ push(self.parse_stack, c)
+
+ if c.token[1] == "doc" then
+ result = self:parseDoc()
+ elseif c.token[1] == "-" then
+ result = self:parseList()
+ elseif c.token[1] == "{" then
+ result = self:parseInlineHash()
+ elseif c.token[1] == "[" then
+ result = self:parseInlineList()
+ elseif c.token[1] == "id" then
+ result = self:parseHash()
+ elseif c.token[1] == "string" then
+ result = self:parseString("\n")
+ elseif c.token[1] == "timestamp" then
+ result = self:parseTimestamp()
+ elseif c.token[1] == "number" then
+ result = tonumber(self:advanceValue())
+ elseif c.token[1] == "pipe" then
+ result = self:parsePipe()
+ elseif c.token.const == true then
+ self:advanceValue()
+ result = c.token.value
+ else
+ error("ParseError: unexpected token '" .. c.token[1] .. "'" .. context(c.token.input))
+ end
+
+ pop(self.parse_stack)
+ while c.indent > 0 do
+ c.indent = c.indent - 1
+ local term = "term " .. c.token[1] .. ": '" .. c.token[2][1] .. "'"
+ self:expectDedent("last " .. term .. " is not properly dedented")
+ end
+
+ if ref then
+ self.refs[ref] = result
+ end
+ return result
end
Parser.parseDoc = function(self)
- self:accept("doc")
- return self:parse()
+ self:accept("doc")
+ return self:parse()
end
Parser.inline = function(self)
- local current = self:peek(0)
- if not current then
- return {}, 0
- end
+ local current = self:peek(0)
+ if not current then
+ return {}, 0
+ end
- local inline = {}
- local i = 0
+ local inline = {}
+ local i = 0
- while self:peek(i) and not self:peekType("indent", i) and current.row == self:peek(i).row do
- inline[self:peek(i)[1]] = true
- i = i - 1
- end
- return inline, -i
+ while self:peek(i) and not self:peekType("indent", i) and current.row == self:peek(i).row do
+ inline[self:peek(i)[1]] = true
+ i = i - 1
+ end
+ return inline, -i
end
Parser.isInline = function(self)
- local _, i = self:inline()
- return i > 0
+ local _, i = self:inline()
+ return i > 0
end
Parser.parent = function(self, level)
- level = level or 1
- return self.parse_stack[#self.parse_stack - level]
+ level = level or 1
+ return self.parse_stack[#self.parse_stack - level]
end
Parser.parentType = function(self, type, level)
- return self:parent(level) and self:parent(level).token[1] == type
+ return self:parent(level) and self:parent(level).token[1] == type
end
Parser.parseString = function(self)
- if self:isInline() then
- local result = self:advanceValue()
+ if self:isInline() then
+ local result = self:advanceValue()
- --[[
+ --[[
- a: this looks
flowing: but is
no: string
--]]
- local types = self:inline()
- if types["id"] and types["-"] then
- if not self:peekType("indent") or not self:peekType("indent", 2) then
- return result
- end
- end
-
- --[[
+ local types = self:inline()
+ if types["id"] and types["-"] then
+ if not self:peekType("indent") or not self:peekType("indent", 2) then
+ return result
+ end
+ end
+
+ --[[
a: 1
b: this is
a flowing string
example
c: 3
--]]
- if self:peekType("indent") then
- self:expect("indent", "text block needs to start with indent")
- local addtl = self:accept("indent")
-
- result = result .. "\n" .. self:parseTextBlock("\n")
-
- self:expectDedent("text block ending dedent missing")
- if addtl then
- self:expectDedent("text block ending dedent missing")
- end
- end
- return result
- else
- --[[
+ if self:peekType("indent") then
+ self:expect("indent", "text block needs to start with indent")
+ local addtl = self:accept("indent")
+
+ result = result .. "\n" .. self:parseTextBlock("\n")
+
+ self:expectDedent("text block ending dedent missing")
+ if addtl then
+ self:expectDedent("text block ending dedent missing")
+ end
+ end
+ return result
+ else
+ --[[
a: 1
b:
this is also
@@ -497,149 +497,149 @@ Parser.parseString = function(self)
example
c: 3
--]]
- return self:parseTextBlock("\n")
- end
+ return self:parseTextBlock("\n")
+ end
end
Parser.parsePipe = function(self)
- local pipe = self:expect("pipe")
- self:expect("indent", "text block needs to start with indent")
- local result = self:parseTextBlock(pipe.sep)
- self:expectDedent("text block ending dedent missing")
- return result
+ local pipe = self:expect("pipe")
+ self:expect("indent", "text block needs to start with indent")
+ local result = self:parseTextBlock(pipe.sep)
+ self:expectDedent("text block ending dedent missing")
+ return result
end
Parser.parseTextBlock = function(self, sep)
- local token = self:advance()
- local result = string_trim(token.raw, "\n")
- local indents = 0
- while self:peek() ~= nil and (indents > 0 or not self:peekType("dedent")) do
- local newtoken = self:advance()
- while token.row < newtoken.row do
- result = result .. sep
- token.row = token.row + 1
- end
- if newtoken[1] == "indent" then
- indents = indents + 1
- elseif newtoken[1] == "dedent" then
- indents = indents - 1
- else
- result = result .. string_trim(newtoken.raw, "\n")
- end
- end
- return result
+ local token = self:advance()
+ local result = string_trim(token.raw, "\n")
+ local indents = 0
+ while self:peek() ~= nil and (indents > 0 or not self:peekType("dedent")) do
+ local newtoken = self:advance()
+ while token.row < newtoken.row do
+ result = result .. sep
+ token.row = token.row + 1
+ end
+ if newtoken[1] == "indent" then
+ indents = indents + 1
+ elseif newtoken[1] == "dedent" then
+ indents = indents - 1
+ else
+ result = result .. string_trim(newtoken.raw, "\n")
+ end
+ end
+ return result
end
Parser.parseHash = function(self, hash)
- hash = hash or {}
- local indents = 0
-
- if self:isInline() then
- local id = self:advanceValue()
- self:expect(":", "expected semi-colon after id")
- self:ignoreSpace()
- if self:accept("indent") then
- indents = indents + 1
- hash[id] = self:parse()
- else
- hash[id] = self:parse()
- if self:accept("indent") then
- indents = indents + 1
- end
- end
- self:ignoreSpace()
- end
-
- while self:peekType("id") do
- local id = self:advanceValue()
- self:expect(":", "expected semi-colon after id")
- self:ignoreSpace()
- hash[id] = self:parse()
- self:ignoreSpace()
- end
-
- while indents > 0 do
- self:expectDedent("expected dedent")
- indents = indents - 1
- end
-
- return hash
+ hash = hash or {}
+ local indents = 0
+
+ if self:isInline() then
+ local id = self:advanceValue()
+ self:expect(":", "expected semi-colon after id")
+ self:ignoreSpace()
+ if self:accept("indent") then
+ indents = indents + 1
+ hash[id] = self:parse()
+ else
+ hash[id] = self:parse()
+ if self:accept("indent") then
+ indents = indents + 1
+ end
+ end
+ self:ignoreSpace()
+ end
+
+ while self:peekType("id") do
+ local id = self:advanceValue()
+ self:expect(":", "expected semi-colon after id")
+ self:ignoreSpace()
+ hash[id] = self:parse()
+ self:ignoreSpace()
+ end
+
+ while indents > 0 do
+ self:expectDedent("expected dedent")
+ indents = indents - 1
+ end
+
+ return hash
end
Parser.parseInlineHash = function(self)
- local id
- local hash = {}
- local i = 0
-
- self:accept("{")
- while not self:accept("}") do
- self:ignoreSpace()
- if i > 0 then
- self:expect(",", "expected comma")
- end
-
- self:ignoreWhitespace()
- if self:peekType("id") then
- id = self:advanceValue()
- if id then
- self:expect(":", "expected semi-colon after id")
- self:ignoreSpace()
- hash[id] = self:parse()
- self:ignoreWhitespace()
- end
- end
-
- i = i + 1
- end
- return hash
+ local id
+ local hash = {}
+ local i = 0
+
+ self:accept("{")
+ while not self:accept("}") do
+ self:ignoreSpace()
+ if i > 0 then
+ self:expect(",", "expected comma")
+ end
+
+ self:ignoreWhitespace()
+ if self:peekType("id") then
+ id = self:advanceValue()
+ if id then
+ self:expect(":", "expected semi-colon after id")
+ self:ignoreSpace()
+ hash[id] = self:parse()
+ self:ignoreWhitespace()
+ end
+ end
+
+ i = i + 1
+ end
+ return hash
end
Parser.parseList = function(self)
- local list = {}
- while self:accept("-") do
- self:ignoreSpace()
- list[#list + 1] = self:parse()
+ local list = {}
+ while self:accept("-") do
+ self:ignoreSpace()
+ list[#list + 1] = self:parse()
- self:ignoreSpace()
- end
- return list
+ self:ignoreSpace()
+ end
+ return list
end
Parser.parseInlineList = function(self)
- local list = {}
- local i = 0
- self:accept("[")
- while not self:accept("]") do
- self:ignoreSpace()
- if i > 0 then
- self:expect(",", "expected comma")
- end
+ local list = {}
+ local i = 0
+ self:accept("[")
+ while not self:accept("]") do
+ self:ignoreSpace()
+ if i > 0 then
+ self:expect(",", "expected comma")
+ end
- self:ignoreSpace()
- list[#list + 1] = self:parse()
- self:ignoreSpace()
- i = i + 1
- end
+ self:ignoreSpace()
+ list[#list + 1] = self:parse()
+ self:ignoreSpace()
+ i = i + 1
+ end
- return list
+ return list
end
Parser.parseTimestamp = function(self)
- local capture = self:advance()[2]
+ local capture = self:advance()[2]
- return os.time({
- year = capture[1],
- month = capture[2],
- day = capture[3],
- hour = capture[4] or 0,
- min = capture[5] or 0,
- sec = capture[6] or 0,
- isdst = false,
- }) - os.time({ year = 1970, month = 1, day = 1, hour = 8 })
+ return os.time({
+ year = capture[1],
+ month = capture[2],
+ day = capture[3],
+ hour = capture[4] or 0,
+ min = capture[5] or 0,
+ sec = capture[6] or 0,
+ isdst = false,
+ }) - os.time({ year = 1970, month = 1, day = 1, hour = 8 })
end
exports.eval = function(str)
- return Parser:new(exports.tokenize(str)):parse()
+ return Parser:new(exports.tokenize(str)):parse()
end
exports.dump = table_print
diff --git a/lua/cmake/telescope/pickers.lua b/lua/cmake/telescope/pickers.lua
index c543df8..c82de90 100644
--- a/lua/cmake/telescope/pickers.lua
+++ b/lua/cmake/telescope/pickers.lua
@@ -9,94 +9,94 @@ local previewers = require("cmake.telescope.previewers")
local M = {}
M.build_dirs = function(opts)
- local cmake = require("cmake")
- pickers
- .new(opts, {
- prompt_title = "CMake Builds",
- finder = finders.new_table({
- results = cmake.project.fileapis,
- -- entry_maker = cmake_make_entry.gen_from_fileapi(opts),
- entry_maker = function(entry)
- return {
- value = entry,
- display = entry.path,
- ordinal = entry.path,
- }
- end,
- sorter = conf.generic_sorter(opts),
- -- attach_mappings = function(prompt_bufnr, map)
- -- actions.select_default:replace(function() end)
- -- return true
- -- end,
- }),
- })
- :find()
+ local cmake = require("cmake")
+ pickers
+ .new(opts, {
+ prompt_title = "CMake Builds",
+ finder = finders.new_table({
+ results = cmake.project.fileapis,
+ -- entry_maker = cmake_make_entry.gen_from_fileapi(opts),
+ entry_maker = function(entry)
+ return {
+ value = entry,
+ display = entry.path,
+ ordinal = entry.path,
+ }
+ end,
+ sorter = conf.generic_sorter(opts),
+ -- attach_mappings = function(prompt_bufnr, map)
+ -- actions.select_default:replace(function() end)
+ -- return true
+ -- end,
+ }),
+ })
+ :find()
end
M.configure = function(opts)
- local cmake = require("cmake")
- local runner = require("cmake.runner")
- opts.layout_strategy = "vertical"
- opts.layout_config = {
- prompt_position = "top",
- preview_cutoff = 0,
- preview_height = 5,
- mirror = true,
- }
- pickers
- .new(opts, {
- default_selection_index = cmake.project:current_configure_index(),
- prompt_title = "CMake Configure Options",
- finder = finders.new_table({
- results = cmake.project:list_configs(),
- entry_maker = cmake_make_entry.gen_from_configure(opts),
- }),
- sorter = conf.generic_sorter(opts),
- previewer = previewers.configure_previewer(),
- attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- actions.close(prompt_bufnr)
- local selection = action_state.get_selected_entry()
- cmake.project.current_config = selection.value
- runner.start(selection.value.generate_command)
- end)
- return true
- end,
- })
- :find()
+ local cmake = require("cmake")
+ local runner = require("cmake.runner")
+ opts.layout_strategy = "vertical"
+ opts.layout_config = {
+ prompt_position = "top",
+ preview_cutoff = 0,
+ preview_height = 5,
+ mirror = true,
+ }
+ pickers
+ .new(opts, {
+ default_selection_index = cmake.project:current_configure_index(),
+ prompt_title = "CMake Configure Options",
+ finder = finders.new_table({
+ results = cmake.project:list_configs(),
+ entry_maker = cmake_make_entry.gen_from_configure(opts),
+ }),
+ sorter = conf.generic_sorter(opts),
+ previewer = previewers.configure_previewer(),
+ attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ actions.close(prompt_bufnr)
+ local selection = action_state.get_selected_entry()
+ cmake.project.current_config = selection.value
+ runner.start(selection.value.generate_command)
+ end)
+ return true
+ end,
+ })
+ :find()
end
M.build = function(opts)
- local cmake = require("cmake")
- local runner = require("cmake.runner")
- opts.layout_strategy = "vertical"
- opts.layout_config = {
- prompt_position = "top",
- preview_cutoff = 0,
- preview_height = 5,
- mirror = true,
- }
- pickers
- .new(opts, {
- default_selection_index = cmake.project:current_build_index(),
- prompt_title = "CMake Build Options",
- finder = finders.new_table({
- results = cmake.project:list_builds(),
- entry_maker = cmake_make_entry.gen_from_configure(opts),
- }),
- sorter = conf.generic_sorter(opts),
- previewer = previewers.build_previewer(),
- attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- actions.close(prompt_bufnr)
- local selection = action_state.get_selected_entry()
- cmake.project.current_config = selection.value
- runner.start(selection.value.build_command)
- end)
- return true
- end,
- })
- :find()
+ local cmake = require("cmake")
+ local runner = require("cmake.runner")
+ opts.layout_strategy = "vertical"
+ opts.layout_config = {
+ prompt_position = "top",
+ preview_cutoff = 0,
+ preview_height = 5,
+ mirror = true,
+ }
+ pickers
+ .new(opts, {
+ default_selection_index = cmake.project:current_build_index(),
+ prompt_title = "CMake Build Options",
+ finder = finders.new_table({
+ results = cmake.project:list_builds(),
+ entry_maker = cmake_make_entry.gen_from_configure(opts),
+ }),
+ sorter = conf.generic_sorter(opts),
+ previewer = previewers.build_previewer(),
+ attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ actions.close(prompt_bufnr)
+ local selection = action_state.get_selected_entry()
+ cmake.project.current_config = selection.value
+ runner.start(selection.value.build_command)
+ end)
+ return true
+ end,
+ })
+ :find()
end
return M
diff --git a/lua/cmake/terminal.lua b/lua/cmake/terminal.lua
index 689590f..c6bb533 100644
--- a/lua/cmake/terminal.lua
+++ b/lua/cmake/terminal.lua
@@ -5,116 +5,113 @@ local api = vim.api
local M = {}
local cmake = {
- bufnr = nil,
- window = nil,
- jobid = nil,
+ bufnr = nil,
+ window = nil,
+ jobid = nil,
}
local runnable
local scroll_to_bottom = function()
- local info = vim.api.nvim_get_mode()
- if info and (info.mode == "n" or info.mode == "nt") then
- vim.cmd("normal! G")
- end
+ local info = vim.api.nvim_get_mode()
+ if info and (info.mode == "n" or info.mode == "nt") then
+ vim.cmd("normal! G")
+ end
end
local prepare_cmake_buf = function()
- if cmake.bufnr and api.nvim_buf_is_valid(cmake.bufnr) then
- api.nvim_buf_delete(cmake.bufnr, { force = true })
- end
- cmake.bufnr = api.nvim_create_buf(false, false)
+ if cmake.bufnr and api.nvim_buf_is_valid(cmake.bufnr) then
+ api.nvim_buf_delete(cmake.bufnr, { force = true })
+ end
+ cmake.bufnr = api.nvim_create_buf(false, false)
end
local termopen = function(command, opts)
- -- For some reason termopen() doesn't like an empty env table
- if command.env and vim.tbl_isempty(command.env) then
- command.env = nil
- end
- vim.fn.termopen(command.cmd .. " " .. command.args, {
- -- detach = 1,
- cwd = command.cwd,
- env = command.env,
- clear_env = config.cmake_terminal.clear_env,
- on_stdout = function(_, data, _)
- api.nvim_buf_call(cmake.bufnr, scroll_to_bottom)
- end,
- on_exit = function(pid, code, event)
- if code == 0 then
- command.after_success()
- if config.cmake_terminal.close_on_exit == "success" or config.cmake_terminal.close_on_exit == true then
- if api.nvim_win_is_valid(cmake.window) then
- api.nvim_win_close(cmake.window, true)
- end
- end
- if config.notification.after == "success" or config.notification.after == true then
- vim.notify(
- vim.tbl_get(opts, "notify", "ok_message") or "CMake successfully completed",
- vim.log.levels.INFO
- )
- end
- else
- if config.notification.after == "failure" or config.notification.after == true then
- local msg = "CMake failed. Code " .. tostring(code)
- local opt_msg = vim.tbl_get(opts, "notify", "err_message")
- if type(opt_msg) == "string" then
- msg = opt_msg
- elseif type(opt_msg) == "function" then
- msg = opt_msg(code)
- end
- vim.notify(msg, vim.log.levels.ERROR)
- end
- end
- end,
- })
+ -- For some reason termopen() doesn't like an empty env table
+ if command.env and vim.tbl_isempty(command.env) then
+ command.env = nil
+ end
+ vim.fn.termopen(command.cmd .. " " .. command.args, {
+ -- detach = 1,
+ cwd = command.cwd,
+ env = command.env,
+ clear_env = config.cmake_terminal.clear_env,
+ on_stdout = function(_, data, _)
+ api.nvim_buf_call(cmake.bufnr, scroll_to_bottom)
+ end,
+ on_exit = function(pid, code, event)
+ if code == 0 then
+ command.after_success()
+ if config.cmake_terminal.close_on_exit == "success" or config.cmake_terminal.close_on_exit == true then
+ if api.nvim_win_is_valid(cmake.window) then
+ api.nvim_win_close(cmake.window, true)
+ end
+ end
+ if config.notification.after == "success" or config.notification.after == true then
+ vim.notify(vim.tbl_get(opts, "notify", "ok_message") or "CMake successfully completed", vim.log.levels.INFO)
+ end
+ else
+ if config.notification.after == "failure" or config.notification.after == true then
+ local msg = "CMake failed. Code " .. tostring(code)
+ local opt_msg = vim.tbl_get(opts, "notify", "err_message")
+ if type(opt_msg) == "string" then
+ msg = opt_msg
+ elseif type(opt_msg) == "function" then
+ msg = opt_msg(code)
+ end
+ vim.notify(msg, vim.log.levels.ERROR)
+ end
+ end
+ end,
+ })
end
local open_window = function()
- if not cmake.bufnr then
- vim.notify("No CMake buffer created yet", vim.log.levels.INFO)
- return
- end
- cmake.window = api.nvim_open_win(cmake.bufnr, config.cmake_terminal.enter, {
- win = 0,
- split = config.cmake_terminal.split,
- height = config.cmake_terminal.size,
- width = config.cmake_terminal.size,
- })
+ if not cmake.bufnr then
+ vim.notify("No CMake buffer created yet", vim.log.levels.INFO)
+ return
+ end
+ cmake.window = api.nvim_open_win(cmake.bufnr, config.cmake_terminal.enter, {
+ win = 0,
+ split = config.cmake_terminal.split,
+ height = config.cmake_terminal.size,
+ width = config.cmake_terminal.size,
+ })
end
M.cmake_execute = function(command, opts)
- opts = opts or {}
+ opts = opts or {}
- prepare_cmake_buf()
- if config.cmake_terminal.open_on_start and not (cmake.window and api.nvim_win_is_valid(cmake.window)) then
- open_window()
- end
- vim.api.nvim_buf_call(cmake.bufnr, function()
- termopen(command, opts)
- end)
+ prepare_cmake_buf()
+ if config.cmake_terminal.open_on_start and not (cmake.window and api.nvim_win_is_valid(cmake.window)) then
+ open_window()
+ end
+ vim.api.nvim_buf_call(cmake.bufnr, function()
+ termopen(command, opts)
+ end)
end
M.cmake_toggle = function()
- if cmake.window and api.nvim_win_is_valid(cmake.window) then
- api.nvim_win_close(cmake.window, true)
- else
- open_window()
- end
+ if cmake.window and api.nvim_win_is_valid(cmake.window) then
+ api.nvim_win_close(cmake.window, true)
+ else
+ open_window()
+ end
end
M.target_execute = function(command, opts)
- opts = opts or {}
- local bufnr = api.nvim_create_buf(true, false)
- api.nvim_open_win(bufnr, config.target_terminal.enter, {
- win = 0,
- split = config.target_terminal.split,
- height = config.target_terminal.size,
- width = config.target_terminal.size,
- })
- api.nvim_buf_call(bufnr, function()
- vim.cmd.terminal()
- api.nvim_chan_send(vim.bo.channel, command.cwd .. "/" .. command.cmd)
- end)
+ opts = opts or {}
+ local bufnr = api.nvim_create_buf(true, false)
+ api.nvim_open_win(bufnr, config.target_terminal.enter, {
+ win = 0,
+ split = config.target_terminal.split,
+ height = config.target_terminal.size,
+ width = config.target_terminal.size,
+ })
+ api.nvim_buf_call(bufnr, function()
+ vim.cmd.terminal()
+ api.nvim_chan_send(vim.bo.channel, command.cwd .. "/" .. command.cmd)
+ end)
end
return M
diff --git a/lua/cmake/utils.lua b/lua/cmake/utils.lua
index ce6d213..9e40aa4 100644
--- a/lua/cmake/utils.lua
+++ b/lua/cmake/utils.lua
@@ -4,102 +4,102 @@ local uv = vim.uv
local utils = {}
utils.substitude = function(str, subs)
- local ret = str
- for k, v in pairs(subs) do
- ret = ret:gsub(k, v)
- end
- return ret
+ local ret = str
+ for k, v in pairs(subs) do
+ ret = ret:gsub(k, v)
+ end
+ return ret
end
function utils.touch_file(path, txt, flag, callback)
- uv.fs_open(path, flag, 438, function(err, fd)
- assert(not err, err)
- assert(fd)
- uv.fs_close(fd, function(c_err)
- assert(not c_err, c_err)
- if type(callback) == "function" then
- callback()
- end
- end)
- end)
+ uv.fs_open(path, flag, 438, function(err, fd)
+ assert(not err, err)
+ assert(fd)
+ uv.fs_close(fd, function(c_err)
+ assert(not c_err, c_err)
+ if type(callback) == "function" then
+ callback()
+ end
+ end)
+ end)
end
function utils.file_exists(path, callback)
- uv.fs_stat(path, function(err, _)
- local exists
- if err then
- exists = false
- else
- exists = true
- end
- if type(callback) == "function" then
- callback(exists)
- end
- end)
+ uv.fs_stat(path, function(err, _)
+ local exists
+ if err then
+ exists = false
+ else
+ exists = true
+ end
+ if type(callback) == "function" then
+ callback(exists)
+ end
+ end)
end
function utils.read_file(path, callback)
- uv.fs_open(path, "r", 438, function(err, fd)
- assert(not err, err)
- assert(fd, fd)
- uv.fs_fstat(fd, function(s_err, stat)
- assert(not s_err, s_err)
- assert(stat, stat)
- uv.fs_read(fd, stat.size, 0, function(r_err, data)
- assert(not r_err, r_err)
- uv.fs_close(fd, function(c_err)
- assert(not c_err, c_err)
- callback(data)
- end)
- end)
- end)
- end)
+ uv.fs_open(path, "r", 438, function(err, fd)
+ assert(not err, err)
+ assert(fd, fd)
+ uv.fs_fstat(fd, function(s_err, stat)
+ assert(not s_err, s_err)
+ assert(stat, stat)
+ uv.fs_read(fd, stat.size, 0, function(r_err, data)
+ assert(not r_err, r_err)
+ uv.fs_close(fd, function(c_err)
+ assert(not c_err, c_err)
+ callback(data)
+ end)
+ end)
+ end)
+ end)
end
function utils.read_file_sync(path)
- local fd = assert(vim.uv.fs_open(path, "r", 438))
- local stat = assert(vim.uv.fs_fstat(fd))
- local data = assert(vim.uv.fs_read(fd, stat.size, 0))
- assert(vim.uv.fs_close(fd))
- return data
+ local fd = assert(vim.uv.fs_open(path, "r", 438))
+ local stat = assert(vim.uv.fs_fstat(fd))
+ local data = assert(vim.uv.fs_read(fd, stat.size, 0))
+ assert(vim.uv.fs_close(fd))
+ return data
end
function utils.write_file(path, txt, callback)
- uv.fs_open(path, "w", 438, function(err, fd)
- assert(not err, err)
- assert(fd)
- uv.fs_write(fd, txt, nil, function(w_err, _)
- assert(not w_err, w_err)
- uv.fs_close(fd, function(c_err)
- assert(not c_err, c_err)
- if type(callback) == "function" then
- callback()
- end
- end)
- end)
- end)
+ uv.fs_open(path, "w", 438, function(err, fd)
+ assert(not err, err)
+ assert(fd)
+ uv.fs_write(fd, txt, nil, function(w_err, _)
+ assert(not w_err, w_err)
+ uv.fs_close(fd, function(c_err)
+ assert(not c_err, c_err)
+ if type(callback) == "function" then
+ callback()
+ end
+ end)
+ end)
+ end)
end
function utils.symlink(src_path, dst_path, callback)
- local src = vim.fs.joinpath(src_path, "compile_commands.json")
- utils.file_exists(src, function()
- uv.spawn(config.cmake.cmake_path, {
- args = {
- "-E",
- "create_symlink",
- src,
- vim.fs.joinpath(dst_path, "compile_commands.json"),
- },
- }, function(code, signal)
- if code ~= 0 then
- vim.notify("CMake: error while creating symlink. Code " .. tostring(code), vim.log.levels.ERROR)
- return
- end
- if type(callback) == "function" then
- callback()
- end
- end)
- end)
+ local src = vim.fs.joinpath(src_path, "compile_commands.json")
+ utils.file_exists(src, function()
+ uv.spawn(config.cmake.cmake_path, {
+ args = {
+ "-E",
+ "create_symlink",
+ src,
+ vim.fs.joinpath(dst_path, "compile_commands.json"),
+ },
+ }, function(code, signal)
+ if code ~= 0 then
+ vim.notify("CMake: error while creating symlink. Code " .. tostring(code), vim.log.levels.ERROR)
+ return
+ end
+ if type(callback) == "function" then
+ callback()
+ end
+ end)
+ end)
end
return utils
diff --git a/lua/cmake/variants.lua b/lua/cmake/variants.lua
index cb846e8..ce7d8a7 100644
--- a/lua/cmake/variants.lua
+++ b/lua/cmake/variants.lua
@@ -8,155 +8,155 @@ local VariantConfig = {}
VariantConfig.__index = VariantConfig
local global_variant_subs = {
- ["${workspaceFolder}"] = uv.cwd(),
- ["${userHome}"] = uv.os_homedir(),
+ ["${workspaceFolder}"] = uv.cwd(),
+ ["${userHome}"] = uv.os_homedir(),
}
local _configure_args = function(obj, build_directory)
- local args = {}
- if obj.generator then
- table.insert(args, "-G " .. '"' .. obj.generator .. '"')
- end
- table.insert(args, "-B" .. build_directory)
- if obj.buildType then
- table.insert(args, "-DCMAKE_BUILD_TYPE=" .. obj.buildType)
- end
- if obj.linkage and string.lower(obj.linkage) == "static" then
- table.insert(args, "-DCMAKE_BUILD_SHARED_LIBS=OFF")
- elseif obj.linkage and string.lower(obj.linkage) == "shared" then
- table.insert(args, "-DCMAKE_BUILD_SHARED_LIBS=ON")
- end
- for k, v in pairs(obj.settings or {}) do
- table.insert(args, "-D" .. k .. "=" .. v)
- end
- table.insert(args, "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON")
- return args
+ local args = {}
+ if obj.generator then
+ table.insert(args, "-G " .. '"' .. obj.generator .. '"')
+ end
+ table.insert(args, "-B" .. build_directory)
+ if obj.buildType then
+ table.insert(args, "-DCMAKE_BUILD_TYPE=" .. obj.buildType)
+ end
+ if obj.linkage and string.lower(obj.linkage) == "static" then
+ table.insert(args, "-DCMAKE_BUILD_SHARED_LIBS=OFF")
+ elseif obj.linkage and string.lower(obj.linkage) == "shared" then
+ table.insert(args, "-DCMAKE_BUILD_SHARED_LIBS=ON")
+ end
+ for k, v in pairs(obj.settings or {}) do
+ table.insert(args, "-D" .. k .. "=" .. v)
+ end
+ table.insert(args, "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON")
+ return args
end
local _configure_command = function(obj, configure_args)
- local ret = {}
- ret.cmd = config.cmake.cmake_path
- ret.args = table.concat(configure_args, " ")
- ret.env = vim.tbl_deep_extend("keep", obj.env, config.cmake.configure_environment, config.cmake.environment)
- return ret
+ local ret = {}
+ ret.cmd = config.cmake.cmake_path
+ ret.args = table.concat(configure_args, " ")
+ ret.env = vim.tbl_deep_extend("keep", obj.env, config.cmake.configure_environment, config.cmake.environment)
+ return ret
end
local _build_args = function(obj, build_directory)
- local args = { "--build" }
- table.insert(args, build_directory)
- if config.cmake.parallel_jobs then
- table.insert(args, "-j " .. tostring(config.cmake.parallel_jobs))
- end
- if #obj.buildArgs ~= 0 then
- for _, v in ipairs(obj.buildArgs) do
- table.insert(args, v)
- end
- elseif #config.cmake.build_args ~= 0 then
- for _, v in ipairs(config.cmake.build_args) do
- table.insert(args, v)
- end
- end
- if #obj.buildToolArgs ~= 0 or #config.cmake.build_tool_args ~= 0 then
- table.insert(args, "--")
- if #obj.buildToolArgs ~= 0 then
- for _, v in ipairs(obj.buildToolArgs) do
- table.insert(args, v)
- end
- elseif #config.cmake.build_tool_args ~= 0 then
- for _, v in ipairs(config.cmake.build_tool_args) do
- table.insert(args, v)
- end
- end
- end
- return args
+ local args = { "--build" }
+ table.insert(args, build_directory)
+ if config.cmake.parallel_jobs then
+ table.insert(args, "-j " .. tostring(config.cmake.parallel_jobs))
+ end
+ if #obj.buildArgs ~= 0 then
+ for _, v in ipairs(obj.buildArgs) do
+ table.insert(args, v)
+ end
+ elseif #config.cmake.build_args ~= 0 then
+ for _, v in ipairs(config.cmake.build_args) do
+ table.insert(args, v)
+ end
+ end
+ if #obj.buildToolArgs ~= 0 or #config.cmake.build_tool_args ~= 0 then
+ table.insert(args, "--")
+ if #obj.buildToolArgs ~= 0 then
+ for _, v in ipairs(obj.buildToolArgs) do
+ table.insert(args, v)
+ end
+ elseif #config.cmake.build_tool_args ~= 0 then
+ for _, v in ipairs(config.cmake.build_tool_args) do
+ table.insert(args, v)
+ end
+ end
+ end
+ return args
end
local _build_command = function(obj, build_args)
- local ret = {}
- ret.cmd = config.cmake.cmake_path
- ret.args = table.concat(build_args, " ")
- ret.env = vim.tbl_deep_extend("keep", obj.env, config.cmake.configure_environment, config.cmake.environment)
- return ret
+ local ret = {}
+ ret.cmd = config.cmake.cmake_path
+ ret.args = table.concat(build_args, " ")
+ ret.env = vim.tbl_deep_extend("keep", obj.env, config.cmake.configure_environment, config.cmake.environment)
+ return ret
end
---Create configuration from variant
---@param source table
---@return CMakeGenerateOption
function VariantConfig:new(source)
- local obj = {}
- local subs = vim.tbl_deep_extend("keep", global_variant_subs, { ["${buildType}"] = source.buildType })
+ local obj = {}
+ local subs = vim.tbl_deep_extend("keep", global_variant_subs, { ["${buildType}"] = source.buildType })
- obj.name = source.short
- obj.long_name = source.long
- obj.directory = utils.substitude(config.cmake.build_directory, subs)
- local configure_args = _configure_args(source, obj.directory)
- obj.generate_command = _configure_command(source, configure_args)
- local build_args = _build_args(source, obj.directory)
- obj.build_options = {
- {
- name = source.short,
- long_name = source.long,
- command = _build_command(source, build_args),
- },
- }
+ obj.name = source.short
+ obj.long_name = source.long
+ obj.directory = utils.substitude(config.cmake.build_directory, subs)
+ local configure_args = _configure_args(source, obj.directory)
+ obj.generate_command = _configure_command(source, configure_args)
+ local build_args = _build_args(source, obj.directory)
+ obj.build_options = {
+ {
+ name = source.short,
+ long_name = source.long,
+ command = _build_command(source, build_args),
+ },
+ }
- setmetatable(obj, VariantConfig)
- return obj
+ setmetatable(obj, VariantConfig)
+ return obj
end
function VariantConfig.cartesian_product(sets)
- local function collapse_result(res)
- local ret = {
- short = {},
- long = {},
- buildType = nil,
- linkage = nil,
- generator = nil,
- buildArgs = {},
- buildToolArgs = {},
- settings = {},
- env = {},
- }
- local is_default = true
- for _, v in ipairs(res) do
- if not v.default then
- is_default = false
- end
- ret.short[#ret.short + 1] = v.short
- ret.long[#ret.long + 1] = v.long
- ret.buildType = v.buildType or ret.buildType
- ret.linkage = v.linkage or ret.linkage
- ret.generator = v.generator or ret.generator
- ret.buildArgs = v.buildArgs or ret.buildArgs
- ret.buildToolArgs = v.buildToolArgs or ret.buildToolArgs
- for sname, sval in pairs(v.settings or {}) do
- ret.settings[sname] = sval
- end
- for ename, eres in pairs(v.env or {}) do
- ret.env[ename] = eres
- end
- end
- return VariantConfig:new(ret), is_default
- end
- local result = {}
- local set_count = #sets
- local function descend(depth)
- for k, v in pairs(sets[depth].choices) do
- if sets[depth].default ~= k then
- result.default = false
- end
- result[depth] = v
- result[depth].default = (k == sets[depth].default)
- if depth == set_count then
- coroutine.yield(collapse_result(result))
- else
- descend(depth + 1)
- end
- end
- end
- return coroutine.wrap(function()
- descend(1)
- end)
+ local function collapse_result(res)
+ local ret = {
+ short = {},
+ long = {},
+ buildType = nil,
+ linkage = nil,
+ generator = nil,
+ buildArgs = {},
+ buildToolArgs = {},
+ settings = {},
+ env = {},
+ }
+ local is_default = true
+ for _, v in ipairs(res) do
+ if not v.default then
+ is_default = false
+ end
+ ret.short[#ret.short + 1] = v.short
+ ret.long[#ret.long + 1] = v.long
+ ret.buildType = v.buildType or ret.buildType
+ ret.linkage = v.linkage or ret.linkage
+ ret.generator = v.generator or ret.generator
+ ret.buildArgs = v.buildArgs or ret.buildArgs
+ ret.buildToolArgs = v.buildToolArgs or ret.buildToolArgs
+ for sname, sval in pairs(v.settings or {}) do
+ ret.settings[sname] = sval
+ end
+ for ename, eres in pairs(v.env or {}) do
+ ret.env[ename] = eres
+ end
+ end
+ return VariantConfig:new(ret), is_default
+ end
+ local result = {}
+ local set_count = #sets
+ local function descend(depth)
+ for k, v in pairs(sets[depth].choices) do
+ if sets[depth].default ~= k then
+ result.default = false
+ end
+ result[depth] = v
+ result[depth].default = (k == sets[depth].default)
+ if depth == set_count then
+ coroutine.yield(collapse_result(result))
+ else
+ descend(depth + 1)
+ end
+ end
+ end
+ return coroutine.wrap(function()
+ descend(1)
+ end)
end
return VariantConfig