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:
@@ -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
@@ -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
@@ -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 = [
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|||||||
Reference in New Issue
Block a user