diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2022-07-12 14:18:50 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2022-07-12 15:24:56 -0700 |
commit | 8bbc1ffe349a78ed2130e24e0356276ddbb22955 (patch) | |
tree | 8e3f748433d5147e258fd1008e75cf2c41700e28 | |
parent | a5f725ab3b860b22199036f7ab0d0a0193a5a6ac (diff) | |
download | text.love-8bbc1ffe349a78ed2130e24e0356276ddbb22955.tar.gz |
group all editor globals
We're still accessing them through a global. But we'll change that next.
-rw-r--r-- | drawing.lua | 188 | ||||
-rw-r--r-- | drawing_tests.lua | 496 | ||||
-rw-r--r-- | edit.lua | 386 | ||||
-rw-r--r-- | help.lua | 214 | ||||
-rw-r--r-- | main.lua | 64 | ||||
-rw-r--r-- | main_tests.lua | 22 | ||||
-rw-r--r-- | search.lua | 82 | ||||
-rw-r--r-- | select.lua | 94 | ||||
-rw-r--r-- | text.lua | 598 | ||||
-rw-r--r-- | text_tests.lua | 1754 | ||||
-rw-r--r-- | undo.lua | 40 |
11 files changed, 1974 insertions, 1964 deletions
diff --git a/drawing.lua b/drawing.lua index 53f2c78..33bfd26 100644 --- a/drawing.lua +++ b/drawing.lua @@ -6,13 +6,13 @@ require 'drawing_tests' -- into 256 parts. function Drawing.draw(line) local pmx,pmy = App.mouse_x(), App.mouse_y() - if pmx < App.screen.width-Margin_right and pmy > line.y and pmy < line.y+Drawing.pixels(line.h) then + if pmx < App.screen.width-Editor_state.margin_right and pmy > line.y and pmy < line.y+Drawing.pixels(line.h) then App.color(Icon_color) - love.graphics.rectangle('line', Margin_left,line.y, App.screen.width-Margin_width,Drawing.pixels(line.h)) - if icon[Current_drawing_mode] then - icon[Current_drawing_mode](App.screen.width-Margin_right-22, line.y+4) + love.graphics.rectangle('line', Editor_state.margin_left,line.y, App.screen.width-Editor_state.margin_width,Drawing.pixels(line.h)) + if icon[Editor_state.current_drawing_mode] then + icon[Editor_state.current_drawing_mode](App.screen.width-Editor_state.margin_right-22, line.y+4) else - icon[Previous_drawing_mode](App.screen.width-Margin_right-22, line.y+4) + icon[Editor_state.previous_drawing_mode](App.screen.width-Editor_state.margin_right-22, line.y+4) end if App.mouse_down(1) and love.keyboard.isDown('h') then @@ -26,7 +26,7 @@ function Drawing.draw(line) return end - local mx,my = Drawing.coord(pmx-Margin_left), Drawing.coord(pmy-line.y) + local mx,my = Drawing.coord(pmx-Editor_state.margin_left), Drawing.coord(pmy-line.y) for _,shape in ipairs(line.shapes) do assert(shape) @@ -35,38 +35,38 @@ function Drawing.draw(line) else App.color(Stroke_color) end - Drawing.draw_shape(Margin_left,line.y, line, shape) + Drawing.draw_shape(Editor_state.margin_left,line.y, line, shape) end for i,p in ipairs(line.points) do if p.deleted == nil then if Drawing.near(p, mx,my) then App.color(Focus_stroke_color) - love.graphics.circle('line', Drawing.pixels(p.x)+Margin_left,Drawing.pixels(p.y)+line.y, 4) + love.graphics.circle('line', Drawing.pixels(p.x)+Editor_state.margin_left,Drawing.pixels(p.y)+line.y, 4) else App.color(Stroke_color) - love.graphics.circle('fill', Drawing.pixels(p.x)+Margin_left,Drawing.pixels(p.y)+line.y, 2) + love.graphics.circle('fill', Drawing.pixels(p.x)+Editor_state.margin_left,Drawing.pixels(p.y)+line.y, 2) end if p.name then -- TODO: clip - local x,y = Drawing.pixels(p.x)+Margin_left+5, Drawing.pixels(p.y)+line.y+5 + local x,y = Drawing.pixels(p.x)+Editor_state.margin_left+5, Drawing.pixels(p.y)+line.y+5 love.graphics.print(p.name, x,y) - if Current_drawing_mode == 'name' and i == line.pending.target_point then + if Editor_state.current_drawing_mode == 'name' and i == line.pending.target_point then -- create a faint red box for the name App.color(Current_name_background_color) local name_text -- TODO: avoid computing name width on every repaint if p.name == '' then - name_text = Em + name_text = Editor_state.em else name_text = App.newText(love.graphics.getFont(), p.name) end - love.graphics.rectangle('fill', x,y, App.width(name_text), Line_height) + love.graphics.rectangle('fill', x,y, App.width(name_text), Editor_state.line_height) end end end end App.color(Current_stroke_color) - Drawing.draw_pending_shape(Margin_left,line.y, line) + Drawing.draw_pending_shape(Editor_state.margin_left,line.y, line) end function Drawing.draw_shape(left,top, drawing, shape) @@ -204,51 +204,51 @@ end function Drawing.in_drawing(drawing, x,y) if drawing.y == nil then return false end -- outside current page - return y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= Margin_left and x < App.screen.width-Margin_right + return y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= Editor_state.margin_left and x < App.screen.width-Editor_state.margin_right end function Drawing.mouse_pressed(drawing, x,y, button) - if Current_drawing_mode == 'freehand' then - drawing.pending = {mode=Current_drawing_mode, points={{x=Drawing.coord(x-Margin_left), y=Drawing.coord(y-drawing.y)}}} - elseif Current_drawing_mode == 'line' or Current_drawing_mode == 'manhattan' then - local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)) - drawing.pending = {mode=Current_drawing_mode, p1=j} - elseif Current_drawing_mode == 'polygon' or Current_drawing_mode == 'rectangle' or Current_drawing_mode == 'square' then - local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)) - drawing.pending = {mode=Current_drawing_mode, vertices={j}} - elseif Current_drawing_mode == 'circle' then - local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)) - drawing.pending = {mode=Current_drawing_mode, center=j} - elseif Current_drawing_mode == 'move' then + if Editor_state.current_drawing_mode == 'freehand' then + drawing.pending = {mode=Editor_state.current_drawing_mode, points={{x=Drawing.coord(x-Editor_state.margin_left), y=Drawing.coord(y-drawing.y)}}} + elseif Editor_state.current_drawing_mode == 'line' or Editor_state.current_drawing_mode == 'manhattan' then + local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)) + drawing.pending = {mode=Editor_state.current_drawing_mode, p1=j} + elseif Editor_state.current_drawing_mode == 'polygon' or Editor_state.current_drawing_mode == 'rectangle' or Editor_state.current_drawing_mode == 'square' then + local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)) + drawing.pending = {mode=Editor_state.current_drawing_mode, vertices={j}} + elseif Editor_state.current_drawing_mode == 'circle' then + local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)) + drawing.pending = {mode=Editor_state.current_drawing_mode, center=j} + elseif Editor_state.current_drawing_mode == 'move' then -- all the action is in mouse_released - elseif Current_drawing_mode == 'name' then + elseif Editor_state.current_drawing_mode == 'name' then -- nothing else - print(Current_drawing_mode) + print(Editor_state.current_drawing_mode) assert(false) end end -- a couple of operations on drawings need to constantly check the state of the mouse function Drawing.update() - if Lines.current_drawing == nil then return end - local drawing = Lines.current_drawing + if Editor_state.lines.current_drawing == nil then return end + local drawing = Editor_state.lines.current_drawing assert(drawing.mode == 'drawing') local x, y = App.mouse_x(), App.mouse_y() if App.mouse_down(1) then if Drawing.in_drawing(drawing, x,y) then if drawing.pending.mode == 'freehand' then - table.insert(drawing.pending.points, {x=Drawing.coord(App.mouse_x()-Margin_left), y=Drawing.coord(App.mouse_y()-drawing.y)}) + table.insert(drawing.pending.points, {x=Drawing.coord(App.mouse_x()-Editor_state.margin_left), y=Drawing.coord(App.mouse_y()-drawing.y)}) elseif drawing.pending.mode == 'move' then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) drawing.pending.target_point.x = mx drawing.pending.target_point.y = my Drawing.relax_constraints(drawing, drawing.pending.target_point_index) end end - elseif Current_drawing_mode == 'move' then + elseif Editor_state.current_drawing_mode == 'move' then if Drawing.in_drawing(drawing, x, y) then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) drawing.pending.target_point.x = mx drawing.pending.target_point.y = my Drawing.relax_constraints(drawing, drawing.pending.target_point_index) @@ -277,15 +277,15 @@ function Drawing.relax_constraints(drawing, p) end function Drawing.mouse_released(x,y, button) - if Current_drawing_mode == 'move' then - Current_drawing_mode = Previous_drawing_mode - Previous_drawing_mode = nil - if Lines.current_drawing then - Lines.current_drawing.pending = {} - Lines.current_drawing = nil - end - elseif Lines.current_drawing then - local drawing = Lines.current_drawing + if Editor_state.current_drawing_mode == 'move' then + Editor_state.current_drawing_mode = Editor_state.previous_drawing_mode + Editor_state.previous_drawing_mode = nil + if Editor_state.lines.current_drawing then + Editor_state.lines.current_drawing.pending = {} + Editor_state.lines.current_drawing = nil + end + elseif Editor_state.lines.current_drawing then + local drawing = Editor_state.lines.current_drawing if drawing.pending then if drawing.pending.mode == nil then -- nothing pending @@ -294,14 +294,14 @@ function Drawing.mouse_released(x,y, button) Drawing.smoothen(drawing.pending) table.insert(drawing.shapes, drawing.pending) elseif drawing.pending.mode == 'line' then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then drawing.pending.p2 = Drawing.insert_point(drawing.points, mx,my) table.insert(drawing.shapes, drawing.pending) end elseif drawing.pending.mode == 'manhattan' then local p1 = drawing.points[drawing.pending.p1] - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then if math.abs(mx-p1.x) > math.abs(my-p1.y) then drawing.pending.p2 = Drawing.insert_point(drawing.points, mx, p1.y) @@ -309,11 +309,11 @@ function Drawing.mouse_released(x,y, button) drawing.pending.p2 = Drawing.insert_point(drawing.points, p1.x, my) end local p2 = drawing.points[drawing.pending.p2] - App.mouse_move(Margin_left+Drawing.pixels(p2.x), drawing.y+Drawing.pixels(p2.y)) + App.mouse_move(Editor_state.margin_left+Drawing.pixels(p2.x), drawing.y+Drawing.pixels(p2.y)) table.insert(drawing.shapes, drawing.pending) end elseif drawing.pending.mode == 'polygon' then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then table.insert(drawing.pending.vertices, Drawing.insert_point(drawing.points, mx,my)) table.insert(drawing.shapes, drawing.pending) @@ -321,7 +321,7 @@ function Drawing.mouse_released(x,y, button) elseif drawing.pending.mode == 'rectangle' then assert(#drawing.pending.vertices <= 2) if #drawing.pending.vertices == 2 then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then local first = drawing.points[drawing.pending.vertices[1]] local second = drawing.points[drawing.pending.vertices[2]] @@ -336,7 +336,7 @@ function Drawing.mouse_released(x,y, button) elseif drawing.pending.mode == 'square' then assert(#drawing.pending.vertices <= 2) if #drawing.pending.vertices == 2 then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then local first = drawing.points[drawing.pending.vertices[1]] local second = drawing.points[drawing.pending.vertices[2]] @@ -347,14 +347,14 @@ function Drawing.mouse_released(x,y, button) end end elseif drawing.pending.mode == 'circle' then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then local center = drawing.points[drawing.pending.center] drawing.pending.radius = geom.dist(center.x,center.y, mx,my) table.insert(drawing.shapes, drawing.pending) end elseif drawing.pending.mode == 'arc' then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then local center = drawing.points[drawing.pending.center] drawing.pending.end_angle = geom.angle_with_hint(center.x,center.y, mx,my, drawing.pending.end_angle) @@ -366,17 +366,17 @@ function Drawing.mouse_released(x,y, button) print(drawing.pending.mode) assert(false) end - Lines.current_drawing.pending = {} - Lines.current_drawing = nil + Editor_state.lines.current_drawing.pending = {} + Editor_state.lines.current_drawing = nil end end end function Drawing.keychord_pressed(chord) if chord == 'C-p' and not App.mouse_down(1) then - Current_drawing_mode = 'freehand' + Editor_state.current_drawing_mode = 'freehand' elseif App.mouse_down(1) and chord == 'l' then - Current_drawing_mode = 'line' + Editor_state.current_drawing_mode = 'line' local _,drawing = Drawing.current_drawing() if drawing.pending.mode == 'freehand' then drawing.pending.p1 = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y) @@ -387,9 +387,9 @@ function Drawing.keychord_pressed(chord) end drawing.pending.mode = 'line' elseif chord == 'C-l' and not App.mouse_down(1) then - Current_drawing_mode = 'line' + Editor_state.current_drawing_mode = 'line' elseif App.mouse_down(1) and chord == 'm' then - Current_drawing_mode = 'manhattan' + Editor_state.current_drawing_mode = 'manhattan' local drawing = Drawing.select_drawing_at_mouse() if drawing.pending.mode == 'freehand' then drawing.pending.p1 = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y) @@ -402,11 +402,11 @@ function Drawing.keychord_pressed(chord) end drawing.pending.mode = 'manhattan' elseif chord == 'C-m' and not App.mouse_down(1) then - Current_drawing_mode = 'manhattan' + Editor_state.current_drawing_mode = 'manhattan' elseif chord == 'C-g' and not App.mouse_down(1) then - Current_drawing_mode = 'polygon' + Editor_state.current_drawing_mode = 'polygon' elseif App.mouse_down(1) and chord == 'g' then - Current_drawing_mode = 'polygon' + Editor_state.current_drawing_mode = 'polygon' local _,drawing = Drawing.current_drawing() if drawing.pending.mode == 'freehand' then drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)} @@ -421,9 +421,9 @@ function Drawing.keychord_pressed(chord) end drawing.pending.mode = 'polygon' elseif chord == 'C-r' and not App.mouse_down(1) then - Current_drawing_mode = 'rectangle' + Editor_state.current_drawing_mode = 'rectangle' elseif App.mouse_down(1) and chord == 'r' then - Current_drawing_mode = 'rectangle' + Editor_state.current_drawing_mode = 'rectangle' local _,drawing = Drawing.current_drawing() if drawing.pending.mode == 'freehand' then drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)} @@ -438,9 +438,9 @@ function Drawing.keychord_pressed(chord) end drawing.pending.mode = 'rectangle' elseif chord == 'C-s' and not App.mouse_down(1) then - Current_drawing_mode = 'square' + Editor_state.current_drawing_mode = 'square' elseif App.mouse_down(1) and chord == 's' then - Current_drawing_mode = 'square' + Editor_state.current_drawing_mode = 'square' local _,drawing = Drawing.current_drawing() if drawing.pending.mode == 'freehand' then drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)} @@ -458,30 +458,30 @@ function Drawing.keychord_pressed(chord) drawing.pending.vertices = {drawing.pending.center} end drawing.pending.mode = 'square' - elseif App.mouse_down(1) and chord == 'p' and Current_drawing_mode == 'polygon' then + elseif App.mouse_down(1) and chord == 'p' and Editor_state.current_drawing_mode == 'polygon' then local _,drawing = Drawing.current_drawing() - local mx,my = Drawing.coord(App.mouse_x()-Margin_left), Drawing.coord(App.mouse_y()-drawing.y) + local mx,my = Drawing.coord(App.mouse_x()-Editor_state.margin_left), Drawing.coord(App.mouse_y()-drawing.y) local j = Drawing.insert_point(drawing.points, mx,my) table.insert(drawing.pending.vertices, j) - elseif App.mouse_down(1) and chord == 'p' and (Current_drawing_mode == 'rectangle' or Current_drawing_mode == 'square') then + elseif App.mouse_down(1) and chord == 'p' and (Editor_state.current_drawing_mode == 'rectangle' or Editor_state.current_drawing_mode == 'square') then local _,drawing = Drawing.current_drawing() - local mx,my = Drawing.coord(App.mouse_x()-Margin_left), Drawing.coord(App.mouse_y()-drawing.y) + local mx,my = Drawing.coord(App.mouse_x()-Editor_state.margin_left), Drawing.coord(App.mouse_y()-drawing.y) local j = Drawing.insert_point(drawing.points, mx,my) while #drawing.pending.vertices >= 2 do table.remove(drawing.pending.vertices) end table.insert(drawing.pending.vertices, j) elseif chord == 'C-o' and not App.mouse_down(1) then - Current_drawing_mode = 'circle' - elseif App.mouse_down(1) and chord == 'a' and Current_drawing_mode == 'circle' then + Editor_state.current_drawing_mode = 'circle' + elseif App.mouse_down(1) and chord == 'a' and Editor_state.current_drawing_mode == 'circle' then local _,drawing = Drawing.current_drawing() drawing.pending.mode = 'arc' - local mx,my = Drawing.coord(App.mouse_x()-Margin_left), Drawing.coord(App.mouse_y()-drawing.y) + local mx,my = Drawing.coord(App.mouse_x()-Editor_state.margin_left), Drawing.coord(App.mouse_y()-drawing.y) local center = drawing.points[drawing.pending.center] drawing.pending.radius = geom.dist(center.x,center.y, mx,my) drawing.pending.start_angle = geom.angle(center.x,center.y, mx,my) elseif App.mouse_down(1) and chord == 'o' then - Current_drawing_mode = 'circle' + Editor_state.current_drawing_mode = 'circle' local _,drawing = Drawing.current_drawing() if drawing.pending.mode == 'freehand' then drawing.pending.center = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y) @@ -494,26 +494,26 @@ function Drawing.keychord_pressed(chord) elseif chord == 'C-u' and not App.mouse_down(1) then local drawing_index,drawing,i,p = Drawing.select_point_at_mouse() if drawing then - if Previous_drawing_mode == nil then - Previous_drawing_mode = Current_drawing_mode + if Editor_state.previous_drawing_mode == nil then + Editor_state.previous_drawing_mode = Editor_state.current_drawing_mode end - Current_drawing_mode = 'move' - drawing.pending = {mode=Current_drawing_mode, target_point=p, target_point_index=i} - Lines.current_drawing_index = drawing_index - Lines.current_drawing = drawing + Editor_state.current_drawing_mode = 'move' + drawing.pending = {mode=Editor_state.current_drawing_mode, target_point=p, target_point_index=i} + Editor_state.lines.current_drawing_index = drawing_index + Editor_state.lines.current_drawing = drawing end elseif chord == 'C-n' and not App.mouse_down(1) then local drawing_index,drawing,point_index,p = Drawing.select_point_at_mouse() if drawing then - if Previous_drawing_mode == nil then + if Editor_state.previous_drawing_mode == nil then -- don't clobber - Previous_drawing_mode = Current_drawing_mode + Editor_state.previous_drawing_mode = Editor_state.current_drawing_mode end - Current_drawing_mode = 'name' + Editor_state.current_drawing_mode = 'name' p.name = '' - drawing.pending = {mode=Current_drawing_mode, target_point=point_index} - Lines.current_drawing_index = drawing_index - Lines.current_drawing = drawing + drawing.pending = {mode=Editor_state.current_drawing_mode, target_point=point_index} + Editor_state.lines.current_drawing_index = drawing_index + Editor_state.lines.current_drawing = drawing end elseif chord == 'C-d' and not App.mouse_down(1) then local _,drawing,i,p = Drawing.select_point_at_mouse() @@ -599,7 +599,7 @@ end function Drawing.current_drawing() local x, y = App.mouse_x(), App.mouse_y() - for drawing_index,drawing in ipairs(Lines) do + for drawing_index,drawing in ipairs(Editor_state.lines) do if drawing.mode == 'drawing' then if Drawing.in_drawing(drawing, x,y) then return drawing_index,drawing @@ -610,11 +610,11 @@ function Drawing.current_drawing() end function Drawing.select_shape_at_mouse() - for _,drawing in ipairs(Lines) do + for _,drawing in ipairs(Editor_state.lines) do if drawing.mode == 'drawing' then local x, y = App.mouse_x(), App.mouse_y() if Drawing.in_drawing(drawing, x,y) then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) for i,shape in ipairs(drawing.shapes) do assert(shape) if geom.on_shape(mx,my, drawing, shape) then @@ -627,11 +627,11 @@ function Drawing.select_shape_at_mouse() end function Drawing.select_point_at_mouse() - for drawing_index,drawing in ipairs(Lines) do + for drawing_index,drawing in ipairs(Editor_state.lines) do if drawing.mode == 'drawing' then local x, y = App.mouse_x(), App.mouse_y() if Drawing.in_drawing(drawing, x,y) then - local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y) + local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y) for i,point in ipairs(drawing.points) do assert(point) if Drawing.near(point, mx,my) then @@ -644,7 +644,7 @@ function Drawing.select_point_at_mouse() end function Drawing.select_drawing_at_mouse() - for _,drawing in ipairs(Lines) do + for _,drawing in ipairs(Editor_state.lines) do if drawing.mode == 'drawing' then local x, y = App.mouse_x(), App.mouse_y() if Drawing.in_drawing(drawing, x,y) then @@ -700,14 +700,14 @@ end function Drawing.near(point, x,y) local px,py = Drawing.pixels(x),Drawing.pixels(y) local cx,cy = Drawing.pixels(point.x), Drawing.pixels(point.y) - return (cx-px)*(cx-px) + (cy-py)*(cy-py) < Margin_left + return (cx-px)*(cx-px) + (cy-py)*(cy-py) < Editor_state.margin_left end function Drawing.pixels(n) -- parts to pixels - return math.floor(n*(App.screen.width-Margin_width)/256) + return math.floor(n*(App.screen.width-Editor_state.margin_width)/256) end function Drawing.coord(n) -- pixels to parts - return math.floor(n*256/(App.screen.width-Margin_width)) + return math.floor(n*256/(App.screen.width-Editor_state.margin_width)) end function table.find(h, x) diff --git a/drawing_tests.lua b/drawing_tests.lua index c170caa..bc3b654 100644 --- a/drawing_tests.lua +++ b/drawing_tests.lua @@ -5,11 +5,11 @@ function test_creating_drawing_saves() io.write('\ntest_creating_drawing_saves') App.screen.init{width=120, height=60} - Filename = 'foo' - Lines = load_array{} + Editor_state.filename = 'foo' + Editor_state.lines = load_array{} edit.draw() -- click on button to create drawing - App.run_after_mouse_click(8,Margin_top+8, 1) + App.run_after_mouse_click(8,Editor_state.margin_top+8, 1) -- file not immediately saved App.update(0.01) check_nil(App.filesystem['foo'], 'F - test_creating_drawing_saves/early') @@ -23,20 +23,20 @@ end function test_draw_line() io.write('\ntest_draw_line') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - check_eq(#Lines, 2, 'F - test_draw_line/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_line/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_line/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_line/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_line/baseline/#shapes') + check_eq(#Editor_state.lines, 2, 'F - test_draw_line/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_line/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_line/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_line/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_line/baseline/#shapes') -- draw a line - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_line/#shapes') check_eq(#drawing.points, 2, 'F - test_draw_line/#points') check_eq(drawing.shapes[1].mode, 'line', 'F - test_draw_line/shape:1') @@ -51,8 +51,8 @@ function test_draw_line() App.update(0) -- The format on disk isn't perfectly stable. Table fields can be reordered. -- So just reload from disk to verify. - Lines = load_from_disk(Filename) - local drawing = Lines[1] + Editor_state.lines = load_from_disk(Editor_state.filename) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_line/save/#shapes') check_eq(#drawing.points, 2, 'F - test_draw_line/save/#points') check_eq(drawing.shapes[1].mode, 'line', 'F - test_draw_line/save/shape:1') @@ -67,19 +67,19 @@ end function test_draw_horizontal_line() io.write('\ntest_draw_horizontal_line') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'manhattan' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'manhattan' edit.draw() - check_eq(#Lines, 2, 'F - test_draw_horizontal_line/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_horizontal_line/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_horizontal_line/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_horizontal_line/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_horizontal_line/baseline/#shapes') + check_eq(#Editor_state.lines, 2, 'F - test_draw_horizontal_line/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_horizontal_line/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_horizontal_line/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_horizontal_line/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_horizontal_line/baseline/#shapes') -- draw a line that is more horizontal than vertical - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_horizontal_line/#shapes') check_eq(#drawing.points, 2, 'F - test_draw_horizontal_line/#points') check_eq(drawing.shapes[1].mode, 'manhattan', 'F - test_draw_horizontal_line/shape_mode') @@ -94,21 +94,21 @@ end function test_draw_circle() io.write('\ntest_draw_circle') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - check_eq(#Lines, 2, 'F - test_draw_circle/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_circle/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_circle/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_circle/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_circle/baseline/#shapes') + check_eq(#Editor_state.lines, 2, 'F - test_draw_circle/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_circle/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_circle/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_circle/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_circle/baseline/#shapes') -- draw a circle - App.mouse_move(Margin_left+4, Margin_top+Drawing_padding_top+4) -- hover on drawing + App.mouse_move(Editor_state.margin_left+4, Editor_state.margin_top+Editor_state.drawing_padding_top+4) -- hover on drawing App.run_after_keychord('C-o') - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_release(Margin_left+35+30, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_release(Editor_state.margin_left+35+30, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_circle/#shapes') check_eq(#drawing.points, 1, 'F - test_draw_circle/#points') check_eq(drawing.shapes[1].mode, 'circle', 'F - test_draw_horizontal_line/shape_mode') @@ -121,58 +121,58 @@ end function test_cancel_stroke() io.write('\ntest_cancel_stroke') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - check_eq(#Lines, 2, 'F - test_cancel_stroke/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_cancel_stroke/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_cancel_stroke/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_cancel_stroke/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_cancel_stroke/baseline/#shapes') + check_eq(#Editor_state.lines, 2, 'F - test_cancel_stroke/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_cancel_stroke/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_cancel_stroke/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_cancel_stroke/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_cancel_stroke/baseline/#shapes') -- start drawing a line - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) -- cancel App.run_after_keychord('escape') - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 0, 'F - test_cancel_stroke/#shapes') end function test_keys_do_not_affect_shape_when_mouse_up() io.write('\ntest_keys_do_not_affect_shape_when_mouse_up') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() -- hover over drawing and press 'o' without holding mouse - App.mouse_move(Margin_left+4, Margin_top+Drawing_padding_top+4) -- hover on drawing + App.mouse_move(Editor_state.margin_left+4, Editor_state.margin_top+Editor_state.drawing_padding_top+4) -- hover on drawing App.run_after_keychord('o') -- no change to drawing mode - check_eq(Current_drawing_mode, 'line', 'F - test_keys_do_not_affect_shape_when_mouse_up/drawing_mode') + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_keys_do_not_affect_shape_when_mouse_up/drawing_mode') -- no change to text either because we didn't run the textinput event end function test_draw_circle_mid_stroke() io.write('\ntest_draw_circle_mid_stroke') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - check_eq(#Lines, 2, 'F - test_draw_circle_mid_stroke/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_circle_mid_stroke/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_circle_mid_stroke/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_circle_mid_stroke/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_circle_mid_stroke/baseline/#shapes') + check_eq(#Editor_state.lines, 2, 'F - test_draw_circle_mid_stroke/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_circle_mid_stroke/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_circle_mid_stroke/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_circle_mid_stroke/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_circle_mid_stroke/baseline/#shapes') -- draw a circle - App.mouse_move(Margin_left+4, Margin_top+Drawing_padding_top+4) -- hover on drawing - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) + App.mouse_move(Editor_state.margin_left+4, Editor_state.margin_top+Editor_state.drawing_padding_top+4) -- hover on drawing + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) App.run_after_keychord('o') - App.run_after_mouse_release(Margin_left+35+30, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+35+30, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_circle_mid_stroke/#shapes') check_eq(#drawing.points, 1, 'F - test_draw_circle_mid_stroke/#points') check_eq(drawing.shapes[1].mode, 'circle', 'F - test_draw_horizontal_line/shape_mode') @@ -185,21 +185,21 @@ end function test_draw_arc() io.write('\ntest_draw_arc') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'circle' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'circle' edit.draw() - check_eq(#Lines, 2, 'F - test_draw_arc/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_arc/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_arc/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_arc/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_arc/baseline/#shapes') + check_eq(#Editor_state.lines, 2, 'F - test_draw_arc/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_arc/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_arc/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_arc/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_arc/baseline/#shapes') -- draw an arc - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.mouse_move(Margin_left+35+30, Margin_top+Drawing_padding_top+36) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.mouse_move(Editor_state.margin_left+35+30, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('a') -- arc mode - App.run_after_mouse_release(Margin_left+35+50, Margin_top+Drawing_padding_top+36+50, 1) -- 45° - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+35+50, Editor_state.margin_top+Editor_state.drawing_padding_top+36+50, 1) -- 45° + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_arc/#shapes') check_eq(#drawing.points, 1, 'F - test_draw_arc/#points') check_eq(drawing.shapes[1].mode, 'arc', 'F - test_draw_horizontal_line/shape_mode') @@ -215,24 +215,24 @@ end function test_draw_polygon() io.write('\ntest_draw_polygon') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} edit.draw() - check_eq(Current_drawing_mode, 'line', 'F - test_draw_polygon/baseline/drawing_mode') - check_eq(#Lines, 2, 'F - test_draw_polygon/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_polygon/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_polygon/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_polygon/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_polygon/baseline/#shapes') + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_polygon/baseline/drawing_mode') + check_eq(#Editor_state.lines, 2, 'F - test_draw_polygon/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_polygon/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_polygon/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_polygon/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_polygon/baseline/#shapes') -- first point - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) App.run_after_keychord('g') -- polygon mode -- second point - App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36) + App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('p') -- add point -- final point - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_polygon/#shapes') check_eq(#drawing.points, 3, 'F - test_draw_polygon/vertices') local shape = drawing.shapes[1] @@ -252,27 +252,27 @@ end function test_draw_rectangle() io.write('\ntest_draw_rectangle') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} edit.draw() - check_eq(Current_drawing_mode, 'line', 'F - test_draw_rectangle/baseline/drawing_mode') - check_eq(#Lines, 2, 'F - test_draw_rectangle/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_rectangle/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_rectangle/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_rectangle/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_rectangle/baseline/#shapes') + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_rectangle/baseline/drawing_mode') + check_eq(#Editor_state.lines, 2, 'F - test_draw_rectangle/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_rectangle/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_rectangle/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_rectangle/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_rectangle/baseline/#shapes') -- first point - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) App.run_after_keychord('r') -- rectangle mode -- second point/first edge - App.mouse_move(Margin_left+42, Margin_top+Drawing_padding_top+45) + App.mouse_move(Editor_state.margin_left+42, Editor_state.margin_top+Editor_state.drawing_padding_top+45) App.run_after_keychord('p') -- override second point/first edge - App.mouse_move(Margin_left+75, Margin_top+Drawing_padding_top+76) + App.mouse_move(Editor_state.margin_left+75, Editor_state.margin_top+Editor_state.drawing_padding_top+76) App.run_after_keychord('p') -- release (decides 'thickness' of rectangle perpendicular to first edge) - App.run_after_mouse_release(Margin_left+15, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+15, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_rectangle/#shapes') check_eq(#drawing.points, 5, 'F - test_draw_rectangle/#points') -- currently includes every point added local shape = drawing.shapes[1] @@ -295,25 +295,25 @@ end function test_draw_rectangle_intermediate() io.write('\ntest_draw_rectangle_intermediate') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} edit.draw() - check_eq(Current_drawing_mode, 'line', 'F - test_draw_rectangle_intermediate/baseline/drawing_mode') - check_eq(#Lines, 2, 'F - test_draw_rectangle_intermediate/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_rectangle_intermediate/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_rectangle_intermediate/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_rectangle_intermediate/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_rectangle_intermediate/baseline/#shapes') + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_rectangle_intermediate/baseline/drawing_mode') + check_eq(#Editor_state.lines, 2, 'F - test_draw_rectangle_intermediate/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_rectangle_intermediate/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_rectangle_intermediate/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_rectangle_intermediate/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_rectangle_intermediate/baseline/#shapes') -- first point - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) App.run_after_keychord('r') -- rectangle mode -- second point/first edge - App.mouse_move(Margin_left+42, Margin_top+Drawing_padding_top+45) + App.mouse_move(Editor_state.margin_left+42, Editor_state.margin_top+Editor_state.drawing_padding_top+45) App.run_after_keychord('p') -- override second point/first edge - App.mouse_move(Margin_left+75, Margin_top+Drawing_padding_top+76) + App.mouse_move(Editor_state.margin_left+75, Editor_state.margin_top+Editor_state.drawing_padding_top+76) App.run_after_keychord('p') - local drawing = Lines[1] + local drawing = Editor_state.lines[1] check_eq(#drawing.points, 3, 'F - test_draw_rectangle_intermediate/#points') -- currently includes every point added local pending = drawing.pending check_eq(pending.mode, 'rectangle', 'F - test_draw_rectangle_intermediate/shape_mode') @@ -330,27 +330,27 @@ end function test_draw_square() io.write('\ntest_draw_square') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} edit.draw() - check_eq(Current_drawing_mode, 'line', 'F - test_draw_square/baseline/drawing_mode') - check_eq(#Lines, 2, 'F - test_draw_square/baseline/#lines') - check_eq(Lines[1].mode, 'drawing', 'F - test_draw_square/baseline/mode') - check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_square/baseline/y') - check_eq(Lines[1].h, 128, 'F - test_draw_square/baseline/y') - check_eq(#Lines[1].shapes, 0, 'F - test_draw_square/baseline/#shapes') + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_square/baseline/drawing_mode') + check_eq(#Editor_state.lines, 2, 'F - test_draw_square/baseline/#lines') + check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_square/baseline/mode') + check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_square/baseline/y') + check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_square/baseline/y') + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_square/baseline/#shapes') -- first point - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) App.run_after_keychord('s') -- square mode -- second point/first edge - App.mouse_move(Margin_left+42, Margin_top+Drawing_padding_top+45) + App.mouse_move(Editor_state.margin_left+42, Editor_state.margin_top+Editor_state.drawing_padding_top+45) App.run_after_keychord('p') -- override second point/first edge - App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+66) + App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+66) App.run_after_keychord('p') -- release (decides which side of first edge to draw square on) - App.run_after_mouse_release(Margin_left+15, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+15, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_draw_square/#shapes') check_eq(#drawing.points, 5, 'F - test_draw_square/#points') -- currently includes every point added check_eq(drawing.shapes[1].mode, 'square', 'F - test_draw_square/shape_mode') @@ -372,15 +372,15 @@ end function test_name_point() io.write('\ntest_name_point') -- create a drawing with a line - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() -- draw a line - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_name_point/baseline/#shapes') check_eq(#drawing.points, 2, 'F - test_name_point/baseline/#points') check_eq(drawing.shapes[1].mode, 'line', 'F - test_name_point/baseline/shape:1') @@ -393,35 +393,35 @@ function test_name_point() check_nil(p2.name, 'F - test_name_point/baseline/p2:name') -- enter 'name' mode without moving the mouse App.run_after_keychord('C-n') - check_eq(Current_drawing_mode, 'name', 'F - test_name_point/mode:1') + check_eq(Editor_state.current_drawing_mode, 'name', 'F - test_name_point/mode:1') App.run_after_textinput('A') check_eq(p2.name, 'A', 'F - test_name_point') -- still in 'name' mode - check_eq(Current_drawing_mode, 'name', 'F - test_name_point/mode:2') + check_eq(Editor_state.current_drawing_mode, 'name', 'F - test_name_point/mode:2') -- exit 'name' mode App.run_after_keychord('return') - check_eq(Current_drawing_mode, 'line', 'F - test_name_point/mode:3') + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_name_point/mode:3') check_eq(p2.name, 'A', 'F - test_name_point') -- wait until save App.wait_fake_time(3.1) App.update(0) -- change is saved - Lines = load_from_disk(Filename) - local p2 = Lines[1].points[drawing.shapes[1].p2] + Editor_state.lines = load_from_disk(Editor_state.filename) + local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2] check_eq(p2.name, 'A', 'F - test_name_point/save') end function test_move_point() io.write('\ntest_move_point') -- create a drawing with a line - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_move_point/baseline/#shapes') check_eq(#drawing.points, 2, 'F - test_move_point/baseline/#points') check_eq(drawing.shapes[1].mode, 'line', 'F - test_move_point/baseline/shape:1') @@ -435,34 +435,34 @@ function test_move_point() App.wait_fake_time(3.1) App.update(0) -- line is saved to disk - Lines = load_from_disk(Filename) - local drawing = Lines[1] - local p2 = Lines[1].points[drawing.shapes[1].p2] + Editor_state.lines = load_from_disk(Editor_state.filename) + local drawing = Editor_state.lines[1] + local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2] check_eq(p2.x, 35, 'F - test_move_point/save/x') check_eq(p2.y, 36, 'F - test_move_point/save/y') edit.draw() -- enter 'move' mode without moving the mouse App.run_after_keychord('C-u') - check_eq(Current_drawing_mode, 'move', 'F - test_move_point/mode:1') + check_eq(Editor_state.current_drawing_mode, 'move', 'F - test_move_point/mode:1') -- point is lifted check_eq(drawing.pending.mode, 'move', 'F - test_move_point/mode:2') check_eq(drawing.pending.target_point, p2, 'F - test_move_point/target') -- move point - App.mouse_move(Margin_left+26, Margin_top+Drawing_padding_top+44) + App.mouse_move(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44) App.update(0.05) local p2 = drawing.points[drawing.shapes[1].p2] check_eq(p2.x, 26, 'F - test_move_point/x') check_eq(p2.y, 44, 'F - test_move_point/y') -- exit 'move' mode - App.run_after_mouse_click(Margin_left+26, Margin_top+Drawing_padding_top+44, 1) - check_eq(Current_drawing_mode, 'line', 'F - test_move_point/mode:3') + App.run_after_mouse_click(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44, 1) + check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_move_point/mode:3') check_eq(drawing.pending, {}, 'F - test_move_point/pending') -- wait until save App.wait_fake_time(3.1) App.update(0) -- change is saved - Lines = load_from_disk(Filename) - local p2 = Lines[1].points[drawing.shapes[1].p2] + Editor_state.lines = load_from_disk(Editor_state.filename) + local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2] check_eq(p2.x, 26, 'F - test_move_point/save/x') check_eq(p2.y, 44, 'F - test_move_point/save/y') end @@ -470,23 +470,23 @@ end function test_move_point_on_manhattan_line() io.write('\ntest_move_point_on_manhattan_line') -- create a drawing with a manhattan line - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'manhattan' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'manhattan' edit.draw() - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+46, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+46, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_move_point_on_manhattan_line/baseline/#shapes') check_eq(#drawing.points, 2, 'F - test_move_point_on_manhattan_line/baseline/#points') check_eq(drawing.shapes[1].mode, 'manhattan', 'F - test_move_point_on_manhattan_line/baseline/shape:1') edit.draw() -- enter 'move' mode App.run_after_keychord('C-u') - check_eq(Current_drawing_mode, 'move', 'F - test_move_point_on_manhattan_line/mode:1') + check_eq(Editor_state.current_drawing_mode, 'move', 'F - test_move_point_on_manhattan_line/mode:1') -- move point - App.mouse_move(Margin_left+26, Margin_top+Drawing_padding_top+44) + App.mouse_move(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44) App.update(0.05) -- line is no longer manhattan check_eq(drawing.shapes[1].mode, 'line', 'F - test_move_point_on_manhattan_line/baseline/shape:1') @@ -495,21 +495,21 @@ end function test_delete_lines_at_point() io.write('\ntest_delete_lines_at_point') -- create a drawing with two lines connected at a point - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_release(Margin_left+55, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_release(Editor_state.margin_left+55, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 2, 'F - test_delete_lines_at_point/baseline/#shapes') check_eq(drawing.shapes[1].mode, 'line', 'F - test_delete_lines_at_point/baseline/shape:1') check_eq(drawing.shapes[2].mode, 'line', 'F - test_delete_lines_at_point/baseline/shape:2') -- hover on the common point and delete - App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+36) + App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('C-d') check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_delete_lines_at_point/shape:1') check_eq(drawing.shapes[2].mode, 'deleted', 'F - test_delete_lines_at_point/shape:2') @@ -517,27 +517,27 @@ function test_delete_lines_at_point() App.wait_fake_time(3.1) App.update(0) -- deleted points disappear after file is reloaded - Lines = load_from_disk(Filename) - check_eq(#Lines[1].shapes, 0, 'F - test_delete_lines_at_point/save') + Editor_state.lines = load_from_disk(Editor_state.filename) + check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_delete_lines_at_point/save') end function test_delete_line_under_mouse_pointer() io.write('\ntest_delete_line_under_mouse_pointer') -- create a drawing with two lines connected at a point - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_release(Margin_left+55, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_release(Editor_state.margin_left+55, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 2, 'F - test_delete_line_under_mouse_pointer/baseline/#shapes') check_eq(drawing.shapes[1].mode, 'line', 'F - test_delete_line_under_mouse_pointer/baseline/shape:1') check_eq(drawing.shapes[2].mode, 'line', 'F - test_delete_line_under_mouse_pointer/baseline/shape:2') -- hover on one of the lines and delete - App.mouse_move(Margin_left+25, Margin_top+Drawing_padding_top+26) + App.mouse_move(Editor_state.margin_left+25, Editor_state.margin_top+Editor_state.drawing_padding_top+26) App.run_after_keychord('C-d') -- only that line is deleted check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_delete_line_under_mouse_pointer/shape:1') @@ -547,27 +547,27 @@ end function test_delete_point_from_polygon() io.write('\ntest_delete_point_from_polygon') -- create a drawing with two lines connected at a point - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() -- first point - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) App.run_after_keychord('g') -- polygon mode -- second point - App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36) + App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('p') -- add point -- third point - App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+26) + App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26) App.run_after_keychord('p') -- add point -- fourth point - App.run_after_mouse_release(Margin_left+14, Margin_top+Drawing_padding_top+16, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+14, Editor_state.margin_top+Editor_state.drawing_padding_top+16, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_delete_point_from_polygon/baseline/#shapes') check_eq(drawing.shapes[1].mode, 'polygon', 'F - test_delete_point_from_polygon/baseline/mode') check_eq(#drawing.shapes[1].vertices, 4, 'F - test_delete_point_from_polygon/baseline/vertices') -- hover on a point and delete - App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+26) + App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26) App.run_after_keychord('C-d') -- just the one point is deleted check_eq(drawing.shapes[1].mode, 'polygon', 'F - test_delete_point_from_polygon/shape') @@ -577,24 +577,24 @@ end function test_delete_point_from_polygon() io.write('\ntest_delete_point_from_polygon') -- create a drawing with two lines connected at a point - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() -- first point - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) App.run_after_keychord('g') -- polygon mode -- second point - App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36) + App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('p') -- add point -- third point - App.run_after_mouse_release(Margin_left+14, Margin_top+Drawing_padding_top+16, 1) - local drawing = Lines[1] + App.run_after_mouse_release(Editor_state.margin_left+14, Editor_state.margin_top+Editor_state.drawing_padding_top+16, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_delete_point_from_polygon/baseline/#shapes') check_eq(drawing.shapes[1].mode, 'polygon', 'F - test_delete_point_from_polygon/baseline/mode') check_eq(#drawing.shapes[1].vertices, 3, 'F - test_delete_point_from_polygon/baseline/vertices') -- hover on a point and delete - App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36) + App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('C-d') -- there's < 3 points left, so the whole polygon is deleted check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_delete_point_from_polygon') @@ -603,15 +603,15 @@ end function test_undo_name_point() io.write('\ntest_undo_name_point') -- create a drawing with a line - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() -- draw a line - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_undo_name_point/baseline/#shapes') check_eq(#drawing.points, 2, 'F - test_undo_name_point/baseline/#points') check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_name_point/baseline/shape:1') @@ -622,40 +622,40 @@ function test_undo_name_point() check_eq(p2.x, 35, 'F - test_undo_name_point/baseline/p2:x') check_eq(p2.y, 36, 'F - test_undo_name_point/baseline/p2:y') check_nil(p2.name, 'F - test_undo_name_point/baseline/p2:name') - check_eq(#History, 1, 'F - test_undo_name_point/baseline/history:1') + check_eq(#Editor_state.history, 1, 'F - test_undo_name_point/baseline/history:1') -- enter 'name' mode without moving the mouse App.run_after_keychord('C-n') App.run_after_textinput('A') App.run_after_keychord('return') check_eq(p2.name, 'A', 'F - test_undo_name_point/baseline') - check_eq(#History, 3, 'F - test_undo_name_point/baseline/history:2') - check_eq(Next_history, 4, 'F - test_undo_name_point/baseline/next_history') + check_eq(#Editor_state.history, 3, 'F - test_undo_name_point/baseline/history:2') + check_eq(Editor_state.next_history, 4, 'F - test_undo_name_point/baseline/next_history') -- undo App.run_after_keychord('C-z') - local drawing = Lines[1] + local drawing = Editor_state.lines[1] local p2 = drawing.points[drawing.shapes[1].p2] - check_eq(Next_history, 3, 'F - test_undo_name_point/next_history') + check_eq(Editor_state.next_history, 3, 'F - test_undo_name_point/next_history') check_eq(p2.name, '', 'F - test_undo_name_point') -- not quite what it was before, but close enough -- wait until save App.wait_fake_time(3.1) App.update(0) -- undo is saved - Lines = load_from_disk(Filename) - local p2 = Lines[1].points[drawing.shapes[1].p2] + Editor_state.lines = load_from_disk(Editor_state.filename) + local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2] check_eq(p2.name, '', 'F - test_undo_name_point/save') end function test_undo_move_point() io.write('\ntest_undo_move_point') -- create a drawing with a line - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 1, 'F - test_undo_move_point/baseline/#shapes') check_eq(#drawing.points, 2, 'F - test_undo_move_point/baseline/#points') check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_move_point/baseline/shape:1') @@ -668,28 +668,28 @@ function test_undo_move_point() check_nil(p2.name, 'F - test_undo_move_point/baseline/p2:name') -- move p2 App.run_after_keychord('C-u') - App.mouse_move(Margin_left+26, Margin_top+Drawing_padding_top+44) + App.mouse_move(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44) App.update(0.05) local p2 = drawing.points[drawing.shapes[1].p2] check_eq(p2.x, 26, 'F - test_undo_move_point/x') check_eq(p2.y, 44, 'F - test_undo_move_point/y') -- exit 'move' mode - App.run_after_mouse_click(Margin_left+26, Margin_top+Drawing_padding_top+44, 1) - check_eq(Next_history, 4, 'F - test_undo_move_point/next_history') + App.run_after_mouse_click(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44, 1) + check_eq(Editor_state.next_history, 4, 'F - test_undo_move_point/next_history') -- undo App.run_after_keychord('C-z') App.run_after_keychord('C-z') -- bug: need to undo twice - local drawing = Lines[1] + local drawing = Editor_state.lines[1] local p2 = drawing.points[drawing.shapes[1].p2] - check_eq(Next_history, 2, 'F - test_undo_move_point/next_history') + check_eq(Editor_state.next_history, 2, 'F - test_undo_move_point/next_history') check_eq(p2.x, 35, 'F - test_undo_move_point/x') check_eq(p2.y, 36, 'F - test_undo_move_point/y') -- wait until save App.wait_fake_time(3.1) App.update(0) -- undo is saved - Lines = load_from_disk(Filename) - local p2 = Lines[1].points[drawing.shapes[1].p2] + Editor_state.lines = load_from_disk(Editor_state.filename) + local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2] check_eq(p2.x, 35, 'F - test_undo_move_point/save/x') check_eq(p2.y, 36, 'F - test_undo_move_point/save/y') end @@ -697,35 +697,35 @@ end function test_undo_delete_point() io.write('\ntest_undo_delete_point') -- create a drawing with two lines connected at a point - Filename = 'foo' - App.screen.init{width=Margin_width+256, height=300} -- drawing coordinates 1:1 with pixels - Lines = load_array{'```lines', '```', ''} - Current_drawing_mode = 'line' + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_width+256, height=300} -- drawing coordinates 1:1 with pixels + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.current_drawing_mode = 'line' edit.draw() - App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1) - App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1) - App.run_after_mouse_release(Margin_left+55, Margin_top+Drawing_padding_top+26, 1) - local drawing = Lines[1] + App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1) + App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1) + App.run_after_mouse_release(Editor_state.margin_left+55, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1) + local drawing = Editor_state.lines[1] check_eq(#drawing.shapes, 2, 'F - test_undo_delete_point/baseline/#shapes') check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_delete_point/baseline/shape:1') check_eq(drawing.shapes[2].mode, 'line', 'F - test_undo_delete_point/baseline/shape:2') -- hover on the common point and delete - App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+36) + App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36) App.run_after_keychord('C-d') check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_undo_delete_point/shape:1') check_eq(drawing.shapes[2].mode, 'deleted', 'F - test_undo_delete_point/shape:2') -- undo App.run_after_keychord('C-z') - local drawing = Lines[1] + local drawing = Editor_state.lines[1] local p2 = drawing.points[drawing.shapes[1].p2] - check_eq(Next_history, 3, 'F - test_undo_move_point/next_history') + check_eq(Editor_state.next_history, 3, 'F - test_undo_move_point/next_history') check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_delete_point/shape:1') check_eq(drawing.shapes[2].mode, 'line', 'F - test_undo_delete_point/shape:2') -- wait until save App.wait_fake_time(3.1) App.update(0) -- undo is saved - Lines = load_from_disk(Filename) - check_eq(#Lines[1].shapes, 2, 'F - test_undo_delete_point/save') + Editor_state.lines = load_from_disk(Editor_state.filename) + check_eq(#Editor_state.lines[1].shapes, 2, 'F - test_undo_delete_point/save') end diff --git a/edit.lua b/edit.lua index a114607..d136c5d 100644 --- a/edit.lua +++ b/edit.lua @@ -22,100 +22,110 @@ require 'icons' edit = {} -- run in both tests and a real run -function edit.initialize_globals() --- a line is either text or a drawing --- a text is a table with: --- mode = 'text', --- string data, --- startpos, the index of data the line starts rendering from (if currently on screen), can only be >1 for topmost line on screen --- starty, the y coord in pixels --- some cached data that's blown away and recomputed when data changes: --- fragments: snippets of rendered love.graphics.Text, guaranteed to not wrap --- screen_line_starting_pos: optional array of grapheme indices if it wraps over more than one screen line --- a drawing is a table with: --- mode = 'drawing' --- a (y) coord in pixels (updated while painting screen), --- a (h)eight, --- an array of points, and --- an array of shapes --- a shape is a table containing: --- a mode --- an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing) --- an array vertices for mode 'polygon', 'rectangle', 'square' --- p1, p2 for mode 'line' --- center, radius for mode 'circle' --- center, radius, start_angle, end_angle for mode 'arc' --- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide --- The field names are carefully chosen so that switching modes in midstream --- remembers previously entered points where that makes sense. -Lines = {{mode='text', data=''}} +function edit.initialize_state() + local result = { + -- a line is either text or a drawing + -- a text is a table with: + -- mode = 'text', + -- string data, + -- startpos, the index of data the line starts rendering from (if currently on screen), can only be >1 for topmost line on screen + -- starty, the y coord in pixels + -- some cached data that's blown away and recomputed when data changes: + -- fragments: snippets of rendered love.graphics.Text, guaranteed to not wrap + -- screen_line_starting_pos: optional array of grapheme indices if it wraps over more than one screen line + -- a drawing is a table with: + -- mode = 'drawing' + -- a (y) coord in pixels (updated while painting screen), + -- a (h)eight, + -- an array of points, and + -- an array of shapes + -- a shape is a table containing: + -- a mode + -- an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing) + -- an array vertices for mode 'polygon', 'rectangle', 'square' + -- p1, p2 for mode 'line' + -- center, radius for mode 'circle' + -- center, radius, start_angle, end_angle for mode 'arc' + -- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide + -- The field names are carefully chosen so that switching modes in midstream + -- remembers previously entered points where that makes sense. + lines = {{mode='text', data=''}}, --- Lines can be too long to fit on screen, in which case they _wrap_ into --- multiple _screen lines_. --- --- Therefore, any potential location for the cursor can be described in two ways: --- * schema 1: As a combination of line index and position within a line (in utf8 codepoint units) --- * schema 2: As a combination of line index, screen line index within the line, and a position within the screen line. --- --- Most of the time we'll only persist positions in schema 1, translating to --- schema 2 when that's convenient. --- --- Make sure these coordinates are never aliased, so that changing one causes --- action at a distance. -Screen_top1 = {line=1, pos=1} -- position of start of screen line at top of screen -Cursor1 = {line=1, pos=1} -- position of cursor -Screen_bottom1 = {line=1, pos=1} -- position of start of screen line at bottom of screen + -- Lines can be too long to fit on screen, in which case they _wrap_ into + -- multiple _screen lines_. + -- + -- Therefore, any potential location for the cursor can be described in two ways: + -- * schema 1: As a combination of line index and position within a line (in utf8 codepoint units) + -- * schema 2: As a combination of line index, screen line index within the line, and a position within the screen line. + -- + -- Most of the time we'll only persist positions in schema 1, translating to + -- schema 2 when that's convenient. + -- + -- Make sure these coordinates are never aliased, so that changing one causes + -- action at a distance. + screen_top1 = {line=1, pos=1}, -- position of start of screen line at top of screen + cursor1 = {line=1, pos=1}, -- position of cursor + screen_bottom1 = {line=1, pos=1}, -- position of start of screen line at bottom of screen -Selection1 = {} -Old_cursor1, Old_selection1, Mousepress_shift = nil -- some extra state to compute selection between mouse press and release -Recent_mouse = {} -- when selecting text, avoid recomputing some state on every single frame + selection1 = {}, + -- some extra state to compute selection between mouse press and release + old_cursor1 = nil, + old_selection1 = nil, + mousepress_shift = nil, + -- when selecting text, avoid recomputing some state on every single frame + recent_mouse = {}, -Cursor_x, Cursor_y = 0, 0 -- in pixels + -- cursor coordinates in pixels + cursor_x = 0, + cursor_y = 0, -Current_drawing_mode = 'line' -Previous_drawing_mode = nil + current_drawing_mode = 'line', + previous_drawing_mode = nil, -- extra state for some ephemeral modes like moving/deleting/naming points --- values for tests -Font_height = 14 -Line_height = 15 --- widest possible character width -Em = App.newText(love.graphics.getFont(), 'm') + -- these default values are important for tests + font_height = 14, + line_height = 15, + -- widest possible character width + em = App.newText(love.graphics.getFont(), 'm'), -Margin_top = 15 -Margin_left = 25 -Margin_right = 25 -Margin_width = Margin_left + Margin_right + margin_top = 15, + margin_left = 25, + margin_right = 25, + margin_width = nil, -Drawing_padding_top = 10 -Drawing_padding_bottom = 10 -Drawing_padding_height = Drawing_padding_top + Drawing_padding_bottom + drawing_padding_top = 10, + drawing_padding_bottom = 10, + drawing_padding_height = nil, -Filename = love.filesystem.getUserDirectory()..'/lines.txt' -Next_save = nil + filename = love.filesystem.getUserDirectory()..'/lines.txt', + next_save = nil, --- undo -History = {} -Next_history = 1 + -- undo + history = {}, + next_history = 1, --- search -Search_term = nil -Search_text = nil -Search_backup = nil -- stuff to restore when cancelling search - -end -- App.initialize_globals + -- search + search_term = nil, + search_text = nil, + search_backup = nil, -- stuff to restore when cancelling search + } + result.margin_width = result.margin_left + result.margin_right + result.drawing_padding_height = result.drawing_padding_top + result.drawing_padding_bottom + return result +end -- App.initialize_state function edit.draw() App.color(Text_color) ---? print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos) - assert(Text.le1(Screen_top1, Cursor1)) - Cursor_y = -1 - local y = Margin_top +--? print(Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos) + assert(Text.le1(Editor_state.screen_top1, Editor_state.cursor1)) + Editor_state.cursor_y = -1 + local y = Editor_state.margin_top --? print('== draw') - for line_index = Screen_top1.line,#Lines do - local line = Lines[line_index] + for line_index = Editor_state.screen_top1.line,#Editor_state.lines do + local line = Editor_state.lines[line_index] --? print('draw:', y, line_index, line) - if y + Line_height > App.screen.height then break end - Screen_bottom1.line = line_index + if y + Editor_state.line_height > App.screen.height then break end + Editor_state.screen_bottom1.line = line_index if line.mode == 'text' and line.data == '' then line.starty = y line.startpos = 1 @@ -124,76 +134,76 @@ function edit.draw() icon = icon.insert_drawing, onpress1 = function() Drawing.before = snapshot(line_index-1, line_index) - table.insert(Lines, line_index, {mode='drawing', y=y, h=256/2, points={}, shapes={}, pending={}}) - if Cursor1.line >= line_index then - Cursor1.line = Cursor1.line+1 + table.insert(Editor_state.lines, line_index, {mode='drawing', y=y, h=256/2, points={}, shapes={}, pending={}}) + if Editor_state.cursor1.line >= line_index then + Editor_state.cursor1.line = Editor_state.cursor1.line+1 end schedule_save() record_undo_event({before=Drawing.before, after=snapshot(line_index-1, line_index+1)}) end }) - if Search_term == nil then - if line_index == Cursor1.line then - Text.draw_cursor(Margin_left, y) + if Editor_state.search_term == nil then + if line_index == Editor_state.cursor1.line then + Text.draw_cursor(Editor_state.margin_left, y) end end - Screen_bottom1.pos = Screen_top1.pos - y = y + Line_height + Editor_state.screen_bottom1.pos = Editor_state.screen_top1.pos + y = y + Editor_state.line_height elseif line.mode == 'drawing' then - y = y+Drawing_padding_top + y = y+Editor_state.drawing_padding_top line.y = y Drawing.draw(line) - y = y + Drawing.pixels(line.h) + Drawing_padding_bottom + y = y + Drawing.pixels(line.h) + Editor_state.drawing_padding_bottom else line.starty = y line.startpos = 1 - if line_index == Screen_top1.line then - line.startpos = Screen_top1.pos + if line_index == Editor_state.screen_top1.line then + line.startpos = Editor_state.screen_top1.pos end --? print('text.draw', y, line_index) - y, Screen_bottom1.pos = Text.draw(line, line_index, line.starty, Margin_left, App.screen.width-Margin_right) - y = y + Line_height + y, Editor_state.screen_bottom1.pos = Text.draw(line, line_index, line.starty, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + y = y + Editor_state.line_height --? print('=> y', y) end end - if Cursor_y == -1 then - Cursor_y = App.screen.height + if Editor_state.cursor_y == -1 then + Editor_state.cursor_y = App.screen.height end ---? print('screen bottom: '..tostring(Screen_bottom1.pos)..' in '..tostring(Lines[Screen_bottom1.line].data)) - if Search_term then +--? print('screen bottom: '..tostring(Editor_state.screen_bottom1.pos)..' in '..tostring(Editor_state.lines[Editor_state.screen_bottom1.line].data)) + if Editor_state.search_term then Text.draw_search_bar() end end function edit.update(dt) Drawing.update(dt) - if Next_save and Next_save < App.getTime() then - save_to_disk(Lines, Filename) - Next_save = nil + if Editor_state.next_save and Editor_state.next_save < App.getTime() then + save_to_disk(Editor_state.lines, Editor_state.filename) + Editor_state.next_save = nil end end function schedule_save() - if Next_save == nil then - Next_save = App.getTime() + 3 -- short enough that you're likely to still remember what you did + if Editor_state.next_save == nil then + Editor_state.next_save = App.getTime() + 3 -- short enough that you're likely to still remember what you did end end function edit.quit() -- make sure to save before quitting - if Next_save then - save_to_disk(Lines, Filename) + if Editor_state.next_save then + save_to_disk(Editor_state.lines, Editor_state.filename) end end function edit.mouse_pressed(x,y, mouse_button) - if Search_term then return end ---? print('press', Selection1.line, Selection1.pos) + if Editor_state.search_term then return end +--? print('press', Editor_state.selection1.line, Editor_state.selection1.pos) propagate_to_button_handlers(x,y, mouse_button) - for line_index,line in ipairs(Lines) do + for line_index,line in ipairs(Editor_state.lines) do if line.mode == 'text' then - if Text.in_line(line, x,y, Margin_left, App.screen.width-Margin_right) then + if Text.in_line(line, x,y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) then -- delicate dance between cursor, selection and old cursor/selection -- scenarios: -- regular press+release: sets cursor, clears selection @@ -203,20 +213,20 @@ function edit.mouse_pressed(x,y, mouse_button) -- press and hold to start a selection: sets selection on press, cursor on release -- press and hold, then press shift: ignore shift -- i.e. mousereleased should never look at shift state - Old_cursor1 = Cursor1 - Old_selection1 = Selection1 - Mousepress_shift = App.shift_down() - Selection1 = { + Editor_state.old_cursor1 = Editor_state.cursor1 + Editor_state.old_selection1 = Editor_state.selection1 + Editor_state.mousepress_shift = App.shift_down() + Editor_state.selection1 = { line=line_index, - pos=Text.to_pos_on_line(line, x, y, Margin_left, App.screen.width-Margin_right), + pos=Text.to_pos_on_line(line, x, y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right), } ---? print('selection', Selection1.line, Selection1.pos) +--? print('selection', Editor_state.selection1.line, Editor_state.selection1.pos) break end elseif line.mode == 'drawing' then if Drawing.in_drawing(line, x, y) then - Lines.current_drawing_index = line_index - Lines.current_drawing = line + Editor_state.lines.current_drawing_index = line_index + Editor_state.lines.current_drawing = line Drawing.before = snapshot(line_index) Drawing.mouse_pressed(line, x,y, mouse_button) break @@ -226,56 +236,56 @@ function edit.mouse_pressed(x,y, mouse_button) end function edit.mouse_released(x,y, mouse_button) - if Search_term then return end + if Editor_state.search_term then return end --? print('release') - if Lines.current_drawing then + if Editor_state.lines.current_drawing then Drawing.mouse_released(x,y, mouse_button) schedule_save() if Drawing.before then - record_undo_event({before=Drawing.before, after=snapshot(Lines.current_drawing_index)}) + record_undo_event({before=Drawing.before, after=snapshot(Editor_state.lines.current_drawing_index)}) Drawing.before = nil end else - for line_index,line in ipairs(Lines) do + for line_index,line in ipairs(Editor_state.lines) do if line.mode == 'text' then - if Text.in_line(line, x,y, Margin_left, App.screen.width-Margin_right) then + if Text.in_line(line, x,y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) then --? print('reset selection') - Cursor1 = { + Editor_state.cursor1 = { line=line_index, - pos=Text.to_pos_on_line(line, x, y, Margin_left, App.screen.width-Margin_right), + pos=Text.to_pos_on_line(line, x, y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right), } ---? print('cursor', Cursor1.line, Cursor1.pos) - if Mousepress_shift then - if Old_selection1.line == nil then - Selection1 = Old_cursor1 +--? print('cursor', Editor_state.cursor1.line, Editor_state.cursor1.pos) + if Editor_state.mousepress_shift then + if Editor_state.old_selection1.line == nil then + Editor_state.selection1 = Editor_state.old_cursor1 else - Selection1 = Old_selection1 + Editor_state.selection1 = Editor_state.old_selection1 end end - Old_cursor1, Old_selection1, Mousepress_shift = nil - if eq(Cursor1, Selection1) then - Selection1 = {} + Editor_state.old_cursor1, Editor_state.old_selection1, Editor_state.mousepress_shift = nil + if eq(Editor_state.cursor1, Editor_state.selection1) then + Editor_state.selection1 = {} end break end end end ---? print('selection:', Selection1.line, Selection1.pos) +--? print('selection:', Editor_state.selection1.line, Editor_state.selection1.pos) end end function edit.textinput(t) - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll - if Search_term then - Search_term = Search_term..t - Search_text = nil + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll + if Editor_state.search_term then + Editor_state.search_term = Editor_state.search_term..t + Editor_state.search_text = nil Text.search_next() - elseif Current_drawing_mode == 'name' then - local before = snapshot(Lines.current_drawing_index) - local drawing = Lines.current_drawing + elseif Editor_state.current_drawing_mode == 'name' then + local before = snapshot(Editor_state.lines.current_drawing_index) + local drawing = Editor_state.lines.current_drawing local p = drawing.points[drawing.pending.target_point] p.name = p.name..t - record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)}) + record_undo_event({before=before, after=snapshot(Editor_state.lines.current_drawing_index)}) else Text.textinput(t) end @@ -283,94 +293,94 @@ function edit.textinput(t) end function edit.keychord_pressed(chord, key) - if Selection1.line and - not Lines.current_drawing and + if Editor_state.selection1.line and + not Editor_state.lines.current_drawing and -- printable character created using shift key => delete selection -- (we're not creating any ctrl-shift- or alt-shift- combinations using regular/printable keys) (not App.shift_down() or utf8.len(key) == 1) and chord ~= 'C-c' and chord ~= 'C-x' and chord ~= 'backspace' and backspace ~= 'delete' and not App.is_cursor_movement(chord) then - Text.delete_selection(Margin_left, App.screen.width-Margin_right) + Text.delete_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) end - if Search_term then + if Editor_state.search_term then if chord == 'escape' then - Search_term = nil - Search_text = nil - Cursor1 = Search_backup.cursor - Screen_top1 = Search_backup.screen_top - Search_backup = nil + Editor_state.search_term = nil + Editor_state.search_text = nil + Editor_state.cursor1 = Editor_state.search_backup.cursor + Editor_state.screen_top1 = Editor_state.search_backup.screen_top + Editor_state.search_backup = nil Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks elseif chord == 'return' then - Search_term = nil - Search_text = nil - Search_backup = nil + Editor_state.search_term = nil + Editor_state.search_text = nil + Editor_state.search_backup = nil elseif chord == 'backspace' then - local len = utf8.len(Search_term) - local byte_offset = Text.offset(Search_term, len) - Search_term = string.sub(Search_term, 1, byte_offset-1) - Search_text = nil + local len = utf8.len(Editor_state.search_term) + local byte_offset = Text.offset(Editor_state.search_term, len) + Editor_state.search_term = string.sub(Editor_state.search_term, 1, byte_offset-1) + Editor_state.search_text = nil elseif chord == 'down' then - Cursor1.pos = Cursor1.pos+1 + Editor_state.cursor1.pos = Editor_state.cursor1.pos+1 Text.search_next() elseif chord == 'up' then Text.search_previous() end return elseif chord == 'C-f' then - Search_term = '' - Search_backup = {cursor={line=Cursor1.line, pos=Cursor1.pos}, screen_top={line=Screen_top1.line, pos=Screen_top1.pos}} - assert(Search_text == nil) + Editor_state.search_term = '' + Editor_state.search_backup = {cursor={line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}, screen_top={line=Editor_state.screen_top1.line, pos=Editor_state.screen_top1.pos}} + assert(Editor_state.search_text == nil) elseif chord == 'C-=' then - initialize_font_settings(Font_height+2) + initialize_font_settings(Editor_state.font_height+2) Text.redraw_all() elseif chord == 'C--' then - initialize_font_settings(Font_height-2) + initialize_font_settings(Editor_state.font_height-2) Text.redraw_all() elseif chord == 'C-0' then initialize_font_settings(20) Text.redraw_all() elseif chord == 'C-z' then - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll local event = undo_event() if event then local src = event.before - Screen_top1 = deepcopy(src.screen_top) - Cursor1 = deepcopy(src.cursor) - Selection1 = deepcopy(src.selection) - patch(Lines, event.after, event.before) + Editor_state.screen_top1 = deepcopy(src.screen_top) + Editor_state.cursor1 = deepcopy(src.cursor) + Editor_state.selection1 = deepcopy(src.selection) + patch(Editor_state.lines, event.after, event.before) Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks schedule_save() end elseif chord == 'C-y' then - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll local event = redo_event() if event then local src = event.after - Screen_top1 = deepcopy(src.screen_top) - Cursor1 = deepcopy(src.cursor) - Selection1 = deepcopy(src.selection) - patch(Lines, event.before, event.after) + Editor_state.screen_top1 = deepcopy(src.screen_top) + Editor_state.cursor1 = deepcopy(src.cursor) + Editor_state.selection1 = deepcopy(src.selection) + patch(Editor_state.lines, event.before, event.after) Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks schedule_save() end -- clipboard elseif chord == 'C-c' then - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll local s = Text.selection() if s then App.setClipboardText(s) end elseif chord == 'C-x' then - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll - local s = Text.cut_selection(Margin_left, App.screen.width-Margin_right) + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll + local s = Text.cut_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) if s then App.setClipboardText(s) end schedule_save() elseif chord == 'C-v' then - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll -- We don't have a good sense of when to scroll, so we'll be conservative -- and sometimes scroll when we didn't quite need to. - local before_line = Cursor1.line + local before_line = Editor_state.cursor1.line local before = snapshot(before_line) local clipboard_data = App.getClipboardText() for _,code in utf8.codes(clipboard_data) do @@ -382,10 +392,10 @@ function edit.keychord_pressed(chord, key) end end if Text.cursor_past_screen_bottom() then - Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.height-Margin_right) + Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.height-Editor_state.margin_right) end schedule_save() - record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)}) + record_undo_event({before=before, after=snapshot(before_line, Editor_state.cursor1.line)}) -- dispatch to drawing or text elseif App.mouse_down(1) or chord:sub(1,2) == 'C-' then -- DON'T reset line.y here @@ -397,33 +407,33 @@ function edit.keychord_pressed(chord, key) schedule_save() end elseif chord == 'escape' and not App.mouse_down(1) then - for _,line in ipairs(Lines) do + for _,line in ipairs(Editor_state.lines) do if line.mode == 'drawing' then line.show_help = false end end - elseif Current_drawing_mode == 'name' then + elseif Editor_state.current_drawing_mode == 'name' then if chord == 'return' then - Current_drawing_mode = Previous_drawing_mode - Previous_drawing_mode = nil + Editor_state.current_drawing_mode = Editor_state.previous_drawing_mode + Editor_state.previous_drawing_mode = nil else - local before = snapshot(Lines.current_drawing_index) - local drawing = Lines.current_drawing + local before = snapshot(Editor_state.lines.current_drawing_index) + local drawing = Editor_state.lines.current_drawing local p = drawing.points[drawing.pending.target_point] if chord == 'escape' then p.name = nil - record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)}) + record_undo_event({before=before, after=snapshot(Editor_state.lines.current_drawing_index)}) elseif chord == 'backspace' then local len = utf8.len(p.name) local byte_offset = Text.offset(p.name, len-1) if len == 1 then byte_offset = 0 end p.name = string.sub(p.name, 1, byte_offset) - record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)}) + record_undo_event({before=before, after=snapshot(Editor_state.lines.current_drawing_index)}) end end schedule_save() else - for _,line in ipairs(Lines) do line.y = nil end -- just in case we scroll + for _,line in ipairs(Editor_state.lines) do line.y = nil end -- just in case we scroll Text.keychord_pressed(chord) end end diff --git a/help.lua b/help.lua index 92cdb0a..c65e33d 100644 --- a/help.lua +++ b/help.lua @@ -1,144 +1,144 @@ function draw_help_without_mouse_pressed(drawing) App.color(Help_color) local y = drawing.y+10 - love.graphics.print("Things you can do:", Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Press the mouse button to start drawing a "..current_shape(), Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Hover on a point and press 'ctrl+u' to pick it up and start moving it,", Margin_left+30,y) - y = y + Line_height - love.graphics.print("then press the mouse button to drop it", Margin_left+30+bullet_indent(),y) - y = y + Line_height - love.graphics.print("* Hover on a point and press 'ctrl+n', type a name, then press 'enter'", Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Hover on a point or shape and press 'ctrl+d' to delete it", Margin_left+30,y) - y = y + Line_height - if Current_drawing_mode ~= 'freehand' then - love.graphics.print("* Press 'ctrl+p' to switch to drawing freehand strokes", Margin_left+30,y) - y = y + Line_height - end - if Current_drawing_mode ~= 'line' then - love.graphics.print("* Press 'ctrl+l' to switch to drawing lines", Margin_left+30,y) - y = y + Line_height - end - if Current_drawing_mode ~= 'manhattan' then - love.graphics.print("* Press 'ctrl+m' to switch to drawing horizontal/vertical lines", Margin_left+30,y) - y = y + Line_height - end - if Current_drawing_mode ~= 'circle' then - love.graphics.print("* Press 'ctrl+o' to switch to drawing circles/arcs", Margin_left+30,y) - y = y + Line_height - end - if Current_drawing_mode ~= 'polygon' then - love.graphics.print("* Press 'ctrl+g' to switch to drawing polygons", Margin_left+30,y) - y = y + Line_height - end - if Current_drawing_mode ~= 'rectangle' then - love.graphics.print("* Press 'ctrl+r' to switch to drawing rectangles", Margin_left+30,y) - y = y + Line_height - end - if Current_drawing_mode ~= 'square' then - love.graphics.print("* Press 'ctrl+s' to switch to drawing squares", Margin_left+30,y) - y = y + Line_height - end - love.graphics.print("* Press 'ctrl+=' or 'ctrl+-' to zoom in or out, ctrl+0 to reset zoom", Margin_left+30,y) - y = y + Line_height - love.graphics.print("Press 'esc' now to hide this message", Margin_left+30,y) - y = y + Line_height + love.graphics.print("Things you can do:", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Press the mouse button to start drawing a "..current_shape(), Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Hover on a point and press 'ctrl+u' to pick it up and start moving it,", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("then press the mouse button to drop it", Editor_state.margin_left+30+bullet_indent(),y) + y = y + Editor_state.line_height + love.graphics.print("* Hover on a point and press 'ctrl+n', type a name, then press 'enter'", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Hover on a point or shape and press 'ctrl+d' to delete it", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + if Editor_state.current_drawing_mode ~= 'freehand' then + love.graphics.print("* Press 'ctrl+p' to switch to drawing freehand strokes", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + if Editor_state.current_drawing_mode ~= 'line' then + love.graphics.print("* Press 'ctrl+l' to switch to drawing lines", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + if Editor_state.current_drawing_mode ~= 'manhattan' then + love.graphics.print("* Press 'ctrl+m' to switch to drawing horizontal/vertical lines", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + if Editor_state.current_drawing_mode ~= 'circle' then + love.graphics.print("* Press 'ctrl+o' to switch to drawing circles/arcs", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + if Editor_state.current_drawing_mode ~= 'polygon' then + love.graphics.print("* Press 'ctrl+g' to switch to drawing polygons", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + if Editor_state.current_drawing_mode ~= 'rectangle' then + love.graphics.print("* Press 'ctrl+r' to switch to drawing rectangles", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + if Editor_state.current_drawing_mode ~= 'square' then + love.graphics.print("* Press 'ctrl+s' to switch to drawing squares", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + end + love.graphics.print("* Press 'ctrl+=' or 'ctrl+-' to zoom in or out, ctrl+0 to reset zoom", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("Press 'esc' now to hide this message", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height App.color(Help_background_color) - love.graphics.rectangle('fill', Margin_left,drawing.y, App.screen.width-Margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y)) + love.graphics.rectangle('fill', Editor_state.margin_left,drawing.y, App.screen.width-Editor_state.margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y)) end function draw_help_with_mouse_pressed(drawing) App.color(Help_color) local y = drawing.y+10 - love.graphics.print("You're currently drawing a "..current_shape(drawing.pending), Margin_left+30,y) - y = y + Line_height - love.graphics.print('Things you can do now:', Margin_left+30,y) - y = y + Line_height - if Current_drawing_mode == 'freehand' then - love.graphics.print('* Release the mouse button to finish drawing the stroke', Margin_left+30,y) - y = y + Line_height - elseif Current_drawing_mode == 'line' or Current_drawing_mode == 'manhattan' then - love.graphics.print('* Release the mouse button to finish drawing the line', Margin_left+30,y) - y = y + Line_height - elseif Current_drawing_mode == 'circle' then + love.graphics.print("You're currently drawing a "..current_shape(drawing.pending), Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print('Things you can do now:', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + if Editor_state.current_drawing_mode == 'freehand' then + love.graphics.print('* Release the mouse button to finish drawing the stroke', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + elseif Editor_state.current_drawing_mode == 'line' or Editor_state.current_drawing_mode == 'manhattan' then + love.graphics.print('* Release the mouse button to finish drawing the line', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + elseif Editor_state.current_drawing_mode == 'circle' then if drawing.pending.mode == 'circle' then - love.graphics.print('* Release the mouse button to finish drawing the circle', Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Press 'a' to draw just an arc of a circle", Margin_left+30,y) + love.graphics.print('* Release the mouse button to finish drawing the circle', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Press 'a' to draw just an arc of a circle", Editor_state.margin_left+30,y) else - love.graphics.print('* Release the mouse button to finish drawing the arc', Margin_left+30,y) + love.graphics.print('* Release the mouse button to finish drawing the arc', Editor_state.margin_left+30,y) end - y = y + Line_height - elseif Current_drawing_mode == 'polygon' then - love.graphics.print('* Release the mouse button to finish drawing the polygon', Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Press 'p' to add a vertex to the polygon", Margin_left+30,y) - y = y + Line_height - elseif Current_drawing_mode == 'rectangle' then + y = y + Editor_state.line_height + elseif Editor_state.current_drawing_mode == 'polygon' then + love.graphics.print('* Release the mouse button to finish drawing the polygon', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Press 'p' to add a vertex to the polygon", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + elseif Editor_state.current_drawing_mode == 'rectangle' then if #drawing.pending.vertices < 2 then - love.graphics.print("* Press 'p' to add a vertex to the rectangle", Margin_left+30,y) - y = y + Line_height + love.graphics.print("* Press 'p' to add a vertex to the rectangle", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height else - love.graphics.print('* Release the mouse button to finish drawing the rectangle', Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Press 'p' to replace the second vertex of the rectangle", Margin_left+30,y) - y = y + Line_height + love.graphics.print('* Release the mouse button to finish drawing the rectangle', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Press 'p' to replace the second vertex of the rectangle", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end - elseif Current_drawing_mode == 'square' then + elseif Editor_state.current_drawing_mode == 'square' then if #drawing.pending.vertices < 2 then - love.graphics.print("* Press 'p' to add a vertex to the square", Margin_left+30,y) - y = y + Line_height + love.graphics.print("* Press 'p' to add a vertex to the square", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height else - love.graphics.print('* Release the mouse button to finish drawing the square', Margin_left+30,y) - y = y + Line_height - love.graphics.print("* Press 'p' to replace the second vertex of the square", Margin_left+30,y) - y = y + Line_height + love.graphics.print('* Release the mouse button to finish drawing the square', Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + love.graphics.print("* Press 'p' to replace the second vertex of the square", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end end - love.graphics.print("* Press 'esc' then release the mouse button to cancel the current shape", Margin_left+30,y) - y = y + Line_height - y = y + Line_height - if Current_drawing_mode ~= 'line' then - love.graphics.print("* Press 'l' to switch to drawing lines", Margin_left+30,y) - y = y + Line_height + love.graphics.print("* Press 'esc' then release the mouse button to cancel the current shape", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height + y = y + Editor_state.line_height + if Editor_state.current_drawing_mode ~= 'line' then + love.graphics.print("* Press 'l' to switch to drawing lines", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end - if Current_drawing_mode ~= 'manhattan' then - love.graphics.print("* Press 'm' to switch to drawing horizontal/vertical lines", Margin_left+30,y) - y = y + Line_height + if Editor_state.current_drawing_mode ~= 'manhattan' then + love.graphics.print("* Press 'm' to switch to drawing horizontal/vertical lines", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end - if Current_drawing_mode ~= 'circle' then - love.graphics.print("* Press 'o' to switch to drawing circles/arcs", Margin_left+30,y) - y = y + Line_height + if Editor_state.current_drawing_mode ~= 'circle' then + love.graphics.print("* Press 'o' to switch to drawing circles/arcs", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end - if Current_drawing_mode ~= 'polygon' then - love.graphics.print("* Press 'g' to switch to drawing polygons", Margin_left+30,y) - y = y + Line_height + if Editor_state.current_drawing_mode ~= 'polygon' then + love.graphics.print("* Press 'g' to switch to drawing polygons", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end - if Current_drawing_mode ~= 'rectangle' then - love.graphics.print("* Press 'r' to switch to drawing rectangles", Margin_left+30,y) - y = y + Line_height + if Editor_state.current_drawing_mode ~= 'rectangle' then + love.graphics.print("* Press 'r' to switch to drawing rectangles", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end - if Current_drawing_mode ~= 'square' then - love.graphics.print("* Press 's' to switch to drawing squares", Margin_left+30,y) - y = y + Line_height + if Editor_state.current_drawing_mode ~= 'square' then + love.graphics.print("* Press 's' to switch to drawing squares", Editor_state.margin_left+30,y) + y = y + Editor_state.line_height end App.color(Help_background_color) - love.graphics.rectangle('fill', Margin_left,drawing.y, App.screen.width-Margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y)) + love.graphics.rectangle('fill', Editor_state.margin_left,drawing.y, App.screen.width-Editor_state.margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y)) end function current_shape(shape) - if Current_drawing_mode == 'freehand' then + if Editor_state.current_drawing_mode == 'freehand' then return 'freehand stroke' - elseif Current_drawing_mode == 'line' then + elseif Editor_state.current_drawing_mode == 'line' then return 'straight line' - elseif Current_drawing_mode == 'manhattan' then + elseif Editor_state.current_drawing_mode == 'manhattan' then return 'horizontal/vertical line' - elseif Current_drawing_mode == 'circle' and shape and shape.start_angle then + elseif Editor_state.current_drawing_mode == 'circle' and shape and shape.start_angle then return 'arc' else - return Current_drawing_mode + return Editor_state.current_drawing_mode end end diff --git a/main.lua b/main.lua index f1ac122..6b136b8 100644 --- a/main.lua +++ b/main.lua @@ -14,7 +14,7 @@ Editor_state = {} -- called both in tests and real run function App.initialize_globals() - edit.initialize_globals() + Editor_state = edit.initialize_state() -- resize Last_resize_time = nil @@ -37,28 +37,28 @@ function App.initialize(arg) end if #arg > 0 then - Filename = arg[1] - Lines = load_from_disk(Filename) - Screen_top1 = {line=1, pos=1} - Cursor1 = {line=1, pos=1} - for i,line in ipairs(Lines) do + Editor_state.filename = arg[1] + Editor_state.lines = load_from_disk(Editor_state.filename) + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.cursor1 = {line=1, pos=1} + for i,line in ipairs(Editor_state.lines) do if line.mode == 'text' then - Cursor1.line = i + Editor_state.cursor1.line = i break end end else - Lines = load_from_disk(Filename) - if Cursor1.line > #Lines or Lines[Cursor1.line].mode ~= 'text' then - for i,line in ipairs(Lines) do + Editor_state.lines = load_from_disk(Editor_state.filename) + if Editor_state.cursor1.line > #Editor_state.lines or Editor_state.lines[Editor_state.cursor1.line].mode ~= 'text' then + for i,line in ipairs(Editor_state.lines) do if line.mode == 'text' then - Cursor1.line = i + Editor_state.cursor1.line = i break end end end end - love.window.setTitle('lines.love - '..Filename) + love.window.setTitle('lines.love - '..Editor_state.filename) if #arg > 1 then print('ignoring commandline args after '..arg[1]) @@ -83,10 +83,10 @@ function load_settings() App.screen.flags.minheight = math.min(App.screen.width, 200) App.screen.width, App.screen.height = settings.width, settings.height love.window.setMode(App.screen.width, App.screen.height, App.screen.flags) - Filename = settings.filename + Editor_state.filename = settings.filename initialize_font_settings(settings.font_height) - Screen_top1 = settings.screen_top - Cursor1 = settings.cursor + Editor_state.screen_top1 = settings.screen_top + Editor_state.cursor1 = settings.cursor end function load_defaults() @@ -99,7 +99,7 @@ function initialize_window_geometry() love.window.setMode(0, 0) -- maximize App.screen.width, App.screen.height, App.screen.flags = love.window.getMode() -- shrink slightly to account for window decoration - App.screen.width = 40*App.width(Em) + App.screen.width = 40*App.width(Editor_state.em) App.screen.height = App.screen.height-100 App.screen.flags.resizable = true App.screen.flags.minwidth = math.min(App.screen.width, 200) @@ -111,37 +111,37 @@ function App.resize(w, h) --? print(("Window resized to width: %d and height: %d."):format(w, h)) App.screen.width, App.screen.height = w, h Text.redraw_all() - Selection1 = {} -- no support for shift drag while we're resizing - Text.tweak_screen_top_and_cursor(Margin_left, App.screen.height-Margin_right) + Editor_state.selection1 = {} -- no support for shift drag while we're resizing + Text.tweak_screen_top_and_cursor(Editor_state.margin_left, App.screen.height-Editor_state.margin_right) Last_resize_time = App.getTime() end function initialize_font_settings(font_height) - Font_height = font_height - love.graphics.setFont(love.graphics.newFont(Font_height)) - Line_height = math.floor(font_height*1.3) + Editor_state.font_height = font_height + love.graphics.setFont(love.graphics.newFont(Editor_state.font_height)) + Editor_state.line_height = math.floor(font_height*1.3) - Em = App.newText(love.graphics.getFont(), 'm') + Editor_state.em = App.newText(love.graphics.getFont(), 'm') end function App.filedropped(file) -- first make sure to save edits on any existing file - if Next_save then - save_to_disk(Lines, Filename) + if Editor_state.next_save then + save_to_disk(Editor_state.lines, Editor_state.filename) end -- clear the slate for the new file App.initialize_globals() -- in particular, forget all undo history - Filename = file:getFilename() + Editor_state.filename = file:getFilename() file:open('r') - Lines = load_from_file(file) + Editor_state.lines = load_from_file(file) file:close() - for i,line in ipairs(Lines) do + for i,line in ipairs(Editor_state.lines) do if line.mode == 'text' then - Cursor1.line = i + Editor_state.cursor1.line = i break end end - love.window.setTitle('Text with Lines - '..Filename) + love.window.setTitle('Text with Editor_state.lines - '..Editor_state.filename) end function App.draw() @@ -166,16 +166,16 @@ function love.quit() edit.quit() -- save some important settings local x,y,displayindex = love.window.getPosition() - local filename = Filename + local filename = Editor_state.filename if filename:sub(1,1) ~= '/' then filename = love.filesystem.getWorkingDirectory()..'/'..filename -- '/' should work even on Windows end local settings = { x=x, y=y, displayindex=displayindex, width=App.screen.width, height=App.screen.height, - font_height=Font_height, + font_height=Editor_state.font_height, filename=filename, - screen_top=Screen_top1, cursor=Cursor1} + screen_top=Editor_state.screen_top1, cursor=Editor_state.cursor1} love.filesystem.write('config', json.encode(settings)) end diff --git a/main_tests.lua b/main_tests.lua index 98cc73d..7b5c4e8 100644 --- a/main_tests.lua +++ b/main_tests.lua @@ -1,8 +1,8 @@ function test_resize_window() io.write('\ntest_resize_window') - Filename = 'foo' - App.screen.init{width=Margin_left+300, height=300} - check_eq(App.screen.width, Margin_left+300, 'F - test_resize_window/baseline/width') + Editor_state.filename = 'foo' + App.screen.init{width=Editor_state.margin_left+300, height=300} + check_eq(App.screen.width, Editor_state.margin_left+300, 'F - test_resize_window/baseline/width') check_eq(App.screen.height, 300, 'F - test_resize_window/baseline/height') App.resize(200, 400) check_eq(App.screen.width, 200, 'F - test_resize_window/width') @@ -12,7 +12,7 @@ end function test_drop_file() io.write('\ntest_drop_file') - App.screen.init{width=Margin_left+300, height=300} + App.screen.init{width=Editor_state.margin_left+300, height=300} App.filesystem['foo'] = 'abc\ndef\nghi\n' local fake_dropped_file = { opened = false, @@ -31,18 +31,18 @@ function test_drop_file() end, } App.filedropped(fake_dropped_file) - check_eq(#Lines, 3, 'F - test_drop_file/#lines') - check_eq(Lines[1].data, 'abc', 'F - test_drop_file/lines:1') - check_eq(Lines[2].data, 'def', 'F - test_drop_file/lines:2') - check_eq(Lines[3].data, 'ghi', 'F - test_drop_file/lines:3') + check_eq(#Editor_state.lines, 3, 'F - test_drop_file/#lines') + check_eq(Editor_state.lines[1].data, 'abc', 'F - test_drop_file/lines:1') + check_eq(Editor_state.lines[2].data, 'def', 'F - test_drop_file/lines:2') + check_eq(Editor_state.lines[3].data, 'ghi', 'F - test_drop_file/lines:3') end function test_drop_file_saves_previous() io.write('\ntest_drop_file_saves_previous') - App.screen.init{width=Margin_left+300, height=300} + App.screen.init{width=Editor_state.margin_left+300, height=300} -- initially editing a file called foo that hasn't been saved to filesystem yet - Lines = load_array{'abc', 'def'} - Filename = 'foo' + Editor_state.lines = load_array{'abc', 'def'} + Editor_state.filename = 'foo' schedule_save() -- now drag a new file bar from the filesystem App.filesystem['bar'] = 'abc\ndef\nghi\n' diff --git a/search.lua b/search.lua index eca7cd7..5d794f2 100644 --- a/search.lua +++ b/search.lua @@ -1,7 +1,7 @@ -- helpers for the search bar (C-f) function Text.draw_search_bar() - local h = Line_height+2 + local h = Editor_state.line_height+2 local y = App.screen.height-h love.graphics.setColor(0.9,0.9,0.9) love.graphics.rectangle('fill', 0, y-10, App.screen.width-1, h+8) @@ -12,92 +12,92 @@ function Text.draw_search_bar() love.graphics.setColor(0.6,0.6,0.6) love.graphics.rectangle('line', 20, y-6, App.screen.width-40, h+2, 2,2) App.color(Text_color) - App.screen.print(Search_term, 25,y-5) + App.screen.print(Editor_state.search_term, 25,y-5) App.color(Cursor_color) - if Search_text == nil then - Search_text = App.newText(love.graphics.getFont(), Search_term) + if Editor_state.search_text == nil then + Editor_state.search_text = App.newText(love.graphics.getFont(), Editor_state.search_term) end - love.graphics.circle('fill', 25+App.width(Search_text),y-5+h, 2) + love.graphics.circle('fill', 25+App.width(Editor_state.search_text),y-5+h, 2) App.color(Text_color) end function Text.search_next() -- search current line - local pos = Lines[Cursor1.line].data:find(Search_term, Cursor1.pos) + local pos = Editor_state.lines[Editor_state.cursor1.line].data:find(Editor_state.search_term, Editor_state.cursor1.pos) if pos then - Cursor1.pos = pos + Editor_state.cursor1.pos = pos end if pos == nil then - for i=Cursor1.line+1,#Lines do - pos = Lines[i].data:find(Search_term) + for i=Editor_state.cursor1.line+1,#Editor_state.lines do + pos = Editor_state.lines[i].data:find(Editor_state.search_term) if pos then - Cursor1.line = i - Cursor1.pos = pos + Editor_state.cursor1.line = i + Editor_state.cursor1.pos = pos break end end end if pos == nil then -- wrap around - for i=1,Cursor1.line-1 do - pos = Lines[i].data:find(Search_term) + for i=1,Editor_state.cursor1.line-1 do + pos = Editor_state.lines[i].data:find(Editor_state.search_term) if pos then - Cursor1.line = i - Cursor1.pos = pos + Editor_state.cursor1.line = i + Editor_state.cursor1.pos = pos break end end end if pos == nil then - Cursor1.line = Search_backup.cursor.line - Cursor1.pos = Search_backup.cursor.pos - Screen_top1.line = Search_backup.screen_top.line - Screen_top1.pos = Search_backup.screen_top.pos + Editor_state.cursor1.line = Editor_state.search_backup.cursor.line + Editor_state.cursor1.pos = Editor_state.search_backup.cursor.pos + Editor_state.screen_top1.line = Editor_state.search_backup.screen_top.line + Editor_state.screen_top1.pos = Editor_state.search_backup.screen_top.pos end - if Text.lt1(Cursor1, Screen_top1) or Text.lt1(Screen_bottom1, Cursor1) then - Screen_top1.line = Cursor1.line - local _, pos = Text.pos_at_start_of_cursor_screen_line(Margin_left, App.screen.width-Margin_right) - Screen_top1.pos = pos + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) or Text.lt1(Editor_state.screen_bottom1, Editor_state.cursor1) then + Editor_state.screen_top1.line = Editor_state.cursor1.line + local _, pos = Text.pos_at_start_of_cursor_screen_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.screen_top1.pos = pos end end function Text.search_previous() -- search current line - local pos = rfind(Lines[Cursor1.line].data, Search_term, Cursor1.pos) + local pos = rfind(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.search_term, Editor_state.cursor1.pos) if pos then - Cursor1.pos = pos + Editor_state.cursor1.pos = pos end if pos == nil then - for i=Cursor1.line-1,1,-1 do - pos = rfind(Lines[i].data, Search_term) + for i=Editor_state.cursor1.line-1,1,-1 do + pos = rfind(Editor_state.lines[i].data, Editor_state.search_term) if pos then - Cursor1.line = i - Cursor1.pos = pos + Editor_state.cursor1.line = i + Editor_state.cursor1.pos = pos break end end end if pos == nil then -- wrap around - for i=#Lines,Cursor1.line+1,-1 do - pos = rfind(Lines[i].data, Search_term) + for i=#Editor_state.lines,Editor_state.cursor1.line+1,-1 do + pos = rfind(Editor_state.lines[i].data, Editor_state.search_term) if pos then - Cursor1.line = i - Cursor1.pos = pos + Editor_state.cursor1.line = i + Editor_state.cursor1.pos = pos break end end end if pos == nil then - Cursor1.line = Search_backup.cursor.line - Cursor1.pos = Search_backup.cursor.pos - Screen_top1.line = Search_backup.screen_top.line - Screen_top1.pos = Search_backup.screen_top.pos + Editor_state.cursor1.line = Editor_state.search_backup.cursor.line + Editor_state.cursor1.pos = Editor_state.search_backup.cursor.pos + Editor_state.screen_top1.line = Editor_state.search_backup.screen_top.line + Editor_state.screen_top1.pos = Editor_state.search_backup.screen_top.pos end - if Text.lt1(Cursor1, Screen_top1) or Text.lt1(Screen_bottom1, Cursor1) then - Screen_top1.line = Cursor1.line - local _, pos = Text.pos_at_start_of_cursor_screen_line(Margin_left, App.screen.width-Margin_right) - Screen_top1.pos = pos + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) or Text.lt1(Editor_state.screen_bottom1, Editor_state.cursor1) then + Editor_state.screen_top1.line = Editor_state.cursor1.line + local _, pos = Text.pos_at_start_of_cursor_screen_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.screen_top1.pos = pos end end diff --git a/select.lua b/select.lua index 9e88c60..15d3690 100644 --- a/select.lua +++ b/select.lua @@ -1,20 +1,20 @@ -- helpers for selecting portions of text --- Return any intersection of the region from Selection1 to Cursor1 (or +-- Return any intersection of the region from Editor_state.selection1 to Editor_state.cursor1 (or -- current mouse, if mouse is pressed; or recent mouse if mouse is pressed and -- currently over a drawing) with the region between {line=line_index, pos=apos} -- and {line=line_index, pos=bpos}. --- apos must be less than bpos. However Selection1 and Cursor1 can be in any order. +-- apos must be less than bpos. However Editor_state.selection1 and Editor_state.cursor1 can be in any order. -- Result: positions spos,epos between apos,bpos. function Text.clip_selection(line_index, apos, bpos, left, right) - if Selection1.line == nil then return nil,nil end - -- min,max = sorted(Selection1,Cursor1) - local minl,minp = Selection1.line,Selection1.pos + if Editor_state.selection1.line == nil then return nil,nil end + -- min,max = sorted(Editor_state.selection1,Editor_state.cursor1) + local minl,minp = Editor_state.selection1.line,Editor_state.selection1.pos local maxl,maxp if App.mouse_down(1) then maxl,maxp = Text.mouse_pos(left, right) else - maxl,maxp = Cursor1.line,Cursor1.pos + maxl,maxp = Editor_state.cursor1.line,Editor_state.cursor1.pos end if minl > maxl then minl,maxl = maxl,minl @@ -69,7 +69,7 @@ function Text.draw_highlight(line, x,y, pos, lo,hi) local text = App.newText(love.graphics.getFont(), s) local text_width = App.width(text) App.color(Highlight_color) - love.graphics.rectangle('fill', x+lo_px,y, text_width,Line_height) + love.graphics.rectangle('fill', x+lo_px,y, text_width,Editor_state.line_height) App.color(Text_color) return lo_px end @@ -78,20 +78,20 @@ end -- inefficient for some reason, so don't do it on every frame function Text.mouse_pos(left, right) local time = love.timer.getTime() - if Recent_mouse.time and Recent_mouse.time > time-0.1 then - return Recent_mouse.line, Recent_mouse.pos + if Editor_state.recent_mouse.time and Editor_state.recent_mouse.time > time-0.1 then + return Editor_state.recent_mouse.line, Editor_state.recent_mouse.pos end - Recent_mouse.time = time + Editor_state.recent_mouse.time = time local line,pos = Text.to_pos(App.mouse_x(), App.mouse_y(), left, right) if line then - Recent_mouse.line = line - Recent_mouse.pos = pos + Editor_state.recent_mouse.line = line + Editor_state.recent_mouse.pos = pos end - return Recent_mouse.line, Recent_mouse.pos + return Editor_state.recent_mouse.line, Editor_state.recent_mouse.pos end function Text.to_pos(x,y, left, right) - for line_index,line in ipairs(Lines) do + for line_index,line in ipairs(Editor_state.lines) do if line.mode == 'text' then if Text.in_line(line, x,y, left, right) then return line_index, Text.to_pos_on_line(line, x,y, left, right) @@ -101,25 +101,25 @@ function Text.to_pos(x,y, left, right) end function Text.cut_selection(left, right) - if Selection1.line == nil then return end + if Editor_state.selection1.line == nil then return end local result = Text.selection() Text.delete_selection(left, right) return result end function Text.delete_selection(left, right) - if Selection1.line == nil then return end - local minl,maxl = minmax(Selection1.line, Cursor1.line) + if Editor_state.selection1.line == nil then return end + local minl,maxl = minmax(Editor_state.selection1.line, Editor_state.cursor1.line) local before = snapshot(minl, maxl) Text.delete_selection_without_undo(left, right) - record_undo_event({before=before, after=snapshot(Cursor1.line)}) + record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)}) end function Text.delete_selection_without_undo(left, right) - if Selection1.line == nil then return end - -- min,max = sorted(Selection1,Cursor1) - local minl,minp = Selection1.line,Selection1.pos - local maxl,maxp = Cursor1.line,Cursor1.pos + if Editor_state.selection1.line == nil then return end + -- min,max = sorted(Editor_state.selection1,Editor_state.cursor1) + local minl,minp = Editor_state.selection1.line,Editor_state.selection1.pos + local maxl,maxp = Editor_state.cursor1.line,Editor_state.cursor1.pos if minl > maxl then minl,maxl = maxl,minl minp,maxp = maxp,minp @@ -128,36 +128,36 @@ function Text.delete_selection_without_undo(left, right) minp,maxp = maxp,minp end end - -- update Cursor1 and Selection1 - Cursor1.line = minl - Cursor1.pos = minp - if Text.lt1(Cursor1, Screen_top1) then - Screen_top1.line = Cursor1.line - _,Screen_top1.pos = Text.pos_at_start_of_cursor_screen_line(left, right) + -- update Editor_state.cursor1 and Editor_state.selection1 + Editor_state.cursor1.line = minl + Editor_state.cursor1.pos = minp + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then + Editor_state.screen_top1.line = Editor_state.cursor1.line + _,Editor_state.screen_top1.pos = Text.pos_at_start_of_cursor_screen_line(left, right) end - Selection1 = {} + Editor_state.selection1 = {} -- delete everything between min (inclusive) and max (exclusive) - Text.clear_cache(Lines[minl]) - local min_offset = Text.offset(Lines[minl].data, minp) - local max_offset = Text.offset(Lines[maxl].data, maxp) + Text.clear_cache(Editor_state.lines[minl]) + local min_offset = Text.offset(Editor_state.lines[minl].data, minp) + local max_offset = Text.offset(Editor_state.lines[maxl].data, maxp) if minl == maxl then --? print('minl == maxl') - Lines[minl].data = Lines[minl].data:sub(1, min_offset-1)..Lines[minl].data:sub(max_offset) + Editor_state.lines[minl].data = Editor_state.lines[minl].data:sub(1, min_offset-1)..Editor_state.lines[minl].data:sub(max_offset) return end assert(minl < maxl) - local rhs = Lines[maxl].data:sub(max_offset) + local rhs = Editor_state.lines[maxl].data:sub(max_offset) for i=maxl,minl+1,-1 do - table.remove(Lines, i) + table.remove(Editor_state.lines, i) end - Lines[minl].data = Lines[minl].data:sub(1, min_offset-1)..rhs + Editor_state.lines[minl].data = Editor_state.lines[minl].data:sub(1, min_offset-1)..rhs end function Text.selection() - if Selection1.line == nil then return end - -- min,max = sorted(Selection1,Cursor1) - local minl,minp = Selection1.line,Selection1.pos - local maxl,maxp = Cursor1.line,Cursor1.pos + if Editor_state.selection1.line == nil then return end + -- min,max = sorted(Editor_state.selection1,Editor_state.cursor1) + local minl,minp = Editor_state.selection1.line,Editor_state.selection1.pos + local maxl,maxp = Editor_state.cursor1.line,Editor_state.cursor1.pos if minl > maxl then minl,maxl = maxl,minl minp,maxp = maxp,minp @@ -166,18 +166,18 @@ function Text.selection() minp,maxp = maxp,minp end end - local min_offset = Text.offset(Lines[minl].data, minp) - local max_offset = Text.offset(Lines[maxl].data, maxp) + local min_offset = Text.offset(Editor_state.lines[minl].data, minp) + local max_offset = Text.offset(Editor_state.lines[maxl].data, maxp) if minl == maxl then - return Lines[minl].data:sub(min_offset, max_offset-1) + return Editor_state.lines[minl].data:sub(min_offset, max_offset-1) end assert(minl < maxl) - local result = {Lines[minl].data:sub(min_offset)} + local result = {Editor_state.lines[minl].data:sub(min_offset)} for i=minl+1,maxl-1 do - if Lines[i].mode == 'text' then - table.insert(result, Lines[i].data) + if Editor_state.lines[i].mode == 'text' then + table.insert(result, Editor_state.lines[i].data) end end - table.insert(result, Lines[maxl].data:sub(1, max_offset-1)) + table.insert(result, Editor_state.lines[maxl].data:sub(1, max_offset-1)) return table.concat(result, '\n') end diff --git a/text.lua b/text.lua index c61a488..0f3cd42 100644 --- a/text.lua +++ b/text.lua @@ -28,13 +28,13 @@ function Text.draw(line, line_index, top, left, right) local frag_width = App.width(frag_text) local frag_len = utf8.len(frag) --? local s=tostring ---? print('('..s(x)..','..s(y)..') '..frag..'('..s(frag_width)..' vs '..s(right)..') '..s(line_index)..' vs '..s(Screen_top1.line)..'; '..s(pos)..' vs '..s(Screen_top1.pos)..'; bottom: '..s(Screen_bottom1.line)..'/'..s(Screen_bottom1.pos)) +--? print('('..s(x)..','..s(y)..') '..frag..'('..s(frag_width)..' vs '..s(right)..') '..s(line_index)..' vs '..s(Editor_state.screen_top1.line)..'; '..s(pos)..' vs '..s(Editor_state.screen_top1.pos)..'; bottom: '..s(Editor_state.screen_bottom1.line)..'/'..s(Editor_state.screen_bottom1.pos)) if x + frag_width > right then assert(x > left) -- no overfull lines -- update y only after drawing the first screen line of screen top - if Text.lt1(Screen_top1, {line=line_index, pos=pos}) then - y = y + Line_height - if y + Line_height > App.screen.height then + if Text.lt1(Editor_state.screen_top1, {line=line_index, pos=pos}) then + y = y + Editor_state.line_height + if y + Editor_state.line_height > App.screen.height then --? print('b', y, App.screen.height, '=>', screen_line_starting_pos) return y, screen_line_starting_pos end @@ -43,10 +43,10 @@ function Text.draw(line, line_index, top, left, right) end x = left end ---? print('checking to draw', pos, Screen_top1.pos) +--? print('checking to draw', pos, Editor_state.screen_top1.pos) -- don't draw text above screen top - if Text.le1(Screen_top1, {line=line_index, pos=pos}) then - if Selection1.line then + if Text.le1(Editor_state.screen_top1, {line=line_index, pos=pos}) then + if Editor_state.selection1.line then local lo, hi = Text.clip_selection(line_index, pos, pos+frag_len, left, right) Text.draw_highlight(line, x,y, pos, lo,hi) end @@ -54,24 +54,24 @@ function Text.draw(line, line_index, top, left, right) App.screen.draw(frag_text, x,y) end -- render cursor if necessary - if line_index == Cursor1.line then - if pos <= Cursor1.pos and pos + frag_len > Cursor1.pos then - if Search_term then - if Lines[Cursor1.line].data:sub(Cursor1.pos, Cursor1.pos+utf8.len(Search_term)-1) == Search_term then - local lo_px = Text.draw_highlight(line, x,y, pos, Cursor1.pos, Cursor1.pos+utf8.len(Search_term)) + if line_index == Editor_state.cursor1.line then + if pos <= Editor_state.cursor1.pos and pos + frag_len > Editor_state.cursor1.pos then + if Editor_state.search_term then + if Editor_state.lines[Editor_state.cursor1.line].data:sub(Editor_state.cursor1.pos, Editor_state.cursor1.pos+utf8.len(Editor_state.search_term)-1) == Editor_state.search_term then + local lo_px = Text.draw_highlight(line, x,y, pos, Editor_state.cursor1.pos, Editor_state.cursor1.pos+utf8.len(Editor_state.search_term)) App.color(Text_color) - love.graphics.print(Search_term, x+lo_px,y) + love.graphics.print(Editor_state.search_term, x+lo_px,y) end else - Text.draw_cursor(x+Text.x(frag, Cursor1.pos-pos+1), y) + Text.draw_cursor(x+Text.x(frag, Editor_state.cursor1.pos-pos+1), y) end end end x = x + frag_width pos = pos + frag_len end - if Search_term == nil then - if line_index == Cursor1.line and Cursor1.pos == pos then + if Editor_state.search_term == nil then + if line_index == Editor_state.cursor1.line and Editor_state.cursor1.pos == pos then Text.draw_cursor(x, y) end end @@ -84,11 +84,11 @@ function Text.draw_cursor(x, y) -- blink every 0.5s if math.floor(Cursor_time*2)%2 == 0 then App.color(Cursor_color) - love.graphics.rectangle('fill', x,y, 3,Line_height) + love.graphics.rectangle('fill', x,y, 3,Editor_state.line_height) App.color(Text_color) end - Cursor_x = x - Cursor_y = y+Line_height + Editor_state.cursor_x = x + Editor_state.cursor_y = y+Editor_state.line_height end function Text.compute_fragments(line, left, right) @@ -137,241 +137,241 @@ end function Text.textinput(t) if App.mouse_down(1) then return end if App.ctrl_down() or App.alt_down() or App.cmd_down() then return end - local before = snapshot(Cursor1.line) ---? print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos) + local before = snapshot(Editor_state.cursor1.line) +--? print(Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos) Text.insert_at_cursor(t) - if Cursor_y >= App.screen.height - Line_height then - Text.populate_screen_line_starting_pos(Lines[Cursor1.line], Margin_left, App.screen.width-Margin_right) - Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.width-Margin_right) ---? print('=>', Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos) + if Editor_state.cursor_y >= App.screen.height - Editor_state.line_height then + Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) +--? print('=>', Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos) end - record_undo_event({before=before, after=snapshot(Cursor1.line)}) + record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)}) end function Text.insert_at_cursor(t) - local byte_offset = Text.offset(Lines[Cursor1.line].data, Cursor1.pos) - Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_offset-1)..t..string.sub(Lines[Cursor1.line].data, byte_offset) - Text.clear_cache(Lines[Cursor1.line]) - Cursor1.pos = Cursor1.pos+1 + local byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos) + Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_offset-1)..t..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_offset) + Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line]) + Editor_state.cursor1.pos = Editor_state.cursor1.pos+1 end -- Don't handle any keys here that would trigger love.textinput above. function Text.keychord_pressed(chord) ---? print('chord', chord, Selection1.line, Selection1.pos) +--? print('chord', chord, Editor_state.selection1.line, Editor_state.selection1.pos) --== shortcuts that mutate text if chord == 'return' then - local before_line = Cursor1.line + local before_line = Editor_state.cursor1.line local before = snapshot(before_line) Text.insert_return() - Selection1 = {} - if (Cursor_y + Line_height) > App.screen.height then - Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.width-Margin_right) + Editor_state.selection1 = {} + if (Editor_state.cursor_y + Editor_state.line_height) > App.screen.height then + Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) end schedule_save() - record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)}) + record_undo_event({before=before, after=snapshot(before_line, Editor_state.cursor1.line)}) elseif chord == 'tab' then - local before = snapshot(Cursor1.line) ---? print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos) + local before = snapshot(Editor_state.cursor1.line) +--? print(Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos) Text.insert_at_cursor('\t') - if Cursor_y >= App.screen.height - Line_height then - Text.populate_screen_line_starting_pos(Lines[Cursor1.line], Margin_left, App.screen.width-Margin_right) - Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.width-Margin_right) ---? print('=>', Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos) + if Editor_state.cursor_y >= App.screen.height - Editor_state.line_height then + Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) +--? print('=>', Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos) end schedule_save() - record_undo_event({before=before, after=snapshot(Cursor1.line)}) + record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)}) elseif chord == 'backspace' then - if Selection1.line then - Text.delete_selection(Margin_left, App.screen.width-Margin_right) + if Editor_state.selection1.line then + Text.delete_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) schedule_save() return end local before - if Cursor1.pos > 1 then - before = snapshot(Cursor1.line) - local byte_start = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos-1) - local byte_end = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos) + if Editor_state.cursor1.pos > 1 then + before = snapshot(Editor_state.cursor1.line) + local byte_start = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1) + local byte_end = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos) if byte_start then if byte_end then - Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1)..string.sub(Lines[Cursor1.line].data, byte_end) + Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1)..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_end) else - Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1) + Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1) end - Cursor1.pos = Cursor1.pos-1 + Editor_state.cursor1.pos = Editor_state.cursor1.pos-1 end - elseif Cursor1.line > 1 then - before = snapshot(Cursor1.line-1, Cursor1.line) - if Lines[Cursor1.line-1].mode == 'drawing' then - table.remove(Lines, Cursor1.line-1) + elseif Editor_state.cursor1.line > 1 then + before = snapshot(Editor_state.cursor1.line-1, Editor_state.cursor1.line) + if Editor_state.lines[Editor_state.cursor1.line-1].mode == 'drawing' then + table.remove(Editor_state.lines, Editor_state.cursor1.line-1) else -- join lines - Cursor1.pos = utf8.len(Lines[Cursor1.line-1].data)+1 - Lines[Cursor1.line-1].data = Lines[Cursor1.line-1].data..Lines[Cursor1.line].data - table.remove(Lines, Cursor1.line) + Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line-1].data)+1 + Editor_state.lines[Editor_state.cursor1.line-1].data = Editor_state.lines[Editor_state.cursor1.line-1].data..Editor_state.lines[Editor_state.cursor1.line].data + table.remove(Editor_state.lines, Editor_state.cursor1.line) end - Cursor1.line = Cursor1.line-1 + Editor_state.cursor1.line = Editor_state.cursor1.line-1 end - if Text.lt1(Cursor1, Screen_top1) then - local top2 = Text.to2(Screen_top1, Margin_left, App.screen.width-Margin_right) - top2 = Text.previous_screen_line(top2, Margin_left, App.screen.width-Margin_right) - Screen_top1 = Text.to1(top2) + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then + local top2 = Text.to2(Editor_state.screen_top1, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + top2 = Text.previous_screen_line(top2, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.screen_top1 = Text.to1(top2) Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks end - Text.clear_cache(Lines[Cursor1.line]) - assert(Text.le1(Screen_top1, Cursor1)) + Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line]) + assert(Text.le1(Editor_state.screen_top1, Editor_state.cursor1)) schedule_save() - record_undo_event({before=before, after=snapshot(Cursor1.line)}) + record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)}) elseif chord == 'delete' then - if Selection1.line then - Text.delete_selection(Margin_left, App.screen.width-Margin_right) + if Editor_state.selection1.line then + Text.delete_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) schedule_save() return end local before - if Cursor1.pos <= utf8.len(Lines[Cursor1.line].data) then - before = snapshot(Cursor1.line) + if Editor_state.cursor1.pos <= utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then + before = snapshot(Editor_state.cursor1.line) else - before = snapshot(Cursor1.line, Cursor1.line+1) + before = snapshot(Editor_state.cursor1.line, Editor_state.cursor1.line+1) end - if Cursor1.pos <= utf8.len(Lines[Cursor1.line].data) then - local byte_start = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos) - local byte_end = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos+1) + if Editor_state.cursor1.pos <= utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then + local byte_start = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos) + local byte_end = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos+1) if byte_start then if byte_end then - Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1)..string.sub(Lines[Cursor1.line].data, byte_end) + Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1)..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_end) else - Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1) + Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1) end - -- no change to Cursor1.pos + -- no change to Editor_state.cursor1.pos end - elseif Cursor1.line < #Lines then - if Lines[Cursor1.line+1].mode == 'drawing' then - table.remove(Lines, Cursor1.line+1) + elseif Editor_state.cursor1.line < #Editor_state.lines then + if Editor_state.lines[Editor_state.cursor1.line+1].mode == 'drawing' then + table.remove(Editor_state.lines, Editor_state.cursor1.line+1) else -- join lines - Lines[Cursor1.line].data = Lines[Cursor1.line].data..Lines[Cursor1.line+1].data - table.remove(Lines, Cursor1.line+1) + Editor_state.lines[Editor_state.cursor1.line].data = Editor_state.lines[Editor_state.cursor1.line].data..Editor_state.lines[Editor_state.cursor1.line+1].data + table.remove(Editor_state.lines, Editor_state.cursor1.line+1) end end - Text.clear_cache(Lines[Cursor1.line]) + Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line]) schedule_save() - record_undo_event({before=before, after=snapshot(Cursor1.line)}) + record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)}) --== shortcuts that move the cursor elseif chord == 'left' then - Text.left(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'right' then - Text.right(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'S-left' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.left(Margin_left, App.screen.width-Margin_right) + Text.left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'S-right' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.right(Margin_left, App.screen.width-Margin_right) + Text.right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) -- C- hotkeys reserved for drawings, so we'll use M- elseif chord == 'M-left' then - Text.word_left(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.word_left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'M-right' then - Text.word_right(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.word_right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'M-S-left' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.word_left(Margin_left, App.screen.width-Margin_right) + Text.word_left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'M-S-right' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.word_right(Margin_left, App.screen.width-Margin_right) + Text.word_right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'home' then Text.start_of_line() - Selection1 = {} + Editor_state.selection1 = {} elseif chord == 'end' then - Text.end_of_line(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.end_of_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'S-home' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end Text.start_of_line() elseif chord == 'S-end' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.end_of_line(Margin_left, App.screen.width-Margin_right) + Text.end_of_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'up' then - Text.up(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.up(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'down' then - Text.down(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.down(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'S-up' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.up(Margin_left, App.screen.width-Margin_right) + Text.up(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'S-down' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.down(Margin_left, App.screen.width-Margin_right) + Text.down(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'pageup' then - Text.pageup(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.pageup(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'pagedown' then - Text.pagedown(Margin_left, App.screen.width-Margin_right) - Selection1 = {} + Text.pagedown(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) + Editor_state.selection1 = {} elseif chord == 'S-pageup' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.pageup(Margin_left, App.screen.width-Margin_right) + Text.pageup(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) elseif chord == 'S-pagedown' then - if Selection1.line == nil then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} + if Editor_state.selection1.line == nil then + Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} end - Text.pagedown(Margin_left, App.screen.width-Margin_right) + Text.pagedown(Editor_state.margin_left, App.screen.width-Editor_state.margin_right) end end function Text.insert_return() - local byte_offset = Text.offset(Lines[Cursor1.line].data, Cursor1.pos) - table.insert(Lines, Cursor1.line+1, {mode='text', data=string.sub(Lines[Cursor1.line].data, byte_offset)}) - Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_offset-1) - Text.clear_cache(Lines[Cursor1.line]) - Text.clear_cache(Lines[Cursor1.line+1]) - Cursor1.line = Cursor1.line+1 - Cursor1.pos = 1 + local byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos) + table.insert(Editor_state.lines, Editor_state.cursor1.line+1, {mode='text', data=string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_offset)}) + Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_offset-1) + Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line]) + Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line+1]) + Editor_state.cursor1.line = Editor_state.cursor1.line+1 + Editor_state.cursor1.pos = 1 end function Text.pageup(left, right) --? print('pageup') -- duplicate some logic from love.draw - local top2 = Text.to2(Screen_top1, left, right) + local top2 = Text.to2(Editor_state.screen_top1, left, right) --? print(App.screen.height) - local y = App.screen.height - Line_height - while y >= Margin_top do + local y = App.screen.height - Editor_state.line_height + while y >= Editor_state.margin_top do --? print(y, top2.line, top2.screen_line, top2.screen_pos) - if Screen_top1.line == 1 and Screen_top1.pos == 1 then break end - if Lines[Screen_top1.line].mode == 'text' then - y = y - Line_height - elseif Lines[Screen_top1.line].mode == 'drawing' then - y = y - Drawing_padding_height - Drawing.pixels(Lines[Screen_top1.line].h) + if Editor_state.screen_top1.line == 1 and Editor_state.screen_top1.pos == 1 then break end + if Editor_state.lines[Editor_state.screen_top1.line].mode == 'text' then + y = y - Editor_state.line_height + elseif Editor_state.lines[Editor_state.screen_top1.line].mode == 'drawing' then + y = y - Editor_state.drawing_padding_height - Drawing.pixels(Editor_state.lines[Editor_state.screen_top1.line].h) end top2 = Text.previous_screen_line(top2, left, right) end - Screen_top1 = Text.to1(top2) - Cursor1.line = Screen_top1.line - Cursor1.pos = Screen_top1.pos + Editor_state.screen_top1 = Text.to1(top2) + Editor_state.cursor1.line = Editor_state.screen_top1.line + Editor_state.cursor1.pos = Editor_state.screen_top1.pos Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right) ---? print(Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos) +--? print(Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos) --? print('pageup end') end @@ -380,133 +380,133 @@ function Text.pagedown(left, right) -- If a line/paragraph gets to a page boundary, I often want to scroll -- before I get to the bottom. -- However, only do this if it makes forward progress. - local top2 = Text.to2(Screen_bottom1, left, right) + local top2 = Text.to2(Editor_state.screen_bottom1, left, right) if top2.screen_line > 1 then top2.screen_line = math.max(top2.screen_line-10, 1) end local new_top1 = Text.to1(top2) - if Text.lt1(Screen_top1, new_top1) then - Screen_top1 = new_top1 + if Text.lt1(Editor_state.screen_top1, new_top1) then + Editor_state.screen_top1 = new_top1 else - Screen_top1.line = Screen_bottom1.line - Screen_top1.pos = Screen_bottom1.pos + Editor_state.screen_top1.line = Editor_state.screen_bottom1.line + Editor_state.screen_top1.pos = Editor_state.screen_bottom1.pos end ---? print('setting top to', Screen_top1.line, Screen_top1.pos) - Cursor1.line = Screen_top1.line - Cursor1.pos = Screen_top1.pos +--? print('setting top to', Editor_state.screen_top1.line, Editor_state.screen_top1.pos) + Editor_state.cursor1.line = Editor_state.screen_top1.line + Editor_state.cursor1.pos = Editor_state.screen_top1.pos Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right) ---? print('top now', Screen_top1.line) +--? print('top now', Editor_state.screen_top1.line) Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks --? print('pagedown end') end function Text.up(left, right) - assert(Lines[Cursor1.line].mode == 'text') ---? print('up', Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos) + assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text') +--? print('up', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos) local screen_line_index,screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line(left, right) if screen_line_starting_pos == 1 then --? print('cursor is at first screen line of its line') -- line is done; skip to previous text line - local new_cursor_line = Cursor1.line + local new_cursor_line = Editor_state.cursor1.line while new_cursor_line > 1 do new_cursor_line = new_cursor_line-1 - if Lines[new_cursor_line].mode == 'text' then + if Editor_state.lines[new_cursor_line].mode == 'text' then --? print('found previous text line') - Cursor1.line = new_cursor_line - Text.populate_screen_line_starting_pos(Lines[Cursor1.line], left, right) + Editor_state.cursor1.line = new_cursor_line + Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right) -- previous text line found, pick its final screen line --? print('has multiple screen lines') - local screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos + local screen_line_starting_pos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos --? print(#screen_line_starting_pos) screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos] --? print('previous screen line starts at pos '..tostring(screen_line_starting_pos)..' of its line') - if Screen_top1.line > Cursor1.line then - Screen_top1.line = Cursor1.line - Screen_top1.pos = screen_line_starting_pos ---? print('pos of top of screen is also '..tostring(Screen_top1.pos)..' of the same line') + if Editor_state.screen_top1.line > Editor_state.cursor1.line then + Editor_state.screen_top1.line = Editor_state.cursor1.line + Editor_state.screen_top1.pos = screen_line_starting_pos +--? print('pos of top of screen is also '..tostring(Editor_state.screen_top1.pos)..' of the same line') end - local screen_line_starting_byte_offset = Text.offset(Lines[Cursor1.line].data, screen_line_starting_pos) - local s = string.sub(Lines[Cursor1.line].data, screen_line_starting_byte_offset) - Cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, Cursor_x, left) - 1 + local screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, screen_line_starting_pos) + local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, screen_line_starting_byte_offset) + Editor_state.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1 break end end - if Cursor1.line < Screen_top1.line then - Screen_top1.line = Cursor1.line + if Editor_state.cursor1.line < Editor_state.screen_top1.line then + Editor_state.screen_top1.line = Editor_state.cursor1.line end else -- move up one screen line in current line --? print('cursor is NOT at first screen line of its line') assert(screen_line_index > 1) - new_screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos[screen_line_index-1] + new_screen_line_starting_pos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos[screen_line_index-1] --? print('switching pos of screen line at cursor from '..tostring(screen_line_starting_pos)..' to '..tostring(new_screen_line_starting_pos)) - if Screen_top1.line == Cursor1.line and Screen_top1.pos == screen_line_starting_pos then - Screen_top1.pos = new_screen_line_starting_pos ---? print('also setting pos of top of screen to '..tostring(Screen_top1.pos)) + if Editor_state.screen_top1.line == Editor_state.cursor1.line and Editor_state.screen_top1.pos == screen_line_starting_pos then + Editor_state.screen_top1.pos = new_screen_line_starting_pos +--? print('also setting pos of top of screen to '..tostring(Editor_state.screen_top1.pos)) end - local new_screen_line_starting_byte_offset = Text.offset(Lines[Cursor1.line].data, new_screen_line_starting_pos) - local s = string.sub(Lines[Cursor1.line].data, new_screen_line_starting_byte_offset) - Cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Cursor_x, left) - 1 ---? print('cursor pos is now '..tostring(Cursor1.pos)) + local new_screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_pos) + local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_byte_offset) + Editor_state.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1 +--? print('cursor pos is now '..tostring(Editor_state.cursor1.pos)) end end function Text.down(left, right) - assert(Lines[Cursor1.line].mode == 'text') ---? print('down', Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos, Screen_bottom1.line, Screen_bottom1.pos) + assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text') +--? print('down', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos) if Text.cursor_at_final_screen_line(left, right) then -- line is done, skip to next text line --? print('cursor at final screen line of its line') - local new_cursor_line = Cursor1.line - while new_cursor_line < #Lines do + local new_cursor_line = Editor_state.cursor1.line + while new_cursor_line < #Editor_state.lines do new_cursor_line = new_cursor_line+1 - if Lines[new_cursor_line].mode == 'text' then - Cursor1.line = new_cursor_line - Cursor1.pos = Text.nearest_cursor_pos(Lines[Cursor1.line].data, Cursor_x, left) ---? print(Cursor1.pos) + if Editor_state.lines[new_cursor_line].mode == 'text' then + Editor_state.cursor1.line = new_cursor_line + Editor_state.cursor1.pos = Text.nearest_cursor_pos(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor_x, left) +--? print(Editor_state.cursor1.pos) break end end - if Cursor1.line > Screen_bottom1.line then ---? print('screen top before:', Screen_top1.line, Screen_top1.pos) + if Editor_state.cursor1.line > Editor_state.screen_bottom1.line then +--? print('screen top before:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos) --? print('scroll up preserving cursor') Text.snap_cursor_to_bottom_of_screen(left, right) ---? print('screen top after:', Screen_top1.line, Screen_top1.pos) +--? print('screen top after:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos) end else -- move down one screen line in current line local scroll_down = false - if Text.le1(Screen_bottom1, Cursor1) then + if Text.le1(Editor_state.screen_bottom1, Editor_state.cursor1) then scroll_down = true end --? print('cursor is NOT at final screen line of its line') local screen_line_index, screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line(left, right) - new_screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos[screen_line_index+1] + new_screen_line_starting_pos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos[screen_line_index+1] --? print('switching pos of screen line at cursor from '..tostring(screen_line_starting_pos)..' to '..tostring(new_screen_line_starting_pos)) - local new_screen_line_starting_byte_offset = Text.offset(Lines[Cursor1.line].data, new_screen_line_starting_pos) - local s = string.sub(Lines[Cursor1.line].data, new_screen_line_starting_byte_offset) - Cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Cursor_x, left) - 1 ---? print('cursor pos is now', Cursor1.line, Cursor1.pos) + local new_screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_pos) + local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_byte_offset) + Editor_state.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1 +--? print('cursor pos is now', Editor_state.cursor1.line, Editor_state.cursor1.pos) if scroll_down then --? print('scroll up preserving cursor') Text.snap_cursor_to_bottom_of_screen(left, right) ---? print('screen top after:', Screen_top1.line, Screen_top1.pos) +--? print('screen top after:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos) end end ---? print('=>', Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos, Screen_bottom1.line, Screen_bottom1.pos) +--? print('=>', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos) end function Text.start_of_line() - Cursor1.pos = 1 - if Text.lt1(Cursor1, Screen_top1) then - Screen_top1 = {line=Cursor1.line, pos=Cursor1.pos} -- copy + Editor_state.cursor1.pos = 1 + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then + Editor_state.screen_top1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} -- copy end end function Text.end_of_line(left, right) - Cursor1.pos = utf8.len(Lines[Cursor1.line].data) + 1 + Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) + 1 local _,botpos = Text.pos_at_start_of_cursor_screen_line(left, right) - local botline1 = {line=Cursor1.line, pos=botpos} + local botline1 = {line=Editor_state.cursor1.line, pos=botpos} if Text.cursor_past_screen_bottom() then Text.snap_cursor_to_bottom_of_screen(left, right) end @@ -515,10 +515,10 @@ end function Text.word_left(left, right) -- skip some whitespace while true do - if Cursor1.pos == 1 then + if Editor_state.cursor1.pos == 1 then break end - if Text.match(Lines[Cursor1.line].data, Cursor1.pos-1, '%S') then + if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1, '%S') then break end Text.left(left, right) @@ -526,11 +526,11 @@ function Text.word_left(left, right) -- skip some non-whitespace while true do Text.left(left, right) - if Cursor1.pos == 1 then + if Editor_state.cursor1.pos == 1 then break end - assert(Cursor1.pos > 1) - if Text.match(Lines[Cursor1.line].data, Cursor1.pos-1, '%s') then + assert(Editor_state.cursor1.pos > 1) + if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1, '%s') then break end end @@ -539,20 +539,20 @@ end function Text.word_right(left, right) -- skip some whitespace while true do - if Cursor1.pos > utf8.len(Lines[Cursor1.line].data) then + if Editor_state.cursor1.pos > utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then break end - if Text.match(Lines[Cursor1.line].data, Cursor1.pos, '%S') then + if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos, '%S') then break end Text.right_without_scroll() end while true do Text.right_without_scroll() - if Cursor1.pos > utf8.len(Lines[Cursor1.line].data) then + if Editor_state.cursor1.pos > utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then break end - if Text.match(Lines[Cursor1.line].data, Cursor1.pos, '%s') then + if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos, '%s') then break end end @@ -571,24 +571,24 @@ function Text.match(s, pos, pat) end function Text.left(left, right) - assert(Lines[Cursor1.line].mode == 'text') - if Cursor1.pos > 1 then - Cursor1.pos = Cursor1.pos-1 + assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text') + if Editor_state.cursor1.pos > 1 then + Editor_state.cursor1.pos = Editor_state.cursor1.pos-1 else - local new_cursor_line = Cursor1.line + local new_cursor_line = Editor_state.cursor1.line while new_cursor_line > 1 do new_cursor_line = new_cursor_line-1 - if Lines[new_cursor_line].mode == 'text' then - Cursor1.line = new_cursor_line - Cursor1.pos = utf8.len(Lines[Cursor1.line].data) + 1 + if Editor_state.lines[new_cursor_line].mode == 'text' then + Editor_state.cursor1.line = new_cursor_line + Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) + 1 break end end end - if Text.lt1(Cursor1, Screen_top1) then - local top2 = Text.to2(Screen_top1, left, right) + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then + local top2 = Text.to2(Editor_state.screen_top1, left, right) top2 = Text.previous_screen_line(top2, left, right) - Screen_top1 = Text.to1(top2) + Editor_state.screen_top1 = Text.to1(top2) end end @@ -600,16 +600,16 @@ function Text.right(left, right) end function Text.right_without_scroll() - assert(Lines[Cursor1.line].mode == 'text') - if Cursor1.pos <= utf8.len(Lines[Cursor1.line].data) then - Cursor1.pos = Cursor1.pos+1 + assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text') + if Editor_state.cursor1.pos <= utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then + Editor_state.cursor1.pos = Editor_state.cursor1.pos+1 else - local new_cursor_line = Cursor1.line - while new_cursor_line <= #Lines-1 do + local new_cursor_line = Editor_state.cursor1.line + while new_cursor_line <= #Editor_state.lines-1 do new_cursor_line = new_cursor_line+1 - if Lines[new_cursor_line].mode == 'text' then - Cursor1.line = new_cursor_line - Cursor1.pos = 1 + if Editor_state.lines[new_cursor_line].mode == 'text' then + Editor_state.cursor1.line = new_cursor_line + Editor_state.cursor1.pos = 1 break end end @@ -617,10 +617,10 @@ function Text.right_without_scroll() end function Text.pos_at_start_of_cursor_screen_line(left, right) - Text.populate_screen_line_starting_pos(Lines[Cursor1.line], left, right) - for i=#Lines[Cursor1.line].screen_line_starting_pos,1,-1 do - local spos = Lines[Cursor1.line].screen_line_starting_pos[i] - if spos <= Cursor1.pos then + Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right) + for i=#Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos,1,-1 do + local spos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos[i] + if spos <= Editor_state.cursor1.pos then return i,spos end end @@ -628,57 +628,57 @@ function Text.pos_at_start_of_cursor_screen_line(left, right) end function Text.cursor_at_final_screen_line(left, right) - Text.populate_screen_line_starting_pos(Lines[Cursor1.line], left, right) - local screen_lines = Lines[Cursor1.line].screen_line_starting_pos ---? print(screen_lines[#screen_lines], Cursor1.pos) - return screen_lines[#screen_lines] <= Cursor1.pos + Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right) + local screen_lines = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos +--? print(screen_lines[#screen_lines], Editor_state.cursor1.pos) + return screen_lines[#screen_lines] <= Editor_state.cursor1.pos end function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right) - local y = Margin_top - while Cursor1.line <= #Lines do - if Lines[Cursor1.line].mode == 'text' then + local y = Editor_state.margin_top + while Editor_state.cursor1.line <= #Editor_state.lines do + if Editor_state.lines[Editor_state.cursor1.line].mode == 'text' then break end ---? print('cursor skips', Cursor1.line) - y = y + Drawing_padding_height + Drawing.pixels(Lines[Cursor1.line].h) - Cursor1.line = Cursor1.line + 1 +--? print('cursor skips', Editor_state.cursor1.line) + y = y + Editor_state.drawing_padding_height + Drawing.pixels(Editor_state.lines[Editor_state.cursor1.line].h) + Editor_state.cursor1.line = Editor_state.cursor1.line + 1 end -- hack: insert a text line at bottom of file if necessary - if Cursor1.line > #Lines then - assert(Cursor1.line == #Lines+1) - table.insert(Lines, {mode='text', data=''}) + if Editor_state.cursor1.line > #Editor_state.lines then + assert(Editor_state.cursor1.line == #Editor_state.lines+1) + table.insert(Editor_state.lines, {mode='text', data=''}) end ---? print(y, App.screen.height, App.screen.height-Line_height) - if y > App.screen.height - Line_height then +--? print(y, App.screen.height, App.screen.height-Editor_state.line_height) + if y > App.screen.height - Editor_state.line_height then --? print('scroll up') Text.snap_cursor_to_bottom_of_screen(left, right) end end --- should never modify Cursor1 +-- should never modify Editor_state.cursor1 function Text.snap_cursor_to_bottom_of_screen(left, right) - local top2 = Text.to2(Cursor1, left, right) + local top2 = Text.to2(Editor_state.cursor1, left, right) top2.screen_pos = 1 -- start of screen line ---? print('cursor pos '..tostring(Cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down') - local y = App.screen.height - Line_height +--? print('cursor pos '..tostring(Editor_state.cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down') + local y = App.screen.height - Editor_state.line_height -- duplicate some logic from love.draw while true do --? print(y, 'top2:', top2.line, top2.screen_line, top2.screen_pos) if top2.line == 1 and top2.screen_line == 1 then break end - if top2.screen_line > 1 or Lines[top2.line-1].mode == 'text' then - local h = Line_height - if y - h < Margin_top then + if top2.screen_line > 1 or Editor_state.lines[top2.line-1].mode == 'text' then + local h = Editor_state.line_height + if y - h < Editor_state.margin_top then break end y = y - h else assert(top2.line > 1) - assert(Lines[top2.line-1].mode == 'drawing') + assert(Editor_state.lines[top2.line-1].mode == 'drawing') -- We currently can't draw partial drawings, so either skip it entirely -- or not at all. - local h = Drawing_padding_height + Drawing.pixels(Lines[top2.line-1].h) - if y - h < Margin_top then + local h = Editor_state.drawing_padding_height + Drawing.pixels(Editor_state.lines[top2.line-1].h) + if y - h < Editor_state.margin_top then break end --? print('skipping drawing of height', h) @@ -687,8 +687,8 @@ function Text.snap_cursor_to_bottom_of_screen(left, right) top2 = Text.previous_screen_line(top2, left, right) end --? print('top2 finally:', top2.line, top2.screen_line, top2.screen_pos) - Screen_top1 = Text.to1(top2) ---? print('top1 finally:', Screen_top1.line, Screen_top1.pos) + Editor_state.screen_top1 = Text.to1(top2) +--? print('top1 finally:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos) Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks end @@ -697,7 +697,7 @@ function Text.in_line(line, x,y, left,right) if x < left then return false end if y < line.starty then return false end Text.populate_screen_line_starting_pos(line, left, right) - return y < line.starty + Line_height*(#line.screen_line_starting_pos - Text.screen_line_index(line, line.startpos) + 1) + return y < line.starty + Editor_state.line_height*(#line.screen_line_starting_pos - Text.screen_line_index(line, line.startpos) + 1) end -- convert mx,my in pixels to schema-1 coordinates @@ -713,7 +713,7 @@ function Text.to_pos_on_line(line, mx, my, left, right) local screen_line_starting_pos = line.screen_line_starting_pos[screen_line_index] local screen_line_starting_byte_offset = Text.offset(line.data, screen_line_starting_pos) --? print('iter', y, screen_line_index, screen_line_starting_pos, string.sub(line.data, screen_line_starting_byte_offset)) - local nexty = y + Line_height + local nexty = y + Editor_state.line_height if my < nexty then -- On all wrapped screen lines but the final one, clicks past end of -- line position cursor on final character of screen line. @@ -738,12 +738,12 @@ end -- click inside e -- line_starting_pos = 1 + 3 = 4 -- nearest_cursor_pos('defgh', mx) = 2 --- Cursor1.pos = 4 + 2 - 1 = 5 +-- Editor_state.cursor1.pos = 4 + 2 - 1 = 5 -- manual test: -- click inside h -- line_starting_pos = 1 + 3 + 3 = 7 -- nearest_cursor_pos('gh', mx) = 2 --- Cursor1.pos = 7 + 2 - 1 = 8 +-- Editor_state.cursor1.pos = 7 + 2 - 1 = 8 function Text.screen_line_width(line, i) local start_pos = line.screen_line_starting_pos[i] @@ -848,13 +848,13 @@ function Text.x(s, pos) end function Text.to2(pos1, left, right) - if Lines[pos1.line].mode == 'drawing' then + if Editor_state.lines[pos1.line].mode == 'drawing' then return {line=pos1.line, screen_line=1, screen_pos=1} end local result = {line=pos1.line, screen_line=1} - Text.populate_screen_line_starting_pos(Lines[pos1.line], left, right) - for i=#Lines[pos1.line].screen_line_starting_pos,1,-1 do - local spos = Lines[pos1.line].screen_line_starting_pos[i] + Text.populate_screen_line_starting_pos(Editor_state.lines[pos1.line], left, right) + for i=#Editor_state.lines[pos1.line].screen_line_starting_pos,1,-1 do + local spos = Editor_state.lines[pos1.line].screen_line_starting_pos[i] if spos <= pos1.pos then result.screen_line = i result.screen_pos = pos1.pos - spos + 1 @@ -868,7 +868,7 @@ end function Text.to1(pos2) local result = {line=pos2.line, pos=pos2.screen_pos} if pos2.screen_line > 1 then - result.pos = Lines[pos2.line].screen_line_starting_pos[pos2.screen_line] + pos2.screen_pos - 1 + result.pos = Editor_state.lines[pos2.line].screen_line_starting_pos[pos2.screen_line] + pos2.screen_pos - 1 end return result end @@ -901,7 +901,7 @@ function Text.offset(s, pos1) if pos1 == 1 then return 1 end local result = utf8.offset(s, pos1) if result == nil then - print(Cursor1.line, Cursor1.pos, #Lines[Cursor1.line].data, Lines[Cursor1.line].data) + print(Editor_state.cursor1.line, Editor_state.cursor1.pos, #Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.lines[Editor_state.cursor1.line].data) print(pos1, #s, s) end assert(result) @@ -913,12 +913,12 @@ function Text.previous_screen_line(pos2, left, right) return {line=pos2.line, screen_line=pos2.screen_line-1, screen_pos=1} elseif pos2.line == 1 then return pos2 - elseif Lines[pos2.line-1].mode == 'drawing' then + elseif Editor_state.lines[pos2.line-1].mode == 'drawing' then return {line=pos2.line-1, screen_line=1, screen_pos=1} else - local l = Lines[pos2.line-1] - Text.populate_screen_line_starting_pos(Lines[pos2.line-1], left, right) - return {line=pos2.line-1, screen_line=#Lines[pos2.line-1].screen_line_starting_pos, screen_pos=1} + local l = Editor_state.lines[pos2.line-1] + Text.populate_screen_line_starting_pos(Editor_state.lines[pos2.line-1], left, right) + return {line=pos2.line-1, screen_line=#Editor_state.lines[pos2.line-1].screen_line_starting_pos, screen_pos=1} end end @@ -948,36 +948,36 @@ function Text.populate_screen_line_starting_pos(line, left, right) end function Text.tweak_screen_top_and_cursor(left, right) ---? print('a', Selection1.line) - if Screen_top1.pos == 1 then return end - local line = Lines[Screen_top1.line] +--? print('a', Editor_state.selection1.line) + if Editor_state.screen_top1.pos == 1 then return end + local line = Editor_state.lines[Editor_state.screen_top1.line] Text.populate_screen_line_starting_pos(line, left, right) for i=2,#line.screen_line_starting_pos do local pos = line.screen_line_starting_pos[i] - if pos == Screen_top1.pos then + if pos == Editor_state.screen_top1.pos then break end - if pos > Screen_top1.pos then + if pos > Editor_state.screen_top1.pos then -- make sure screen top is at start of a screen line local prev = line.screen_line_starting_pos[i-1] - if Screen_top1.pos - prev < pos - Screen_top1.pos then - Screen_top1.pos = prev + if Editor_state.screen_top1.pos - prev < pos - Editor_state.screen_top1.pos then + Editor_state.screen_top1.pos = prev else - Screen_top1.pos = pos + Editor_state.screen_top1.pos = pos end break end end -- make sure cursor is on screen - if Text.lt1(Cursor1, Screen_top1) then - Cursor1 = {line=Screen_top1.line, pos=Screen_top1.pos} - elseif Cursor1.line >= Screen_bottom1.line then + if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then + Editor_state.cursor1 = {line=Editor_state.screen_top1.line, pos=Editor_state.screen_top1.pos} + elseif Editor_state.cursor1.line >= Editor_state.screen_bottom1.line then --? print('too low') if Text.cursor_past_screen_bottom() then --? print('tweak') - local line = Lines[Screen_bottom1.line] - Cursor1 = { - line=Screen_bottom1.line, + local line = Editor_state.lines[Editor_state.screen_bottom1.line] + Editor_state.cursor1 = { + line=Editor_state.screen_bottom1.line, pos=Text.to_pos_on_line(line, App.screen.width-5, App.screen.height-5, left, right), } end @@ -987,17 +987,17 @@ end -- slightly expensive since it redraws the screen function Text.cursor_past_screen_bottom() App.draw() - return Cursor_y >= App.screen.height - Line_height + return Editor_state.cursor_y >= App.screen.height - Editor_state.line_height -- this approach is cheaper and almost works, except on the final screen -- where file ends above bottom of screen --? local _,botpos = Text.pos_at_start_of_cursor_screen_line(left, right) ---? local botline1 = {line=Cursor1.line, pos=botpos} ---? return Text.lt1(Screen_bottom1, botline1) +--? local botline1 = {line=Editor_state.cursor1.line, pos=botpos} +--? return Text.lt1(Editor_state.screen_bottom1, botline1) end function Text.redraw_all() --? print('clearing fragments') - for _,line in ipairs(Lines) do + for _,line in ipairs(Editor_state.lines) do line.starty = nil line.startpos = nil Text.clear_cache(line) diff --git a/text_tests.lua b/text_tests.lua index be6d0d9..29d59ae 100644 --- a/text_tests.lua +++ b/text_tests.lua @@ -3,50 +3,50 @@ function test_initial_state() io.write('\ntest_initial_state') App.screen.init{width=120, height=60} - Lines = load_array{} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() - check_eq(#Lines, 1, 'F - test_initial_state/#lines') - check_eq(Cursor1.line, 1, 'F - test_initial_state/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_initial_state/cursor:pos') - check_eq(Screen_top1.line, 1, 'F - test_initial_state/screen_top:line') - check_eq(Screen_top1.pos, 1, 'F - test_initial_state/screen_top:pos') + check_eq(#Editor_state.lines, 1, 'F - test_initial_state/#lines') + check_eq(Editor_state.cursor1.line, 1, 'F - test_initial_state/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_initial_state/cursor:pos') + check_eq(Editor_state.screen_top1.line, 1, 'F - test_initial_state/screen_top:line') + check_eq(Editor_state.screen_top1.pos, 1, 'F - test_initial_state/screen_top:pos') end function test_click_to_create_drawing() io.write('\ntest_click_to_create_drawing') App.screen.init{width=120, height=60} - Lines = load_array{} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() - App.run_after_mouse_click(8,Margin_top+8, 1) + App.run_after_mouse_click(8,Editor_state.margin_top+8, 1) -- cursor skips drawing to always remain on text - check_eq(#Lines, 2, 'F - test_click_to_create_drawing/#lines') - check_eq(Cursor1.line, 2, 'F - test_click_to_create_drawing/cursor') + check_eq(#Editor_state.lines, 2, 'F - test_click_to_create_drawing/#lines') + check_eq(Editor_state.cursor1.line, 2, 'F - test_click_to_create_drawing/cursor') end function test_backspace_to_delete_drawing() io.write('\ntest_backspace_to_delete_drawing') -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end) App.screen.init{width=120, height=60} - Lines = load_array{'```lines', '```', ''} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'```lines', '```', ''} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left -- cursor is on text as always (outside tests this will get initialized correctly) - Cursor1.line = 2 + Editor_state.cursor1.line = 2 -- backspacing deletes the drawing App.run_after_keychord('backspace') - check_eq(#Lines, 1, 'F - test_backspace_to_delete_drawing/#lines') - check_eq(Cursor1.line, 1, 'F - test_backspace_to_delete_drawing/cursor') + check_eq(#Editor_state.lines, 1, 'F - test_backspace_to_delete_drawing/#lines') + check_eq(Editor_state.cursor1.line, 1, 'F - test_backspace_to_delete_drawing/cursor') end function test_insert_first_character() io.write('\ntest_insert_first_character') App.screen.init{width=120, height=60} - Lines = load_array{} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_textinput('a') - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'a', 'F - test_insert_first_character/screen:1') end @@ -54,264 +54,264 @@ function test_press_ctrl() io.write('\ntest_press_ctrl') -- press ctrl while the cursor is on text App.screen.init{width=50, height=80} - Lines = load_array{''} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{''} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} App.run_after_keychord('C-m') end function test_move_left() io.write('\ntest_move_left') App.screen.init{width=120, height=60} - Lines = load_array{'a'} - Cursor1 = {line=1, pos=2} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'a'} + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('left') - check_eq(Cursor1.pos, 1, 'F - test_move_left') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_left') end function test_move_right() io.write('\ntest_move_right') App.screen.init{width=120, height=60} - Lines = load_array{'a'} - Cursor1 = {line=1, pos=1} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'a'} + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('right') - check_eq(Cursor1.pos, 2, 'F - test_move_right') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_move_right') end function test_move_left_to_previous_line() io.write('\ntest_move_left_to_previous_line') App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def'} - Cursor1 = {line=2, pos=1} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc', 'def'} + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('left') - check_eq(Cursor1.line, 1, 'F - test_move_left_to_previous_line/line') - check_eq(Cursor1.pos, 4, 'F - test_move_left_to_previous_line/pos') -- past end of line + check_eq(Editor_state.cursor1.line, 1, 'F - test_move_left_to_previous_line/line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_move_left_to_previous_line/pos') -- past end of line end function test_move_right_to_next_line() io.write('\ntest_move_right_to_next_line') App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def'} - Cursor1 = {line=1, pos=4} -- past end of line - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc', 'def'} + Editor_state.cursor1 = {line=1, pos=4} -- past end of line + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('right') - check_eq(Cursor1.line, 2, 'F - test_move_right_to_next_line/line') - check_eq(Cursor1.pos, 1, 'F - test_move_right_to_next_line/pos') + check_eq(Editor_state.cursor1.line, 2, 'F - test_move_right_to_next_line/line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_right_to_next_line/pos') end function test_move_to_start_of_word() io.write('\ntest_move_to_start_of_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc'} - Cursor1 = {line=1, pos=3} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc'} + Editor_state.cursor1 = {line=1, pos=3} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-left') - check_eq(Cursor1.pos, 1, 'F - test_move_to_start_of_word') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_to_start_of_word') end function test_move_to_start_of_previous_word() io.write('\ntest_move_to_start_of_previous_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def'} - Cursor1 = {line=1, pos=4} -- at the space between words - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def'} + Editor_state.cursor1 = {line=1, pos=4} -- at the space between words + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-left') - check_eq(Cursor1.pos, 1, 'F - test_move_to_start_of_previous_word') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_to_start_of_previous_word') end function test_skip_to_previous_word() io.write('\ntest_skip_to_previous_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def'} - Cursor1 = {line=1, pos=5} -- at the start of second word - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def'} + Editor_state.cursor1 = {line=1, pos=5} -- at the start of second word + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-left') - check_eq(Cursor1.pos, 1, 'F - test_skip_to_previous_word') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_skip_to_previous_word') end function test_skip_past_tab_to_previous_word() io.write('\ntest_skip_past_tab_to_previous_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def\tghi'} - Cursor1 = {line=1, pos=10} -- within third word - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def\tghi'} + Editor_state.cursor1 = {line=1, pos=10} -- within third word + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-left') - check_eq(Cursor1.pos, 9, 'F - test_skip_past_tab_to_previous_word') + check_eq(Editor_state.cursor1.pos, 9, 'F - test_skip_past_tab_to_previous_word') end function test_skip_multiple_spaces_to_previous_word() io.write('\ntest_skip_multiple_spaces_to_previous_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def'} - Cursor1 = {line=1, pos=6} -- at the start of second word - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def'} + Editor_state.cursor1 = {line=1, pos=6} -- at the start of second word + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-left') - check_eq(Cursor1.pos, 1, 'F - test_skip_multiple_spaces_to_previous_word') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_skip_multiple_spaces_to_previous_word') end function test_move_to_start_of_word_on_previous_line() io.write('\ntest_move_to_start_of_word_on_previous_line') App.screen.init{width=120, height=60} - Lines = load_array{'abc def', 'ghi'} - Cursor1 = {line=2, pos=1} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def', 'ghi'} + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-left') - check_eq(Cursor1.line, 1, 'F - test_move_to_start_of_word_on_previous_line/line') - check_eq(Cursor1.pos, 5, 'F - test_move_to_start_of_word_on_previous_line/pos') + check_eq(Editor_state.cursor1.line, 1, 'F - test_move_to_start_of_word_on_previous_line/line') + check_eq(Editor_state.cursor1.pos, 5, 'F - test_move_to_start_of_word_on_previous_line/pos') end function test_move_past_end_of_word() io.write('\ntest_move_past_end_of_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def'} - Cursor1 = {line=1, pos=1} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def'} + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-right') - check_eq(Cursor1.pos, 4, 'F - test_move_past_end_of_word') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_move_past_end_of_word') end function test_skip_to_next_word() io.write('\ntest_skip_to_next_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def'} - Cursor1 = {line=1, pos=4} -- at the space between words - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def'} + Editor_state.cursor1 = {line=1, pos=4} -- at the space between words + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-right') - check_eq(Cursor1.pos, 8, 'F - test_skip_to_next_word') + check_eq(Editor_state.cursor1.pos, 8, 'F - test_skip_to_next_word') end function test_skip_past_tab_to_next_word() io.write('\ntest_skip_past_tab_to_next_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc\tdef'} - Cursor1 = {line=1, pos=1} -- at the space between words - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc\tdef'} + Editor_state.cursor1 = {line=1, pos=1} -- at the space between words + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-right') - check_eq(Cursor1.pos, 4, 'F - test_skip_past_tab_to_next_word') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_skip_past_tab_to_next_word') end function test_skip_multiple_spaces_to_next_word() io.write('\ntest_skip_multiple_spaces_to_next_word') App.screen.init{width=120, height=60} - Lines = load_array{'abc def'} - Cursor1 = {line=1, pos=4} -- at the start of second word - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def'} + Editor_state.cursor1 = {line=1, pos=4} -- at the start of second word + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-right') - check_eq(Cursor1.pos, 9, 'F - test_skip_multiple_spaces_to_next_word') + check_eq(Editor_state.cursor1.pos, 9, 'F - test_skip_multiple_spaces_to_next_word') end function test_move_past_end_of_word_on_next_line() io.write('\ntest_move_past_end_of_word_on_next_line') App.screen.init{width=120, height=60} - Lines = load_array{'abc def', 'ghi'} - Cursor1 = {line=1, pos=8} - Margin_right = 0; Margin_width = Margin_left + Editor_state.lines = load_array{'abc def', 'ghi'} + Editor_state.cursor1 = {line=1, pos=8} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left edit.draw() App.run_after_keychord('M-right') - check_eq(Cursor1.line, 2, 'F - test_move_past_end_of_word_on_next_line/line') - check_eq(Cursor1.pos, 4, 'F - test_move_past_end_of_word_on_next_line/pos') + check_eq(Editor_state.cursor1.line, 2, 'F - test_move_past_end_of_word_on_next_line/line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_move_past_end_of_word_on_next_line/pos') end function test_click_with_mouse() io.write('\ntest_click_with_mouse') -- display two lines with cursor on one of them App.screen.init{width=50, height=80} - Lines = load_array{'abc', 'def'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- click on the other line edit.draw() - App.run_after_mouse_click(Margin_left+8,Margin_top+5, 1) + App.run_after_mouse_click(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) -- cursor moves - check_eq(Cursor1.line, 1, 'F - test_click_with_mouse/cursor') - check_nil(Selection1.line, 'F - test_click_with_mouse/selection is empty to avoid perturbing future edits') + check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse/cursor') + check_nil(Editor_state.selection1.line, 'F - test_click_with_mouse/selection is empty to avoid perturbing future edits') end function test_click_with_mouse_on_empty_line() io.write('\ntest_click_with_mouse_on_empty_line') -- display two lines with the first one empty App.screen.init{width=50, height=80} - Lines = load_array{'', 'def'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'', 'def'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- click on the empty line edit.draw() - App.run_after_mouse_click(Margin_left+8,Margin_top+5, 1) + App.run_after_mouse_click(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) -- cursor moves - check_eq(Cursor1.line, 1, 'F - test_click_with_mouse_on_empty_line/cursor') + check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse_on_empty_line/cursor') end function test_draw_text() io.write('\ntest_draw_text') App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_draw_text/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_draw_text/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_draw_text/screen:3') end function test_draw_wrapping_text() io.write('\ntest_draw_wrapping_text') App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'defgh', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'defgh', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_draw_wrapping_text/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_draw_wrapping_text/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'gh', 'F - test_draw_wrapping_text/screen:3') end function test_draw_word_wrapping_text() io.write('\ntest_draw_word_wrapping_text') App.screen.init{width=60, height=60} - Lines = load_array{'abc def ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc def ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc ', 'F - test_draw_word_wrapping_text/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def ', 'F - test_draw_word_wrapping_text/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_draw_word_wrapping_text/screen:3') end @@ -319,17 +319,17 @@ function test_draw_text_wrapping_within_word() -- arrange a screen line that needs to be split within a word io.write('\ntest_draw_text_wrapping_within_word') App.screen.init{width=60, height=60} - Lines = load_array{'abcd e fghijk', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abcd e fghijk', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abcd ', 'F - test_draw_text_wrapping_within_word/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'e fghi', 'F - test_draw_text_wrapping_within_word/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jk', 'F - test_draw_text_wrapping_within_word/screen:3') end @@ -337,17 +337,17 @@ function test_draw_wrapping_text_containing_non_ascii() -- draw a long line containing non-ASCII io.write('\ntest_draw_wrapping_text_containing_non_ascii') App.screen.init{width=60, height=60} - Lines = load_array{'madam I’m adam', 'xyz'} -- notice the non-ASCII apostrophe - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'madam I’m adam', 'xyz'} -- notice the non-ASCII apostrophe + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'mada', 'F - test_draw_wrapping_text_containing_non_ascii/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'm I’', 'F - test_draw_wrapping_text_containing_non_ascii/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'm ad', 'F - test_draw_wrapping_text_containing_non_ascii/screen:3') end @@ -356,22 +356,22 @@ function test_click_on_wrapping_line() -- display a wrapping line App.screen.init{width=75, height=80} -- 12345678901234 - Lines = load_array{"madam I'm adam"} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{"madam I'm adam"} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'madam ', 'F - test_click_on_wrapping_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, "I'm ada", 'F - test_click_on_wrapping_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height -- click past end of second screen line App.run_after_mouse_click(App.screen.width-2,y-2, 1) -- cursor moves to end of screen line - check_eq(Cursor1.line, 1, 'F - test_click_on_wrapping_line/cursor:line') - check_eq(Cursor1.pos, 13, 'F - test_click_on_wrapping_line/cursor:pos') + check_eq(Editor_state.cursor1.line, 1, 'F - test_click_on_wrapping_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 13, 'F - test_click_on_wrapping_line/cursor:pos') end function test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen() @@ -379,20 +379,20 @@ function test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen() -- display a wrapping line from its second screen line App.screen.init{width=75, height=80} -- 12345678901234 - Lines = load_array{"madam I'm adam"} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=8} - Screen_top1 = {line=1, pos=7} - Screen_bottom1 = {} + Editor_state.lines = load_array{"madam I'm adam"} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=8} + Editor_state.screen_top1 = {line=1, pos=7} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, "I'm ada", 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height -- click past end of second screen line App.run_after_mouse_click(App.screen.width-2,y-2, 1) -- cursor moves to end of screen line - check_eq(Cursor1.line, 1, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:line') - check_eq(Cursor1.pos, 13, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:pos') + check_eq(Editor_state.cursor1.line, 1, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:line') + check_eq(Editor_state.cursor1.pos, 13, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:pos') end function test_click_past_end_of_wrapping_line() @@ -400,23 +400,23 @@ function test_click_past_end_of_wrapping_line() -- display a wrapping line App.screen.init{width=75, height=80} -- 12345678901234 - Lines = load_array{"madam I'm adam"} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{"madam I'm adam"} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'madam ', 'F - test_click_past_end_of_wrapping_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, "I'm ada", 'F - test_click_past_end_of_wrapping_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'm', 'F - test_click_past_end_of_wrapping_line/baseline/screen:3') - y = y + Line_height + y = y + Editor_state.line_height -- click past the end of it App.run_after_mouse_click(App.screen.width-2,y-2, 1) -- cursor moves to end of line - check_eq(Cursor1.pos, 15, 'F - test_click_past_end_of_wrapping_line/cursor') -- one more than the number of UTF-8 code-points + check_eq(Editor_state.cursor1.pos, 15, 'F - test_click_past_end_of_wrapping_line/cursor') -- one more than the number of UTF-8 code-points end function test_click_on_wrapping_line_containing_non_ascii() @@ -424,23 +424,23 @@ function test_click_on_wrapping_line_containing_non_ascii() -- display a wrapping line containing non-ASCII App.screen.init{width=75, height=80} -- 12345678901234 - Lines = load_array{'madam I’m adam'} -- notice the non-ASCII apostrophe - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'madam I’m adam'} -- notice the non-ASCII apostrophe + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'madam ', 'F - test_click_on_wrapping_line_containing_non_ascii/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'I’m ada', 'F - test_click_on_wrapping_line_containing_non_ascii/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'm', 'F - test_click_on_wrapping_line_containing_non_ascii/baseline/screen:3') - y = y + Line_height + y = y + Editor_state.line_height -- click past the end of it App.run_after_mouse_click(App.screen.width-2,y-2, 1) -- cursor moves to end of line - check_eq(Cursor1.pos, 15, 'F - test_click_on_wrapping_line_containing_non_ascii/cursor') -- one more than the number of UTF-8 code-points + check_eq(Editor_state.cursor1.pos, 15, 'F - test_click_on_wrapping_line_containing_non_ascii/cursor') -- one more than the number of UTF-8 code-points end function test_click_past_end_of_word_wrapping_line() @@ -449,30 +449,30 @@ function test_click_past_end_of_word_wrapping_line() App.screen.init{width=160, height=80} -- 0 1 2 -- 123456789012345678901 - Lines = load_array{'the quick brown fox jumped over the lazy dog'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'the quick brown fox jumped over the lazy dog'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'the quick brown fox ', 'F - test_click_past_end_of_word_wrapping_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height -- click past the end of the screen line App.run_after_mouse_click(App.screen.width-2,y-2, 1) -- cursor moves to end of screen line - check_eq(Cursor1.pos, 20, 'F - test_click_past_end_of_word_wrapping_line/cursor') + check_eq(Editor_state.cursor1.pos, 20, 'F - test_click_past_end_of_word_wrapping_line/cursor') end function test_select_text() io.write('\ntest_select_text') -- display a line of text App.screen.init{width=75, height=80} - Lines = load_array{'abc def'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc def'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- select a letter App.fake_key_press('lshift') @@ -480,57 +480,57 @@ function test_select_text() App.fake_key_release('lshift') App.keyreleased('lshift') -- selection persists even after shift is released - check_eq(Selection1.line, 1, 'F - test_select_text/selection:line') - check_eq(Selection1.pos, 1, 'F - test_select_text/selection:pos') - check_eq(Cursor1.line, 1, 'F - test_select_text/cursor:line') - check_eq(Cursor1.pos, 2, 'F - test_select_text/cursor:pos') + check_eq(Editor_state.selection1.line, 1, 'F - test_select_text/selection:line') + check_eq(Editor_state.selection1.pos, 1, 'F - test_select_text/selection:pos') + check_eq(Editor_state.cursor1.line, 1, 'F - test_select_text/cursor:line') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_select_text/cursor:pos') end function test_cursor_movement_without_shift_resets_selection() io.write('\ntest_cursor_movement_without_shift_resets_selection') -- display a line of text with some part selected App.screen.init{width=75, height=80} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- press an arrow key without shift App.run_after_keychord('right') -- no change to data, selection is reset - check_nil(Selection1.line, 'F - test_cursor_movement_without_shift_resets_selection') - check_eq(Lines[1].data, 'abc', 'F - test_cursor_movement_without_shift_resets_selection/data') + check_nil(Editor_state.selection1.line, 'F - test_cursor_movement_without_shift_resets_selection') + check_eq(Editor_state.lines[1].data, 'abc', 'F - test_cursor_movement_without_shift_resets_selection/data') end function test_edit_deletes_selection() io.write('\ntest_edit_deletes_selection') -- display a line of text with some part selected App.screen.init{width=75, height=80} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- press a key App.run_after_textinput('x') -- selected text is deleted and replaced with the key - check_eq(Lines[1].data, 'xbc', 'F - test_edit_deletes_selection') + check_eq(Editor_state.lines[1].data, 'xbc', 'F - test_edit_deletes_selection') end function test_edit_with_shift_key_deletes_selection() io.write('\ntest_edit_with_shift_key_deletes_selection') -- display a line of text with some part selected App.screen.init{width=75, height=80} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- mimic precise keypresses for a capital letter App.fake_key_press('lshift') @@ -539,56 +539,56 @@ function test_edit_with_shift_key_deletes_selection() App.keyreleased('d') App.fake_key_release('lshift') -- selected text is deleted and replaced with the key - check_nil(Selection1.line, 'F - test_edit_with_shift_key_deletes_selection') - check_eq(Lines[1].data, 'Dbc', 'F - test_edit_with_shift_key_deletes_selection/data') + check_nil(Editor_state.selection1.line, 'F - test_edit_with_shift_key_deletes_selection') + check_eq(Editor_state.lines[1].data, 'Dbc', 'F - test_edit_with_shift_key_deletes_selection/data') end function test_copy_does_not_reset_selection() io.write('\ntest_copy_does_not_reset_selection') -- display a line of text with a selection App.screen.init{width=75, height=80} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- copy selection App.run_after_keychord('C-c') check_eq(App.clipboard, 'a', 'F - test_copy_does_not_reset_selection/clipboard') -- selection is reset since shift key is not pressed - check(Selection1.line, 'F - test_copy_does_not_reset_selection') + check(Editor_state.selection1.line, 'F - test_copy_does_not_reset_selection') end function test_cut() io.write('\ntest_cut') -- display a line of text with some part selected App.screen.init{width=75, height=80} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- press a key App.run_after_keychord('C-x') check_eq(App.clipboard, 'a', 'F - test_cut/clipboard') -- selected text is deleted - check_eq(Lines[1].data, 'bc', 'F - test_cut/data') + check_eq(Editor_state.lines[1].data, 'bc', 'F - test_cut/data') end function test_paste_replaces_selection() io.write('\ntest_paste_replaces_selection') -- display a line of text with a selection App.screen.init{width=75, height=80} - Lines = load_array{'abc', 'def'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Selection1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.selection1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- set clipboard App.clipboard = 'xyz' @@ -596,259 +596,259 @@ function test_paste_replaces_selection() App.run_after_keychord('C-v') -- selection is reset since shift key is not pressed -- selection includes the newline, so it's also deleted - check_eq(Lines[1].data, 'xyzdef', 'F - test_paste_replaces_selection') + check_eq(Editor_state.lines[1].data, 'xyzdef', 'F - test_paste_replaces_selection') end function test_deleting_selection_may_scroll() io.write('\ntest_deleting_selection_may_scroll') -- display lines 2/3/4 App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=2} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=2} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_deleting_selection_may_scroll/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_deleting_selection_may_scroll/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_deleting_selection_may_scroll/baseline/screen:3') -- set up a selection starting above the currently displayed page - Selection1 = {line=1, pos=2} + Editor_state.selection1 = {line=1, pos=2} -- delete selection App.run_after_keychord('backspace') -- page scrolls up - check_eq(Screen_top1.line, 1, 'F - test_deleting_selection_may_scroll') - check_eq(Lines[1].data, 'ahi', 'F - test_deleting_selection_may_scroll/data') + check_eq(Editor_state.screen_top1.line, 1, 'F - test_deleting_selection_may_scroll') + check_eq(Editor_state.lines[1].data, 'ahi', 'F - test_deleting_selection_may_scroll/data') end function test_edit_wrapping_text() io.write('\ntest_edit_wrapping_text') App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'def', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=4} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=4} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() App.run_after_textinput('g') App.run_after_textinput('h') App.run_after_textinput('i') App.run_after_textinput('j') - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_edit_wrapping_text/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_edit_wrapping_text/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghij', 'F - test_edit_wrapping_text/screen:3') end function test_insert_newline() io.write('\ntest_insert_newline') -- display a few lines - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_insert_newline/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_insert_newline/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_insert_newline/baseline/screen:3') -- hitting the enter key splits the line App.run_after_keychord('return') - check_eq(Screen_top1.line, 1, 'F - test_insert_newline/screen_top') - check_eq(Cursor1.line, 2, 'F - test_insert_newline/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_insert_newline/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_insert_newline/screen_top') + check_eq(Editor_state.cursor1.line, 2, 'F - test_insert_newline/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_insert_newline/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'a', 'F - test_insert_newline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'bc', 'F - test_insert_newline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_insert_newline/screen:3') end function test_insert_newline_at_start_of_line() io.write('\ntest_insert_newline_at_start_of_line') -- display a line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- hitting the enter key splits the line App.run_after_keychord('return') - check_eq(Cursor1.line, 2, 'F - test_insert_newline_at_start_of_line/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_insert_newline_at_start_of_line/cursor:pos') - check_eq(Lines[1].data, '', 'F - test_insert_newline_at_start_of_line/data:1') - check_eq(Lines[2].data, 'abc', 'F - test_insert_newline_at_start_of_line/data:2') + check_eq(Editor_state.cursor1.line, 2, 'F - test_insert_newline_at_start_of_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_insert_newline_at_start_of_line/cursor:pos') + check_eq(Editor_state.lines[1].data, '', 'F - test_insert_newline_at_start_of_line/data:1') + check_eq(Editor_state.lines[2].data, 'abc', 'F - test_insert_newline_at_start_of_line/data:2') end function test_insert_from_clipboard() io.write('\ntest_insert_from_clipboard') -- display a few lines - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_insert_from_clipboard/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_insert_from_clipboard/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_insert_from_clipboard/baseline/screen:3') -- paste some text including a newline, check that new line is created App.clipboard = 'xy\nz' App.run_after_keychord('C-v') - check_eq(Screen_top1.line, 1, 'F - test_insert_from_clipboard/screen_top') - check_eq(Cursor1.line, 2, 'F - test_insert_from_clipboard/cursor:line') - check_eq(Cursor1.pos, 2, 'F - test_insert_from_clipboard/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_insert_from_clipboard/screen_top') + check_eq(Editor_state.cursor1.line, 2, 'F - test_insert_from_clipboard/cursor:line') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_insert_from_clipboard/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'axy', 'F - test_insert_from_clipboard/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'zbc', 'F - test_insert_from_clipboard/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_insert_from_clipboard/screen:3') end function test_move_cursor_using_mouse() io.write('\ntest_move_cursor_using_mouse') App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'def', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - Selection1 = {} - edit.draw() -- populate line.y for each line in Lines - App.run_after_mouse_release(Margin_left+8,Margin_top+5, 1) - check_eq(Cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line') - check_eq(Cursor1.pos, 2, 'F - test_move_cursor_using_mouse/cursor:pos') - check_nil(Selection1.line, 'F - test_move_cursor_using_mouse/selection:line') - check_nil(Selection1.pos, 'F - test_move_cursor_using_mouse/selection:pos') + Editor_state.lines = load_array{'abc', 'def', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + Editor_state.selection1 = {} + edit.draw() -- populate line.y for each line in Editor_state.lines + App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) + check_eq(Editor_state.cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_move_cursor_using_mouse/cursor:pos') + check_nil(Editor_state.selection1.line, 'F - test_move_cursor_using_mouse/selection:line') + check_nil(Editor_state.selection1.pos, 'F - test_move_cursor_using_mouse/selection:pos') end function test_select_text_using_mouse() io.write('\ntest_select_text_using_mouse') App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'def', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - Selection1 = {} - edit.draw() -- populate line.y for each line in Lines + Editor_state.lines = load_array{'abc', 'def', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + Editor_state.selection1 = {} + edit.draw() -- populate line.y for each line in Editor_state.lines -- press and hold on first location - App.run_after_mouse_press(Margin_left+8,Margin_top+5, 1) + App.run_after_mouse_press(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) -- drag and release somewhere else - App.run_after_mouse_release(Margin_left+20,Margin_top+Line_height+5, 1) - check_eq(Selection1.line, 1, 'F - test_select_text_using_mouse/selection:line') - check_eq(Selection1.pos, 2, 'F - test_select_text_using_mouse/selection:pos') - check_eq(Cursor1.line, 2, 'F - test_select_text_using_mouse/cursor:line') - check_eq(Cursor1.pos, 4, 'F - test_select_text_using_mouse/cursor:pos') + App.run_after_mouse_release(Editor_state.margin_left+20,Editor_state.margin_top+Editor_state.line_height+5, 1) + check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_using_mouse/selection:line') + check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_using_mouse/selection:pos') + check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_using_mouse/cursor:line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_select_text_using_mouse/cursor:pos') end function test_select_text_using_mouse_and_shift() io.write('\ntest_select_text_using_mouse_and_shift') App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'def', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - Selection1 = {} - edit.draw() -- populate line.y for each line in Lines + Editor_state.lines = load_array{'abc', 'def', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + Editor_state.selection1 = {} + edit.draw() -- populate line.y for each line in Editor_state.lines -- click on first location - App.run_after_mouse_press(Margin_left+8,Margin_top+5, 1) - App.run_after_mouse_release(Margin_left+8,Margin_top+5, 1) + App.run_after_mouse_press(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) + App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) -- hold down shift and click somewhere else App.fake_key_press('lshift') - App.run_after_mouse_press(Margin_left+20,Margin_top+5, 1) - App.run_after_mouse_release(Margin_left+20,Margin_top+Line_height+5, 1) + App.run_after_mouse_press(Editor_state.margin_left+20,Editor_state.margin_top+5, 1) + App.run_after_mouse_release(Editor_state.margin_left+20,Editor_state.margin_top+Editor_state.line_height+5, 1) App.fake_key_release('lshift') - check_eq(Selection1.line, 1, 'F - test_select_text_using_mouse_and_shift/selection:line') - check_eq(Selection1.pos, 2, 'F - test_select_text_using_mouse_and_shift/selection:pos') - check_eq(Cursor1.line, 2, 'F - test_select_text_using_mouse_and_shift/cursor:line') - check_eq(Cursor1.pos, 4, 'F - test_select_text_using_mouse_and_shift/cursor:pos') + check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_using_mouse_and_shift/selection:line') + check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_using_mouse_and_shift/selection:pos') + check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_using_mouse_and_shift/cursor:line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_select_text_using_mouse_and_shift/cursor:pos') end function test_select_text_repeatedly_using_mouse_and_shift() io.write('\ntest_select_text_repeatedly_using_mouse_and_shift') App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'def', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - Selection1 = {} - edit.draw() -- populate line.y for each line in Lines + Editor_state.lines = load_array{'abc', 'def', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + Editor_state.selection1 = {} + edit.draw() -- populate line.y for each line in Editor_state.lines -- click on first location - App.run_after_mouse_press(Margin_left+8,Margin_top+5, 1) - App.run_after_mouse_release(Margin_left+8,Margin_top+5, 1) + App.run_after_mouse_press(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) + App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+5, 1) -- hold down shift and click on a second location App.fake_key_press('lshift') - App.run_after_mouse_press(Margin_left+20,Margin_top+5, 1) - App.run_after_mouse_release(Margin_left+20,Margin_top+Line_height+5, 1) + App.run_after_mouse_press(Editor_state.margin_left+20,Editor_state.margin_top+5, 1) + App.run_after_mouse_release(Editor_state.margin_left+20,Editor_state.margin_top+Editor_state.line_height+5, 1) -- hold down shift and click at a third location App.fake_key_press('lshift') - App.run_after_mouse_press(Margin_left+20,Margin_top+5, 1) - App.run_after_mouse_release(Margin_left+8,Margin_top+Line_height+5, 1) + App.run_after_mouse_press(Editor_state.margin_left+20,Editor_state.margin_top+5, 1) + App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+Editor_state.line_height+5, 1) App.fake_key_release('lshift') -- selection is between first and third location. forget the second location, not the first. - check_eq(Selection1.line, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:line') - check_eq(Selection1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos') - check_eq(Cursor1.line, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:line') - check_eq(Cursor1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos') + check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:line') + check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos') + check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:line') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos') end function test_cut_without_selection() io.write('\ntest_cut_without_selection') -- display a few lines - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - Selection1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + Editor_state.selection1 = {} edit.draw() -- try to cut without selecting text App.run_after_keychord('C-x') -- no crash - check_nil(Selection1.line, 'F - test_cut_without_selection') + check_nil(Editor_state.selection1.line, 'F - test_cut_without_selection') end function test_pagedown() io.write('\ntest_pagedown') App.screen.init{width=120, height=45} - Lines = load_array{'abc', 'def', 'ghi'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- initially the first two lines are displayed edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_pagedown/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_pagedown/baseline/screen:2') -- after pagedown the bottom line becomes the top App.run_after_keychord('pagedown') - check_eq(Screen_top1.line, 2, 'F - test_pagedown/screen_top') - check_eq(Cursor1.line, 2, 'F - test_pagedown/cursor') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown/screen_top') + check_eq(Editor_state.cursor1.line, 2, 'F - test_pagedown/cursor') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_pagedown/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_pagedown/screen:2') end @@ -856,28 +856,28 @@ function test_pagedown_skips_drawings() io.write('\ntest_pagedown_skips_drawings') -- some lines of text with a drawing intermixed local drawing_width = 50 - App.screen.init{width=Margin_left+drawing_width, height=80} - Lines = load_array{'abc', -- height 15 + App.screen.init{width=Editor_state.margin_left+drawing_width, height=80} + Editor_state.lines = load_array{'abc', -- height 15 '```lines', '```', -- height 25 'def', -- height 15 'ghi'} -- height 15 - Margin_right = 0; Margin_width = Margin_left - check_eq(Lines[2].mode, 'drawing', 'F - test_pagedown_skips_drawings/baseline/lines') - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - local drawing_height = Drawing_padding_height + drawing_width/2 -- default + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + check_eq(Editor_state.lines[2].mode, 'drawing', 'F - test_pagedown_skips_drawings/baseline/lines') + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + local drawing_height = Editor_state.drawing_padding_height + drawing_width/2 -- default -- initially the screen displays the first line and the drawing -- 15px margin + 15px line1 + 10px margin + 25px drawing + 10px margin = 75px < screen height 80px edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_pagedown_skips_drawings/baseline/screen:1') -- after pagedown the screen draws the drawing up top -- 15px margin + 10px margin + 25px drawing + 10px margin + 15px line3 = 75px < screen height 80px App.run_after_keychord('pagedown') - check_eq(Screen_top1.line, 2, 'F - test_pagedown_skips_drawings/screen_top') - check_eq(Cursor1.line, 3, 'F - test_pagedown_skips_drawings/cursor') - y = Margin_top + drawing_height + check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown_skips_drawings/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_pagedown_skips_drawings/cursor') + y = Editor_state.margin_top + drawing_height App.screen.check(y, 'def', 'F - test_pagedown_skips_drawings/screen:1') end @@ -885,86 +885,86 @@ function test_pagedown_often_shows_start_of_wrapping_line() io.write('\ntest_pagedown_often_shows_start_of_wrapping_line') -- draw a few lines ending in part of a wrapping line App.screen.init{width=50, height=60} - Lines = load_array{'abc', 'def ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def ', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:3') -- after pagedown we start drawing from the bottom _line_ (multiple screen lines) App.run_after_keychord('pagedown') - check_eq(Screen_top1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:line') - check_eq(Screen_top1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:pos') - check_eq(Cursor1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:line') + check_eq(Editor_state.screen_top1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:pos') + check_eq(Editor_state.cursor1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def ', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:3') end function test_pagedown_can_start_from_middle_of_long_wrapping_line() io.write('\ntest_pagedown_can_start_from_middle_of_long_wrapping_line') -- draw a few lines starting from a very long wrapping line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc def ghi jkl mno pqr stu vwx yza bcd efg hij', 'XYZ'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc def ghi jkl mno pqr stu vwx yza bcd efg hij', 'XYZ'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:3') -- after pagedown we scroll down the very long wrapping line App.run_after_keychord('pagedown') - check_eq(Screen_top1.line, 1, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:line') - check_eq(Screen_top1.pos, 9, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:line') + check_eq(Editor_state.screen_top1.pos, 9, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:pos') + y = Editor_state.margin_top App.screen.check(y, 'ghi ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl m', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'no ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:3') end function test_down_arrow_moves_cursor() io.write('\ntest_down_arrow_moves_cursor') App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- initially the first three lines are displayed edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_down_arrow_moves_cursor/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_down_arrow_moves_cursor/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_down_arrow_moves_cursor/baseline/screen:3') -- after hitting the down arrow, the cursor moves down by 1 line App.run_after_keychord('down') - check_eq(Screen_top1.line, 1, 'F - test_down_arrow_moves_cursor/screen_top') - check_eq(Cursor1.line, 2, 'F - test_down_arrow_moves_cursor/cursor') + check_eq(Editor_state.screen_top1.line, 1, 'F - test_down_arrow_moves_cursor/screen_top') + check_eq(Editor_state.cursor1.line, 2, 'F - test_down_arrow_moves_cursor/cursor') -- the screen is unchanged - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_down_arrow_moves_cursor/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_down_arrow_moves_cursor/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_down_arrow_moves_cursor/screen:3') end @@ -972,118 +972,118 @@ function test_down_arrow_scrolls_down_by_one_line() io.write('\ntest_down_arrow_scrolls_down_by_one_line') -- display the first three lines with the cursor on the bottom line App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_down_arrow_scrolls_down_by_one_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_down_arrow_scrolls_down_by_one_line/baseline/screen:3') -- after hitting the down arrow the screen scrolls down by one line App.run_after_keychord('down') - check_eq(Screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_line/screen_top') - check_eq(Cursor1.line, 4, 'F - test_down_arrow_scrolls_down_by_one_line/cursor') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_line/screen_top') + check_eq(Editor_state.cursor1.line, 4, 'F - test_down_arrow_scrolls_down_by_one_line/cursor') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_down_arrow_scrolls_down_by_one_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_down_arrow_scrolls_down_by_one_line/screen:3') end function test_down_arrow_scrolls_down_by_one_screen_line() io.write('\ntest_down_arrow_scrolls_down_by_one_screen_line') -- display the first three lines with the cursor on the bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_down_arrow_scrolls_down_by_one_screen_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_down_arrow_scrolls_down_by_one_screen_line/baseline/screen:3') -- line wrapping includes trailing whitespace -- after hitting the down arrow the screen scrolls down by one line App.run_after_keychord('down') - check_eq(Screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:line') - check_eq(Cursor1.pos, 5, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 5, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:3') end function test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word() io.write('\ntest_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word') -- display the first three lines with the cursor on the bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghijkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghijkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghijk', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/baseline/screen:3') -- after hitting the down arrow the screen scrolls down by one line App.run_after_keychord('down') - check_eq(Screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen_top') - check_eq(Cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:line') - check_eq(Cursor1.pos, 6, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:line') + check_eq(Editor_state.cursor1.pos, 6, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghijk', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'l', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen:3') end function test_page_down_followed_by_down_arrow_does_not_scroll_screen_up() io.write('\ntest_page_down_followed_by_down_arrow_does_not_scroll_screen_up') - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghijkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghijkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghijk', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline/screen:3') -- after hitting pagedown the screen scrolls down to start of a long line App.run_after_keychord('pagedown') - check_eq(Screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/screen_top') - check_eq(Cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:pos') + check_eq(Editor_state.screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:pos') -- after hitting down arrow the screen doesn't scroll down further, and certainly doesn't scroll up App.run_after_keychord('down') - check_eq(Screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen_top') - check_eq(Cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:line') - check_eq(Cursor1.pos, 6, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:line') + check_eq(Editor_state.cursor1.pos, 6, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'ghijk', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'l', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen:3') end @@ -1091,28 +1091,28 @@ function test_up_arrow_moves_cursor() io.write('\ntest_up_arrow_moves_cursor') -- display the first 3 lines with the cursor on the bottom line App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=1} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=1} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_up_arrow_moves_cursor/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_up_arrow_moves_cursor/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_up_arrow_moves_cursor/baseline/screen:3') -- after hitting the up arrow the cursor moves up by 1 line App.run_after_keychord('up') - check_eq(Screen_top1.line, 1, 'F - test_up_arrow_moves_cursor/screen_top') - check_eq(Cursor1.line, 2, 'F - test_up_arrow_moves_cursor/cursor') + check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_moves_cursor/screen_top') + check_eq(Editor_state.cursor1.line, 2, 'F - test_up_arrow_moves_cursor/cursor') -- the screen is unchanged - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_up_arrow_moves_cursor/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_up_arrow_moves_cursor/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_up_arrow_moves_cursor/screen:3') end @@ -1120,413 +1120,413 @@ function test_up_arrow_scrolls_up_by_one_line() io.write('\ntest_up_arrow_scrolls_up_by_one_line') -- display the lines 2/3/4 with the cursor on line 2 App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_by_one_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_by_one_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_line/baseline/screen:3') -- after hitting the up arrow the screen scrolls up by one line App.run_after_keychord('up') - check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/screen_top') - check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/cursor') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/cursor') + y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_up_arrow_scrolls_up_by_one_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_by_one_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_by_one_line/screen:3') end function test_up_arrow_scrolls_up_by_one_screen_line() io.write('\ntest_up_arrow_scrolls_up_by_one_screen_line') -- display lines starting from second screen line of a line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=6} - Screen_top1 = {line=3, pos=5} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=6} + Editor_state.screen_top1 = {line=3, pos=5} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_screen_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_by_one_screen_line/baseline/screen:2') -- after hitting the up arrow the screen scrolls up to first screen line App.run_after_keychord('up') - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'ghi ', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:3') - check_eq(Screen_top1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top') - check_eq(Screen_top1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:pos') + check_eq(Editor_state.screen_top1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top') + check_eq(Editor_state.screen_top1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:pos') end function test_up_arrow_scrolls_up_to_final_screen_line() io.write('\ntest_up_arrow_scrolls_up_to_final_screen_line') -- display lines starting just after a long line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:3') -- after hitting the up arrow the screen scrolls up to final screen line of previous line App.run_after_keychord('up') - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:3') - check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top') - check_eq(Screen_top1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top') - check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:line') - check_eq(Cursor1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:pos') + check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top') + check_eq(Editor_state.screen_top1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:pos') end function test_up_arrow_scrolls_up_to_empty_line() io.write('\ntest_up_arrow_scrolls_up_to_empty_line') -- display a screenful of text with an empty line just above it outside the screen App.screen.init{width=120, height=60} - Lines = load_array{'', 'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'', 'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_up_arrow_scrolls_up_to_empty_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_empty_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_empty_line/baseline/screen:3') -- after hitting the up arrow the screen scrolls up by one line App.run_after_keychord('up') - check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/screen_top') - check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/cursor') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/cursor') + y = Editor_state.margin_top -- empty first line - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'abc', 'F - test_up_arrow_scrolls_up_to_empty_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_empty_line/screen:3') end function test_pageup() io.write('\ntest_pageup') App.screen.init{width=120, height=45} - Lines = load_array{'abc', 'def', 'ghi'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} -- initially the last two lines are displayed edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_pageup/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_pageup/baseline/screen:2') -- after pageup the cursor goes to first line App.run_after_keychord('pageup') - check_eq(Screen_top1.line, 1, 'F - test_pageup/screen_top') - check_eq(Cursor1.line, 1, 'F - test_pageup/cursor') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_pageup/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_pageup/cursor') + y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_pageup/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_pageup/screen:2') end function test_pageup_scrolls_up_by_screen_line() io.write('\ntest_pageup_scrolls_up_by_screen_line') -- display the first three lines with the cursor on the bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'ghi', 'F - test_pageup_scrolls_up_by_screen_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_pageup_scrolls_up_by_screen_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_pageup_scrolls_up_by_screen_line/baseline/screen:3') -- line wrapping includes trailing whitespace -- after hitting the page-up key the screen scrolls up to top App.run_after_keychord('pageup') - check_eq(Screen_top1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/screen_top') - check_eq(Cursor1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'abc ', 'F - test_pageup_scrolls_up_by_screen_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_pageup_scrolls_up_by_screen_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_pageup_scrolls_up_by_screen_line/screen:3') end function test_pageup_scrolls_up_from_middle_screen_line() io.write('\ntest_pageup_scrolls_up_from_middle_screen_line') - -- display a few lines starting from the middle of a line (Cursor1.pos > 1) - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=5} - Screen_top1 = {line=2, pos=5} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + -- display a few lines starting from the middle of a line (Editor_state.cursor1.pos > 1) + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=5} + Editor_state.screen_top1 = {line=2, pos=5} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'jkl', 'F - test_pageup_scrolls_up_from_middle_screen_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_pageup_scrolls_up_from_middle_screen_line/baseline/screen:3') -- line wrapping includes trailing whitespace -- after hitting the page-up key the screen scrolls up to top App.run_after_keychord('pageup') - check_eq(Screen_top1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/screen_top') - check_eq(Cursor1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'abc ', 'F - test_pageup_scrolls_up_from_middle_screen_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_pageup_scrolls_up_from_middle_screen_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_pageup_scrolls_up_from_middle_screen_line/screen:3') end function test_enter_on_bottom_line_scrolls_down() io.write('\ntest_enter_on_bottom_line_scrolls_down') -- display a few lines with cursor on bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_enter_on_bottom_line_scrolls_down/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_enter_on_bottom_line_scrolls_down/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_enter_on_bottom_line_scrolls_down/baseline/screen:3') -- after hitting the enter key the screen scrolls down App.run_after_keychord('return') - check_eq(Screen_top1.line, 2, 'F - test_enter_on_bottom_line_scrolls_down/screen_top') - check_eq(Cursor1.line, 4, 'F - test_enter_on_bottom_line_scrolls_down/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_enter_on_bottom_line_scrolls_down/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_enter_on_bottom_line_scrolls_down/screen_top') + check_eq(Editor_state.cursor1.line, 4, 'F - test_enter_on_bottom_line_scrolls_down/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_enter_on_bottom_line_scrolls_down/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_enter_on_bottom_line_scrolls_down/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'g', 'F - test_enter_on_bottom_line_scrolls_down/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'hi', 'F - test_enter_on_bottom_line_scrolls_down/screen:3') end function test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom() io.write('\ntest_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom') -- display just the bottom line on screen - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=4, pos=2} - Screen_top1 = {line=4, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=4, pos=2} + Editor_state.screen_top1 = {line=4, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'jkl', 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/baseline/screen:1') -- after hitting the enter key the screen does not scroll down App.run_after_keychord('return') - check_eq(Screen_top1.line, 4, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top') - check_eq(Cursor1.line, 5, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 4, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top') + check_eq(Editor_state.cursor1.line, 5, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'j', 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'kl', 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen:2') end function test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom() io.write('\ntest_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom') -- display just an empty bottom line on screen - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', ''} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', ''} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- after hitting the inserting_text key the screen does not scroll down App.run_after_textinput('a') - check_eq(Screen_top1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top') - check_eq(Cursor1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line') - check_eq(Cursor1.pos, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos') - local y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top') + check_eq(Editor_state.cursor1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line') + check_eq(Editor_state.cursor1.pos, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos') + local y = Editor_state.margin_top App.screen.check(y, 'a', 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen:1') end function test_typing_on_bottom_line_scrolls_down() io.write('\ntest_typing_on_bottom_line_scrolls_down') -- display a few lines with cursor on bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=4} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=4} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_typing_on_bottom_line_scrolls_down/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_typing_on_bottom_line_scrolls_down/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_typing_on_bottom_line_scrolls_down/baseline/screen:3') -- after typing something the line wraps and the screen scrolls down App.run_after_textinput('j') App.run_after_textinput('k') App.run_after_textinput('l') - check_eq(Screen_top1.line, 2, 'F - test_typing_on_bottom_line_scrolls_down/screen_top') - check_eq(Cursor1.line, 3, 'F - test_typing_on_bottom_line_scrolls_down/cursor:line') - check_eq(Cursor1.pos, 7, 'F - test_typing_on_bottom_line_scrolls_down/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_typing_on_bottom_line_scrolls_down/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_typing_on_bottom_line_scrolls_down/cursor:line') + check_eq(Editor_state.cursor1.pos, 7, 'F - test_typing_on_bottom_line_scrolls_down/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_typing_on_bottom_line_scrolls_down/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghijk', 'F - test_typing_on_bottom_line_scrolls_down/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'l', 'F - test_typing_on_bottom_line_scrolls_down/screen:3') end function test_left_arrow_scrolls_up_in_wrapped_line() io.write('\ntest_left_arrow_scrolls_up_in_wrapped_line') -- display lines starting from second screen line of a line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Screen_top1 = {line=3, pos=5} - Screen_bottom1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.screen_top1 = {line=3, pos=5} + Editor_state.screen_bottom1 = {} -- cursor is at top of screen - Cursor1 = {line=3, pos=5} + Editor_state.cursor1 = {line=3, pos=5} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'jkl', 'F - test_left_arrow_scrolls_up_in_wrapped_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_left_arrow_scrolls_up_in_wrapped_line/baseline/screen:2') -- after hitting the left arrow the screen scrolls up to first screen line App.run_after_keychord('left') - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'ghi ', 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen:3') - check_eq(Screen_top1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top') - check_eq(Screen_top1.pos, 1, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:line') - check_eq(Cursor1.pos, 4, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:pos') + check_eq(Editor_state.screen_top1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top') + check_eq(Editor_state.screen_top1.pos, 1, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:pos') end function test_right_arrow_scrolls_down_in_wrapped_line() io.write('\ntest_right_arrow_scrolls_down_in_wrapped_line') -- display the first three lines with the cursor on the bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- cursor is at bottom right of screen - Cursor1 = {line=3, pos=5} + Editor_state.cursor1 = {line=3, pos=5} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_right_arrow_scrolls_down_in_wrapped_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_right_arrow_scrolls_down_in_wrapped_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_right_arrow_scrolls_down_in_wrapped_line/baseline/screen:3') -- line wrapping includes trailing whitespace -- after hitting the right arrow the screen scrolls down by one line App.run_after_keychord('right') - check_eq(Screen_top1.line, 2, 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:line') - check_eq(Cursor1.pos, 6, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 6, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen:3') end function test_home_scrolls_up_in_wrapped_line() io.write('\ntest_home_scrolls_up_in_wrapped_line') -- display lines starting from second screen line of a line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Screen_top1 = {line=3, pos=5} - Screen_bottom1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.screen_top1 = {line=3, pos=5} + Editor_state.screen_bottom1 = {} -- cursor is at top of screen - Cursor1 = {line=3, pos=5} + Editor_state.cursor1 = {line=3, pos=5} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'jkl', 'F - test_home_scrolls_up_in_wrapped_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_home_scrolls_up_in_wrapped_line/baseline/screen:2') -- after hitting home the screen scrolls up to first screen line App.run_after_keychord('home') - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'ghi ', 'F - test_home_scrolls_up_in_wrapped_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_home_scrolls_up_in_wrapped_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_home_scrolls_up_in_wrapped_line/screen:3') - check_eq(Screen_top1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/screen_top') - check_eq(Screen_top1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/cursor:line') - check_eq(Cursor1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/cursor:pos') + check_eq(Editor_state.screen_top1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/screen_top') + check_eq(Editor_state.screen_top1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/cursor:pos') end function test_end_scrolls_down_in_wrapped_line() io.write('\ntest_end_scrolls_down_in_wrapped_line') -- display the first three lines with the cursor on the bottom line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- cursor is at bottom right of screen - Cursor1 = {line=3, pos=5} + Editor_state.cursor1 = {line=3, pos=5} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_end_scrolls_down_in_wrapped_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_end_scrolls_down_in_wrapped_line/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_end_scrolls_down_in_wrapped_line/baseline/screen:3') -- line wrapping includes trailing whitespace -- after hitting end the screen scrolls down by one line App.run_after_keychord('end') - check_eq(Screen_top1.line, 2, 'F - test_end_scrolls_down_in_wrapped_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_end_scrolls_down_in_wrapped_line/cursor:line') - check_eq(Cursor1.pos, 8, 'F - test_end_scrolls_down_in_wrapped_line/cursor:pos') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 2, 'F - test_end_scrolls_down_in_wrapped_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_end_scrolls_down_in_wrapped_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 8, 'F - test_end_scrolls_down_in_wrapped_line/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_end_scrolls_down_in_wrapped_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi ', 'F - test_end_scrolls_down_in_wrapped_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_end_scrolls_down_in_wrapped_line/screen:3') end @@ -1534,102 +1534,102 @@ function test_position_cursor_on_recently_edited_wrapping_line() -- draw a line wrapping over 2 screen lines io.write('\ntest_position_cursor_on_recently_edited_wrapping_line') App.screen.init{width=100, height=200} - Lines = load_array{'abc def ghi jkl mno pqr ', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=25} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc def ghi jkl mno pqr ', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=25} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'abc def ghi ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline1/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl mno pqr ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline1/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'xyz', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline1/screen:3') -- add to the line until it's wrapping over 3 screen lines App.run_after_textinput('s') App.run_after_textinput('t') App.run_after_textinput('u') - check_eq(Cursor1.pos, 28, 'F - test_move_cursor_using_mouse/cursor:pos') - y = Margin_top + check_eq(Editor_state.cursor1.pos, 28, 'F - test_move_cursor_using_mouse/cursor:pos') + y = Editor_state.margin_top App.screen.check(y, 'abc def ghi ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline2/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl mno pqr ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline2/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'stu', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline2/screen:3') -- try to move the cursor earlier in the third screen line by clicking the mouse - App.run_after_mouse_release(Margin_left+8,Margin_top+Line_height*2+5, 1) + App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+Editor_state.line_height*2+5, 1) -- cursor should move - check_eq(Cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line') - check_eq(Cursor1.pos, 26, 'F - test_move_cursor_using_mouse/cursor:pos') + check_eq(Editor_state.cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line') + check_eq(Editor_state.cursor1.pos, 26, 'F - test_move_cursor_using_mouse/cursor:pos') end function test_backspace_can_scroll_up() io.write('\ntest_backspace_can_scroll_up') -- display the lines 2/3/4 with the cursor on line 2 App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Screen_top1 = {line=2, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.screen_top1 = {line=2, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() - local y = Margin_top + local y = Editor_state.margin_top App.screen.check(y, 'def', 'F - test_backspace_can_scroll_up/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_backspace_can_scroll_up/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_backspace_can_scroll_up/baseline/screen:3') -- after hitting backspace the screen scrolls up by one line App.run_after_keychord('backspace') - check_eq(Screen_top1.line, 1, 'F - test_backspace_can_scroll_up/screen_top') - check_eq(Cursor1.line, 1, 'F - test_backspace_can_scroll_up/cursor') - y = Margin_top + check_eq(Editor_state.screen_top1.line, 1, 'F - test_backspace_can_scroll_up/screen_top') + check_eq(Editor_state.cursor1.line, 1, 'F - test_backspace_can_scroll_up/cursor') + y = Editor_state.margin_top App.screen.check(y, 'abcdef', 'F - test_backspace_can_scroll_up/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'ghi', 'F - test_backspace_can_scroll_up/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'jkl', 'F - test_backspace_can_scroll_up/screen:3') end function test_backspace_can_scroll_up_screen_line() io.write('\ntest_backspace_can_scroll_up_screen_line') -- display lines starting from second screen line of a line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=3, pos=5} - Screen_top1 = {line=3, pos=5} - Screen_bottom1 = {} - edit.draw() - local y = Margin_top + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=3, pos=5} + Editor_state.screen_top1 = {line=3, pos=5} + Editor_state.screen_bottom1 = {} + edit.draw() + local y = Editor_state.margin_top App.screen.check(y, 'jkl', 'F - test_backspace_can_scroll_up_screen_line/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_backspace_can_scroll_up_screen_line/baseline/screen:2') -- after hitting backspace the screen scrolls up by one screen line App.run_after_keychord('backspace') - y = Margin_top + y = Editor_state.margin_top App.screen.check(y, 'ghijk', 'F - test_backspace_can_scroll_up_screen_line/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'l', 'F - test_backspace_can_scroll_up_screen_line/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'mno', 'F - test_backspace_can_scroll_up_screen_line/screen:3') - check_eq(Screen_top1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/screen_top') - check_eq(Screen_top1.pos, 1, 'F - test_backspace_can_scroll_up_screen_line/screen_top') - check_eq(Cursor1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/cursor:line') - check_eq(Cursor1.pos, 4, 'F - test_backspace_can_scroll_up_screen_line/cursor:pos') + check_eq(Editor_state.screen_top1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/screen_top') + check_eq(Editor_state.screen_top1.pos, 1, 'F - test_backspace_can_scroll_up_screen_line/screen_top') + check_eq(Editor_state.cursor1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/cursor:line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_backspace_can_scroll_up_screen_line/cursor:pos') end function test_backspace_past_line_boundary() io.write('\ntest_backspace_past_line_boundary') -- position cursor at start of a (non-first) line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} -- backspace joins with previous line App.run_after_keychord('backspace') - check_eq(Lines[1].data, 'abcdef', "F - test_backspace_past_line_boundary") + check_eq(Editor_state.lines[1].data, 'abcdef', "F - test_backspace_past_line_boundary") end -- some tests for operating over selections created using Shift- chords @@ -1638,165 +1638,165 @@ end function test_backspace_over_selection() io.write('\ntest_backspace_over_selection') -- select just one character within a line with cursor before selection - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} -- backspace deletes the selected character, even though it's after the cursor App.run_after_keychord('backspace') - check_eq(Lines[1].data, 'bc', "F - test_backspace_over_selection/data") + check_eq(Editor_state.lines[1].data, 'bc', "F - test_backspace_over_selection/data") -- cursor (remains) at start of selection - check_eq(Cursor1.line, 1, "F - test_backspace_over_selection/cursor:line") - check_eq(Cursor1.pos, 1, "F - test_backspace_over_selection/cursor:pos") + check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_over_selection/cursor:line") + check_eq(Editor_state.cursor1.pos, 1, "F - test_backspace_over_selection/cursor:pos") -- selection is cleared - check_nil(Selection1.line, "F - test_backspace_over_selection/selection") + check_nil(Editor_state.selection1.line, "F - test_backspace_over_selection/selection") end function test_backspace_over_selection_reverse() io.write('\ntest_backspace_over_selection_reverse') -- select just one character within a line with cursor after selection - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Selection1 = {line=1, pos=1} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.selection1 = {line=1, pos=1} -- backspace deletes the selected character App.run_after_keychord('backspace') - check_eq(Lines[1].data, 'bc', "F - test_backspace_over_selection_reverse/data") + check_eq(Editor_state.lines[1].data, 'bc', "F - test_backspace_over_selection_reverse/data") -- cursor moves to start of selection - check_eq(Cursor1.line, 1, "F - test_backspace_over_selection_reverse/cursor:line") - check_eq(Cursor1.pos, 1, "F - test_backspace_over_selection_reverse/cursor:pos") + check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_over_selection_reverse/cursor:line") + check_eq(Editor_state.cursor1.pos, 1, "F - test_backspace_over_selection_reverse/cursor:pos") -- selection is cleared - check_nil(Selection1.line, "F - test_backspace_over_selection_reverse/selection") + check_nil(Editor_state.selection1.line, "F - test_backspace_over_selection_reverse/selection") end function test_backspace_over_multiple_lines() io.write('\ntest_backspace_over_multiple_lines') -- select just one character within a line with cursor after selection - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Selection1 = {line=4, pos=2} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.selection1 = {line=4, pos=2} -- backspace deletes the region and joins the remaining portions of lines on either side App.run_after_keychord('backspace') - check_eq(Lines[1].data, 'akl', "F - test_backspace_over_multiple_lines/data:1") - check_eq(Lines[2].data, 'mno', "F - test_backspace_over_multiple_lines/data:2") + check_eq(Editor_state.lines[1].data, 'akl', "F - test_backspace_over_multiple_lines/data:1") + check_eq(Editor_state.lines[2].data, 'mno', "F - test_backspace_over_multiple_lines/data:2") -- cursor remains at start of selection - check_eq(Cursor1.line, 1, "F - test_backspace_over_multiple_lines/cursor:line") - check_eq(Cursor1.pos, 2, "F - test_backspace_over_multiple_lines/cursor:pos") + check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_over_multiple_lines/cursor:line") + check_eq(Editor_state.cursor1.pos, 2, "F - test_backspace_over_multiple_lines/cursor:pos") -- selection is cleared - check_nil(Selection1.line, "F - test_backspace_over_multiple_lines/selection") + check_nil(Editor_state.selection1.line, "F - test_backspace_over_multiple_lines/selection") end function test_backspace_to_end_of_line() io.write('\ntest_backspace_to_end_of_line') -- select region from cursor to end of line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=2} - Selection1 = {line=1, pos=4} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=2} + Editor_state.selection1 = {line=1, pos=4} -- backspace deletes rest of line without joining to any other line App.run_after_keychord('backspace') - check_eq(Lines[1].data, 'a', "F - test_backspace_to_start_of_line/data:1") - check_eq(Lines[2].data, 'def', "F - test_backspace_to_start_of_line/data:2") + check_eq(Editor_state.lines[1].data, 'a', "F - test_backspace_to_start_of_line/data:1") + check_eq(Editor_state.lines[2].data, 'def', "F - test_backspace_to_start_of_line/data:2") -- cursor remains at start of selection - check_eq(Cursor1.line, 1, "F - test_backspace_to_start_of_line/cursor:line") - check_eq(Cursor1.pos, 2, "F - test_backspace_to_start_of_line/cursor:pos") + check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_to_start_of_line/cursor:line") + check_eq(Editor_state.cursor1.pos, 2, "F - test_backspace_to_start_of_line/cursor:pos") -- selection is cleared - check_nil(Selection1.line, "F - test_backspace_to_start_of_line/selection") + check_nil(Editor_state.selection1.line, "F - test_backspace_to_start_of_line/selection") end function test_backspace_to_start_of_line() io.write('\ntest_backspace_to_start_of_line') -- select region from cursor to start of line - App.screen.init{width=Margin_left+30, height=60} - Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=1} - Selection1 = {line=2, pos=3} + App.screen.init{width=Editor_state.margin_left+30, height=60} + Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=1} + Editor_state.selection1 = {line=2, pos=3} -- backspace deletes beginning of line without joining to any other line App.run_after_keychord('backspace') - check_eq(Lines[1].data, 'abc', "F - test_backspace_to_start_of_line/data:1") - check_eq(Lines[2].data, 'f', "F - test_backspace_to_start_of_line/data:2") + check_eq(Editor_state.lines[1].data, 'abc', "F - test_backspace_to_start_of_line/data:1") + check_eq(Editor_state.lines[2].data, 'f', "F - test_backspace_to_start_of_line/data:2") -- cursor remains at start of selection - check_eq(Cursor1.line, 2, "F - test_backspace_to_start_of_line/cursor:line") - check_eq(Cursor1.pos, 1, "F - test_backspace_to_start_of_line/cursor:pos") + check_eq(Editor_state.cursor1.line, 2, "F - test_backspace_to_start_of_line/cursor:line") + check_eq(Editor_state.cursor1.pos, 1, "F - test_backspace_to_start_of_line/cursor:pos") -- selection is cleared - check_nil(Selection1.line, "F - test_backspace_to_start_of_line/selection") + check_nil(Editor_state.selection1.line, "F - test_backspace_to_start_of_line/selection") end function test_undo_insert_text() io.write('\ntest_undo_insert_text') App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'def', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=4} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'def', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=4} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- insert a character edit.draw() App.run_after_textinput('g') - check_eq(Cursor1.line, 2, 'F - test_undo_insert_text/baseline/cursor:line') - check_eq(Cursor1.pos, 5, 'F - test_undo_insert_text/baseline/cursor:pos') - check_nil(Selection1.line, 'F - test_undo_insert_text/baseline/selection:line') - check_nil(Selection1.pos, 'F - test_undo_insert_text/baseline/selection:pos') - local y = Margin_top + check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_insert_text/baseline/cursor:line') + check_eq(Editor_state.cursor1.pos, 5, 'F - test_undo_insert_text/baseline/cursor:pos') + check_nil(Editor_state.selection1.line, 'F - test_undo_insert_text/baseline/selection:line') + check_nil(Editor_state.selection1.pos, 'F - test_undo_insert_text/baseline/selection:pos') + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_undo_insert_text/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'defg', 'F - test_undo_insert_text/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'xyz', 'F - test_undo_insert_text/baseline/screen:3') -- undo App.run_after_keychord('C-z') - check_eq(Cursor1.line, 2, 'F - test_undo_insert_text/cursor:line') - check_eq(Cursor1.pos, 4, 'F - test_undo_insert_text/cursor:pos') - check_nil(Selection1.line, 'F - test_undo_insert_text/selection:line') - check_nil(Selection1.pos, 'F - test_undo_insert_text/selection:pos') - y = Margin_top + check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_insert_text/cursor:line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_undo_insert_text/cursor:pos') + check_nil(Editor_state.selection1.line, 'F - test_undo_insert_text/selection:line') + check_nil(Editor_state.selection1.pos, 'F - test_undo_insert_text/selection:pos') + y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_undo_insert_text/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_undo_insert_text/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'xyz', 'F - test_undo_insert_text/screen:3') end function test_undo_delete_text() io.write('\ntest_undo_delete_text') App.screen.init{width=120, height=60} - Lines = load_array{'abc', 'defg', 'xyz'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=2, pos=5} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc', 'defg', 'xyz'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=2, pos=5} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} -- delete a character App.run_after_keychord('backspace') - check_eq(Cursor1.line, 2, 'F - test_undo_delete_text/baseline/cursor:line') - check_eq(Cursor1.pos, 4, 'F - test_undo_delete_text/baseline/cursor:pos') - check_nil(Selection1.line, 'F - test_undo_delete_text/baseline/selection:line') - check_nil(Selection1.pos, 'F - test_undo_delete_text/baseline/selection:pos') - local y = Margin_top + check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_delete_text/baseline/cursor:line') + check_eq(Editor_state.cursor1.pos, 4, 'F - test_undo_delete_text/baseline/cursor:pos') + check_nil(Editor_state.selection1.line, 'F - test_undo_delete_text/baseline/selection:line') + check_nil(Editor_state.selection1.pos, 'F - test_undo_delete_text/baseline/selection:pos') + local y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_undo_delete_text/baseline/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'def', 'F - test_undo_delete_text/baseline/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'xyz', 'F - test_undo_delete_text/baseline/screen:3') -- undo --? -- after undo, the backspaced key is selected App.run_after_keychord('C-z') - check_eq(Cursor1.line, 2, 'F - test_undo_delete_text/cursor:line') - check_eq(Cursor1.pos, 5, 'F - test_undo_delete_text/cursor:pos') - check_nil(Selection1.line, 'F - test_undo_delete_text/selection:line') - check_nil(Selection1.pos, 'F - test_undo_delete_text/selection:pos') ---? check_eq(Selection1.line, 2, 'F - test_undo_delete_text/selection:line') ---? check_eq(Selection1.pos, 4, 'F - test_undo_delete_text/selection:pos') - y = Margin_top + check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_delete_text/cursor:line') + check_eq(Editor_state.cursor1.pos, 5, 'F - test_undo_delete_text/cursor:pos') + check_nil(Editor_state.selection1.line, 'F - test_undo_delete_text/selection:line') + check_nil(Editor_state.selection1.pos, 'F - test_undo_delete_text/selection:pos') +--? check_eq(Editor_state.selection1.line, 2, 'F - test_undo_delete_text/selection:line') +--? check_eq(Editor_state.selection1.pos, 4, 'F - test_undo_delete_text/selection:pos') + y = Editor_state.margin_top App.screen.check(y, 'abc', 'F - test_undo_delete_text/screen:1') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'defg', 'F - test_undo_delete_text/screen:2') - y = y + Line_height + y = y + Editor_state.line_height App.screen.check(y, 'xyz', 'F - test_undo_delete_text/screen:3') end @@ -1804,21 +1804,21 @@ function test_undo_restores_selection() io.write('\ntest_undo_restores_selection') -- display a line of text with some part selected App.screen.init{width=75, height=80} - Lines = load_array{'abc'} - Margin_right = 0; Margin_width = Margin_left - Cursor1 = {line=1, pos=1} - Selection1 = {line=1, pos=2} - Screen_top1 = {line=1, pos=1} - Screen_bottom1 = {} + Editor_state.lines = load_array{'abc'} + Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left + Editor_state.cursor1 = {line=1, pos=1} + Editor_state.selection1 = {line=1, pos=2} + Editor_state.screen_top1 = {line=1, pos=1} + Editor_state.screen_bottom1 = {} edit.draw() -- delete selected text App.run_after_textinput('x') - check_eq(Lines[1].data, 'xbc', 'F - test_undo_restores_selection/baseline') - check_nil(Selection1.line, 'F - test_undo_restores_selection/baseline:selection') + check_eq(Editor_state.lines[1].data, 'xbc', 'F - test_undo_restores_selection/baseline') + check_nil(Editor_state.selection1.line, 'F - test_undo_restores_selection/baseline:selection') -- undo App.run_after_keychord('C-z') App.run_after_keychord('C-z') -- selection is restored - check_eq(Selection1.line, 1, 'F - test_undo_restores_selection/line') - check_eq(Selection1.pos, 2, 'F - test_undo_restores_selection/pos') + check_eq(Editor_state.selection1.line, 1, 'F - test_undo_restores_selection/line') + check_eq(Editor_state.selection1.pos, 2, 'F - test_undo_restores_selection/pos') end diff --git a/undo.lua b/undo.lua index 3504577..8e5491c 100644 --- a/undo.lua +++ b/undo.lua @@ -7,27 +7,27 @@ -- TODO: coalesce multiple similar operations function record_undo_event(data) - History[Next_history] = data - Next_history = Next_history+1 - for i=Next_history,#History do - History[i] = nil + Editor_state.history[Editor_state.next_history] = data + Editor_state.next_history = Editor_state.next_history+1 + for i=Editor_state.next_history,#Editor_state.history do + Editor_state.history[i] = nil end end function undo_event() - if Next_history > 1 then ---? print('moving to history', Next_history-1) - Next_history = Next_history-1 - local result = History[Next_history] + if Editor_state.next_history > 1 then +--? print('moving to history', Editor_state.next_history-1) + Editor_state.next_history = Editor_state.next_history-1 + local result = Editor_state.history[Editor_state.next_history] return result end end function redo_event() - if Next_history <= #History then ---? print('restoring history', Next_history+1) - local result = History[Next_history] - Next_history = Next_history+1 + if Editor_state.next_history <= #Editor_state.history then +--? print('restoring history', Editor_state.next_history+1) + local result = Editor_state.history[Editor_state.next_history] + Editor_state.next_history = Editor_state.next_history+1 return result end end @@ -40,18 +40,18 @@ function snapshot(s,e) if e == nil then e = s end - assert(#Lines > 0) + assert(#Editor_state.lines > 0) if s < 1 then s = 1 end - if s > #Lines then s = #Lines end + if s > #Editor_state.lines then s = #Editor_state.lines end if e < 1 then e = 1 end - if e > #Lines then e = #Lines end + if e > #Editor_state.lines then e = #Editor_state.lines end -- compare with App.initialize_globals local event = { - screen_top=deepcopy(Screen_top1), - selection=deepcopy(Selection1), - cursor=deepcopy(Cursor1), + screen_top=deepcopy(Editor_state.screen_top1), + selection=deepcopy(Editor_state.selection1), + cursor=deepcopy(Editor_state.cursor1), current_drawing_mode=Drawing_mode, - previous_drawing_mode=Previous_drawing_mode, + previous_drawing_mode=Editor_state.previous_drawing_mode, lines={}, start_line=s, end_line=e, @@ -59,7 +59,7 @@ function snapshot(s,e) } -- deep copy lines without cached stuff like text fragments for i=s,e do - local line = Lines[i] + local line = Editor_state.lines[i] if line.mode == 'text' then table.insert(event.lines, {mode='text', data=line.data}) elseif line.mode == 'drawing' then |