Port "not" and "or" modifiers to new criteria objects

This commit is contained in:
Jason Perkins 2012-10-31 19:34:53 -04:00
parent 837b3afbeb
commit 6c19509737
5 changed files with 121 additions and 78 deletions

View File

@ -6,31 +6,11 @@
-- Copyright (c) 2012 Jason Perkins and the Premake project -- Copyright (c) 2012 Jason Perkins and the Premake project
-- --
local configset = premake.configset
--
-- Create a "root" configuration set, to hold the global configuration. Values
-- that are added to this set become available for all add-ons, solution, projects,
-- and on down the line.
--
configset.root = configset.new()
local root = configset.root
-- --
-- Set up the global environment for the systems I know about. I would like to see -- Set up the global environment for the systems I know about. I would like to see
-- at least some if not all of this moved into add-ons in the future. -- at least some if not all of this moved into add-ons in the future.
-- --
-- TODO: use the same configuration API as the user project scripts, once they
-- have been ported, like:
--
-- configuration { "Windows or Xbox360", "SharedLib" }
-- targetprefix ""
-- targetextension ".dll"
-- implibextension ".lib"
--
-- --
-- Use Posix-style target naming by default, since it is the most common. -- Use Posix-style target naming by default, since it is the most common.
@ -60,47 +40,14 @@
-- Windows and friends. -- Windows and friends.
-- --
configuration { "Windows", "ConsoleApp" } configuration { "Windows or Xbox360 or C#", "ConsoleApp or WindowedApp" }
targetextension ".exe" targetextension ".exe"
configuration { "Windows", "WindowedApp" } configuration { "Windows or Xbox360 or C#", "SharedLib" }
targetextension ".exe"
configuration { "Windows", "SharedLib" }
targetprefix "" targetprefix ""
targetextension ".dll" targetextension ".dll"
implibextension ".lib" implibextension ".lib"
configuration { "Windows", "StaticLib" } configuration { "Windows or Xbox360 or C#", "StaticLib" }
targetprefix "" targetprefix ""
targetextension ".lib" targetextension ".lib"
configuration { "Xbox360", "ConsoleApp" }
targetextension ".exe"
configuration { "Xbox360", "WindowedApp" }
targetextension ".exe"
configuration { "Xbox360", "SharedLib" }
targetprefix ""
targetextension ".dll"
implibextension ".lib"
configuration { "Xbox360", "StaticLib" }
targetprefix ""
targetextension ".lib"
--
-- .NET languages always use Windows-style naming.
--
configuration { "C#", "ConsoleApp" }
targetextension ".exe"
configuration { "C#", "WindowedApp" }
targetextension ".exe"
configuration { "C#", "SharedLib" }
targetprefix ""
targetextension ".dll"

View File

@ -27,7 +27,6 @@
} }
-- --
-- A place to store the current active objects in each project scope. -- A place to store the current active objects in each project scope.
-- --
@ -35,6 +34,16 @@
api.scope = {} api.scope = {}
--
-- Create a "root" configuration set, to hold the global configuration. Values
-- that are added to this set become available for all add-ons, solution, projects,
-- and on down the line.
--
configset.root = configset.new()
local root = configset.root
-- --
-- Register a new API function. See the built-in API definitions below -- Register a new API function. See the built-in API definitions below
-- for usage examples. -- for usage examples.
@ -1211,7 +1220,7 @@
-- TODO: Fetch the current config set from api.scope instead -- TODO: Fetch the current config set from api.scope instead
local container = api.scope.project or api.scope.solution or {} local container = api.scope.project or api.scope.solution or {}
local cset = container.configset or configset.root local cset = container.configset or configset.root
configset.addblock(cset, terms) configset.addblock(cset, {terms})
-- OLD APPROACH: -- OLD APPROACH:
-- TODO: Phase this out ASAP -- TODO: Phase this out ASAP

View File

