基于Vorpal(Node.js)的命令行应用:如何按上下文启用并展示命令?
Absolutely! Vorpal is built to handle exactly this kind of context-based command workflow. You can dynamically show/hide commands based on your app's current context, while keeping a global switch command available at all times. Here's a practical implementation:
1. Set Up Your Base Structure & Context Tracking
First, initialize Vorpal and create a variable to track your current context—this will be the "source of truth" for which commands are visible.
const Vorpal = require('vorpal'); const vorpal = new Vorpal(); // Track your current context (start with context1 by default) let currentContext = 'context1';
2. Create a Global Context Switch Command
This command will always be available, no matter the current context. It lets users switch between contexts and updates the context tracker.
vorpal .command('switch-context <context>', 'Switch to context1 or context2') .autocomplete(['context1', 'context2']) .action(function(args, callback) { const validContexts = ['context1', 'context2']; if (!validContexts.includes(args.context)) { this.log(`Invalid context! Choose from: ${validContexts.join(', ')}`); return callback(); } currentContext = args.context; this.log(`Switched to ${args.context} successfully!`); callback(); });
3. Define Context-Specific Commands
Use Vorpal's when() method to conditionally show commands only when the correct context is active. This method dynamically evaluates whether the command should appear in the help menu and be executable.
Context1-Only Commands (A & B)
vorpal .command('command-a', 'Executes command A (only in context1)') .when(() => currentContext === 'context1') .action(function(args, callback) { this.log('Running Command A in context1!'); callback(); }); vorpal .command('command-b', 'Executes command B (only in context1)') .when(() => currentContext === 'context1') .action(function(args, callback) { this.log('Running Command B in context1!'); callback(); });
Context2-Only Commands (C & D)
vorpal .command('command-c', 'Executes command C (only in context2)') .when(() => currentContext === 'context2') .action(function(args, callback) { this.log('Running Command C in context2!'); callback(); }); vorpal .command('command-d', 'Executes command D (only in context2)') .when(() => currentContext === 'context2') .action(function(args, callback) { this.log('Running Command D in context2!'); callback(); });
4. Test the Workflow
When you run your app:
- Start in
context1→ runhelpto seeswitch-context,command-a, andcommand-b - Run
switch-context context2→ runhelpagain, and you'll seeswitch-context,command-c, andcommand-d - Try running
command-aincontext2→ Vorpal will throw an error saying the command doesn't exist (exactly the behavior we want!)
Bonus: Advanced Context Filtering
If you have a lot of commands, you can use Vorpal's global filter to bulk-manage visibility instead of adding when() to every command:
vorpal.filter((command) => { // Always keep the switch-context command visible if (command.name() === 'switch-context') return true; // Show context1 commands only in context1 if (['command-a', 'command-b'].includes(command.name())) { return currentContext === 'context1'; } // Show context2 commands only in context2 if (['command-c', 'command-d'].includes(command.name())) { return currentContext === 'context2'; } // Default to hiding any other commands return false; });
This approach keeps your code clean as your app scales.
内容的提问来源于stack exchange,提问作者Andrea

