anchor.diff:          new fl.Widget(0, 0, toolbar.w - pad - runButton.w, toolbar.h);
       toolbar.end();
   
  -    // Fancy text display setup
  -    final textDisplaySetup = (fl.TextDisplay editor) {
  -      editor.box = fl.FLAT_BOX;
  -      editor.cursorStyle = fl.TextDisplay.SIMPLE_CURSOR;
  -      editor.textFont = fl.COURIER;
  -      editor.textSize = 18;
  -      editor.linenumberFont = fl.COURIER_BOLD;
  -      editor.scrollbarBox = fl.FLAT_BOX;
  -      editor.scrollbarTrackColor = bg1;
  -    };
  -
       // Create code editor.
  -    codeEditor = new fl.TextEditor(0, toolbar.h, half1, height - toolbar.h);
  -    textDisplaySetup(codeEditor);
  -    codeEditor.color = bg1;
  -    codeEditor.linenumberWidth = 60;
  -    codeEditor.linenumberBgColor = bg1;
  -    codeEditor.linenumberFgColor = fl.grayscale(128);
  -    codeEditor.linenumberFormat = '%d ';
  -    codeEditor.linenumberSize = 18;
  -    codeEditor.cursorColor = fl.grayscale(223);
  -    codeEditor.textColor = fl.grayscale(223);
  -
  -    // Setup code buffer.
  -    codeBuffer = new fl.TextBuffer();
  -    codeEditor.buffer = codeBuffer;
  -    codeBuffer.text = "print('Hello World!');\n";
  +    editor.d = new fl.TextEditor(0, toolbar.h, half1, height - toolbar.h);
  +    editor.init(editorStyleTable);
  +    editor.d.color = bg1;
  +    editor.d.linenumberWidth = 60;
  +    editor.d.linenumberBgColor = bg1;
  +    editor.d.linenumberFgColor = fl.grayscale(128);
  +    editor.d.linenumberFormat = '%d ';
  +    editor.d.linenumberSize = 18;
  +    editor.d.cursorColor = fl.grayscale(223);
  +    editor.d.textColor = fl.grayscale(223);
  +
  +    // Setup editor syntax highlighting.
  +    editor.textBuffer.onModify.listen((data) {
  +      if (data.nInserted != 0 || data.nDeleted != 0) {
  +        updateEditorSyntax();
  +      }
  +    });
  +    editor.textBuffer.text = defaultDartCode;
   
       // Create console.
       final cpad = 20; // Console padding
  -    console = new fl.TextDisplay(half1, 0, half2, height);
  -    textDisplaySetup(console);
  -    console.color = bg2;
  -    console.linenumberWidth = cpad;
  -    console.linenumberBgColor = bg2;
  -    console.linenumberFormat = '';
  -    console.linenumberSize = 10;
  -
  -    // Setup console buffer.
  -    consoleBuffer = new fl.TextBuffer();
  -    console.buffer = consoleBuffer;
  -    consoleBuffer.text = '\nWelcome to DartPad!\n';
  -
  -    // Setup console highlighting.
  -    consoleStyleBuffer = new fl.TextBuffer();
  -    consoleStyleBuffer.text = strSeq('A', consoleBuffer.text.length);
  -    console.highlightData(consoleStyleBuffer, consoleStyleTable);
  +    console.d = new fl.TextDisplay(half1, 0, half2, height);
  +    console.init(consoleStyleTable);
  +    console.d.color = bg2;
  +    console.d.linenumberWidth = cpad;
  +    console.d.linenumberBgColor = bg2;
  +    console.d.linenumberFormat = '';
  +    console.d.linenumberSize = 10;
  +    console.textBuffer.text = '\nWelcome to DartPad!\n';
  +    console.styleBuffer.text = strSeq('A', console.textBuffer.text.length);
   
       // Make window resizable.
       resizable = new fl.Widget(0, toolbar.h, width, height - toolbar.h);
   
       // Setup run code event.
       runButton.onCallback.listen((_) {
  -      var code = codeBuffer.text;
  -
  -      // Prepend line ending for search porposes.
  -      code = '\n$code';
  -
  -      // Split code into imports and code.
  -      final regex = new RegExp(r'''\n\s*import ["'].*["'];''');
  -      final matches = regex.allMatches(code);
  -      final splixIndex = matches.isNotEmpty ? matches.last.end : 0;
  -      final imports = code.substring(0, splixIndex);
  -      code = code.substring(splixIndex);
  -
  -      // Wrap code in a special wrapper that proves a special print function.
  -      final wrappedCode = '''
  -/// All imports
  -$imports
  -
  -/// Main
  -main(List<String> args, SendPort __printSendPort) {
  -  // Define new print function.
  -  final print = (String line) {
  -    __printSendPort.send(line);
  -  };
  -
  -  // Run actual code.
  -  $code
  -}
  -''';
  -
  -      // Code data URI.
  -      final uri = new Uri.dataFromString(wrappedCode);
  -
  -      // Receive port for isolate errors
  -      final onError = new ReceivePort();
  -      onError.listen((e) {
  -        // Replace URI references in stack trace.
  -        var msg = e.toString();
  -        final regex = r'\(' + escapeAll(uri.toString()) + r':[0-9]*:[0-9]*\)';
  -        msg = msg.replaceAll(new RegExp(regex), '(DartPad)');
  -
  -        // Prettify a little more.
  -        msg = msg.replaceFirst("'$uri': ", '');
  -        msg = msg.replaceFirst(', #0', ',\n#0');
  -        msg = msg.substring(1, msg.length - 2);
  -
  -        println('An error has occured:\n$msg', error: true);
  -      });
  -
  -      // Receive port for isolate print messages
  -      final onPrint = new ReceivePort();
  -      onPrint.listen((msg) {
  -        println(msg);
  -      });
  -
  -      // Receive port for isolate exit event
  -      final onExit = new ReceivePort();
  -      onExit.listen((msg) {
  -        println('Isolate exited.');
  -        onError.close();
  -        onPrint.close();
  -        onExit.close();
  -      });
  -
  -      // Start isolate.
  -      println('\nSpawning isolate...');
  -      runZoned(() {
  -        Isolate.spawnUri(uri, [], onPrint.sendPort,
  -            onError: onError.sendPort,
  -            onExit: onExit.sendPort,
  -            errorsAreFatal: true);
  -      }, onError: (e) {
  -        // Remove URI reference from error message.
  -        var msg = e.toString();
  -        msg = msg.replaceFirst(" '$uri': ", '\n');
  -
  -        println(msg, error: true);
  -
  -        // Close send ports.
  -        onError.close();
  -        onPrint.close();
  -        onExit.close();
  -      });
  +      runCode();
  +    });
  +  }
  +
  +  /// Update editor syntax highlighting.
  +  void updateEditorSyntax() {
  +    final text = editor.textBuffer.text;
  +    var style = '';
  +    var current = 'A';
  +    var next = 'A';
  +
  +    // String parsing
  +    var strOpen = [0];
  +    final handleStringDelimiter = (int n) {
  +      if (strOpen[0] == 0) {
  +        strOpen[0] = n;
  +        current = 'D';
  +        next = 'D';
  +      } else if (strOpen[0] == n) {
  +        strOpen[0] = 0;
  +
  +        if (strOpen.length == 1) {
  +          next = 'A';
  +        }
  +      }
  +    };
  +
  +    // Go through each character.
  +    for (var i = 0; i < text.length; i++) {
  +      current = next;
  +
  +      if (text.startsWith('//', i)) {
  +        current = 'B';
  +        next = 'B';
  +      } else if (text.startsWith('\n', i)) {
  +        current = 'A';
  +        next = 'A';
  +      } else if (current != 'B') {
  +        if (text.startsWith("'", i)) {
  +          handleStringDelimiter(1);
  +        } else if (text.startsWith('"', i)) {
  +          handleStringDelimiter(2);
  +        } else if (strOpen[0] > 0 && text.startsWith('{', i)) {
  +          strOpen.insert(0, 0);
  +        } else if (strOpen.length > 1 && text.startsWith('}', i)) {
  +          strOpen.removeAt(0);
  +        } else {
  +          for (final keyword in dartKeywords) {
  +            if (text.startsWith('$keyword ', i)) {
  +              style += strSeq('C', keyword.length);
  +              i += keyword.length;
  +              current = 'A';
  +              continue;
  +            }
  +          }
  +        }
  +      }
  +
  +      style += current;
  +    }
  +
  +    editor.styleBuffer.text = style;
  +    editor.d.redraw();
  +  }
  +
  +  /// Execute editor code.
  +  void runCode() {
  +    var code = editor.textBuffer.text;
  +
  +    // Prepend line ending for search porposes.
  +    code = '\n$code';
  +
  +    // Split code into imports and code.
  +    final regex = new RegExp(r'''\n\s*import ["'].*["'];''');
  +    final matches = regex.allMatches(code);
  +    final splixIndex = matches.isNotEmpty ? matches.last.end : 0;
  +    final imports = code.substring(0, splixIndex);
  +    code = code.substring(splixIndex);
  +
  +    // Wrap code in a special wrapper that proves a special print function.
  +    final wrappedCode = createWrappedCode(imports, code);
  +
  +    // Code data URI.
  +    final uri = new Uri.dataFromString(wrappedCode);
  +
  +    // Receive port for isolate errors
  +    final onError = new ReceivePort();
  +    onError.listen((e) {
  +      // Replace URI references in stack trace.
  +      var msg = e[0].toString();
  +      final regex = r'\(' + escapeAll(uri.toString()) + r':[0-9]*:[0-9]*\)';
  +      msg = msg.replaceAll(new RegExp(regex), '(DartPad)');
  +
  +      // Prettify a little more.
  +      msg = msg.replaceAll("'$uri': ", '');
  +      msg = msg.replaceFirst(', #0', ',\n#0');
  +      msg = msg.trimRight();
  +
  +      println('An error has occured:\n$msg', error: true);
  +    });
  +
  +    // Receive port for isolate print messages
  +    final onPrint = new ReceivePort();
  +    onPrint.listen((msg) {
  +      println(msg);
  +    });
  +
  +    // Receive port for isolate exit event
  +    final onExit = new ReceivePort();
  +    onExit.listen((msg) {
  +      println('Isolate exited.');
  +      onError.close();
  +      onPrint.close();
  +      onExit.close();
  +    });
  +
  +    // Start isolate.
  +    println('\nSpawning isolate...');
  +    runZoned(() {
  +      Isolate.spawnUri(uri, [], onPrint.sendPort,
  +          onError: onError.sendPort,
  +          onExit: onExit.sendPort,
  +          errorsAreFatal: true);
  +    }, onError: (e) {
  +      // Remove URI reference from error message.
  +      var msg = e.toString();
  +      msg = msg.replaceFirst(" '$uri': ", '\n');
  +      msg = msg.replaceAll("'$uri': ", '');
  +
  +      println(msg, error: true);
  +
  +      // Close send ports.
  +      onError.close();
  +      onPrint.close();
  +      onExit.close();
       });
     }
   
     /// Add line to console.
     void println(String line, {bool error: false}) {
       line = '$line\n';
  -    consoleBuffer.text += line;
  +    console.textBuffer.text += line;
   
       // Add to style buffer.
  -    consoleStyleBuffer.text += strSeq(error ? 'B' : 'A', line.length);
  +    console.styleBuffer.text += strSeq(error ? 'B' : 'A', line.length);
   
       // Scroll all the way down.
  -    console.scroll(consoleBuffer.text.split('\n').length, 0);
  +    console.d.scroll(console.textBuffer.text.split('\n').length, 0);
     }
   }
   
  
positive.code:   pad.show();
    return fl.runAsync();
  }
  
negative.code:     // Global theme settings
      fl.scheme('gleam');
      fl.background(38, 38, 38);
      fl.foreground(128, 128, 128);
      fl.option(fl.Option.VISIBLE_FOCUS, false);
      fl.setColor(fl.SELECTION_COLOR, 64, 64, 64);
  
  