From 9a4e99b436efefa00277d592ff67798eb491e87a Mon Sep 17 00:00:00 2001 From: Albert Cervin Date: Sun, 12 May 2024 22:55:43 +0200 Subject: [PATCH] Improve API docs and configure system There is now a super minimalistic configure script that automatically detects the event system (epoll/kqueue) and generates a config.h and a config.mk. --- .gitignore | 4 + Doxyfile | 2 +- Makefile | 45 ++++++--- configure | 24 +++++ dged.nix | 9 +- linux.mk | 4 +- openbsd.mk | 3 - scripts/has_header | 2 + src/dged/binding.h | 27 ++++- src/dged/btree.h | 119 ++++++++++++++++++++++ src/dged/buffer.c | 13 ++- src/dged/buffer.h | 225 ++++++++++++++++++++++++++++++++++++++---- src/dged/display.h | 5 +- src/dged/keyboard.h | 2 + src/dged/location.h | 8 +- src/dged/minibuffer.h | 5 +- src/dged/settings.h | 18 ++-- src/main/completion.h | 96 +++++++++++++++++- 18 files changed, 538 insertions(+), 73 deletions(-) create mode 100755 configure create mode 100755 scripts/has_header diff --git a/.gitignore b/.gitignore index be788a6..df73aa8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ /build/ /obj/ +# generated files +/config.mk +/src/config.h + # clangd things /compile_commands.json diff --git a/Doxyfile b/Doxyfile index 7d47437..74682c1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -712,7 +712,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = src/ +INPUT = $(CURDIR)/src/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/Makefile b/Makefile index ea77788..7d84085 100644 --- a/Makefile +++ b/Makefile @@ -9,13 +9,19 @@ SYNTAX_ENABLE ?= true build: mkdir -p build +.if ! exists(${.CURDIR}/config.mk) +. error "Please run ./configure first" +.endif + +.include "config.mk" + HEADERS = src/dged/settings.h src/dged/minibuffer.h src/dged/keyboard.h src/dged/binding.h \ src/dged/buffers.h src/dged/text.h src/dged/display.h src/dged/hashmap.h src/dged/path.h \ src/dged/buffer.h src/dged/btree.h src/dged/command.h src/dged/allocator.h src/dged/reactor.h \ src/dged/vec.h src/dged/window.h src/dged/hash.h src/dged/undo.h src/dged/lang.h \ src/dged/settings-parse.h src/dged/utf8.h src/main/cmds.h src/main/bindings.h \ src/main/search-replace.h src/dged/location.h src/dged/buffer_view.h src/main/completion.h \ - src/dged/timers.h src/dged/s8.h src/main/version.h + src/dged/timers.h src/dged/s8.h src/main/version.h src/config.h SOURCES = src/dged/binding.c src/dged/buffer.c src/dged/command.c src/dged/display.c \ src/dged/keyboard.c src/dged/minibuffer.c src/dged/text.c \ @@ -25,6 +31,13 @@ SOURCES = src/dged/binding.c src/dged/buffer.c src/dged/command.c src/dged/displ MAIN_SOURCES = src/main/main.c src/main/cmds.c src/main/bindings.c src/main/search-replace.c src/main/completion.c +.if $(HAS_EPOLL) == true && !make(run-tests) + MAIN_SOURCES += src/dged/reactor-epoll.c +.elif $(HAS_KQUEUE) == true && !make() && !make(run-tests) + MAIN_SOURCES += src/dged/reactor-kqueue.c +.endif + + TEST_SOURCES = test/assert.c test/buffer.c test/text.c test/utf8.c test/main.c \ test/command.c test/keyboard.c test/fake-reactor.c test/allocator.c \ test/minibuffer.c test/undo.c test/settings.c test/container.c @@ -44,19 +57,19 @@ CFLAGS += -Werror -g -O2 -std=c99 \ ASAN ?= false .if $(ASAN) == true -CFLAGS += -fsanitize=address -fno-omit-frame-pointer -LDFLAGS += -fsanitize=address + CFLAGS += -fsanitize=address -fno-omit-frame-pointer + LDFLAGS += -fsanitize=address .endif .if $(SYNTAX_ENABLE) == true -HEADERS += src/dged/syntax.h -SOURCES += src/dged/syntax.c + HEADERS += src/dged/syntax.h + SOURCES += src/dged/syntax.c -treesitterflags != pkg-config tree-sitter --cflags -CFLAGS += ${treesitterflags} -DSYNTAX_ENABLE + treesitterflags != pkg-config tree-sitter --cflags + CFLAGS += ${treesitterflags} -DSYNTAX_ENABLE -treesitterld != pkg-config tree-sitter --libs -LDFLAGS += ${treesitterld} + treesitterld != pkg-config tree-sitter --libs + LDFLAGS += ${treesitterld} .endif UNAME_S != uname -s | tr '[:upper:]' '[:lower:]' @@ -64,12 +77,15 @@ UNAME_S != uname -s | tr '[:upper:]' '[:lower:]' . include "$(.CURDIR)/$(UNAME_S).mk" .endif +# add a define like LINUX/OPENBSD +UNAME_UPPER != uname -s | tr '[:lower:]' '[:upper:]' +CFLAGS += -D$(UNAME_UPPER) + FORMAT_TOOL ?= clang-format DEPS = $(SOURCES:.c=.d) $(MAIN_SOURCES:.c=.d) $(TEST_SOURCES:.c=.d) OBJS = $(SOURCES:.c=.o) -PLATFORM_OBJS = $(PLATFORM_SOURCES:.c=.o) MAIN_OBJS = $(MAIN_SOURCES:.c=.o) TEST_OBJS = $(TEST_SOURCES:.c=.o) @@ -77,7 +93,6 @@ FILES = $(DEPS) \ $(MAIN_OBJS) \ $(OBJS) \ $(TEST_OBJS) \ - $(PLATFORM_OBJS) \ dged \ libdged.a @@ -104,8 +119,8 @@ grammars: dged: $(MAIN_OBJS) libdged.a grammars $(CC) $(LDFLAGS) $(MAIN_OBJS) libdged.a -o dged -lm -libdged.a: $(OBJS) $(PLATFORM_OBJS) - $(AR) -rc libdged.a $(OBJS) $(PLATFORM_OBJS) +libdged.a: $(OBJS) + $(AR) -rc libdged.a $(OBJS) run-tests: $(TEST_OBJS) $(OBJS) $(CC) $(LDFLAGS) $(TEST_OBJS) $(OBJS) -lm -o run-tests @@ -114,7 +129,6 @@ check: run-tests @echo "Running $(FORMAT_TOOL) (--dry-run --Werror)..." @$(FORMAT_TOOL) --dry-run --Werror \ $(SOURCES:%.c=$(.CURDIR)/%.c) \ - $(PLATFORM_SOURCES:%.c=$(.CURDIR)/%.c) \ $(MAIN_SOURCES:%.c=$(.CURDIR)/%.c) \ $(TEST_SOURCES:%c=$(.CURDIR)/%c) \ $(HEADERS:%.h=$(.CURDIR)/%.h) @@ -134,7 +148,6 @@ format: @$(FORMAT_TOOL) -i \ $(SOURCES:%.c=$(.CURDIR)/%.c) \ $(MAIN_SOURCES:%.c=$(.CURDIR)/%.c) \ - $(PLATFORM_SOURCES:%.c=$(.CURDIR)/%.c) \ $(TEST_SOURCES:%c=$(.CURDIR)/%c) \ $(HEADERS:%.h=$(.CURDIR)/%.h) @@ -154,7 +167,7 @@ install: dged cp -RL $(.OBJDIR)/grammars "$(DESTDIR)/$(datadir)/" docs: - doxygen $(.CURDIR)/Doxyfile + CURDIR=$(.CURDIR) doxygen $(.CURDIR)/Doxyfile depend: $(DEPS) @: diff --git a/configure b/configure new file mode 100755 index 0000000..820344e --- /dev/null +++ b/configure @@ -0,0 +1,24 @@ +#! /usr/bin/env sh + +echo "/* Generated by configure */" > src/config.h +echo "#ifndef _CONFIG_H" >> src/config.h +echo "#define _CONFIG_H" >> src/config.h + +echo "# generated by configure" > config.mk + +echo -n "detecting event system... " +if ./scripts/has_header "sys/epoll.h"; then + echo "epoll." + echo "#define HAS_EPOLL 1" >> src/config.h + echo "HAS_EPOLL ?= true" >> config.mk +elif ./scripts/has_header "sys/event.h"; then + echo "kqueue." + echo "#define HAS_KQUEUE 1" >> src/config.h + echo "HAS_KQUEUE ?= true" >> config.mk +else + echo "none." +fi + +echo "#endif" >> src/config.h +echo "wrote src/config.h" +echo "wrote config.mk" diff --git a/dged.nix b/dged.nix index 39b32e1..a8f1a8f 100644 --- a/dged.nix +++ b/dged.nix @@ -45,6 +45,7 @@ stdenv.mkDerivation { ''; }); "rust" = tree-sitter-rust; + "hcl" = tree-sitter-hcl; "nix" = tree-sitter-nix; "python" = tree-sitter-python; "make" = tree-sitter-make; @@ -73,6 +74,10 @@ stdenv.mkDerivation { postInstall = '' cd .. cp -r queries $out + + echo "" >> "$out"/queries/highlights.scm + echo ";; Inserted from javascript" >> "$out"/queries/highlights.scm + cat "${javascript}"/queries/highlights.scm >> "$out"/queries/highlights.scm ''; }; "qmljs" = tree-sitter.buildGrammar { @@ -90,10 +95,6 @@ stdenv.mkDerivation { unlink "$out/queries/highlights-javascript.scm" unlink "$out/queries/highlights-typescript.scm" - echo "" >> "$out"/queries/highlights.scm - echo ";; Inserted from javascript" >> "$out"/queries/highlights.scm - cat "${javascript}"/queries/highlights.scm >> "$out"/queries/highlights.scm - echo "" >> "$out"/queries/highlights.scm echo ";; Inserted from typescript" >> "$out"/queries/highlights.scm cat "${typescript}"/queries/highlights.scm >> "$out"/queries/highlights.scm diff --git a/linux.mk b/linux.mk index c30ff9b..7bcaca3 100644 --- a/linux.mk +++ b/linux.mk @@ -1,3 +1 @@ -CFLAGS += -DLINUX -D_XOPEN_SOURCE=700 - -PLATFORM_SOURCES += src/dged/reactor-epoll.c +CFLAGS += -D_XOPEN_SOURCE=700 diff --git a/openbsd.mk b/openbsd.mk index 59e6ed2..1b1ca61 100644 --- a/openbsd.mk +++ b/openbsd.mk @@ -1,4 +1 @@ -CFLAGS += -DOPENBSD -DBSD - -PLATFORM_SOURCES += src/dged/reactor-kqueue.c FORMAT_TOOL = clang-format-13 diff --git a/scripts/has_header b/scripts/has_header new file mode 100755 index 0000000..5807bdb --- /dev/null +++ b/scripts/has_header @@ -0,0 +1,2 @@ +#! /usr/bin/env sh +echo "#include <$1>" | cc -E - 2>&1 >/dev/null diff --git a/src/dged/binding.h b/src/dged/binding.h index f2a531d..79f8c47 100644 --- a/src/dged/binding.h +++ b/src/dged/binding.h @@ -52,8 +52,31 @@ enum binding_type { .keymap = keymap_ \ } +/** + * Define a key binding. + * + * Used like BINDING((mod), key, "") where + * the key modifier is optional. + */ #define BINDING(...) BINDING_INNER(__VA_ARGS__) + +/** + * Define a prefix (a keybinding for a keymap). + * + * Used like PREFIX((mod), key, ) where + * the key modifier is optional. + */ #define PREFIX(...) PREFIX_INNER(__VA_ARGS__) + +/** + * Define an anonymous binding, i.e. a binding directly to a function. + * + * Note the function that this key binds to cannot usually be + * executed dynamically (with M-x). + * + * Used like ANONYMOUS_BINDING((mod), key, ) where + * the key modifier is optional. + */ #define ANONYMOUS_BINDING(...) ANONYMOUS_BINDING_INNER(__VA_ARGS__) /** @@ -110,7 +133,7 @@ struct keymap keymap_create(const char *name, uint32_t capacity); * * @param keymap The keymap to bind keys in. * @param bindings Bindings to add. - * @param nbindings Number of bindings in @ref bindings. + * @param nbindings Number of bindings in @p bindings. */ void keymap_bind_keys(struct keymap *keymap, struct binding *bindings, uint32_t nbindings); @@ -127,7 +150,7 @@ void keymap_destroy(struct keymap *keymap); * Lookup the binding for a key in a set of keymaps. * * @param keymaps The keymaps to look in. - * @param nkeymaps The number of keymaps in @ref keymaps. + * @param nkeymaps The number of keymaps in @p keymaps. * @param key The keystroke to look up bindings for. * @param commands Available commands for lookup. * @returns A @ref lookup_result with the result of the lookup. diff --git a/src/dged/btree.h b/src/dged/btree.h index 8743b32..8969108 100644 --- a/src/dged/btree.h +++ b/src/dged/btree.h @@ -5,6 +5,13 @@ #include +/** @file btree.h + * Generic binary tree implementation. + */ + +/** + * Define the entry type for the binary tree. + */ #define BINTREE_ENTRY_TYPE(name, entry) \ struct name { \ struct name *parent; \ @@ -13,25 +20,101 @@ entry value; \ } +/** + * Declare a binary tree. + */ #define BINTREE(entry) \ struct { \ struct entry *root; \ } +/** + * Initialize the binary tree. + * + * @param tree The binary tree to initialize. + */ #define BINTREE_INIT(tree) ((tree)->root = NULL) + +/** + * Destroy the binary tree. + * + * Note that this does not clean up any resources and + * you should call @ref BINTREE_FREE_NODES before calling this. + */ #define BINTREE_DESTROY(tree, entry_type) BINTREE_INIT(tree) +/** + * Get the root of the binary tree. + * + * @param tree The binary tree to get root for. + */ #define BINTREE_ROOT(tree) (tree)->root +/** + * Get the left child of the node. + * + * This can be NULL. + * @param node The node to get left child for. + */ #define BINTREE_LEFT(node) (node)->left + +/** + * Get the right child of the node. + * + * This can be NULL. + * @param node The node to get right child for. + */ #define BINTREE_RIGHT(node) (node)->right + +/** + * Get the parent node for this node. + * + * Can be NULL if node is root. + * @param node The node to get parent node of. + */ #define BINTREE_PARENT(node) (node)->parent + +/** + * Get the value for a binary tree node. + * + * @param node The node to get value for + */ #define BINTREE_VALUE(node) (node)->value + +/** + * Check if this node has a parent node. + * + * @param node The node to check. + */ #define BINTREE_HAS_PARENT(node) ((node)->parent != NULL) + +/** + * Check if this node has a left child. + * + * @param node The node to check. + */ #define BINTREE_HAS_LEFT(node) ((node)->left != NULL) + +/** + * Check if this node has a right child. + * + * @param node The node to check. + */ #define BINTREE_HAS_RIGHT(node) ((node)->right != NULL) +/** + * Free any resources associated with @p node + * + * @param node The node to free resources for + */ #define BINTREE_FREE_NODE(node) free(node) + +/** + * Free all nodes from @p root, downwards. + * + * @param root The node to start freeing at. + * @param entry_type The type of entries in this tree. + */ #define BINTREE_FREE_NODES(root, entry_type) \ { \ BINTREE_FIRST(root); \ @@ -45,6 +128,11 @@ VEC_DESTROY(&to_delete); \ } +/** + * Get the first (leftmost) node in the tree. + * + * @param res The result of the operation. + */ #define BINTREE_FIRST(res) \ if (res == NULL) { \ res = NULL; \ @@ -54,6 +142,11 @@ } \ } +/** + * Get the next binary tree node. + * + * @param res The result of the operation. + */ #define BINTREE_NEXT(res) \ if (res == NULL) { \ res = NULL; \ @@ -69,6 +162,14 @@ } \ } +/** + * Insert a node in the bintree as a child to @p parent. + * + * If the parent has no children, the new node is inserted + * as the left child, otherwise it is inserted as the right. + * @param parent The parent node of the new node. + * @param entry The new node to insert. + */ #define BINTREE_INSERT(parent, entry) \ if (parent != NULL) { \ if (!BINTREE_HAS_LEFT(parent)) { \ @@ -82,6 +183,11 @@ } \ } +/** + * Remove @p node from the tree. + * + * @param node The node to remove. + */ #define BINTREE_REMOVE(node) \ if (BINTREE_HAS_PARENT(node)) { \ if (BINTREE_LEFT(BINTREE_PARENT(node)) == node) { \ @@ -92,10 +198,23 @@ BINTREE_PARENT(node) = NULL; \ } +/** + * Set the root of the binary tree. + * + * @param tree The tree to set the root for. + * @param value The value entry for the root node. + */ #define BINTREE_SET_ROOT(tree, value) \ (tree)->root = calloc(1, sizeof(*(tree)->root)); \ BINTREE_VALUE((tree)->root) = value; +/** + * Find a specific value in the binary tree. + * + * @param tree The tree to search in. + * @param needle The value to search for (will be compared with ==). + * @param res A var to store the result in, will be NULL if not found. + */ #define BINTREE_FIND(tree, needle, res) \ { \ res = BINTREE_ROOT(tree); \ diff --git a/src/dged/buffer.c b/src/dged/buffer.c index 3a47db2..c1d9280 100644 --- a/src/dged/buffer.c +++ b/src/dged/buffer.c @@ -129,6 +129,11 @@ uint32_t buffer_add_destroy_hook(struct buffer *buffer, userdata); } +void buffer_remove_destroy_hook(struct buffer *buffer, uint32_t hook_id, + remove_hook_cb callback) { + remove_destroy_hook(&buffer->hooks->destroy_hooks, hook_id, callback); +} + void buffer_static_init() { VEC_INIT(&g_create_hooks, 8); @@ -996,10 +1001,10 @@ void buffer_remove_update_hook(struct buffer *buffer, uint32_t hook_id, remove_update_hook(&buffer->hooks->update_hooks, hook_id, callback); } -uint32_t buffer_add_render_hook(struct buffer *buffer, render_hook_cb hook, +uint32_t buffer_add_render_hook(struct buffer *buffer, render_hook_cb callback, void *userdata) { return insert_render_hook(&buffer->hooks->render_hooks, - &buffer->hooks->render_hook_id, hook, userdata); + &buffer->hooks->render_hook_id, callback, userdata); } void buffer_remove_render_hook(struct buffer *buffer, uint32_t hook_id, @@ -1007,10 +1012,10 @@ void buffer_remove_render_hook(struct buffer *buffer, uint32_t hook_id, remove_render_hook(&buffer->hooks->render_hooks, hook_id, callback); } -uint32_t buffer_add_reload_hook(struct buffer *buffer, reload_hook_cb hook, +uint32_t buffer_add_reload_hook(struct buffer *buffer, reload_hook_cb callback, void *userdata) { return insert_reload_hook(&buffer->hooks->reload_hooks, - &buffer->hooks->reload_hook_id, hook, userdata); + &buffer->hooks->reload_hook_id, callback, userdata); } void buffer_remove_reload_hook(struct buffer *buffer, uint32_t hook_id, diff --git a/src/dged/buffer.h b/src/dged/buffer.h index 496086a..2b53ec2 100644 --- a/src/dged/buffer.h +++ b/src/dged/buffer.h @@ -16,6 +16,13 @@ struct command_list; struct hooks; +/** @file buffer.h + * A buffer of text. + * + * The buffer is one of the fundamental types of DGED. Most + * of the text editing operations are implemented here. + */ + /** * A buffer of text that can be modified, read from and written to disk. * @@ -70,7 +77,7 @@ struct buffer buffer_create(const char *name); * Create a new buffer from a file path. * * @param [in] path Path to the file to load into the new buffer. - * @returns A new buffer with @ref path loaded. + * @returns A new buffer with @p path loaded. */ struct buffer buffer_from_file(const char *path); @@ -188,7 +195,7 @@ bool buffer_is_backed(struct buffer *buffer); * * @param [in] buffer The buffer to use. * @param [in] dot The location to start from. - * @returns The location in front of the previous char given @ref dot. + * @returns The location in front of the previous char given @p dot. */ struct location buffer_previous_char(struct buffer *buffer, struct location dot); @@ -198,7 +205,7 @@ struct location buffer_previous_char(struct buffer *buffer, * * @param [in] buffer The buffer to look in. * @param [in] dot The location to start from. - * @returns The location at the start of the previous word, given @ref dot. + * @returns The location at the start of the previous word, given @p dot. */ struct location buffer_previous_word(struct buffer *buffer, struct location dot); @@ -209,7 +216,7 @@ struct location buffer_previous_word(struct buffer *buffer, * @param [in] buffer The buffer to look in. * @param [in] dot The location to start from. * @returns The location at the start of the line above the current one (the one - * @ref dot is on). If @ref dot is on the first line, the location (0, 0) is + * @p dot is on). If @p dot is on the first line, the location (0, 0) is * returned. */ struct location buffer_previous_line(struct buffer *buffer, @@ -220,7 +227,7 @@ struct location buffer_previous_line(struct buffer *buffer, * * @param [in] buffer The buffer to use. * @param [in] dot The location to start from. - * @returns The location in front of the next char given @ref dot. + * @returns The location in front of the next char given @p dot. */ struct location buffer_next_char(struct buffer *buffer, struct location dot); @@ -229,7 +236,7 @@ struct location buffer_next_char(struct buffer *buffer, struct location dot); * * @param [in] buffer The buffer to look in. * @param [in] dot The location to start from. - * @returns The location at the start of the next word, given @ref dot. + * @returns The location at the start of the next word, given @p dot. */ struct location buffer_next_word(struct buffer *buffer, struct location dot); @@ -239,13 +246,13 @@ struct location buffer_next_word(struct buffer *buffer, struct location dot); * @param [in] buffer The buffer to look in. * @param [in] dot The location to start from. * @returns The location at the start of the line above the current one (the one - * @ref dot is on). If @ref dot is on the last line, the last location in the + * @p dot is on). If @p dot is on the last line, the last location in the * buffer is returned. */ struct location buffer_next_line(struct buffer *buffer, struct location dot); /** - * Get the extents of the word located at @ref at. + * Get the extents of the word located at @p at. * * @param [in] buffer The buffer to look in. * @param [in] at The location to start from. @@ -258,7 +265,7 @@ struct region buffer_word_at(struct buffer *buffer, struct location at); /** * Clamp a buffer position to the boundaries of the buffer. * - * Note that both @ref line and @ref col can be negative or bigger than the + * Note that both @ref line and @p col can be negative or bigger than the * buffer. * * @param [in] buffer The buffer to use for clamping. @@ -338,7 +345,7 @@ struct location buffer_undo(struct buffer *buffer, struct location dot); * @param [in] buffer The buffer to search in. * @param [in] pattern The substring to search for. * @param [out] matches The pointer passed in is modified to point at the - * resulting matches. This pointer should be freed using @ref free. + * resulting matches. This pointer should be freed using @c free. * @param [nmatches] nmatches The pointer passed in is modified to point at the * number of resulting matches. */ @@ -410,21 +417,48 @@ struct text_chunk buffer_line(struct buffer *buffer, uint32_t line); */ struct text_chunk buffer_region(struct buffer *buffer, struct region region); +/** + * Add a text property to a region of the buffer. + * + * @param buffer The buffer to add a text property to. + * @param start The start of the region to set the property for. + * @param end The end of the region to set the property for. + * @param property The text property to set. + */ void buffer_add_text_property(struct buffer *buffer, struct location start, struct location end, struct text_property property); +/** + * Get active text properties at @p location in @p buffer. + * + * @param buffer The buffer to get properties for. + * @param location The location to get properties at. + * @param properties Caller-provided array of properties set by this function. + * @param max_nproperties Max num properties to put in @p properties. + * @param nproperties Number of properties that got stored in @p properties. + */ void buffer_get_text_properties(struct buffer *buffer, struct location location, struct text_property **properties, uint32_t max_nproperties, uint32_t *nproperties); +/** + * Clear any text properties for @p buffer. + * + * @param buffer The buffer to clear properties for. + */ void buffer_clear_text_properties(struct buffer *buffer); /** Callback when removing hooks to clean up userdata */ typedef void (*remove_hook_cb)(void *userdata); -/** Buffer update hook callback function */ +/** + * Buffer update hook callback function. + * + * @param buffer The buffer. + * @param userdata Userdata pointer passed in to @ref buffer_add_update_hook. + */ typedef void (*update_hook_cb)(struct buffer *buffer, void *userdata); /** @@ -438,56 +472,198 @@ typedef void (*update_hook_cb)(struct buffer *buffer, void *userdata); uint32_t buffer_add_update_hook(struct buffer *buffer, update_hook_cb hook, void *userdata); +/** + * Remove a buffer update hook. + * + * @param [in] buffer The buffer to remove the hook from. + * @param [in] hook_id The hook id as returned from @ref buffer_add_update_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ void buffer_remove_update_hook(struct buffer *buffer, uint32_t hook_id, remove_hook_cb callback); -/** Buffer render hook callback function */ +/** + * Buffer render hook callback function. + * + * @param buffer The buffer. + * @param userdata Userdata sent in when registering the hook. + * @param origin The upper left corner of the region of the buffer + * currently rendering. + * @param width The width of the rendered region. + * @param height The height of the rendered region. + */ typedef void (*render_hook_cb)(struct buffer *buffer, void *userdata, struct location origin, uint32_t width, uint32_t height); -uint32_t buffer_add_render_hook(struct buffer *buffer, render_hook_cb hook, +/** + * Add a buffer render hook. + * + * @param [in] buffer The buffer to add the hook to. + * @param [in] callback The render hook callback. + * @param [in] userdata Data that is passed unmodified to the render hook. + * @returns The hook id. + */ +uint32_t buffer_add_render_hook(struct buffer *buffer, render_hook_cb callback, void *userdata); + +/** + * Remove a buffer render hook. + * + * @param [in] buffer The buffer to remove the hook from. + * @param [in] hook_id The hook id as returned from @ref buffer_add_render_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ void buffer_remove_render_hook(struct buffer *buffer, uint32_t hook_id, remove_hook_cb callback); -/** Buffer reload hook callback function */ +/** + * Buffer reload hook callback function. + * + * @param buffer The buffer. + * @param userdata The userdata as sent in to @ref buffer_add_reload_hook. + */ typedef void (*reload_hook_cb)(struct buffer *buffer, void *userdata); -uint32_t buffer_add_reload_hook(struct buffer *buffer, reload_hook_cb hook, + +/** + * Add a reload hook, called when the buffer is reloaded from disk. + * + * Since this is called when the buffer is reloaded from disk it is + * only useful for buffers that are backed by a file on disk. + * + * @param buffer The buffer to add a reload hook to. + * @param callback The function to call when @p buffer is reloaded. + * @param userdata Data that is passed unmodified to the reload hook. + * @returns The hook id. + */ +uint32_t buffer_add_reload_hook(struct buffer *buffer, reload_hook_cb callback, void *userdata); + +/** + * Remove a buffer reload hook. + * + * @param [in] buffer The buffer to remove the hook from. + * @param [in] hook_id The hook id as returned from @ref buffer_add_reload_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ void buffer_remove_reload_hook(struct buffer *buffer, uint32_t hook_id, remove_hook_cb callback); -/** Buffer insert hook callback function */ +/** + * Buffer insert hook callback function. + * + * @param buffer The buffer. + * @param inserted The position in the @p buffer where text was inserted. + * @param begin_idx The global byte offset to the start of where text was + * inserted. + * @param end_idx The global byte offset to the end of where text was inserted. + * @param userdata The userdata as sent in to @ref buffer_add_insert_hook. + */ typedef void (*insert_hook_cb)(struct buffer *buffer, struct region inserted, uint32_t begin_idx, uint32_t end_idx, void *userdata); +/** + * Add an insert hook, called when text is inserted into the @p buffer. + * + * @param buffer The buffer to add an insert hook to. + * @param callback The function to call when text is inserted into @p buffer. + * @param userdata Data that is passed unmodified to the insert hook. + * @returns The hook id. + */ uint32_t buffer_add_insert_hook(struct buffer *buffer, insert_hook_cb callback, void *userdata); + +/** + * Remove a buffer insert hook. + * + * @param [in] buffer The buffer to remove the hook from. + * @param [in] hook_id The hook id as returned from @ref buffer_add_insert_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ void buffer_remove_insert_hook(struct buffer *buffer, uint32_t hook_id, remove_hook_cb callback); -/** Buffer delete hook callback function */ +/** + * Buffer delete hook callback function + * + * @param buffer The buffer. + * @param removed The region that was removed from the @p buffer. + * @param begin_idx The global byte offset to the start of the removed text. + * @param end_idx The global byte offset to the end of the removed text. + * @param userdata The userdata as sent in to @ref buffer_add_delete_hook. + */ typedef void (*delete_hook_cb)(struct buffer *buffer, struct region removed, uint32_t begin_idx, uint32_t end_idx, void *userdata); +/** + * Add a delete hook, called when text is removed from the @p buffer. + * + * @param buffer The buffer to add a delete hook to. + * @param callback The function to call when text is removed from @p buffer. + * @param userdata Data that is passed unmodified to the delete hook. + * @returns The hook id. + */ uint32_t buffer_add_delete_hook(struct buffer *buffer, delete_hook_cb callback, void *userdata); + +/** + * Remove a buffer delete hook. + * + * @param [in] buffer The buffer to remove the hook from. + * @param [in] hook_id The hook id as returned from @ref buffer_add_delete_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ void buffer_remove_delete_hook(struct buffer *buffer, uint32_t hook_id, remove_hook_cb callback); -/** Buffer destroy hook callback function */ +/** + * Buffer destroy hook callback function. + * + * @param buffer The buffer. + * @param userdata The userdata as sent in to @ref buffer_add_destroy_hook. + */ typedef void (*destroy_hook_cb)(struct buffer *buffer, void *userdata); + +/** + * Add a destroy hook, called when @p buffer is destroyed. + * + * @param buffer The buffer to add a destroy hook to. + * @param callback The function to call @p buffer is destroyed. + * @param userdata Data that is passed unmodified to the destroy hook. + * @returns The hook id. + */ uint32_t buffer_add_destroy_hook(struct buffer *buffer, destroy_hook_cb callback, void *userdata); -/** Buffer create hook callback function */ +/** + * Remove a buffer destroy hook. + * + * @param [in] buffer The buffer to remove the hook from. + * @param [in] hook_id The hook id as returned from @ref + * buffer_add_destroy_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ +void buffer_remove_destroy_hook(struct buffer *buffer, uint32_t hook_id, + remove_hook_cb callback); + +/** + * Buffer create hook callback function. + * + * @param buffer The newly created buffer. + * @param userdata The userdata as sent in to @ref buffer_add_create_hook. + */ typedef void (*create_hook_cb)(struct buffer *buffer, void *userdata); /** - * Add a buffer create hook. + * Add a buffer create hook, called everytime a new buffer is created. * * @param [in] callback Create hook callback. * @param [in] userdata Pointer to data that is passed unmodified to the update @@ -496,6 +672,13 @@ typedef void (*create_hook_cb)(struct buffer *buffer, void *userdata); */ uint32_t buffer_add_create_hook(create_hook_cb callback, void *userdata); +/** + * Remove a buffer create hook. + * + * @param [in] hook_id The hook id as returned from @ref buffer_add_create_hook. + * @param [in] callback A function called with the userdata pointer to do + * cleanup. + */ void buffer_remove_create_hook(uint32_t hook_id, remove_hook_cb callback); /** @@ -526,7 +709,7 @@ struct buffer_render_params { * * @param [in] buffer The buffer to update. * @param [inout] params The parameters for the update. The @ref commands field - * in @ref params will be modified with the rendering commands needed for this + * in @p params will be modified with the rendering commands needed for this * buffer. */ void buffer_update(struct buffer *buffer, struct buffer_update_params *params); diff --git a/src/dged/display.h b/src/dged/display.h index 7e3d62c..0fda30d 100644 --- a/src/dged/display.h +++ b/src/dged/display.h @@ -113,12 +113,15 @@ struct command_list *command_list_create(uint32_t capacity, /** * Enable/disable rendering of whitespace characters. * - * ' ' will be rendered with a dot and '\t' as an arrow. + * ' ' will be rendered with a dot and '\\t' as an arrow. * @param list Command list to record command in. * @param show True if whitespace chars should be displayed, false otherwise. */ void command_list_set_show_whitespace(struct command_list *list, bool show); +/** + * Names for the first 16 colors. + */ enum colors { Color_Black = 0, Color_Red, diff --git a/src/dged/keyboard.h b/src/dged/keyboard.h index e65563f..1a8a149 100644 --- a/src/dged/keyboard.h +++ b/src/dged/keyboard.h @@ -105,6 +105,8 @@ struct keyboard keyboard_create_fd(struct reactor *reactor, int fd); * * @param kbd The @ref keyboard to update. * @param reactor The @ref reactor used when creating the @ref keyboard. + * @param frame_alloc Allocation function to use for creating the keyboard + * update buffer. * @returns An instance of @ref keyboard_update representing the result of the * update operation. */ diff --git a/src/dged/location.h b/src/dged/location.h index d11dd94..4404595 100644 --- a/src/dged/location.h +++ b/src/dged/location.h @@ -21,7 +21,7 @@ struct location { * @param [in] location The location to test. * @param [in] l1 The first location. * @param [in] l2 The other location. - * @returns True if @ref location is between @ref l1 and @ref l2. + * @returns True if @p location is between @p l1 and @p l2. */ bool location_is_between(struct location location, struct location l1, struct location l2); @@ -32,8 +32,8 @@ bool location_is_between(struct location location, struct location l1, * @param [in] l1 The first location. * @param [in] l2 The second location. * - * @returns -1 if @ref l1 is before @ref l2, 0 if @ref l1 is equal to @ref l2 - * and +1 if @ref l1 is after @ref l2. + * @returns -1 if @p l1 is before @p l2, 0 if @p l1 is equal to @p l2 + * and +1 if @p l1 is after @p l2. */ int location_compare(struct location l1, struct location l2); @@ -72,7 +72,7 @@ bool region_has_size(struct region region); * * @param [in] region The region to test. * @param [in] location The location to test. - * @returns True if @ref location is inside @ref region. + * @returns True if @p location is inside @p region. */ bool region_is_inside(struct region region, struct location location); diff --git a/src/dged/minibuffer.h b/src/dged/minibuffer.h index 3e94f8c..6ac69c1 100644 --- a/src/dged/minibuffer.h +++ b/src/dged/minibuffer.h @@ -14,7 +14,8 @@ struct keymap; * * Note that the minibuffer is a global instance and this function will do * nothing if called more than once. - * @param buffer underlying buffer to use for text IO in the minibuffer. + * @param buffer Underlying buffer to use for text IO in the minibuffer. + * @param buffers Buffer list used to create and store messages buffer. */ void minibuffer_init(struct buffer *buffer, struct buffers *buffers); @@ -40,7 +41,7 @@ void message(const char *fmt, ...); void minibuffer_echo(const char *fmt, ...); /** - * Echo a message to the minibuffer that disappears after @ref timeout. + * Echo a message to the minibuffer that disappears after @p timeout. * * @param timeout The timeout in seconds after which the message should * disappear. diff --git a/src/dged/settings.h b/src/dged/settings.h index 6e94d64..b88e483 100644 --- a/src/dged/settings.h +++ b/src/dged/settings.h @@ -67,7 +67,6 @@ struct settings { * Initialize the global collection of settings. * * @param initial_capacity Initial capacity of the settings collection. - * @returns Nothing, the settings collection is a global instance. */ void settings_init(uint32_t initial_capacity); @@ -80,7 +79,7 @@ void settings_destroy(); * Retrieve a single setting by path. * * @param path The exact path of the setting on - * the form ... + * the form @code .. @endcode. * @returns A pointer to the setting if found, NULL otherwise. */ struct setting *settings_get(const char *path); @@ -101,7 +100,7 @@ void settings_get_prefix(const char *prefix, struct setting **settings_out[], * Set a value for a setting. * * @param path The exact path of the setting on - * the form ... + * the form @code .. @endcode. * @param value The new value of the setting. The type has to match the declared * type for the setting. If not, the new value is ignored. */ @@ -114,7 +113,7 @@ void settings_set(const char *path, struct setting_value value); * will not overwrite the value if the setting already has one. * * @param path The exact path of the setting on - * the form ... + * the form @code .. @code. * @param value The new value of the setting. The type has to match the declared * type for the setting. If not, the new value is ignored. */ @@ -124,7 +123,7 @@ void settings_set_default(const char *path, struct setting_value value); * Set a value for a setting. * * @param setting Pointer to a setting to set. - * @param value The new value of the setting. The type has to match the declared + * @param val The new value of the setting. The type has to match the declared * type for the setting. If not, the new value is ignored. */ void setting_set_value(struct setting *setting, struct setting_value val); @@ -134,7 +133,7 @@ void setting_set_value(struct setting *setting, struct setting_value val); * * @param setting Pointer to a setting to turn into a string. * @param buf Character buffer to store resulting string in. - * @param n Size in bytes of @ref buf. + * @param n Size in bytes of @p buf. */ void setting_to_string(struct setting *setting, char *buf, size_t n); @@ -147,18 +146,17 @@ const char *setting_join_key(const char *initial, const char *setting); * @param errmsgs Pointer to a string array where error messages will be placed. * These messages must be freed after use. * @returns 0 on success, n > 0 where n denotes the number of error messages in - * @ref errmsgs + * @p errmsgs */ int32_t settings_from_string(const char *toml, char **errmsgs[]); /** * Parse settings from a file in TOML format. * - * @param toml Pointer to a NULL-terminated string describing a path to a TOML - * file with settings. + * @param path Path to a TOML file containing settings. * @param errmsgs Pointer to a string array where error messages will be placed. * These messages must be freed after use. * @returns 0 on success, n > 0 where n denotes the number of error messages in - * @ref errmsgs + * @p errmsgs */ int32_t settings_from_file(const char *path, char **errmsgs[]); diff --git a/src/main/completion.h b/src/main/completion.h index 776ef9b..28871b9 100644 --- a/src/main/completion.h +++ b/src/main/completion.h @@ -3,43 +3,99 @@ #include "dged/location.h" +/** @file completion.h + * Auto-complete system. + */ + struct buffer; struct buffers; struct commands; +/** + * A single completion. + */ struct completion { + /** The display text for the completion. */ const char *display; + + /** The text to insert for this completion. */ const char *insert; + + /** + * True if this completion item represent a fully expanded value. + * + * One example might be when the file completion represents a + * file (and not a directory) which means that there is not + * going to be more to complete after picking this completion + * item. + */ bool complete; }; +/** + * Context for calculating completions. + */ struct completion_context { + /** The buffer to complete in. */ struct buffer *buffer; + + /** The current location in the buffer. */ const struct location location; + + /** The capacity of @ref completion_context.completions. */ const uint32_t max_ncompletions; + + /** The resulting completions */ struct completion *completions; }; +/** + * A function that provides completions. + */ typedef uint32_t (*completion_fn)(struct completion_context ctx, void *userdata); +/** + * A completion provider. + */ struct completion_provider { + /** Name of the completion provider */ char name[16]; + + /** Completion function. Called to get new completions. */ completion_fn complete; + + /** Userdata sent to @ref completion_provider.complete */ void *userdata; }; +/** + * Type of event that triggers a completion. + */ enum completion_trigger_kind { + /** Completion is triggered on any input. */ CompletionTrigger_Input = 0, + + /** Completion is triggered on a specific char. */ CompletionTrigger_Char = 1, }; +/** + * Description for @c CompletionTrigger_Input. + */ struct completion_trigger_input { + /** Trigger completion after this many chars */ uint32_t nchars; + + /** Trigger an initial complete? */ bool trigger_initially; }; +/** + * Completion trigger descriptor. + */ struct completion_trigger { + /** Type of trigger. */ enum completion_trigger_kind kind; union { uint32_t c; @@ -47,25 +103,61 @@ struct completion_trigger { }; }; +/** + * Initialize the completion system. + * + * @param buffers The buffer list to complete from. + * @param commands The command list to complete from. + */ void init_completion(struct buffers *buffers, struct commands *commands); + +/** + * Tear down the completion system. + */ void destroy_completion(); +/** + * Callback for completion inserted. + */ typedef void (*insert_cb)(); /** - * Enable completions in the buffer @ref source. + * Enable completions in the buffer @p source. * * @param source [in] The buffer to provide completions for. * @param trigger [in] The completion trigger to use for this completion. * @param providers [in] The completion providers to use. - * @param nproviders [in] The number of providers in @ref providers. + * @param nproviders [in] The number of providers in @p providers. + * @param on_completion_inserted [in] Callback to be called when a completion + * has been inserted. */ void enable_completion(struct buffer *source, struct completion_trigger trigger, struct completion_provider *providers, uint32_t nproviders, insert_cb on_completion_inserted); +/** + * Create a new path completion provider. + * + * This provider completes filesystem paths. + * @returns A filesystem path @ref completion_provider. + */ struct completion_provider path_provider(); + +/** + * Create a new buffer completion provider. + * + * This provider completes buffer names from the + * buffer list. + * @returns A buffer name @ref completion_provider. + */ struct completion_provider buffer_provider(); + +/** + * Create a new command completion provider. + * + * This provider completes registered command names. + * @returns A command name @ref completion_provider. + */ struct completion_provider commands_provider(); /**