Syntax highlighting and comment
This commit is contained in:
+218
-2
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user