From 65c8996136f69ba4373465dfd9dcdb7908959ce0 Mon Sep 17 00:00:00 2001
From: taynpg <taynpg@163.com>
Date: Tue, 11 Feb 2025 10:53:32 +0800
Subject: [PATCH] =?UTF-8?q?add=EF=BC=9A=E6=B7=BB=E5=8A=A0=E4=B8=80?=
 =?UTF-8?q?=E4=B8=AA=E5=89=8D=E7=BC=80=E6=8F=90=E7=A4=BA=E7=AC=A6=E6=98=BE?=
 =?UTF-8?q?=E7=A4=BA=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .vscode/settings.json |  3 +-
 filecomplete.cpp      | 76 +++++++++++++++++++++++---------------
 filecomplete.h        | 86 ++++++++++++++++++++++++++++++++-----------
 main.cpp              |  7 +++-
 4 files changed, 118 insertions(+), 54 deletions(-)

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8239b74..0f85196 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -108,6 +108,7 @@
         "optional": "cpp",
         "sstream": "cpp",
         "stop_token": "cpp",
-        "thread": "cpp"
+        "thread": "cpp",
+        "regex": "cpp"
     }
 }
\ No newline at end of file
diff --git a/filecomplete.cpp b/filecomplete.cpp
index e4cfcf6..601f2e9 100644
--- a/filecomplete.cpp
+++ b/filecomplete.cpp
@@ -59,7 +59,7 @@ namespace fs = std::filesystem;
 #define SPECIAL_SEQ_1 0
 #define SPECIAL_SEQ_2 224
 #define COLOR_TYPE uint16_t
-#define DEFAULT_TITLE_COLOR 160
+#define DEFAULT_TITLE_COLOR 10
 #define DEFAULT_PREDICT_COLOR 8
 #define DEFAULT_MAIN_COLOR 7
 #elif defined(OS_UNIX)
@@ -92,6 +92,8 @@ static size_t wo{};
 static size_t len{};
 static char* main_buf{};
 static std::mutex mut;
+static std::string header{};
+static size_t header_len{};
 
 void trans2buf(char* buffer);
 void clear_line();
@@ -99,6 +101,7 @@ void set_cursor_x(short x);
 short get_cursor_y();
 char* fc_readline();
 void color_print(const char* text, const COLOR_TYPE color);
+void add_newer(const std::vector<char>& wch);
 
 static std::vector<std::string> cur_work_content;
 static std::vector<char> deadline_vch;
@@ -382,7 +385,7 @@ void clear_line()
 
 void set_cursor_x(short x)
 {
-    lock_print();
+    fc_lock_print();
 #if defined(OS_WINDOWS)
     HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE);
     if (h_console == NULL) {
@@ -406,7 +409,7 @@ void set_cursor_x(short x)
 #elif defined(OS_UNIX)
     printf("\033[%d;%dH", get_cursor_y(), x);
 #endif
-    unlock_print();
+    fc_unlock_print();
 }
 
 short get_cursor_y()
@@ -487,6 +490,36 @@ void fc_append(char deadline_ch)
     deadline_vch.push_back(deadline_ch);
 }
 
+void add_newer(const std::vector<char>& wch)
+{
+    if (wo < buf.size()) {
+        if (len >= buf.size()) {
+            buf.resize(buf.size() * 2);
+        }
+        if (len > 0) {
+            for (size_t i = len - 1; i >= wo; --i) {
+                buf[i + 1] = buf[i];
+            }
+        }
+        buf[wo] = wch;
+    } else {
+        buf.push_back(wch);
+    }
+    ++wo;
+    ++len;
+};
+
+void fc_set_header(const char* h)
+{
+    header.clear();
+    header.append(h);
+    header_len = 0;
+    auto v = str_to_vec(header);
+    for (const auto& item : v) {
+        header_len += item.size();
+    }
+}
+
 char* fc_readline()
 {
     main_buf = (char*)malloc(sizeof(char) * buf_size);
@@ -504,33 +537,16 @@ char* fc_readline()
     });
 
     flush_content(".", cur_work_content);
-    auto add_newer = [&](const std::vector<char>& wch) {
-        if (wo < buf.size()) {
-            if (len >= buf.size()) {
-                buf.resize(buf.size() * 2);
-            }
-            if (len > 0) {
-                for (size_t i = len - 1; i >= wo; --i) {
-                    buf[i + 1] = buf[i];
-                }
-            }
-            buf[wo] = wch;
-        } else {
-            buf.push_back(wch);
-        }
-        ++wo;
-        ++len;
-    };
-
     bool need_predic = true;
     std::chrono::time_point<std::chrono::high_resolution_clock> p1, p2;
     p1 = std::chrono::high_resolution_clock::now();
 
-    enable_cur();
+    fc_enable_cur();
     auto refresh_show = [&]() {
         word.clear();
         clear_line();
         // Print current buffer
+        color_print(header.c_str(), DEFAULT_TITLE_COLOR);
         color_print(nullptr, DEFAULT_MAIN_COLOR);
         if (!str_predict.empty()) {
             color_print(str_predict.data(), DEFAULT_PREDICT_COLOR);
@@ -550,7 +566,7 @@ char* fc_readline()
             }
         }
 #endif
