From bfdf34d02eb2bd0dbfc5b741d754ce55c1904c51 Mon Sep 17 00:00:00 2001 From: taynpg Date: Wed, 8 Jan 2025 20:35:08 +0800 Subject: [PATCH] =?UTF-8?q?update=EF=BC=9A=E5=88=9D=E6=AD=A5=E8=83=BD?= =?UTF-8?q?=E8=BE=93=E5=85=A5(=E5=8C=85=E5=90=ABGBK=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E8=BE=93=E5=85=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-format | 17 ++ .gitignore | 13 +- .vscode/settings.json | 29 ++- CMakeLists.txt | 26 +++ README.md | 5 - filecomplete.cpp | 400 ++++++++++++++++++++++++++++++++++++++++++ filecomplete.h | 3 + main.cpp | 14 ++ src/filecomplete.cpp | 238 ------------------------- src/filecomplete.h | 6 - src/main.cpp | 6 - xmake.lua | 10 -- 12 files changed, 489 insertions(+), 278 deletions(-) create mode 100644 .clang-format create mode 100644 CMakeLists.txt delete mode 100644 README.md create mode 100644 filecomplete.cpp create mode 100644 filecomplete.h create mode 100644 main.cpp delete mode 100644 src/filecomplete.cpp delete mode 100644 src/filecomplete.h delete mode 100644 src/main.cpp delete mode 100644 xmake.lua diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..402f22e --- /dev/null +++ b/.clang-format @@ -0,0 +1,17 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +PointerAlignment: Left +AccessModifierOffset: -4 +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true + AfterClass: true +Cpp11BracedListStyle: true +ReflowComments: true +SpacesBeforeTrailingComments: 3 +TabWidth: 4 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ColumnLimit: 80 +AllowShortBlocksOnASingleLine: Never +AllowShortFunctionsOnASingleLine: None +AllowShortEnumsOnASingleLine: false diff --git a/.gitignore b/.gitignore index de3a27d..f940a2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ -# Xmake cache -.xmake/ -build/ - -# MacOS Cache -.DS_Store -compile_commands.json - +build +.vs +.cache +cmake-* +out \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 21c6db6..5069fe4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,16 +3,35 @@ "editor.fontSize": 14, "editor.fontFamily": "'Source Code Pro', 'Courier New', monospace", "terminal.integrated.fontFamily": "Source Code Pro", - "editor.fontLigatures": true, - "C_Cpp.default.configurationProvider": "tboox.xmake-vscode", - "cmake.configureOnOpen": false, + "cmake.configureOnOpen": true, + "cmake.debugConfig": { + "console": "integratedTerminal", + "setupCommands": [ + { + "description": "-gdb-set charset utf-8", + "text": "-gdb-set charset UTF-8" + }, + { + "description": "Enable gdb pretty-printing", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "args": [ + ] + }, + // "cmake.configureSettings": { + // "CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + // }, + "cmake.options.statusBarVisibility": "visible", + "cmake.generator": "Ninja", "C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json", "C_Cpp.default.cppStandard": "c++17", + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", "editor.inlayHints.enabled": "off", "editor.unicodeHighlight.allowedLocales": { "ja": true, "zh-hant": true, "zh-hans": true - }, - "makefile.configureOnOpen": false + } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4c8c146 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.16) + +project(filecomplete LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (MSVC) + add_compile_options(/source-charset:utf-8) +endif() + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") + MESSAGE(STATUS "Add MinGW Param.") + add_compile_options(-finput-charset=utf-8) + add_compile_options(-fexec-charset=gbk) +endif() + +set(CMAKE_DEBUG_POSTFIX "d") +message(STATUS "System: ${CMAKE_SYSTEM_NAME}") +message(STATUS "Compiler CXX ID: ${CMAKE_CXX_COMPILER_ID}") + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/) + +add_library(filecomplete STATIC filecomplete.h filecomplete.cpp) +add_executable(example main.cpp) +target_link_libraries(example PRIVATE filecomplete) \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 904d3cf..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# 简介 - -在控制台程序中,可以补全文件路径。 - -本项目修改自 [https://github.com/DieTime/cli-autocomplete](https://github.com/DieTime/cli-autocomplete) 。 \ No newline at end of file diff --git a/filecomplete.cpp b/filecomplete.cpp new file mode 100644 index 0000000..0d59fa3 --- /dev/null +++ b/filecomplete.cpp @@ -0,0 +1,400 @@ +#include "filecomplete.h" +#include +#include + +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#endif + +#include +#include +#include + +#define MAX_OF(x, y) (((x) > (y)) ? (x) : (y)) + +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN64) +#ifndef OS_WINDOWS +#define OS_WINDOWS + +#include +#include +#include +#endif +#elif defined(__APPLE__) || defined(__unix__) || defined(__unix) || \ + defined(unix) || defined(__linux__) +#ifndef OS_UNIX +#define OS_UNIX + +#include +#include +#include +#endif +#else +#error Unknown environment! +#endif + +#if defined(OS_WINDOWS) +#define ENTER 13 +#define BACKSPACE 8 +#define LEFT 75 +#define RIGHT 77 +#define UP 72 +#define DOWN 80 +#define DEL 83 +#define CTRL_C 3 +#define SPECIAL_SEQ_1 0 +#define SPECIAL_SEQ_2 224 +#define COLOR_TYPE uint16_t +#define DEFAULT_TITLE_COLOR 160 +#define DEFAULT_PREDICT_COLOR 8 +#define DEFAULT_MAIN_COLOR 7 +#elif defined(OS_UNIX) +#define ENTER 10 +#define BACKSPACE 127 +#define LEFT 68 +#define RIGHT 67 +#define UP 65 +#define DOWN 66 +#define DEL 51 +#define DEL_AFTER 126 +#define SPECIAL_SEQ_1 27 +#define SPECIAL_SEQ_2 91 +#define COLOR_TYPE char* +#define DEFAULT_TITLE_COLOR "0;30;102" +#define DEFAULT_PREDICT_COLOR "90" +#define DEFAULT_MAIN_COLOR "0" +#endif +#define SPACE 32 +#define TAB 9 + +static std::vector> g_buff{}; +static std::vector g_wch{}; +static size_t g_woffset{}; +static size_t g_len{}; + +short terminal_width(); +void clear_line(); +void set_cursor_x(short x); +short get_cursor_y(); +char* readline(); +void color_print(char* text, COLOR_TYPE color); + +void supply(std::vector& wch, char ch) +{ + wch.push_back(ch); + if (ch >= 0 && ch < 128) { + return; + } + auto tch = _getch(); + wch.push_back(tch); +} + +short terminal_width() +{ +#if defined(OS_WINDOWS) + // Handle current terminal + HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); + if (h_console == NULL) { + fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); + exit(1); + } + + // Get current attributes + CONSOLE_SCREEN_BUFFER_INFO console_info; + if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) { + fprintf(stderr, "[ERROR] Couldn't get terminal info\n"); + exit(1); + } + + // Return current width + return console_info.dwSize.X; +#elif defined(OS_UNIX) + struct winsize t_size; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &t_size) == -1) { + fprintf(stderr, "[ERROR] Couldn't get terminal info\n"); + exit(1); + } + + return (short)t_size.ws_col; +#endif +} + +void clear_line() +{ +#if defined(OS_WINDOWS) + // Get current terminal width + short width = terminal_width(); + if (width < 1) { + fprintf(stderr, "[ERROR] Size of terminal is too small\n"); + exit(1); + } + + // Create long empty string + char* empty = (char*)malloc(sizeof(char) * width); + if (empty) { + memset(empty, ' ', width); + empty[width - 1] = '\0'; + } + // Clear line + printf("\r%s\r", empty); + + // Free line + free(empty); +#elif defined(OS_UNIX) + printf("\033[2K\r"); +#endif +} + +void set_cursor_x(short x) +{ +#if defined(OS_WINDOWS) + HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); + if (h_console == NULL) { + fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); + exit(1); + } + + // Create position + COORD xy; + xy.X = x - 1; + xy.Y = get_cursor_y(); + + // Set cursor position + if (SetConsoleCursorPosition(h_console, xy) == 0) { + fprintf(stderr, "[ERROR] Couldn't set terminal cursor position\n"); + exit(1); + } +#elif defined(OS_UNIX) + printf("\033[%d;%dH", get_cursor_y(), x); +#endif +} + +short get_cursor_y() +{ +#if defined(OS_WINDOWS) + HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); + if (h_console == NULL) { + fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); + exit(1); + } + + // Get terminal info + CONSOLE_SCREEN_BUFFER_INFO console_info; + if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) { + fprintf(stderr, "[ERROR] Couldn't get terminal Y position\n"); + exit(1); + } + + // Return Y position + return console_info.dwCursorPosition.Y; +#elif defined(OS_UNIX) + struct termios old_attr, new_attr; + char ch, buf[30] = {0}; + int i = 0, pow = 1, y = 0; + + // Backup terminal attributes + if (tcgetattr(STDIN_FILENO, &new_attr) == -1) { + fprintf(stderr, "[ERROR] Couldn't get terminal attributes\n"); + exit(1); + } + + // Disable echo + old_attr = new_attr; + old_attr.c_lflag &= ~(ICANON | ECHO); + if (tcsetattr(STDIN_FILENO, TCSANOW, &old_attr) == -1) { + fprintf(stderr, "[ERROR] Couldn't set terminal attributes\n"); + exit(1); + } + + // Get info about cursor + if (write(STDOUT_FILENO, "\033[6n", 4) != 4) { + fprintf(stderr, "[ERROR] Couldn't get cursor information\n"); + exit(1); + } + + // Get ^[[{this};1R value + + for (ch = 0; ch != 'R'; i++) { + if (read(STDIN_FILENO, &ch, 1) != 1) { + fprintf(stderr, "[ERROR] Couldn't read cursor information"); + exit(1); + } + 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; +#endif +} + +char* readline() +{ + short buff_cap = terminal_width(); + char* buff = (char*)calloc((size_t)buff_cap, sizeof(char)); + if (buff == NULL) { + fprintf(stderr, "[ERROR] Couldn't allocate memory for buffer\n"); + exit(1); + } + + short buff_len = 0; + // Cursor offset in buffer for moving + int offset = 0; + + // Current hint number + int hint_num = 0; + while (1) { + + g_wch.clear(); + clear_line(); + // Print current buffer + color_print(buff, DEFAULT_MAIN_COLOR); + + // Move cursor to buffer end + // short x = (short)(buff_len + 1 - offset); + // set_cursor_x(x); + + // Read character from console + int ch = _getch(); + + switch (ch) { + case ENTER: + return nullptr; +#if defined(OS_WINDWS) + case CTRL_C: { + exit(0); + } +#endif + case BACKSPACE: { + if (g_woffset > 0) { + for (size_t i = g_woffset - 1; i < g_buff.size() - 1; ++i) { + g_buff[i] = g_buff[i + 1]; + } + --g_woffset; + --g_len; + } + break; + } + case TAB: { + break; + } +#if defined(OS_WINDOWS) + case SPECIAL_SEQ_1: + case SPECIAL_SEQ_2: +#elif defined(OS_UNIX) + case SPECIAL_SEQ_1: +#endif + { +#if defined(OS_UNIX) + if (_getch() != SPECIAL_SEQ_2) { + continue; + } +#endif + switch (_getch()) { + case LEFT: + offset = offset < 1 ? 0 : (--offset); + break; + case RIGHT: + offset = offset > g_buff.size() ? g_buff.size() : (++offset); + break; + case UP: + break; + case DOWN: + break; + case DEL: + // Edit buffer like DELETE key +#if defined(OS_UNIX) + if (_getch() == DEL_AFTER) +#endif + { + } + break; + default: + break; + } + break; + } + default: { + supply(g_wch, ch); + g_buff.push_back(g_wch); + ++g_woffset; + ++g_len; + break; + } + } + } + return buff; +} + +void color_print(char* text, COLOR_TYPE color) +{ +#if defined(OS_WINDOWS) + HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); + if (h_console == NULL) { + fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); + exit(1); + } + + CONSOLE_SCREEN_BUFFER_INFO console_info; + COLOR_TYPE backup; + + // Save current attributes + if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) { + fprintf(stderr, "[ERROR] Couldn't get terminal info\n"); + exit(1); + } + backup = console_info.wAttributes; + + // Print colored text + if (SetConsoleTextAttribute(h_console, color) == 0) { + fprintf(stderr, "[ERROR] Couldn't set terminal color\n"); + exit(1); + } + + std::string tbuf; + + for (size_t i = 0; i < g_buff.size() && i < g_len; ++i) { + for (const auto& c : g_buff[i]) { + tbuf.push_back(c); + } + } + tbuf.push_back('\0'); + printf("%s", tbuf.c_str()); + + // Restore original color + if (SetConsoleTextAttribute(h_console, backup) == 0) { + fprintf(stderr, "[ERROR] Couldn't reset terminal color\n"); + exit(1); + } +#elif defined(OS_UNIX) + // Set new terminal color + printf("\033["); + printf("%s", color); + printf("m"); + + // Print colored text + printf("%s", text); + + // Resets the text to default color + printf("\033[0m"); +#endif +} diff --git a/filecomplete.h b/filecomplete.h new file mode 100644 index 0000000..a6fec9b --- /dev/null +++ b/filecomplete.h @@ -0,0 +1,3 @@ +#pragma once + +char* readline(); \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..12a9471 --- /dev/null +++ b/main.cpp @@ -0,0 +1,14 @@ +#include "filecomplete.h" +#include + +int main(int argc, char** argv) +{ + while (1) { + char* content = readline(); + if (content) { + std::cout << std::string(content) << std::endl; + free(content); + } + } + return 0; +} diff --git a/src/filecomplete.cpp b/src/filecomplete.cpp deleted file mode 100644 index 4bb25ab..0000000 --- a/src/filecomplete.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "filecomplete.h" - -#ifdef _MSC_VER -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#endif - -#include -#include -#include - -#define MAX_OF(x, y) (((x) > (y)) ? (x) : (y)) - -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN64) -#ifndef OS_WINDOWS -#define OS_WINDOWS - -#include -#include -#include -#endif -#elif defined(__APPLE__) || defined(__unix__) || defined(__unix) || defined(unix) || defined(__linux__) -#ifndef OS_UNIX -#define OS_UNIX - -#include -#include -#include -#endif -#else -#error Unknown environment! -#endif - -#if defined(OS_WINDOWS) -#define ENTER 13 -#define BACKSPACE 8 -#define LEFT 75 -#define RIGHT 77 -#define UP 72 -#define DOWN 80 -#define DEL 83 -#define CTRL_C 3 -#define SPECIAL_SEQ_1 0 -#define SPECIAL_SEQ_2 224 -#define COLOR_TYPE uint16_t -#define DEFAULT_TITLE_COLOR 160 -#define DEFAULT_PREDICT_COLOR 8 -#define DEFAULT_MAIN_COLOR 7 -#elif defined(OS_UNIX) -#define ENTER 10 -#define BACKSPACE 127 -#define LEFT 68 -#define RIGHT 67 -#define UP 65 -#define DOWN 66 -#define DEL 51 -#define DEL_AFTER 126 -#define SPECIAL_SEQ_1 27 -#define SPECIAL_SEQ_2 91 -#define COLOR_TYPE char * -#define DEFAULT_TITLE_COLOR "0;30;102" -#define DEFAULT_PREDICT_COLOR "90" -#define DEFAULT_MAIN_COLOR "0" -#endif -#define SPACE 32 -#define TAB 9 - -short terminal_width() -{ -#if defined(OS_WINDOWS) - // Handle current terminal - HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); - if (h_console == NULL) - { - fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); - exit(1); - } - - // Get current attributes - CONSOLE_SCREEN_BUFFER_INFO console_info; - if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) - { - fprintf(stderr, "[ERROR] Couldn't get terminal info\n"); - exit(1); - } - - // Return current width - return console_info.dwSize.X; -#elif defined(OS_UNIX) - struct winsize t_size; - - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &t_size) == -1) - { - fprintf(stderr, "[ERROR] Couldn't get terminal info\n"); - exit(1); - } - - return (short)t_size.ws_col; -#endif -} - -void clear_line() -{ -#if defined(OS_WINDOWS) - // Get current terminal width - short width = terminal_width(); - if (width < 1) - { - fprintf(stderr, "[ERROR] Size of terminal is too small\n"); - exit(1); - } - - // Create long empty string - char *empty = (char *)malloc(sizeof(char) * width); - memset(empty, ' ', width); - empty[width - 1] = '\0'; - - // Clear line - printf("\r%s\r", empty); - - // Free line - free(empty); -#elif defined(OS_UNIX) - printf("\033[2K\r"); -#endif -} - -void set_cursor_x(short x) -{ -#if defined(OS_WINDOWS) - HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); - if (h_console == NULL) - { - fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); - exit(1); - } - - // Create position - COORD xy; - xy.X = x - 1; - xy.Y = get_cursor_y(); - - // Set cursor position - if (SetConsoleCursorPosition(h_console, xy) == 0) - { - fprintf(stderr, "[ERROR] Couldn't set terminal cursor position\n"); - exit(1); - } -#elif defined(OS_UNIX) - printf("\033[%d;%dH", get_cursor_y(), x); -#endif -} - -short get_cursor_y() -{ -#if defined(OS_WINDOWS) - HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); - if (h_console == NULL) - { - fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); - exit(1); - } - - // Get terminal info - CONSOLE_SCREEN_BUFFER_INFO console_info; - if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) - { - fprintf(stderr, "[ERROR] Couldn't get terminal Y position\n"); - exit(1); - } - - // Return Y position - return console_info.dwCursorPosition.Y; -#elif defined(OS_UNIX) - struct termios old_attr, new_attr; - char ch, buf[30] = {0}; - int i = 0, pow = 1, y = 0; - - // Backup terminal attributes - if (tcgetattr(STDIN_FILENO, &new_attr) == -1) - { - fprintf(stderr, "[ERROR] Couldn't get terminal attributes\n"); - exit(1); - } - - // Disable echo - old_attr = new_attr; - old_attr.c_lflag &= ~(ICANON | ECHO); - if (tcsetattr(STDIN_FILENO, TCSANOW, &old_attr) == -1) - { - fprintf(stderr, "[ERROR] Couldn't set terminal attributes\n"); - exit(1); - } - - // Get info about cursor - if (write(STDOUT_FILENO, "\033[6n", 4) != 4) - { - fprintf(stderr, "[ERROR] Couldn't get cursor information\n"); - exit(1); - } - - // Get ^[[{this};1R value - - for (ch = 0; ch != 'R'; i++) - { - if (read(STDIN_FILENO, &ch, 1) != 1) - { - fprintf(stderr, "[ERROR] Couldn't read cursor information"); - exit(1); - } - 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; -#endif -} diff --git a/src/filecomplete.h b/src/filecomplete.h deleted file mode 100644 index 20f2c66..0000000 --- a/src/filecomplete.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -short terminal_width(); -void clear_line(); -void set_cursor_x(short x); -short get_cursor_y(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index b374e27..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "filecomplete.h" -#include - -int main(int argc, char** argv) { - return 0; -} diff --git a/xmake.lua b/xmake.lua deleted file mode 100644 index 02d55f3..0000000 --- a/xmake.lua +++ /dev/null @@ -1,10 +0,0 @@ -add_rules("mode.debug", "mode.release") - -target("filecomplete") - set_kind("static") - add_files("src/filecomplete.cpp") - -target("example") - set_kind("binary") - add_deps("filecomplete") - add_files("src/main.cpp") \ No newline at end of file