CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-theia--core

Core framework for building cloud and desktop IDE applications using modern web technologies with TypeScript and dependency injection.

Pending
Overview
Eval results
Files

commands.mddocs/

Command System

Theia's command system provides centralized command registry with handler prioritization, context awareness, and event-driven lifecycle management for building extensible applications.

Capabilities

Command Definition

Define commands that can be executed throughout the application.

/**
 * Command definition interface
 */
interface Command {
    /** Unique command identifier */
    id: string;
    /** Human-readable label for UI display */
    label?: string;
    /** CSS class for command icon */
    iconClass?: string;
    /** Short title used for display in menus */
    shortTitle?: string;
    /** Category for grouping commands */
    category?: string;
    /** Original label before localization */
    originalLabel?: string;
    /** Original category before localization */
    originalCategory?: string;
}

/**
 * Command utility functions
 */
namespace Command {
    /**
     * Determine whether object is a Command
     * @param arg - Object to test
     * @returns True if object is a Command
     */
    function is(arg: unknown): arg is Command;
    
    /**
     * Utility function to easily translate commands
     * @param command - Command to localize
     * @param nlsLabelKey - NLS key for label (defaults to command.id)
     * @param nlsCategoryKey - NLS key for category
     * @returns Localized command
     */
    function toLocalizedCommand(command: Command, nlsLabelKey?: string, nlsCategoryKey?: string): Command;
    
    /**
     * Convert command to default localized version
     * @param command - Command to localize
     * @returns Default localized command
     */
    function toDefaultLocalizedCommand(command: Command): Command;
    
    /**
     * Comparator function for sorting commands
     * @param a - First command
     * @param b - Second command
     * @returns Comparison result
     */
    function compareCommands(a: Command, b: Command): number;
    
    /**
     * Determine if two commands are equal
     * @param a - First command for comparison
     * @param b - Second command for comparison
     * @returns True if commands are equal
     */
    function equals(a: Command, b: Command): boolean;
}

Usage Example:

import { Command } from "@theia/core";

export const SAVE_COMMAND: Command = {
    id: 'core.save',
    label: 'Save',
    iconClass: 'fa fa-save',
    category: 'File'
};

export const CUSTOM_COMMAND: Command = {
    id: 'my-extension.custom-action',
    label: 'Custom Action',
    category: 'Custom'
};

Command Handler

Implement command execution logic with optional enablement and visibility conditions.

/**
 * Command handler interface
 */
interface CommandHandler {
    /**
     * Execute the command with optional arguments
     * @param args - Command arguments
     * @returns Command result or promise
     */
    execute(...args: any[]): any;
    
    /**
     * Determine if command is enabled in current context
     * @param args - Command arguments  
     * @returns True if command should be enabled
     */
    isEnabled?(...args: any[]): boolean;
    
    /**
     * Determine if command is visible in current context
     * @param args - Command arguments
     * @returns True if command should be visible
     */
    isVisible?(...args: any[]): boolean;
    
    /**
     * Determine if command should toggle state
     * @param args - Command arguments
     * @returns True if command is in toggled state
     */
    isToggled?(...args: any[]): boolean;
}

Usage Examples:

import { CommandHandler } from "@theia/core";

// Simple command handler
const saveHandler: CommandHandler = {
    execute: () => {
        console.log("Save executed");
        return "saved";
    }
};

// Context-aware command handler  
const conditionalHandler: CommandHandler = {
    execute: (uri: string) => {
        console.log(`Processing: ${uri}`);
    },
    
    isEnabled: (uri: string) => {
        return uri && uri.endsWith('.txt');
    },
    
    isVisible: (uri: string) => {
        return uri !== undefined;
    }
};

Command Registry

Central registry for registering commands and handlers with execution capabilities.

/**
 * Command registry interface
 */
interface CommandRegistry {
    /**
     * Register a command with optional handler
     * @param command - Command definition
     * @param handler - Optional command handler
     * @returns Disposable to unregister the command
     */
    registerCommand(command: Command, handler?: CommandHandler): Disposable;
    
    /**
     * Unregister command from the registry
     * @param command - Command to unregister
     */
    unregisterCommand(command: Command): void;
    
    /**
     * Unregister command from the registry
     * @param id - Command ID to unregister
     */
    unregisterCommand(id: string): void;
    
