2 Commits

Author SHA1 Message Date
arthur 6b6b3d1766 meson error
Build project / build (push) Has been cancelled
2026-05-26 08:31:59 +02:00
arthur 3d49a0e2eb copy paste functions
Build project / build (push) Has been cancelled
2026-05-26 08:28:38 +02:00
23 changed files with 369 additions and 287 deletions
+4
View File
@@ -86,3 +86,7 @@
(map-key "\"" editor-split-screen-vertical "user") (map-key "\"" editor-split-screen-vertical "user")
(map-key "o" editor-switch-next-pane "user") (map-key "o" editor-switch-next-pane "user")
(map-key "*" editor-unify-panes "user") (map-key "*" editor-unify-panes "user")
(map-key "CTRL-y" editor-paste "no-prefix")
(map-key "CTRL-k" editor-cut-end-line "no-prefix")
(map-key "a" editor-move-cursor-beg-buffer "user")
(map-key "z" editor-move-cursor-end-buffer "user")
+7 -1
View File
@@ -57,7 +57,13 @@ int bufferSaveAll(void);
void bufferFind(struct buffer_t *buf); void bufferFind(struct buffer_t *buf);
void bufferFindReverse(struct buffer_t* buf); void bufferFindReverse(struct buffer_t* buf);
void bufferInsertNewLine();
void bufferInsertBytes(const char *src, int n);
void bufferDelBytes();
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at, const char *src, int n);
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n);
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len);
void bufferFreeRow(row_t *row);
#endif #endif
+6 -2
View File
@@ -45,12 +45,16 @@ Lisp editorSwitchNextPane(Lisp args, LispError *e, LispContext ctx);
Lisp editorUnifiedPanes(Lisp args, LispError *e, LispContext ctx); Lisp editorUnifiedPanes(Lisp args, LispError *e, LispContext ctx);
Lisp editorPaste(Lisp args, LispError *e, LispContext ctx);
Lisp editorCutEndLine(Lisp args, LispError *e, LispContext ctx);
Lisp editorMoveBegBuffer(Lisp args, LispError *e, LispContext ctx);
Lisp editorMoveEndBuffer(Lisp args, LispError *e, LispContext ctx);
// Other // Other
void free_structs(void); void free_structs(void);
#endif #endif
+9
View File
@@ -19,6 +19,13 @@ typedef struct row {
char *chars; /**< Characters of the line */ char *chars; /**< Characters of the line */
} row_t; } row_t;
typedef struct context_buffer_t
{
int editor_x, editor_y;
int width, height;
row_t *rows;
} ContextBuffer;
/** /**
* @brief Split modes for screen layout * @brief Split modes for screen layout
*/ */
@@ -113,6 +120,8 @@ struct editorConfig {
row_t *rows; /**< Store all the rows printed */ row_t *rows; /**< Store all the rows printed */
ContextBuffer* context_buffers;
int dirty; int dirty;
char *status_msg; char *status_msg;
+12 -2
View File
@@ -2,15 +2,17 @@
#define DEFINE_H_ #define DEFINE_H_
#define CTRL_KEY(k) ((k) & 0x1f) #define CTRL_KEY(k) ((k) & 0x1f)
#define ALT(k) ((k) | 0x200) // set bit 9 to mark as Option combo
#define ESCAPE '\x1b' #define ESCAPE '\x1b'
#define CURSOR_TOP_LEFT "\x1b[H" #define CURSOR_TOP_LEFT "\x1b[H"
#define HIDE_CURSOR "\x1b[?25l" #define HIDE_CURSOR "\x1b[?25l"
#define SHOW_CURSOR "\x1b[?25h" #define SHOW_CURSOR "\x1b[?25h"
#define ERASE_END_LINE "\x1b[K" #define ERASE_END_LINE "\x1b[K"
#define TAB "\x9" #define TAB "\t"
#define SPACE "\x20" #define SPACE "\x20"
// #define APP_DEBUG #define APP_DEBUG
enum editorKey_e { enum editorKey_e {
BACKSPACE = 127, BACKSPACE = 127,
@@ -29,4 +31,12 @@ enum editorKey_e {
#define BELUGA_VERSION "2.4" #define BELUGA_VERSION "2.4"
#ifdef __APPLE__
#define CLIPBOARD_COPY_CMD "pbcopy"
#define CLIPBOARD_PASTE_CMD "pbpaste"
#else
#define CLIPBOARD_COPY_CMD "xclip -selection clipboard"
#define CLIPBOARD_PASTE_CMD "xclip -selection clipboard -o"
#endif
#endif // DEFINE_H_ #endif // DEFINE_H_
+4 -3
View File
@@ -3,10 +3,11 @@
#include "data.h" #include "data.h"
void bufferInsertNewLine();
void bufferInsertBytes(char *src, int n);
void editorSetStatusMessage(const char *fmt, ...); void editorSetStatusMessage(const char *fmt, ...);
void bufferDelBytes(); int editorRowCharCount(row_t *row, int x);
int editorRowCxToByte(const row_t *row, int cursor_x);
char *editorGetClipboard(void);
void editorSetClipboard(const char *text, int len);
#endif // EDITOR_OP_H_ #endif // EDITOR_OP_H_
-2
View File
@@ -2,8 +2,6 @@
#define FILE_IO_H_ #define FILE_IO_H_
#include "data.h" #include "data.h"
#include "row_op.h"
#include "terminal.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
+1 -1
View File
@@ -22,7 +22,7 @@
char *editorPrompt(char *prompt, char * PlaceHolder, char bPathMode); char *editorPrompt(char *prompt, char * PlaceHolder, char bPathMode);
const char *file_completion(const char *path); const char *fileCompletion(const char *path);
int editorMoveCursor(int key); int editorMoveCursor(int key);
+3 -6
View File
@@ -8,11 +8,8 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len);
int editorRowCxToByte(const row_t *row, int cursor_x);
void bufferFreeRow(row_t *row);
int editorRowCharCount(row_t *row, int x);
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at, char *src, int n);
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n);
#endif // ROW_OP_H_ #endif // ROW_OP_H_
-2
View File
@@ -1,7 +1,6 @@
#ifndef SYNTAX_HIGHLIGHTER_H_ #ifndef SYNTAX_HIGHLIGHTER_H_
#define SYNTAX_HIGHLIGHTER_H_ #define SYNTAX_HIGHLIGHTER_H_
#include "color.h"
// Color codes that only affect foreground, preserving your background color // Color codes that only affect foreground, preserving your background color
#define COLOR_RESET "\x1b[39m" // Reset all (4 bytes) #define COLOR_RESET "\x1b[39m" // Reset all (4 bytes)
@@ -20,4 +19,3 @@ typedef enum {
char *highlight_line(const char * line, int *length); char *highlight_line(const char * line, int *length);
#endif #endif
+1 -3
View File
@@ -4,8 +4,6 @@
/* includes */ /* includes */
#include "data.h"
#include "define.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -31,7 +29,7 @@ int getCursorPosition(int *rows, int *cols);
int getWindowSize(int *rows, int *cols); int getWindowSize(int *rows, int *cols);
char *key_to_string(int key); char *keyToString(int key);
void appDebug(const char *fmt, ...); void appDebug(const char *fmt, ...);
-3
View File
@@ -11,13 +11,10 @@
#include "include/buffer.h" #include "include/buffer.h"
#include "include/split_screen.h" #include "include/split_screen.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "include/data.h" #include "include/data.h"
#include "include/file_io.h"
#include "include/init.h" #include "include/init.h"
#include "include/input.h" #include "include/input.h"
#include "include/editor_op.h" #include "include/editor_op.h"
+2
View File
@@ -30,4 +30,6 @@ src_files = files(
executable('beluga', executable('beluga',
src_files, src_files,
dependencies: [m] dependencies: [m]
)
dependencies: [m]
) )
+153 -3
View File
@@ -15,7 +15,6 @@
#include "include/input.h" #include "include/input.h"
extern struct editorConfig E;
/** /**
* @brief Finds a buffer by filename * @brief Finds a buffer by filename
@@ -284,7 +283,6 @@ void bufferFind(struct buffer_t* buf)
{ {
appDebug("searching\n"); appDebug("searching\n");
char* query = editorPrompt("Search: %s (ESC to cancel)", "", 0); char* query = editorPrompt("Search: %s (ESC to cancel)", "", 0);
EditorPane* active = splitScreenGetActivePane();
if (query == NULL) if (query == NULL)
return; return;
@@ -306,7 +304,6 @@ void bufferFindReverse(struct buffer_t* buf)
{ {
appDebug("searching\n"); appDebug("searching\n");
char* query = editorPrompt("Reverse search: %s (ESC to cancel)", "", 0); char* query = editorPrompt("Reverse search: %s (ESC to cancel)", "", 0);
EditorPane* active = splitScreenGetActivePane();
if (query == NULL) if (query == NULL)
return; return;
@@ -325,3 +322,156 @@ void bufferFindReverse(struct buffer_t* buf)
} }
free(query); free(query);
} }
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len) {
if (at < 0 || at > buffer->numrows)
return;
row_t *tmp = realloc(buffer->row, sizeof(row_t) * (buffer->numrows + 1));
if (!tmp)
return;
buffer->row = tmp;
/* Shift existing rows to make room at 'at' — no at++ */
if (at < buffer->numrows) {
memmove(&buffer->row[at + 1], &buffer->row[at],
sizeof(row_t) * (buffer->numrows - at)); /* not -at+1 */
}
buffer->row[at].size = len;
buffer->row[at].cap = len + 1;
buffer->row[at].chars = malloc(len + 1);
if (!buffer->row[at].chars)
return;
memcpy(buffer->row[at].chars, s, len);
buffer->row[at].chars[len] = '\0'; /* always NUL-terminate */
buffer->numrows++;
buffer->dirty++;
}
void bufferFreeRow(row_t *row) { free(row->chars); }
/**
* \fn editorRowInsertChar(erow *row, int at, int c)
* \param at Index of where we want to insert the char */
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at,
const char *src, int n) {
if (buffer->state == READ_ONLY)
return;
if (row->size + n + 1 > row->cap) {
row->cap = (row->size + n + 1) * 2;
row->chars = realloc(row->chars, row->cap);
}
memmove(row->chars + at + n, row->chars + at, row->size - at);
memcpy(row->chars + at, src, n);
row->size += n;
row->chars = realloc(row->chars, row->size + 2);
++buffer->dirty;
}
/**
* \fn bufferRowDelChar(struct bufferConfig *E, frow *frow, int at)
* \brief Delete the a char at the chosen position on the given row
* \param at Index of the char to delete
* \param row Row on operation is made */
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n) {
if (buffer->state == READ_ONLY)
return;
if (at < 0 || at >= row->size)
return;
memmove(row->chars + at, row->chars + at + n, row->size - at - n);
row->size -= n;
row->chars[row->size] = '\0';
buffer->x -= n;
++buffer->dirty;
}
void bufferInsertBytes(const char* src, int n)
{
appDebug("bufferInsertBytes \r\n");
EditorPane* active = splitScreenGetActivePane();
struct buffer_t* buf = bufferFindById(active->buffer_id);
if (buf->y == buf->numrows)
{
bufferInsertRow(buf, buf->numrows, "", 0);
}
bufferRowInsertBytes(buf, &buf->row[buf->y], buf->x, src, n);
buf->x += n;
}
void bufferDelBytes(void)
{
EditorPane* active = splitScreenGetActivePane();
struct buffer_t* buf = bufferFindById(active->buffer_id);
/* Nothing to delete */
if (buf->numrows == 0) return;
if (buf->x == 0 && buf->y == 0) return;
/* Use row_offset, not col_offset, for row indexing */
row_t* r = &buf->row[buf->y];
if (buf->x > 0)
{
int byte_end = editorRowCxToByte(r, buf->x);
int byte_start = editorRowCxToByte(r, buf->x - 1);
int char_width = byte_end - byte_start; /* byte width of the character */
bufferRowDelByte(buf, r, byte_start, char_width);
E.dirty = 1;
}
else
{
/* Merge current row into the previous one */
row_t* prev = &buf->row[buf->y - 1]; // FIX: was buf->y (same as r)
int prev_char_count = editorRowCharCount(prev, prev->size);
bufferRowInsertBytes(buf, prev, prev->size, r->chars, r->size);
free(r->chars);
r->chars = NULL;
memmove(&buf->row[buf->y],
&buf->row[buf->y + 1],
sizeof(row_t) * (buf->numrows - buf->y - 1));
buf->numrows--;
active->cursor_x = prev_char_count;
buf->x = prev_char_count;
active->cursor_y--;
buf->y--;
E.dirty = 1;
}
}
void bufferInsertNewLine(void) {
appDebug("Inserting new line\n");
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buf = bufferFindById(active->buffer_id);
appDebug("buf x %d\n", buf->x);
if (buf->y >= buf->numrows) {
/* Cursor is past the last row: just append a blank line */
bufferInsertRow(buf, buf->numrows, "", 0);
} else {
row_t *row = &buf->row[buf->y];
/* Insert the tail (from cursor to end) as a new row below */
bufferInsertRow(buf, buf->y + 1, &row->chars[buf->x], row->size - buf->x);
/* Re-fetch: realloc inside bufferInsertRow may have moved the array */
row = &buf->row[buf->y];
/* Truncate the current row at the cursor */
row->size = buf->x;
row->chars[row->size] = '\0';
/* Do NOT touch row->cap — the allocation is still valid */
}
buf->y++;
buf->x = 0;
appDebug("Insert new line done\n");
}
+49 -4
View File
@@ -13,8 +13,9 @@
#include "../include/editor_op.h" #include "../include/editor_op.h"
#include "../include/file_io.h" #include "../include/file_io.h"
#include "../include/input.h" #include "../include/input.h"
#include "../include/row_op.h" #include "../include/terminal.h"
#include "../include/split_screen.h" #include "../include/split_screen.h"
#include "../include/completion.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -223,8 +224,6 @@ Lisp l_editorInsertNewLine(Lisp args, LispError *e, LispContext ctx) {
* @note Uses E.constantes.TAB_LENGTH for indentation width * @note Uses E.constantes.TAB_LENGTH for indentation width
*/ */
Lisp l_editorInserTab(Lisp args, LispError *e, LispContext ctx) { Lisp l_editorInserTab(Lisp args, LispError *e, LispContext ctx) {
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buf = bufferFindById(active->buffer_id);
for (int i = 0; i < E.constantes.TAB_LENGTH; ++i) { for (int i = 0; i < E.constantes.TAB_LENGTH; ++i) {
bufferInsertBytes(" ", 1); bufferInsertBytes(" ", 1);
} }
@@ -359,7 +358,7 @@ Lisp editorOpenFile(Lisp args, LispError *e, LispContext ctx) {
* @note Uses first character of the string argument * @note Uses first character of the string argument
*/ */
Lisp editorPrintC(Lisp args, LispError *e, LispContext ctx) { Lisp editorPrintC(Lisp args, LispError *e, LispContext ctx) {
char *src = lisp_string(lisp_car(args)); const char *src = lisp_string(lisp_car(args));
bufferInsertBytes(src, strlen(src)); bufferInsertBytes(src, strlen(src));
return lisp_null(); return lisp_null();
} }
@@ -514,3 +513,49 @@ Lisp editorPrefix(Lisp args, LispError *e, LispContext ctx) {
64); 64);
return lisp_null(); return lisp_null();
} }
Lisp editorPaste(Lisp args, LispError *e, LispContext ctx)
{
const char *char_to_paste = editorGetClipboard();
appDebug("editor-paste, %s\n", char_to_paste);
bufferInsertBytes(char_to_paste, (int) strlen(char_to_paste));
return lisp_null();
}
Lisp editorCutEndLine(Lisp args, LispError *e, LispContext ctx)
{
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buffer = bufferFindById(active->buffer_id);
int bytes_to_delete = buffer->row[buffer->y].size - buffer->x;
editorSetClipboard(&buffer->row[buffer->y].chars[buffer->x], bytes_to_delete);
buffer->x = buffer->row[buffer->y].size;
while (bytes_to_delete--)
{
bufferDelBytes();
}
return lisp_null();
}
Lisp editorMoveBegBuffer(Lisp args, LispError *e, LispContext ctx)
{
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buffer = bufferFindById(active->buffer_id);
buffer->x = 0;
buffer->y = 0;
return lisp_null();
}
Lisp editorMoveEndBuffer(Lisp args, LispError *e, LispContext ctx)
{
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buffer = bufferFindById(active->buffer_id);
buffer->x = buffer->row[buffer->numrows-1].size;
buffer->y = buffer->numrows-1;
return lisp_null();
}
Lisp editorAutoComplete(Lisp args, LispError *e, LispContext ctx)
{
createContextBuffer(E.cursor_x - 2, E.cursor_y + 1, "hello");
return lisp_null();
}
+92 -82
View File
@@ -31,90 +31,100 @@ void editorSetStatusMessage(const char* fmt, ...)
E.status_msg_time = time(NULL); E.status_msg_time = time(NULL);
} }
/**
void bufferInsertBytes(char* src, int n) * @brief Moves the cursor based on arrow key input
{ * @details Updates cursor position (E.cursor_x, E.cursor_y) based on the given
appDebug("bufferInsertBytes \r\n"); * key direction. Handles line wrapping and boundary conditions. Prevents cursor
EditorPane* active = splitScreenGetActivePane(); * from exceeding line lengths.
struct buffer_t* buf = bufferFindById(active->buffer_id); * @param key The arrow key code (ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT)
if (buf->y == buf->numrows) * @return 1 if cursor movement was valid, 0 if cursor was constrained to line boundary
{ * @note Updates global editor state E
bufferInsertRow(buf, buf->numrows, "", 0); */
} int editorMoveCursor(int key) {
bufferRowInsertBytes(buf, &buf->row[buf->y], buf->x, src, n);
buf->x += n;
}
void bufferDelBytes(void)
{
EditorPane* active = splitScreenGetActivePane();
struct buffer_t* buf = bufferFindById(active->buffer_id);
/* Nothing to delete */
if (buf->numrows == 0) return;
if (buf->x == 0 && buf->y == 0) return;
/* Use row_offset, not col_offset, for row indexing */
row_t* r = &buf->row[buf->y];
if (buf->x > 0)
{
int byte_end = editorRowCxToByte(r, buf->x);
int byte_start = editorRowCxToByte(r, buf->x - 1);
int char_width = byte_end - byte_start; /* byte width of the character */
bufferRowDelByte(buf, r, byte_start, char_width);
E.dirty = 1;
}
else
{
/* Merge current row into the previous one */
row_t* prev = &buf->row[buf->y - 1]; // FIX: was buf->y (same as r)
int prev_char_count = editorRowCharCount(prev, prev->size);
bufferRowInsertBytes(buf, prev, prev->size, r->chars, r->size);
free(r->chars);
r->chars = NULL;
memmove(&buf->row[buf->y],
&buf->row[buf->y + 1],
sizeof(row_t) * (buf->numrows - buf->y - 1));
buf->numrows--;
active->cursor_x = prev_char_count;
buf->x = prev_char_count;
active->cursor_y--;
buf->y--;
E.dirty = 1;
}
}
void bufferInsertNewLine(void) {
appDebug("Inserting new line\n");
EditorPane *active = splitScreenGetActivePane(); EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buf = bufferFindById(active->buffer_id); struct buffer_t *buf = bufferFindById(active->buffer_id);
row_t *row = &buf->row[buf->y];
switch (key) {
case ARROW_RIGHT:
if (row && buf->x < row->size) {
int len = utf8Seqlen(row->chars[buf->x]);
buf->x += len;
} else if (row && buf->y < buf->numrows) {
buf->y++;
buf->x = 0;
}
break;
case ARROW_DOWN:
if (buf->y < buf->numrows) {
appDebug("buf x %d\n", buf->x); buf->y++;
}
if (buf->y >= buf->numrows) { break;
/* Cursor is past the last row: just append a blank line */ case ARROW_UP:
bufferInsertRow(buf, buf->numrows, "", 0); if (buf->y != 0) {
} else { --buf->y;
row_t *row = &buf->row[buf->y]; }
break;
/* Insert the tail (from cursor to end) as a new row below */ case ARROW_LEFT:
bufferInsertRow(buf, buf->y + 1, &row->chars[buf->x], row->size - buf->x); if (buf->x != 0) {
--buf->x;
/* Re-fetch: realloc inside bufferInsertRow may have moved the array */ } else if (buf->y > 0) {
row = &buf->row[buf->y]; --buf->y;
buf->x = buf->row[buf->y].size;
/* Truncate the current row at the cursor */ }
row->size = buf->x; break;
row->chars[row->size] = '\0';
/* Do NOT touch row->cap — the allocation is still valid */
} }
return 1;
buf->y++;
buf->x = 0;
appDebug("Insert new line done\n");
} }
char *editorGetClipboard(void) {
FILE *pipe = popen(CLIPBOARD_PASTE_CMD, "r");
if (!pipe) return NULL;
size_t cap = 4096;
size_t len = 0;
char *buf = malloc(cap);
int c;
while ((c = fgetc(pipe)) != EOF) {
if (len + 1 >= cap) {
cap *= 2;
buf = realloc(buf, cap);
}
buf[len++] = (char)c;
}
buf[len] = '\0';
pclose(pipe);
return buf; // caller must free
}
void editorSetClipboard(const char *text, int len) {
FILE *pipe = popen(CLIPBOARD_COPY_CMD, "w");
if (!pipe) return;
fwrite(text, 1, len, pipe);
pclose(pipe);
}
int editorRowCxToByte(const row_t *row, int cursor_x) {
int i = 0, col = 0;
while (col < cursor_x && i < row->size) {
int sl = utf8Seqlen((unsigned char)row->chars[i]);
if (sl < 1)
sl = 1;
col++;
i += sl;
}
return i;
}
int editorRowCharCount(row_t *row, int x) {
int n = 0, i = 0;
while (i < x && i < row->size) {
int sl = utf8Seqlen((unsigned char)row->chars[i]);
if (sl < 1)
sl = 1;
n++;
i += sl;
}
return n;
}
+1
View File
@@ -12,6 +12,7 @@
#include "../include/buffer.h" #include "../include/buffer.h"
#include "../include/data.h" #include "../include/data.h"
#include "../include/split_screen.h" #include "../include/split_screen.h"
#include "../include/row_op.h"
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
+6 -2
View File
@@ -45,6 +45,10 @@ void initBuiltins() {
registerBuiltin("editor-split-screen-vertical", l_editorSplitScreenVertical); registerBuiltin("editor-split-screen-vertical", l_editorSplitScreenVertical);
registerBuiltin("editor-switch-next-pane", editorSwitchNextPane); registerBuiltin("editor-switch-next-pane", editorSwitchNextPane);
registerBuiltin("editor-unify-panes", editorUnifiedPanes); registerBuiltin("editor-unify-panes", editorUnifiedPanes);
registerBuiltin("editor-paste", editorPaste);
registerBuiltin("editor-cut-end-line", editorCutEndLine);
registerBuiltin("editor-move-cursor-beg-buffer", editorMoveBegBuffer);
registerBuiltin("editor-move-cursor-end-buffer", editorMoveEndBuffer);
} }
void initConfig() { void initConfig() {
@@ -64,7 +68,7 @@ void initConfig() {
lisp_eval(E.ctx_data, &E.ctx_error, E.ctx); lisp_eval(E.ctx_data, &E.ctx_error, E.ctx);
} }
void init_theme() { void initTheme() {
E.constantes.THEME = (char *)lisp_string( E.constantes.THEME = (char *)lisp_string(
lisp_eval(lisp_read("THEME", &E.ctx_error, E.ctx), &E.ctx_error, E.ctx)); lisp_eval(lisp_read("THEME", &E.ctx_error, E.ctx), &E.ctx_error, E.ctx));
if (strcmp(E.constantes.THEME, "dark") == 0) { if (strcmp(E.constantes.THEME, "dark") == 0) {
@@ -130,7 +134,7 @@ void initEditor() {
initConfig(); initConfig();
init_theme(); initTheme();
// To modify // To modify
+3 -62
View File
@@ -5,7 +5,6 @@
#include "include/data.h" #include "include/data.h"
#include "include/buffer.h" #include "include/buffer.h"
#include "include/data.h" #include "include/data.h"
#include "include/row_op.h"
#include "include/split_screen.h" #include "include/split_screen.h"
#include <ctype.h> #include <ctype.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -41,7 +40,7 @@ extern struct editorConfig E;
* @note Caller is responsible for freeing the returned string * @note Caller is responsible for freeing the returned string
* @note Uses static buffer internally; may return stale pointers across calls * @note Uses static buffer internally; may return stale pointers across calls
*/ */
const char *file_completion(const char *path) { const char *fileCompletion(const char *path) {
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
char directory[256]; char directory[256];
@@ -153,7 +152,7 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
} }
memset(buf, 0, 256); memset(buf, 0, 256);
buf_len = 0; buf_len = 0;
char * buf_complete = (char *) file_completion(path); char * buf_complete = (char *) fileCompletion(path);
strcpy(buf, buf_complete); strcpy(buf, buf_complete);
free(buf_complete); free(buf_complete);
buf_len = strlen(buf); buf_len = strlen(buf);
@@ -170,65 +169,7 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
} }
} }
/**
* @brief Moves the cursor based on arrow key input
* @details Updates cursor position (E.cursor_x, E.cursor_y) based on the given
* key direction. Handles line wrapping and boundary conditions. Prevents cursor
* from exceeding line lengths.
* @param key The arrow key code (ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT)
* @return 1 if cursor movement was valid, 0 if cursor was constrained to line boundary
* @note Updates global editor state E
*/
int editorMoveCursor(int key) {
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buf = bufferFindById(active->buffer_id);
row_t *row = &buf->row[buf->y];
switch (key) {
case ARROW_RIGHT:
if (row && buf->x < row->size) {
int len = utf8Seqlen(row->chars[buf->x]);
buf->x += len;
} else if (row && buf->y < buf->numrows) {
buf->y++;
buf->x = 0;
}
break;
case ARROW_DOWN:
if (buf->y < buf->numrows) {
buf->y++;
}
break;
case ARROW_UP:
if (buf->y != 0) {
--buf->y;
}
break;
case ARROW_LEFT:
if (buf->x != 0) {
--buf->x;
} else if (buf->y > 0) {
--buf->y;
buf->x = buf->row[buf->y].size;
}
break;
}
/*
fprintf(stderr, "acx: %d acy %d aox %d aoy %d bx %d by %d ah %d aw %d\n",
active->cursor_x,
active->cursor_y,
active->x_offset,
active->y_offset,
buf->x,
buf->y,
active->height,
active->width
);
*/
return 1;
}
/** /**
* @brief Executes the command bound to a key sequence * @brief Executes the command bound to a key sequence
@@ -272,7 +213,7 @@ void editorProcessKeypress() {
int c = editorReadKey(); int c = editorReadKey();
char key_sequence[8]; char key_sequence[8];
if (executeKeyBind(key_to_string(c))) { if (executeKeyBind(keyToString(c))) {
return; return;
} }
int seq_len = utf8Encode(c, key_sequence); int seq_len = utf8Encode(c, key_sequence);
+11 -17
View File
@@ -8,6 +8,7 @@
#include "../include/output.h" #include "../include/output.h"
#include "../include/append_buffer.h" #include "../include/append_buffer.h"
#include "../include/buffer.h" #include "../include/buffer.h"
#include "../include/editor_op.h"
#include "../include/data.h" #include "../include/data.h"
#include "../include/define.h" #include "../include/define.h"
#include "../include/row_op.h" #include "../include/row_op.h"
@@ -29,14 +30,9 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
int file_row; int file_row;
char pos_buf[32]; char pos_buf[32];
int pos_len; int pos_len;
int chars_printed;
int start_offset;
int byte_len_to_print; int byte_len_to_print;
int bytes_to_print; int bytes_to_print;
char* highlighted; char* highlighted;
char welcome[80];
int welcome_len;
int padding;
if (pane == NULL || pane->buffer_id < 0) if (pane == NULL || pane->buffer_id < 0)
return; return;
@@ -56,9 +52,8 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
abAppend(ab, pos_buf, pos_len); abAppend(ab, pos_buf, pos_len);
// Apply background color (6 bytes for RGB format) // Apply background color (6 bytes for RGB format)
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR)); abAppend(ab, E.theme.BACKGROUND_COLOR, (int) strlen(E.theme.BACKGROUND_COLOR));
chars_printed = 0;
// pane line is out of buffer // pane line is out of buffer
if (file_row >= buf->numrows) if (file_row >= buf->numrows)
@@ -75,7 +70,7 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
} }
else else
{ {
start_offset = pane->x_offset;
if (buf->filename[strlen(buf->filename) - 1] == 'c' || buf->filename[strlen(buf->filename) - 1] == 'h') if (buf->filename[strlen(buf->filename) - 1] == 'c' || buf->filename[strlen(buf->filename) - 1] == 'h')
{ {
@@ -135,7 +130,7 @@ static void editorDrawAllPanes(struct abuf* ab)
{ {
char pos_buf[32]; char pos_buf[32];
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", y + 1, divider_col); snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", y + 1, divider_col);
abAppend(ab, pos_buf, strlen(pos_buf)); abAppend(ab, pos_buf, (int) strlen(pos_buf));
abAppend(ab, "\x1b[1m|\x1b[0m", 9); // Bold pipe divider abAppend(ab, "\x1b[1m|\x1b[0m", 9); // Bold pipe divider
} }
} }
@@ -145,7 +140,7 @@ static void editorDrawAllPanes(struct abuf* ab)
int divider_row = layout->panes[0].height; int divider_row = layout->panes[0].height;
char pos_buf[32]; char pos_buf[32];
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", divider_row + 1, 1); snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", divider_row + 1, 1);
abAppend(ab, pos_buf, strlen(pos_buf)); abAppend(ab, pos_buf, (int) strlen(pos_buf));
for (int x = 0; x < E.screencols; x++) for (int x = 0; x < E.screencols; x++)
{ {
abAppend(ab, "\x1b[1m-\x1b[0m", 9); // Bold dash divider abAppend(ab, "\x1b[1m-\x1b[0m", 9); // Bold dash divider
@@ -231,15 +226,13 @@ void editorScroll()
char * basename(char *path) char * basename(char *path)
{ {
int len = strlen(path); int len = (int) strlen(path);
int flag=0;
for(int i=len-1; i>0; i--) for(int i=len-1; i>0; i--)
{ {
if(path[i]=='/' ) if(path[i]=='/' )
{ {
flag=1;
path = path+i+1; path = path+i+1;
break; break;
} }
@@ -323,7 +316,7 @@ void editorDrawStatusBar(struct abuf* ab)
*/ */
void editorDrawMessageBar(struct abuf* ab) void editorDrawMessageBar(struct abuf* ab)
{ {
int msg_len = strlen(E.status_msg); int msg_len = (int) strlen(E.status_msg);
abAppend(ab, ERASE_END_LINE, 3); abAppend(ab, ERASE_END_LINE, 3);
if (msg_len > E.screencols) if (msg_len > E.screencols)
{ {
@@ -335,6 +328,7 @@ void editorDrawMessageBar(struct abuf* ab)
} }
} }
/** /**
* @brief Performs complete screen refresh and buffer synchronization * @brief Performs complete screen refresh and buffer synchronization
* @details Clears screen, redraws all visible content (rows, status bar, * @details Clears screen, redraws all visible content (rows, status bar,
@@ -354,7 +348,7 @@ void editorRefreshScreen()
abAppend(&ab, HIDE_CURSOR, 6); abAppend(&ab, HIDE_CURSOR, 6);
abAppend(&ab, CURSOR_TOP_LEFT, 3); abAppend(&ab, CURSOR_TOP_LEFT, 3);
abAppend(&ab, E.theme.BACKGROUND_COLOR, abAppend(&ab, E.theme.BACKGROUND_COLOR,
strlen(E.theme.BACKGROUND_COLOR)); // RGB background is 12 bytes (int) strlen(E.theme.BACKGROUND_COLOR)); // RGB background is 12 bytes
// Draw all panes // Draw all panes
editorScroll(); editorScroll();
@@ -363,16 +357,16 @@ void editorRefreshScreen()
// Draw status bar and message bar // Draw status bar and message bar
editorDrawStatusBar(&ab); editorDrawStatusBar(&ab);
editorDrawMessageBar(&ab); editorDrawMessageBar(&ab);
// editorDrawContextBuffer(&ab);
// Position cursor in active pane // Position cursor in active pane
EditorPane* active = splitScreenGetActivePane(); EditorPane* active = splitScreenGetActivePane();
struct buffer_t* buffer = bufferGetCurrent();
if (active != NULL) if (active != NULL)
{ {
snprintf(buf, sizeof(buf), "\x1b[%d;%dH", snprintf(buf, sizeof(buf), "\x1b[%d;%dH",
active->cursor_y + active->origin_y + 1, active->cursor_y + active->origin_y + 1,
active->cursor_x + active->origin_x + 1); active->cursor_x + active->origin_x + 1);
abAppend(&ab, buf, strlen(buf)); abAppend(&ab, buf, (int) strlen(buf));
} }
abAppend(&ab, SHOW_CURSOR, 6); abAppend(&ab, SHOW_CURSOR, 6);
+1 -89
View File
@@ -1,100 +1,12 @@
#include "../include/row_op.h" #include "../include/row_op.h"
#include "../include/data.h" #include "../include/data.h"
#include "../include/define.h" #include "../include/utf8.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "include/terminal.h"
#include "include/utf8.h"
extern struct editorConfig E; extern struct editorConfig E;
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len) {
if (at < 0 || at > buffer->numrows)
return;
row_t *tmp = realloc(buffer->row, sizeof(row_t) * (buffer->numrows + 1));
if (!tmp)
return;
buffer->row = tmp;
/* Shift existing rows to make room at 'at' — no at++ */
if (at < buffer->numrows) {
memmove(&buffer->row[at + 1], &buffer->row[at],
sizeof(row_t) * (buffer->numrows - at)); /* not -at+1 */
}
buffer->row[at].size = len;
buffer->row[at].cap = len + 1;
buffer->row[at].chars = malloc(len + 1);
if (!buffer->row[at].chars)
return;
memcpy(buffer->row[at].chars, s, len);
buffer->row[at].chars[len] = '\0'; /* always NUL-terminate */
buffer->numrows++;
buffer->dirty++;
}
void bufferFreeRow(row_t *row) { free(row->chars); }
int editorRowCxToByte(const row_t *row, int cursor_x) {
int i = 0, col = 0;
while (col < cursor_x && i < row->size) {
int sl = utf8Seqlen((unsigned char)row->chars[i]);
if (sl < 1)
sl = 1;
col++;
i += sl;
}
return i;
}
/**
* \fn editorRowInsertChar(erow *row, int at, int c)
* \param at Index of where we want to insert the char */
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at,
char *src, int n) {
if (buffer->state == READ_ONLY)
return;
if (row->size + n + 1 > row->cap) {
row->cap = (row->size + n + 1) * 2;
row->chars = realloc(row->chars, row->cap);
}
memmove(row->chars + at + n, row->chars + at, row->size - at);
memcpy(row->chars + at, src, n);
row->size += n;
row->chars = realloc(row->chars, row->size + 2);
++buffer->dirty;
}
/**
* \fn bufferRowDelChar(struct bufferConfig *E, frow *frow, int at)
* \brief Delete the a char at the chosen position on the given row
* \param at Index of the char to delete
* \param row Row on operation is made */
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n) {
if (buffer->state == READ_ONLY)
return;
if (at < 0 || at >= row->size)
return;
memmove(row->chars + at, row->chars + at + n, row->size - at - n);
row->size -= n;
row->chars[row->size] = '\0';
buffer->x -= n;
++buffer->dirty;
}
int editorRowCharCount(row_t *row, int x) {
int n = 0, i = 0;
while (i < x && i < row->size) {
int sl = utf8Seqlen((unsigned char)row->chars[i]);
if (sl < 1)
sl = 1;
n++;
i += sl;
}
return n;
}
+4 -2
View File
@@ -46,7 +46,7 @@ void enableRawMode() {
#include <ctype.h> /* isprint */ #include <ctype.h> /* isprint */
char *key_to_string(int key) { char *keyToString(int key) {
static char key_str[32]; static char key_str[32];
if (key == '\r') { if (key == '\r') {
@@ -111,7 +111,7 @@ int editorReadKey() {
/* read first byte — may be start of UTF-8 or escape */ /* read first byte — may be start of UTF-8 or escape */
while (read(STDIN_FILENO, &c, 1) != 1) while (read(STDIN_FILENO, &c, 1) != 1)
; ;
appDebug("f : %X\r\n", c); appDebug("f : %hhu %ld\r\n", c, 0x200);
if (c == '\x1b') { if (c == '\x1b') {
char seq[6]; char seq[6];
@@ -120,6 +120,8 @@ int editorReadKey() {
return '\x1b'; return '\x1b';
if (read(STDIN_FILENO, &seq[1], 1) != 1) if (read(STDIN_FILENO, &seq[1], 1) != 1)
return '\x1b'; return '\x1b';
appDebug("f2 : %s\r\n", seq);
if (seq[0] == '[') { if (seq[0] == '[') {
if (seq[1] >= '0' && seq[1] <= '9') { if (seq[1] >= '0' && seq[1] <= '9') {
if (read(STDIN_FILENO, &seq[2], 1) != 1) if (read(STDIN_FILENO, &seq[2], 1) != 1)
-1
View File
@@ -3,7 +3,6 @@
*/ */
#include "../include/utf8.h" #include "../include/utf8.h"
#include "../include/data.h"
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>