diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-12-23 11:05:37 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-12-23 11:24:44 -0800 |
commit | 984d3450891d00de9769af446401acd028bf1c1d (patch) | |
tree | 04509fe1b601cd8e9023442b03a9f3d496234c6e | |
parent | 34e1595922f531eee68585e2f312c34f90da1ff9 (diff) | |
download | teliva-984d3450891d00de9769af446401acd028bf1c1d.tar.gz |
toot-toot: reorg definitions
-rw-r--r-- | toot-toot.tlv | 322 |
1 files changed, 113 insertions, 209 deletions
diff --git a/toot-toot.tlv b/toot-toot.tlv index 7cd27cb..0f9de69 100644 --- a/toot-toot.tlv +++ b/toot-toot.tlv @@ -151,55 +151,19 @@ >window = curses.stdscr() >curses.curs_set(0) -- we'll simulate our own cursor - __teliva_timestamp: original - render: - >function render(window) - > window:clear() - > -- draw stuff to screen here - > window:attron(curses.A_BOLD) - > window:mvaddstr(1, 5, "example app") - > window:attrset(curses.A_NORMAL) - > for i=0,15 do - > window:attrset(curses.color_pair(i)) - > window:mvaddstr(3+i, 5, "========================") - > end - >end -- __teliva_timestamp: original menu: >menu = { > {'^u', 'clear'}, > {'^w', 'write prose to file "toot" (edit hotkey does NOT save)'}, >} - __teliva_timestamp: original - update: - >function update(window) - > local key = curses.getch() - > if key == curses.KEY_LEFT then - > if cursor > 1 then - > cursor = cursor-1 - > end - > elseif key == curses.KEY_RIGHT then - > if cursor <= #prose then - > cursor = cursor+1 - > end - > elseif key == curses.KEY_DOWN then - > cursor = cursor_down(prose, cursor) - > elseif key == curses.KEY_UP then - > cursor = cursor_up(prose, cursor) - > elseif key == curses.KEY_BACKSPACE then - > if cursor > 1 then - > cursor = cursor-1 - > prose = prose:remove(cursor) - > end - > elseif key == 21 then -- ctrl-u - > prose = '' - > cursor = 1 - > elseif key == 23 then -- ctrl-w - > local out = io.open('toot', 'w') - > out:write(prose, '\n') - > out:close() - > elseif key == 10 or (key >= 32 and key < 127) then - > prose = prose:insert(string.char(key), cursor-1) - > cursor = cursor+1 + main: + >function main() + > init_colors() + > + > while true do + > render(window) + > update(window) > end >end - __teliva_timestamp: original @@ -218,22 +182,32 @@ > curses.init_pair(15, -1, 15) >end - __teliva_timestamp: original - main: - >function main() - > init_colors() - > - > while true do - > render(window) - > update(window) - > end - >end -- __teliva_timestamp: original prose: >prose = '' - __teliva_timestamp: original cursor: >cursor = 1 - __teliva_timestamp: original + render: + >function render(window) + > window:clear() + > debugy = 5 + > local toots = split(prose, '\n\n===\n\n') + > pos = 1 + > debugy = 5 + > for i, toot in ipairs(toots) do + > if i > 1 then + > pos = render_delimiter(window, '\n\n===\n\n', pos, cursor) + > end + > pos = render_text(window, toot, pos, cursor) + > print('') + > window:attron(curses.A_BOLD) + > window:addstr(string.len(toot)) + > window:attroff(curses.A_BOLD) + > end + > curses.refresh() + >end +- __teliva_timestamp: original render_delimiter: >function render_delimiter(window, s, pos, cursor) > local newpos = pos @@ -259,6 +233,92 @@ > return newpos >end - __teliva_timestamp: original + render_text: + >-- https://gankra.github.io/blah/text-hates-you + >-- https://lord.io/text-editing-hates-you-too + > + >-- manual tests: + >-- cursor on some character + >-- cursor on (within) '\n\n===\n\n' delimiter (delimiter is hardcoded; things may break if you change it) + >-- cursor at end of each line + >-- render digits + > + >-- positions serve two purposes: + >-- character to index into prose + >-- cursor-printing + > + >-- sequence of stories + >-- focus on rendering a single piece of text, first get that rock-solid + >-- split prose into toots, manage transitions between toots in response to cursor movements + >-- cursor movement: left/right vs up/down + > + >-- what is the ideal representation? + >-- prose + cursor has issues in multi-toot context. when to display cursor? + >function render_text(window, s, pos, cursor) + > local newpos = pos + >--? dbg(window, '--') + > for i=1,string.len(s) do + >--? dbg(window, tostring(newpos)..' '..tostring(string.byte(s[i]))) + > if newpos == cursor then + >--? dbg(window, 'cursor: '..tostring(cursor)) + > if s[i] == '\n' then + > -- newline at cursor = render extra space in reverse video before jumping to new line + > window:attron(curses.A_REVERSE) + > window:addch(' ') + > window:attroff(curses.A_REVERSE) + > window:addstr(s[i]) + > else + > -- most characters at cursor = render in reverse video + > window:attron(curses.A_REVERSE) + > window:addstr(s[i]) + > window:attroff(curses.A_REVERSE) + > end + > else + > window:addstr(s[i]) + > end + > newpos = newpos+1 + > end + > if newpos == cursor then + > window:attron(curses.A_REVERSE) + > window:addch(' ') + > window:attroff(curses.A_REVERSE) + > end + > return newpos + >end +- __teliva_timestamp: original + update: + >function update(window) + > local key = curses.getch() + > if key == curses.KEY_LEFT then + > if cursor > 1 then + > cursor = cursor-1 + > end + > elseif key == curses.KEY_RIGHT then + > if cursor <= #prose then + > cursor = cursor+1 + > end + > elseif key == curses.KEY_DOWN then + > cursor = cursor_down(prose, cursor) + > elseif key == curses.KEY_UP then + > cursor = cursor_up(prose, cursor) + > elseif key == curses.KEY_BACKSPACE then + > if cursor > 1 then + > cursor = cursor-1 + > prose = prose:remove(cursor) + > end + > elseif key == 21 then -- ctrl-u + > prose = '' + > cursor = 1 + > elseif key == 23 then -- ctrl-w + > local out = io.open('toot', 'w') + > out:write(prose, '\n') + > out:close() + > elseif key == 10 or (key >= 32 and key < 127) then + > prose = prose:insert(string.char(key), cursor-1) + > cursor = cursor+1 + > end + >end +- __teliva_timestamp: original cursor_down: >function cursor_down(s, old_idx) > local max = string.len(s) @@ -325,89 +385,6 @@ > check_eq(cursor_down('abc\n\ndef', 2), 5, 'cursor_down: to shorter line') >end - __teliva_timestamp: original - skip_past_newline: - >function skip_past_newline(s, idx) - > local result = idx - > while true do - > if result >= string.len(s) then - > return idx - > end - > if s[result] == '\n' then - > return result+1 - > end - > result = result+1 - > end - >end -- __teliva_timestamp: original - col_within_line: - >function col_within_line(s, idx) - > if idx <= 1 then - > return idx - > end - > idx = idx-1 - > local result = 1 - > while idx >= 1 do - > if s[idx] == '\n' then break end - > idx = idx-1 - > result=result+1 - > end - > return result - >end - > - >function test_col_within_line() - > check_eq(col_within_line('', 4), 4, 'col_within_line("")') - > check_eq(col_within_line('abc\ndef', 1), 1, 'col_within_line(..., 1)') - > check_eq(col_within_line('abc\ndef', 3), 3, 'col_within_line(..., -1)') - > check_eq(col_within_line('abc\ndef', 4), 4, 'col_within_line(..., newline)') - > check_eq(col_within_line('abc\ndef', 5), 1, 'col_within_line(..., after newline)') - >end -- __teliva_timestamp: original - skip_to_start_of_previous_line: - >function skip_to_start_of_previous_line(s, idx) - > local result = idx - > -- skip to newline - > if idx == 1 then return 1 end - > result = result-1 -- just in case we start out on a newline - > while true do - > if result <= 1 then - > return idx - > end - > if s[result] == '\n' then - > result = result-1 - > break - > end - > result = result-1 - > end - > -- dbg(window, 'skip: '..tostring(result)) - > while true do - > if result <= 1 then - > return result - > end - > if s[result] == '\n' then - > return result+1 - > end - > result = result-1 - > end - >end - > - >function test_skip_to_start_of_previous_line() - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 1), 1, 'start of previous line: first line, first char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 2), 2, 'start of previous line: first line, mid char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 3), 3, 'start of previous line: first line, final char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 4), 4, 'start of previous line: first line, newline') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 5), 1, 'start of previous line: second line, first char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 6), 1, 'start of previous line: second line, mid char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 7), 1, 'start of previous line: second line, final char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 8), 1, 'start of previous line: second line, newline') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 9), 5, 'start of previous line: final line, first char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 10), 5, 'start of previous line: final line, mid char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 11), 5, 'start of previous line: final line, final char') - > check_eq(skip_to_start_of_previous_line('abc\ndef\nghi', 12), 5, 'start of previous line: end of file') - > - > check_eq(skip_to_start_of_previous_line('abc\n\nghi', 7), 5, 'start of previous line: to empty line') - > check_eq(skip_to_start_of_previous_line('abc\nd\nghi', 8), 5, 'start of previous line: to shorter line') - >end -- __teliva_timestamp: original cursor_up: >function cursor_up(s, old_idx, width) > local max = string.len(s) @@ -524,76 +501,3 @@ > check_eq(cursor_up('abcdefg\nhij', 11, 5), 8, 'cursor_up to wrapping line: final char') > check_eq(cursor_up('abcdefg\nhij', 12, 5), 8, 'cursor_up to wrapping line: to shorter line') >end -- __teliva_timestamp: original - render: - >function render(window) - > window:clear() - > debugy = 5 - > local toots = split(prose, '\n\n===\n\n') - > pos = 1 - > debugy = 5 - > for i, toot in ipairs(toots) do - > if i > 1 then - > pos = render_delimiter(window, '\n\n===\n\n', pos, cursor) - > end - > pos = render_text(window, toot, pos, cursor) - > print('') - > window:attron(curses.A_BOLD) - > window:addstr(string.len(toot)) - > window:attroff(curses.A_BOLD) - > end - > curses.refresh() - >end -- __teliva_timestamp: original - render_text: - >-- https://gankra.github.io/blah/text-hates-you - >-- https://lord.io/text-editing-hates-you-too - > - >-- manual tests: - >-- cursor on some character - >-- cursor on (within) '\n\n===\n\n' delimiter (delimiter is hardcoded; things may break if you change it) - >-- cursor at end of each line - >-- render digits - > - >-- positions serve two purposes: - >-- character to index into prose - >-- cursor-printing - > - >-- sequence of stories - >-- focus on rendering a single piece of text, first get that rock-solid - >-- split prose into toots, manage transitions between toots in response to cursor movements - >-- cursor movement: left/right vs up/down - > - >-- what is the ideal representation? - >-- prose + cursor has issues in multi-toot context. when to display cursor? - >function render_text(window, s, pos, cursor) - > local newpos = pos - >--? dbg(window, '--') - > for i=1,string.len(s) do - >--? dbg(window, tostring(newpos)..' '..tostring(string.byte(s[i]))) - > if newpos == cursor then - >--? dbg(window, 'cursor: '..tostring(cursor)) - > if s[i] == '\n' then - > -- newline at cursor = render extra space in reverse video before jumping to new line - > window:attron(curses.A_REVERSE) - > window:addch(' ') - > window:attroff(curses.A_REVERSE) - > window:addstr(s[i]) - > else - > -- most characters at cursor = render in reverse video - > window:attron(curses.A_REVERSE) - > window:addstr(s[i]) - > window:attroff(curses.A_REVERSE) - > end - > else - > window:addstr(s[i]) - > end - > newpos = newpos+1 - > end - > if newpos == cursor then - > window:attron(curses.A_REVERSE) - > window:addch(' ') - > window:attroff(curses.A_REVERSE) - > end - > return newpos - >end |