Merge luaML.love
This commit is contained in:
commit
af9c6f5e0b
2
app.lua
2
app.lua
|
@ -232,6 +232,8 @@ function App.run_tests(record_error_fn)
|
|||
App = App_for_tests
|
||||
local saved_font = love.graphics.getFont()
|
||||
love.graphics.setFont(Love_snapshot.initial_font)
|
||||
--? App.initialize_for_test() -- debug: run a single test at a time like these 2 lines
|
||||
--? test_click_below_all_lines()
|
||||
for _,name in ipairs(sorted_names) do
|
||||
App.initialize_for_test()
|
||||
--? print('=== '..name)
|
||||
|
|
24
edit.lua
24
edit.lua
|
@ -26,7 +26,6 @@ function edit.initialize_state(top, left, right, font, font_height, line_height)
|
|||
|
||||
-- rendering wrapped text lines needs some additional short-lived data per line:
|
||||
-- startpos, the index of data the line starts rendering from, can only be >1 for topmost line on screen
|
||||
-- starty, the y coord in pixels the line starts rendering from
|
||||
-- fragments: snippets of the line guaranteed to not straddle screen lines
|
||||
-- screen_line_starting_pos: optional array of grapheme indices if it wraps over more than one screen line
|
||||
line_cache = {},
|
||||
|
@ -40,9 +39,10 @@ function edit.initialize_state(top, left, right, font, font_height, line_height)
|
|||
--
|
||||
-- Make sure these coordinates are never aliased, so that changing one causes
|
||||
-- action at a distance.
|
||||
--
|
||||
-- On lines that are drawings, pos will be nil.
|
||||
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
|
||||
cursor1 = {line=1, pos=1}, -- position of cursor; must be on a text line
|
||||
|
||||
selection1 = {},
|
||||
-- some extra state to compute selection between mouse press and release
|
||||
|
@ -109,22 +109,19 @@ function edit.draw(State, fg, hide_cursor)
|
|||
State.cursor_x = nil
|
||||
State.cursor_y = nil
|
||||
local y = State.top
|
||||
local screen_bottom1 = {line=nil, pos=nil}
|
||||
--? print('== draw')
|
||||
for line_index = State.screen_top1.line,#State.lines do
|
||||
local line = State.lines[line_index]
|
||||
--? print('draw:', y, line_index, line)
|
||||
if y + State.line_height > App.screen.height then break end
|
||||
screen_bottom1.line = line_index
|
||||
--? print('text.draw', y, line_index)
|
||||
local startpos = 1
|
||||
if line_index == State.screen_top1.line then
|
||||
startpos = State.screen_top1.pos
|
||||
end
|
||||
y, screen_bottom1.pos = Text.draw(State, line_index, y, startpos, fg, hide_cursor)
|
||||
y = Text.draw(State, line_index, y, startpos, fg, hide_cursor)
|
||||
--? print('=> y', y)
|
||||
end
|
||||
State.screen_bottom1 = screen_bottom1
|
||||
if State.search_term then
|
||||
Text.draw_search_bar(State, hide_cursor)
|
||||
end
|
||||
|
@ -180,10 +177,7 @@ function edit.mouse_press(State, x,y, mouse_button)
|
|||
State.old_cursor1 = State.cursor1
|
||||
State.old_selection1 = State.selection1
|
||||
State.mousepress_shift = App.shift_down()
|
||||
State.selection1 = {
|
||||
line=State.screen_bottom1.line,
|
||||
pos=Text.pos_at_end_of_screen_line(State, State.screen_bottom1),
|
||||
}
|
||||
State.selection1 = Text.final_text_loc_on_screen(State)
|
||||
end
|
||||
|
||||
function edit.mouse_release(State, x,y, mouse_button)
|
||||
|
@ -209,7 +203,7 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
end
|
||||
|
||||
-- still here? mouse release is below all screen lines
|
||||
State.cursor1.line, State.cursor1.pos = State.screen_bottom1.line, Text.pos_at_end_of_screen_line(State, State.screen_bottom1)
|
||||
State.cursor1 = Text.final_text_loc_on_screen(State)
|
||||
edit.clean_up_mouse_press(State)
|
||||
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
|
||||
end
|
||||
|
@ -235,7 +229,8 @@ function edit.mouse_wheel_move(State, dx,dy)
|
|||
Text.up(State)
|
||||
end
|
||||
elseif dy < 0 then
|
||||
State.cursor1 = {line=State.screen_bottom1.line, pos=State.screen_bottom1.pos}
|
||||
State.cursor1 = Text.screen_bottom1(State)
|
||||
edit.put_cursor_on_next_text_line(State)
|
||||
for i=1,math.floor(-dy) do
|
||||
Text.down(State)
|
||||
end
|
||||
|
@ -263,7 +258,6 @@ function edit.keychord_press(State, chord, key, readonly)
|
|||
end
|
||||
-- search
|
||||
if State.search_term then
|
||||
for _,line_cache in ipairs(State.line_cache) do line_cache.starty = nil end -- just in case we scroll
|
||||
if chord == 'escape' then
|
||||
State.search_term = nil
|
||||
State.cursor1 = State.search_backup.cursor
|
||||
|
@ -360,7 +354,6 @@ function edit.keychord_press(State, chord, key, readonly)
|
|||
record_undo_event(State, {before=before, after=snapshot(State, before_line, State.cursor1.line)})
|
||||
-- dispatch to text
|
||||
else
|
||||
for _,line_cache in ipairs(State.line_cache) do line_cache.starty = nil end -- just in case we scroll
|
||||
Text.keychord_press(State, chord, readonly)
|
||||
end
|
||||
end
|
||||
|
@ -415,6 +408,7 @@ end
|
|||
function edit.run_after_mouse_click(State, x,y, mouse_button)
|
||||
App.fake_mouse_press(x,y, mouse_button)
|
||||
edit.mouse_press(State, x,y, mouse_button)
|
||||
edit.draw(State, Text_color)
|
||||
App.fake_mouse_release(x,y, mouse_button)
|
||||
edit.mouse_release(State, x,y, mouse_button)
|
||||
App.screen.contents = {}
|
||||
|
|
|
@ -62,7 +62,8 @@ function Text.search_next(State)
|
|||
State.screen_top1.line = State.search_backup.screen_top.line
|
||||
State.screen_top1.pos = State.search_backup.screen_top.pos
|
||||
end
|
||||
if Text.lt1(State.cursor1, State.screen_top1) or Text.lt1(State.screen_bottom1, State.cursor1) then
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
if Text.lt1(State.cursor1, State.screen_top1) or Text.lt1(screen_bottom1, State.cursor1) then
|
||||
State.screen_top1.line = State.cursor1.line
|
||||
local pos = Text.pos_at_start_of_screen_line(State, State.cursor1)
|
||||
State.screen_top1.pos = pos
|
||||
|
@ -115,7 +116,8 @@ function Text.search_previous(State)
|
|||
State.screen_top1.line = State.search_backup.screen_top.line
|
||||
State.screen_top1.pos = State.search_backup.screen_top.pos
|
||||
end
|
||||
if Text.lt1(State.cursor1, State.screen_top1) or Text.lt1(State.screen_bottom1, State.cursor1) then
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
if Text.lt1(State.cursor1, State.screen_top1) or Text.lt1(screen_bottom1, State.cursor1) then
|
||||
State.screen_top1.line = State.cursor1.line
|
||||
local pos = Text.pos_at_start_of_screen_line(State, State.cursor1)
|
||||
State.screen_top1.pos = pos
|
||||
|
|
|
@ -69,7 +69,7 @@ end
|
|||
|
||||
function Text.mouse_pos(State)
|
||||
local x,y = App.mouse_x(), App.mouse_y()
|
||||
if y < State.line_cache[State.screen_top1.line].starty then
|
||||
if y < State.top then
|
||||
return State.screen_top1.line, State.screen_top1.pos
|
||||
end
|
||||
for line_index,line in ipairs(State.lines) do
|
||||
|
@ -77,7 +77,8 @@ function Text.mouse_pos(State)
|
|||
return line_index, Text.to_pos_on_line(State, line_index, x,y)
|
||||
end
|
||||
end
|
||||
return State.screen_bottom1.line, Text.pos_at_end_of_screen_line(State, State.screen_bottom1)
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
return screen_bottom1.line, Text.pos_at_end_of_screen_line(State, screen_bottom1)
|
||||
end
|
||||
|
||||
function Text.cut_selection(State)
|
||||
|
|
162
text.lua
162
text.lua
|
@ -7,14 +7,13 @@ require 'undo'
|
|||
require 'text_tests'
|
||||
|
||||
-- draw a line starting from startpos to screen at y between State.left and State.right
|
||||
-- return y for the next line, and position of start of final screen line drawn
|
||||
-- return y for the next line
|
||||
function Text.draw(State, line_index, y, startpos, fg, hide_cursor)
|
||||
--? print('text.draw', line_index, y)
|
||||
local line = State.lines[line_index]
|
||||
local line_cache = State.line_cache[line_index]
|
||||
line_cache.starty = y
|
||||
line_cache.startpos = startpos
|
||||
-- wrap long lines
|
||||
local final_screen_line_starting_pos = startpos -- track value to return
|
||||
Text.populate_screen_line_starting_pos(State, line_index)
|
||||
App.color(Line_number_color)
|
||||
love.graphics.print(line_index, State.left-Line_number_width*State.font:getWidth('m')+10,y)
|
||||
|
@ -27,7 +26,6 @@ function Text.draw(State, line_index, y, startpos, fg, hide_cursor)
|
|||
if pos < startpos then
|
||||
-- render nothing
|
||||
else
|
||||
final_screen_line_starting_pos = pos
|
||||
local screen_line = Text.screen_line(line, line_cache, i)
|
||||
--? print('text.draw:', screen_line, 'at', line_index,pos, 'after', x,y)
|
||||
local frag_len = utf8.len(screen_line)
|
||||
|
@ -84,7 +82,7 @@ function Text.draw(State, line_index, y, startpos, fg, hide_cursor)
|
|||
end
|
||||
end
|
||||
end
|
||||
return y, final_screen_line_starting_pos
|
||||
return y
|
||||
end
|
||||
|
||||
function Text.screen_line(line, line_cache, i)
|
||||
|
@ -163,7 +161,7 @@ function Text.text_input(State, t)
|
|||
end
|
||||
end
|
||||
local before = snapshot(State, State.cursor1.line)
|
||||
--? print(State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print(State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos)
|
||||
Text.insert_at_cursor(State, t)
|
||||
if State.cursor_y > App.screen.height - State.line_height then
|
||||
Text.populate_screen_line_starting_pos(State, State.cursor1.line)
|
||||
|
@ -195,12 +193,12 @@ function Text.keychord_press(State, chord, readonly)
|
|||
record_undo_event(State, {before=before, after=snapshot(State, before_line, State.cursor1.line)})
|
||||
elseif chord == 'tab' then
|
||||
local before = snapshot(State, State.cursor1.line)
|
||||
--? print(State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print(State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos)
|
||||
Text.insert_at_cursor(State, '\t')
|
||||
if State.cursor_y > App.screen.height - State.line_height then
|
||||
Text.populate_screen_line_starting_pos(State, State.cursor1.line)
|
||||
Text.snap_cursor_to_bottom_of_screen(State, State.left, State.right)
|
||||
--? print('=>', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print('=>', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos)
|
||||
end
|
||||
record_undo_event(State, {before=before, after=snapshot(State, State.cursor1.line)})
|
||||
elseif chord == 'backspace' then
|
||||
|
@ -370,45 +368,64 @@ function Text.insert_return(State)
|
|||
end
|
||||
|
||||
function Text.pageup(State)
|
||||
--? print('pageup')
|
||||
-- duplicate some logic from love.draw
|
||||
local top2 = Text.to2(State, State.screen_top1)
|
||||
--? print(App.screen.height)
|
||||
local y = App.screen.height - State.line_height
|
||||
while y >= State.top do
|
||||
--? print(y, top2.line, top2.screen_line, top2.screen_pos)
|
||||
if State.screen_top1.line == 1 and State.screen_top1.pos == 1 then break end
|
||||
y = y - State.line_height
|
||||
top2 = Text.previous_screen_line(State, top2)
|
||||
end
|
||||
State.screen_top1 = Text.to1(State, top2)
|
||||
State.screen_top1 = Text.previous_screen_top1(State)
|
||||
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
|
||||
Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State)
|
||||
--? print(State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos)
|
||||
--? print('pageup end')
|
||||
Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks
|
||||
end
|
||||
|
||||
-- return the top y coordinate of a given line_index,
|
||||
-- or nil if no part of it is on screen
|
||||
function Text.starty(State, line_index)
|
||||
-- duplicate some logic from love.draw
|
||||
-- does not modify State (except to populate line_cache)
|
||||
if line_index < State.screen_top1.line then return end
|
||||
local loc2 = Text.to2(State, State.screen_top1)
|
||||
local y = State.top
|
||||
while true do
|
||||
if loc2.line == line_index then return y end
|
||||
y = y + State.line_height
|
||||
if y + State.line_height > App.screen.height then break end
|
||||
local next_loc2 = Text.next_screen_line(State, loc2)
|
||||
if Text.eq2(next_loc2, loc2) then break end -- end of file
|
||||
loc2 = next_loc2
|
||||
end
|
||||
end
|
||||
|
||||
function Text.previous_screen_top1(State)
|
||||
-- duplicate some logic from love.draw
|
||||
-- does not modify State (except to populate line_cache)
|
||||
local loc2 = Text.to2(State, State.screen_top1)
|
||||
local y = App.screen.height - State.line_height
|
||||
while y >= State.top do
|
||||
if loc2.line == 1 and loc2.screen_line == 1 and loc2.screen_pos == 1 then break end
|
||||
y = y - State.line_height
|
||||
loc2 = Text.previous_screen_line(State, loc2)
|
||||
end
|
||||
return Text.to1(State, loc2)
|
||||
end
|
||||
|
||||
function Text.pagedown(State)
|
||||
--? print('pagedown')
|
||||
-- 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 bot2 = Text.to2(State, State.screen_bottom1)
|
||||
if bot2.screen_line > 1 then
|
||||
bot2.screen_line = math.max(bot2.screen_line-10, 1)
|
||||
end
|
||||
local new_top1 = Text.to1(State, bot2)
|
||||
if Text.lt1(State.screen_top1, new_top1) then
|
||||
State.screen_top1 = new_top1
|
||||
else
|
||||
State.screen_top1 = {line=State.screen_bottom1.line, pos=State.screen_bottom1.pos}
|
||||
end
|
||||
--? print('setting top to', State.screen_top1.line, State.screen_top1.pos)
|
||||
State.screen_top1 = Text.screen_bottom1(State)
|
||||
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
|
||||
Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State)
|
||||
--? print('top now', State.screen_top1.line)
|
||||
Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks
|
||||
--? print('pagedown end')
|
||||
end
|
||||
|
||||
-- return the location of the start of the bottom-most line on screen
|
||||
function Text.screen_bottom1(State)
|
||||
-- duplicate some logic from love.draw
|
||||
-- does not modify State (except to populate line_cache)
|
||||
local loc2 = Text.to2(State, State.screen_top1)
|
||||
local y = State.top
|
||||
while true do
|
||||
y = y + State.line_height
|
||||
if y + State.line_height > App.screen.height then break end
|
||||
local next_loc2 = Text.next_screen_line(State, loc2)
|
||||
if Text.eq2(next_loc2, loc2) then break end
|
||||
loc2 = next_loc2
|
||||
end
|
||||
return Text.to1(State, loc2)
|
||||
end
|
||||
|
||||
function Text.up(State)
|
||||
|
@ -450,7 +467,7 @@ function Text.up(State)
|
|||
end
|
||||
|
||||
function Text.down(State)
|
||||
--? print('down', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print('down', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos)
|
||||
assert(State.cursor1.pos, 'cursor has no pos')
|
||||
if Text.cursor_at_final_screen_line(State) then
|
||||
-- line is done, skip to next text line
|
||||
|
@ -461,7 +478,9 @@ function Text.down(State)
|
|||
State.cursor1.pos = Text.nearest_cursor_pos(State.font, State.lines[State.cursor1.line].data, State.cursor_x, State.left)
|
||||
--? print(State.cursor1.pos)
|
||||
end
|
||||
if State.cursor1.line > State.screen_bottom1.line then
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
--? print('down 2', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, screen_bottom1.line, screen_bottom1.pos)
|
||||
if State.cursor1.line > screen_bottom1.line then
|
||||
--? print('screen top before:', State.screen_top1.line, State.screen_top1.pos)
|
||||
--? print('scroll up preserving cursor')
|
||||
Text.snap_cursor_to_bottom_of_screen(State)
|
||||
|
@ -469,7 +488,8 @@ function Text.down(State)
|
|||
end
|
||||
else
|
||||
-- move down one screen line in current line
|
||||
local scroll_down = Text.le1(State.screen_bottom1, State.cursor1)
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
local scroll_down = Text.le1(screen_bottom1, State.cursor1)
|
||||
--? print('cursor is NOT at final screen line of its line')
|
||||
local screen_line_starting_pos, screen_line_index = Text.pos_at_start_of_screen_line(State, State.cursor1)
|
||||
Text.populate_screen_line_starting_pos(State, State.cursor1.line)
|
||||
|
@ -485,7 +505,7 @@ function Text.down(State)
|
|||
--? print('screen top after:', State.screen_top1.line, State.screen_top1.pos)
|
||||
end
|
||||
end
|
||||
--? print('=>', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print('=>', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos)
|
||||
end
|
||||
|
||||
function Text.start_of_line(State)
|
||||
|
@ -618,6 +638,14 @@ function Text.pos_at_end_of_screen_line(State, loc1)
|
|||
assert(false, ('invalid pos %d'):format(loc1.pos))
|
||||
end
|
||||
|
||||
function Text.final_text_loc_on_screen(State)
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
return {
|
||||
line=screen_bottom1.line,
|
||||
pos=Text.pos_at_end_of_screen_line(State, screen_bottom1),
|
||||
}
|
||||
end
|
||||
|
||||
function Text.cursor_at_final_screen_line(State)
|
||||
Text.populate_screen_line_starting_pos(State, State.cursor1.line)
|
||||
local screen_lines = State.line_cache[State.cursor1.line].screen_line_starting_pos
|
||||
|
@ -639,7 +667,7 @@ function Text.snap_cursor_to_bottom_of_screen(State)
|
|||
--? print('to2: =>', top2.line, top2.screen_line, top2.screen_pos)
|
||||
-- slide to start of screen line
|
||||
top2.screen_pos = 1 -- start of screen line
|
||||
--? print('snap', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print('snap', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos)
|
||||
--? print('cursor pos '..tostring(State.cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down')
|
||||
local y = App.screen.height - State.line_height
|
||||
-- duplicate some logic from love.draw
|
||||
|
@ -656,26 +684,28 @@ function Text.snap_cursor_to_bottom_of_screen(State)
|
|||
--? print('top2 finally:', top2.line, top2.screen_line, top2.screen_pos)
|
||||
State.screen_top1 = Text.to1(State, top2)
|
||||
--? print('top1 finally:', State.screen_top1.line, State.screen_top1.pos)
|
||||
--? print('snap =>', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
|
||||
--? print('snap =>', State.screen_top1.line, State.screen_top1.pos, State.cursor1.line, State.cursor1.pos)
|
||||
Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks
|
||||
end
|
||||
|
||||
function Text.in_line(State, line_index, x,y)
|
||||
local line = State.lines[line_index]
|
||||
local line_cache = State.line_cache[line_index]
|
||||
if line_cache.starty == nil then return false end -- outside current page
|
||||
if y < line_cache.starty then return false end
|
||||
local starty = Text.starty(State, line_index)
|
||||
if starty == nil then return false end -- outside current page
|
||||
if y < starty then return false end
|
||||
Text.populate_screen_line_starting_pos(State, line_index)
|
||||
return y < line_cache.starty + State.line_height*(#line_cache.screen_line_starting_pos - Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos) + 1)
|
||||
return y < starty + State.line_height*(#line_cache.screen_line_starting_pos - Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos) + 1)
|
||||
end
|
||||
|
||||
-- convert mx,my in pixels to schema-1 coordinates
|
||||
function Text.to_pos_on_line(State, line_index, mx, my)
|
||||
local line = State.lines[line_index]
|
||||
local line_cache = State.line_cache[line_index]
|
||||
assert(my >= line_cache.starty, 'failed to map y pixel to line')
|
||||
local starty = Text.starty(State, line_index)
|
||||
assert(my >= starty, 'failed to map y pixel to line')
|
||||
-- duplicate some logic from Text.draw
|
||||
local y = line_cache.starty
|
||||
local y = starty
|
||||
local start_screen_line_index = Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos)
|
||||
for screen_line_index = start_screen_line_index,#line_cache.screen_line_starting_pos do
|
||||
local screen_line_starting_pos = line_cache.screen_line_starting_pos[screen_line_index]
|
||||
|
@ -858,6 +888,10 @@ function Text.le1(a, b)
|
|||
return a.pos <= b.pos
|
||||
end
|
||||
|
||||
function Text.eq2(a, b)
|
||||
return a.line == b.line and a.screen_line == b.screen_line and a.screen_pos == b.screen_pos
|
||||
end
|
||||
|
||||
function Text.offset(s, pos1)
|
||||
if pos1 == 1 then return 1 end
|
||||
local result = utf8.offset(s, pos1)
|
||||
|
@ -879,6 +913,19 @@ function Text.previous_screen_line(State, loc2)
|
|||
end
|
||||
end
|
||||
|
||||
function Text.next_screen_line(State, loc2)
|
||||
Text.populate_screen_line_starting_pos(State, loc2.line)
|
||||
if loc2.screen_line >= #State.line_cache[loc2.line].screen_line_starting_pos then
|
||||
if loc2.line < #State.lines then
|
||||
return {line=loc2.line+1, screen_line=1, screen_pos=1}
|
||||
else
|
||||
return loc2
|
||||
end
|
||||
else
|
||||
return {line=loc2.line, screen_line=loc2.screen_line+1, screen_pos=1}
|
||||
end
|
||||
end
|
||||
|
||||
-- resize helper
|
||||
function Text.tweak_screen_top_and_cursor(State)
|
||||
--? print('a', State.selection1.line)
|
||||
|
@ -903,16 +950,12 @@ function Text.tweak_screen_top_and_cursor(State)
|
|||
end
|
||||
end
|
||||
-- make sure cursor is on screen
|
||||
local screen_bottom1 = Text.screen_bottom1(State)
|
||||
if Text.lt1(State.cursor1, State.screen_top1) then
|
||||
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
|
||||
elseif State.cursor1.line >= State.screen_bottom1.line then
|
||||
--? print('too low')
|
||||
elseif State.cursor1.line >= screen_bottom1.line then
|
||||
if Text.cursor_out_of_screen(State) then
|
||||
--? print('tweak')
|
||||
State.cursor1 = {
|
||||
line=State.screen_bottom1.line,
|
||||
pos=Text.to_pos_on_line(State, State.screen_bottom1.line, State.right-5, App.screen.height-5),
|
||||
}
|
||||
State.cursor1 = Text.final_text_loc_on_screen(State)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -921,11 +964,6 @@ end
|
|||
function Text.cursor_out_of_screen(State)
|
||||
edit.draw(State, --[[should be drawn over]] Cursor_color)
|
||||
return State.cursor_y == nil
|
||||
-- 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_screen_line(State, State.cursor1)
|
||||
--? local botline1 = {line=State.cursor1.line, pos=botpos}
|
||||
--? return Text.lt1(State.screen_bottom1, botline1)
|
||||
end
|
||||
|
||||
function Text.redraw_all(State)
|
||||
|
|
158
text_tests.lua
158
text_tests.lua
|
@ -49,7 +49,6 @@ function test_press_ctrl()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.run_after_keychord(Editor_state, 'C-m', 'm')
|
||||
end
|
||||
|
||||
|
@ -229,9 +228,8 @@ function test_click_moves_cursor()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.starty for each line Editor_state.line_cache
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.startpos for each line
|
||||
edit.run_after_mouse_release(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
check_eq(Editor_state.cursor1.line, 1, 'cursor:line')
|
||||
check_eq(Editor_state.cursor1.pos, 2, 'cursor:pos')
|
||||
|
@ -248,7 +246,6 @@ function test_click_to_left_of_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=3}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click to the left of the line
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -268,7 +265,6 @@ function test_click_takes_margins_into_account()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click on the other line
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -287,7 +283,6 @@ function test_click_on_empty_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click on the empty line
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -306,7 +301,6 @@ function test_click_below_all_lines()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click below first line
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -324,7 +318,6 @@ function test_draw_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'screen:1')
|
||||
|
@ -341,7 +334,6 @@ function test_draw_wrapping_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'screen:1')
|
||||
|
@ -358,7 +350,6 @@ function test_draw_word_wrapping_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc ', 'screen:1')
|
||||
|
@ -376,7 +367,6 @@ function test_click_on_wrapping_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=20}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- click on the other line
|
||||
edit.draw(Editor_state, Text_color)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
|
@ -395,7 +385,6 @@ function test_click_on_wrapping_line_takes_margins_into_account()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=20}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- click on the other line
|
||||
edit.draw(Editor_state, Text_color)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
|
@ -413,7 +402,6 @@ function test_draw_text_wrapping_within_word()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abcd ', 'screen:1')
|
||||
|
@ -431,7 +419,6 @@ function test_draw_wrapping_text_containing_non_ascii()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'mad', 'screen:1')
|
||||
|
@ -450,7 +437,6 @@ function test_click_past_end_of_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'madam ', 'baseline/screen:1')
|
||||
|
@ -473,7 +459,6 @@ function test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=8}
|
||||
Editor_state.screen_top1 = {line=1, pos=7}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, "I'm ad", 'baseline/screen:2')
|
||||
|
@ -494,7 +479,6 @@ function test_click_past_end_of_wrapping_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'madam ', 'baseline/screen:1')
|
||||
|
@ -518,7 +502,6 @@ function test_click_past_end_of_wrapping_line_containing_non_ascii()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'madam ', 'baseline/screen:1')
|
||||
|
@ -543,7 +526,6 @@ function test_click_past_end_of_word_wrapping_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'the quick brown fox ', 'baseline/screen:1')
|
||||
|
@ -562,7 +544,6 @@ function test_select_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- select a letter
|
||||
App.fake_key_press('lshift')
|
||||
|
@ -585,7 +566,6 @@ function test_cursor_movement_without_shift_resets_selection()
|
|||
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(Editor_state, Text_color)
|
||||
-- press an arrow key without shift
|
||||
edit.run_after_keychord(Editor_state, 'right', 'right')
|
||||
|
@ -603,7 +583,6 @@ function test_edit_deletes_selection()
|
|||
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(Editor_state, Text_color)
|
||||
-- press a key
|
||||
edit.run_after_text_input(Editor_state, 'x')
|
||||
|
@ -620,7 +599,6 @@ function test_edit_with_shift_key_deletes_selection()
|
|||
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(Editor_state, Text_color)
|
||||
-- mimic precise keypresses for a capital letter
|
||||
App.fake_key_press('lshift')
|
||||
|
@ -642,7 +620,6 @@ function test_copy_does_not_reset_selection()
|
|||
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(Editor_state, Text_color)
|
||||
-- copy selection
|
||||
edit.run_after_keychord(Editor_state, 'C-c', 'c')
|
||||
|
@ -660,7 +637,6 @@ function test_cut()
|
|||
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(Editor_state, Text_color)
|
||||
-- press a key
|
||||
edit.run_after_keychord(Editor_state, 'C-x', 'x')
|
||||
|
@ -678,7 +654,6 @@ function test_paste_replaces_selection()
|
|||
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(Editor_state, Text_color)
|
||||
-- set clipboard
|
||||
App.clipboard = 'xyz'
|
||||
|
@ -697,7 +672,6 @@ function test_deleting_selection_may_scroll()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=2}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'def', 'baseline/screen:1')
|
||||
|
@ -721,7 +695,6 @@ function test_edit_wrapping_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=4}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
edit.run_after_text_input(Editor_state, 'g')
|
||||
local y = Editor_state.top
|
||||
|
@ -740,7 +713,6 @@ function test_insert_newline()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=2}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -769,7 +741,6 @@ function test_insert_newline_at_start_of_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
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
|
||||
edit.run_after_keychord(Editor_state, 'return', 'return')
|
||||
check_eq(Editor_state.cursor1.line, 2, 'cursor:line')
|
||||
|
@ -786,7 +757,6 @@ function test_insert_from_clipboard()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=2}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -815,9 +785,8 @@ function test_select_text_using_mouse()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.starty for each line Editor_state.line_cache
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.startpos for each line
|
||||
-- press and hold on first location
|
||||
edit.run_after_mouse_press(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
-- drag and release somewhere else
|
||||
|
@ -835,9 +804,8 @@ function test_select_text_using_mouse_starting_above_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.starty for each line Editor_state.line_cache
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.startpos for each line
|
||||
-- press mouse above first line of text
|
||||
edit.run_after_mouse_press(Editor_state, Editor_state.left+8,5, 1)
|
||||
check(Editor_state.selection1.line ~= nil, 'selection:line-not-nil')
|
||||
|
@ -849,34 +817,32 @@ function test_select_text_using_mouse_starting_above_text_wrapping_line()
|
|||
-- first screen line starts in the middle of a line
|
||||
App.screen.init{width=50, height=60}
|
||||
Editor_state = edit.initialize_test_state()
|
||||
Editor_state.lines = load_array{'abc', 'defgh', 'xyz'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=5}
|
||||
Editor_state.screen_top1 = {line=2, pos=3}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- press mouse above first line of text
|
||||
edit.draw(Editor_state, Text_color)
|
||||
edit.run_after_mouse_press(Editor_state, Editor_state.left+8,5, 1)
|
||||
-- selection is at screen top
|
||||
check(Editor_state.selection1.line ~= nil, 'selection:line-not-nil')
|
||||
check_eq(Editor_state.selection1.line, 2, 'selection:line')
|
||||
check_eq(Editor_state.selection1.pos, 3, 'selection:pos')
|
||||
Editor_state.lines = load_array{'abc', 'defgh', 'xyz'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=5}
|
||||
Editor_state.screen_top1 = {line=2, pos=3}
|
||||
-- press mouse above first line of text
|
||||
edit.draw(Editor_state, Text_color)
|
||||
edit.run_after_mouse_press(Editor_state, Editor_state.left+8,5, 1)
|
||||
-- selection is at screen top
|
||||
check(Editor_state.selection1.line ~= nil, 'selection:line-not-nil')
|
||||
check_eq(Editor_state.selection1.line, 2, 'selection:line')
|
||||
check_eq(Editor_state.selection1.pos, 3, 'selection:pos')
|
||||
end
|
||||
|
||||
function test_select_text_using_mouse_starting_below_text()
|
||||
-- I'd like to test what happens when a mouse click is below some page of
|
||||
-- text, potentially even in the middle of a line.
|
||||
-- However, it's brittle to set up a text line boundary just right.
|
||||
-- So I'm going to just check things below the bottom of the final line of
|
||||
-- text when it's in the middle of the screen.
|
||||
-- final screen line ends in the middle of screen
|
||||
App.screen.init{width=50, height=60}
|
||||
Editor_state = edit.initialize_test_state()
|
||||
Editor_state.lines = load_array{'abcde'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- I'd like to test what happens when a mouse click is below some page of
|
||||
-- text, potentially even in the middle of a line.
|
||||
-- However, it's brittle to set up a text line boundary just right.
|
||||
-- So I'm going to just check things below the bottom of the final line of
|
||||
-- text when it's in the middle of the screen.
|
||||
-- final screen line ends in the middle of screen
|
||||
App.screen.init{width=50, height=60}
|
||||
Editor_state = edit.initialize_test_state()
|
||||
Editor_state.lines = load_array{'abcde'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'ab', 'baseline:screen:1')
|
||||
|
@ -897,9 +863,8 @@ function test_select_text_using_mouse_and_shift()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.starty for each line Editor_state.line_cache
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.startpos for each line
|
||||
-- click on first location
|
||||
edit.run_after_mouse_press(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
edit.run_after_mouse_release(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
|
@ -922,9 +887,8 @@ function test_select_text_repeatedly_using_mouse_and_shift()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.starty for each line Editor_state.line_cache
|
||||
edit.draw(Editor_state, Text_color) -- populate line_cache.startpos for each line
|
||||
-- click on first location
|
||||
edit.run_after_mouse_press(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
edit.run_after_mouse_release(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
|
@ -952,7 +916,6 @@ function test_select_all_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- select all
|
||||
App.fake_key_press('lctrl')
|
||||
|
@ -974,7 +937,6 @@ function test_cut_without_selection()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=2}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- try to cut without selecting text
|
||||
|
@ -990,7 +952,6 @@ function test_pagedown()
|
|||
Text.redraw_all(Editor_state)
|
||||
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(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
|
@ -1007,36 +968,6 @@ function test_pagedown()
|
|||
App.screen.check(y, 'ghi', 'screen:2')
|
||||
end
|
||||
|
||||
function test_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}
|
||||
Editor_state = edit.initialize_test_state()
|
||||
Editor_state.lines = load_array{'abc', 'def ghi jkl', 'mno'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
y = y + Editor_state.line_height
|
||||
App.screen.check(y, 'def ', 'baseline/screen:2')
|
||||
y = y + Editor_state.line_height
|
||||
App.screen.check(y, 'ghi ', 'baseline/screen:3')
|
||||
-- after pagedown we start drawing from the bottom _line_ (multiple screen lines)
|
||||
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
|
||||
check_eq(Editor_state.screen_top1.line, 2, 'screen_top:line')
|
||||
check_eq(Editor_state.screen_top1.pos, 1, 'screen_top:pos')
|
||||
check_eq(Editor_state.cursor1.line, 2, 'cursor:line')
|
||||
check_eq(Editor_state.cursor1.pos, 1, 'cursor:pos')
|
||||
y = Editor_state.top
|
||||
App.screen.check(y, 'def ', 'screen:1')
|
||||
y = y + Editor_state.line_height
|
||||
App.screen.check(y, 'ghi ', 'screen:2')
|
||||
y = y + Editor_state.line_height
|
||||
App.screen.check(y, 'jkl', 'screen:3')
|
||||
end
|
||||
|
||||
function test_pagedown_can_start_from_middle_of_long_wrapping_line()
|
||||
-- draw a few lines starting from a very long wrapping line
|
||||
App.screen.init{width=Editor_state.left+30, height=60}
|
||||
|
@ -1045,7 +976,6 @@ function test_pagedown_can_start_from_middle_of_long_wrapping_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=2}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc ', 'baseline/screen:1')
|
||||
|
@ -1080,7 +1010,6 @@ function test_pagedown_never_moves_up()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=9}
|
||||
Editor_state.screen_top1 = {line=1, pos=9}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- pagedown makes no change
|
||||
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
|
||||
|
@ -1095,7 +1024,6 @@ function test_down_arrow_moves_cursor()
|
|||
Text.redraw_all(Editor_state)
|
||||
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(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
|
@ -1125,7 +1053,6 @@ function test_down_arrow_scrolls_down_by_one_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1153,7 +1080,6 @@ function test_down_arrow_scrolls_down_by_one_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1182,7 +1108,6 @@ function test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1210,7 +1135,6 @@ function test_pagedown_followed_by_down_arrow_does_not_scroll_screen_up()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1244,7 +1168,6 @@ function test_up_arrow_moves_cursor()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1273,7 +1196,6 @@ function test_up_arrow_scrolls_up_by_one_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'def', 'baseline/screen:1')
|
||||
|
@ -1301,7 +1223,6 @@ function test_up_arrow_scrolls_up_by_one_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=6}
|
||||
Editor_state.screen_top1 = {line=3, pos=5}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'jkl', 'baseline/screen:1')
|
||||
|
@ -1329,7 +1250,6 @@ function test_up_arrow_scrolls_up_to_final_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'ghi', 'baseline/screen:1')
|
||||
|
@ -1359,7 +1279,6 @@ function test_up_arrow_scrolls_up_to_empty_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1386,7 +1305,6 @@ function test_pageup()
|
|||
Text.redraw_all(Editor_state)
|
||||
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(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
|
@ -1411,7 +1329,6 @@ function test_pageup_scrolls_up_by_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'ghi', 'baseline/screen:1')
|
||||
|
@ -1440,7 +1357,6 @@ function test_pageup_scrolls_up_from_middle_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=5}
|
||||
Editor_state.screen_top1 = {line=2, pos=5}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'jkl', 'baseline/screen:2')
|
||||
|
@ -1467,7 +1383,6 @@ function test_enter_on_bottom_line_scrolls_down()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=2}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1496,7 +1411,6 @@ function test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=4, pos=2}
|
||||
Editor_state.screen_top1 = {line=4, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'jkl', 'baseline/screen:1')
|
||||
|
@ -1519,7 +1433,6 @@ function test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bot
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- after hitting the inserting_text key the screen does not scroll down
|
||||
edit.run_after_text_input(Editor_state, 'a')
|
||||
|
@ -1538,7 +1451,6 @@ function test_typing_on_bottom_line_scrolls_down()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=4}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc', 'baseline/screen:1')
|
||||
|
@ -1568,7 +1480,6 @@ function test_left_arrow_scrolls_up_in_wrapped_line()
|
|||
Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.screen_top1 = {line=3, pos=5}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- cursor is at top of screen
|
||||
Editor_state.cursor1 = {line=3, pos=5}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -1597,7 +1508,6 @@ function test_right_arrow_scrolls_down_in_wrapped_line()
|
|||
Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- cursor is at bottom right of screen
|
||||
Editor_state.cursor1 = {line=3, pos=5}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -1627,7 +1537,6 @@ function test_home_scrolls_up_in_wrapped_line()
|
|||
Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.screen_top1 = {line=3, pos=5}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- cursor is at top of screen
|
||||
Editor_state.cursor1 = {line=3, pos=5}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -1656,7 +1565,6 @@ function test_end_scrolls_down_in_wrapped_line()
|
|||
Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- cursor is at bottom right of screen
|
||||
Editor_state.cursor1 = {line=3, pos=5}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
|
@ -1687,7 +1595,6 @@ function test_position_cursor_on_recently_edited_wrapping_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=25}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'abc def ghi ', 'baseline1/screen:1')
|
||||
|
@ -1721,7 +1628,6 @@ function test_backspace_can_scroll_up()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=2, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'def', 'baseline/screen:1')
|
||||
|
@ -1749,7 +1655,6 @@ function test_backspace_can_scroll_up_screen_line()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=3, pos=5}
|
||||
Editor_state.screen_top1 = {line=3, pos=5}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
local y = Editor_state.top
|
||||
App.screen.check(y, 'jkl', 'baseline/screen:1')
|
||||
|
@ -1884,7 +1789,6 @@ function test_undo_insert_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=4}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- insert a character
|
||||
edit.draw(Editor_state, Text_color)
|
||||
edit.run_after_text_input(Editor_state, 'g')
|
||||
|
@ -1919,7 +1823,6 @@ function test_undo_delete_text()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=5}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
-- delete a character
|
||||
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
|
||||
check_eq(Editor_state.cursor1.line, 2, 'baseline/cursor:line')
|
||||
|
@ -1958,7 +1861,6 @@ function test_undo_restores_selection()
|
|||
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(Editor_state, Text_color)
|
||||
-- delete selected text
|
||||
edit.run_after_text_input(Editor_state, 'x')
|
||||
|
@ -1979,7 +1881,6 @@ function test_search()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- search for a string
|
||||
edit.run_after_keychord(Editor_state, 'C-f', 'f')
|
||||
|
@ -2006,7 +1907,6 @@ function test_search_upwards()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- search for a string
|
||||
edit.run_after_keychord(Editor_state, 'C-f', 'f')
|
||||
|
@ -2024,7 +1924,6 @@ function test_search_wrap()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- search for a string
|
||||
edit.run_after_keychord(Editor_state, 'C-f', 'f')
|
||||
|
@ -2042,7 +1941,6 @@ function test_search_wrap_upwards()
|
|||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
edit.draw(Editor_state, Text_color)
|
||||
-- search upwards for a string
|
||||
edit.run_after_keychord(Editor_state, 'C-f', 'f')
|
||||
|
|
Loading…
Reference in New Issue