run method

  1. @override
Future<void> run(
  1. Iterable<String> args
)

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();
  }
}