nirish

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

directory-movement.lua (7433B)


      1 
      2 local mp = require 'mp'
      3 local msg = require 'mp.msg'
      4 local utils = require 'mp.utils'
      5 
      6 local o = require 'modules.options'
      7 local g = require 'modules.globals'
      8 local ass = require 'modules.ass'
      9 local scanning = require 'modules.navigation.scanning'
     10 local fb_utils = require 'modules.utils'
     11 local cursor = require 'modules.navigation.cursor'
     12 
     13 ---@class directory_movement
     14 local directory_movement = {}
     15 local NavType = scanning.NavType
     16 
     17 ---Appends an item to the directory stack, wiping any
     18 ---directories further ahead than the current position.
     19 ---@param dir string
     20 local function directory_stack_append(dir)
     21     -- don't clear the stack if we're re-entering the same directory
     22     if g.directory_stack.stack[g.directory_stack.position + 1] == dir then
     23         g.directory_stack.position = g.directory_stack.position + 1
     24         return
     25     end
     26 
     27     local j = #g.directory_stack.stack
     28     while g.directory_stack.position < j do
     29         g.directory_stack.stack[j] = nil
     30         j = j - 1
     31     end
     32     table.insert(g.directory_stack.stack, dir)
     33     g.directory_stack.position = g.directory_stack.position + 1
     34 end
     35 
     36 ---@param dir string
     37 local function directory_stack_prepend(dir)
     38     table.insert(g.directory_stack.stack, 1, dir)
     39     g.directory_stack.position = 1
     40 end
     41 
     42 ---Clears directories from the history
     43 ---@param from? number All entries >= this index are cleared.
     44 ---@return string[]
     45 function directory_movement.clear_history(from)
     46     ---@type string[]
     47     local cleared = {}
     48 
     49     from = from or 1
     50     for i = g.history.size, from, -1 do
     51         table.insert(cleared, g.history.list[i])
     52         g.history.list[i] = nil
     53         g.history.size = g.history.size - 1
     54 
     55         if g.history.position >= i then
     56             g.history.position = g.history.position - 1
     57         end
     58     end
     59 
     60     return cleared
     61 end
     62 
     63 ---Append a directory to the history
     64 ---If we have navigated backward in the history,
     65 ---then clear any history beyond the current point.
     66 ---@param directory string
     67 function directory_movement.append_history(directory)
     68     if g.history.list[g.history.position] == directory then
     69         msg.debug('reloading same directory - history unchanged:', directory)
     70         return
     71     end
     72 
     73     msg.debug('appending to history:', directory)
     74     if g.history.position < g.history.size then
     75         directory_movement.clear_history(g.history.position + 1)
     76     end
     77 
     78     table.insert(g.history.list, directory)
     79     g.history.size = g.history.size + 1
     80     g.history.position = g.history.position + 1
     81 
     82     if g.history.size > o.history_size then
     83         table.remove(g.history.list, 1)
     84         g.history.size = g.history.size - 1
     85     end
     86 end
     87 
     88 ---@param filepath string
     89 function directory_movement.set_current_file(filepath)
     90     --if we're in idle mode then we want to open the working directory
     91     if filepath == nil then
     92         g.current_file.directory = fb_utils.fix_path( mp.get_property("working-directory", ""), true)
     93         g.current_file.name = nil
     94         g.current_file.path = nil
     95         g.current_file.original_path = nil
     96         return
     97     end
     98 
     99     local absolute_path = fb_utils.absolute_path(filepath)
    100     local resolved_path = fb_utils.resolve_directory_mapping(absolute_path)
    101 
    102     g.current_file.directory, g.current_file.name = utils.split_path(resolved_path)
    103     g.current_file.original_path = absolute_path
    104     g.current_file.path = resolved_path
    105 
    106     if o.cursor_follows_playing_item then cursor.select_playing_item() end
    107     ass.update_ass()
    108 end
    109 
    110 --the base function for moving to a directory
    111 ---@param directory string
    112 ---@param nav_type? NavigationType
    113 ---@param store_history? boolean default `true`
    114 ---@param parse_properties? ParseProperties
    115 ---@return thread
    116 function directory_movement.goto_directory(directory, nav_type, store_history, parse_properties)
    117     local current = g.state.list[g.state.selected]
    118     g.state.directory = directory
    119 
    120     if g.state.directory_label then
    121         if nav_type == NavType.DOWN then
    122             g.state.directory_label = g.state.directory_label..(current.label or current.name)
    123         elseif nav_type == NavType.UP then
    124             g.state.directory_label = string.match(g.state.directory_label, "^(.-/+)[^/]+/*$")
    125         end
    126     end
    127 
    128     if o.history_size > 0 and store_history == nil or store_history then
    129         directory_movement.append_history(directory)
    130     end
    131 
    132     return scanning.rescan(nav_type or NavType.GOTO, nil, parse_properties)
    133 end
    134 
    135 ---Move the browser to a particular point in the browser history.
    136 ---The history is a linear list of visited directories from oldest to newest.
    137 ---If the user changes directories while the current history position is not the head of the list,
    138 ---any later directories get cleared and the new directory becomes the new head.
    139 ---@param pos number The history index to move to. Clamped to [1,history_length]
    140 ---@return number|false # The index actually moved to after clamping. Returns -1 if the index was invalid (can occur if history is empty or disabled)
    141 function directory_movement.goto_history(pos)
    142     if type(pos) ~= "number" then return false end
    143 
    144     if pos < 1 then pos = 1
    145     elseif pos > g.history.size then pos = g.history.size end
    146     if not g.history.list[pos] then return false end
    147 
    148     g.history.position = pos
    149     directory_movement.goto_directory(g.history.list[pos])
    150     return pos
    151 end
    152 
    153 --loads the root list
    154 function directory_movement.goto_root()
    155     msg.verbose('jumping to root')
    156     return directory_movement.goto_directory("")
    157 end
    158 
    159 --switches to the directory of the currently playing file
    160 function directory_movement.goto_current_dir()
    161     msg.verbose('jumping to current directory')
    162     return directory_movement.goto_directory(g.current_file.directory)
    163 end
    164 
    165 --moves up a directory
    166 function directory_movement.up_dir()
    167     if g.state.directory == '' then return end
    168 
    169     local cached_parent_dir = g.directory_stack.stack[g.directory_stack.position - 1]
    170     if cached_parent_dir then
    171         g.directory_stack.position = g.directory_stack.position - 1
    172         return directory_movement.goto_directory(cached_parent_dir, NavType.UP)
    173     end
    174 
    175     local parent_dir = g.state.directory:match("^(.-/+)[^/]+/*$") or ""
    176 
    177     if o.skip_protocol_schemes and parent_dir:find("^(%a[%w+-.]*)://$") then
    178         return directory_movement.goto_root()
    179     end
    180 
    181     directory_stack_prepend(parent_dir)
    182     return directory_movement.goto_directory(parent_dir, NavType.UP)
    183 end
    184 
    185 --moves down a directory
    186 function directory_movement.down_dir()
    187     local current = g.state.list[g.state.selected]
    188     if not current or not fb_utils.parseable_item(current) then return end
    189 
    190     local directory, redirected = fb_utils.get_new_directory(current, g.state.directory)
    191     directory_stack_append(directory)
    192     return directory_movement.goto_directory(directory, redirected and NavType.REDIRECT or NavType.DOWN)
    193 end
    194 
    195 --moves backwards through the directory history
    196 function directory_movement.back_history()
    197     msg.debug('moving backwards in history to', g.history.list[g.history.position-1])
    198     if g.history.position == 1 then return end
    199     directory_movement.goto_history(g.history.position - 1)
    200 end
    201 
    202 --moves forward through the history
    203 function directory_movement.forwards_history()
    204     msg.debug('moving forwards in history to', g.history.list[g.history.position+1])
    205     if g.history.position == g.history.size then return end
    206     directory_movement.goto_history(g.history.position + 1)
    207 end
    208 
    209 return directory_movement