This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
**#%#*****###%**
|
||||||
|
*##+--------------------=##*
|
||||||
|
#*=----------------------------=*#*
|
||||||
|
#*------------------------------------*#
|
||||||
|
%+----------------------------------------=#*
|
||||||
|
#+---------------------------------------------##
|
||||||
|
*#-------------------------------------------------=##
|
||||||
|
*#----------------------------------------------------:-##
|
||||||
|
#----------------------------------------------------------##
|
||||||
|
#=-------------------------------------------------------------##
|
||||||
|
#----------------------------==----------------------------------=#*
|
||||||
|
+--------------------------+@#-%*-----------------------------------#*
|
||||||
|
+--------------------------%@@@@#-------------------------------------**
|
||||||
|
*-=-------------------------#@@*---------------------------------------=%
|
||||||
|
%*#==--------------------------------------------------------------------+#
|
||||||
|
*%%=-=--------------------------------------------------------------------=#
|
||||||
|
%=--------------------------------------------------------------------------#*
|
||||||
|
%-----------------------------------------------------------------------------**
|
||||||
|
*+--=---===----=---------------=*-----------------------------------------------**
|
||||||
|
#--=## *#%#*+==----==+**+----------------------= ***=---------------------%
|
||||||
|
*%**=-----------==== ==---------------------------------=+#+-----------------=#
|
||||||
|
*%=----------------------------------------------------------=#*---------------#
|
||||||
|
##=----------------------------------=------------------------+%=------------+#
|
||||||
|
#%+---------------------------------=*------------------------+%------------#
|
||||||
|
*#%*=-------------=-----------------#-------------------------#+----------#
|
||||||
|
**#%#*******+=======-------------#=------------------------#----------#
|
||||||
|
#===#*=======------------------#*----=-----------=--=##*-----------#
|
||||||
|
-====##=------------------------*%+------------=*#+=====----------#
|
||||||
|
--=====+#*=----------------------=-=+*#####***+=======-----------=*
|
||||||
|
%------=====*%*=-------------------------========-----------------+*
|
||||||
|
*-=--------====%%###+=--------------------------=-----------------#
|
||||||
|
#-----------=% +*##%%%%%%@@%%%%####*==---------------------**
|
||||||
|
%=-------#* #%*=-----------------+#
|
||||||
|
*%+--=## ##=-----------------=#*
|
||||||
|
** #+----=-------------------#*
|
||||||
|
%+----------------------------#*
|
||||||
|
*%-------------==----------------+#
|
||||||
|
##--------------==------------------#
|
||||||
|
*#--------------===%-----------------=%
|
||||||
|
##---------------=-##*-----------------+#
|
||||||
|
*#---------------==#+=#%-----------------%
|
||||||
|
*%---------------+# %*---------------#*
|
||||||
|
*#------------=+#* #%*=-----------#*
|
||||||
|
#****##****** *#%%##+=----%
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
(define TAB-LENGTH 2)
|
||||||
|
(define QUIT-TIMES 1)
|
||||||
|
|
||||||
|
(map-key "CTRL-q" editor-quit)
|
||||||
|
(map-key "CTRL-s" editor-save)
|
||||||
|
|
||||||
|
(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 "ENTER" editor-insert-new-line)
|
||||||
|
(map-key "CTRL-a" move-cursor-beg-line)
|
||||||
|
(map-key "CTRL-e" move-cursor-end-line)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef BUILTINS_H_
|
||||||
|
#define BUILTINS_H_
|
||||||
|
|
||||||
|
#include "../lisp-interpreter/dist/lisp.h"
|
||||||
|
|
||||||
|
Lisp moveCursor(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
Lisp mapKey(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
void registerBuiltin(char * key_sequence, LispCFunc f);
|
||||||
|
|
||||||
|
Lisp editorQuit(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
Lisp l_editorSave(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
Lisp l_editorInsertNewLine(Lisp args, LispError* e, LispContext ctx);
|
||||||
|
|
||||||
|
Lisp moveCursorBeginLine(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
Lisp moveCursorEndLine(Lisp args, LispError* e, LispContext ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
+27
-4
@@ -1,10 +1,12 @@
|
|||||||
#ifndef DATA_H_
|
#ifndef DATA_H_
|
||||||
#define DATA_H_
|
#define DATA_H_
|
||||||
|
|
||||||
#include "../lisp-interpreter/dist/lisp.h"
|
#include <stdio.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "../lisp-interpreter/dist/lisp.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \struct erow
|
* \struct erow
|
||||||
* \brief Store one editor row
|
* \brief Store one editor row
|
||||||
@@ -18,6 +20,18 @@ typedef struct erow {
|
|||||||
char *render; /**< The actual line we will print */
|
char *render; /**< The actual line we will print */
|
||||||
} erow;
|
} erow;
|
||||||
|
|
||||||
|
|
||||||
|
struct const_t {
|
||||||
|
int TAB_LENGTH;
|
||||||
|
int QUIT_TIMES;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct keyBind_t {
|
||||||
|
char *key_sequence;
|
||||||
|
Lisp command;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \struct editorConfig
|
* \struct editorConfig
|
||||||
* \brief Containing our editor state.
|
* \brief Containing our editor state.
|
||||||
@@ -36,9 +50,18 @@ struct editorConfig {
|
|||||||
char status_msg[80];
|
char status_msg[80];
|
||||||
time_t status_msg_time;
|
time_t status_msg_time;
|
||||||
struct termios orig_termios; /**< Terminal communication interface */
|
struct termios orig_termios; /**< Terminal communication interface */
|
||||||
LispContext ctx; /** Lisp context */
|
|
||||||
Lisp ctx_data; /** Lisp data context */
|
struct const_t constantes;
|
||||||
LispError ctx_error; /** Lisp ctx error */
|
int quit_times_buffer;
|
||||||
|
|
||||||
|
FILE *fd_init_file;
|
||||||
|
Lisp env;
|
||||||
|
LispContext ctx; /** Lisp context */
|
||||||
|
Lisp ctx_data; /** Lisp data context */
|
||||||
|
LispError ctx_error; /** Lisp ctx error */
|
||||||
|
|
||||||
|
struct keyBind_t* key_binds;
|
||||||
|
int number_of_keybinds;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -25,7 +25,5 @@ enum editorKey {
|
|||||||
#define ABUF_INIT {NULL, 0}
|
#define ABUF_INIT {NULL, 0}
|
||||||
|
|
||||||
#define BELUGA_VERSION "1.0"
|
#define BELUGA_VERSION "1.0"
|
||||||
#define TAB_LENGTH 4
|
|
||||||
#define QUIT_TIMES 1
|
|
||||||
|
|
||||||
#endif // DEFINE_H_
|
#endif // DEFINE_H_
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
* \brief Job's function is to initialize all the fields of editorConfig.
|
* \brief Job's function is to initialize all the fields of editorConfig.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
void initBuiltins();
|
||||||
|
|
||||||
void initEditor();
|
void initEditor();
|
||||||
|
|
||||||
#endif // INIT_H_
|
#endif // INIT_H_
|
||||||
|
|||||||
@@ -21,8 +21,12 @@
|
|||||||
|
|
||||||
char *editorPrompt(char *prompt);
|
char *editorPrompt(char *prompt);
|
||||||
|
|
||||||
|
char *key_to_string(int key);
|
||||||
|
|
||||||
void editorMoveCursor(int key);
|
void editorMoveCursor(int key);
|
||||||
|
|
||||||
|
int executeKeyBind(char *key_sequence);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \fn void editorProcessKeypress()
|
* \fn void editorProcessKeypress()
|
||||||
* \brief Get the last key input and do the proper action.
|
* \brief Get the last key input and do the proper action.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
* interactions. \version 0.1 \date 21 septembre 2024
|
* interactions. \version 0.1 \date 21 septembre 2024
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#define _DEFAULT_SOURCE
|
#define _DEFAULT_SOURCE
|
||||||
#define _BSD_SOURCE
|
#define _BSD_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ src_files = files(
|
|||||||
'src/output.c',
|
'src/output.c',
|
||||||
'src/row_op.c',
|
'src/row_op.c',
|
||||||
'src/terminal.c',
|
'src/terminal.c',
|
||||||
|
'src/builtins.c',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Executable
|
# Executable
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
#include "../include/builtins.h"
|
||||||
|
#include "../include/define.h"
|
||||||
|
#include "../include/input.h"
|
||||||
|
#include "../include/file_io.h"
|
||||||
|
#include "../include/editor_op.h"
|
||||||
|
#include "../include/data.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Lisp mapKey(Lisp args, LispError *e, LispContext ctx) {
|
||||||
|
const char* key_sequence = lisp_string(lisp_car(args));
|
||||||
|
args = lisp_cdr(args);
|
||||||
|
// second argument
|
||||||
|
Lisp func = lisp_car(args);
|
||||||
|
|
||||||
|
E.key_binds =
|
||||||
|
(struct keyBind_t *)realloc(E.key_binds, ++E.number_of_keybinds * sizeof(struct keyBind_t));
|
||||||
|
E.key_binds[E.number_of_keybinds - 1].key_sequence = (char *) malloc(50 * sizeof(char));
|
||||||
|
|
||||||
|
strncpy(E.key_binds[E.number_of_keybinds - 1].key_sequence, key_sequence, 50);
|
||||||
|
|
||||||
|
E.key_binds[E.number_of_keybinds - 1].command = func;
|
||||||
|
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp moveCursor(Lisp args, LispError* e, LispContext ctx) {
|
||||||
|
const char *direction = lisp_string(lisp_car(args));
|
||||||
|
switch (direction[0]) {
|
||||||
|
case 'u':
|
||||||
|
editorMoveCursor(ARROW_UP);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
editorMoveCursor(ARROW_DOWN);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
editorMoveCursor(ARROW_RIGHT);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
editorMoveCursor(ARROW_LEFT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp editorQuit(Lisp args, LispError* e, LispContext ctx) {
|
||||||
|
if (E.dirty && E.quit_times_buffer > 0) {
|
||||||
|
editorSetStatusMessage("WARNING! Changes hasn't been saved. Press Ctrl-Q "
|
||||||
|
"another time to quit.");
|
||||||
|
--E.quit_times_buffer;
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||||
|
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||||
|
disableRawMode();
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
return lisp_null();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lisp l_editorSave(Lisp args, LispError* e, LispContext ctx) {
|
||||||
|
|
||||||
|
editorSave();
|
||||||
|
|
||||||
|
return lisp_null();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp l_editorInsertNewLine(Lisp args, LispError* e, LispContext ctx) {
|
||||||
|
|
||||||
|
editorInsertNewLine();
|
||||||
|
|
||||||
|
return lisp_null();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp moveCursorBeginLine(Lisp args, LispError *e, LispContext ctx) {
|
||||||
|
E.cursor_x = 0;
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp moveCursorEndLine(Lisp args, LispError* e, LispContext ctx) {
|
||||||
|
if (E.cursor_y < E.numrows) {
|
||||||
|
E.cursor_x = E.row[E.cursor_y].size;
|
||||||
|
}
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "../include/editor_op.h"
|
#include "../include/editor_op.h"
|
||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
extern struct editorConfig E;
|
extern struct editorConfig E;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -22,7 +22,7 @@ char *editorRowsToString(int *buffer_len) {
|
|||||||
|
|
||||||
for (j = 0; j < E.numrows; ++j) {
|
for (j = 0; j < E.numrows; ++j) {
|
||||||
tot_len += E.row[j].size + 1;
|
tot_len += E.row[j].size + 1;
|
||||||
}
|
}
|
||||||
*buffer_len = tot_len;
|
*buffer_len = tot_len;
|
||||||
buf = malloc(tot_len);
|
buf = malloc(tot_len);
|
||||||
p = buf;
|
p = buf;
|
||||||
@@ -42,7 +42,7 @@ void editorOpen(char *filename) {
|
|||||||
free(E.filename);
|
free(E.filename);
|
||||||
E.filename = strdup(filename);
|
E.filename = strdup(filename);
|
||||||
|
|
||||||
fp = fopen(filename, "r");
|
fp = fopen(filename, "a+");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
die("fopen");
|
die("fopen");
|
||||||
|
|
||||||
|
|||||||
+54
-4
@@ -1,9 +1,35 @@
|
|||||||
#include "../include/init.h"
|
#include "../include/init.h"
|
||||||
#include "../include/data.h"
|
#include "../include/data.h"
|
||||||
|
#include "../include/terminal.h"
|
||||||
|
#include "../include/builtins.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define LISP_IMPLEMENTATION
|
||||||
|
#include "../lisp-interpreter/dist/lisp.h"
|
||||||
|
#include "../lisp-interpreter/dist/lisp_lib.h"
|
||||||
|
|
||||||
extern struct editorConfig;
|
extern struct editorConfig;
|
||||||
|
|
||||||
|
|
||||||
|
void registerBuiltin(char *key_sequence, LispCFunc f) {
|
||||||
|
lisp_env_define(E.ctx.p->env, lisp_make_symbol(key_sequence, E.ctx),
|
||||||
|
lisp_make_func(f), E.ctx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initBuiltins() {
|
||||||
|
// move cursor
|
||||||
|
registerBuiltin("MOVE-CURSOR", moveCursor);
|
||||||
|
registerBuiltin("MAP-KEY", mapKey);
|
||||||
|
registerBuiltin("EDITOR-QUIT", editorQuit);
|
||||||
|
registerBuiltin("EDITOR-SAVE", l_editorSave);
|
||||||
|
registerBuiltin("EDITOR-INSERT-NEW-LINE", l_editorInsertNewLine);
|
||||||
|
registerBuiltin("MOVE-CURSOR-BEG-LINE", moveCursorBeginLine);
|
||||||
|
registerBuiltin("MOVE-CURSOR-END-LINE", moveCursorEndLine);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void initEditor() {
|
void initEditor() {
|
||||||
E.cursor_x = 0;
|
E.cursor_x = 0;
|
||||||
E.cursor_y = 0;
|
E.cursor_y = 0;
|
||||||
@@ -21,9 +47,33 @@ void initEditor() {
|
|||||||
}
|
}
|
||||||
E.screenrows -= 2;
|
E.screenrows -= 2;
|
||||||
|
|
||||||
// E.fd_init_file = fopen("../config/init.el", "r");
|
E.number_of_keybinds = 0;
|
||||||
|
|
||||||
// E.ctx = lisp_init();
|
|
||||||
// E.ctx_data = lisp_read_file(E.fd_init_file, &E.ctx_error, E.ctx);
|
E.fd_init_file = fopen("config/init.el", "r");
|
||||||
// lisp_printf(stderr, E.ctx_data);
|
E.ctx = lisp_init();
|
||||||
|
E.env = lisp_env(E.ctx);
|
||||||
|
lisp_lib_load(E.ctx);
|
||||||
|
// Init builtins lisp functions
|
||||||
|
initBuiltins();
|
||||||
|
|
||||||
|
// Read config file
|
||||||
|
E.ctx_data = lisp_read_file(E.fd_init_file, &E.ctx_error, E.ctx);
|
||||||
|
if (E.ctx_error != LISP_ERROR_NONE) {
|
||||||
|
die("init failed");
|
||||||
|
}
|
||||||
|
lisp_eval(E.ctx_data, &E.ctx_error, E.ctx);
|
||||||
|
|
||||||
|
// To modify
|
||||||
|
|
||||||
|
E.constantes.TAB_LENGTH =
|
||||||
|
(int)lisp_eval(lisp_read("TAB-LENGTH", &E.ctx_error, E.ctx), &E.ctx_error,
|
||||||
|
E.ctx)
|
||||||
|
.val.int_val;
|
||||||
|
E.constantes.QUIT_TIMES =
|
||||||
|
(int)lisp_eval(lisp_read("QUIT-TIMES", &E.ctx_error, E.ctx), &E.ctx_error,
|
||||||
|
E.ctx)
|
||||||
|
.val.int_val;
|
||||||
|
|
||||||
|
E.quit_times_buffer = E.constantes.QUIT_TIMES;
|
||||||
}
|
}
|
||||||
|
|||||||
+89
-77
@@ -1,11 +1,13 @@
|
|||||||
#include "../include/input.h"
|
#include "../include/input.h"
|
||||||
#include "../include/editor_op.h"
|
#include "../include/editor_op.h"
|
||||||
#include "../include/file_io.h"
|
|
||||||
#include "../include/output.h"
|
#include "../include/output.h"
|
||||||
|
#include "../include/define.h"
|
||||||
|
#include "data.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
extern struct editorConfig E;
|
extern struct editorConfig E;
|
||||||
@@ -30,7 +32,6 @@ char *editorPrompt(char *prompt) {
|
|||||||
buf[--buf_len] = '\0';
|
buf[--buf_len] = '\0';
|
||||||
}
|
}
|
||||||
} else if (c == ESCAPE) {
|
} else if (c == ESCAPE) {
|
||||||
fprintf(stderr, "escape");
|
|
||||||
editorSetStatusMessage("");
|
editorSetStatusMessage("");
|
||||||
free(buf);
|
free(buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -50,6 +51,70 @@ char *editorPrompt(char *prompt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *key_to_string(int key) {
|
||||||
|
static char key_str[32];
|
||||||
|
|
||||||
|
char tmp[10];
|
||||||
|
sprintf(tmp, "%d", key);
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void editorMoveCursor(int key) {
|
void editorMoveCursor(int key) {
|
||||||
erow *row = (E.cursor_y >= E.numrows) ? NULL : &E.row[E.cursor_y];
|
erow *row = (E.cursor_y >= E.numrows) ? NULL : &E.row[E.cursor_y];
|
||||||
int row_len;
|
int row_len;
|
||||||
@@ -89,81 +154,28 @@ void editorMoveCursor(int key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void editorProcessKeypress() {
|
int executeKeyBind(char *key_sequence) {
|
||||||
static int quit_times = QUIT_TIMES;
|
int i;
|
||||||
int c = editorReadKey();
|
for (i = 0; i < E.number_of_keybinds; ++i) {
|
||||||
int times;
|
if (!strcmp(key_sequence, E.key_binds[i].key_sequence)) {
|
||||||
|
|
||||||
switch (c) {
|
fprintf(stderr, "lisp function %s\n", key_sequence);
|
||||||
|
// It's a symbol, create a function call
|
||||||
case '\r':
|
lisp_eval(lisp_cons(E.key_binds[i].command, lisp_null(), E.ctx),
|
||||||
editorInsertNewLine();
|
&E.ctx_error, E.ctx);
|
||||||
break;
|
return 1;
|
||||||
case CTRL_KEY('q'):
|
|
||||||
if (E.dirty && quit_times > 0) {
|
|
||||||
editorSetStatusMessage("WARNING! Changes hasn't been saved. Press Ctrl-Q "
|
|
||||||
"another time to quit.");
|
|
||||||
--quit_times;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
|
||||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
|
||||||
disableRawMode();
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CTRL_KEY('s'):
|
|
||||||
editorSave();
|
|
||||||
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(ARROW_RIGHT);
|
|
||||||
}
|
|
||||||
editorDelChar();
|
|
||||||
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(c == PAGE_UP ? ARROW_UP : ARROW_DOWN);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case ARROW_UP:
|
|
||||||
case ARROW_DOWN:
|
|
||||||
case ARROW_LEFT:
|
|
||||||
case ARROW_RIGHT:
|
|
||||||
editorMoveCursor(c);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CTRL_KEY('l'):
|
|
||||||
case '\x1b':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
editorInsertChar(c);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
quit_times = QUIT_TIMES;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorProcessKeypress() {
|
||||||
|
int c = editorReadKey();
|
||||||
|
|
||||||
|
if (executeKeyBind(key_to_string(c))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editorInsertChar(c);
|
||||||
|
E.quit_times_buffer = E.constantes.QUIT_TIMES;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-6
@@ -1,4 +1,6 @@
|
|||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
|
#include "data.h"
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -10,7 +12,7 @@ int editorRowCxToRx(erow *row, int cursor_x) {
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < cursor_x; ++i) {
|
for (i = 0; i < cursor_x; ++i) {
|
||||||
if (row->chars[i] == '\t') {
|
if (row->chars[i] == '\t') {
|
||||||
render_x += (TAB_LENGTH - 1) - (render_x % TAB_LENGTH);
|
render_x += (E.constantes.TAB_LENGTH - 1) - (render_x % E.constantes.TAB_LENGTH);
|
||||||
}
|
}
|
||||||
render_x++;
|
render_x++;
|
||||||
}
|
}
|
||||||
@@ -34,8 +36,8 @@ void editorUpdateRow(erow *row) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(row->render);
|
free(row->render);
|
||||||
row->render = malloc(row->size + tabs * (TAB_LENGTH - 1) +
|
row->render = malloc(row->size + tabs * (E.constantes.TAB_LENGTH - 1) +
|
||||||
1); /**< Tabs needs TAB_LENGTH chars so TAB_LENGTH - 1
|
1); /**< Tabs needs E.constantes.TAB_LENGTH chars so E.constantes.TAB_LENGTH - 1
|
||||||
more than the first already counted. */
|
more than the first already counted. */
|
||||||
|
|
||||||
// end of counting
|
// end of counting
|
||||||
@@ -43,7 +45,7 @@ void editorUpdateRow(erow *row) {
|
|||||||
for (i = 0; i < row->size; ++i) {
|
for (i = 0; i < row->size; ++i) {
|
||||||
if (row->chars[i] == '\t') {
|
if (row->chars[i] == '\t') {
|
||||||
row->render[i_render++] = ' ';
|
row->render[i_render++] = ' ';
|
||||||
while (i_render % TAB_LENGTH) {
|
while (i_render % E.constantes.TAB_LENGTH) {
|
||||||
row->render[i_render++] =
|
row->render[i_render++] =
|
||||||
' '; /**< Addind the right amount of spaces for tabs */
|
' '; /**< Addind the right amount of spaces for tabs */
|
||||||
}
|
}
|
||||||
@@ -57,10 +59,14 @@ void editorUpdateRow(erow *row) {
|
|||||||
|
|
||||||
void editorInsertRow(int at, char *s, size_t len) {
|
void editorInsertRow(int at, char *s, size_t len) {
|
||||||
if (at < 0 || at > E.numrows) {
|
if (at < 0 || at > E.numrows) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
erow *tmp = (erow *)realloc(E.row, sizeof(erow) * (E.numrows + 1));
|
||||||
E.row = realloc(E.row, sizeof(erow) * (E.numrows + 1));
|
if (!tmp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
E.row = tmp;
|
||||||
memmove(&E.row[at + 1], &E.row[at], sizeof(erow) * (E.numrows - at));
|
memmove(&E.row[at + 1], &E.row[at], sizeof(erow) * (E.numrows - at));
|
||||||
|
|
||||||
E.row[at].size = len;
|
E.row[at].size = len;
|
||||||
|
|||||||
+115
-114
@@ -4,145 +4,146 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void die(const char *s) {
|
void die(const char *s) {
|
||||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||||
perror(s);
|
lisp_shutdown(E.ctx);
|
||||||
exit(1);
|
perror(s);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disableRawMode() {
|
void disableRawMode() {
|
||||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &E.orig_termios) == -1) {
|
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &E.orig_termios) == -1) {
|
||||||
die("tcsetattr");
|
die("tcsetattr");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableRawMode() {
|
void enableRawMode() {
|
||||||
if (tcgetattr(STDIN_FILENO, &E.orig_termios) == -1) {
|
if (tcgetattr(STDIN_FILENO, &E.orig_termios) == -1) {
|
||||||
die("tcgetattr");
|
die("tcgetattr");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct termios raw = E.orig_termios;
|
struct termios raw = E.orig_termios;
|
||||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||||
raw.c_oflag &= ~(OPOST);
|
raw.c_oflag &= ~(OPOST);
|
||||||
raw.c_cflag |= (CS8);
|
raw.c_cflag |= (CS8);
|
||||||
raw.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
|
raw.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
|
||||||
raw.c_cc[VMIN] = 0;
|
raw.c_cc[VMIN] = 0;
|
||||||
raw.c_cc[VTIME] = 1;
|
raw.c_cc[VTIME] = 1;
|
||||||
|
|
||||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
|
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
|
||||||
die("tcgetattr");
|
die("tcgetattr");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int editorReadKey() {
|
int editorReadKey() {
|
||||||
int nread;
|
int nread;
|
||||||
char c;
|
char c;
|
||||||
char seq[3];
|
char seq[3];
|
||||||
while ((nread = read(STDIN_FILENO, &c, 1)) != 1) {
|
while ((nread = read(STDIN_FILENO, &c, 1)) != 1) {
|
||||||
if (nread == -1 && errno != EAGAIN) {
|
if (nread == -1 && errno != EAGAIN) {
|
||||||
die("read");
|
die("read");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (c == '\x1b') {
|
if (c == '\x1b') {
|
||||||
if (read(STDIN_FILENO, &seq[0], 1) != 1 ||
|
if (read(STDIN_FILENO, &seq[0], 1) != 1 ||
|
||||||
read(STDIN_FILENO, &seq[1], 1) != 1) {
|
read(STDIN_FILENO, &seq[1], 1) != 1) {
|
||||||
return '\x1b';
|
return '\x1b';
|
||||||
}
|
|
||||||
if (seq[0] == '[') {
|
|
||||||
if (seq[1] >= '0' && seq[1] <= '9') {
|
|
||||||
if (read(STDIN_FILENO, &seq[2], 1) != 1) {
|
|
||||||
return '\x1b';
|
|
||||||
}
|
|
||||||
if (seq[2] == '~') {
|
|
||||||
switch (seq[1]) {
|
|
||||||
case '1':
|
|
||||||
return BEG_LINE;
|
|
||||||
case '3':
|
|
||||||
return DEL_KEY;
|
|
||||||
case '4':
|
|
||||||
return END_LINE;
|
|
||||||
case '5':
|
|
||||||
return PAGE_UP;
|
|
||||||
case '6':
|
|
||||||
return PAGE_DOWN;
|
|
||||||
case '7':
|
|
||||||
return BEG_LINE;
|
|
||||||
case '8':
|
|
||||||
return END_LINE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
switch (seq[1]) {
|
|
||||||
case 'A':
|
|
||||||
return ARROW_UP;
|
|
||||||
case 'B':
|
|
||||||
return ARROW_DOWN;
|
|
||||||
case 'C':
|
|
||||||
return ARROW_RIGHT;
|
|
||||||
case 'D':
|
|
||||||
return ARROW_LEFT;
|
|
||||||
case 'H':
|
|
||||||
return BEG_LINE;
|
|
||||||
case 'F':
|
|
||||||
return END_LINE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (seq[0] == 'O') {
|
|
||||||
switch (seq[1]) {
|
|
||||||
case 'H':
|
|
||||||
return BEG_LINE;
|
|
||||||
case 'F':
|
|
||||||
return END_LINE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '\x1b';
|
|
||||||
} else {
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
if (seq[0] == '[') {
|
||||||
|
if (seq[1] >= '0' && seq[1] <= '9') {
|
||||||
|
if (read(STDIN_FILENO, &seq[2], 1) != 1) {
|
||||||
|
return '\x1b';
|
||||||
|
}
|
||||||
|
if (seq[2] == '~') {
|
||||||
|
switch (seq[1]) {
|
||||||
|
case '1':
|
||||||
|
return BEG_LINE;
|
||||||
|
case '3':
|
||||||
|
return DEL_KEY;
|
||||||
|
case '4':
|
||||||
|
return END_LINE;
|
||||||
|
case '5':
|
||||||
|
return PAGE_UP;
|
||||||
|
case '6':
|
||||||
|
return PAGE_DOWN;
|
||||||
|
case '7':
|
||||||
|
return BEG_LINE;
|
||||||
|
case '8':
|
||||||
|
return END_LINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
switch (seq[1]) {
|
||||||
|
case 'A':
|
||||||
|
return ARROW_UP;
|
||||||
|
case 'B':
|
||||||
|
return ARROW_DOWN;
|
||||||
|
case 'C':
|
||||||
|
return ARROW_RIGHT;
|
||||||
|
case 'D':
|
||||||
|
return ARROW_LEFT;
|
||||||
|
case 'H':
|
||||||
|
return BEG_LINE;
|
||||||
|
case 'F':
|
||||||
|
return END_LINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (seq[0] == 'O') {
|
||||||
|
switch (seq[1]) {
|
||||||
|
case 'H':
|
||||||
|
return BEG_LINE;
|
||||||
|
case 'F':
|
||||||
|
return END_LINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '\x1b';
|
||||||
|
} else {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getCursorPosition(int *rows, int *cols) {
|
int getCursorPosition(int *rows, int *cols) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
|
||||||
if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) {
|
if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i < sizeof(buf) - 1) {
|
while (i < sizeof(buf) - 1) {
|
||||||
if (read(STDIN_FILENO, &buf[i], 1) != 1) {
|
if (read(STDIN_FILENO, &buf[i], 1) != 1) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (buf[i] == 'R') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
buf[i] = '\0';
|
if (buf[i] == 'R') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
buf[i] = '\0';
|
||||||
|
|
||||||
if (buf[0] != '\x1b' || buf[1] != '[') {
|
if (buf[0] != '\x1b' || buf[1] != '[') {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sscanf(&buf[2], "%d;%d", rows, cols) != 2) {
|
if (sscanf(&buf[2], "%d;%d", rows, cols) != 2) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWindowSize(int *rows, int *cols) {
|
int getWindowSize(int *rows, int *cols) {
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
|
|
||||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
|
||||||
if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) {
|
if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
return getCursorPosition(rows, cols);
|
|
||||||
} else {
|
|
||||||
*cols = ws.ws_col;
|
|
||||||
*rows = ws.ws_row;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return getCursorPosition(rows, cols);
|
||||||
|
} else {
|
||||||
|
*cols = ws.ws_col;
|
||||||
|
*rows = ws.ws_row;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user