@@ -9,6 +9,13 @@ public protocol TerminalType {
99 environment: [ String : String ]
1010 ) -> AsyncThrowingStream < String , Error >
1111
12+ func streamLineForCommand(
13+ _ command: String ,
14+ arguments: [ String ] ,
15+ currentDirectoryURL: URL ? ,
16+ environment: [ String : String ]
17+ ) -> AsyncThrowingStream < String , Error >
18+
1219 func runCommand(
1320 _ command: String ,
1421 arguments: [ String ] ,
@@ -133,6 +140,46 @@ public final class Terminal: TerminalType, @unchecked Sendable {
133140 return contentStream
134141 }
135142
143+ public func streamLineForCommand(
144+ _ command: String = " /bin/bash " ,
145+ arguments: [ String ] ,
146+ currentDirectoryURL: URL ? = nil ,
147+ environment: [ String : String ]
148+ ) -> AsyncThrowingStream < String , Error > {
149+ let chunkStream = streamCommand (
150+ command,
151+ arguments: arguments,
152+ currentDirectoryURL: currentDirectoryURL,
153+ environment: environment
154+ )
155+
156+ return AsyncThrowingStream < String , Error > { continuation in
157+ Task {
158+ var buffer = " "
159+ do {
160+ for try await chunk in chunkStream {
161+ buffer. append ( chunk)
162+
163+ while let range = buffer. range ( of: " \n " ) {
164+ let line = String ( buffer [ ..< range. lowerBound] )
165+ buffer. removeSubrange ( buffer. startIndex... range. upperBound)
166+ continuation. yield ( line)
167+ }
168+ }
169+
170+ let trailing = buffer. trimmingCharacters ( in: . whitespacesAndNewlines)
171+ if !trailing. isEmpty {
172+ continuation. yield ( trailing)
173+ }
174+
175+ continuation. finish ( )
176+ } catch {
177+ continuation. finish ( throwing: error)
178+ }
179+ }
180+ }
181+ }
182+
136183 public func runCommand(
137184 _ command: String = " /bin/bash " ,
138185 arguments: [ String ] ,
0 commit comments