package net.thechunk.playpen.utils.process;

import java.nio.CharBuffer;

public abstract class ProcessBuffer {
    private final StringBuilder buffer = new StringBuilder(1024);
    private static final String LINE_SEPERATOR = System.lineSeparator();

    public void append(CharBuffer buffer) {
        // Okay, I'll admit it: this thing is literally a Rube Goldberg machine. But it works well enough!
        char[] all = new char[buffer.remaining()];
        buffer.get(all);
        this.buffer.append(all);

        int lastNewlineIdx = this.buffer.lastIndexOf(LINE_SEPERATOR);
        if (lastNewlineIdx != -1) {
            int stop = lastNewlineIdx + LINE_SEPERATOR.length();
            String[] fullLines = this.buffer.substring(0, stop).split(LINE_SEPERATOR);
            for (String fullLine : fullLines) {
                if (!fullLine.isEmpty())
                    onOutput(fullLine);
            }
            this.buffer.delete(0, stop);
        }
    }

    protected abstract void onOutput(String output);
}

@@ -66,16 +66,358 @@
 Buffer;%0A
+import java.util.Arrays;%0Aimport java.util.Collections;%0Aimport java.util.List;%0Aimport java.util.concurrent.locks.Lock;%0Aimport java.util.concurrent.locks.ReentrantLock;%0A%0A/**%0A * ProcessBuffer implements a way to turn %7B@code CharBuffers%7D from NuProcess into by-line output.%0A *%0A * This class is thread-safe (the buffer is protected by a lock).%0A */
 %0Apublic 
@@ -585,16 +585,67 @@
 rator();
+%0A    private final Lock lock = new ReentrantLock();
 %0A%0A    pu
@@ -865,16 +865,111 @@
 t(all);%0A
+%0A        List%3CString%3E lines = Collections.emptyList();%0A%0A        lock.lock();%0A        try %7B%0A    
         
@@ -986,32 +986,36 @@
 r.append(all);%0A%0A
+    
         int last
@@ -1072,24 +1072,28 @@
 R);%0A        
+    
 if (lastNewl
@@ -1116,24 +1116,28 @@
             
+  
+  
 int stop = l
@@ -1193,29 +1193,34 @@
     
-String%5B%5D fullLines = 
+    lines = Arrays.asList(
 this
@@ -1259,32 +1259,33 @@
 (LINE_SEPERATOR)
+)
 ;%0A            fo
@@ -1286,43 +1286,40 @@
     
-for (String fullLine : fullLines) %7B
+    this.buffer.delete(0, stop);
 %0A   
@@ -1331,88 +1331,65 @@
     
+%7D%0A
     
-if (!fullLine.isEmpty())%0A                    onOutput(fullLine);%0A   
+    %7D finally %7B%0A            lock.unlock();%0A
         
  %7D%0A 
@@ -1376,34 +1376,34 @@
 lock();%0A        
- 
 %7D
+%0A
 %0A            thi
@@ -1399,50 +1399,79 @@
     
-    this.buffer.delete(0, stop);%0A        %7D
+lines.stream().filter(line -%3E !line.isEmpty()).forEach(this::onOutput);
 %0A   

Make ProcessBuffer thread-safe.