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 | ++++++ |
M | config.def.c | | | 47 | ++++++++++++++++++++++++++++++++++++----------- |
M | se.c | | | 215 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | se.h | | | 20 | ++++++++++++++++++-- |
M | x.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",