Skip to content

Instantly share code, notes, and snippets.

@NeatMonster
Created February 10, 2013 18:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NeatMonster/74f2d1debe03d4699697 to your computer and use it in GitHub Desktop.
Save NeatMonster/74f2d1debe03d4699697 to your computer and use it in GitHub Desktop.
A proof of concept class showing that it's easy to replicate the Windows command line interface.
package fr.neatmonster.console;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
/*
* MM'""""'YMM dP
* M' .mmm. `M 88
* M MMMMMooM .d8888b. 88d888b. .d8888b. .d8888b. 88 .d8888b.
* M MMMMMMMM 88' `88 88' `88 Y8ooooo. 88' `88 88 88ooood8
* M. `MMM' .M 88. .88 88 88 88 88. .88 88 88. ...
* MM. .dM `88888P' dP dP `88888P' `88888P' dP `88888P'
* MMMMMMMMMMM
*/
/**
* A proof of concept class showing that it's easy to replicate the Windows command line interface.
*
* @author NeatMonster.
*/
public class Console {
/** The special characters allowed in the console. */
private static final String SPECIAL_CHARACTERS = " ²&~\"#'{([|`_\\^@)°]=+}€^¨$£¤ù%*µ<>,?;.:!§/*-+";
/**
* The method called when the application starts.
*
* @param args
* the arguments
*/
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
final Console console = new Console();
console.frame.setVisible(true);
} catch (final Exception e) {
e.printStackTrace();
}
}
});
}
private String consoleText = "";
private File currentDirectory = new File(System.getProperty("user.home"));
private int cursorDisplayed = 0;
private boolean cursorEnabled = false;
private int cursorPosition = 0;
private JFrame frame;
private JScrollPane scrollPane;
private JTextArea textArea;
private Timer timer;
private String userText = "";
/**
* Instantiates a new console.
*/
public Console() {
initialize();
}
/**
* Adds the specified character to the console.
*
* @param c
* the caracter
*/
public void addCharacter(final String c) {
String userText = this.userText + c;
if (cursorEnabled && cursorPosition < this.userText.length()) {
userText = this.userText.substring(0, cursorPosition) + c;
if (cursorPosition < this.userText.length() - 1)
userText += this.userText.substring(cursorPosition, this.userText.length());
}
this.userText = userText;
cursorPosition++;
update();
}
/**
* Simulate an user pressing backspace.
*/
public void backspace() {
if (cursorPosition > 0) {
String userText = this.userText.substring(0, cursorPosition - 1);
if (cursorPosition < this.userText.length() - 1)
userText += this.userText.substring(cursorPosition, this.userText.length());
this.userText = userText;
if (cursorPosition > 0)
cursorPosition--;
update();
}
}
/**
* Simulate an user pressing delete.
*/
public void delete() {
if (cursorEnabled && cursorPosition < userText.length()) {
String userText = this.userText.substring(0, cursorPosition);
if (cursorPosition < this.userText.length() - 1)
userText += this.userText.substring(cursorPosition + 1, this.userText.length());
this.userText = userText;
update();
}
}
/**
* Handle a key event.
*
* @param e
* the event
*/
public void handleKeyEvent(final KeyEvent e) {
if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK && e.getKeyCode() != KeyEvent.VK_LEFT
&& e.getKeyCode() != KeyEvent.VK_RIGHT)
return;
if (e.getKeyChar() == '\n') {
cursorEnabled = false;
final String userText = this.userText;
println(userText);
this.userText = "";
if (!userText.isEmpty()) {
String[] args = userText.trim().replaceAll(" {2,}", " ").split(" ");
if (args.length > 0) {
final String command = args[0];
if (args.length == 1)
args = new String[0];
else
args = Arrays.copyOfRange(args, 1, args.length);
if (command.equalsIgnoreCase("cd")) {
if (args.length > 0) {
final File currentDirectory = this.currentDirectory.toPath().resolve(args[0]).normalize().toFile();
if (currentDirectory.exists() && currentDirectory.isDirectory()) {
this.currentDirectory = currentDirectory;
} else
println("Le chemin d'accès spécifié est introuvable.");
} else
try {
println(currentDirectory.getCanonicalPath());
} catch (final Exception e1) {
println(currentDirectory.getAbsolutePath());
}
println("");
} else if (command.equalsIgnoreCase("exit")) {
int status = 0;
if (args.length > 0)
try {
status = Integer.parseInt(args[0]);
} catch (final Exception e1) {
}
System.exit(status);
} else {
println("'" + command + "' n'est pas reconnu en tant que commande interne");
println("ou externe, un programme exécutable ou un fichier de commandes.");
println("");
}
}
}
requestUserInput();
} else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
if (cursorPosition > 0) {
e.consume();
backspace();
}
} else if (e.getKeyCode() == KeyEvent.VK_DELETE) {
if (cursorPosition < userText.length()) {
e.consume();
delete();
}
} else if (e.getKeyCode() == KeyEvent.VK_LEFT && (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
if (cursorPosition > 0) {
e.consume();
cursorPosition = userText.substring(0, cursorPosition - 1).lastIndexOf(" ") >= 0 ? userText.substring(0, cursorPosition - 1)
.lastIndexOf(" ") + 1 : 0;
cursorDisplayed = 0;
update();
}
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
if (cursorPosition > 0) {
cursorPosition--;
cursorDisplayed = 0;
update();
}
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT && (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
if (cursorPosition < userText.length() - 1) {
e.consume();
cursorPosition += userText.substring(cursorPosition + 1, userText.length()).indexOf(" ") >= 0 ? userText.substring(
cursorPosition + 1, userText.length()).indexOf(" ") + 2 : userText.substring(cursorPosition + 1, userText.length()).length();
cursorDisplayed = 0;
update();
}
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
if (cursorPosition < userText.length()) {
cursorPosition++;
cursorDisplayed = 0;
update();
}
} else if (e.getKeyCode() == KeyEvent.VK_HOME) {
cursorPosition = 0;
cursorDisplayed = 0;
update();
} else if (e.getKeyCode() == KeyEvent.VK_END) {
cursorPosition = userText.length();
cursorDisplayed = 0;
update();
} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
userText = "";
cursorPosition = 0;
cursorDisplayed = 0;
update();
} else if (Character.isUnicodeIdentifierPart(e.getKeyChar()) || SPECIAL_CHARACTERS.contains(Character.toString(e.getKeyChar())))
addCharacter(Character.toString(e.getKeyChar()));
}
/**
* Initialize the console.
*/
public void initialize() {
initializeFrame();
initializeTimer();
initializeTextArea();
initializeScrollPane();
}
/**
* Initialize the frame.
*/
public void initializeFrame() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (final Exception e) {
}
frame = new JFrame();
final int width = 675;
final int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
final int height = 342;
final int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
frame.setBounds((screenWidth - width) / 2, (screenHeight - height) / 2, width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Administateur : C:\\Windows\\system32\\cmd.exe");
final ArrayList<Image> icons = new ArrayList<Image>();
icons.add(new ImageIcon(getClass().getResource("/resources/cmd_x16.png")).getImage());
icons.add(new ImageIcon(getClass().getResource("/resources/cmd_x32.png")).getImage());
icons.add(new ImageIcon(getClass().getResource("/resources/cmd_x48.png")).getImage());
icons.add(new ImageIcon(getClass().getResource("/resources/cmd_x256.png")).getImage());
frame.setIconImages(icons);
frame.setResizable(false);
}
/**
* Initialize the scrollpane.
*/
public void initializeScrollPane() {
scrollPane = new JScrollPane(textArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
frame.setContentPane(scrollPane);
}
/**
* Initialize the text area.
*/
public void initializeTextArea() {
textArea = new JTextArea();
textArea.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
handleKeyEvent(e);
}
});
textArea.setEditable(false);
textArea.setBackground(Color.BLACK);
textArea.setForeground(Color.WHITE);
textArea.setFont(new Font("Lucida Console", Font.PLAIN, 13));
textArea.setLineWrap(true);
println("Microsoft Windows [version 6.1.7601]");
println("Copyright (c) 2009 Microsoft Corporation. Tous droits réservés.");
println("");
requestUserInput();
}
/**
* Initialize the timer responsible for the blinking cursor.
*/
public void initializeTimer() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (cursorEnabled) {
cursorDisplayed = (cursorDisplayed + 1) % 4;
update();
}
}
}, 0L, 250L);
}
/**
* Prints the String on the console.
*
* @param s
* the string to print
*/
public void print(final String s) {
consoleText += s;
update();
}
/**
* Print the screen to the console and add a new line.
*
* @param s
* the string to print
*/
public void println(final String s) {
print(s + "\n");
}
/**
* Request an input of the user.
*/
public void requestUserInput() {
try {
print(currentDirectory.getCanonicalPath() + ">");
} catch (final Exception e) {
print(currentDirectory.getAbsolutePath() + ">");
}
cursorEnabled = true;
cursorDisplayed = 0;
cursorPosition = 0;
userText = "";
}
/**
* Update the console display.
*/
public synchronized void update() {
String userText = this.userText;
if (cursorEnabled) {
if (cursorDisplayed < 3) {
userText = this.userText.substring(0, cursorPosition) + "_";
if (cursorPosition < this.userText.length() - 1)
userText += this.userText.substring(cursorPosition + 1, this.userText.length());
}
}
textArea.setText(consoleText + userText);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment