Repository: valkey-io/valkey
File: deps/linenoise/linenoise.c (C)

Code before:
    if (l->pos > 0) {
        l->pos--;
        refreshLine(l);
    }
}

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

/* Consider letters/digits/underscore as “word”; others as delimiters. */
static int isWordChar(char c) {
    return (c == '_' || (c >= '0' && c <= '9') ||
            (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
}

static void linenoiseEditMoveWordLeft(struct linenoiseState *l) {
    if (l->pos == 0) return;
    /* Move cursor to the left over any delimiters */
    while (l->pos > 0 && !isWordChar(l->buf[l->pos - 1])) l->pos--;
    /* Then continue moving over a word */
    while (l->pos > 0 && isWordChar(l->buf[l->pos - 1])) l->pos--;
    refreshLine(l);
}

static void linenoiseEditMoveWordRight(struct linenoiseState *l) {
    if (l->pos == l->len) return;
    /* Move cursor to the right over any delimiters */
    while (l->pos < l->len &&  isWordChar(l->buf[l->pos])) l->pos++;
    /* Then continue moving over a word */
    while (l->pos < l->len && !isWordChar(l->buf[l->pos])) l->pos++;
    refreshLine(l);
}


/* Move cursor to the start of the line. */
void linenoiseEditMoveHome(struct linenoiseState *l) {
    if (l->pos != 0) {
        l->pos = 0;
        refreshLine(l);
    }
}

/* Move cursor to the end of the line. */
void linenoiseEditMoveEnd(struct linenoiseState *l) {
    if (l->pos != l->len) {
        l->pos = l->len;

Review comment (suggestion):
```suggestion
    while (l->pos > 0 && l->isWordChar(l->buf[l->pos - 1])) l->pos--;
```
If we want to keep it generic, we might consider allowing linenoise to take in a callback for what a "word" is. 

Code after:
    if (l->pos > 0) {
        l->pos--;
        refreshLine(l);
    }
}

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

/* People have different preferences on what is considered a word
 * when editing commandline. For example, in command
 * `set business:department:product value`,
 * some might treat the entire long key as a word, while others
 * treat it as 3 subwords and prefer granular word jumping navigation
 * to make fixing a typo (e.g. "business:deaprtment:product") easier.
 * In order to accommodate this, we treat escape sequences
 * ESC b/f (usually Alt + ←/→ on MacOS, but you might get ESC[1;3D/C) and
 * ESC[1;5D/C (usually Ctrl + ←/→) differently.
 *
 * Notice that the exact behavior of key mapping depends on your
 * terminal/keyboard setup. To see how your environment maps keys
 * to escape sequences, you can run command `cat -v` and then press
 * arbitrary keys to see how they work.
 */
static int isSubWordDelimiter(const char c) {
    return !isalnum(c);
}
static int isBigWordDelimiter(const char c) {
    return isspace(c);
}

typedef int (*isDelimiterFunc)(char c);

static void linenoiseEditMoveWordLeft(struct linenoiseState *l, const isDelimiterFunc isDelimiter) {
    if (l->pos == 0) return;
    /* Move cursor to the left over any delimiters */
    while (l->pos > 0 && isDelimiter(l->buf[l->pos - 1])) l->pos--;
    /* Then continue moving over a word */
    while (l->pos > 0 && !isDelimiter(l->buf[l->pos - 1])) l->pos--;
    refreshLine(l);
}

static void linenoiseEditMoveWordRight(struct linenoiseState *l, const isDelimiterFunc isDelimiter) {
    if (l->pos == l->len) return;
    /* Move cursor to the right over any delimiters */
    while (l->pos < l->len && isDelimiter(l->buf[l->pos])) l->pos++;