public EditorConsolePane() {
    super();
    textArea = new JTextPane();
    textArea.setEditorKit(new HTMLEditorKit());
    textArea.setTransferHandler(new JTextPaneHTMLTransferHandler());
    String css = PreferencesUser.getInstance().getConsoleCSS();
    ((HTMLEditorKit) textArea.getEditorKit()).getStyleSheet().addRule(css);
    textArea.setEditable(false);

    setLayout(new BorderLayout());
    add(new JScrollPane(textArea), BorderLayout.CENTER);

    if (ENABLE_IO_REDIRECT) {
      Debug.log(3, "EditorConsolePane: starting redirection to message area");
      int npipes = 2;
      NUM_PIPES = npipes * ScriptRunner.scriptRunner.size();
      pin = new PipedInputStream[NUM_PIPES];
      reader = new Thread[NUM_PIPES];
      for (int i = 0; i < NUM_PIPES; i++) {
        pin[i] = new PipedInputStream();
      }

      int irunner = 0;
      for (IScriptRunner srunner : ScriptRunner.scriptRunner.values()) {
        Debug.log(3, "EditorConsolePane: redirection for %s", srunner.getName());
        if (srunner.doSomethingSpecial(
            "redirect", Arrays.copyOfRange(pin, irunner * npipes, irunner * npipes + 2))) {
          Debug.log(3, "EditorConsolePane: redirection success for %s", srunner.getName());
          quit = false; // signals the Threads that they should exit
          // TODO Hack to avoid repeated redirect of stdout/err
          ScriptRunner.systemRedirected = true;

          // Starting two seperate threads to read from the PipedInputStreams
          for (int i = irunner * npipes; i < irunner * npipes + npipes; i++) {
            reader[i] = new Thread(this);
            reader[i].setDaemon(true);
            reader[i].start();
          }
          irunner++;
        }
      }
    }

    // Create the popup menu.
    popup = new JPopupMenu();
    JMenuItem menuItem = new JMenuItem("Clear messages");
    // Add ActionListener that clears the textArea
    menuItem.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            textArea.setText("");
          }
        });
    popup.add(menuItem);

    // Add listener to components that can bring up popup menus.
    MouseListener popupListener = new PopupListener(popup);
    textArea.addMouseListener(popupListener);
  }
  public static void main() {
    // Main
    frame = new JFrame("Java Playground");
    frame.setSize(640, 480);
    // Make sure the divider is properly resized
    frame.addComponentListener(
        new ComponentAdapter() {
          public void componentResized(ComponentEvent c) {
            splitter.setDividerLocation(.8);
          }
        });
    // Make sure the JVM is reset on close
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosed(WindowEvent w) {
            new FrameAction().kill();
          }
        });

    // Setting up the keybinding
    // Ctrl+k or Cmd+k -> compile
    bind(KeyEvent.VK_K);

    // Ctrl+e or Cmd+e -> console
    bind(KeyEvent.VK_E);

    // Save, New file, Open file, Print.
    // Currently UNUSED until I figure out how normal java files and playground files will
    // interface.
    bind(KeyEvent.VK_S);
    bind(KeyEvent.VK_N);
    bind(KeyEvent.VK_O);
    bind(KeyEvent.VK_P);

    // Binds the keys to the action defined in the FrameAction class.
    frame.getRootPane().getActionMap().put("console", new FrameAction());

    // The main panel for typing code in.
    text = new JTextPane();
    textScroll = new JScrollPane(text);
    textScroll.setBorder(null);
    textScroll.setPreferredSize(new Dimension(640, 480));

    // Document with syntax highlighting. Currently unfinished.
    doc = text.getStyledDocument();
    doc.addDocumentListener(
        new DocumentListener() {
          public void changedUpdate(DocumentEvent d) {}

          public void insertUpdate(DocumentEvent d) {}

          public void removeUpdate(DocumentEvent d) {}
        });

    ((AbstractDocument) doc).setDocumentFilter(new NewLineFilter());

    // The output log; a combination compiler warning/error/runtime error/output log.
    outputText = new JTextPane();
    outputScroll = new JScrollPane(outputText);
    outputScroll.setBorder(null);

    // "Constant" for the error font
    error = new SimpleAttributeSet();
    error.addAttribute(StyleConstants.CharacterConstants.Italic, Boolean.TRUE);
    error.addAttribute(StyleConstants.Foreground, Color.RED);

    // "Constant" for the warning message font
    warning = new SimpleAttributeSet();
    warning.addAttribute(StyleConstants.CharacterConstants.Italic, Boolean.TRUE);
    warning.addAttribute(StyleConstants.Foreground, Color.PINK);

    // "Constant" for the debugger error font
    progErr = new SimpleAttributeSet();
    progErr.addAttribute(StyleConstants.Foreground, Color.BLUE);

    // Print streams to redirect System.out and System.err.
    out = new TextOutputStream(outputText, null);
    err = new TextOutputStream(outputText, error);
    System.setOut(new PrintStream(out));
    System.setErr(new PrintStream(err));

    // Sets up the output log
    outputText.setEditable(false);
    outputScroll.setVisible(true);

    // File input/output setup
    chooser = new JFileChooser();

    // Setting up miscellaneous stuff
    compiler = ToolProvider.getSystemJavaCompiler();
    JVMrunning = false;
    redirectErr = null;
    redirectOut = null;
    redirectIn = null;

    // Sets up the splitter pane and opens the program up
    splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textScroll, outputScroll);
    consoleDisplayed = false;
    splitter.remove(outputScroll); // Initially hides terminal until it is needed
    splitter.setOneTouchExpandable(true);
    frame.add(splitter);
    frame.setVisible(true);

    // Sets the divider to the proper one, for debugging
    // splitter.setDividerLocation(.8);
  }