diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2022-08-14 09:17:53 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2022-08-14 09:20:14 -0700 |
commit | 9d792a203bb00b0f5521698fd1c6890f0cc12032 (patch) | |
tree | be2f89a515b0d5e7ff936c98cb5f4e17d618bbe4 /text.lua | |
parent | 974d17ffc071e2eb254d0dbc11cf932c62e59d5c (diff) | |
download | view.love-9d792a203bb00b0f5521698fd1c6890f0cc12032.tar.gz |
new fork: rip out drawing support
Diffstat (limited to 'text.lua')
-rw-r--r-- | text.lua | 228 |
1 files changed, 78 insertions, 150 deletions
diff --git a/text.lua b/text.lua index 3d70f93..014f77c 100644 --- a/text.lua +++ b/text.lua @@ -50,7 +50,7 @@ function Text.draw(State, line_index, y, startpos) if 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 + if State.lines[State.cursor1.line]: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) @@ -92,7 +92,7 @@ function Text.compute_fragments(State, line_index) line_cache.fragments = {} local x = State.left -- try to wrap at word boundaries - for frag in line.data:gmatch('%S*%s*') do + for frag in line:gmatch('%S*%s*') do local frag_text = App.newText(love.graphics.getFont(), frag) local frag_width = App.width(frag_text) --? print('x: '..tostring(x)..'; '..tostring(State.right-x)..'px to go') @@ -142,8 +142,8 @@ function Text.textinput(State, t) end function Text.insert_at_cursor(State, t) - local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos) - State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1)..t..string.sub(State.lines[State.cursor1.line].data, byte_offset) + local byte_offset = Text.offset(State.lines[State.cursor1.line], State.cursor1.pos) + State.lines[State.cursor1.line] = string.sub(State.lines[State.cursor1.line], 1, byte_offset-1)..t..string.sub(State.lines[State.cursor1.line], byte_offset) Text.clear_screen_line_cache(State, State.cursor1.line) State.cursor1.pos = State.cursor1.pos+1 end @@ -182,28 +182,23 @@ function Text.keychord_pressed(State, chord) local before if State.cursor1.pos > 1 then before = snapshot(State, State.cursor1.line) - local byte_start = utf8.offset(State.lines[State.cursor1.line].data, State.cursor1.pos-1) - local byte_end = utf8.offset(State.lines[State.cursor1.line].data, State.cursor1.pos) + local byte_start = utf8.offset(State.lines[State.cursor1.line], State.cursor1.pos-1) + local byte_end = utf8.offset(State.lines[State.cursor1.line], State.cursor1.pos) if byte_start then if byte_end then - State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_start-1)..string.sub(State.lines[State.cursor1.line].data, byte_end) + State.lines[State.cursor1.line] = string.sub(State.lines[State.cursor1.line], 1, byte_start-1)..string.sub(State.lines[State.cursor1.line], byte_end) else - State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_start-1) + State.lines[State.cursor1.line] = string.sub(State.lines[State.cursor1.line], 1, byte_start-1) end State.cursor1.pos = State.cursor1.pos-1 end elseif State.cursor1.line > 1 then before = snapshot(State, State.cursor1.line-1, State.cursor1.line) - if State.lines[State.cursor1.line-1].mode == 'drawing' then - table.remove(State.lines, State.cursor1.line-1) - table.remove(State.line_cache, State.cursor1.line-1) - else - -- join lines - State.cursor1.pos = utf8.len(State.lines[State.cursor1.line-1].data)+1 - State.lines[State.cursor1.line-1].data = State.lines[State.cursor1.line-1].data..State.lines[State.cursor1.line].data - table.remove(State.lines, State.cursor1.line) - table.remove(State.line_cache, State.cursor1.line) - end + -- join lines + State.cursor1.pos = utf8.len(State.lines[State.cursor1.line-1])+1 + State.lines[State.cursor1.line-1] = State.lines[State.cursor1.line-1]..State.lines[State.cursor1.line] + table.remove(State.lines, State.cursor1.line) + table.remove(State.line_cache, State.cursor1.line) State.cursor1.line = State.cursor1.line-1 end if State.screen_top1.line > #State.lines then @@ -227,27 +222,25 @@ function Text.keychord_pressed(State, chord) return end local before - if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line].data) then + if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line]) then before = snapshot(State, State.cursor1.line) else before = snapshot(State, State.cursor1.line, State.cursor1.line+1) end - if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line].data) then - local byte_start = utf8.offset(State.lines[State.cursor1.line].data, State.cursor1.pos) - local byte_end = utf8.offset(State.lines[State.cursor1.line].data, State.cursor1.pos+1) + if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line]) then + local byte_start = utf8.offset(State.lines[State.cursor1.line], State.cursor1.pos) + local byte_end = utf8.offset(State.lines[State.cursor1.line], State.cursor1.pos+1) if byte_start then if byte_end then - State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_start-1)..string.sub(State.lines[State.cursor1.line].data, byte_end) + State.lines[State.cursor1.line] = string.sub(State.lines[State.cursor1.line], 1, byte_start-1)..string.sub(State.lines[State.cursor1.line], byte_end) else - State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_start-1) + State.lines[State.cursor1.line] = string.sub(State.lines[State.cursor1.line], 1, byte_start-1) end -- no change to State.cursor1.pos end elseif State.cursor1.line < #State.lines then - if State.lines[State.cursor1.line+1].mode == 'text' then - -- join lines - State.lines[State.cursor1.line].data = State.lines[State.cursor1.line].data..State.lines[State.cursor1.line+1].data - end + -- join lines + State.lines[State.cursor1.line] = State.lines[State.cursor1.line]..State.lines[State.cursor1.line+1] table.remove(State.lines, State.cursor1.line+1) table.remove(State.line_cache, State.cursor1.line+1) end @@ -340,10 +333,10 @@ function Text.keychord_pressed(State, chord) end function Text.insert_return(State) - local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos) - table.insert(State.lines, State.cursor1.line+1, {mode='text', data=string.sub(State.lines[State.cursor1.line].data, byte_offset)}) + local byte_offset = Text.offset(State.lines[State.cursor1.line], State.cursor1.pos) + table.insert(State.lines, State.cursor1.line+1, string.sub(State.lines[State.cursor1.line], byte_offset)) table.insert(State.line_cache, State.cursor1.line+1, {}) - State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1) + State.lines[State.cursor1.line] = string.sub(State.lines[State.cursor1.line], 1, byte_offset-1) Text.clear_screen_line_cache(State, State.cursor1.line) State.cursor1.line = State.cursor1.line+1 State.cursor1.pos = 1 @@ -358,11 +351,7 @@ function Text.pageup(State) 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 - if State.lines[State.screen_top1.line].mode == 'text' then - y = y - State.line_height - elseif State.lines[State.screen_top1.line].mode == 'drawing' then - y = y - Drawing_padding_height - Drawing.pixels(State.lines[State.screen_top1.line].h, State.width) - end + y = y - State.line_height top2 = Text.previous_screen_line(State, top2) end State.screen_top1 = Text.to1(State, top2) @@ -399,35 +388,30 @@ function Text.pagedown(State) end function Text.up(State) - assert(State.lines[State.cursor1.line].mode == 'text') --? print('up', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos) local screen_line_index,screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line(State) if screen_line_starting_pos == 1 then --? print('cursor is at first screen line of its line') -- line is done; skip to previous text line - local new_cursor_line = State.cursor1.line - while new_cursor_line > 1 do - new_cursor_line = new_cursor_line-1 - if State.lines[new_cursor_line].mode == 'text' then ---? print('found previous text line') - State.cursor1.line = new_cursor_line - Text.populate_screen_line_starting_pos(State, State.cursor1.line) - -- previous text line found, pick its final screen line ---? print('has multiple screen lines') - local screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos ---? print(#screen_line_starting_pos) - screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos] ---? print('previous screen line starts at pos '..tostring(screen_line_starting_pos)..' of its line') - if State.screen_top1.line > State.cursor1.line then - State.screen_top1.line = State.cursor1.line - State.screen_top1.pos = screen_line_starting_pos ---? print('pos of top of screen is also '..tostring(State.screen_top1.pos)..' of the same line') - end - local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, screen_line_starting_pos) - local s = string.sub(State.lines[State.cursor1.line].data, screen_line_starting_byte_offset) - State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1 - break + if State.cursor1.line > 1 then + local new_cursor_line = State.cursor1.line-1 +--? print('found previous text line') + State.cursor1.line = new_cursor_line + Text.populate_screen_line_starting_pos(State, State.cursor1.line) + -- previous text line found, pick its final screen line +--? print('has multiple screen lines') + local screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos +--? print(#screen_line_starting_pos) + screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos] +--? print('previous screen line starts at pos '..tostring(screen_line_starting_pos)..' of its line') + if State.screen_top1.line > State.cursor1.line then + State.screen_top1.line = State.cursor1.line + State.screen_top1.pos = screen_line_starting_pos +--? print('pos of top of screen is also '..tostring(State.screen_top1.pos)..' of the same line') end + local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line], screen_line_starting_pos) + local s = string.sub(State.lines[State.cursor1.line], screen_line_starting_byte_offset) + State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1 end if State.cursor1.line < State.screen_top1.line then State.screen_top1.line = State.cursor1.line @@ -442,28 +426,23 @@ function Text.up(State) State.screen_top1.pos = new_screen_line_starting_pos --? print('also setting pos of top of screen to '..tostring(State.screen_top1.pos)) end - local new_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, new_screen_line_starting_pos) - local s = string.sub(State.lines[State.cursor1.line].data, new_screen_line_starting_byte_offset) + local new_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line], new_screen_line_starting_pos) + local s = string.sub(State.lines[State.cursor1.line], new_screen_line_starting_byte_offset) State.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1 --? print('cursor pos is now '..tostring(State.cursor1.pos)) end end function Text.down(State) - assert(State.lines[State.cursor1.line].mode == 'text') --? print('down', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, State.screen_bottom1.line, State.screen_bottom1.pos) if Text.cursor_at_final_screen_line(State) then -- line is done, skip to next text line --? print('cursor at final screen line of its line') - local new_cursor_line = State.cursor1.line - while new_cursor_line < #State.lines do - new_cursor_line = new_cursor_line+1 - if State.lines[new_cursor_line].mode == 'text' then - State.cursor1.line = new_cursor_line - State.cursor1.pos = Text.nearest_cursor_pos(State.lines[State.cursor1.line].data, State.cursor_x, State.left) ---? print(State.cursor1.pos) - break - end + if State.cursor1.line < #State.lines then + local new_cursor_line = State.cursor1.line+1 + State.cursor1.line = new_cursor_line + State.cursor1.pos = Text.nearest_cursor_pos(State.lines[State.cursor1.line], State.cursor_x, State.left) +--? print(State.cursor1.pos) end if State.cursor1.line > State.screen_bottom1.line then --? print('screen top before:', State.screen_top1.line, State.screen_top1.pos) @@ -481,8 +460,8 @@ function Text.down(State) local screen_line_index, screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line(State) new_screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos[screen_line_index+1] --? print('switching pos of screen line at cursor from '..tostring(screen_line_starting_pos)..' to '..tostring(new_screen_line_starting_pos)) - local new_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, new_screen_line_starting_pos) - local s = string.sub(State.lines[State.cursor1.line].data, new_screen_line_starting_byte_offset) + local new_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line], new_screen_line_starting_pos) + local s = string.sub(State.lines[State.cursor1.line], new_screen_line_starting_byte_offset) State.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, State.left) - 1 --? print('cursor pos is now', State.cursor1.line, State.cursor1.pos) if scroll_down then @@ -502,7 +481,7 @@ function Text.start_of_line(State) end function Text.end_of_line(State) - State.cursor1.pos = utf8.len(State.lines[State.cursor1.line].data) + 1 + State.cursor1.pos = utf8.len(State.lines[State.cursor1.line]) + 1 local _,botpos = Text.pos_at_start_of_cursor_screen_line(State) local botline1 = {line=State.cursor1.line, pos=botpos} if Text.cursor_past_screen_bottom(State) then @@ -516,7 +495,7 @@ function Text.word_left(State) if State.cursor1.pos == 1 then break end - if Text.match(State.lines[State.cursor1.line].data, State.cursor1.pos-1, '%S') then + if Text.match(State.lines[State.cursor1.line], State.cursor1.pos-1, '%S') then break end Text.left(State) @@ -528,7 +507,7 @@ function Text.word_left(State) break end assert(State.cursor1.pos > 1) - if Text.match(State.lines[State.cursor1.line].data, State.cursor1.pos-1, '%s') then + if Text.match(State.lines[State.cursor1.line], State.cursor1.pos-1, '%s') then break end end @@ -537,20 +516,20 @@ end function Text.word_right(State) -- skip some whitespace while true do - if State.cursor1.pos > utf8.len(State.lines[State.cursor1.line].data) then + if State.cursor1.pos > utf8.len(State.lines[State.cursor1.line]) then break end - if Text.match(State.lines[State.cursor1.line].data, State.cursor1.pos, '%S') then + if Text.match(State.lines[State.cursor1.line], State.cursor1.pos, '%S') then break end Text.right_without_scroll(State) end while true do Text.right_without_scroll(State) - if State.cursor1.pos > utf8.len(State.lines[State.cursor1.line].data) then + if State.cursor1.pos > utf8.len(State.lines[State.cursor1.line]) then break end - if Text.match(State.lines[State.cursor1.line].data, State.cursor1.pos, '%s') then + if Text.match(State.lines[State.cursor1.line], State.cursor1.pos, '%s') then break end end @@ -569,19 +548,11 @@ function Text.match(s, pos, pat) end function Text.left(State) - assert(State.lines[State.cursor1.line].mode == 'text') if State.cursor1.pos > 1 then State.cursor1.pos = State.cursor1.pos-1 - else - local new_cursor_line = State.cursor1.line - while new_cursor_line > 1 do - new_cursor_line = new_cursor_line-1 - if State.lines[new_cursor_line].mode == 'text' then - State.cursor1.line = new_cursor_line - State.cursor1.pos = utf8.len(State.lines[State.cursor1.line].data) + 1 - break - end - end + elseif State.cursor1.line > 1 then + State.cursor1.line = State.cursor1.line-1 + State.cursor1.pos = utf8.len(State.lines[State.cursor1.line]) + 1 end if Text.lt1(State.cursor1, State.screen_top1) then local top2 = Text.to2(State, State.screen_top1) @@ -598,19 +569,11 @@ function Text.right(State) end function Text.right_without_scroll(State) - assert(State.lines[State.cursor1.line].mode == 'text') - if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line].data) then + if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line]) then State.cursor1.pos = State.cursor1.pos+1 - else - local new_cursor_line = State.cursor1.line - while new_cursor_line <= #State.lines-1 do - new_cursor_line = new_cursor_line+1 - if State.lines[new_cursor_line].mode == 'text' then - State.cursor1.line = new_cursor_line - State.cursor1.pos = 1 - break - end - end + elseif State.cursor1.line <= #State.lines-1 then + State.cursor1.line = State.cursor1.line+1 + State.cursor1.pos = 1 end end @@ -633,23 +596,7 @@ function Text.cursor_at_final_screen_line(State) end function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State) - local y = State.top - while State.cursor1.line <= #State.lines do - if State.lines[State.cursor1.line].mode == 'text' then - break - end ---? print('cursor skips', State.cursor1.line) - y = y + Drawing_padding_height + Drawing.pixels(State.lines[State.cursor1.line].h, State.width) - State.cursor1.line = State.cursor1.line + 1 - end - -- hack: insert a text line at bottom of file if necessary - if State.cursor1.line > #State.lines then - assert(State.cursor1.line == #State.lines+1) - table.insert(State.lines, {mode='text', data=''}) - table.insert(State.line_cache, {}) - end ---? print(y, App.screen.height, App.screen.height-State.line_height) - if y > App.screen.height - State.line_height then + if State.top > App.screen.height - State.line_height then --? print('scroll up') Text.snap_cursor_to_bottom_of_screen(State) end @@ -665,24 +612,11 @@ function Text.snap_cursor_to_bottom_of_screen(State) while true do --? print(y, 'top2:', top2.line, top2.screen_line, top2.screen_pos) if top2.line == 1 and top2.screen_line == 1 then break end - if top2.screen_line > 1 or State.lines[top2.line-1].mode == 'text' then - local h = State.line_height - if y - h < State.top then - break - end - y = y - h - else - assert(top2.line > 1) - assert(State.lines[top2.line-1].mode == 'drawing') - -- We currently can't draw partial drawings, so either skip it entirely - -- or not at all. - local h = Drawing_padding_height + Drawing.pixels(State.lines[top2.line-1].h, State.width) - if y - h < State.top then - break - end ---? print('skipping drawing of height', h) - y = y - h + local h = State.line_height + if y - h < State.top then + break end + y = y - h top2 = Text.previous_screen_line(State, top2) end --? print('top2 finally:', top2.line, top2.screen_line, top2.screen_pos) @@ -713,8 +647,8 @@ function Text.to_pos_on_line(State, line_index, mx, my) 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] - local screen_line_starting_byte_offset = Text.offset(line.data, screen_line_starting_pos) ---? print('iter', y, screen_line_index, screen_line_starting_pos, string.sub(line.data, screen_line_starting_byte_offset)) + local screen_line_starting_byte_offset = Text.offset(line, screen_line_starting_pos) +--? print('iter', y, screen_line_index, screen_line_starting_pos, string.sub(line, screen_line_starting_byte_offset)) local nexty = y + State.line_height if my < nexty then -- On all wrapped screen lines but the final one, clicks past end of @@ -724,7 +658,7 @@ function Text.to_pos_on_line(State, line_index, mx, my) --? print('past end of non-final line; return') return line_cache.screen_line_starting_pos[screen_line_index+1]-1 end - local s = string.sub(line.data, screen_line_starting_byte_offset) + local s = string.sub(line, screen_line_starting_byte_offset) --? print('return', mx, Text.nearest_cursor_pos(s, mx, State.left), '=>', screen_line_starting_pos + Text.nearest_cursor_pos(s, mx, State.left) - 1) return screen_line_starting_pos + Text.nearest_cursor_pos(s, mx, State.left) - 1 end @@ -737,14 +671,14 @@ function Text.screen_line_width(State, line_index, i) local line = State.lines[line_index] local line_cache = State.line_cache[line_index] local start_pos = line_cache.screen_line_starting_pos[i] - local start_offset = Text.offset(line.data, start_pos) + local start_offset = Text.offset(line, start_pos) local screen_line if i < #line_cache.screen_line_starting_pos then local past_end_pos = line_cache.screen_line_starting_pos[i+1] - local past_end_offset = Text.offset(line.data, past_end_pos) - screen_line = string.sub(line.data, start_offset, past_end_offset-1) + local past_end_offset = Text.offset(line, past_end_pos) + screen_line = string.sub(line, start_offset, past_end_offset-1) else - screen_line = string.sub(line.data, start_pos) + screen_line = string.sub(line, start_pos) end local screen_line_text = App.newText(love.graphics.getFont(), screen_line) return App.width(screen_line_text) @@ -847,9 +781,6 @@ function Text.x(s, pos) end function Text.to2(State, loc1) - if State.lines[loc1.line].mode == 'drawing' then - return {line=loc1.line, screen_line=1, screen_pos=1} - end local result = {line=loc1.line, screen_line=1} Text.populate_screen_line_starting_pos(State, loc1.line) for i=#State.line_cache[loc1.line].screen_line_starting_pos,1,-1 do @@ -911,8 +842,6 @@ function Text.previous_screen_line(State, loc2) return {line=loc2.line, screen_line=loc2.screen_line-1, screen_pos=1} elseif loc2.line == 1 then return loc2 - elseif State.lines[loc2.line-1].mode == 'drawing' then - return {line=loc2.line-1, screen_line=1, screen_pos=1} else local l = State.lines[loc2.line-1] Text.populate_screen_line_starting_pos(State, loc2.line-1) @@ -922,7 +851,6 @@ end function Text.populate_screen_line_starting_pos(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.screen_line_starting_pos then return |