Merge lines.love

[?]
Sep 5, 2022, 9:19 PM
VHUNJHXB4BQISKAXTMVB66C4QKF2NUZQRPRB37Z7OADC7PW5IMRAC

Dependencies

  • [2] 3PSFWAIL Merge lines.love
  • [3] UN7GKYV5 support hyperlinks in the source editor
  • [4] BJ5X5O4A let's prevent the text cursor from ever getting on a drawing
  • [5] XX7G2FFJ intermingle freehand line drawings with text
  • [6] T4FRZSYL delete an ancient, unused file
  • [7] 2CTN2IEF Merge lines.love
  • [8] 6LJZN727 handle chords
  • [9] BULPIBEG beginnings of a module for the text editor
  • [10] GUOQRUL7 Merge lines.love
  • [11] K2X6G75Z start writing some tests for drawings
  • [12] D2GCFTTT clean up repl functionality
  • [13] VXORMHME delete experimental REPL
  • [14] AVTNUQYR basic test-enabled framework
  • [15] TLOAPLBJ add a license
  • [16] 4KC7I3E2 make colors easier to edit
  • [17] OI4FPFIN support drawings in the source editor
  • [18] RSZD5A7G forgot to add json.lua
  • [19] 32V6ZHQB Merge lines.love
  • [20] 3QNOKBFM beginnings of a test harness
  • [21] 66X36NZN a little more prose describing manual_tests
  • [22] OTIBCAUJ love2d scaffold
  • [23] VHQCNMAR several more modules
  • [24] LXTTOB33 extract a couple of files
  • [25] KKMFQDR4 editing source code from within the app
  • [26] TVCPXAAU rename
  • [27] R5QXEHUI somebody stop me
  • [28] FS2ITYYH record a known issue
  • [29] BLWAYPKV extract a module
  • [30] MD3W5IRA new fork: rip out drawing support
  • [31] 2L5MEZV3 experiment: new edit namespace
  • [32] 73OCE2MC after much struggle, a brute-force undo
  • [33] OGUV4HSA remove some memory leaks from rendered fragments
  • [34] QS3YLNKZ Merge lines.love
  • [35] CE4LZV4T drop last couple of manual tests
  • [36] 4YDBYBA4 clean up memory leak experiments
  • [37] JOPVPUSA editing source code from within the app

