diff --git a/filecomplete.cpp b/filecomplete.cpp index 3274e10..85169cc 100644 --- a/filecomplete.cpp +++ b/filecomplete.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include @@ -89,6 +91,7 @@ static std::vector word{}; static size_t wo{}; static size_t len{}; static char* main_buf{}; +static std::mutex mut; void trans2buf(char* buffer); void clear_line(); @@ -104,6 +107,28 @@ static std::map> path_cache; static std::vector history; static size_t his_pos{}; +// 获取终端屏幕的行数和列数 +// bool get_terminal_size(int& rows, int& cols) +// { +// #ifdef _WIN32 +// #else +// FILE* pipe = popen("stty size", "r"); // 执行 stty size 命令 +// if (!pipe) { +// return false; +// } +// char buffer[128]; +// if (fgets(buffer, sizeof(buffer), pipe) != nullptr) { +// // 解析输出,格式为 "行数 列数" +// if (sscanf(buffer, "%d %d", &rows, &cols) == 2) { +// pclose(pipe); +// return true; +// } +// } +// pclose(pipe); +// return false; +// #endif +// } + void append_his(const std::string& his) { history.push_back(his); @@ -357,6 +382,7 @@ void clear_line() void set_cursor_x(short x) { + lock_print(); #if defined(OS_WINDOWS) HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); if (h_console == NULL) { @@ -380,6 +406,7 @@ void set_cursor_x(short x) #elif defined(OS_UNIX) printf("\033[%d;%dH", get_cursor_y(), x); #endif + unlock_print(); } short get_cursor_y() @@ -435,25 +462,23 @@ short get_cursor_y() buf[i] = ch; } - i -= 2; - while (buf[i] != ';') { - i -= 1; - } - - i -= 1; - while (buf[i] != '[') { - y = y + (buf[i] - '0') * pow; - pow *= 10; - i -= 1; - } - // Reset attributes if (tcsetattr(0, TCSANOW, &new_attr) == -1) { fprintf(stderr, "[ERROR] Couldn't reset terminal attributes\n"); exit(1); } - return (short)y; + std::regex rg("\033\\[(\\d*);(\\d+)R"); + std::smatch match; + std::string input(buf); + + // 使用正则表达式匹配输入 + int mx{}, my{}; + if (std::regex_search(input, match, rg)) { + mx = match[1].str().empty() ? 1 : std::stoi(match[1].str()); // 行号,默认为 1 + my = std::stoi(match[2].str()); // 列号 + } + return mx; #endif } @@ -501,14 +526,7 @@ char* fc_readline() std::chrono::time_point p1, p2; p1 = std::chrono::high_resolution_clock::now(); -#if defined(OS_WINDOWS) - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_CURSOR_INFO cursorInfo; - GetConsoleCursorInfo(hConsole, &cursorInfo); - cursorInfo.bVisible = TRUE; - SetConsoleCursorInfo(hConsole, &cursorInfo); -#endif - + enable_cur(); auto refresh_show = [&]() { word.clear(); clear_line(); @@ -531,19 +549,13 @@ char* fc_readline() cur_pos += 1; } } -#endif -#if defined(OS_UNIX) - fflush(stdout); #endif set_cursor_x(cur_pos + 1); -#if defined(OS_UNIX) - fflush(stdout); -#endif }; while (1) { - refresh_show(); + refresh_show(); need_predic = true; // Read character from console @@ -559,13 +571,7 @@ char* fc_readline() switch (ch) { case ENTER: -#if defined(OS_WINDOWS) - hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_CURSOR_INFO cursorInfo; - GetConsoleCursorInfo(hConsole, &cursorInfo); - cursorInfo.bVisible = FALSE; - SetConsoleCursorInfo(hConsole, &cursorInfo); -#endif + disable_cur(); // 这里还需要清除预测显示 str_predict.clear(); refresh_show(); @@ -676,6 +682,50 @@ char* fc_readline() return main_buf; } +void enable_cur() +{ +#if defined(OS_WINDOWS) + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == NULL) { + fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); + exit(1); + } + CONSOLE_CURSOR_INFO cursorInfo; + GetConsoleCursorInfo(hConsole, &cursorInfo); + cursorInfo.bVisible = TRUE; + SetConsoleCursorInfo(hConsole, &cursorInfo); +#else + printf("\033[?25h"); +#endif +} + +void disable_cur() +{ +#if defined(OS_WINDOWS) + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == NULL) { + fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); + exit(1); + } + CONSOLE_CURSOR_INFO cursorInfo; + GetConsoleCursorInfo(hConsole, &cursorInfo); + cursorInfo.bVisible = FALSE; + SetConsoleCursorInfo(hConsole, &cursorInfo); +#else + printf("\033[?25l"); +#endif +} + +void lock_print() +{ + mut.lock(); +} + +void unlock_print() +{ + mut.unlock(); +} + void fc_free(char* str) { buf.clear(); @@ -697,6 +747,7 @@ void trans2buf(char* buffer) void color_print(const char* text, const COLOR_TYPE color) { + lock_print(); #if defined(OS_WINDOWS) HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); if (h_console == NULL) { @@ -755,4 +806,5 @@ void color_print(const char* text, const COLOR_TYPE color) // Resets the text to default color printf("\033[0m"); #endif + unlock_print(); } diff --git a/filecomplete.h b/filecomplete.h index ddc4c4a..d4f0f95 100644 --- a/filecomplete.h +++ b/filecomplete.h @@ -14,16 +14,18 @@ ******************************************************/ void fc_append(char deadline_ch); -/***************************************************** - 读取用户输入,替代 std::getline - - 如果返回值为 nullptr,表示用户输入了终止命令(ctrl-c)。 -******************************************************/ +// 读取用户输入,替代 std::getline 如果返回值为 nullptr,表示用户输入了终止命令(ctrl-c)。 char* fc_readline(); -/***************************************************** - 用于释放 fc_readline() 返回的 buffer 堆内存。 -******************************************************/ +// 光标禁用与启用 +void enable_cur(); +void disable_cur(); + +// 保证打印的顺序,三方打印需要等待内部打印结束才能打印,故有此锁。 +void lock_print(); +void unlock_print(); + +// 用于释放 fc_readline() 返回的 buffer 堆内存。 void fc_free(char* str); #endif \ No newline at end of file