#include "Noncanonical.h" using namespace std; // 全局终端设置 terminal_mode_t original_termios; std::vector cmdList{}; // 支持的命令列表 const vector commands = {"setant", "seteph", "query","list", "exit", "help"}; void restore_terminal() { #if defined(_WIN32) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), original_termios); #else tcsetattr(STDIN_FILENO, TCSANOW, &original_termios); #endif } void set_noncanonical_mode() { #if defined(_WIN32) HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hStdin, &original_termios); DWORD new_mode = original_termios; new_mode &= ~ENABLE_ECHO_INPUT; // 禁用回显 new_mode &= ~ENABLE_LINE_INPUT; // 禁用行缓冲 new_mode &= ~ENABLE_PROCESSED_INPUT; // 禁用Ctrl+C处理 SetConsoleMode(hStdin, new_mode); #else struct termios new_termios; tcgetattr(STDIN_FILENO, &original_termios); new_termios = original_termios; new_termios.c_lflag &= ~(ICANON | ECHO | ISIG); new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSANOW, &new_termios); #endif atexit(restore_terminal); } string toLower(const string &str) { string result; for (char c : str) { result += tolower(c); } return result; } string tabCompletion(const string ¤tLine, size_t cursorPos) { // 分割当前行 vector tokens; string token; for (char c: currentLine) { if (isspace(c)) { if (!token.empty()) { tokens.push_back(token); token.clear(); } } else { token += c; } } if (!token.empty()) tokens.push_back(token); // 如果没有token或当前token为空 if (tokens.empty() || token.empty()) return currentLine; bool isFirstToken = (tokens.size() == 1); string lastToken = tokens.back(); // 候选列表 vector candidates; // 第一个token:匹配命令 if (isFirstToken) { for (const string &cmd: commands) { if (cmd.substr(0, lastToken.size()) == lastToken) { candidates.push_back(cmd); } } } // // 第二个token:匹配键 // else if (tokens.size() == 2) { // for (const auto &kv: kvStore) { // if (kv.first.substr(0, lastToken.size()) == lastToken) { // candidates.push_back(kv.first); // } // } // } // 没有候选结果 if (candidates.empty()) { // cout << "\n> " << currentLine << std::flush; return currentLine; } // 唯一候选结果 - 直接补全 if (candidates.size() == 1) { // 计算要删除的字符数 size_t charsToErase = lastToken.size(); // 创建新行 string newLine = currentLine.substr(0, currentLine.size() - charsToErase); newLine += candidates[0]; if (isFirstToken) newLine += " "; return newLine; } // 多个候选结果 - 打印选项 cout << "\nPossible completions:\n"; for (const auto &cand: candidates) { cout << " " << cand << "\n"; } cout << "> " << currentLine << std::flush; return currentLine; } string readLine(const string &prompt) { cout << prompt << flush; string line; static int historyIndex = -1; // 当前历史命令索引 static string tempLine = ""; // 临时保存当前编辑行 #if defined(_WIN32) while (true) { int ch = _getch(); // Windows专用字符读取 // 处理特殊键 if (ch == 0x00 || ch == 0xE0) { int ext = _getch(); // 获取扩展按键 // 上方向键 if (ext == 72) { if (!cmdList.empty()) { // 保存当前编辑行 if (historyIndex == -1) tempLine = line; // 更新历史索引 if (historyIndex < cmdList.size() - 1) historyIndex++; else if (historyIndex == -1) historyIndex = 0; //清除 cout << "\r" << prompt << string(line.size(), ' ') << flush; // 更新当前行 line = cmdList[cmdList.size() - 1 - historyIndex]; //重绘 cout << "\r" << prompt << line << flush; } continue; } // 下方向键 else if (ext == 80) { if (historyIndex != -1) { //清除 cout << "\r" << prompt << string(line.size(), ' ') << flush; if (historyIndex > 0) { historyIndex--; line = cmdList[cmdList.size() - 1 - historyIndex]; } else { historyIndex = -1; line = tempLine; } //重绘 cout << "\r" << prompt << line << flush; } continue; } } switch (ch) { case '\r': // Enter键 cout << endl; return line; case '\t': // Tab键 line = tabCompletion(line, line.size()); cout << "\r" << prompt << string(line.size(), ' ') << flush; cout << "\r" << prompt << line << flush; break; case 8: // Backspace键 if (!line.empty()) { line.pop_back(); cout << "\b \b" << flush; } break; case 3: // Ctrl+C cout << endl; exit(0); break; default: // 可打印字符 if (isprint(ch)) { line += ch; cout << static_cast(ch) << flush; } } } #else char ch; while (read(STDIN_FILENO, &ch, 1) == 1) { // 处理方向键序列 (ESC [ A 或 ESC [ B) if (ch == 27) { // ESC char seq[2]; if (read(STDIN_FILENO, seq, 2) == 2) { // 上方向键 if (seq[0] == '[' && seq[1] == 'A') { if (!cmdList.empty()) { // 保存当前编辑行 if (historyIndex == -1) tempLine = line; // 更新历史索引 if (historyIndex < cmdList.size() - 1) historyIndex++; else if (historyIndex == -1) historyIndex = 0; for (size_t i = 0; i < line.size(); i++) cout << "\b \b"; // 更新当前行 line = cmdList[cmdList.size() - 1 - historyIndex]; // 清除并重绘 cout << line << flush; } continue; } // 下方向键 else if (seq[0] == '[' && seq[1] == 'B') { if (historyIndex != -1) { for (size_t i = 0; i < line.size(); i++) cout << "\b \b"; if (historyIndex > 0) { historyIndex--; line = cmdList[cmdList .size() - 1 - historyIndex]; } else { historyIndex = -1; line = tempLine; } // 清除并重绘 cout << line << flush; } continue; } } } // Enter键 - 完成输入 if (ch == '\n') { cout << endl; return line; } // Tab键 - 触发补全 if (ch == '\t') { string newLine = tabCompletion(line, line.size()); if (newLine != line) { // 清除当前行 for (size_t i = 0; i < line.size(); i++) { cout << "\b \b"; } line = newLine; cout << line << flush; } continue; } // Backspace键 - 删除字符(支持不同终端的两种编码) if (ch == 127 || ch == 8) { if (!line.empty()) { line.pop_back(); // 清除字符:\b 移动光标,空格覆盖字符,再\b移动光标 cout << "\b \b" << flush; } continue; } // Ctrl+C - 退出程序 if (ch == 3) { cout << endl; exit(0); } // 其他可打印字符 if (isprint(ch)) { line += ch; cout << ch << flush; } } #endif return line; }