summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2016-01-23 21:01:42 +0800
committerruki <[email protected]>2016-02-15 19:10:25 +0800
commitb8b1b5129ddcc0154e701dbac023f19ae1a3bf8c (patch)
tree01049fc26145c1fed661984d33cd362bcc2923b4
parent1dc00c7159433c07412c5081388aafbe93040186 (diff)
reimpl template
-rw-r--r--xmake/core/action/_create.lua56
-rw-r--r--xmake/core/base/interpreter.lua181
-rw-r--r--xmake/core/base/table.lua40
-rw-r--r--xmake/core/base/template.lua121
-rw-r--r--xmake/core/base/utils.lua5
-rw-r--r--xmake/templates/c/console/template.lua5
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")