From 0885128ee706f35ccac435170f0705a25b53830d Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Fri, 24 Oct 2025 19:11:07 +0200 Subject: [PATCH 1/2] Support discovering commands with a query --- jupyterlab_commands_toolkit/tools.py | 4 ++-- src/index.ts | 32 ++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/jupyterlab_commands_toolkit/tools.py b/jupyterlab_commands_toolkit/tools.py index e229eb7..980063f 100644 --- a/jupyterlab_commands_toolkit/tools.py +++ b/jupyterlab_commands_toolkit/tools.py @@ -85,7 +85,7 @@ def handle_command_result(event_data): future.set_result(event_data) -async def list_all_commands() -> dict: +async def list_all_commands(query: str) -> dict: """ Retrieve a list of all available JupyterLab commands. @@ -104,7 +104,7 @@ async def list_all_commands() -> dict: asyncio.TimeoutError: If the frontend doesn't respond within the timeout period """ return await emit_and_wait_for_result( - {"name": "jupyterlab-commands-toolkit:list-all-commands", "args": {}} + {"name": "jupyterlab-commands-toolkit:list-all-commands", "args": {"query": query}} ) diff --git a/src/index.ts b/src/index.ts index a7173ee..588d0d8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -103,7 +103,9 @@ const plugin: JupyterFrontEndPlugin = { describedBy: { args: {} }, - execute: async () => { + execute: async (args: any) => { + const query = args['query'] as string | undefined; + const commandList: Array<{ id: string; label?: string; @@ -112,23 +114,45 @@ const plugin: JupyterFrontEndPlugin = { args?: any; }> = []; + // Get all command IDs const commandIds = commands.listCommands(); for (const id of commandIds) { + // Get command metadata using various CommandRegistry methods const description = await commands.describedBy(id); const label = commands.label(id); const caption = commands.caption(id); const usage = commands.usage(id); - commandList.push({ + const command = { id, label: label || undefined, caption: caption || undefined, description: usage || undefined, args: description?.args || undefined - }); + }; + + // Filter by query if provided + if (query) { + const searchTerm = query.toLowerCase(); + const matchesQuery = + id.toLowerCase().includes(searchTerm) || + label?.toLowerCase().includes(searchTerm) || + caption?.toLowerCase().includes(searchTerm) || + usage?.toLowerCase().includes(searchTerm); + + if (matchesQuery) { + commandList.push(command); + } + } else { + commandList.push(command); + } } - return commandList; + return { + success: true, + commandCount: commandList.length, + commands: commandList + }; } }); } From 33d595ee9f8c662b3fd02e5249643de637ee3861 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Fri, 24 Oct 2025 19:14:40 +0200 Subject: [PATCH 2/2] better docstrings --- jupyterlab_commands_toolkit/tools.py | 33 +++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/jupyterlab_commands_toolkit/tools.py b/jupyterlab_commands_toolkit/tools.py index 980063f..cdcfd75 100644 --- a/jupyterlab_commands_toolkit/tools.py +++ b/jupyterlab_commands_toolkit/tools.py @@ -85,7 +85,7 @@ def handle_command_result(event_data): future.set_result(event_data) -async def list_all_commands(query: str) -> dict: +async def list_all_commands(query: Optional[str] = None) -> dict: """ Retrieve a list of all available JupyterLab commands. @@ -93,18 +93,45 @@ async def list_all_commands(query: str) -> dict: registered commands in the application. It waits for the response and returns the complete list of available commands with their metadata. + Args: + query (Optional[str], optional): An optional search query to filter commands. + When provided, only commands whose ID, label, + caption, or description contain the query string + (case-insensitive) will be returned. If None or + omitted, all commands will be returned. + Defaults to None. + Returns: dict: A dictionary containing the command list response from JupyterLab. The structure typically includes: - success (bool): Whether the operation succeeded - - commands (list): List of available command objects, with arguments and types + - commandCount (int): Number of commands returned + - commands (list): List of available command objects, each with: + - id (str): The command identifier + - label (str, optional): Human-readable command label + - caption (str, optional): Short description + - description (str, optional): Detailed usage information + - args (dict, optional): Command argument schema - error (str, optional): Error message if the operation failed Raises: asyncio.TimeoutError: If the frontend doesn't respond within the timeout period + + Examples: + >>> # Get all commands + >>> await list_all_commands() + {'success': True, 'commandCount': 150, 'commands': [...]} + + >>> # Filter commands by query + >>> await list_all_commands(query="notebook") + {'success': True, 'commandCount': 25, 'commands': [...]} """ + args = {} + if query is not None: + args["query"] = query + return await emit_and_wait_for_result( - {"name": "jupyterlab-commands-toolkit:list-all-commands", "args": {"query": query}} + {"name": "jupyterlab-commands-toolkit:list-all-commands", "args": args} )