bim: more search improvements
This commit is contained in:
parent
0c66bce50a
commit
50f2ab2bcf
181
apps/bim.c
181
apps/bim.c
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user