@fugood/llama.node 0.3.9 → 0.3.11
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/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/linux-cuda/arm64/llama-node.node +0 -0
- package/bin/linux-cuda/x64/llama-node.node +0 -0
- package/bin/linux-vulkan/arm64/llama-node.node +0 -0
- package/bin/linux-vulkan/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/bin/win32-vulkan/arm64/llama-node.node +0 -0
- package/bin/win32-vulkan/arm64/node.lib +0 -0
- package/bin/win32-vulkan/x64/llama-node.node +0 -0
- package/bin/win32-vulkan/x64/node.lib +0 -0
- package/lib/binding.js +2 -2
- package/lib/binding.ts +47 -8
- package/lib/index.js +21 -1
- package/lib/index.ts +31 -1
- package/package.json +12 -3
- package/src/LlamaCompletionWorker.cpp +33 -6
- package/src/LlamaCompletionWorker.h +3 -1
- package/src/LlamaContext.cpp +336 -28
- package/src/LlamaContext.h +2 -0
- package/src/common.hpp +19 -2
- package/src/llama.cpp/.github/workflows/build.yml +289 -107
- package/src/llama.cpp/.github/workflows/close-issue.yml +1 -1
- package/src/llama.cpp/.github/workflows/docker.yml +2 -1
- package/src/llama.cpp/.github/workflows/server.yml +25 -2
- package/src/llama.cpp/CMakeLists.txt +10 -19
- package/src/llama.cpp/cmake/build-info.cmake +1 -1
- package/src/llama.cpp/common/CMakeLists.txt +32 -0
- package/src/llama.cpp/common/arg.cpp +66 -16
- package/src/llama.cpp/common/chat-template.hpp +515 -0
- package/src/llama.cpp/common/chat.cpp +966 -0
- package/src/llama.cpp/common/chat.hpp +52 -0
- package/src/llama.cpp/common/common.cpp +159 -36
- package/src/llama.cpp/common/common.h +56 -14
- package/src/llama.cpp/common/json-schema-to-grammar.cpp +46 -66
- package/src/llama.cpp/common/json-schema-to-grammar.h +15 -1
- package/src/llama.cpp/common/llguidance.cpp +270 -0
- package/src/llama.cpp/common/log.cpp +1 -10
- package/src/llama.cpp/common/log.h +10 -0
- package/src/llama.cpp/common/minja.hpp +2868 -0
- package/src/llama.cpp/common/sampling.cpp +22 -1
- package/src/llama.cpp/common/sampling.h +3 -0
- package/src/llama.cpp/docs/build.md +54 -9
- package/src/llama.cpp/examples/export-lora/export-lora.cpp +12 -2
- package/src/llama.cpp/examples/gbnf-validator/gbnf-validator.cpp +1 -1
- package/src/llama.cpp/examples/llava/CMakeLists.txt +7 -0
- package/src/llama.cpp/examples/llava/clip-quantize-cli.cpp +59 -0
- package/src/llama.cpp/examples/llava/clip.cpp +133 -14
- package/src/llama.cpp/examples/llava/clip.h +2 -0
- package/src/llama.cpp/examples/llava/llava.cpp +22 -8
- package/src/llama.cpp/examples/llava/minicpmv-cli.cpp +9 -1
- package/src/llama.cpp/examples/main/main.cpp +26 -25
- package/src/llama.cpp/examples/run/linenoise.cpp/linenoise.cpp +136 -137
- package/src/llama.cpp/examples/run/linenoise.cpp/linenoise.h +18 -4
- package/src/llama.cpp/examples/run/run.cpp +224 -69
- package/src/llama.cpp/examples/server/server.cpp +252 -81
- package/src/llama.cpp/examples/server/utils.hpp +73 -21
- package/src/llama.cpp/examples/simple-chat/simple-chat.cpp +6 -4
- package/src/llama.cpp/examples/simple-cmake-pkg/CMakeLists.txt +11 -0
- package/src/llama.cpp/ggml/CMakeLists.txt +78 -1
- package/src/llama.cpp/ggml/include/ggml.h +1 -1
- package/src/llama.cpp/ggml/src/CMakeLists.txt +21 -4
- package/src/llama.cpp/ggml/src/ggml-alloc.c +1 -13
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-quants.c +91 -78
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.c +7 -7
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.cpp +2 -1
- package/src/llama.cpp/ggml/src/ggml-cuda/CMakeLists.txt +1 -1
- package/src/llama.cpp/ggml/src/ggml-cuda/vendors/hip.h +46 -0
- package/src/llama.cpp/ggml/src/ggml-hip/CMakeLists.txt +16 -1
- package/src/llama.cpp/ggml/src/ggml-musa/CMakeLists.txt +1 -1
- package/src/llama.cpp/ggml/src/ggml-rpc/ggml-rpc.cpp +28 -8
- package/src/llama.cpp/ggml/src/ggml-sycl/ggml-sycl.cpp +5 -7
- package/src/llama.cpp/ggml/src/ggml-sycl/softmax.cpp +33 -23
- package/src/llama.cpp/ggml/src/ggml-sycl/softmax.hpp +1 -5
- package/src/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp +323 -121
- package/src/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +13 -3
- package/src/llama.cpp/ggml/src/ggml.c +23 -13
- package/src/llama.cpp/include/llama.h +14 -1
- package/src/llama.cpp/models/ggml-vocab-deepseek-r1-qwen.gguf.inp +112 -0
- package/src/llama.cpp/models/ggml-vocab-deepseek-r1-qwen.gguf.out +46 -0
- package/src/llama.cpp/src/CMakeLists.txt +1 -1
- package/src/llama.cpp/src/llama-arch.cpp +7 -2
- package/src/llama.cpp/src/llama-arch.h +3 -1
- package/src/llama.cpp/src/llama-chat.cpp +11 -2
- package/src/llama.cpp/src/llama-chat.h +1 -0
- package/src/llama.cpp/src/llama-grammar.cpp +86 -6
- package/src/llama.cpp/src/llama-grammar.h +22 -1
- package/src/llama.cpp/src/llama-mmap.cpp +1 -0
- package/src/llama.cpp/src/llama-model-loader.cpp +1 -1
- package/src/llama.cpp/src/llama-model.cpp +76 -6
- package/src/llama.cpp/src/llama-sampling.cpp +47 -4
- package/src/llama.cpp/src/llama-vocab.cpp +10 -4
- package/src/llama.cpp/src/llama.cpp +181 -123
- package/src/llama.cpp/tests/CMakeLists.txt +4 -0
- package/src/llama.cpp/tests/test-backend-ops.cpp +158 -57
- package/src/llama.cpp/tests/test-chat-template.cpp +154 -31
- package/src/llama.cpp/tests/test-chat.cpp +607 -0
- package/src/llama.cpp/tests/test-grammar-integration.cpp +2 -2
- package/src/llama.cpp/tests/test-grammar-llguidance.cpp +1140 -0
- package/src/llama.cpp/tests/test-json-schema-to-grammar.cpp +1 -1
- package/src/llama.cpp/examples/main-cmake-pkg/CMakeLists.txt +0 -32
|
@@ -140,6 +140,9 @@ static void process_image(struct llava_context * ctx_llava, struct llava_image_e
|
|
|
140
140
|
else if (has_minicpmv_projector == 3) {
|
|
141
141
|
system_prompt = "<|im_start|>user\n";
|
|
142
142
|
}
|
|
143
|
+
else if (has_minicpmv_projector == 4) {
|
|
144
|
+
system_prompt = "<|im_start|>user\n";
|
|
145
|
+
}
|
|
143
146
|
LOG_INF("%s: image token past: %d\n", __func__, n_past);
|
|
144
147
|
eval_string(ctx_llava->ctx_llama, (system_prompt+"<image>").c_str(), params->n_batch, &n_past, false);
|
|
145
148
|
process_eval_image_embed(ctx_llava, embeds, params->n_batch, &n_past, idx++);
|
|
@@ -227,6 +230,9 @@ static struct common_sampler * llama_init(struct llava_context * ctx_llava, comm
|
|
|
227
230
|
else if (has_minicpmv_projector == 3) {
|
|
228
231
|
user_prompt = "<|im_start|>user\n" + prompt;
|
|
229
232
|
}
|
|
233
|
+
else if (has_minicpmv_projector == 4) {
|
|
234
|
+
user_prompt = "<|im_start|>user\n" + prompt;
|
|
235
|
+
}
|
|
230
236
|
}
|
|
231
237
|
|
|
232
238
|
eval_string(ctx_llava->ctx_llama, user_prompt.c_str(), params->n_batch, &n_past, false);
|
|
@@ -236,6 +242,9 @@ static struct common_sampler * llama_init(struct llava_context * ctx_llava, comm
|
|
|
236
242
|
else if (has_minicpmv_projector == 3) {
|
|
237
243
|
eval_string(ctx_llava->ctx_llama, "<|im_end|><|im_start|>assistant\n", params->n_batch, &n_past, false);
|
|
238
244
|
}
|
|
245
|
+
else if (has_minicpmv_projector == 4) {
|
|
246
|
+
eval_string(ctx_llava->ctx_llama, "<|im_end|><|im_start|>assistant\n", params->n_batch, &n_past, false);
|
|
247
|
+
}
|
|
239
248
|
|
|
240
249
|
// generate the response
|
|
241
250
|
|
|
@@ -308,7 +317,6 @@ int main(int argc, char ** argv) {
|
|
|
308
317
|
const auto * tmp = llama_loop(ctx_llava, smpl, n_past);
|
|
309
318
|
response += tmp;
|
|
310
319
|
if (strcmp(tmp, "</s>") == 0) break;
|
|
311
|
-
if (strstr(tmp, "###")) break; // Yi-VL behavior
|
|
312
320
|
printf("%s", tmp);// mistral llava-1.6
|
|
313
321
|
if (strstr(response.c_str(), "<user>")) break; // minicpm-v
|
|
314
322
|
fflush(stdout);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include "log.h"
|
|
5
5
|
#include "sampling.h"
|
|
6
6
|
#include "llama.h"
|
|
7
|
+
#include "chat-template.hpp"
|
|
7
8
|
|
|
8
9
|
#include <cstdio>
|
|
9
10
|
#include <cstring>
|
|
@@ -84,14 +85,6 @@ static void sigint_handler(int signo) {
|
|
|
84
85
|
}
|
|
85
86
|
#endif
|
|
86
87
|
|
|
87
|
-
static std::string chat_add_and_format(struct llama_model * model, std::vector<common_chat_msg> & chat_msgs, const std::string & role, const std::string & content) {
|
|
88
|
-
common_chat_msg new_msg{role, content};
|
|
89
|
-
auto formatted = common_chat_format_single(model, g_params->chat_template, chat_msgs, new_msg, role == "user");
|
|
90
|
-
chat_msgs.push_back({role, content});
|
|
91
|
-
LOG_DBG("formatted: '%s'\n", formatted.c_str());
|
|
92
|
-
return formatted;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
88
|
int main(int argc, char ** argv) {
|
|
96
89
|
common_params params;
|
|
97
90
|
g_params = ¶ms;
|
|
@@ -165,6 +158,7 @@ int main(int argc, char ** argv) {
|
|
|
165
158
|
}
|
|
166
159
|
|
|
167
160
|
const llama_vocab * vocab = llama_model_get_vocab(model);
|
|
161
|
+
auto chat_templates = common_chat_templates_from_model(model, params.chat_template);
|
|
168
162
|
|
|
169
163
|
LOG_INF("%s: llama threadpool init, n_threads = %d\n", __func__, (int) params.cpuparams.n_threads);
|
|
170
164
|
|
|
@@ -207,7 +201,7 @@ int main(int argc, char ** argv) {
|
|
|
207
201
|
}
|
|
208
202
|
|
|
209
203
|
// auto enable conversation mode if chat template is available
|
|
210
|
-
const bool has_chat_template =
|
|
204
|
+
const bool has_chat_template = chat_templates.has_explicit_template && chat_templates.template_default;
|
|
211
205
|
if (params.conversation_mode == COMMON_CONVERSATION_MODE_AUTO) {
|
|
212
206
|
if (has_chat_template) {
|
|
213
207
|
LOG_INF("%s: chat template is available, enabling conversation mode (disable it with -no-cnv)\n", __func__);
|
|
@@ -225,7 +219,7 @@ int main(int argc, char ** argv) {
|
|
|
225
219
|
// print chat template example in conversation mode
|
|
226
220
|
if (params.conversation_mode) {
|
|
227
221
|
if (params.enable_chat_template) {
|
|
228
|
-
LOG_INF("%s: chat template example:\n%s\n", __func__, common_chat_format_example(
|
|
222
|
+
LOG_INF("%s: chat template example:\n%s\n", __func__, common_chat_format_example(*chat_templates.template_default, params.use_jinja).c_str());
|
|
229
223
|
} else {
|
|
230
224
|
LOG_INF("%s: in-suffix/prefix is specified, chat template will be disabled\n", __func__);
|
|
231
225
|
}
|
|
@@ -260,7 +254,7 @@ int main(int argc, char ** argv) {
|
|
|
260
254
|
}
|
|
261
255
|
}
|
|
262
256
|
|
|
263
|
-
const bool add_bos = llama_vocab_get_add_bos(vocab);
|
|
257
|
+
const bool add_bos = llama_vocab_get_add_bos(vocab) && !params.use_jinja;
|
|
264
258
|
if (!llama_model_has_encoder(model)) {
|
|
265
259
|
GGML_ASSERT(!llama_vocab_get_add_eos(vocab));
|
|
266
260
|
}
|
|
@@ -269,10 +263,18 @@ int main(int argc, char ** argv) {
|
|
|
269
263
|
|
|
270
264
|
std::vector<llama_token> embd_inp;
|
|
271
265
|
|
|
266
|
+
auto chat_add_and_format = [&chat_msgs, &chat_templates](const std::string & role, const std::string & content) {
|
|
267
|
+
common_chat_msg new_msg{role, content, {}};
|
|
268
|
+
auto formatted = common_chat_format_single(*chat_templates.template_default, chat_msgs, new_msg, role == "user", g_params->use_jinja);
|
|
269
|
+
chat_msgs.push_back({role, content, {}});
|
|
270
|
+
LOG_DBG("formatted: '%s'\n", formatted.c_str());
|
|
271
|
+
return formatted;
|
|
272
|
+
};
|
|
273
|
+
|
|
272
274
|
{
|
|
273
275
|
auto prompt = (params.conversation_mode && params.enable_chat_template)
|
|
274
276
|
// format the system prompt in conversation mode (fallback to default if empty)
|
|
275
|
-
? chat_add_and_format(
|
|
277
|
+
? chat_add_and_format("system", params.prompt.empty() ? DEFAULT_SYSTEM_MESSAGE : params.prompt)
|
|
276
278
|
// otherwise use the prompt as is
|
|
277
279
|
: params.prompt;
|
|
278
280
|
if (params.interactive_first || !params.prompt.empty() || session_tokens.empty()) {
|
|
@@ -501,12 +503,14 @@ int main(int argc, char ** argv) {
|
|
|
501
503
|
|
|
502
504
|
std::vector<llama_token> embd;
|
|
503
505
|
|
|
504
|
-
//
|
|
505
|
-
std::vector<
|
|
506
|
+
// single-token antiprompts
|
|
507
|
+
std::vector<llama_token> antiprompt_token;
|
|
506
508
|
|
|
507
|
-
antiprompt_ids.reserve(params.antiprompt.size());
|
|
508
509
|
for (const std::string & antiprompt : params.antiprompt) {
|
|
509
|
-
|
|
510
|
+
auto ids = ::common_tokenize(ctx, antiprompt, false, true);
|
|
511
|
+
if (ids.size() == 1) {
|
|
512
|
+
antiprompt_token.push_back(ids[0]);
|
|
513
|
+
}
|
|
510
514
|
}
|
|
511
515
|
|
|
512
516
|
if (llama_model_has_encoder(model)) {
|
|
@@ -751,14 +755,11 @@ int main(int argc, char ** argv) {
|
|
|
751
755
|
|
|
752
756
|
// check for reverse prompt using special tokens
|
|
753
757
|
llama_token last_token = common_sampler_last(smpl);
|
|
754
|
-
|
|
755
|
-
if (
|
|
756
|
-
|
|
757
|
-
is_interacting = true;
|
|
758
|
-
}
|
|
759
|
-
is_antiprompt = true;
|
|
760
|
-
break;
|
|
758
|
+
if (std::find(antiprompt_token.begin(), antiprompt_token.end(), last_token) != antiprompt_token.end()) {
|
|
759
|
+
if (params.interactive) {
|
|
760
|
+
is_interacting = true;
|
|
761
761
|
}
|
|
762
|
+
is_antiprompt = true;
|
|
762
763
|
}
|
|
763
764
|
|
|
764
765
|
if (is_antiprompt) {
|
|
@@ -779,7 +780,7 @@ int main(int argc, char ** argv) {
|
|
|
779
780
|
}
|
|
780
781
|
|
|
781
782
|
if (params.enable_chat_template) {
|
|
782
|
-
chat_add_and_format(
|
|
783
|
+
chat_add_and_format("assistant", assistant_ss.str());
|
|
783
784
|
}
|
|
784
785
|
is_interacting = true;
|
|
785
786
|
LOG("\n");
|
|
@@ -844,7 +845,7 @@ int main(int argc, char ** argv) {
|
|
|
844
845
|
|
|
845
846
|
bool format_chat = params.conversation_mode && params.enable_chat_template;
|
|
846
847
|
std::string user_inp = format_chat
|
|
847
|
-
? chat_add_and_format(
|
|
848
|
+
? chat_add_and_format("user", std::move(buffer))
|
|
848
849
|
: std::move(buffer);
|
|
849
850
|
// TODO: one inconvenient of current chat template implementation is that we can't distinguish between user input and special tokens (prefix/postfix)
|
|
850
851
|
const auto line_pfx = common_tokenize(ctx, params.input_prefix, false, true);
|
|
@@ -103,24 +103,26 @@
|
|
|
103
103
|
*
|
|
104
104
|
*/
|
|
105
105
|
|
|
106
|
-
#include
|
|
107
|
-
|
|
108
|
-
#include <
|
|
109
|
-
#include <
|
|
110
|
-
#include <
|
|
111
|
-
#include <string.h>
|
|
112
|
-
#include <
|
|
113
|
-
#include <
|
|
114
|
-
#include <sys/stat.h>
|
|
115
|
-
#include <sys/types.h>
|
|
116
|
-
#include <
|
|
117
|
-
#include <unistd.h>
|
|
118
|
-
|
|
119
|
-
#include
|
|
120
|
-
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
|
|
106
|
+
# include "linenoise.h"
|
|
107
|
+
|
|
108
|
+
# include <ctype.h>
|
|
109
|
+
# include <errno.h>
|
|
110
|
+
# include <stdio.h>
|
|
111
|
+
# include <string.h>
|
|
112
|
+
# include <sys/file.h>
|
|
113
|
+
# include <sys/ioctl.h>
|
|
114
|
+
# include <sys/stat.h>
|
|
115
|
+
# include <sys/types.h>
|
|
116
|
+
# include <termios.h>
|
|
117
|
+
# include <unistd.h>
|
|
118
|
+
|
|
119
|
+
# include <memory>
|
|
120
|
+
# include <string>
|
|
121
|
+
# include <vector>
|
|
122
|
+
|
|
123
|
+
# define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
|
|
124
|
+
# define LINENOISE_MAX_LINE 4096
|
|
125
|
+
static std::vector<const char *> unsupported_term = { "dumb", "cons25", "emacs" };
|
|
124
126
|
static linenoiseCompletionCallback *completionCallback = NULL;
|
|
125
127
|
static linenoiseHintsCallback *hintsCallback = NULL;
|
|
126
128
|
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
|
|
@@ -166,21 +168,58 @@ int linenoiseHistoryAdd(const char *line);
|
|
|
166
168
|
#define REFRESH_ALL (REFRESH_CLEAN|REFRESH_WRITE) // Do both.
|
|
167
169
|
static void refreshLine(struct linenoiseState *l);
|
|
168
170
|
|
|
171
|
+
class File {
|
|
172
|
+
public:
|
|
173
|
+
FILE * file = nullptr;
|
|
174
|
+
|
|
175
|
+
FILE * open(const std::string & filename, const char * mode) {
|
|
176
|
+
file = fopen(filename.c_str(), mode);
|
|
177
|
+
|
|
178
|
+
return file;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
int lock() {
|
|
182
|
+
if (file) {
|
|
183
|
+
fd = fileno(file);
|
|
184
|
+
if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
|
|
185
|
+
fd = -1;
|
|
186
|
+
|
|
187
|
+
return 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
~File() {
|
|
195
|
+
if (fd >= 0) {
|
|
196
|
+
flock(fd, LOCK_UN);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (file) {
|
|
200
|
+
fclose(file);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private:
|
|
205
|
+
int fd = -1;
|
|
206
|
+
};
|
|
207
|
+
|
|
169
208
|
__attribute__((format(printf, 1, 2)))
|
|
170
209
|
/* Debugging function. */
|
|
171
210
|
#if 0
|
|
172
211
|
static void lndebug(const char *fmt, ...) {
|
|
173
|
-
static
|
|
174
|
-
if (
|
|
175
|
-
|
|
212
|
+
static File file;
|
|
213
|
+
if (file.file == nullptr) {
|
|
214
|
+
file.open("/tmp/lndebug.txt", "a");
|
|
176
215
|
}
|
|
177
216
|
|
|
178
|
-
if (
|
|
217
|
+
if (file.file != nullptr) {
|
|
179
218
|
va_list args;
|
|
180
219
|
va_start(args, fmt);
|
|
181
|
-
vfprintf(
|
|
220
|
+
vfprintf(file.file, fmt, args);
|
|
182
221
|
va_end(args);
|
|
183
|
-
fflush(
|
|
222
|
+
fflush(file.file);
|
|
184
223
|
}
|
|
185
224
|
}
|
|
186
225
|
#else
|
|
@@ -213,8 +252,11 @@ void linenoiseSetMultiLine(int ml) {
|
|
|
213
252
|
static int isUnsupportedTerm(void) {
|
|
214
253
|
char *term = getenv("TERM");
|
|
215
254
|
if (term == NULL) return 0;
|
|
216
|
-
for (
|
|
217
|
-
if (!strcasecmp(term, unsupported_term[j]))
|
|
255
|
+
for (size_t j = 0; j < unsupported_term.size(); ++j) {
|
|
256
|
+
if (!strcasecmp(term, unsupported_term[j])) {
|
|
257
|
+
return 1;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
218
260
|
return 0;
|
|
219
261
|
}
|
|
220
262
|
|
|
@@ -334,17 +376,6 @@ static void linenoiseBeep(void) {
|
|
|
334
376
|
fflush(stderr);
|
|
335
377
|
}
|
|
336
378
|
|
|
337
|
-
/* ============================== Completion ================================ */
|
|
338
|
-
|
|
339
|
-
/* Free a list of completion option populated by linenoiseAddCompletion(). */
|
|
340
|
-
static void freeCompletions(linenoiseCompletions *lc) {
|
|
341
|
-
size_t i;
|
|
342
|
-
for (i = 0; i < lc->len; i++)
|
|
343
|
-
free(lc->cvec[i]);
|
|
344
|
-
if (lc->cvec != NULL)
|
|
345
|
-
free(lc->cvec);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
379
|
/* Called by completeLine() and linenoiseShow() to render the current
|
|
349
380
|
* edited line with the proposed completion. If the current completion table
|
|
350
381
|
* is already available, it is passed as second argument, otherwise the
|
|
@@ -353,9 +384,9 @@ static void freeCompletions(linenoiseCompletions *lc) {
|
|
|
353
384
|
* Flags are the same as refreshLine*(), that is REFRESH_* macros. */
|
|
354
385
|
static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseCompletions *lc, int flags) {
|
|
355
386
|
/* Obtain the table of completions if the caller didn't provide one. */
|
|
356
|
-
linenoiseCompletions ctable
|
|
387
|
+
linenoiseCompletions ctable;
|
|
357
388
|
if (lc == NULL) {
|
|
358
|
-
completionCallback(ls->buf
|
|
389
|
+
completionCallback(ls->buf, &ctable);
|
|
359
390
|
lc = &ctable;
|
|
360
391
|
}
|
|
361
392
|
|
|
@@ -364,16 +395,17 @@ static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseComple
|
|
|
364
395
|
struct linenoiseState saved = *ls;
|
|
365
396
|
ls->len = ls->pos = strlen(lc->cvec[ls->completion_idx]);
|
|
366
397
|
ls->buf = lc->cvec[ls->completion_idx];
|
|
367
|
-
refreshLineWithFlags(ls,flags);
|
|
398
|
+
refreshLineWithFlags(ls, flags);
|
|
368
399
|
ls->len = saved.len;
|
|
369
400
|
ls->pos = saved.pos;
|
|
370
401
|
ls->buf = saved.buf;
|
|
371
402
|
} else {
|
|
372
|
-
refreshLineWithFlags(ls,flags);
|
|
403
|
+
refreshLineWithFlags(ls, flags);
|
|
373
404
|
}
|
|
374
405
|
|
|
375
|
-
|
|
376
|
-
|
|
406
|
+
if (lc == &ctable) {
|
|
407
|
+
ctable.to_free = false;
|
|
408
|
+
}
|
|
377
409
|
}
|
|
378
410
|
|
|
379
411
|
/* This is an helper function for linenoiseEdit*() and is called when the
|
|
@@ -391,11 +423,11 @@ static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseComple
|
|
|
391
423
|
* possible completions, and the caller should read for the next characters
|
|
392
424
|
* from stdin. */
|
|
393
425
|
static int completeLine(struct linenoiseState *ls, int keypressed) {
|
|
394
|
-
linenoiseCompletions lc
|
|
426
|
+
linenoiseCompletions lc;
|
|
395
427
|
int nwritten;
|
|
396
428
|
char c = keypressed;
|
|
397
429
|
|
|
398
|
-
completionCallback(ls->buf
|
|
430
|
+
completionCallback(ls->buf, &lc);
|
|
399
431
|
if (lc.len == 0) {
|
|
400
432
|
linenoiseBeep();
|
|
401
433
|
ls->in_completion = 0;
|
|
@@ -406,7 +438,7 @@ static int completeLine(struct linenoiseState *ls, int keypressed) {
|
|
|
406
438
|
ls->in_completion = 1;
|
|
407
439
|
ls->completion_idx = 0;
|
|
408
440
|
} else {
|
|
409
|
-
ls->completion_idx = (ls->completion_idx+1) % (lc.len+1);
|
|
441
|
+
ls->completion_idx = (ls->completion_idx + 1) % (lc.len + 1);
|
|
410
442
|
if (ls->completion_idx == lc.len) linenoiseBeep();
|
|
411
443
|
}
|
|
412
444
|
c = 0;
|
|
@@ -420,8 +452,7 @@ static int completeLine(struct linenoiseState *ls, int keypressed) {
|
|
|
420
452
|
default:
|
|
421
453
|
/* Update buffer and return */
|
|
422
454
|
if (ls->completion_idx < lc.len) {
|
|
423
|
-
nwritten = snprintf(ls->buf,ls->buflen,"%s",
|
|
424
|
-
lc.cvec[ls->completion_idx]);
|
|
455
|
+
nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[ls->completion_idx]);
|
|
425
456
|
ls->len = ls->pos = nwritten;
|
|
426
457
|
}
|
|
427
458
|
ls->in_completion = 0;
|
|
@@ -430,13 +461,12 @@ static int completeLine(struct linenoiseState *ls, int keypressed) {
|
|
|
430
461
|
|
|
431
462
|
/* Show completion or original buffer */
|
|
432
463
|
if (ls->in_completion && ls->completion_idx < lc.len) {
|
|
433
|
-
refreshLineWithCompletion(ls
|
|
464
|
+
refreshLineWithCompletion(ls, &lc, REFRESH_ALL);
|
|
434
465
|
} else {
|
|
435
466
|
refreshLine(ls);
|
|
436
467
|
}
|
|
437
468
|
}
|
|
438
469
|
|
|
439
|
-
freeCompletions(&lc);
|
|
440
470
|
return c; /* Return last read character */
|
|
441
471
|
}
|
|
442
472
|
|
|
@@ -462,53 +492,25 @@ void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
|
|
|
462
492
|
* user typed <tab>. See the example.c source code for a very easy to
|
|
463
493
|
* understand example. */
|
|
464
494
|
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
|
|
465
|
-
size_t len
|
|
466
|
-
char
|
|
467
|
-
|
|
468
|
-
copy = (char*) malloc(len + 1);
|
|
469
|
-
if (copy == NULL) return;
|
|
470
|
-
memcpy(copy,str,len+1);
|
|
471
|
-
cvec = (char**) realloc(lc->cvec,sizeof(char*)*(lc->len+1));
|
|
472
|
-
if (cvec == NULL) {
|
|
473
|
-
free(copy);
|
|
495
|
+
const size_t len = strlen(str);
|
|
496
|
+
auto copy = std::make_unique<char[]>(len + 1);
|
|
497
|
+
if (!copy) {
|
|
474
498
|
return;
|
|
475
499
|
}
|
|
476
|
-
lc->cvec = cvec;
|
|
477
|
-
lc->cvec[lc->len++] = copy;
|
|
478
|
-
}
|
|
479
500
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
* output in a single call, to avoid flickering effects. */
|
|
486
|
-
struct abuf {
|
|
487
|
-
char *b;
|
|
488
|
-
int len;
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
static void abInit(struct abuf *ab) {
|
|
492
|
-
ab->b = NULL;
|
|
493
|
-
ab->len = 0;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
static void abAppend(struct abuf *ab, const char *s, int len) {
|
|
497
|
-
char *new_ptr = (char*) realloc(ab->b,ab->len+len);
|
|
498
|
-
|
|
499
|
-
if (new_ptr == NULL) return;
|
|
500
|
-
memcpy(new_ptr+ab->len,s,len);
|
|
501
|
-
ab->b = new_ptr;
|
|
502
|
-
ab->len += len;
|
|
503
|
-
}
|
|
501
|
+
memcpy(copy.get(), str, len + 1);
|
|
502
|
+
char ** cvec = static_cast<char **>(std::realloc(lc->cvec, sizeof(char *) * (lc->len + 1)));
|
|
503
|
+
if (cvec == nullptr) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
504
506
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
+
lc->cvec = cvec;
|
|
508
|
+
lc->cvec[lc->len++] = copy.release();
|
|
507
509
|
}
|
|
508
510
|
|
|
509
511
|
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
|
|
510
512
|
* to the right of the prompt. */
|
|
511
|
-
static void refreshShowHints(
|
|
513
|
+
static void refreshShowHints(std::string & ab, struct linenoiseState * l, int plen) {
|
|
512
514
|
char seq[64];
|
|
513
515
|
if (hintsCallback && plen+l->len < l->cols) {
|
|
514
516
|
int color = -1, bold = 0;
|
|
@@ -522,10 +524,11 @@ static void refreshShowHints(struct abuf * ab, struct linenoiseState * l, int pl
|
|
|
522
524
|
snprintf(seq,64,"\033[%d;%d;49m",bold,color);
|
|
523
525
|
else
|
|
524
526
|
seq[0] = '\0';
|
|
525
|
-
|
|
526
|
-
|
|
527
|
+
ab.append(seq);
|
|
528
|
+
ab.append(hint, hintlen);
|
|
527
529
|
if (color != -1 || bold != 0)
|
|
528
|
-
|
|
530
|
+
ab.append("\033[0m");
|
|
531
|
+
|
|
529
532
|
/* Call the function to free the hint returned. */
|
|
530
533
|
if (freeHintsCallback) freeHintsCallback(hint);
|
|
531
534
|
}
|
|
@@ -546,8 +549,7 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) {
|
|
|
546
549
|
char *buf = l->buf;
|
|
547
550
|
size_t len = l->len;
|
|
548
551
|
size_t pos = l->pos;
|
|
549
|
-
|
|
550
|
-
|
|
552
|
+
std::string ab;
|
|
551
553
|
while((plen+pos) >= l->cols) {
|
|
552
554
|
buf++;
|
|
553
555
|
len--;
|
|
@@ -557,35 +559,34 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) {
|
|
|
557
559
|
len--;
|
|
558
560
|
}
|
|
559
561
|
|
|
560
|
-
abInit(&ab);
|
|
561
562
|
/* Cursor to left edge */
|
|
562
563
|
snprintf(seq,sizeof(seq),"\r");
|
|
563
|
-
|
|
564
|
+
ab.append(seq);
|
|
564
565
|
|
|
565
566
|
if (flags & REFRESH_WRITE) {
|
|
566
567
|
/* Write the prompt and the current buffer content */
|
|
567
|
-
|
|
568
|
+
ab.append(l->prompt);
|
|
568
569
|
if (maskmode == 1) {
|
|
569
|
-
while (len--)
|
|
570
|
+
while (len--) {
|
|
571
|
+
ab.append("*");
|
|
572
|
+
}
|
|
570
573
|
} else {
|
|
571
|
-
|
|
574
|
+
ab.append(buf, len);
|
|
572
575
|
}
|
|
573
576
|
/* Show hits if any. */
|
|
574
|
-
refreshShowHints(
|
|
577
|
+
refreshShowHints(ab, l, plen);
|
|
575
578
|
}
|
|
576
579
|
|
|
577
580
|
/* Erase to right */
|
|
578
581
|
snprintf(seq,sizeof(seq),"\x1b[0K");
|
|
579
|
-
|
|
580
|
-
|
|
582
|
+
ab.append(seq);
|
|
581
583
|
if (flags & REFRESH_WRITE) {
|
|
582
584
|
/* Move cursor to original position. */
|
|
583
585
|
snprintf(seq,sizeof(seq),"\r\x1b[%dC", (int)(pos+plen));
|
|
584
|
-
|
|
586
|
+
ab.append(seq);
|
|
585
587
|
}
|
|
586
588
|
|
|
587
|
-
|
|
588
|
-
abFree(&ab);
|
|
589
|
+
(void) !write(fd, ab.c_str(), ab.size()); /* Can't recover from write error. */
|
|
589
590
|
}
|
|
590
591
|
|
|
591
592
|
/* Multi line low level line refresh.
|
|
@@ -604,26 +605,23 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
|
|
604
605
|
int col; /* colum position, zero-based. */
|
|
605
606
|
int old_rows = l->oldrows;
|
|
606
607
|
int fd = l->ofd, j;
|
|
607
|
-
|
|
608
|
-
|
|
608
|
+
std::string ab;
|
|
609
609
|
l->oldrows = rows;
|
|
610
610
|
|
|
611
611
|
/* First step: clear all the lines used before. To do so start by
|
|
612
612
|
* going to the last row. */
|
|
613
|
-
abInit(&ab);
|
|
614
|
-
|
|
615
613
|
if (flags & REFRESH_CLEAN) {
|
|
616
614
|
if (old_rows-rpos > 0) {
|
|
617
615
|
lndebug("go down %d", old_rows-rpos);
|
|
618
616
|
snprintf(seq,64,"\x1b[%dB", old_rows-rpos);
|
|
619
|
-
|
|
617
|
+
ab.append(seq);
|
|
620
618
|
}
|
|
621
619
|
|
|
622
620
|
/* Now for every row clear it, go up. */
|
|
623
621
|
for (j = 0; j < old_rows-1; j++) {
|
|
624
622
|
lndebug("clear+up");
|
|
625
623
|
snprintf(seq,64,"\r\x1b[0K\x1b[1A");
|
|
626
|
-
|
|
624
|
+
ab.append(seq);
|
|
627
625
|
}
|
|
628
626
|
}
|
|
629
627
|
|
|
@@ -631,21 +629,22 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
|
|
631
629
|
/* Clean the top line. */
|
|
632
630
|
lndebug("clear");
|
|
633
631
|
snprintf(seq,64,"\r\x1b[0K");
|
|
634
|
-
|
|
632
|
+
ab.append(seq);
|
|
635
633
|
}
|
|
636
634
|
|
|
637
635
|
if (flags & REFRESH_WRITE) {
|
|
638
636
|
/* Write the prompt and the current buffer content */
|
|
639
|
-
|
|
637
|
+
ab.append(l->prompt);
|
|
640
638
|
if (maskmode == 1) {
|
|
641
|
-
unsigned int i;
|
|
642
|
-
|
|
639
|
+
for (unsigned int i = 0; i < l->len; ++i) {
|
|
640
|
+
ab.append("*");
|
|
641
|
+
}
|
|
643
642
|
} else {
|
|
644
|
-
|
|
643
|
+
ab.append(l->buf, l->len);
|
|
645
644
|
}
|
|
646
645
|
|
|
647
646
|
/* Show hits if any. */
|
|
648
|
-
refreshShowHints(
|
|
647
|
+
refreshShowHints(ab, l, plen);
|
|
649
648
|
|
|
650
649
|
/* If we are at the very end of the screen with our prompt, we need to
|
|
651
650
|
* emit a newline and move the prompt to the first column. */
|
|
@@ -654,9 +653,9 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
|
|
654
653
|
(l->pos+plen) % l->cols == 0)
|
|
655
654
|
{
|
|
656
655
|
lndebug("<newline>");
|
|
657
|
-
|
|
656
|
+
ab.append("\n");
|
|
658
657
|
snprintf(seq,64,"\r");
|
|
659
|
-
|
|
658
|
+
ab.append(seq);
|
|
660
659
|
rows++;
|
|
661
660
|
if (rows > (int)l->oldrows) l->oldrows = rows;
|
|
662
661
|
}
|
|
@@ -669,7 +668,7 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
|
|
669
668
|
if (rows-rpos2 > 0) {
|
|
670
669
|
lndebug("go-up %d", rows-rpos2);
|
|
671
670
|
snprintf(seq,64,"\x1b[%dA", rows-rpos2);
|
|
672
|
-
|
|
671
|
+
ab.append(seq);
|
|
673
672
|
}
|
|
674
673
|
|
|
675
674
|
/* Set column. */
|
|
@@ -679,14 +678,12 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
|
|
679
678
|
snprintf(seq,64,"\r\x1b[%dC", col);
|
|
680
679
|
else
|
|
681
680
|
snprintf(seq,64,"\r");
|
|
682
|
-
|
|
681
|
+
ab.append(seq);
|
|
683
682
|
}
|
|
684
683
|
|
|
685
684
|
lndebug("\n");
|
|
686
685
|
l->oldpos = l->pos;
|
|
687
|
-
|
|
688
|
-
if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
|
|
689
|
-
abFree(&ab);
|
|
686
|
+
(void) !write(fd, ab.c_str(), ab.size()); /* Can't recover from write error. */
|
|
690
687
|
}
|
|
691
688
|
|
|
692
689
|
/* Calls the two low level functions refreshSingleLine() or
|
|
@@ -1313,16 +1310,17 @@ int linenoiseHistorySetMaxLen(int len) {
|
|
|
1313
1310
|
* otherwise -1 is returned. */
|
|
1314
1311
|
int linenoiseHistorySave(const char *filename) {
|
|
1315
1312
|
mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
fp = fopen(filename,"w");
|
|
1313
|
+
File file;
|
|
1314
|
+
file.open(filename, "w");
|
|
1320
1315
|
umask(old_umask);
|
|
1321
|
-
if (
|
|
1316
|
+
if (file.file == NULL) {
|
|
1317
|
+
return -1;
|
|
1318
|
+
}
|
|
1322
1319
|
chmod(filename,S_IRUSR|S_IWUSR);
|
|
1323
|
-
for (j = 0; j < history_len; j
|
|
1324
|
-
fprintf(
|
|
1325
|
-
|
|
1320
|
+
for (int j = 0; j < history_len; ++j) {
|
|
1321
|
+
fprintf(file.file, "%s\n", history[j]);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1326
1324
|
return 0;
|
|
1327
1325
|
}
|
|
1328
1326
|
|
|
@@ -1332,12 +1330,14 @@ int linenoiseHistorySave(const char *filename) {
|
|
|
1332
1330
|
* If the file exists and the operation succeeded 0 is returned, otherwise
|
|
1333
1331
|
* on error -1 is returned. */
|
|
1334
1332
|
int linenoiseHistoryLoad(const char *filename) {
|
|
1335
|
-
|
|
1333
|
+
File file;
|
|
1334
|
+
file.open(filename, "r");
|
|
1336
1335
|
char buf[LINENOISE_MAX_LINE];
|
|
1336
|
+
if (file.file == NULL) {
|
|
1337
|
+
return -1;
|
|
1338
|
+
}
|
|
1337
1339
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
|
|
1340
|
+
while (fgets(buf, LINENOISE_MAX_LINE, file.file) != NULL) {
|
|
1341
1341
|
char *p;
|
|
1342
1342
|
|
|
1343
1343
|
p = strchr(buf,'\r');
|
|
@@ -1345,7 +1345,6 @@ int linenoiseHistoryLoad(const char *filename) {
|
|
|
1345
1345
|
if (p) *p = '\0';
|
|
1346
1346
|
linenoiseHistoryAdd(buf);
|
|
1347
1347
|
}
|
|
1348
|
-
fclose(fp);
|
|
1349
1348
|
return 0;
|
|
1350
1349
|
}
|
|
1351
1350
|
#endif
|