Skip to content

Stdout not printing until after reading stdin when using terminal #2164

Closed

Description

@mpfaff

I've noticed that stdout output and stdin input don't seem to be happening in the correct order if I set "console": "terminal" in my launch config. I'm guessing that maybe Dart-Code is caching the stdout output for some reason.

import 'dart:convert';
import 'dart:io';

import 'package:io/io.dart';

final Stream<String> stdinUtf8 = sharedStdIn.transform(utf8.decoder).asBroadcastStream();
final Stream<String> stdinLined = stdinUtf8.transform(LineSplitter());

Future<T> prompt<T>(String question, {T fallback, T def, String hint, T Function(String) parse}) async {
  assert(T is String || parse != null, '`parse` can only be null if T is String. T is $T');
  stdout.write('$question${hint != null || def != null ? ' (${hint ?? def})' : ''} >>> ');
  final ret = await stdinLined.first;
  print('[OUTPUT = $ret]'); // for debugging
  if (ret.isEmpty && fallback != null) return def;
  else if (parse != null) {
    try {
      return parse(ret);
    } on FormatException {
      return fallback;
    }
  }

  return ret as T;
}

Example:

Future<void> main() async {
  final name = await prompt<String>('What is your name?');
}

Expected Output (works in non-debug terminal):

$ dart bin/main.dart
What is your name? >>> <some user input>
[OUTPUT = <some user input>]

Actual Output:

$ dart bin/main.dart
<some user input>
What is your name? >>> [OUTPUT = <some user input>]

Activity

  1. DanTup commented on Dec 10, 2019

    @DanTup
    Member

    You're right - we do buffer the output until we get a newline. This was done because sometimes messages from Dart were coming through in pieces, and we sometimes missed paths in the stack traces, and failed to link them up (see 70a2a8a).

    This does seem like a problem though. We could potentially flush the buffer periodically (eg. make it time-based rather than line-based), though I'm not sure if that might just introduce other issues.

    I'll have a think!

  2. added
    in dartRelates to running Dart programs
    in debuggingRelates to the debug adapter or process of running debug sessions
    on Dec 10, 2019
  3. added this to the v3.8.0 milestone on Dec 10, 2019
  4. mpfaff commented on Dec 10, 2019

    @mpfaff
    Author

    @DanTup, thanks for the quick update! Could it be configured to print to the same line until a newline character is received, or does it only support full lines?

  5. DanTup commented on Dec 11, 2019

    @DanTup
    Member

    @mpfaff we can send characters at any time, the issue is just that we need to scan a whole line in order to detect stack frame paths. For example we might get:

    [5:01:50] tion: Oop
    [5:01:50] s
    [5:01:50]
    [5:01:50] #
    [5:01:50] 0
    [5:01:50]
    [5:01:50]
    [5:01:50]     main (file:///D:/a/
    [5:01:50] Dart-Code/Dart-Code/src/test/test_projects/hello_world/bin/broken.dart:2:3)
    

    Each line is a chunk of data we received. If we sent each chunk as we got it, then we wouldn't be able to send a single line with the additional metadata required to make links. The links won't actually work in the terminal though, so it's a bit weird to have this limitation (it's because the terminal and the debug console share the same debug adapter code).

    Some possible thoughts:

    • Just skip the buffering (or immediately flush the buffer) when in terminal mode
    • Test what happens if we send a line in multiple chunks and attach the location metadata only to the last chunk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    in dartRelates to running Dart programsin debuggingRelates to the debug adapter or process of running debug sessionsis bug

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions