From 4b8db533619ee8eef64ded0793f413faaa7609c2 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Tue, 16 Feb 2021 15:38:59 -0500 Subject: detecting errors in build output --- buffer.c | 33 +++++++++++++++++++++++++++++++++ build.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ find.c | 12 ------------ main.c | 33 ++++----------------------------- ted.c | 29 +++++++++++++++++++++++++++++ ted.h | 11 +++++++++++ 6 files changed, 137 insertions(+), 41 deletions(-) diff --git a/buffer.c b/buffer.c index eeadff0..6d5b211 100644 --- a/buffer.c +++ b/buffer.c @@ -2085,6 +2085,38 @@ void buffer_render(TextBuffer *buffer, Rect r) { buffer->x1 = x1; buffer->y1 = y1; buffer->x2 = x2; buffer->y2 = y2; + // handle mouse clicks + for (u32 i = 0; i < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++i) { + v2 point = ted->mouse_clicks[SDL_BUTTON_LEFT][i]; + u8 times = ted->mouse_click_times[SDL_BUTTON_LEFT][i]; + BufferPos pos; + if (buffer_pixels_to_pos(buffer, point, &pos)) { + // user clicked on buffer + if (!ted->menu) + ted->active_buffer = buffer; + if (buffer == ted->active_buffer) { + buffer_cursor_move_to_pos(buffer, pos); + + switch ((times - 1) % 3) { + case 0: break; // single-click + case 1: // double-click: select word + buffer_select_word(buffer); + break; + case 2: // triple-click: select line + buffer_select_line(buffer); + break; + } + ted->drag_buffer = buffer; + } + } + } + + if (rect_contains_point(rect4(x1, y1, x2, y2), ted->mouse_pos)) { + // scroll with mouse wheel + double scroll_speed = 2.5; + buffer_scroll(buffer, ted->scroll_total_x * scroll_speed, ted->scroll_total_y * scroll_speed); + } + // get screen coordinates of cursor v2 cursor_display_pos = buffer_pos_to_pixels(buffer, buffer->cursor_pos); // the rectangle that the cursor is rendered as @@ -2283,6 +2315,7 @@ void buffer_render(TextBuffer *buffer, Rect r) { } gl_geometry_draw(); } + } // if you do: diff --git a/build.c b/build.c index 0afee56..6b439e2 100644 --- a/build.c +++ b/build.c @@ -1,4 +1,5 @@ static void build_start(Ted *ted) { + chdir(ted->cwd); #if __unix__ char *program = "/bin/sh"; char *argv[] = { @@ -19,6 +20,9 @@ static void build_start(Ted *ted) { static void build_stop(Ted *ted) { if (ted->building) process_kill(&ted->build_process); + arr_foreach_ptr(ted->build_errors, BuildError, err) { + free(err->filename); + } ted->building = false; ted->build_shown = false; } @@ -89,6 +93,62 @@ static void build_frame(Ted *ted, float x1, float y1, float x2, float y2) { } else { buffer_insert_utf8_at_cursor(buffer, message); ted->building = false; + + // check for errors + for (u32 line_idx = 0; line_idx < buffer->nlines; ++line_idx) { + Line *line = &buffer->lines[line_idx]; + if (line->len < 3) { + continue; + } + bool is_error = true; + u32 i = 0; + char32_t *str = line->str; u32 len = line->len; + + // we have something like main.c:5 + + // get file name + while (i < len) { + if (str[i] == ':') break; + if (!is32_alnum(str[i]) && str[i] != '/' && str[i] != '.' && str[i] != '\\') { + is_error = false; + break; + } + ++i; + } + if (i >= len) is_error = false; + + if (is_error) { + u32 filename_len = i; + u32 line_number_len = 0; + ++i; + while (i < len) { + if (str[i] == ':') break; + if (str[i] < '0' || str[i] > '9') { + is_error = false; + break; + } + ++i; + ++line_number_len; + } + if (i >= len) is_error = false; + if (line_number_len == 0) is_error = false; + + if (is_error) { + char *line_number_str = str32_to_utf8_cstr(str32(str + filename_len + 1, line_number_len)); + if (line_number_str) { + int line_number = atoi(line_number_str); + free(line_number_str); + + char *filename = str32_to_utf8_cstr(str32(str, filename_len)); + if (filename) { + char full_path[TED_PATH_MAX]; + ted_full_path(ted, filename, full_path, sizeof full_path); + printf("File %s line %d\n",full_path,line_number); + } + } + } + } + } } buffer->view_only = true; } diff --git a/find.c b/find.c index 2612577..12455bd 100644 --- a/find.c +++ b/find.c @@ -413,18 +413,6 @@ static void find_menu_frame(Ted *ted, float x1, float y1, float x2, float y2) { x += checkbox_frame(ted, &ted->find_case_sensitive, "Case sensitive", V2(x, y1)).x + 2*padding; x += checkbox_frame(ted, &ted->find_regex, "Regular expression", V2(x, y1)).x + 2*padding; - if (replace) { - // check if the find or replace line buffer was clicked on - for (u32 i = 0; i < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++i) { - v2 point = ted->mouse_clicks[SDL_BUTTON_LEFT][i]; - if (rect_contains_point(find_buffer_bounds, point)) - ted->active_buffer = find_buffer; - else if (rect_contains_point(replace_buffer_bounds, point)) - ted->active_buffer = replace_buffer; - - } - } - buffer_render(find_buffer, find_buffer_bounds); if (replace) buffer_render(replace_buffer, replace_buffer_bounds); diff --git a/main.c b/main.c index f2f5ec7..09009f5 100644 --- a/main.c +++ b/main.c @@ -412,9 +412,6 @@ int main(int argc, char **argv) { Sint32 dx = event.wheel.x, dy = -event.wheel.y; ted->scroll_total_x += dx; ted->scroll_total_y += dy; - double scroll_speed = 2.5; - if (ted->active_buffer) - buffer_scroll(ted->active_buffer, dx * scroll_speed, dy * scroll_speed); } break; case SDL_MOUSEBUTTONDOWN: { Uint32 button = event.button.button; @@ -435,33 +432,11 @@ int main(int argc, char **argv) { add = false; } } - if (add) - ted->mouse_clicks[button][ted->nmouse_clicks[button]++] = pos; - } - switch (button) { - case SDL_BUTTON_LEFT: { - if (buffer) { - BufferPos pos = {0}; - if (buffer_pixels_to_pos(buffer, V2(x, y), &pos)) { - if (key_modifier == KEY_MODIFIER_SHIFT) { - buffer_select_to_pos(buffer, pos); - } else if (key_modifier == 0) { - buffer_cursor_move_to_pos(buffer, pos); - switch ((event.button.clicks - 1) % 3) { - case 0: break; // single-click - case 1: // double-click: select word - buffer_select_word(buffer); - break; - case 2: // triple-click: select line - buffer_select_line(buffer); - break; - } - } - ted->drag_buffer = buffer; - - } + if (add) { + ted->mouse_clicks[button][ted->nmouse_clicks[button]] = pos; + ted->mouse_click_times[button][ted->nmouse_clicks[button]] = event.button.clicks; + ++ted->nmouse_clicks[button]; } - } break; } } break; case SDL_MOUSEMOTION: { diff --git a/ted.c b/ted.c index a1cbed5..94505df 100644 --- a/ted.c +++ b/ted.c @@ -262,3 +262,32 @@ static bool ted_save_all(Ted *ted) { } return success; } + +static void ted_full_path(Ted *ted, char const *relpath, char *abspath, size_t abspath_size) { + str_cpy(abspath, abspath_size, ted->cwd); + + while (1) { + size_t component_len = strcspn(relpath, ALL_PATH_SEPARATORS); + char const *component_end = relpath + component_len; + + size_t len = strlen(abspath); + if (abspath[len - 1] != PATH_SEPARATOR) + str_cat(abspath, abspath_size, PATH_SEPARATOR_STR); + if (component_len == 1 && relpath[0] == '.') { + // ., do nothing + } else if (component_len == 2 && relpath[0] == '.' && relpath[1] == '.') { + // .. + char *lastsep = strrchr(abspath, PATH_SEPARATOR); + if (lastsep == abspath) + lastsep[1] = '\0'; + else + lastsep[0] = '\0'; + } else { + strn_cat(abspath, abspath_size, relpath, component_len); + } + if (*component_end == 0) + break; + else + relpath = component_end + 1; + } +} diff --git a/ted.h b/ted.h index 32a41c1..3278e73 100644 --- a/ted.h +++ b/ted.h @@ -202,6 +202,12 @@ typedef struct { BufferPos end; } FindResult; +typedef struct { + char *filename; + u32 line; + u32 build_output_line; // which line in the build output corresponds to this error +} BuildError; + typedef struct Ted { SDL_Window *window; Font *font_bold; @@ -219,6 +225,8 @@ typedef struct Ted { v2 mouse_pos; u8 nmouse_clicks[4]; // nmouse_clicks[i] = length of mouse_clicks[i] v2 mouse_clicks[4][32]; // mouse_clicks[SDL_BUTTON_RIGHT], for example, is all the right mouse-clicks that have happened this frame + // number of times mouse was clicked at each position + u8 mouse_click_times[4][32]; int scroll_total_x, scroll_total_y; // total amount scrolled in the x and y direction this frame Menu menu; FileSelector file_selector; @@ -241,6 +249,9 @@ typedef struct Ted { Command warn_unsaved; // if non-zero, the user is trying to execute this command, but there are unsaved changes bool build_shown; // are we showing the build output? bool building; // is the build process running? + + BuildError *build_errors; // dynamic array of build errors + Process build_process; // When we read the stdout from the build process, the tail end of the read could be an // incomplete UTF-8 code point. This is where we store that "tail end" until more -- cgit v1.2.3