5 Commits

Author SHA1 Message Date
36013e42e4 version bump
Some checks are pending
Release / Bump Homebrew formula (push) Waiting to run
2025-11-22 12:13:56 -08:00
dd667c1ef5 revert back to older version with some previous fixes
the ai was getting wild
2025-11-22 12:13:03 -08:00
c9977b0fc0 checkpoint
Some checks are pending
Release / Bump Homebrew formula (push) Waiting to run
2025-11-22 12:00:50 -08:00
dd2c888766 update man page
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
2025-11-22 01:48:31 -08:00
2967998893 Update README
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
2025-11-22 01:45:59 -08:00
4 changed files with 51 additions and 112 deletions

View File

@@ -2,10 +2,11 @@ cmake_minimum_required(VERSION 3.15)
project(ke C) # Specify C language explicitly project(ke C) # Specify C language explicitly
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
set(KE_VERSION "1.0.4") set(KE_VERSION "1.0.8")
set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g") set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -D_XOPEN_SOURCE") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -D_XOPEN_SOURCE")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
# Add executable # Add executable

View File

@@ -6,6 +6,9 @@ used fairly often.
See the man page for more info. See the man page for more info.
It should be available via homebrew, even. It should be available via homebrew, even:
brew tap kisom/homebrew-tap
brew install ke
Released under an ISC license. Released under an ISC license.

2
ke.1
View File

@@ -24,8 +24,6 @@ saving a file can be done with either C-k s or C-k C-s.
.Bl -tag -width xxxxxxxxxxxx -offset indent .Bl -tag -width xxxxxxxxxxxx -offset indent
.It C-k BACKSPACE .It C-k BACKSPACE
Delete from the cursor to the beginning of the line. Delete from the cursor to the beginning of the line.
.It C-k C-d
Delete the current row.
.It C-k d .It C-k d
Delete from the cursor to the end of the line. Delete from the cursor to the end of the line.
.It C-k e .It C-k e

139
main.c
View File

