summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile17
-rw-r--r--base.h2
-rw-r--r--buffer.c50
-rw-r--r--build.c10
-rw-r--r--command.c6
-rw-r--r--config.c25
-rw-r--r--find.c4
-rw-r--r--gl.c10
-rw-r--r--ide-hover.c4
-rw-r--r--ide-rename.c0
-rw-r--r--ide-signature-help.c5
-rw-r--r--lsp-json.c6
-rw-r--r--lsp-parse.c2
-rw-r--r--lsp-write.c2
-rw-r--r--lsp.c11
-rw-r--r--lsp.h20
-rw-r--r--main.c10
-rw-r--r--menu.c2
-rw-r--r--os-posix.c3
-rw-r--r--os-win.c2
-rw-r--r--os.h6
-rw-r--r--pcre-inc.h3
-rw-r--r--sdl-inc.h15
-rw-r--r--syntax.c2
-rw-r--r--tags.c1
-rw-r--r--ted.c33
-rw-r--r--ted.h53
-rw-r--r--text.c19
-rw-r--r--text.h5
-rw-r--r--ui.c1
-rw-r--r--util.c9
31 files changed, 202 insertions, 136 deletions
diff --git a/Makefile b/Makefile
index ee33799..3216aa0 100644
--- a/Makefile
+++ b/Makefile
@@ -10,10 +10,21 @@ PROFILE_CFLAGS=$(ALL_CFLAGS) -O3 -g -DPROFILE=1
GLOBAL_DATA_DIR=/usr/share/ted
LOCAL_DATA_DIR=/home/`logname`/.local/share/ted
INSTALL_BIN_DIR=/usr/bin
-ted: *.[ch] libpcre2-32.a stb_truetype.o stb_image.o
- $(CC) main.c stb_truetype.o stb_image.o -o ted $(DEBUG_CFLAGS) $(LIBS)
-%.o: %.c
+OBJECTS=obj/buffer.o obj/build.o obj/colors.o obj/command.o\
+ obj/config.o obj/find.o obj/gl.o obj/ide-autocomplete.o\
+ obj/ide-definitions.o obj/ide-highlights.o obj/ide-hover.o\
+ obj/ide-signature-help.o obj/ide-usages.o obj/lsp.o obj/lsp-json.o\
+ obj/lsp-parse.o obj/lsp-write.o obj/main.o obj/menu.o obj/node.o\
+ obj/os-posix.o obj/session.o obj/stb_image.o obj/stb_truetype.o\
+ obj/syntax.o obj/tags.o obj/ted.o obj/text.o obj/ui.o obj/util.o
+ted: *.[ch] libpcre2-32.a $(OBJECTS)
+ $(CC) $(OBJECTS) -o ted $(DEBUG_CFLAGS) $(LIBS)
+obj/stb_%.o: stb_%.c obj
$(CC) -O3 -Wall $< -c -o $@
+obj/%.o: %.c *.h obj
+ $(CC) -Wall $< -c -o $@ $(DEBUG_CFLAGS)
+obj:
+ mkdir obj
release: *.[ch] libpcre2-32.a
$(CC) main.c -o ted $(RELEASE_CFLAGS) $(LIBS)
profile: *.[ch] libpcre2-32.a
diff --git a/base.h b/base.h
index f775bd5..30d9b2c 100644
--- a/base.h
+++ b/base.h
@@ -40,6 +40,8 @@
#include <limits.h>
#include <assert.h>
#include <time.h>
+#include <math.h>
+#include <errno.h>
#if __linux__ || _WIN32
#include <uchar.h>
#else
diff --git a/buffer.c b/buffer.c
index 310d7f0..050676b 100644
--- a/buffer.c
+++ b/buffer.c
@@ -49,7 +49,7 @@ static void buffer_clear_undo_history(TextBuffer *buffer) {
buffer->undo_history_write_pos = U32_MAX;
}
-static void buffer_clear_undo_redo(TextBuffer *buffer) {
+void buffer_clear_undo_redo(TextBuffer *buffer) {
buffer_clear_undo_history(buffer);
buffer_clear_redo_history(buffer);
}
@@ -127,8 +127,7 @@ void line_buffer_create(TextBuffer *buffer, Ted *ted) {
}
}
-// ensures that `p` refers to a valid position.
-static void buffer_pos_validate(TextBuffer *buffer, BufferPos *p) {
+void buffer_pos_validate(TextBuffer *buffer, BufferPos *p) {
if (p->line >= buffer->nlines)
p->line = buffer->nlines - 1;
u32 line_len = buffer->lines[p->line].len;
@@ -167,7 +166,7 @@ static void buffer_pos_handle_inserted_chars(BufferPos *pos, BufferPos ins_pos,
}
}
-static bool buffer_pos_valid(TextBuffer *buffer, BufferPos p) {
+bool buffer_pos_valid(TextBuffer *buffer, BufferPos p) {
return p.line < buffer->nlines && p.index <= buffer->lines[p.line].len;
}
@@ -317,40 +316,13 @@ LSP *buffer_lsp(TextBuffer *buffer) {
}
-// score is higher if context is closer match.
-static long context_score(const char *path, Language lang, const SettingsContext *context) {
- long score = 0;
-
- if (context->language) {
- if (lang == context->language) {
- score += 10000;
- } else {
- // dont use this. it's language-specific and for the wrong language.
- return INT_MIN;
- }
- }
-
- if (context->path) {
- if (path && str_has_path_prefix(path, context->path)) {
- score += (long)strlen(context->path);
- } else {
- // dont use this. it's path-specific and for the wrong path.
- return INT_MIN;
- }
- }
-
- return score;
-}
-// Get the settings used for this buffer.
Settings *buffer_settings(TextBuffer *buffer) {
return ted_get_settings(buffer->ted, buffer->filename, buffer_language(buffer));
}
-// NOTE: this string will be invalidated when the line is edited!!!
-// only use it briefly!!
-static String32 buffer_get_line(TextBuffer *buffer, u32 line_number) {
+String32 buffer_get_line(TextBuffer *buffer, u32 line_number) {
Line *line = &buffer->lines[line_number];
return (String32) {
.str = line->str, .len = line->len
@@ -518,12 +490,7 @@ static i64 buffer_pos_diff(TextBuffer *buffer, BufferPos p1, BufferPos p2) {
return total * factor;
}
-// returns:
-// -1 if p1 comes before p2
-// +1 if p1 comes after p2
-// 0 if p1 = p2
-// faster than buffer_pos_diff (constant time)
-static int buffer_pos_cmp(BufferPos p1, BufferPos p2) {
+int buffer_pos_cmp(BufferPos p1, BufferPos p2) {
if (p1.line < p2.line) {
return -1;
} else if (p1.line > p2.line) {
@@ -539,7 +506,7 @@ static int buffer_pos_cmp(BufferPos p1, BufferPos p2) {
}
}
-static bool buffer_pos_eq(BufferPos p1, BufferPos p2) {
+bool buffer_pos_eq(BufferPos p1, BufferPos p2) {
return p1.line == p2.line && p1.index == p2.index;
}
@@ -990,8 +957,7 @@ bool buffer_pixels_to_pos(TextBuffer *buffer, v2 pixel_coords, BufferPos *pos) {
return ret;
}
-// clip the rectangle so it's all inside the buffer. returns true if there's any rectangle left.
-static bool buffer_clip_rect(TextBuffer *buffer, Rect *r) {
+bool buffer_clip_rect(TextBuffer *buffer, Rect *r) {
float x1, y1, x2, y2;
rect_coords(*r, &x1, &y1, &x2, &y2);
if (x1 > buffer->x2 || y1 > buffer->y2 || x2 < buffer->x1 || y2 < buffer->y1) {
@@ -3018,7 +2984,7 @@ void buffer_toggle_comment_selection(TextBuffer *buffer) {
void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range) {
Font *font = buffer_font(buffer);
const u32 *colors = buffer_settings(buffer)->colors;
- float char_height = font->char_height;
+ const float char_height = text_font_char_height(font);
BufferPos range_start = buffer_pos_from_lsp(buffer, range.start);
BufferPos range_end = buffer_pos_from_lsp(buffer, range.end);
// draw the highlight
diff --git a/build.c b/build.c
index 1ce198f..6046b86 100644
--- a/build.c
+++ b/build.c
@@ -2,7 +2,7 @@
void build_stop(Ted *ted) {
if (ted->building)
- process_kill(&ted->build_process);
+ process_kill(ted->build_process);
ted->building = false;
ted->build_shown = false;
arr_foreach_ptr(ted->build_errors, BuildError, err) {
@@ -38,7 +38,9 @@ static bool build_run_next_command_in_queue(Ted *ted) {
char *command = ted->build_queue[0];
arr_remove(ted->build_queue, 0);
if (ted_save_all(ted)) {
- if (process_run(&ted->build_process, command)) {
+ ted->build_process = process_run(command);
+ const char *error = process_geterr(ted->build_process);
+ if (!error) {
ted->building = true;
ted->build_shown = true;
TextBuffer *build_buffer = &ted->build_buffer;
@@ -50,7 +52,7 @@ static bool build_run_next_command_in_queue(Ted *ted) {
free(command);
return true;
} else {
- ted_seterr(ted, "Couldn't start build: %s", process_geterr(&ted->build_process));
+ ted_seterr(ted, "Couldn't start build: %s", error);
build_stop(ted);
return false;
}
@@ -238,7 +240,7 @@ void build_check_for_errors(Ted *ted) {
void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
TextBuffer *buffer = &ted->build_buffer;
- Process *process = &ted->build_process;
+ Process *process = ted->build_process;
assert(ted->build_shown);
char buf[256];
if (ted->building) {
diff --git a/command.c b/command.c
index 0347544..a21647c 100644
--- a/command.c
+++ b/command.c
@@ -311,7 +311,7 @@ void command_execute(Ted *ted, Command c, i64 argument) {
menu_open(ted, MENU_OPEN);
break;
case CMD_NEW:
- ted_new_file(ted, NULL);
+ (void)ted_new_file(ted, NULL);
break;
case CMD_SAVE:
ted->last_save_time = ted->frame_time;
@@ -331,7 +331,7 @@ void command_execute(Ted *ted, Command c, i64 argument) {
break;
case CMD_SAVE_ALL:
ted->last_save_time = ted->frame_time;
- ted_save_all(ted);
+ (void)ted_save_all(ted);
break;
case CMD_RELOAD_ALL:
ted_reload_all(ted);
@@ -412,7 +412,7 @@ void command_execute(Ted *ted, Command c, i64 argument) {
case CMD_OPEN_CONFIG: {
char local_config_filename[TED_PATH_MAX];
strbuf_printf(local_config_filename, "%s" PATH_SEPARATOR_STR TED_CFG, ted->local_data_dir);
- ted_open_file(ted, local_config_filename);
+ (void)ted_open_file(ted, local_config_filename);
} break;
case CMD_COMMAND_SELECTOR:
menu_open(ted, MENU_COMMAND_SELECTOR);
diff --git a/config.c b/config.c
index bc02e5c..4582f3b 100644
--- a/config.c
+++ b/config.c
@@ -170,6 +170,31 @@ static void context_copy(SettingsContext *dest, const SettingsContext *src) {
dest->path = str_dup(src->path);
}
+// score is higher if context is closer match.
+long context_score(const char *path, Language lang, const SettingsContext *context) {
+ long score = 0;
+
+ if (context->language) {
+ if (lang == context->language) {
+ score += 10000;
+ } else {
+ // dont use this. it's language-specific and for the wrong language.
+ return INT_MIN;
+ }
+ }
+
+ if (context->path) {
+ if (path && str_has_path_prefix(path, context->path)) {
+ score += (long)strlen(context->path);
+ } else {
+ // dont use this. it's path-specific and for the wrong path.
+ return INT_MIN;
+ }
+ }
+
+ return score;
+}
+
/* does being in the context of `parent` imply you are in the context of `child`? */
static bool context_is_parent(const SettingsContext *parent, const SettingsContext *child) {
if (child->language == 0 && parent->language != 0)
diff --git a/find.c b/find.c
index cb50f1a..f0dfb90 100644
--- a/find.c
+++ b/find.c
@@ -1,8 +1,6 @@
#include "ted.h"
+#include "pcre-inc.h"
-#define PCRE2_STATIC
-#define PCRE2_CODE_UNIT_WIDTH 32
-#include <pcre2.h>
#define FIND_MAX_GROUPS 50
diff --git a/gl.c b/gl.c
index 65f474d..57b716c 100644
--- a/gl.c
+++ b/gl.c
@@ -167,7 +167,7 @@ GLuint gl_compile_and_link_shaders(char error_buf[256], const char *vshader_code
return program;
}
-GLuint gl_attrib_loc(GLuint program, const char *attrib) {
+GLuint gl_attrib_location(GLuint program, const char *attrib) {
GLint loc = glGetAttribLocation(program, attrib);
if (loc == -1) {
debug_print("Couldn't find vertex attribute %s.\n", attrib);
@@ -176,7 +176,7 @@ GLuint gl_attrib_loc(GLuint program, const char *attrib) {
return (GLuint)loc;
}
-GLint gl_uniform_loc(GLuint program, const char *uniform) {
+GLint gl_uniform_location(GLuint program, const char *uniform) {
GLint loc = glGetUniformLocation(program, uniform);
if (loc == -1) {
debug_print("Couldn't find uniform: %s.\n", uniform);
@@ -218,9 +218,9 @@ void gl_geometry_init(void) {
";
gl_geometry_program = gl_compile_and_link_shaders(NULL, vshader_code, fshader_code);
- gl_geometry_v_pos = gl_attrib_loc(gl_geometry_program, "v_pos");
- gl_geometry_v_color = gl_attrib_loc(gl_geometry_program, "v_color");
- gl_geometry_u_window_size = gl_uniform_loc(gl_geometry_program, "u_window_size");
+ gl_geometry_v_pos = gl_attrib_location(gl_geometry_program, "v_pos");
+ gl_geometry_v_color = gl_attrib_location(gl_geometry_program, "v_color");
+ gl_geometry_u_window_size = gl_uniform_location(gl_geometry_program, "u_window_size");
glGenBuffers(1, &gl_geometry_vbo);
if (gl_version_major >= 3)
diff --git a/ide-hover.c b/ide-hover.c
index ecca8d8..254f56d 100644
--- a/ide-hover.c
+++ b/ide-hover.c
@@ -120,8 +120,8 @@ void hover_frame(Ted *ted, double dt) {
const u32 *colors = settings->colors;
const char *text = hover->text;
Font *font = ted->font;
- float x = ted->mouse_pos.x, y = ted->mouse_pos.y + font->char_height;
- float char_height = font->char_height;
+ float char_height = text_font_char_height(font);
+ float x = ted->mouse_pos.x, y = ted->mouse_pos.y + char_height;
buffer_highlight_lsp_range(buffer, hover->range);
diff --git a/ide-rename.c b/ide-rename.c
deleted file mode 100644
index e69de29..0000000
--- a/ide-rename.c
+++ /dev/null
diff --git a/ide-signature-help.c b/ide-signature-help.c
index 0e6fd91..e573f3e 100644
--- a/ide-signature-help.c
+++ b/ide-signature-help.c
@@ -117,9 +117,10 @@ void signature_help_frame(Ted *ted) {
float width = buffer->x2 - buffer->x1;
float height = FLT_MAX;
+ const float char_height = text_font_char_height(font);
// make sure signature help doesn't take up too much space
while (1) {
- height = font->char_height * signature_count;
+ height = char_height * signature_count;
if (height < (buffer->y2 - buffer->y1) * 0.25f)
break;
--signature_count;
@@ -146,7 +147,7 @@ void signature_help_frame(Ted *ted) {
text_utf8_with_state(font, &state, signature->label_pre);
text_utf8_with_state(font_bold, &state, signature->label_active);
text_utf8_with_state(font, &state, signature->label_post);
- y += font->char_height;
+ y += char_height;
}
gl_geometry_draw();
diff --git a/lsp-json.c b/lsp-json.c
index 4d5a2c7..94bb556 100644
--- a/lsp-json.c
+++ b/lsp-json.c
@@ -4,7 +4,8 @@
#define LSP_INTERNAL 1
#include "lsp.h"
-
+#include "util.h"
+#include "unicode.h"
#define SKIP_WHITESPACE while (json_is_space(text[index])) ++index;
@@ -587,8 +588,7 @@ void json_string_get(const JSON *json, JSONString string, char *buf, size_t buf_
*buf = '\0';
}
-// returns a malloc'd null-terminated string.
-static char *json_string_get_alloc(const JSON *json, JSONString string) {
+char *json_string_get_alloc(const JSON *json, JSONString string) {
u32 n = string.len + 1;
if (n == 0) --n; // extreme edge case
char *buf = calloc(1, n);
diff --git a/lsp-parse.c b/lsp-parse.c
index 17650c3..7b5849f 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -1,5 +1,7 @@
#define LSP_INTERNAL 1
#include "lsp.h"
+#include "util.h"
+#include "unicode.h"
static WarnUnusedResult bool lsp_expect_type(LSP *lsp, JSONValue value, JSONValueType type, const char *what) {
if (value.type != type) {
diff --git a/lsp-write.c b/lsp-write.c
index 1a1093c..ecb8527 100644
--- a/lsp-write.c
+++ b/lsp-write.c
@@ -324,7 +324,7 @@ static void message_writer_write_and_free(LSP *lsp, JSONWriter *o) {
#endif
// @TODO: does write always write the full amount? probably not. this should be fixed.
- process_write(&lsp->process, content, strlen(content));
+ process_write(lsp->process, content, strlen(content));
str_builder_free(&builder);
}
diff --git a/lsp.c b/lsp.c
index 35ec0d7..2fea94b 100644
--- a/lsp.c
+++ b/lsp.c
@@ -1,5 +1,8 @@
#define LSP_INTERNAL 1
#include "lsp.h"
+#include "util.h"
+
+const char *language_to_str(Language language);
// it's nice to have request IDs be totally unique, including across LSP servers.
static LSPRequestID get_request_id(void) {
@@ -249,7 +252,7 @@ static void lsp_receive(LSP *lsp, size_t max_size) {
// read stderr. if all goes well, we shouldn't get anything over stderr.
char stderr_buf[1024] = {0};
for (size_t i = 0; i < (max_size + sizeof stderr_buf) / sizeof stderr_buf; ++i) {
- ssize_t nstderr = process_read_stderr(&lsp->process, stderr_buf, sizeof stderr_buf - 1);
+ ssize_t nstderr = process_read_stderr(lsp->process, stderr_buf, sizeof stderr_buf - 1);
if (nstderr > 0) {
// uh oh
stderr_buf[nstderr] = '\0';
@@ -262,7 +265,7 @@ static void lsp_receive(LSP *lsp, size_t max_size) {
size_t received_so_far = arr_len(lsp->received_data);
arr_reserve(lsp->received_data, received_so_far + max_size + 1);
- long long bytes_read = process_read(&lsp->process, lsp->received_data + received_so_far, max_size);
+ long long bytes_read = process_read(lsp->process, lsp->received_data + received_so_far, max_size);
if (bytes_read <= 0) {
// no data
return;
@@ -449,7 +452,7 @@ LSP *lsp_create(const char *root_dir, Language language, const char *analyzer_co
.separate_stderr = true,
.working_directory = root_dir,
};
- process_run_ex(&lsp->process, analyzer_command, &settings);
+ lsp->process = process_run_ex(analyzer_command, &settings);
LSPRequest initialize = {
.type = LSP_REQUEST_INITIALIZE
};
@@ -513,7 +516,7 @@ void lsp_free(LSP *lsp) {
SDL_DestroyMutex(lsp->workspace_folders_mutex);
SDL_DestroyMutex(lsp->error_mutex);
SDL_DestroySemaphore(lsp->quit_sem);
- process_kill(&lsp->process);
+ process_kill(lsp->process);
arr_free(lsp->received_data);
diff --git a/lsp.h b/lsp.h
index 7803ea1..5c35113 100644
--- a/lsp.h
+++ b/lsp.h
@@ -3,10 +3,14 @@
#include "base.h"
#include "ds.h"
+#include "os.h"
typedef u32 LSPDocumentID;
typedef u32 LSPID;
typedef u32 LSPRequestID;
+typedef struct SDL_mutex *LSPMutex;
+typedef struct SDL_semaphore *LSPSemaphore;
+typedef struct SDL_Thread *LSPThread;
typedef struct {
u32 line;
@@ -496,14 +500,14 @@ typedef struct LSP {
// thread-safety: created in lsp_create, then only accessed by the communication thread
Process *process;
- SDL_mutex *document_mutex;
+ LSPMutex document_mutex;
// for our purposes, folders are "documents"
// the spec kinda does this too: WorkspaceFolder has a `uri: DocumentUri` member.
StrHashTable document_ids; // values are u32. they are indices into document_data.
// this is a dynamic array which just keeps growing.
// but the user isn't gonna open millions of files so it's fine.
LSPDocumentData *document_data;
- SDL_mutex *messages_mutex;
+ LSPMutex messages_mutex;
LSPMessage *messages_server2client;
LSPMessage *messages_client2server;
// we keep track of client-to-server requests
@@ -516,8 +520,8 @@ typedef struct LSP {
_Atomic bool initialized;
// thread-safety: only set once in lsp_create.
Language language;
- SDL_Thread *communication_thread;
- SDL_sem *quit_sem;
+ LSPThread communication_thread;
+ LSPSemaphore quit_sem;
// thread-safety: only accessed in communication thread
char *received_data; // dynamic array
// thread-safety: in the communication thread, we fill this in, then set `initialized = true`.
@@ -530,9 +534,9 @@ typedef struct LSP {
char32_t *signature_help_trigger_chars; // dynamic array
// thread-safety: same as `capabilities`
char32_t *signature_help_retrigger_chars; // dynamic array
- SDL_mutex *workspace_folders_mutex;
+ LSPMutex workspace_folders_mutex;
LSPDocumentID *workspace_folders; // dynamic array of root directories of LSP workspace folders
- SDL_mutex *error_mutex;
+ LSPMutex error_mutex;
char error[256];
} LSP;
@@ -578,6 +582,8 @@ void lsp_free(LSP *lsp);
#if defined LSP_INTERNAL && !defined LSP_INTERNAL_H_
#define LSP_INTERNAL_H_
+#include "sdl-inc.h"
+
#define lsp_set_error(lsp, ...) do {\
SDL_LockMutex(lsp->error_mutex);\
strbuf_printf(lsp->error, __VA_ARGS__);\
@@ -679,6 +685,8 @@ JSONValue json_root(const JSON *json);
JSONValue json_get(const JSON *json, const char *path);
bool json_has(const JSON *json, const char *path);
void json_string_get(const JSON *json, JSONString string, char *buf, size_t buf_sz);
+// returns a malloc'd null-terminated string.
+char *json_string_get_alloc(const JSON *json, JSONString string);
void json_debug_print(const JSON *json);
size_t json_escape_to(char *out, size_t out_sz, const char *in);
char *json_escape(const char *str);
diff --git a/main.c b/main.c
index f8e07d7..59db07b 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,6 @@
/*
@TODO:
+- don't include SDL when possible
- rename v[234] to vec[234]
- make ctrl+up/ctrl+down move to next/prev blank line
- broken session fix: close buffers not in any used node
@@ -17,11 +18,9 @@
- when searching files, put exact matches at the top
- auto-set build command for cmake (both for windows and unix)
--- LSP MERGE ---
-- improve structure of ted source code to make LSP completions better
- (make every c file a valid translation unit)
- - some way of opening + closing all C files in directory for clangd workspace/symbols to work?
- is this still necessary?
- - maybe it can be done with the clangd config instead.s
+- some way of opening + closing all C files in directory for clangd workspace/symbols to work?
+ is this still necessary?
+ - maybe it can be done with the clangd config instead.
- CSS highlighting
- styles ([color] sections)
- more documentation generally (development.md or something?)
@@ -57,7 +56,6 @@ FUTURE FEATURES:
#include "ted.h"
#include <locale.h>
-#include <wctype.h>
#include <signal.h>
#if __linux__
#include <execinfo.h>
diff --git a/menu.c b/menu.c
index d6d954f..3a71a9f 100644
--- a/menu.c
+++ b/menu.c
@@ -181,7 +181,7 @@ void menu_update(Ted *ted) {
if (selected_file) {
// open that file!
menu_close(ted);
- ted_open_file(ted, selected_file);
+ (void)ted_open_file(ted, selected_file);
free(selected_file);
}
} break;
diff --git a/os-posix.c b/os-posix.c
index 5b37268..5b67836 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -1,4 +1,5 @@
#include "os.h"
+#include "util.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -178,7 +179,6 @@ Process *process_run_ex(const char *command, const ProcessSettings *settings) {
}
}
- bool success = false;
pid_t pid = fork();
if (pid == 0) {
// child process
@@ -295,6 +295,7 @@ void process_kill(Process *proc) {
waitpid(proc->pid, NULL, 0);
proc->pid = 0;
process_close_pipes(proc);
+ free(proc);
}
int process_check_status(Process *proc, char *message, size_t message_size) {
diff --git a/os-win.c b/os-win.c
index d22ae40..4279c3f 100644
--- a/os-win.c
+++ b/os-win.c
@@ -1,4 +1,4 @@
-#include "filesystem.h"
+#include "os.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
diff --git a/os.h b/os.h
index 37b7128..27b0d79 100644
--- a/os.h
+++ b/os.h
@@ -2,6 +2,8 @@
#ifndef OS_H_
#define OS_H_
+#include "base.h"
+
typedef enum {
FS_NON_EXISTENT,
FS_FILE,
@@ -55,7 +57,9 @@ static void fs_dir_entries_free(FsDirectoryEntry **entries) {
}
static double time_get_seconds(void) {
- return timespec_to_seconds(time_get());
+ struct timespec t = time_get();
+ return (double)t.tv_sec
+ + (double)t.tv_nsec * 1e-9;
}
diff --git a/pcre-inc.h b/pcre-inc.h
new file mode 100644
index 0000000..44088ec
--- /dev/null
+++ b/pcre-inc.h
@@ -0,0 +1,3 @@
+#define PCRE2_STATIC
+#define PCRE2_CODE_UNIT_WIDTH 32
+#include <pcre2.h>
diff --git a/sdl-inc.h b/sdl-inc.h
new file mode 100644
index 0000000..7bb613b
--- /dev/null
+++ b/sdl-inc.h
@@ -0,0 +1,15 @@
+#ifndef SDL_INC_H_
+#define SDL_INC_H_
+
+no_warn_start
+#if _WIN32
+ #include <SDL.h>
+#else
+ #if DEBUG || __TINYC__ // speed up compile time on debug, also tcc doesn't have immintrin.h
+ #define SDL_DISABLE_IMMINTRIN_H
+ #endif
+ #include <SDL2/SDL.h>
+#endif
+no_warn_end
+
+#endif // SDL_INC_H_
diff --git a/syntax.c b/syntax.c
index 3d8c34f..7526f62 100644
--- a/syntax.c
+++ b/syntax.c
@@ -1253,7 +1253,7 @@ static void syntax_highlight_javascript_like(
// this is not foolproof for detecting regex literals
// but should handle all "reasonable" uses of regex.
bool is_regex = i == 0 // slash is first char in line
- || (line[i-1] <= WCHAR_MAX && iswspace((wint_t)line[i-1])) // slash preceded by space
+ || is32_space(line[i-1]) // slash preceded by space
|| (line[i-1] <= 128 && strchr(";({[=,:", (char)line[i-1])); // slash preceded by any of these characters
if (is_regex) {
in_string = true;
diff --git a/tags.c b/tags.c
index efbf5e2..5b7541d 100644
--- a/tags.c
+++ b/tags.c
@@ -1,4 +1,5 @@
#include "ted.h"
+#include "pcre-inc.h"
static const char *tags_filename(Ted *ted, bool error_if_does_not_exist) {
change_directory(ted->cwd);
diff --git a/ted.c b/ted.c
index 647b48b..627f413 100644
--- a/ted.c
+++ b/ted.c
@@ -39,19 +39,19 @@ static void ted_out_of_mem(Ted *ted) {
ted_seterr(ted, "Out of memory.");
}
-static void *ted_malloc(Ted *ted, size_t size) {
+void *ted_malloc(Ted *ted, size_t size) {
void *ret = malloc(size);
if (!ret) ted_out_of_mem(ted);
return ret;
}
-static void *ted_calloc(Ted *ted, size_t n, size_t size) {
+void *ted_calloc(Ted *ted, size_t n, size_t size) {
void *ret = calloc(n, size);
if (!ret) ted_out_of_mem(ted);
return ret;
}
-static void *ted_realloc(Ted *ted, void *p, size_t new_size) {
+void *ted_realloc(Ted *ted, void *p, size_t new_size) {
void *ret = realloc(p, new_size);
if (!ret) ted_out_of_mem(ted);
return ret;
@@ -175,7 +175,7 @@ u32 ted_color(Ted *ted, ColorSetting color) {
return ted_active_settings(ted)->colors[color];
}
-static void ted_path_full(Ted *ted, const char *relpath, char *abspath, size_t abspath_size) {
+void ted_path_full(Ted *ted, const char *relpath, char *abspath, size_t abspath_size) {
path_full(ted->cwd, relpath, abspath, abspath_size);
}
@@ -269,7 +269,7 @@ void ted_switch_to_buffer(Ted *ted, TextBuffer *buffer) {
}
// set ted->active_buffer to something nice
-static void ted_reset_active_buffer(Ted *ted) {
+void ted_reset_active_buffer(Ted *ted) {
if (ted->nodes_used[0]) {
Node *node = &ted->nodes[0];
while (!node->tabs)
@@ -282,8 +282,7 @@ static void ted_reset_active_buffer(Ted *ted) {
}
-// returns the index of an available buffer, or -1 if none are available
-static i32 ted_new_buffer(Ted *ted) {
+i32 ted_new_buffer(Ted *ted) {
bool *buffers_used = ted->buffers_used;
for (i32 i = 1; // start from 1, so as not to use the null buffer
i < TED_MAX_BUFFERS; ++i) {
@@ -296,9 +295,7 @@ static i32 ted_new_buffer(Ted *ted) {
return -1;
}
-// Opposite of ted_new_buffer
-// Make sure you set active_buffer to something else if you delete it!
-static void ted_delete_buffer(Ted *ted, u16 index) {
+void ted_delete_buffer(Ted *ted, u16 index) {
TextBuffer *buffer = &ted->buffers[index];
if (buffer == ted->active_buffer)
ted_switch_to_buffer(ted, NULL); // make sure we don't set the active buffer to something invalid
@@ -308,8 +305,7 @@ static void ted_delete_buffer(Ted *ted, u16 index) {
ted->buffers_used[index] = false;
}
-// Returns the index of an available node, or -1 if none are available
-static i32 ted_new_node(Ted *ted) {
+i32 ted_new_node(Ted *ted) {
bool *nodes_used = ted->nodes_used;
for (i32 i = 0; i < TED_MAX_NODES; ++i) {
if (!nodes_used[i]) {
@@ -323,14 +319,12 @@ static i32 ted_new_node(Ted *ted) {
}
-// how tall is a line buffer?
-static float ted_line_buffer_height(Ted *ted) {
+float ted_line_buffer_height(Ted *ted) {
const float char_height = text_font_char_height(ted->font);
return char_height + 2 * ted_active_settings(ted)->border_thickness;
}
-// switch to this node
-static void ted_node_switch(Ted *ted, Node *node) {
+void ted_node_switch(Ted *ted, Node *node) {
assert(node->tabs);
ted_switch_to_buffer(ted, &ted->buffers[node->tabs[node->active_tab]]);
}
@@ -370,8 +364,7 @@ static Status ted_open_buffer(Ted *ted, u16 *buffer_idx, u16 *tab) {
}
}
-// Returns the buffer containing the file at `path`, or NULL if there is none.
-static TextBuffer *ted_get_buffer_with_file(Ted *ted, const char *path) {
+TextBuffer *ted_get_buffer_with_file(Ted *ted, const char *path) {
bool *buffers_used = ted->buffers_used;
TextBuffer *buffers = ted->buffers;
for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) {
@@ -440,7 +433,7 @@ Status ted_new_file(Ted *ted, const char *filename) {
Status ted_save_all(Ted *ted) {
- Status success = true;
+ bool success = true;
bool *buffers_used = ted->buffers_used;
for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) {
if (buffers_used[i]) {
@@ -463,7 +456,7 @@ Status ted_save_all(Ted *ted) {
return success;
}
-static void ted_reload_all(Ted *ted) {
+void ted_reload_all(Ted *ted) {
bool *buffers_used = ted->buffers_used;
for (u64 i = 0; i < TED_MAX_BUFFERS; ++i) {
if (buffers_used[i]) {
diff --git a/ted.h b/ted.h
index 9c7305f..83b3a08 100644
--- a/ted.h
+++ b/ted.h
@@ -2,16 +2,7 @@
#define TED_H_
#include "base.h"
-no_warn_start
-#if _WIN32
- #include <SDL.h>
-#else
- #if DEBUG || __TINYC__ // speed up compile time on debug, also tcc doesn't have immintrin.h
- #define SDL_DISABLE_IMMINTRIN_H
- #endif
- #include <SDL2/SDL.h>
-#endif
-no_warn_end
+#include "sdl-inc.h"
#include "util.h"
#include "os.h"
#include "unicode.h"
@@ -615,6 +606,7 @@ typedef struct Ted {
bool buffer_haserr(TextBuffer *buffer);
const char *buffer_geterr(TextBuffer *buffer);
void buffer_clearerr(TextBuffer *buffer);
+void buffer_clear_undo_redo(TextBuffer *buffer);
bool buffer_empty(TextBuffer *buffer);
const char *buffer_get_filename(TextBuffer *buffer);
bool buffer_is_untitled(TextBuffer *buffer);
@@ -629,16 +621,24 @@ char32_t buffer_char_before_cursor(TextBuffer *buffer);
char32_t buffer_char_after_cursor(TextBuffer *buffer);
BufferPos buffer_pos_start_of_file(TextBuffer *buffer);
BufferPos buffer_pos_end_of_file(TextBuffer *buffer);
+// ensures that `p` refers to a valid position, moving it if needed.
+void buffer_pos_validate(TextBuffer *buffer, BufferPos *p);
+bool buffer_pos_valid(TextBuffer *buffer, BufferPos p);
Language buffer_language(TextBuffer *buffer);
+// clip the rectangle so it's all inside the buffer. returns true if there's any rectangle left.
+bool buffer_clip_rect(TextBuffer *buffer, Rect *r);
LSP *buffer_lsp(TextBuffer *buffer);
+// Get the settings used for this buffer.
Settings *buffer_settings(TextBuffer *buffer);
+// NOTE: this string will be invalidated when the line is edited!!!
+// only use it briefly!!
+String32 buffer_get_line(TextBuffer *buffer, u32 line_number);
size_t buffer_get_text_at_pos(TextBuffer *buffer, BufferPos pos, char32_t *text, size_t nchars);
String32 buffer_get_str32_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars);
char *buffer_get_utf8_text_at_pos(TextBuffer *buffer, BufferPos pos, size_t nchars);
size_t buffer_contents_utf8(TextBuffer *buffer, char *out);
char *buffer_contents_utf8_alloc(TextBuffer *buffer);
void buffer_check_valid(TextBuffer *buffer);
-void buffer_check_valid(TextBuffer *buffer);
void buffer_free(TextBuffer *buffer);
void buffer_clear(TextBuffer *buffer);
void buffer_text_dimensions(TextBuffer *buffer, u32 *lines, u32 *columns);
@@ -749,6 +749,14 @@ void buffer_toggle_comment_lines(TextBuffer *buffer, u32 first_line, u32 last_li
void buffer_toggle_comment_selection(TextBuffer *buffer);
// make sure to call gl_geometry_draw after this
void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range);
+bool buffer_pos_eq(BufferPos p1, BufferPos p2);
+
+// returns:
+// -1 if p1 comes before p2
+// +1 if p1 comes after p2
+// 0 if p1 = p2
+// faster than buffer_pos_diff (constant time)
+int buffer_pos_cmp(BufferPos p1, BufferPos p2);
// === build.c ===
// clear build errors and stop
@@ -805,6 +813,7 @@ void config_read(Ted *ted, ConfigPart **parts, const char *filename);
void config_parse(Ted *ted, ConfigPart **pparts);
void config_free(Ted *ted);
char *settings_get_root_dir(Settings *settings, const char *path);
+long context_score(const char *path, Language lang, const SettingsContext *context);
// === find.c ===
TextBuffer *find_search_buffer(Ted *ted);
@@ -923,6 +932,7 @@ void autocomplete_frame(Ted *ted);
// Note: the document position is required for LSP requests because of overloading (where the name
// alone isn't sufficient)
void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition pos);
+void definition_cancel_lookup(Ted *ted);
void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *response);
void definitions_selector_open(Ted *ted);
void definitions_selector_update(Ted *ted);
@@ -1021,9 +1031,19 @@ SymbolInfo *tags_get_symbols(Ted *ted);
snprintf((ted)->error, sizeof (ted)->error - 1, __VA_ARGS__)
// for fatal errors
void die(PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
+void *ted_malloc(Ted *ted, size_t size);
+void *ted_calloc(Ted *ted, size_t n, size_t size);
+void *ted_realloc(Ted *ted, void *p, size_t new_size);
Status ted_get_file(Ted const *ted, const char *name, char *out, size_t outsz);
+// get full path relative to ted->cwd.
+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);
+Status 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);
@@ -1039,11 +1059,20 @@ LSP *ted_active_lsp(Ted *ted);
u32 ted_color(Ted *ted, ColorSetting color);
Status ted_open_file(Ted *ted, const char *filename);
Status ted_new_file(Ted *ted, const char *filename);
+// returns the index of an available buffer, or -1 if none are available
+i32 ted_new_buffer(Ted *ted);
+// Returns the index of an available node, or -1 if none are available
+i32 ted_new_node(Ted *ted);
+// Opposite of ted_new_buffer
+// Make sure you set active_buffer to something else if you delete it!
+void ted_delete_buffer(Ted *ted, u16 index);
// save all changes to all buffers with unsaved changes.
Status ted_save_all(Ted *ted);
// sets the active buffer to this buffer, and updates active_node, etc. accordingly
// you can pass NULL to buffer to make it so no buffer is active.
void ted_switch_to_buffer(Ted *ted, TextBuffer *buffer);
+// switch to this node
+void ted_node_switch(Ted *ted, Node *node);
void ted_load_configs(Ted *ted, bool reloading);
void ted_press_key(Ted *ted, SDL_Scancode scancode, SDL_Keymod modifier);
bool ted_get_mouse_buffer_pos(Ted *ted, TextBuffer **pbuffer, BufferPos *ppos);
@@ -1051,6 +1080,8 @@ void ted_flash_error_cursor(Ted *ted);
void ted_go_to_position(Ted *ted, const char *path, u32 line, u32 index, bool is_lsp);
void ted_go_to_lsp_document_position(Ted *ted, LSP *lsp, LSPDocumentPosition position);
void ted_cancel_lsp_request(Ted *ted, LSPID lsp, LSPRequestID request);
+// how tall is a line buffer?
+float ted_line_buffer_height(Ted *ted);
// === ui.c ===
void selector_up(Ted *ted, Selector *s, i64 n);
diff --git a/text.c b/text.c
index 94dd8c7..6e40733 100644
--- a/text.c
+++ b/text.c
@@ -1,6 +1,5 @@
-#include "base.h"
-#include "text.h"
-#include "unicode.h"
+#include "ted.h"
+
#if DEBUG
typedef struct
{
@@ -23,8 +22,6 @@ no_warn_end
#endif
-#include <stdlib.h>
-
// We split up code points into a bunch of pages, so we don't have to load all of the font at
// once into one texture.
#define CHAR_PAGE_SIZE 2048
@@ -52,7 +49,7 @@ struct Font {
TextTriangle *triangles[CHAR_PAGE_COUNT]; // triangles to render for each page
};
-TextRenderState const text_render_state_default = {
+const TextRenderState text_render_state_default = {
.render = true,
.wrap = false,
.x = 0, .y = 0,
@@ -114,11 +111,11 @@ void main() {\n\
";
text_program = gl_compile_and_link_shaders(NULL, vshader_code, fshader_code);
- text_v_pos = gl_attrib_loc(text_program, "v_pos");
- text_v_color = gl_attrib_loc(text_program, "v_color");
- text_v_tex_coord = gl_attrib_loc(text_program, "v_tex_coord");
- text_u_sampler = gl_uniform_loc(text_program, "sampler");
- text_u_window_size = gl_uniform_loc(text_program, "u_window_size");
+ text_v_pos = gl_attrib_location(text_program, "v_pos");
+ text_v_color = gl_attrib_location(text_program, "v_color");
+ text_v_tex_coord = gl_attrib_location(text_program, "v_tex_coord");
+ text_u_sampler = gl_uniform_location(text_program, "sampler");
+ text_u_window_size = gl_uniform_location(text_program, "u_window_size");
glGenBuffers(1, &text_vbo);
glGenVertexArrays(1, &text_vao);
diff --git a/text.h b/text.h
index 0074448..01fc053 100644
--- a/text.h
+++ b/text.h
@@ -1,6 +1,9 @@
#ifndef TEXT_H_
#define TEXT_H_
+#include "base.h"
+#include "util.h"
+
// A text-rendering interface.
// Example usage:
// Font *font = text_font_load("font.ttf", 18);
@@ -73,6 +76,6 @@ void text_render(Font *font);
// TextRenderState state = text_render_state_default;
// (set a few options)
// text_render_with_state(font, &state, ...)
-const TextRenderState text_render_state_default;
+extern const TextRenderState text_render_state_default;
#endif
diff --git a/ui.c b/ui.c
index d9ac83f..c87596f 100644
--- a/ui.c
+++ b/ui.c
@@ -2,6 +2,7 @@
#if __unix__
#include <fcntl.h>
+#include <unistd.h>
#endif
static Status file_selector_cd_(Ted *ted, FileSelector *fs, const char *path, int symlink_depth);
diff --git a/util.c b/util.c
index 8cd1527..0c1c1c3 100644
--- a/util.c
+++ b/util.c
@@ -1,3 +1,7 @@
+#include "base.h"
+#include "util.h"
+#include "unicode.h"
+
#if _WIN32
#include <intrin.h>
#include <direct.h>
@@ -6,10 +10,7 @@
#else
#error "Unrecognized operating system."
#endif
-
-#include "base.h"
-#include "util.h"
-#include "unicode.h"
+#include <wctype.h>
// on 16-bit systems, this is 16383. on 32/64-bit systems, this is 1073741823
// it is unusual to have a string that long.