pensieve.love/commands.lua

725 lines
22 KiB
Lua
Raw Normal View History

Recently_modified_lookback_window = 30
Opposite = {
next='previous',
previous='next',
child='parent',
parent='child',
}
-- Candidate commands to show in in the command palette in different contexts.
-- Ideally we'd have rules for:
-- contexts to show a command at
-- order in which to show commands for each context
-- But I don't want to design that, so I'm just going to embrace a
-- combinatorial explosion of duplication for a while.
2022-07-28 04:29:41 +00:00
Commands = {
normal={
'capture',
'edit note at cursor (ctrl+e)',
'maximize note',
'close column surrounding cursor',
'add (___) (create immediately link)',
'step (___) (open link in new column)',
'extract (open note in new column)',
'unroll (___) (repeatedly step from cursor)',
'append (___) (add link after repeatedly stepping from cursor)',
'down one pane (ctrl+down)',
'up one pane (ctrl+up)',
'top pane of column (ctrl+home)',
'bottom pane of column (ctrl+end)',
'wider columns (X)',
'narrower columns (x)',
'recently modified',
2022-07-31 05:10:32 +00:00
'open file ___',
'reload all',
'delete note at cursor from disk (if possible)',
'search (all notes)',
'/ (find on screen)',
},
editable={
'exit editing (ctrl+e)',
'capture',
'maximize note',
'close column surrounding cursor',
'add (___) (create immediately link)',
'step (___) (open link in new column)',
'unroll (___) (repeatedly step from cursor)',
'append (___) (add link after repeatedly stepping from cursor)',
'down one pane (ctrl+down)',
'up one pane (ctrl+up)',
'top pane of column (ctrl+home)',
'bottom pane of column (ctrl+end)',
'wider columns (X)',
'narrower columns (x)',
'recently modified',
'reload all',
'search (all notes)',
'/ (find on screen)',
},
maximized={
'back to surface',
'edit note at cursor (ctrl+e)',
'reload note at cursor from disk',
'/ (find on screen)',
},
maximized_editable={
'exit editing (ctrl+e)',
'back to surface',
'reload note at cursor from disk',
'search (all notes)',
'/ (find on screen)',
},
2022-07-28 04:29:41 +00:00
}
-- We incrementally create the menu based on context. Menu_cursor tracks how
-- far along the screen width we've gotten.
Menu_cursor = 0
Palette_cursor = {y=0, x=0}
function draw_menu_bar()
if App.run_tests then return end -- disable in tests
App.color(Command_palette_background_color)
love.graphics.rectangle('fill', 0,0, App.screen.width, Menu_status_bar_height)
App.color(Command_palette_border_color)
love.graphics.rectangle('line', 0,0, App.screen.width, Menu_status_bar_height)
if Display_settings.show_palette then
return
end
App.color(Command_palette_command_color)
love.graphics.print('ctrl+enter: search commands...', 5,5)
App.color(Command_palette_border_color)
Menu_cursor = 360
love.graphics.line(Menu_cursor-10,2, Menu_cursor-10,Menu_status_bar_height-2)
if Display_settings.mode == 'normal' then
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
if not pane.editable then
local left_sx = left_edge_sx(Cursor_pane.col)
local up_sy = up_edge_sy(Cursor_pane.col, Cursor_pane.row)
if overlap(left_sx, left_sx+Display_settings.column_width, Display_settings.x, Display_settings.x+App.screen.width)
and overlap(up_sy, up_sy+pane.height, Display_settings.y, Display_settings.y+App.screen.height-Header_height) then
add_hotkey_to_menu('ctrl+e: edit')
add_panning_hotkeys_to_menu()
end
add_hotkey_to_menu('x/X: narrower/wider columns')
else
if pane.cursor_x >= 0 and pane.cursor_x < App.screen.width and pane.cursor_y >= Header_height and pane.cursor_y < App.screen.height then
add_hotkey_to_menu('ctrl+e: stop editing')
else
add_panning_hotkeys_to_menu()
end
end
end
add_hotkey_to_menu('ctrl+= ctrl+- ctrl+0: zoom')
end
function add_panning_hotkeys_to_menu()
add_hotkey_to_menu('arrows shift+arrows ctrl+up/down: pan')
end
function add_hotkey_to_menu(s)
if Menu_text_cache[s] == nil then
Menu_text_cache[s] = App.newText(love.graphics.getFont(), s)
end
local width = App.width(Menu_text_cache[s])
if Menu_cursor + width > App.screen.width - 5 then
return
end
App.color(Command_palette_command_color)
App.screen.draw(Menu_text_cache[s], Menu_cursor,5)
Menu_cursor = Menu_cursor + width + 30
end
-- unused
function draw_maximized_mode_menu_bar(left, right)
App.color(Command_palette_background_color)
love.graphics.rectangle('fill', left-Margin_left,0, Margin_left+right-left+Margin_right, Menu_status_bar_height)
App.color(Command_palette_border_color)
love.graphics.rectangle('line', left-Margin_left,0, Margin_left+right-left+Margin_right, Menu_status_bar_height)
end
2022-08-04 04:03:12 +00:00
function keychord_pressed_on_command_palette(chord, key)
2022-07-24 04:00:49 +00:00
if chord == 'escape' then
Display_settings.show_palette = false
-- don't forget text in case we want to continue it
2022-07-24 04:00:49 +00:00
elseif chord == 'backspace' then
local len = utf8.len(Display_settings.palette)
local byte_offset = Text.offset(Display_settings.palette, len)
Display_settings.palette = string.sub(Display_settings.palette, 1, byte_offset-1)
Display_settings.palette_text = App.newText(love.graphics.getFont(), Display_settings.palette)
2022-07-24 05:21:00 +00:00
elseif chord == 'tab' then
-- select top candidate, but don't submit
local candidates = candidates()
2022-07-30 22:40:22 +00:00
Display_settings.palette = command_string(candidates[1])
2022-07-24 05:21:00 +00:00
Display_settings.palette_text = App.newText(love.graphics.getFont(), Display_settings.palette)
2022-07-24 04:00:49 +00:00
elseif chord == 'return' then
2022-07-24 05:21:00 +00:00
-- select top candidate and submit
2022-07-24 04:00:49 +00:00
-- TODO: handle search command
local candidates = candidates()
if #candidates > 0 then
2022-07-29 18:32:53 +00:00
if file_exists(Directory..candidates[1]) then
command.open_file(candidates[1])
2022-07-24 04:26:35 +00:00
else
2022-07-30 22:40:22 +00:00
run_command(command_string(candidates[1]))
2022-07-24 04:26:35 +00:00
end
else
-- try to run the command as if it contains args
run_command_with_args(Display_settings.palette)
2022-07-24 04:00:49 +00:00
end
-- forget text for next command
Display_settings.palette = ''
Display_settings.palette_text = App.newText(love.graphics.getFont(), '')
--
Display_settings.show_palette = false
2022-07-24 04:00:49 +00:00
end
end
2022-07-30 22:40:22 +00:00
function command_string(s)
local result, _ = s:gsub(' %(.*', ''):gsub(' _.*', '')
return result
2022-07-30 22:40:22 +00:00
end
2022-07-24 04:00:49 +00:00
function draw_command_palette()
-- background
App.color(Command_palette_background_color)
love.graphics.rectangle('fill', 0,0, App.screen.width, Menu_status_bar_height)
2022-07-24 04:00:49 +00:00
App.color(Command_palette_border_color)
love.graphics.rectangle('line', 0,0, App.screen.width, Menu_status_bar_height)
2022-07-24 04:00:49 +00:00
-- input box
App.color(Command_palette_command_color)
draw_palette_input(5, 5)
2022-07-24 04:00:49 +00:00
-- alternatives
App.color(Command_palette_background_color)
love.graphics.rectangle('fill', 0, Menu_status_bar_height, App.screen.width, 5+5*Line_height+5)
App.color(Command_palette_border_color)
love.graphics.rectangle('line', 0, Menu_status_bar_height, App.screen.width, 5+5*Line_height+5)
2022-07-24 04:00:49 +00:00
App.color(Command_palette_alternatives_color)
Palette_cursor = {y=Menu_status_bar_height+5, x=5, nextx=5}
for i,cmd in ipairs(candidates()) do
add_command_to_palette(cmd)
end
end
function add_command_to_palette(s)
if Menu_text_cache[s] == nil then
Menu_text_cache[s] = App.newText(love.graphics.getFont(), s)
end
local width = App.width(Menu_text_cache[s])
if Palette_cursor.x + width/2 > App.screen.width - 5 then
return
end
App.screen.draw(Menu_text_cache[s], Palette_cursor.x, Palette_cursor.y)
Palette_cursor.nextx = math.max(Palette_cursor.nextx, Palette_cursor.x+width+10)
Palette_cursor.y = Palette_cursor.y + Line_height
if Palette_cursor.y >= Menu_status_bar_height + 5+5*Line_height then
love.graphics.line(Palette_cursor.nextx, Menu_status_bar_height+2, Palette_cursor.nextx, Menu_status_bar_height + 5+5*Line_height+5)
Palette_cursor.x = Palette_cursor.nextx + 5
Palette_cursor.y = Menu_status_bar_height+5
2022-07-24 04:00:49 +00:00
end
end
function draw_palette_input(x, y)
love.graphics.draw(Display_settings.palette_text, x,y)
x = x+App.width(Display_settings.palette_text)
draw_cursor(x, y)
end
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,Line_height)
end
end
function candidates()
2022-07-29 05:08:59 +00:00
-- slight context-sensitive tweaks
local candidates = initial_candidates()
if Display_settings.palette == '' then
return candidates
elseif Display_settings.palette:sub(1,1) == '/' then
return {}
else
local results = filter_candidates(candidates, Display_settings.palette)
append(results, file_candidates(Display_settings.palette))
return results
end
end
function initial_candidates()
if empty(Surface) then
return Commands.normal
end
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
if Display_settings.mode == 'normal' then
if not pane.editable then
return Commands.normal
else
return Commands.editable
end
elseif Display_settings.mode == 'maximize' then
if not pane.editable then
return Commands.maximized
else
return Commands.maximized_editable
end
end
2022-07-24 04:00:49 +00:00
end
function filter_candidates(candidates, prefix)
local result = {}
for _,cand in ipairs(candidates) do
if cand:find(prefix, 1, --[[literal pattern]] true) == 1 then
2022-07-24 04:00:49 +00:00
table.insert(result, cand)
end
end
return result
end
function file_candidates(prefix)
if file_exists(Directory..prefix) then
2022-07-27 01:05:48 +00:00
return {prefix}
end
2022-07-24 06:27:44 +00:00
local path = Directory
2022-07-24 05:17:41 +00:00
local visible_dir = ''
if prefix:find('/') then
visible_dir = dirname(prefix)
path = path..dirname(prefix)
2022-07-24 04:00:49 +00:00
end
local files = love.filesystem.getDirectoryItems(path)
local base = basename(prefix)
return concat_all(visible_dir, filter_candidates(reorder(path, files), base))
end
function reorder(dir, files)
local result = {}
local info = {}
for _,file in ipairs(files) do
info[file] = love.filesystem.getInfo(dir..'/'..file)
end
-- files before directories
for _,file in ipairs(files) do
if info[file].type ~= 'directory' then
table.insert(result, file)
end
end
for _,file in ipairs(files) do
if info[file].type == 'directory' then
table.insert(result, file..'/')
end
end
return result
end
2022-07-24 04:26:35 +00:00
function run_command(cmd, args)
if cmd == 'capture' then
command.capture()
elseif cmd == 'maximize note' then
command.maximize_note()
elseif cmd == 'back to surface' then
command.back_to_surface()
elseif cmd == 'edit note at cursor' then
command.edit_note_at_cursor()
elseif cmd == 'exit editing' then
command.exit_editing()
elseif cmd == 'close column surrounding cursor' then
command.close_column_surrounding_cursor()
2022-08-02 20:22:04 +00:00
elseif cmd == 'add' then
command.add_note(args)
2022-08-02 20:35:04 +00:00
elseif cmd == 'step' then
2022-08-02 22:40:13 +00:00
command.step(args)
elseif cmd == 'extract' then
command.extract()
elseif cmd == 'unroll' then
command.unroll(args)
elseif cmd == 'append' then
command.append_note(args)
elseif cmd == 'down one pane' then
command.down_one_pane()
elseif cmd == 'up one pane' then
command.up_one_pane()
2022-07-31 07:26:11 +00:00
elseif cmd == 'top pane of column' then
command.top_pane_of_column()
elseif cmd == 'bottom pane of column' then
command.bottom_pane_of_column()
elseif cmd == 'wider columns' then
command.wider_columns()
elseif cmd == 'narrower columns' then
command.narrower_columns()
elseif cmd == 'recently modified' then
command.recently_modified()
elseif cmd == 'open file' then
command.open_file(args)
elseif cmd == 'reload all' then
command.reload_all()
2022-08-04 11:32:45 +00:00
elseif cmd == 'reload note at cursor from disk' then
command.reload_note()
elseif cmd == 'delete note at cursor from disk' then
command.delete_note()
else
print(('not implemented yet: %s'):format(function_name))
end
end
function run_command_with_args(cmd_with_args)
for _,cand in ipairs(initial_candidates()) do
2022-07-30 22:40:22 +00:00
cand = command_string(cand)
local found_offset = cmd_with_args:find(cand, 1, --[[literal pattern]] true)
if found_offset == 1 then
local pivot = #cand+1
if cmd_with_args:sub(pivot, pivot) == ' ' then
run_command(cand, trim(cmd_with_args:sub(pivot)))
end
return
end
end
end
2022-07-24 04:26:35 +00:00
command = {}
function command.capture()
2022-07-24 04:26:35 +00:00
local filename = os.date('%Y/%m/%d/%H-%M-%S')
print('creating directory '..Directory..dirname(filename))
2022-07-24 06:27:44 +00:00
local status = love.filesystem.createDirectory(Directory..dirname(filename))
2022-07-24 04:26:35 +00:00
assert(status)
Cache[filename] = {lines={{mode='text', data=''}}, left=0, right=Display_settings.column_width, links={}}
2022-07-26 06:40:09 +00:00
initialize_file_metadata(Cache[filename])
2022-07-24 04:26:35 +00:00
local column = {name=filename}
2022-07-26 06:42:03 +00:00
local pane = load_pane_from_file(filename)
2022-07-24 04:26:35 +00:00
table.insert(column, pane)
table.insert(Surface, Cursor_pane.col+1, column)
Cursor_pane.col = Cursor_pane.col+1
Cursor_pane.row = 1
local col_sx = left_edge_sx(Cursor_pane.col)
if col_sx > Display_settings.x + App.screen.width - Display_settings.column_width then
Display_settings.x = math.max(0, col_sx + Display_settings.column_width + Margin_right + Padding_horizontal - App.screen.width)
Display_settings.y = 0
end
2022-07-24 04:26:35 +00:00
stop_editing_all()
2022-07-29 19:27:45 +00:00
pane.editable = true
Display_settings.mode = 'maximize'
2022-07-24 04:26:35 +00:00
end
2022-07-24 04:37:24 +00:00
2022-07-29 05:08:59 +00:00
function command.maximize_note()
Display_settings.mode = 'maximize'
end
2022-07-29 05:08:59 +00:00
function command.back_to_surface()
Display_settings.mode = 'normal'
2022-07-30 03:54:37 +00:00
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
update_metadata(pane)
update_pane_bounds()
2022-07-29 05:08:59 +00:00
end
2022-07-24 04:37:24 +00:00
function command.close_column_surrounding_cursor()
stop_editing_all()
table.remove(Surface, Cursor_pane.col)
if Cursor_pane.col > 1 then
Cursor_pane.col = Cursor_pane.col - 1
Cursor_pane.row = 1
2022-08-03 01:48:08 +00:00
bring_cursor_column_on_screen()
2022-08-03 01:48:19 +00:00
update_pane_bounds()
2022-07-24 04:37:24 +00:00
end
end
function command.edit_note_at_cursor()
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
2022-07-29 19:27:45 +00:00
assert(not pane.editable)
stop_editing_all()
pane.recent_updated = false
2022-07-29 19:27:45 +00:00
pane.editable = true
if pane.lines == Cache[pane.id].lines then
-- break an alias
pane.lines = deepcopy(pane.lines)
end
end
function command.exit_editing()
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
2022-07-29 19:27:45 +00:00
assert(pane.editable)
stop_editing(pane)
end
function command.down_one_pane()
if Cursor_pane.row < #Surface[Cursor_pane.col] then
Cursor_pane.row = Cursor_pane.row + 1
end
Display_settings.y = up_edge_sy(Cursor_pane.col, Cursor_pane.row) - Padding_vertical
update_pane_bounds()
end
function command.up_one_pane()
if Cursor_pane.row > 1 then
Cursor_pane.row = Cursor_pane.row - 1
end
Display_settings.y = up_edge_sy(Cursor_pane.col, Cursor_pane.row) - Padding_vertical
update_pane_bounds()
end
function command.bottom_pane_of_column()
if Cursor_pane.row < #Surface[Cursor_pane.col] then
Cursor_pane.row = #Surface[Cursor_pane.col]
end
Display_settings.y = up_edge_sy(Cursor_pane.col, Cursor_pane.row) - Padding_vertical
update_pane_bounds()
end
function command.top_pane_of_column()
if Cursor_pane.row > 1 then
Cursor_pane.row = 1
end
Display_settings.y = up_edge_sy(Cursor_pane.col, Cursor_pane.row) - Padding_vertical
update_pane_bounds()
end
function command.wider_columns()
Display_settings.column_width = Display_settings.column_width + 5*App.width(Em)
redraw_all()
update_pane_bounds()
end
function command.narrower_columns()
Display_settings.column_width = Display_settings.column_width - 5*App.width(Em)
redraw_all()
update_pane_bounds()
end
function command.recently_modified()
if not file_exists(Directory..'recent') then
return
end
2022-07-26 17:02:27 +00:00
local filenames = {}
2022-07-24 06:27:44 +00:00
for line in love.filesystem.lines(Directory..'recent') do
2022-07-26 17:02:27 +00:00
table.insert(filenames, line)
end
local done, ndone = {}, 0
local column = {name='recently modified'}
2022-07-26 17:02:27 +00:00
for i=#filenames,1,-1 do
local filename = filenames[i]
if ndone >= Recently_modified_lookback_window then break end
if not done[filename] then
done[filename] = true
ndone = ndone+1
--? print('loading', filename)
local pane = load_pane_from_file(filename)
table.insert(column, pane)
end
end
table.insert(Surface, Cursor_pane.col+1, column)
Cursor_pane.col = Cursor_pane.col+1
Cursor_pane.row = 1
local col_sx = left_edge_sx(Cursor_pane.col)
if col_sx > Display_settings.x + App.screen.width - Display_settings.column_width then
Display_settings.x = math.max(0, col_sx + Display_settings.column_width + Margin_right + Padding_horizontal - App.screen.width)
Display_settings.y = 0
end
update_pane_bounds()
end
function command.open_file(filename)
local column = {name=filename}
local pane = load_pane_from_file(filename)
table.insert(column, pane)
2022-08-03 01:48:08 +00:00
add_column_to_right_of_cursor(column)
update_pane_bounds()
end
function command.reload_all()
2022-08-03 04:35:22 +00:00
local column_names = {}
for _,column in ipairs(Surface) do
table.insert(column_names, column.name)
end
Surface = {}
Cache = {}
local old_cursor_pane = Cursor_pane
Cursor_pane = {col=0,row=1}
for _,column_name in ipairs(column_names) do
create_column(column_name)
end
Cursor_pane = old_cursor_pane
2022-08-03 05:16:01 +00:00
update_pane_bounds()
end
2022-08-02 20:22:04 +00:00
function command.add_note(rel)
if rel == nil then
rel = 'next'
end
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
if Cache[pane.id].links[rel] then
print(('%s already has a %s note'):format(pane.id, rel))
return
end
2022-08-03 01:40:13 +00:00
local new_pane = new_pane()
stop_editing_all()
new_pane.editable = true
print('connecting up links')
Cache[pane.id].links[rel] = new_pane.id
Cache[new_pane.id].links[Opposite[rel]] = pane.id
2022-08-03 01:40:13 +00:00
local column = {name=new_pane.id}
table.insert(column, new_pane)
2022-08-03 01:48:08 +00:00
add_column_to_right_of_cursor(column)
update_pane_bounds()
end
2022-08-02 22:40:13 +00:00
function command.step(rel)
2022-08-02 20:35:04 +00:00
if rel == nil then
rel = 'next'
end
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
if Cache[pane.id].links[rel] == nil then
print(('%s has no %s note'):format(pane.id, rel))
return
end
command.open_file(Cache[pane.id].links[rel])
end
function command.extract(rel)
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
command.open_file(pane.id)
end
function command.unroll(rel)
if rel == nil then
rel = 'next'
end
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
local column = unroll_column(pane.id, rel)
if column == nil then
return
end
if #Surface[Cursor_pane.col] == 1 then
assert(Cursor_pane.row == 1)
Surface[Cursor_pane.col] = column
else
table.insert(Surface, Cursor_pane.col+1, column)
Cursor_pane.col = Cursor_pane.col+1
Cursor_pane.row = 1
end
2022-08-03 01:48:08 +00:00
bring_cursor_column_on_screen()
update_pane_bounds()
end
function unroll_column(id, rel)
2022-08-03 22:45:45 +00:00
while Cache[id].links[Opposite[rel]] do
id = Cache[id].links[Opposite[rel]]
initialize_cache_if_necessary(id)
end
if Cache[id].links[rel] == nil then
print(('%s has no %s note'):format(id, rel))
return
end
local column = {name=('%s from %s'):format(rel, id)}
local curr = id
while curr do
local pane = load_pane_from_file(curr)
table.insert(column, pane)
curr = Cache[curr].links[rel]
end
return column
end
function command.append_note(rel)
if rel == nil then
rel = 'next'
end
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
local curr_id = pane.id
while true do
initialize_cache_if_necessary(curr_id)
local next_id = Cache[curr_id].links[rel]
if next_id == nil then
break
end
curr_id = next_id
end
2022-08-03 01:40:13 +00:00
local new_pane = new_pane()
2022-08-03 01:30:40 +00:00
stop_editing_all()
new_pane.editable = true
2022-08-03 01:40:13 +00:00
print('connecting up links')
Cache[curr_id].links[rel] = new_pane.id
Cache[new_pane.id].links[Opposite[rel]] = curr_id
2022-08-03 01:40:13 +00:00
local column = {name=new_pane.id}
table.insert(column, new_pane)
table.insert(Surface, Cursor_pane.col+1, column)
Cursor_pane.col = Cursor_pane.col+1
Cursor_pane.row = 1
local col_sx = left_edge_sx(Cursor_pane.col)
if col_sx > Display_settings.x + App.screen.width - Display_settings.column_width then
Display_settings.x = math.max(0, col_sx + Display_settings.column_width + Margin_right + Padding_horizontal - App.screen.width)
Display_settings.y = 0
end
update_pane_bounds()
end
2022-08-04 11:32:45 +00:00
function command.reload_note()
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
Cache[pane.id] = nil
for _,column in ipairs(Surface) do
for i,curr in ipairs(column) do
if curr.id == pane.id then
column[i] = load_pane_from_file(pane.id)
end
end
end
redraw_all()
end
function command.delete_note()
local pane = Surface[Cursor_pane.col][Cursor_pane.row]
if #Cache[pane.id].links > 0 then
return
end
-- TODO: test harness support for file ops below
if App.run_tests then
return
end
-- delete from disk
love.filesystem.remove(Directory..pane.id)
-- delete from recently modified
local filenames = {}
for line in love.filesystem.lines(Directory..'recent') do
if line ~= pane.id then
table.insert(filenames, line)
end
end
local f = love.filesystem.newFile(Directory..'recent')
f:open('w')
for _,filename in ipairs(filenames) do
f:write(filename)
f:write('\n')
end
f:close()
--
command.reload_all()
end
2022-08-03 01:40:13 +00:00
-- return a new pane with a unique filename
function new_pane()
local filename = os.date('%Y/%m/%d/%H-%M-%S')
print('creating directory '..Directory..dirname(filename))
local status = love.filesystem.createDirectory(Directory..dirname(filename))
assert(status)
Cache[filename] = {lines={{mode='text', data=''}}, left=0, right=Display_settings.column_width, links={}}
initialize_file_metadata(Cache[filename])
return load_pane_from_file(filename)
end
2022-08-03 01:48:08 +00:00
function add_column_to_right_of_cursor(column)
table.insert(Surface, Cursor_pane.col+1, column)
Cursor_pane.col = Cursor_pane.col+1
Cursor_pane.row = 1
bring_cursor_column_on_screen()
end
function bring_cursor_column_on_screen()
local col_sx = left_edge_sx(Cursor_pane.col)
if col_sx > Display_settings.x + App.screen.width - Display_settings.column_width then
Display_settings.x = math.max(0, col_sx + Display_settings.column_width + Margin_right + Padding_horizontal - App.screen.width)
Display_settings.y = 0
end
end
function trim(s)
return s:gsub('^%s+', ''):gsub('%s+$', '')
end