run method
Parses args and invokes Command.run on the chosen command.
This always returns a Future in case the command is asynchronous. The
Future will throw a UsageException if args was invalid.
Implementation
@override
Future<void> run(Iterable<String> args) async {
// artisanal.run(args) handles global setup and catches UsageException.
// However, it expects subcommands. Since Lua uses flags for logic,
// we need to handle the parsed results if no command matches.
// Setup renderer etc by calling artisanal's run logic via super.run
// But super.run will likely throw if we have no commands.
// Let's use artisanal's public properties to mimic its behavior.
final argResults = argParser.parse(args);
if (argResults['help'] as bool) {
printUsage();
return;
}
if (argResults['version'] as bool) {
final versionCmd = VersionCommand();
await versionCmd.run();
if (args.length == 1) return;
}
final restArgs = argResults.rest;
final config = LuaLikeConfig();
final useIr = argResults['ir'] as bool;
final useLuaBytecode = argResults['lua-bytecode'] as bool;
final useAst = argResults['ast'] as bool;
final autoUseLuaBytecode =
restArgs.isNotEmpty &&
_looksLikeTrackedLuaBytecodeScript(restArgs.first);
if (useLuaBytecode || autoUseLuaBytecode) {
config.defaultEngineMode = EngineMode.luaBytecode;
} else if (useIr || !useAst) {
config.defaultEngineMode = EngineMode.ir;
} else {
config.defaultEngineMode = EngineMode.ast;
}
config.dumpIr = argResults['dump-ir'] as bool;
BaseCommand.resetBridge();
final emitDocsFormat = argResults['emit-docs'] as String?;
if (emitDocsFormat != null) {
await _emitDocs(
format: emitDocsFormat,
output: argResults['emit-docs-output'] as String?,
);
return;
}
// Handle debug mode
if (argResults['debug'] as bool) {
debugMode = true;
io.writeln('Debug mode enabled');
}
// Set up logging
final logLevel = argResults['level'] as String?;
final logCategories =
(argResults['category'] as List<String>?) ?? const <String>[];
ctx.Level? cliLevel;
if (logLevel != null && logLevel.isNotEmpty) {
cliLevel = parseLogLevel(logLevel) ?? ctx.Level.warning;
}
setLualikeLogging(
enabled: debugMode,
level: cliLevel,
categories: logCategories.isEmpty ? null : logCategories,
);
// Handle special case where no arguments provided
if (args.isEmpty) {
if (stdin.hasTerminal) {
// Terminal mode: show version and enter interactive mode
final versionCmd = VersionCommand();
await versionCmd.run();
final interactiveCmd = InteractiveCommandWrapper(debugMode: debugMode);
await interactiveCmd.run();
} else {
// Non-terminal mode: read from stdin
final stdinCmd = StdinCommand([], args.toList());
await stdinCmd.run();
}
return;
}
// Handle special case for single '-' argument (stdin)
if (args.length == 1 && args.first == '-') {
final stdinCmd = StdinCommand([], args.toList());
await stdinCmd.run();
return;
}
// Handle LUA_INIT using BaseCommand functionality
final baseCmd = _LuaInitCommand();
await baseCmd.handleLuaInit();
// Handle require files (-l)
final requireFiles = argResults['require'] as List<String>;
for (final file in requireFiles) {
final requireCmd = RequireCommand(file, args.toList());
await requireCmd.run();
}
// Handle execute strings (-e)
final executeStrings = argResults['execute'] as List<String>;
for (final code in executeStrings) {
final executeCmd = ExecuteCommand(code, args.toList());
await executeCmd.run();
}
// Handle script file and arguments
if (restArgs.isNotEmpty) {
final scriptPath = restArgs.first;
final scriptArgs = restArgs.skip(1).toList();
final scriptCmd = ScriptCommand(scriptPath, scriptArgs, args.toList());
await scriptCmd.run();
}
// Handle interactive mode (-i)
if (argResults['interactive'] as bool) {
final interactiveCmd = InteractiveCommandWrapper(debugMode: debugMode);
await interactiveCmd.run();
}
}