Index the cursor from the beginning instead of the end, which is easier
(at least for me) to think about.
This also fixes issues with Ctrl-W in the previous implementation.
| ... | ... |
@@ -95,8 +95,7 @@ static void draw(tty_interface_t *state) {
|
| 95 | 95 |
tty_moveup(tty, num_lines); |
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 |
- int length = strlen(options->prompt) + strlen(state->search); |
|
| 99 |
- tty_setcol(tty, length + state->offset); |
|
| 98 |
+ tty_setcol(tty, strlen(options->prompt) + state->cursor); |
|
| 100 | 99 |
tty_flush(tty); |
| 101 | 100 |
} |
| 102 | 101 |
|
| ... | ... |
@@ -135,26 +134,33 @@ static void action_emit(tty_interface_t *state) {
|
| 135 | 134 |
|
| 136 | 135 |
static void action_del_char(tty_interface_t *state) {
|
| 137 | 136 |
if (*state->search) {
|
| 138 |
- int length = strlen(state->search); |
|
| 139 |
- int index = length + state->offset - 1; |
|
| 140 |
- if (index < 0) {
|
|
| 137 |
+ size_t length = strlen(state->search); |
|
| 138 |
+ if(state->cursor == 0) {
|
|
| 141 | 139 |
return; |
| 142 | 140 |
} |
| 143 | 141 |
|
| 144 |
- memmove(&state->search[index], &state->search[index + 1], length - index); |
|
| 142 |
+ state->cursor--; |
|
| 143 |
+ memmove(&state->search[state->cursor], &state->search[state->cursor + 1], length - state->cursor); |
|
| 145 | 144 |
} |
| 146 | 145 |
} |
| 147 | 146 |
|
| 148 | 147 |
static void action_del_word(tty_interface_t *state) {
|
| 149 |
- size_t search_size = strlen(state->search); |
|
| 150 |
- if (search_size) |
|
| 151 |
- state->search[--search_size] = '\0'; |
|
| 152 |
- while (search_size && !isspace(state->search[--search_size])) |
|
| 153 |
- state->search[search_size] = '\0'; |
|
| 148 |
+ size_t original_cursor = state->cursor; |
|
| 149 |
+ size_t cursor = state->cursor; |
|
| 150 |
+ |
|
| 151 |
+ while (cursor && isspace(state->search[cursor - 1])) |
|
| 152 |
+ cursor--; |
|
| 153 |
+ |
|
| 154 |
+ while (cursor && !isspace(state->search[cursor - 1])) |
|
| 155 |
+ cursor--; |
|
| 156 |
+ |
|
| 157 |
+ memmove(&state->search[cursor], &state->search[original_cursor], strlen(state->search) - original_cursor + 1); |
|
| 158 |
+ state->cursor = cursor; |
|
| 154 | 159 |
} |
| 155 | 160 |
|
| 156 | 161 |
static void action_del_all(tty_interface_t *state) {
|
| 157 |
- strcpy(state->search, ""); |
|
| 162 |
+ memmove(state->search, &state->search[state->cursor], strlen(state->search) - state->cursor + 1); |
|
| 163 |
+ state->cursor = 0; |
|
| 158 | 164 |
} |
| 159 | 165 |
|
| 160 | 166 |
static void action_prev(tty_interface_t *state) {
|
| ... | ... |
@@ -172,21 +178,21 @@ static void action_next(tty_interface_t *state) {
|
| 172 | 178 |
} |
| 173 | 179 |
|
| 174 | 180 |
static void action_left(tty_interface_t *state) {
|
| 175 |
- if ((unsigned long)abs(state->offset) < strlen(state->search)) |
|
| 176 |
- state->offset--; |
|
| 181 |
+ if (state->cursor > 0) |
|
| 182 |
+ state->cursor--; |
|
| 177 | 183 |
} |
| 178 | 184 |
|
| 179 | 185 |
static void action_right(tty_interface_t *state) {
|
| 180 |
- if (state->offset < 0) |
|
| 181 |
- state->offset++; |
|
| 186 |
+ if (state->cursor < strlen(state->search)) |
|
| 187 |
+ state->cursor++; |
|
| 182 | 188 |
} |
| 183 | 189 |
|
| 184 | 190 |
static void action_beginning(tty_interface_t *state) {
|
| 185 |
- state->offset = -strlen(state->search); |
|
| 191 |
+ state->cursor = 0; |
|
| 186 | 192 |
} |
| 187 | 193 |
|
| 188 | 194 |
static void action_end(tty_interface_t *state) {
|
| 189 |
- state->offset = 0; |
|
| 195 |
+ state->cursor = strlen(state->search); |
|
| 190 | 196 |
} |
| 191 | 197 |
|
| 192 | 198 |
static void action_pageup(tty_interface_t *state) {
|
| ... | ... |
@@ -206,6 +212,7 @@ static void action_autocomplete(tty_interface_t *state) {
|
| 206 | 212 |
const char *current_selection = choices_get(state->choices, state->choices->selection); |
| 207 | 213 |
if (current_selection) {
|
| 208 | 214 |
strncpy(state->search, choices_get(state->choices, state->choices->selection), SEARCH_SIZE_MAX); |
| 215 |
+ state->cursor = strlen(state->search); |
|
| 209 | 216 |
} |
| 210 | 217 |
} |
| 211 | 218 |
|
| ... | ... |
@@ -220,14 +227,10 @@ static void append_search(tty_interface_t *state, char ch) {
|
| 220 | 227 |
char *search = state->search; |
| 221 | 228 |
size_t search_size = strlen(search); |
| 222 | 229 |
if (search_size < SEARCH_SIZE_MAX) {
|
| 223 |
- int location = state->offset + search_size; |
|
| 224 |
- for (int i = search_size; i >= 0; i--) {
|
|
| 225 |
- if (i >= location) {
|
|
| 226 |
- search[i + 1] = search[i]; |
|
| 227 |
- } |
|
| 228 |
- } |
|
| 230 |
+ memmove(&search[state->cursor+1], &search[state->cursor], search_size - state->cursor + 1); |
|
| 231 |
+ search[state->cursor] = ch; |
|
| 229 | 232 |
|
| 230 |
- search[location] = ch; |
|
| 233 |
+ state->cursor++; |
|
| 231 | 234 |
} |
| 232 | 235 |
} |
| 233 | 236 |
|
| ... | ... |
@@ -235,7 +238,6 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices, |
| 235 | 238 |
state->tty = tty; |
| 236 | 239 |
state->choices = choices; |
| 237 | 240 |
state->options = options; |
| 238 |
- state->offset = 0; |
|
| 239 | 241 |
|
| 240 | 242 |
strcpy(state->input, ""); |
| 241 | 243 |
strcpy(state->search, ""); |
| ... | ... |
@@ -246,6 +248,8 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices, |
| 246 | 248 |
if (options->init_search) |
| 247 | 249 |
strncpy(state->search, options->init_search, SEARCH_SIZE_MAX); |
| 248 | 250 |
|
| 251 |
+ state->cursor = strlen(state->search); |
|
| 252 |
+ |
|
| 249 | 253 |
update_search(state); |
| 250 | 254 |
} |
| 251 | 255 |
|