Skip to content

Instantly share code, notes, and snippets.

@johnd0e
Last active June 8, 2025 21:35
Show Gist options
  • Save johnd0e/9ee42fafec787fc822cae9daeaa24f20 to your computer and use it in GitHub Desktop.
Save johnd0e/9ee42fafec787fc822cae9daeaa24f20 to your computer and use it in GitHub Desktop.
Fix MoonScript line numbers in error messages, for FAR Manager environment
--luacheck: globals lpeg debug.traceback_ ;new_globals debug.traceback
--luacheck: ignore 231/S
if select(2,...)>1 then return end --runonce
-- modified from https://github.com/leafo/moonscript/blob/master/moonscript/util.lua#L34
require"moonscript.util".pos_to_line = function(str, pos)
local line = 1
for _ in string.sub(str,1,pos):gmatch("\n") do
line = line + 1
end
return line
end
-- modified from https://github.com/leafo/moonscript/blob/master/moonscript/errors.moon#L44
local rewrite_traceback
rewrite_traceback = function(text, err, thread)
local line_tables = require("moonscript.line_tables")
local V, S, Ct, C
V, S, Ct, C = lpeg.V, lpeg.S, lpeg.Ct, lpeg.C
local header_text = "stack traceback:"
local Header, Line = V("Header"), V("Line")
local Break = lpeg.S("\n")
local g = lpeg.P({
Header,
Header = header_text * Break * Ct(Line ^ 1),
Line = "\t" * C((1 - Break) ^ 0) * (Break + -1)
})
local cache = { }
-- added ----------------
local reverse_line_number = require"moonscript.errors".reverse_line_number
local level = thread and 0 or 1
local function getFullName (short_src, line)
line = tonumber(line)
repeat
local info = debug.getinfo(unpack({thread,level,"Sl"}, thread and 1 or 2))
if info and info.short_src==short_src then
if info.currentline==line or info.linedefined==line
or info.currentline==-1 and info.linedefined<line and info.lastlinedefined>=line then
return info.source:match"^@(.+)"
end
end
level = level+1
until not info
--far.Message("Unable to reverse traceback line", "MoonScript", nil, "w")--debug
end
local concat = table.concat
-- enhanced ---------------
local function rev (str,fname,line,trail)
local fullname = fname and getFullName(fname,line)
local tbl = fullname and line_tables["@" .. fullname]
local rev_line = tbl and reverse_line_number(fullname, tbl, line, cache)
return rev_line and str:gsub(":"..line..trail, (":%s (%s)%s"):format(rev_line, line, trail))
end
local function rewrite_single (trace)
return trace
:gsub('^((.-):(%d+)(:))', rev)
:gsub('(: in function <(.-):(%d+)(>))$', rev)
end
-------------------------
err = err and rewrite_single(err)
local match = g:match(text)
if not (match) then
return nil
end
for i, trace in ipairs(match) do
match[i] = rewrite_single(trace)
end
local parts = {
err,
header_text,
"\t" .. concat(match, "\n\t")
}
if not err then table.remove(parts,1) end
return concat(parts, "\n")
end
debug.traceback_ = debug.traceback_ or debug.traceback -- save original
-- based on https://github.com/leafo/moonscript/blob/master/bin/moon.moon#L83
function debug.traceback (...)
local thread,err,level = ...
if type(thread)~="thread" then
thread,err,level = nil,...
end
if level~=nil and type(level)~="number" then
far.Message("Unexpected traceback level type: "..type(level))
level = nil
end
if select("#",...)>(thread and 1 or 0) and type(err)~="string" then
-- standard traceback function behavior
return err
end
if not thread then
level = level and level+1 or 2
end
local trace = debug.traceback_(unpack({thread, "", level}, thread and 1 or 2))
local util = require"moonscript.util"
--local errors = require"moonscript.errors"
--local truncated = errors.truncate_traceback(util.trim(trace))
local truncated = util.trim(trace)
return rewrite_traceback(util.trim(truncated), err, thread)
or table.concat({ err, util.trim(trace) }, "\n")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment