From b0148872660860b86dc3882a4e4dc91ddb4c3f4c Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Wed, 14 Mar 2018 18:45:32 -0700 Subject: [PATCH] Cleaner and better. --- cursed.lua | 170 +++++++++++++++++++++++++++------------------------- cursed.moon | 135 +++++++++++++++++++++-------------------- 2 files changed, 159 insertions(+), 146 deletions(-) diff --git a/cursed.lua b/cursed.lua index c06d478..594a636 100644 --- a/cursed.lua +++ b/cursed.lua @@ -2,7 +2,7 @@ local C = require("curses") local repr = require('repr') local COLORS = { } local run_debugger, guard, stdscr -local AUTO = -1 +local AUTO = { } local log = io.open("output.log", "w") local callstack_range callstack_range = function() @@ -51,10 +51,13 @@ do return end self.active = active - return self._pad:attrset(active and self.colors.active_frame or self.colors.inactive_frame) + return self._frame:attrset(active and self.colors.active_frame or self.colors.inactive_frame) end, select = function(self, i) - if i == self.selected or #self.lines == 0 then + if #self.lines == 0 then + i = nil + end + if i == self.selected then return self.selected end if i ~= nil then @@ -62,62 +65,56 @@ do end if self.selected then local j = self.selected - local attr = (j % 2 == 0) and self.colors.even_row or self.colors.odd_row + local attr = self.colors.line_colors[j] self.chstrs[j]:set_str(0, self.lines[j], attr) self.chstrs[j]:set_str(#self.lines[j], ' ', attr, self.chstrs[j]:len() - #self.lines[j]) - self._pad:mvaddchstr(j - 1 + 1, 0 + 1, self.chstrs[j]) + self._pad:mvaddchstr(j - 1, 0, self.chstrs[j]) end if i then local attr = self.active and self.colors.active or self.colors.highlight self.chstrs[i]:set_str(0, self.lines[i], attr) self.chstrs[i]:set_str(#self.lines[i], ' ', attr, self.chstrs[i]:len() - #self.lines[i]) - self._pad:mvaddchstr(i - 1 + 1, 0 + 1, self.chstrs[i]) + self._pad:mvaddchstr(i - 1, 0, self.chstrs[i]) + local scrolloff = 3 + if i > self.scroll_y + (self.height - 2) - scrolloff then + self.scroll_y = i - (self.height - 2) + scrolloff + elseif i < self.scroll_y + scrolloff then + self.scroll_y = i - scrolloff + end + self.scroll_y = math.max(1, math.min(#self.lines, self.scroll_y)) end self.selected = i - if self.selected then - if self.scroll_y + self.height - 1 < self.selected then - self.scroll_y = math.min(self.selected - (self.height - 1), #self.lines - self.height) - elseif self.scroll_y + 1 > self.selected then - self.scroll_y = self.selected - 1 - end - end self:refresh() if self.on_select then self:on_select(self.selected) end return self.selected end, - scroll = function(self, delta) - if self.selected == nil then - return self:select(1) + scroll = function(self, dy, dx) + if self.selected ~= nil then + self:select(self.selected + (dy or 0)) + else + self.scroll_y = math.max(1, math.min(self._height - self.height, self.scroll_y + (dy or 0))) end - return self:select(self.selected + delta) + self.scroll_x = math.max(1, math.min(self._width - self.width, self.scroll_x + (dx or 0))) + return self:refresh() end, refresh = function(self) - self._pad:border(C.ACS_VLINE, C.ACS_VLINE, C.ACS_HLINE, C.ACS_HLINE, C.ACS_ULCORNER, C.ACS_URCORNER, C.ACS_LLCORNER, C.ACS_LRCORNER) + self._frame:border(C.ACS_VLINE, C.ACS_VLINE, C.ACS_HLINE, C.ACS_HLINE, C.ACS_ULCORNER, C.ACS_URCORNER, C.ACS_LLCORNER, C.ACS_LRCORNER) if self.label then - self._pad:mvaddstr(0, math.floor((self.width - #self.label - 2) / 2), " " .. tostring(self.label) .. " ") + self._frame:mvaddstr(0, math.floor((self.width - #self.label - 2) / 2), " " .. tostring(self.label) .. " ") end - return self._pad:pnoutrefresh(self.scroll_y, self.scroll_x, self.y, self.x, self.y + self.height + 1, self.x + self.width) + self._frame:refresh() + local h, w = math.min(self.height - 2, self._height), math.min(self.width - 2, self._width) + return self._pad:pnoutrefresh(self.scroll_y - 1, self.scroll_x - 1, self.y + 1, self.x + 1, self.y + h, self.x + w) end, erase = function(self) - self._pad:erase() - return self._pad:pnoutrefresh(self.scroll_y, self.scroll_x, self.y, self.x, self.y + self.height, self.x + self.width) + self._frame:erase() + return self._frame:refresh() end, - clear = function(self) - self:erase() - self.lines = { } - self.chstrs = { } - self:set_internal_size(2, 2) - if self.resize_height then - self:set_size(self._height, self.width) - end - if self.resize_width then - self:set_size(self.height, self._width) - end - self.selected = nil - self.scroll_y, self.scroll_x = 0, 0 - return self:refresh() + __gc = function(self) + self._frame:cancel() + return self._pad:cancel() end } _base_0.__index = _base_0 @@ -132,28 +129,29 @@ do __index = default_colors }) end - self.scroll_y, self.scroll_x = 0, 0 + self.scroll_y, self.scroll_x = 1, 1 self.selected = nil - if self.width == AUTO then - self.width = 2 - local _list_0 = self.lines - for _index_0 = 1, #_list_0 do - local x = _list_0[_index_0] - self.width = math.max(self.width, #x + 2) - end - end - self._width = self.width + self._height = #self.lines if self.height == AUTO then - self.height = #self.lines + 2 + self.height = self._height + 2 end - self._height = self.height + self._width = 0 + local _list_0 = self.lines + for _index_0 = 1, #_list_0 do + local x = _list_0[_index_0] + self._width = math.max(self._width, #x + 2) + end + if self.width == AUTO then + self.width = self._width + 2 + end + self._frame = C.newwin(self.height, self.width, self.y, self.x) self._pad = C.newpad(self._height, self._width) self._pad:scrollok(true) self:set_active(false) self.chstrs = { } for i, line in ipairs(self.lines) do - local attr = (i % 2 == 0) and self.colors.even_row or self.colors.odd_row - local chstr = C.new_chstr(self.width - 2) + local attr = self.colors.line_colors[i] + local chstr = C.new_chstr(self._width) self.chstrs[i] = chstr if #line >= chstr:len() then line = line:sub(1, chstr:len()) @@ -161,7 +159,7 @@ do line = line .. (" "):rep(chstr:len() - #line) end chstr:set_str(0, line, attr) - self._pad:mvaddchstr(i - 1 + 1, 0 + 1, chstr) + self._pad:mvaddchstr(i - 1, 0, chstr) end return self:refresh() end, @@ -234,8 +232,11 @@ run_debugger = function(err_msg) default_colors = { active_frame = COLORS.BLUE, inactive_frame = COLORS.BROWN, - odd_row = COLORS.REGULAR, - even_row = COLORS.INVERTED, + line_colors = setmetatable({ }, { + __index = function(self, i) + return (i % 2 == 0 and COLORS.INVERTED or COLORS.REGULAR) + end + }), highlight = COLORS.WHITE_BG, active = COLORS.YELLOW_BG } @@ -248,8 +249,11 @@ run_debugger = function(err_msg) err_msg_lines[i] = (" "):rep(math.floor((SCREEN_W - 2 - #line) / 2)) .. line end pads.err = Pad(0, 0, AUTO, SCREEN_W, err_msg_lines, "Error Message", { - even_row = COLORS.RED | C.A_BOLD, - odd_row = COLORS.RED | C.A_BOLD, + line_colors = setmetatable({ }, { + __index = function() + return COLORS.RED | C.A_BOLD + end + }), inactive_frame = COLORS.RED | C.A_DIM }) end @@ -303,30 +307,19 @@ run_debugger = function(err_msg) show_src = function(filename, line_no) local file = file_cache[filename] local src_lines = { } - local selected = nil + local err_line = nil if file then local i = 0 for line in file:gmatch("[^\n]*") do - local _continue_0 = false - repeat - i = i + 1 - if i < line_no - (pads.stack.height - 2) / 2 then - _continue_0 = true - break - end - table.insert(src_lines, line) - if i == line_no then - selected = #src_lines - end - if #src_lines >= pads.stack.height - 2 then - break - end - _continue_0 = true - until true - if not _continue_0 then - break + i = i + 1 + table.insert(src_lines, line) + if i == line_no then + err_line = #src_lines end end + while #src_lines < pads.stack.height do + table.insert(src_lines, "") + end else table.insert(src_lines, "") end @@ -334,10 +327,15 @@ run_debugger = function(err_msg) pads.src:erase() end pads.src = Pad(pads.err.height, pads.stack.x + pads.stack.width, pads.stack.height, SCREEN_W - pads.stack.x - pads.stack.width - 0, src_lines, "(S)ource Code", { - highlight = COLORS.RED_BG, - inactive_frame = COLORS.GREEN | C.A_BOLD + line_colors = setmetatable({ + [err_line] = COLORS.RED_BG + }, { + __index = function(self, i) + return (i % 2 == 0) and INVERTED or REGULAR + end + }) }) - return pads.src:select(selected) + return pads.src:select(err_line) end local show_vars show_vars = function(stack_index) @@ -401,13 +399,21 @@ run_debugger = function(err_msg) local c = stdscr:getch() local _exp_0 = c if C.KEY_DOWN == _exp_0 or C.KEY_SF == _exp_0 or ("j"):byte() == _exp_0 then - selected_pad:scroll(1) - elseif C.KEY_UP == _exp_0 or C.KEY_SR == _exp_0 or ("k"):byte() == _exp_0 then - selected_pad:scroll(-1) + selected_pad:scroll(1, 0) elseif ('J'):byte() == _exp_0 then - selected_pad:scroll(10) + selected_pad:scroll(10, 0) + elseif C.KEY_UP == _exp_0 or C.KEY_SR == _exp_0 or ("k"):byte() == _exp_0 then + selected_pad:scroll(-1, 0) elseif ('K'):byte() == _exp_0 then - selected_pad:scroll(-10) + selected_pad:scroll(-10, 0) + elseif C.KEY_RIGHT == _exp_0 or ("l"):byte() == _exp_0 then + selected_pad:scroll(0, 1) + elseif ("L"):byte() == _exp_0 then + selected_pad:scroll(0, 10) + elseif C.KEY_LEFT == _exp_0 or ("h"):byte() == _exp_0 then + selected_pad:scroll(0, -1) + elseif ("H"):byte() == _exp_0 then + selected_pad:scroll(0, -10) elseif ('c'):byte() == _exp_0 then select_pad(pads.stack) elseif ('s'):byte() == _exp_0 then diff --git a/cursed.moon b/cursed.moon index 6c72a68..afa9636 100644 --- a/cursed.moon +++ b/cursed.moon @@ -2,7 +2,7 @@ C = require "curses" repr = require 'repr' COLORS = {} local run_debugger, guard, stdscr -AUTO = -1 +AUTO = {} log = io.open("output.log", "w") -- Return the callstack index of the code that actually caused an error and the max index @@ -41,17 +41,19 @@ class Pad new: (@y,@x,@height,@width,@lines,@label,@colors=default_colors)=> if @colors and @colors != default_colors setmetatable(@colors, __index:default_colors) - @scroll_y, @scroll_x = 0, 0 + @scroll_y, @scroll_x = 1, 1 @selected = nil - if @width == AUTO - @width = 2 - for x in *@lines do @width = math.max(@width, #x+2) - @_width = @width - + @_height = #@lines if @height == AUTO - @height = #@lines + 2 - @_height = @height + @height = @_height + 2 + + @_width = 0 + for x in *@lines do @_width = math.max(@_width, #x+2) + if @width == AUTO + @width = @_width + 2 + + @_frame = C.newwin(@height, @width, @y, @x) @_pad = C.newpad(@_height, @_width) @_pad\scrollok(true) @@ -59,81 +61,78 @@ class Pad @chstrs = {} for i, line in ipairs(@lines) - attr = (i % 2 == 0) and @colors.even_row or @colors.odd_row - chstr = C.new_chstr(@width-2) + attr = @colors.line_colors[i] + chstr = C.new_chstr(@_width) @chstrs[i] = chstr if #line >= chstr\len! line = line\sub(1, chstr\len!) else line ..= (" ")\rep(chstr\len!-#line) chstr\set_str(0, line, attr) - @_pad\mvaddchstr(i-1+1,0+1,chstr) + @_pad\mvaddchstr(i-1,0,chstr) @refresh! set_active: (active)=> return if active == @active @active = active - @_pad\attrset(active and @colors.active_frame or @colors.inactive_frame) + @_frame\attrset(active and @colors.active_frame or @colors.inactive_frame) select: (i)=> - if i == @selected or #@lines == 0 then return @selected + if #@lines == 0 then i = nil + if i == @selected then return @selected if i != nil i = math.max(1, math.min(#@lines, i)) if @selected j = @selected - attr = (j % 2 == 0) and @colors.even_row or @colors.odd_row + attr = @colors.line_colors[j] @chstrs[j]\set_str(0, @lines[j], attr) @chstrs[j]\set_str(#@lines[j], ' ', attr, @chstrs[j]\len!-#@lines[j]) - @_pad\mvaddchstr(j-1+1,0+1,@chstrs[j]) + @_pad\mvaddchstr(j-1,0,@chstrs[j]) if i attr = @active and @colors.active or @colors.highlight @chstrs[i]\set_str(0, @lines[i], attr) @chstrs[i]\set_str(#@lines[i], ' ', attr, @chstrs[i]\len!-#@lines[i]) - @_pad\mvaddchstr(i-1+1,0+1,@chstrs[i]) + @_pad\mvaddchstr(i-1,0,@chstrs[i]) + + scrolloff = 3 + if i > @scroll_y + (@height-2) - scrolloff + @scroll_y = i - (@height-2) + scrolloff + elseif i < @scroll_y + scrolloff + @scroll_y = i - scrolloff + @scroll_y = math.max(1, math.min(#@lines, @scroll_y)) @selected = i - - if @selected - if @scroll_y + @height-1 < @selected - @scroll_y = math.min(@selected - (@height-1), #@lines-@height) - elseif @scroll_y + 1 > @selected - @scroll_y = @selected - 1 @refresh! if @on_select then @on_select(@selected) return @selected - scroll: (delta)=> - if @selected == nil - return @select 1 - @select(@selected + delta) + scroll: (dy,dx)=> + if @selected != nil + @select(@selected + (dy or 0)) + else + @scroll_y = math.max(1, math.min(@_height-@height, @scroll_y+(dy or 0))) + @scroll_x = math.max(1, math.min(@_width-@width, @scroll_x+(dx or 0))) + @refresh! refresh: => - @_pad\border(C.ACS_VLINE, C.ACS_VLINE, + @_frame\border(C.ACS_VLINE, C.ACS_VLINE, C.ACS_HLINE, C.ACS_HLINE, C.ACS_ULCORNER, C.ACS_URCORNER, C.ACS_LLCORNER, C.ACS_LRCORNER) if @label - @_pad\mvaddstr(0, math.floor((@width-#@label-2)/2), " #{@label} ") - @_pad\pnoutrefresh(@scroll_y,@scroll_x,@y,@x,@y+@height+1,@x+@width) + @_frame\mvaddstr(0, math.floor((@width-#@label-2)/2), " #{@label} ") + @_frame\refresh! + h,w = math.min(@height-2,@_height),math.min(@width-2,@_width) + @_pad\pnoutrefresh(@scroll_y-1,@scroll_x-1,@y+1,@x+1,@y+h,@x+w) erase: => - @_pad\erase! - @_pad\pnoutrefresh(@scroll_y,@scroll_x,@y,@x,@y+@height,@x+@width) - - clear: => - @erase! - @lines = {} - @chstrs = {} - @set_internal_size(2,2) - if @resize_height - @set_size(@_height, @width) - if @resize_width - @set_size(@height, @_width) - @selected = nil - @scroll_y, @scroll_x = 0, 0 - @refresh! + @_frame\erase! + @_frame\refresh! + __gc: => + @_frame\cancel! + @_pad\cancel! ok, to_lua = pcall -> require('moonscript.base').to_lua if not ok then to_lua = -> nil @@ -180,8 +179,7 @@ run_debugger = (err_msg)-> default_colors = { active_frame: COLORS.BLUE, inactive_frame: COLORS.BROWN, - odd_row: COLORS.REGULAR, - even_row: COLORS.INVERTED, + line_colors: setmetatable({}, __index:(i)=> (i % 2 == 0 and COLORS.INVERTED or COLORS.REGULAR)) highlight: COLORS.WHITE_BG, active: COLORS.YELLOW_BG, } @@ -196,7 +194,7 @@ run_debugger = (err_msg)-> for i,line in ipairs(err_msg_lines) err_msg_lines[i] = (" ")\rep(math.floor((SCREEN_W-2-#line)/2))..line pads.err = Pad(0,0,AUTO,SCREEN_W, err_msg_lines, "Error Message", { - even_row: COLORS.RED | C.A_BOLD, odd_row: COLORS.RED | C.A_BOLD, + line_colors: setmetatable({}, __index:->COLORS.RED | C.A_BOLD) inactive_frame: COLORS.RED | C.A_DIM }) @@ -233,18 +231,20 @@ run_debugger = (err_msg)-> show_src = (filename, line_no)-> file = file_cache[filename] src_lines = {} - selected = nil + err_line = nil if file i = 0 for line in file\gmatch("[^\n]*") i += 1 - if i < line_no-(pads.stack.height-2)/2 - continue + --if i < line_no-(pads.stack.height-2)/2 + -- continue table.insert src_lines, line if i == line_no - selected = #src_lines - if #src_lines >= pads.stack.height-2 - break + err_line = #src_lines + --if #src_lines >= pads.stack.height-2 + -- break + while #src_lines < pads.stack.height + table.insert(src_lines, "") else table.insert(src_lines, "") @@ -252,10 +252,9 @@ run_debugger = (err_msg)-> pads.src\erase! pads.src = Pad(pads.err.height,pads.stack.x+pads.stack.width, pads.stack.height,SCREEN_W-pads.stack.x-pads.stack.width-0, src_lines, "(S)ource Code", { - highlight: COLORS.RED_BG, - inactive_frame: COLORS.GREEN | C.A_BOLD, + line_colors:setmetatable({[err_line]:COLORS.RED_BG}, {__index:(i)=> (i % 2 == 0) and INVERTED or REGULAR}) }) - pads.src\select(selected) + pads.src\select(err_line) show_vars = (stack_index)-> if pads.vars @@ -313,16 +312,24 @@ run_debugger = (err_msg)-> c = stdscr\getch! switch c when C.KEY_DOWN, C.KEY_SF, ("j")\byte! - selected_pad\scroll(1) + selected_pad\scroll(1,0) + when ('J')\byte! + selected_pad\scroll(10,0) when C.KEY_UP, C.KEY_SR, ("k")\byte! - selected_pad\scroll(-1) - - when ('J')\byte! - selected_pad\scroll(10) - + selected_pad\scroll(-1,0) when ('K')\byte! - selected_pad\scroll(-10) + selected_pad\scroll(-10,0) + + when C.KEY_RIGHT, ("l")\byte! + selected_pad\scroll(0,1) + when ("L")\byte! + selected_pad\scroll(0,10) + + when C.KEY_LEFT, ("h")\byte! + selected_pad\scroll(0,-1) + when ("H")\byte! + selected_pad\scroll(0,-10) when ('c')\byte! select_pad(pads.stack) -- (C)allstack