From 86124bddb5638368985c0b59b7c134e499a9e21b Mon Sep 17 00:00:00 2001 From: Civitasv Date: Sun, 11 Dec 2022 20:45:28 +0800 Subject: [PATCH] support inherits of CMake Presets --- lua/cmake-tools/config.lua | 55 +++++++++++++++++------------- lua/cmake-tools/const.lua | 8 ++--- lua/cmake-tools/init.lua | 2 +- lua/cmake-tools/presets.lua | 67 ++++++++++++++++++++++++++++++++++--- lua/cmake-tools/utils.lua | 24 ++++++------- 5 files changed, 111 insertions(+), 45 deletions(-) diff --git a/lua/cmake-tools/config.lua b/lua/cmake-tools/config.lua index a859581..26f5374 100644 --- a/lua/cmake-tools/config.lua +++ b/lua/cmake-tools/config.lua @@ -47,30 +47,6 @@ function Config:update_build_dir(build_dir) ) end -function Config:get_codemodel_targets() - -- if reply_directory exists - local reply_directory = Path:new(vim.loop.cwd(), self.reply_directory) - if not reply_directory:exists() then - return Result:new(Types.NOT_CONFIGURED, nil, "Configure fail") - end - - local found_files = scandir.scan_dir( - reply_directory.filename, - { search_pattern = "codemodel*" } - ) - if #found_files == 0 then - return Result:new(Types.CANNOT_FIND_CODEMODEL_FILE, nil, "Unable to find codemodel file") - end - local codemodel = Path:new(found_files[1]) - local codemodel_json = vim.json.decode(codemodel:read()) - return Result:new(Types.SUCCESS, codemodel_json["configurations"][1]["targets"], "find it") -end - -function Config:get_code_model_target_info(codemodel_target) - local reply_directory = Path:new(vim.loop.cwd(), self.reply_directory) - return vim.json.decode((reply_directory / codemodel_target["jsonFile"]):read()) -end - function Config:generate_build_directory() local build_directory = Path:new(vim.loop.cwd(), self.build_directory) @@ -99,6 +75,31 @@ function Config:generate_query_files() return Result:new(Types.SUCCESS, true, "yeah, that could be") end +function Config:get_codemodel_targets() + -- if reply_directory exists + local reply_directory = Path:new(vim.loop.cwd(), self.reply_directory) + if not reply_directory:exists() then + return Result:new(Types.NOT_CONFIGURED, nil, "Configure fail") + end + + local found_files = scandir.scan_dir( + reply_directory.filename, + { search_pattern = "codemodel*" } + ) + if #found_files == 0 then + return Result:new(Types.CANNOT_FIND_CODEMODEL_FILE, nil, "Unable to find codemodel file") + end + local codemodel = Path:new(found_files[1]) + local codemodel_json = vim.json.decode(codemodel:read()) + return Result:new(Types.SUCCESS, codemodel_json["configurations"][1]["targets"], "find it") +end + +function Config:get_code_model_target_info(codemodel_target) + local reply_directory = Path:new(vim.loop.cwd(), self.reply_directory) + return vim.json.decode((reply_directory / codemodel_target["jsonFile"]):read()) +end + +-- Check if launch target is built function Config:check_launch_target() -- 1. not configured local build_directory = Path:new(vim.loop.cwd(), self.build_directory) @@ -139,6 +140,8 @@ function Config:check_launch_target() ) end +-- Retrieve launch target path: self.launch_target +-- it will first check if this launch target is built function Config:get_launch_target() local check_result = self:check_launch_target() if check_result.code ~= Types.SUCCESS then @@ -149,9 +152,11 @@ function Config:get_launch_target() local target_path = target_info["artifacts"][1]["path"] target_path = Path:new(target_path) if not target_path:is_absolute() then + -- then it is a relative path, based on build directory local build_directory = Path:new(vim.loop.cwd(), self.build_directory) target_path = build_directory / target_path end + -- else it is an absolute path if not target_path:is_file() then return Result:new( @@ -164,6 +169,8 @@ function Config:get_launch_target() return Result:new(Types.SUCCESS, target_path.filename, "yeah, that's good") end +-- Check if this launch target is debuggable +-- use variants.debuggable function Config:validate_for_debugging() local build_type = self.build_type diff --git a/lua/cmake-tools/const.lua b/lua/cmake-tools/const.lua index bcd1b24..7ab515d 100644 --- a/lua/cmake-tools/const.lua +++ b/lua/cmake-tools/const.lua @@ -7,11 +7,11 @@ then end local const = { - cmake_command = "/usr/bin/cmake", - cmake_build_directory = "", + cmake_command = "/usr/bin/cmake", -- cmake command path + cmake_build_directory = "", -- cmake generate directory cmake_build_directory_prefix = "cmake_build_", -- when cmake_build_directory is "", this option will be activated - cmake_generate_options = { "-DCMAKE_EXPORT_COMPILE_COMMANDS=1" }, - cmake_build_options = {}, + cmake_generate_options = { "-DCMAKE_EXPORT_COMPILE_COMMANDS=1" }, -- it will be activated when invoke `cmake.generate` + cmake_build_options = {}, -- it will be activated when invoke `cmake.build` cmake_console_position = "belowright", -- "bottom", "top" cmake_console_size = 10, cmake_show_console = "always", -- "always", "only_on_error" diff --git a/lua/cmake-tools/init.lua b/lua/cmake-tools/init.lua index 59f1836..9524182 100644 --- a/lua/cmake-tools/init.lua +++ b/lua/cmake-tools/init.lua @@ -56,7 +56,7 @@ function cmake.generate(opt, callback) local build_directory = presets.get_build_dir( presets.get_preset_by_name(config.configure_preset, "configurePresets") ) - if build_directory ~= -1 then + if build_directory ~= "" then config:update_build_dir(build_directory) end config:generate_build_directory() diff --git a/lua/cmake-tools/presets.lua b/lua/cmake-tools/presets.lua index b7d3292..6195111 100644 --- a/lua/cmake-tools/presets.lua +++ b/lua/cmake-tools/presets.lua @@ -1,8 +1,9 @@ local Path = require("plenary.path") +local utils = require("cmake-tools.utils") local presets = {} --- checks if there is a CMakePresets.json or CMakeUserPresets.json file +-- Checks if there is a CMakePresets.json or CMakeUserPresets.json file function presets.check() -- helper function to find the config file -- returns file path if found, nil otherwise @@ -24,6 +25,8 @@ function presets.check() return file end +-- Retrieve all presets with type +-- @param type: `buildPresets` or `configurePresets` function presets.parse(type) local file = presets.check() local options = {} @@ -37,6 +40,9 @@ function presets.parse(type) return options end +-- Retrieve preset by name and type +-- @param name: from `name` option +-- @param type: `buildPresets` or `configurePresets` function presets.get_preset_by_name(name, type) local file = presets.check() if not file then @@ -51,6 +57,7 @@ function presets.get_preset_by_name(name, type) return nil end +-- Retrieve build type from preset function presets.get_build_type(preset) if preset and preset.cacheVariables and preset.cacheVariables.CMAKE_BUILD_TYPE then return preset.cacheVariables.CMAKE_BUILD_TYPE @@ -58,11 +65,63 @@ function presets.get_build_type(preset) return "Debug" end +-- Retrieve build directory from preset function presets.get_build_dir(preset) - if preset and preset.binaryDir then - return Path:new(preset.binaryDir) + -- check if this preset is extended + local function helper(p_preset) + local build_dir = "" + + if not p_preset then + return build_dir + end + + if p_preset.inherits then + local inherits = p_preset.inherits + + -- iterate inherits from end, cause + -- If multiple inherits presets provide conflicting + -- values for the same field, the earlier preset in + -- the inherits array will be preferred. + for i = #inherits, 1, -1 do + local parent = inherits[i] + + -- retrieve its parent preset + local ppreset = presets.get_preset_by_name(parent, "configurePresets") + local ppreset_build_dir = helper(ppreset) + if ppreset_build_dir ~= "" then + build_dir = ppreset_build_dir + end + end + end + + if p_preset.binaryDir then + build_dir = p_preset.binaryDir + end + + return build_dir + end + + local build_dir = helper(preset) + + -- macro expansion + local source_path = Path:new(vim.loop.cwd()) + local source_relative = vim.fn.fnamemodify(vim.loop.cwd(), ":t") + + build_dir = build_dir:gsub("${sourceDir}", vim.loop.cwd()) + build_dir = build_dir:gsub("${sourceParentDir}", source_path:parent().filename) + build_dir = build_dir:gsub("${sourceDirName}", source_relative) + build_dir = build_dir:gsub("${presetName}", preset.name) + if preset.generator then + build_dir = build_dir:gsub("${generator}", preset.generator) end - return -1 + build_dir = build_dir:gsub("${hostSystemName}", vim.loop.os_uname().sysname) + build_dir = build_dir:gsub("${fileDir}", source_path.filename) + build_dir = build_dir:gsub("${dollar}", "$") + build_dir = build_dir:gsub("${pathListSep}", "/") + + build_dir = vim.fn.fnamemodify(build_dir, ":.") + + return build_dir end return presets diff --git a/lua/cmake-tools/utils.lua b/lua/cmake-tools/utils.lua index f629682..d0a20a4 100644 --- a/lua/cmake-tools/utils.lua +++ b/lua/cmake-tools/utils.lua @@ -35,6 +35,18 @@ function utils.dump(o) end end +function utils.get_cmake_configuration() + local cmakelists = Path:new(vim.loop.cwd(), "CMakeLists.txt") + if not cmakelists:is_file() then + return Result:new( + Types.CANNOT_FIND_CMAKE_CONFIGURATION_FILE, + nil, + "Cannot find CMakeLists.txt at cwd." + ) + end + return Result:new(Types.SUCCESS, cmakelists, "cmake-tools has found CMakeLists.txt.") +end + function utils.show_cmake_console(cmake_console_size) vim.api.nvim_command("copen " .. cmake_console_size) vim.api.nvim_command("wincmd j") @@ -133,18 +145,6 @@ function utils.has_active_job() return false end -function utils.get_cmake_configuration() - local cmakelists = Path:new(vim.loop.cwd(), "CMakeLists.txt") - if not cmakelists:is_file() then - return Result:new( - Types.CANNOT_FIND_CMAKE_CONFIGURATION_FILE, - nil, - "Cannot find CMakeLists.txt at cwd." - ) - end - return Result:new(Types.SUCCESS, cmakelists, "cmake-tools has found CMakeLists.txt.") -end - function utils.rmdir(dir) local _dir = Path:new(vim.loop.cwd(), dir) if _dir:exists() then