Skip to content

Commit

Permalink
Merge pull request #436 from cunarist/improve-cli-output
Browse files Browse the repository at this point in the history
Improve CLI output
  • Loading branch information
temeddix authored Sep 17, 2024
2 parents 3a24434 + 50cbb5b commit 18c98e6
Show file tree
Hide file tree
Showing 15 changed files with 412 additions and 163 deletions.
2 changes: 1 addition & 1 deletion documentation/docs/detailed-techniques.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ message SomeData { ... }
This applies same to marked Protobuf messages.

```proto title="Protobuf"
// [RINF:DART-SIGNAL]
// [DART-SIGNAL]
// This is an audio data sample of...
// contains...
// responsible for...
Expand Down
4 changes: 2 additions & 2 deletions documentation/docs/frequently-asked-questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,13 @@ However, if you really need to store some state in a Flutter widget, you can ach
syntax = "proto3";
package tutorial_resource;
// [RINF:DART-SIGNAL]
// [DART-SIGNAL]
message MyUniqueInput {
int32 interaction_id = 1;
int32 before_number = 2;
}
// [RINF:RUST-SIGNAL]
// [RUST-SIGNAL]
message MyUniqueOutput {
int32 interaction_id = 1;
int32 after_number = 2;
Expand Down
20 changes: 10 additions & 10 deletions documentation/docs/messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ There are special comments that you can mark messages with.

## 📢 Channels

`[RINF:RUST-SIGNAL]` generates a message channel from Rust to Dart.
`[RUST-SIGNAL]` generates a message channel from Rust to Dart.

```proto title="Protobuf"
// [RINF:RUST-SIGNAL]
// [RUST-SIGNAL]
message MyDataOutput { ... }
```

Expand All @@ -29,10 +29,10 @@ StreamBuilder(
)
```

Use `[RINF:RUST-SIGNAL-BINARY]` to include binary data without the overhead of serialization.
Use `[RUST-SIGNAL-BINARY]` to include binary data without the overhead of serialization.

```proto title="Protobuf"
// [RINF:RUST-SIGNAL-BINARY]
// [RUST-SIGNAL-BINARY]
message MyDataOutput { ... }
```

Expand All @@ -56,10 +56,10 @@ StreamBuilder(
)
```

`[RINF:DART-SIGNAL]` generates a message channel from Dart to Rust.
`[DART-SIGNAL]` generates a message channel from Dart to Rust.

```proto title="Protobuf"
// [RINF:DART-SIGNAL]
// [DART-SIGNAL]
message MyDataInput { ... }
```

Expand All @@ -75,10 +75,10 @@ while let Some(dart_signal) = receiver.recv().await {
}
```

Use `[RINF:DART-SIGNAL-BINARY]` to include binary data without the overhead of serialization.
Use `[DART-SIGNAL-BINARY]` to include binary data without the overhead of serialization.

```proto title="Protobuf"
// [RINF:DART-SIGNAL-BINARY]
// [DART-SIGNAL-BINARY]
message MyDataInput { ... }
```