@@ -14,7 +14,6 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@@ -25,6 +24,10 @@
#include <unistd.h> #include <unistd.h>
#ifndef KE_VERSION
#define KE_VERSION "ke dev build"
#endif
#define ESCSEQ "\x1b[" #define ESCSEQ "\x1b["
#define CTRL_KEY(key) ((key)&0x1f) #define CTRL_KEY(key) ((key)&0x1f)
#define TAB_STOP 8 #define TAB_STOP 8
@@ -44,33 +47,35 @@
#define TAB_STOP 8 #define TAB_STOP 8
#define INITIAL_BUFSIZE 64 #define INITIAL_CAPACITY 64
int int
next_power_of_2(int n) next_power_of_2(int n)
{ {
if (n < 2) {
n = 2;
}
n--; n--;
n |= n >> 1; n |= n >> 1;
n |= n >> 2; n |= n >> 2;
n |= n >> 4; n |= n >> 4;
n |= n >> 8; n |= n >> 8;
n |= n >> 16; n |= n >> 16;
return n + 1; return n + 1;
} }
/*
* cap_growth is a generalized strategy to growing buffers.
*/
int int
cap_growth(int cap, int sz) cap_growth(int cap, int sz)
{ {
if (cap == 0) { if (cap == 0) {
return INITIAL_BUFSIZE; cap = INITIAL_CAPACITY;
} }
while (sz < cap) { while (cap <= sz) {
cap = next_power_of_2(cap); cap = next_power_of_2(cap + 1);
} }
return cap; return cap;
@@ -107,8 +112,8 @@ struct erow {
char nibble_to_hex(char c); char nibble_to_hex(char c);
int erow_render_to_cursor(struct erow *row, int cx); int erow_render_to_cursor(struct erow *row, int cx);
int erow_cursor_to_render(struct erow *row, int rx); int erow_cursor_to_render(struct erow *row, int rx);
int erow_init(struct erow *row, int len);
void erow_update(struct erow *row); void erow_update(struct erow *row);
int erow_init(struct erow *row, int len);
void erow_insert(int at, char *s, int len); void erow_insert(int at, char *s, int len);
void erow_free(struct erow *row); void erow_free(struct erow *row);
void editor_set_status(const char *fmt, ...); void editor_set_status(const char *fmt, ...);
@@ -137,7 +142,6 @@ void move_cursor(int16_t c);
void newline(void); void newline(void);
void process_kcommand(int16_t c); void process_kcommand(int16_t c);
void process_normal(int16_t c); void process_normal(int16_t c);
void navonly_escape(int16_t c);
void process_escape(int16_t c); void process_escape(int16_t c);
int process_keypress(void); int process_keypress(void);
void enable_termraw(void); void enable_termraw(void);
@@ -216,7 +220,7 @@ init_editor(void)
editor.rows = 0; editor.rows = 0;
if (get_winsz(&editor.rows, &editor.cols) == -1) { if (get_winsz(&editor.rows, &editor.cols) == -1) {
// die("can't get window size - is this an interactive terminal?"); die("can't get window size");
} }
editor.rows--; /* status bar */ editor.rows--; /* status bar */
editor.rows--; /* message line */ editor.rows--; /* message line */
@@ -237,8 +241,7 @@ init_editor(void)
/* /*
* reset_editor presumes that editor has been initialized. That is, * reset_editor presumes that editor has been initialized.
* before reset_editor is called, init_editor should be called.
*/ */
void void
reset_editor(void) reset_editor(void)
@@ -260,37 +263,24 @@ reset_editor(void)
void void
ab_append(struct abuf *buf, const char *s, int len) ab_append(struct abuf *buf, const char *s, int len)
{ {
const int delta = (len < 0) ? 0 : len;
char *nc = buf->b; char *nc = buf->b;
int sz; int sz = buf->len + len;
assert((delta >= 0 && buf->len < INT_MAX - delta)); if (sz >= buf->cap) {
sz = buf->len + delta; while (sz > buf->cap) {
if (sz > buf->cap) {
if (buf->cap == 0) { if (buf->cap == 0) {
buf->cap = 64; buf->cap = 1;
} } else {
while (sz < buf->cap) {
if (buf->cap > INT_MAX/2) {
buf->cap = INT_MAX;
break;
}
buf->cap *= 2; buf->cap *= 2;
} }
}
assert(sz <= buf->cap);
nc = realloc(nc, buf->cap); nc = realloc(nc, buf->cap);
assert(nc != NULL); assert(nc != NULL);
} }
if (delta > 0) { memcpy(&nc[buf->len], s, len);
memcpy(&nc[buf->len], s, (size_t)delta);
buf->b = nc; buf->b = nc;
buf->len += delta; buf->len += len; /* DANGER: overflow */
}
} }
@@ -461,14 +451,14 @@ erow_free(struct erow *row)
void void
die(const char *s) die(const char *s)
{ {
/*
* NOTE(kyle): this is a duplication of the code in display.c
* but I would like to be able to import these files from there.
*/
write(STDOUT_FILENO, "\x1b[2J", 4); write(STDOUT_FILENO, "\x1b[2J", 4);
write(STDOUT_FILENO, "\x1b[H", 3); write(STDOUT_FILENO, "\x1b[H", 3);
if (errno != 0) {
perror(s); perror(s);
} else {
fprintf(stderr, "%s\n", s);
}
exit(1); exit(1);
} }
@@ -549,9 +539,6 @@ row_append_row(struct erow *row, char *s, int len)
void void
row_insert_ch(struct erow *row, int at, int16_t c) row_insert_ch(struct erow *row, int at, int16_t c)
{ {
int ncap = 0;
char *nline = NULL;
/* /*
* row_insert_ch just concerns itself with how to update a row. * row_insert_ch just concerns itself with how to update a row.
*/ */
@@ -560,19 +547,6 @@ row_insert_ch(struct erow *row, int at, int16_t c)
} }
assert(c > 0); assert(c > 0);
if (row->size == row->cap) {
ncap = cap_growth(row->cap, row->size+1);
nline = realloc(row->line, ncap);
assert(nline != NULL);
if (nline == NULL) {
return;
}
row->cap = ncap;
row->line = nline;
}
row->line = realloc(row->line, row->size+2); row->line = realloc(row->line, row->size+2);
assert(row->line != NULL); assert(row->line != NULL);
memmove(&row->line[at+1], &row->line[at], row->size - at + 1); memmove(&row->line[at+1], &row->line[at], row->size - at + 1);
@@ -697,14 +671,9 @@ rows_to_buffer(int *buflen)
} }
if (len == 0) { if (len == 0) {
if (buflen != NULL) {
*buflen = 0;
}
return NULL; return NULL;
} }
assert(buflen != NULL);
*buflen = len; *buflen = len;
buf = malloc(len); buf = malloc(len);
assert(buf != NULL); assert(buf != NULL);
@@ -762,7 +731,7 @@ save_file(void)
status = 0; status = 0;
save_exit: save_exit:
if (fd != -1) close(fd); if (fd) close(fd);
if (buf) { if (buf) {
free(buf); free(buf);
buf = NULL; buf = NULL;
@@ -1008,11 +977,7 @@ editor_openfile(void)
return; return;
} }
/* open_file() will handle freeing the previous file/buffer state
* via reset_editor() and will strdup() the filename internally. */
open_file(filename); open_file(filename);
free(filename);
} }
@@ -1230,25 +1195,7 @@ process_normal(int16_t c)
void void
process_escape(int16_t c) process_escape(int16_t c)
{ {
struct erow *row = NULL; struct erow *row = &editor.row[editor.cury];
/* if there are no rows, there's nothing to do */
if (editor.nrows <= 0) {
return;
}
if (editor.cury <0) {
editor.cury = 0;
} else if (editor.cury >= editor.nrows) {
editor.cury = editor.nrows - 1;
}
row = &editor.row[editor.cury];
if (editor.curx < 0) {
editor.curx = 0;
} else if (editor.curx > row->size) {
editor.curx = row->size;
}
editor_set_status("hi"); editor_set_status("hi");
@@ -1262,12 +1209,7 @@ process_escape(int16_t c)
editor.curx = 0; editor.curx = 0;
break; break;
case BACKSPACE: case BACKSPACE:
row = &editor.row[editor.cury]; /* cury may have changed */ if (isalnum(row->line[editor.curx])) {
if (editor.curx == 0 || editor.curx < row->size) {
break;
}
if ((unsigned char)isalnum(row->line[editor.curx])) {
editor_set_status("is alnum"); editor_set_status("is alnum");
while (editor.curx > 0 && isalnum(row->line[editor.curx])) { while (editor.curx > 0 && isalnum(row->line[editor.curx])) {
process_normal(BACKSPACE); process_normal(BACKSPACE);
@@ -1396,8 +1338,7 @@ draw_rows(struct abuf *ab)
{ {
assert(editor.cols >= 0); assert(editor.cols >= 0);
int cols = editor.cols > 0 ? editor.cols : 1; char buf[editor.cols];
char buf[cols];
int buflen, filerow, padding; int buflen, filerow, padding;
int y; int y;
@@ -1420,6 +1361,7 @@ draw_rows(struct abuf *ab)
ab_append(ab, "|", 1); ab_append(ab, "|", 1);
} }
} else { } else {
erow_update(&editor.row[filerow]);
buflen = editor.row[filerow].rsize - editor.coloffs; buflen = editor.row[filerow].rsize - editor.coloffs;
if (buflen < 0) { if (buflen < 0) {
buflen = 0; buflen = 0;
@@ -1428,7 +1370,6 @@ draw_rows(struct abuf *ab)
if (buflen > editor.cols) { if (buflen > editor.cols) {
buflen = editor.cols; buflen = editor.cols;
} }
ab_append(ab, editor.row[filerow].render+editor.coloffs, ab_append(ab, editor.row[filerow].render+editor.coloffs,
buflen); buflen);
} }
@@ -1571,10 +1512,10 @@ editor_set_status(const char *fmt, ...)
void void
loop(void) loop(void)
{ {
display_refresh(); int up = 1; /* update on the first runthrough */
while (1) { while (1) {
int update = 0; if (up) display_refresh();
/* /*
* ke should only refresh the display if it has received keyboard * ke should only refresh the display if it has received keyboard
@@ -1582,12 +1523,8 @@ loop(void)
* handling pastes without massive screen flicker. * handling pastes without massive screen flicker.
* *
*/ */
while (process_keypress()) { if ((up = process_keypress()) != 0) {
update = 1; while (process_keypress()) ;
}
if (update) {
display_refresh();
} }
} }
} }