From fb2d22d019ea6a36d46a232a1948c745522320fa Mon Sep 17 00:00:00 2001 From: Brian Evans Date: Fri, 3 Jan 2020 15:56:40 -0800 Subject: [PATCH] Adds readme and more syntaxes to highlight --- README.md | 42 ++++++++++++++++++++ config.h | 2 +- hermes.c | 51 ++++++++++++++---------- syntaxhl.h | 113 ++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 177 insertions(+), 31 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e1acf3f --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# Hermes + +Hermes is a a small text editor (~40k compiled), and is a fork of [kilo](https://github.com/antirez/kilo) by antirez. Hermes takes _kilo_ and modifies the control mechanisms to give a stripped down/lo-fi vi-like experience. This is still a big work in progress but is semi-usable. + +## Requirements + +You will need a C compiler. I believe all of the headers are pretty standard and should be present. I have built this on Debian and on OSX and did not need to install any additional headers/tooling. + +## Configuring + +The file `config.h` allows for configuring a few items: width of tabs, how many times to verify quitting without saving, whether or not to use the alternate terminal screen/buffer, and configuring the colors. + +Additionally, the file `syntaxhl.h` controls the syntax highlighting for programming languages. The format is pretty clear in the file so it should be easy enough to add basic support for languages that I have not provided. + +Both files are commented and should be easily configurable. + +## Status + +Things are buggy as I work through them, but it should be a usable experience. That said, there is no undo buffer... which is rough. The paste buffer is mostly working, so some things can be undone by pasting after deleting. Visual mode is woring... sort of: multiline selections work for deleting, but have issues adding the deleted content (or yanked content as the case may be) to the paste buffer. + +I think the editor in its current state will work fine for its intended purpose: writing gopher phlogs on colorfield.space + +Anything much heavier than that might be problematic. It works pretty well as a file viewer as well though and the code highlighting helps. + +## Reasoning + +I mostly started working on this because my server community needs a more complete text editor than [chalk](https://tildegit.org/sloum/chalk) and I still want to keep most of the userspace limited to programs that users, myself included, made or contributed to. This is my first time writing any decent amount of C code, so has also worked out as a good project to introduce me to more C. I am convinced that the C that I have added to this project is maybe the ugliest code I have ever written, lol. But everyone has to start somewhere, right? Rather than just start with a full version of Kilo, I used [this tutorial](https://viewsourcecode.org/snaptoken/kilo/) to get me started and typed every character by hand. I left out some features and added some of my own in the process. + +## Known issues +- Pasting in from the system clipboard works, but things get kind of weird and unpredictable. Particularly for long lines. +- In general really long lines have some issues +- VisualMode is buggy and cannot yank multiline selections (but can delete them) +- Numerical multipliers work (ie. `10dw` would delete the next ten words), but there are issues dealing with the paste buffer and only the last deleted item will be added to the buffer, rather than the whole group of them +- Will not create a file when passed a filepath that does not exist. Instead, call without arguments and then save the file as whatever you want +- Only supports ascii, NO UNICODE support whatsoever + +Try things out to see what works. Save often when you know things are in a good state. + +## License + +This project uses the same license as kilo (BSD 2-clause). If you modify or distribute it please be sure to do so with the included LICENSE file which credits antirez for kilo and myself for the modifications I have made, and describes the terms of the license. + diff --git a/config.h b/config.h index 7ef9c31..2e8cb06 100644 --- a/config.h +++ b/config.h @@ -10,7 +10,7 @@ static const int tabwidth = 4; // Enable use of the "alternate screen" in the terminal -static const int use_alternate_screen = 1; // use as bool +static const int use_alternate_screen = 1; // use as bool (0 or 1) /* * Values from 1 to 256 representing 256 color/8-bit pallate diff --git a/hermes.c b/hermes.c index 7e34f4c..48310f4 100644 --- a/hermes.c +++ b/hermes.c @@ -896,27 +896,6 @@ void editorNextWord() { } } -void editorDeleteSelection() { - int sx = E.cx; - int sy = E.cy; - int ex = E.vx; - int ey = E.vy; - if (E.cy < E.vy || (E.cx < E.vx && E.cy == E.vy)) { - sx = E.vx; - sy = E.vy; - ex = E.cx; - ey = E.cy; - E.cx = sx; - E.cy = sy; - } - - if (sx < E.row[sy].size) - E.cx++; - while (E.cx != ex || E.cy != ey) { - editorDeleteChar(); - } -} - void editorEndOfWord() { int x = E.cx; int y = E.cy; @@ -962,6 +941,28 @@ void editorCopySelection() { // TODO multiline copy... been having problems } +void editorDeleteSelection() { + editorCopySelection(); + int sx = E.cx; + int sy = E.cy; + int ex = E.vx; + int ey = E.vy; + if (E.cy < E.vy || (E.cx < E.vx && E.cy == E.vy)) { + sx = E.vx; + sy = E.vy; + ex = E.cx; + ey = E.cy; + E.cx = sx; + E.cy = sy; + } + + if (sx < E.row[sy].size) + E.cx++; + while (E.cx != ex || E.cy != ey) { + editorDeleteChar(); + } +} + // // input // ----- @@ -1361,6 +1362,14 @@ void editorCommandKp(int c) { E.mode = VisualMode; } break; + case 'V': + if (E.mode == CommandMode) { + E.vx = 0; + E.vy = E.cy; + E.cx = E.row[E.cy].size - 1; + E.mode = VisualMode; + } + break; case 'y': if (E.mode == VisualMode) { editorCopySelection(); diff --git a/syntaxhl.h b/syntaxhl.h index ebf61d6..eb0d913 100644 --- a/syntaxhl.h +++ b/syntaxhl.h @@ -16,7 +16,25 @@ struct editorSyntax { // // filetypes // --------- +// To create highlighting for a language do the following: + +// 1. Create a list of file extensions this will apply to. +// Name the variable after the language: (ex. *LUA_HL_Extensions) +// The list MUST end in NULL (see examples below) char *C_HL_extensions[] = {".c", ".h", ".cpp", NULL}; +char *PY_HL_extensions[] = {".py", ".pyc", NULL}; +char *GO_HL_extensions[] = {".go", NULL}; +char *SH_HL_extensions[] = {".sh", NULL}; +char *HTML_HL_extensions[] = {".html", ".html", NULL}; +char *PHP_HL_extensions[] = {".php", NULL}; +char *LUA_HL_extensions[] = {".lua", NULL}; + + +// 2. Create a list of keywords. Keywords that end in "|" will be given +// a secondary highlight color and words without them will be given the +// primary highlight color. Like in step 1, the list MUST end in NULL + +// C char *C_HL_keywords[] = { "switch", "if", "while", "for", "break", "return", "else", "continue", "struct|", "union", "typedef", "static", "enum|", "class", "case|", @@ -24,7 +42,7 @@ char *C_HL_keywords[] = { "void|", "NULL", NULL }; -char *PY_HL_extensions[] = {".py", ".pyc", NULL}; +// Python char *PY_HL_keywords[] = { "if", "elif", "for", "break", "return", "else", "def", "", "static", "enum", "class", "with", "assert", @@ -34,7 +52,7 @@ char *PY_HL_keywords[] = { "raise|", "del|", NULL }; -char *GO_HL_extensions[] = {".go", NULL}; +// Go char *GO_HL_keywords[] = { "break", "switch", "continue", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", @@ -45,15 +63,56 @@ char *GO_HL_keywords[] = { "byte|", "rune|", "uintptr|", "string|", "bool|", NULL }; +// Shell +char *SH_HL_keywords[] = { + "echo|", "readonly|", "if", "fi", "read", "set", "unset", "shift", + "export", "else", "while", "do|", "done|", "for", "until", "case", + "esac", "break|", "continue|", "exit", "return", "trap|", "wait|", + "eval|", "exec|", "ulimit|", "umask|", NULL +} + +// HTML +char *HTML_HL_keywords[] = { + "html", "body", "br", "hr", "p", "blockquote", "title", "head", "header", + "nav", "a", "div", "section", "footer", "main", "button", "ul", "li", + "form", "input", "class|", "id|", "href|", "img", "src|", "target|", + "style|", "meta", "h1", "h2", "h3", "h4", "h5", "role|", "!DOCTYPE|", + "script", "type|", "link", "rel|", NULL +} + +// PHP +char *PHP_HL_keywords[] = { + "abstract|", "and|", "array|", "as|", "break|", "callable|", "case|", + "catch", "class", "clone|", "const|", "continue|", "declare|", "default|", + "die", "do|", "echo|", "else", "elseif", "empty|", "enddeclare|", "endfor", + "endforeach", "endif", "endswitch", "endwhile", "eval|", "exit|", "extends|", + "final|", "finally", "for", "foreach", "function", "global", "goto", "if", + "implements|", "include", "include_once", "instanceof|", "insteadof|", "interface", + "isset|", "list|", "namespace", "new|", "or|", "print|", "private|", "protected|", + "public|", "require", "require_once", "return", "static|", "switch", "throw", + "trait|", "try", "unset|", "use|", "var|", "while", "xor|", "yield", NULL +} + +// Lua +char *LUA_HL_keywords[] = { + "function", "return", "for", "while", "do", "if", "else", "elseif", + "and|", "or|", "false|", "true|", "nil|", "until", "then|", "repeat|", + "local|", "not|", "in|", "break|", NULL +} + static struct editorSyntax HLDB[] = { +// 3. Add an entry to the editorSyndax db (this var). +// See the C example comments for what each array member +// does... { - "c", - C_HL_extensions, - "//", - "/*", - "*/", - C_HL_keywords, - HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS + "c", // The name of the language, this will be displayed in the status bar + C_HL_extensions, // the variable name created in step 1 + "//", // Text representing the beginning of a single line comment, NULL if not wanted + "/*", // Text representing the start of a multiline comment, NULL if not wanted + "*/", // Text representing the end of a multiline comment, NULL if not wanted + C_HL_keywords, // the variable name created in step 2 + HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS // This controls whether or not to highlight numbers and strings + // can be NULL, both (as seen here) or just one of them (without the pipe) }, { "python", @@ -72,6 +131,42 @@ static struct editorSyntax HLDB[] = { "*/", GO_HL_keywords, HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS + }, + { + "shell", + SH_HL_extensions, + "#", + NULL, + NULL, + SH_HL_keywords, + HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS + }, + { + "html", + HTML_HL_extensions, + NULL, + "", + HTML_HL_keywords, + NULL + }, + { + "php", + PHP_HL_extensions, + "//", + "/*", + "*/", + PHP_HL_keywords, + HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS + }, + { + "lua", + LUA_HL_extensions, + "--", + "--[[", + "]]", + LUA_HL_keywords, + HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS } };