command history rotation

This commit is contained in:
Radek Davidek 2026-03-04 19:21:53 +01:00
parent f1875e5343
commit 31715240b6

View File

@ -37,6 +37,7 @@ public class MainWindow extends JFrame {
private int lastMainPanelExtent = -1;
private boolean applyingSavedDividerLocation = false;
private boolean wildcardDialogOpen = false;
private int commandHistoryIndex = -1;
public MainWindow() {
super("KF Manager v" + MainApp.APP_VERSION + " (" + MainApp.CURRENT_OS + ")");
@ -390,6 +391,8 @@ public class MainWindow extends JFrame {
} else if (e.getKeyCode() == KeyEvent.VK_E && e.isControlDown()) {
showCommandLineHistory();
e.consume();
} else if (!e.isControlDown() && !e.isAltDown() && !e.isMetaDown()) {
commandHistoryIndex = -1;
}
}
});
@ -1233,6 +1236,7 @@ public class MainWindow extends JFrame {
Object currentItem = commandLine.getEditor().getItem();
if (currentItem != null && !currentItem.toString().isEmpty()) {
commandLine.getEditor().setItem("");
commandHistoryIndex = -1;
textCleared = true;
}
@ -2347,15 +2351,14 @@ public class MainWindow extends JFrame {
private void showCommandLineHistory() {
if (commandLine != null && commandLine.getItemCount() > 0) {
commandLine.requestFocusInWindow();
if (!commandLine.isPopupVisible()) {
commandLine.setSelectedIndex(0);
commandLine.showPopup();
} else {
int count = commandLine.getItemCount();
int current = commandLine.getSelectedIndex();
// If index is -1 or invalid, start from 0, otherwise go to next
int nextIndex = (current < 0) ? 0 : (current + 1) % count;
commandLine.setSelectedIndex(nextIndex);
int count = commandLine.getItemCount();
commandHistoryIndex = (commandHistoryIndex + 1) % count;
String nextCommand = commandLine.getItemAt(commandHistoryIndex);
commandLine.getEditor().setItem(nextCommand);
Component editorComp = commandLine.getEditor().getEditorComponent();
if (editorComp instanceof JTextField tf) {
tf.setCaretPosition(tf.getText().length());
}
}
}
@ -2554,8 +2557,14 @@ public class MainWindow extends JFrame {
// Special handling for bash/sh to open a terminal with that shell
openTerminal(trimmed.toLowerCase());
} else {
// Execute natively for other commands
executeNative(trimmed, null);
// On Linux, run command line commands in an external terminal.
// This keeps command output visible and uses the active panel directory.
if (MainApp.CURRENT_OS == MainApp.OS.LINUX) {
openTerminalWithCommand(trimmed);
} else {
// Execute natively for other commands
executeNative(trimmed, null);
}
}
// Final prompt update after command execution (path might have changed)
@ -2645,6 +2654,115 @@ public class MainWindow extends JFrame {
}
}
private void openTerminalWithCommand(String command) {
if (command == null || command.trim().isEmpty()) return;
File currentDir = activePanel.getCurrentDirectory();
if (currentDir == null || !currentDir.exists()) {
currentDir = new File(System.getProperty("user.home"));
}
// Keep terminal open after running command so user can inspect output.
String shellScript = command + "; exec sh -i";
try {
List<String> terminals = new ArrayList<>();
String envTerminal = System.getenv("TERMINAL");
if (envTerminal != null && !envTerminal.isEmpty()) {
terminals.add(envTerminal);
}
terminals.add("xdg-terminal-exec");
terminals.addAll(Arrays.asList(
"x-terminal-emulator",
"gnome-terminal",
"konsole",
"xfce4-terminal",
"alacritty",
"kitty",
"foot",
"wezterm",
"mate-terminal",
"terminator",
"tilix",
"qterminal",
"urxvt",
"st",
"xterm"
));
boolean started = false;
for (String terminal : terminals) {
try {
List<String> args = new ArrayList<>();
args.add(terminal);
if (terminal.equals("gnome-terminal") || terminal.equals("xfce4-terminal") ||
terminal.equals("mate-terminal") || terminal.equals("terminator") ||
terminal.equals("tilix")) {
args.add("--working-directory=" + currentDir.getAbsolutePath());
args.add("--");
args.add("sh");
args.add("-c");
args.add(shellScript);
} else if (terminal.equals("alacritty") || terminal.equals("foot")) {
args.add("--working-directory");
args.add(currentDir.getAbsolutePath());
args.add("-e");
args.add("sh");
args.add("-c");
args.add(shellScript);
} else if (terminal.equals("kitty")) {
args.add("--directory");
args.add(currentDir.getAbsolutePath());
args.add("sh");
args.add("-c");
args.add(shellScript);
} else if (terminal.equals("konsole") || terminal.equals("qterminal")) {
args.add("--workdir");
args.add(currentDir.getAbsolutePath());
args.add("-e");
args.add("sh");
args.add("-c");
args.add(shellScript);
} else if (terminal.equals("wezterm")) {
args.add("start");
args.add("--cwd");
args.add(currentDir.getAbsolutePath());
args.add("sh");
args.add("-c");
args.add(shellScript);
} else if (terminal.equals("xdg-terminal-exec")) {
args.add("sh");
args.add("-c");
args.add(shellScript);
} else {
args.add("-e");
args.add("sh");
args.add("-c");
args.add(shellScript);
}
new ProcessBuilder(args).directory(currentDir).start();
started = true;
break;
} catch (IOException ignore) {
// Try next terminal command.
}
}
if (!started) {
throw new Exception("Could not start any terminal emulator.");
}
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
"Error opening terminal for command execution: " + e.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE);
}
}
private List<String> parseCommand(String command) {
List<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
@ -2679,6 +2797,7 @@ public class MainWindow extends JFrame {
}
}
commandLine.insertItemAt(command, 0);
commandHistoryIndex = -1;
// We don't necessarily want to select it here as it might interfere with the editor state
}