about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-09-18 01:56:42 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-09-18 01:56:42 -0700
commitf6596832fd50b3c640b5ed0707ddd0fda845d75e (patch)
tree94a7da182fb6391f98196ba55eb4264593e57801
parentcb261f56b2e6cad297921a4d4457c0fbf2d78103 (diff)
parentcf227f9031a6b8a9186b534bc51425655a7e0970 (diff)
downloadview.love-f6596832fd50b3c640b5ed0707ddd0fda845d75e.tar.gz
Merge lines.love
-rw-r--r--app.lua4
-rw-r--r--commands.lua223
-rw-r--r--log_browser.lua9
-rw-r--r--main.lua1
-rw-r--r--run.lua1
-rw-r--r--source.lua15
-rw-r--r--source_edit.lua4
-rw-r--r--source_text.lua6
8 files changed, 235 insertions, 28 deletions
diff --git a/app.lua b/app.lua
index 994f0c7..62ecd38 100644
--- a/app.lua
+++ b/app.lua
@@ -194,6 +194,10 @@ function App.color(color)
   love.graphics.setColor(color.r, color.g, color.b, color.a)
 end
 
+function colortable(app_color)
+  return {app_color.r, app_color.g, app_color.b, app_color.a}
+end
+
 App.time = 1
 function App.getTime()
   return App.time
diff --git a/commands.lua b/commands.lua
index be9c9bf..583d1ef 100644
--- a/commands.lua
+++ b/commands.lua
@@ -42,52 +42,120 @@ function source.draw_menu_bar()
 end
 
 function add_hotkey_to_menu(s)
-  if Text_cache[s] == nil then
-    Text_cache[s] = App.newText(love.graphics.getFont(), s)
-  end
-  local width = App.width(Text_cache[s])
+  local s_text = to_text(s)
+  local width = App.width(s_text)
   if Menu_cursor + width > App.screen.width - 5 then
     return
   end
   App.color(Menu_command_color)
-  App.screen.draw(Text_cache[s], Menu_cursor,5)
+  App.screen.draw(s_text, Menu_cursor,5)
   Menu_cursor = Menu_cursor + width + 30
 end
 
 function source.draw_file_navigator()
-  for i,file in ipairs(File_navigation.candidates) do
-    if file == 'source' then
+  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)
+  if File_navigation.num_lines == nil then
+    File_navigation.num_lines = source.num_lines_for_file_navigator(File_navigation.candidates)
+  end
+  App.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_height
+  for i,filename in ipairs(File_navigation.candidates) do
+    if filename == 'source' then
       App.color(Menu_border_color)
       love.graphics.line(Menu_cursor-10,2, Menu_cursor-10,Menu_status_bar_height-2)
     end
-    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 then
+      break
+    end
   end
 end
 
-function add_file_to_menu(s, cursor_highlight)
-  if Text_cache[s] == nil then
-    Text_cache[s] = App.newText(love.graphics.getFont(), s)
+function draw_cursor(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,Editor_state.line_height)
   end
-  local width = App.width(Text_cache[s])
-  if Menu_cursor + width > App.screen.width - 5 then
-    return
+end
+
+function source.file_navigator_candidates()
+  if File_navigation.filter == '' then
+    return File_navigation.all_candidates
+  end
+  local result = {}
+  for _,filename in ipairs(File_navigation.all_candidates) do
+    if starts_with(filename, File_navigation.filter) then
+      table.insert(result, filename)
+    end
   end
+  return result
+end
+
+function source.num_lines_for_file_navigator(candidates)
+  local result = 1
+  local x = 5
+  for i,filename in ipairs(candidates) do
+    local width = App.width(to_text(filename))
+    if x + width > App.screen.width - 5 then
+      result = result+1
+      x = 5 + width
+    else
+      x = x + width + 30
+    end
+  end
+  return result
+end
+
+function 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 then
+    y = y + Editor_state.line_height
+    x = 5
+  end
+  local color = Menu_background_color
   if cursor_highlight then
-    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
   end
+  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 = false
+    end
+  })
   App.color(Menu_command_color)
-  App.screen.draw(Text_cache[s], Menu_cursor,5)
-  Menu_cursor = Menu_cursor + width + 30
+  App.screen.draw(s_text, x,y)
+  x = x + width + 30
+  return x,y
 end
 
 function keychord_pressed_on_file_navigator(chord, key)
+  log(2, 'file navigator: '..chord)
+  log(2, {name='file_navigator_state', files=File_navigation.candidates, index=File_navigation.index})
   if chord == 'escape' then
     Show_file_navigator = false
+    File_navigation.index = 1
+    File_navigation.filter = ''
+    File_navigation.candidates = File_navigation.all_candidates
   elseif chord == 'return' then
     local candidate = guess_source(File_navigation.candidates[File_navigation.index]..'.lua')
     source.switch_to_file(candidate)
     Show_file_navigator = false
+    File_navigation.index = 1
+    File_navigation.filter = ''
+    File_navigation.candidates = File_navigation.all_candidates
+  elseif chord == 'backspace' then
+    local 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 = 1
+    File_navigation.candidates = source.file_navigator_candidates()
   elseif chord == 'left' then
     if File_navigation.index > 1 then
       File_navigation.index = File_navigation.index-1
@@ -96,5 +164,124 @@ function keychord_pressed_on_file_navigator(chord, key)
     if File_navigation.index < #File_navigation.candidates then
       File_navigation.index = File_navigation.index+1
     end
+  elseif chord == 'down' then
+    file_navigator_down()
+  elseif chord == 'up' then
+    file_navigator_up()
   end
 end
+
+function log_render.file_navigator_state(o, x,y, w)
+  -- duplicate structure of source.draw_file_navigator
+  local num_lines = source.num_lines_for_file_navigator(o.files)
+  local h = num_lines * Editor_state.line_height
+  App.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,0
+  local width = 0
+  for i,filename in ipairs(o.files) do
+    local filename_text = to_text(filename)
+    width = App.width(filename_text)
+    if x2 + width > App.screen.width - 5 then
+      y2 = y2 + Editor_state.line_height
+      x2 = 0
+    end
+    if i == o.index then
+      break
+    end
+    x2 = x2 + width + 30
+  end
+  -- figure out how much of the menu to display
+  local menu_xmin = math.max(0, x2-w/2)
+  local menu_xmax = math.min(App.screen.width, x2+w/2)
+  -- now selectively print out entries
+  local x3,y3 = 0,y  -- x3 is relative, y3 is absolute
+  local width = 0
+  for i,filename in ipairs(o.files) do
+    local filename_text = to_text(filename)
+    width = App.width(filename_text)
+    if x3 + width > App.screen.width - 5 then
+      y3 = y3 + Editor_state.line_height
+      x3 = 0
+    end
+    if i == o.index then
+      App.color(Menu_highlight_color)
+      love.graphics.rectangle('fill', x + x3-menu_xmin - 5, y3-2, width+5*2, Editor_state.line_height+2*2)
+    end
+    if x3 >= menu_xmin and x3 + width < menu_xmax then
+      App.color(Menu_command_color)
+      App.screen.draw(filename_text, x + x3-menu_xmin, y3)
+    end
+    x3 = x3 + width + 30
+  end
+  --
+  return h+20
+end
+
+function 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 then
+    File_navigation.index = index
+  end
+end
+
+function 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 then
+    File_navigation.index = index
+  end
+end
+
+function file_coord(index)
+  local y,x = Menu_status_bar_height, 5
+  for i,filename in ipairs(File_navigation.candidates) do
+    local width = App.width(to_text(filename))
+    if x + width > App.screen.width - 5 then
+      y = y + Editor_state.line_height
+      x = 5
+    end
+    if i == index then
+    return y, x, width
+    end
+    x = x + width + 30
+  end
+end
+
+function 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, 5
+  local best_guess, best_guess_x, best_guess_width
+  for i,filename in ipairs(File_navigation.candidates) do
+    local width = App.width(to_text(filename))
+    if x + width > App.screen.width - 5 then
+      y = y + Editor_state.line_height
+      x = 5
+    end
+    if y == fy then
+      log(2, ('%d: correct row; considering %d %s %d %d'):format(y, i, filename, x, width))
+      if best_guess == nil then
+        log(2, 'nil')
+        best_guess = i
+        best_guess_x = x
+        best_guess_width = width
+      elseif math.abs(fx + fwidth/2 - x - width/2) < math.abs(fx + fwidth/2 - best_guess_x - best_guess_width/2) then
+        best_guess = i
+        best_guess_x = x
+        best_guess_width = width
+      end
+      log(2, ('best guess now %d %s %d %d'):format(best_guess, File_navigation.candidates[best_guess], best_guess_x, best_guess_width))
+    end
+    x = x + width + 30
+  end
+  log_end('file index')
+  return best_guess
+end
+
+function textinput_on_file_navigator(t)
+  File_navigation.filter = File_navigation.filter..t
+  File_navigation.candidates = source.file_navigator_candidates()
+end
diff --git a/log_browser.lua b/log_browser.lua
index f65117f..91f02eb 100644
--- a/log_browser.lua
+++ b/log_browser.lua
@@ -27,7 +27,14 @@ log_browser = {}
 function log_browser.parse(State)
   for _,line in ipairs(State.lines) do
     if line.data ~= '' then
-      line.filename, line.line_number, line.data = line.data:match('%[string "([^:]*)"%]:([^:]*):%s*(.*)')
+      local rest
+      line.filename, line.line_number, rest = line.data:match('%[string "([^:]*)"%]:([^:]*):%s*(.*)')
+      if line.filename == nil then
+        line.filename, line.line_number, rest = line.data:match('([^:]*):([^:]*):%s*(.*)')
+      end
+      if rest then
+        line.data = rest
+      end
       line.filename = guess_source(line.filename)
       line.line_number = tonumber(line.line_number)
       if line.data:sub(1,1) == '{' then
