--============================================================================= -- logger.lua --- logger api implemented in lua -- Copyright (c) 2016-2023 Wang Shidong & Contributors -- Author: Wang Shidong < wsdjeg@outlook.com > -- URL: https://spacevim.org -- License: GPLv3 --============================================================================= local fn = vim.fn or require('spacevim').fn local cmd = require('spacevim').cmd local M = { ['name'] = '', ['silent'] = 1, ['level'] = 1, ['verbose'] = 1, ['file'] = '', ['temp'] = {}, } -- 0 : log debug, info, warn, error messages -- 1 : log info, warn, error messages -- 2 : log warn, error messages -- 3 : log error messages M.levels = { 'Info ', 'Warn ', 'Error', 'Debug' } M.clock = fn.reltime() function M.set_silent(sl) M.silent = sl end function M.set_verbose(vb) M.verbose = vb end function M.set_level(l) -- the level only can be: -- 0 : log debug, info, warn, error messages -- 1 : log info, warn, error messages -- 2 : log warn, error messages -- 3 : log error messages if l == 0 or l == 1 or l == 2 or l == 3 then M.level = l end end function M._build_msg(msg, l) msg = msg or '' -- local time = fn.strftime('%H:%M:%S') -- error(string.format("Tried to call API function with vim.fn: use vim.api.%s instead", key)) -- local log = '[ ' .. M.name .. ' ] [' .. time .. '] [ ' .. M.levels[l] .. '] ' .. msg -- change the format to -- [ name ] [00:00:00:000] [level] msg -- https://github.com/neovim/neovim/issues/4433 -- string.format("%s:%03d", os.date("%H:%M:%S"), vim.loop.now() % 1000) -- local clock = fn.reltimefloat(fn.reltime(M.clock)) -- local h = fn.float2nr(clock / 60 / 60) -- local m = fn.float2nr(clock / 60) -- local s = fn.float2nr(clock) % 60 -- local mic = string.format('%00.3f', clock - fn.float2nr(clock)) local _, mic = vim.loop.gettimeofday() local c = string.format("%s:%03d", os.date("%H:%M:%S"), mic / 1000) local log = string.format('[ %s ] [%s] [ %s ] %s', M.name, c, M.levels[l], msg) return log end function M.debug(msg) if M.level <= 0 then local log = M._build_msg(msg, 4) if M.silent == 0 and M.verbose >= 4 then cmd('echom "' .. log .. '"') end M.write(log) end end function M.error(msg) local log = M._build_msg(msg, 3) if M.silent == 0 and M.verbose >= 1 then cmd('echohl Error') cmd('echom "' .. log .. '"') cmd('echohl None') end M.write(log) end function M.write(msg) table.insert(M.temp, msg) if M.file ~= '' then if fn.isdirectory(fn.fnamemodify(M.file, ':p:h')) == 0 then fn.mkdir(fn.expand(fn.fnamemodify(M.file, ':p:h')), 'p') end local flags = '' if fn.filereadable(M.file) == 1 then flags = 'a' end fn.writefile({ msg }, M.file, flags) end end function M.warn(msg, ...) if M.level <= 2 then local log = M._build_msg(msg, 2) if (M.silent == 0 and M.verbose >= 2) or select(1, ...) == 0 then cmd('echohl WarningMsg') cmd('echom "' .. log .. '"') cmd('echohl None') end M.write(log) end end function M.info(msg) if M.level <= 1 then local log = M._build_msg(msg, 1) if M.silent == 0 and M.verbose >= 3 then cmd('echom "' .. log .. '"') end M.write(log) end end function M.view(l) local info = '' local logs = '' if fn.filereadable(M.file) == 1 then logs = fn.readfile(M.file, '') info = info .. fn.join(fn.filter(logs, 'self._comp(v:val, a:l)'), '\n') else info = info .. '[ ' .. M.name .. ' ] : logger file ' .. M.file .. ' does not exists, only log for current process will be shown!' .. '\n' for key, value in pairs(M.temp) do if M._comp(value, l) == 1 then info = info .. value .. '\n' end end end return info end function M._comp(msg, l) -- if a:msg =~# '\[ ' . self.name . ' \] \[\d\d\:\d\d\:\d\d\] \[ ' if string.find(msg, M.levels[2]) ~= nil then return 1 elseif string.find(msg, M.levels[1]) ~= nil then if l > 2 then return 0 else return 1 end else if l > 1 then return 0 else return 1 end end end function M.set_name(name) M.name = name end function M.get_name() return M.name end function M.set_file(file) M.file = file end return M