functional lisp config files
Build and Deploy Docs / build (push) Successful in 47s

This commit is contained in:
Arthur Barraux
2025-10-02 11:26:18 +02:00
parent 53d6572c8c
commit 3b6c60a49e
16 changed files with 482 additions and 209 deletions
+44
View File
@@ -0,0 +1,44 @@
**#%#*****###%**
*##+--------------------=##*
#*=----------------------------=*#*
#*------------------------------------*#
%+----------------------------------------=#*
#+---------------------------------------------##
*#-------------------------------------------------=##
*#----------------------------------------------------:-##
#----------------------------------------------------------##
#=-------------------------------------------------------------##
#----------------------------==----------------------------------=#*
+--------------------------+@#-%*-----------------------------------#*
+--------------------------%@@@@#-------------------------------------**
*-=-------------------------#@@*---------------------------------------=%
%*#==--------------------------------------------------------------------+#
*%%=-=--------------------------------------------------------------------=#
%=--------------------------------------------------------------------------#*
%-----------------------------------------------------------------------------**
*+--=---===----=---------------=*-----------------------------------------------**
#--=## *#%#*+==----==+**+----------------------= ***=---------------------%
*%**=-----------==== ==---------------------------------=+#+-----------------=#
*%=----------------------------------------------------------=#*---------------#
##=----------------------------------=------------------------+%=------------+#
#%+---------------------------------=*------------------------+%------------#
*#%*=-------------=-----------------#-------------------------#+----------#
**#%#*******+=======-------------#=------------------------#----------#
#===#*=======------------------#*----=-----------=--=##*-----------#
-====##=------------------------*%+------------=*#+=====----------#
--=====+#*=----------------------=-=+*#####***+=======-----------=*
%------=====*%*=-------------------------========-----------------+*
*-=--------====%%###+=--------------------------=-----------------#
#-----------=% +*##%%%%%%@@%%%%####*==---------------------**
%=-------#* #%*=-----------------+#
*%+--=## ##=-----------------=#*
** #+----=-------------------#*
%+----------------------------#*
*%-------------==----------------+#
##--------------==------------------#
*#--------------===%-----------------=%
##---------------=-##*-----------------+#
*#---------------==#+=#%-----------------%
*%---------------+# %*---------------#*
*#------------=+#* #%*=-----------#*
#****##****** *#%%##+=----%
+13
View File
@@ -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)
+22
View File
@@ -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
View File
@@ -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;
}; };
/** /**
-2
View File
@@ -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_
+2
View File
@@ -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_
+4
View File
@@ -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.
+1
View File
@@ -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
+1
View File
@@ -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
+95
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
} }