Looking mostly good, sorta working for moonscript.

This commit is contained in:
Bruce Hill 2018-03-13 03:44:03 -07:00
parent 2a1cdf7c89
commit c921ad41bd

View File

@ -1,7 +1,7 @@
C = require "curses"
repr = require 'repr'
local REGULAR, INVERTED, HIGHLIGHTED, RED, SCREEN_H, SCREEN_W
local run_debugger, cursed, stdscr, main_loop
local REGULAR, INVERTED, HIGHLIGHTED, RED, BLUE, SCREEN_H, SCREEN_W
local run_debugger, guard, stdscr, main_loop
AUTO = -1
log = io.open("output.log", "w")
@ -10,23 +10,36 @@ callstack_range = ->
min, max = 0, -1
for i=1,999 do
info = debug.getinfo(i, 'f')
if not info
error("Could not find info at level #{i}")
continue unless info
if not info then break
if info.func == main_loop
min = i+2
min = i+1
break
for i=min,999
info = debug.getinfo(i, 'f')
continue unless info
if info.func == cursed then
if not info
max = i-3
break
if info.func == guard
max = i-3
break
return min, max
wrap_text = (text, width)->
lines = {}
for line in text\gmatch("[^\n]*")
buff = ""
for word in line\gmatch("%S%S*%s*")
if #buff + #word > width
table.insert(lines, " "..buff)
buff = word
else
buff = buff .. word
table.insert(lines, " "..buff)
return lines
alternating_colors = setmetatable({}, {__index:(i)=> if i % 2 == 0 then INVERTED else REGULAR})
class Pad
new: (@y,@x,@height,@width,@lines,@attrs=alternating_colors)=>
new: (@y,@x,@height,@width,@lines,@attrs=alternating_colors, pad_attr=0)=>
--log\write("New Pad:\n #{table.concat @lines, "\n "}\n")
@offset = 0
@selected = nil
@ -43,6 +56,7 @@ class Pad
--log\write("#lines = #{#@lines}, height = #{@_height}, width = #{@_width}\n")
@_pad = C.newpad(@_height, @_width)
@_pad\scrollok(true)
@_pad\attrset(pad_attr)
@chstrs = {}
for i, line in ipairs(@lines)
@ -79,6 +93,7 @@ class Pad
@offset = @selected - 1
@refresh!
if @on_select then @on_select(@selected)
return @selected
refresh: =>
@_pad\border(C.ACS_VLINE, C.ACS_VLINE,
@ -108,7 +123,21 @@ class Pad
@select(@selected and (@selected + delta) or 1)
main_loop = (err_msg, stack_index=1, var_index)->
ok, to_lua = pcall -> require('moonscript.base').to_lua
if not ok then to_lua = -> nil
file_cache = setmetatable({}, {__index:(filename)=>
@[filename] = io.open(filename)\read("*a")
return @[filename]
})
line_tables = setmetatable({}, {__index:(filename)=>
file = file_cache[filename]
ok, line_table = to_lua(file)
if ok
@[filename] = line_table
return line_table
})
main_loop = (err_msg, stack_index=1, var_index, value_index)->
SCREEN_H, SCREEN_W = stdscr\getmaxyx!
stdscr\clear!
@ -122,28 +151,26 @@ main_loop = (err_msg, stack_index=1, var_index)->
info = debug.getinfo(i)
if not info then break
table.insert(stack_names, info.name or "<unnamed function>")
filename = info.short_src..":"..info.currentline
table.insert(stack_locations, filename)
max_filename = math.max(max_filename, #filename)
line = if line_tables[info.short_src]
char = line_tables[info.short_src][info.currentline]
line_num = 1
file = file_cache[info.short_src]
for _ in file\sub(1,char)\gmatch("\n") do line_num += 1
"#{info.short_src}:#{line_num}"
else
info.short_src..":"..info.currentline
table.insert(stack_locations, line)
max_filename = math.max(max_filename, #line)
callstack = {}
for i=1,#stack_names do
callstack[i] = stack_locations[i]..(" ")\rep(max_filename-#stack_locations[i]).." | "..stack_names[i].." "
err_msg_lines = {}
for line in err_msg\gmatch("[^\n]*")
buff = ""
for word in line\gmatch("%S%S*%s*")
if #buff + #word > SCREEN_W - 4
table.insert(err_msg_lines, " "..buff)
buff = word
else
buff = buff .. word
table.insert(err_msg_lines, " "..buff)
err_pad = Pad(0,0,AUTO,SCREEN_W, err_msg_lines,setmetatable({}, __index:->RED))
err_pad._pad\attrset(RED)
err_msg_lines = wrap_text(err_msg, SCREEN_W - 4)
err_pad = Pad(0,0,AUTO,SCREEN_W, err_msg_lines,setmetatable({}, __index:->RED), RED)
stack_pad = Pad(err_pad.height,0,AUTO,AUTO, callstack)
stack_pad\select(stack_index)
stack_pad = Pad(err_pad.height,0,AUTO,AUTO, callstack, nil, BLUE)
stack_index = stack_pad\select(stack_index)
callstack_min, _ = callstack_range!
_var_names, _var_values = {}, {}
@ -158,55 +185,71 @@ main_loop = (err_msg, stack_index=1, var_index)->
else
table.insert(_var_values, repr(value))
var_names = Pad(err_pad.height,stack_pad.x+stack_pad.width,10,AUTO,_var_names)
var_values = Pad(err_pad.height,var_names.x+var_names.width,10,AUTO,_var_values)
var_names = Pad(err_pad.height,stack_pad.x+stack_pad.width,AUTO,AUTO,_var_names, nil, BLUE)
if var_index and #_var_names > 0
var_names\select(var_index)
var_values\select(var_index)
var_index = var_names\select(var_index)
value_x = var_names.x+var_names.width
value_w = SCREEN_W-(value_x+1)
if value_index
var_values = Pad(err_pad.height,value_x,AUTO,value_w,wrap_text(_var_values[var_index], value_w), nil, BLUE)
value_index = var_values\select(value_index)
else
var_values = Pad(err_pad.height,value_x,AUTO,value_w,_var_values, nil, BLUE)
while true
C.doupdate!
c = stdscr\getch!
switch c
when C.KEY_DOWN, C.KEY_SF, ("j")\byte!
if var_index
var_names\scroll(1)
return main_loop(err_msg,stack_pad.selected,var_names.selected)
if value_index
value_index += 1
elseif var_index
var_index += 1
else
stack_pad\scroll(1)
return main_loop(err_msg,stack_pad.selected,nil)
stack_index += 1
return main_loop(err_msg,stack_index,var_index,value_index)
when C.KEY_UP, C.KEY_SR, ("k")\byte!
if var_index
var_names\scroll(-1)
return main_loop(err_msg,stack_pad.selected,var_names.selected)
if value_index
value_index -= 1
elseif var_index
var_index -= 1
else
stack_pad\scroll(-1)
return main_loop(err_msg,stack_pad.selected,nil)
stack_index -= 1
return main_loop(err_msg,stack_index,var_index,value_index)
when ('J')\byte!
if var_index
var_names\scroll(10)
return main_loop(err_msg,stack_pad.selected,var_names.selected)
if value_index
value_index += 10
elseif var_index
var_index += 10
else
stack_pad\scroll(10)
return main_loop(err_msg,stack_pad.selected,nil)
stack_index += 10
return main_loop(err_msg,stack_index,var_index,value_index)
when ('K')\byte!
if var_index
var_names\scroll(-10)
return main_loop(err_msg,stack_pad.selected,var_names.selected)
if value_index
value_index -= 10
elseif var_index
var_index -= 10
else
stack_pad\scroll(-10)
return main_loop(err_msg,stack_pad.selected,nil)
stack_index -= 10
return main_loop(err_msg,stack_index,var_index,value_index)
when C.KEY_RIGHT, ("l")\byte!
if var_index == nil
return main_loop(err_msg,stack_pad.selected,1)
var_index = 1
elseif value_index == nil
value_index = 1
return main_loop(err_msg,stack_index,var_index,value_index)
when C.KEY_LEFT, ("h")\byte!
if var_index != nil
return main_loop(err_msg,stack_pad.selected,nil)
if value_index
value_index = nil
elseif var_index
var_index = nil
return main_loop(err_msg,stack_index,var_index,value_index)
when ('o')\byte!
file = stack_locations[stack_pad.selected]
@ -232,18 +275,17 @@ run_debugger = (err_msg)->
C.start_color!
C.use_default_colors!
export REGULAR, INVERTED, HIGHLIGHTED, RED
export REGULAR, INVERTED, HIGHLIGHTED, RED, BLUE
_, REGULAR = C.init_pair(1, -1, -1), C.color_pair(1)
_, INVERTED = C.init_pair(2, -1, C.COLOR_BLACK), C.color_pair(2)
_, HIGHLIGHTED = C.init_pair(3, C.COLOR_BLACK, C.COLOR_YELLOW), C.color_pair(3)
_, RED = C.init_pair(4, C.COLOR_RED, -1), C.color_pair(4) | C.A_BOLD
_, BLUE = C.init_pair(5, C.COLOR_BLUE, -1), C.color_pair(5) | C.A_BOLD
return main_loop(err_msg)
cursed = (fn, ...)->
-- To display Lua errors, we must close curses to return to
-- normal terminal mode, and then write the error to stdout.
guard = (fn, ...)->
err_hand = (err)->
C.endwin!
print "Caught an error:"
@ -252,4 +294,13 @@ cursed = (fn, ...)->
return xpcall(fn, ((err_msg)-> xpcall(run_debugger, err_hand, err_msg)), ...)
return cursed
breakpoint = ->
err_hand = (err)->
C.endwin!
print "Caught an error:"
print(debug.traceback(err, 2))
os.exit(2)
return xpcall(run_debugger, err_hand, "Breakpoint triggered!")
return {:guard, :breakpoint}