    /**
     * Register a handler for a command ID
     * @param commandId - Command ID
     * @param handler - Command handler
     * @returns Disposable to unregister the handler
     */
    registerHandler(commandId: string, handler: CommandHandler): Disposable;
    
    /**
     * Execute a command by ID with arguments
     * @param id - Command ID
     * @param args - Command arguments
     * @returns Promise resolving to command result
     */
    executeCommand<T>(id: string, ...args: any[]): Promise<T | undefined>;
    
    /**
     * Get all registered commands with their handlers
     * @returns Iterator of commands with handlers
     */
    getAllCommands(): IterableIterator<Readonly<Command & { handlers: CommandHandler[] }>>;
    
    /**
     * Get all handlers for a command
     * @param commandId - Command ID
     * @returns Array of handlers for the command
     */
    getAllHandlers(commandId: string): CommandHandler[];
    
    /**
     * Get command by ID
     * @param id - Command ID
     * @returns Command definition or undefined
     */
    getCommand(id: string): Command | undefined;
    
    /**
     * Get all registered command objects
     * @returns Array of all registered commands
     */
    readonly commands: Command[];
    
    /**
     * Get all registered command IDs
     * @returns Array of all command IDs
     */
    readonly commandIds: string[];
    
    /**
     * Get visible handler for command
     * @param commandId - Command ID
     * @param args - Command arguments
     * @returns Visible handler or undefined
     */
    getVisibleHandler(commandId: string, ...args: any[]): CommandHandler | undefined;
    
    /**
     * Get active handler for command
     * @param commandId - Command ID
     * @param args - Command arguments
     * @returns Active handler or undefined
     */
    getActiveHandler(commandId: string, ...args: any[]): CommandHandler | undefined;
    
    /**
     * Get toggled handler for command
     * @param commandId - Command ID
     * @param args - Command arguments
     * @returns Toggled handler or undefined
     */
    getToggledHandler(commandId: string, ...args: any[]): CommandHandler | undefined;
    
    /**
     * Check if command is enabled
     * @param id - Command ID
     * @param args - Command arguments
     * @returns True if command is enabled
     */
    isEnabled(id: string, ...args: any[]): boolean;
    
    /**
     * Check if command is visible
     * @param id - Command ID
     * @param args - Command arguments
     * @returns True if command is visible
     */
    isVisible(id: string, ...args: any[]): boolean;
    
    /**
     * Check if command is toggled
     * @param id - Command ID
     * @param args - Command arguments
     * @returns True if command is toggled
     */
    isToggled(id: string, ...args: any[]): boolean;
    
    /**
     * Get the list of recently used commands
     */
    recent: Command[];
    
    /**
     * Add a command to recently used list
     * @param recent - Recent command or array of commands
     */
    addRecentCommand(recent: Command | Command[]): void;
    
    /**
     * Clear the list of recently used commands
     */
    clearCommandHistory(): void;
    
    /**
     * Event fired when commands change
     */
    readonly onCommandsChanged: Event<void>;
    
    /**
     * Event fired before command execution
     */
    readonly onWillExecuteCommand: Event<WillExecuteCommandEvent>;
    
    /**
     * Event fired after command execution
     */
    readonly onDidExecuteCommand: Event<CommandEvent>;
}

/**
 * Command event types
 */
interface CommandEvent {
    commandId: string;
    args: any[];
}

interface WillExecuteCommandEvent {
    commandId: string;
    args: any[];
    waitUntil(thenable: Promise<any>): void;
}

/**
 * Service token for CommandRegistry
 */
const CommandRegistry: symbol;

Usage Example:

import { inject, injectable } from "@theia/core";
import { CommandRegistry, Command, CommandHandler } from "@theia/core";

@injectable()
export class MyCommandManager {
    constructor(
        @inject(CommandRegistry) private readonly commands: CommandRegistry
    ) {}
    
    registerCommands(): void {
        // Register command with handler
        this.commands.registerCommand(SAVE_COMMAND, {
            execute: () => this.save()
        });
        
        // Register command without handler (handler added later)
        this.commands.registerCommand(CUSTOM_COMMAND);
    }
    
