Merge lines.love
[?]
Sep 18, 2022, 8:56 AM
VBU5YHLRO5ZSKFWBJRX7DWQGWPEHEWZMRRVV2WMWDJ54PKUNYCNQCDependencies
- [2]
UI3IP45FMerge lines.love - [3]
N7VXEGLGyet another bugfix in log parsing - [4]
BYKXF3YYbugfix: draw menu after everything else - [5]
D3FLL7SLstart showing source menu file navigation state graphically - [6]
3QWK3GSAsupport mouse clicks in file navigator - [7]
B4JEWKWIhide editor cursor while in file navigator - [8]
RQUVBX62filter candidates in file navigator - [9]
SXTQMD44include some missing source files - [10]
T4FRZSYLdelete an ancient, unused file - [11]
MFZW24ANbugfix: disable typing while file navigator is open - [12]
BULPIBEGbeginnings of a module for the text editor - [13]
BJ5X5O4Alet's prevent the text cursor from ever getting on a drawing - [14]
K2X6G75Zstart writing some tests for drawings - [15]
66X36NZNa little more prose describing manual_tests - [16]
K464QQR4more defensive resize handling - [17]
IOCATA27bugfix: never skip files in file navigator - [18]
VXORMHMEdelete experimental REPL - [19]
AKZWDWIAMerge lines.love - [20]
TVCPXAAUrename - [21]
73OCE2MCafter much struggle, a brute-force undo - [22]
ZQZX364Vuse a helper - [23]
2L5MEZV3experiment: new edit namespace - [24]
OI4FPFINsupport drawings in the source editor - [25]
FS2ITYYHrecord a known issue - [26]
QZ2SXLHFsome debug prints - [27]
QFTLLRGLindent - [28]
TCWGD2RKdelete a duplicate filename candidate - [29]
X3CQLBTRset window title within each app - [30]
AYX33NBCMerge lines.love - [31]
O2PYNFUBuse existing local - [32]
SDRXK4X5move - [33]
GUOQRUL7Merge lines.love - [34]
VHQCNMARseveral more modules - [35]
4VQGE7RAnew test - [36]
KKMFQDR4editing source code from within the app - [37]
6DYSB5DYbugfix: perform matches in the right order - [38]
2CTN2IEFMerge lines.love - [39]
ENENSZLKbugfix: source margins when toggling log browser - [40]
D2GCFTTTclean up repl functionality - [41]
OTIBCAUJlove2d scaffold - [42]
LXTTOB33extract a couple of files - [43]
4YDBYBA4clean up memory leak experiments - [44]
JMUD7T3Oget rid of ugly side-effects in tests - [45]
AVTNUQYRbasic test-enabled framework - [46]
CE4LZV4Tdrop last couple of manual tests - [47]
R5QXEHUIsomebody stop me - [48]
ME7WBLF5bugfix: log filenames can have 2 formats - [49]
TLOAPLBJadd a license - [50]
3QNOKBFMbeginnings of a test harness - [51]
MD3W5IRAnew fork: rip out drawing support - [52]
C3NYQP57Merge lines.love - [53]
32V6ZHQBMerge lines.love - [54]
6LJZN727handle chords - [55]
YGCT2D2Ostart loading settings as applicable - [56]
D4B52CQ2Merge lines.love - [57]
VHUNJHXBMerge lines.love - [58]
BLWAYPKVextract a module - [59]
LZYLOTP3rename - [60]
CQYKYJJUremember window positions across restart/ctrl+e - [61]
MDGHRTIFsource: up/down in file navigator - [62]
P3K7UH5CMerge lines.love - [63]
GQKUD7QXdelete some logs - [64]
JOPVPUSAediting source code from within the app - [65]
RSZD5A7Gforgot to add json.lua - [66]
KMSL74GAsupport selections in the source editor - [67]
XW7ANEJXswitch shortcuts for bifold text - [68]
XX7G2FFJintermingle freehand line drawings with text - [69]
OGUV4HSAremove some memory leaks from rendered fragments - [70]
3PSFWAILMerge lines.love - [71]
NYRESFK6source: show all files in navigator
Change contents
- file deletion: source_text.lua source_text.lua
if not hide_cursor and not State.search_term then--? if line_index == 8 then print('c', State.cursor1.line, State.cursor1.posB, line_index, pos) endif line_index == State.cursor1.line and State.cursor1.posB == pos thenText.draw_cursor(State, x, y)endendendreturn y, nil, screen_line_starting_posend-- Given an array of fragments, draw the subset starting from pos to screen-- starting from (x,y).-- Return:-- - whether we got to bottom of screen before end of line-- - the final (x,y)-- - the final pos-- - starting pos of the final screen line drawnfunction Text.draw_wrapping_line(State, line_index, x,y, startpos)local line = State.lines[line_index]local line_cache = State.line_cache[line_index]--? print('== line', line_index, '^'..line.data..'$')local screen_line_starting_pos = startposText.compute_fragments(State, line_index)local pos = 1initialize_color()for _, f in ipairs(line_cache.fragments) doApp.color(Text_color)local frag, frag_text = f.data, f.textselect_color(frag)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 fragmentlocal frag_width = App.width(frag_text)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 --[[screen filled]] true, x,y, pos, screen_line_starting_posendscreen_line_starting_pos = posx = State.leftif not hide_cursor and not State.search_term thenif line_index == State.cursor1.line and State.cursor1.pos == pos thenText.draw_cursor(State, x, y)endendendelsex = State.leftend-- check for B side--? if line_index == 8 then print('checking for B side') endif line.dataB == nil thenassert(y)assert(screen_line_starting_pos)--? if line_index == 8 then print('return 1') endreturn y, screen_line_starting_posendif not State.expanded and not line.expanded thenassert(y)assert(screen_line_starting_pos)--? if line_index == 8 then print('return 2') endbutton(State, 'expand', {x=x+AB_padding, y=y+2, w=App.width(State.em), h=State.line_height-4, color={1,1,1},icon = function(button_params)App.color(Fold_background_color)love.graphics.rectangle('fill', button_params.x, button_params.y, App.width(State.em), State.line_height-4, 2,2)end,onpress1 = function()line.expanded = trueend,})return y, screen_line_starting_posend-- draw B side--? if line_index == 8 then print('drawing B side') endApp.color(Fold_color)function Text.draw(State, line_index, y, startpos, startposB, hide_cursor)local line = State.lines[line_index]local line_cache = State.line_cache[line_index]line_cache.starty = yline_cache.startpos = startposline_cache.startposB = startposB-- draw A sidelocal overflows_screen, x, pos, screen_line_starting_posif startpos thenoverflows_screen, x, y, pos, screen_line_starting_pos = Text.draw_wrapping_line(State, line_index, State.left, y, startpos)if overflows_screen thenreturn y, screen_line_starting_posendif Focus == 'edit' and State.cursor1.pos then - file deletion: source_edit.lua source_edit.lua
y, State.screen_bottom1.pos, State.screen_bottom1.posB = Text.draw(State, line_index, y, startpos, startposB, hide_cursor)y = y + State.line_height--? print('=> y', y)elseif line.mode == 'drawing' theny = y+Drawing_padding_topDrawing.draw(State, line_index, y)y = y + Drawing.pixels(line.h, State.width) + Drawing_padding_bottomelseprint(line.mode)assert(false)function edit.draw(State, hide_cursor)State.button_handlers = {}App.color(Text_color) - file deletion: source.lua source.lua
log_new('source')edit.draw(Editor_state, --[[hide cursor?]] Show_file_navigator)if Show_log_browser_side then-- dividerApp.color(Divider_color)love.graphics.rectangle('fill', App.screen.width/2-1,Menu_status_bar_height, 3,App.screen.height)--log_browser.draw(Log_browser_state)endsource.draw_menu_bar()if Show_file_navigator thentextinput_on_file_navigator(t)returnendif Focus == 'edit' thenreturn edit.textinput(Editor_state, t)elsereturn log_browser.textinput(Log_browser_state, t)endendfunction source.keychord_pressed(chord, key)Cursor_time = 0 -- ensure cursor is visible immediately after it moves--? print('source keychord')if Show_file_navigator thenkeychord_pressed_on_file_navigator(chord, key)returnendif chord == 'C-l' then--? print('C-l')Show_log_browser_side = not Show_log_browser_sideif Show_log_browser_side thenendfunction source.update(dt)Cursor_time = Cursor_time + dtif App.mouse_x() < Editor_state.right thenedit.update(Editor_state, dt)elseif Show_log_browser_side thenlog_browser.update(Log_browser_state, dt)endendfunction source.quit()edit.quit(Editor_state)log_browser.quit(Log_browser_state)-- convert any bifold files hereendfunction source.convert_bifold_text(infilename, outfilename)local contents = love.filesystem.read(infilename)contents = contents:gsub('\u{1e}', ';')love.filesystem.write(outfilename, contents)endfunction source.settings()if Current_app == 'source' then--? print('reading source window position')love.keyboard.setTextInput(true) -- bring up keyboard on touch screenlove.keyboard.setKeyRepeat(true)love.graphics.setBackgroundColor(1,1,1)if Settings and Settings.source thensource.load_settings()elsesource.initialize_default_settings()endsource.initialize_edit_side{'run.lua'}source.initialize_log_browser_side()Menu_status_bar_height = 5 + Editor_state.line_height + 5Editor_state.top = Editor_state.top + Menu_status_bar_heightLog_browser_state.top = Log_browser_state.top + Menu_status_bar_heightlog_render = {}File_navigation.candidates = File_navigation.all_candidates -- modified with filterfilter = '',}all_candidates = {Editor_state = {}-- called both in tests and real runfunction source.initialize_globals()-- tests currently mostly clear their own stateShow_log_browser_side = falseFocus = 'edit'Show_file_navigator = falseFile_navigation = { - file deletion: run.lua run.lua
log_new('run')love.keyboard.setTextInput(true) -- bring up keyboard on touch screenlove.keyboard.setKeyRepeat(true)love.graphics.setBackgroundColor(1,1,1)if Settings thenrun.load_settings()elserun.initialize_default_settings()endif #arg > 0 thenEditor_state.filename = arg[1]load_from_disk(Editor_state)Text.redraw_all(Editor_state)Editor_state.screen_top1 = {line=1, pos=1}Editor_state.cursor1 = {line=1, pos=1}edit.fixup_cursor(Editor_state)elseload_from_disk(Editor_state)Text.redraw_all(Editor_state)if Editor_state.cursor1.line > #Editor_state.lines or Editor_state.lines[Editor_state.cursor1.line].mode ~= 'text' thenedit.fixup_cursor(Editor_state)endendlove.window.setTitle('lines.love - '..Editor_state.filename)if #arg > 1 thenprint('ignoring commandline args after '..arg[1])endif rawget(_G, 'jit') thenjit.off()jit.flush()endendfunction run.load_settings()love.graphics.setFont(love.graphics.newFont(Settings.font_height))-- maximize window to determine maximum allowable dimensionsApp.screen.width, App.screen.height, App.screen.flags = love.window.getMode()-- set up desired window dimensions - file deletion: log_browser.lua log_browser.lua
local restline.filename, line.line_number, rest = line.data:match('%[string "([^:]*)"%]:([^:]*):%s*(.*)')if line.filename == nil thenendline.filename = guess_source(line.filename)line.line_number = tonumber(line.line_number)if line.data:sub(1,1) == '{' thenlocal data = json.decode(line.data)if log_render[data.name] thenline.data = dataendline.section_stack = table.shallowcopy(Section_stack)elseif line.data:match('\u{250c}') thenline.section_stack = table.shallowcopy(Section_stack) -- as it is at the beginninglocal section_name = line.data:match('\u{250c}%s*(.*)')table.insert(Section_stack, {name=section_name})line.section_begin = trueline.section_name = section_nameline.data = nilelseif line.data:match('\u{2518}') thenlocal section_name = line.data:match('\u{2518}%s*(.*)')if array.find(Section_stack, function(x) return x.name == section_name end) thenwhile table.remove(Section_stack).name ~= section_name do--endline.section_end = trueline.section_name = section_nameline.data = nilendline.section_stack = table.shallowcopy(Section_stack)else-- stringline.section_stack = table.shallowcopy(Section_stack)endelseline.section_stack = {}endendendfunction table.shallowcopy(x)return {unpack(x)}endfunction guess_source(filename)local possible_source = filename:gsub('%.lua$', '%.splua')if file_exists(possible_source) thenreturn possible_sourceelsereturn filenameendendfunction log_browser.draw(State)assert(#State.lines == #State.line_cache)local mouse_line_index = log_browser.line_index(State, App.mouse_x(), App.mouse_y())local y = State.topfor line_index = State.screen_top1.line,#State.lines doApp.color(Text_color)local line = State.lines[line_index]if y + State.line_height > App.screen.height then break endlocal height = State.line_heightif should_show(line) thenlocal xleft = render_stack_left_margin(State, line_index, line, y)local xright = render_stack_right_margin(State, line_index, line, y)if line.section_name thenApp.color(Section_border_color)local section_text = to_text(line.section_name)if line.section_begin thenlocal sectiony = y+Section_border_padding_verticallove.graphics.line(xleft,sectiony, xleft,y+State.line_height)love.graphics.line(xright,sectiony, xright,y+State.line_height)love.graphics.line(xleft,sectiony, xleft+50-2,sectiony)love.graphics.draw(section_text, xleft+50,y)love.graphics.line(xleft+50+App.width(section_text)+2,sectiony, xright,sectiony)else assert(line.section_end)local sectiony = y+State.line_height-Section_border_padding_verticallove.graphics.line(xleft,y, xleft,sectiony)love.graphics.line(xright,y, xright,sectiony)love.graphics.line(xleft,sectiony, xleft+50-2,sectiony)love.graphics.draw(section_text, xleft+50,y)love.graphics.line(xleft+50+App.width(section_text)+2,sectiony, xright,sectiony)endelseif type(line.data) == 'string' thenlocal old_left, old_right = State.left,State.rightState.left,State.right = xleft,xrighty = Text.draw(State, line_index, y, --[[startpos]] 1)State.left,State.right = old_left,old_rightelseheight = log_render[line.data.name](line.data, xleft, y, xright-xleft)endendif App.mouse_x() > Log_browser_state.left and line_index == mouse_line_index thenApp.color(Cursor_line_background_color)love.graphics.rectangle('fill', xleft,y, xright-xleft, height)endy = y + heightendendendfunction render_stack_left_margin(State, line_index, line, y)if line.section_stack == nil then-- assertion messagefor k,v in pairs(line) doprint(k)endendApp.color(Section_border_color)for i=1,#line.section_stack dolocal x = State.left + (i-1)*Section_border_padding_horizontallove.graphics.line(x,y, x,y+log_browser.height(State, line_index))if y < 30 thenlove.graphics.print(line.section_stack[i].name, x+State.font_height+5, y+5, --[[vertically]] math.pi/2)endif y > App.screen.height-log_browser.height(State, line_index) thenlove.graphics.print(line.section_stack[i].name, x+State.font_height+5, App.screen.height-App.width(to_text(line.section_stack[i].name))-5, --[[vertically]] math.pi/2)endendreturn log_browser.left_margin(State, line)endfunction render_stack_right_margin(State, line_index, line, y)App.color(Section_border_color)for i=1,#line.section_stack dolocal x = State.right - (i-1)*Section_border_padding_horizontallove.graphics.line(x,y, x,y+log_browser.height(State, line_index))if y < 30 thenlove.graphics.print(line.section_stack[i].name, x, y+5, --[[vertically]] math.pi/2)endif y > App.screen.height-log_browser.height(State, line_index) thenlove.graphics.print(line.section_stack[i].name, x, App.screen.height-App.width(to_text(line.section_stack[i].name))-5, --[[vertically]] math.pi/2)endendreturn log_browser.right_margin(State, line)endfunction should_show(line)-- Show a line if every single section it's in is expanded.for i=1,#line.section_stack dolocal section = line.section_stack[i]if not section.expanded thenreturn falseendendreturn trueendfunction log_browser.left_margin(State, line)return State.left + #line.section_stack*Section_border_padding_horizontalendfunction log_browser.right_margin(State, line)return State.right - #line.section_stack*Section_border_padding_horizontalendfunction log_browser.update(State, dt)endfunction log_browser.quit(State)endfunction log_browser.mouse_pressed(State, x,y, mouse_button)local line_index = log_browser.line_index(State, x,y)if line_index == nil then-- below lower marginreturnend-- leave some space to click without focusinglocal line = State.lines[line_index]local xleft = log_browser.left_margin(State, line)local xright = log_browser.right_margin(State, line)if x < xleft or x > xright thenreturnend-- if it's a section begin/end and the section is collapsed, expand it-- TODO: how to collapse?if line.section_begin or line.section_end then-- HACK: get section reference from next/previous linelocal new_sectionif line.section_begin thenif line_index < #State.lines thenlocal next_section_stack = State.lines[line_index+1].section_stackif next_section_stack thennew_section = next_section_stack[#next_section_stack]endendelseif line.section_end thenif line_index > 1 thenlocal previous_section_stack = State.lines[line_index-1].section_stackif previous_section_stack thennew_section = previous_section_stack[#previous_section_stack]endendendif new_section and new_section.expanded == nil thennew_section.expanded = truereturnendend-- open appropriate file in source sideif line.filename ~= Editor_state.filename thensource.switch_to_file(line.filename)end-- set cursorEditor_state.cursor1 = {line=line.line_number, pos=1, posB=nil}-- make sure it's visible-- TODO: handle extremely long linesEditor_state.screen_top1.line = math.max(0, Editor_state.cursor1.line-5)-- show cursorFocus = 'edit'-- expand B sideEditor_state.expanded = trueendfunction log_browser.line_index(State, mx,my)-- duplicate some logic from log_browser.drawlocal y = State.topfor line_index = State.screen_top1.line,#State.lines dolocal line = State.lines[line_index]if should_show(line) theny = y + log_browser.height(State, line_index)if my < y thenreturn line_indexendif y > App.screen.height then break endendendendfunction log_browser.mouse_released(State, x,y, mouse_button)endfunction log_browser.textinput(State, t)endfunction log_browser.keychord_pressed(State, chord, key)-- moveif chord == 'up' thenwhile State.screen_top1.line > 1 doState.screen_top1.line = State.screen_top1.line-1if should_show(State.lines[State.screen_top1.line]) thenbreakendendelseif chord == 'down' thenwhile State.screen_top1.line < #State.lines doState.screen_top1.line = State.screen_top1.line+1if should_show(State.lines[State.screen_top1.line]) thenbreakendendelseif chord == 'pageup' thenlocal y = 0while State.screen_top1.line > 1 and y < App.screen.height - 100 doState.screen_top1.line = State.screen_top1.line - 1if should_show(State.lines[State.screen_top1.line]) theny = y + log_browser.height(State, State.screen_top1.line)endendelseif chord == 'pagedown' thenlocal y = 0while State.screen_top1.line < #State.lines and y < App.screen.height - 100 doif should_show(State.lines[State.screen_top1.line]) theny = y + log_browser.height(State, State.screen_top1.line)endState.screen_top1.line = State.screen_top1.line + 1endendendfunction log_browser.height(State, line_index)local line = State.lines[line_index]if line.data == nil then-- section headerreturn State.line_heightelseif type(line.data) == 'string' thenreturn State.line_heightelseif line.height == nil then--? print('nil line height! rendering off screen to calculate')line.height = log_render[line.data.name](line.data, State.left, App.screen.height, State.right-State.left)endreturn line.heightendendfunction log_browser.keyreleased(State, key, scancode)endline.filename, line.line_number, rest = line.data:match('([^:]*):([^:]*):%s*(.*)')endif rest thenline.data = rest - file deletion: commands.lua commands.lua
App.screen.draw(s_text, Menu_cursor,5)App.screen.draw(s_text, x,y)x = x + width + 30return x,ylog_end('file index')return best_guessfunction textinput_on_file_navigator(t)File_navigation.filter = File_navigation.filter..tFile_navigation.candidates = source.file_navigator_candidates()endendif y == fy thenlog(2, ('%d: correct row; considering %d %s %d %d'):format(y, i, filename, x, width))if best_guess == nil thenlog(2, 'nil')best_guess = ibest_guess_x = xbest_guess_width = widthelseif math.abs(fx + fwidth/2 - x - width/2) < math.abs(fx + fwidth/2 - best_guess_x - best_guess_width/2) thenbest_guess = ibest_guess_x = xbest_guess_width = widthendlog(2, ('best guess now %d %s %d %d'):format(best_guess, File_navigation.candidates[best_guess], best_guess_x, best_guess_width))endx = x + width + 30endendelseif chord == 'down' thenfile_navigator_down()elseif chord == 'up' thenfile_navigator_up()endendfunction log_render.file_navigator_state(o, x,y, w)-- duplicate structure of source.draw_file_navigatorlocal num_lines = source.num_lines_for_file_navigator(o.files)local h = num_lines * Editor_state.line_heightApp.color(Menu_background_color)love.graphics.rectangle('fill', x,y, w,h)-- compute the x,y,width of the current index (in offsets from top left)local x2,y2 = 0,0local width = 0for i,filename in ipairs(o.files) dolocal filename_text = to_text(filename)width = App.width(filename_text)if x2 + width > App.screen.width - 5 theny2 = y2 + Editor_state.line_heightx2 = 0endif i == o.index thenbreakendx2 = x2 + width + 30end-- figure out how much of the menu to displaylocal menu_xmin = math.max(0, x2-w/2)local menu_xmax = math.min(App.screen.width, x2+w/2)-- now selectively print out entrieslocal x3,y3 = 0,y -- x3 is relative, y3 is absolutelocal width = 0for i,filename in ipairs(o.files) dolocal filename_text = to_text(filename)width = App.width(filename_text)if x3 + width > App.screen.width - 5 theny3 = y3 + Editor_state.line_heightx3 = 0endif i == o.index thenApp.color(Menu_highlight_color)love.graphics.rectangle('fill', x + x3-menu_xmin - 5, y3-2, width+5*2, Editor_state.line_height+2*2)endif x3 >= menu_xmin and x3 + width < menu_xmax thenApp.color(Menu_command_color)App.screen.draw(filename_text, x + x3-menu_xmin, y3)endx3 = x3 + width + 30end--return h+20endfunction file_navigator_up()local y, x, width = file_coord(File_navigation.index)local index = file_index(y-Editor_state.line_height, x, width)if index thenFile_navigation.index = indexendendfunction file_navigator_down()local y, x, width = file_coord(File_navigation.index)local index = file_index(y+Editor_state.line_height, x, width)if index thenFile_navigation.index = indexendendfunction file_coord(index)local y,x = Menu_status_bar_height, 5for i,filename in ipairs(File_navigation.candidates) dolocal width = App.width(to_text(filename))if x + width > App.screen.width - 5 theny = y + Editor_state.line_heightx = 5endif i == index thenreturn y, x, widthendx = x + width + 30endendfunction file_index(fy, fx, fwidth)log_start('file index')log(2, ('for %d %d %d'):format(fy, fx, fwidth))local y,x = Menu_status_bar_height, 5local best_guess, best_guess_x, best_guess_widthfor i,filename in ipairs(File_navigation.candidates) dolocal width = App.width(to_text(filename))if x + width > App.screen.width - 5 theny = y + Editor_state.line_heightx = 5endlog(2, 'file navigator: '..chord)log(2, {name='file_navigator_state', files=File_navigation.candidates, index=File_navigation.index})File_navigation.index = 1File_navigation.filter = ''File_navigation.candidates = File_navigation.all_candidateselseif chord == 'backspace' thenlocal len = utf8.len(File_navigation.filter)local byte_offset = Text.offset(File_navigation.filter, len)File_navigation.filter = string.sub(File_navigation.filter, 1, byte_offset-1)File_navigation.index = 1File_navigation.candidates = source.file_navigator_candidates()elseif chord == 'left' thenif File_navigation.index > 1 thenFile_navigation.index = File_navigation.index-1endelseif chord == 'right' thenif File_navigation.index < #File_navigation.candidates thenFile_navigation.index = File_navigation.index+1File_navigation.index = 1File_navigation.filter = ''File_navigation.candidates = File_navigation.all_candidateselseif chord == 'return' thenlocal candidate = guess_source(File_navigation.candidates[File_navigation.index]..'.lua')source.switch_to_file(candidate)Show_file_navigator = falseif chord == 'escape' thenShow_file_navigator = falseendfunction keychord_pressed_on_file_navigator(chord, key)App.color(Menu_command_color)local filter_text = to_text(File_navigation.filter)App.screen.draw(filter_text, 5, 5)draw_cursor(5 + App.width(filter_text), 5)local s_text = to_text(s)local width = App.width(s_text)if x + width > App.screen.width - 5 theny = y + Editor_state.line_heightx = 5endbutton(Editor_state, 'menu', {x=x-5, y=y-2, w=width+5*2, h=Editor_state.line_height+2*2, color=colortable(color),onpress1 = function()local candidate = guess_source(s..'.lua')source.switch_to_file(candidate)Show_file_navigator = falseend})App.color(Menu_command_color)local color = Menu_background_colorcolor = Menu_highlight_colorendif cursor_highlight thenif File_navigation.num_lines == nil thenendApp.color(Menu_background_color)local x,y = 5, Menu_status_bar_heightlove.graphics.rectangle('fill', 0,Menu_status_bar_height, App.screen.width, File_navigation.num_lines * Editor_state.line_height + --[[highlight padding]] 2)File_navigation.num_lines = source.num_lines_for_file_navigator(File_navigation.candidates)if Menu_cursor >= App.screen.width - 5 thenbreakendendendfunction draw_cursor(x, y)-- blink every 0.5sif math.floor(Cursor_time*2)%2 == 0 thenApp.color(Cursor_color)love.graphics.rectangle('fill', x,y, 3,Editor_state.line_height)endendfunction source.file_navigator_candidates()if File_navigation.filter == '' thenreturn File_navigation.all_candidatesendlocal result = {}for _,filename in ipairs(File_navigation.all_candidates) doif starts_with(filename, File_navigation.filter) thentable.insert(result, filename)endreturn resultendlocal result = 1local x = 5endreturn resultendfunction add_file_to_menu(x,y, s, cursor_highlight)local width = App.width(to_text(filename))if x + width > App.screen.width - 5 thenresult = result+1x = 5 + widthelsex = x + width + 30endfor i,filename in ipairs(candidates) dofunction source.num_lines_for_file_navigator(candidates)endfor i,filename in ipairs(File_navigation.candidates) doif filename == 'source' thenx,y = add_file_to_menu(x,y, filename, i == File_navigation.index)App.color(Menu_border_color)love.graphics.line(Menu_cursor-10,2, Menu_cursor-10,Menu_status_bar_height-2)endMenu_cursor = Menu_cursor + width + 30endfunction source.draw_file_navigator()local s_text = to_text(s)local width = App.width(s_text)if Menu_cursor + width > App.screen.width - 5 thenreturnendApp.color(Menu_command_color) - replacement in source_text.lua at line 7
function Text.draw(State, line_index, y, startpos, startposB)function Text.draw(State, line_index, y, startpos, startposB, hide_cursor) - replacement in source_text.lua at line 21
if State.search_term == nil thenif not hide_cursor and not State.search_term then - replacement in source_text.lua at line 67
if State.search_term == nil thenif not hide_cursor and not State.search_term then - replacement in source_edit.lua at line 127
function edit.draw(State)function edit.draw(State, hide_cursor) - replacement in source_edit.lua at line 173
y, State.screen_bottom1.pos, State.screen_bottom1.posB = Text.draw(State, line_index, y, startpos, startposB)y, State.screen_bottom1.pos, State.screen_bottom1.posB = Text.draw(State, line_index, y, startpos, startposB, hide_cursor) - edit in source.lua at line 2
log_render = {} - replacement in source.lua at line 14
candidates = {all_candidates = { - edit in source.lua at line 47
filter = '', - edit in source.lua at line 49
File_navigation.candidates = File_navigation.all_candidates -- modified with filter - edit in source.lua at line 62
log_new('source') - replacement in source.lua at line 226
source.draw_menu_bar()edit.draw(Editor_state)edit.draw(Editor_state, --[[hide cursor?]] Show_file_navigator) - edit in source.lua at line 234
source.draw_menu_bar() - edit in source.lua at line 311
if Show_file_navigator thentextinput_on_file_navigator(t)returnend - edit in source.lua at line 352
File_navigation.index = 1 - edit in run.lua at line 18
log_new('run') - edit in main.lua at line 29
- resurrect zombie in main.lua at line 29
log_new('session') - resolve order conflict in main.lua at line 29
- replacement in log_browser.lua at line 30
line.filename, line.line_number, line.data = line.data:match('%[string "([^:]*)"%]:([^:]*):%s*(.*)')local restline.filename, line.line_number, rest = line.data:match('%[string "([^:]*)"%]:([^:]*):%s*(.*)')if line.filename == nil thenline.filename, line.line_number, rest = line.data:match('([^:]*):([^:]*):%s*(.*)')endif rest thenline.data = restend - replacement in commands.lua at line 45
if Text_cache[s] == nil thenText_cache[s] = App.newText(love.graphics.getFont(), s)endlocal width = App.width(Text_cache[s])local s_text = to_text(s)local width = App.width(s_text) - replacement in commands.lua at line 51
App.screen.draw(Text_cache[s], Menu_cursor,5)App.screen.draw(s_text, Menu_cursor,5) - replacement in commands.lua at line 56
for i,file in ipairs(File_navigation.candidates) doif file == 'source' thenApp.color(Menu_command_color)local filter_text = to_text(File_navigation.filter)App.screen.draw(filter_text, 5, 5)draw_cursor(5 + App.width(filter_text), 5)if File_navigation.num_lines == nil thenFile_navigation.num_lines = source.num_lines_for_file_navigator(File_navigation.candidates)endApp.color(Menu_background_color)love.graphics.rectangle('fill', 0,Menu_status_bar_height, App.screen.width, File_navigation.num_lines * Editor_state.line_height + --[[highlight padding]] 2)local x,y = 5, Menu_status_bar_heightfor i,filename in ipairs(File_navigation.candidates) doif filename == 'source' then - replacement in commands.lua at line 71
add_file_to_menu(file, i == File_navigation.index)x,y = add_file_to_menu(x,y, filename, i == File_navigation.index)if Menu_cursor >= App.screen.width - 5 thenbreakend - replacement in commands.lua at line 78
function add_file_to_menu(s, cursor_highlight)if Text_cache[s] == nil thenText_cache[s] = App.newText(love.graphics.getFont(), s)function draw_cursor(x, y)-- blink every 0.5sif math.floor(Cursor_time*2)%2 == 0 thenApp.color(Cursor_color)love.graphics.rectangle('fill', x,y, 3,Editor_state.line_height) - replacement in commands.lua at line 84
local width = App.width(Text_cache[s])if Menu_cursor + width > App.screen.width - 5 thenreturnendfunction source.file_navigator_candidates()if File_navigation.filter == '' thenreturn File_navigation.all_candidatesendlocal result = {}for _,filename in ipairs(File_navigation.all_candidates) doif starts_with(filename, File_navigation.filter) thentable.insert(result, filename)endendreturn resultendfunction source.num_lines_for_file_navigator(candidates)local result = 1local x = 5for i,filename in ipairs(candidates) dolocal width = App.width(to_text(filename))if x + width > App.screen.width - 5 thenresult = result+1x = 5 + widthelsex = x + width + 30endendreturn resultendfunction add_file_to_menu(x,y, s, cursor_highlight)local s_text = to_text(s)local width = App.width(s_text)if x + width > App.screen.width - 5 theny = y + Editor_state.line_heightx = 5 - edit in commands.lua at line 121
local color = Menu_background_color - replacement in commands.lua at line 123
App.color(Menu_highlight_color)love.graphics.rectangle('fill', Menu_cursor-5,5-2, App.width(Text_cache[s])+5*2,Editor_state.line_height+2*2)color = Menu_highlight_color - edit in commands.lua at line 125
button(Editor_state, 'menu', {x=x-5, y=y-2, w=width+5*2, h=Editor_state.line_height+2*2, color=colortable(color),onpress1 = function()local candidate = guess_source(s..'.lua')source.switch_to_file(candidate)Show_file_navigator = falseend}) - replacement in commands.lua at line 133
App.screen.draw(Text_cache[s], Menu_cursor,5)Menu_cursor = Menu_cursor + width + 30App.screen.draw(s_text, x,y)x = x + width + 30return x,y - edit in commands.lua at line 139
log(2, 'file navigator: '..chord)log(2, {name='file_navigator_state', files=File_navigation.candidates, index=File_navigation.index}) - edit in commands.lua at line 143
File_navigation.index = 1File_navigation.filter = ''File_navigation.candidates = File_navigation.all_candidates - edit in commands.lua at line 150
File_navigation.index = 1File_navigation.filter = ''File_navigation.candidates = File_navigation.all_candidateselseif chord == 'backspace' thenlocal len = utf8.len(File_navigation.filter)local byte_offset = Text.offset(File_navigation.filter, len)File_navigation.filter = string.sub(File_navigation.filter, 1, byte_offset-1)File_navigation.index = 1File_navigation.candidates = source.file_navigator_candidates() - edit in commands.lua at line 167
elseif chord == 'down' thenfile_navigator_down()elseif chord == 'up' thenfile_navigator_up() - edit in commands.lua at line 173[9.207181]
function log_render.file_navigator_state(o, x,y, w)-- duplicate structure of source.draw_file_navigatorlocal num_lines = source.num_lines_for_file_navigator(o.files)local h = num_lines * Editor_state.line_heightApp.color(Menu_background_color)love.graphics.rectangle('fill', x,y, w,h)-- compute the x,y,width of the current index (in offsets from top left)local x2,y2 = 0,0local width = 0for i,filename in ipairs(o.files) dolocal filename_text = to_text(filename)width = App.width(filename_text)if x2 + width > App.screen.width - 5 theny2 = y2 + Editor_state.line_heightx2 = 0endif i == o.index thenbreakendx2 = x2 + width + 30end-- figure out how much of the menu to displaylocal menu_xmin = math.max(0, x2-w/2)local menu_xmax = math.min(App.screen.width, x2+w/2)-- now selectively print out entrieslocal x3,y3 = 0,y -- x3 is relative, y3 is absolutelocal width = 0for i,filename in ipairs(o.files) dolocal filename_text = to_text(filename)width = App.width(filename_text)if x3 + width > App.screen.width - 5 theny3 = y3 + Editor_state.line_heightx3 = 0endif i == o.index thenApp.color(Menu_highlight_color)love.graphics.rectangle('fill', x + x3-menu_xmin - 5, y3-2, width+5*2, Editor_state.line_height+2*2)endif x3 >= menu_xmin and x3 + width < menu_xmax thenApp.color(Menu_command_color)App.screen.draw(filename_text, x + x3-menu_xmin, y3)endx3 = x3 + width + 30end--return h+20endfunction file_navigator_up()local y, x, width = file_coord(File_navigation.index)local index = file_index(y-Editor_state.line_height, x, width)if index thenFile_navigation.index = indexendendfunction file_navigator_down()local y, x, width = file_coord(File_navigation.index)local index = file_index(y+Editor_state.line_height, x, width)if index thenFile_navigation.index = indexendendfunction file_coord(index)local y,x = Menu_status_bar_height, 5for i,filename in ipairs(File_navigation.candidates) dolocal width = App.width(to_text(filename))if x + width > App.screen.width - 5 theny = y + Editor_state.line_heightx = 5endif i == index thenreturn y, x, widthendx = x + width + 30endendfunction file_index(fy, fx, fwidth)log_start('file index')log(2, ('for %d %d %d'):format(fy, fx, fwidth))local y,x = Menu_status_bar_height, 5local best_guess, best_guess_x, best_guess_widthfor i,filename in ipairs(File_navigation.candidates) dolocal width = App.width(to_text(filename))if x + width > App.screen.width - 5 theny = y + Editor_state.line_heightx = 5endif y == fy thenlog(2, ('%d: correct row; considering %d %s %d %d'):format(y, i, filename, x, width))if best_guess == nil thenlog(2, 'nil')best_guess = ibest_guess_x = xbest_guess_width = widthelseif math.abs(fx + fwidth/2 - x - width/2) < math.abs(fx + fwidth/2 - best_guess_x - best_guess_width/2) thenbest_guess = ibest_guess_x = xbest_guess_width = widthendlog(2, ('best guess now %d %s %d %d'):format(best_guess, File_navigation.candidates[best_guess], best_guess_x, best_guess_width))endx = x + width + 30endlog_end('file index')return best_guessendfunction textinput_on_file_navigator(t)File_navigation.filter = File_navigation.filter..tFile_navigation.candidates = source.file_navigator_candidates()end