Last active
February 5, 2023 10:14
-
-
Save mmkathurima/d5c4f3791dc487892656db94ea8c05fe to your computer and use it in GitHub Desktop.
Basic shell control created using JavaFX. Can be embedded into Swing and JavaFX applications. Emulates a command line UI. To process commands, use the `onEnter` functional interface.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.beans.value.ChangeListener; | |
import javafx.beans.value.ObservableValue; | |
import javafx.event.EventHandler; | |
import javafx.scene.control.TextArea; | |
import javafx.scene.input.KeyEvent; | |
import java.util.ArrayList; | |
import java.util.function.Consumer; | |
public class ShellControl extends TextArea { | |
private String prompt = ">>>"; | |
private String input; | |
private int caretPos, histIndex = 0; | |
public Consumer<ShellControl> onEnter; | |
private ArrayList<String> history; | |
public String getPrompt() { | |
return this.prompt + " "; | |
} | |
public void setPrompt(String prompt) { | |
this.setText(this.getText().replace(this.prompt, prompt)); | |
this.prompt = prompt; | |
} | |
public String getInput() { | |
return this.input; | |
} | |
private void setInput(String input) { | |
this.input = input; | |
} | |
public void print(String text) { | |
this.appendText("\n" + text); | |
} | |
public void println(String text) { | |
this.appendText(String.format("\n%s\n", text)); | |
} | |
public void println() { | |
this.appendText("\n"); | |
} | |
public void printf(String format, Object... args) { | |
this.appendText(String.format("\n" + format, args)); | |
} | |
private int getLongLastPos() { | |
return this.getText().lastIndexOf(this.getPrompt()) + this.getPrompt().length(); | |
} | |
public ArrayList<String> getHistory() { | |
return this.history; | |
} | |
public ShellControl() { | |
history = new ArrayList<>(); | |
this.setText(this.getPrompt()); | |
this.textProperty().addListener(new ChangeListener<String>() { | |
@Override | |
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { | |
caretPos = getCaretPosition(); | |
int pos = oldValue.lastIndexOf(getPrompt()) + getPrompt().length() + 1; | |
if (caretPos < pos && oldValue.length() > newValue.length()) { | |
setText(oldValue); | |
positionCaret(caretPos); | |
} | |
} | |
}); | |
this.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() { | |
@Override | |
public void handle(KeyEvent event) { | |
switch (event.getCode()) { | |
case ENTER: | |
event.consume(); | |
setInput(getText().substring(getLongLastPos())); | |
if (getInput().equals("cls") | getInput().equals("clear")) | |
clear(); | |
else | |
onEnter.accept(ShellControl.this); | |
appendText(getPrompt()); | |
caretPos = getCaretPosition(); | |
history.add(getInput()); | |
histIndex++; | |
break; | |
case UP: | |
event.consume(); | |
if (!history.isEmpty() & histIndex > 0) | |
replaceText(getLongLastPos(), getText().length(), history.get(--histIndex)); | |
break; | |
case DOWN: | |
event.consume(); | |
if (!history.isEmpty() & histIndex < history.size()) | |
replaceText(getLongLastPos(), getText().length(), history.get(++histIndex)); | |
break; | |
case RIGHT: | |
if (!history.isEmpty() && getText().substring(getLongLastPos()).isEmpty()) { | |
event.consume(); | |
replaceText(getLongLastPos(), getText().length(), history.get(history.size() - 1)); | |
} | |
break; | |
} | |
} | |
}); | |
this.positionCaret(getLongLastPos()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shellcontrol; | |
import javafx.application.Platform; | |
import javafx.embed.swing.JFXPanel; | |
import javafx.scene.Scene; | |
import javafx.scene.text.Font; | |
import javax.swing.*; | |
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
public class ShellTest { | |
public static void main(String[] args) { | |
JFrame frame = new JFrame(); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
JFXPanel panel = new JFXPanel(); | |
frame.add(panel); | |
Platform.runLater(() -> { | |
ShellControl control = new ShellControl(); | |
/*control.setStyle("-fx-control-inner-background: black; -fx-text-fill: white"); | |
control.setFont(new Font("Consolas", control.getFont().getSize() + 3)); | |
control.setPrompt("4ZVla =>> ");*/ | |
control.requestFocus(); | |
/*control.onEnter = (ShellControl c) -> { | |
try { | |
//c.printf("%s\n", c.getInput()); | |
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", c.getInput()); | |
builder.redirectErrorStream(true); | |
Process process = builder.start(); | |
new BufferedReader(new InputStreamReader(process.getInputStream())).lines().forEach(c::print); | |
c.println(); | |
} catch (IOException e) { | |
c.printf("ERROR: %s\n", e.toString()); | |
} | |
};*/ | |
control.onEnter = c -> c.println(c.getInput()); | |
Scene scene = new Scene(control); | |
panel.setScene(scene); | |
}); | |
frame.setSize(500, 500); | |
frame.setVisible(true); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment