Skip to content

Conversation

Luckey-Elijah
Copy link

I tried to decrease the imprint of any API changes (specifically, those in utils.dart). But I think it would be ideal if we could also use the other APIs of mason_logger for writing to stdout/stderr (err/info/detail/etc) methods.

should fix #12 and #14

@Luckey-Elijah Luckey-Elijah changed the title draft: feat: Integrate mason_logger for improved logging and user prompts feat: Integrate mason_logger for improved logging and user prompts Apr 19, 2025
@Luckey-Elijah Luckey-Elijah marked this pull request as ready for review April 19, 2025 02:12
@Luckey-Elijah Luckey-Elijah marked this pull request as draft April 19, 2025 02:28

final name = getString(
isInteractive: interactive,
logger: logger,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we standardize the logger to be the first parameter?

import 'package:process_run/process_run.dart';

Future<void> createCommand(ArgResults command) async {
Future<void> createCommand(ArgResults command, Logger logger) async {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for a followup, I would envision we creating some class that wraps the ArgResults and Logger to pass around as a unit, and then the "utils" methods would live on this class as well
something like "CLI context", not sure what is a good name
but as I said - this is def a followup!

@Luckey-Elijah
Copy link
Author

CC: @luanpotter @spydon
What are your thoughts on converting this to a more conventional args Command/CommandRunner application? It would look something like this:

Future<void> mainCommand(List<String> args) async {
  await FlameVersionManager.init();
  final runner = IgniteCommandRunner(
    logger: Logger(),
    flameVersionManager: FlameVersionManager.singleton,
  );

  exit((await runner.run(args)).code);
}
class IgniteCommandRunner extends CommandRunner<ExitCode> {
  IgniteCommandRunner({
    required Logger logger,
    required FlameVersionManager flameVersionManager,
  })  : _logger = logger,
        super(_name, _description) {
    addCommand(
      CreateCommand(
        logger: logger,
        flameVersionManager: flameVersionManager,
      ),
    );
    argParser.addFlag(
      'version',
      abbr: 'v',
      help: 'Print the current version.',
      negatable: false,
    );
  }
}
class CreateCommand extends Command<ExitCode> {
  CreateCommand({
    required Logger logger,
    required FlameVersionManager flameVersionManager,
  })  : _logger = logger,
        _manager = flameVersionManager,
        super() {
    final packages = flameVersionManager.versions;
    final flameVersions = packages[Package.flame]!;

    argParser
      ..addFlag(
        'interactive',
        abbr: 'i',
        help: 'Whether to run in interactive mode or not.',
        defaultsTo: true,
      )
      ..addOption(
        'name',
        help: 'The name of your game (valid dart identifier).',
      )
      ..addOption(
        'org',
        help: 'The org name, in reverse domain notation '
            '(package name/bundle identifier).',
      )
      ..addFlag(
        'create-folder',
        abbr: 'f',
        help: 'If you want to create a new folder on the current location with '
            "the project name or if you are already on the new project's folder.",
      )
      ..addOption(
        'template',
        help: 'What Flame template you would like to use for your new project',
        allowed: ['simple', 'example'],
      )
      ..addOption(
        'flame-version',
        help: 'What Flame version you would like to use.',
        allowed: [
          ...flameVersions.versions.take(5),
          '...',
          flameVersions.versions.last,
        ],
      )
      ..addMultiOption(
        'extra-packages',
        help: 'Which packages to use',
        allowed: packages.keys.map((e) => e.name).toList(),
      );
  }
}

@spydon
Copy link
Member

spydon commented Apr 23, 2025

What are your thoughts on converting this to a more conventional args Command/CommandRunner application?

What would the differences be? The code definitely looks cleaner.

@Luckey-Elijah
Copy link
Author

The Command/CommandRunner setup handles usages like -h/--help for you. And it a bit more clearer to future contributors for add a new flag, option, or behavior to a specific command (or even adding a brand new command). And as you pointed out, it keeps the configuration/ArgParser of a given command more "scoped" to that command

@luanpotter
Copy link
Member

If I'm understanding it correctly, this is quite similar to what we have, just uses the Command class for each command and moves the "setup" logic inside each command, correct? (eg these lines, that already exist, are just move inside the command)

we would still need to keep all the code for the interactive mode, and the functionality would be exactly the same?

if so - definitely, let's do it!

@luanpotter
Copy link
Member

maybe we can also create an IgniteContext class that wraps

    required Logger logger,
    required FlameVersionManager flameVersionManager,

similar to my idea above? then all commands can receive the same parameter and we can easily add more injected helpers later on w/o modifying signatures

@Luckey-Elijah
Copy link
Author

Luckey-Elijah commented Apr 25, 2025

maybe we can also create an IgniteContext class that wraps

Yes! I will add something that can encapsulate those (and future) objects

linter:
rules:
avoid_print: false # since it is a CLI application
avoid_print: true # should always use a Logger
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can just remove the override - it will be true by default :)

}
}

static const _description = 'Ignite your projects with flame; '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static const _description = 'Ignite your projects with flame; '
static const _description = 'Ignite your projects with Flame; '

Copy link
Member

@luanpotter luanpotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@Luckey-Elijah
Copy link
Author

I am wrapping up some tests now that I am at a more comfortable spot for how the APIs are setup. The IgniteContext right now is going to be the object used to get services (manager and version manager) and do some actions (execute Process.run and mason bundler actions). Basically to we can mock it's members.

@Luckey-Elijah
Copy link
Author

I haven't forgot about this 😅. I working on a feature for felangel/mason#1550 first then going to integrate that new feature here to bring it back to parity

@luanpotter
Copy link
Member

@Luckey-Elijah is this something I could help out with? is it blocked on a mason PR that I can help expedite, or require some implementation there that we can figure out, or can we merge an initial version and then followup with @felangel later?

happy to help with whatever is needed to get this through, such a huge improvement!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Stuck in package picker submenu
3 participants