Change contents

  • file deletion: icons.lua (----------)
    [4.2][2.25414:25447](),[2.25447][2.23747:23747]()
    icon = {}
    function icon.insert_drawing(button_params)
    local x,y = button_params.x, button_params.y
    App.color(Icon_color)
    love.graphics.rectangle('line', x,y, 12,12)
    love.graphics.line(4,y+6, 16,y+6)
    love.graphics.line(10,y, 10,y+12)
    end
    function icon.freehand(x, y)
    love.graphics.line(x+4,y+7,x+5,y+5)
    love.graphics.line(x+5,y+5,x+7,y+4)
    love.graphics.line(x+7,y+4,x+9,y+3)
    love.graphics.line(x+9,y+3,x+10,y+5)
    love.graphics.line(x+10,y+5,x+12,y+6)
    love.graphics.line(x+12,y+6,x+13,y+8)
    love.graphics.line(x+13,y+8,x+13,y+10)
    love.graphics.line(x+13,y+10,x+14,y+12)
    love.graphics.line(x+14,y+12,x+15,y+14)
    love.graphics.line(x+15,y+14,x+15,y+16)
    end
    function icon.line(x, y)
    love.graphics.line(x+4,y+2, x+16,y+18)
    end
    function icon.manhattan(x, y)
    love.graphics.line(x+4,y+20, x+4,y+2)
    love.graphics.line(x+4,y+2, x+10,y+2)
    love.graphics.line(x+10,y+2, x+10,y+10)
    love.graphics.line(x+10,y+10, x+18,y+10)
    end
    function icon.polygon(x, y)
    love.graphics.line(x+8,y+2, x+14,y+2)
    love.graphics.line(x+14,y+2, x+18,y+10)
    love.graphics.line(x+18,y+10, x+10,y+18)
    love.graphics.line(x+10,y+18, x+4,y+12)
    love.graphics.line(x+4,y+12, x+8,y+2)
    end
    function icon.rectangle(x, y)
    love.graphics.line(x+4,y+8, x+4,y+16)
    love.graphics.line(x+4,y+16, x+16,y+16)
    love.graphics.line(x+16,y+16, x+16,y+8)
    love.graphics.line(x+16,y+8, x+4,y+8)
    end
    function icon.square(x, y)
    love.graphics.line(x+6,y+6, x+6,y+16)
    love.graphics.line(x+6,y+16, x+16,y+16)
    love.graphics.line(x+16,y+16, x+16,y+6)
    love.graphics.line(x+16,y+6, x+6,y+6)
    end
    function icon.circle(x, y)
    love.graphics.circle('line', x+10,y+10, 8)
    end
  • file deletion: source_text.lua (----------)source_text.lua (----------)
    [4.2][4.147062:147101](),[4.2][4.147062:147101](),[4.147101][4.83723:83723]()
    end
    function starts_with(s, sub)
    return s:find(sub, 1, --[[no escapes]] true) == 1
    end
    function ends_with(s, sub)
    return s:reverse():find(sub:reverse(), 1, --[[no escapes]] true) == 1
    end
    State.link_cache = {}
    end
    function Text.clear_screen_line_cache(State, line_index)
    State.line_cache[line_index].fragments = nil
    State.line_cache[line_index].fragmentsB = nil
    State.line_cache[line_index].screen_line_starting_pos = nil
    State.line_cache[line_index].screen_line_starting_posB = nil
    end
    function trim(s)
    return s:gsub('^%s+', ''):gsub('%s+$', '')
    end
    function ltrim(s)
    return s:gsub('^%s+', '')
    end
    function rtrim(s)
    return s:gsub('%s+$', '')
    function source.link_exists(State, filename)
    if State.link_cache == nil then
    State.link_cache = {}
    end
    if State.link_cache[filename] == nil then
    State.link_cache[filename] = file_exists(filename)
    end
    return State.link_cache[filename]
    end
    function Text.redraw_all(State)
    --? print('clearing fragments')
    State.line_cache = {}
    for i=1,#State.lines do
    State.line_cache[i] = {}
    end
    -- Make [[WikiWords]] (single word, all in one screen line) clickable.
    local trimmed_word = rtrim(frag) -- compute_fragments puts whitespace at the end
    if starts_with(trimmed_word, '[[') and ends_with(trimmed_word, ']]') then
    local filename = trimmed_word:gsub('^..(.*)..$', '%1')
    if source.link_exists(State, filename) then
    local filename_text = App.newText(love.graphics.getFont(), filename)
    button(State, 'link', {x=x+App.width(to_text('[[')), y=y, w=App.width(filename_text), h=State.line_height, color={1,1,1},
    icon = icon.hyperlink_decoration,
    onpress1 = function()
    source.switch_to_file(filename)
    end,
    })
    end
    end
    App.screen.draw(frag_text, x,y)
    -- render cursor if necessary
    if State.cursor1.pos and line_index == State.cursor1.line then
    if pos <= State.cursor1.pos and pos + frag_len > State.cursor1.pos then
    if State.search_term then
    if State.lines[State.cursor1.line].data:sub(State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term)-1) == State.search_term then
    local lo_px = Text.draw_highlight(State, line, x,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term))
    App.color(Text_color)
    love.graphics.print(State.search_term, x+lo_px,y)
    end
    elseif Focus == 'edit' then
    Text.draw_cursor(State, x+Text.x(frag, State.cursor1.pos-pos+1), y)
    App.color(Text_color)
    end
    end
    end
    x = x + frag_width
    end
    pos = pos + frag_len
    end
    return false, x,y, pos, screen_line_starting_pos
    end
    function Text.draw_wrapping_lineB(State, line_index, x,y, startpos)
    local line = State.lines[line_index]
    local line_cache = State.line_cache[line_index]
    local screen_line_starting_pos = startpos
    Text.compute_fragmentsB(State, line_index, x)
    local pos = 1
    for _, f in ipairs(line_cache.fragmentsB) do
    local frag, frag_text = f.data, f.text
    local frag_len = utf8.len(frag)
    --? print('text.draw:', frag, 'at', line_index,pos, 'after', x,y)
    if pos < startpos then
    -- render nothing
    --? print('skipping', frag)
    else
    -- render fragment
    local frag_width = App.width(frag_text)
    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 --[[screen filled]] true, x,y, pos, screen_line_starting_pos
    end
    screen_line_starting_pos = pos
    x = State.left
    end
    App.screen.draw(frag_text, x,y)
    -- render cursor if necessary
    if State.cursor1.posB and line_index == State.cursor1.line then
    if pos <= State.cursor1.posB and pos + frag_len > State.cursor1.posB then
    if State.search_term then
    if State.lines[State.cursor1.line].dataB:sub(State.cursor1.posB, State.cursor1.posB+utf8.len(State.search_term)-1) == State.search_term then
    local lo_px = Text.draw_highlight(State, line, x,y, pos, State.cursor1.posB, State.cursor1.posB+utf8.len(State.search_term))
    App.color(Fold_color)
    love.graphics.print(State.search_term, x+lo_px,y)
    end
    elseif Focus == 'edit' then
    Text.draw_cursor(State, x+Text.x(frag, State.cursor1.posB-pos+1), y)
    App.color(Fold_color)
    end
    end
    end
    x = x + frag_width
    end
    pos = pos + frag_len
    end
    return false, x,y, pos, screen_line_starting_pos
    end
    function Text.draw_cursor(State, 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,State.line_height)
    end
    State.cursor_x = x
    State.cursor_y = y+State.line_height
    end
    function Text.populate_screen_line_starting_pos(State, line_index)
    local line = State.lines[line_index]
  • file deletion: source_edit.lua (----------)source_edit.lua (----------)
    [4.2][4.165725:165764](),[4.2][4.165725:165764](),[4.165764][4.152440:152440]()
    Hyperlink_decoration_color = {r=0.4, g=0.4, b=1}
    Stroke_color = {r=0, g=0, b=0}
    Current_stroke_color = {r=0.7, g=0.7, b=0.7} -- in process of being drawn
    Current_name_background_color = {r=1, g=0, b=0, a=0.1} -- name currently being edited
  • edit in source_text.lua at line 113
    [4.88252]
    [4.88252]
    -- Make [[WikiWords]] (single word, all in one screen line) clickable.
    local trimmed_word = rtrim(frag) -- compute_fragments puts whitespace at the end
    if starts_with(trimmed_word, '[[') and ends_with(trimmed_word, ']]') then
    local filename = trimmed_word:gsub('^..(.*)..$', '%1')
    if source.link_exists(State, filename) then
    local filename_text = App.newText(love.graphics.getFont(), filename)
    button(State, 'link', {x=x+App.width(to_text('[[')), y=y, w=App.width(filename_text), h=State.line_height, color={1,1,1},
    icon = icon.hyperlink_decoration,
    onpress1 = function()
    source.switch_to_file(filename)
    end,
    })
    end
    end
  • edit in source_text.lua at line 1627
    [4.146518]
    [4.146518]
    function source.link_exists(State, filename)
    if State.link_cache == nil then
    State.link_cache = {}
    end
    if State.link_cache[filename] == nil then
    State.link_cache[filename] = file_exists(filename)
    end
    return State.link_cache[filename]
    end
  • edit in source_text.lua at line 1643
    [4.146669]
    [4.146669]
    State.link_cache = {}
  • edit in source_text.lua at line 1663
    [4.147120]
    [4.147120]
    end
    function starts_with(s, sub)
    return s:find(sub, 1, --[[no escapes]] true) == 1
    end
    function ends_with(s, sub)
    return s:reverse():find(sub:reverse(), 1, --[[no escapes]] true) == 1
  • edit in source_edit.lua at line 4
    [4.152609]
    [2.16390]
    Hyperlink_decoration_color = {r=0.4, g=0.4, b=1}
  • file un-deletion: icons.lua (----------)icons.lua (----------)
    [4.6620][4.5323:5323](),[4.2][4.6587:6620](),[4.2][4.6587:6620]()
  • resurrect zombie in icons.lua at line 1
    [4.5526][3.1318:1557](),[4.5526][3.1318:1557]()
    end
    function icon.hyperlink_decoration(button_params)
    local x,y = button_params.x, button_params.y
    App.color(Hyperlink_decoration_color)
    love.graphics.line(x,y+Editor_state.line_height, x+button_params.w,y+Editor_state.line_height)
  • edit in icons.lua at line 1
    [4.5323]
    [3.1318]
    icon = {}
    function icon.insert_drawing(button_params)
    local x,y = button_params.x, button_params.y
    App.color(Icon_color)
    love.graphics.rectangle('line', x,y, 12,12)
    love.graphics.line(4,y+6, 16,y+6)
    love.graphics.line(10,y, 10,y+12)
  • edit in icons.lua at line 15
    [3.1557]
    end
    function icon.freehand(x, y)
    love.graphics.line(x+4,y+7,x+5,y+5)
    love.graphics.line(x+5,y+5,x+7,y+4)
    love.graphics.line(x+7,y+4,x+9,y+3)
    love.graphics.line(x+9,y+3,x+10,y+5)
    love.graphics.line(x+10,y+5,x+12,y+6)
    love.graphics.line(x+12,y+6,x+13,y+8)
    love.graphics.line(x+13,y+8,x+13,y+10)
    love.graphics.line(x+13,y+10,x+14,y+12)
    love.graphics.line(x+14,y+12,x+15,y+14)
    love.graphics.line(x+15,y+14,x+15,y+16)
    end
    function icon.line(x, y)
    love.graphics.line(x+4,y+2, x+16,y+18)
    end
    function icon.manhattan(x, y)
    love.graphics.line(x+4,y+20, x+4,y+2)
    love.graphics.line(x+4,y+2, x+10,y+2)
    love.graphics.line(x+10,y+2, x+10,y+10)
    love.graphics.line(x+10,y+10, x+18,y+10)
    end
    function icon.polygon(x, y)
    love.graphics.line(x+8,y+2, x+14,y+2)
    love.graphics.line(x+14,y+2, x+18,y+10)
    love.graphics.line(x+18,y+10, x+10,y+18)
    love.graphics.line(x+10,y+18, x+4,y+12)
    love.graphics.line(x+4,y+12, x+8,y+2)
    end
    function icon.rectangle(x, y)
    love.graphics.line(x+4,y+8, x+4,y+16)
    love.graphics.line(x+4,y+16, x+16,y+16)
    love.graphics.line(x+16,y+16, x+16,y+8)
    love.graphics.line(x+16,y+8, x+4,y+8)
    end
    function icon.square(x, y)
    love.graphics.line(x+6,y+6, x+6,y+16)
    love.graphics.line(x+6,y+16, x+16,y+16)
    love.graphics.line(x+16,y+16, x+16,y+6)
    love.graphics.line(x+16,y+6, x+6,y+6)
    end
    function icon.circle(x, y)
    love.graphics.circle('line', x+10,y+10, 8)
    end