diff --git a/src/main/java/cz/kamma/kfmanager/MainApp.java b/src/main/java/cz/kamma/kfmanager/MainApp.java index 2d0b3b4..a5eb4f6 100644 --- a/src/main/java/cz/kamma/kfmanager/MainApp.java +++ b/src/main/java/cz/kamma/kfmanager/MainApp.java @@ -27,7 +27,7 @@ public class MainApp { String os = System.getProperty("os.name").toLowerCase(); if (os.contains("win")) { CURRENT_OS = OS.WINDOWS; - } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) { + } else if (os.contains("linux") || os.contains("nix") || os.contains("nux") || os.contains("aix")) { CURRENT_OS = OS.LINUX; } else if (os.contains("mac")) { CURRENT_OS = OS.MACOS; diff --git a/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java b/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java index bd46475..2b99efd 100644 --- a/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java +++ b/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java @@ -117,6 +117,8 @@ public class MainWindow extends JFrame { addTabKeyHandler(table); addCommandLineRedirect(table); }); + addCommandLineRedirect(leftPanel.getFileTable()); + addTabKeyHandler(leftPanel.getFileTable()); // Load and set ViewMode for left panel try { @@ -137,6 +139,8 @@ public class MainWindow extends JFrame { addTabKeyHandler(table); addCommandLineRedirect(table); }); + addCommandLineRedirect(rightPanel.getFileTable()); + addTabKeyHandler(rightPanel.getFileTable()); // Load and set ViewMode for right panel try { @@ -291,14 +295,6 @@ public class MainWindow extends JFrame { } }); - // Add TAB handler to switch between panels - addTabKeyHandler(leftPanel.getFileTable()); - addTabKeyHandler(rightPanel.getFileTable()); - - // Add command line focus redirection - addCommandLineRedirect(leftPanel.getFileTable()); - addCommandLineRedirect(rightPanel.getFileTable()); - // Container for everything below the file panels JPanel bottomContainer = new JPanel(new BorderLayout()); @@ -319,8 +315,21 @@ public class MainWindow extends JFrame { if (editorComp instanceof JTextField) { JTextField tf = (JTextField) editorComp; tf.setFocusTraversalKeysEnabled(false); + tf.putClientProperty("JTextField.selectAllOnFocus", Boolean.FALSE); tf.addActionListener(e -> executeCommand(tf.getText())); + tf.addFocusListener(new java.awt.event.FocusAdapter() { + @Override + public void focusGained(java.awt.event.FocusEvent e) { + // Force caret to the end and clear selection when focus is gained + SwingUtilities.invokeLater(() -> { + tf.setSelectionStart(tf.getText().length()); + tf.setSelectionEnd(tf.getText().length()); + tf.setCaretPosition(tf.getText().length()); + }); + } + }); + // Enable standard clipboard operations (Cut, Copy, Paste) even if not focused initially tf.getComponentPopupMenu(); // Ensure it has a menu or at least default actions works @@ -1523,6 +1532,7 @@ public class MainWindow extends JFrame { * Automatically focus command line when user starts typing on a table */ public void addCommandLineRedirect(JTable table) { + if (table == null) return; // Use InputMap/ActionMap for Ctrl+Enter and Ctrl+Shift+Enter as KeyListener might be bypassed by JTable table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK), "copyNameToCmd"); @@ -1563,7 +1573,6 @@ public class MainWindow extends JFrame { private void copyFocusedToCommandLine(boolean fullPath) { FileItem focused = activePanel.getFocusedItem(); if (focused != null && !focused.getName().equals("..")) { - String current = commandLine.getEditor().getItem().toString(); String toAdd = fullPath ? focused.getFile().getAbsolutePath() : focused.getName(); // If it contains spaces, wrap in quotes @@ -1571,11 +1580,15 @@ public class MainWindow extends JFrame { toAdd = "\"" + toAdd + "\""; } + String current = commandLine.getEditor().getItem().toString(); + String newText; if (!current.isEmpty() && !current.endsWith(" ")) { - commandLine.getEditor().setItem(current + " " + toAdd); + newText = current + " " + toAdd; } else { - commandLine.getEditor().setItem(current + toAdd); + newText = current + toAdd; } + + commandLine.getEditor().setItem(newText); commandLine.requestFocusInWindow(); } } @@ -2213,54 +2226,89 @@ public class MainWindow extends JFrame { * Open terminal in the current directory */ private void openTerminal() { + openTerminal(null); + } + + /** + * Open terminal in the current directory, optionally executing a command (like a shell) + */ + /** + * Open terminal in the current directory, optionally executing a command (like a shell) + */ + private void openTerminal(String shellCommand) { File currentDir = activePanel.getCurrentDirectory(); if (currentDir == null) { currentDir = new File(System.getProperty("user.home")); } try { - ProcessBuilder pb = null; - if (MainApp.CURRENT_OS == MainApp.OS.WINDOWS) { - // Windows - open cmd.exe - pb = new ProcessBuilder("cmd.exe", "/c", "start", "cmd.exe"); + // Windows - open cmd.exe or the specific shell + if (shellCommand != null) { + new ProcessBuilder("cmd.exe", "/c", "start", shellCommand).directory(currentDir).start(); + } else { + new ProcessBuilder("cmd.exe", "/c", "start", "cmd.exe").directory(currentDir).start(); + } } else if (MainApp.CURRENT_OS == MainApp.OS.MACOS) { - // macOS - pb = new ProcessBuilder("open", "-a", "Terminal", currentDir.getAbsolutePath()); + // macOS - open Terminal.app + new ProcessBuilder("open", "-a", "Terminal", currentDir.getAbsolutePath()).directory(currentDir).start(); } else { - // Linux and other Unix-like systems - // Try common terminal emulators with working directory arguments - String[] terminals = {"gnome-terminal", "konsole", "xfce4-terminal", "mate-terminal", "xterm"}; + // Linux - try common terminal emulators + String[] terminals = { + "x-terminal-emulator", + "gnome-terminal", + "konsole", + "xfce4-terminal", + "mate-terminal", + "terminator", + "tilix", + "qterminal", + "xterm" + }; + boolean successfullyStarted = false; for (String terminal : terminals) { try { - Process p = Runtime.getRuntime().exec(new String[]{"which", terminal}); - if (p.waitFor() == 0) { - if (terminal.equals("gnome-terminal") || terminal.equals("xfce4-terminal") || terminal.equals("mate-terminal")) { - pb = new ProcessBuilder(terminal, "--working-directory=" + currentDir.getAbsolutePath()); - } else if (terminal.equals("konsole")) { - pb = new ProcessBuilder(terminal, "--workdir", currentDir.getAbsolutePath()); - } else { - pb = new ProcessBuilder(terminal); + List 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()); + if (shellCommand != null) { + args.add("--"); + args.add(shellCommand); + args.add("-i"); + } + } else if (terminal.equals("konsole") || terminal.equals("qterminal")) { + args.add("--workdir"); + args.add(currentDir.getAbsolutePath()); + if (shellCommand != null) { + args.add("-e"); + args.add(shellCommand); + args.add("-i"); + } + } else { + if (shellCommand != null) { + args.add("-e"); + args.add(shellCommand); + args.add("-i"); } - break; } - } catch (Exception e) { - // Try next terminal + + new ProcessBuilder(args).directory(currentDir).start(); + successfullyStarted = true; + break; + } catch (IOException e) { + // try next } } - if (pb == null) { - // Fallback to xterm - pb = new ProcessBuilder("xterm"); + if (!successfullyStarted) { + throw new Exception("Could not start any terminal emulator."); } } - - if (pb != null) { - pb.directory(currentDir); - pb.start(); - } - } catch (Exception e) { JOptionPane.showMessageDialog(this, "Error opening terminal: " + e.getMessage(), @@ -2307,6 +2355,9 @@ public class MainWindow extends JFrame { } } } + } else if (trimmed.equalsIgnoreCase("bash") || trimmed.equalsIgnoreCase("sh")) { + // Special handling for bash/sh to open a terminal with that shell + openTerminal(trimmed.toLowerCase()); } else { // Execute natively for other commands executeNative(trimmed, null); diff --git a/src/main/resources/icon.ico b/src/main/resources/icon.ico index 054eb9e..9608b73 100644 Binary files a/src/main/resources/icon.ico and b/src/main/resources/icon.ico differ