Color theming
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
(define TAB-LENGTH 4)
|
(define TAB-LENGTH 4)
|
||||||
(define QUIT-TIMES 1)
|
(define QUIT-TIMES 1)
|
||||||
|
(define BACKGROUND-COLOR "light yellow")
|
||||||
|
|
||||||
;; PACKAGES
|
;; PACKAGES
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef BUFFER_H_
|
||||||
|
#define BUFFER_H_
|
||||||
|
|
||||||
|
#include "data.h"
|
||||||
|
|
||||||
|
int new_buffer(enum buffer_type type, char * filename, int width, int height);
|
||||||
|
|
||||||
|
#endif
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
#ifndef COLOR_H_
|
||||||
|
#define COLOR_H_
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// TEXT STYLES / ATTRIBUTES
|
||||||
|
// ============================================================================
|
||||||
|
#define ANSI_RESET "\x1b[0m" // Reset all attributes
|
||||||
|
#define ANSI_BOLD "\x1b[1m" // Bold text
|
||||||
|
#define ANSI_DIM "\x1b[2m" // Dim/faint text
|
||||||
|
#define ANSI_ITALIC "\x1b[3m" // Italic text
|
||||||
|
#define ANSI_UNDERLINE "\x1b[4m" // Underline text
|
||||||
|
#define ANSI_BLINK "\x1b[5m" // Blinking text
|
||||||
|
#define ANSI_REVERSE "\x1b[7m" // Reverse video (invert colors)
|
||||||
|
#define ANSI_HIDDEN "\x1b[8m" // Hidden/invisible text
|
||||||
|
#define ANSI_STRIKETHROUGH "\x1b[9m" // Strikethrough text
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// FOREGROUND COLORS (30-37 standard, 90-97 bright)
|
||||||
|
// ============================================================================
|
||||||
|
#define ANSI_BLACK "\x1b[30m"
|
||||||
|
#define ANSI_RED "\x1b[31m"
|
||||||
|
#define ANSI_GREEN "\x1b[32m"
|
||||||
|
#define ANSI_YELLOW "\x1b[33m"
|
||||||
|
#define ANSI_BLUE "\x1b[34m"
|
||||||
|
#define ANSI_MAGENTA "\x1b[35m"
|
||||||
|
#define ANSI_CYAN "\x1b[36m"
|
||||||
|
#define ANSI_WHITE "\x1b[37m"
|
||||||
|
|
||||||
|
// Bright/Light foreground colors (90-97)
|
||||||
|
#define ANSI_BRIGHT_BLACK "\x1b[90m"
|
||||||
|
#define ANSI_BRIGHT_RED "\x1b[91m"
|
||||||
|
#define ANSI_BRIGHT_GREEN "\x1b[92m"
|
||||||
|
#define ANSI_BRIGHT_YELLOW "\x1b[93m"
|
||||||
|
#define ANSI_BRIGHT_BLUE "\x1b[94m"
|
||||||
|
#define ANSI_BRIGHT_MAGENTA "\x1b[95m"
|
||||||
|
#define ANSI_BRIGHT_CYAN "\x1b[96m"
|
||||||
|
#define ANSI_BRIGHT_WHITE "\x1b[97m"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// BACKGROUND COLORS (40-47 standard, 100-107 bright)
|
||||||
|
// ============================================================================
|
||||||
|
#define ANSI_BG_BLACK "\x1b[40m"
|
||||||
|
#define ANSI_BG_RED "\x1b[41m"
|
||||||
|
#define ANSI_BG_GREEN "\x1b[42m"
|
||||||
|
#define ANSI_BG_YELLOW "\x1b[43m"
|
||||||
|
#define ANSI_BG_BLUE "\x1b[44m"
|
||||||
|
#define ANSI_BG_MAGENTA "\x1b[45m"
|
||||||
|
#define ANSI_BG_CYAN "\x1b[46m"
|
||||||
|
#define ANSI_BG_WHITE "\x1b[47m"
|
||||||
|
|
||||||
|
// Bright/Light background colors (100-107)
|
||||||
|
#define ANSI_BG_BRIGHT_BLACK "\x1b[100m"
|
||||||
|
#define ANSI_BG_BRIGHT_RED "\x1b[101m"
|
||||||
|
#define ANSI_BG_BRIGHT_GREEN "\x1b[102m"
|
||||||
|
#define ANSI_BG_BRIGHT_YELLOW "\x1b[103m"
|
||||||
|
#define ANSI_BG_BRIGHT_BLUE "\x1b[104m"
|
||||||
|
#define ANSI_BG_BRIGHT_MAGENTA "\x1b[105m"
|
||||||
|
#define ANSI_BG_BRIGHT_CYAN "\x1b[106m"
|
||||||
|
#define ANSI_BG_BRIGHT_WHITE "\x1b[107m"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 256-COLOR MODE (for more colors)
|
||||||
|
// ============================================================================
|
||||||
|
// Foreground: \x1b[38;5;Nm where N is 0-255
|
||||||
|
// Background: \x1b[48;5;Nm where N is 0-255
|
||||||
|
// Example macros:
|
||||||
|
#define ANSI_FG_256(N) "\x1b[38;5;" #N "m"
|
||||||
|
#define ANSI_BG_256(N) "\x1b[48;5;" #N "m"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// TRUE COLOR / 24-BIT COLOR (RGB)
|
||||||
|
// ============================================================================
|
||||||
|
// Foreground: \x1b[38;2;R;G;Bm
|
||||||
|
// Background: \x1b[48;2;R;G;Bm
|
||||||
|
// Example macros:
|
||||||
|
#define ANSI_FG_RGB(R,G,B) "\x1b[38;2;" #R ";" #G ";" #B "m"
|
||||||
|
#define ANSI_BG_RGB(R,G,B) "\x1b[48;2;" #R ";" #G ";" #B "m"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// CURSOR MOVEMENT
|
||||||
|
// ============================================================================
|
||||||
|
#define ANSI_CURSOR_UP(N) "\x1b[" #N "A" // Move up N lines
|
||||||
|
#define ANSI_CURSOR_DOWN(N) "\x1b[" #N "B" // Move down N lines
|
||||||
|
#define ANSI_CURSOR_RIGHT(N) "\x1b[" #N "C" // Move right N columns
|
||||||
|
#define ANSI_CURSOR_LEFT(N) "\x1b[" #N "D" // Move left N columns
|
||||||
|
#define ANSI_CURSOR_HOME "\x1b[H" // Move to home (0,0)
|
||||||
|
#define ANSI_CURSOR_HIDE "\x1b[?25l" // Hide cursor
|
||||||
|
#define ANSI_CURSOR_SHOW "\x1b[?25h" // Show cursor
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// SCREEN CONTROL
|
||||||
|
// ============================================================================
|
||||||
|
#define ANSI_CLEAR_SCREEN "\x1b[2J" // Clear entire screen
|
||||||
|
#define ANSI_CLEAR_LINE "\x1b[K" // Clear from cursor to end of line
|
||||||
|
#define ANSI_CLEAR_UP "\x1b[1J" // Clear from cursor to start
|
||||||
|
#define ANSI_CLEAR_DOWN "\x1b[0J" // Clear from cursor to end
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// EXAMPLE USAGE
|
||||||
|
// ============================================================================
|
||||||
|
/*
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
// Simple color example
|
||||||
|
printf("%sHello in Red%s\n", ANSI_RED, ANSI_RESET);
|
||||||
|
|
||||||
|
// Bold and colored
|
||||||
|
printf("%s%sBold Green%s\n", ANSI_BOLD, ANSI_GREEN, ANSI_RESET);
|
||||||
|
|
||||||
|
// Background color
|
||||||
|
printf("%s%sYellow on Blue%s\n", ANSI_YELLOW, ANSI_BG_BLUE, ANSI_RESET);
|
||||||
|
|
||||||
|
// Combine multiple styles
|
||||||
|
printf("%s%s%sUnderlined Bold Cyan%s\n",
|
||||||
|
ANSI_UNDERLINE, ANSI_BOLD, ANSI_CYAN, ANSI_RESET);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
||||||
+26
-1
@@ -20,6 +20,17 @@ typedef struct erow {
|
|||||||
char *render; /**< The actual line we will print */
|
char *render; /**< The actual line we will print */
|
||||||
} erow;
|
} erow;
|
||||||
|
|
||||||
|
typedef struct theme {
|
||||||
|
char *BACKGROUND_COLOR;
|
||||||
|
char *COLOR_KEYWORD;
|
||||||
|
char *COLOR_TYPE;
|
||||||
|
char *COLOR_STRING;
|
||||||
|
char *COLOR_COMMENT;
|
||||||
|
char *COLOR_NUMBER;
|
||||||
|
char *COLOR_DEFAULT;
|
||||||
|
|
||||||
|
} theme_t;
|
||||||
|
|
||||||
enum editorStatus_e {
|
enum editorStatus_e {
|
||||||
IDLE,
|
IDLE,
|
||||||
READ_ONLY,
|
READ_ONLY,
|
||||||
@@ -29,6 +40,7 @@ enum editorStatus_e {
|
|||||||
struct const_t {
|
struct const_t {
|
||||||
int TAB_LENGTH;
|
int TAB_LENGTH;
|
||||||
int QUIT_TIMES;
|
int QUIT_TIMES;
|
||||||
|
char *THEME;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prefix_t {
|
struct prefix_t {
|
||||||
@@ -40,7 +52,16 @@ struct keyBind_t {
|
|||||||
char *key_sequence;
|
char *key_sequence;
|
||||||
int prefix_id;
|
int prefix_id;
|
||||||
Lisp command;
|
Lisp command;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum buffer_type { FILE_BUFF, TERMINAL_BUFF };
|
||||||
|
|
||||||
|
struct buffer_t {
|
||||||
|
enum buffer_type type;
|
||||||
|
int buffer_id;
|
||||||
|
int width, height;
|
||||||
|
int x, y; /**< Position of the buffer*/
|
||||||
|
char *filename;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,6 +101,11 @@ struct editorConfig {
|
|||||||
struct prefix_t *prefix;
|
struct prefix_t *prefix;
|
||||||
int number_of_prefix;
|
int number_of_prefix;
|
||||||
|
|
||||||
|
struct buffer_t buffers[64];
|
||||||
|
struct buffer_t ***screen_layout; /**< Which buffer is the current cell*/
|
||||||
|
int number_of_buffer;
|
||||||
|
|
||||||
|
theme_t theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,5 +120,4 @@ struct abuf {
|
|||||||
|
|
||||||
extern struct editorConfig E;
|
extern struct editorConfig E;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,4 +8,6 @@ void editorInsertNewLine();
|
|||||||
|
|
||||||
void editorDelChar();
|
void editorDelChar();
|
||||||
|
|
||||||
|
void editorSetStatusMessage(const char *fmt, ...);
|
||||||
|
|
||||||
#endif // EDITOR_OP_H_
|
#endif // EDITOR_OP_H_
|
||||||
|
|||||||
@@ -23,6 +23,4 @@ void editorDrawStatusBar(struct abuf *ab);
|
|||||||
|
|
||||||
void editorDrawMessageBar(struct abuf *ab);
|
void editorDrawMessageBar(struct abuf *ab);
|
||||||
|
|
||||||
void editorSetStatusMessage(const char *fmt, ...);
|
|
||||||
|
|
||||||
#endif // OUTPUT_H_
|
#endif // OUTPUT_H_
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#define COLOR_RESET "\033[0m"
|
#ifndef SYNTAX_HIGHLIGHTER_H_
|
||||||
#define COLOR_KEYWORD "\033[1;35m" // Bold magenta
|
#define SYNTAX_HIGHLIGHTER_H_
|
||||||
#define COLOR_TYPE "\033[1;34m" // Bold blue
|
|
||||||
#define COLOR_STRING "\033[1;32m" // Bold green
|
#include "color.h"
|
||||||
#define COLOR_COMMENT "\033[0;36m" // Cyan
|
|
||||||
#define COLOR_NUMBER "\033[1;33m" // Bold yellow
|
// Color codes that only affect foreground, preserving your background color
|
||||||
#define COLOR_DEFAULT "\033[0;37m" // White
|
#define COLOR_RESET "\x1b[39m" // Reset all (4 bytes)
|
||||||
|
|
||||||
// Token types
|
// Token types
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -18,3 +18,6 @@ typedef enum {
|
|||||||
} TokenType;
|
} TokenType;
|
||||||
|
|
||||||
char *highlight_line(const char * line, int *length);
|
char *highlight_line(const char * line, int *length);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "include/file_io.h"
|
#include "include/file_io.h"
|
||||||
#include "include/init.h"
|
#include "include/init.h"
|
||||||
#include "include/input.h"
|
#include "include/input.h"
|
||||||
#include "include/output.h"
|
#include "include/editor_op.h"
|
||||||
#include "include/terminal.h"
|
#include "include/terminal.h"
|
||||||
|
|
||||||
struct editorConfig E;
|
struct editorConfig E;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include "../include/data.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int new_buffer(enum buffer_type type, char *filename, int x, int y, int width,
|
||||||
|
int height) {
|
||||||
|
// Create a new buffer
|
||||||
|
|
||||||
|
struct buffer_t *buffer = &E.buffers[E.number_of_buffer];
|
||||||
|
buffer->type = type;
|
||||||
|
|
||||||
|
if (type == FILE_BUFF) {
|
||||||
|
strcpy(buffer->filename, filename);
|
||||||
|
}
|
||||||
|
buffer->width = width, buffer->height = height;
|
||||||
|
buffer->x = x, buffer->y = y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
#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/row_op.h"
|
||||||
#include "include/output.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
@@ -1,9 +1,30 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "../include/editor_op.h"
|
#include "../include/editor_op.h"
|
||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
|
|
||||||
|
|
||||||
extern struct editorConfig E;
|
extern struct editorConfig E;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a temporary status message for display
|
||||||
|
* @details Formats and stores a message that will be displayed in the message
|
||||||
|
* bar for 5 seconds. Uses printf-style variable argument formatting.
|
||||||
|
* @param fmt Printf-style format string
|
||||||
|
* @param ... Variable arguments for format string
|
||||||
|
* @note Updates global editor state E (status_msg, status_msg_time)
|
||||||
|
* @see editorDrawMessageBar()
|
||||||
|
*/
|
||||||
|
void editorSetStatusMessage(const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(E.status_msg, sizeof(E.status_msg), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
E.status_msg_time = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void editorInsertChar(int c) {
|
void editorInsertChar(int c) {
|
||||||
if (E.cursor_y == E.numrows) {
|
if (E.cursor_y == E.numrows) {
|
||||||
editorInsertRow(E.numrows, "", 0);
|
editorInsertRow(E.numrows, "", 0);
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "../include/file_io.h"
|
#include "../include/file_io.h"
|
||||||
#include "../include/input.h"
|
#include "../include/input.h"
|
||||||
#include "../include/output.h"
|
#include "../include/editor_op.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
+73
-32
@@ -1,9 +1,11 @@
|
|||||||
#include "../include/init.h"
|
#include "../include/init.h"
|
||||||
#include "../include/builtins.h"
|
#include "../include/builtins.h"
|
||||||
|
#include "../include/color.h"
|
||||||
#include "../include/data.h"
|
#include "../include/data.h"
|
||||||
#include "../include/terminal.h"
|
#include "../include/terminal.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define LISP_IMPLEMENTATION
|
#define LISP_IMPLEMENTATION
|
||||||
#include "../include/lisp.h"
|
#include "../include/lisp.h"
|
||||||
@@ -17,7 +19,7 @@ void registerBuiltin(char *key_sequence, LispCFunc f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initBuiltins() {
|
void initBuiltins() {
|
||||||
// move cursor
|
// Registering C functions as lisp macro
|
||||||
registerBuiltin("move-cursor", moveCursor);
|
registerBuiltin("move-cursor", moveCursor);
|
||||||
registerBuiltin("map-key", mapKey);
|
registerBuiltin("map-key", mapKey);
|
||||||
registerBuiltin("editor-quit", editorQuit);
|
registerBuiltin("editor-quit", editorQuit);
|
||||||
@@ -39,38 +41,8 @@ void initBuiltins() {
|
|||||||
registerBuiltin("editor-insert-tab", l_editorInserTab);
|
registerBuiltin("editor-insert-tab", l_editorInserTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initEditor() {
|
void initConfig() {
|
||||||
E.init_file_path = (char *)calloc(256, sizeof(char));
|
|
||||||
E.cursor_x = 0;
|
|
||||||
E.cursor_y = 0;
|
|
||||||
E.rx = 0;
|
|
||||||
E.row_offset = 0;
|
|
||||||
E.col_offset = 0;
|
|
||||||
E.numrows = 0;
|
|
||||||
E.row = NULL;
|
|
||||||
E.dirty = 0;
|
|
||||||
E.filename = NULL;
|
|
||||||
E.state = READ_ONLY;
|
|
||||||
E.status_msg[0] = '\0';
|
|
||||||
E.status_msg_time = 0;
|
|
||||||
if (getWindowSize(&E.screenrows, &E.screencols) == -1) {
|
|
||||||
die("getWindowSize");
|
|
||||||
}
|
|
||||||
E.screenrows -= 2;
|
|
||||||
|
|
||||||
E.number_of_keybinds = 0;
|
|
||||||
E.number_of_prefix = 0;
|
|
||||||
// General prefix is 0 (no prefix)
|
|
||||||
E.prefix = (struct prefix_t *)malloc(sizeof(struct prefix_t));
|
|
||||||
E.prefix[0].prefix_id = 0;
|
|
||||||
strncpy(E.prefix[0].prefix_name, "no-prefix", 64);
|
|
||||||
|
|
||||||
E.prefix_state = 0;
|
|
||||||
|
|
||||||
strcat(E.init_file_path, getenv("HOME"));
|
|
||||||
strcat(E.init_file_path, "/.beluga/config/init.lisp");
|
|
||||||
// printf("%s\n", init_file_path);
|
|
||||||
E.fd_init_file = fopen(E.init_file_path, "r");
|
|
||||||
E.ctx = lisp_init();
|
E.ctx = lisp_init();
|
||||||
E.env = lisp_env(E.ctx);
|
E.env = lisp_env(E.ctx);
|
||||||
lisp_lib_load(E.ctx);
|
lisp_lib_load(E.ctx);
|
||||||
@@ -83,6 +55,75 @@ void initEditor() {
|
|||||||
die("init failed");
|
die("init failed");
|
||||||
}
|
}
|
||||||
lisp_eval(E.ctx_data, &E.ctx_error, E.ctx);
|
lisp_eval(E.ctx_data, &E.ctx_error, E.ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_theme() {
|
||||||
|
E.constantes.THEME = (char *)lisp_string(
|
||||||
|
lisp_eval(lisp_read("THEME", &E.ctx_error, E.ctx), &E.ctx_error, E.ctx));
|
||||||
|
if (strcmp(E.constantes.THEME, "dark") == 0) {
|
||||||
|
E.theme.BACKGROUND_COLOR = ANSI_BG_RGB(40, 44, 52);
|
||||||
|
E.theme.COLOR_KEYWORD = ANSI_FG_RGB(198, 120, 221);
|
||||||
|
E.theme.COLOR_TYPE = ANSI_FG_RGB(97, 175, 239);
|
||||||
|
E.theme.COLOR_STRING = ANSI_FG_RGB(152, 195, 121);
|
||||||
|
E.theme.COLOR_COMMENT = ANSI_FG_RGB(92, 99, 112);
|
||||||
|
E.theme.COLOR_NUMBER = ANSI_FG_RGB(209, 154, 102);
|
||||||
|
E.theme.COLOR_DEFAULT = ANSI_FG_RGB(171, 178, 191);
|
||||||
|
} else {
|
||||||
|
E.theme.BACKGROUND_COLOR = ANSI_BG_RGB(250, 251, 252);
|
||||||
|
E.theme.COLOR_KEYWORD = ANSI_FG_RGB(166, 38, 164);
|
||||||
|
E.theme.COLOR_TYPE = ANSI_FG_RGB(4, 90, 180);
|
||||||
|
E.theme.COLOR_STRING = ANSI_FG_RGB(80, 161, 79);
|
||||||
|
E.theme.COLOR_COMMENT = ANSI_FG_RGB(152, 152, 152);
|
||||||
|
E.theme.COLOR_NUMBER = ANSI_FG_RGB(206, 102, 54);
|
||||||
|
E.theme.COLOR_DEFAULT = ANSI_FG_RGB(86, 89, 90);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initEditor() {
|
||||||
|
// Init graphics variables
|
||||||
|
E.cursor_x = 0;
|
||||||
|
E.cursor_y = 0;
|
||||||
|
E.rx = 0;
|
||||||
|
E.row_offset = 0;
|
||||||
|
E.col_offset = 0;
|
||||||
|
E.numrows = 0;
|
||||||
|
E.row = NULL;
|
||||||
|
// File relative variables
|
||||||
|
E.dirty = 0;
|
||||||
|
E.filename = NULL;
|
||||||
|
E.init_file_path = (char *)calloc(256, sizeof(char));
|
||||||
|
strcat(E.init_file_path, getenv("HOME"));
|
||||||
|
strcat(E.init_file_path, "/.beluga/config/init.lisp");
|
||||||
|
E.fd_init_file = fopen(E.init_file_path, "r");
|
||||||
|
E.state = READ_ONLY;
|
||||||
|
|
||||||
|
// Status bar
|
||||||
|
E.status_msg[0] = '\0';
|
||||||
|
E.status_msg_time = 0;
|
||||||
|
if (getWindowSize(&E.screenrows, &E.screencols) == -1) {
|
||||||
|
die("getWindowSize");
|
||||||
|
}
|
||||||
|
E.screenrows -= 2;
|
||||||
|
|
||||||
|
E.screen_layout =
|
||||||
|
(struct buffer_t ***)malloc(E.screenrows * sizeof(struct buffer_t **));
|
||||||
|
for (int i = 0; i < E.screenrows; ++i) {
|
||||||
|
E.screen_layout[i] =
|
||||||
|
(struct buffer_t **)malloc(E.screencols * sizeof(struct buffer_t *));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key binds
|
||||||
|
E.number_of_keybinds = 0;
|
||||||
|
E.number_of_prefix = 0;
|
||||||
|
// General prefix is 0 (no prefix)
|
||||||
|
E.prefix = (struct prefix_t *)malloc(sizeof(struct prefix_t));
|
||||||
|
E.prefix[0].prefix_id = 0;
|
||||||
|
strncpy(E.prefix[0].prefix_name, "no-prefix", 64);
|
||||||
|
E.prefix_state = 0;
|
||||||
|
|
||||||
|
initConfig();
|
||||||
|
|
||||||
|
init_theme();
|
||||||
|
|
||||||
// To modify
|
// To modify
|
||||||
|
|
||||||
|
|||||||
+16
-27
@@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* @file output.c
|
* @file output.c
|
||||||
* @brief Screen rendering and output module for the Beluga text editor
|
* @brief Screen rendering and output module for the Beluga text editor
|
||||||
* @details Handles all screen updates, cursor positioning, status bar rendering,
|
* @details Handles all screen updates, cursor positioning, status bar
|
||||||
* and display synchronization using ANSI escape sequences
|
* rendering, and display synchronization using ANSI escape sequences
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/output.h"
|
#include "../include/output.h"
|
||||||
|
#include "../include/append_buffer.h"
|
||||||
#include "../include/syntax_highlighter.h"
|
#include "../include/syntax_highlighter.h"
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -34,6 +34,7 @@ void editorDrawRows(struct abuf *ab) {
|
|||||||
int file_row;
|
int file_row;
|
||||||
for (y = 0; y < E.screenrows; ++y) {
|
for (y = 0; y < E.screenrows; ++y) {
|
||||||
file_row = y + E.row_offset;
|
file_row = y + E.row_offset;
|
||||||
|
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||||
if (file_row >= E.numrows) {
|
if (file_row >= E.numrows) {
|
||||||
if (E.numrows == 0 && y == E.screenrows / 3) {
|
if (E.numrows == 0 && y == E.screenrows / 3) {
|
||||||
welcome_len =
|
welcome_len =
|
||||||
@@ -60,10 +61,13 @@ void editorDrawRows(struct abuf *ab) {
|
|||||||
len = 0;
|
len = 0;
|
||||||
if (len > E.screencols)
|
if (len > E.screencols)
|
||||||
len = E.screencols;
|
len = E.screencols;
|
||||||
char * highlighted = highlight_line(&E.row[file_row].render[E.col_offset], &E.row[file_row].rsize);
|
char *highlighted = highlight_line(&E.row[file_row].render[E.col_offset],
|
||||||
|
&E.row[file_row].rsize);
|
||||||
abAppend(ab, highlighted, E.row[file_row].rsize);
|
abAppend(ab, highlighted, E.row[file_row].rsize);
|
||||||
|
|
||||||
free(highlighted);
|
free(highlighted);
|
||||||
}
|
}
|
||||||
|
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||||
abAppend(ab, ERASE_END_LINE, 3);
|
abAppend(ab, ERASE_END_LINE, 3);
|
||||||
abAppend(ab, "\r\n", 2);
|
abAppend(ab, "\r\n", 2);
|
||||||
}
|
}
|
||||||
@@ -98,8 +102,9 @@ void editorScroll() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Renders the status bar at the bottom of the screen
|
* @brief Renders the status bar at the bottom of the screen
|
||||||
* @details Displays filename, line count, dirty flag, and current cursor position
|
* @details Displays filename, line count, dirty flag, and current cursor
|
||||||
* in an inverted color bar. Right-aligns the cursor position indicator.
|
* position in an inverted color bar. Right-aligns the cursor position
|
||||||
|
* indicator.
|
||||||
* @param ab Pointer to append buffer structure for accumulating output
|
* @param ab Pointer to append buffer structure for accumulating output
|
||||||
* @note Uses ANSI escape codes for color inversion
|
* @note Uses ANSI escape codes for color inversion
|
||||||
*/
|
*/
|
||||||
@@ -150,9 +155,9 @@ 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, message bar),
|
* @details Clears screen, redraws all visible content (rows, status bar,
|
||||||
* positions cursor, and writes accumulated buffer to stdout. This is the main
|
* message bar), positions cursor, and writes accumulated buffer to stdout. This
|
||||||
* rendering function called each frame.
|
* is the main rendering function called each frame.
|
||||||
* @note Updates global editor state E (via editorScroll())
|
* @note Updates global editor state E (via editorScroll())
|
||||||
* @see editorDrawRows()
|
* @see editorDrawRows()
|
||||||
* @see editorDrawStatusBar()
|
* @see editorDrawStatusBar()
|
||||||
@@ -163,9 +168,11 @@ void editorRefreshScreen() {
|
|||||||
struct abuf ab = ABUF_INIT;
|
struct abuf ab = ABUF_INIT;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
|
|
||||||
abAppend(&ab, HIDE_CURSOR, 6);
|
abAppend(&ab, HIDE_CURSOR, 6);
|
||||||
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
||||||
|
|
||||||
|
|
||||||
editorDrawRows(&ab);
|
editorDrawRows(&ab);
|
||||||
editorDrawStatusBar(&ab);
|
editorDrawStatusBar(&ab);
|
||||||
editorDrawMessageBar(&ab);
|
editorDrawMessageBar(&ab);
|
||||||
@@ -178,21 +185,3 @@ void editorRefreshScreen() {
|
|||||||
write(STDOUT_FILENO, ab.b, ab.len);
|
write(STDOUT_FILENO, ab.b, ab.len);
|
||||||
abFree(&ab);
|
abFree(&ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets a temporary status message for display
|
|
||||||
* @details Formats and stores a message that will be displayed in the message bar
|
|
||||||
* for 5 seconds. Uses printf-style variable argument formatting.
|
|
||||||
* @param fmt Printf-style format string
|
|
||||||
* @param ... Variable arguments for format string
|
|
||||||
* @note Updates global editor state E (status_msg, status_msg_time)
|
|
||||||
* @see editorDrawMessageBar()
|
|
||||||
*/
|
|
||||||
void editorSetStatusMessage(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vsnprintf(E.status_msg, sizeof(E.status_msg), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
E.status_msg_time = time(NULL);
|
|
||||||
}
|
|
||||||
|
|||||||
+66
-31
@@ -1,31 +1,35 @@
|
|||||||
#include "../include/syntax_highlighter.h"
|
#include "../include/syntax_highlighter.h"
|
||||||
|
#include "../include/data.h"
|
||||||
|
#include "../include/theme.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
extern struct editorConfig E;
|
||||||
|
|
||||||
const char *c_keywords[] = {
|
const char *c_keywords[] = {
|
||||||
"if", "else", "while", "for", "do", "switch", "case", "break",
|
"if", "else", "while", "for", "do", "switch",
|
||||||
"continue", "return", "goto", "struct", "union", "enum",
|
"case", "break", "#include", "#define", "continue", "return",
|
||||||
"typedef", "static", "extern", "const", "volatile", "sizeof",
|
"goto", "struct", "union", "enum", "typedef", "static",
|
||||||
"auto", "register", "inline", "restrict", NULL
|
"extern", "const", "volatile", "sizeof", "auto", "register",
|
||||||
};
|
"inline", "restrict", NULL};
|
||||||
|
|
||||||
// C types
|
// C types
|
||||||
const char *c_types[] = {
|
const char *c_types[] = {"int", "char", "float", "double",
|
||||||
"int", "char", "float", "double", "void", "long", "short",
|
"void", "long", "short", "unsigned",
|
||||||
"unsigned", "signed", "bool", NULL
|
"signed", "bool", NULL};
|
||||||
};
|
|
||||||
|
|
||||||
// Check if character is alphanumeric or underscore
|
// Check if character is alphanumeric or underscore
|
||||||
int is_word_char(char c) {
|
int is_word_char(char c) {
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||||
(c >= '0' && c <= '9') || c == '_';
|
(c >= '0' && c <= '9') || c == '_' || c == '#';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if string is a keyword
|
// Check if string is a keyword
|
||||||
int is_keyword(const char *word) {
|
int is_keyword(const char *word) {
|
||||||
for (int i = 0; c_keywords[i] != NULL; i++) {
|
for (int i = 0; c_keywords[i] != NULL; i++) {
|
||||||
if (strcmp(word, c_keywords[i]) == 0) return 1;
|
if (strcmp(word, c_keywords[i]) == 0)
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -33,7 +37,8 @@ int is_keyword(const char *word) {
|
|||||||
// Check if string is a type
|
// Check if string is a type
|
||||||
int is_type(const char *word) {
|
int is_type(const char *word) {
|
||||||
for (int i = 0; c_types[i] != NULL; i++) {
|
for (int i = 0; c_types[i] != NULL; i++) {
|
||||||
if (strcmp(word, c_types[i]) == 0) return 1;
|
if (strcmp(word, c_types[i]) == 0)
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -41,15 +46,23 @@ int is_type(const char *word) {
|
|||||||
// Get color code for token type
|
// Get color code for token type
|
||||||
const char *get_color(TokenType type) {
|
const char *get_color(TokenType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TOKEN_KEYWORD: return COLOR_KEYWORD;
|
case TOKEN_KEYWORD:
|
||||||
case TOKEN_TYPE: return COLOR_TYPE;
|
return E.theme.COLOR_KEYWORD;
|
||||||
case TOKEN_STRING: return COLOR_STRING;
|
case TOKEN_TYPE:
|
||||||
case TOKEN_COMMENT: return COLOR_COMMENT;
|
return E.theme.COLOR_TYPE;
|
||||||
case TOKEN_NUMBER: return COLOR_NUMBER;
|
case TOKEN_STRING:
|
||||||
default: return COLOR_DEFAULT;
|
return E.theme.COLOR_STRING;
|
||||||
|
case TOKEN_COMMENT:
|
||||||
|
return E.theme.COLOR_COMMENT;
|
||||||
|
case TOKEN_NUMBER:
|
||||||
|
return E.theme.COLOR_NUMBER;
|
||||||
|
default:
|
||||||
|
return E.theme.COLOR_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int comment_section = 0;
|
||||||
|
|
||||||
// Highlight a line of C code and return the highlighted string
|
// Highlight a line of C code and return the highlighted string
|
||||||
// Returns a newly allocated string that must be freed by the caller
|
// Returns a newly allocated string that must be freed by the caller
|
||||||
char *highlight_line(const char *line, int *length) {
|
char *highlight_line(const char *line, int *length) {
|
||||||
@@ -64,9 +77,23 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comment_section) {
|
||||||
|
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
||||||
|
while (line[i] != '\0' && line[i] != '\n') {
|
||||||
|
|
||||||
|
if (line[i] == '*' && line[i + 1] == '/') {
|
||||||
|
comment_section = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[result_pos++] = line[i++];
|
||||||
|
}
|
||||||
|
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle line comments
|
// Handle line comments
|
||||||
if (line[i] == '/' && line[i + 1] == '/') {
|
if (line[i] == '/' && line[i + 1] == '/') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_COMMENT);
|
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
||||||
while (line[i] != '\0' && line[i] != '\n') {
|
while (line[i] != '\0' && line[i] != '\n') {
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
}
|
}
|
||||||
@@ -75,8 +102,9 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle block comments
|
// Handle block comments
|
||||||
if (line[i] == '/' && line[i + 1] == '*') {
|
if ((line[i] == '/' && line[i + 1] == '*')) {
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_COMMENT);
|
comment_section = 1;
|
||||||
|
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
while (line[i] != '\0') {
|
while (line[i] != '\0') {
|
||||||
@@ -93,7 +121,7 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
|
|
||||||
// Handle strings
|
// Handle strings
|
||||||
if (line[i] == '"') {
|
if (line[i] == '"') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s\"", COLOR_STRING);
|
result_pos += sprintf(&result[result_pos], "%s\"", E.theme.COLOR_STRING);
|
||||||
i++;
|
i++;
|
||||||
while (line[i] != '\0' && line[i] != '"') {
|
while (line[i] != '\0' && line[i] != '"') {
|
||||||
if (line[i] == '\\') {
|
if (line[i] == '\\') {
|
||||||
@@ -103,14 +131,15 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line[i] == '"') result[result_pos++] = line[i++];
|
if (line[i] == '"')
|
||||||
|
result[result_pos++] = line[i++];
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle character literals
|
// Handle character literals
|
||||||
if (line[i] == '\'') {
|
if (line[i] == '\'') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s'", COLOR_STRING);
|
result_pos += sprintf(&result[result_pos], "%s'", E.theme.COLOR_STRING);
|
||||||
i++;
|
i++;
|
||||||
while (line[i] != '\0' && line[i] != '\'') {
|
while (line[i] != '\0' && line[i] != '\'') {
|
||||||
if (line[i] == '\\') {
|
if (line[i] == '\\') {
|
||||||
@@ -120,14 +149,15 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line[i] == '\'') result[result_pos++] = line[i++];
|
if (line[i] == '\'')
|
||||||
|
result[result_pos++] = line[i++];
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle numbers
|
// Handle numbers
|
||||||
if (line[i] >= '0' && line[i] <= '9') {
|
if (line[i] >= '0' && line[i] <= '9') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_NUMBER);
|
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_NUMBER);
|
||||||
while (is_word_char(line[i]) || line[i] == '.') {
|
while (is_word_char(line[i]) || line[i] == '.') {
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
}
|
}
|
||||||
@@ -138,23 +168,28 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
// Handle identifiers and keywords
|
// Handle identifiers and keywords
|
||||||
if (is_word_char(line[i])) {
|
if (is_word_char(line[i])) {
|
||||||
int start = i;
|
int start = i;
|
||||||
while (is_word_char(line[i])) i++;
|
while (is_word_char(line[i]))
|
||||||
|
i++;
|
||||||
|
|
||||||
char word[256];
|
char word[256];
|
||||||
strncpy(word, &line[start], i - start);
|
strncpy(word, &line[start], i - start);
|
||||||
word[i - start] = '\0';
|
word[i - start] = '\0';
|
||||||
|
|
||||||
TokenType type = TOKEN_DEFAULT;
|
TokenType type = TOKEN_DEFAULT;
|
||||||
if (is_keyword(word)) type = TOKEN_KEYWORD;
|
if (is_keyword(word))
|
||||||
else if (is_type(word)) type = TOKEN_TYPE;
|
type = TOKEN_KEYWORD;
|
||||||
|
else if (is_type(word))
|
||||||
|
type = TOKEN_TYPE;
|
||||||
|
|
||||||
result_pos += sprintf(&result[result_pos], "%s%s%s",
|
result_pos += sprintf(&result[result_pos], "%s%s%s", get_color(type),
|
||||||
get_color(type), word, COLOR_RESET);
|
word, COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle operators and other characters
|
// Handle operators and other characters
|
||||||
|
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_DEFAULT);
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
|
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
result[result_pos] = '\0';
|
result[result_pos] = '\0';
|
||||||
|
|||||||
Reference in New Issue
Block a user