bim: more search improvements

This commit is contained in:
K. Lange 2022-08-13 13:46:23 +09:00
parent 0c66bce50a
commit 50f2ab2bcf
2 changed files with 121 additions and 61 deletions

View File

@ -16,7 +16,7 @@
*/
#include "bim.h"
#define BIM_VERSION "3.0.0" TAG
#define BIM_VERSION "3.1.0" TAG
#define BIM_COPYRIGHT "Copyright 2012-2021 K. Lange <\033[3mklange@toaruos.org\033[23m>"
#include <kuroko/kuroko.h>
@ -42,6 +42,7 @@ global_config_t global_config = {
.command_offset = 0,
.command_col_no = 0,
.history_point = -1,
.search_point = -1,
/* Bitset starts here */
.highlight_on_open = 1,
.initial_file_is_read_only = 0,
@ -4757,7 +4758,7 @@ int subsearch_matches(line_t * line, int j, uint32_t * needle, int ignorecase, i
/**
* Replace text on a given line with other text.
*/
void perform_replacement(int line_no, uint32_t * needle, uint32_t * replacement, int col, int ignorecase, int *out_col) {
void perform_replacement(int line_no, uint32_t * needle, uint32_t * replacement, int col, int ignorecase, int *out_col, int *line_out) {
line_t * line = env->lines[line_no-1];
int j = col;
while (j < line->actual + 1) {
@ -4800,6 +4801,14 @@ void perform_replacement(int line_no, uint32_t * needle, uint32_t * replacement,
}
t += refs[i].len;
rep = 0;
} else if (*r == '\\' && (r[1] == 'n')) {
++r;
env->lines = split_line(env->lines, line_no - 1, j + t);
line_no++;
line = env->lines[line_no-1];
j = 0;
t = 0;
continue;
}
if (rep) {
_c.codepoint = rep;
@ -4813,6 +4822,7 @@ void perform_replacement(int line_no, uint32_t * needle, uint32_t * replacement,
}
}
*out_col = j + t;
*line_out = line_no;
set_modified();
for (int i = 0; i < MAX_REFS; ++i) {
@ -4828,6 +4838,7 @@ void perform_replacement(int line_no, uint32_t * needle, uint32_t * replacement,
#define COMMAND_HISTORY_MAX 255
unsigned char * command_history[COMMAND_HISTORY_MAX] = {NULL};
unsigned char * search_history[COMMAND_HISTORY_MAX] = {NULL};
/**
* Add a command to the history. If that command was
@ -4835,12 +4846,12 @@ unsigned char * command_history[COMMAND_HISTORY_MAX] = {NULL};
* otherwise, the whole list is shifted backwards and
* overflow is freed up.
*/
void insert_command_history(char * cmd) {
void insert_command_history(unsigned char ** which_history, char * cmd) {
/* See if this is already in the history. */
size_t amount_to_shift = COMMAND_HISTORY_MAX - 1;
for (int i = 0; i < COMMAND_HISTORY_MAX && command_history[i]; ++i) {
if (!strcmp((char*)command_history[i], cmd)) {
free(command_history[i]);
for (int i = 0; i < COMMAND_HISTORY_MAX && which_history[i]; ++i) {
if (!strcmp((char*)which_history[i], cmd)) {
free(which_history[i]);
amount_to_shift = i;
break;
}
@ -4848,13 +4859,13 @@ void insert_command_history(char * cmd) {
/* Remove last entry that will roll off the stack */
if (amount_to_shift == COMMAND_HISTORY_MAX - 1) {
if (command_history[COMMAND_HISTORY_MAX-1]) free(command_history[COMMAND_HISTORY_MAX-1]);
if (which_history[COMMAND_HISTORY_MAX-1]) free(which_history[COMMAND_HISTORY_MAX-1]);
}
/* Roll the history */
memmove(&command_history[1], &command_history[0], sizeof(char *) * (amount_to_shift));
memmove(&which_history[1], &which_history[0], sizeof(char *) * (amount_to_shift));
command_history[0] = (unsigned char*)strdup(cmd);
which_history[0] = (unsigned char*)strdup(cmd);
}
static uint32_t term_colors[] = {
@ -5317,11 +5328,20 @@ int replace_text(int range_top, int range_bot, char divider, char * needle) {
for (int line = range_top; line <= range_bot; ++line) {
int col = 0;
while (col != -1) {
perform_replacement(line, needle_c, replacement_c, col, case_insensitive, &col);
int _line = line;
perform_replacement(line, needle_c, replacement_c, col, case_insensitive, &col, &_line);
if (col != -1) replacements++;
if (_line > line) {
range_bot += _line - line;
line = _line;
}
if (!global) break;
}
}
if (env->mode == MODE_LINE_SELECTION) {
env->start_line = env->start_line < env->line_no ? range_top : range_bot;
env->line_no = env->start_line < env->line_no ? range_bot : range_top;
}
free(needle_c);
free(replacement_c);
if (replacements) {
@ -6619,24 +6639,6 @@ done:
#define _syn_command() do { env->syntax = global_config.command_syn; } while (0)
#define _syn_restore() do { env->syntax = global_config.command_syn_back; } while (0)
#define _restore_history(point) do { \
unsigned char * t = command_history[point]; \
global_config.command_col_no = 1; \
global_config.command_buffer->actual = 0; \
_syn_command(); \
uint32_t state = 0; \
uint32_t c = 0; \
while (*t) { \
if (!decode(&state, &c, *t)) { \
char_t _c = {codepoint_width(c), 0, c}; \
global_config.command_buffer = line_insert(global_config.command_buffer, _c, global_config.command_col_no - 1, -1); \
global_config.command_col_no++; \
} else if (state == UTF8_REJECT) state = 0; \
t++; \
} \
_syn_restore(); \
} while (0)
/**
* Draw the command buffer and any prefix.
*/
@ -6749,10 +6751,7 @@ BIM_ACTION(enter_command, 0,
render_command_input_buffer();
}
BIM_ACTION(command_accept, 0,
"Accept the command input and run the requested command."
)(void) {
/* Convert command buffer to UTF-8 char-array string */
static char * command_buffer_to_utf8(void) {
size_t size = 0;
for (int i = 0; i < global_config.command_buffer->actual; ++i) {
char tmp[8] = {0};
@ -6764,6 +6763,14 @@ BIM_ACTION(command_accept, 0,
t += to_eight(global_config.command_buffer->text[i].codepoint, t);
}
*t = '\0';
return tmp;
}
BIM_ACTION(command_accept, 0,
"Accept the command input and run the requested command."
)(void) {
/* Convert command buffer to UTF-8 char-array string */
char * tmp = command_buffer_to_utf8();
/* Free the original editing buffer */
free(global_config.command_buffer);
@ -6771,7 +6778,7 @@ BIM_ACTION(command_accept, 0,
/* Run the converted command */
global_config.break_from_selection = 0;
insert_command_history(tmp);
insert_command_history(command_history, tmp);
global_config.overlay_mode = OVERLAY_MODE_NONE;
process_command(tmp);
free(tmp);
@ -6853,26 +6860,54 @@ BIM_ACTION(command_backspace, 0,
global_config.command_offset = 0;
}
BIM_ACTION(command_scroll_history, ARG_IS_CUSTOM,
"Scroll through command input history."
)(int direction) {
static void _restore_history(unsigned char **which_history, int point) {
unsigned char * t = which_history[point];
global_config.command_col_no = 1;
global_config.command_buffer->actual = 0;
_syn_command();
uint32_t state = 0;
uint32_t c = 0;
while (*t) {
if (!decode(&state, &c, *t)) {
char_t _c = {codepoint_width(c), 0, c};
global_config.command_buffer = line_insert(global_config.command_buffer, _c, global_config.command_col_no - 1, -1);
global_config.command_col_no++;
} else if (state == UTF8_REJECT) state = 0;
t++;
}
_syn_restore();
}
static void _scroll_history(int direction, unsigned char **which_history, int * which_point) {
if (direction == -1) {
if (command_history[global_config.history_point+1]) {
_restore_history(global_config.history_point+1);
global_config.history_point++;
if (which_history[*which_point+1]) {
_restore_history(which_history, *which_point+1);
(*which_point)++;
}
} else {
if (global_config.history_point > 0) {
global_config.history_point--;
_restore_history(global_config.history_point);
if (*which_point > 0) {
(*which_point)--;
_restore_history(which_history, *which_point);
} else {
global_config.history_point = -1;
*which_point = -1;
global_config.command_col_no = 1;
global_config.command_buffer->actual = 0;
}
}
}
BIM_ACTION(command_scroll_history, ARG_IS_CUSTOM,
"Scroll through command input history."
)(int direction) {
_scroll_history(direction, command_history, &global_config.history_point);
}
BIM_ACTION(command_scroll_search_history, ARG_IS_CUSTOM,
"Scroll through search input history."
)(int direction) {
_scroll_history(direction, search_history, &global_config.search_point);
}
BIM_ACTION(command_word_left, 0,
"Move to the start of the previous word in the input buffer."
)(void) {
@ -7192,6 +7227,10 @@ BIM_ACTION(search_accept, 0,
}
global_config.search[global_config.command_buffer->actual] = 0;
char * tmp = command_buffer_to_utf8();
insert_command_history(search_history, tmp);
free(tmp);
_finish:
/* Free the original editing buffer */
free(global_config.command_buffer);
@ -8747,6 +8786,18 @@ BIM_ACTION(insert_char_at_column, ARG_IS_INPUT | ACTION_IS_RW,
place_cursor_actual();
}
BIM_ACTION(insert_tab_at_column, ACTION_IS_RW,
"Insert an indentation character on multiple lines."
)(void) {
if (env->tabs) {
insert_char_at_column('\t');
} else {
for (int i = 0; i < env->tabstop; ++i) {
insert_char_at_column(' ');
}
}
}
BIM_ACTION(enter_col_insert, ACTION_IS_RW,
"Enter column insert mode."
)(void) {
@ -9168,13 +9219,20 @@ _finish_completion:
* some effort when trying to search for things we pulled from the outside world.
* (eg., ctags search terms)
*/
void set_search_from_bytes(char * bytes) {
static void set_search_from_bytes(char * bytes) {
if (global_config.search) free(global_config.search);
global_config.search = malloc(sizeof(uint32_t) * (strlen(bytes) + 1));
global_config.search = malloc(sizeof(uint32_t) * (strlen(bytes) * 2 + 1));
uint32_t * s = global_config.search;
char * tmp = bytes;
uint32_t c, istate = 0;
while (*tmp) {
if (strchr("\\.()[]+*?", *tmp)) {
*s++ = '\\';
*s++ = *tmp;
*s = 0;
tmp++;
continue;
}
if (!decode(&istate, &c, *tmp)) {
*s = c;
s++;
@ -9186,6 +9244,15 @@ void set_search_from_bytes(char * bytes) {
}
}
static void _perform_correct_search(struct completion_match * matches, int i) {
if (matches[i].search[0] == '/') {
set_search_from_bytes(&matches[i].search[1]);
search_next();
} else {
goto_line(atoi(matches[i].search));
}
}
BIM_ACTION(goto_definition, 0,
"Jump to the definition of the word under under cursor."
)(void) {
@ -9208,22 +9275,13 @@ BIM_ACTION(goto_definition, 0,
goto _done;
}
#define _perform_correct_search(i) do { \
if (matches[i].search[0] == '/') { \
set_search_from_bytes(&matches[i].search[1]); \
search_next(); \
} else { \
goto_line(atoi(matches[i].search)); \
} \
} while (0)
if (env->file_name && !strcmp(matches[0].file, env->file_name)) {
_perform_correct_search(0);
_perform_correct_search(matches, 0);
} else {
/* Check if there were other matches that are in this file */
for (int i =1; env->file_name && i < matches_count; ++i) {
if (!strcmp(matches[i].file, env->file_name)) {
_perform_correct_search(i);
_perform_correct_search(matches, i);
goto _done;
}
}
@ -9233,7 +9291,7 @@ BIM_ACTION(goto_definition, 0,
if (left_buffer && buffers[i] != left_buffer && buffers[i] != right_buffer) unsplit();
env = buffers[i];
redraw_tabbar();
_perform_correct_search(i);
_perform_correct_search(matches, i);
goto _done;
}
}
@ -9241,7 +9299,7 @@ BIM_ACTION(goto_definition, 0,
buffer_t * old_buf = env;
open_file(matches[0].file);
if (env != old_buf) {
_perform_correct_search(0);
_perform_correct_search(matches, 0);
} else {
render_error("Could not locate file containing definition");
}
@ -9832,6 +9890,7 @@ struct action_map _COL_INSERT_MAP[] = {
{KEY_ENTER, NULL, 0, 0},
{KEY_CTRL_W, NULL, 0, 0},
{KEY_CTRL_V, insert_char_at_column, opt_char, 0},
{'\t', insert_tab_at_column, 0, 0},
{KEY_LEFT, column_left, 0, 0},
{KEY_RIGHT, column_right, 0, 0},
{KEY_UP, column_up, 0, 0},
@ -9934,8 +9993,8 @@ struct action_map _FILESEARCH_MAP[] = {
struct action_map _SEARCH_MAP[] = {
{KEY_ENTER, search_accept, 0, 0},
{KEY_UP, NULL, 0, 0},
{KEY_DOWN, NULL, 0, 0},
{KEY_UP, command_scroll_search_history, opt_arg, -1}, /* back */
{KEY_DOWN, command_scroll_search_history, opt_arg, 1}, /* forward */
{-1, NULL, 0, 0}
};
@ -10317,7 +10376,7 @@ void normal_mode(void) {
}
refresh = 0;
} else if (handle_action(COL_INSERT_MAP, key)) {
/* pass */
refresh = 2;
} else if (key < KEY_ESCAPE) {
insert_char_at_column(key);
refresh = 1;

View File

@ -177,6 +177,7 @@ typedef struct {
int command_offset, command_col_no;
struct syntax_definition * command_syn, * command_syn_back;
int history_point;
int search_point;
int search_direction;
int prev_line, prev_col, prev_coffset, prev_offset;