Create a "Command" Console
Asked Answered
V

7

11

I have a bit of an unusual question: How can I create a "Command Console" using Swing?

What I want to have is a console where the users type in commands, press enter, and the output from the command is displayed under. I don't want to allow the user to change the "prompt" and older output. I am thinking of something like Windows CMD.EXE.

I had a look at this question, however it doesn't answer my question.

Valenba answered 10/8, 2009 at 14:53 Comment(3)
Do you mean something like the BeanShell Workspace?Roger
Why would you use Swing? What's wrong with just creating a Java console app directly?Ginkgo
This is a better answer than the one I was thinking of. :-)Cardinale
C
8

BeanShell provides a JConsole, a command line input console with the following features:

  • a blinking cursor
  • command history
  • cut/copy/paste including selection with CTRL+arrow keys
  • command completion
  • Unicode character input
  • coloured text output
  • ...and it all comes wrapped in a scroll pane.

The BeanShell JARs are available from http://www.beanshell.org/download.html and the source is available via SVN from svn co http://ikayzo.org/svn/beanshell

For more info on JConsole see http://www.beanshell.org/manual/jconsole.html

Here is an example of using BeanShell's JConsole in your application:

import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

import javax.swing.JFrame;

import bsh.util.GUIConsoleInterface;
import bsh.util.JConsole;

/** 
 * Example of using the BeanShell project's JConsole in
 * your own application.
 * 
 * JConsole is a command line input console that has support 
 * for command history, cut/copy/paste, a blinking cursor, 
 * command completion, Unicode character input, coloured text 
 * output and comes wrapped in a scroll pane.
 * 
 * For more info, see http://www.beanshell.org/manual/jconsole.html
 * 
 * @author tukushan
 */
public class JConsoleExample {

    public static void main(String[] args) {

        //define a frame and add a console to it
        JFrame frame = new JFrame("JConsole example");

        JConsole console = new JConsole();

        frame.getContentPane().add(console);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600,400);

        frame.setVisible(true);

        inputLoop(console, "JCE (type 'quit' to exit): ");

