aboutsummaryrefslogtreecommitdiff
path: root/include/ecex.h
diff options
context:
space:
mode:
authorDavid Moc <personal@cdatgoose.org>2026-06-02 13:50:21 +0200
committerDavid Moc <personal@cdatgoose.org>2026-06-02 13:50:21 +0200
commita15cb041654ae307add0b998b526c87c3f42bf5f (patch)
tree225bb4b70e9fa05aa5f4d2722a1a9cf5fc6fca7f /include/ecex.h
parent6aeaa171dc1ca43392f53cbd02097f76e1b1c5a0 (diff)
Add plugin hooks and mode plugins
Diffstat (limited to 'include/ecex.h')
-rw-r--r--include/ecex.h127
1 files changed, 80 insertions, 47 deletions
diff --git a/include/ecex.h b/include/ecex.h
index efcbe5a..085c3d2 100644
--- a/include/ecex.h
+++ b/include/ecex.h
@@ -6,6 +6,7 @@
#include "eval.h"
#include "path.h"
#include "media.h"
+#include "plugin.h"
typedef struct ecex_config_command {
@@ -24,6 +25,9 @@ typedef struct ecex_config_mode_keybind {
const char *command;
} ecex_config_mode_keybind_t;
+#define ECEX_COMPLETION_DEFAULT 0
+#define ECEX_COMPLETION_ED_ARROW 1
+
ecex_t *ecex_new(void);
void ecex_free(ecex_t *ed);
@@ -35,61 +39,34 @@ void *ecex_config_calloc(size_t count, size_t size);
void ecex_config_free(void *ptr);
double ecex_time_seconds(void);
void ecex_log(const char *message);
+void ecex_logf(const char *fmt, ...);
+void ecex_log_group_begin(const char *message);
+void ecex_log_group_end(const char *message);
void ecex_log_int(const char *message, int value);
void ecex_log_double(const char *message, double value);
void ecex_log_ptr(const char *message, const void *ptr);
+void ecex_log_flush(void);
void ecex_mem_zero(void *ptr, size_t size);
int ecex_i32_get(const int *items, size_t index);
void ecex_i32_set(int *items, size_t index, int value);
int ecex_prng_next_bounded(unsigned int *state, int bound);
int ecex_random_bounded(int bound);
-int ecex_tetris_shape_cell(int piece, int rot, int col, int row);
-
-/* Host-owned variable registry for JIT plugins. Plugins can keep persistent
- * scalar values, dynamic arrays, or static host buffers behind a stable owner
- * pointer and a name instead of relying on fragile JIT struct/array storage. */
-void *ecex_var_get(ecex_t *ed, void *owner, const char *name);
-void *ecex_var_get_or_alloc(ecex_t *ed, void *owner, const char *name, size_t count, size_t elem_size);
-int ecex_var_bind_static(ecex_t *ed, void *owner, const char *name, void *data, size_t count, size_t elem_size);
-int ecex_var_free(ecex_t *ed, void *owner, const char *name);
-int ecex_var_free_owner(ecex_t *ed, void *owner);
-int ecex_var_i32_get(ecex_t *ed, void *owner, const char *name, size_t index, int fallback);
-int ecex_var_i32_set(ecex_t *ed, void *owner, const char *name, size_t index, int value);
-int ecex_var_i32(ecex_t *ed, void *owner, const char *name, int fallback);
-int ecex_var_i32_set_scalar(ecex_t *ed, void *owner, const char *name, int value);
-
-/* Host-owned object allocator for plugin state. Returned pointers are tracked
- * by the editor and can be freed through the API. Prefer this for callback
- * userdata over plugin/local allocations when the object has callback lifetime.
- */
-void *ecex_object_alloc(ecex_t *ed, size_t size);
-void *ecex_object_calloc(ecex_t *ed, size_t count, size_t size);
-int ecex_object_free(ecex_t *ed, void *object);
-int ecex_object_valid(ecex_t *ed, void *object);
-int ecex_object_i32_get(ecex_t *ed, void *object, size_t byte_offset, int fallback);
-int ecex_object_i32_set(ecex_t *ed, void *object, size_t byte_offset, int value);
-void *ecex_object_ptr_get(ecex_t *ed, void *object, size_t byte_offset);
-int ecex_object_ptr_set(ecex_t *ed, void *object, size_t byte_offset, void *value);
-
-/* Host-owned text registry for plugins that need to render arbitrary text.
- * Plugins copy text into host storage, then draw by owner/id. This avoids
- * passing JIT-owned literals or stack strings into the normal text renderer. */
-int ecex_text_set(ecex_t *ed, void *owner, int id, const char *text, int len);
-int ecex_text_set_buffer_title(ecex_t *ed, void *owner, int id, buffer_t *buffer);
-int ecex_text_free(ecex_t *ed, void *owner, int id);
-int ecex_text_free_owner(ecex_t *ed, void *owner);
+
+/* The plugin runtime owns long-lived JIT/plugin state. Plugins must register a
+ * stable id and then allocate slots, objects, text, and file handlers through
+ * the returned opaque handle. Slots are private unless explicitly exported,
+ * and cross-plugin reads are copy-only. */
int ecex_buffer_text_len(buffer_t *buffer);
-int ecex_buffer_scroll_line(buffer_t *buffer);
-int ecex_buffer_line_count_i(buffer_t *buffer);
-int ecex_buffer_line_copy(buffer_t *buffer, int line, char *out, int out_cap);
-int ecex_markdown_draw_line_from_buffer_i(ecex_draw_context_t *ctx, void *owner, buffer_t *buffer, int line, int y, int in_code);
-int ecex_markdown_body_y_i(ecex_draw_context_t *ctx);
-int ecex_draw_context_height_i(ecex_draw_context_t *ctx);
-int ecex_draw_context_line_height_i(ecex_draw_context_t *ctx);
+int ecex_buffer_scroll_line_index(buffer_t *buffer);
+int ecex_buffer_line_count_int(buffer_t *buffer);
+int ecex_buffer_line_copy_text(buffer_t *buffer, int line, char *out, int out_cap);
+int ecex_markdown_draw_buffer_line_i(ecex_draw_context_t *ctx, void *owner, buffer_t *buffer, int line, int y, int in_code);
+int ecex_markdown_body_y_px(ecex_draw_context_t *ctx);
+int ecex_draw_context_height_px(ecex_draw_context_t *ctx);
+int ecex_draw_context_line_height_px(ecex_draw_context_t *ctx);
-int ecex_register_file_handler(ecex_t *ed, const char *extension, ecex_file_handler_fn fn);
-int ecex_run_file_handlers(ecex_t *ed, buffer_t *buffer);
+int ecex_run_plugin_file_handlers(ecex_t *ed, buffer_t *buffer);
int ecex_reserve_buffers(ecex_t *ed, size_t needed);
int ecex_add_buffer(ecex_t *ed, buffer_t *buffer);
@@ -137,6 +114,52 @@ int ecex_apply_theme(ecex_t *ed, const ecex_theme_t *theme);
int ecex_register_command(ecex_t *ed, const char *name, ecex_command_fn fn);
int ecex_execute_command(ecex_t *ed, const char *name);
+int ecex_add_command_hook(ecex_t *ed,
+ const char *name,
+ ecex_command_hook_fn fn,
+ void *userdata,
+ ecex_hook_free_fn free_fn);
+int ecex_remove_command_hook(ecex_t *ed, const char *name);
+int ecex_add_prefix_hook(ecex_t *ed,
+ const char *name,
+ ecex_prefix_hook_fn fn,
+ void *userdata,
+ ecex_hook_free_fn free_fn);
+int ecex_remove_prefix_hook(ecex_t *ed, const char *name);
+void ecex_notify_prefix_hooks(ecex_t *ed, const char *prefix, int event);
+int ecex_add_buffer_hook(ecex_t *ed,
+ const char *name,
+ ecex_buffer_hook_fn fn,
+ void *userdata,
+ ecex_hook_free_fn free_fn);
+int ecex_remove_buffer_hook(ecex_t *ed, const char *name);
+void ecex_notify_buffer_hooks(ecex_t *ed, buffer_t *buffer, int event);
+void ecex_message(ecex_t *ed, const char *message);
+int ecex_dependency_available(const char *program);
+int ecex_plugin_require_dependency(ecex_t *ed, const char *plugin_id, const char *program);
+int ecex_add_completion_provider(ecex_t *ed,
+ const char *name,
+ const char *mode_name,
+ ecex_completion_provider_fn fn,
+ void *userdata,
+ ecex_hook_free_fn free_fn);
+int ecex_add_word_completion_provider(ecex_t *ed,
+ const char *name,
+ const char *mode_name,
+ const char *const *words,
+ size_t word_count,
+ int flags);
+int ecex_define_word_completion_provider(ecex_t *ed,
+ const char *name,
+ const char *mode_name,
+ int flags);
+int ecex_completion_provider_add_word(ecex_t *ed, const char *name, const char *word);
+int ecex_completion_provider_add_words(ecex_t *ed, const char *name, const char *words);
+int ecex_completion_provider_set_detail(ecex_t *ed, const char *name, const char *detail);
+int ecex_add_clangd_completion_provider(ecex_t *ed, const char *name, const char *mode_name);
+int ecex_remove_completion_provider(ecex_t *ed, const char *name);
+int ecex_buffer_identifier_prefix(buffer_t *buffer, char *out, size_t out_size);
+int ecex_complete_at_point(ecex_t *ed);
void ecex_set_clipboard_callbacks(ecex_t *ed,
ecex_clipboard_get_fn get_fn,
ecex_clipboard_set_fn set_fn,
@@ -156,6 +179,12 @@ const char *ecex_buffer_major_mode_name(ecex_t *ed, buffer_t *buffer);
int ecex_bind_mode_key(ecex_t *ed, const char *mode_name, const char *key, const char *command);
const char *ecex_lookup_key_for_buffer(ecex_t *ed, buffer_t *buffer, const char *key);
int ecex_key_sequence_has_prefix_for_buffer(ecex_t *ed, buffer_t *buffer, const char *prefix);
+int ecex_describe_key_prefix(ecex_t *ed,
+ buffer_t *buffer,
+ const char *prefix,
+ char *out,
+ size_t out_size,
+ size_t max_items);
int ecex_auto_set_major_mode(ecex_t *ed, buffer_t *buffer);
int ecex_list_commands(ecex_t *ed);
@@ -244,12 +273,13 @@ void ecex_draw_rgba(ecex_draw_context_t *ctx,
/* CCDJIT-safe integer drawing wrappers. Prefer these from plugins when the
* JIT ABI is known to be fragile with float/double arguments. Colors are
* 0..255 RGBA and coordinates are integer pixels local to the buffer window. */
-void ecex_draw_color_rgba8(ecex_draw_context_t *ctx, int r, int g, int b, int a);
+void ecex_draw_color_rgba8_i(ecex_draw_context_t *ctx, int r, int g, int b, int a);
void ecex_draw_rect_i(ecex_draw_context_t *ctx, int x, int y, int w, int h);
void ecex_draw_rect_outline_i(ecex_draw_context_t *ctx, int x, int y, int w, int h, int thickness);
void ecex_draw_line_i(ecex_draw_context_t *ctx, int x1, int y1, int x2, int y2, int thickness);
void ecex_draw_text_i(ecex_draw_context_t *ctx, int x, int y, const char *text);
-void ecex_draw_text_id_i(ecex_draw_context_t *ctx, void *owner, int id, int x, int y);
+void ecex_draw_plugin_text_i(ecex_draw_context_t *ctx, void *owner, int id, int x, int y);
+void ecex_draw_plugin_text_rect_i(ecex_draw_context_t *ctx, void *owner, int id, int x, int y, int w, int h, int padding, unsigned int bg_rgba, unsigned int fg_rgba);
void ecex_draw_markdown_canvas_i(ecex_draw_context_t *ctx, void *owner, int title_id, int x, int y, int w, int line_h);
void ecex_draw_markdown_text_i(ecex_draw_context_t *ctx, void *owner, int text_id, int x, int y, int w, int line_h, int style);
@@ -273,6 +303,7 @@ int ecex_rerun_compile(ecex_t *ed);
int ecex_rerun_grep(ecex_t *ed);
int ecex_next_interactive_action(ecex_t *ed);
int ecex_previous_interactive_action(ecex_t *ed);
+int ecex_indent_line_to(buffer_t *buffer, int target_cols);
int ecex_comment_region(ecex_t *ed);
int ecex_uncomment_region(ecex_t *ed);
void ecex_request_prompt(ecex_t *ed, ecex_prompt_request_t request, const char *message);
@@ -320,7 +351,9 @@ void ecex_set_current_line_enabled(ecex_t *ed, int enabled);
#define ECEX_RGB8(r, g, b) ((float)(r) / 255.0f), ((float)(g) / 255.0f), ((float)(b) / 255.0f)
#define ECEX_CONFIG_BEGIN int ecex_config_init(ecex_t *ed) {
#define ECEX_CONFIG_END return 0; }
-#define ECEX_PLUGIN_BEGIN(name) int name(ecex_t *ed) {
+#define ECEX_PLUGIN_BEGIN(name, id) int name(ecex_t *ed) { \
+ ecex_plugin_t *plugin = ecex_plugin_require(ed, (id), ECEX_PLUGIN_API_VERSION); \
+ if (!plugin) return -1;
#define ECEX_PLUGIN_END return 0; }
#define ECEX_CONFIG_TRY(expr) \
do { \