avoid saving fragments in lines

[?]
Apr 2, 2023, 3:03 AM
I64IPGJXWRTGHHVAYJUBUIWFR4BY6NM5P7TLTV4JOD7K4BVYDECQC

Dependencies

  • [2] 4EGQRXDA bugfix: naming points
  • [3] S2QMLRXL stop creating a singleton table for every word
  • [4] V5SYDHPQ start thinking of compute_fragments as a detail
  • [5] LWPRYDLW set color for each fragment
  • [6] H4R5BHVY no more Text allocations
  • [7] FBVUNLS4 clean up some debug prints
  • [8] 3TFEAQSW start using some globals
  • [9] PR4KIAZD first stab at equally hacky cursor down support
  • [10] FZBXBUFF bugfix: search
  • [11] X3F7ECSL add state arg to some functions
  • [12] XUGDTYW2 stop confusingly reading a global
  • [13] TXHMMX25 move caching behavior inside compute_fragments
  • [14] 6WDBV52Z move a var closer to its use
  • [15] HALS7E5U more clearly skip prints before screen top
  • [16] JY4VK7L2 rename
  • [17] ISOFHXB2 App.width can no longer take a Text
  • [18] PLKNHYZ4 extract a function
  • [19] ESETRNLB bugfix: printing the first part of a line at the bottom made it seem non-wrapping
  • [20] LF7BWEG4 group all editor globals
  • [21] BULPIBEG beginnings of a module for the text editor
  • [22] XNFTJHC4 split keyboard handling between Text and Drawing
  • [23] A2NV3WVO scrolling with up arrow
  • [24] CAMMFOJ4 make cursor more obvious
  • [25] ZDAJXYIX remove some unnecessary work
  • [26] KWOJ6XHE cut/copy selected text to clipboard
  • [27] PFT5Y2ZY move
  • [28] MYC7XR5Q bugfix: lines that aren't drawn from the start
  • [29] AYE2VEGJ extract a couple of methods
  • [30] LXTTOB33 extract a couple of files
  • [31] Z4XRNDTR find text
  • [32] S2MISTTM add state arg to a few functions
  • [33] 73OCE2MC after much struggle, a brute-force undo
  • [34] LAW2O3NW extract variable Margin_left
  • [35] HOSPP2AN crisp font rendering
  • [36] QYIFOHW3 first test!
  • [37] CBPV5SSI stop handling nil screen_line_starting_pos everywhere
  • [38] 2H67P75X switch arg for a function
  • [39] KJKKASHZ reduce ambitions a bit: page up/down need not start screen from the middle of a line
  • [40] YTSPVDZH first successful pagedown test, first bug found by test
  • [41] AVTNUQYR basic test-enabled framework
  • [42] OIB2QPRC start remembering where the cursor is drawn in px
  • [43] R53OF3ON one bug I've repeatedly run into while testing with Moby Dick
  • [44] J2SVGR2E experiment: blinking cursor
  • [45] JJMTEZPQ obsolete comment
  • [46] DHI6IJCN selecting text and deleting selections
  • [47] 5DOC2CBM extract a function
  • [48] WLHI7KD3 new globals: draw partial screen line up top
  • [49] B3IWYWSR delete another arg that can be deduced
  • [50] RTDYYP4H bugfix: text past cursor was rendered red on wrapped lines
  • [51] H2DPLWMV snapshot: wrapping long lines at word boundaries
  • [52] HIKLULFQ extract a function
  • [53] 5DOTWNVM right margin
  • [54] NDHQN23G done passing left/right margins everywhere
  • [55] UHB4GARJ left/right margin -> left/right coordinates
  • [56] 3ZSUBI57 drop some redundant args from Text.draw
  • [57] MDXGMZU2 disable all debug prints
  • [58] PESSMQBJ no, make sure to compute line width after screen dimensions
  • [59] EHX6Q4OJ make the cursor a little thicker
  • [60] LSYLEVBD drop some redundant args when clearing the cache
  • [61] ODLKHO7B switch to line index in a function
  • [62] KURLAXXI clean up some prints
  • [63] 3OC7AIC7 exclude left margin from my word-split heuristic
  • [64] TGHAJBES use line cache for drawings as well
  • [65] Y4SPXCM3 bugfix: pagedown was sometimes bouncing up
  • [66] UV4EWOLY add args to some functions
  • [67] CVSRHMJ2 experiment: slightly adaptive scrolling
  • [68] XVR2O5PI change text cursor shape
  • [69] BW2IUB3K keep all text cache writes inside text.lua
  • [70] HVJKBW5U drop some unnecessary calls
  • [71] OYVFFWBK move
  • [72] OI4FPFIN support drawings in the source editor
  • [73] ORRSP7FV deduce test names on failures
  • [74] LERERVPH keep one screen line of overlap on pagedown
  • [75] 6K5PFF6X helper: trimming whitespace from strings
  • [76] BYG5CEMV support for naming points
  • [77] MXA3RZYK deduce left/right from state where possible
  • [78] 4KC7I3E2 make colors easier to edit
  • [79] MGT5FTJ3 first stab at supporting wrapping in cursor up
  • [80] Y36LOGR5 bugfix: show cursor when past end of line
  • [81] EWMPYCDO bugfix
  • [82] ULKLJBN6 couple of renames
  • [83] ILOA5BYF separate data structure for each line's cache data
  • [84] IMEJA43L snapshot
  • [85] 2RXZ3PGO beginning of a new approach to scroll+wrap
  • [86] HGC5RGJP switch to line index in a function
  • [87] 537TQ2QN some more logging
  • [88] VVAGDVCU experiment: line cursor
  • [89] CVGE3SIG I feel confident now that page-down is working.
  • [90] BZRRUIFQ correct location of the line width slider
  • [91] UPCIYZEU drop an unnecessary level of indent
  • [92] M6TH7VSZ rip out notion of Line_width
  • [93] JLU2RMC4 allow Text.nearest_pos_less_than to return 0
  • [94] GK47BBCY start passing left/right margins everywhere
  • [95] OYXDYPGS get rid of debug variables
  • [*] R5OKMVVC fix a regression in line wrapping
  • [*] 3QNOKBFM beginnings of a test harness

