diff options
| author | ruki <[email protected]> | 2016-01-23 21:01:42 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2016-02-15 19:10:25 +0800 |
| commit | b8b1b5129ddcc0154e701dbac023f19ae1a3bf8c (patch) | |
| tree | 01049fc26145c1fed661984d33cd362bcc2923b4 | |
| parent | 1dc00c7159433c07412c5081388aafbe93040186 (diff) | |
reimpl template
| -rw-r--r-- | xmake/core/action/_create.lua | 56 | ||||
| -rw-r--r-- | xmake/core/base/interpreter.lua | 181 | ||||
| -rw-r--r-- | xmake/core/base/table.lua | 40 | ||||
| -rw-r--r-- | xmake/core/base/template.lua | 121 | ||||
| -rw-r--r-- | xmake/core/base/utils.lua | 5 | ||||
| -rw-r--r-- | xmake/templates/c/console/template.lua | 5 |
6 files changed, 325 insertions, 83 deletions
diff --git a/xmake/core/action/_create.lua b/xmake/core/action/_create.lua index 840631f65..39c3ba83a 100644 --- a/xmake/core/action/_create.lua +++ b/xmake/core/action/_create.lua @@ -24,6 +24,7 @@ local _create = _create or {} -- load modules +local path = require("base/path") local utils = require("base/utils") local template = require("base/template") @@ -47,64 +48,13 @@ function _create.done() -- trace utils.printf("create %s ...", targetname) - -- the language - local language = options.language - if not language then - utils.error("no language!") - return false - end - - -- the template id - local templateid = tonumber(options.template) - if type(templateid) ~= "number" then - utils.error("invalid template id: %s!", options.template) - return false - end - - -- load all templates for the given language - local templates = template.loadall(language) - - -- load the template module - local module = nil - if templates then module = templates[templateid] end - if not module then - utils.error("invalid template id: %s!", options.template) - return false - end - - -- enter the template directory - if not module._DIRECTORY or not os.cd(module._DIRECTORY) then - -- error - utils.error("not found template id: %s!", options.template) - return false - end - - -- check the template project - if not os.isdir("project") then - -- errors - utils.error("the template project not exists!") - return false - end - - -- ensure the project directory - if not os.isdir(xmake._PROJECT_DIR) then - os.mkdir(xmake._PROJECT_DIR) - end - - -- copy the project files - local ok, errors = os.cp("project/*", xmake._PROJECT_DIR) + -- create project from template + local ok, errors = template.create(options.language, options.template, targetname) if not ok then - -- errors utils.error(errors) return false end - -- done the template files - if not module.done(targetname, xmake._PROJECT_DIR, xmake._PACKAGES_DIR) then - utils.error("update the template failed!") - return false - end - -- trace utils.printf("create %s ok!", targetname) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 8ad27d64f..acca229dd 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -256,39 +256,63 @@ function interpreter._filter(self, values, filter) -- check assert(self and values and filter) - -- done - local results = {} - for _, value in ipairs(utils.wrap(values)) do + -- replace value + local replace = function (value) - -- only filter string value - if type(value) == "string" then + -- replace the builtin variables + return (value:gsub("%$%((.-)%)", function (variable) - -- replace the builtin variables - value = value:gsub("%$%((.-)%)", function (variable) + -- check + assert(variable) + + -- is upper? + local isupper = false + local c = string.char(variable:byte()) + if c >= 'A' and c <= 'Z' then isupper = true end - -- check - assert(variable) - - -- is upper? - local isupper = false - local c = string.char(variable:byte()) - if c >= 'A' and c <= 'Z' then isupper = true end + -- filter it + local result = filter(variable:lower()) - -- filter it - local result = filter(variable:lower()) + -- convert to upper? + if isupper and result and type(result) == "string" then + result = result:upper() + end - -- convert to upper? - if isupper and result and type(result) == "string" then - result = result:upper() - end + -- ok? + return result + end)) + end - -- ok? - return result - end) + -- done + local results = {} + if table.is_dictionary(values) then + -- replace keyvalues + for key, value in pairs(values) do + results[replace(key)] = replace(value) end + else + for _, value in ipairs(utils.wrap(values)) do + + -- string? + if type(value) == "string" then + + -- replace value + value = replace(value) + + -- array? + elseif table.is_array(value) then - -- append value - table.insert(results, value) + -- replace values + local values = {} + for _, v in ipairs(value) do + table.insert(values, replace(v)) + end + value = values + end + + -- append value + table.insert(results, value) + end end -- ok? @@ -306,7 +330,7 @@ function interpreter._handle(self, scope, remove_repeat, enable_filter, filter) for name, values in pairs(scope) do -- remove repeat first - if remove_repeat then + if remove_repeat and not table.is_dictionary(values) then values = utils.unique(values) end @@ -343,10 +367,10 @@ function interpreter._make(self, scope_kind, remove_repeat, enable_filter) local results = {} if scope_kind then - -- the scope for kind + -- not this scope for kind? local scope_for_kind = scopes[scope_kind] if not scope_for_kind then - return nil, string.format("this scope kind: %s not found!", scope_kind) + return nil end -- the root scope @@ -700,6 +724,107 @@ function interpreter.api_register_add_values(self, scope_kind, prefix, ...) self:_api_register_xxx_values(scope_kind, "add", prefix, implementation, ...) end +-- register api for set_array +function interpreter.api_register_set_array(self, scope_kind, prefix, ...) + + -- check + assert(self) + + -- define implementation + local implementation = function (self, scope, name, ...) + + -- update array? + scope[name] = {} + table.insert(scope[name], {...}) + + end + + -- register implementation + self:_api_register_xxx_values(scope_kind, "set", prefix, implementation, ...) +end + +-- register api for add_array +function interpreter.api_register_add_array(self, scope_kind, prefix, ...) + + -- check + assert(self) + + -- define implementation + local implementation = function (self, scope, name, ...) + + -- append array? + scope[name] = scope[name] or {} + table.insert(scope[name], {...}) + + end + + -- register implementation + self:_api_register_xxx_values(scope_kind, "add", prefix, implementation, ...) +end + +-- register api for set_keyvalues +function interpreter.api_register_set_keyvalues(self, scope_kind, prefix, ...) + + -- check + assert(self) + + -- define implementation + local implementation = function (self, scope, name, ...) + + -- update keyvalues? + scope[name] = {} + table.insert(scope[name], {...}) + + end + + -- register implementation + self:_api_register_xxx_values(scope_kind, "set", prefix, implementation, ...) +end + +-- register api for add_keyvalues +function interpreter.api_register_add_keyvalues(self, scope_kind, prefix, ...) + + -- check + assert(self) + + -- define implementation + local implementation = function (self, scope, name, ...) + + -- append keyvalues? + scope[name] = scope[name] or {} + + -- the values + local values = {...} + local count = #values + + -- check count + if (count % 2) == 1 then + utils.error("add_%s() values must be key-value pair!", name) + utils.abort() + end + + -- done + local i = 0 + local keyvalues = scope[name] + while i + 2 <= count do + + -- the key and value + local key = values[i + 1] + local val = values[i + 2] + + -- insert key and value + keyvalues[key] = val + + -- next pair + i = i + 2 + end + + end + + -- register implementation + self:_api_register_xxx_values(scope_kind, "add", prefix, implementation, ...) +end + -- register api for set_pathes function interpreter.api_register_set_pathes(self, scope_kind, prefix, ...) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 52b726412..dfc5def8b 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -95,5 +95,45 @@ function table.copy2(self, copied) end +-- is array? +function table.is_array(self) + + -- not table? + if type(self) ~= "table" then + return false + end + + -- is array? + for k, v in pairs(self) do + if type(k) == "number" then + return true + end + break + end + + -- dictionary + return false +end + +-- is dictionary? +function table.is_dictionary(self) + + -- not table? + if type(self) ~= "table" then + return false + end + + -- is dictionary? + for k, v in pairs(self) do + if type(k) == "string" then + return true + end + break + end + + -- array + return false +end + -- return module: table return table diff --git a/xmake/core/base/template.lua b/xmake/core/base/template.lua index 8675d77d2..2dc7135fa 100644 --- a/xmake/core/base/template.lua +++ b/xmake/core/base/template.lua @@ -25,8 +25,11 @@ local template = template or {} -- load modules local os = require("base/os") +local io = require("base/io") local path = require("base/path") +local table = require("base/table") local utils = require("base/utils") +local string = require("base/string") local interpreter = require("base/interpreter") -- get interpreter @@ -45,6 +48,12 @@ function template._interpreter() interp:api_register_set_values(nil, nil, "description" , "projectdir") + -- register api: add_values() for root + interp:api_register_add_values(nil, nil, "macrofiles") + + -- register api: add_keyvalues() for root + interp:api_register_add_keyvalues(nil, nil, "macros") + -- save interpreter template._INTERPRETER = interp @@ -52,6 +61,32 @@ function template._interpreter() return interp end +-- replace macros +function template._replace(macros, macrofiles) + + -- check + assert(macros and macrofiles) + + -- make all files + local files = {} + for _, macrofile in ipairs(utils.wrap(macrofiles)) do + local matchfiles = os.match(macrofile) + if matchfiles then + table.join2(files, matchfiles) + end + end + + -- replace all files + for _, file in ipairs(files) do + for macro, value in pairs(macros) do + io.gsub(file, "%[" .. macro .. "%]", value) + end + end + + -- ok + return true +end + -- get the language list function template.languages() @@ -96,6 +131,9 @@ function template.loadall(language) utils.abort() end + -- save template directory + results._DIRECTORY = path.directory(templatefile) + -- insert to templates table.insert(templates, results) @@ -106,5 +144,88 @@ function template.loadall(language) return templates end +-- create project from template +function template.create(language, templateid, targetname) + + -- check the language + if not language then + return false, "no language!" + end + + -- check the template id + if not templateid then + return false, "no template id!" + end + + templateid = tonumber(templateid) + if type(templateid) ~= "number" then + return false, "invalid template id!" + end + + -- get interpreter + local interp = template._interpreter() + assert(interp) + + -- set filter + interp:filter_set(function (variable) + + -- replace targetname + if variable == "targetname" then + variable = targetname + end + + -- ok? + return variable + + end) + + -- load all templates for the given language + local templates = template.loadall(language) + + -- load the template module + local module = nil + if templates then module = templates[templateid] end + if not module then + return false, string.format("invalid template id: %d!", templateid) + end + + -- enter the template directory + if not module._DIRECTORY or not os.cd(module._DIRECTORY) then + return false, string.format("not found template id: %d!", templateid) + end + + -- check the template project + if not module.projectdir or not os.isdir(module.projectdir) then + return false, string.format("the template project not exists!") + end + + -- ensure the project directory + if not os.isdir(xmake._PROJECT_DIR) then + os.mkdir(xmake._PROJECT_DIR) + end + + -- copy the project files + local ok, errors = os.cp(path.join(module.projectdir, "*"), xmake._PROJECT_DIR) + if not ok then + return false, errors + end + + -- enter the project directory + if not os.cd(xmake._PROJECT_DIR) then + return false, string.format("can not enter %s!", xmake._PROJECT_DIR) + end + + -- replace macros + if module.macros and module.macrofiles then + ok, errors = template._replace(module.macros, module.macrofiles) + if not ok then + return false, errors + end + end + + -- ok + return true +end + -- return module: template return template diff --git a/xmake/core/base/utils.lua b/xmake/core/base/utils.lua index 596826ed9..1ee861922 100644 --- a/xmake/core/base/utils.lua +++ b/xmake/core/base/utils.lua @@ -219,8 +219,9 @@ function utils.unique(array) table.insert(unique, v) end else - if not exists["\"" .. v .. "\""] then - exists["\"" .. v .. "\""] = true + local key = "\"" .. tostring(v) .. "\"" + if not exists[key] then + exists[key] = true table.insert(unique, v) end end diff --git a/xmake/templates/c/console/template.lua b/xmake/templates/c/console/template.lua index 0339fb968..09412f86d 100644 --- a/xmake/templates/c/console/template.lua +++ b/xmake/templates/c/console/template.lua @@ -4,3 +4,8 @@ set_description("The Console Program") -- set project directory set_projectdir("project") +-- add macros +add_macros("targetname", "$(targetname)") + +-- add macro files +add_macrofiles("xmake.lua") |
