Skip to content

Commit

Permalink
fix backspace, move left, move right operations
Browse files Browse the repository at this point in the history
  • Loading branch information
anuchak committed Mar 22, 2023
1 parent 5ecb5eb commit 7d211e1
Showing 1 changed file with 53 additions and 91 deletions.
144 changes: 53 additions & 91 deletions tools/shell/linenoise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ struct linenoiseState {
size_t pos; /* Current cursor position. */
size_t oldpos; /* Previous refresh cursor position. */
size_t len; /* Current edited line length. */
size_t chars; /* Number of utf-8 chars in buffer. */
size_t totalUTF8Chars; /* Number of utf-8 chars in buffer. */
size_t cols; /* Number of columns in terminal. */
size_t maxrows; /* Maximum num of rows used so far (multiline mode) */
int history_index; /* The history index we are currently editing. */
Expand Down Expand Up @@ -190,8 +190,6 @@ static void refreshLine(struct linenoiseState* l);
std::string oldInput = "";
bool inputLeft;

std::string utf8store = "";

/* Debugging macro. */
#if 0
FILE *lndebug_fp = NULL;
Expand Down Expand Up @@ -569,22 +567,6 @@ uint32_t linenoiseComputeRenderWidth(const char* buf, size_t len) {
return renderWidth;
}

int getBufCharPos(struct linenoiseState* l) {
if (l->chars == 0) {
return l->pos;
}
if (l->pos == l->chars) {
return l->len;
}
size_t idx = 0;
size_t ctr = 0;
while (ctr < l->pos) {
idx = utf8proc_next_grapheme(l->buf, l->len, idx);
ctr++;
}
return idx;
}

/* Single line low level line refresh.
*
* Rewrite the currently edited line accordingly to the buffer content,
Expand All @@ -596,7 +578,7 @@ static void refreshSingleLine(struct linenoiseState* l) {
char buf[LINENOISE_MAX_LINE];
size_t len = l->len;
size_t pos = l->pos;
size_t chars = l->chars;
size_t chars = l->totalUTF8Chars;
struct abuf ab;
uint32_t renderWidth = 0;
uint32_t renderPos = 0;
Expand All @@ -616,7 +598,7 @@ static void refreshSingleLine(struct linenoiseState* l) {
posCounter++;
totalRenderWidth += charRenderWidth;
if (totalRenderWidth >= remainingRenderWidth) {
if (prevPos >= getBufCharPos(l)) {
if (prevPos >= pos) {
// We passed the cursor: break, we no longer need to render.
charPos = prevPos;
break;
Expand Down Expand Up @@ -794,91 +776,68 @@ bool pastedInput(int ifd) {
* On error writing to the terminal -1 is returned, otherwise 0. */
int linenoiseEditInsert(struct linenoiseState* l, char c) {
if (l->len < l->buflen) {
if (l->chars == l->pos) {
l->buf[l->len] = c;
if (l->len == l->pos) {
l->buf[l->pos] = c;
l->pos++;
l->len++;
l->buf[l->len] = '\0';

if ((!mlmode && !hintsCallback)) {
char d = (maskmode == 1) ? '*' : c;
if (!Utf8Proc::isValid(&d, 1)) {
utf8store += d;
if (Utf8Proc::isValid(utf8store.c_str(), utf8store.length())) {
utf8store = "";
l->chars++;
l->pos++;
}
} else {
if (l->plen + l->chars < l->cols) {
if (write(l->ofd, &d, 1) == -1)
return -1;
}
l->chars++;
l->pos++;
}
}
if (!pastedInput(l->ifd) && !inputLeft) {
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 {
if (!Utf8Proc::isValid(&c, 1)) {
utf8store += c;
l->len++;
}
if (Utf8Proc::isValid(utf8store.c_str(), utf8store.length())) {
uint32_t charLoc = getBufCharPos(l);
uint32_t charWidth = std::max((uint32_t)utf8store.length(), 1u);
memmove(l->buf + charLoc + charWidth, l->buf + charLoc, l->len - charLoc);
if (utf8store != "") {
for (auto i = 0u; i < utf8store.length(); i++) {
l->buf[charLoc + i] = utf8store[i];
}
utf8store = "";
l->pos++;
l->chars++;
l->buf[l->len] = '\0';
refreshLine(l);
} else {
l->buf[l->pos] = c;
l->len++;
l->pos++;
l->chars++;
l->buf[l->len] = '\0';
refreshLine(l);
}
}
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);
return 0;
}

static uint32_t prevChar(struct linenoiseState* l) {
return Utf8Proc::previousGraphemeCluster(l->buf, l->len, getBufCharPos(l));
return Utf8Proc::previousGraphemeCluster(l->buf, l->len, l->pos);
}

static uint32_t nextChar(struct linenoiseState* l) {
return utf8proc_next_grapheme(l->buf, l->len, getBufCharPos(l));
return utf8proc_next_grapheme(l->buf, l->len, l->pos);
}

/* Move cursor on the left. */
void linenoiseEditMoveLeft(struct linenoiseState* l) {
if (l->pos > 0) {
l->pos--;
l->pos = prevChar(l);
refreshLine(l);
}
}

/* Move cursor on the right. */
void linenoiseEditMoveRight(struct linenoiseState* l) {
if (l->pos != l->chars) {
l->pos++;
if (l->pos != l->len) {
l->pos = nextChar(l);
refreshLine(l);
}
}

/* Checks to see if character defines a separation between words */
bool isWordSeparator(char c) {
return (c == 0x20);
if (c >= 'a' && c <= 'z') {
return false;
}
if (c >= 'A' && c <= 'Z') {
return false;
}
if (c >= '0' && c <= '9') {
return false;
}
return true;
}

/* Move cursor one word to the left */
Expand All @@ -887,19 +846,19 @@ void linenoiseEditMoveWordLeft(struct linenoiseState* l) {
return;
}
do {
l->pos--;
} while (l->pos > 0 && !isWordSeparator(l->buf[getBufCharPos(l)]));
l->pos = prevChar(l);
} while (l->pos > 0 && !isWordSeparator(l->buf[l->pos]));
refreshLine(l);
}

/* Move cursor one word to the right */
void linenoiseEditMoveWordRight(struct linenoiseState* l) {
if (l->pos == l->chars) {
if (l->pos == l->len) {
return;
}
do {
l->pos++;
} while (l->pos != l->chars && !isWordSeparator(l->buf[getBufCharPos(l)]));
l->pos = nextChar(l);
} while (l->pos != l->len && !isWordSeparator(l->buf[l->pos]));
refreshLine(l);
}

Expand All @@ -913,8 +872,8 @@ void linenoiseEditMoveHome(struct linenoiseState* l) {

/* Move cursor to the end of the line. */
void linenoiseEditMoveEnd(struct linenoiseState* l) {
if (l->pos != l->chars) {
l->pos = l->chars;
if (l->pos != l->len) {
l->pos = l->len;
refreshLine(l);
}
}
Expand Down Expand Up @@ -950,10 +909,12 @@ void linenoiseEditHistoryNext(struct linenoiseState* l, int dir) {
void linenoiseEditDelete(struct linenoiseState* l) {
if (l->len > 0 && l->pos < l->len) {
uint32_t newPos = nextChar(l);
uint32_t oldPos = getBufCharPos(l);
uint32_t charSize = newPos - oldPos;
memmove(l->buf + oldPos, l->buf + newPos, l->len - oldPos);
uint32_t charSize = newPos - l->pos;
memmove(l->buf + l->pos, l->buf + newPos, l->len - newPos);
l->len -= charSize;
if(charSize > 1) {
l->totalUTF8Chars--;
}
l->buf[l->len] = '\0';
refreshLine(l);
}
Expand All @@ -963,12 +924,13 @@ void linenoiseEditDelete(struct linenoiseState* l) {
void linenoiseEditBackspace(struct linenoiseState* l) {
if (l->pos > 0 && l->len > 0) {
uint32_t newPos = prevChar(l);
uint32_t oldPos = getBufCharPos(l);
uint32_t charSize = oldPos - newPos;
memmove(l->buf + newPos, l->buf + oldPos, l->len - newPos);
uint32_t charSize = l->pos - newPos;
memmove(l->buf + newPos, l->buf + l->pos, l->len - l->pos);
l->len -= charSize;
l->pos--;
l->chars--;
l->pos = newPos;
if(charSize > 1) {
l->totalUTF8Chars--;
}
l->buf[l->len] = '\0';
refreshLine(l);
}
Expand Down Expand Up @@ -1012,7 +974,7 @@ static int linenoiseEdit(
l.plen = strlen(prompt);
l.oldpos = l.pos = 0;
l.len = 0;
l.chars = 0;
l.totalUTF8Chars = 0;
l.cols = getColumns(stdin_fd, stdout_fd);
l.maxrows = 0;
l.history_index = 0;
Expand Down

0 comments on commit 7d211e1

Please sign in to comment.