summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--colors.c5
-rw-r--r--colors.h5
-rw-r--r--command.c6
-rw-r--r--config.c25
-rw-r--r--lsp.h8
-rw-r--r--main.c93
-rw-r--r--ted.c91
-rw-r--r--ted.cfg7
-rw-r--r--ted.h33
9 files changed, 168 insertions, 105 deletions
diff --git a/colors.c b/colors.c
index 081d99e..edd7de4 100644
--- a/colors.c
+++ b/colors.c
@@ -24,9 +24,12 @@ static ColorName const color_names[] = {
{COLOR_MENU_BACKDROP, "menu-backdrop"},
{COLOR_MENU_BG, "menu-bg"},
{COLOR_MENU_HL, "menu-hl"},
- {COLOR_ERROR_TEXT, "error-text"},
{COLOR_ERROR_BG, "error-bg"},
{COLOR_ERROR_BORDER, "error-border"},
+ {COLOR_INFO_BG, "info-bg"},
+ {COLOR_INFO_BORDER, "info-border"},
+ {COLOR_WARNING_BG, "warning-bg"},
+ {COLOR_WARNING_BORDER, "warning-border"},
{COLOR_ACTIVE_TAB_HL, "active-tab-hl"},
{COLOR_SELECTED_TAB_HL, "selected-tab-hl"},
{COLOR_FIND_HL, "find-hl"},
diff --git a/colors.h b/colors.h
index f6f910e..cc5faa3 100644
--- a/colors.h
+++ b/colors.h
@@ -21,9 +21,12 @@ typedef enum {
COLOR_MENU_BACKDROP,
COLOR_MENU_BG,
COLOR_MENU_HL,
- COLOR_ERROR_TEXT,
COLOR_ERROR_BG,
COLOR_ERROR_BORDER,
+ COLOR_WARNING_BG,
+ COLOR_WARNING_BORDER,
+ COLOR_INFO_BG,
+ COLOR_INFO_BORDER,
COLOR_ACTIVE_TAB_HL,
COLOR_SELECTED_TAB_HL,
COLOR_FIND_HL,
diff --git a/command.c b/command.c
index cd64d38..fb9a390 100644
--- a/command.c
+++ b/command.c
@@ -516,9 +516,9 @@ void command_execute(Ted *ted, Command c, i64 argument) {
case CMD_ESCAPE:
definition_cancel_lookup(ted);
usages_cancel_lookup(ted);
- if (*ted->error_shown) {
- // dismiss error box
- *ted->error_shown = '\0';
+ if (*ted->message_shown) {
+ // dismiss message box
+ *ted->message_shown = '\0';
} else if (ted->autocomplete.open) {
autocomplete_close(ted);
} else if (ted->menu) {
diff --git a/config.c b/config.c
index 4582f3b..25915cc 100644
--- a/config.c
+++ b/config.c
@@ -147,16 +147,6 @@ static void setting_string_set(Settings *settings, const SettingString *set, con
}
-
-
-
-// all worth it for the -Wformat warnings
-#define config_err(cfg, ...) do {\
- if ((cfg)->error) break;\
- snprintf((cfg)->ted->error, sizeof (cfg)->ted->error - 1, "%s:%u: ", (cfg)->filename, (cfg)->line_number), \
- snprintf((cfg)->ted->error + strlen((cfg)->ted->error), sizeof (cfg)->ted->error - 1 - strlen((cfg)->ted->error), __VA_ARGS__), \
- (cfg)->error = true; } while (0)
-
typedef struct {
Ted *ted;
const char *filename;
@@ -164,6 +154,16 @@ typedef struct {
bool error;
} ConfigReader;
+static void config_err(ConfigReader *cfg, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
+static void config_err(ConfigReader *cfg, const char *fmt, ...) {
+ char error[1024] = {0};
+ strbuf_printf(error, "%s:%u: ", cfg->filename, cfg->line_number);
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(error + strlen(error), sizeof error - strlen(error) - 1, fmt, args);
+ va_end(args);
+}
+
static void context_copy(SettingsContext *dest, const SettingsContext *src) {
*dest = *src;
if (src->path)
@@ -647,7 +647,10 @@ uniform sampler2D t_texture;\n\
gl_rc_sab_decref(&s->bg_shader);
- GLuint shader = gl_compile_and_link_shaders(ted->error, vshader, fshader);
+ char error[512] = {0};
+ GLuint shader = gl_compile_and_link_shaders(error, vshader, fshader);
+ if (*error)
+ ted_seterr(ted, "%s", error);
if (shader) {
GLuint buffer = 0, array = 0;
glGenBuffers(1, &buffer);
diff --git a/lsp.h b/lsp.h
index 8218cdc..c256ec7 100644
--- a/lsp.h
+++ b/lsp.h
@@ -119,10 +119,10 @@ typedef struct {
} LSPRequestDidChange;
typedef enum {
- ERROR = 1,
- WARNING = 2,
- INFO = 3,
- LOG = 4
+ LSP_WINDOW_MESSAGE_ERROR = 1,
+ LSP_WINDOW_MESSAGE_WARNING = 2,
+ LSP_WINDOW_MESSAGE_INFO = 3,
+ LSP_WINDOW_MESSAGE_LOG = 4
} LSPWindowMessageType;
typedef struct {
diff --git a/main.c b/main.c
index 0926d5d..2254d51 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,8 @@
/*
@TODO:
+- rename ted_seterr to ted_error
+- use keycodes instead of scancodes (maybe that will make numlock modifier no longer necessary)
+- go to declaration with LSP
- ted.h documentation
- handle multiple symbols with same name in go-to-definition menu
- better non-error window/showMessage(Request)
@@ -26,8 +29,8 @@
- rust-analyzer bug reports:
- bad json can give "Unexpected error: client exited without proper shutdown sequence"
FUTURE FEATURES:
+- add numlock as a key modifier? (but make sure "Ctrl+S" handles both "No NumLock+Ctrl+S" and "NumLock+Ctrl+S")
- comment-start + comment-end settings
-- go to declaration with LSP
- robust find (results shouldn't move around when you type things)
- multiple files with command line arguments
- :set-build-command
@@ -37,7 +40,6 @@ FUTURE FEATURES:
- i'm putting this off for now since it seems hard to have undo support for it.
- possible idea: open all files altered, and create undo chains for each of them.
if there are too many files, give an error like "use a different tool for this"
-- add numlock as a key modifier? (but make sure "Ctrl+S" handles both "No NumLock+Ctrl+S" and "NumLock+Ctrl+S")
- better undo chaining (dechain on backspace?)
- allow multiple fonts (fonts directory?)
- regenerate tags for completion too if there are no results
@@ -117,7 +119,7 @@ FUTURE FEATURES:
#endif
-static Rect error_box_rect(Ted *ted) {
+static Rect message_box_rect(Ted *ted) {
Font *font = ted->font;
const Settings *settings = ted_active_settings(ted);
float padding = settings->padding;
@@ -431,9 +433,6 @@ int main(int argc, char **argv) {
// (for testing on Unix systems without /proc)
ted->search_cwd = true;
#endif
-
-
- char config_err[sizeof ted->error] = {0};
PROFILE_TIME(misc_end)
@@ -508,10 +507,6 @@ int main(int argc, char **argv) {
PROFILE_TIME(configs_start)
ted_load_configs(ted, false);
- if (ted_haserr(ted)) {
- strcpy(config_err, ted->error);
- ted_clearerr(ted); // clear the error so later things (e.g. loading font) don't detect an error
- }
PROFILE_TIME(configs_end)
PROFILE_TIME(fonts_start)
@@ -519,8 +514,6 @@ int main(int argc, char **argv) {
PROFILE_TIME(fonts_end)
PROFILE_TIME(create_start)
- if (ted_haserr(ted))
- die("Error loading font: %s", ted_geterr(ted));
{
TextBuffer *lbuffer = &ted->line_buffer;
line_buffer_create(lbuffer, ted);
@@ -535,17 +528,9 @@ int main(int argc, char **argv) {
{
if (starting_filename) {
if (fs_file_exists(starting_filename)) {
- if (!ted_open_file(ted, starting_filename)) {
- char err[512] = {0};
- sprintf(err, "%.500s", ted_geterr(ted)); // -Wrestrict (rightly) complains without this intermediate step
- ted_seterr(ted, "Couldn't load file: %s", err);
- }
+ ted_open_file(ted, starting_filename);
} else {
- if (!ted_new_file(ted, starting_filename)) {
- char err[512] = {0};
- sprintf(err, "%.500s", ted_geterr(ted));
- ted_seterr(ted, "Couldn't create file: %s", err);
- }
+ ted_new_file(ted, starting_filename);
}
} else {
session_read(ted);
@@ -567,8 +552,6 @@ int main(int argc, char **argv) {
PROFILE_TIME(get_ready_start)
Uint32 time_at_last_frame = SDL_GetTicks();
-
- strbuf_cpy(ted->error, config_err);
SDL_GL_SetSwapInterval(1); // vsync
@@ -659,12 +642,12 @@ int main(int argc, char **argv) {
&& ted->nmouse_clicks[button] < arr_count(ted->mouse_clicks[button])) {
vec2 pos = Vec2(x, y);
bool add = true;
- if (*ted->error_shown) {
- if (rect_contains_point(error_box_rect(ted), pos)) {
- // clicked on error
+ if (*ted->message_shown) {
+ if (rect_contains_point(message_box_rect(ted), pos)) {
+ // clicked on message
if (button == SDL_BUTTON_LEFT) {
- // dismiss error
- *ted->error_shown = '\0';
+ // dismiss message
+ *ted->message_shown = '\0';
}
// don't let anyone else use this event
add = false;
@@ -848,13 +831,12 @@ int main(int argc, char **argv) {
switch (r->type) {
case LSP_REQUEST_SHOW_MESSAGE: {
LSPRequestMessage *m = &r->data.message;
- // @TODO: multiple messages
- ted_seterr(ted, "%s", m->message);
+ MessageType type = ted_message_type_from_lsp(m->type);
+ ted_set_message(ted, type, "%s", m->message);
} break;
case LSP_REQUEST_LOG_MESSAGE: {
LSPRequestMessage *m = &r->data.message;
- // @TODO: actual logging
- printf("%s\n", m->message);
+ ted_log(ted, "%s\n", m->message);
} break;
default: break;
}
@@ -1011,39 +993,36 @@ int main(int argc, char **argv) {
}
for (int i = 0; ted->lsps[i]; ++i) {
LSP *lsp = ted->lsps[i];
- if (lsp_get_error(lsp, NULL, 0, false)) {
- lsp_get_error(lsp, ted->error, sizeof ted->error, true);
+ char error[512] = {0};
+ if (lsp_get_error(lsp, error, sizeof error, true)) {
+ ted_seterr(ted, "%s", error);
}
}
// check if there's a new error
- if (ted_haserr(ted)) {
- ted->error_time = ted->frame_time;
- str_cpy(ted->error_shown, sizeof ted->error_shown, ted->error);
-
- // output error to log file
- char tstr[256];
- time_t t = time(NULL);
- struct tm *tm = localtime(&t);
- strftime(tstr, sizeof tstr, "%Y-%m-%d %H:%M:%S", tm);
- ted_log(ted, "[ERROR %s] %s\n", tstr, ted->error);
-
- ted_clearerr(ted);
+ if (*ted->message) {
+ ted->message_time = ted->frame_time;
+ str_cpy(ted->message_shown, sizeof ted->message_shown, ted->message);
+ ted->message_shown_type = ted->message_type;
+ *ted->message = '\0';
}
- // error box
- if (*ted->error_shown) {
- double time_passed = ted->frame_time - ted->error_time;
+ // message box
+ if (*ted->message_shown) {
+ double time_passed = ted->frame_time - ted->message_time;
Settings *settings = ted_active_settings(ted);
if (time_passed > settings->error_display_time) {
// stop showing error
- *ted->error_shown = '\0';
+ *ted->message_shown = '\0';
} else {
- Rect r = error_box_rect(ted);
+ Rect r = message_box_rect(ted);
float padding = settings->padding;
-
- gl_geometry_rect(r, ted_color(ted, COLOR_ERROR_BG));
- gl_geometry_rect_border(r, settings->border_thickness, ted_color(ted, COLOR_ERROR_BORDER));
+ ColorSetting bg_color=0, border_color=0;
+
+ ted_color_settings_for_message_type(ted->message_type, &bg_color, &border_color);
+
+ gl_geometry_rect(r, ted_color(ted, bg_color));
+ gl_geometry_rect_border(r, settings->border_thickness, ted_color(ted, border_color));
float text_x1 = rect_x1(r) + padding, text_x2 = rect_x2(r) - padding;
float text_y1 = rect_y1(r) + padding;
@@ -1055,8 +1034,8 @@ int main(int argc, char **argv) {
text_state.x = text_x1;
text_state.y = text_y1;
text_state.wrap = true;
- rgba_u32_to_floats(ted_color(ted, COLOR_ERROR_TEXT), text_state.color);
- text_utf8_with_state(font, &text_state, ted->error_shown);
+ rgba_u32_to_floats(ted_color(ted, COLOR_TEXT), text_state.color);
+ text_utf8_with_state(font, &text_state, ted->message_shown);
gl_geometry_draw();
text_render(font);
}
diff --git a/ted.c b/ted.c
index 89890a8..5033467 100644
--- a/ted.c
+++ b/ted.c
@@ -16,10 +16,48 @@ void die(const char *fmt, ...) {
exit(EXIT_FAILURE);
}
+static void ted_vset_message(Ted *ted, MessageType type, const char *fmt, va_list args) {
+ char message[sizeof ted->message] = {0};
+ vsnprintf(message, sizeof message - 1, fmt, args);
+
+ // output error to log file
+ char tstr[256];
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&t);
+ strftime(tstr, sizeof tstr, "%Y-%m-%d %H:%M:%S", tm);
+ ted_log(ted, "[ERROR %s] %s\n", tstr, message);
+
+ if (type >= ted->message_type) {
+ ted->message_type = type;
+ strbuf_cpy(ted->message, message);
+ }
+}
+
+void ted_set_message(Ted *ted, MessageType type, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ ted_vset_message(ted, type, fmt, args);
+ va_end(args);
+}
+
void ted_seterr(Ted *ted, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
- vsnprintf(ted->error, sizeof ted->error - 1, fmt, args);
+ ted_vset_message(ted, MESSAGE_ERROR, fmt, args);
+ va_end(args);
+}
+
+void ted_warn(Ted *ted, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ ted_vset_message(ted, MESSAGE_WARNING, fmt, args);
+ va_end(args);
+}
+
+void ted_info(Ted *ted, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ ted_vset_message(ted, MESSAGE_INFO, fmt, args);
va_end(args);
}
@@ -34,24 +72,9 @@ void ted_log(Ted *ted, const char *fmt, ...) {
void ted_seterr_to_buferr(Ted *ted, TextBuffer *buffer) {
- size_t size = sizeof ted->error;
- if (sizeof buffer->error < size) size = sizeof buffer->error;
- memcpy(ted->error, buffer->error, size);
-}
-
-bool ted_haserr(Ted *ted) {
- return ted->error[0] != '\0';
+ ted_seterr(ted, "%s", buffer->error);
}
-const char *ted_geterr(Ted *ted) {
- return ted->error;
-}
-
-void ted_clearerr(Ted *ted) {
- ted->error[0] = '\0';
-}
-
-
void ted_out_of_mem(Ted *ted) {
ted_seterr(ted, "Out of memory.");
}
@@ -235,11 +258,10 @@ static void ted_load_font(Ted *ted, const char *filename, Font **out) {
}
*out = font;
} else {
- ted_seterr(ted, "Couldn't load font: %s", text_get_err());
- text_clear_err();
+ die("Couldn't load font: %s", text_get_err());
}
} else {
- ted_seterr(ted, "Couldn't find font file. There is probably a problem with your ted installation.");
+ die("Couldn't find font file. There is probably a problem with your ted installation.");
}
}
@@ -624,3 +646,32 @@ void ted_check_for_node_problems(Ted *ted) {
}
}
}
+
+MessageType ted_message_type_from_lsp(LSPWindowMessageType type) {
+ switch (type) {
+ case LSP_WINDOW_MESSAGE_ERROR: return MESSAGE_ERROR;
+ case LSP_WINDOW_MESSAGE_WARNING: return MESSAGE_WARNING;
+ case LSP_WINDOW_MESSAGE_INFO:
+ case LSP_WINDOW_MESSAGE_LOG:
+ return MESSAGE_INFO;
+ }
+ assert(0);
+ return MESSAGE_ERROR;
+}
+
+void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_color, ColorSetting *border_color) {
+ switch (type) {
+ case MESSAGE_ERROR:
+ *bg_color = COLOR_ERROR_BG;
+ *border_color = COLOR_ERROR_BORDER;
+ break;
+ case MESSAGE_WARNING:
+ *bg_color = COLOR_WARNING_BG;
+ *border_color = COLOR_WARNING_BORDER;
+ break;
+ case MESSAGE_INFO:
+ *bg_color = COLOR_INFO_BG;
+ *border_color = COLOR_INFO_BORDER;
+ break;
+ }
+}
diff --git a/ted.cfg b/ted.cfg
index 205ab74..1871987 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -310,7 +310,12 @@ menu-hl = #afa2
# error box colors
error-border = #f00
error-bg = #800
-error-text = #fdd
+# warning box colors
+warning-border = #ff0
+warning-bg = #660
+# info box colors
+info-border = #00f
+info-bg = #004
# color to highlight search results with
find-hl = #fff4
yes = #afa
diff --git a/ted.h b/ted.h
index 85eac8d..7f759b5 100644
--- a/ted.h
+++ b/ted.h
@@ -482,6 +482,14 @@ typedef struct {
LSPDocumentPosition requested_position;
} Highlights;
+// more severe message types should have higher numbers.
+// they will override less severe messages.
+typedef enum {
+ MESSAGE_INFO,
+ MESSAGE_WARNING,
+ MESSAGE_ERROR
+} MessageType;
+
typedef struct Ted {
LSP *lsps[TED_LSP_MAX + 1];
// current time (see time_get_seconds), as of the start of this frame
@@ -518,7 +526,6 @@ typedef struct Ted {
TextBuffer replace_buffer; // "replace" for find+replace
TextBuffer build_buffer; // buffer for build output (view only)
TextBuffer argument_buffer; // used for command selector
- double error_time; // time error box was opened (in seconds -- see time_get_seconds)
double cursor_error_time; // time which the cursor error animation started (cursor turns red, e.g. when there's no autocomplete suggestion)
bool search_start_cwd; // should start_cwd be searched for files? set to true if the executable isn't "installed"
char start_cwd[TED_PATH_MAX];
@@ -598,8 +605,13 @@ typedef struct Ted {
u32 nstrings;
char *strings[TED_MAX_STRINGS];
char window_title[256];
- char error[512];
- char error_shown[512]; // error display in box on screen
+
+ // little box used to display errors and info.
+ double message_time; // time message box was opened
+ MessageType message_type;
+ char message[512];
+ MessageType message_shown_type;
+ char message_shown[512];
} Ted;
// === buffer.c ===
@@ -1034,8 +1046,14 @@ SymbolInfo *tags_get_symbols(Ted *ted);
// === ted.c ===
// for fatal errors
void die(PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
-// for non-fatal errors that should be displayed to the user
+// display a message to the user
+void ted_set_message(Ted *ted, MessageType type, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(3, 4);
+// display an error to the user
void ted_seterr(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
+// display a warning to the user
+void ted_warn(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
+// display information to the user
+void ted_info(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
// for information that should be logged
void ted_log(Ted *ted, PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
// set error to "out of memory" message.
@@ -1048,15 +1066,12 @@ Status ted_get_file(Ted const *ted, const char *name, char *out, size_t outsz);
void ted_path_full(Ted *ted, const char *relpath, char *abspath, size_t abspath_size);
void ted_reset_active_buffer(Ted *ted);
void ted_seterr_to_buferr(Ted *ted, TextBuffer *buffer);
-bool ted_haserr(Ted *ted);
// Returns the buffer containing the file at `path`, or NULL if there is none.
TextBuffer *ted_get_buffer_with_file(Ted *ted, const char *path);
bool ted_save_all(Ted *ted);
void ted_reload_all(Ted *ted);
-const char *ted_geterr(Ted *ted);
// Load all the fonts ted will use.
void ted_load_fonts(Ted *ted);
-void ted_clearerr(Ted *ted);
char *ted_get_root_dir_of(Ted *ted, const char *path);
char *ted_get_root_dir(Ted *ted);
// the settings of the active buffer, or the default settings if there is no active buffer
@@ -1093,6 +1108,10 @@ void ted_cancel_lsp_request(Ted *ted, LSPID lsp, LSPRequestID request);
float ted_line_buffer_height(Ted *ted);
// check for orphaned nodes and node cycles
void ted_check_for_node_problems(Ted *ted);
+// convert LSPWindowMessageType to MessageType
+MessageType ted_message_type_from_lsp(LSPWindowMessageType type);
+// get colors to use for message box
+void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_color, ColorSetting *border_color);
// === ui.c ===
void selector_up(Ted *ted, Selector *s, i64 n);