Configurable settings with blisp
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
tmp/*
|
||||
bin/*
|
||||
doc/*
|
||||
build/*
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Specify the minimum version of CMake required
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Define the project name and the programming language (C)
|
||||
project(Beluga)
|
||||
|
||||
# Set the C standard (optional)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
|
||||
# Add the header files directory to the include path
|
||||
include_directories(include)
|
||||
include_directories(blisp/include)
|
||||
|
||||
# Add the source files for the project
|
||||
set(SRCS
|
||||
main.c
|
||||
src/append_buffer.c
|
||||
src/file_io.c
|
||||
src/input.c
|
||||
src/row_op.c
|
||||
src/editor_op.c
|
||||
src/init.c
|
||||
src/output.c
|
||||
src/terminal.c
|
||||
src/builtins.c
|
||||
blisp/src/config_tools.c
|
||||
blisp/src/data.c
|
||||
blisp/src/lexer.c
|
||||
blisp/src/parser.c)
|
||||
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
# set input and output for doxygen
|
||||
set(DOXYGEN_OUT ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
|
||||
|
||||
add_custom_target(
|
||||
doc_doxygen ALL
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating documentation with Doxygen"
|
||||
VERBATIM)
|
||||
else(DOXYGEN_FOUND)
|
||||
message("Doxygen not found")
|
||||
endif(DOXYGEN_FOUND)
|
||||
|
||||
# we default to Release build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wall -Wextra")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-g")
|
||||
|
||||
# Create an executable target with the specified source files
|
||||
add_executable(beluga ${SRCS})
|
||||
|
||||
# Optionally, you can set the output directory for the executable
|
||||
set_target_properties(beluga PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin)
|
||||
@@ -1,32 +0,0 @@
|
||||
##
|
||||
# TEST
|
||||
#
|
||||
# @file
|
||||
# @version 0.1
|
||||
|
||||
BELUGA_OUTPUT=bin
|
||||
|
||||
BUILD_FLAGS=-Wall -Wextra -pedantic
|
||||
|
||||
build: main.c src/*
|
||||
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
||||
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/* $(BUILD_FLAGS)
|
||||
|
||||
DEBUG_FLAGS=-Wall -Wextra -pedantic -Werror -fsanitize=address -g
|
||||
|
||||
debug: main.c src/*
|
||||
if [ ! -d $(BELUGA_OUTPUT) ]; then mkdir $(BELUGA_OUTPUT); fi
|
||||
$(CC) main.c -o $(BELUGA_OUTPUT)/beluga src/* $(DEBUG_FLAGS)
|
||||
|
||||
doc:
|
||||
if [ ! -d doc/ ]; then mkdir doc; fi
|
||||
doxygen
|
||||
|
||||
clean:
|
||||
rm -r $(BELUGA_OUTPUT)
|
||||
rm -rf doc/
|
||||
rm -rf tmp/
|
||||
|
||||
all: build doc
|
||||
|
||||
# end
|
||||
@@ -4,17 +4,17 @@ Beluga is a project of CLI text editor that will fit perfectly with your azerty
|
||||
|
||||
## Requirements
|
||||
|
||||
You will only need **make** or **gcc** to compile the editor.
|
||||
You will only need **cmake** and **clang** to compile the editor.
|
||||
|
||||
## Installation
|
||||
|
||||
Here is the installation line :
|
||||
|
||||
```git clone --branch V1.0 --single-branch https://github.com/le-cocotier/beluga.git ~/.beluga && cd ~/.beluga && make build```
|
||||
```git clone --branch V1.0 --single-branch https://github.com/le-cocotier/beluga.git ~/.beluga && cd ~/.beluga && mkdir build && cd build && cmake ../ && make beluga```
|
||||
|
||||
The executable file will be in `bin/beluga`. Feel free to add it to your path.
|
||||
|
||||
You can either run `make all` if you're interested by the doxygen documentation.
|
||||
You can either run `make all` or `make doc_doxygen` if you're interested by the doxygen documentation.
|
||||
|
||||
## Getting start
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Configuration file
|
||||
|
||||
,map-key("ARROW-UP" %move-cursor-up)
|
||||
,map-key("ARROW-DOWN" %move-cursor-down)
|
||||
,map-key("ARROW-RIGHT" %move-cursor-right)
|
||||
,map-key("ARROW-LEFT" %move-cursor-left)
|
||||
,map-key("PAGE-UP" %move-cursor-page-up)
|
||||
,map-key("PAGE-DOWN" %move-cursor-page-down)
|
||||
,map-key("DEL_KEY" %delete-next-char)
|
||||
,map-key("BACKSPACE" %delete-previous-char)
|
||||
,map-key("ENTER" %editor-insert-new-line)
|
||||
,map-key("CTRL-s" %editor-save)
|
||||
,map-key("CTRL-q" %editor-quit)
|
||||
,map-key("CTRL-a" %move-cursor-beg-line)
|
||||
,map-key("CTRL-z" %move-cursor-end-line)
|
||||
,map-key("CTRL-f o" %open-file)
|
||||
,map-key("CTRL-w s h" %window-split-horizontal)
|
||||
,map-key("CTRL-w s v" %window-split-vertical)
|
||||
|
||||
,define(theme "dark")
|
||||
,define(auto-save true)
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef BUILTINS_H_
|
||||
#define BUILTINS_H_
|
||||
|
||||
#include "../blisp/include/config_tools.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/file_io.h"
|
||||
#include "../include/output.h"
|
||||
#include "../include/input.h"
|
||||
#include "data.h"
|
||||
#include "file_io.h"
|
||||
|
||||
// Function pointer type for commands
|
||||
typedef void (*command_func_t)(struct editorConfig *E);
|
||||
|
||||
// Structure to hold function mappings
|
||||
typedef struct {
|
||||
const char *name;
|
||||
command_func_t func;
|
||||
} function_entry_t;
|
||||
|
||||
// Function registry
|
||||
|
||||
void init_function_registry(void);
|
||||
int register_function(const char *name, command_func_t func);
|
||||
command_func_t find_function(const char *name);
|
||||
int execute_command(const char *name, struct editorConfig *E);
|
||||
|
||||
void moveCursorBeginLine(struct editorConfig *E);
|
||||
void moveCursorEndLine(struct editorConfig *E);
|
||||
void editorQuit(struct editorConfig *E);
|
||||
|
||||
void editorMoveCursorUp(struct editorConfig *E);
|
||||
void editorMoveCursorDown(struct editorConfig *E);
|
||||
void editorMoveCursorLeft(struct editorConfig *E);
|
||||
void editorMoveCursorRight(struct editorConfig *E);
|
||||
void deleteNextChar(struct editorConfig *E);
|
||||
void editorMoveCursorPageUp(struct editorConfig *E);
|
||||
void editorMoveCursorPageDown(struct editorConfig *E);
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include "../blisp/include/data.h"
|
||||
|
||||
/**
|
||||
* \struct erow
|
||||
@@ -31,10 +32,12 @@ struct editorConfig {
|
||||
int numrows; /**< Number of rows contained */
|
||||
erow *row; /**< Store all the rows printed */
|
||||
int dirty;
|
||||
int quit_times;
|
||||
char *filename;
|
||||
char status_msg[80];
|
||||
time_t status_msg_time;
|
||||
struct termios orig_termios; /**< Terminal communication interface */
|
||||
config_t *config;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -47,4 +50,12 @@ struct abuf {
|
||||
int len; /**< Length of the text */
|
||||
};
|
||||
|
||||
// Enhanced key sequence handling for multi-key bindings like "CTRL-f o"
|
||||
typedef struct {
|
||||
char sequence[64];
|
||||
int sequence_len;
|
||||
int last_key_time; // You might want to add timing if needed
|
||||
} key_sequence_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ enum editorKey {
|
||||
#define ABUF_INIT {NULL, 0}
|
||||
|
||||
#define BELUGA_VERSION "1.0"
|
||||
#define TAB_LENGTH 4
|
||||
#define TAB_LENGTH 2
|
||||
#define QUIT_TIMES 1
|
||||
|
||||
#endif // DEFINE_H_
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
|
||||
#include "data.h"
|
||||
#include "terminal.h"
|
||||
#include "builtins.h"
|
||||
#include "../blisp/include/config_tools.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void getConfig();
|
||||
|
||||
/**
|
||||
* \fn void initEditor()
|
||||
* \brief Job's function is to initialize all the fields of editorConfig.
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "define.h"
|
||||
#include "output.h"
|
||||
#include "terminal.h"
|
||||
#include "builtins.h"
|
||||
#include "../blisp/include/config_tools.h"
|
||||
#include <unistd.h>
|
||||
|
||||
// KEYS keycode
|
||||
@@ -19,6 +21,12 @@
|
||||
// END \x1b[4~ || <esc>[8~ || <esc>[F || <esc>OF
|
||||
// DELETE \x1b[3~
|
||||
|
||||
char *key_to_string(int key);
|
||||
|
||||
int execute_key_binding(config_t *config, const char *key_combo, void *context);
|
||||
|
||||
int handle_key_sequence(struct editorConfig *E, int key);
|
||||
|
||||
char *editorPrompt(struct editorConfig *E, char *prompt);
|
||||
|
||||
void editorMoveCursor(struct editorConfig *E, int key);
|
||||
|
||||
@@ -25,4 +25,6 @@ void editorRowAppendString(struct editorConfig *E, erow *row, char *s,
|
||||
|
||||
void editorRowDelchar(struct editorConfig *E, erow *row, int at);
|
||||
|
||||
void log_string(char * string);
|
||||
|
||||
#endif // ROW_OP_H_
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* interactions. \version 0.1 \date 21 septembre 2024
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _BSD_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
@@ -17,15 +18,12 @@
|
||||
#include "include/terminal.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
struct editorConfig E;
|
||||
|
||||
static struct editorConfig E;
|
||||
enableRawMode(&E);
|
||||
initEditor(&E);
|
||||
if (argc >= 2) {
|
||||
editorOpen(&E, argv[1]);
|
||||
}
|
||||
|
||||
editorSetStatusMessage(&E, "HELP: Ctrl-S = save | Ctrl-Q = quit");
|
||||
|
||||
while (1) {
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
|
||||
// function_registry.c
|
||||
#include "../include/builtins.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Static array to hold function mappings
|
||||
function_entry_t function_registry[256];
|
||||
int registry_count = 0;
|
||||
|
||||
// Initialize the function registry
|
||||
void init_function_registry(void) {
|
||||
register_function("editor-save", editorSave);
|
||||
register_function("move-cursor-beg-line", moveCursorBeginLine);
|
||||
register_function("move-cursor-end-line", moveCursorEndLine);
|
||||
register_function("editor-quit", editorQuit);
|
||||
register_function("move-cursor-up", editorMoveCursorUp);
|
||||
register_function("move-cursor-down", editorMoveCursorDown);
|
||||
register_function("move-cursor-right", editorMoveCursorRight);
|
||||
register_function("move-cursor-left", editorMoveCursorLeft);
|
||||
register_function("move-cursor-page-up", editorMoveCursorPageUp);
|
||||
register_function("move-cursor-page-down", editorMoveCursorPageDown);
|
||||
register_function("delete-previous-char", editorDelChar);
|
||||
register_function("delete-next-char", deleteNextChar);
|
||||
register_function("editor-insert-new-line", editorInsertNewLine);
|
||||
}
|
||||
|
||||
// Register a function with a name
|
||||
int register_function(const char *name, command_func_t func) {
|
||||
if (registry_count >= 256) {
|
||||
return -1; // Registry full
|
||||
}
|
||||
|
||||
function_registry[registry_count].name = strdup(name);
|
||||
function_registry[registry_count].func = func;
|
||||
registry_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find a function by name
|
||||
command_func_t find_function(const char *name) {
|
||||
log_string("registry :");
|
||||
char *tmp = malloc(3 * sizeof(char));
|
||||
sprintf(tmp, "%d\n", registry_count);
|
||||
log_string(tmp);
|
||||
for (int i = 0; i < registry_count; i++) {
|
||||
if (strcmp(function_registry[i].name, name) == 0) {
|
||||
return function_registry[i].func;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Execute a command by name
|
||||
int execute_command(const char *name, struct editorConfig *E) {
|
||||
log_string(name);
|
||||
command_func_t func = find_function(name);
|
||||
if (func) {
|
||||
func(E);
|
||||
return 0;
|
||||
}
|
||||
log_string("Unknown command: \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Builtins tools
|
||||
|
||||
void moveCursorBeginLine(struct editorConfig *E) { E->cursor_x = 0; }
|
||||
|
||||
void moveCursorEndLine(struct editorConfig *E) {
|
||||
if (E->cursor_y < E->numrows) {
|
||||
E->cursor_x = E->row[E->cursor_y].size;
|
||||
}
|
||||
}
|
||||
|
||||
void editorQuit(struct editorConfig *E) {
|
||||
log_string("time to quit\n");
|
||||
if (E->dirty && E->quit_times > 0) {
|
||||
editorSetStatusMessage(E,
|
||||
"WARNING! Changes hasn't been saved. Press Ctrl-Q "
|
||||
"another time to quit.");
|
||||
--E->quit_times;
|
||||
return;
|
||||
}
|
||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||
disableRawMode(E);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void editorMoveCursorUp(struct editorConfig *E) {
|
||||
editorMoveCursor(E, ARROW_UP);
|
||||
}
|
||||
|
||||
void editorMoveCursorDown(struct editorConfig *E) {
|
||||
editorMoveCursor(E, ARROW_DOWN);
|
||||
}
|
||||
|
||||
void editorMoveCursorRight(struct editorConfig *E) {
|
||||
editorMoveCursor(E, ARROW_RIGHT);
|
||||
}
|
||||
|
||||
void editorMoveCursorLeft(struct editorConfig *E) {
|
||||
editorMoveCursor(E, ARROW_LEFT);
|
||||
}
|
||||
|
||||
void deleteNextChar(struct editorConfig *E) {
|
||||
editorMoveCursorRight(E);
|
||||
editorDelChar(E);
|
||||
}
|
||||
|
||||
void editorMoveCursorPageUp(struct editorConfig *E) {
|
||||
E->cursor_y = E->row_offset;
|
||||
int times = E->screenrows;
|
||||
while (--times) {
|
||||
editorMoveCursor(E, ARROW_UP);
|
||||
}
|
||||
}
|
||||
|
||||
void editorMoveCursorPageDown(struct editorConfig *E) {
|
||||
E->cursor_y = E->row_offset + E->screenrows - 1;
|
||||
if (E->cursor_y > E->numrows) {
|
||||
E->cursor_y = E->numrows;
|
||||
}
|
||||
int times = E->screenrows;
|
||||
while (--times) {
|
||||
editorMoveCursor(E, ARROW_DOWN);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,11 @@ char *editorRowsToString(struct editorConfig *E, int *buffer_len) {
|
||||
}
|
||||
|
||||
void editorOpen(struct editorConfig *E, char *filename) {
|
||||
/**
|
||||
\function void editorOpen(struct editorConfig *E, char *filename)
|
||||
\brief Open filename on editor stream. Throw fopen error if file doesn't
|
||||
exist.
|
||||
*/
|
||||
FILE *fp;
|
||||
|
||||
free(E->filename);
|
||||
|
||||
@@ -9,6 +9,7 @@ void initEditor(struct editorConfig *E) {
|
||||
E->numrows = 0;
|
||||
E->row = NULL;
|
||||
E->dirty = 0;
|
||||
E->quit_times = QUIT_TIMES;
|
||||
E->filename = NULL;
|
||||
E->status_msg[0] = '\0';
|
||||
E->status_msg_time = 0;
|
||||
@@ -16,4 +17,11 @@ void initEditor(struct editorConfig *E) {
|
||||
die("getWindowSize");
|
||||
}
|
||||
E->screenrows -= 2;
|
||||
|
||||
E->config = config_create();
|
||||
config_parse_file(E->config, "../config/init.bl");
|
||||
|
||||
config_print_all(E->config);
|
||||
|
||||
init_function_registry();
|
||||
}
|
||||
|
||||
+134
-78
@@ -1,17 +1,76 @@
|
||||
#include "../include/input.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/file_io.h"
|
||||
#include "../include/output.h"
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* \fn char * editorPrompt(struct editorConfig *E, char *prompt)
|
||||
* \brief Return user input in a prompt when enter is hit. */
|
||||
|
||||
char *key_to_string(int key) {
|
||||
static char key_str[32];
|
||||
|
||||
char * tmp = malloc(10 * sizeof(char));
|
||||
sprintf(tmp, "%d\n", key);
|
||||
log_string(tmp);
|
||||
|
||||
|
||||
// First test enter key
|
||||
|
||||
if (key == '\r') {
|
||||
strcpy(key_str, "ENTER");
|
||||
} else if (key >= 1 && key <= 26) { // CTRL keys
|
||||
snprintf(key_str, sizeof(key_str), "CTRL-%c", 'a' + key - 1);
|
||||
} else {
|
||||
switch (key) {
|
||||
case ARROW_UP:
|
||||
strcpy(key_str, "ARROW-UP");
|
||||
break;
|
||||
case ARROW_DOWN:
|
||||
strcpy(key_str, "ARROW-DOWN");
|
||||
break;
|
||||
case ARROW_LEFT:
|
||||
strcpy(key_str, "ARROW-LEFT");
|
||||
break;
|
||||
case ARROW_RIGHT:
|
||||
strcpy(key_str, "ARROW-RIGHT");
|
||||
break;
|
||||
case PAGE_UP:
|
||||
strcpy(key_str, "PAGE-UP");
|
||||
break;
|
||||
case PAGE_DOWN:
|
||||
strcpy(key_str, "PAGE-DOWN");
|
||||
break;
|
||||
case DEL_KEY:
|
||||
strcpy(key_str, "DEL");
|
||||
break;
|
||||
case BACKSPACE:
|
||||
strcpy(key_str, "BACKSPACE");
|
||||
break;
|
||||
case '\r':
|
||||
strcpy(key_str, "ENTER");
|
||||
break;
|
||||
case '\x1b':
|
||||
strcpy(key_str, "ESCAPE");
|
||||
break;
|
||||
case BEG_LINE:
|
||||
strcpy(key_str, "HOME");
|
||||
break;
|
||||
case END_LINE:
|
||||
strcpy(key_str, "END");
|
||||
break;
|
||||
default:
|
||||
// For regular characters
|
||||
if (isprint(key)) {
|
||||
snprintf(key_str, sizeof(key_str), "%c", key);
|
||||
} else {
|
||||
snprintf(key_str, sizeof(key_str), "KEY-%d", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return key_str;
|
||||
}
|
||||
|
||||
char *editorPrompt(struct editorConfig *E, char *prompt) {
|
||||
size_t buf_size = 128;
|
||||
char *buf = malloc(buf_size);
|
||||
@@ -51,6 +110,7 @@ char *editorPrompt(struct editorConfig *E, char *prompt) {
|
||||
void editorMoveCursor(struct editorConfig *E, int key) {
|
||||
erow *row = (E->cursor_y >= E->numrows) ? NULL : &E->row[E->cursor_y];
|
||||
int row_len;
|
||||
char *sequence = key_to_string(key);
|
||||
switch (key) {
|
||||
case ARROW_RIGHT:
|
||||
if (row && E->cursor_x < row->size) {
|
||||
@@ -87,82 +147,78 @@ void editorMoveCursor(struct editorConfig *E, int key) {
|
||||
}
|
||||
}
|
||||
|
||||
key_sequence_t current_sequence = {0};
|
||||
|
||||
int handle_key_sequence(struct editorConfig *E, int key) {
|
||||
char *key_str = key_to_string(key);
|
||||
|
||||
log_string(key_str);
|
||||
|
||||
// Add current key to sequence
|
||||
if (current_sequence.sequence_len > 0) {
|
||||
strcat(current_sequence.sequence, " ");
|
||||
}
|
||||
strcat(current_sequence.sequence, key_str);
|
||||
current_sequence.sequence_len++;
|
||||
|
||||
// Check if this sequence matches any binding
|
||||
const char *command =
|
||||
config_get_key_mapping(E->config, current_sequence.sequence);
|
||||
if (command) {
|
||||
log_string("Command found\n");
|
||||
// Found a complete binding - execute it
|
||||
execute_key_binding(E->config, current_sequence.sequence, E);
|
||||
|
||||
// Reset sequence
|
||||
memset(¤t_sequence, 0, sizeof(current_sequence));
|
||||
return 1; // Handled
|
||||
}
|
||||
|
||||
// Check if this could be the start of a longer sequence
|
||||
// (This is a simple check - you might want to make it more sophisticated)
|
||||
int potential_match = 0;
|
||||
// You'd implement a function to check for partial matches here
|
||||
|
||||
if (!potential_match) {
|
||||
// No potential matches, reset sequence and handle as single key
|
||||
memset(¤t_sequence, 0, sizeof(current_sequence));
|
||||
return 0; // Not handled
|
||||
}
|
||||
|
||||
return 1; // Waiting for more keys in sequence
|
||||
}
|
||||
|
||||
int execute_key_binding(config_t *config, const char *key_combo,
|
||||
void *context) {
|
||||
const char *command = config_get_key_mapping(config, key_combo);
|
||||
if (!command) {
|
||||
log_string("No mapping found for key combination: ");
|
||||
log_string(key_combo);
|
||||
log_string("\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Remove the '%' prefix if present
|
||||
const char *func_name = command;
|
||||
if (command[0] == '%') {
|
||||
func_name = command + 1;
|
||||
}
|
||||
|
||||
return execute_command(func_name, context);
|
||||
}
|
||||
|
||||
void editorProcessKeypress(struct editorConfig *E) {
|
||||
static int quit_times = QUIT_TIMES;
|
||||
int c = editorReadKey();
|
||||
int times;
|
||||
|
||||
switch (c) {
|
||||
|
||||
case '\r':
|
||||
editorInsertNewLine(E);
|
||||
break;
|
||||
case CTRL_KEY('q'):
|
||||
if (E->dirty && quit_times > 0) {
|
||||
editorSetStatusMessage(E,
|
||||
"WARNING! Changes hasn't been saved. Press Ctrl-Q "
|
||||
"another time to quit.");
|
||||
--quit_times;
|
||||
return;
|
||||
if (E->config) {
|
||||
if (handle_key_sequence(E, c)) {
|
||||
quit_times = QUIT_TIMES;
|
||||
return; // Key was handled by config system
|
||||
}
|
||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||
disableRawMode(E);
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case CTRL_KEY('s'):
|
||||
editorSave(E);
|
||||
break;
|
||||
|
||||
case BEG_LINE:
|
||||
E->cursor_x = 0;
|
||||
break;
|
||||
|
||||
case END_LINE:
|
||||
if (E->cursor_y < E->numrows) {
|
||||
E->cursor_x = E->row[E->cursor_y].size;
|
||||
}
|
||||
break;
|
||||
|
||||
case BACKSPACE:
|
||||
case CTRL_KEY('h'):
|
||||
case DEL_KEY:
|
||||
if (c == DEL_KEY) {
|
||||
editorMoveCursor(E, ARROW_RIGHT);
|
||||
}
|
||||
editorDelChar(E);
|
||||
break;
|
||||
|
||||
case PAGE_UP:
|
||||
case PAGE_DOWN: {
|
||||
if (c == PAGE_UP) {
|
||||
E->cursor_y = E->row_offset;
|
||||
} else if (c == PAGE_DOWN) {
|
||||
E->cursor_y = E->row_offset + E->screenrows - 1;
|
||||
if (E->cursor_y > E->numrows) {
|
||||
E->cursor_y = E->numrows;
|
||||
}
|
||||
}
|
||||
times = E->screenrows;
|
||||
while (--times) {
|
||||
editorMoveCursor(E, c == PAGE_UP ? ARROW_UP : ARROW_DOWN);
|
||||
}
|
||||
} break;
|
||||
|
||||
case ARROW_UP:
|
||||
case ARROW_DOWN:
|
||||
case ARROW_LEFT:
|
||||
case ARROW_RIGHT:
|
||||
editorMoveCursor(E, c);
|
||||
break;
|
||||
|
||||
case CTRL_KEY('l'):
|
||||
case '\x1b':
|
||||
break;
|
||||
default:
|
||||
editorInsertChar(E, c);
|
||||
break;
|
||||
}
|
||||
quit_times = QUIT_TIMES;
|
||||
|
||||
editorInsertChar(E, c);
|
||||
// reset quit times
|
||||
E->quit_times = QUIT_TIMES;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../include/row_op.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -129,3 +130,10 @@ void editorRowDelchar(struct editorConfig *E, erow *row, int at) {
|
||||
editorUpdateRow(row);
|
||||
++E->dirty;
|
||||
}
|
||||
|
||||
void log_string(char * string){
|
||||
FILE * fd = fopen("tmp/log.txt", "a");
|
||||
fprintf(fd, "%s\n", string);
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -1,14 +1,18 @@
|
||||
#include "../include/terminal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void die(const char *s) {
|
||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||
|
||||
perror(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void disableRawMode(struct editorConfig *E) {
|
||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &E->orig_termios) == -1) {
|
||||
free(E);
|
||||
die("tcsetattr");
|
||||
}
|
||||
}
|
||||
@@ -27,7 +31,7 @@ void enableRawMode(struct editorConfig *E) {
|
||||
raw.c_cc[VTIME] = 1;
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
|
||||
die("tcgetattr");
|
||||
die("tcsetattr");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +45,7 @@ int editorReadKey() {
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%X (%c)\n", c, c);
|
||||
if (c == '\x1b') {
|
||||
if (read(STDIN_FILENO, &seq[0], 1) != 1 ||
|
||||
read(STDIN_FILENO, &seq[1], 1) != 1) {
|
||||
|
||||
Reference in New Issue
Block a user