should be it
This commit is contained in:
154
external/duckdb/tools/shell/linenoise/linenoise-c.cpp
vendored
Normal file
154
external/duckdb/tools/shell/linenoise/linenoise-c.cpp
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "linenoise.hpp"
|
||||
#include "linenoise.h"
|
||||
#include "history.hpp"
|
||||
#include "terminal.hpp"
|
||||
|
||||
using duckdb::History;
|
||||
using duckdb::idx_t;
|
||||
using duckdb::Linenoise;
|
||||
using duckdb::Terminal;
|
||||
|
||||
/* The high level function that is the main API of the linenoise library.
|
||||
* This function checks if the terminal has basic capabilities, just checking
|
||||
* for a blacklist of stupid terminals, and later either calls the line
|
||||
* editing function or uses dummy fgets() so that you will be able to type
|
||||
* something even in the most desperate of the conditions. */
|
||||
char *linenoise(const char *prompt) {
|
||||
char buf[LINENOISE_MAX_LINE];
|
||||
int count;
|
||||
|
||||
if (!Terminal::IsAtty()) {
|
||||
/* Not a tty: read from file / pipe. In this mode we don't want any
|
||||
* limit to the line size, so we call a function to handle that. */
|
||||
return Terminal::EditNoTTY();
|
||||
} else if (Terminal::IsUnsupportedTerm()) {
|
||||
size_t len;
|
||||
|
||||
printf("%s", prompt);
|
||||
fflush(stdout);
|
||||
if (fgets(buf, LINENOISE_MAX_LINE, stdin) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(buf);
|
||||
while (len && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
}
|
||||
return strdup(buf);
|
||||
} else {
|
||||
count = Terminal::EditRaw(buf, LINENOISE_MAX_LINE, prompt);
|
||||
if (count == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return strdup(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is just a wrapper the user may want to call in order to make sure
|
||||
* the linenoise returned buffer is freed with the same allocator it was
|
||||
* created with. Useful when the main program is using an alternative
|
||||
* allocator. */
|
||||
void linenoiseFree(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
/* ================================ History ================================= */
|
||||
|
||||
/* This is the API call to add a new entry in the linenoise history.
|
||||
* It uses a fixed array of char pointers that are shifted (memmoved)
|
||||
* when the history max length is reached in order to remove the older
|
||||
* entry and make room for the new one, so it is not exactly suitable for huge
|
||||
* histories, but will work well for a few hundred of entries.
|
||||
*
|
||||
* Using a circular buffer is smarter, but a bit more complex to handle. */
|
||||
int linenoiseHistoryAdd(const char *line) {
|
||||
return History::Add(line);
|
||||
}
|
||||
|
||||
/* Set the maximum length for the history. This function can be called even
|
||||
* if there is already some history, the function will make sure to retain
|
||||
* just the latest 'len' elements if the new history length value is smaller
|
||||
* than the amount of items already inside the history. */
|
||||
int linenoiseHistorySetMaxLen(int len) {
|
||||
if (len < 0) {
|
||||
return 0;
|
||||
}
|
||||
return History::SetMaxLength(idx_t(len));
|
||||
}
|
||||
|
||||
/* Save the history in the specified file. On success 0 is returned
|
||||
* otherwise -1 is returned. */
|
||||
int linenoiseHistorySave(const char *filename) {
|
||||
return History::Save(filename);
|
||||
}
|
||||
|
||||
/* Load the history from the specified file. If the file does not exist
|
||||
* zero is returned and no operation is performed.
|
||||
*
|
||||
* If the file exists and the operation succeeded 0 is returned, otherwise
|
||||
* on error -1 is returned. */
|
||||
int linenoiseHistoryLoad(const char *filename) {
|
||||
return History::Load(filename);
|
||||
}
|
||||
|
||||
/* Register a callback function to be called for tab-completion. */
|
||||
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
|
||||
Linenoise::SetCompletionCallback(fn);
|
||||
}
|
||||
|
||||
/* Register a hits function to be called to show hits to the user at the
|
||||
* right of the prompt. */
|
||||
void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
|
||||
Linenoise::SetHintsCallback(fn);
|
||||
}
|
||||
|
||||
/* Register a function to free the hints returned by the hints callback
|
||||
* registered with linenoiseSetHintsCallback(). */
|
||||
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
|
||||
Linenoise::SetFreeHintsCallback(fn);
|
||||
}
|
||||
|
||||
void linenoiseSetMultiLine(int ml) {
|
||||
Terminal::SetMultiLine(ml);
|
||||
}
|
||||
|
||||
void linenoiseSetPrompt(const char *continuation, const char *continuationSelected) {
|
||||
Linenoise::SetPrompt(continuation, continuationSelected);
|
||||
}
|
||||
|
||||
/* This function is used by the callback function registered by the user
|
||||
* in order to add completion options given the input string when the
|
||||
* user typed <tab>. See the example.c source code for a very easy to
|
||||
* understand example. */
|
||||
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
|
||||
size_t len = strlen(str);
|
||||
char *copy, **cvec;
|
||||
|
||||
copy = (char *)malloc(len + 1);
|
||||
if (copy == NULL)
|
||||
return;
|
||||
memcpy(copy, str, len + 1);
|
||||
cvec = (char **)realloc(lc->cvec, sizeof(char *) * (lc->len + 1));
|
||||
if (cvec == NULL) {
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
lc->cvec = cvec;
|
||||
lc->cvec[lc->len++] = copy;
|
||||
}
|
||||
|
||||
size_t linenoiseComputeRenderWidth(const char *buf, size_t len) {
|
||||
return Linenoise::ComputeRenderWidth(buf, len);
|
||||
}
|
||||
|
||||
int linenoiseGetRenderPosition(const char *buf, size_t len, int max_width, int *n) {
|
||||
return Linenoise::GetRenderPosition(buf, len, max_width, n);
|
||||
}
|
||||
|
||||
void linenoiseClearScreen(void) {
|
||||
Terminal::ClearScreen();
|
||||
}
|
||||
|
||||
int linenoiseParseOption(const char **azArg, int nArg, const char **out_error) {
|
||||
return Linenoise::ParseOption(azArg, nArg, out_error);
|
||||
}
|
||||
Reference in New Issue
Block a user