/* TclShell: a simple Tcl shell for Jacl * * Copyright (c) 1998 The Regents of the University of California. * All Rights Reserved. See the COPYRIGHT file for details. */ package tutorial.tcltk98; import tcl.lang.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class TclShell extends Panel { // The command input private StringBuffer commandBuffer = new StringBuffer(); // The Tcl interpreter private Interp tclInterp = new Interp(); // The TextArea widget for displaying commands and results public TextArea textArea; // Prompts public String mainPrompt = "% "; public String contPrompt = "> "; // Cursors private int promptCursor = 0; private int commandCursor = 0; // History public int historyLength = 10; private int historyCursor = 0; private Vector historyCommands = new Vector(); // Platform dependent newline private static String newline = System.getProperty("line.separator"); // Create a new Shell instance public TclShell () { // Graphics part super(new BorderLayout()); textArea = new TextArea("", 10, 40, TextArea.SCROLLBARS_BOTH); add("Center", textArea); // Event handling part textArea.addKeyListener(new ShellKeyListener()); // Initialize the interpreter try { tclInterp.setVar("tclShell", ReflectObject.newInstance(tclInterp, this), 0); tclInterp.eval("proc puts {s} {global tclShell; $tclShell putText $s\\n}"); } catch (TclException e) { System.out.println(tclInterp.getResult()); } } // Override this to initialize the prompt. We need to do // because we can't write to the TextArea until the peer // has been created public void addNotify () { super.addNotify(); putText(mainPrompt); } // Print output to the console, update the prompt cursor public void putText (String s) { if (s.length() != 0) { textArea.append(s); promptCursor += s.length(); textArea.setCaretPosition(promptCursor); } } // Evaluate the command so far, if possible, printing // a continuation prompt if not. protected void evalCommand () { String newtext = textArea.getText().substring(promptCursor); promptCursor += newtext.length(); if (commandBuffer.length() > 0) { commandBuffer.append("\n"); } commandBuffer.append(newtext); String command = commandBuffer.toString(); if (tclInterp.commandComplete(command)) { // Process it putText("\n"); Cursor oldCursor = textArea.getCursor(); textArea.setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { tclInterp.eval(command); } catch (TclException e) { // ignore } String result = tclInterp.getResult().toString(); if (result.length() > 0) { putText(result + "\n" + mainPrompt); } else { putText(mainPrompt); } commandBuffer.setLength(0); commandCursor = promptCursor; textArea.setCursor(oldCursor); updateHistory(command); } else { putText("\n" + contPrompt); } } // Update the command history void updateHistory (String command) { historyCursor = 0; if (historyCommands.size() == historyLength) { historyCommands.removeElementAt(0); } historyCommands.addElement(command); } // Replace the command with an entry from the history void nextCommand () { String text; if (historyCursor == 0) { text = ""; } else { historyCursor --; text = (String)historyCommands.elementAt( historyCommands.size() - historyCursor - 1); } textArea.replaceRange(text, commandCursor, textArea.getText().length()); } void previousCommand () { String text; if (historyCursor == historyCommands.size()) { return; } else { historyCursor ++; text = (String)historyCommands.elementAt( historyCommands.size() - historyCursor); } textArea.replaceRange(text, commandCursor, textArea.getText().length()); } // The key listener class ShellKeyListener extends KeyAdapter { public void keyPressed (KeyEvent keyEvent) { // Process keys switch (keyEvent.getKeyCode()) { case KeyEvent.VK_ENTER: keyEvent.consume(); evalCommand(); break; case KeyEvent.VK_BACK_SPACE: if (textArea.getCaretPosition() == promptCursor) { keyEvent.consume(); // don't backspace over prompt! } break; case KeyEvent.VK_LEFT: if (textArea.getCaretPosition() == promptCursor) { keyEvent.consume(); } break; case KeyEvent.VK_UP: previousCommand(); keyEvent.consume(); break; case KeyEvent.VK_DOWN: nextCommand(); keyEvent.consume(); break; default: // Otherwise we got a regular character. Don't consume it, // and TextArea will take care of displaying it. } } } }