update CLI.py and SYS/cli_parsing.py to add new command line options for the pipeline. Also updated SYS/pipeline.py to handle the new options. Modified plugins/mpv/LUA/main.lua and plugins/mpv/portable_config/input.conf to reflect changes in the pipeline configuration.

This commit is contained in:
2026-07-04 18:19:02 -07:00
parent c97f3df288
commit e748c21e2e
5 changed files with 62 additions and 25 deletions
+2 -2
View File
@@ -1917,7 +1917,7 @@ class CmdletExecutor:
selection = SelectionSyntax.parse(arg) selection = SelectionSyntax.parse(arg)
if selection is not None: if selection is not None:
zero_based = sorted(idx - 1 for idx in selection) zero_based = [idx - 1 for idx in selection]
for idx in zero_based: for idx in zero_based:
if idx not in selected_indices: if idx not in selected_indices:
selected_indices.append(idx) selected_indices.append(idx)
@@ -2326,7 +2326,7 @@ class CLI:
self._pipeline_executor = PipelineExecutor(config_loader=self._config_loader) self._pipeline_executor = PipelineExecutor(config_loader=self._config_loader)
@staticmethod @staticmethod
def parse_selection_syntax(token: str) -> Optional[Set[int]]: def parse_selection_syntax(token: str) -> Optional[List[int]]:
return SelectionSyntax.parse(token) return SelectionSyntax.parse(token)
@classmethod @classmethod
+13 -8
View File
@@ -7,7 +7,7 @@ these pure helpers are easier to test.
from __future__ import annotations from __future__ import annotations
import re import re
from typing import Any, Callable, Dict, List, Optional, Set, Tuple from typing import Any, Callable, Dict, List, Optional, Tuple
from SYS.logger import debug from SYS.logger import debug
# Prompt-toolkit lexer types are optional and expensive (~300ms). Use find_spec # Prompt-toolkit lexer types are optional and expensive (~300ms). Use find_spec
@@ -66,13 +66,13 @@ DRIVE_RE = re.compile(r"^[A-Za-z]:[\\/]")
class SelectionSyntax: class SelectionSyntax:
"""Parses @ selection syntax into 1-based indices.""" """Parses @ selection syntax into ordered 1-based indices."""
_RANGE_RE = re.compile(r"^[0-9\-]+$") _RANGE_RE = re.compile(r"^[0-9\-]+$")
@staticmethod @staticmethod
def parse(token: str) -> Optional[Set[int]]: def parse(token: str) -> Optional[List[int]]:
"""Return 1-based indices or None when not a concrete selection. """Return ordered 1-based indices or None when not a concrete selection.
Concrete selections: Concrete selections:
- @2 - @2
@@ -96,7 +96,8 @@ class SelectionSyntax:
if selector.startswith("{") and selector.endswith("}"): if selector.startswith("{") and selector.endswith("}"):
selector = selector[1:-1].strip() selector = selector[1:-1].strip()
indices: Set[int] = set() indices: List[int] = []
seen: set[int] = set()
for part in selector.split(","): for part in selector.split(","):
part = part.strip() part = part.strip()
if not part: if not part:
@@ -117,7 +118,10 @@ class SelectionSyntax:
return None return None
if start <= 0 or end <= 0 or start > end: if start <= 0 or end <= 0 or start > end:
return None return None
indices.update(range(start, end + 1)) for value in range(start, end + 1):
if value not in seen:
seen.add(value)
indices.append(value)
continue continue
try: try:
@@ -126,7 +130,9 @@ class SelectionSyntax:
return None return None
if value <= 0: if value <= 0:
return None return None
indices.add(value) if value not in seen:
seen.add(value)
indices.append(value)
return indices if indices else None return indices if indices else None
@@ -498,4 +504,3 @@ class MedeiaLexer(Lexer):
return get_line return get_line
+2 -6
View File
@@ -1452,9 +1452,7 @@ class PipelineExecutor:
if token.startswith("@"): # selection if token.startswith("@"): # selection
selection = _cli_parsing().SelectionSyntax.parse(token) selection = _cli_parsing().SelectionSyntax.parse(token)
if selection is not None: if selection is not None:
first_stage_selection_indices = sorted( first_stage_selection_indices = [i - 1 for i in selection]
[i - 1 for i in selection]
)
continue continue
if token == "@*": if token == "@*":
first_stage_select_all = True first_stage_select_all = True
@@ -2893,9 +2891,7 @@ class PipelineExecutor:
if _cli_parsing().SelectionFilterSyntax.matches(item, filter_spec) if _cli_parsing().SelectionFilterSyntax.matches(item, filter_spec)
] ]
else: else:
selected_indices = sorted( selected_indices = [i - 1 for i in selection] # type: ignore[arg-type]
[i - 1 for i in selection]
) # type: ignore[arg-type]
resolved_items = items_list if items_list else [] resolved_items = items_list if items_list else []
filtered = [ filtered = [
+44 -9
View File
@@ -1573,7 +1573,7 @@ end
function M._attempt_start_lyric_helper_async(reason) function M._attempt_start_lyric_helper_async(reason)
reason = trim(tostring(reason or 'startup')) reason = trim(tostring(reason or 'startup'))
local state = M._lyric_helper_state or { last_start_ts = -1000, debounce = 3.0 } local state = M._lyric_helper_state or { last_start_ts = -1000, debounce = 3.0, launch_inflight = false }
M._lyric_helper_state = state M._lyric_helper_state = state
if not ensure_mpv_ipc_server() then if not ensure_mpv_ipc_server() then
@@ -1581,6 +1581,10 @@ function M._attempt_start_lyric_helper_async(reason)
return false return false
end end
if state.launch_inflight then
return false
end
local now = mp.get_time() or 0 local now = mp.get_time() or 0
if (state.last_start_ts or -1000) > -1 and (now - (state.last_start_ts or -1000)) < (state.debounce or 3.0) then if (state.last_start_ts or -1000) > -1 and (now - (state.last_start_ts or -1000)) < (state.debounce or 3.0) then
return false return false
@@ -1626,16 +1630,32 @@ function M._attempt_start_lyric_helper_async(reason)
args[#args + 1] = lyric_log args[#args + 1] = lyric_log
end end
local ok, result, detail = _run_subprocess_command({ name = 'subprocess', args = args, detach = true }) state.launch_inflight = true
if not ok then local ok_async, async_err = pcall(mp.command_native_async, {
ok, result, detail = _run_subprocess_command({ name = 'subprocess', args = args }) name = 'subprocess',
end args = args,
if not ok then detach = true,
_lua_log('lyric-helper: spawn failed reason=' .. tostring(reason) .. ' detail=' .. tostring(detail or _describe_subprocess_result(result))) }, function(success, result, callback_err)
state.launch_inflight = false
if not success then
_lua_log('lyric-helper: async spawn failed reason=' .. tostring(reason) .. ' detail=' .. tostring(callback_err or 'subprocess failed'))
return
end
if type(result) == 'table' then
local result_err = trim(tostring(result.error or ''))
local status = tonumber(result.status)
if (result_err ~= '' and result_err ~= 'success') or (status ~= nil and status ~= 0) then
_lua_log('lyric-helper: async spawn failed reason=' .. tostring(reason) .. ' detail=' .. tostring(_describe_subprocess_result(result)))
return
end
end
_lua_log('lyric-helper: start requested reason=' .. tostring(reason) .. ' script=' .. tostring(lyric_script))
end)
if not ok_async then
state.launch_inflight = false
_lua_log('lyric-helper: async spawn failed reason=' .. tostring(reason) .. ' detail=' .. tostring(async_err))
return false return false
end end
_lua_log('lyric-helper: start requested reason=' .. tostring(reason) .. ' script=' .. tostring(lyric_script))
return true return true
end end
@@ -6840,6 +6860,21 @@ mp.add_timeout(0, function()
else else
_lua_log('[KEY] forced mbtn_right failed: ' .. tostring(rclick_err) .. ' (falling back to input.conf)') _lua_log('[KEY] forced mbtn_right failed: ' .. tostring(rclick_err) .. ' (falling back to input.conf)')
end end
-- Some mpv/uosc input paths emit double-right-click as `mbtn_right_dbl`.
-- Register it explicitly so menu invocation still works and mpv doesn't
-- warn about missing binding for this key.
local ok_rclick_dbl, rclick_dbl_err = pcall(function()
mp.add_forced_key_binding('mbtn_right_dbl', 'medios-mbtn-right-dbl-forced', function()
_lua_log('[KEY] mbtn_right_dbl -> show_menu')
M.show_menu()
end, {repeatable = false})
end)
if ok_rclick_dbl then
_lua_log('[KEY] registered forced mbtn_right_dbl binding')
else
_lua_log('[KEY] forced mbtn_right_dbl failed: ' .. tostring(rclick_dbl_err) .. ' (falling back to input.conf)')
end
end) end)
return M return M
+1
View File
@@ -1,6 +1,7 @@
# Medios Macina keybindings # Medios Macina keybindings
# Route right-click to our menu handler (before UOSC can claim it) # Route right-click to our menu handler (before UOSC can claim it)
mbtn_right script-message medios-show-menu mbtn_right script-message medios-show-menu
mbtn_right_dbl script-message medios-show-menu
# Route 'm' key (alternative to keybinding, in case keybinding doesn't work) # Route 'm' key (alternative to keybinding, in case keybinding doesn't work)
m script-message medios-show-menu m script-message medios-show-menu