Got most of a paste buffer working

This commit is contained in:
sloumdrone 2020-01-01 22:51:00 -08:00
parent 8ad3f71a1c
commit 3915c8ab68
6 changed files with 228 additions and 93 deletions

27
LICENSE Normal file
View File

@ -0,0 +1,27 @@
This software (c) 2020, Brian Evans <sloum at colorfield dot space>
based on/extending "kilo" by Salvatore Sanfilippo:
Copyright (c) 2016, Salvatore Sanfilippo <antirez at gmail dot com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

BIN
hermes

Binary file not shown.

View File

@ -10,7 +10,7 @@
.SH DESCRIPTION
\fBhermes\fP is a minimalist modal text editor with support for some vi-like key commands. \fBhermes\fP supports basic syntax highlighting and filetype detection.
.SH USAGE
Most of the key bindings that follow are only available in command mode (the exceptions being any Ctrl based key combinations, the arrow keys, home,a nd end). In addition to the listed keys, while in command mode you may enter numbers that will modify the following action keys in some way. For example 10w would move the cursor forward 10 words. 10<enter> would move the cursor to the 10th row of the file. The d key is also special, as it does not do anything on its own, but modifies a key that follows it. For example 10dw would delete the next ten words.
Most of the key bindings that follow are only available in command mode (the exceptions being any Ctrl based key combinations, the arrow keys, home, and end). In addition to the listed keys, while in command mode you may enter numbers that will modify the following action keys in some way. For example 10w would move the cursor forward 10 words. 10<enter> would move the cursor to the 10th row of the file. The d key is also special, as it modifies a key that follows it. For example 10dw would delete the next ten words.
.TP
.B
a
@ -46,11 +46,11 @@ Go from input mode to command mode.
.TP
.B
g
Move cursor to the top left of the document.
Move cursor to the beginning of the document.
.TP
.B
G
Move cursor to the bottom right of the document.
Move cursor to the end of the document.
.TP
.B
h or left arrow

203
hermes.c
View File

