se

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

commit 1fac2f32640f0345924c7913b09698871921c0d5
parent 341f6365ef49480bcef99e5f51bb2d02f7211907
Author: Samdal <samdal@protonmail.com>
Date:   Sat, 22 Jan 2022 01:28:36 +0100

searching

Diffstat:
Mconfig.def.c | 37++++++++++++++++++++++++++++++++++++-
Mse.c | 144++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mse.h | 34++++++++++++++++++++++++----------
Mx.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
4 files changed, 284 insertions(+), 31 deletions(-)

diff --git a/config.def.c b/config.def.c @@ -84,8 +84,11 @@ 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_next(const Arg* arg); +static void search_previous(const Arg* arg); static void open_file_browser(const Arg* arg); static void buffer_kill(const Arg* arg); @@ -136,6 +139,9 @@ const Shortcut shortcuts[] = { { ControlMask, XK_z, undo, {0} }, { TERMMOD, XK_Z, redo, {0} }, { ControlMask, XK_s, save_buffer, {0} }, + { ControlMask, XK_f, search, {0} }, + { ControlMask, XK_n, search_next, {0} }, + { TERMMOD, XK_N, search_previous,{0} }, { ControlMask, XK_c, clipboard_copy, {0} }, { ControlMask, XK_v, clipboard_paste,{0} }, { TERMMOD, XK_Prior, zoom, {.f = +1} }, @@ -153,6 +159,7 @@ void(*buffer_contents_updated)(struct file_buffer*, int, enum buffer_content_rea int(*keypress_callback)(KeySym, int) = keypress_actions; void(*string_input_callback)(const char*, int) = string_insert_callback; void(*draw_callback)(void) = NULL; +void(*startup_callback)(void) = NULL; void(*buffer_written_to_screen_callback)(struct file_buffer*, int, int, int, int, int, int) = NULL; @@ -329,6 +336,14 @@ 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)); @@ -341,6 +356,22 @@ redo(const Arg* arg) } void +search_next(const Arg* arg) +{ + focused_window->cursor_offset = + buffer_seek_string_wrap(focused_window, focused_window->cursor_offset+1, + get_file_buffer(focused_window)->search_term); +} + +void +search_previous(const Arg* arg) +{ + focused_window->cursor_offset = + buffer_seek_string_wrap_backwards(focused_window, focused_window->cursor_offset-1, + get_file_buffer(focused_window)->search_term); +} + +void open_file_browser(const Arg* arg) { int last_fb = focused_window->buffer_index; @@ -433,6 +464,11 @@ keypress_actions(KeySym keysym, int modkey) buffer_move_offset_relative, -move, CURSOR_COMMAND_MOVEMENT); return 1; case XK_Escape: + fb->mode &= ~BUFFER_SEARCH_BLOCKING_MASK; + fb->mode &= ~BUFFER_SEARCH_NON_BLOCKING; + fb->mode &= ~BUFFER_SEARCH_NON_BLOCKING_BACKWARDS; + fb->mode &= ~BUFFER_SEARCH_BLOCKING_BACKWARDS; + writef_to_status_bar(""); return 1; case XK_Return: delete_selection(fb); @@ -479,7 +515,6 @@ void string_insert_callback(const char* buf, int buflen) { struct file_buffer* fb = get_file_buffer(focused_window); - // TODO: allow blocking of the bufferwrite, redirecting to keybinds with multiple characther length if (buf[0] >= 32 || buflen > 1) { delete_selection(fb); buffer_insert(fb, buf, buflen, focused_window->cursor_offset, 0); diff --git a/se.c b/se.c @@ -259,6 +259,42 @@ buffer_seek_string_backwards(const struct file_buffer* buf, int offset, const ch } int +buffer_seek_string_wrap(const struct window_buffer* wb, int offset, const char* search) +{ + struct file_buffer* fb = get_file_buffer(focused_window); + if (*search == 0 || !buffer_count_string_instances(fb, search, 0, NULL)) { + writef_to_status_bar("no results for \"%s\"", search); + return -1; + } + int new_offset = buffer_seek_string(fb, offset, search); + if (new_offset < 0) { + new_offset = buffer_seek_string(fb, 0, search); + writef_to_status_bar("search wrapped"); + } + if (!(fb->mode & BUFFER_SEARCH_BLOCKING)) + fb->mode |= BUFFER_SEARCH_BLOCKING_IDLE; + return new_offset; +} + +int +buffer_seek_string_wrap_backwards(const struct window_buffer* wb, int offset, const char* search) +{ + struct file_buffer* fb = get_file_buffer(focused_window); + if (*search == 0 || !buffer_count_string_instances(fb, search, 0, NULL)) { + writef_to_status_bar("no results for \"%s\"", search); + return -1; + } + int new_offset = buffer_seek_string_backwards(fb, offset, search); + if (new_offset < 0) { + new_offset = buffer_seek_string_backwards(fb, fb->len, search); + writef_to_status_bar("search wrapped"); + } + if (!(fb->mode & BUFFER_SEARCH_BLOCKING)) + fb->mode |= BUFFER_SEARCH_BLOCKING_IDLE; + return new_offset; +} + +int buffer_is_on_a_word(const struct file_buffer* fb, int offset, const char* word_seperators) { LIMIT(offset, 0, fb->len); @@ -350,6 +386,31 @@ buffer_seek_not_whitespace_backwrads(const struct file_buffer* fb, int offset) return offset; } +int +buffer_count_string_instances(const struct file_buffer* fb, const char* string, int offset, int* before_offset) +{ + int tmp; + if (!before_offset) + before_offset = &tmp; + if (*fb->search_term == 0) { + *before_offset = 0; + return 0; + } + + int pos = 0; + int count = 0; + int once = 1; + while((pos = buffer_seek_string(fb, pos, string)) >= 0) { + count++; + pos++; + if (once && pos > offset) { + *before_offset = count; + once = 0; + } + } + return count; +} + void buffer_move_on_line(struct window_buffer* buf, int amount, enum cursor_reason callback_reason) { @@ -888,11 +949,13 @@ draw_status_bar() global_attr = default_attributes; global_attr.bg = alternate_bg_dark; tsetregion(0, term.row-1, term.col-1, term.row-1, ' '); - writef_to_status_bar(NULL); + int x_end = writef_to_status_bar(NULL); global_attr = default_attributes; xdrawline(0, term.row-1, term.col); draw_horisontal_line(term.row-2, 0, term.col-1); + if (get_file_buffer(focused_window)->mode & BUFFER_SEARCH_BLOCKING) + xdrawcursor(x_end, term.row-1, 1); } void @@ -1046,7 +1109,11 @@ buffer_new(const char* file_path) } buffer.ub = xmalloc(sizeof(struct undo_buffer) * UNDO_BUFFERS_COUNT); + buffer.search_term = xmalloc(SEARCH_TERM_MAX_LEN); + buffer.non_blocking_search_term = xmalloc(SEARCH_TERM_MAX_LEN); memset(buffer.ub, 0, sizeof(struct undo_buffer) * UNDO_BUFFERS_COUNT); + memset(buffer.search_term, 0, SEARCH_TERM_MAX_LEN); + memset(buffer.non_blocking_search_term, 0, SEARCH_TERM_MAX_LEN); if (buffer_contents_updated) buffer_contents_updated(&buffer, 0, BUFFER_CONTENT_INIT); @@ -1062,6 +1129,8 @@ buffer_destroy(struct file_buffer* fb) free(fb->ub); free(fb->contents); free(fb->file_path); + free(fb->search_term); + free(fb->non_blocking_search_term); *fb = (struct file_buffer){0}; } @@ -1132,6 +1201,32 @@ buffer_remove(struct file_buffer* buf, const int offset, int len, int do_not_cal return removed_len; } +void +remove_utf8_string_end(char* string) +{ + int line_start = 0; + + int len = strlen(string); + if (len <= 0) + return; + int move; + int seek_pos = line_start, follower_pos = line_start; + int n = 0; + while (seek_pos < len) { + Rune u; + int charsize = t_decode_utf8_buffer(string + seek_pos, len - seek_pos, &u); + seek_pos += charsize; + if (!n) { + move = charsize; + n = 1; + } else { + follower_pos += move; + move = charsize; + } + } + string[follower_pos] = 0; +} + int buffer_get_charsize(Rune u, int cur_x_pos) { @@ -1206,6 +1301,7 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i LIMIT(miny, 0, maxy); LIMIT(buf->cursor_offset, 0, fb->len); 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); @@ -1213,7 +1309,7 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i 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, buf == focused_window); + draw_dir(folder, fb->contents, &buf->y_scroll, minx, miny, maxx, maxy, focused); free(folder); return; @@ -1297,6 +1393,8 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i // actually write to the screen int once = 0; + int search_found = 0; + int non_blocking_search_found = 0; for (int charsize = 1; repl < last && charsize; repl += charsize) { if (!once && repl - fb->contents >= buf->cursor_offset) { // if the buffer being drawn is focused, set the cursor position global @@ -1348,6 +1446,26 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i else width = wcwidth(u); + // drawing search highlight + if (fb->mode & BUFFER_SEARCH_BLOCKING_MASK) { + if (!search_found && buffer_offset_starts_with(fb, repl - fb->contents, fb->search_term)) + search_found = strlen(fb->search_term); + if (search_found) { + tsetattr(x - xscroll, y)->bg = highlight_color; + tsetattr(x - xscroll, y)->fg = default_attributes.bg; + search_found--; + } + } + if (fb->mode & BUFFER_SEARCH_NON_BLOCKING) { + if (!non_blocking_search_found && buffer_offset_starts_with(fb, repl - fb->contents, fb->non_blocking_search_term)) + non_blocking_search_found = strlen(fb->search_term); + if (non_blocking_search_found) { + tsetattr(x - xscroll, y)->fg = highlight_color; + tsetattr(x - xscroll, y)->mode |= ATTR_UNDERLINE; + non_blocking_search_found--; + } + } + x += width; } int offset_end = repl - fb->contents; @@ -1362,7 +1480,13 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i buffer_written_to_screen_callback(buf, offset_start, offset_end, minx, miny, maxx, maxy); // TODO: let the user do this - int status_end = writef_string(maxy-1, minx, maxx+1, " %dk %s %d:%d %d%%", + int status_end = minx; + if (fb->mode & BUFFER_SEARCH_BLOCKING_IDLE) { + int before; + int search_count = buffer_count_string_instances(fb, fb->search_term, focused_window->cursor_offset, &before); + status_end = writef_string(maxy-1, status_end, maxx+1, " %d/%d", before, search_count); + } + status_end = writef_string(maxy-1, status_end, maxx+1, " %dk %s %d:%d %d%%", fb->len/1000, fb->file_path, cursor_y + buf->y_scroll, cursor_x, (int)(((float)(buf->cursor_offset+1)/(float)fb->len)*100.0f)); if (fb->mode & BUFFER_SELECTION_ON) { @@ -1372,10 +1496,12 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i writef_string(maxy-1, status_end, maxx, " %dL", abs(y1-y2)); } - if (buf == focused_window) { + if (focused) { for (int i = minx; i < maxx+1; i++) { - if (!(fb->mode & BUFFER_SELECTION_ON)) - tsetattr(i, cursor_y)->bg = mouse_line_bg; + if (!(fb->mode & BUFFER_SELECTION_ON)) { + if (tsetattr(i, cursor_y)->bg == default_attributes.bg) + tsetattr(i, cursor_y)->bg = mouse_line_bg; + } tsetattr(i, maxy-1)->bg = alternate_bg_bright; } } @@ -1387,7 +1513,8 @@ buffer_draw_to_screen(struct window_buffer* buf, int minx, int miny, int maxx, i xdrawline(minx, i, maxx+1); draw_horisontal_line(maxy-1, minx, maxx); - xdrawcursor(cursor_x, cursor_y, buf == focused_window); + + xdrawcursor(cursor_x, cursor_y, focused); } // TODO: Scope checks (with it's own system, so that it can be used for auto indent as well) @@ -1637,7 +1764,8 @@ str_contains_char(const char* string, char check) void color_selection(Glyph* letter) { - letter->bg = selection_bg; + if (letter->bg == default_attributes.bg) + letter->bg = selection_bg; } diff --git a/se.h b/se.h @@ -14,7 +14,7 @@ #define UNDO_BUFFERS_COUNT 32 #define UPPER_CASE_WORD_MIN_LEN 3 #define STATUS_BAR_MAX_LEN 4096 -#define SEARCH_TERM_LEN 4096 +#define SEARCH_TERM_MAX_LEN 4096 #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -200,17 +200,33 @@ struct undo_buffer { int y_scroll; }; +enum buffer_flags { + BUFFER_SELECTION_ON = 1 << 0, + BUFFER_BLOCK_SELECT = 1 << 1, + BUFFER_LINE_SELECT = 1 << 2, + BUFFER_READ_ONLY = 1 << 3, + BUFFER_UTF8_SIGNED = 1 << 4, + BUFFER_SEARCH_BLOCKING = 1 << 5, + BUFFER_SEARCH_BLOCKING_IDLE = 1 << 6, + BUFFER_SEARCH_BLOCKING_MASK = (BUFFER_SEARCH_BLOCKING | BUFFER_SEARCH_BLOCKING_IDLE), + BUFFER_SEARCH_NON_BLOCKING = 1 << 7, + BUFFER_SEARCH_BLOCKING_BACKWARDS = 1 << 8, + BUFFER_SEARCH_NON_BLOCKING_BACKWARDS = 1 << 9, +}; + // Contents of a file buffer struct file_buffer { char* file_path; char* contents; // !! NOT NULL TERMINATED !! int len; int capacity; - int mode; // flags + enum buffer_flags mode; struct undo_buffer* ub; int current_undo_buffer; int available_redo_buffers; int s1o, s2o; // selection start offset and end offset + char* search_term; + char* non_blocking_search_term; }; const struct color_scheme* buffer_get_color_scheme(struct file_buffer* fb); @@ -223,6 +239,7 @@ void buffer_write_to_filepath(const struct file_buffer* buffer); void buffer_undo(struct file_buffer* buf); void buffer_redo(struct file_buffer* buf); +// TODO: string compare that doesn't care if of capitalisation if the search is all lower case int buffer_is_on_a_word(const struct file_buffer* fb, int offset, const char* word_seperators); int buffer_is_start_of_a_word(const struct file_buffer* fb, int offset, const char* word_seperators); int buffer_is_on_word(const struct file_buffer* fb, int offset, const char* word_seperators, const char* word); @@ -231,6 +248,8 @@ int buffer_seek_char(const struct file_buffer* buf, int offset, char byte); int buffer_seek_char_backwards(const struct file_buffer* buf, int offset, char byte); int buffer_seek_string(const struct file_buffer* buf, int offset, const char* string); int buffer_seek_string_backwards(const struct file_buffer* buf, int offset, const char* string); +int buffer_seek_string_wrap(const struct window_buffer* wb, int offset, const char* search); +int buffer_seek_string_wrap_backwards(const struct window_buffer* wb, int offset, const char* search); int buffer_seek_word(const struct file_buffer* fb, int offset, const char* word_seperators); int buffer_seek_word_end(const struct file_buffer* fb, int offset, const char* word_seperators); int buffer_seek_word_backwards(const struct file_buffer* fb, int offset, const char* word_seperators); @@ -239,6 +258,8 @@ int buffer_seek_whitespace_backwrads(const struct file_buffer* fb, int offset); int buffer_seek_not_whitespace(const struct file_buffer* fb, int offset); int buffer_seek_not_whitespace_backwrads(const struct file_buffer* fb, int offset); +int buffer_count_string_instances(const struct file_buffer* fb, const char* string, int offset, int* before_offset); + /////////////////////////////////// // returns a null terminated string containing the selection // the returned value must be freed by the reciever @@ -260,6 +281,7 @@ int file_browser_next_item(DIR* dir, const char* path, const char* search, char* int write_string(const char* string, int y, int minx, int maxx); int writef_to_status_bar(const char* fmt, ...); void draw_status_bar(); +void remove_utf8_string_end(char* string); // Internal representation of the screen typedef struct { @@ -289,12 +311,4 @@ enum buffer_content_reason { void buffer_add_to_undo(struct file_buffer* buffer, int offset, enum buffer_content_reason reason); -enum buffer_flags { - BUFFER_SELECTION_ON = 1 << 0, - BUFFER_BLOCK_SELECT = 1 << 1, - BUFFER_LINE_SELECT = 1 << 2, - BUFFER_READ_ONLY = 1 << 3, - BUFFER_UTF8_SIGNED = 1 << 4, -}; - #endif // _ST_H diff --git a/x.c b/x.c @@ -44,6 +44,7 @@ extern void(*buffer_contents_updated)(struct file_buffer* modified_fb, int curre // non-zero return value means the kpress function will not proceed further extern int(*keypress_callback)(KeySym keycode, int modkey); extern void(*string_input_callback)(const char* buf, int len); +extern void(*startup_callback)(void); // TODO: planned callbacks: // buffer focused // window focused @@ -77,6 +78,8 @@ extern void(*string_input_callback)(const char* buf, int len); static int file_browser_actions(KeySym keysym, int modkey); static void file_browser_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 xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); static void xdrawglyph(Glyph, int, int); @@ -137,9 +140,6 @@ struct window_split_node root_node = {.mode = WINDOW_SINGULAR}; struct window_split_node* focused_node = &root_node; struct window_buffer* focused_window = &root_node.window; -char searc_term[SEARCH_TERM_LEN]; -int search_mode_on; - Atom xtarget; char* copy_buffer; int copy_len; @@ -1225,8 +1225,7 @@ draw_horisontal_line(int y, int x1, int x2) Color drawcol = dc.col[default_attributes.fg]; XftDrawRect(xw.draw, &drawcol, - border_px + x1 * win.cw, - border_px + (y + 1) * win.ch - cursor_thickness, + border_px + x1 * win.cw, border_px + (y + 1) * win.ch - cursor_thickness, win.cw * (x2-x1+1), 1); } @@ -1514,6 +1513,74 @@ file_browser_string_insert(const char* buf, int buflen) } } +int +search_term_actions(KeySym keysym, int modkey) +{ + static int first = 0; + struct file_buffer* fb = get_file_buffer(focused_window); + if (keysym == XK_Return || keysym == XK_Escape) { + int count = buffer_count_string_instances(fb, fb->search_term, 0, NULL); + if (!count) { + fb->mode &= ~BUFFER_SEARCH_BLOCKING_MASK; + writef_to_status_bar("no resulrs for \"%s\"", fb->search_term); + } else { + fb->mode &= ~BUFFER_SEARCH_BLOCKING; + fb->mode &= ~BUFFER_SEARCH_BLOCKING_BACKWARDS; + fb->mode |= BUFFER_SEARCH_BLOCKING_IDLE; + + writef_to_status_bar("%d results for \"%s\"", count, fb->search_term); + if (fb->mode & BUFFER_SEARCH_BLOCKING_BACKWARDS) + focused_window->cursor_offset = buffer_seek_string_backwards(fb, focused_window->cursor_offset, fb->search_term); + else + focused_window->cursor_offset = buffer_seek_string(fb, focused_window->cursor_offset, fb->search_term); + } + first = 1; + search_term_string_insert(NULL, 0); + return 1; + } + if (keysym == XK_BackSpace) { + if (first) { + first = 0; + *fb->search_term = 0; + } else { + remove_utf8_string_end(fb->search_term); + focused_window->cursor_offset = buffer_seek_string_wrap(focused_window, focused_window->cursor_offset, fb->search_term); + } + writef_to_status_bar("search: %s", fb->search_term); + return 1; + } + first = 0; + return 0; +} + +void +search_term_string_insert(const char* buf, int buflen) +{ + static int first = 0; + + struct file_buffer* fb = get_file_buffer(focused_window); + if (!buf) { + first = 1; + return; + } + if (first) { + *fb->search_term = 0; + first = 0; + } + if (buf[0] >= 32 || buflen > 1) { + int len = strlen(fb->search_term); + if (len + buflen + 1 > SEARCH_TERM_MAX_LEN) + return; + memcpy(fb->search_term + len, buf, buflen); + fb->search_term[len + buflen] = 0; + if (fb->mode & BUFFER_SEARCH_BLOCKING_BACKWARDS) + focused_window->cursor_offset = buffer_seek_string_backwards(fb, focused_window->cursor_offset, fb->search_term); + else + focused_window->cursor_offset = buffer_seek_string(fb, focused_window->cursor_offset, fb->search_term); + writef_to_status_bar("search: %s", fb->search_term); + } +} + int match(uint mask, uint state) { const uint ignoremod = Mod2Mask|XK_SWITCH_MOD; return mask == XK_ANY_MOD || mask == (state & ~ignoremod); @@ -1536,10 +1603,14 @@ kpress(XEvent *ev) len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); else len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + const struct file_buffer* fb = get_file_buffer(focused_window); // keysym callback if (focused_window->mode == WINDOW_BUFFER_FILE_BROWSER) { - if(file_browser_actions(ksym, e->state)) + if (file_browser_actions(ksym, e->state)) + return; + } else if (fb->mode & BUFFER_SEARCH_BLOCKING) { + if (search_term_actions(ksym, e->state)) return; } else if (keypress_callback) { if (keypress_callback(ksym, e->state)) @@ -1558,6 +1629,8 @@ kpress(XEvent *ev) } if (focused_window->mode == WINDOW_BUFFER_FILE_BROWSER) file_browser_string_insert(buf, len); + else if (fb->mode & BUFFER_SEARCH_BLOCKING) + search_term_string_insert(buf, len); else string_input_callback(buf, len); } @@ -1644,15 +1717,17 @@ run(void) XFlush(xw.dpy); } } -#include <sys/time.h> + int main(int argc, char *argv[]) { + if (startup_callback) { + startup_callback(); + } xw.l = xw.t = 0; xw.isfixed = False; xsetcursor(cursor_shape); - setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); int cols = MAX(default_cols, 1); @@ -1690,10 +1765,11 @@ main(int argc, char *argv[]) } } - static const char* const welcome[] = {"Welcome to se!", "Good day", "Happy Coding", "se: the Simple Editor", - "Time to get some progress done!", "When someone extends se, will it be called sex?", "Ready for combat", - "Initialising...Done", "Fun fact: vscode has over two times as many lines describing dependencies than se has in total", - "You look based"}; + 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", + "Fun fact: vscode has over two times as many lines describing dependencies than se has in total", + "You look based", "Another day, another bug to fix", "Who needs a mouse ¯\\_(ツ)_/¯", "grrgrrggghhaaaaaa (╯°□ °)╯︵ ┻━┻", + "┬┴┬┤(・_├┬┴┬┤├┬┴┬┴┬┤ʖ ͡°) ├┬┴┬┴┬┴┬┴┬┴┬┴┬┴┬┴┬┴┬┴", "ʰᵉˡˡᵒ", "(=^ ◡ ^=)"}; srand(time(NULL)); writef_to_status_bar(welcome[rand() % LEN(welcome)]);