Files
CpCtrl/Noncanonical/Noncanonical.cpp

310 lines
8.1 KiB
C++
Raw Permalink Normal View History

2025-06-12 15:28:37 +08:00
#include "Noncanonical.h"
using namespace std;
// 全局终端设置
terminal_mode_t original_termios;
std::vector<std::string> cmdList{};
// 支持的命令列表
const vector<string> 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 &currentLine, size_t cursorPos) {
// 分割当前行
vector<string> 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<string> 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<char>(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;
}