@ -24,8 +24,6 @@
// -----------
#define HERMES_VERSION "0.5"
#define CTRL_KEY(k) ((k) & 0x1f)
#define HL_HIGHLIGHT_NUMBERS (1<<0)
#define HL_HIGHLIGHT_STRINGS (1<<1)
//
// definitions for config file
@ -56,10 +54,13 @@ enum editorKey {
END_KEY
};
//
// data
// ----
#include "syntaxhl.h"
typedef struct erow {
int idx;
int size;
@ -79,7 +80,9 @@ struct editorConfig {
int screenCols;
int numRows;
int unsaved;
int pastelen;
erow *row;
char *paste;
char *filename;
char statusmsg[80];
time_t statusmsg_time;
@ -87,82 +90,10 @@ struct editorConfig {
struct editorSyntax *syntax;
};
struct editorSyntax {
char *filetype;
char **filematch;
char *singleline_comment_start;
char *multiline_comment_start;
char *multiline_comment_end;
char **keywords;
int flags;
};
struct editorConfig E;
//
// filetypes
// ---------
char *C_HL_extensions[] = {".c", ".h", ".cpp", NULL};
char *C_HL_keywords[] = {
"switch", "if", "while", "for", "break", "return", "else", "continue",
"struct|", "union", "typedef", "static", "enum|", "class", "case|",
"int|", "long|", "double|", "float|", "char|", "unsigned|", "signed|",
"void|", "NULL", NULL
};
char *PY_HL_extensions[] = {".py", ".pyc", NULL};
char *PY_HL_keywords[] = {
"if", "elif", "for", "break", "return", "else",
"def", "", "static", "enum", "class", "with", "assert",
"except", "continue", "while", "finally", "try", "global",
"False|", "True|", "None|", "not|", "and|", "as|", "yield|",
"void|", "or|", "import|", "is|", "in|", "lambda|", "pass|",
"raise|", "del|", NULL
};
char *GO_HL_extensions[] = {".go", NULL};
char *GO_HL_keywords[] = {
"break", "switch", "continue", "func", "interface", "select",
"case", "defer", "go", "map", "struct", "chan", "else", "goto",
"package", "const", "fallthrough|", "if", "range|", "type",
"for", "import", "return", "var", "uint8|", "uint16|", "uint32|",
"uint64", "int|", "uint|", "int8|", "int16|", "int32|", "int64|",
"float32|", "float", "float64|", "complex64|", "complex128|",
"byte|", "rune|", "uintptr|", "string|", "bool|", NULL
};
struct editorSyntax HLDB[] = {
{
"c",
C_HL_extensions,
"//",
"/*",
"*/",
C_HL_keywords,
HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS
},
{
"python",
PY_HL_extensions,
"#",
"'''",
"'''",
PY_HL_keywords,
HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS
},
{
"go",
GO_HL_extensions,
"//",
"/*",
"*/",
GO_HL_keywords,
HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS
}
};
#define HLDB_ENTRIES (sizeof(HLDB) / sizeof(HLDB[0]))
//
// prototypes
@ -594,6 +525,12 @@ void editorInsertNewline() {
E.cx = 0;
}
void editorUpdatePaste(char *str, int len) {
E.paste = realloc(E.paste, len);
memcpy(E.paste, str, len);
E.pastelen = len;
}
//
// file io
// -------
@ -1053,7 +990,7 @@ void editorInputKp(int c) {
switch (c) {
case '\033':
case CTRL_KEY('l'):
if (E.cx == E.row[E.cy].size) editorMoveCursor(ARROW_LEFT);
editorMoveCursor(ARROW_LEFT);
E.mode = CommandMode;
break;
case '\r':
@ -1087,18 +1024,66 @@ void editorCommandKp(int c) {
}
break;
case 'g':
E.cy = 0;
E.cx = 0;
if (deleting) {
int totlen = 0;
int j;
for (j = 0; j <= E.cy; j++)
totlen += E.row[j].size + 1;
char *buf = malloc(totlen);
char *p = buf;
int count = E.cy;
E.cy = 0;
while (count >= 0) {
memcpy(p, E.row[E.cy].chars, E.row[E.cy].size);
p += E.row[E.cy].size;
*p = '\r';
p++;
deleting = 1;
editorCommandKp('d');
count--;
}
editorUpdatePaste(buf, totlen);
} else {
E.cy = 0;
E.cx = 0;
}
break;
case 'G':
if (E.numRows > E.screenRows) {
E.cy = E.numRows - 1;
E.rowoff = E.numRows - E.screenRows - 1;
if (deleting) {
int totlen = 0;
int j;
for (j = E.cy; j <= E.numRows; j++)
totlen += E.row[j].size + 1;
char *buf = malloc(totlen);
char *p = buf;
int count = E.numRows - E.cy - 1;
if (count < 0) count = 0;
while (count >= 0) {
memcpy(p, E.row[E.cy].chars, E.row[E.cy].size);
p += E.row[E.cy].size;
*p = '\r';
p++;
deleting = 1;
editorCommandKp('d');
count--;
}
editorUpdatePaste(buf, totlen);
} else {
E.cy = E.numRows - 1;
if (E.numRows > E.screenRows) {
E.cy = E.numRows - 1;
E.rowoff = E.numRows - E.screenRows - 1;
} else {
E.cy = E.numRows - 1;
}
E.cx = E.row[E.cy].size - 1;
if (E.cx < 0) E.cx = 0;
}
E.cx = E.row[E.cy].size - 1;
if (E.cx < 0) E.cx = 0;
break;
case '\r':
if (counting) {
@ -1113,23 +1098,25 @@ void editorCommandKp(int c) {
}
break;
case 'o':
editorCommandKp('$');
editorCommandKp('i');
deleting = 0;
E.cx = E.row[E.cy].size;
E.mode = InputMode;
editorMoveCursor(ARROW_RIGHT);
editorInsertNewline();
break;
case 'O':
editorCommandKp('^');
E.cx = 0;
editorInsertNewline();
editorMoveCursor(ARROW_UP);
editorCommandKp('i');
E.mode = InputMode;
break;
case 'x':
while (counter > 0) {
editorUpdatePaste(&E.row[E.cy].chars[E.cx], 1);
E.mode = InputMode;
editorMoveCursor(ARROW_RIGHT);
E.mode = CommandMode;
editorDeleteChar();
E.mode = CommandMode;
if (E.cx == E.row[E.cy].size) editorMoveCursor(ARROW_LEFT);
counter--;
}
@ -1144,6 +1131,12 @@ void editorCommandKp(int c) {
deleting++;
return;
} else {
// TODO fix this. There are issues.... :(
char *buf = malloc(E.row[E.cy].size + 1);
int len = snprintf(buf, E.row[E.cy].size, "%s", E.row[E.cy].chars);
buf[len] = '\r';
editorUpdatePaste(buf, len);
free(buf);
while (counter > 0) {
editorDelRow(E.cy);
if (E.cy == E.numRows) E.cy--;
@ -1155,13 +1148,14 @@ void editorCommandKp(int c) {
case '$':
if (deleting) {
int diff = E.row[E.cy].size - E.cx;
editorUpdatePaste(&E.row[E.cy].chars[E.cx], diff);
E.cx = E.row[E.cy].size - 1;
if (E.cx < 0) E.cx = 0;
while (diff > 0) {
E.mode = InputMode;
editorMoveCursor(ARROW_RIGHT);
E.mode = CommandMode;
editorDeleteChar();
E.mode = CommandMode;
if (E.cx == E.row[E.cy].size) editorMoveCursor(ARROW_LEFT);
diff--;
}
@ -1176,6 +1170,7 @@ void editorCommandKp(int c) {
int start_x = E.cx;
int start_y = E.cy;
editorNextWord();
editorUpdatePaste(&E.row[E.cy].chars[start_x], E.cx - start_x);
while (E.cy != start_y || E.cx != start_x) {
editorDeleteChar();
}
@ -1185,6 +1180,30 @@ void editorCommandKp(int c) {
counter--;
}
break;
case 'P':
case 'p':
{
char open = c == 'p' ? 'o' : 'O';
int startx = E.cx;
int multiline = 0;
if (E.paste && E.paste[E.pastelen-1] == '\r') multiline = 1;
if (multiline) {
editorCommandKp(open);
} else {
E.mode = InputMode;
if (open == 'o') editorMoveCursor(ARROW_RIGHT);
}
for (int i = 0; i < E.pastelen; i++) {
editorInputKp(E.paste[i]);
}
if (multiline) {
editorInputKp(DEL_KEY);
E.cx = startx <= E.row[E.cy].size ? startx : E.row[E.cy].size;
}
E.mode = CommandMode;
break;
}
case 'b':
while (counter > 0) {
if (deleting) {
@ -1195,6 +1214,7 @@ void editorCommandKp(int c) {
int end_y = E.cy;
E.cx = start_x;
E.cy = start_y;
editorUpdatePaste(&E.row[E.cy].chars[end_x], start_x - end_x);
while (E.cy != end_y || E.cx != end_x) {
editorDeleteChar();
}
@ -1210,13 +1230,14 @@ void editorCommandKp(int c) {
int start_x = E.cx;
int start_y = E.cy;
editorEndOfWord();
editorUpdatePaste(&E.row[E.cy].chars[start_x], E.cx - start_x);
while (E.cy != start_y || E.cx != start_x) {
editorDeleteChar();
}
E.mode = InputMode;
editorMoveCursor(ARROW_RIGHT);
E.mode = CommandMode;
editorDeleteChar();
E.mode = CommandMode;
if (E.cx == E.row[E.cy].size) editorMoveCursor(ARROW_LEFT);
} else {
editorEndOfWord();
@ -1226,6 +1247,7 @@ void editorCommandKp(int c) {
break;
case '^':
if (deleting) {
editorUpdatePaste(&E.row[E.cy].chars[0], E.cx);
while (E.cx > 0) {
editorDeleteChar();
}
@ -1327,6 +1349,7 @@ void initEditor() {
E.cx = 0;
E.cy = 0;
E.rx = 0;
E.paste = NULL;
E.row = NULL;
E.filename = NULL;
E.syntax = NULL;

78
syntaxhl.h Normal file
View File

@ -0,0 +1,78 @@
#include <stdlib.h>
#define HL_HIGHLIGHT_NUMBERS (1<<0)
#define HL_HIGHLIGHT_STRINGS (1<<1)
struct editorSyntax {
char *filetype;
char **filematch;
char *singleline_comment_start;
char *multiline_comment_start;
char *multiline_comment_end;
char **keywords;
int flags;
};
//
// filetypes
// ---------
char *C_HL_extensions[] = {".c", ".h", ".cpp", NULL};
char *C_HL_keywords[] = {
"switch", "if", "while", "for", "break", "return", "else", "continue",
"struct|", "union", "typedef", "static", "enum|", "class", "case|",
"int|", "long|", "double|", "float|", "char|", "unsigned|", "signed|",
"void|", "NULL", NULL
};
char *PY_HL_extensions[] = {".py", ".pyc", NULL};
char *PY_HL_keywords[] = {
"if", "elif", "for", "break", "return", "else",
"def", "", "static", "enum", "class", "with", "assert",
"except", "continue", "while", "finally", "try", "global",
"False|", "True|", "None|", "not|", "and|", "as|", "yield|",
"void|", "or|", "import|", "is|", "in|", "lambda|", "pass|",
"raise|", "del|", NULL
};
char *GO_HL_extensions[] = {".go", NULL};
char *GO_HL_keywords[] = {
"break", "switch", "continue", "func", "interface", "select",
"case", "defer", "go", "map", "struct", "chan", "else", "goto",
"package", "const", "fallthrough|", "if", "range|", "type",
"for", "import", "return", "var", "uint8|", "uint16|", "uint32|",
"uint64", "int|", "uint|", "int8|", "int16|", "int32|", "int64|",
"float32|", "float", "float64|", "complex64|", "complex128|",
"byte|", "rune|", "uintptr|", "string|", "bool|", NULL
};
static struct editorSyntax HLDB[] = {
{
"c",
C_HL_extensions,
"//",
"/*",
"*/",
C_HL_keywords,
HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS
},
{
"python",
PY_HL_extensions,
"#",
"'''",
"'''",
PY_HL_keywords,
HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS
},
{
"go",
GO_HL_extensions,
"//",
"/*",
"*/",
GO_HL_keywords,
HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS
}
};
#define HLDB_ENTRIES (sizeof(HLDB) / sizeof(HLDB[0]))

7
test.txt Normal file
View File

@ -0,0 +1,7 @@
This is a test
to see if this
will work out
if I keep doing
this same thing
over and over
and over again.