se

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 0f1494bc0a8b07c352df0b20586b91f93efa2b71
parent 4809d6ddc1d90d01458206cf75a5385681822957
Author: Samdal <samdal@protonmail.com>
Date:   Sun, 23 Jan 2022 19:35:19 +0100

search in loaded buffers, search keyword in all open buffers

Diffstat:
A.seproj | 6++++++
Mconfig.def.c | 47++++++++++++++++++++++++++++++++++++-----------
Mse.c | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mse.h | 20++++++++++++++++++--
Mx.c | 127++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
5 files changed, 350 insertions(+), 65 deletions(-)

diff --git a/.seproj b/.seproj @@ -0,0 +1,6 @@ +se.c +se.h +x.c +x.h +config.c +config.mk diff --git a/config.def.c b/config.def.c @@ -84,11 +84,13 @@ static void move_cursor_to_offset(const Arg* arg); static void move_cursor_to_end_of_buffer(const Arg* arg); static void clipboard_copy(const Arg* arg); static void clipboard_paste(const Arg* arg); -static void search(const Arg* arg); static void undo(const Arg* arg); static void redo(const Arg* arg); +static void search(const Arg* arg); static void search_next(const Arg* arg); static void search_previous(const Arg* arg); +static void search_for_buffer(const Arg* arg); +static void search_keyword_in_buffers(const Arg* arg); static void open_file_browser(const Arg* arg); static void buffer_kill(const Arg* arg); @@ -140,6 +142,8 @@ const Shortcut shortcuts[] = { { TERMMOD, XK_Z, redo, {0} }, { ControlMask, XK_s, save_buffer, {0} }, { ControlMask, XK_f, search, {0} }, + { TERMMOD, XK_F, search_keyword_in_buffers,{0},}, + { ControlMask, XK_space, search_for_buffer,{0}, }, { ControlMask, XK_n, search_next, {0} }, { TERMMOD, XK_N, search_previous,{0} }, { ControlMask, XK_c, clipboard_copy, {0} }, @@ -322,14 +326,6 @@ clipboard_paste(const Arg* arg) } void -search(const Arg* arg) -{ - get_file_buffer(focused_window)->mode &= ~BUFFER_SEARCH_BLOCKING_IDLE; - get_file_buffer(focused_window)->mode |= BUFFER_SEARCH_BLOCKING; - writef_to_status_bar("search: %s", get_file_buffer(focused_window)->search_term); -} - -void undo(const Arg* arg) { buffer_undo(get_file_buffer(focused_window)); @@ -342,6 +338,14 @@ redo(const Arg* arg) } void +search(const Arg* arg) +{ + get_file_buffer(focused_window)->mode &= ~BUFFER_SEARCH_BLOCKING_IDLE; + get_file_buffer(focused_window)->mode |= BUFFER_SEARCH_BLOCKING; + writef_to_status_bar("search: %s", get_file_buffer(focused_window)->search_term); +} + +void search_next(const Arg* arg) { int new_offset = buffer_seek_string_wrap(focused_window, focused_window->cursor_offset+1, @@ -370,6 +374,27 @@ search_previous(const Arg* arg) } void +search_for_buffer(const Arg* arg) +{ + if (focused_window->mode != WINDOW_BUFFER_NORMAL) + return; + *focused_node->search = 0; + focused_node->selected = 0; + focused_window->mode = WINDOW_BUFFER_SEARCH_BUFFERS; +} + +void +search_keyword_in_buffers(const Arg* arg) +{ + if (focused_window->mode != WINDOW_BUFFER_NORMAL) + return; + *focused_node->search = 0; + focused_node->selected = 0; + focused_window->mode = WINDOW_BUFFER_KEYWORD_ALL_BUFFERS; +} + + +void open_file_browser(const Arg* arg) { int last_fb = focused_window->buffer_index; @@ -414,7 +439,7 @@ cursor_callback(struct window_buffer* buf, enum cursor_reason callback_reason) keep_cursor_col(buf, callback_reason); move_selection(buf, callback_reason); - printf("moved to: %d | reason: %d\n", buf->cursor_offset, callback_reason); + //printf("moved to: %d | reason: %d\n", buf->cursor_offset, callback_reason); } void @@ -519,6 +544,6 @@ void string_insert_callback(const char* buf, int buflen) window_move_all_cursors_on_same_buf(&root_node, NULL, focused_window->buffer_index, focused_window->cursor_offset, buffer_move_offset_relative, buflen, CURSOR_COMMAND_MOVEMENT); } else { - printf("unhandled control character %x\n", buf[0]); + writef_to_status_bar("unhandled control character 0x%x\n", buf[0]); } } diff --git a/se.c b/se.c @@ -58,12 +58,23 @@ extern void(*buffer_written_to_screen_callback)(struct window_buffer*, int, int, // Internal functions // +static void buffer_draw_to_screen(struct window_split_node* wn, int minx, int miny, int maxx, int maxy); +static void choose_one_of_selection(const char* prefix, const char* search, const char* err, + const char*(*get_next_element)(const char*, const char*, int* offset, Glyph* attr, void* data), + int* selected_line, int minx, int miny, int maxx, int maxy, int focused); +static void draw_dir(struct window_split_node* win, int minx, int miny, int maxx, int maxy, int focused); +static void draw_search_buffers(struct window_split_node* wn, int minx, int miny, int maxx, int maxy, int focused); +static void draw_search_keyword_in_all_buffers(struct window_split_node* wn, int minx, int miny, int maxx, int maxy, int focused); +void(*alternate_buffer_modes[WINDOW_BUFFER_MODE_LEN]) +(struct window_split_node* wn, int minx, int miny, int maxx, int maxy, int focused) = { + [WINDOW_BUFFER_NORMAL] = NULL, + [WINDOW_BUFFER_FILE_BROWSER] = draw_dir, + [WINDOW_BUFFER_SEARCH_BUFFERS] = draw_search_buffers, + [WINDOW_BUFFER_KEYWORD_ALL_BUFFERS] = draw_search_keyword_in_all_buffers +}; + static void recursive_mkdir(char* path); static int writef_string(int y, int x1, int x2, const char* fmt, ...); -void choose_one_of_selection(const char* prefix, const char* search, const char* err, - const char*(*get_next_element)(const char*, const char*, int* offset, Glyph* attr), - int* selected_line, int minx, int miny, int maxx, int maxy, int focused); -static void draw_dir(const char* path, const char* search, int* sel, int minx, int miny, int maxx, int maxy, int focused); static void color_selection(Glyph* letter); static void do_color_scheme(struct file_buffer* fb, const struct color_scheme* cs, int offset); static int str_contains_char(const char* string, char check); @@ -568,6 +579,8 @@ window_node_split(struct window_split_node* parent, float ratio, enum window_spl parent->node1 = xmalloc(sizeof(struct window_split_node)); parent->node2 = xmalloc(sizeof(struct window_split_node)); + parent->node1->search = xmalloc(SEARCH_TERM_MAX_LEN); + parent->node2->search = xmalloc(SEARCH_TERM_MAX_LEN); *parent->node1 = *parent; *parent->node2 = *parent; @@ -594,6 +607,7 @@ window_node_delete(struct window_split_node* node) struct window_split_node* old = node; node = node->parent; struct window_split_node* other = (node->node1 == old) ? node->node2 : node->node1; + free(old->search); free(old); struct window_split_node* parent = node->parent; @@ -614,7 +628,7 @@ window_draw_tree_to_screen(struct window_split_node* root, int minx, int miny, i assert(root); if (root->mode == WINDOW_SINGULAR) { - buffer_draw_to_screen(&root->window, minx, miny, maxx, maxy); + buffer_draw_to_screen(root, minx, miny, maxx, maxy); } else if (root->mode == WINDOW_HORISONTAL) { int middlex = ((float)(maxx - minx) * root->ratio) + minx; @@ -772,7 +786,7 @@ file_path_get_path(const char* path) } const char* -file_browser_next_item(const char* path, const char* search, int* offset, Glyph* attr) +file_browser_next_item(const char* path, const char* search, int* offset, Glyph* attr, void* data) { static char filename_search[PATH_MAX]; static char filename[PATH_MAX]; @@ -837,12 +851,126 @@ file_browser_next_item(const char* path, const char* search, int* offset, Glyph* return NULL; } +const char* +buffer_search_next_item(const char* tmp, const char* search, int* offset, Glyph* attr, void* data) +{ + static struct window_buffer wb; + static char file_path[PATH_MAX]; + static int quit_next = 0; + if (!tmp || !search) { + wb.buffer_index = 0; + quit_next = 0; + return NULL; + } + + int len = strlen(search); + for(;;) { + if (quit_next) { + wb.buffer_index = 0; + quit_next = 0; + return NULL; + } + struct file_buffer* fb = get_file_buffer(&wb); + int last_buffer_index = wb.buffer_index; + wb.buffer_index++; + get_file_buffer(&wb); + if (wb.buffer_index <= last_buffer_index) + quit_next = 1; + + strcpy(file_path, fb->file_path); + + const char* s_repl = search; + while(!isupper(*s_repl++)) { + if (*s_repl == 0) { + for (char* fs = file_path; *fs; fs++) + *fs = tolower(*fs); + break; + } + } + char* search_start = file_path; + + if (!len) + goto search_match; + while ((search_start = strchr(search_start+1, *search))) { + if (memcmp(search_start, search, len) == 0) { + search_match: + if (offset) + *offset = search_start - file_path; + if (data) + *(int*)data = last_buffer_index; + return fb->file_path; + } + } + } +} + +const char* +buffers_search_keyword_next_item(const char* tmp, const char* search, int* offset, Glyph* attr, void* data) +{ + static char item[2048]; + static struct window_buffer wb; + static int pos = -1; + if (!tmp || !search) { + wb.buffer_index = 0; + pos = -1; + return NULL; + } + int len = strlen(search); + if (!len) + return NULL; + + for (;;) { + struct file_buffer* fb = get_file_buffer(&wb); + + if ((pos = buffer_seek_string(fb, pos+1, search)) >= 0) { + const char* filename = strrchr(fb->file_path, '/')+1; + if (!filename) + filename = fb->file_path; + + int tmp, y; + buffer_offset_to_xy(&wb, pos, 0, &tmp, &y); + + snprintf(item, 2048, "%s:%d: ", filename, y); + int itemlen = strlen(item); + + char* line = buffer_get_line_at_offset(fb, pos); + char* line_no_whitespace = line; + if (!isspace(*search)) + while(isspace(*line_no_whitespace)) line_no_whitespace++; + + snprintf(item + itemlen, 2048 - itemlen, "%s", line_no_whitespace); + free(line); + + int line_start = buffer_seek_char_backwards(fb, pos, '\n') + (line_no_whitespace - line); + if (line_start < 0) + line_start = 0; + if (offset) + *offset = (pos - line_start) + itemlen; + if (data) + *(struct keyword_pos*)data = (struct keyword_pos){.offset = pos, .buffer_index = wb.buffer_index}; + pos = buffer_seek_char(fb, pos+1, '\n'); + return item; + } else { + int last_buffer_index = wb.buffer_index; + wb.buffer_index++; + get_file_buffer(&wb); + if (wb.buffer_index <= last_buffer_index) + break; + pos = -1; + } + } + wb.buffer_index = 0; + pos = -1; + return NULL; +} + void choose_one_of_selection(const char* prefix, const char* search, const char* err, - const char*(*get_next_element)(const char*, const char*, int* offset, Glyph* attr), + const char*(*get_next_element)(const char*, const char*, int* offset, Glyph* attr, void* data), int* selected_line, int minx, int miny, int maxx, int maxy, int focused) { assert(prefix); + assert(search); assert(err); assert(selected_line); assert(get_next_element); @@ -851,28 +979,31 @@ choose_one_of_selection(const char* prefix, const char* search, const char* err, global_attr.bg = alternate_bg_dark; tsetregion(minx, miny+1, maxx, maxy, ' '); global_attr = default_attributes; - get_next_element(NULL, NULL, NULL, NULL); + get_next_element(NULL, NULL, NULL, NULL, NULL); int len = strlen(search); // count folders to get scroll - int folder_lines = maxy - miny - 1; + int folder_lines = maxy - miny - 2; int elements = 0; int tmp_offset; - while(get_next_element(prefix, search, &tmp_offset, NULL)) + int limit = MAX(*selected_line, 999); + while(get_next_element(prefix, search, &tmp_offset, NULL, NULL) && elements <= limit) elements++; - get_next_element(NULL, NULL, NULL, NULL); + get_next_element(NULL, NULL, NULL, NULL, NULL); *selected_line = MIN(*selected_line, elements-1); int sel_local = *selected_line; // print num of files char count[256]; - if (sel_local > folder_lines) - snprintf(count, sizeof(count), "^[%2d] ", elements); + if (elements >= 1000) + snprintf(count, sizeof(count), "[>999:%2d] ", *selected_line+1); + else if (*selected_line > folder_lines) + snprintf(count, sizeof(count), "^[%3d:%2d] ", elements, *selected_line+1); else if (elements-1 > folder_lines) - snprintf(count, sizeof(count), "ˇ[%2d] ", elements); + snprintf(count, sizeof(count), "ˇ[%3d:%2d] ", elements, *selected_line+1); else - snprintf(count, sizeof(count), " [%2d] ", elements); + snprintf(count, sizeof(count), " [%3d:%2d] ", elements, *selected_line+1); // print search term with prefix in front of it // prefix is in path_color @@ -890,7 +1021,7 @@ choose_one_of_selection(const char* prefix, const char* search, const char* err, global_attr = default_attributes; global_attr.bg = alternate_bg_dark; const char* element; - while(miny <= maxy && (element = get_next_element(prefix, search, &offset, &global_attr))) { + while(miny <= maxy && (element = get_next_element(prefix, search, &offset, &global_attr, NULL))) { if (elements > folder_lines && sel_local > folder_lines) { elements--; sel_local--; @@ -899,7 +1030,7 @@ choose_one_of_selection(const char* prefix, const char* search, const char* err, write_string(element, miny, minx, maxx+1); // change the color to highlight search term - for (int i = minx + offset; i < minx + len + offset && i < maxx; i++) + for (int i = minx + offset; i < minx + len + offset && i < maxx+1; i++) tsetattr(i, miny)->fg = highlight_color; // change the background of the selected line if (miny - start_miny - 1 == sel_local) @@ -926,9 +1057,32 @@ choose_one_of_selection(const char* prefix, const char* search, const char* err, } void -draw_dir(const char* path, const char* search, int* sel, int minx, int miny, int maxx, int maxy, int focused) +draw_dir(struct window_split_node* wn, int minx, int miny, int maxx, int maxy, int focused) +{ + struct file_buffer* fb = get_file_buffer(&wn->window); + char* folder = file_path_get_path(fb->file_path); + + buffer_change(fb, "\0", 1, fb->len, 1); + if (fb->len > 0) fb->len--; + + choose_one_of_selection(folder, fb->contents, " [Create New File]", + file_browser_next_item, &wn->selected, minx, miny, maxx, maxy, focused); + + free(folder); +} + +void +draw_search_buffers(struct window_split_node* wn, int minx, int miny, int maxx, int maxy, int focused) { - choose_one_of_selection(path, search, " [Create New File]", file_browser_next_item, sel, minx, miny, maxx, maxy, focused); + choose_one_of_selection("Find loaded buffer: ", wn->search, " [No resuts]", + buffer_search_next_item, &wn->selected, minx, miny, maxx, maxy, focused); +} + +void +draw_search_keyword_in_all_buffers(struct window_split_node* wn, int minx, int miny, int maxx, int maxy, int focused) +{ + choose_one_of_selection("Find in all buffers: ", wn->search, " [No resuts]", + buffers_search_keyword_next_item, &wn->selected, minx, miny, maxx, maxy, focused); } void recursive_mkdir(char *path) { @@ -1328,8 +1482,9 @@ buffer_offset_to_xy(struct window_buffer* buf, int offset, int maxx, int* cx, in } void -buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, int maxy) +buffer_draw_to_screen(struct window_split_node* wn, int minx, int miny, int maxx, int maxy) { + struct window_buffer* buf = &wn->window; assert(buf); struct file_buffer* fb = get_file_buffer(buf); @@ -1341,15 +1496,10 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i tsetregion(minx, miny, maxx, maxy, ' '); int focused = buf == focused_window && !(fb->mode & BUFFER_SEARCH_BLOCKING); - if (buf->mode == WINDOW_BUFFER_FILE_BROWSER) { - char* folder = file_path_get_path(fb->file_path); - - buffer_change(fb, "\0", 1, fb->len, 1); - if (fb->len > 0) fb->len--; - - draw_dir(folder, fb->contents, &buf->y_scroll, minx, miny, maxx, maxy, focused); - - free(folder); + if (buf->mode > WINDOW_BUFFER_NORMAL) { + // alternate buffer modes + assert(buf->mode < WINDOW_BUFFER_MODE_LEN); + alternate_buffer_modes[buf->mode](wn, minx, miny, maxx, maxy, focused); return; } @@ -1534,7 +1684,7 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i const char* name = strrchr(fb->file_path, '/'); if (name) status_end = writef_string(maxy-1, status_end, maxx+1, "%s", name+1); - status_end = writef_string(maxy-1, status_end, maxx+1, " %d:%d %d%%" , cursor_y + buf->y_scroll, cursor_x, + status_end = writef_string(maxy-1, status_end, maxx+1, " %d:%d %d%%" , cursor_y + buf->y_scroll, cursor_x - minx + xscroll, (int)(((float)(buf->cursor_offset+1)/(float)fb->len)*100.0f)); if (fb->mode & BUFFER_SELECTION_ON) { int y1, y2, tmp; @@ -1792,7 +1942,10 @@ write_string(const char* string, int y, int minx, int maxx) int len = strlen(string); while(minx < maxx && offset < len) { Rune u; - offset += t_decode_utf8_buffer(string + offset, len - offset, &u); + int charsize = t_decode_utf8_buffer(string + offset, len - offset, &u); + offset += charsize; + if (charsize == 1 && u <= 32) + u = ' '; minx += tsetchar(u, minx, y); } return minx; diff --git a/se.h b/se.h @@ -61,9 +61,15 @@ typedef Glyph *Line; // Window buffer // +// NOTE: +// refrain from entering the buffers or buffer keyword searching +// mode if you already are in file browser mode enum window_buffer_mode { WINDOW_BUFFER_NORMAL = 0, WINDOW_BUFFER_FILE_BROWSER, + WINDOW_BUFFER_SEARCH_BUFFERS, + WINDOW_BUFFER_KEYWORD_ALL_BUFFERS, + WINDOW_BUFFER_MODE_LEN, }; struct window_buffer { @@ -81,7 +87,6 @@ void buffer_write_selection(struct window_buffer* buf, int minx, int miny, int m void buffer_move_cursor_to_selection_start(struct window_buffer* buffer); void buffer_offset_to_xy(struct window_buffer* buf, int offset, int maxx, int* cx, int* cy); -void buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, int maxy); enum cursor_reason { CURSOR_DO_NOT_CALLBACK = 0, @@ -109,6 +114,8 @@ struct window_split_node { enum window_split_mode mode; float ratio; struct window_split_node *node1, *node2, *parent; + char* search; + int selected; }; void window_node_split(struct window_split_node* parent, float ratio, enum window_split_mode mode); @@ -280,10 +287,19 @@ char* file_path_get_path(const char* path); // Other // +struct keyword_pos { + int offset, buffer_index; +}; + +const char* file_browser_next_item(const char* path, const char* search, int* offset, Glyph* attr, void* data); +// data pointer will give the file buffer of the current item +const char* buffer_search_next_item(const char* tmp, const char* search, int* offset, Glyph* attr, void* data); +// data pointer will give the keyword_pos of the current item +const char* buffers_search_keyword_next_item(const char* tmp, const char* search, int* offset, Glyph* attr, void* data); + void die(const char *, ...); int is_file_type(const char* file_path, const char* file_type); int path_is_folder(const char* path); -const char* file_browser_next_item(const char* path, const char* search, int* offset, Glyph* attr); int write_string(const char* string, int y, int minx, int maxx); int writef_to_status_bar(const char* fmt, ...); void draw_status_bar(); diff --git a/x.c b/x.c @@ -78,6 +78,9 @@ extern void(*startup_callback)(void); static int file_browser_actions(KeySym keysym, int modkey); static void file_browser_string_insert(const char* buf, int buflen); +static int buffer_search_actions(KeySym keysym, int modkey); +static void buffer_search_string_insert(const char* buf, int buflen); + static int search_term_actions(KeySym keysym, int modkey); static void search_term_string_insert(const char* buf, int buflen); static int open_seproj(struct file_buffer fb); @@ -137,7 +140,8 @@ extern Term term; static struct file_buffer* file_buffers; static int available_buffer_slots = 0; -struct window_split_node root_node = {.mode = WINDOW_SINGULAR}; +static char root_node_search[SEARCH_TERM_MAX_LEN]; +struct window_split_node root_node = {.mode = WINDOW_SINGULAR, .search = root_node_search}; struct window_split_node* focused_node = &root_node; struct window_buffer* focused_window = &root_node.window; @@ -217,7 +221,7 @@ open_seproj(struct file_buffer fb) } if (first < 0) - first = new_file_buffer_entry("/home/halvard/Code/C/se/se.c"); + first = new_file_buffer_entry(NULL); writef_to_status_bar("opened project %s", path); free(path); @@ -1446,7 +1450,7 @@ file_browser_actions(KeySym keysym, int modkey) offset = focused_window->cursor_offset; buffer_remove(fb, offset, 1, 0, 0); - focused_window->y_scroll = 0; + focused_node->selected = 0; return 1; case XK_Tab: case XK_Return: @@ -1455,22 +1459,21 @@ file_browser_actions(KeySym keysym, int modkey) buffer_change(fb, "\0", 1, fb->len, 1); if (fb->len > 0) fb->len--; - file_browser_next_item(NULL, NULL, NULL, NULL); + file_browser_next_item(NULL, NULL, NULL, NULL, NULL); const char* filename; - for (int y = 0; (filename = file_browser_next_item(path, fb->contents, NULL, NULL)); y++) { + for (int y = 0; (filename = file_browser_next_item(path, fb->contents, NULL, NULL, NULL)); y++) { strcpy(full_path, path); strcat(full_path, filename); - if (y == focused_window->y_scroll) { + if (y == focused_node->selected) { if (path_is_folder(full_path)) { strcpy(fb->file_path, full_path); fb->len = 0; fb->contents[0] = '\0'; - focused_window->y_scroll = 0; - focused_window->y_scroll = 0; + focused_node->selected = 0; free(path); - file_browser_next_item(NULL, NULL, NULL, NULL); + file_browser_next_item(NULL, NULL, NULL, NULL, NULL); *full_path = 0; return 1; } @@ -1495,14 +1498,12 @@ open_file: return 1; } case XK_Down: - focused_window->y_scroll++; - if (focused_window->y_scroll < 0) - focused_window->y_scroll = 0; + focused_node->selected++; return 1; case XK_Up: - focused_window->y_scroll--; - if (focused_window->y_scroll < 0) - focused_window->y_scroll = 0; + focused_node->selected--; + if (focused_node->selected < 0) + focused_node->selected = 0; return 1; case XK_Escape: if (destroy_file_buffer_entry(focused_node, &root_node)) @@ -1538,8 +1539,7 @@ file_browser_string_insert(const char* buf, int buflen) if (buf[0] >= 32 || buflen > 1) { buffer_insert(fb, buf, buflen, fb->len, 0); - buffer_move_offset_relative(focused_window, buflen, 0); - focused_window->y_scroll = 0; + focused_node->selected = 0; if (*buf == '/') { buffer_change(fb, "\0", 1, fb->len, 0); @@ -1556,7 +1556,87 @@ file_browser_string_insert(const char* buf, int buflen) } } } else { - printf("unhandled control character %x\n", buf[0]); + writef_to_status_bar("unhandled control character 0x%x\n", buf[0]); + } +} + +int +buffer_search_actions(KeySym keysym, int modkey) +{ + switch (keysym) { + case XK_Return: + case XK_Tab: + if (focused_window->mode == WINDOW_BUFFER_KEYWORD_ALL_BUFFERS) { + struct keyword_pos kw; + int n = 0; + buffers_search_keyword_next_item(NULL, NULL, NULL, NULL, NULL); + while (buffers_search_keyword_next_item("", focused_node->search, NULL, NULL, &kw)) { + if (n == focused_node->selected) { + *focused_window = window_buffer_new(kw.buffer_index); + focused_window->cursor_offset = kw.offset; + return 1; + } + n++; + } + buffers_search_keyword_next_item(NULL, NULL, NULL, NULL, NULL); + } else if (focused_window->mode == WINDOW_BUFFER_SEARCH_BUFFERS) { + int buffer_index; + int n = 0; + buffer_search_next_item(NULL, NULL, NULL, NULL, NULL); + while (buffer_search_next_item("", focused_node->search, NULL, NULL, &buffer_index)) { + if (n == focused_node->selected) { + *focused_window = window_buffer_new(buffer_index); + return 1; + } + n++; + } + buffer_search_next_item(NULL, NULL, NULL, NULL, NULL); + } + puts("n"); + return 1; + case XK_BackSpace: + remove_utf8_string_end(focused_node->search); + focused_node->selected = 0; + return 1; + case XK_Down: + focused_node->selected++; + return 1; + case XK_Up: + focused_node->selected--; + if (focused_node->selected < 0) + focused_node->selected = 0; + return 1; + case XK_Page_Down: + focused_node->selected += 10; + return 1; + case XK_Page_Up: + focused_node->selected -= 10; + if (focused_node->selected < 0) + focused_node->selected = 0; + return 1; + case XK_Escape: + if (path_is_folder(get_file_buffer(focused_window)->file_path)) + focused_window->mode = WINDOW_BUFFER_FILE_BROWSER; + else + focused_window->mode = WINDOW_BUFFER_NORMAL; + return 1; + } + return 0; +} + +void +buffer_search_string_insert(const char* buf, int buflen) +{ + int len = strlen(focused_node->search); + if (buflen + len + 1 > SEARCH_TERM_MAX_LEN) + return; + + if (buf[0] >= 32 || buflen > 1) { + memcpy(focused_node->search + len, buf, buflen); + focused_node->search[len + buflen] = 0; + focused_node->selected = 0; + } else { + writef_to_status_bar("unhandled control character 0x%x\n", buf[0]); } } @@ -1656,6 +1736,10 @@ kpress(XEvent *ev) if (focused_window->mode == WINDOW_BUFFER_FILE_BROWSER) { if (file_browser_actions(ksym, e->state)) return; + } else if (focused_window->mode & WINDOW_BUFFER_SEARCH_BUFFERS || + focused_window->mode & WINDOW_BUFFER_KEYWORD_ALL_BUFFERS) { + if (buffer_search_actions(ksym, e->state)) + return; } else if (fb->mode & BUFFER_SEARCH_BLOCKING) { if (search_term_actions(ksym, e->state)) return; @@ -1676,6 +1760,9 @@ kpress(XEvent *ev) } if (focused_window->mode == WINDOW_BUFFER_FILE_BROWSER) file_browser_string_insert(buf, len); + else if (focused_window->mode & WINDOW_BUFFER_SEARCH_BUFFERS || + focused_window->mode & WINDOW_BUFFER_KEYWORD_ALL_BUFFERS) + buffer_search_string_insert(buf, len); else if (fb->mode & BUFFER_SEARCH_BLOCKING) search_term_string_insert(buf, len); else @@ -1785,8 +1872,7 @@ main(int argc, char *argv[]) // TODO: fix things when the file buffer is empty // for example on a new file - *focused_window = window_buffer_new(new_file_buffer_entry(".seproj")); - /* + if (argc <= 1) { *focused_window = window_buffer_new(new_file_buffer_entry(NULL)); } else { @@ -1816,7 +1902,6 @@ main(int argc, char *argv[]) } } } - */ static const char* const welcome[] = {"Welcome to se!", "Good day, Human", "Happy Coding", "se: the Simple Editor", "Time to get some progress done!", "Ready for combat", "Initialising...Done", "loaded in %%d seconds",