diff --git a/.DS_Store b/.DS_Store index 22a716b..41f4662 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/EnhancedTerminal.app/Contents/MacOS/EnhancedTerminal b/EnhancedTerminal.app/Contents/MacOS/EnhancedTerminal index aa9c761..2642a18 100755 Binary files a/EnhancedTerminal.app/Contents/MacOS/EnhancedTerminal and b/EnhancedTerminal.app/Contents/MacOS/EnhancedTerminal differ diff --git a/TerminalSession.swift b/TerminalSession.swift index f58fe57..2afb024 100644 --- a/TerminalSession.swift +++ b/TerminalSession.swift @@ -12,6 +12,9 @@ class TerminalSession: NSObject, NSTextViewDelegate, NSMenuDelegate { var title: String var currentWorkingDirectory: String = "~" private var currentSuggestion: String? + private var historyIndex: Int = -1 + private var historyBuffer: [String] = [] + private var currentInput: String = "" init(title: String = "Terminal") { self.sessionID = UUID() @@ -232,6 +235,80 @@ class TerminalSession: NSObject, NSTextViewDelegate, NSMenuDelegate { return cleaned } + func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool { + // Handle up arrow - previous command in history + if commandSelector == #selector(NSResponder.moveUp(_:)) { + navigateHistory(direction: .previous) + return true + } + + // Handle down arrow - next command in history + if commandSelector == #selector(NSResponder.moveDown(_:)) { + navigateHistory(direction: .next) + return true + } + + return false + } + + private enum HistoryDirection { + case previous, next + } + + private func navigateHistory(direction: HistoryDirection) { + // Load history if not already loaded + if historyBuffer.isEmpty { + historyBuffer = HistoryManager.shared.getRecentCommands(100) + } + + guard !historyBuffer.isEmpty else { return } + + // Save current input if we're starting to navigate + if historyIndex == -1 { + currentInput = getCurrentCommand() + } + + // Navigate history + switch direction { + case .previous: + if historyIndex < historyBuffer.count - 1 { + historyIndex += 1 + } + case .next: + if historyIndex > -1 { + historyIndex -= 1 + } + } + + // Update command line + let newCommand: String + if historyIndex == -1 { + // Back to original input + newCommand = currentInput + } else { + // Show history command + newCommand = historyBuffer[historyIndex] + } + + // Replace current command with history command + replaceCurrentCommand(with: newCommand) + } + + private func replaceCurrentCommand(with newCommand: String) { + let currentLength = textView.string.count + let commandLength = currentLength - promptPosition + + if commandLength > 0 { + let range = NSRange(location: promptPosition, length: commandLength) + textView.textStorage?.replaceCharacters(in: range, with: newCommand) + } else { + textView.insertText(newCommand, replacementRange: NSRange(location: promptPosition, length: 0)) + } + + // Move cursor to end + textView.setSelectedRange(NSRange(location: textView.string.count, length: 0)) + } + func textView(_ textView: NSTextView, shouldChangeTextIn range: NSRange, replacementString: String?) -> Bool { // Don't allow editing before the prompt if range.location < promptPosition { @@ -402,6 +479,11 @@ class TerminalSession: NSObject, NSTextViewDelegate, NSMenuDelegate { let trimmed = command.trimmingCharacters(in: .whitespacesAndNewlines) + // Reset history navigation + historyIndex = -1 + currentInput = "" + historyBuffer = [] // Reload on next navigation + // Check for aliases - match the first word var actualCommand = trimmed let components = trimmed.split(separator: " ", maxSplits: 1)