summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c17
-rw-r--r--build.c104
-rw-r--r--command.c6
-rw-r--r--command.h4
-rw-r--r--ted.cfg2
-rw-r--r--ted.h6
6 files changed, 122 insertions, 17 deletions
diff --git a/buffer.c b/buffer.c
index 6d5b211..b4d9833 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1889,7 +1889,8 @@ void buffer_reload(TextBuffer *buffer) {
BufferPos cursor_pos = buffer->cursor_pos;
float x1 = buffer->x1, y1 = buffer->y1, x2 = buffer->x2, y2 = buffer->y2;
double scroll_x = buffer->scroll_x; double scroll_y = buffer->scroll_y;
- if (buffer_load_file(buffer, buffer->filename)) {
+ char *filename = str_dup(buffer->filename);
+ if (buffer_load_file(buffer, filename)) {
buffer->x1 = x1; buffer->y1 = y1; buffer->x2 = x2; buffer->y2 = y2;
buffer->cursor_pos = cursor_pos;
buffer->scroll_x = scroll_x;
@@ -1897,6 +1898,7 @@ void buffer_reload(TextBuffer *buffer) {
buffer_validate_cursor(buffer);
buffer_correct_scroll(buffer);
}
+ free(filename);
}
}
@@ -2051,7 +2053,6 @@ void buffer_render(TextBuffer *buffer, Rect r) {
float render_start_y = y1 - (float)(buffer->scroll_y - start_line) * char_height; // where the 1st line is rendered
- bool render_cursor = buffer == ted->active_buffer;
// line numbering
if (!buffer->is_line_buffer && settings->line_numbers) {
@@ -2062,7 +2063,7 @@ void buffer_render(TextBuffer *buffer, Rect r) {
text_state.max_y = y2;
float y = render_start_y;
- u32 cursor_line = render_cursor ? buffer->cursor_pos.line : U32_MAX;
+ u32 cursor_line = buffer->cursor_pos.line;
for (u32 line = start_line; line < nlines; ++line) {
char str[32] = {0};
strbuf_printf(str, U32_FMT, line + 1); // convert line number to string
@@ -2085,6 +2086,11 @@ void buffer_render(TextBuffer *buffer, Rect r) {
buffer->x1 = x1; buffer->y1 = y1; buffer->x2 = x2; buffer->y2 = y2;
+ if (buffer->center_cursor_next_frame) {
+ buffer_center_cursor(buffer);
+ buffer->center_cursor_next_frame = false;
+ }
+
// handle mouse clicks
for (u32 i = 0; i < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++i) {
v2 point = ted->mouse_clicks[SDL_BUTTON_LEFT][i];
@@ -2122,8 +2128,7 @@ void buffer_render(TextBuffer *buffer, Rect r) {
// the rectangle that the cursor is rendered as
Rect cursor_rect = rect(cursor_display_pos, V2(settings->cursor_width, char_height));
- if (render_cursor) {
- // highlight line cursor is on
+ { // highlight line cursor is on
Rect hl_rect = rect(V2(x1, cursor_display_pos.y), V2(x2-x1-1, char_height));
buffer_clip_rect(buffer, &hl_rect);
gl_geometry_rect(hl_rect, colors[COLOR_CURSOR_LINE_BG]);
@@ -2265,7 +2270,7 @@ void buffer_render(TextBuffer *buffer, Rect r) {
text_render(font);
- if (render_cursor) {
+ if (ted->active_buffer == buffer) {
// render cursor
float time_on = settings->cursor_blink_time_on;
float time_off = settings->cursor_blink_time_off;
diff --git a/build.c b/build.c
index 6b439e2..1ff93e5 100644
--- a/build.c
+++ b/build.c
@@ -1,4 +1,15 @@
+// clear build errors.
+static void build_clear(Ted *ted) {
+ arr_foreach_ptr(ted->build_errors, BuildError, err) {
+ free(err->filename);
+ }
+ arr_clear(ted->build_errors);
+}
+
static void build_start(Ted *ted) {
+ // get rid of any old build errors
+ build_clear(ted);
+
chdir(ted->cwd);
#if __unix__
char *program = "/bin/sh";
@@ -13,20 +24,55 @@ static void build_start(Ted *ted) {
ted->building = true;
ted->build_shown = true;
buffer_new_file(&ted->build_buffer, NULL);
- ted->build_buffer.store_undo_events = false;
+ ted->build_buffer.store_undo_events = false; // don't need undo events for build output buffer
ted->build_buffer.view_only = true;
}
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;
+ build_clear(ted);
}
+static void build_go_to_error(Ted *ted) {
+ if (ted->build_error < arr_len(ted->build_errors)) {
+ BuildError error = ted->build_errors[ted->build_error];
+ // open the file where the error happened
+ if (ted_open_file(ted, error.filename)) {
+ TextBuffer *buffer = ted->active_buffer;
+ assert(buffer);
+ // move cursor to error
+ buffer_cursor_move_to_pos(buffer, error.pos);
+ buffer->center_cursor_next_frame = true;
+
+ // move cursor to error in build output
+ TextBuffer *build_buffer = &ted->build_buffer;
+ BufferPos error_pos = {.line = error.build_output_line, .index = 0};
+ buffer_cursor_move_to_pos(build_buffer, error_pos);
+ buffer_center_cursor(build_buffer);
+ }
+ }
+}
+
+static void build_next_error(Ted *ted) {
+ if (ted->build_errors) {
+ ted->build_error += 1;
+ ted->build_error %= arr_len(ted->build_errors);
+ build_go_to_error(ted);
+ }
+}
+
+static void build_prev_error(Ted *ted) {
+ if (ted->build_errors) {
+ ted->build_error += arr_len(ted->build_errors) - 1;
+ ted->build_error %= arr_len(ted->build_errors);
+ build_go_to_error(ted);
+ }
+}
+
+
static void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
TextBuffer *buffer = &ted->build_buffer;
Process *process = &ted->build_process;
@@ -82,6 +128,7 @@ static void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
}
if (any_text_inserted) {
+ // show bottom of output (only relevant if there are no build errors)
buffer->cursor_pos = buffer_end_of_file(buffer);
buffer_scroll_to_cursor(buffer);
}
@@ -132,23 +179,60 @@ static void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
}
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);
+
+ if (line_number > 0) {
+ // it's an error
+
+ // check if there's a column number
+ u32 column_len = 0;
+ ++i;
+ while (i < len) {
+ if (str[i] >= '0' && str[i] <= '9')
+ ++column_len;
+ else
+ break;
+ ++i;
+ }
+ int column = 0;
+ if (column_len) {
+ // file:line:column syntax
+ char *column_str = str32_to_utf8_cstr(str32(str + filename_len + 1 + line_number_len + 1, column_len));
+ if (column_str) {
+ column = atoi(column_str);
+ column -= 1;
+ if (column < 0) column = 0;
+ free(column_str);
+ }
+ }
+
+ line_number -= 1; // line numbers in output start from 1.
+ 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);
+ BuildError error = {
+ .filename = str_dup(full_path),
+ .pos = {.line = (u32)line_number, .index = (u32)column},
+ .build_output_line = line_idx
+ };
+ arr_add(ted->build_errors, error);
+ }
}
}
}
}
}
+
+ // go to the first error (if there is one)
+ ted->build_error = 0;
+ build_go_to_error(ted);
}
buffer->view_only = true;
}
diff --git a/command.c b/command.c
index 01a7a88..5926a67 100644
--- a/command.c
+++ b/command.c
@@ -310,5 +310,11 @@ void command_execute(Ted *ted, Command c, i64 argument) {
}
build_start(ted);
break;
+ case CMD_BUILD_NEXT_ERROR:
+ build_next_error(ted);
+ break;
+ case CMD_BUILD_PREV_ERROR:
+ build_prev_error(ted);
+ break;
}
}
diff --git a/command.h b/command.h
index 1e15886..61fd04b 100644
--- a/command.h
+++ b/command.h
@@ -66,6 +66,8 @@ ENUM_U16 {
CMD_VIEW_ONLY, // toggle view-only mode
CMD_BUILD,
+ CMD_BUILD_PREV_ERROR,
+ CMD_BUILD_NEXT_ERROR,
CMD_ESCAPE, // by default this is the escape key. closes menus, etc.
@@ -131,6 +133,8 @@ static CommandName const command_names[CMD_COUNT] = {
{"decrease-text-size", CMD_TEXT_SIZE_DECREASE},
{"view-only", CMD_VIEW_ONLY},
{"build", CMD_BUILD},
+ {"build-prev-error", CMD_BUILD_PREV_ERROR},
+ {"build-next-error", CMD_BUILD_NEXT_ERROR},
{"escape", CMD_ESCAPE},
};
diff --git a/ted.cfg b/ted.cfg
index f222c37..2a8214d 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -112,6 +112,8 @@ Ctrl+- = 3 :decrease-text-size
Ctrl+Alt+Shift+v = :view-only
F4 = :build
+Ctrl+[ = :build-prev-error
+Ctrl+] = :build-next-error
Escape = :escape
diff --git a/ted.h b/ted.h
index 3278e73..ad94ab8 100644
--- a/ted.h
+++ b/ted.h
@@ -137,6 +137,9 @@ typedef struct {
bool will_chain_edits;
bool chaining_edits; // are we chaining undo events together?
bool view_only;
+ // If set to true, buffer will be scrolled to the cursor position next frame.
+ // This is to fix the problem that x1,y1,x2,y2 are not updated until the buffer is rendered.
+ bool center_cursor_next_frame;
float x1, y1, x2, y2;
u32 nlines;
u32 lines_capacity;
@@ -204,7 +207,7 @@ typedef struct {
typedef struct {
char *filename;
- u32 line;
+ BufferPos pos;
u32 build_output_line; // which line in the build output corresponds to this error
} BuildError;
@@ -251,6 +254,7 @@ typedef struct Ted {
bool building; // is the build process running?
BuildError *build_errors; // dynamic array of build errors
+ u32 build_error; // build error we are currently "on"
Process build_process;
// When we read the stdout from the build process, the tail end of the read could be an