Syntax highlighting and comment

This commit is contained in:
Arthur Barraux
2026-01-11 19:41:30 +01:00
parent 815114923d
commit fc93832130
11 changed files with 623 additions and 25 deletions
+218 -2
View File
@@ -1,3 +1,10 @@
/**
* @file builtins.c
* @brief Built-in Lisp functions for editor operations
* @details Provides Lisp bindings for core editor functionality including
* cursor movement, file operations, keybinding management, and text manipulation
*/
#include "../include/builtins.h"
#include "../include/data.h"
#include "../include/define.h"
@@ -11,6 +18,14 @@
#include <stdlib.h>
#include <string.h>
/**
* @brief Finds a prefix configuration by name
* @details Searches the prefix array for a prefix matching the given name.
* Returns the first prefix (default) if no match is found.
* @param prefix_name Name of the prefix to search for (max 64 chars)
* @return Matching prefix_t structure, or E.prefix[0] if not found
* @note Updates global editor state E
*/
struct prefix_t find_prefix(const char prefix_name[64]) {
int i = E.number_of_prefix + 1;
while (i--) {
@@ -21,6 +36,19 @@ struct prefix_t find_prefix(const char prefix_name[64]) {
return E.prefix[0];
}
/**
* @brief Lisp function to bind a command to a key sequence
* @details Registers a keybinding with an associated Lisp command and optional
* prefix modifier. Dynamically extends the keybind array.
* @param args Lisp list of 3 arguments: (key-sequence command prefix-name)
* - key_sequence (string): The key or key combination to bind
* - command (Lisp): The Lisp command/function to execute
* - prefix_name (string): Prefix modifier name
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E (key_binds array)
*/
Lisp mapKey(Lisp args, LispError *e, LispContext ctx) {
/*
* 3 arguments keybind command prefix
@@ -49,6 +77,17 @@ Lisp mapKey(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to move cursor in a specified direction
* @details Moves the editor cursor up, down, left, or right based on direction string.
* @param args Lisp list with one argument: direction string
* - "u": up, "d": down, "r": right, "l": left
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return Lisp boolean indicating whether movement was valid
* @note Updates global editor state E
* @see editorMoveCursor()
*/
Lisp moveCursor(Lisp args, LispError *e, LispContext ctx) {
const char *direction = lisp_string(lisp_car(args));
int is_in = 0;
@@ -70,6 +109,12 @@ Lisp moveCursor(Lisp args, LispError *e, LispContext ctx) {
return lisp_make_bool(is_in);
}
/**
* @brief Frees all dynamically allocated editor structures
* @details Releases memory for prefix table, keybinds, filename, and all rows.
* Called during shutdown to prevent memory leaks.
* @note Updates global editor state E
*/
void free_structs(void) {
int i;
free(E.prefix);
@@ -78,12 +123,28 @@ void free_structs(void) {
}
free(E.key_binds);
free(E.filename);
free(E.row->chars);
free(E.row->render);
for (i = 0; i < E.numrows; ++i) {
free(E.row[i].render);
free(E.row[i].chars);
}
free(E.row);
free(E.init_file_path);
fclose(E.fd_init_file);
}
/**
* @brief Lisp function to quit the editor
* @details Closes editor with unsaved changes protection. Prompts user to confirm
* quit after multiple attempts if file is dirty. Cleans up resources and restores terminal.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null() (never returns on successful exit)
* @note Calls exit(0) to terminate program
* @note Updates quit_times_buffer counter
* @see free_structs()
*/
Lisp editorQuit(Lisp args, LispError *e, LispContext ctx) {
if (E.dirty && E.quit_times_buffer > 0) {
editorSetStatusMessage("WARNING! Changes hasn't been saved. Press Ctrl-Q "
@@ -101,6 +162,15 @@ Lisp editorQuit(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to save the current file
* @details Wrapper around editorSave() for use in Lisp keybindings.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @see editorSave()
*/
Lisp l_editorSave(Lisp args, LispError *e, LispContext ctx) {
editorSave();
@@ -108,6 +178,15 @@ Lisp l_editorSave(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to insert a new line at cursor
* @details Wrapper around editorInsertNewLine() for use in Lisp keybindings.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @see editorInsertNewLine()
*/
Lisp l_editorInsertNewLine(Lisp args, LispError *e, LispContext ctx) {
editorInsertNewLine();
@@ -115,6 +194,15 @@ Lisp l_editorInsertNewLine(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to insert a tab (spaces) at cursor
* @details Inserts TAB_LENGTH spaces at the current cursor position.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Uses E.constantes.TAB_LENGTH for indentation width
*/
Lisp l_editorInserTab(Lisp args, LispError *e, LispContext ctx) {
for (int i = 0; i<E.constantes.TAB_LENGTH; ++i) {
@@ -124,11 +212,29 @@ Lisp l_editorInserTab(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to move cursor to beginning of line
* @details Moves cursor to column 0 of the current line.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E
*/
Lisp moveCursorBeginLine(Lisp args, LispError *e, LispContext ctx) {
E.cursor_x = 0;
return lisp_null();
}
/**
* @brief Lisp function to move cursor to end of line
* @details Moves cursor to the end of the current line content.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E
*/
Lisp moveCursorEndLine(Lisp args, LispError *e, LispContext ctx) {
if (E.cursor_y < E.numrows) {
E.cursor_x = E.row[E.cursor_y].size;
@@ -136,11 +242,30 @@ Lisp moveCursorEndLine(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to delete character before cursor
* @details Wrapper around editorDelChar() for use in Lisp keybindings.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @see editorDelChar()
*/
Lisp deletePreviousChar(Lisp args, LispError *e, LispContext ctx) {
editorDelChar();
return lisp_null();
}
/**
* @brief Lisp function to move cursor up by one screen
* @details Scrolls up one full screen height, moving cursor to top of visible area.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E
* @see editorMoveCursor()
*/
Lisp editorMoveCursorPageUp(Lisp args, LispError *e, LispContext ctx) {
E.cursor_y = E.row_offset;
int times = E.screenrows;
@@ -150,6 +275,16 @@ Lisp editorMoveCursorPageUp(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to move cursor down by one screen
* @details Scrolls down one full screen height, moving cursor to bottom of visible area.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E
* @see editorMoveCursor()
*/
Lisp editorMoveCursorPageDown(Lisp args, LispError *e, LispContext ctx) {
E.cursor_y = E.row_offset + E.screenrows - 1;
if (E.cursor_y > E.numrows) {
@@ -163,6 +298,17 @@ Lisp editorMoveCursorPageDown(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to open a file
* @details Prompts user for filename and opens the file for editing.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E
* @see editorOpen()
* @see editorPrompt()
*/
Lisp editorOpenFile(Lisp args, LispError *e, LispContext ctx) {
char *filename = editorPrompt("Open : %s", getenv("PWD"), 1);
if (filename){
@@ -174,12 +320,32 @@ Lisp editorOpenFile(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to insert a character
* @details Extracts a character from Lisp string argument and inserts it at cursor.
* @param args Lisp list with one string argument
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Uses first character of the string argument
*/
Lisp editorPrintC(Lisp args, LispError *e, LispContext ctx) {
char c = lisp_string(lisp_car(args))[0];
editorInsertChar(c);
return lisp_null();
}
/**
* @brief Lisp function to load and execute a package
* @details Loads a Lisp package from the user's packages directory
* (~/.beluga/packages/<package_name>/init.lisp) and evaluates it.
* @param args Lisp list with one argument: package name (string)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Package files must be valid Lisp code
* @note Package directory defaults to ~/.beluga/packages/
*/
Lisp addPackage(Lisp args, LispError *e, LispContext ctx) {
const char *package_name = lisp_string(lisp_car(args));
fprintf(stderr, "%s\n", package_name);
@@ -199,16 +365,45 @@ Lisp addPackage(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to delete the current row
* @details Removes the line at the current cursor position.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E
* @see editorDelRow()
*/
Lisp editorDelRow_L(Lisp args, LispError *e, LispContext ctx) {
editorDelRow(E.cursor_y);
return lisp_null();
}
/**
* @brief Lisp function to search for text
* @details Wrapper around editorFind() for use in Lisp keybindings.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @see editorFind()
*/
Lisp editorFind_L(Lisp args, LispError *e, LispContext ctx) {
fprintf(stderr, "LispFind\n");
editorFind();
return lisp_null();
}
/**
* @brief Lisp function to read character at cursor
* @details Returns the character at the current cursor position as a Lisp character.
* Returns 'a' if at end of line.
* @param args Lisp arguments (unused)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return Lisp character object representing the character at cursor
*/
Lisp editorReadChar_L(Lisp args, LispError *e, LispContext ctx) {
Lisp returned_char;
if (E.row[E.cursor_y].render[E.cursor_x] == 0) {
@@ -220,6 +415,17 @@ Lisp editorReadChar_L(Lisp args, LispError *e, LispContext ctx) {
return returned_char;
}
/**
* @brief Lisp function to set the current prefix mode
* @details Changes the editor's prefix state to a named prefix, affecting which
* keybindings are active. Updates status message to show active prefix.
* @param args Lisp list with one argument: prefix name (string)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E (prefix_state)
* @see find_prefix()
*/
Lisp editorSetPrefix(Lisp args, LispError *e, LispContext ctx) {
/*
* Set the prefix state of editor to the prefix in argument
@@ -233,6 +439,16 @@ Lisp editorSetPrefix(Lisp args, LispError *e, LispContext ctx) {
return lisp_null();
}
/**
* @brief Lisp function to define a new prefix modifier
* @details Registers a named prefix modifier that can be used with keybindings
* to create context-aware command sequences (e.g., Ctrl-X as a prefix).
* @param args Lisp list with one argument: prefix name (string, max 64 chars)
* @param e Error pointer for Lisp error handling
* @param ctx Lisp context
* @return lisp_null()
* @note Updates global editor state E (prefix array)
*/
Lisp editorPrefix(Lisp args, LispError *e, LispContext ctx) {
E.prefix = (struct prefix_t *)realloc(E.prefix, (++(E.number_of_prefix) + 1) *
sizeof(struct prefix_t));