@@ -473,6 +473,15 @@ function API.coroutine.run(fn, ...)
473473 API .coroutine .resume_err (co , ... )
474474end
475475
476+ -- schedules a coroutine to run when next idle.
477+ -- returns the coroutine object
478+ function API .coroutine .schedule (fn , ...)
479+ local co = coroutine.create (fn )
480+ local args = table.pack (... )
481+ mp .add_timeout (0 , function () API .coroutine .resume_err (co , table.unpack (args )) end )
482+ return co
483+ end
484+
476485-- get the full path for the current file
477486function API .get_full_path (item , dir )
478487 if item .path then return item .path end
@@ -951,38 +960,49 @@ end
951960
952961-- disables multiselect
953962local function disable_select_mode ()
954- state .multiselect_start = nil
955- state .initial_selection = nil
963+ -- state.multiselect_start = nil
964+ -- state.initial_selection = nil
965+ update_state (2 , {
966+ multiselect_start = NIL_STATE ,
967+ initial_selection = NIL_STATE
968+ })
969+ print_state ()
956970end
957971
958972-- enables multiselect
959973local function enable_select_mode ()
960- state .multiselect_start = state .selected
961- state .initial_selection = API .copy_table (state .selection )
974+ update_state (2 , {
975+ multiselect_start = state .selected ,
976+ initial_selection = API .copy_table (state .selection )
977+ })
978+ print_state ()
962979end
963980
964981-- calculates what drag behaviour is required for that specific movement
965982local function drag_select (original_pos , new_pos )
966983 if original_pos == new_pos then return end
967984
985+ local new_selection = API .copy_table (state .selection )
968986 local setting = state .selection [state .multiselect_start ]
969987 for i = original_pos , new_pos , (new_pos > original_pos and 1 or - 1 ) do
970988 -- if we're moving the cursor away from the starting point then set the selection
971989 -- otherwise restore the original selection
972990 if i > state .multiselect_start then
973991 if new_pos > original_pos then
974- state . selection [i ] = setting
992+ new_selection [i ] = setting
975993 elseif i ~= new_pos then
976- state . selection [i ] = state .initial_selection [i ]
994+ new_selection [i ] = state .initial_selection [i ]
977995 end
978996 elseif i < state .multiselect_start then
979997 if new_pos < original_pos then
980- state . selection [i ] = setting
998+ new_selection [i ] = setting
981999 elseif i ~= new_pos then
982- state . selection [i ] = state .initial_selection [i ]
1000+ new_selection [i ] = state .initial_selection [i ]
9831001 end
9841002 end
9851003 end
1004+
1005+ return new_selection
9861006end
9871007
9881008-- moves the selector up and down the list by the entered amount
@@ -991,31 +1011,43 @@ local function scroll(n, wrap)
9911011 if num_items == 0 then return end
9921012
9931013 local original_pos = state .selected
1014+ local new_pos
1015+ local new_multiselect
9941016
9951017 if original_pos + n > num_items then
996- state . selected = wrap and 1 or num_items
1018+ new_pos = wrap and 1 or num_items
9971019 elseif original_pos + n < 1 then
998- state . selected = wrap and num_items or 1
1020+ new_pos = wrap and num_items or 1
9991021 else
1000- state .selected = original_pos + n
1022+ new_pos = original_pos + n
1023+ end
1024+
1025+ if state .multiselect_start then
1026+ new_multiselect = drag_select (original_pos , new_pos )
10011027 end
10021028
1003- if state . multiselect_start then drag_select ( original_pos , state . selected ) end
1029+ update_state ( 2 , { selected = new_pos , selection = new_multiselect })
10041030 update_ass ()
10051031end
10061032
10071033-- toggles the selection
10081034local function toggle_selection ()
10091035 if not state .list [state .selected ] then return end
1010- state .selection [state .selected ] = not state .selection [state .selected ] or nil
1036+ -- state.selection[state.selected] = not state.selection[state.selected] or nil
1037+ local selection = API .copy_table (state .selection )
1038+ selection [state .selected ] = not selection [state .selected ] or nil
1039+ update_state (2 , { selection = selection })
10111040 update_ass ()
10121041end
10131042
10141043-- select all items in the list
10151044local function select_all ()
1045+ local selection = {}
10161046 for i ,_ in ipairs (state .list ) do
1017- state . selection [i ] = true
1047+ selection [i ] = true
10181048 end
1049+
1050+ update_state (2 , {selection = selection })
10191051 update_ass ()
10201052end
10211053
@@ -1133,18 +1165,18 @@ end
11331165local function update_list (moving_adjacent )
11341166 msg .verbose (' opening directory: ' .. state .directory )
11351167
1136- state .selected = 1
1137- state .selection = {}
1168+ -- state.selected = 1
1169+ -- state.selection = {}
11381170
11391171 -- loads the current directry from the cache to save loading time
11401172 -- there will be a way to forcibly reload the current directory at some point
11411173 -- the cache is in the form of a stack, items are taken off the stack when the dir moves up
1142- if cache [1 ] and cache [# cache ].directory == state .directory then
1143- msg .verbose (' found directory in cache' )
1144- cache :apply ()
1145- state .prev_directory = state .directory
1146- return
1147- end
1174+ -- if cache[1] and cache[#cache].directory == state.directory then
1175+ -- msg.verbose('found directory in cache')
1176+ -- cache:apply()
1177+ -- state.prev_directory = state.directory
1178+ -- return
1179+ -- end
11481180 local directory = state .directory
11491181 local list , opts = parse_directory (state .directory , { source = " browser" })
11501182
@@ -1157,19 +1189,21 @@ local function update_list(moving_adjacent)
11571189 end
11581190
11591191 -- apply fallbacks if the scan failed
1160- if not list and cache [1 ] then
1161- -- switches settings back to the previously opened directory
1162- -- to the user it will be like the directory never changed
1163- msg .warn (" could not read directory" , state .directory )
1164- cache :apply ()
1165- return
1166- elseif not list then
1192+ -- if not list and cache[1] then
1193+ -- --switches settings back to the previously opened directory
1194+ -- --to the user it will be like the directory never changed
1195+ -- msg.warn("could not read directory", state.directory)
1196+ -- cache:apply()
1197+ -- return
1198+ if not list then
11671199 msg .warn (" could not read directory" , state .directory )
11681200 list , opts = root_parser :parse ()
11691201 end
11701202
1171- state .list = list
1172- state .parser = opts .parser
1203+ local finished_state = {}
1204+
1205+ finished_state .list = list
1206+ finished_state .parser = opts .parser
11731207
11741208 -- this only matters when displaying the list on the screen, so it doesn't need to be in the scan function
11751209 if not opts .escaped then
@@ -1179,54 +1213,71 @@ local function update_list(moving_adjacent)
11791213 end
11801214
11811215 -- setting custom options from parsers
1182- state .directory_label = opts .directory_label
1183- state .empty_text = opts . empty_text or state .empty_text
1216+ finished_state .directory_label = opts .directory_label
1217+ finished_state .empty_text = opts .empty_text
11841218
11851219 -- we assume that directory is only changed when redirecting to a different location
11861220 -- therefore, the cache should be wiped
11871221 if opts .directory then
1188- state .directory = opts .directory
1222+ finished_state .directory = opts .directory
11891223 cache :clear ()
11901224 end
11911225
11921226 if opts .selected_index then
1193- state .selected = opts .selected_index or state .selected
1194- if state .selected > # state . list then state .selected = # state . list
1195- elseif state .selected < 1 then state .selected = 1 end
1227+ finished_state .selected = opts .selected_index or state .selected
1228+ if finished_state .selected > # list then finished_state .selected = # list
1229+ elseif finished_state .selected < 1 then finished_state .selected = 1 end
11961230 end
11971231
11981232 if moving_adjacent then select_prev_directory ()
11991233 else select_playing_item () end
1200- state .prev_directory = state .directory
1234+ finished_state .prev_directory = finished_state .directory
1235+
1236+ print (utils .to_string (finished_state ))
1237+ return finished_state
12011238end
12021239
12031240-- rescans the folder and updates the list
1204- local function update (moving_adjacent )
1241+ local function update (new_state , moving_adjacent )
1242+ if not new_state then new_state = {} end
1243+ local directory = new_state .directory or state .directory
1244+ cache :clear ()
1245+
12051246 -- we can only make assumptions about the directory label when moving from adjacent directories
1206- if not moving_adjacent then
1207- state .directory_label = nil
1208- cache :clear ()
1209- end
1247+ -- if not moving_adjacent then
1248+ -- state.directory_label = nil
1249+ -- cache:clear()
1250+ -- end
12101251
1211- state .empty_text = " ~"
1212- state .list = {}
1213- disable_select_mode ()
1214- update_ass ()
1252+ new_state .directory = directory
1253+ new_state .empty_text = " ~"
1254+ new_state .list = {}
1255+
1256+ -- set_state(1, new_state)
1257+ -- -- disable_select_mode()
1258+ -- update_ass()
12151259
12161260 -- the directory is always handled within a coroutine to allow addons to
12171261 -- pause execution for asynchronous operations
1218- API .coroutine .run (function ()
1219- state .co = coroutine.running ()
1220- update_list (moving_adjacent )
1221- state .empty_text = " empty directory"
1262+ new_state .co = API .coroutine .schedule (function ()
1263+ local newer_state = update_list (moving_adjacent )
1264+ if not newer_state then error () end
1265+ newer_state .empty_text = newer_state .empty_text or NIL_STATE
1266+ update_state (1 , newer_state )
1267+ print_state ()
1268+
12221269 update_ass ()
12231270 end )
1271+
1272+ set_state (1 , new_state )
1273+ print_state ()
1274+ update_ass ()
12241275end
12251276
12261277-- the base function for moving to a directory
12271278local function goto_directory (directory )
1228- state .directory = directory
1229- update (false )
1279+ -- state.directory = directory
1280+ update ({ directory = directory }, false )
12301281end
12311282
12321283-- loads the root list
@@ -1251,13 +1302,14 @@ local function up_dir()
12511302 index = dir :find (" [/\\ ]" )
12521303 end
12531304
1254- if index == nil then state . directory = " "
1255- else state . directory = dir :sub (index ):reverse () end
1305+ if index == nil then dir = " "
1306+ else dir = dir :sub (index ):reverse () end
12561307
12571308 -- we can make some assumptions about the next directory label when moving up or down
1258- if state .directory_label then state .directory_label = state .directory_label :match (" ^(.+/)[^/]+/$" ) end
1309+ local dir_label = nil
1310+ if state .directory_label then dir_label = state .directory_label :match (" ^(.+/)[^/]+/$" ) end
12591311
1260- update (true )
1312+ update ({ directory = dir , directory_label = dir_label } , true )
12611313 cache :pop ()
12621314end
12631315
@@ -1268,11 +1320,11 @@ local function down_dir()
12681320
12691321 cache :push ()
12701322 local directory , redirected = API .get_new_directory (current , state .directory )
1271- state .directory = directory
12721323
12731324 -- we can make some assumptions about the next directory label when moving up or down
1274- if state .directory_label then state .directory_label = state .directory_label .. (current .label or current .name ) end
1275- update (not redirected )
1325+ local dir_label
1326+ if state .directory_label then dir_label = state .directory_label .. (current .label or current .name ) end
1327+ update ({ directory = directory , directory_label = dir_label }, not redirected )
12761328end
12771329
12781330
@@ -1330,7 +1382,7 @@ local function escape()
13301382 -- if multiple items are selection cancel the
13311383 -- selection instead of closing the browser
13321384 if next (state .selection ) or state .multiselect_start then
1333- state . selection = {}
1385+ update_state ( 2 , { selection = {} })
13341386 disable_select_mode ()
13351387 update_ass ()
13361388 return
@@ -2247,6 +2299,7 @@ local function setup_root()
22472299 end
22482300end
22492301
2302+ set_state (0 , state )
22502303setup_root ()
22512304
22522305setup_parser (file_parser , " file-browser.lua" )
0 commit comments