@@ -86,4 +86,3 @@
|
|||||||
(map-key "\"" editor-split-screen-vertical "user")
|
(map-key "\"" editor-split-screen-vertical "user")
|
||||||
(map-key "o" editor-switch-next-pane "user")
|
(map-key "o" editor-switch-next-pane "user")
|
||||||
(map-key "*" editor-unify-panes "user")
|
(map-key "*" editor-unify-panes "user")
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
#define ERASE_END_LINE "\x1b[K"
|
#define ERASE_END_LINE "\x1b[K"
|
||||||
#define TAB "\x9"
|
#define TAB "\x9"
|
||||||
#define SPACE "\x20"
|
#define SPACE "\x20"
|
||||||
#define APP_DEBUG
|
// #define APP_DEBUG
|
||||||
|
|
||||||
enum editorKey_e {
|
enum editorKey_e {
|
||||||
BACKSPACE = 127,
|
BACKSPACE = 127,
|
||||||
|
|||||||
+1
-1
@@ -116,13 +116,13 @@ void editorSave() {
|
|||||||
len = strlen(buffer->row[i].chars);
|
len = strlen(buffer->row[i].chars);
|
||||||
if (write(fd, buffer->row[i].chars, len) != len) {
|
if (write(fd, buffer->row[i].chars, len) != len) {
|
||||||
close(fd);
|
close(fd);
|
||||||
E.dirty = 0;
|
|
||||||
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
|
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
write(fd, "\n", 1);
|
write(fd, "\n", 1);
|
||||||
}
|
}
|
||||||
|
buffer->dirty = 0;
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
editorSetStatusMessage("File saved");
|
editorSetStatusMessage("File saved");
|
||||||
|
|||||||
+1
-1
@@ -77,7 +77,7 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
|
|||||||
{
|
{
|
||||||
start_offset = pane->x_offset;
|
start_offset = pane->x_offset;
|
||||||
|
|
||||||
if (buf->filename[strlen(buf->filename) - 1] == 'c')
|
if (buf->filename[strlen(buf->filename) - 1] == 'c' || buf->filename[strlen(buf->filename) - 1] == 'h')
|
||||||
{
|
{
|
||||||
// Render line with syntax highlighting, constrain to pane width
|
// Render line with syntax highlighting, constrain to pane width
|
||||||
highlighted = highlight_line(
|
highlighted = highlight_line(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ extern struct editorConfig E;
|
|||||||
|
|
||||||
const char *c_keywords[] = {
|
const char *c_keywords[] = {
|
||||||
"if", "else", "while", "for", "do", "switch",
|
"if", "else", "while", "for", "do", "switch",
|
||||||
"case", "break", "#include", "#define", "continue", "return",
|
"case", "break", "#include", "#define", "#if", "#endif", "#ifndef", "continue", "return",
|
||||||
"goto", "struct", "union", "enum", "typedef", "static",
|
"goto", "struct", "union", "enum", "typedef", "static",
|
||||||
"extern", "const", "volatile", "sizeof", "auto", "register",
|
"extern", "const", "volatile", "sizeof", "auto", "register",
|
||||||
"inline", "restrict", NULL};
|
"inline", "restrict", NULL};
|
||||||
|
|||||||
+74
-32
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "include/utf8.h"
|
#include "include/utf8.h"
|
||||||
|
|
||||||
@@ -51,21 +51,45 @@ char *key_to_string(int key) {
|
|||||||
|
|
||||||
if (key == '\r') {
|
if (key == '\r') {
|
||||||
strcpy(key_str, "ENTER");
|
strcpy(key_str, "ENTER");
|
||||||
|
} else if (key == 0x09) {
|
||||||
|
strcpy(key_str, "TAB");
|
||||||
} else if (key >= 1 && key <= 26) {
|
} else if (key >= 1 && key <= 26) {
|
||||||
snprintf(key_str, sizeof(key_str), "CTRL-%c", 'a' + key - 1);
|
snprintf(key_str, sizeof(key_str), "CTRL-%c", 'a' + key - 1);
|
||||||
} else {
|
} else {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case ARROW_UP: strcpy(key_str, "ARROW-UP"); break;
|
case ARROW_UP:
|
||||||
case ARROW_DOWN: strcpy(key_str, "ARROW-DOWN"); break;
|
strcpy(key_str, "ARROW-UP");
|
||||||
case ARROW_LEFT: strcpy(key_str, "ARROW-LEFT"); break;
|
break;
|
||||||
case ARROW_RIGHT: strcpy(key_str, "ARROW-RIGHT"); break;
|
case ARROW_DOWN:
|
||||||
case PAGE_UP: strcpy(key_str, "PAGE-UP"); break;
|
strcpy(key_str, "ARROW-DOWN");
|
||||||
case PAGE_DOWN: strcpy(key_str, "PAGE-DOWN"); break;
|
break;
|
||||||
case DEL_KEY: strcpy(key_str, "DEL"); break;
|
case ARROW_LEFT:
|
||||||
case BACKSPACE: strcpy(key_str, "BACKSPACE"); break;
|
strcpy(key_str, "ARROW-LEFT");
|
||||||
case BEG_LINE: strcpy(key_str, "HOME"); break;
|
break;
|
||||||
case END_LINE: strcpy(key_str, "END"); break;
|
case ARROW_RIGHT:
|
||||||
case '\x1b': strcpy(key_str, "ESCAPE"); break;
|
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 BEG_LINE:
|
||||||
|
strcpy(key_str, "HOME");
|
||||||
|
break;
|
||||||
|
case END_LINE:
|
||||||
|
strcpy(key_str, "END");
|
||||||
|
break;
|
||||||
|
case '\x1b':
|
||||||
|
strcpy(key_str, "ESCAPE");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (key > 127) {
|
if (key > 127) {
|
||||||
/* UTF-8 code point — re-encode into the buffer */
|
/* UTF-8 code point — re-encode into the buffer */
|
||||||
@@ -85,36 +109,53 @@ char *key_to_string(int key) {
|
|||||||
int editorReadKey() {
|
int editorReadKey() {
|
||||||
char c;
|
char c;
|
||||||
/* read first byte — may be start of UTF-8 or escape */
|
/* read first byte — may be start of UTF-8 or escape */
|
||||||
while (read(STDIN_FILENO, &c, 1) != 1);
|
while (read(STDIN_FILENO, &c, 1) != 1)
|
||||||
|
;
|
||||||
appDebug("f : %X\r\n", c);
|
appDebug("f : %X\r\n", c);
|
||||||
|
|
||||||
if (c == '\x1b') {
|
if (c == '\x1b') {
|
||||||
char seq[6];
|
char seq[6];
|
||||||
/* try to read escape sequence */
|
/* try to read escape sequence */
|
||||||
if (read(STDIN_FILENO, &seq[0], 1) != 1) return '\x1b';
|
if (read(STDIN_FILENO, &seq[0], 1) != 1)
|
||||||
if (read(STDIN_FILENO, &seq[1], 1) != 1) return '\x1b';
|
return '\x1b';
|
||||||
|
if (read(STDIN_FILENO, &seq[1], 1) != 1)
|
||||||
|
return '\x1b';
|
||||||
if (seq[0] == '[') {
|
if (seq[0] == '[') {
|
||||||
if (seq[1] >= '0' && seq[1] <= '9') {
|
if (seq[1] >= '0' && seq[1] <= '9') {
|
||||||
if (read(STDIN_FILENO, &seq[2], 1) != 1) return '\x1b';
|
if (read(STDIN_FILENO, &seq[2], 1) != 1)
|
||||||
|
return '\x1b';
|
||||||
if (seq[2] == '~') {
|
if (seq[2] == '~') {
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
case '1': return BEG_LINE;
|
case '1':
|
||||||
case '3': return DEL_KEY;
|
return BEG_LINE;
|
||||||
case '4': return END_LINE;
|
case '3':
|
||||||
case '5': return PAGE_UP;
|
return DEL_KEY;
|
||||||
case '6': return PAGE_DOWN;
|
case '4':
|
||||||
case '7': return BEG_LINE;
|
return END_LINE;
|
||||||
case '8': return END_LINE;
|
case '5':
|
||||||
|
return PAGE_UP;
|
||||||
|
case '6':
|
||||||
|
return PAGE_DOWN;
|
||||||
|
case '7':
|
||||||
|
return BEG_LINE;
|
||||||
|
case '8':
|
||||||
|
return END_LINE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
case 'A': return ARROW_UP;
|
case 'A':
|
||||||
case 'B': return ARROW_DOWN;
|
return ARROW_UP;
|
||||||
case 'C': return ARROW_RIGHT;
|
case 'B':
|
||||||
case 'D': return ARROW_LEFT;
|
return ARROW_DOWN;
|
||||||
case 'H': return BEG_LINE;
|
case 'C':
|
||||||
case 'F': return END_LINE;
|
return ARROW_RIGHT;
|
||||||
|
case 'D':
|
||||||
|
return ARROW_LEFT;
|
||||||
|
case 'H':
|
||||||
|
return BEG_LINE;
|
||||||
|
case 'F':
|
||||||
|
return END_LINE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +169,8 @@ int editorReadKey() {
|
|||||||
we handle encoding/decoding at the row level */
|
we handle encoding/decoding at the row level */
|
||||||
char buf[4] = {c, 0, 0, 0};
|
char buf[4] = {c, 0, 0, 0};
|
||||||
for (int i = 1; i < seqlen; i++)
|
for (int i = 1; i < seqlen; i++)
|
||||||
if (read(STDIN_FILENO, &buf[i], 1) != 1) break;
|
if (read(STDIN_FILENO, &buf[i], 1) != 1)
|
||||||
|
break;
|
||||||
/* decode and return as uint32, but we need int — use high range */
|
/* decode and return as uint32, but we need int — use high range */
|
||||||
const char *p = buf;
|
const char *p = buf;
|
||||||
uint32_t cp = utf8Decode(&p);
|
uint32_t cp = utf8Decode(&p);
|
||||||
@@ -183,12 +225,12 @@ int getWindowSize(int *rows, int *cols) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void appDebug(const char *fmt, ...) {
|
void appDebug(const char *fmt, ...) {
|
||||||
#ifdef APP_DEBUG
|
#ifdef APP_DEBUG
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char message[256];
|
char message[256];
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(message, 256, fmt, ap);
|
vsnprintf(message, 256, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
fprintf(stderr, "%s\n", message);
|
fprintf(stderr, "%s\n", message);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user