You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
runAsync for-loop does not wait until loop body ends to print prompt #3
import'package:cli_repl/cli_repl.dart';
voidmain() async {
final repl =Repl(prompt:'> ');
awaitfor (final answer in repl.runAsync()) {
if (answer =='exit') break;
awaitFuture(() =>print("You said '$answer'"));
}
print("done");
await repl.exit();
}
When running this program, the You said x message is always printed after the prompt. This makes writing REPLs that evaluate commands async impossible even when the for-loop body awaits, as in this example.
The expected behaviour is to wait for the body to complete before printing the prompt.
From what I can see, the current design makes it impossible for the desired behaviour to be used. That's a shame because the sync method blocks the event loop and causes tools like the observatory to become unusable, not to mention that scheduled async processes will also be inactive while the user does not interact with the shell.
I would propose a design change (unless a solution can be found with the current design - which I could not do) to make this library usable in "async mode"...
Instead of returning a Stream from runAsync, it should take a function, akin to forEach(), and the function should return whether the loop should continue or not, as in this simplified implementation:
import'dart:async';
import'dart:io';
const prompt ='> ';
enumNextAction { go_on, stop }
Future<void> runAsync(FutureOr<NextAction> Function(String) onLine) async {
var stream = stdin.expand((b) => b);
stdout.write(prompt);
final buf =StringBuffer();
awaitfor (int i in stream) {
final c =String.fromCharCode(i);
stdout.write(c);
if (c =='\n') {
final action =awaitonLine(buf.toString());
buf.clear();
if (action ==NextAction.stop) break;
stdout.write(prompt);
} else {
buf.write(c);
}
}
}
Now, this program will work as expected:
voidmain() async {
stdin.echoMode =false;
stdin.lineMode =false;
// user loopawaitrunAsync((line) async {
if (line =='exit') returnNextAction.stop;
awaitFuture.delayed(Duration(seconds:1));
print("You said $line");
returnNextAction.go_on;
});
print("done");
}
From what I've seen, the few libraries depending on this package don't use runAsync, so I think a design change is acceptable given it's still in version 0.x. What do you think @jathak ?
Hi, sorry for the delay responding. I must have missed the notification email.
I'm open to a potential design change for this function, though it would need to be something that works on both the Dart VM (where it uses a pure-Dart reimplementation of readline) and Node (where it just uses the Node readline module).
I'll also note that Dart Sass uses runAsync, and it's by far the most widely used dependent of this package, so any changes made would need to make sure not to break it (on the Dart VM or on Node, since it uses both).
I don't really have any bandwidth to work on this right now, but if you'd like to work on a PR yourself, I'd be happy to review it.
Activity
renatoathaydes commentedon Aug 31, 2019
From what I can see, the current design makes it impossible for the desired behaviour to be used. That's a shame because the sync method blocks the event loop and causes tools like the observatory to become unusable, not to mention that scheduled async processes will also be inactive while the user does not interact with the shell.
I would propose a design change (unless a solution can be found with the current design - which I could not do) to make this library usable in "async mode"...
Instead of returning a
StreamfromrunAsync, it should take a function, akin toforEach(), and the function should return whether the loop should continue or not, as in this simplified implementation:Now, this program will work as expected:
This also fixes issue #2 .
From what I've seen, the few libraries depending on this package don't use
runAsync, so I think a design change is acceptable given it's still in version0.x. What do you think @jathak ?jathak commentedon Sep 19, 2019
Hi, sorry for the delay responding. I must have missed the notification email.
I'm open to a potential design change for this function, though it would need to be something that works on both the Dart VM (where it uses a pure-Dart reimplementation of readline) and Node (where it just uses the Node readline module).
I'll also note that Dart Sass uses
runAsync, and it's by far the most widely used dependent of this package, so any changes made would need to make sure not to break it (on the Dart VM or on Node, since it uses both).I don't really have any bandwidth to work on this right now, but if you'd like to work on a PR yourself, I'd be happy to review it.