        System.exit(0);
    }

    /**
     * Print prompt and echos commands entered via the JConsole
     * 
     * @param console a GUIConsoleInterface which in addition to 
     *         basic input and output also provides coloured text
     *         output and name completion
     * @param prompt text to display before each input line
     */
    private static void inputLoop(GUIConsoleInterface console, String prompt) {
        Reader input = console.getIn();
        BufferedReader bufInput = new BufferedReader(input);

        String newline = System.getProperty("line.separator");

        console.print(prompt, Color.BLUE);

        String line;
        try {
            while ((line = bufInput.readLine()) != null) {
                console.print("You typed: " + line + newline, Color.ORANGE);

                // try to sync up the console
                //System.out.flush();
                //System.err.flush();
                //Thread.yield();  // this helps a little

                if (line.equals("quit")) break; 
                console.print(prompt, Color.BLUE);
            }
            bufInput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

NB: JConsole returns ";" if you hit Enter by itself.

Cassity answered 24/8, 2009 at 20:21 Comment(1)
This doesn't work for me. I'm using bsh-2.0b4.jar. Typeing quit and hitting enter does nothing but bring the cursor to the new line. The background color is white. The letter colors are black. I never see You typed:.Sideswipe
M
3

Take a look at the Groovy Console. This is what it looks like:

Groovy Console http://groovy.codehaus.org/download/attachments/36800/GroovyConsole.gif

Although it's a console for Groovy rather than arbitrary commands, you should be able to adapt ideas and/or code from it to get what you need.

Mullen answered 10/8, 2009 at 15:3 Comment(0)
T
2

If I understand your question correctly, you're looking to execute commands specific to your application. My advice would be, if this is in fact the case, to use two textareas, one that's a single line and one that takes up the rest of the space. Add some keypress event handlers to the small one, which would be editable, and make the other one read-only. If you must have a single text area, you could make it read-only and then add a few keypress handlers to handle character input and up/down keypresses.

Hope I've understood your question correctly, best of luck.

Truesdale answered 10/8, 2009 at 15:8 Comment(0)
R
1

Try this code:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

/**
 *
 * @author Alistair
 */
public class Console extends JPanel implements KeyListener {

    private static final long serialVersionUID = -4538532229007904362L;
    private JLabel keyLabel;
    private String prompt = "";
    public boolean ReadOnly = false;
    private ConsoleVector vec = new ConsoleVector();
    private ConsoleListener con = null;
    private String oldTxt = "";
    private Vector history = new Vector();
    private int history_index = -1;
    private boolean history_mode = false;

    public Console() {
        super();
        setSize(300, 200);
        setLayout(new FlowLayout(FlowLayout.CENTER));
        keyLabel = new JLabel("");
        setFocusable(true);
        keyLabel.setFocusable(true);
        keyLabel.addKeyListener(this);
        addKeyListener(this);
        add(keyLabel);
        setVisible(true);
    }

    public void registerConsoleListener(ConsoleListener c) {
        this.con = c;
    }

    public String getPrompt() {
        return this.prompt;
    }

    public void setPrompt(String s) {
        this.prompt = s;
    }

    private void backspace() {
        if (!this.vec.isEmpty()) {
            this.vec.remove(this.vec.size() - 1);
            this.print();
        }
    }

    @SuppressWarnings("unchecked")
    private void enter() {
        String com = this.vec.toString();
        String return$ = "";
        if (this.con != null) {
            return$ = this.con.receiveCommand(com);
        }

        this.history.add(com);
        this.vec.clear();
        if (!return$.equals("")) {
            return$ = return$ + "<br>";
        }
        // <HTML> </HTML>
        String h = this.keyLabel.getText().substring(6, this.keyLabel.getText().length() - 7);
        this.oldTxt = h.substring(0, h.length() - 1) + "<BR>" + return$;
        this.keyLabel.setText("<HTML>" + this.oldTxt + this.prompt + "_</HTML>");
    }

    private void print() {
        this.keyLabel.setText("<HTML>" + this.oldTxt + this.prompt + this.vec.toString() + "_</HTML>");
        this.repaint();
    }

    @SuppressWarnings("unchecked")
    private void print(String s) {
        this.vec.add(s);
        this.print();
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
        this.handleKey(e);
    }

    private void history(int dir) {
        if (this.history.isEmpty()) {
            return;
        }
        if (dir == 1) {
            this.history_mode = true;
            this.history_index++;
            if (this.history_index > this.history.size() - 1) {
                this.history_index = 0;
            }
            // System.out.println(this.history_index);
            this.vec.clear();
            String p = (String) this.history.get(this.history_index);
            this.vec.fromString(p.split(""));

        } else if (dir == 2) {
            this.history_index--;
            if (this.history_index < 0) {
                this.history_index = this.history.size() - 1;
            }
            // System.out.println(this.history_index);
            this.vec.clear();
            String p = (String) this.history.get(this.history_index);
            this.vec.fromString(p.split(""));
        }

        print();
    }

    private void handleKey(KeyEvent e) {

        if (!this.ReadOnly) {
            if (e.getKeyCode() == 38 | e.getKeyCode() == 40) {
                if (e.getKeyCode() == 38) {
                    history(1);
                } else if (e.getKeyCode() == 40 & this.history_mode != false) {
                    history(2);
                }
            } else {
                this.history_index = -1;
                this.history_mode = false;
                if (e.getKeyCode() == 13 | e.getKeyCode() == 10) {
                    enter();
                } else if (e.getKeyCode() == 8) {
                    this.backspace();
                } else {
                    if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
                        this.print(String.valueOf(e.getKeyChar()));
                    }
                }
            }
        }
    }
}


class ConsoleVector extends Vector {

    private static final long serialVersionUID = -5527403654365278223L;

    @SuppressWarnings("unchecked")
    public void fromString(String[] p) {
        for (int i = 0; i < p.length; i++) {
            this.add(p[i]);
        }
    }

    public ConsoleVector() {
        super();
    }

    @Override
    public String toString() {
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < this.size(); i++) {
            s.append(this.get(i));
        }
        return s.toString();
    }
}

public interface ConsoleListener {
    public String receiveCommand(String command);
}

It uses a JPanel as the panel and a JLabel as the console. The commands are passed to a CommandListener object and the returned value is printed to the console.

Roger answered 11/8, 2009 at 9:31 Comment(0)
D
0

You can execute arbitrary commands with Plexus using Commandline. It handles escaping of the arguments, environment specific execution, and allows you to attach consumers to stdout and stderr, leaving you to focus on the handling.

Here's a link to another answer I gave, showing how you can set up a Commandline and handle the output.

Deidredeific answered 10/8, 2009 at 14:59 Comment(0)
T
0

I wouldn't try shortcuts (like groovy/beanshell) unless they fit your needs exactly. Trying to make a high-level tool do what you want when it's not what it already does can be the most frustrating thing about programming.

It should be fairly easy to take a text area and "Make it your own", but it would be much easier to do as someone else suggested and use a one-line text control combined with a multi-line display area.

In either case you want to keep pretty close control on the whole system, intercept and filter some keystrokes, disable input to the "Display" area if you decide to go with that, force a click on your display area to send focus to your input field, ...

If you do the single box thing, you'll want to make sure your input is always at the bottom of the box and that you control their cursor positioning (you probably don't want them able to do any input to any line except the last line).

I suggest you don't assume a single control is just going to work without modification, expect to do the legwork and everything will be fine.

Thelen answered 10/8, 2009 at 18:34 Comment(0)
W
0

If you want

something like Windows CMD.EXE.

use cmd.exe. All you print using System.out.println("") will appear there. What you have to do is create a .bat file where your compiled file is.

echo off
cls
java -jar fileName.jar
Widmer answered 19/4, 2014 at 15:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.