Drop redundant stream utils (#2369)

- `streamFirst` does not behave differently from `stream.first`. The
  comment about being able to use it with single-subscription streams is
  a lie.
- `streamLines` is redundant against `LineSplitter`.
diff --git a/lib/src/io.dart b/lib/src/io.dart
index fc770d7..e4b4b30 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -569,7 +569,7 @@
 
 /// A line-by-line stream of standard input.
 final Stream<String> _stdinLines =
-    streamToLines(ByteStream(stdin).toStringStream());
+    ByteStream(stdin).toStringStream().transform(const LineSplitter());
 
 /// Displays a message and reads a yes/no confirmation from the user.
 ///
@@ -587,7 +587,7 @@
   } else {
     stdout.write(log.format('$message (y/N)? '));
   }
-  return streamFirst(_stdinLines).then(RegExp(r'^[yY]').hasMatch);
+  return _stdinLines.first.then(RegExp(r'^[yY]').hasMatch);
 }
 
 /// Flushes the stdout and stderr streams, then exits the program with the given
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 15d0fc3..2466dde 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -360,24 +360,6 @@
   future.then(completer.complete, onError: completer.completeError);
 }
 
-// TODO(nweiz): remove this when issue 7964 is fixed.
-/// Returns a [Future] that will complete to the first element of [stream].
-///
-/// Unlike [Stream.first], this is safe to use with single-subscription streams.
-Future<T> streamFirst<T>(Stream<T> stream) {
-  var completer = Completer<T>();
-  StreamSubscription<T> subscription;
-  subscription = stream.listen((value) {
-    subscription.cancel();
-    completer.complete(value);
-  }, onError: (e, [StackTrace stackTrace]) {
-    completer.completeError(e, stackTrace);
-  }, onDone: () {
-    completer.completeError(StateError('No elements'), Chain.current());
-  }, cancelOnError: true);
-  return completer.future;
-}
-
 /// A regular expression matching a trailing CR character.
 final _trailingCR = RegExp(r'\r$');
 
@@ -387,35 +369,6 @@
 List<String> splitLines(String text) =>
     text.split('\n').map((line) => line.replaceFirst(_trailingCR, '')).toList();
 
-/// Converts a stream of arbitrarily chunked strings into a line-by-line stream.
-///
-/// The lines don't include line termination characters. A single trailing
-/// newline is ignored.
-Stream<String> streamToLines(Stream<String> stream) {
-  var buffer = StringBuffer();
-  return stream
-      .transform(StreamTransformer.fromHandlers(handleData: (chunk, sink) {
-    var lines = splitLines(chunk);
-    var leftover = lines.removeLast();
-    for (var line in lines) {
-      if (buffer.isNotEmpty) {
-        buffer.write(line);
-        line = buffer.toString();
-        buffer = StringBuffer();
-      }
-
-      sink.add(line);
-    }
-    buffer.write(leftover);
-  }, handleDone: (sink) {
-    if (buffer.isNotEmpty) sink.add(buffer.toString());
-    sink.close();
-  }));
-}
-
-// TODO(nweiz): unify the following functions with the utility functions in
-// pkg/http.
-
 /// Like [String.split], but only splits on the first occurrence of the pattern.
 ///
 /// This always returns an array of two elements or fewer.