@fugood/llama.node 0.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +85 -0
- package/README.md +56 -0
- package/bin/darwin/arm64/llama-node.node +0 -0
- package/bin/darwin/x64/llama-node.node +0 -0
- package/bin/linux/arm64/llama-node.node +0 -0
- package/bin/linux/x64/llama-node.node +0 -0
- package/bin/win32/arm64/llama-node.node +0 -0
- package/bin/win32/arm64/node.lib +0 -0
- package/bin/win32/x64/llama-node.node +0 -0
- package/bin/win32/x64/node.lib +0 -0
- package/lib/binding.js +13 -0
- package/lib/binding.ts +57 -0
- package/lib/index.js +24 -0
- package/lib/index.ts +13 -0
- package/package.json +65 -0
- package/src/addons.cpp +506 -0
- package/src/llama.cpp/CMakeLists.txt +1320 -0
- package/src/llama.cpp/build.zig +172 -0
- package/src/llama.cpp/cmake/FindSIMD.cmake +100 -0
- package/src/llama.cpp/common/CMakeLists.txt +87 -0
- package/src/llama.cpp/common/base64.hpp +392 -0
- package/src/llama.cpp/common/common.cpp +2949 -0
- package/src/llama.cpp/common/common.h +324 -0
- package/src/llama.cpp/common/console.cpp +501 -0
- package/src/llama.cpp/common/console.h +19 -0
- package/src/llama.cpp/common/grammar-parser.cpp +440 -0
- package/src/llama.cpp/common/grammar-parser.h +29 -0
- package/src/llama.cpp/common/json-schema-to-grammar.cpp +764 -0
- package/src/llama.cpp/common/json-schema-to-grammar.h +4 -0
- package/src/llama.cpp/common/json.hpp +24766 -0
- package/src/llama.cpp/common/log.h +724 -0
- package/src/llama.cpp/common/ngram-cache.cpp +282 -0
- package/src/llama.cpp/common/ngram-cache.h +94 -0
- package/src/llama.cpp/common/sampling.cpp +353 -0
- package/src/llama.cpp/common/sampling.h +147 -0
- package/src/llama.cpp/common/stb_image.h +8396 -0
- package/src/llama.cpp/common/train.cpp +1513 -0
- package/src/llama.cpp/common/train.h +233 -0
- package/src/llama.cpp/examples/CMakeLists.txt +52 -0
- package/src/llama.cpp/examples/baby-llama/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/baby-llama/baby-llama.cpp +1640 -0
- package/src/llama.cpp/examples/batched/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/batched/batched.cpp +262 -0
- package/src/llama.cpp/examples/batched-bench/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/batched-bench/batched-bench.cpp +261 -0
- package/src/llama.cpp/examples/beam-search/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/beam-search/beam-search.cpp +188 -0
- package/src/llama.cpp/examples/benchmark/CMakeLists.txt +6 -0
- package/src/llama.cpp/examples/benchmark/benchmark-matmult.cpp +275 -0
- package/src/llama.cpp/examples/convert-llama2c-to-ggml/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/convert-llama2c-to-ggml/convert-llama2c-to-ggml.cpp +936 -0
- package/src/llama.cpp/examples/embedding/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/embedding/embedding.cpp +211 -0
- package/src/llama.cpp/examples/eval-callback/CMakeLists.txt +9 -0
- package/src/llama.cpp/examples/eval-callback/eval-callback.cpp +195 -0
- package/src/llama.cpp/examples/export-lora/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/export-lora/export-lora.cpp +462 -0
- package/src/llama.cpp/examples/finetune/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/finetune/finetune.cpp +1861 -0
- package/src/llama.cpp/examples/gbnf-validator/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/gbnf-validator/gbnf-validator.cpp +132 -0
- package/src/llama.cpp/examples/gguf/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/gguf/gguf.cpp +256 -0
- package/src/llama.cpp/examples/gguf-split/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/gguf-split/gguf-split.cpp +553 -0
- package/src/llama.cpp/examples/gritlm/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/gritlm/gritlm.cpp +215 -0
- package/src/llama.cpp/examples/imatrix/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/imatrix/imatrix.cpp +655 -0
- package/src/llama.cpp/examples/infill/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/infill/infill.cpp +767 -0
- package/src/llama.cpp/examples/jeopardy/questions.txt +100 -0
- package/src/llama.cpp/examples/llama-bench/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/llama-bench/llama-bench.cpp +1286 -0
- package/src/llama.cpp/examples/llama.android/app/src/main/cpp/CMakeLists.txt +50 -0
- package/src/llama.cpp/examples/llama.android/app/src/main/cpp/llama-android.cpp +443 -0
- package/src/llama.cpp/examples/llava/CMakeLists.txt +37 -0
- package/src/llama.cpp/examples/llava/clip.cpp +2027 -0
- package/src/llama.cpp/examples/llava/clip.h +85 -0
- package/src/llama.cpp/examples/llava/llava-cli.cpp +309 -0
- package/src/llama.cpp/examples/llava/llava.cpp +426 -0
- package/src/llama.cpp/examples/llava/llava.h +50 -0
- package/src/llama.cpp/examples/llava/requirements.txt +3 -0
- package/src/llama.cpp/examples/lookahead/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/lookahead/lookahead.cpp +485 -0
- package/src/llama.cpp/examples/lookup/CMakeLists.txt +23 -0
- package/src/llama.cpp/examples/lookup/lookup-create.cpp +41 -0
- package/src/llama.cpp/examples/lookup/lookup-merge.cpp +47 -0
- package/src/llama.cpp/examples/lookup/lookup-stats.cpp +160 -0
- package/src/llama.cpp/examples/lookup/lookup.cpp +258 -0
- package/src/llama.cpp/examples/main/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/main/main.cpp +957 -0
- package/src/llama.cpp/examples/main-cmake-pkg/CMakeLists.txt +33 -0
- package/src/llama.cpp/examples/parallel/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/parallel/parallel.cpp +427 -0
- package/src/llama.cpp/examples/passkey/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/passkey/passkey.cpp +302 -0
- package/src/llama.cpp/examples/perplexity/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/perplexity/perplexity.cpp +1943 -0
- package/src/llama.cpp/examples/quantize/CMakeLists.txt +6 -0
- package/src/llama.cpp/examples/quantize/quantize.cpp +423 -0
- package/src/llama.cpp/examples/quantize-stats/CMakeLists.txt +6 -0
- package/src/llama.cpp/examples/quantize-stats/quantize-stats.cpp +424 -0
- package/src/llama.cpp/examples/retrieval/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/retrieval/retrieval.cpp +350 -0
- package/src/llama.cpp/examples/save-load-state/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/save-load-state/save-load-state.cpp +246 -0
- package/src/llama.cpp/examples/server/CMakeLists.txt +40 -0
- package/src/llama.cpp/examples/server/bench/requirements.txt +2 -0
- package/src/llama.cpp/examples/server/httplib.h +9465 -0
- package/src/llama.cpp/examples/server/server.cpp +3826 -0
- package/src/llama.cpp/examples/server/tests/requirements.txt +6 -0
- package/src/llama.cpp/examples/server/utils.hpp +653 -0
- package/src/llama.cpp/examples/simple/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/simple/simple.cpp +183 -0
- package/src/llama.cpp/examples/speculative/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/speculative/speculative.cpp +614 -0
- package/src/llama.cpp/examples/sycl/CMakeLists.txt +9 -0
- package/src/llama.cpp/examples/sycl/ls-sycl-device.cpp +13 -0
- package/src/llama.cpp/examples/tokenize/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/tokenize/tokenize.cpp +42 -0
- package/src/llama.cpp/examples/train-text-from-scratch/CMakeLists.txt +5 -0
- package/src/llama.cpp/examples/train-text-from-scratch/train-text-from-scratch.cpp +1252 -0
- package/src/llama.cpp/ggml-alloc.c +985 -0
- package/src/llama.cpp/ggml-alloc.h +76 -0
- package/src/llama.cpp/ggml-backend-impl.h +141 -0
- package/src/llama.cpp/ggml-backend.c +2099 -0
- package/src/llama.cpp/ggml-backend.h +233 -0
- package/src/llama.cpp/ggml-common.h +1853 -0
- package/src/llama.cpp/ggml-cuda.h +43 -0
- package/src/llama.cpp/ggml-impl.h +265 -0
- package/src/llama.cpp/ggml-kompute.cpp +2006 -0
- package/src/llama.cpp/ggml-kompute.h +46 -0
- package/src/llama.cpp/ggml-metal.h +66 -0
- package/src/llama.cpp/ggml-mpi.c +216 -0
- package/src/llama.cpp/ggml-mpi.h +39 -0
- package/src/llama.cpp/ggml-opencl.cpp +2301 -0
- package/src/llama.cpp/ggml-opencl.h +36 -0
- package/src/llama.cpp/ggml-quants.c +12678 -0
- package/src/llama.cpp/ggml-quants.h +133 -0
- package/src/llama.cpp/ggml-sycl.cpp +17882 -0
- package/src/llama.cpp/ggml-sycl.h +49 -0
- package/src/llama.cpp/ggml-vulkan-shaders.hpp +69849 -0
- package/src/llama.cpp/ggml-vulkan.cpp +6442 -0
- package/src/llama.cpp/ggml-vulkan.h +29 -0
- package/src/llama.cpp/ggml.c +21819 -0
- package/src/llama.cpp/ggml.h +2403 -0
- package/src/llama.cpp/llama.cpp +17468 -0
- package/src/llama.cpp/llama.h +1117 -0
- package/src/llama.cpp/pocs/CMakeLists.txt +12 -0
- package/src/llama.cpp/pocs/vdot/CMakeLists.txt +9 -0
- package/src/llama.cpp/pocs/vdot/q8dot.cpp +172 -0
- package/src/llama.cpp/pocs/vdot/vdot.cpp +310 -0
- package/src/llama.cpp/prompts/LLM-questions.txt +49 -0
- package/src/llama.cpp/prompts/alpaca.txt +1 -0
- package/src/llama.cpp/prompts/assistant.txt +31 -0
- package/src/llama.cpp/prompts/chat-with-baichuan.txt +4 -0
- package/src/llama.cpp/prompts/chat-with-bob.txt +7 -0
- package/src/llama.cpp/prompts/chat-with-qwen.txt +1 -0
- package/src/llama.cpp/prompts/chat-with-vicuna-v0.txt +7 -0
- package/src/llama.cpp/prompts/chat-with-vicuna-v1.txt +7 -0
- package/src/llama.cpp/prompts/chat.txt +28 -0
- package/src/llama.cpp/prompts/dan-modified.txt +1 -0
- package/src/llama.cpp/prompts/dan.txt +1 -0
- package/src/llama.cpp/prompts/mnemonics.txt +93 -0
- package/src/llama.cpp/prompts/parallel-questions.txt +43 -0
- package/src/llama.cpp/prompts/reason-act.txt +18 -0
- package/src/llama.cpp/requirements/requirements-convert-hf-to-gguf.txt +3 -0
- package/src/llama.cpp/requirements/requirements-convert-llama-ggml-to-gguf.txt +1 -0
- package/src/llama.cpp/requirements/requirements-convert-lora-to-ggml.txt +2 -0
- package/src/llama.cpp/requirements/requirements-convert-persimmon-to-gguf.txt +2 -0
- package/src/llama.cpp/requirements/requirements-convert.txt +5 -0
- package/src/llama.cpp/requirements.txt +12 -0
- package/src/llama.cpp/scripts/gen-build-info-cpp.cmake +24 -0
- package/src/llama.cpp/scripts/xxd.cmake +16 -0
- package/src/llama.cpp/sgemm.cpp +999 -0
- package/src/llama.cpp/sgemm.h +12 -0
- package/src/llama.cpp/tests/CMakeLists.txt +78 -0
- package/src/llama.cpp/tests/get-model.cpp +21 -0
- package/src/llama.cpp/tests/get-model.h +2 -0
- package/src/llama.cpp/tests/test-autorelease.cpp +24 -0
- package/src/llama.cpp/tests/test-backend-ops.cpp +2266 -0
- package/src/llama.cpp/tests/test-c.c +7 -0
- package/src/llama.cpp/tests/test-chat-template.cpp +107 -0
- package/src/llama.cpp/tests/test-double-float.cpp +57 -0
- package/src/llama.cpp/tests/test-grad0.cpp +1606 -0
- package/src/llama.cpp/tests/test-grammar-integration.cpp +243 -0
- package/src/llama.cpp/tests/test-grammar-parser.cpp +250 -0
- package/src/llama.cpp/tests/test-json-schema-to-grammar.cpp +899 -0
- package/src/llama.cpp/tests/test-llama-grammar.cpp +402 -0
- package/src/llama.cpp/tests/test-model-load-cancel.cpp +27 -0
- package/src/llama.cpp/tests/test-opt.cpp +181 -0
- package/src/llama.cpp/tests/test-quantize-fns.cpp +185 -0
- package/src/llama.cpp/tests/test-quantize-perf.cpp +363 -0
- package/src/llama.cpp/tests/test-rope.cpp +221 -0
- package/src/llama.cpp/tests/test-sampling.cpp +301 -0
- package/src/llama.cpp/tests/test-tokenizer-0-falcon.cpp +187 -0
- package/src/llama.cpp/tests/test-tokenizer-0-llama.cpp +190 -0
- package/src/llama.cpp/tests/test-tokenizer-1-bpe.cpp +123 -0
- package/src/llama.cpp/tests/test-tokenizer-1-llama.cpp +111 -0
- package/src/llama.cpp/unicode-data.cpp +1651 -0
- package/src/llama.cpp/unicode-data.h +16 -0
- package/src/llama.cpp/unicode.cpp +277 -0
- package/src/llama.cpp/unicode.h +28 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
#include "console.h"
|
|
2
|
+
#include <vector>
|
|
3
|
+
#include <iostream>
|
|
4
|
+
|
|
5
|
+
#if defined(_WIN32)
|
|
6
|
+
#define WIN32_LEAN_AND_MEAN
|
|
7
|
+
#ifndef NOMINMAX
|
|
8
|
+
#define NOMINMAX
|
|
9
|
+
#endif
|
|
10
|
+
#include <windows.h>
|
|
11
|
+
#include <fcntl.h>
|
|
12
|
+
#include <io.h>
|
|
13
|
+
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|
14
|
+
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
|
15
|
+
#endif
|
|
16
|
+
#else
|
|
17
|
+
#include <climits>
|
|
18
|
+
#include <sys/ioctl.h>
|
|
19
|
+
#include <unistd.h>
|
|
20
|
+
#include <wchar.h>
|
|
21
|
+
#include <stdio.h>
|
|
22
|
+
#include <stdlib.h>
|
|
23
|
+
#include <signal.h>
|
|
24
|
+
#include <termios.h>
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#define ANSI_COLOR_RED "\x1b[31m"
|
|
28
|
+
#define ANSI_COLOR_GREEN "\x1b[32m"
|
|
29
|
+
#define ANSI_COLOR_YELLOW "\x1b[33m"
|
|
30
|
+
#define ANSI_COLOR_BLUE "\x1b[34m"
|
|
31
|
+
#define ANSI_COLOR_MAGENTA "\x1b[35m"
|
|
32
|
+
#define ANSI_COLOR_CYAN "\x1b[36m"
|
|
33
|
+
#define ANSI_COLOR_RESET "\x1b[0m"
|
|
34
|
+
#define ANSI_BOLD "\x1b[1m"
|
|
35
|
+
|
|
36
|
+
namespace console {
|
|
37
|
+
|
|
38
|
+
//
|
|
39
|
+
// Console state
|
|
40
|
+
//
|
|
41
|
+
|
|
42
|
+
static bool advanced_display = false;
|
|
43
|
+
static bool simple_io = true;
|
|
44
|
+
static display_t current_display = reset;
|
|
45
|
+
|
|
46
|
+
static FILE* out = stdout;
|
|
47
|
+
|
|
48
|
+
#if defined (_WIN32)
|
|
49
|
+
static void* hConsole;
|
|
50
|
+
#else
|
|
51
|
+
static FILE* tty = nullptr;
|
|
52
|
+
static termios initial_state;
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
//
|
|
56
|
+
// Init and cleanup
|
|
57
|
+
//
|
|
58
|
+
|
|
59
|
+
void init(bool use_simple_io, bool use_advanced_display) {
|
|
60
|
+
advanced_display = use_advanced_display;
|
|
61
|
+
simple_io = use_simple_io;
|
|
62
|
+
#if defined(_WIN32)
|
|
63
|
+
// Windows-specific console initialization
|
|
64
|
+
DWORD dwMode = 0;
|
|
65
|
+
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
66
|
+
if (hConsole == INVALID_HANDLE_VALUE || !GetConsoleMode(hConsole, &dwMode)) {
|
|
67
|
+
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
|
68
|
+
if (hConsole != INVALID_HANDLE_VALUE && (!GetConsoleMode(hConsole, &dwMode))) {
|
|
69
|
+
hConsole = nullptr;
|
|
70
|
+
simple_io = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (hConsole) {
|
|
74
|
+
// Check conditions combined to reduce nesting
|
|
75
|
+
if (advanced_display && !(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) &&
|
|
76
|
+
!SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
|
|
77
|
+
advanced_display = false;
|
|
78
|
+
}
|
|
79
|
+
// Set console output codepage to UTF8
|
|
80
|
+
SetConsoleOutputCP(CP_UTF8);
|
|
81
|
+
}
|
|
82
|
+
HANDLE hConIn = GetStdHandle(STD_INPUT_HANDLE);
|
|
83
|
+
if (hConIn != INVALID_HANDLE_VALUE && GetConsoleMode(hConIn, &dwMode)) {
|
|
84
|
+
// Set console input codepage to UTF16
|
|
85
|
+
_setmode(_fileno(stdin), _O_WTEXT);
|
|
86
|
+
|
|
87
|
+
// Set ICANON (ENABLE_LINE_INPUT) and ECHO (ENABLE_ECHO_INPUT)
|
|
88
|
+
if (simple_io) {
|
|
89
|
+
dwMode |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
|
|
90
|
+
} else {
|
|
91
|
+
dwMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
|
|
92
|
+
}
|
|
93
|
+
if (!SetConsoleMode(hConIn, dwMode)) {
|
|
94
|
+
simple_io = true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
#else
|
|
98
|
+
// POSIX-specific console initialization
|
|
99
|
+
if (!simple_io) {
|
|
100
|
+
struct termios new_termios;
|
|
101
|
+
tcgetattr(STDIN_FILENO, &initial_state);
|
|
102
|
+
new_termios = initial_state;
|
|
103
|
+
new_termios.c_lflag &= ~(ICANON | ECHO);
|
|
104
|
+
new_termios.c_cc[VMIN] = 1;
|
|
105
|
+
new_termios.c_cc[VTIME] = 0;
|
|
106
|
+
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
|
107
|
+
|
|
108
|
+
tty = fopen("/dev/tty", "w+");
|
|
109
|
+
if (tty != nullptr) {
|
|
110
|
+
out = tty;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setlocale(LC_ALL, "");
|
|
115
|
+
#endif
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void cleanup() {
|
|
119
|
+
// Reset console display
|
|
120
|
+
set_display(reset);
|
|
121
|
+
|
|
122
|
+
#if !defined(_WIN32)
|
|
123
|
+
// Restore settings on POSIX systems
|
|
124
|
+
if (!simple_io) {
|
|
125
|
+
if (tty != nullptr) {
|
|
126
|
+
out = stdout;
|
|
127
|
+
fclose(tty);
|
|
128
|
+
tty = nullptr;
|
|
129
|
+
}
|
|
130
|
+
tcsetattr(STDIN_FILENO, TCSANOW, &initial_state);
|
|
131
|
+
}
|
|
132
|
+
#endif
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
//
|
|
136
|
+
// Display and IO
|
|
137
|
+
//
|
|
138
|
+
|
|
139
|
+
// Keep track of current display and only emit ANSI code if it changes
|
|
140
|
+
void set_display(display_t display) {
|
|
141
|
+
if (advanced_display && current_display != display) {
|
|
142
|
+
fflush(stdout);
|
|
143
|
+
switch(display) {
|
|
144
|
+
case reset:
|
|
145
|
+
fprintf(out, ANSI_COLOR_RESET);
|
|
146
|
+
break;
|
|
147
|
+
case prompt:
|
|
148
|
+
fprintf(out, ANSI_COLOR_YELLOW);
|
|
149
|
+
break;
|
|
150
|
+
case user_input:
|
|
151
|
+
fprintf(out, ANSI_BOLD ANSI_COLOR_GREEN);
|
|
152
|
+
break;
|
|
153
|
+
case error:
|
|
154
|
+
fprintf(out, ANSI_BOLD ANSI_COLOR_RED);
|
|
155
|
+
}
|
|
156
|
+
current_display = display;
|
|
157
|
+
fflush(out);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static char32_t getchar32() {
|
|
162
|
+
#if defined(_WIN32)
|
|
163
|
+
HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
|
|
164
|
+
wchar_t high_surrogate = 0;
|
|
165
|
+
|
|
166
|
+
while (true) {
|
|
167
|
+
INPUT_RECORD record;
|
|
168
|
+
DWORD count;
|
|
169
|
+
if (!ReadConsoleInputW(hConsole, &record, 1, &count) || count == 0) {
|
|
170
|
+
return WEOF;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) {
|
|
174
|
+
wchar_t wc = record.Event.KeyEvent.uChar.UnicodeChar;
|
|
175
|
+
if (wc == 0) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate
|
|
180
|
+
high_surrogate = wc;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if ((wc >= 0xDC00) && (wc <= 0xDFFF)) { // Check if wc is a low surrogate
|
|
184
|
+
if (high_surrogate != 0) { // Check if we have a high surrogate
|
|
185
|
+
return ((high_surrogate - 0xD800) << 10) + (wc - 0xDC00) + 0x10000;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
high_surrogate = 0; // Reset the high surrogate
|
|
190
|
+
return static_cast<char32_t>(wc);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
#else
|
|
194
|
+
wchar_t wc = getwchar();
|
|
195
|
+
if (static_cast<wint_t>(wc) == WEOF) {
|
|
196
|
+
return WEOF;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
#if WCHAR_MAX == 0xFFFF
|
|
200
|
+
if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate
|
|
201
|
+
wchar_t low_surrogate = getwchar();
|
|
202
|
+
if ((low_surrogate >= 0xDC00) && (low_surrogate <= 0xDFFF)) { // Check if the next wchar is a low surrogate
|
|
203
|
+
return (static_cast<char32_t>(wc & 0x03FF) << 10) + (low_surrogate & 0x03FF) + 0x10000;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if ((wc >= 0xD800) && (wc <= 0xDFFF)) { // Invalid surrogate pair
|
|
207
|
+
return 0xFFFD; // Return the replacement character U+FFFD
|
|
208
|
+
}
|
|
209
|
+
#endif
|
|
210
|
+
|
|
211
|
+
return static_cast<char32_t>(wc);
|
|
212
|
+
#endif
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static void pop_cursor() {
|
|
216
|
+
#if defined(_WIN32)
|
|
217
|
+
if (hConsole != NULL) {
|
|
218
|
+
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
|
|
219
|
+
GetConsoleScreenBufferInfo(hConsole, &bufferInfo);
|
|
220
|
+
|
|
221
|
+
COORD newCursorPosition = bufferInfo.dwCursorPosition;
|
|
222
|
+
if (newCursorPosition.X == 0) {
|
|
223
|
+
newCursorPosition.X = bufferInfo.dwSize.X - 1;
|
|
224
|
+
newCursorPosition.Y -= 1;
|
|
225
|
+
} else {
|
|
226
|
+
newCursorPosition.X -= 1;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
SetConsoleCursorPosition(hConsole, newCursorPosition);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
#endif
|
|
233
|
+
putc('\b', out);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static int estimateWidth(char32_t codepoint) {
|
|
237
|
+
#if defined(_WIN32)
|
|
238
|
+
(void)codepoint;
|
|
239
|
+
return 1;
|
|
240
|
+
#else
|
|
241
|
+
return wcwidth(codepoint);
|
|
242
|
+
#endif
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
static int put_codepoint(const char* utf8_codepoint, size_t length, int expectedWidth) {
|
|
246
|
+
#if defined(_WIN32)
|
|
247
|
+
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
|
|
248
|
+
if (!GetConsoleScreenBufferInfo(hConsole, &bufferInfo)) {
|
|
249
|
+
// go with the default
|
|
250
|
+
return expectedWidth;
|
|
251
|
+
}
|
|
252
|
+
COORD initialPosition = bufferInfo.dwCursorPosition;
|
|
253
|
+
DWORD nNumberOfChars = length;
|
|
254
|
+
WriteConsole(hConsole, utf8_codepoint, nNumberOfChars, &nNumberOfChars, NULL);
|
|
255
|
+
|
|
256
|
+
CONSOLE_SCREEN_BUFFER_INFO newBufferInfo;
|
|
257
|
+
GetConsoleScreenBufferInfo(hConsole, &newBufferInfo);
|
|
258
|
+
|
|
259
|
+
// Figure out our real position if we're in the last column
|
|
260
|
+
if (utf8_codepoint[0] != 0x09 && initialPosition.X == newBufferInfo.dwSize.X - 1) {
|
|
261
|
+
DWORD nNumberOfChars;
|
|
262
|
+
WriteConsole(hConsole, &" \b", 2, &nNumberOfChars, NULL);
|
|
263
|
+
GetConsoleScreenBufferInfo(hConsole, &newBufferInfo);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
int width = newBufferInfo.dwCursorPosition.X - initialPosition.X;
|
|
267
|
+
if (width < 0) {
|
|
268
|
+
width += newBufferInfo.dwSize.X;
|
|
269
|
+
}
|
|
270
|
+
return width;
|
|
271
|
+
#else
|
|
272
|
+
// We can trust expectedWidth if we've got one
|
|
273
|
+
if (expectedWidth >= 0 || tty == nullptr) {
|
|
274
|
+
fwrite(utf8_codepoint, length, 1, out);
|
|
275
|
+
return expectedWidth;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
fputs("\033[6n", tty); // Query cursor position
|
|
279
|
+
int x1;
|
|
280
|
+
int y1;
|
|
281
|
+
int x2;
|
|
282
|
+
int y2;
|
|
283
|
+
int results = 0;
|
|
284
|
+
results = fscanf(tty, "\033[%d;%dR", &y1, &x1);
|
|
285
|
+
|
|
286
|
+
fwrite(utf8_codepoint, length, 1, tty);
|
|
287
|
+
|
|
288
|
+
fputs("\033[6n", tty); // Query cursor position
|
|
289
|
+
results += fscanf(tty, "\033[%d;%dR", &y2, &x2);
|
|
290
|
+
|
|
291
|
+
if (results != 4) {
|
|
292
|
+
return expectedWidth;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
int width = x2 - x1;
|
|
296
|
+
if (width < 0) {
|
|
297
|
+
// Calculate the width considering text wrapping
|
|
298
|
+
struct winsize w;
|
|
299
|
+
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
|
300
|
+
width += w.ws_col;
|
|
301
|
+
}
|
|
302
|
+
return width;
|
|
303
|
+
#endif
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
static void replace_last(char ch) {
|
|
307
|
+
#if defined(_WIN32)
|
|
308
|
+
pop_cursor();
|
|
309
|
+
put_codepoint(&ch, 1, 1);
|
|
310
|
+
#else
|
|
311
|
+
fprintf(out, "\b%c", ch);
|
|
312
|
+
#endif
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
static void append_utf8(char32_t ch, std::string & out) {
|
|
316
|
+
if (ch <= 0x7F) {
|
|
317
|
+
out.push_back(static_cast<unsigned char>(ch));
|
|
318
|
+
} else if (ch <= 0x7FF) {
|
|
319
|
+
out.push_back(static_cast<unsigned char>(0xC0 | ((ch >> 6) & 0x1F)));
|
|
320
|
+
out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));
|
|
321
|
+
} else if (ch <= 0xFFFF) {
|
|
322
|
+
out.push_back(static_cast<unsigned char>(0xE0 | ((ch >> 12) & 0x0F)));
|
|
323
|
+
out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 6) & 0x3F)));
|
|
324
|
+
out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));
|
|
325
|
+
} else if (ch <= 0x10FFFF) {
|
|
326
|
+
out.push_back(static_cast<unsigned char>(0xF0 | ((ch >> 18) & 0x07)));
|
|
327
|
+
out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 12) & 0x3F)));
|
|
328
|
+
out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 6) & 0x3F)));
|
|
329
|
+
out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));
|
|
330
|
+
} else {
|
|
331
|
+
// Invalid Unicode code point
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Helper function to remove the last UTF-8 character from a string
|
|
336
|
+
static void pop_back_utf8_char(std::string & line) {
|
|
337
|
+
if (line.empty()) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
size_t pos = line.length() - 1;
|
|
342
|
+
|
|
343
|
+
// Find the start of the last UTF-8 character (checking up to 4 bytes back)
|
|
344
|
+
for (size_t i = 0; i < 3 && pos > 0; ++i, --pos) {
|
|
345
|
+
if ((line[pos] & 0xC0) != 0x80) {
|
|
346
|
+
break; // Found the start of the character
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
line.erase(pos);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
static bool readline_advanced(std::string & line, bool multiline_input) {
|
|
353
|
+
if (out != stdout) {
|
|
354
|
+
fflush(stdout);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
line.clear();
|
|
358
|
+
std::vector<int> widths;
|
|
359
|
+
bool is_special_char = false;
|
|
360
|
+
bool end_of_stream = false;
|
|
361
|
+
|
|
362
|
+
char32_t input_char;
|
|
363
|
+
while (true) {
|
|
364
|
+
fflush(out); // Ensure all output is displayed before waiting for input
|
|
365
|
+
input_char = getchar32();
|
|
366
|
+
|
|
367
|
+
if (input_char == '\r' || input_char == '\n') {
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (input_char == (char32_t) WEOF || input_char == 0x04 /* Ctrl+D*/) {
|
|
372
|
+
end_of_stream = true;
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (is_special_char) {
|
|
377
|
+
set_display(user_input);
|
|
378
|
+
replace_last(line.back());
|
|
379
|
+
is_special_char = false;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (input_char == '\033') { // Escape sequence
|
|
383
|
+
char32_t code = getchar32();
|
|
384
|
+
if (code == '[' || code == 0x1B) {
|
|
385
|
+
// Discard the rest of the escape sequence
|
|
386
|
+
while ((code = getchar32()) != (char32_t) WEOF) {
|
|
387
|
+
if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z') || code == '~') {
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
} else if (input_char == 0x08 || input_char == 0x7F) { // Backspace
|
|
393
|
+
if (!widths.empty()) {
|
|
394
|
+
int count;
|
|
395
|
+
do {
|
|
396
|
+
count = widths.back();
|
|
397
|
+
widths.pop_back();
|
|
398
|
+
// Move cursor back, print space, and move cursor back again
|
|
399
|
+
for (int i = 0; i < count; i++) {
|
|
400
|
+
replace_last(' ');
|
|
401
|
+
pop_cursor();
|
|
402
|
+
}
|
|
403
|
+
pop_back_utf8_char(line);
|
|
404
|
+
} while (count == 0 && !widths.empty());
|
|
405
|
+
}
|
|
406
|
+
} else {
|
|
407
|
+
int offset = line.length();
|
|
408
|
+
append_utf8(input_char, line);
|
|
409
|
+
int width = put_codepoint(line.c_str() + offset, line.length() - offset, estimateWidth(input_char));
|
|
410
|
+
if (width < 0) {
|
|
411
|
+
width = 0;
|
|
412
|
+
}
|
|
413
|
+
widths.push_back(width);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (!line.empty() && (line.back() == '\\' || line.back() == '/')) {
|
|
417
|
+
set_display(prompt);
|
|
418
|
+
replace_last(line.back());
|
|
419
|
+
is_special_char = true;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
bool has_more = multiline_input;
|
|
424
|
+
if (is_special_char) {
|
|
425
|
+
replace_last(' ');
|
|
426
|
+
pop_cursor();
|
|
427
|
+
|
|
428
|
+
char last = line.back();
|
|
429
|
+
line.pop_back();
|
|
430
|
+
if (last == '\\') {
|
|
431
|
+
line += '\n';
|
|
432
|
+
fputc('\n', out);
|
|
433
|
+
has_more = !has_more;
|
|
434
|
+
} else {
|
|
435
|
+
// llama will just eat the single space, it won't act as a space
|
|
436
|
+
if (line.length() == 1 && line.back() == ' ') {
|
|
437
|
+
line.clear();
|
|
438
|
+
pop_cursor();
|
|
439
|
+
}
|
|
440
|
+
has_more = false;
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
if (end_of_stream) {
|
|
444
|
+
has_more = false;
|
|
445
|
+
} else {
|
|
446
|
+
line += '\n';
|
|
447
|
+
fputc('\n', out);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
fflush(out);
|
|
452
|
+
return has_more;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
static bool readline_simple(std::string & line, bool multiline_input) {
|
|
456
|
+
#if defined(_WIN32)
|
|
457
|
+
std::wstring wline;
|
|
458
|
+
if (!std::getline(std::wcin, wline)) {
|
|
459
|
+
// Input stream is bad or EOF received
|
|
460
|
+
line.clear();
|
|
461
|
+
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), NULL, 0, NULL, NULL);
|
|
466
|
+
line.resize(size_needed);
|
|
467
|
+
WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), &line[0], size_needed, NULL, NULL);
|
|
468
|
+
#else
|
|
469
|
+
if (!std::getline(std::cin, line)) {
|
|
470
|
+
// Input stream is bad or EOF received
|
|
471
|
+
line.clear();
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
#endif
|
|
475
|
+
if (!line.empty()) {
|
|
476
|
+
char last = line.back();
|
|
477
|
+
if (last == '/') { // Always return control on '/' symbol
|
|
478
|
+
line.pop_back();
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
if (last == '\\') { // '\\' changes the default action
|
|
482
|
+
line.pop_back();
|
|
483
|
+
multiline_input = !multiline_input;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
line += '\n';
|
|
487
|
+
|
|
488
|
+
// By default, continue input if multiline_input is set
|
|
489
|
+
return multiline_input;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
bool readline(std::string & line, bool multiline_input) {
|
|
493
|
+
set_display(user_input);
|
|
494
|
+
|
|
495
|
+
if (simple_io) {
|
|
496
|
+
return readline_simple(line, multiline_input);
|
|
497
|
+
}
|
|
498
|
+
return readline_advanced(line, multiline_input);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Console functions
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
namespace console {
|
|
8
|
+
enum display_t {
|
|
9
|
+
reset = 0,
|
|
10
|
+
prompt,
|
|
11
|
+
user_input,
|
|
12
|
+
error
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
void init(bool use_simple_io, bool use_advanced_display);
|
|
16
|
+
void cleanup();
|
|
17
|
+
void set_display(display_t display);
|
|
18
|
+
bool readline(std::string & line, bool multiline_input);
|
|
19
|
+
}
|