|
|
@@ -7,6 +7,7 @@
|
|
|
#include <chrono>
|
|
|
#include <string>
|
|
|
#include <sstream>
|
|
|
+#include <algorithm>
|
|
|
|
|
|
// Global debug log
|
|
|
std::ofstream debug_log("lumacs_debug.log");
|
|
|
@@ -44,7 +45,9 @@ public:
|
|
|
|
|
|
// Set initial viewport size (leave room for status and message lines)
|
|
|
int content_height = height_ - 2; // -1 for status, -1 for message
|
|
|
- int content_width = width_ - 6; // -6 for line numbers (3 digits + " | ")
|
|
|
+ bool show_line_numbers = core_->config().get<bool>("show_line_numbers", true);
|
|
|
+ int line_number_width = show_line_numbers ? core_->config().get<int>("line_number_width", 6) : 0;
|
|
|
+ int content_width = width_ - line_number_width;
|
|
|
core_->set_viewport_size(content_width, content_height);
|
|
|
|
|
|
// Then LuaApi, which depends on Core
|
|
|
@@ -107,7 +110,9 @@ public:
|
|
|
height_ = new_height;
|
|
|
width_ = new_width;
|
|
|
int content_height = height_ - 2;
|
|
|
- int content_width = width_ - 6;
|
|
|
+ bool show_line_numbers = core_->config().get<bool>("show_line_numbers", true);
|
|
|
+ int line_number_width = show_line_numbers ? core_->config().get<int>("line_number_width", 6) : 0;
|
|
|
+ int content_width = width_ - line_number_width;
|
|
|
core_->set_viewport_size(content_width, content_height);
|
|
|
debug_log << "Screen resized to: " << width_ << "x" << height_ << std::endl;
|
|
|
debug_log << "Content area: " << content_width << "x" << content_height << std::endl;
|
|
|
@@ -158,6 +163,13 @@ private:
|
|
|
size_t completion_index_ = 0;
|
|
|
std::string completion_prefix_;
|
|
|
|
|
|
+ // Minibuffer history
|
|
|
+ std::vector<std::string> command_history_;
|
|
|
+ std::vector<std::string> buffer_switch_history_;
|
|
|
+ std::vector<std::string> kill_buffer_history_;
|
|
|
+ std::vector<std::string> isearch_history_;
|
|
|
+ size_t history_index_ = 0;
|
|
|
+
|
|
|
// Prefix handling
|
|
|
bool waiting_for_prefix_ = false;
|
|
|
std::string prefix_key_;
|
|
|
@@ -178,14 +190,17 @@ private:
|
|
|
mode_ = Mode::Command;
|
|
|
command_buffer_.clear();
|
|
|
reset_completion();
|
|
|
+ reset_history_navigation();
|
|
|
} else if (event == EditorEvent::BufferSwitchMode) {
|
|
|
mode_ = Mode::BufferSwitch;
|
|
|
command_buffer_.clear();
|
|
|
reset_completion();
|
|
|
+ reset_history_navigation();
|
|
|
} else if (event == EditorEvent::KillBufferMode) {
|
|
|
mode_ = Mode::KillBuffer;
|
|
|
command_buffer_.clear();
|
|
|
reset_completion();
|
|
|
+ reset_history_navigation();
|
|
|
} else if (event == EditorEvent::ISearchMode) {
|
|
|
mode_ = Mode::ISearch;
|
|
|
isearch_query_.clear();
|
|
|
@@ -273,6 +288,64 @@ private:
|
|
|
}
|
|
|
|
|
|
// Helper to filter candidates based on prefix
|
|
|
+ // History management
|
|
|
+ std::vector<std::string>& get_current_history() {
|
|
|
+ switch (mode_) {
|
|
|
+ case Mode::Command: return command_history_;
|
|
|
+ case Mode::BufferSwitch: return buffer_switch_history_;
|
|
|
+ case Mode::KillBuffer: return kill_buffer_history_;
|
|
|
+ case Mode::ISearch: return isearch_history_;
|
|
|
+ default: return command_history_;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void add_to_history(const std::string& entry) {
|
|
|
+ if (entry.empty()) return;
|
|
|
+
|
|
|
+ auto& history = get_current_history();
|
|
|
+
|
|
|
+ // Remove if already exists (move to front)
|
|
|
+ auto it = std::find(history.begin(), history.end(), entry);
|
|
|
+ if (it != history.end()) {
|
|
|
+ history.erase(it);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Add to front
|
|
|
+ history.insert(history.begin(), entry);
|
|
|
+
|
|
|
+ // Limit history size
|
|
|
+ const size_t MAX_HISTORY = 100;
|
|
|
+ if (history.size() > MAX_HISTORY) {
|
|
|
+ history.resize(MAX_HISTORY);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void previous_history() {
|
|
|
+ auto& history = get_current_history();
|
|
|
+ if (history.empty()) return;
|
|
|
+
|
|
|
+ if (history_index_ < history.size()) {
|
|
|
+ command_buffer_ = history[history_index_];
|
|
|
+ history_index_++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void next_history() {
|
|
|
+ auto& history = get_current_history();
|
|
|
+ if (history.empty() || history_index_ == 0) return;
|
|
|
+
|
|
|
+ history_index_--;
|
|
|
+ if (history_index_ == 0) {
|
|
|
+ command_buffer_ = "";
|
|
|
+ } else {
|
|
|
+ command_buffer_ = history[history_index_ - 1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void reset_history_navigation() {
|
|
|
+ history_index_ = 0;
|
|
|
+ }
|
|
|
+
|
|
|
void update_completion_candidates(const std::string& prefix) {
|
|
|
auto all_buffers = core_->get_buffer_names();
|
|
|
completion_candidates_.clear();
|
|
|
@@ -448,6 +521,9 @@ private:
|
|
|
|
|
|
// Return - execute
|
|
|
if (ch == '\n' || ch == '\r') {
|
|
|
+ // Add to history before execution
|
|
|
+ add_to_history(command_buffer_);
|
|
|
+
|
|
|
if (mode_ == Mode::Command) {
|
|
|
execute_command(command_buffer_);
|
|
|
} else if (mode_ == Mode::FindFile) {
|
|
|
@@ -482,6 +558,21 @@ private:
|
|
|
mode_ = Mode::Normal;
|
|
|
command_buffer_.clear();
|
|
|
reset_completion();
|
|
|
+ reset_history_navigation();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // M-p (Alt+p) - Previous history
|
|
|
+ if (ch == '\x90') { // Meta+p
|
|
|
+ previous_history();
|
|
|
+ reset_completion();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // M-n (Alt+n) - Next history
|
|
|
+ if (ch == '\x8E') { // Meta+n
|
|
|
+ next_history();
|
|
|
+ reset_completion();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -490,6 +581,7 @@ private:
|
|
|
if (!command_buffer_.empty()) {
|
|
|
command_buffer_.pop_back();
|
|
|
reset_completion(); // Reset completion on edit
|
|
|
+ reset_history_navigation(); // Reset history on edit
|
|
|
} else {
|
|
|
mode_ = Mode::Normal;
|
|
|
}
|
|
|
@@ -816,8 +908,11 @@ private:
|
|
|
void render_window(std::shared_ptr<Window> window, int x, int y, int width, int height) {
|
|
|
if (!window) return;
|
|
|
|
|
|
+ // Check configuration for line numbers
|
|
|
+ bool show_line_numbers = core_->config().get<bool>("show_line_numbers", true);
|
|
|
+ int line_number_width = show_line_numbers ? core_->config().get<int>("line_number_width", 6) : 0;
|
|
|
+
|
|
|
// Update window viewport size
|
|
|
- int line_number_width = 6; // "999 │ "
|
|
|
int content_width = width - line_number_width;
|
|
|
window->set_viewport_size(content_width, height);
|
|
|
|
|
|
@@ -841,8 +936,10 @@ private:
|
|
|
move(y + screen_y, x);
|
|
|
for (int i = 0; i < width; ++i) addch(' ');
|
|
|
|
|
|
- // Line number
|
|
|
- mvprintw(y + screen_y, x, "%3zu │ ", buffer_line_idx + 1);
|
|
|
+ // Line number (if enabled)
|
|
|
+ if (show_line_numbers) {
|
|
|
+ mvprintw(y + screen_y, x, "%3zu │ ", buffer_line_idx + 1);
|
|
|
+ }
|
|
|
|
|
|
// Line content with syntax highlighting
|
|
|
if (!line_text.empty()) {
|