Expand All @@ -98,9 +98,9 @@ while let Some(dart_signal) = receiver.recv().await {

## 🔖 Attributes

`[RINF:RUST-ATTRIBUTE(...)]` writes an attribute above the generated message struct in Rust. This is useful when you want to automatically implement a trait for the message struct in Rust.
`[RUST-ATTRIBUTE(...)]` writes an attribute above the generated message struct in Rust. This is useful when you want to automatically implement a trait for the message struct in Rust.

```proto title="Protobuf"
// [RINF:RUST-ATTRIBUTE(#[derive(Hash)])]
// [RUST-ATTRIBUTE(#[derive(Hash)])]
message MyDataInput { ... }
```
12 changes: 6 additions & 6 deletions documentation/docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ child: Column(

Let's say that you want to create a new button in Dart that sends an array of numbers and a string to Rust. We need a signal to notify Rust that a user event has occurred.

Write a new `.proto` file in the `./messages` directory with a new message. Note that the message should have the comment `[RINF:DART-SIGNAL]` above it.
Write a new `.proto` file in the `./messages` directory with a new message. Note that the message should have the comment `[DART-SIGNAL]` above it.

```proto title="messages/tutorial_messages.proto"
syntax = "proto3";
package tutorial_messages;
// [RINF:DART-SIGNAL]
// [DART-SIGNAL]
message MyPreciousData {
repeated int32 input_numbers = 1;
string input_string = 2;
Expand Down Expand Up @@ -99,13 +99,13 @@ flutter: ZERO-COST ABSTRACTION

Let's say that you want to send increasing numbers every second from Rust to Dart.

Define the message. Note that the message should have the comment `[RINF:RUST-SIGNAL]` above it.
Define the message. Note that the message should have the comment `[RUST-SIGNAL]` above it.

```proto title="messages/tutorial_messages.proto"
syntax = "proto3";
package tutorial_messages;
// [RINF:RUST-SIGNAL]
// [RUST-SIGNAL]
message MyAmazingNumber { int32 current_number = 1; }
```

Expand Down Expand Up @@ -172,10 +172,10 @@ You can easily show the updated state on the screen by combining those two ways
syntax = "proto3";
package tutorial_messages;
// [RINF:DART-SIGNAL]
// [DART-SIGNAL]
message MyTreasureInput {}
// [RINF:RUST-SIGNAL]
// [RUST-SIGNAL]
message MyTreasureOutput { int32 current_value = 1; }
```

Expand Down
144 changes: 100 additions & 44 deletions flutter_package/bin/rinf.dart
Original file line number Diff line number Diff line change
@@ -1,55 +1,111 @@
import 'package:args/command_runner.dart';
import 'package:chalkdart/chalkstrings.dart';

import 'src/config.dart';
import 'src/helpers.dart';
import 'src/message.dart';
import 'src/internet.dart';
import 'src/common.dart';

Future<void> main(List<String> args) async {
if (args.isEmpty) {
print('No operation is provided.');
print('Use `rinf --help` to see all available operations.');
return;
}
// After running `dart run rinf`,
// Unnecessary two lines of
//`Building package executable...\nBuilt rinf:rinf.` appear.
// Remove those before proceeding.
removeCliLines(2);

final rinfConfig = await loadVerifiedRinfConfig('pubspec.yaml');
// Check the internet connection status and rembember it.
await checkConnectivity();

switch (args[0]) {
case 'config':
print(rinfConfig);
break;
case 'template':
await applyRustTemplate(messageConfig: rinfConfig.message);
break;
case 'message':
if (args.contains('--watch') || args.contains('-w')) {
await watchAndGenerateMessageCode(messageConfig: rinfConfig.message);
} else {
await generateMessageCode(messageConfig: rinfConfig.message);
}
break;
case 'wasm':
if (args.contains('--release') || args.contains('-r')) {
await buildWebassembly(isReleaseMode: true);
} else {
await buildWebassembly();
}
break;
case '--help':
case '-h':
print('Usage: rinf [arguments]');
print('Arguments:');
print(' -h, --help Shows this usage information.');
print(' config Shows current Rinf configuration'
'\n resolved from `pubspec.yaml`'
'\n with defaults applied.');
print(' template Applies Rust template'
'\n to current Flutter project.');
print(' message Generates message code from `.proto` files.');
print(' -w, --watch Continuously watches `.proto` files.');
print(' wasm Builds webassembly module.');
print(' -r, --release Builds in release mode.');
default:
print('No such operation is available.');
print('Use `rinf --help` to see all available operations.');
// Parse CLI arguments and run the corresponding function.
final runner = CommandRunner(
'rinf',
'Helper commands for building apps with Rust in Flutter.',
usageLineLength: 80,
)
..addCommand(ConfigCommand())
..addCommand(TemplateCommand())
..addCommand(MessageCommand())
..addCommand(WasmCommand());

try {
await runner.run(args);
} catch (error) {
// Print the error gracefully without backtrace.
print(error.toString().trim().red);
}
}

class ConfigCommand extends Command {
final name = 'config';
final description = 'Shows current Rinf configuration' +
' resolved from `pubspec.yaml` with defaults applied.';

ConfigCommand() {}

Future<void> run() async {
final rinfConfig = await loadVerifiedRinfConfig('pubspec.yaml');
print(rinfConfig.toString().dim);
}
}

class TemplateCommand extends Command {
final name = 'template';
final description = 'Applies Rust template to the current Flutter project.';

TemplateCommand() {}

Future<void> run() async {
final rinfConfig = await loadVerifiedRinfConfig('pubspec.yaml');
await applyRustTemplate(messageConfig: rinfConfig.message);
}
}

class MessageCommand extends Command {
final name = 'message';
final description = 'Generates message code from `.proto` files.';

MessageCommand() {
argParser.addFlag(
'watch',
abbr: 'w',
help: 'Continuously watches `.proto` files.',
);
}

Future<void> run() async {
final results = argResults;
if (results == null) {
return;
}
final watch = results.flag('watch');
final rinfConfig = await loadVerifiedRinfConfig('pubspec.yaml');
if (watch) {
await watchAndGenerateMessageCode(messageConfig: rinfConfig.message);
} else {
await generateMessageCode(messageConfig: rinfConfig.message);
}
}
}

class WasmCommand extends Command {
final name = 'wasm';
final description = 'Builds the webassembly module for the web.';

WasmCommand() {
argParser.addFlag(
'release',
abbr: 'r',
help: 'Builds in release mode.',
);
}

Future<void> run() async {
final results = argResults;
if (results == null) {
return;
}
final release = results.flag('release');
await buildWebassembly(release);
}
}
11 changes: 11 additions & 0 deletions flutter_package/bin/src/common.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

extension UriJoin on Uri {
Uri join(String path) {
if (path.isEmpty || path == '/') {
Expand All @@ -12,3 +14,12 @@ extension UriJoin on Uri {
}
}
}

/// Removes an existing line from the CLI.
void removeCliLines(int lines) {
for (var i = 0; i < lines; i++) {
stdout.write('\x1B[1A'); // Move the cursor up one line
stdout.write('\x1B[2K'); // Clear the line
stdout.write('\r'); // Return the cursor to the front
}
}
1 change: 1 addition & 0 deletions flutter_package/bin/src/config.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:io';

import 'package:yaml/yaml.dart';

class RinfConfigMessage {
Expand Down
Loading

0 comments on commit 18c98e6

Please sign in to comment.