Change contents

  • replacement in text_tests.lua at line 1010
    [5.26911][5.8877:8919]()
    App.screen.check(y, 'mno ', 'screen:3')
    [5.26911]
    [5.10090]
    App.screen.check(y, 'mn', 'screen:3')
  • edit in text.lua at line 7
    [5.214]
    [5.42]
    --? print('text.draw', line_index, y)
  • replacement in text.lua at line 13
    [5.1768][5.53:76](),[5.92][5.1802:1818](),[5.106][5.1802:1818](),[5.1013][5.1802:1818](),[5.1802][5.1802:1818](),[5.1818][5.3:47]()
    local x = State.left
    local pos = 1
    local screen_line_starting_pos = startpos
    [5.1768]
    [4.3]
    local final_screen_line_starting_pos = startpos -- track value to return
  • replacement in text.lua at line 15
    [5.47][5.3860:3906](),[4.63][5.3860:3906](),[5.93][5.3860:3906](),[5.19][5.3860:3906](),[5.3906][5.3:29](),[5.29][3.3:103]()
    for _, f in ipairs(line_cache.fragments) do
    App.color(Text_color)
    local frag_len = utf8.len(f)
    --? print('text.draw:', f, 'at', line_index,pos, 'after', x,y)
    [4.63]
    [5.48]
    assert(#line_cache.screen_line_starting_pos >= 1)
    for i=1,#line_cache.screen_line_starting_pos do
    local pos = line_cache.screen_line_starting_pos[i]
  • edit in text.lua at line 22
    [5.138]
    [5.3]
    final_screen_line_starting_pos = pos
    local 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)
  • edit in text.lua at line 27
    [5.28][3.136:174](),[5.46][5.138:234](),[5.74][5.138:234](),[3.174][5.138:234](),[5.138][5.138:234](),[5.234][5.405:497](),[5.405][5.405:497](),[5.499][5.499:556](),[5.104][5.255:294](),[5.108][5.255:294](),[5.272][5.255:294](),[5.556][5.255:294](),[5.255][5.255:294](),[5.648][5.235:258](),[5.110][5.119:129](),[5.127][5.119:129](),[5.258][5.119:129](),[5.266][5.119:129](),[5.119][5.119:129]()
    local frag_width = App.width(f)
    if x + frag_width > State.right then
    assert(x > State.left) -- no overfull lines
    y = y + State.line_height
    if y + State.line_height > App.screen.height then
    return y, screen_line_starting_pos
    end
    screen_line_starting_pos = pos
    x = State.left
    end
  • replacement in text.lua at line 29
    [5.405][5.97:155](),[5.97][5.97:155]()
    Text.draw_highlight(State, line, x,y, pos, lo,hi)
    [5.405]
    [5.1056]
    Text.draw_highlight(State, line, State.left,y, pos, lo,hi)
  • replacement in text.lua at line 31
    [5.1066][3.175:206]()
    App.screen.print(f, x,y)
    [5.1066]
    [5.259]
    App.color(Text_color)
    App.screen.print(f, State.left,y)
  • replacement in text.lua at line 35
    [5.342][5.342:422]()
    if pos <= State.cursor1.pos and pos + frag_len > State.cursor1.pos then
    [5.342]
    [5.422]
    if pos <= State.cursor1.pos and pos + frag_len >= State.cursor1.pos then
  • replacement in text.lua at line 38
    [5.608][5.1429:1566]()
    local lo_px = Text.draw_highlight(State, line, x,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term))
    [5.608]
    [5.738]
    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 text.lua at line 40
    [5.774][5.774:838]()
    love.graphics.print(State.search_term, x+lo_px,y)
    [5.774]
    [5.838]
    love.graphics.print(State.search_term, State.left+lo_px,y)
  • replacement in text.lua at line 43
    [5.869][3.207:284]()
    Text.draw_cursor(State, x+Text.x(f, State.cursor1.pos-pos+1), y)
    [5.869]
    [5.530]
    Text.draw_cursor(State, State.left+Text.x(f, State.cursor1.pos-pos+1), y)
  • replacement in text.lua at line 47
    [5.2604][5.950:975]()
    x = x + frag_width
    [5.2604]
    [5.2604]
    y = y + State.line_height
    if y >= App.screen.height then
    break
    end
  • edit in text.lua at line 52
    [5.2635][5.2635:2660]()
    pos = pos + frag_len
  • replacement in text.lua at line 53
    [5.37][5.1242:1387](),[5.1387][5.755:763](),[5.755][5.755:763]()
    if State.search_term == nil then
    if line_index == State.cursor1.line and State.cursor1.pos == pos then
    Text.draw_cursor(State, x, y)
    end
    [5.37]
    [5.138]
    return y - State.line_height, final_screen_line_starting_pos
    end
    function 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 then
    return line.data:sub(offset)
  • replacement in text.lua at line 62
    [5.310][5.295:332]()
    return y, screen_line_starting_pos
    [5.144]
    [5.37]
    local endpos = line_cache.screen_line_starting_pos[i+1]-1
    local end_offset = Text.offset(line.data, endpos)
    return line.data:sub(offset, end_offset)
  • edit in text.lua at line 85
    [5.268][5.268:309](),[5.309][5.48:92]()
    -- duplicate some logic from Text.draw
    Text.compute_fragments(State, line_index)
  • replacement in text.lua at line 86
    [5.443][5.443:466]()
    local x = State.left
    [5.443]
    [5.466]
    local x = 0
  • edit in text.lua at line 88
    [5.482][5.482:528](),[5.571][5.571:594](),[5.594][3.285:321](),[5.88][5.638:792](),[3.321][5.638:792](),[5.638][5.638:792](),[5.792][3.322:350](),[5.304][5.853:859](),[3.350][5.853:859](),[5.853][5.853:859](),[5.51][5.256:260](),[5.687][5.256:260](),[5.859][5.256:260](),[5.1551][5.256:260](),[5.55726][5.256:260](),[5.256][5.256:260](),[5.260][5.41:42](),[5.2796][5.41:42](),[5.41][5.41:42](),[5.42][5.50:101](),[5.155][5.147:186](),[5.147][5.147:186](),[5.186][5.93:134](),[5.134][5.54:104](),[5.186][5.54:104](),[5.104][5.135:183](),[5.104][5.3962:3990](),[5.183][5.3962:3990](),[5.3962][5.3962:3990](),[5.3990][5.187:210](),[5.73][5.187:210]()
    for _, f in ipairs(line_cache.fragments) do
    -- render fragment
    local frag_width = App.width(f)
    if x + frag_width > State.right then
    x = State.left
    table.insert(line_cache.screen_line_starting_pos, pos)
    end
    x = x + frag_width
    pos = pos + utf8.len(f)
    end
    end
    function Text.compute_fragments(State, line_index)
    local line = State.lines[line_index]
    if line.mode ~= 'text' then return end
    local line_cache = State.line_cache[line_index]
    if line_cache.fragments then
    return
    end
    line_cache.fragments = {}
    local x = State.left
  • replacement in text.lua at line 91
    [5.120][5.3:45](),[5.288][5.3:45](),[5.169][5.189:251]()
    while x + frag_width > State.right do
    if (x-State.left) < 0.8 * (State.right-State.left) then
    [5.128]
    [5.234]
    --? 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
  • replacement in text.lua at line 97
    [5.331][5.331:402](),[5.434][5.213:299]()
    local bpos = Text.nearest_pos_less_than(frag, State.right - x)
    if bpos == 0 then break end -- avoid infinite loop when window is too narrow
    [5.331]
    [5.509]
    local bpos = Text.nearest_pos_less_than(frag, State.width - x)
    -- everything works if bpos == 0, but is a little inefficient
    pos = pos + bpos
  • edit in text.lua at line 101
    [5.676][5.676:729](),[5.800][5.129:174](),[5.935][5.935:982](),[5.982][3.351:401]()
    local 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)
  • edit in text.lua at line 102
    [5.1097]
    [5.175]
    --? if bpos > 0 then
    --? print('after chop:', frag)
    --? end
  • replacement in text.lua at line 107
    [5.1377][5.1203:1237](),[5.1237][5.1377:1407](),[5.1377][5.1377:1407](),[5.1407][3.402:449]()
    x = State.left -- new line
    end
    if #frag > 0 then
    table.insert(line_cache.fragments, frag)
    [5.1377]
    [5.1549]
    --? print('screen line:', pos)
    table.insert(line_cache.screen_line_starting_pos, pos)
    x = 0 -- new screen line
  • edit in text.lua at line 112
    [97.1627]
    [5.1557]
    pos = pos + utf8.len(frag)
  • edit in text.lua at line 957
    [5.462][5.1668:1715]()
    State.line_cache[line_index].fragments = nil
  • replacement in app.lua at line 376
    [5.60904][2.1995:2057]()
    local stack_trace = debug.traceback('', --[[stack frame]]4)
    [5.60904]
    [5.60966]
    local stack_trace = debug.traceback('', --[[stack frame]]5)