Color theming
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
(define TAB-LENGTH 4)
|
||||
(define QUIT-TIMES 1)
|
||||
(define BACKGROUND-COLOR "light yellow")
|
||||
|
||||
;; 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
|
||||
+28
-3
@@ -20,6 +20,17 @@ typedef struct erow {
|
||||
char *render; /**< The actual line we will print */
|
||||
} 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 {
|
||||
IDLE,
|
||||
READ_ONLY,
|
||||
@@ -29,6 +40,7 @@ enum editorStatus_e {
|
||||
struct const_t {
|
||||
int TAB_LENGTH;
|
||||
int QUIT_TIMES;
|
||||
char *THEME;
|
||||
};
|
||||
|
||||
struct prefix_t {
|
||||
@@ -40,7 +52,16 @@ struct keyBind_t {
|
||||
char *key_sequence;
|
||||
int prefix_id;
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -74,12 +95,17 @@ struct editorConfig {
|
||||
Lisp ctx_data; /** Lisp data context */
|
||||
LispError ctx_error; /** Lisp ctx error */
|
||||
|
||||
struct keyBind_t* key_binds;
|
||||
struct keyBind_t *key_binds;
|
||||
int number_of_keybinds;
|
||||
|
||||
struct prefix_t* prefix;
|
||||
struct prefix_t *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;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,4 +8,6 @@ void editorInsertNewLine();
|
||||
|
||||
void editorDelChar();
|
||||
|
||||
void editorSetStatusMessage(const char *fmt, ...);
|
||||
|
||||
#endif // EDITOR_OP_H_
|
||||
|
||||
@@ -23,6 +23,4 @@ void editorDrawStatusBar(struct abuf *ab);
|
||||
|
||||
void editorDrawMessageBar(struct abuf *ab);
|
||||
|
||||
void editorSetStatusMessage(const char *fmt, ...);
|
||||
|
||||
#endif // OUTPUT_H_
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#define COLOR_RESET "\033[0m"
|
||||
#define COLOR_KEYWORD "\033[1;35m" // Bold magenta
|
||||
#define COLOR_TYPE "\033[1;34m" // Bold blue
|
||||
#define COLOR_STRING "\033[1;32m" // Bold green
|
||||
#define COLOR_COMMENT "\033[0;36m" // Cyan
|
||||
#define COLOR_NUMBER "\033[1;33m" // Bold yellow
|
||||
#define COLOR_DEFAULT "\033[0;37m" // White
|
||||
#ifndef SYNTAX_HIGHLIGHTER_H_
|
||||
#define SYNTAX_HIGHLIGHTER_H_
|
||||
|
||||
#include "color.h"
|
||||
|
||||
// Color codes that only affect foreground, preserving your background color
|
||||
#define COLOR_RESET "\x1b[39m" // Reset all (4 bytes)
|
||||
|
||||
// Token types
|
||||
typedef enum {
|
||||
@@ -18,3 +18,6 @@ typedef enum {
|
||||
} TokenType;
|
||||
|
||||
char *highlight_line(const char * line, int *length);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "include/file_io.h"
|
||||
#include "include/init.h"
|
||||
#include "include/input.h"
|
||||
#include "include/output.h"
|
||||
#include "include/editor_op.h"
|
||||
#include "include/terminal.h"
|
||||
|
||||
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/input.h"
|
||||
#include "../include/row_op.h"
|
||||
#include "include/output.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/row_op.h"
|
||||
|
||||
|
||||
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) {
|
||||
if (E.cursor_y == E.numrows) {
|
||||
editorInsertRow(E.numrows, "", 0);
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "../include/file_io.h"
|
||||
#include "../include/input.h"
|
||||
#include "../include/output.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
+73
-32
@@ -1,9 +1,11 @@
|
||||
#include "../include/init.h"
|
||||
#include "../include/builtins.h"
|
||||
#include "../include/color.h"
|
||||
#include "../include/data.h"
|
||||
#include "../include/terminal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LISP_IMPLEMENTATION
|
||||
#include "../include/lisp.h"
|
||||
@@ -17,7 +19,7 @@ void registerBuiltin(char *key_sequence, LispCFunc f) {
|
||||
}
|
||||
|
||||
void initBuiltins() {
|
||||
// move cursor
|
||||
// Registering C functions as lisp macro
|
||||
registerBuiltin("move-cursor", moveCursor);
|
||||
registerBuiltin("map-key", mapKey);
|
||||
registerBuiltin("editor-quit", editorQuit);
|
||||
@@ -39,38 +41,8 @@ void initBuiltins() {
|
||||
registerBuiltin("editor-insert-tab", l_editorInserTab);
|
||||
}
|
||||
|
||||
void initEditor() {
|
||||
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;
|
||||
void initConfig() {
|
||||
|
||||
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.env = lisp_env(E.ctx);
|
||||
lisp_lib_load(E.ctx);
|
||||
@@ -83,6 +55,75 @@ void initEditor() {
|
||||
die("init failed");
|
||||
}
|
||||
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
|
||||
|
||||
|
||||
+16
-27
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* @file output.c
|
||||
* @brief Screen rendering and output module for the Beluga text editor
|
||||
* @details Handles all screen updates, cursor positioning, status bar rendering,
|
||||
* and display synchronization using ANSI escape sequences
|
||||
* @details Handles all screen updates, cursor positioning, status bar
|
||||
* rendering, and display synchronization using ANSI escape sequences
|
||||
*/
|
||||
|
||||
#include "../include/output.h"
|
||||
#include "../include/append_buffer.h"
|
||||
#include "../include/syntax_highlighter.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -34,6 +34,7 @@ void editorDrawRows(struct abuf *ab) {
|
||||
int file_row;
|
||||
for (y = 0; y < E.screenrows; ++y) {
|
||||
file_row = y + E.row_offset;
|
||||
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||
if (file_row >= E.numrows) {
|
||||
if (E.numrows == 0 && y == E.screenrows / 3) {
|
||||
welcome_len =
|
||||
@@ -60,10 +61,13 @@ void editorDrawRows(struct abuf *ab) {
|
||||
len = 0;
|
||||
if (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);
|
||||
|
||||
free(highlighted);
|
||||
}
|
||||
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||
abAppend(ab, ERASE_END_LINE, 3);
|
||||
abAppend(ab, "\r\n", 2);
|
||||
}
|
||||
@@ -98,8 +102,9 @@ void editorScroll() {
|
||||
|
||||
/**
|
||||
* @brief Renders the status bar at the bottom of the screen
|
||||
* @details Displays filename, line count, dirty flag, and current cursor position
|
||||
* in an inverted color bar. Right-aligns the cursor position indicator.
|
||||
* @details Displays filename, line count, dirty flag, and current cursor
|
||||
* position in an inverted color bar. Right-aligns the cursor position
|
||||
* indicator.
|
||||
* @param ab Pointer to append buffer structure for accumulating output
|
||||
* @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
|
||||
* @details Clears screen, redraws all visible content (rows, status bar, message bar),
|
||||
* positions cursor, and writes accumulated buffer to stdout. This is the main
|
||||
* rendering function called each frame.
|
||||
* @details Clears screen, redraws all visible content (rows, status bar,
|
||||
* message bar), positions cursor, and writes accumulated buffer to stdout. This
|
||||
* is the main rendering function called each frame.
|
||||
* @note Updates global editor state E (via editorScroll())
|
||||
* @see editorDrawRows()
|
||||
* @see editorDrawStatusBar()
|
||||
@@ -163,9 +168,11 @@ void editorRefreshScreen() {
|
||||
struct abuf ab = ABUF_INIT;
|
||||
char buf[32];
|
||||
|
||||
|
||||
abAppend(&ab, HIDE_CURSOR, 6);
|
||||
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
||||
|
||||
|
||||
editorDrawRows(&ab);
|
||||
editorDrawStatusBar(&ab);
|
||||
editorDrawMessageBar(&ab);
|
||||
@@ -178,21 +185,3 @@ void editorRefreshScreen() {
|
||||
write(STDOUT_FILENO, ab.b, ab.len);
|
||||
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/data.h"
|
||||
#include "../include/theme.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern struct editorConfig E;
|
||||
|
||||
const char *c_keywords[] = {
|
||||
"if", "else", "while", "for", "do", "switch", "case", "break",
|
||||
"continue", "return", "goto", "struct", "union", "enum",
|
||||
"typedef", "static", "extern", "const", "volatile", "sizeof",
|
||||
"auto", "register", "inline", "restrict", NULL
|
||||
};
|
||||
"if", "else", "while", "for", "do", "switch",
|
||||
"case", "break", "#include", "#define", "continue", "return",
|
||||
"goto", "struct", "union", "enum", "typedef", "static",
|
||||
"extern", "const", "volatile", "sizeof", "auto", "register",
|
||||
"inline", "restrict", NULL};
|
||||
|
||||
// C types
|
||||
const char *c_types[] = {
|
||||
"int", "char", "float", "double", "void", "long", "short",
|
||||
"unsigned", "signed", "bool", NULL
|
||||
};
|
||||
const char *c_types[] = {"int", "char", "float", "double",
|
||||
"void", "long", "short", "unsigned",
|
||||
"signed", "bool", NULL};
|
||||
|
||||
// Check if character is alphanumeric or underscore
|
||||
int is_word_char(char c) {
|
||||
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
|
||||
int is_keyword(const char *word) {
|
||||
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;
|
||||
}
|
||||
@@ -33,7 +37,8 @@ int is_keyword(const char *word) {
|
||||
// Check if string is a type
|
||||
int is_type(const char *word) {
|
||||
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;
|
||||
}
|
||||
@@ -41,15 +46,23 @@ int is_type(const char *word) {
|
||||
// Get color code for token type
|
||||
const char *get_color(TokenType type) {
|
||||
switch (type) {
|
||||
case TOKEN_KEYWORD: return COLOR_KEYWORD;
|
||||
case TOKEN_TYPE: return COLOR_TYPE;
|
||||
case TOKEN_STRING: return COLOR_STRING;
|
||||
case TOKEN_COMMENT: return COLOR_COMMENT;
|
||||
case TOKEN_NUMBER: return COLOR_NUMBER;
|
||||
default: return COLOR_DEFAULT;
|
||||
case TOKEN_KEYWORD:
|
||||
return E.theme.COLOR_KEYWORD;
|
||||
case TOKEN_TYPE:
|
||||
return E.theme.COLOR_TYPE;
|
||||
case TOKEN_STRING:
|
||||
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
|
||||
// Returns a newly allocated string that must be freed by the caller
|
||||
char *highlight_line(const char *line, int *length) {
|
||||
@@ -64,9 +77,23 @@ char *highlight_line(const char *line, int *length) {
|
||||
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
|
||||
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') {
|
||||
result[result_pos++] = line[i++];
|
||||
}
|
||||
@@ -75,8 +102,9 @@ char *highlight_line(const char *line, int *length) {
|
||||
}
|
||||
|
||||
// Handle block comments
|
||||
if (line[i] == '/' && line[i + 1] == '*') {
|
||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_COMMENT);
|
||||
if ((line[i] == '/' && line[i + 1] == '*')) {
|
||||
comment_section = 1;
|
||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
||||
result[result_pos++] = line[i++];
|
||||
result[result_pos++] = line[i++];
|
||||
while (line[i] != '\0') {
|
||||
@@ -93,7 +121,7 @@ char *highlight_line(const char *line, int *length) {
|
||||
|
||||
// Handle strings
|
||||
if (line[i] == '"') {
|
||||
result_pos += sprintf(&result[result_pos], "%s\"", COLOR_STRING);
|
||||
result_pos += sprintf(&result[result_pos], "%s\"", E.theme.COLOR_STRING);
|
||||
i++;
|
||||
while (line[i] != '\0' && line[i] != '"') {
|
||||
if (line[i] == '\\') {
|
||||
@@ -103,14 +131,15 @@ char *highlight_line(const char *line, int *length) {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle character literals
|
||||
if (line[i] == '\'') {
|
||||
result_pos += sprintf(&result[result_pos], "%s'", COLOR_STRING);
|
||||
result_pos += sprintf(&result[result_pos], "%s'", E.theme.COLOR_STRING);
|
||||
i++;
|
||||
while (line[i] != '\0' && line[i] != '\'') {
|
||||
if (line[i] == '\\') {
|
||||
@@ -120,14 +149,15 @@ char *highlight_line(const char *line, int *length) {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle numbers
|
||||
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] == '.') {
|
||||
result[result_pos++] = line[i++];
|
||||
}
|
||||
@@ -138,23 +168,28 @@ char *highlight_line(const char *line, int *length) {
|
||||
// Handle identifiers and keywords
|
||||
if (is_word_char(line[i])) {
|
||||
int start = i;
|
||||
while (is_word_char(line[i])) i++;
|
||||
while (is_word_char(line[i]))
|
||||
i++;
|
||||
|
||||
char word[256];
|
||||
strncpy(word, &line[start], i - start);
|
||||
word[i - start] = '\0';
|
||||
|
||||
TokenType type = TOKEN_DEFAULT;
|
||||
if (is_keyword(word)) type = TOKEN_KEYWORD;
|
||||
else if (is_type(word)) type = TOKEN_TYPE;
|
||||
if (is_keyword(word))
|
||||
type = TOKEN_KEYWORD;
|
||||
else if (is_type(word))
|
||||
type = TOKEN_TYPE;
|
||||
|
||||
result_pos += sprintf(&result[result_pos], "%s%s%s",
|
||||
get_color(type), word, COLOR_RESET);
|
||||
result_pos += sprintf(&result[result_pos], "%s%s%s", get_color(type),
|
||||
word, COLOR_RESET);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle operators and other characters
|
||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_DEFAULT);
|
||||
result[result_pos++] = line[i++];
|
||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
||||
}
|
||||
|
||||
result[result_pos] = '\0';
|
||||
|
||||
Reference in New Issue
Block a user