    async executeCustomCommand(): Promise<void> {
        const result = await this.commands.executeCommand('my-extension.custom-action');
        console.log('Command result:', result);
    }
    
    private save(): void {
        console.log("Saving...");
    }
}

Command Service

High-level service interface for command execution.

/**
 * Command service interface
 */
interface CommandService {
    /**
     * Execute a command by ID
     * @param id - Command ID
     * @param args - Command arguments
     * @returns Promise resolving to command result
     */
    executeCommand<T>(id: string, ...args: any[]): Promise<T | undefined>;
}

/**
 * Service token for CommandService
 */
const CommandService: symbol;

Command Contribution

Extension point for contributing commands to the application.

/**
 * Command contribution interface for extensions
 */
interface CommandContribution {
    /**
     * Register commands with the command registry
     * @param commands - Command registry instance
     */
    registerCommands(commands: CommandRegistry): void;
}

/**
 * Service token for CommandContribution
 */
const CommandContribution: symbol;

Usage Example:

import { injectable } from "@theia/core";
import { CommandContribution, CommandRegistry } from "@theia/core";

@injectable()
export class MyCommandContribution implements CommandContribution {
    
    registerCommands(registry: CommandRegistry): void {
        registry.registerCommand({
            id: 'my-extension.hello',
            label: 'Say Hello',
            category: 'Demo'
        }, {
            execute: () => {
                console.log('Hello from my extension!');
                return 'Hello executed';
            },
            isEnabled: () => true,
            isVisible: () => true
        });
        
        registry.registerCommand({
            id: 'my-extension.toggle',
            label: 'Toggle Feature',
            category: 'Demo'
        }, {
            execute: () => {
                this.toggleFeature();
            },
            isToggled: () => this.isFeatureEnabled()
        });
    }
    
    private toggleFeature(): void {
        // Toggle implementation
    }
    
    private isFeatureEnabled(): boolean {
        // Return current state
        return false;
    }
}

Command Events

Events related to command execution lifecycle.

/**
 * Command event fired when command is executed
 */
interface CommandEvent {
    /** Command ID that was executed */
    commandId: string;
    /** Arguments passed to command */
    args: any[];
}

/**
 * Event fired before command execution
 */
interface WillExecuteCommandEvent {
    /** Command ID about to be executed */
    commandId: string;
    /** Arguments to be passed to command */
    args: any[];
}

Advanced Usage Patterns

Handler Prioritization

Register multiple handlers for the same command with priority:

// Higher priority handler (registered later wins)
registry.registerCommand(SAVE_COMMAND, primarySaveHandler);
registry.registerCommand(SAVE_COMMAND, fallbackSaveHandler);

Conditional Commands

Create commands that adapt to context:

const CONTEXT_COMMAND: Command = {
    id: 'context.action',
    label: 'Context Action'
};

const contextHandler: CommandHandler = {
    execute: (context: any) => {
        if (context.type === 'file') {
            return this.handleFile(context);
        } else if (context.type === 'folder') {
            return this.handleFolder(context);
        }
    },
    
    isEnabled: (context: any) => {
        return context && (context.type === 'file' || context.type === 'folder');
    },
    
    isVisible: (context: any) => {
        return context !== undefined;
    }
};

Command Chaining

Execute multiple commands in sequence:

async executeCommandChain(): Promise<void> {
    await this.commands.executeCommand('prepare.action');
    const result = await this.commands.executeCommand('main.action', result);
    await this.commands.executeCommand('cleanup.action', result);
}

Types

/**
 * Command utilities namespace
 */
namespace Command {
    /**
     * Type predicate to check if object is a Command
     * @param arg - Object to check
     * @returns True if object is a Command
     */
    function is(arg: any): arg is Command;
    
    /**
     * Compare two commands for equality
     * @param a - First command
     * @param b - Second command
     * @returns True if commands are equal
     */
    function equals(a: Command, b: Command): boolean;
}

/**
 * Disposable interface for cleaning up registrations
 */
interface Disposable {
    dispose(): void;
}

Install with Tessl CLI

npx tessl i tessl/npm-theia--core

docs

application-framework.md

commands.md

dependency-injection.md

events-messaging.md

index.md

keybindings.md

menus.md

preferences-configuration.md

resources-files.md

widgets-ui.md

tile.json