diff --git a/cursorless-talon-dev/src/spoken_form_test.py b/cursorless-talon-dev/src/spoken_form_test.py index 525f6eae74..df29ca8dec 100644 --- a/cursorless-talon-dev/src/spoken_form_test.py +++ b/cursorless-talon-dev/src/spoken_form_test.py @@ -42,17 +42,23 @@ def did_emit_pre_phrase_signal(): return True def private_cursorless_run_rpc_command_and_wait( - command_id: str, arg1: Any, arg2: Any = None + command_id: str, # pyright: ignore [reportGeneralTypeIssues] + arg1: Any, + arg2: Any = None, ): commands_run.append(arg1) def private_cursorless_run_rpc_command_no_wait( - command_id: str, arg1: Any, arg2: Any = None + command_id: str, # pyright: ignore [reportGeneralTypeIssues] + arg1: Any, + arg2: Any = None, ): commands_run.append(arg1) def private_cursorless_run_rpc_command_get( - command_id: str, arg1: Any, arg2: Any = None + command_id: str, # pyright: ignore [reportGeneralTypeIssues] + arg1: Any, + arg2: Any = None, ) -> Any: commands_run.append(arg1) return mockedGetValue @@ -60,7 +66,7 @@ def private_cursorless_run_rpc_command_get( @mod.action_class class Actions: - def private_cursorless_spoken_form_test_mode(enable: bool): + def private_cursorless_spoken_form_test_mode(enable: bool): # pyright: ignore [reportGeneralTypeIssues] """Enable/disable Cursorless spoken form test mode""" global saved_modes, saved_microphone @@ -84,7 +90,7 @@ def private_cursorless_spoken_form_test_mode(enable: bool): "Cursorless spoken form tests are done. Talon microphone is re-enabled." ) - def private_cursorless_use_community_snippets(enable: bool): + def private_cursorless_use_community_snippets(enable: bool): # pyright: ignore [reportGeneralTypeIssues] """Enable/disable cursorless community snippets in test mode""" if enable: tags = set(ctx.tags) @@ -99,7 +105,8 @@ def private_cursorless_use_community_snippets(enable: bool): print(f"Set community snippet enablement to {enable}") def private_cursorless_spoken_form_test( - phrase: str, mockedGetValue_: Optional[str] + phrase: str, # pyright: ignore [reportGeneralTypeIssues] + mockedGetValue_: Optional[str], ): """Run Cursorless spoken form test""" global commands_run, mockedGetValue diff --git a/cursorless-talon/.github/workflows/black.yml b/cursorless-talon/.github/workflows/black.yml deleted file mode 100644 index 81e6a948b5..0000000000 --- a/cursorless-talon/.github/workflows/black.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Lint - -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: psf/black@stable diff --git a/cursorless-talon/README.md b/cursorless-talon/README.md index cb792d7ef1..dc4ac1c302 100644 --- a/cursorless-talon/README.md +++ b/cursorless-talon/README.md @@ -10,7 +10,7 @@ Tests - Maintenance + Maintenance License: MIT diff --git a/cursorless-talon/src/actions/actions.py b/cursorless-talon/src/actions/actions.py index 2b44f08492..c9e75cf750 100644 --- a/cursorless-talon/src/actions/actions.py +++ b/cursorless-talon/src/actions/actions.py @@ -4,6 +4,7 @@ from ..targets.target_types import ( CursorlessDestination, + CursorlessExplicitTarget, CursorlessTarget, ImplicitDestination, ) @@ -48,7 +49,7 @@ "custom_action", ] -callback_actions: dict[str, Callable[[CursorlessTarget], None]] = { +callback_actions: dict[str, Callable[[CursorlessExplicitTarget], None]] = { "nextHomophone": cursorless_homophones_action, } @@ -88,7 +89,7 @@ def cursorless_action_or_ide_command(m) -> dict[str, str]: @mod.action_class class Actions: - def cursorless_command(action_name: str, target: CursorlessTarget): + def cursorless_command(action_name: str, target: CursorlessExplicitTarget): # pyright: ignore [reportGeneralTypeIssues] """Perform cursorless command on target""" if action_name in callback_actions: callback_actions[action_name](target) @@ -107,7 +108,7 @@ def cursorless_command(action_name: str, target: CursorlessTarget): action = {"name": action_name, "target": target} actions.user.private_cursorless_command_and_wait(action) - def cursorless_vscode_command(command_id: str, target: CursorlessTarget): + def cursorless_vscode_command(command_id: str, target: CursorlessTarget): # pyright: ignore [reportGeneralTypeIssues] """ Perform vscode command on cursorless target @@ -115,12 +116,13 @@ def cursorless_vscode_command(command_id: str, target: CursorlessTarget): """ return actions.user.cursorless_ide_command(command_id, target) - def cursorless_ide_command(command_id: str, target: CursorlessTarget): + def cursorless_ide_command(command_id: str, target: CursorlessTarget): # pyright: ignore [reportGeneralTypeIssues] """Perform ide command on cursorless target""" return cursorless_execute_command_action(command_id, target) def cursorless_insert( - destination: CursorlessDestination, text: Union[str, list[str]] + destination: CursorlessDestination, # pyright: ignore [reportGeneralTypeIssues] + text: Union[str, list[str]], ): """Perform text insertion on Cursorless destination""" if isinstance(text, str): @@ -128,7 +130,8 @@ def cursorless_insert( cursorless_replace_action(destination, text) def private_cursorless_action_or_ide_command( - instruction: dict[str, str], target: CursorlessTarget + instruction: dict[str, str], # pyright: ignore [reportGeneralTypeIssues] + target: CursorlessTarget, ): """Perform cursorless action or ide command on target (internal use only)""" type = instruction["type"] diff --git a/cursorless-talon/src/actions/bring_move.py b/cursorless-talon/src/actions/bring_move.py index 7861f76fd4..bb13497ada 100644 --- a/cursorless-talon/src/actions/bring_move.py +++ b/cursorless-talon/src/actions/bring_move.py @@ -35,7 +35,7 @@ def cursorless_bring_move_targets(m) -> BringMoveTargets: @mod.action_class class Actions: - def private_cursorless_bring_move(action_name: str, targets: BringMoveTargets): + def private_cursorless_bring_move(action_name: str, targets: BringMoveTargets): # pyright: ignore [reportGeneralTypeIssues] """Execute Cursorless move/bring action""" actions.user.private_cursorless_command_and_wait( { diff --git a/cursorless-talon/src/actions/call.py b/cursorless-talon/src/actions/call.py index 6601d7ba5f..7bfe75cb78 100644 --- a/cursorless-talon/src/actions/call.py +++ b/cursorless-talon/src/actions/call.py @@ -9,7 +9,7 @@ @mod.action_class class Actions: def private_cursorless_call( - callee: CursorlessTarget, + callee: CursorlessTarget, # pyright: ignore [reportGeneralTypeIssues] argument: CursorlessTarget = ImplicitTarget(), ): """Execute Cursorless call action""" diff --git a/cursorless-talon/src/actions/get_text.py b/cursorless-talon/src/actions/get_text.py index e95f35de90..6f1770ad85 100644 --- a/cursorless-talon/src/actions/get_text.py +++ b/cursorless-talon/src/actions/get_text.py @@ -10,7 +10,7 @@ @mod.action_class class Actions: def cursorless_get_text( - target: CursorlessTarget, + target: CursorlessTarget, # pyright: ignore [reportGeneralTypeIssues] hide_decorations: bool = False, ) -> str: """Get target text. If hide_decorations is True, don't show decorations""" @@ -21,7 +21,7 @@ def cursorless_get_text( )[0] def cursorless_get_text_list( - target: CursorlessTarget, + target: CursorlessTarget, # pyright: ignore [reportGeneralTypeIssues] hide_decorations: bool = False, ) -> list[str]: """Get texts for multiple targets. If hide_decorations is True, don't show decorations""" diff --git a/cursorless-talon/src/actions/homophones.py b/cursorless-talon/src/actions/homophones.py index df571f9469..4b3b7f3280 100644 --- a/cursorless-talon/src/actions/homophones.py +++ b/cursorless-talon/src/actions/homophones.py @@ -2,12 +2,15 @@ from talon import actions, app -from ..targets.target_types import CursorlessTarget, PrimitiveDestination +from ..targets.target_types import ( + CursorlessExplicitTarget, + PrimitiveDestination, +) from .get_text import cursorless_get_text_action from .replace import cursorless_replace_action -def cursorless_homophones_action(target: CursorlessTarget): +def cursorless_homophones_action(target: CursorlessExplicitTarget): """Replaced target with next homophone""" texts = cursorless_get_text_action(target, show_decorations=False) try: diff --git a/cursorless-talon/src/actions/paste.py b/cursorless-talon/src/actions/paste.py index bcef75d9b5..5ee32b97bc 100644 --- a/cursorless-talon/src/actions/paste.py +++ b/cursorless-talon/src/actions/paste.py @@ -9,7 +9,9 @@ @mod.action_class class Actions: - def private_cursorless_paste(destination: CursorlessDestination): + def private_cursorless_paste( + destination: CursorlessDestination, # pyright: ignore [reportGeneralTypeIssues] + ): """Execute Cursorless paste action""" actions.user.private_cursorless_command_and_wait( { diff --git a/cursorless-talon/src/actions/reformat.py b/cursorless-talon/src/actions/reformat.py index ce2b89d427..1b60bee875 100644 --- a/cursorless-talon/src/actions/reformat.py +++ b/cursorless-talon/src/actions/reformat.py @@ -1,6 +1,9 @@ from talon import Module, actions -from ..targets.target_types import CursorlessTarget, PrimitiveDestination +from ..targets.target_types import ( + CursorlessExplicitTarget, + PrimitiveDestination, +) from .get_text import cursorless_get_text_action from .replace import cursorless_replace_action @@ -11,7 +14,10 @@ @mod.action_class class Actions: - def private_cursorless_reformat(target: CursorlessTarget, formatters: str): + def private_cursorless_reformat( + target: CursorlessExplicitTarget, # pyright: ignore [reportGeneralTypeIssues] + formatters: str, + ): """Execute Cursorless reformat action. Reformat target with formatter""" texts = cursorless_get_text_action(target, show_decorations=False) updated_texts = [actions.user.reformat_text(text, formatters) for text in texts] diff --git a/cursorless-talon/src/actions/swap.py b/cursorless-talon/src/actions/swap.py index cb3eb8d990..862f7dcaba 100644 --- a/cursorless-talon/src/actions/swap.py +++ b/cursorless-talon/src/actions/swap.py @@ -36,7 +36,9 @@ def cursorless_swap_targets(m) -> SwapTargets: @mod.action_class class Actions: - def private_cursorless_swap(targets: SwapTargets): + def private_cursorless_swap( + targets: SwapTargets, # pyright: ignore [reportGeneralTypeIssues] + ): """Execute Cursorless swap action""" actions.user.private_cursorless_command_and_wait( { diff --git a/cursorless-talon/src/actions/wrap.py b/cursorless-talon/src/actions/wrap.py index df0fe182fa..f9e846fc56 100644 --- a/cursorless-talon/src/actions/wrap.py +++ b/cursorless-talon/src/actions/wrap.py @@ -10,7 +10,9 @@ @mod.action_class class Actions: def private_cursorless_wrap_with_paired_delimiter( - action_name: str, target: CursorlessTarget, paired_delimiter: list[str] + action_name: str, # pyright: ignore [reportGeneralTypeIssues] + target: CursorlessTarget, + paired_delimiter: list[str], ): """Execute Cursorless wrap/rewrap with paired delimiter action""" if action_name == "rewrap": @@ -26,7 +28,9 @@ def private_cursorless_wrap_with_paired_delimiter( ) def private_cursorless_wrap_with_snippet( - action_name: str, target: CursorlessTarget, snippet_location: str + action_name: str, # pyright: ignore [reportGeneralTypeIssues] + target: CursorlessTarget, + snippet_location: str, ): """Execute Cursorless wrap with snippet action""" if action_name == "wrapWithPairedDelimiter": diff --git a/cursorless-talon/src/apps/vscode_settings.py b/cursorless-talon/src/apps/vscode_settings.py index 42d05af1a3..f1ec80a631 100644 --- a/cursorless-talon/src/apps/vscode_settings.py +++ b/cursorless-talon/src/apps/vscode_settings.py @@ -28,8 +28,9 @@ class Actions: def vscode_settings_path() -> Path: """Get path of vscode settings json file""" + ... - def vscode_get_setting(key: str, default_value: Any = None): + def vscode_get_setting(key: str, default_value: Any = None): # pyright: ignore [reportGeneralTypeIssues] """Get the value of vscode setting at the given key""" path: Path = actions.user.vscode_settings_path() settings: dict = loads(path.read_text()) @@ -40,7 +41,7 @@ def vscode_get_setting(key: str, default_value: Any = None): return settings[key] def vscode_get_setting_with_fallback( - key: str, + key: str, # pyright: ignore [reportGeneralTypeIssues] default_value: Any, fallback_value: Any, fallback_message: str, diff --git a/cursorless-talon/src/cheatsheet/cheat_sheet.py b/cursorless-talon/src/cheatsheet/cheat_sheet.py index 673feb628b..5d4b938576 100644 --- a/cursorless-talon/src/cheatsheet/cheat_sheet.py +++ b/cursorless-talon/src/cheatsheet/cheat_sheet.py @@ -76,7 +76,7 @@ def cheatsheet_dir_linux() -> Path: """Get cheatsheet directory for Linux""" try: # 1. Get users actual document directory - import platformdirs + import platformdirs # pyright: ignore [reportMissingImports] return Path(platformdirs.user_documents_dir()) except Exception: diff --git a/cursorless-talon/src/cheatsheet/get_list.py b/cursorless-talon/src/cheatsheet/get_list.py index c74f364344..341873fd6a 100644 --- a/cursorless-talon/src/cheatsheet/get_list.py +++ b/cursorless-talon/src/cheatsheet/get_list.py @@ -1,4 +1,5 @@ import re +import typing from collections.abc import Mapping, Sequence from typing import Optional, TypedDict @@ -37,7 +38,7 @@ def get_lists( def get_raw_list(name: str) -> Mapping[str, str]: cursorless_list_name = get_cursorless_list_name(name) - return registry.lists[cursorless_list_name][0].copy() + return typing.cast(dict[str, str], registry.lists[cursorless_list_name][0]).copy() def get_spoken_form_from_list(list_name: str, value: str) -> str: diff --git a/cursorless-talon/src/command.py b/cursorless-talon/src/command.py index 329678649c..5d7c94594d 100644 --- a/cursorless-talon/src/command.py +++ b/cursorless-talon/src/command.py @@ -16,7 +16,7 @@ class CursorlessCommand: CURSORLESS_COMMAND_ID = "cursorless.command" -last_phrase = None +last_phrase: dict = {} mod = Module() @@ -31,7 +31,7 @@ def on_phrase(d): @mod.action_class class Actions: - def private_cursorless_command_and_wait(action: dict): + def private_cursorless_command_and_wait(action: dict): # pyright: ignore [reportGeneralTypeIssues] """Execute cursorless command and wait for it to finish""" response = actions.user.private_cursorless_run_rpc_command_get( CURSORLESS_COMMAND_ID, @@ -40,14 +40,14 @@ def private_cursorless_command_and_wait(action: dict): if "fallback" in response: perform_fallback(response["fallback"]) - def private_cursorless_command_no_wait(action: dict): + def private_cursorless_command_no_wait(action: dict): # pyright: ignore [reportGeneralTypeIssues] """Execute cursorless command without waiting""" actions.user.private_cursorless_run_rpc_command_no_wait( CURSORLESS_COMMAND_ID, construct_cursorless_command(action), ) - def private_cursorless_command_get(action: dict): + def private_cursorless_command_get(action: dict): # pyright: ignore [reportGeneralTypeIssues] """Execute cursorless command and return result""" response = actions.user.private_cursorless_run_rpc_command_get( CURSORLESS_COMMAND_ID, diff --git a/cursorless-talon/src/csv_overrides.py b/cursorless-talon/src/csv_overrides.py index f989113969..f71b0d9097 100644 --- a/cursorless-talon/src/csv_overrides.py +++ b/cursorless-talon/src/csv_overrides.py @@ -1,4 +1,5 @@ import csv +import typing from collections import defaultdict from collections.abc import Container from dataclasses import dataclass @@ -453,7 +454,9 @@ def get_full_path(filename: str): filename = f"{filename}.csv" user_dir: Path = actions.path.talon_user() - settings_directory = Path(settings.get("user.cursorless_settings_directory")) + settings_directory = Path( + typing.cast(str, settings.get("user.cursorless_settings_directory")) + ) if not settings_directory.is_absolute(): settings_directory = user_dir / settings_directory diff --git a/cursorless-talon/src/cursorless_command_server.py b/cursorless-talon/src/cursorless_command_server.py index c6177d30ff..78d30ad78d 100644 --- a/cursorless-talon/src/cursorless_command_server.py +++ b/cursorless-talon/src/cursorless_command_server.py @@ -8,7 +8,9 @@ @mod.action_class class Actions: def private_cursorless_run_rpc_command_and_wait( - command_id: str, arg1: Any = None, arg2: Any = None + command_id: str, # pyright: ignore [reportGeneralTypeIssues] + arg1: Any = None, + arg2: Any = None, ): """Execute command via rpc and wait for command to finish.""" try: @@ -17,7 +19,9 @@ def private_cursorless_run_rpc_command_and_wait( actions.user.vscode_with_plugin_and_wait(command_id, arg1, arg2) def private_cursorless_run_rpc_command_no_wait( - command_id: str, arg1: Any = None, arg2: Any = None + command_id: str, # pyright: ignore [reportGeneralTypeIssues] + arg1: Any = None, + arg2: Any = None, ): """Execute command via rpc and DON'T wait.""" try: @@ -26,7 +30,9 @@ def private_cursorless_run_rpc_command_no_wait( actions.user.vscode_with_plugin(command_id, arg1, arg2) def private_cursorless_run_rpc_command_get( - command_id: str, arg1: Any = None, arg2: Any = None + command_id: str, # pyright: ignore [reportGeneralTypeIssues] + arg1: Any = None, + arg2: Any = None, ) -> Any: """Execute command via rpc and return command output.""" try: diff --git a/cursorless-talon/src/modifiers/surrounding_pair.py b/cursorless-talon/src/modifiers/surrounding_pair.py index a6df5b2be9..72e1cbddf0 100644 --- a/cursorless-talon/src/modifiers/surrounding_pair.py +++ b/cursorless-talon/src/modifiers/surrounding_pair.py @@ -11,7 +11,9 @@ "cursorless_delimiter_force_direction", desc="Can be used to force an ambiguous delimiter to extend in one direction", ) -ctx.lists["user.cursorless_delimiter_force_direction"] = [ +# FIXME: Remove type ignore once Talon supports list types +# See https://github.com/talonvoice/talon/issues/654 +ctx.lists["user.cursorless_delimiter_force_direction"] = [ # pyright: ignore [reportArgumentType] "left", "right", ] diff --git a/cursorless-talon/src/number_small.py b/cursorless-talon/src/number_small.py index 28ce298f70..fd800ae232 100644 --- a/cursorless-talon/src/number_small.py +++ b/cursorless-talon/src/number_small.py @@ -33,7 +33,9 @@ def private_cursorless_number_small(m) -> int: number_small_map = {n: i for i, n in enumerate(number_small_list)} mod.list("private_cursorless_number_small", desc="List of small numbers") -ctx.lists["self.private_cursorless_number_small"] = number_small_map.keys() +# FIXME: Remove type ignore once Talon supports list types +# See https://github.com/talonvoice/talon/issues/654 +ctx.lists["self.private_cursorless_number_small"] = number_small_map.keys() # pyright: ignore [reportArgumentType] @ctx.capture( diff --git a/cursorless-talon/src/private_api/private_api.py b/cursorless-talon/src/private_api/private_api.py index dd047e2108..16665942c2 100644 --- a/cursorless-talon/src/private_api/private_api.py +++ b/cursorless-talon/src/private_api/private_api.py @@ -25,14 +25,15 @@ class TargetBuilderActions: """Cursorless private api low-level target builder actions""" def cursorless_private_build_primitive_target( - modifiers: list[dict], mark: Optional[dict] + modifiers: list[dict], # pyright: ignore [reportGeneralTypeIssues] + mark: Optional[dict], ) -> PrimitiveTarget: """Cursorless private api low-level target builder: Create a primitive target""" return PrimitiveTarget(mark, modifiers) def cursorless_private_build_list_target( - elements: list[Union[PrimitiveTarget, RangeTarget]], - ) -> Union[PrimitiveTarget, ListTarget]: + elements: list[Union[PrimitiveTarget, RangeTarget]], # pyright: ignore [reportGeneralTypeIssues] + ) -> Union[PrimitiveTarget, RangeTarget, ListTarget]: """Cursorless private api low-level target builder: Create a list target""" if len(elements) == 1: return elements[0] @@ -50,7 +51,8 @@ def cursorless_private_target_nothing() -> PrimitiveTarget: @mod.action_class class ActionActions: def cursorless_private_action_highlight( - target: CursorlessTarget, highlightId: Optional[str] = None + target: CursorlessTarget, # pyright: ignore [reportGeneralTypeIssues] + highlightId: Optional[str] = None, ) -> None: """Cursorless private api: Highlights a target""" payload = { diff --git a/cursorless-talon/src/scope_visualizer.py b/cursorless-talon/src/scope_visualizer.py index 96180b8ba0..423796bacf 100644 --- a/cursorless-talon/src/scope_visualizer.py +++ b/cursorless-talon/src/scope_visualizer.py @@ -12,7 +12,8 @@ @mod.action_class class Actions: def private_cursorless_show_scope_visualizer( - scope_type: dict, visualization_type: str + scope_type: dict, # pyright: ignore [reportGeneralTypeIssues] + visualization_type: str, ): """Shows scope visualizer""" actions.user.private_cursorless_run_rpc_command_no_wait( diff --git a/cursorless-talon/src/snippets.py b/cursorless-talon/src/snippets.py index ae4b766bcb..1a28fb1df8 100644 --- a/cursorless-talon/src/snippets.py +++ b/cursorless-talon/src/snippets.py @@ -19,14 +19,14 @@ class InsertionSnippet: @dataclass class CommunityInsertionSnippet: body: str - scopes: list[str] = None + scopes: list[str] | None = None @dataclass class CommunityWrapperSnippet: body: str variable_name: str - scope: str = None + scope: str | None = None mod = Module() @@ -99,7 +99,7 @@ def insert_named_snippet( destination: CursorlessDestination, substitutions: Optional[dict] = None, ): - snippet = { + snippet: dict = { "type": "named", "name": name, } @@ -113,7 +113,7 @@ def insert_custom_snippet( destination: CursorlessDestination, scope_types: Optional[list[dict]] = None, ): - snippet = { + snippet: dict = { "type": "custom", "body": body, } @@ -126,7 +126,7 @@ def insert_custom_snippet( @mod.action_class class Actions: - def private_cursorless_insert_snippet(insertion_snippet: InsertionSnippet): + def private_cursorless_insert_snippet(insertion_snippet: InsertionSnippet): # pyright: ignore [reportGeneralTypeIssues] """Execute Cursorless insert snippet action""" insert_named_snippet( insertion_snippet.name, @@ -134,7 +134,8 @@ def private_cursorless_insert_snippet(insertion_snippet: InsertionSnippet): ) def private_cursorless_insert_snippet_with_phrase( - snippet_description: str, text: str + snippet_description: str, # pyright: ignore [reportGeneralTypeIssues] + text: str, ): """Cursorless: Insert snippet with phrase """ snippet_name, snippet_variable = snippet_description.split(".") @@ -144,7 +145,7 @@ def private_cursorless_insert_snippet_with_phrase( {snippet_variable: text}, ) - def cursorless_insert_snippet_by_name(name: str): + def cursorless_insert_snippet_by_name(name: str): # pyright: ignore [reportGeneralTypeIssues] """Cursorless: Insert named snippet """ insert_named_snippet( name, @@ -152,8 +153,8 @@ def cursorless_insert_snippet_by_name(name: str): ) def cursorless_insert_snippet( - body: str, - destination: Optional[CursorlessDestination] = ImplicitDestination(), + body: str, # pyright: ignore [reportGeneralTypeIssues] + destination: CursorlessDestination = ImplicitDestination(), scope_type: Optional[Union[str, list[str]]] = None, ): """Cursorless: Insert custom snippet """ @@ -168,7 +169,9 @@ def cursorless_insert_snippet( insert_custom_snippet(body, destination, scope_types) def cursorless_wrap_with_snippet_by_name( - name: str, variable_name: str, target: CursorlessTarget + name: str, # pyright: ignore [reportGeneralTypeIssues] + variable_name: str, + target: CursorlessTarget, ): """Cursorless: Wrap target with a named snippet """ wrap_with_snippet( @@ -181,7 +184,7 @@ def cursorless_wrap_with_snippet_by_name( ) def cursorless_wrap_with_snippet( - body: str, + body: str, # pyright: ignore [reportGeneralTypeIssues] target: CursorlessTarget, variable_name: Optional[str] = None, scope: Optional[str] = None, @@ -201,7 +204,8 @@ def cursorless_wrap_with_snippet( ) def private_cursorless_insert_community_snippet( - name: str, destination: CursorlessDestination + name: str, # pyright: ignore [reportGeneralTypeIssues] + destination: CursorlessDestination, ): """Cursorless: Insert community snippet """ snippet: CommunityInsertionSnippet = actions.user.get_insertion_snippet(name) @@ -210,7 +214,8 @@ def private_cursorless_insert_community_snippet( ) def private_cursorless_wrap_with_community_snippet( - name: str, target: CursorlessTarget + name: str, # pyright: ignore [reportGeneralTypeIssues] + target: CursorlessTarget, ): """Cursorless: Wrap target with community snippet """ snippet: CommunityWrapperSnippet = actions.user.get_wrapper_snippet(name) diff --git a/cursorless-talon/src/targets/target_types.py b/cursorless-talon/src/targets/target_types.py index 49e028322b..05800e52d2 100644 --- a/cursorless-talon/src/targets/target_types.py +++ b/cursorless-talon/src/targets/target_types.py @@ -40,6 +40,11 @@ class ListTarget: PrimitiveTarget, ImplicitTarget, ] +CursorlessExplicitTarget = Union[ + ListTarget, + RangeTarget, + PrimitiveTarget, +] @dataclass diff --git a/cursorless-talon/src/terms.py b/cursorless-talon/src/terms.py index f8ef66c693..d41727af64 100644 --- a/cursorless-talon/src/terms.py +++ b/cursorless-talon/src/terms.py @@ -12,7 +12,9 @@ "Various alternative pronunciations of 'cursorless' to improve accuracy", ) -ctx.lists["user.cursorless_homophone"] = [ +# FIXME: Remove type ignore once Talon supports list types +# See https://github.com/talonvoice/talon/issues/654 +ctx.lists["user.cursorless_homophone"] = [ # pyright: ignore [reportArgumentType] "cursorless", "cursor less", "cursor list", diff --git a/data/fixtures/recorded/fallback/takeToken2.yml b/data/fixtures/recorded/fallback/takeToken2.yml new file mode 100644 index 0000000000..bdcb9f8ce8 --- /dev/null +++ b/data/fixtures/recorded/fallback/takeToken2.yml @@ -0,0 +1,24 @@ +languageId: plaintext +focusedElementType: textEditor +command: + version: 7 + spokenForm: take token + action: + name: setSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: token} + usePrePhraseSnapshot: true +initialState: + documentContents: foo + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: foo + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 3} diff --git a/docs/user/customization.md b/docs/user/customization.md index c9039286d7..b8309e9813 100644 --- a/docs/user/customization.md +++ b/docs/user/customization.md @@ -70,6 +70,40 @@ push down, editor.action.moveLinesDownAction Now when you say eg "push down air and bat", cursorless will first select the two tokens with a gray hat over the `a` and `b`, then issue the VSCode command `editor.action.moveLinesDownAction`, and then restore your original selection. +## \[Experimental\] Cursorless custom regex scopes + +You can define custom scopes using regexes in `user/cursorless-settings/experimental/regex_scope_types.csv` + +:::tip + +Use `"visualize "` to see a live preview of the regex scope in [the scope visualizer](./scope-visualizer.md). It updates in real time every time you save `regex_scope_types.csv`. + +::: + +For example, here's what `"visualize dotted"` would show with the scope type `dotted,"[\w.]+"`: + +
+ ![visualization of a custom regex scope](./images/custom-regex-scopes.png) +
+ +You can then use commands such as + +- `"take dotted sun"` to select `user.text` (line 10) +- `"copy dotted urge"` to copy `user.chrome_mod` (line 11) +- `"take every dotted urge"` to select `user.chrome_mod`, `shift`, and `a` + +:::tip + +> Check out [our wiki page](https://github.com/cursorless-dev/cursorless/wiki/Custom-regex-scopes) for a recipe book of user-created regex scopes! + +::: + +:::warning + +Regex matches cannot cross line boundaries (so multiline matches are not supported). The regexes also have the unicode flag set. + +::: + ## Toggling "hat" display It is possible to show / hide the hats with a command. Keep in mind that many users, often after less than a week using Cursorless, find that their brain starts to tune out the hat display. Some start to miss them when they're gone 🥲 diff --git a/docs/user/images/custom-regex-scopes.png b/docs/user/images/custom-regex-scopes.png new file mode 100644 index 0000000000..b595c6a156 Binary files /dev/null and b/docs/user/images/custom-regex-scopes.png differ diff --git a/package.json b/package.json index 09b4ba6903..f011c3b303 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,6 @@ "engines": { "node": ">=18.18.2" }, - "packageManager": "pnpm@8.15.5", + "packageManager": "pnpm@9.0.6", "type": "module" } diff --git a/packages/common/src/FakeCommandServerApi.ts b/packages/common/src/FakeCommandServerApi.ts index 8a96f44527..8ea7b91009 100644 --- a/packages/common/src/FakeCommandServerApi.ts +++ b/packages/common/src/FakeCommandServerApi.ts @@ -10,7 +10,6 @@ export class FakeCommandServerApi implements CommandServerApi { constructor() { this.signals = { prePhrase: { getVersion: async () => null } }; - this.focusedElementType = "textEditor"; } async getFocusedElementType(): Promise { diff --git a/packages/common/src/types/CommandServerApi.ts b/packages/common/src/types/CommandServerApi.ts index 96f1ecb3ae..0d3fdaa890 100644 --- a/packages/common/src/types/CommandServerApi.ts +++ b/packages/common/src/types/CommandServerApi.ts @@ -9,7 +9,7 @@ export interface CommandServerApi { }; } -export type FocusedElementType = "textEditor" | "terminal"; +export type FocusedElementType = "textEditor" | "terminal" | "other"; export interface InboundSignal { getVersion(): Promise; diff --git a/packages/common/src/types/TestCaseFixture.ts b/packages/common/src/types/TestCaseFixture.ts index 7b366e694a..c3030e2b40 100644 --- a/packages/common/src/types/TestCaseFixture.ts +++ b/packages/common/src/types/TestCaseFixture.ts @@ -15,7 +15,7 @@ interface TestCaseFixtureBase { /** * The type of element that is focused before the command is executed. If undefined default to text editor. */ - focusedElementType?: FocusedElementType | "other"; + focusedElementType?: FocusedElementType; /** * A list of marks to check in the case of navigation map test otherwise undefined diff --git a/packages/cursorless-engine/src/core/getCommandFallback.ts b/packages/cursorless-engine/src/core/getCommandFallback.ts index d69a4b86dc..941a02c0eb 100644 --- a/packages/cursorless-engine/src/core/getCommandFallback.ts +++ b/packages/cursorless-engine/src/core/getCommandFallback.ts @@ -14,10 +14,9 @@ export async function getCommandFallback( runAction: (actionDescriptor: ActionDescriptor) => Promise, command: CommandComplete, ): Promise { - if ( - commandServerApi == null || - (await commandServerApi.getFocusedElementType()) === "textEditor" - ) { + const focusedElementType = await commandServerApi?.getFocusedElementType(); + + if (focusedElementType == null || focusedElementType === "textEditor") { return null; } diff --git a/packages/cursorless-engine/src/cursorlessEngine.ts b/packages/cursorless-engine/src/cursorlessEngine.ts index ea699e0aea..5baa773a13 100644 --- a/packages/cursorless-engine/src/cursorlessEngine.ts +++ b/packages/cursorless-engine/src/cursorlessEngine.ts @@ -31,13 +31,13 @@ import { ScopeSupportWatcher } from "./scopeProviders/ScopeSupportWatcher"; import { injectIde } from "./singletons/ide.singleton"; import { TreeSitter } from "./typings/TreeSitter"; -export function createCursorlessEngine( +export async function createCursorlessEngine( treeSitter: TreeSitter, ide: IDE, hats: Hats, commandServerApi: CommandServerApi | null, fileSystem: FileSystem, -): CursorlessEngine { +): Promise { injectIde(ide); const debug = new Debug(treeSitter); @@ -61,6 +61,7 @@ export function createCursorlessEngine( const storedTargets = new StoredTargetMap(); const languageDefinitions = new LanguageDefinitions(fileSystem, treeSitter); + await languageDefinitions.init(); const talonSpokenForms = new TalonSpokenFormsJsonReader(fileSystem); diff --git a/packages/cursorless-engine/src/languages/LanguageDefinitions.ts b/packages/cursorless-engine/src/languages/LanguageDefinitions.ts index fbd44b951a..b8c211b5b0 100644 --- a/packages/cursorless-engine/src/languages/LanguageDefinitions.ts +++ b/packages/cursorless-engine/src/languages/LanguageDefinitions.ts @@ -60,10 +60,6 @@ export class LanguageDefinitions { ? join(getCursorlessRepoRoot(), "queries") : "queries"; - ide().visibleTextEditors.forEach(({ document }) => - this.loadLanguage(document.languageId), - ); - if (ide().runMode === "development") { this.disposables.push( fileSystem.watchDir(this.queryDir, () => { @@ -73,6 +69,20 @@ export class LanguageDefinitions { } } + public async init(): Promise { + await this.loadAllLanguages(); + } + + private async loadAllLanguages(): Promise { + const languageIds = ide().visibleTextEditors.map( + ({ document }) => document.languageId, + ); + + await Promise.all( + languageIds.map((languageId) => this.loadLanguage(languageId)), + ); + } + public async loadLanguage(languageId: string): Promise { if (this.languageDefinitions.has(languageId)) { return; diff --git a/packages/cursorless-engine/src/testCaseRecorder/TestCase.ts b/packages/cursorless-engine/src/testCaseRecorder/TestCase.ts index 0dd2dad532..2d4959b496 100644 --- a/packages/cursorless-engine/src/testCaseRecorder/TestCase.ts +++ b/packages/cursorless-engine/src/testCaseRecorder/TestCase.ts @@ -141,9 +141,9 @@ export class TestCase { const fixture: EnforceUndefined = { languageId: this.languageId, focusedElementType: - this.focusedElementType !== "textEditor" - ? this.focusedElementType ?? "other" - : undefined, + this.focusedElementType === "textEditor" + ? undefined + : this.focusedElementType, postEditorOpenSleepTimeMs: undefined, postCommandSleepTimeMs: undefined, command: this.command, diff --git a/packages/cursorless-neovim-e2e/src/suite/recorded.neovim.test.ts b/packages/cursorless-neovim-e2e/src/suite/recorded.neovim.test.ts index fc2c5fbb68..f1ed8b423f 100644 --- a/packages/cursorless-neovim-e2e/src/suite/recorded.neovim.test.ts +++ b/packages/cursorless-neovim-e2e/src/suite/recorded.neovim.test.ts @@ -349,6 +349,11 @@ function isFailingFixture(name: string, fixture: TestCaseFixtureLegacy) { return true; } + // "recorded/fallback/take*" -> wrong fixture.finalState.selections + if (name.includes("/fallback/take")) { + return true; + } + // We blacklist remaining unsorted failing tests if (failingFixtures.includes(name)) { return true; diff --git a/packages/cursorless-neovim/src/extension.ts b/packages/cursorless-neovim/src/extension.ts index fdcc08b1af..b84dcfc626 100644 --- a/packages/cursorless-neovim/src/extension.ts +++ b/packages/cursorless-neovim/src/extension.ts @@ -64,7 +64,7 @@ export async function activate(plugin: NvimPlugin) { runIntegrationTests, addCommandRunnerDecorator, customSpokenFormGenerator, - } = createCursorlessEngine( + } = await createCursorlessEngine( treeSitter, normalizedIde, hats, diff --git a/packages/cursorless-org-docs/src/css/custom.css b/packages/cursorless-org-docs/src/css/custom.css index 911fe1a5d7..9dca5a9900 100644 --- a/packages/cursorless-org-docs/src/css/custom.css +++ b/packages/cursorless-org-docs/src/css/custom.css @@ -20,3 +20,7 @@ [data-theme="dark"] .dark-mode-invert { filter: invert(90%) hue-rotate(180deg); } + +[data-theme="light"] .light-mode-invert { + filter: invert(90%) hue-rotate(180deg); +} diff --git a/packages/cursorless-vscode-e2e/src/endToEndTestSetup.ts b/packages/cursorless-vscode-e2e/src/endToEndTestSetup.ts index a6fab13c66..4cfc633ecd 100644 --- a/packages/cursorless-vscode-e2e/src/endToEndTestSetup.ts +++ b/packages/cursorless-vscode-e2e/src/endToEndTestSetup.ts @@ -28,7 +28,9 @@ export function endToEndTestSetup(suite: Mocha.Suite) { const title = this.test!.fullTitle(); retryCount = title === previousTestTitle ? retryCount + 1 : 0; previousTestTitle = title; - ({ ide, injectIde } = (await getCursorlessApi()).testHelpers!); + const testHelpers = (await getCursorlessApi()).testHelpers!; + ({ ide, injectIde } = testHelpers); + testHelpers.commandServerApi.setFocusedElementType(undefined); spy = new SpyIDE(ide); injectIde(spy); }); diff --git a/packages/cursorless-vscode-e2e/src/suite/recorded.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/recorded.vscode.test.ts index 1ab8788122..a6d69a4ca6 100644 --- a/packages/cursorless-vscode-e2e/src/suite/recorded.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/recorded.vscode.test.ts @@ -104,11 +104,7 @@ async function runTest(file: string, spyIde: SpyIDE) { // spyIde.clipboard.writeText(fixture.initialState.clipboard); } - commandServerApi.setFocusedElementType( - fixture.focusedElementType === "other" - ? undefined - : fixture.focusedElementType ?? "textEditor", - ); + commandServerApi.setFocusedElementType(fixture.focusedElementType); // Ensure that the expected hats are present await hatTokenMap.allocateHats( diff --git a/packages/cursorless-vscode/src/extension.ts b/packages/cursorless-vscode/src/extension.ts index fcc7e2334d..de08aa21b6 100644 --- a/packages/cursorless-vscode/src/extension.ts +++ b/packages/cursorless-vscode/src/extension.ts @@ -92,7 +92,7 @@ export async function activate( runIntegrationTests, addCommandRunnerDecorator, customSpokenFormGenerator, - } = createCursorlessEngine( + } = await createCursorlessEngine( treeSitter, normalizedIde, hats, diff --git a/packages/meta-updater/package.json b/packages/meta-updater/package.json index 41aba69644..54d5ddc0d4 100644 --- a/packages/meta-updater/package.json +++ b/packages/meta-updater/package.json @@ -11,9 +11,9 @@ }, "dependencies": { "@cursorless/common": "workspace:*", - "@pnpm/lockfile-file": "8.1.8", + "@pnpm/lockfile-file": "9.0.2", "@pnpm/logger": "^5.0.0", - "@pnpm/types": "9.4.2", + "@pnpm/types": "10.0.0", "@types/normalize-path": "^3.0.2", "js-yaml": "^4.1.0", "lodash": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e22d137fc4..b082b58835 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -656,14 +656,14 @@ importers: specifier: workspace:* version: link:../common '@pnpm/lockfile-file': - specifier: 8.1.8 - version: 8.1.8(@pnpm/logger@5.0.0) + specifier: 9.0.2 + version: 9.0.2(@pnpm/logger@5.0.0) '@pnpm/logger': specifier: ^5.0.0 version: 5.0.0 '@pnpm/types': - specifier: 9.4.2 - version: 9.4.2 + specifier: 10.0.0 + version: 10.0.0 '@types/normalize-path': specifier: ^3.0.2 version: 3.0.2 @@ -4087,6 +4087,11 @@ packages: - '@pnpm/logger' dev: true + /@pnpm/constants@6.2.0: + resolution: {integrity: sha512-GlDVUkeTR2WK0oZAM+wtDY6RBMLw6b0Z/5qKgBbDszx4e+R7CHyfG7JofyypogRCfeWXeAXp2C2FkFTh+sNgIg==} + engines: {node: '>=14.6'} + dev: false + /@pnpm/constants@7.1.0: resolution: {integrity: sha512-PzpiPtGF+bIrmkNaHgOIfBZw669+rkUtt/5UFzHukiETwI4/+BTYz8FAr+m5Dfuns531Y+fYRFOpB0PdbAU0+w==} engines: {node: '>=16.14'} @@ -4095,6 +4100,22 @@ packages: /@pnpm/constants@7.1.1: resolution: {integrity: sha512-31pZqMtjwV+Vaq7MaPrT1EoDFSYwye3dp6BiHIGRJmVThCQwySRKM7hCvqqI94epNkqFAAYoWrNynWoRYosGdw==} engines: {node: '>=16.14'} + dev: true + + /@pnpm/constants@8.0.0: + resolution: {integrity: sha512-yQosGUvYPpAjb1jOFcdbwekRjZRVxN6C0hHzfRCZrMKbxGjt/E0g0RcFlEDNVZ95tm4oMMcr7nEPa7H7LX3emw==} + engines: {node: '>=18.12'} + dev: false + + /@pnpm/core-loggers@10.0.0(@pnpm/logger@5.0.0): + resolution: {integrity: sha512-nf6DWO+75llaOxZ4Wb5xIzC86jb9PEeD8y7E4bbkLCJUvv/vRVgaPO3+Fo2GFTw5ZY7cip60rTF6dUzbP9dOVw==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': ^5.0.0 + dependencies: + '@pnpm/logger': 5.0.0 + '@pnpm/types': 10.0.0 + dev: false /@pnpm/core-loggers@9.0.1(@pnpm/logger@5.0.0): resolution: {integrity: sha512-qP/kk6OeLSxqhvA4n6u4XB6evqD9h1w9p4qtdBOVbkZloCK7L9btkSmKNolBoQ3wrOz7WRFfjRekYUSKphMMCg==} @@ -4106,9 +4127,9 @@ packages: '@pnpm/types': 9.1.0 dev: true - /@pnpm/crypto.base32-hash@2.0.0: - resolution: {integrity: sha512-3ttOeHBpmWRbgJrpDQ8Nwd3W8s8iuiP5YZM0JRyKWaMtX8lu9d7/AKyxPmhYsMJuN+q/1dwHa7QFeDZJ53b0oA==} - engines: {node: '>=16.14'} + /@pnpm/crypto.base32-hash@3.0.0: + resolution: {integrity: sha512-iGKP6rRKng5Tcad1+S+j3UoY5wVZN+z0ZgemlGp69jNgn6EaM4N0Q3mvnDNJ7UZFmL2ClXZZYLNuCk9pUYV3Xg==} + engines: {node: '>=18.12'} dependencies: rfc4648: 1.5.3 dev: false @@ -4156,16 +4177,22 @@ packages: strip-ansi: 6.0.1 dev: true - /@pnpm/dependency-path@2.1.8: - resolution: {integrity: sha512-ywBaTjy0iSEF7lH3DlF8UXrdL2bw4AQFV2tTOeNeY7wc1W5CE+RHSJhf9MXBYcZPesqGRrPiU7Pimj3l05L9VA==} - engines: {node: '>=16.14'} + /@pnpm/dependency-path@3.0.0: + resolution: {integrity: sha512-7n6pwEN/BiqUQEEBct62kXU0SB0gSgt2b+1RObAD7aEo4kvHbqgRy5ZXn4/DPStUy6YlccZJ8veI5ne+GQ9hKA==} + engines: {node: '>=18.12'} dependencies: - '@pnpm/crypto.base32-hash': 2.0.0 - '@pnpm/types': 9.4.2 - encode-registry: 3.0.1 + '@pnpm/crypto.base32-hash': 3.0.0 + '@pnpm/types': 10.0.0 semver: 7.6.0 dev: false + /@pnpm/error@4.0.1: + resolution: {integrity: sha512-6UFakGqUDhnZVzYCfN+QaG1epxtBVS1M9mb9RzoBuvWxcimBYTT04fdYuyk1Nay8y/TvAVl3AVB/lCziWG0+2w==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/constants': 6.2.0 + dev: false + /@pnpm/error@5.0.1: resolution: {integrity: sha512-JQSOeSEqrV6k6+kKgrlSJ7gddJRcjxtNCxSVJRIqwckkGSdSTNpXmKEdGgLlaDuEwElPAZUmLDGSqk5InJ5pMA==} engines: {node: '>=16.14'} @@ -4178,6 +4205,32 @@ packages: engines: {node: '>=16.14'} dependencies: '@pnpm/constants': 7.1.1 + dev: true + + /@pnpm/error@6.0.0: + resolution: {integrity: sha512-SKtHdV09k9+6jkohv9YuYmKMKNpxknoGjo0c6eN8x2Z3MHW2cuSt1OD/L16eCqdKQL+FUbvULxig0b9X9VK2/g==} + engines: {node: '>=18.12'} + dependencies: + '@pnpm/constants': 8.0.0 + dev: false + + /@pnpm/fetch@8.0.0(@pnpm/logger@5.0.0): + resolution: {integrity: sha512-V9khLYMUmadH45A5zZnrt1nUsZ0NokWkw0QjjgSdiBCgRyQnf1SvFjVcj4sVWxK0ZaijZQnIhIcKvlV3/zB0Ig==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': ^5.0.0 + dependencies: + '@pnpm/core-loggers': 10.0.0(@pnpm/logger@5.0.0) + '@pnpm/fetching-types': 6.0.0 + '@pnpm/logger': 5.0.0 + '@pnpm/network.agent': 1.0.1 + '@pnpm/types': 10.0.0 + '@zkochan/retry': 0.2.0 + node-fetch: /@pnpm/node-fetch@1.0.0 + transitivePeerDependencies: + - domexception + - supports-color + dev: false /@pnpm/fetcher-base@14.0.1: resolution: {integrity: sha512-DXPZ33CrmDQXnYzwvqyP7I0BF0MQELo4ah2JGpXhLhgOdzU+vj7zdKFo2x82L8anrK861IRi01V8o14oATq1vA==} @@ -4188,6 +4241,16 @@ packages: '@types/ssri': 7.1.5 dev: true + /@pnpm/fetching-types@6.0.0: + resolution: {integrity: sha512-fnsaegb+0q7Ku6AyCmoVtBeCuO8ytB7YMEaGHC+0MGoRsxxa6EVLgi2H4abKr8LLslf5tHJBnOH24DjST3UNfQ==} + engines: {node: '>=18.12'} + dependencies: + '@zkochan/retry': 0.2.0 + node-fetch: /@pnpm/node-fetch@1.0.0 + transitivePeerDependencies: + - domexception + dev: false + /@pnpm/find-workspace-dir@6.0.3: resolution: {integrity: sha512-0iJnNkS4T8lJE4ldOhRERgER1o59iHA1nMlvpUI5lxNC9SUruH6peRUOlP4/rNcDg+UQ9u0rt5loYOnWKCojtw==} engines: {node: '>=16.14'} @@ -4221,11 +4284,34 @@ packages: p-filter: 2.1.0 dev: true + /@pnpm/git-resolver@9.0.1(@pnpm/logger@5.0.0): + resolution: {integrity: sha512-B1FtKwEEUm8130XqmX7eqgMhqdBxJ5gPrWssOLnpIlp/rvmJFsfD2P//80OjORPNFWnpfqdfBF34c/+ZCzAxZg==} + engines: {node: '>=18.12'} + dependencies: + '@pnpm/fetch': 8.0.0(@pnpm/logger@5.0.0) + '@pnpm/resolver-base': 12.0.0 + graceful-git: 3.1.2 + hosted-git-info: /@pnpm/hosted-git-info@1.0.0 + semver: 7.6.0 + transitivePeerDependencies: + - '@pnpm/logger' + - domexception + - supports-color + dev: false + /@pnpm/git-utils@1.0.0: resolution: {integrity: sha512-lUI+XrzOJN4zdPGOGnFUrmtXAXpXi8wD8OI0nWOZmlh+raqbLzC3VkXu1zgaduOK6YonOcnQW88O+ojav1rAdA==} engines: {node: '>=16.14'} dependencies: execa: /safe-execa@0.1.2 + dev: true + + /@pnpm/git-utils@2.0.0: + resolution: {integrity: sha512-k1rv4Zvno/5zJAqE/Mh9V0ehlm14NsYwpXTdaGMtyhkoHvlSckRfr23OIOIM7Q/TRX+LhqyJ2kep50SY2TsZ+g==} + engines: {node: '>=18.12'} + dependencies: + execa: /safe-execa@0.1.2 + dev: false /@pnpm/graceful-fs@3.0.0: resolution: {integrity: sha512-72kkqIL2sacOVr6Y6B6xDGjRC4QgTLeIGkw/5XYyeMgMeL9mDE0lonZEOL9JuLS0XPOXQoyDtRCSmUrzAA57LQ==} @@ -4242,30 +4328,42 @@ packages: '@pnpm/types': 9.1.0 dev: true - /@pnpm/lockfile-file@8.1.8(@pnpm/logger@5.0.0): - resolution: {integrity: sha512-bRadYzGFyFtwiynwp4Mkn7NDNHkgKvJ9xtjsCT5XiE6S8wpzS3W8yx2WzHGk9Mm1J/2wM0F52+NzCWhlz5eIqA==} - engines: {node: '>=16.14'} + /@pnpm/hosted-git-info@1.0.0: + resolution: {integrity: sha512-QzmNiLShTnNyeTHr+cykG5hYjwph0+v49KHV36Dh8uA2rRMWw30qoZMARuxd00SYdoTwT8bIouqqmzi6TWfJHQ==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: false + + /@pnpm/lockfile-file@9.0.2(@pnpm/logger@5.0.0): + resolution: {integrity: sha512-lgrVC3pkAKKLfLnQIotQ6zeiZgRypblZ/v5fat1eaK4e4KJmjSvkiqlqzC+RXj0njxB7O7a9XCnb6XzTe+63hQ==} + engines: {node: '>=18.12'} peerDependencies: '@pnpm/logger': ^5.0.0 dependencies: - '@pnpm/constants': 7.1.1 - '@pnpm/dependency-path': 2.1.8 - '@pnpm/error': 5.0.3 - '@pnpm/git-utils': 1.0.0 - '@pnpm/lockfile-types': 5.1.5 + '@pnpm/constants': 8.0.0 + '@pnpm/dependency-path': 3.0.0 + '@pnpm/error': 6.0.0 + '@pnpm/git-resolver': 9.0.1(@pnpm/logger@5.0.0) + '@pnpm/git-utils': 2.0.0 + '@pnpm/lockfile-types': 6.0.0 + '@pnpm/lockfile-utils': 10.0.0 '@pnpm/logger': 5.0.0 - '@pnpm/merge-lockfile-changes': 5.0.7 - '@pnpm/types': 9.4.2 - '@pnpm/util.lex-comparator': 1.0.0 + '@pnpm/merge-lockfile-changes': 6.0.0 + '@pnpm/types': 10.0.0 + '@pnpm/util.lex-comparator': 3.0.0 '@zkochan/rimraf': 2.1.3 comver-to-semver: 1.0.0 - js-yaml: /@zkochan/js-yaml@0.0.6 + js-yaml: /@zkochan/js-yaml@0.0.7 normalize-path: 3.0.0 ramda: /@pnpm/ramda@0.28.1 semver: 7.6.0 sort-keys: 4.2.0 strip-bom: 4.0.0 write-file-atomic: 5.0.1 + transitivePeerDependencies: + - domexception + - supports-color dev: false /@pnpm/lockfile-types@5.1.0: @@ -4275,11 +4373,24 @@ packages: '@pnpm/types': 9.1.0 dev: true - /@pnpm/lockfile-types@5.1.5: - resolution: {integrity: sha512-02FP0HynzX+2DcuPtuMy7PH+kLIC0pevAydAOK+zug2bwdlSLErlvSkc+4+3dw60eRWgUXUqyfO2eR/Ansdbng==} - engines: {node: '>=16.14'} + /@pnpm/lockfile-types@6.0.0: + resolution: {integrity: sha512-a4/ULIPLZIIq8Qmi2HEoFgRTtEouGU5RNhuGDxnSmkxu1BjlNMNjLJeEI5jzMZCGOjBoML+AirY/XOO3bcEQ/w==} + engines: {node: '>=18.12'} dependencies: - '@pnpm/types': 9.4.2 + '@pnpm/types': 10.0.0 + dev: false + + /@pnpm/lockfile-utils@10.0.0: + resolution: {integrity: sha512-R2JXeAVdtXwu7NxfA4936Og6JHMGZCjOJ+45DUVP9SR7k2WS1bfOSeD5NRuuwqqdw+gYjsTvaYMYXhH6Sr0k2Q==} + engines: {node: '>=18.12'} + dependencies: + '@pnpm/dependency-path': 3.0.0 + '@pnpm/lockfile-types': 6.0.0 + '@pnpm/pick-fetcher': 3.0.0 + '@pnpm/resolver-base': 12.0.0 + '@pnpm/types': 10.0.0 + get-npm-tarball-url: 2.1.0 + ramda: /@pnpm/ramda@0.28.1 dev: false /@pnpm/logger@5.0.0: @@ -4307,11 +4418,11 @@ packages: escape-string-regexp: 4.0.0 dev: true - /@pnpm/merge-lockfile-changes@5.0.7: - resolution: {integrity: sha512-fYmX1+EHv3wg7l4A9FCEkjgEBIHaY6JosknkLk3pL8dbB9k6unjIrF9f2onNtpj3XUlWxZ3aBw9THk/Bf6hKow==} - engines: {node: '>=16.14'} + /@pnpm/merge-lockfile-changes@6.0.0: + resolution: {integrity: sha512-K9ARTZ+o/EZ10RPZY4dftlSnvPgJrVeOG0QwZLNTb9Z9q8D6EqSVwEh7CxDobGFe5FAj2lkDK6DY7EgPI4hhdw==} + engines: {node: '>=18.12'} dependencies: - '@pnpm/lockfile-types': 5.1.5 + '@pnpm/lockfile-types': 6.0.0 comver-to-semver: 1.0.0 ramda: /@pnpm/ramda@0.28.1 semver: 7.6.0 @@ -4333,12 +4444,54 @@ packages: write-json-file: 5.0.0 dev: true + /@pnpm/network.agent@1.0.1: + resolution: {integrity: sha512-yRm8MzpZvst5IYF5IUgK7q5SvcncCUWOVBqpl527Pz6BafmDlcxAYyFy7lV4AiQr+VZ9VWudQsaHQeaYikyDGw==} + engines: {node: '>=12.22.0'} + dependencies: + '@pnpm/network.config': 1.0.1 + '@pnpm/network.proxy-agent': 1.0.1 + agentkeepalive: 4.2.1 + lru-cache: 7.10.1 + transitivePeerDependencies: + - supports-color + dev: false + /@pnpm/network.ca-file@1.0.2: resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} dependencies: graceful-fs: 4.2.10 + /@pnpm/network.config@1.0.1: + resolution: {integrity: sha512-ZmTsSFxd4QT5+IZvwHtQjzSlkB7OXAty6MfSenRyHOvR1f8j3l1VDWVXJiNaiLrKeidiZH6ADfsMTr2N0CGDeA==} + engines: {node: '>=12.22.0'} + dependencies: + nerf-dart: 1.0.0 + dev: false + + /@pnpm/network.proxy-agent@1.0.1: + resolution: {integrity: sha512-0q9Btpw43aTPzEJJmQY1TNBrwNlPINRae8EpO7VpqbmFflBRO6u6qady6XFfbi+wwPxpcpVOYr6rCDBzALXYHA==} + engines: {node: '>=12.22.0'} + dependencies: + '@pnpm/error': 4.0.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + lru-cache: 7.10.1 + socks-proxy-agent: 6.1.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@pnpm/node-fetch@1.0.0: + resolution: {integrity: sha512-eYwrzhKUBGFdq78rJStGjaHTUHA2VH+Avr//CVx/T+EJkI7hnFmOy6YghvcB2clj8HpO4V8tXRNuFNfRX08ayw==} + engines: {node: ^10.17 || >=12.3} + dependencies: + data-uri-to-buffer: 3.0.1 + fetch-blob: 2.1.2 + transitivePeerDependencies: + - domexception + dev: false + /@pnpm/npm-conf@2.2.0: resolution: {integrity: sha512-roLI1ul/GwzwcfcVpZYPdrgW2W/drLriObl1h+yLF5syc8/5ULWw2ALbCHUWF+4YltIqA3xFSbG4IwyJz37e9g==} engines: {node: '>=12'} @@ -4373,6 +4526,11 @@ packages: semver: 7.6.0 dev: true + /@pnpm/pick-fetcher@3.0.0: + resolution: {integrity: sha512-2eisylRAU/jeuxFEPnS1gjLZKJGbYc4QEtEW6MVUYjO4Xi+2ttkSm7825S0J5IPpUIvln8HYPCUS0eQWSfpOaQ==} + engines: {node: '>=18.12'} + dev: false + /@pnpm/pnpmfile@5.0.7(@pnpm/logger@5.0.0): resolution: {integrity: sha512-A8uwamvs9jhf3DYLuGHCngWW8WXEDgcm3nwOeRTWJOOgButgXueIRHcEZPiKgQwy6t116ntimNeW5H3/hjim6w==} engines: {node: '>=16.14'} @@ -4429,6 +4587,13 @@ packages: '@pnpm/types': 9.1.0 dev: true + /@pnpm/resolver-base@12.0.0: + resolution: {integrity: sha512-R5FmojIoHRIC8hZDyr6a9SM6TkpAQXQXgq5QrycUwknRvGjTnrOFD5JaTzMZohcfFg6TWdA3sp3B0w/mhj98Rg==} + engines: {node: '>=18.12'} + dependencies: + '@pnpm/types': 10.0.0 + dev: false + /@pnpm/store-controller-types@15.0.1: resolution: {integrity: sha512-S88sR6xhQ1ZDhMRIjhaRBA11N2OIDU2W+60szQLU8e2bw+KgGU60LbcXMunTdRnJskuB9UfDyoN6YuRtETBqYA==} engines: {node: '>=16.14'} @@ -4445,6 +4610,11 @@ packages: strip-comments-strings: 1.2.0 dev: true + /@pnpm/types@10.0.0: + resolution: {integrity: sha512-P608MRTOExt5BkIN2hsrb/ycEchwaPW/x80ujJUAqxKZSXNVAOrlEu3KJ+2+jTCunyWmo/EcE01ZdwCw8jgVrQ==} + engines: {node: '>=18.12'} + dev: false + /@pnpm/types@9.1.0: resolution: {integrity: sha512-MMPDMLOY17bfNhLhR9Qmq6/2keoocnR5DWXZfZDC4dKXugrMsE1jB6RnuU8swJIo4zyCsMT/iVSAtl/XK+9Z+A==} engines: {node: '>=16.14'} @@ -4453,10 +4623,17 @@ packages: /@pnpm/types@9.4.2: resolution: {integrity: sha512-g1hcF8Nv4gd76POilz9gD4LITAPXOe5nX4ijgr8ixCbLQZfcpYiMfJ+C1RlMNRUDo8vhlNB4O3bUlxmT6EAQXA==} engines: {node: '>=16.14'} + dev: true /@pnpm/util.lex-comparator@1.0.0: resolution: {integrity: sha512-3aBQPHntVgk5AweBWZn+1I/fqZ9krK/w01197aYVkAJQGftb+BVWgEepxY5GChjSW12j52XX+CmfynYZ/p0DFQ==} engines: {node: '>=12.22.0'} + dev: true + + /@pnpm/util.lex-comparator@3.0.0: + resolution: {integrity: sha512-ead+l3IiuVXwKDf/QJPX6G93cwhXki3yOVEA/VdAO7AhZ5vUuSBxHe6gQKEbB0QacJ4H5VsYxeM1xUgwjjOO/Q==} + engines: {node: '>=18.12'} + dev: false /@pnpm/write-project-manifest@5.0.1: resolution: {integrity: sha512-zU4vDfBUx/jUBPmR4CzCqPDOPObb/7iLT3UZvhXSJ8ZXDo9214V6agnJvxQ6bYBcypdiKva0hnb3tmo1chQBYg==} @@ -5789,13 +5966,18 @@ packages: /@xtuc/long@4.2.2: resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - /@zkochan/js-yaml@0.0.6: - resolution: {integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==} + /@zkochan/js-yaml@0.0.7: + resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} hasBin: true dependencies: argparse: 2.0.1 dev: false + /@zkochan/retry@0.2.0: + resolution: {integrity: sha512-WhB+2B/ZPlW2Xy/kMJBrMbqecWXcbDDgn0K0wKBAgO2OlBTz1iLJrRWduo+DGGn0Akvz1Lu4Xvls7dJojximWw==} + engines: {node: '>=10'} + dev: false + /@zkochan/rimraf@2.1.3: resolution: {integrity: sha512-mCfR3gylCzPC+iqdxEA6z5SxJeOgzgbwmyxanKriIne5qZLswDe/M43aD3p5MNzwzXRhbZg/OX+MpES6Zk1a6A==} engines: {node: '>=12.10'} @@ -5874,6 +6056,17 @@ packages: transitivePeerDependencies: - supports-color + /agentkeepalive@4.2.1: + resolution: {integrity: sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==} + engines: {node: '>= 8.0.0'} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + depd: 1.1.2 + humanize-ms: 1.2.1 + transitivePeerDependencies: + - supports-color + dev: false + /agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} engines: {node: '>= 8.0.0'} @@ -7637,6 +7830,11 @@ packages: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} dev: true + /data-uri-to-buffer@3.0.1: + resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} + engines: {node: '>= 6'} + dev: false + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} @@ -8128,13 +8326,6 @@ packages: /enabled@2.0.0: resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} - /encode-registry@3.0.1: - resolution: {integrity: sha512-6qOwkl1g0fv0DN3Y3ggr2EaZXN71aoAqPp3p/pVaWSBSIo+YjLOWN61Fva43oVyQNPf7kgm8lkudzlzojwE2jw==} - engines: {node: '>=10'} - dependencies: - mem: 8.1.1 - dev: false - /encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -9074,6 +9265,16 @@ packages: xml-js: 1.6.11 dev: false + /fetch-blob@2.1.2: + resolution: {integrity: sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==} + engines: {node: ^10.17.0 || >=12.3.0} + peerDependencies: + domexception: '*' + peerDependenciesMeta: + domexception: + optional: true + dev: false + /figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -9389,6 +9590,11 @@ packages: has-symbols: 1.0.3 hasown: 2.0.2 + /get-npm-tarball-url@2.1.0: + resolution: {integrity: sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==} + engines: {node: '>=12.17'} + dev: false + /get-own-enumerable-property-symbols@3.0.2: resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} dev: false @@ -9572,6 +9778,14 @@ packages: /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + /graceful-git@3.1.2: + resolution: {integrity: sha512-Xyh9Y43yA23/KQ16mpwO4zkzVGUAXyzuSVZQxw9ddQklssIYIY0el24VYfJBFhyCWGriZPRAB2nCgsDizqna9g==} + engines: {node: '>=10'} + dependencies: + retry: 0.12.0 + safe-execa: 0.1.2 + dev: false + /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -11559,6 +11773,11 @@ packages: dependencies: yallist: 4.0.0 + /lru-cache@7.10.1: + resolution: {integrity: sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==} + engines: {node: '>=12'} + dev: false + /lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -11660,6 +11879,7 @@ packages: engines: {node: '>=6'} dependencies: p-defer: 1.0.0 + dev: true /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} @@ -11945,6 +12165,7 @@ packages: dependencies: map-age-cleaner: 0.1.3 mimic-fn: 3.1.0 + dev: true /memfs@3.5.3: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} @@ -12385,6 +12606,7 @@ packages: /mimic-fn@3.1.0: resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} engines: {node: '>=8'} + dev: true /mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} @@ -12694,6 +12916,10 @@ packages: '@msgpack/msgpack': 2.8.0 winston: 3.11.0 + /nerf-dart@1.0.0: + resolution: {integrity: sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==} + dev: false + /next@14.1.4(@babel/core@7.24.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ==} engines: {node: '>=18.17.0'} @@ -13215,6 +13441,7 @@ packages: /p-defer@1.0.0: resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} engines: {node: '>=4'} + dev: true /p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} @@ -15550,6 +15777,17 @@ packages: uuid: 8.3.2 websocket-driver: 0.7.4 + /socks-proxy-agent@6.1.1: + resolution: {integrity: sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4(supports-color@8.1.1) + socks: 2.8.1 + transitivePeerDependencies: + - supports-color + dev: false + /socks-proxy-agent@6.2.1: resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} engines: {node: '>= 10'} diff --git a/pyproject.toml b/pyproject.toml index e537f0d8c8..f31b824fea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,3 +17,5 @@ ignore = ["E501", "SIM105", "UP007", "UP035"] [tool.pyright] reportSelfClsParameterName = false +reportMissingModuleSource = false +exclude = ["**/node_modules", "**/__pycache__", "**/.*", "**/vendor", "data/playground"]