mirror of
https://github.com/Doodle3D/doodle3d-firmware.git
synced 2024-12-22 11:03:48 +01:00
Initial version of log filter/highlight script.
This commit is contained in:
parent
1439bd0434
commit
b29eb5289e
20
src/script/loglite-filters.lua
Normal file
20
src/script/loglite-filters.lua
Normal file
@ -0,0 +1,20 @@
|
||||
local M = {}
|
||||
|
||||
M.printstart = {
|
||||
['options'] = { ['mode'] = 'delete' },
|
||||
['patterns'] = {
|
||||
['print started'] = '_uppercase,bwhite'
|
||||
}
|
||||
}
|
||||
|
||||
M.test = {
|
||||
['options'] = { 'delete_mode' },
|
||||
['patterns'] = {
|
||||
['(verbose)'] = 'underline,cyan,_delete'
|
||||
['(info)'] = 'magenta',
|
||||
['ABSD'] = '_nodelete',
|
||||
['SE?RV?'] = 'bblue'
|
||||
}
|
||||
}
|
||||
|
||||
return M
|
183
src/script/loglite.lua
Normal file
183
src/script/loglite.lua
Normal file
@ -0,0 +1,183 @@
|
||||
-- Notes
|
||||
-- * directives: either a color, a color prefixed by 'b' or one of: _delete, _nodelete, [_matchonly]
|
||||
-- * pattern rules are matched top to bottom, the last one encountered overriding any previous conflicting directive
|
||||
--
|
||||
-- TODO:
|
||||
-- * move script to firmware repo (since it's shared between that and print3d) and remove commit from print3d
|
||||
-- * pre-split keyword lists for efficiency?
|
||||
-- * keep formats separate and only concat in the end, so things like upperasing can work properly
|
||||
-- * add more directives like uppercase, prefix/suffix?
|
||||
-- * options: en/dis total count, en/dis match count (how to deal with multiple matches?), en/dis keep_mode / delete_mode/
|
||||
-- * create named sets of options+patterns to allow for task-specific filter sets - choose/parse options and includes (pcall require()d) in main and pass on to workhorse function
|
||||
-- * add specialized patterns for levels/modules?
|
||||
--
|
||||
-- FIXME:
|
||||
-- * with deleteMode enabled, multiple matches and _nodelete in a later match, previous directives are ignored
|
||||
|
||||
--[[
|
||||
-- * https://stackoverflow.com/questions/17363973/how-can-i-tail-f-a-log-filetruncate-aware-in-lua
|
||||
-- * http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html
|
||||
]]--
|
||||
|
||||
|
||||
--[[========================================================================]]--
|
||||
|
||||
local ANSI_COLORS = {
|
||||
['blink'] = 5, -- no dice on osx/iterm2
|
||||
['underline'] = 24, -- no dice on osx/iterm2
|
||||
['black'] = 30,
|
||||
['red'] = 31,
|
||||
['green'] = 32,
|
||||
['yellow'] = 33,
|
||||
['blue'] = 34,
|
||||
['magenta'] = 35,
|
||||
['cyan'] = 36,
|
||||
['white'] = 37,
|
||||
['bblack'] = 40,
|
||||
['bred'] = 41,
|
||||
['bgreen'] = 42,
|
||||
['byellow'] = 43,
|
||||
['bblue'] = 44,
|
||||
['bmagenta'] = 45,
|
||||
['bcyan'] = 46,
|
||||
['bwhite'] = 47
|
||||
}
|
||||
|
||||
local ESCAPE_STR = string.char(27) .. "["
|
||||
local RESET_CODE = ESCAPE_STR .. "m"
|
||||
local DFL_FILTERSET_FILE = "loglite-filters.lua"
|
||||
|
||||
local DEFAULT_FILTERSET = {
|
||||
['options'] = { 'default_enabled', 'keep_mode' },
|
||||
['patterns'] = {
|
||||
['(error)'] = 'red',
|
||||
['(warning)'] = 'yellow',
|
||||
['(bulk)'] = 'gray'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
--- Stringifies the given object.
|
||||
-- From util/utils.lua
|
||||
-- Note that self-referencing objects will cause an endless loop with the current implementation.
|
||||
-- @param o The object to convert.
|
||||
-- @treturn string Stringified version of o.
|
||||
local function dump(o)
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
for k,v in pairs(o) do
|
||||
if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||
s = s .. '['..k..'] = ' .. dump(v) .. ','
|
||||
end
|
||||
return s .. '} '
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
|
||||
--- Splits a string on a given divider character.
|
||||
-- From util/utils.lua
|
||||
-- @string[opt=':'] div The divider character to use.
|
||||
-- @return An array containing the resultant substrings.
|
||||
-- @usage local str = "a,b,c"; local parts = str:split(',')
|
||||
function string:split(div)
|
||||
local div, pos, arr = div or ':', 0, {}
|
||||
for st,sp in function() return self:find(div, pos, true) end do
|
||||
table.insert(arr, self:sub(pos, st - 1))
|
||||
pos = sp + 1
|
||||
end
|
||||
table.insert(arr, self:sub(pos))
|
||||
return arr
|
||||
end
|
||||
|
||||
local function makeAnsiCode(key)
|
||||
if not ANSI_COLORS[key] then return nil end
|
||||
return ESCAPE_STR .. ANSI_COLORS[key] .. 'm'
|
||||
end
|
||||
|
||||
local function hasValue(t, needle)
|
||||
for k,v in pairs(t) do
|
||||
if needle == v then return k end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[[========================================================================]]--
|
||||
|
||||
local function tailStream(stream, patterns, options)
|
||||
local c = 0
|
||||
for line in stream:lines() do
|
||||
--c = c + 1 -- Note: this would also count deleted lines
|
||||
local embellished = line
|
||||
local keepLine = (options.mode == 'keep')
|
||||
local keepLineOverridden = false
|
||||
|
||||
-- look for a pattern matching this line
|
||||
for p,c in pairs(patterns) do
|
||||
if line:match(p) then
|
||||
-- print("+matched rule '" .. p .. "'/'" .. c .. "' against '" .. line .. "'")
|
||||
local kws = c:split(',')
|
||||
|
||||
if hasValue(kws, '_delete') then keepLine = false; keepLineOverridden = true
|
||||
elseif hasValue(kws, '_nodelete') then keepLine = true; keepLineOverridden = true
|
||||
end
|
||||
|
||||
if keepLine then
|
||||
-- first collect formatting sequences
|
||||
local fmt = ''
|
||||
for _,kw in ipairs(kws) do
|
||||
local code = makeAnsiCode(kw)
|
||||
if code then fmt = fmt .. code end
|
||||
end
|
||||
|
||||
-- then wrap the line in formatting, if any
|
||||
if fmt:len() > 0 then embellished = fmt .. embellished .. RESET_CODE end
|
||||
else
|
||||
-- Note: break out of loop and stop processing when line should be deleted _if_ the default has been overridden to do so
|
||||
if keepLineOverridden then
|
||||
embellished = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--break -- Note: don't break, allow multiple matches per line, e.g. to mix and match fg and bg colors
|
||||
end
|
||||
end
|
||||
|
||||
if embellished and keepLine then
|
||||
c = c + 1
|
||||
|
||||
if options.count == 'all' then print(c, embellished)
|
||||
else print(embellished) end
|
||||
else
|
||||
-- print("-skipped '"..line.."'")
|
||||
end
|
||||
|
||||
--c = line:match 'truncated' and 0 or c -- from tail on stderr apparently
|
||||
end
|
||||
end
|
||||
|
||||
local function main()
|
||||
if #arg > 0 and arg[1] == "-h" or arg[1] == "--help" then
|
||||
print("Usage: either pass file to tail as argument, or pipe through stdin.")
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
local followFile = #arg > 0 and arg[1] or nil
|
||||
|
||||
--print("following file: '" .. (followFile and followFile or "<stdin>") .. "'.")
|
||||
|
||||
|
||||
--local tailin = io.popen('tail -F '..(...)..' 2>&1', 'r')
|
||||
local tailin = followFile and io.popen('tail -f ' .. followFile, 'r') or io.stdin
|
||||
|
||||
local patterns = DEFAULT_FILTERSET.patterns
|
||||
local options = { ['mode'] = 'keep', count = 'all' }
|
||||
|
||||
pcall(tailStream, tailin, patterns, options) -- Note: protected call to suppress interrupt error thrown by lines iterator
|
||||
end
|
||||
|
||||
main()
|
||||
os.exit(0)
|
Loading…
Reference in New Issue
Block a user