repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
neovim/lua/std/dbg.lua.bak
Rawlocal user_command = require 'std.user_command'
local icon = require 'std.icon'
local DBG_FILE = vim.fn.stdpath 'state' .. '/bugabinga_config_debug.jsonl'
---Debug kinds and their mapped highlight groups and icons.
---@type table<string,[string, string]>
local DBG_KINDS = {
--TODO
DEBUG = {},
TRACE = {},
ERROR = {},
}
---@alias dbg_kind
---| 'DEBUG' normal debug event -> use this, when logging debug information
---| 'TRACE' function trace event -> use this, when tracing function call flow
---| 'ERROR' error event -> use this, when logging unexpected events
---Get context information from `debug.traceback()` and other `debug` functions.
---Wwhen getting the stacktrace, we need to account for the function call graph inside this `dbg` module.
---Either its: `callsite -> metatable -> print_debug -> print_debug_kind -> get_context`.
---Or: `callsite -> print_debug_kind -> get_context`.
---In both cases we are only interested in callsite to determine file name, the function name and line number.
---
---@return string filename The filename, the calling function resides in.
---@return string function_name The name of the function, where `dbg` was called in.
---@return integer line_number Line number the calling functions is invoking the `dbg` function at.
local function get_context()
--TODO
local filename = nil
local function_name = nil
local line_number = nil
return filename, function_name, line_number
end
--- Encodes debug event to JSON
--- @param event table<string, table, string, table, string, string, integer> debug event to log
--- @return string json JSON-encoded debug event
local function encode( event )
return vim.json.encode( event, {
escape_slash = true,
} )
end
--- Decodes debug event from JSON
--- @param line string JSON-encoded debug event
--- @return table<string, table, string, table, string, string, integer> event debug event to log
local function decode( line )
return vim.json.decode( line, {
luanil = {
object = true,
array = true,
},
} )
end
--- Writes debug events to the debug file, one per line.
---
--- @see encode
--- @param event table<string, table, string, table, string, string, integer> debug event to log
local function write_to_debug_file( event )
local file, errmsg = io.open( DBG_FILE, 'a+' )
if not file then
error( 'Unable to open debug log file `' .. DBG_FILE .. '`: ' .. errmsg )
end
local json_line = encode( event )
file:write( json_line )
file:flush()
file:close()
end
---Replaces expressions inside the given `format`, by indexing into `user_data`.
---
---Resolve `format`, by replacing `{<expr>}` inside format string.
---`<expr>` is used to index into `user_data`.
---e.g.: `user_data = {a = 1, b = 2, c = 3}`
---To get `b`: the format expression would be `{b}`.
---`{b}` would be replaced by `2` in format string.
---
---e.g.: `user_data = {{a=1},{b=2},{c=3}}`
---To index into nested structures, use numbers: `{2.b}`.
---`{2.b}` would be replaced by `2` in format string.
---Indexing is 1-based, as per usual in lua.
---Values are converted by `vim.inspect` to strings.
---
---@see vim.inspect
---
---@param format string Message with optional "{}"-style expressions inside
---@param data table Arbitrary data, that can be indexed into, to pick values for the `format` string
---@return string formatted_message Message with format expressions resolved
local function format_message( format, data )
local formatted_message
--TODO
return formatted_message
end
if vim.g.bugabinga_debug_mode == nil then
vim.g.bugabinga_debug_mode = false
end
local function is_debug_mode()
return vim.g.bugabinga_debug_mode
end
---Log debug message of particular kind.
---@param kind dbg_kind kind of event
---@param message string message format string
---@param ... any arbitrary user data, that can be referenced in message format
local function print_debug_kind( kind, message, ... )
if not is_debug_mode() then
return
end
local now = os.date '!*t'
local user_data = { ... }
local filename, function_name, line_number = get_context()
write_to_debug_file {
kind = kind,
date = now,
format = message,
data = user_data,
filename = filename,
fn = function_name,
line = line_number,
}
end
---Log a debug event.
---@param message string message format string
---@param ... any arbitrary user data, that can be referenced in message format
local function print_debug( message, ... )
if not is_debug_mode() then
return
end
print_debug_kind( 'DEBUG', message, ... )
end
local function toggle_debug_mode()
vim.g.bugabinga_debug_mode = not vim.g.bugabinga_debug_mode
vim.notify( 'Toggled debug mode to ' .. tostring( is_debug_mode() ) )
end
--- Opens the debug file in a special buffer, that is not modifiable.
--- It renders the debug events in a table with special functions:
--- - filter by type
--- - jump to location
--- - colors and icons for different kinds
--- Filters are a label, e.g. "Filter by kind: " plus a special region after it on one line in the buffer above the table.
--- Typing in that region activates the filtering in the table.
---
--- Icons are shown as prefix to kind values in their cells: <icon> <KIND>.
--- The table rows are highlighted according to kinds in `DBG_KINDS`.
--- Note: table row can be multiline because of formatted messages. Highlighting needs to account for that.
---
--- Pressing enter while the cursor is on a table row, jumps to this events location.
---
--- Debug events are read and decoded from `DBG_FILE` and converted to a table of:
--- Kind, Date, Message, Location
---
--- Kind -> debug event kind + icon
--- Date -> human readable datetime in hosts timezone
--- Message -> formatted message from format string and user data
--- Locataion -> combined file name, function name and line number
local function open_special_debug_buffer()
--TODO
end
--- Opens the file `DBG_FILE` in a normal neovim buffer
local function open_raw_debug_file()
--TODO
end
user_command.Debug 'Toggle global vim config debug mode.' ( toggle_debug_mode )
user_command.DebugOpen 'Open special buffer with debug events' ( open_special_debug_buffer )
user_command.DebugOpenRaw 'Opens the JSON debug file in normal buffer' ( open_raw_debug_file )
return setmetatable(
{
kind = print_debug_kind,
toggle = toggle_debug_mode,
get = is_debug_mode,
}, {
--TODO: refactor usages of this function in other code to new name
__call = print_debug,
__newindex = function ( ... )
error(
'Assignments are not supported for std.dbg.\n' .. vim.inspect( ... ), 2 )
end,
} )