-        set_cursor_x(cur_pos + 1);
+        set_cursor_x(cur_pos + 1 + header_len);
     };
 
     while (1) {
@@ -571,7 +587,7 @@ char* fc_readline()
 
         switch (ch) {
         case ENTER:
-            disable_cur();
+            fc_disable_cur();
             // 这里还需要清除预测显示
             str_predict.clear();
             refresh_show();
@@ -682,7 +698,7 @@ char* fc_readline()
     return main_buf;
 }
 
-void enable_cur()
+void fc_enable_cur()
 {
 #if defined(OS_WINDOWS)
     auto hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -699,7 +715,7 @@ void enable_cur()
 #endif
 }
 
-void disable_cur()
+void fc_disable_cur()
 {
 #if defined(OS_WINDOWS)
     auto hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -716,12 +732,12 @@ void disable_cur()
 #endif
 }
 
-void lock_print()
+void fc_lock_print()
 {
     mut.lock();
 }
 
-void unlock_print()
+void fc_unlock_print()
 {
     mut.unlock();
 }
@@ -747,7 +763,7 @@ void trans2buf(char* buffer)
 
 void color_print(const char* text, const COLOR_TYPE color)
 {
-    lock_print();
+    fc_lock_print();
 #if defined(OS_WINDOWS)
     HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE);
     if (h_console == NULL) {
@@ -806,5 +822,5 @@ void color_print(const char* text, const COLOR_TYPE color)
     // Resets the text to default color
     printf("\033[0m");
 #endif
-    unlock_print();
+    fc_unlock_print();
 }
diff --git a/filecomplete.h b/filecomplete.h
index d4f0f95..43f9ba8 100644
--- a/filecomplete.h
+++ b/filecomplete.h
@@ -1,31 +1,75 @@
 #ifndef FILE_COMPLETE_H
 #define FILE_COMPLETE_H
 
-/* ***************************************************
-    如果编译的结果的【执行】环境为GBK, 请手动定义宏
-            BINARY_GBK
-    否则默认是 UTF-8 编码。
-******************************************************
-    添加截止符号,提示路径时,以此截断,比如当前输入为:
-            GetFile someparm|tesa_fil_
-    如果设置了截止符号|, 提示时将认为 tesa_fil 是某个
-    文件的名称开头,否则认为 someparm|tesa_fil 是文件
-    名称的开头
-******************************************************/
+/**
+ * @file file_complete.h
+ * @brief 控制台读取用户输入时,文件自动补全功能
+ *
+ * 编码说明:
+ * - 如果程序运行环境使用 GBK 编码,请手动定义宏 `BINARY_GBK`。
+ * - 默认编码为 UTF-8。
+ *
+ * 功能说明:
+ * - 支持添加截止符号以确定路径补全范围。
+ * - 提供替代 `std::getline` 的用户输入读取函数。
+ * - 提供控制台光标控制与线程安全打印机制。
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief 设置路径补全的截止符号。
+ *
+ * @param deadline_ch 截止符号(例如 '|')。
+ */
 void fc_append(char deadline_ch);
 
-// 读取用户输入,替代 std::getline 如果返回值为 nullptr,表示用户输入了终止命令(ctrl-c)。
-char* fc_readline();
+/**
+ * @brief 设置补全提示的前缀显示内容。
+ *
+ * @param header 要显示的前缀字符串。
+ */
+void fc_set_header(const char* h);
 
-// 光标禁用与启用
-void enable_cur();
-void disable_cur();
+/**
+ * @brief 读取用户输入,替代 `std::getline`。
+ *
+ * @return 成功返回堆分配的字符串,需使用 `fc_free` 释放;
+ *         如果返回 `NULL`,表示检测到终止命令(如 Ctrl+C)。
+ */
+char* fc_readline(void);
 
-// 保证打印的顺序,三方打印需要等待内部打印结束才能打印,故有此锁。
-void lock_print();
-void unlock_print();
+/**
+ * @brief 启用控制台光标显示。
+ */
+void fc_enable_cur(void);
 
-// 用于释放 fc_readline() 返回的 buffer 堆内存。
+/**
+ * @brief 禁用控制台光标显示。
+ */
+void fc_disable_cur(void);
+
+/**
+ * @brief 锁定打印,确保多线程环境下的打印顺序一致。
+ */
+void fc_lock_print(void);
+
+/**
+ * @brief 解锁打印,允许其他线程继续输出。
+ */
+void fc_unlock_print(void);
+
+/**
+ * @brief 释放 `fc_readline` 返回的字符串内存。
+ *
+ * @param str 需要释放的字符串指针。
+ */
 void fc_free(char* str);
 
-#endif
\ No newline at end of file
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FILE_COMPLETE_H */
diff --git a/main.cpp b/main.cpp
index a6b1781..fc34d68 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,16 +19,19 @@ int main(int argc, char** argv)
     std::cout << "PreContent1 " << std::endl;
     std::cout << "PreContent2 " << std::endl;
     fc_append('|');
-    std::thread t(delay_auto_show);
+    fc_set_header("测试$:");
+    // std::thread t(delay_auto_show);
 
     while (1) {
         char* content = fc_readline();
         if (content) {
+            std::string cmd_input(content);
             fc_free(content);
             std::cout << "" << std::endl;
+            std::cout << cmd_input << std::endl;
         }
     }
 
-    t.join();
+    // t.join();
     return 0;
 }