switch source side to new screen-line-based render
[?]
Apr 3, 2023, 3:33 PM
GZ5WULJVEZJJQPQPSQZE7CEPIYPJ2BJDYUJBMZRA5HLOO7TE3DOQCDependencies
- [2]
G54H3YG2get rid of all bifold text - [3]
S2QMLRXLstop creating a singleton table for every word - [4]
V5SYDHPQstart thinking of compute_fragments as a detail - [5]
H6QZ7GRRmore precise name - [6]
FBVUNLS4clean up some debug prints - [7]
ORRSP7FVdeduce test names on failures - [8]
H4R5BHVYno more Text allocations - [9]
KMSL74GAsupport selections in the source editor - [10]
OI4FPFINsupport drawings in the source editor - [11]
QZ2SXLHFsome debug prints - [12]
4KC7I3E2make colors easier to edit - [13]
2WGHUWE6self-documenting 0 Test_right_margin - [14]
2CK5QI7Wmake love event names consistent - [15]
KKMFQDR4editing source code from within the app - [16]
X3F7ECSLadd state arg to some functions - [17]
2Y7YH7UPinfrastructure for caching LÖVE text objects - [18]
EKJUHVHBhoist out some common settings - [19]
B4JEWKWIhide editor cursor while in file navigator - [20]
ISOFHXB2App.width can no longer take a Text - [21]
UN7GKYV5support hyperlinks in the source editor - [22]
4VQGE7RAnew test - [23]
LF7BWEG4group all editor globals - [24]
R3KXFRZNget rid of to_text - [25]
J2SVGR2Eexperiment: blinking cursor - [*]
BULPIBEGbeginnings of a module for the text editor - [*]
VHQCNMARseveral more modules - [*]
2L5MEZV3experiment: new edit namespace
Change contents
- edit in text.lua at line 72
App.color(Text_color) - replacement in source_text_tests.lua at line 980
App.screen.check(y, 'mno ', 'screen:3')App.screen.check(y, 'mn', 'screen:3') - replacement in source_text.lua at line 5
-- return the final y, and position of start of final screen line drawn-- return y for the next line, and position of start of final screen line drawn - replacement in source_text.lua at line 12
local x = State.leftlocal pos = 1local screen_line_starting_pos = startposlocal final_screen_line_starting_pos = startpos -- track value to return - replacement in source_text.lua at line 14
local pos = 1Text.populate_link_offsets(State, line_index) - replacement in source_text.lua at line 16
for _, f in ipairs(line_cache.fragments) doApp.color(Text_color)select_color(f)local frag_len = utf8.len(f)--? print('text.draw:', f, 'at', line_index,pos, 'after', x,y)assert(#line_cache.screen_line_starting_pos >= 1)for i=1,#line_cache.screen_line_starting_pos dolocal pos = line_cache.screen_line_starting_pos[i] - replacement in source_text.lua at line 23[5.87768]→[5.87768:87793](∅→∅),[5.87793]→[3.607:645](∅→∅),[5.353]→[5.87839:88027](∅→∅),[3.645]→[5.87839:88027](∅→∅),[5.87839]→[5.87839:88027](∅→∅),[5.88027]→[2.205:250](∅→∅)
-- render fragmentlocal frag_width = App.width(f)if x + frag_width > State.right thenassert(x > State.left) -- no overfull linesy = y + State.line_heightif y + State.line_height > App.screen.height thenreturn y, screen_line_starting_posfinal_screen_line_starting_pos = poslocal f = Text.screen_line(line, line_cache, i)--? print('text.draw:', f, 'at', line_index,pos, 'after', x,y)local frag_len = utf8.len(f)-- render any link decorationsfor _,link_offsets in ipairs(line_cache.link_offsets) dolocal s,e,filename = unpack(link_offsets)local lo, hi = Text.clip_wikiword_with_screen_line(line, line_cache, i, s, e)if lo thenbutton(State, 'link', {x=State.left+lo, y=y, w=hi-lo, h=State.line_height, color={1,1,1},icon = icon.hyperlink_decoration,onpress1 = function()if file_exists(filename) thensource.switch_to_file(filename)endend,}) - edit in source_text.lua at line 41
screen_line_starting_pos = posx = State.left - edit in source_text.lua at line 42
-- render fragment - replacement in source_text.lua at line 45
Text.draw_highlight(State, line, x,y, pos, lo,hi)Text.draw_highlight(State, line, State.left,y, pos, lo,hi) - replacement in source_text.lua at line 47[5.88189]→[5.7:84](∅→∅),[5.84]→[3.646:731](∅→∅),[5.685]→[5.172:367](∅→∅),[3.731]→[5.172:367](∅→∅),[5.172]→[5.172:367](∅→∅),[5.367]→[5.7:125](∅→∅),[5.125]→[5.578:779](∅→∅),[5.578]→[5.578:779](∅→∅),[5.779]→[3.732:763](∅→∅)
-- Make [[WikiWords]] (single word, all in one screen line) clickable.local trimmed_word = rtrim(f) -- compute_fragments puts whitespace at the endif starts_with(trimmed_word, '[[') and ends_with(trimmed_word, ']]') thenlocal filename = trimmed_word:gsub('^..(.*)..$', '%1')if source.link_exists(State, filename) thenbutton(State, 'link', {x=x+App.width('[['), y=y, w=App.width(filename), h=State.line_height, color={1,1,1},icon = icon.hyperlink_decoration,onpress1 = function()source.switch_to_file(filename)end,})endendApp.screen.print(f, x,y)select_color(f)App.screen.print(f, State.left,y) - replacement in source_text.lua at line 50
if line_index == State.cursor1.line thenif pos <= State.cursor1.pos and pos + frag_len > State.cursor1.pos thenif not hide_cursor and line_index == State.cursor1.line thenif pos <= State.cursor1.pos and pos + frag_len >= State.cursor1.pos then - replacement in source_text.lua at line 54
local lo_px = Text.draw_highlight(State, line, x,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term))local lo_px = Text.draw_highlight(State, line, State.left,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term)) - replacement in source_text.lua at line 56
love.graphics.print(State.search_term, x+lo_px,y)love.graphics.print(State.search_term, State.left+lo_px,y) - replacement in source_text.lua at line 59[5.88889]→[3.764:841](∅→∅),[5.805]→[5.88969:89003](∅→∅),[3.841]→[5.88969:89003](∅→∅),[5.88969]→[5.88969:89003](∅→∅)
Text.draw_cursor(State, x+Text.x(f, State.cursor1.pos-pos+1), y)App.color(Text_color)Text.draw_cursor(State, State.left+Text.x(f, State.cursor1.pos-pos+1), y) - replacement in source_text.lua at line 63
x = x + frag_widthy = y + State.line_heightif y >= App.screen.height thenbreakend - edit in source_text.lua at line 68
pos = pos + frag_len - replacement in source_text.lua at line 69
if Focus == 'edit' and not hide_cursor and State.search_term == nil thenif line_index == State.cursor1.line and State.cursor1.pos == pos thenText.draw_cursor(State, x, y)endreturn y, final_screen_line_starting_posendfunction Text.screen_line(line, line_cache, i)local pos = line_cache.screen_line_starting_pos[i]local offset = Text.offset(line.data, pos)if i >= #line_cache.screen_line_starting_pos thenreturn line.data:sub(offset) - replacement in source_text.lua at line 78
return y, screen_line_starting_poslocal endpos = line_cache.screen_line_starting_pos[i+1]-1local end_offset = Text.offset(line.data, endpos)return line.data:sub(offset, end_offset) - edit in source_text.lua at line 100
-- duplicate some logic from Text.drawText.compute_fragments(State, line_index) - replacement in source_text.lua at line 101
local x = State.leftlocal x = 0 - replacement in source_text.lua at line 103[5.91766]→[5.91766:91812](∅→∅),[5.91855]→[5.91855:91878](∅→∅),[5.91878]→[3.842:878](∅→∅),[5.395]→[5.91922:91984](∅→∅),[3.878]→[5.91922:91984](∅→∅),[5.91922]→[5.91922:91984](∅→∅)
for _, f in ipairs(line_cache.fragments) do-- render fragmentlocal frag_width = App.width(f)if x + frag_width > State.right thenx = State.left-- try to wrap at word boundariesfor frag in line.data:gmatch('%S*%s*') dolocal frag_width = App.width(frag)--? print('-- frag:', frag, pos, x, frag_width, State.width)while x + frag_width > State.width do--? print('frag:', frag, pos, x, frag_width, State.width)if x < 0.8 * State.width then-- long word; chop it at some letter-- We're not going to reimplement TeX here.local bpos = Text.nearest_pos_less_than(frag, State.width - x)-- everything works if bpos == 0, but is a little inefficientpos = pos + bposlocal boffset = Text.offset(frag, bpos+1) -- byte _after_ bposfrag = string.sub(frag, boffset)--? if bpos > 0 then--? print('after chop:', frag)--? endfrag_width = App.width(frag)end--? print('screen line:', pos) - edit in source_text.lua at line 124
x = 0 -- new screen line - replacement in source_text.lua at line 127
pos = pos + utf8.len(f)pos = pos + utf8.len(frag) - replacement in source_text.lua at line 131
function Text.compute_fragments(State, line_index)function Text.populate_link_offsets(State, line_index) - replacement in source_text.lua at line 135
if line_cache.fragments thenif line_cache.link_offsets then - replacement in source_text.lua at line 138
line_cache.fragments = {}local x = State.leftline_cache.link_offsets = {}local pos = 1 - replacement in source_text.lua at line 141[5.92504]→[5.92504:92548](∅→∅),[5.92613]→[5.396:435](∅→∅),[5.92774]→[5.92774:92816](∅→∅),[5.92940]→[5.92940:93002](∅→∅),[5.93033]→[5.93033:93201](∅→∅),[5.93233]→[5.93233:93391](∅→∅),[5.93486]→[5.93486:93539](∅→∅),[5.93610]→[5.436:481](∅→∅),[5.93745]→[5.93745:93792](∅→∅),[5.93792]→[3.908:958](∅→∅),[5.897]→[5.93866:93907](∅→∅),[3.958]→[5.93866:93907](∅→∅),[5.93866]→[5.93866:93907](∅→∅),[5.93970]→[5.482:519](∅→∅),[5.519]→[5.94012:94086](∅→∅),[5.94012]→[5.94012:94086](∅→∅),[5.94086]→[3.959:1006](∅→∅)
for frag in line.data:gmatch('%S*%s*') dolocal frag_width = App.width(frag)while x + frag_width > State.right doif (x-State.left) < 0.8 * (State.right-State.left) then-- long word; chop it at some letter-- We're not going to reimplement TeX here.local bpos = Text.nearest_pos_less_than(frag, State.right - x)if bpos == 0 then break end -- avoid infinite loop when window is too narrowlocal boffset = Text.offset(frag, bpos+1) -- byte _after_ bposlocal frag1 = string.sub(frag, 1, boffset-1)local frag1_width = App.width(frag1)assert(x + frag1_width <= State.right)table.insert(line_cache.fragments, frag1)frag = string.sub(frag, boffset)frag_width = App.width(frag)endx = State.left -- new lineendif #frag > 0 thentable.insert(line_cache.fragments, frag)local s, e = 1, 0while s <= #line.data dos, e = line.data:find('%[%[%S+%]%]', s)if s == nil then break endlocal word = line.data:sub(s+2, e-2) -- strip out surrounding '[[..]]'--? print('wikiword:', s, e, word)table.insert(line_cache.link_offsets, {s, e, word})s = e + 1endend-- Intersect the filename between byte offsets s,e with the bounds of screen line i.-- Return the left/right pixel coordinates of of the intersection,-- or nil if it doesn't intersect with screen line i.function Text.clip_wikiword_with_screen_line(line, line_cache, i, s, e)local spos = line_cache.screen_line_starting_pos[i]local soff = Text.offset(line.data, spos)if e < soff thenreturnendlocal eoffif i < #line_cache.screen_line_starting_pos thenlocal epos = line_cache.screen_line_starting_pos[i+1]eoff = Text.offset(line.data, epos)if s > eoff thenreturn - replacement in source_text.lua at line 168
x = x + frag_widthendlocal loff = math.max(s, soff)local hoffif eoff thenhoff = math.min(e, eoff)elsehoff = e - edit in source_text.lua at line 176
--? print(s, e, soff, eoff, loff, hoff)return App.width(line.data:sub(1, loff-1)), App.width(line.data:sub(1, hoff)) - replacement in source_text.lua at line 1003
App.draw()edit.draw(State) - edit in source_text.lua at line 1012
function source.link_exists(State, filename)if State.link_cache == nil thenState.link_cache = {}endif State.link_cache[filename] == nil thenState.link_cache[filename] = file_exists(filename)endreturn State.link_cache[filename]end - edit in source_text.lua at line 1018
State.link_cache = {} - edit in source_text.lua at line 1021
State.line_cache[line_index].fragments = nil - edit in source_text.lua at line 1022
State.line_cache[line_index].link_offsets = nil - edit in source_edit.lua at line 187
y = y + State.line_height - edit in source_edit.lua at line 510
Text_cache = {} - edit in source.lua at line 53
-- a few text objects we can avoid recomputing unless the font changesText_cache = {} - edit in run.lua at line 9
-- a few text objects we can avoid recomputing unless the font changesText_cache = {} - replacement in log_browser.lua at line 120
y = Text.draw(State, line_index, y, --[[startpos]] 1)Text.draw(State, line_index, y, --[[startpos]] 1) - edit in icons.lua at line 13
-- hack: set the hyperlink color so that caller can draw the text of the-- hyperlink in the same color - edit in edit.lua at line 509
Text_cache = {}