Files
dotfiles/mpv/scripts/file-browser/modules/ass.lua
2025-06-14 20:26:14 +02:00

176 lines
5.5 KiB
Lua

--------------------------------------------------------------------------------------------------------
-----------------------------------------List Formatting------------------------------------------------
--------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------
local utils = require 'mp.utils'
local g = require 'modules.globals'
local o = require 'modules.options'
local fb_utils = require 'modules.utils'
local state = g.state
local style = g.style
local ass = g.ass
local function draw()
ass:update()
end
local function remove()
ass:remove()
end
local string_buffer = {}
--appends the entered text to the overlay
local function append(...)
for i = 1, select("#", ...) do
table.insert(string_buffer, select(i, ...) or '' )
end
end
--appends a newline character to the osd
local function newline()
table.insert(string_buffer, '\\N')
end
local function flush_buffer()
ass.data = table.concat(string_buffer, '')
string_buffer = {}
end
--detects whether or not to highlight the given entry as being played
local function highlight_entry(v)
if g.current_file.path == nil then return false end
local full_path = fb_utils.get_full_path(v)
local alt_path = v.name and g.state.directory..v.name or nil
if fb_utils.parseable_item(v) then
return string.find(g.current_file.directory, full_path, 1, true)
or (alt_path and string.find(g.current_file.directory, alt_path, 1, true))
else
return g.current_file.path == full_path
or (alt_path and g.current_file.path == alt_path)
end
end
local ass_cache = setmetatable({}, {__mode = 'k'})
-- escape ass values and replace newlines
local function ass_escape(str)
if ass_cache[str] then return ass_cache[str] end
local escaped = fb_utils.ass_escape(str, true)
ass_cache[str] = escaped
return escaped
end
--refreshes the ass text using the contents of the list
local function update_ass()
if state.hidden then state.flag_update = true ; return end
append(style.global)
local dir_name = state.directory_label or state.directory
if dir_name == "" then dir_name = "ROOT" end
append(style.header)
append(fb_utils.substitute_codes(o.format_string_header, nil, nil, nil, ass_escape))
newline()
if #state.list < 1 then
append(state.empty_text)
flush_buffer()
draw()
return
end
local start = 1
local finish = start+o.num_entries-1
--handling cursor positioning
local mid = math.ceil(o.num_entries/2)+1
if state.selected+mid > finish then
local offset = state.selected - finish + mid
--if we've overshot the end of the list then undo some of the offset
if finish + offset > #state.list then
offset = offset - ((finish+offset) - #state.list)
end
start = start + offset
finish = finish + offset
end
--making sure that we don't overstep the boundaries
if start < 1 then start = 1 end
local overflow = finish < #state.list
--this is necessary when the number of items in the dir is less than the max
if not overflow then finish = #state.list end
-- these are the number values to place into the wrappers
local wrapper_overrides = {['<'] = tostring(start-1), ['>'] = tostring(#state.list-finish)}
--adding a header to show there are items above in the list
if o.format_string_topwrapper ~= '' and start > 1 then
append(style.footer_header, fb_utils.substitute_codes(o.format_string_topwrapper, wrapper_overrides, nil, nil, ass_escape))
newline()
end
for i=start, finish do
local v = state.list[i]
local playing_file = highlight_entry(v)
append(style.body)
--handles custom styles for different entries
if i == state.selected or i == state.multiselect_start then
if not (i == state.selected) then append(style.selection_marker) end
if not state.multiselect_start then append(style.cursor)
else
if state.selection[state.multiselect_start] then append(style.cursor_select)
else append(style.cursor_deselect) end
end
append(o.cursor_icon, "\\h", style.body)
else
append(g.style.indent, o.cursor_icon, "\\h", style.body)
end
--sets the selection colour scheme
local multiselected = state.selection[i]
--sets the colour for the item
local function set_colour()
if multiselected then append(style.multiselect)
elseif i == state.selected then append(style.selected) end
if playing_file then append( multiselected and style.playing_selected or style.playing) end
end
set_colour()
--sets the folder icon
if v.type == 'dir' then
append(style.folder, o.folder_icon, "\\h", style.body)
set_colour()
end
--adds the actual name of the item
append(v.ass or ass_escape(v.label or v.name))
newline()
end
if o.format_string_bottomwrapper ~= '' and overflow then
append(style.footer_header)
append(fb_utils.substitute_codes(o.format_string_bottomwrapper, wrapper_overrides, nil, nil, ass_escape))
end
flush_buffer()
draw()
end
return {
update_ass = update_ass,
highlight_entry = highlight_entry,
draw = draw,
remove = remove,
}