Skip to content

Commit

Permalink
Improved shell copy paste (#2930)
Browse files Browse the repository at this point in the history
I have read and agree to the CLA of the Kuzu repository.
  • Loading branch information
MSebanc committed Feb 22, 2024
1 parent 5f7ab4e commit 93fc6e2
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 18 deletions.
35 changes: 35 additions & 0 deletions tools/shell/embedded_shell.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "embedded_shell.h"

#ifndef _WIN32
#include <termios.h>
#include <unistd.h>
#endif
#include <algorithm>
Expand Down Expand Up @@ -77,6 +78,11 @@ const int defaultMaxRows = 20;

static Connection* globalConnection;

#ifndef _WIN32
struct termios orig_termios;
bool noEcho = false;
#endif

void EmbeddedShell::updateTableNames() {
nodeTableNames.clear();
relTableNames.clear();
Expand Down Expand Up @@ -258,6 +264,25 @@ void EmbeddedShell::run() {
std::stringstream ss;
const char ctrl_c = '\3';
int numCtrlC = 0;

#ifndef _WIN32
struct termios raw;
if (isatty(STDIN_FILENO)) {
if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) {
errno = ENOTTY;
return;
}
raw = orig_termios;
raw.c_lflag &= ~ECHO;

if (tcsetattr(STDIN_FILENO, TCSANOW, &raw) < 0) {
errno = ENOTTY;
return;
}
noEcho = true;
}
#endif

while ((line = linenoise(continueLine ? ALTPROMPT : PROMPT)) != nullptr) {
auto lineStr = std::string(line);
lineStr = lineStr.erase(lineStr.find_last_not_of(" \t\n\r\f\v") + 1);
Expand Down Expand Up @@ -306,10 +331,20 @@ void EmbeddedShell::run() {
linenoiseHistorySave(path_to_history);
free(line);
}
#ifndef _WIN32
/* Don't even check the return value as it's too late. */
if (noEcho && tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios) != -1)
noEcho = false;
#endif
}

void EmbeddedShell::interruptHandler(int /*signal*/) {
globalConnection->interrupt();
#ifndef _WIN32
/* Don't even check the return value as it's too late. */
if (noEcho && tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios) != -1)
noEcho = false;
#endif
}

void EmbeddedShell::setMaxRows(const std::string& maxRowsString) {
Expand Down
51 changes: 33 additions & 18 deletions tools/shell/linenoise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ struct linenoiseState {
size_t maxrows; /* Maximum num of rows used so far (multiline mode) */
int history_index; /* The history index we are currently editing. */
bool search; /* Whether or not we are searching our history */
bool render; /* Whether or not to re-render */
bool hasMoreData; /* Whether or not there is more data available in the buffer (copy+paste)*/
std::string search_buf; //! The search buffer
std::vector<searchMatch> search_matches; //! The set of search matches in our history
std::string prev_search_match; //! The previous search match
Expand Down Expand Up @@ -850,6 +852,10 @@ static void truncateText(char*& buf, size_t& len, size_t pos, size_t cols, size_
* Rewrite the currently edited line accordingly to the buffer content,
* cursor position, and number of columns of the terminal. */
static void refreshSingleLine(struct linenoiseState* l) {
if (!l->render) {
return;
}

char seq[64];
uint32_t plen = linenoiseComputeRenderWidth(l->prompt, strlen(l->prompt));
int fd = l->ofd;
Expand Down Expand Up @@ -1368,11 +1374,15 @@ bool pastedInput(int ifd) {
int isPasted = select(0, &readfds, NULL, NULL, NULL);
return (isPasted != 0 && isPasted != SOCKET_ERROR);
#else
struct pollfd fd {
ifd, POLLIN, 0
};
int isPasted = poll(&fd, 1, 0);
return (isPasted != 0);
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(ifd, &rfds);

// no timeout: return immediately
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
return select(1, &rfds, NULL, NULL, &tv);
#endif
}

Expand Down Expand Up @@ -1534,27 +1544,21 @@ static char linenoiseSearch(linenoiseState *l, char c) {
*
* On error writing to the terminal -1 is returned, otherwise 0. */
int linenoiseEditInsert(struct linenoiseState* l, char c) {
if (l->hasMoreData) {
l->render = false;
}
if (l->len < l->buflen) {
if (l->len == l->pos) {
l->buf[l->pos] = c;
l->pos++;
l->len++;
l->buf[l->len] = '\0';
if ((!mlmode && l->plen + l->len < l->cols && !hintsCallback)) {
/* Avoid a full update of the line in the
* trivial case. */
if (write(l->ofd, &c, 1) == -1)
return -1;
} else {
refreshLine(l);
}
} else {
memmove(l->buf + l->pos + 1, l->buf + l->pos, l->len - l->pos);
l->buf[l->pos] = c;
l->len++;
l->pos++;
l->buf[l->len] = '\0';
refreshLine(l);
}
}
refreshLine(l);
Expand Down Expand Up @@ -1736,6 +1740,8 @@ static int linenoiseEdit(
l.maxrows = 0;
l.history_index = 0;
l.search = false;
l.render = true;
l.hasMoreData = false;

/* Buffer starts empty. */
l.buf[0] = '\0';
Expand All @@ -1762,7 +1768,11 @@ static int linenoiseEdit(
if (nread <= 0)
return l.len;

l.cols = getColumns(stdin_fd, stdout_fd);
l.hasMoreData = pastedInput(l.ifd);
l.render = true;
if (!l.hasMoreData) {
l.cols = getColumns(stdin_fd, stdout_fd);
}

if (l.search) {
char ret = linenoiseSearch(&l, c);
Expand All @@ -1778,7 +1788,7 @@ static int linenoiseEdit(
* there was an error reading from fd. Otherwise it will return the
* character that should be handled next. */
if (c == TAB && completionCallback != NULL) {
if (pastedInput(l.ifd)) {
if (l.hasMoreData) {
for (int i = 0; i < 4; i++) {
if (linenoiseEditInsert(&l, ' '))
return -1;
Expand All @@ -1793,6 +1803,7 @@ static int linenoiseEdit(
if (c == 0)
continue;
}

switch (c) {
case CTRL_G:
case CTRL_C: /* ctrl-c */
Expand Down Expand Up @@ -1827,6 +1838,8 @@ static int linenoiseEdit(
hintsCallback = NULL;
refreshLine(&l);
hintsCallback = hc;
} else {
refreshLine(&l);
}
return (int)l.len;
case BACKSPACE: /* backspace */
Expand Down Expand Up @@ -2005,7 +2018,7 @@ static int linenoiseEdit(
default:
if (linenoiseEditInsert(&l, c))
return -1;
if (strlen(l.buf) > buflen - 2 && pastedInput(l.ifd)) {
if (strlen(l.buf) > buflen - 2 && l.hasMoreData) {
history_len--;
free(history[history_len]);
if (mlmode)
Expand All @@ -2017,6 +2030,8 @@ static int linenoiseEdit(
hintsCallback = NULL;
refreshLine(&l);
hintsCallback = hc;
} else {
refreshLine(&l);
}
return (int)l.len;
}
Expand Down Expand Up @@ -2319,7 +2334,7 @@ int linenoiseHistoryLoad(const char* filename) {
buf[LINENOISE_MAX_LINE] = '\0';

if (fp == NULL)
return -1;
return -1;

std::string result;
while (fgets(buf, LINENOISE_MAX_LINE, fp) != NULL) {
Expand Down

0 comments on commit 93fc6e2

Please sign in to comment.