diff --git a/ansicolors.lua b/ansicolors.lua index 3e0ad31..8a1334a 100644 --- a/ansicolors.lua +++ b/ansicolors.lua @@ -19,9 +19,10 @@ -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -local ansicolors = {} +local keys = { + -- reset + reset = 0, -local codes = { -- misc bright = 1, dim = 2, @@ -51,54 +52,39 @@ local codes = { whitebg = 47 } -local codeNames = {} -for name,_ in pairs(codes) do table.insert(codeNames, name) end -table.sort(codeNames, function(a,b) return codes[a] > codes[b] end) - local escapeString = string.char(27) .. '[%dm' local function escapeNumber(number) return escapeString:format(number) end -local function escapeNumbers(numbers) - local buffer = {} - for i=1, #numbers do - table.insert(buffer, escapeNumber(numbers[i])) - end - return table.concat(buffer) -end +local reset = escapeNumber(keys.reset) -local reset = escapeNumber(0) +local function escapeKeys(text) -local function options2numbers(options) - local numbers, substitutions, codeName = {}, 0 - for i = 1, #codeNames do - codeName = codeNames[i] - options, substitutions = options:gsub(codeName, '') - if substitutions > 0 then - table.insert(numbers, codes[codeName]) - end + local buffer = {} + local number + for word in text:gmatch("%w+") do + number = keys[word] + assert(number, "Unknown key: " .. word) + table.insert(buffer, escapeNumber(number) ) end - return numbers -end -function ansicolors.colorize( options, text ) - options = string.lower(options or '') - - local numbers = options2numbers(options) + return table.concat(buffer) +end - if #numbers == 0 then return text end - - return escapeNumbers(numbers) .. text .. reset +local function replaceCodes(text) + text = string.gsub(text,"(%%{(.-)})", function(_, text) return escapeKeys(text) end ) + return reset .. text .. reset end +-- public -local mt = {} +local function ansicolors( text ) + text = tostring(text or '') -function mt.__index(_, name) - return function(str) return ansicolors.colorize(name, str) end + return replaceCodes(text) end -setmetatable(ansicolors, mt) + return ansicolors diff --git a/specs/ansicolors_spec.lua b/specs/ansicolors_spec.lua index 6ebeed5..1ff3336 100644 --- a/specs/ansicolors_spec.lua +++ b/specs/ansicolors_spec.lua @@ -4,51 +4,24 @@ local c27 = string.char(27) describe('ansicolors', function() - describe('.colorize', function() - - it('should do nothing with no options', function() - assert_equal(ansicolors.colorize(nil, 'foo'), 'foo') - end) - - it('should add red color to text', function() - assert_equal(ansicolors.colorize('red', 'foo'), c27 .. '[31mfoo' .. c27 .. '[0m') - end) - - it('should add red color to text with uppercase', function() - assert_equal(ansicolors.colorize('Red', 'foo'), c27 .. '[31mfoo' .. c27 .. '[0m') - end) - - it('should add red underlined text', function() - assert_equal(ansicolors.colorize('UnderlineRed', 'foo'), c27 .. '[31m' .. c27 .. '[4mfoo' .. c27 .. '[0m') - end) - - it('should parse the red background before the red foreground', function() - assert_equal(ansicolors.colorize('RedBG', 'foo'), c27 .. '[41mfoo' .. c27 .. '[0m') - end) - - it('should allow multiple attributes and spureous chars', function() - assert_equal(ansicolors.colorize('underline_redbg_yellow_dim', 'foo'), c27 .. '[41m' .. c27 .. '[33m' .. c27 .. '[4m' .. c27 .. '[2mfoo' .. c27 .. '[0m') - end) - - it('should ignore order', function() - assert_equal(ansicolors.colorize('underline_redbg_yellow', 'foo'), ansicolors.colorize('yellowRedBGUnderline', 'foo')) - end) - + it('should add resets if no options given', function() + assert_equal(ansicolors('foo'), c27 .. '[0m' .. 'foo' .. c27 .. '[0m' ) end) - describe('__call', function() - - it('should work with any method, throwing no errors', function() - assert_not_error(function() ansicolors.foo('foo') end) - assert_not_error(function() ansicolors.red('foo') end) - end) + it('should throw an error on invalid options', function() + assert_error(function() ansicolors('%{blah}foo') end) + end) + + it('should add red color to text', function() + assert_equal(ansicolors('%{red}foo'), c27 .. '[0m' .. c27 .. '[31mfoo' .. c27 .. '[0m') + end) - it('should work just like colorize', function() - assert_equal(ansicolors.red('foo'), ansicolors.colorize('red', 'foo') ) - assert_equal(ansicolors.underline_redbg_yellow('foo'), ansicolors.colorize('yellowRedBGUnderline', 'foo')) - end) + it('should add red underlined text', function() + assert_equal(ansicolors('%{red underline}foo'), c27 .. '[0m' .. c27 .. '[31m' .. c27 .. '[4mfoo' .. c27 .. '[0m') + end) + it('should with heterogeneous attributes', function() + assert_equal(ansicolors('%{bright white}*%{bright red}BEEP%{bright white}*'), c27 .. '[0m' .. c27 .. '[1m' .. c27 .. '[37m*' .. c27 .. '[1m' .. c27 .. '[31mBEEP' .. c27 .. '[1m' .. c27 .. '[37m*' .. c27 .. '[0m') end) - - + end)