nirish

config files for niri window manager
Log | Files | Refs | README | LICENSE

fb.lua (6839B)


      1 local mp = require 'mp'
      2 local msg = require 'mp.msg'
      3 local utils = require 'mp.utils'
      4 
      5 local o = require 'modules.options'
      6 local g = require 'modules.globals'
      7 local fb_utils = require 'modules.utils'
      8 local ass = require 'modules.ass'
      9 local directory_movement = require 'modules.navigation.directory-movement'
     10 local scanning = require 'modules.navigation.scanning'
     11 local controls = require 'modules.controls'
     12 
     13 ---@class FbAPI: fb_utils
     14 local fb = setmetatable({}, { __index = setmetatable({}, { __index = fb_utils }) })
     15 package.loaded["file-browser"] = setmetatable({}, { __index = fb })
     16 
     17 --these functions we'll provide as-is
     18 fb.redraw = ass.update_ass
     19 fb.browse_directory = controls.browse_directory
     20 
     21 ---Clears the directory cache.
     22 ---@return thread
     23 function fb.rescan()
     24     return scanning.rescan()
     25 end
     26 
     27 ---@async
     28 ---@return thread
     29 function fb.rescan_await()
     30     local co = scanning.rescan(nil, fb_utils.coroutine.callback())
     31     coroutine.yield()
     32     return co
     33 end
     34 
     35 ---@param directories? string[]
     36 function fb.clear_cache(directories)
     37     if directories then
     38         mp.commandv('script-message-to', mp.get_script_name(), 'cache/clear', utils.format_json(directories))
     39     else
     40         mp.commandv('script-message-to', mp.get_script_name(), 'cache/clear')
     41     end
     42 end
     43 
     44 ---A wrapper around scan_directory for addon API.
     45 ---@async
     46 ---@param directory string
     47 ---@param parse_state ParseStateTemplate
     48 ---@return Item[]|nil
     49 ---@return Opts
     50 function fb.parse_directory(directory, parse_state)
     51     if not parse_state then parse_state = { source = "addon" }
     52     elseif not parse_state.source then parse_state.source = "addon" end
     53     return scanning.scan_directory(directory, parse_state)
     54 end
     55 
     56 ---Register file extensions which can be opened by the browser.
     57 ---@param ext string
     58 function fb.register_parseable_extension(ext)
     59     g.parseable_extensions[string.lower(ext)] = true
     60 end
     61 
     62 ---Deregister file extensions which can be opened by the browser.
     63 ---@param ext string
     64 function fb.remove_parseable_extension(ext)
     65     g.parseable_extensions[string.lower(ext)] = nil
     66 end
     67 
     68 ---Add a compatible extension to show through the filter, only applies if run during the setup() method.
     69 ---@param ext string
     70 function fb.add_default_extension(ext)
     71     table.insert(g.compatible_file_extensions, ext)
     72 end
     73 
     74 ---Add item to root at position pos.
     75 ---@param item Item
     76 ---@param pos? number
     77 function fb.insert_root_item(item, pos)
     78     msg.debug("adding item to root", item.label or item.name, pos)
     79     item.ass = item.ass or fb.ass_escape(item.label or item.name)
     80     item.type = "dir"
     81     table.insert(g.root, pos or (#g.root + 1), item)
     82 end
     83 
     84 ---Add a new mapping to the given directory.
     85 ---@param directory string
     86 ---@param mapping string
     87 ---@param pattern? boolean
     88 ---@return string
     89 function fb.register_directory_mapping(directory, mapping, pattern)
     90     if not pattern then mapping = '^'..fb_utils.pattern_escape(mapping) end
     91     g.directory_mappings[mapping] = directory
     92     msg.verbose('registering directory alias', mapping, directory)
     93 
     94     directory_movement.set_current_file(g.current_file.original_path)
     95     return mapping
     96 end
     97 
     98 ---Remove all directory mappings that map to the given directory.
     99 ---@param directory string
    100 ---@return string[]
    101 function fb.remove_all_mappings(directory)
    102     local removed = {}
    103     for mapping, target in pairs(g.directory_mappings) do
    104         if target == directory then
    105             g.directory_mappings[mapping] = nil
    106             table.insert(removed, mapping)
    107         end
    108     end
    109     return removed
    110 end
    111 
    112 ---A newer API for adding items to the root.
    113 ---Only adds the item if the same item does not already exist in the root.
    114 ---@param item Item|string
    115 ---@param priority? number Specifies the insertion location, a lower priority
    116 ---                        is placed higher in the list and the default is 100.
    117 ---@return boolean
    118 function fb.register_root_item(item, priority)
    119     msg.verbose('registering root item:', utils.to_string(item))
    120     if type(item) == 'string' then
    121         item = {name = item, type = 'dir'}
    122     end
    123 
    124     -- if the item is already in the list then do nothing
    125     if fb.list.some(g.root, function(r)
    126         return fb.get_full_path(r, '') == fb.get_full_path(item, '')
    127     end) then return false end
    128 
    129     ---@type table<Item,number>
    130     local priorities = {}
    131 
    132     priorities[item] = priority
    133     for i, v in ipairs(g.root) do
    134         if (priorities[v] or 100) > (priority or 100) then
    135             fb.insert_root_item(item, i)
    136             return true
    137         end
    138     end
    139     fb.insert_root_item(item)
    140     return true
    141 end
    142 
    143 --providing getter and setter functions so that addons can't modify things directly
    144 
    145 
    146 ---@param key string
    147 ---@return boolean|string|number
    148 function fb.get_opt(key) return o[key] end
    149 
    150 function fb.get_script_opts() return fb.copy_table(o) end
    151 function fb.get_platform() return g.PLATFORM end
    152 function fb.get_extensions() return fb.copy_table(g.extensions) end
    153 function fb.get_sub_extensions() return fb.copy_table(g.sub_extensions) end
    154 function fb.get_audio_extensions() return fb.copy_table(g.audio_extensions) end
    155 function fb.get_parseable_extensions() return fb.copy_table(g.parseable_extensions) end
    156 function fb.get_state() return fb.copy_table(g.state) end
    157 function fb.get_parsers() return fb.copy_table(g.parsers) end
    158 function fb.get_root() return fb.copy_table(g.root) end
    159 function fb.get_directory() return g.state.directory end
    160 function fb.get_list() return fb.copy_table(g.state.list) end
    161 function fb.get_current_file() return fb.copy_table(g.current_file) end
    162 function fb.get_current_parser() return g.state.parser:get_id() end
    163 function fb.get_current_parser_keyname() return g.state.parser.keybind_name or g.state.parser.name end
    164 function fb.get_selected_index() return g.state.selected end
    165 function fb.get_selected_item() return fb.copy_table(g.state.list[g.state.selected]) end
    166 function fb.get_open_status() return not g.state.hidden end
    167 function fb.get_parse_state(co) return g.parse_states[co or coroutine.running() or ""] end
    168 function fb.get_history() return fb.copy_table(g.history.list) end
    169 function fb.get_history_index() return g.history.position end
    170 
    171 ---@deprecated
    172 ---@return string|nil
    173 function fb.get_dvd_device()
    174     local dvd_device = mp.get_property('dvd-device')
    175     if not dvd_device or dvd_device == '' then return nil end
    176     return fb_utils.fix_path(dvd_device, true)
    177 end
    178 
    179 ---@param str string
    180 function fb.set_empty_text(str)
    181     g.state.empty_text = str
    182     fb.redraw()
    183 end
    184 
    185 ---@param index number
    186 ---@return number|false
    187 function fb.set_selected_index(index)
    188     if type(index) ~= "number" then return false end
    189     if index < 1 then index = 1 end
    190     if index > #g.state.list then index = #g.state.list end
    191     g.state.selected = index
    192     fb.redraw()
    193     return index
    194 end
    195 
    196 fb.set_history_index = directory_movement.goto_history
    197 
    198 return fb