-- Copyright (C) 2019 the mpv developers---- Permission to use, copy, modify, and/or distribute this software for any-- purpose with or without fee is hereby granted, provided that the above-- copyright notice and this permission notice appear in all copies.---- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. local utils = require 'mp.utils'local assdraw = require 'mp.assdraw' -- Default optionslocal opts = { font = "", font_size = 24, border_size = 1.5, scale_with_window = "auto", case_sensitive = true, history_dedup = true, font_hw_ratio = 'auto',} local function detect_platform() local platform = mp.get_property_native('platform') if platform == 'darwin' or platform == 'windows' then return platform elseif os.getenv('WAYLAND_DISPLAY') then return 'wayland' end return 'x11'end -- Pick a better default font for Windows and macOSlocal platform = detect_platform()if platform == 'windows' then opts.font = 'Consolas' opts.case_sensitive = falseelseif platform == 'darwin' then opts.font = 'Menlo'else opts.font = 'monospace'end -- Apply user-set optionsrequire 'mp.options'.read_options(opts) local styles = { -- Colors are stolen from base16 Eighties by Chris Kempson -- and converted to BGR as is required by ASS. -- 2d2d2d 393939 515151 697374 -- 939fa0 c8d0d3 dfe6e8 ecf0f2 -- 7a77f2 5791f9 66ccff 99cc99 -- cccc66 cc9966 cc99cc 537bd2 debug = '{\\1c&Ha09f93&}', v = '{\\1c&H99cc99&}', warn = '{\\1c&H66ccff&}', error = '{\\1c&H7a77f2&}', fatal = '{\\1c&H5791f9&}', suggestion = '{\\1c&Hcc99cc&}', selected_suggestion = '{\\1c&H2fbdfa&\\b1}', default_item = '{\\1c&H2fbdfa&}', disabled = '{\\1c&Hcccccc&}',} local terminal_styles = { debug = '\027[90m', v = '\027[32m', warn = '\027[33m', error = '\027[31m', fatal = '\027[91m', selected_suggestion = '\027[7m', default_item = '\027[1m', disabled = '\027[38;5;8m',} local repl_active = falselocal osd_msg_active = falselocal insert_mode = falselocal pending_update = falselocal line = ''local cursor = 1local default_prompt = '>'local prompt = default_promptlocal default_id = 'default'local id = default_idlocal histories = {[id] = {}}local history = histories[id]local history_pos = 1local searching_history = falselocal log_buffers = {[id] = {}}local key_bindings = {}local dont_bind_up_down = falselocal global_margins = { t = 0, b = 0 }local input_caller local suggestion_buffer = {}local selected_suggestion_indexlocal completion_poslocal completion_appendlocal path_separator = platform == 'windows' and '\\' or '/'local completion_old_linelocal completion_old_cursor local selectable_itemslocal matches = {}local selected_match = 1local first_match_to_print = 1local default_item local set_active -- Naive helper function to find the next UTF-8 character in 'str' after 'pos'-- by skipping continuation bytes. Assumes 'str' contains valid UTF-8.local function next_utf8(str, pos) if pos > str:len() then return pos end repeat pos = pos + 1 until pos > str:len() or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf return posend -- As above, but finds the previous UTF-8 character in 'str' before 'pos'local function prev_utf8(str, pos) if pos <= 1 then return pos end repeat pos = pos - 1 until pos <= 1 or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf return posend local function len_utf8(str) local len = 0 local pos = 1 while pos <= str:len() do pos = next_utf8(str, pos) len = len + 1 end return lenend -- Functions to calculate the font width.local width_length_ratio = 0.5local osd_width, osd_height = 100, 100 ---Update osd resolution if validlocal function update_osd_resolution() local dim = mp.get_property_native('osd-dimensions') if not dim or dim.w == 0 or dim.h == 0 then return end osd_width = dim.w osd_height = dim.hend local text_osd = mp.create_osd_overlay('ass-events')text_osd.compute_bounds, text_osd.hidden = true, true local function measure_bounds(ass_text) update_osd_resolution() text_osd.res_x, text_osd.res_y = osd_width, osd_height text_osd.data = ass_text local res = text_osd:update() return res.x0, res.y0, res.x1, res.y1end ---Measure text width and normalize to a font size of 1---text has to be ass safelocal function normalized_text_width(text, size, horizontal) local align, rotation = horizontal and 7 or 1, horizontal and 0 or -90 local template = '{\\pos(0,0)\\rDefault\\blur0\\bord0\\shad0\\q2\\an%s\\fs%s\\fn%s\\frz%s}%s' size = size / 0.8 local width -- Limit to 5 iterations local repetitions_left = 5 for i = 1, repetitions_left do size = size * 0.8 local ass = assdraw.ass_new() ass.text = template:format(align, size, opts.font, rotation, text) local _, _, x1, y1 = measure_bounds(ass.text) -- Check if nothing got clipped if x1 and x1 < osd_width and y1 < osd_height then width = horizontal and x1 or y1 break end if i == repetitions_left then width = 0 end end return width / size, horizontal and osd_width or osd_heightend local function fit_on_osd(text) local estimated_width = #text * width_length_ratio if osd_width >= osd_height then -- Fill the osd as much as possible, bigger is more accurate. return math.min(osd_width / estimated_width, osd_height), true else return math.min(osd_height / estimated_width, osd_width), false endend local measured_font_hw_ratio = nillocal function get_font_hw_ratio() local font_hw_ratio = tonumber(opts.font_hw_ratio) if font_hw_ratio then return font_hw_ratio end if not measured_font_hw_ratio then local alphabet = 'abcdefghijklmnopqrstuvwxyz' local text = alphabet:rep(3) update_osd_resolution() local size, horizontal = fit_on_osd(text) local normalized_width = normalized_text_width(text, size * 0.9, horizontal) measured_font_hw_ratio = #text / normalized_width * 0.95 end return measured_font_hw_ratioend -- Escape a string for verbatim display on the OSDlocal function ass_escape(str) return mp.command_native({'escape-ass', str})end local function should_scale() return opts.scale_with_window == "yes" or (opts.scale_with_window == "auto" and mp.get_property_native("osd-scale-by-window"))end local function get_scaled_osd_dimensions() local w, h, aspect = mp.get_osd_size() if w == 0 then return 0, 0 end local scale = mp.get_property_native('display-hidpi-scale') if should_scale() then h = 720 w = 720 * aspect scale = 1 end w = w / scale h = h / scale return w, hend local function calculate_max_log_lines() if not mp.get_property_native('vo-configured') or not mp.get_property_native('video-osd') then -- Subtract 1 for the input line and for each line in the status line. -- This does not detect wrapped lines. return mp.get_property_native('term-size/h', 24) - 2 - select(2, mp.get_property('term-status-msg'):gsub('\\n', '')) end return math.floor(select(2, get_scaled_osd_dimensions()) * (1 - global_margins.t - global_margins.b) / opts.font_size -- Subtract 1 for the input line and 1 for the newline -- between the log and the input line. - 2)end -- Takes a list of strings, a max width in characters and-- optionally a max row count.-- The result contains at least one column.-- Rows are cut off from the top if rows_max is specified.-- returns a string containing the formatted table and the row countlocal function format_table(list, width_max, rows_max) if #list == 0 then return '', 0 end local spaces_min = 2 local spaces_max = 8 local list_size = #list local column_count = 1 local row_count = list_size local column_widths -- total width without spacing local width_total = 0 local list_widths = {} for i, item in ipairs(list) do list_widths[i] = len_utf8(item) end -- use as many columns as possible for columns = 2, list_size do local rows_lower_bound = math.min(rows_max, math.ceil(list_size / columns)) local rows_upper_bound = math.min(rows_max, list_size, math.ceil(list_size / (columns - 1) - 1)) for rows = rows_upper_bound, rows_lower_bound, -1 do local cw = {} width_total = 0 -- find out width of each column for column = 1, columns do local width = 0 for row = 1, rows do local i = row + (column - 1) * rows local item_width = list_widths[i] if not item_width then break end if width < item_width then width = item_width end end cw[column] = width width_total = width_total + width if width_total + (columns - 1) * spaces_min > width_max then break end end if width_total + (columns - 1) * spaces_min <= width_max then row_count = rows column_count = columns column_widths = cw else break end end if width_total + (columns - 1) * spaces_min > width_max then break end end local spaces = math.floor((width_max - width_total) / (column_count - 1)) spaces = math.max(spaces_min, math.min(spaces_max, spaces)) local spacing = column_count > 1 and ass_escape(string.format('%' .. spaces .. 's', ' ')) or '' local rows = {} for row = 1, row_count do local columns = {} for column = 1, column_count do local i = row + (column - 1) * row_count if i > #list then break end -- more then 99 leads to 'invalid format (width or precision too long)' local format_string = column == column_count and '%s' or '%-' .. math.min(column_widths[column], 99) .. 's' columns[column] = ass_escape(string.format(format_string, list[i])) if i == selected_suggestion_index then columns[column] = styles.selected_suggestion .. columns[column] .. '{\\b0}'.. styles.suggestion end end -- first row is at the bottom rows[row_count - row + 1] = table.concat(columns, spacing) end return table.concat(rows, ass_escape('\n')), row_countend local function fuzzy_find(needle, haystacks) local result = require 'mp.fzy'.filter(needle, haystacks) if line ~= '' then -- Prevent table.sort() from reordering the items. table.sort(result, function (i, j) return i[3] > j[3] end) end for i, value in ipairs(result) do result[i] = value[1] end return resultend local function populate_log_with_matches() if not selectable_items or selected_match == 0 then return end log_buffers[id] = {} local log = log_buffers[id] local max_log_lines = calculate_max_log_lines() local print_counter = false if #matches > max_log_lines then print_counter = true max_log_lines = max_log_lines - 1 end if selected_match < first_match_to_print then first_match_to_print = selected_match elseif selected_match > first_match_to_print + max_log_lines - 1 then first_match_to_print = selected_match - max_log_lines + 1 end local last_match_to_print = math.min(first_match_to_print + max_log_lines - 1, #matches) if print_counter then log[1] = { text = '', style = styles.disabled .. selected_match .. '/' .. #matches .. ' {\\fs' .. opts.font_size * 0.75 .. '}[' .. first_match_to_print .. '-' .. last_match_to_print .. ']', terminal_style = terminal_styles.disabled .. selected_match .. '/' .. #matches .. ' [' .. first_match_to_print .. '-' .. last_match_to_print .. ']', } end for i = first_match_to_print, last_match_to_print do local style = '' local terminal_style = '' if i == selected_match then style = styles.selected_suggestion terminal_style = terminal_styles.selected_suggestion end if matches[i].index == default_item then style = style .. styles.default_item terminal_style = terminal_style .. terminal_styles.default_item end log[#log + 1] = { text = matches[i].text, style = style, terminal_style = terminal_style, } endend local function print_to_terminal() -- Clear the log after closing the console. if not repl_active then if osd_msg_active then mp.osd_message('') end osd_msg_active = false return end populate_log_with_matches() local log = '' local clip = selectable_items and mp.get_property('term-clip-cc') or '' for _, log_line in ipairs(log_buffers[id]) do log = log .. clip .. log_line.terminal_style .. log_line.text .. '\027[0m\n' end local suggestions = '' for i, suggestion in ipairs(suggestion_buffer) do if i == selected_suggestion_index then suggestions = suggestions .. terminal_styles.selected_suggestion .. suggestion .. '\027[0m' else suggestions = suggestions .. suggestion end suggestions = suggestions .. (i < #suggestion_buffer and '\t' or '\n') end local before_cur = line:sub(1, cursor - 1) local after_cur = line:sub(cursor) -- Ensure there is a character with inverted colors to print. if after_cur == '' then after_cur = ' ' end mp.osd_message(log .. suggestions .. prompt .. ' ' .. before_cur .. '\027[7m' .. after_cur:sub(1, 1) .. '\027[0m' .. after_cur:sub(2), 999) osd_msg_active = trueend -- Render the REPL and console as an ASS OSDlocal function update() pending_update = false -- Unlike vo-configured, current-vo doesn't become falsy while switching VO, -- which would print the log to the OSD. if not mp.get_property('current-vo') or not mp.get_property_native('video-osd') then print_to_terminal() return end -- Clear the OSD if the console was being printed to the terminal if osd_msg_active then mp.osd_message('') osd_msg_active = false end -- Clear the OSD if the REPL is not active if not repl_active then mp.set_osd_ass(0, 0, '')Lines 1–500 of 1925. Load more
-- Copyright (C) 2019 the mpv developers -- -- Permission to use, copy, modify, and/or distribute this software for any -- purpose with or without fee is hereby granted, provided that the above -- copyright notice and this permission notice appear in all copies. -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. local utils = require 'mp.utils' local assdraw = require 'mp.assdraw' -- Default options local opts = { font = "", font_size = 24, border_size = 1.5, scale_with_window = "auto", case_sensitive = true, history_dedup = true, font_hw_ratio = 'auto', } local function detect_platform() local platform = mp.get_property_native('platform') if platform == 'darwin' or platform == 'windows' then return platform elseif os.getenv('WAYLAND_DISPLAY') then return 'wayland' end return 'x11' end -- Pick a better default font for Windows and macOS local platform = detect_platform() if platform == 'windows' then opts.font = 'Consolas' opts.case_sensitive = false elseif platform == 'darwin' then opts.font = 'Menlo' else opts.font = 'monospace' end -- Apply user-set options require 'mp.options'.read_options(opts) local styles = { -- Colors are stolen from base16 Eighties by Chris Kempson -- and converted to BGR as is required by ASS. -- 2d2d2d 393939 515151 697374 -- 939fa0 c8d0d3 dfe6e8 ecf0f2 -- 7a77f2 5791f9 66ccff 99cc99 -- cccc66 cc9966 cc99cc 537bd2 debug = '{\\1c&Ha09f93&}', v = '{\\1c&H99cc99&}', warn = '{\\1c&H66ccff&}', error = '{\\1c&H7a77f2&}', fatal = '{\\1c&H5791f9&}', suggestion = '{\\1c&Hcc99cc&}', selected_suggestion = '{\\1c&H2fbdfa&\\b1}', default_item = '{\\1c&H2fbdfa&}', disabled = '{\\1c&Hcccccc&}', } local terminal_styles = { debug = '\027[90m', v = '\027[32m', warn = '\027[33m', error = '\027[31m', fatal = '\027[91m', selected_suggestion = '\027[7m', default_item = '\027[1m', disabled = '\027[38;5;8m', } local repl_active = false local osd_msg_active = false local insert_mode = false local pending_update = false local line = '' local cursor = 1 local default_prompt = '>' local prompt = default_prompt local default_id = 'default' local id = default_id local histories = {[id] = {}} local history = histories[id] local history_pos = 1 local searching_history = false local log_buffers = {[id] = {}} local key_bindings = {} local dont_bind_up_down = false local global_margins = { t = 0, b = 0 } local input_caller local suggestion_buffer = {} local selected_suggestion_index local completion_pos local completion_append local path_separator = platform == 'windows' and '\\' or '/' local completion_old_line local completion_old_cursor local selectable_items local matches = {} local selected_match = 1 local first_match_to_print = 1 local default_item local set_active -- Naive helper function to find the next UTF-8 character in 'str' after 'pos' -- by skipping continuation bytes. Assumes 'str' contains valid UTF-8. local function next_utf8(str, pos) if pos > str:len() then return pos end repeat pos = pos + 1 until pos > str:len() or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf return pos end -- As above, but finds the previous UTF-8 character in 'str' before 'pos' local function prev_utf8(str, pos) if pos <= 1 then return pos end repeat pos = pos - 1 until pos <= 1 or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf return pos end local function len_utf8(str) local len = 0 local pos = 1 while pos <= str:len() do pos = next_utf8(str, pos) len = len + 1 end return len end -- Functions to calculate the font width. local width_length_ratio = 0.5 local osd_width, osd_height = 100, 100 ---Update osd resolution if valid local function update_osd_resolution() local dim = mp.get_property_native('osd-dimensions') if not dim or dim.w == 0 or dim.h == 0 then return end osd_width = dim.w osd_height = dim.h end local text_osd = mp.create_osd_overlay('ass-events') text_osd.compute_bounds, text_osd.hidden = true, true local function measure_bounds(ass_text) update_osd_resolution() text_osd.res_x, text_osd.res_y = osd_width, osd_height text_osd.data = ass_text local res = text_osd:update() return res.x0, res.y0, res.x1, res.y1 end ---Measure text width and normalize to a font size of 1 ---text has to be ass safe local function normalized_text_width(text, size, horizontal) local align, rotation = horizontal and 7 or 1, horizontal and 0 or -90 local template = '{\\pos(0,0)\\rDefault\\blur0\\bord0\\shad0\\q2\\an%s\\fs%s\\fn%s\\frz%s}%s' size = size / 0.8 local width -- Limit to 5 iterations local repetitions_left = 5 for i = 1, repetitions_left do size = size * 0.8 local ass = assdraw.ass_new() ass.text = template:format(align, size, opts.font, rotation, text) local _, _, x1, y1 = measure_bounds(ass.text) -- Check if nothing got clipped if x1 and x1 < osd_width and y1 < osd_height then width = horizontal and x1 or y1 break end if i == repetitions_left then width = 0 end end return width / size, horizontal and osd_width or osd_height end local function fit_on_osd(text) local estimated_width = #text * width_length_ratio if osd_width >= osd_height then -- Fill the osd as much as possible, bigger is more accurate. return math.min(osd_width / estimated_width, osd_height), true else return math.min(osd_height / estimated_width, osd_width), false end end local measured_font_hw_ratio = nil local function get_font_hw_ratio() local font_hw_ratio = tonumber(opts.font_hw_ratio) if font_hw_ratio then return font_hw_ratio end if not measured_font_hw_ratio then local alphabet = 'abcdefghijklmnopqrstuvwxyz' local text = alphabet:rep(3) update_osd_resolution() local size, horizontal = fit_on_osd(text) local normalized_width = normalized_text_width(text, size * 0.9, horizontal) measured_font_hw_ratio = #text / normalized_width * 0.95 end return measured_font_hw_ratio end -- Escape a string for verbatim display on the OSD local function ass_escape(str) return mp.command_native({'escape-ass', str}) end local function should_scale() return opts.scale_with_window == "yes" or (opts.scale_with_window == "auto" and mp.get_property_native("osd-scale-by-window")) end local function get_scaled_osd_dimensions() local w, h, aspect = mp.get_osd_size() if w == 0 then return 0, 0 end local scale = mp.get_property_native('display-hidpi-scale') if should_scale() then h = 720 w = 720 * aspect scale = 1 end w = w / scale h = h / scale return w, h end local function calculate_max_log_lines() if not mp.get_property_native('vo-configured') or not mp.get_property_native('video-osd') then -- Subtract 1 for the input line and for each line in the status line. -- This does not detect wrapped lines. return mp.get_property_native('term-size/h', 24) - 2 - select(2, mp.get_property('term-status-msg'):gsub('\\n', '')) end return math.floor(select(2, get_scaled_osd_dimensions()) * (1 - global_margins.t - global_margins.b) / opts.font_size -- Subtract 1 for the input line and 1 for the newline -- between the log and the input line. - 2) end -- Takes a list of strings, a max width in characters and -- optionally a max row count. -- The result contains at least one column. -- Rows are cut off from the top if rows_max is specified. -- returns a string containing the formatted table and the row count local function format_table(list, width_max, rows_max) if #list == 0 then return '', 0 end local spaces_min = 2 local spaces_max = 8 local list_size = #list local column_count = 1 local row_count = list_size local column_widths -- total width without spacing local width_total = 0 local list_widths = {} for i, item in ipairs(list) do list_widths[i] = len_utf8(item) end -- use as many columns as possible for columns = 2, list_size do local rows_lower_bound = math.min(rows_max, math.ceil(list_size / columns)) local rows_upper_bound = math.min(rows_max, list_size, math.ceil(list_size / (columns - 1) - 1)) for rows = rows_upper_bound, rows_lower_bound, -1 do local cw = {} width_total = 0 -- find out width of each column for column = 1, columns do local width = 0 for row = 1, rows do local i = row + (column - 1) * rows local item_width = list_widths[i] if not item_width then break end if width < item_width then width = item_width end end cw[column] = width width_total = width_total + width if width_total + (columns - 1) * spaces_min > width_max then break end end if width_total + (columns - 1) * spaces_min <= width_max then row_count = rows column_count = columns column_widths = cw else break end end if width_total + (columns - 1) * spaces_min > width_max then break end end local spaces = math.floor((width_max - width_total) / (column_count - 1)) spaces = math.max(spaces_min, math.min(spaces_max, spaces)) local spacing = column_count > 1 and ass_escape(string.format('%' .. spaces .. 's', ' ')) or '' local rows = {} for row = 1, row_count do local columns = {} for column = 1, column_count do local i = row + (column - 1) * row_count if i > #list then break end -- more then 99 leads to 'invalid format (width or precision too long)' local format_string = column == column_count and '%s' or '%-' .. math.min(column_widths[column], 99) .. 's' columns[column] = ass_escape(string.format(format_string, list[i])) if i == selected_suggestion_index then columns[column] = styles.selected_suggestion .. columns[column] .. '{\\b0}'.. styles.suggestion end end -- first row is at the bottom rows[row_count - row + 1] = table.concat(columns, spacing) end return table.concat(rows, ass_escape('\n')), row_count end local function fuzzy_find(needle, haystacks) local result = require 'mp.fzy'.filter(needle, haystacks) if line ~= '' then -- Prevent table.sort() from reordering the items. table.sort(result, function (i, j) return i[3] > j[3] end) end for i, value in ipairs(result) do result[i] = value[1] end return result end local function populate_log_with_matches() if not selectable_items or selected_match == 0 then return end log_buffers[id] = {} local log = log_buffers[id] local max_log_lines = calculate_max_log_lines() local print_counter = false if #matches > max_log_lines then print_counter = true max_log_lines = max_log_lines - 1 end if selected_match < first_match_to_print then first_match_to_print = selected_match elseif selected_match > first_match_to_print + max_log_lines - 1 then first_match_to_print = selected_match - max_log_lines + 1 end local last_match_to_print = math.min(first_match_to_print + max_log_lines - 1, #matches) if print_counter then log[1] = { text = '', style = styles.disabled .. selected_match .. '/' .. #matches .. ' {\\fs' .. opts.font_size * 0.75 .. '}[' .. first_match_to_print .. '-' .. last_match_to_print .. ']', terminal_style = terminal_styles.disabled .. selected_match .. '/' .. #matches .. ' [' .. first_match_to_print .. '-' .. last_match_to_print .. ']', } end for i = first_match_to_print, last_match_to_print do local style = '' local terminal_style = '' if i == selected_match then style = styles.selected_suggestion terminal_style = terminal_styles.selected_suggestion end if matches[i].index == default_item then style = style .. styles.default_item terminal_style = terminal_style .. terminal_styles.default_item end log[#log + 1] = { text = matches[i].text, style = style, terminal_style = terminal_style, } end end local function print_to_terminal() -- Clear the log after closing the console. if not repl_active then if osd_msg_active then mp.osd_message('') end osd_msg_active = false return end populate_log_with_matches() local log = '' local clip = selectable_items and mp.get_property('term-clip-cc') or '' for _, log_line in ipairs(log_buffers[id]) do log = log .. clip .. log_line.terminal_style .. log_line.text .. '\027[0m\n' end local suggestions = '' for i, suggestion in ipairs(suggestion_buffer) do if i == selected_suggestion_index then suggestions = suggestions .. terminal_styles.selected_suggestion .. suggestion .. '\027[0m' else suggestions = suggestions .. suggestion end suggestions = suggestions .. (i < #suggestion_buffer and '\t' or '\n') end local before_cur = line:sub(1, cursor - 1) local after_cur = line:sub(cursor) -- Ensure there is a character with inverted colors to print. if after_cur == '' then after_cur = ' ' end mp.osd_message(log .. suggestions .. prompt .. ' ' .. before_cur .. '\027[7m' .. after_cur:sub(1, 1) .. '\027[0m' .. after_cur:sub(2), 999) osd_msg_active = true end -- Render the REPL and console as an ASS OSD local function update() pending_update = false -- Unlike vo-configured, current-vo doesn't become falsy while switching VO, -- which would print the log to the OSD. if not mp.get_property('current-vo') or not mp.get_property_native('video-osd') then print_to_terminal() return end -- Clear the OSD if the console was being printed to the terminal if osd_msg_active then mp.osd_message('') osd_msg_active = false end -- Clear the OSD if the REPL is not active if not repl_active then mp.set_osd_ass(0, 0, '')