update:初步能输入(包含GBK中文输入)

This commit is contained in:
taynpg 2025-01-08 20:35:08 +08:00
parent 332e0c53b7
commit bfdf34d02e
12 changed files with 489 additions and 278 deletions

17
.clang-format Normal file
View File

@ -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

13
.gitignore vendored
View File

@ -1,8 +1,5 @@
# Xmake cache build
.xmake/ .vs
build/ .cache
cmake-*
# MacOS Cache out
.DS_Store
compile_commands.json

29
.vscode/settings.json vendored
View File

@ -3,16 +3,35 @@
"editor.fontSize": 14, "editor.fontSize": 14,
"editor.fontFamily": "'Source Code Pro', 'Courier New', monospace", "editor.fontFamily": "'Source Code Pro', 'Courier New', monospace",
"terminal.integrated.fontFamily": "Source Code Pro", "terminal.integrated.fontFamily": "Source Code Pro",
"editor.fontLigatures": true, "cmake.configureOnOpen": true,
"C_Cpp.default.configurationProvider": "tboox.xmake-vscode", "cmake.debugConfig": {
"cmake.configureOnOpen": false, "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.compileCommands": "${workspaceRoot}/build/compile_commands.json",
"C_Cpp.default.cppStandard": "c++17", "C_Cpp.default.cppStandard": "c++17",
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"editor.inlayHints.enabled": "off", "editor.inlayHints.enabled": "off",
"editor.unicodeHighlight.allowedLocales": { "editor.unicodeHighlight.allowedLocales": {
"ja": true, "ja": true,
"zh-hant": true, "zh-hant": true,
"zh-hans": true "zh-hans": true
}, }
"makefile.configureOnOpen": false
} }

26
CMakeLists.txt Normal file
View File

@ -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)

View File

@ -1,5 +0,0 @@
# 简介
在控制台程序中,可以补全文件路径。
本项目修改自 [https://github.com/DieTime/cli-autocomplete](https://github.com/DieTime/cli-autocomplete) 。

400
filecomplete.cpp Normal file
View File

@ -0,0 +1,400 @@
#include "filecomplete.h"
#include <string>
#include <vector>
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_OF(x, y) (((x) > (y)) ? (x) : (y))
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN64)
#ifndef OS_WINDOWS
#define OS_WINDOWS
#include <conio.h>
#include <stdint.h>
#include <windows.h>
#endif
#elif defined(__APPLE__) || defined(__unix__) || defined(__unix) || \
defined(unix) || defined(__linux__)
#ifndef OS_UNIX
#define OS_UNIX
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#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<std::vector<char>> g_buff{};
static std::vector<char> 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<char>& 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
}

3
filecomplete.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
char* readline();

14
main.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "filecomplete.h"
#include <iostream>
int main(int argc, char** argv)
{
while (1) {
char* content = readline();
if (content) {
std::cout << std::string(content) << std::endl;
free(content);
}
}
return 0;
}

View File

@ -1,238 +0,0 @@
#include "filecomplete.h"
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_OF(x, y) (((x) > (y)) ? (x) : (y))
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN64)
#ifndef OS_WINDOWS
#define OS_WINDOWS
#include <windows.h>
#include <conio.h>
#include <stdint.h>
#endif
#elif defined(__APPLE__) || defined(__unix__) || defined(__unix) || defined(unix) || defined(__linux__)
#ifndef OS_UNIX
#define OS_UNIX
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#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
}

View File

@ -1,6 +0,0 @@
#pragma once
short terminal_width();
void clear_line();
void set_cursor_x(short x);
short get_cursor_y();

View File

@ -1,6 +0,0 @@
#include "filecomplete.h"
#include <iostream>
int main(int argc, char** argv) {
return 0;
}

View File

@ -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")