From 5e05691227e3e784531c1835a5362d1d23995a73 Mon Sep 17 00:00:00 2001
From: taynpg <taynpg@163.com>
Date: Tue, 25 Feb 2025 16:39:35 +0800
Subject: [PATCH] =?UTF-8?q?add=EF=BC=9A=E6=B7=BB=E5=8A=A0~=E4=BB=A3?=
 =?UTF-8?q?=E8=A1=A8=E7=94=A8=E6=88=B7=E5=AE=B6=E7=9B=AE=E5=BD=95=E5=8A=9F?=
 =?UTF-8?q?=E8=83=BD=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .vscode/settings.json |  3 ++-
 filecomplete.cpp      | 55 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 0f85196..da4cb4f 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -109,6 +109,7 @@
         "sstream": "cpp",
         "stop_token": "cpp",
         "thread": "cpp",
-        "regex": "cpp"
+        "regex": "cpp",
+        "csignal": "cpp"
     }
 }
\ No newline at end of file
diff --git a/filecomplete.cpp b/filecomplete.cpp
index 65630c1..7a280b0 100644
--- a/filecomplete.cpp
+++ b/filecomplete.cpp
@@ -112,6 +112,7 @@ static std::string str_predict;
 static std::map<std::string, std::vector<std::string>> path_cache;
 static std::vector<std::string> history;
 static size_t his_pos{};
+static std::string home_path{};
 
 // 获取终端屏幕的行数和列数
 // bool get_terminal_size(int& rows, int& cols)
@@ -135,6 +136,38 @@ static size_t his_pos{};
 // #endif
 // }
 
+std::string get_home()
+{
+#if defined(_WIN32)
+    char* value = nullptr;
+    std::size_t len = 0;
+// _dupenv_s() 在 Visual Studio 2008 的 CRT (msvcr90) 中引入的,似乎没有进入系统 CRT (msvcrt)。
+// mingw-w64 GCC 通常默认只链接到系统 CRT,所以找不到这个符号。
+#if defined(MINGW32) || defined(MINGW64)
+    char* homedir = getenv("USERPROFILE");
+    if (homedir) {
+        return std::string(homedir);
+    }
+    return "";
+#else
+    auto err = _dupenv_s(&value, &len, "USERPROFILE");
+    if (err == 0 && value != nullptr) {
+        std::string ret(value);
+        free(value);
+        return ret;
+    } else {
+        return "";
+    }
+#endif
+#else
+    char* homedir = getenv("HOME");
+    if (homedir) {
+        return std::string(homedir);
+    }
+    return "";
+#endif
+}
+
 void append_his(const std::string& his)
 {
     history.push_back(his);
@@ -173,7 +206,14 @@ std::string next_his()
 void flush_content(const std::string& search_dir, std::vector<std::string>& out)
 {
     out.clear();
-    fs::path work_path(search_dir);
+
+    bool have_rep = false;
+    auto ts = search_dir;
+    if (search_dir.find("~") == 0) {
+        ts = home_path + search_dir.substr(1, search_dir.size() - 1);
+        have_rep = true;
+    }
+    fs::path work_path(ts);
     try {
         if (!fs::exists(work_path)) {
             return;
@@ -181,13 +221,17 @@ void flush_content(const std::string& search_dir, std::vector<std::string>& out)
     } catch (const std::exception& e) {
         return;
     }
-    if (path_cache.count(search_dir)) {
-        out = path_cache[search_dir];
+    if (path_cache.count(ts)) {
+        out = path_cache[ts];
     } else {
         for (const auto& entry : fs::directory_iterator(work_path)) {
-            out.push_back(entry.path().lexically_normal().string());
+            auto fstrin = entry.path().lexically_normal().string();
+            if (have_rep) {
+                fstrin = "~" + fstrin.substr(home_path.size(), fstrin.size() - home_path.size());
+            }
+            out.push_back(fstrin);
         }
-        path_cache[search_dir] = out;
+        path_cache[ts] = out;
     }
 }
 
@@ -546,6 +590,7 @@ char* fc_readline()
         free(tmp_buf);
     });
 
+    home_path = get_home();
     flush_content(".", cur_work_content);
     bool need_predic = true;
     std::chrono::time_point<std::chrono::high_resolution_clock> p1, p2;