--- Debug logging facade. Minimal by design: everything goes to one JSONL file. --- File: stdpath('state')/bugabinga_config_debug.jsonl --- --- API: --- dbg( message, ... ) -- DEBUG level, printf-style ( string.format ) --- dbg.kind( kind, message, ... ) --- dbg.print( message, ... ) -- DEBUG level, explicit method form --- dbg.get() -- is debug mode on --- dbg.toggle() --- --- Commands: :DbgModeToggle :DbgOpenFile :DbgClear local user_command = require 'std.user_command' local DBG_FILE = vim.fn.stdpath 'state' .. '/bugabinga_config_debug.jsonl' if vim.g.bugabinga_debug_mode == nil then vim.g.bugabinga_debug_mode = false end local function path() return vim.g.bugabinga_debug_file_override or DBG_FILE end local function enabled() return vim.g.bugabinga_debug_mode end -- filename, function name and line of the caller, skipping this module's frames. local function context() local level = 2 while true do local info = debug.getinfo( level, 'Sln' ) if not info then return 'unknown', '', 0 end local source = info.short_src or info.source if source and not source:match 'std/dbg' then return source, info.name or '', info.currentline or 0 end level = level + 1 end end local function log( kind, message, ... ) if not enabled() then return end local data = { ... } local ok, formatted = pcall( string.format, message, ... ) local source, fn, line = context() local event = { kind = kind, date = os.time(), message = ok and formatted or message, data = data, filename = source, fn = fn, line = line, } local file_path = path() vim.fn.mkdir( vim.fs.dirname( file_path ), 'p' ) local handle, err = io.open( file_path, 'a' ) if not handle then error( 'dbg: cannot open ' .. file_path .. ': ' .. tostring( err ) ) end handle:write( vim.json.encode( event ) .. '\n' ) handle:close() end local function toggle() vim.g.bugabinga_debug_mode = not enabled() vim.notify( 'debug mode: ' .. tostring( enabled() ) ) end user_command.DbgModeToggle 'Toggle global vim config debug mode.' ( toggle ) user_command.DbgOpenFile 'Open the JSONL debug file in a buffer' ( function () vim.cmd.edit( path() ) end ) user_command.DbgClear 'Clear the JSONL debug file' ( function () local handle = io.open( path(), 'w' ) if handle then handle:close() end end ) return setmetatable( { kind = log, print = function ( message, ... ) log( 'DEBUG', message, ... ) end, toggle = toggle, get = enabled, }, { __call = function ( _, message, ... ) log( 'DEBUG', message, ... ) end, __newindex = function ( ... ) error( 'Assignments are not supported for std.dbg.\n' .. vim.inspect( ... ), 2 ) end, } )