@ -56,12 +56,8 @@
function configset.addblock(cfgset, terms) function configset.addblock(cfgset, terms)
local block = {} local block = {}
-- convert terms to a simple, all-lower-case array -- attach a criteria object to the block to control its application
terms = table.flatten({ terms }) block.criteria = criteria.new(terms)
for i, term in ipairs(terms) do
terms[i] = term:lower()
end
block.terms = terms
table.insert(cfgset.blocks, block) table.insert(cfgset.blocks, block)
cfgset.current = block cfgset.current = block
@ -108,7 +104,7 @@
local value = nil local value = nil
for _, block in ipairs(cfgset.blocks) do for _, block in ipairs(cfgset.blocks) do
if criteria.matches(block.terms, context) then if criteria.matches(block.criteria, context) then
value = block[fieldname] or value value = block[fieldname] or value
end end
end end

View File

@ -24,15 +24,21 @@
-- A new criteria object. -- A new criteria object.
-- --
function criteria.new(terms) function criteria.new(terms)
terms = table.flatten(terms) terms = table.flatten(terms)
-- make future tests case-insensitive -- convert Premake wildcard symbols into the appropriate Lua patterns; this
for i, term in ipairs(terms) do -- list of patterns is what will actually be tested against
terms[i] = term:lower() local patterns = {}
for _, term in ipairs(terms) do
local pattern = path.wildcards(term):lower()
table.insert(patterns, pattern)
end end
return terms local crit = {}
crit.terms = terms
crit.patterns = patterns
return crit
end end
@ -49,16 +55,25 @@
-- --
function criteria.matches(crit, context) function criteria.matches(crit, context)
local checkterm = function(term)
for _, value in ipairs(context) do function testpattern(pattern)
if value:match(term) == value then for _, part in ipairs(pattern:explode(" or ")) do
return true if part:startswith("not ") then
return not testpattern(part:sub(5))
end
for _, value in ipairs(context) do
if value:match(part) == value then
return true
end
end end
end end
return false
end end
for _, term in ipairs(crit) do for _, pattern in ipairs(crit.patterns) do
if not checkterm(term) then if not testpattern(pattern) then
return false return false
end end
end end

View File

@ -55,3 +55,79 @@
crit = criteria.new { "ps3" } crit = criteria.new { "ps3" }
test.isfalse(criteria.matches(crit, { "ps3 ppu sn" })) test.isfalse(criteria.matches(crit, { "ps3 ppu sn" }))
end end
--
-- Wildcard matches should work.
--
function suite.passes_onPatternMatch()
crit = criteria.new { "vs*" }
test.istrue(criteria.matches(crit, { "vs2005" }))
end
--
-- The "not" modifier should fail the test if the term is matched.
--
function suite.fails_onNotMatch()
crit = criteria.new { "not windows" }
test.isfalse(criteria.matches(crit, { "windows" }))
end
function suite.passes_onNotUnmatched()
crit = criteria.new { "not windows" }
test.istrue(criteria.matches(crit, { "linux" }))
end
--
-- The "or" modifier should pass if either term is present.
--
function suite.passes_onFirstOrTermMatched()
crit = criteria.new { "windows or linux" }
test.istrue(criteria.matches(crit, { "windows" }))
end
function suite.passes_onSecondOrTermMatched()
crit = criteria.new { "windows or linux" }
test.istrue(criteria.matches(crit, { "linux" }))
end
function suite.passes_onThirdOrTermMatched()
crit = criteria.new { "windows or linux or vs2005" }
test.istrue(criteria.matches(crit, { "vs2005" }))
end
function suite.fails_onNoOrTermMatched()
crit = criteria.new { "windows or linux" }
test.isfalse(criteria.matches(crit, { "vs2005" }))
end
--
-- The "not" modifier should fail on any match with an "or" modifier.
--
function suite.passes_onNotOrMatchesFirst()
crit = criteria.new { "not windows or linux" }
test.isfalse(criteria.matches(crit, { "windows" }))
end
function suite.passes_onNotOrMatchesSecond()
crit = criteria.new { "windows or not linux" }
test.isfalse(criteria.matches(crit, { "linux" }))
end
--
-- The "not" modifier should succeed with "or" if there are no matches.
--
function suite.passes_onNoNotMatch()
crit = criteria.new { "not windows or linux" }
test.istrue(criteria.matches(crit, { "macosx" }))
end