diff --git a/main.lua b/main.lua
index 8e926c8..87b867f 100644
--- a/main.lua
+++ b/main.lua
@@ -26,6 +26,7 @@ load_file_from_source_or_save_directory('log.lua')
 
 -- but some files we want to only load sometimes
 function App.load()
+  log_new('session')
   if love.filesystem.getInfo('config') then
     Settings = json.decode(love.filesystem.read('config'))
     Current_app = Settings.current_app
diff --git a/run.lua b/run.lua
index e395978..8d03aa2 100644
--- a/run.lua
+++ b/run.lua
@@ -15,6 +15,7 @@ end
 
 -- called only for real run
 function run.initialize(arg)
+  log_new('run')
   love.keyboard.setTextInput(true)  -- bring up keyboard on touch screen
   love.keyboard.setKeyRepeat(true)
 
diff --git a/source.lua b/source.lua
index a259494..c763994 100644
--- a/source.lua
+++ b/source.lua
@@ -1,4 +1,5 @@
 source = {}
+log_render = {}
 
 Editor_state = {}
 
@@ -10,7 +11,7 @@ function source.initialize_globals()
   Focus = 'edit'
   Show_file_navigator = false
   File_navigation = {
-    candidates = {
+    all_candidates = {
       'run',
       'run_tests',
       'log',
@@ -43,7 +44,9 @@ function source.initialize_globals()
       'json',
     },
     index = 1,
+    filter = '',
   }
+  File_navigation.candidates = File_navigation.all_candidates  -- modified with filter
 
   Menu_status_bar_height = 5 + --[[line height in tests]] 15 + 5
 
@@ -56,6 +59,7 @@ end
 
 -- called only for real run
 function source.initialize()
+  log_new('source')
   love.keyboard.setTextInput(true)  -- bring up keyboard on touch screen
   love.keyboard.setKeyRepeat(true)
 
@@ -219,8 +223,7 @@ function source.switch_to_file(filename)
 end
 
 function source.draw()
-  source.draw_menu_bar()
-  edit.draw(Editor_state)
+  edit.draw(Editor_state, --[[hide cursor?]] Show_file_navigator)
   if Show_log_browser_side then
     -- divider
     App.color(Divider_color)
@@ -228,6 +231,7 @@ function source.draw()
     --
     log_browser.draw(Log_browser_state)
   end
+  source.draw_menu_bar()
 end
 
 function source.update(dt)
@@ -304,6 +308,10 @@ end
 
 function source.textinput(t)
   Cursor_time = 0  -- ensure cursor is visible immediately after it moves
+  if Show_file_navigator then
+    textinput_on_file_navigator(t)
+    return
+  end
   if Focus == 'edit' then
     return edit.textinput(Editor_state, t)
   else
@@ -341,7 +349,6 @@ function source.keychord_pressed(chord, key)
   end
   if chord == 'C-g' then
     Show_file_navigator = true
-    File_navigation.index = 1
     return
   end
   if Focus == 'edit' then
diff --git a/source_edit.lua b/source_edit.lua
index c17ce26..4f55083 100644
--- a/source_edit.lua
+++ b/source_edit.lua
@@ -124,7 +124,7 @@ function edit.fixup_cursor(State)
   end
 end
 
-function edit.draw(State)
+function edit.draw(State, hide_cursor)
   State.button_handlers = {}
   App.color(Text_color)
   if #State.lines ~= #State.line_cache then
@@ -170,7 +170,7 @@ function edit.draw(State)
                      end,
         })
       end
-      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)
       y = y + State.line_height
 --?       print('=> y', y)
     elseif line.mode == 'drawing' then
diff --git a/source_text.lua b/source_text.lua
index 5959fd5..3e70343 100644
--- a/source_text.lua
+++ b/source_text.lua
@@ -4,7 +4,7 @@ AB_padding = 20  -- space in pixels between A side and B side
 
 -- draw a line starting from startpos to screen at y between State.left and State.right
 -- return the final y, and pos,posB of start of final screen line drawn
-function Text.draw(State, line_index, y, startpos, startposB)
+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 = y
@@ -18,7 +18,7 @@ function Text.draw(State, line_index, y, startpos, startposB)
       return y, screen_line_starting_pos
     end
     if Focus == 'edit' and State.cursor1.pos then
-      if State.search_term == nil then
+      if not hide_cursor and not State.search_term then
         if line_index == State.cursor1.line and State.cursor1.pos == pos then
           Text.draw_cursor(State, x, y)
         end
@@ -64,7 +64,7 @@ function Text.draw(State, line_index, y, startpos, startposB)
 --?   if line_index == 8 then print('a') end
   if Focus == 'edit' and State.cursor1.posB then
 --?     if line_index == 8 then print('b') end
-    if State.search_term == nil then
+    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) end
       if line_index == State.cursor1.line and State.cursor1.posB == pos then
         Text.draw_cursor(State, x, y)