KN4TZ6RJ55FT3FPOZXM7WMS7UWG3VKERDEIJVRAJYEB4BETI4IRAC
6YWKM6WS4IKDNRDZED7A7L5G7SR5PXINOH53X2IH2DFJKS4TVPZQC
2QLTVKM6MVC25L44BSHKPZAXOOLK2VAUCGCYRUDRXXNYNSWDIWQAC
MBAJPTDJ4KHWACEHWYGCFMHPQYM6FQKCSIIDKWCE765UI3VTDMIAC
R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC
JOPVPUSAMMU6RFVDQR4NJC4GNNUFB7GPKVH7OS5FKCYS5QZ53VLQC
KCDRLLAAANY5USQHWZ5QQDZDHJFJB6NS4WYZB3WE4AW4LPIV2RAAC
VP5KC4XZBKD536KCBFO47UKH74RNONENDCFJAHUMVUTPVPGJWD4AC
AYX33NBCPCBFWEZI5KZXHP3Y2Q62GYVT4WHYJUYRIPYV67KPSYZAC
A4BSGS2CX4JK7IELL655EC6HAY6ILCWTGIHWZXHRGQOKU3HSUPLAC
ICUW7F3XQLURK4LSNPH5E3NDEFSRHKATEUHH2UPFJTMHYR3ZJF3QC
LXTTOB33N2HCUZFIUDRQGGBVHK2HODRG4NBLH6RXRQZDCHF27BSAC
FNJFBXABRFX5WK6SSRDLZDCNCABN5X36HUPKRMJ7ECQTEK2XJJJQC
3OY667VAHI7ZNCTQH7NVPLJP42G3IBEZCU3CBYTQCOTJOZF5ZAZQC
62JEPVQ34SOTQI6VQNLGLKS5O4KFU52UKAVDHN6N7G5T6Z5EZO5QC
FHNPQBLKB5EEJA4XDF2QJBCKB4W56LYWHJLVYA7ZPUSKM27QWWNQC
LLQC2M2IMEJBJQXZTKC3OAKG5WKHSERXKAKCYHQRUZZD6CVRIHAQC
3SMSYTKNRPZXV5TFOVAKW7FUPPPDSTG6BWVT3ZAXB23YCH36MXCAC
LF7BWEG4DKQI7NMXMZC4LC2BE5PB42HK5PD6OYBNIDMAZBJASOKQC
LNUHQOGHIOFGJXNGA3DZLYEASLYYDGLN2I3EDZY5ANASQAHCG3YQC
EMHRPJ3RAVIVJEQIRXIVDGENV6QHUUGXXRWTJ3BXC7SZNC66VK5QC
6PCE7VUWEE5UVSE3ZZSQAMGUJDDHOBNO2MVD6POUWFP7UY7WOZHAC
7EQLPB3O4DPUWGILY4P5D32SSIKL63QWWU5XRL2HISGNJXFWD2SAC
4WAFGF4ZMUQOLBWRZ2SI6RWEBKMFNFZQJMPECT25C2VPYHNDK2JQC
KMRJOSLYYHHPGMYXBSLUQTICP6F4LXRCGYSP55YTZQSX4SZISDEAC
4J2L6JMR7NZBGCNX63CL2E3AIB7P7QTCC7QQBPNAEPQ7ISQXL7EQC
CUIV2LE5D6GUQ4NU7K2TGUVO5CTUXVJDRCZUIV47LXTOUSEPEJHQC
DSLD74DK3P6J2VAFCYF5BGTHZ637QTW3PDHOUHFACDZU66YNM3IAC
CVSRHMJ2BM4LPVG67ULIVQMP2NW3YY2JC2ZQBEA6EB5KVM4O2L5AC
FO6ZBUW6N7MTC5EXKJ5MP5NAUEBDM24DD5CVOJ6QYSANNKL2HNEQC
T3B4NLV33PBD2L3YL3MHSOXZUWHDOGHPWLKKKHEBKJFSHYQWUK3AC
7RKFA3VAGK73SLC3NCOKHVMOWLTC4EUQYS47P3LVVKDVLBVGBEHAC
Y4SPXCM3PKARGUU22FNBEDRU7S6CJSNYVAA76JYH4I4EMMMKP6LQC
HTWAM4NZFOY463TNSKYIM2EWB7QNBGDRRTTGHF5N3Z4TGC7Q3SFAC
S2YQBEYCOBS4ADO5VX4YLAWY6CJEQOOZM3THYTDOTXM7ADID6PGQC
FZBXBUFFNRE5ZJO5DLRU375HOXT2B7FO35XD7BTHHUXSARVWDFLQC
GG2553RBUKMCWIAD3EWJV7C2QH2BIS5V2E3BDTFSTYRHAPXGBF7QC
2CK5QI7WA7M4IVSACFGOJYAIDKRUTZVMMPSFWEJTUNMWTN7AX4NAC
LLAOOMULEBXFMIGRBY6LRVEK4RXQGPNTFVWMCZNUEJZHWC7UGUEAC
MSOQI3A5BC5PY2MZXZQAQ4EQDT4KICQJPN3YUZVDYTWXSPZWBLIAC
AMOPICKVRHMQERJLFPMAAEBV7TL5QACGGSBJWRCMV5R5O3KDVETAC
3PSFWAILGRA4OYXWS2DX7VF332AIBPYBXHEA4GIQY2XEJVD65UMAC
GLZ6ZD6U52AJ7QYPR3CCJUGD3JDDGZ4NU3FAQXBMHMZ5O5XGOKAQC
3VHUIIATPOF7FXB7NTL5MESCV5BCQACII2D7QZ4UIUCBX3CWXMMAC
D4B52CQ2QKG2HQKFUQOO5S2ME325DTW3PH2D7SBXCW4BPQFYG7CAC
5XMBCKJZ7YCUOOQWWZRNLXMXD3MUYC2VAF3VKA4BIEHQRPDQMUMAC
ONHKBLLCD5NDO3HSSUMAMGJ7HDT53JYVV56DI42AEYI3W63GKACQC
WB66TPZSJ6SPPZKQVDON56URAO3XPKSY7CE5WKDSE4S36U2ZE6PAC
NAGDS5E2LF4PFXZS72KKDWQ5K5KMZXLV763Q4VCKIT6GOBAWB6MAC
F52PSTYSIIUD7UPEVLEJPVSBQU7IKVHM4GN4YASNSKFP4MRE6S6AC
B4FAIVRAXKCS2ZZXYUHL7HHWVMDMG2MQ3BY6IOJARK7B5XTBAQNAC
2TQUKHBC2EB3WDBD5UL62DQYV7CV6B7OJYK7CHOEDNOZENSOG42AC
M7SW76FQORGMK7VH5LCFBFZMGONVIAEHYPGQAWTKTKANU7ZAT6CQC
ORKN6EOBUFVAD2TXYW5OIKSL55RU24LOFDTTTXHDZUZ57QRDCY7QC
22K3VJIL4SRPXVAEJSWRS7KM4UPV4SOODPSTSSKPFWKLTYRG365QC
TOJA6VDEWPXDE4KE6URFLNIZBQ6ASAFDZMSYSIBDBKACBGUKZI3QC
CE4LZV4TNXJT54CVGM3QANCBP42TMLMZWF2DBSMUYKAHILXIZEMQC
R2ASHK5CEE3PTRLS37GP4PXJ7HIGJ6UD72KKBI57UDJI7VRROQGQC
UGTWUIS4MWIITRDEAGULOPRV5KJD7HEGCOSR5BP4KLVBAVHU2ETQC
2L5MEZV344TOZLVY3432RHJFIRVXFD6O3GWLL5O4CV66BGAFTURQC
QMRQL2FOIIXU3PCSH7UQIDRLKJN2DQHB5IUL4TLBVANNHWWETL6AC
MYQNSDA3BKAVX3AKPKUDVFOL7B2O53O7U75B6Y673HJZGOULFBYAC
App.run_after_keychord('C-l', 'l')
App.run_after_keychord('C-l', 'l')
-- margins are now adjusted
check(Show_log_browser_side, 'check')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'C-m', 'm')
edit.run_after_keychord(Editor_state, 'left', 'left')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'left', 'left')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'S-right', 'right')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'C-c', 'c')
edit.run_after_keychord(Editor_state, 'C-x', 'x')
edit.run_after_keychord(Editor_state, 'C-v', 'v')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-v', 'v')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'C-x', 'x')
edit.run_after_keychord(Editor_state, 'C-a', 'a')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'pageup', 'pageup')
edit.run_after_keychord(Editor_state, 'pageup', 'pageup')
edit.run_after_keychord(Editor_state, 'pageup', 'pageup')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'left', 'left')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'home', 'home')
edit.run_after_keychord(Editor_state, 'end', 'end')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'C-z', 'z')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'C-z', 'z')
edit.run_after_keychord(Editor_state, 'C-z', 'z')
edit.run_after_keychord(Editor_state, 'C-z', 'z')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'M-left')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'C-m', 'm')
edit.run_after_keychord(Editor_state, 'left', 'left')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'left', 'left')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-left', 'left')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'M-right', 'right')
edit.run_after_keychord(Editor_state, 'S-right', 'right')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'C-c', 'c')
edit.run_after_keychord(Editor_state, 'C-x', 'x')
edit.run_after_keychord(Editor_state, 'C-v', 'v')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-v', 'v')
edit.run_after_keychord(Editor_state, 'C-a', 'a')
edit.run_after_keychord(Editor_state, 'C-x', 'x')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'pagedown', 'pagedown')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'pageup', 'pageup')
edit.run_after_keychord(Editor_state, 'pageup', 'pageup')
edit.run_after_keychord(Editor_state, 'pageup', 'pageup')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'left', 'left')
edit.run_after_keychord(Editor_state, 'right', 'right')
edit.run_after_keychord(Editor_state, 'home', 'home')
edit.run_after_keychord(Editor_state, 'end', 'end')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
edit.run_after_keychord(Editor_state, 'backspace', 'backspace')
check_eq(Editor_state.cursor1.line, 2, 'baseline/cursor:line')
check_eq(Editor_state.cursor1.pos, 4, 'baseline/cursor:pos')
check_nil(Editor_state.selection1.line, 'baseline/selection:line')
check_nil(Editor_state.selection1.pos, 'baseline/selection:pos')
check_eq(Editor_state.cursor1.line, 2, 'cursor:line')
check_eq(Editor_state.cursor1.pos, 5, 'cursor:pos')
check_nil(Editor_state.selection1.line, 'selection:line')
check_nil(Editor_state.selection1.pos, 'selection:pos')
--? check_eq(Editor_state.selection1.line, 2, 'selection:line')
--? check_eq(Editor_state.selection1.pos, 4, 'selection:pos')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'down', 'down')
edit.run_after_keychord(Editor_state, 'return', 'return')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'up', 'up')
edit.run_after_keychord(Editor_state, 'C-f', 'f')
edit.run_after_keychord(Editor_state, 'return', 'return')
function edit.run_after_keychord(State, chord)
edit.keychord_press(State, chord)
edit.key_release(State, chord)
function edit.run_after_keychord(State, chord, key)
edit.keychord_press(State, chord, key)
edit.key_release(State, key)
Text.delete_selection(State, State.left, State.right)
end
if State.search_term then
for _,line_cache in ipairs(State.line_cache) do line_cache.starty = nil end -- just in case we scroll
if chord == 'escape' then
State.search_term = nil
State.cursor1 = State.search_backup.cursor
State.screen_top1 = State.search_backup.screen_top
State.search_backup = nil
Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks
elseif chord == 'return' then
State.search_term = nil
State.search_backup = nil
elseif chord == 'backspace' then
local len = utf8.len(State.search_term)
local byte_offset = Text.offset(State.search_term, len)
State.search_term = string.sub(State.search_term, 1, byte_offset-1)
elseif chord == 'down' then
State.cursor1.pos = State.cursor1.pos+1
Text.search_next(State)
elseif chord == 'up' then
Text.search_previous(State)
end
return
elseif chord == 'C-f' then
State.search_term = ''
State.search_backup = {
cursor={line=State.cursor1.line, pos=State.cursor1.pos},
screen_top={line=State.screen_top1.line, pos=State.screen_top1.pos},
}
-- zoom
elseif chord == 'C-=' then
edit.update_font_settings(State, State.font_height+2)
Text.redraw_all(State)
elseif chord == 'C--' then
if State.font_height > 2 then
edit.update_font_settings(State, State.font_height-2)
Text.redraw_all(State)
end
elseif chord == 'C-0' then
edit.update_font_settings(State, 20)
Text.redraw_all(State)
-- undo
elseif chord == 'C-z' then
local event = undo_event(State)
if event then
local src = event.before
State.screen_top1 = deepcopy(src.screen_top)
State.cursor1 = deepcopy(src.cursor)
State.selection1 = deepcopy(src.selection)
patch(State.lines, event.after, event.before)
patch_placeholders(State.line_cache, event.after, event.before)
-- if we're scrolling, reclaim all fragments to avoid memory leaks
Text.redraw_all(State)
schedule_save(State)
end
elseif chord == 'C-y' then
local event = redo_event(State)
if event then
local src = event.after
State.screen_top1 = deepcopy(src.screen_top)
State.cursor1 = deepcopy(src.cursor)
State.selection1 = deepcopy(src.selection)
patch(State.lines, event.before, event.after)
-- if we're scrolling, reclaim all fragments to avoid memory leaks
Text.redraw_all(State)
schedule_save(State)
end
-- clipboard
elseif chord == 'C-a' then
State.selection1 = {line=1, pos=1}
State.cursor1 = {line=#State.lines, pos=utf8.len(State.lines[#State.lines].data)+1}
elseif chord == 'C-c' then
local s = Text.selection(State)
if s then
App.set_clipboard(s)
end
elseif chord == 'C-x' then
local s = Text.cut_selection(State, State.left, State.right)
if s then
App.set_clipboard(s)
end
schedule_save(State)
elseif chord == 'C-v' then
-- We don't have a good sense of when to scroll, so we'll be conservative
-- and sometimes scroll when we didn't quite need to.
local before_line = State.cursor1.line
local before = snapshot(State, before_line)
local clipboard_data = App.get_clipboard()
for _,code in utf8.codes(clipboard_data) do
local c = utf8.char(code)
if c == '\n' then
Text.insert_return(State)
else
Text.insert_at_cursor(State, c)
end
end
if Text.cursor_out_of_screen(State) then
Text.snap_cursor_to_bottom_of_screen(State, State.left, State.right)
end
schedule_save(State)
record_undo_event(State, {before=before, after=snapshot(State, before_line, State.cursor1.line)})
-- dispatch to text
else
for _,line_cache in ipairs(State.line_cache) do line_cache.starty = nil end -- just in case we scroll
Text.keychord_press(State, chord)
end
end
function edit.key_release(State, key, scancode)
end
function edit.update_font_settings(State, font_height)
State.font_height = font_height
State.line_height = math.floor(font_height*1.3)
end
--== some methods for tests
-- Insulate tests from some key globals so I don't have to change the vast
-- majority of tests when they're modified for the real app.
Test_margin_left = 25
Test_margin_right = 0
function edit.initialize_test_state()
-- if you change these values, tests will start failing
return edit.initialize_state(
15, -- top margin
Test_margin_left,
App.screen.width - Test_margin_right,
15) -- line height
end
-- all text_input events are also keypresses
-- TODO: handle chords of multiple keys
function edit.run_after_text_input(State, t)
edit.keychord_press(State, t)
edit.text_input(State, t)
edit.key_release(State, t)
App.screen.contents = {}
edit.update(State, 0)
edit.draw(State)
end
-- not all keys are text_input
App.screen.contents = {}
edit.update(State, 0)
edit.draw(State)
end
function edit.run_after_mouse_click(State, x,y, mouse_button)
App.fake_mouse_press(x,y, mouse_button)
edit.mouse_press(State, x,y, mouse_button)
App.fake_mouse_release(x,y, mouse_button)
edit.mouse_release(State, x,y, mouse_button)
App.screen.contents = {}
edit.update(State, 0)
edit.draw(State)
end
function edit.run_after_mouse_press(State, x,y, mouse_button)
App.fake_mouse_press(x,y, mouse_button)
edit.mouse_press(State, x,y, mouse_button)
App.screen.contents = {}
edit.update(State, 0)
edit.draw(State)
end
function edit.run_after_mouse_release(State, x,y, mouse_button)
App.fake_mouse_release(x,y, mouse_button)
edit.mouse_release(State, x,y, mouse_button)
App.screen.contents = {}
edit.update(State, 0)
edit.draw(State)
end