diff --git a/red/src/printer/mod.rs b/red/src/printer/mod.rs
index b10fe5e..2173ffb 100644
--- a/red/src/printer/mod.rs
+++ b/red/src/printer/mod.rs
@@ -1,14 +1,14 @@
 pub mod gcode;
+use futures::AsyncWriteExt;
 use lazy_static::lazy_static;
 
-use bytes::BytesMut;
 use core::panic;
 use regex::Regex;
 use serialport::SerialPort;
 use serialport::TTYPort;
 use std::io::Read;
 use std::io::Write;
-use std::ops::{Deref, DerefMut, Index};
+use std::ops::{Deref, DerefMut};
 use std::os::fd::{FromRawFd, RawFd};
 use std::sync::mpsc;
 use std::sync::mpsc::Receiver;
@@ -18,7 +18,6 @@ use std::sync::Arc;
 use std::sync::Mutex;
 use std::time::{Duration, Instant};
 use std::{io, str};
-use tokio;
 
 pub use gcode::{GcodeCommand, GcodeReply};
 
@@ -65,6 +64,7 @@ pub struct PrinterPosition {
     pub z: f64,
 }
 
+#[derive(Debug, Clone, Copy)]
 pub enum MovementMode {
     AbsoluteMovements,
     RelativeMovements,
@@ -87,12 +87,7 @@ pub struct Printer {
 
 impl Printer {
     /// Send gcode to the printer and parse its reply
-    fn send_gcode<T: GcodeCommand>(
-        &mut self,
-        command: T,
-        ignore_pos: bool,
-        timeout: Duration,
-    ) -> Result<T::Reply, PrinterError> {
+    fn send_gcode<T: GcodeCommand>(&mut self, command: T) -> Result<T::Reply, PrinterError> {
         let command_text = command.command() + "\n";
         self.to_io_thread
             .send(command_text.clone())
@@ -146,7 +141,6 @@ impl Printer {
             last_buffer_capacity: 0, // this is updated on the next call to `send_gcode()`
         }));
 
-        //TODO: Spawn IO-Thread
         let state_for_io = state.clone();
         std::thread::spawn(move || {
             Self::io_thread_work(to_user_thread, from_user_thread, port, state_for_io)
@@ -281,15 +275,14 @@ impl Printer {
             e: None, // Machine has no e
             velocity,
         };
-        if let MovementMode::AbsoluteMovements =
-            self.state.lock().unwrap().deref_mut().movement_mode
-        {
+        let movement_mode = self.state.lock().unwrap().deref_mut().movement_mode;
+        if let MovementMode::AbsoluteMovements = movement_mode {
             self.use_relative_movements()?;
-            let res = self.send_gcode(command, true, DEFAULT_COMMAND_TIMEOUT);
+            let res = self.send_gcode(command);
             self.use_absolute_movements()?;
             res
         } else {
-            self.send_gcode(command, true, DEFAULT_COMMAND_TIMEOUT)
+            self.send_gcode(command)
         }?;
 
         self.state.lock().unwrap().deref_mut().position.x += x;
@@ -321,13 +314,14 @@ impl Printer {
             e: None, // Machine has no e
             velocity,
         };
-        if let MovementMode::RelativeMovements = self.state.lock().unwrap().deref().movement_mode {
+        let movement_mode = self.state.lock().unwrap().deref().movement_mode;
+        if let MovementMode::RelativeMovements = movement_mode {
             self.use_absolute_movements()?;
-            let res = self.send_gcode(command, true, DEFAULT_COMMAND_TIMEOUT);
+            let res = self.send_gcode(command);
             self.use_relative_movements()?;
             res
         } else {
-            self.send_gcode(command, true, DEFAULT_COMMAND_TIMEOUT)
+            self.send_gcode(command)
         }?;
 
         self.state.lock().unwrap().deref_mut().position.x = x;
@@ -350,7 +344,12 @@ impl Printer {
     ) {
         loop {
             match from_user_thread.try_recv() {
-                Ok(user_command) => handle_user_command(&mut port, user_command, state.clone()),
+                Ok(user_command) => handle_user_command(
+                    &mut port,
+                    user_command,
+                    state.clone(),
+                    to_user_thread.clone(),
+                ),
                 Err(TryRecvError::Disconnected) => break,
                 Err(TryRecvError::Empty) => handle_printer_autoreport(&mut port, state.clone()),
             }
@@ -368,21 +367,21 @@ fn handle_printer_autoreport(port: &mut TTYPort, state: Arc<Mutex<State>>) {
 /// Parameters
 /// * `port` - The port to read from
 /// * `already_read` - Read bytes from a previous call. May not contain `\n`
-/// * `timeout` - Time to wait before raising a timeout error
+/// * `timeout` - Time to wait for new bytes from the `port` before raising a timeout error
 ///
 /// Returns
-/// `(potential_line, rest)`, where
-/// - `potential_line` is `None` if no complete line was read or `Some(line)` if a whole
-///    line was received from the port
-/// - `rest` contains the bytes that were read since the last occurence of `\n`
+///
+/// * `Ok(Some(line))` if a complete line was read from the port
+/// * `Ok(None)` if there was no `\n` received
+/// * `Err(e)` in case reading failed
 fn read_line(
     port: &mut TTYPort,
-    mut already_read: Vec<u8>,
+    already_read: &mut Vec<u8>,
     timeout: Duration,
-) -> io::Result<(Option<Vec<u8>>, Vec<u8>)> {
+) -> io::Result<Option<Vec<u8>>> {
     let deadline = Instant::now() + timeout;
     while Instant::now() < deadline {
-        match port.read(&mut already_read) {
+        match port.read(already_read) {
             Err(e) => {
                 if let io::ErrorKind::TimedOut = e.kind() {
                     continue;
@@ -393,10 +392,7 @@ fn read_line(
             Ok(0) => panic!("TTYPort returned 0 bytes!"),
             Ok(n) => {
                 if let Some(line_break_idx) = already_read[..n].iter().position(|x| *x == b'\n') {
-                    return Ok((
-                        Some(already_read[..line_break_idx].into()),
-                        already_read[line_break_idx..].into(),
-                    ));
+                    return Ok(Some(already_read[..line_break_idx].into()));
                 }
             }
         }
@@ -407,32 +403,41 @@ fn read_line(
     ))
 }
 
-fn handle_user_command(port: &mut TTYPort, user_command: String, state: Arc<Mutex<State>>) {
+fn handle_user_command(
+    port: &mut TTYPort,
+    user_command: String,
+    state: Arc<Mutex<State>>,
+    to_user_thread: Sender<Vec<u8>>,
+) {
     port.write(user_command.as_bytes())
-        .expect("Printer IO-Thread hung up its incoming mpsc");
+        .expect("Failed to write to printer serial port");
     port.flush().unwrap();
-    let ignore_pos = false;
-    let mut reply = String::with_capacity(RECV_BUFFER_CAPACITY);
-    let mut already_read = Vec::new();
+
+    let mut already_read_lines = Vec::new();
+    let mut rest = Vec::new();
     loop {
-        let (mut line, mut rest) = read_line(port, Vec::new(), DEFAULT_COMMAND_TIMEOUT).unwrap();
-        let timeout = Instant::now() + DEFAULT_COMMAND_TIMEOUT;
-        while line.is_none() && Instant::now() < timeout {
-            let buf = Vec::new();
-            _ = port.read(&mut buf);
-            if line.is_none() {
+        let mut line;
+        loop {
+            line = read_line(port, &mut rest, DEFAULT_COMMAND_TIMEOUT)
+                .expect("Failed to read from printer");
+            if line.is_some() {
+                break;
+            } else {
                 std::thread::sleep(Duration::from_millis(5));
             }
         }
-        if let Some(line) = line {
-            let line = String::from_utf8(line).unwrap();
-            if line.starts_with("ok") {
-                (*state.lock().unwrap()).last_buffer_capacity = Printer::parse_ok(&line)?;
-                let reply = command_parser(&reply);
-                return reply.map_err(PrinterError::GcodeReply);
-            } else {
-                reply.push_str(&line);
-            }
+        let line = line.expect("Line must be set as otherwise we don't leave the loop");
+
+        let str_line = String::from_utf8(line.clone()).expect("Read line was no valid utf8");
+
+        if str_line.starts_with("ok") {
+            (*state.lock().unwrap()).last_buffer_capacity =
+                Printer::parse_ok(&str_line).expect("Couldn't parse line as 'ok'-message");
+            to_user_thread
+                .send(already_read_lines.join(&b'\n'))
+                .expect("Failed to send read bytes to user thread");
+        } else {
+            already_read_lines.push(line);
         }
     }
 }