Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e345b55595 | |||
| d1978a3b98 | |||
| 5ee8234ab7 | |||
| f82d1f8831 | |||
| 2019ec10ce | |||
| 0110f82705 | |||
| a62a8e50fa | |||
| 33e19e7d76 | |||
| fd01e3593f | |||
| 47bbc5339c | |||
| 2962a6c92e | |||
| 7fa887273b | |||
| fb02f37512 | |||
| 1722dbee0b |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
*.log
|
||||
build
|
||||
ke
|
||||
*.txt
|
||||
@@ -2,15 +2,29 @@ cmake_minimum_required(VERSION 3.15)
|
||||
project(ke C) # Specify C language explicitly
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(KE_VERSION "1.0.10")
|
||||
set(KE_VERSION "1.1.1")
|
||||
|
||||
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} -fsanitize=address -fno-omit-frame-pointer")
|
||||
|
||||
# Optionally enable AddressSanitizer (ASan)
|
||||
option(ENABLE_ASAN "Enable AddressSanitizer for builds" OFF)
|
||||
|
||||
if (ENABLE_ASAN)
|
||||
message(STATUS "ASan enabled")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
# Ensure the sanitizer is linked too (especially important on some platforms)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Add executable
|
||||
add_executable(ke main.c)
|
||||
|
||||
# Define KE_VERSION for use in C code (e.g., #define KE_VERSION)
|
||||
target_compile_definitions(ke PRIVATE KE_VERSION="ke version ${KE_VERSION}")
|
||||
install(TARGETS ke RUNTIME DESTINATION bin)
|
||||
install(FILES ke.1 TYPE MAN)
|
||||
|
||||
install(TARGETS ke RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES ke.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
|
||||
|
||||
21
Makefile
Normal file
21
Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
TARGET := ke
|
||||
KE_VERSION := devel
|
||||
|
||||
|
||||
CFLAGS := -Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g
|
||||
CFLAGS += -D_DEFAULT_SOURCE -D_XOPEN_SOURCE
|
||||
CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
||||
|
||||
LDFLAGS := -fsanitize=address
|
||||
|
||||
all: $(TARGET) test.txt
|
||||
|
||||
$(TARGET): main.c
|
||||
$(CC) $(CFLAGS) -o $(TARGET) $(LDFLAGS) main.c
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
|
||||
.PHONY: test.txt
|
||||
test.txt:
|
||||
cp test.txt.bak $@
|
||||
@@ -11,4 +11,8 @@ It should be available via homebrew, even:
|
||||
brew tap kisom/homebrew-tap
|
||||
brew install ke
|
||||
|
||||
Released under an ISC license.
|
||||
To get verbose ASAN messages:
|
||||
|
||||
export LSAN_OPTIONS=verbosity=1:log_threads=1
|
||||
|
||||
Released under an ISC license.
|
||||
|
||||
2
ke.1
2
ke.1
@@ -42,7 +42,7 @@ exit the editor. Also C-k C-q.
|
||||
save the file, prompting for a filename if needed. Also C-k C-s.
|
||||
.It C-k x
|
||||
save the file and exit. Also C-k C-x.
|
||||
.It C-k \
|
||||
.It C-k \[char92]
|
||||
Dump core.
|
||||
.El
|
||||
.Sh FIND
|
||||
|
||||
155
main.c
155
main.c
@@ -122,6 +122,11 @@ void editor_set_status(const char *fmt, ...);
|
||||
void die(const char *s);
|
||||
int get_winsz(int *rows, int *cols);
|
||||
void goto_line(void);
|
||||
int cursor_at_eol(void);
|
||||
void find_next_word(void);
|
||||
void delete_next_word(void);
|
||||
void find_prev_word(void);
|
||||
void delete_prev_word(void);
|
||||
void delete_row(int at);
|
||||
void row_append_row(struct erow *row, char *s, int len);
|
||||
void row_insert_ch(struct erow *row, int at, int16_t c);
|
||||
@@ -364,7 +369,7 @@ erow_update(struct erow *row)
|
||||
}
|
||||
}
|
||||
|
||||
if (row->rsize) {
|
||||
if (row->rsize || row->render != NULL) {
|
||||
free(row->render);
|
||||
row->rsize = 0;
|
||||
}
|
||||
@@ -463,6 +468,7 @@ die(const char *s)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* get_winsz uses the TIOCGWINSZ to get the window size.
|
||||
*
|
||||
@@ -508,6 +514,121 @@ goto_line(void)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cursor_at_eol(void)
|
||||
{
|
||||
assert(editor.curx >= 0);
|
||||
assert(editor.cury >= 0);
|
||||
assert(editor.cury <= editor.nrows);
|
||||
assert(editor.curx <= editor.row[editor.cury].size);
|
||||
|
||||
return editor.curx == editor.row[editor.cury].size;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
find_next_word(void)
|
||||
{
|
||||
while (cursor_at_eol()) {
|
||||
move_cursor(ARROW_RIGHT);
|
||||
}
|
||||
|
||||
if (isalnum(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (!isspace(editor.row[editor.cury].line[editor.curx]) && !cursor_at_eol()) {
|
||||
move_cursor(ARROW_RIGHT);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
move_cursor(ARROW_RIGHT);
|
||||
}
|
||||
|
||||
find_next_word();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
delete_next_word(void)
|
||||
{
|
||||
while (cursor_at_eol()) {
|
||||
move_cursor(ARROW_RIGHT);
|
||||
deletech();
|
||||
}
|
||||
|
||||
if (isalnum(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (!isspace(editor.row[editor.cury].line[editor.curx]) && !cursor_at_eol()) {
|
||||
move_cursor(ARROW_RIGHT);
|
||||
deletech();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
move_cursor(ARROW_RIGHT);
|
||||
deletech();
|
||||
}
|
||||
|
||||
delete_next_word();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
find_prev_word(void)
|
||||
{
|
||||
if (editor.cury == 0 && editor.curx == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
move_cursor(ARROW_LEFT);
|
||||
|
||||
while (cursor_at_eol() || isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
if (editor.cury == 0 && editor.curx == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
move_cursor(ARROW_LEFT);
|
||||
}
|
||||
|
||||
while (editor.curx > 0 && !isspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||
move_cursor(ARROW_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
delete_prev_word(void)
|
||||
{
|
||||
if (editor.cury == 0 && editor.curx == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
deletech();
|
||||
|
||||
while (editor.cury > 0 || editor.curx > 0) {
|
||||
if (editor.curx == 0) {
|
||||
deletech();
|
||||
} else {
|
||||
if (!isspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||
break;
|
||||
}
|
||||
deletech();
|
||||
}
|
||||
}
|
||||
|
||||
while (editor.curx > 0) {
|
||||
if (isspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||
break;
|
||||
}
|
||||
deletech();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
delete_row(int at)
|
||||
{
|
||||
@@ -588,6 +709,9 @@ insertch(int16_t c)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* deletech
|
||||
*/
|
||||
void
|
||||
deletech(void)
|
||||
{
|
||||
@@ -985,7 +1109,7 @@ void
|
||||
move_cursor(int16_t c)
|
||||
{
|
||||
struct erow *row;
|
||||
int reps;
|
||||
int reps;
|
||||
|
||||
row = (editor.cury >= editor.nrows) ? NULL : &editor.row[editor.cury];
|
||||
|
||||
@@ -1109,9 +1233,15 @@ process_kcommand(int16_t c)
|
||||
delete_row(editor.cury);
|
||||
break;
|
||||
case 'd':
|
||||
if (editor.curx == 0 && cursor_at_eol()) {
|
||||
delete_row(editor.cury);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((editor.row[editor.cury].size - editor.curx) > 0) {
|
||||
process_normal(DEL_KEY);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'g':
|
||||
case CTRL_KEY('g'):
|
||||
@@ -1195,8 +1325,6 @@ process_normal(int16_t c)
|
||||
void
|
||||
process_escape(int16_t c)
|
||||
{
|
||||
struct erow *row = &editor.row[editor.cury];
|
||||
|
||||
editor_set_status("hi");
|
||||
|
||||
switch (c) {
|
||||
@@ -1208,16 +1336,17 @@ process_escape(int16_t c)
|
||||
editor.cury = 0;
|
||||
editor.curx = 0;
|
||||
break;
|
||||
case 'b':
|
||||
find_prev_word();
|
||||
break;
|
||||
case 'd':
|
||||
delete_next_word();
|
||||
break;
|
||||
case 'f':
|
||||
find_next_word();
|
||||
break;
|
||||
case BACKSPACE:
|
||||
if (isalnum(row->line[editor.curx])) {
|
||||
editor_set_status("is alnum");
|
||||
while (editor.curx > 0 && isalnum(row->line[editor.curx])) {
|
||||
process_normal(BACKSPACE);
|
||||
}
|
||||
} else {
|
||||
editor_set_status("not alnum");
|
||||
process_normal(BACKSPACE);
|
||||
}
|
||||
delete_prev_word();
|
||||
break;
|
||||
default:
|
||||
editor_set_status("unknown ESC key: %04x", c);
|
||||
|
||||
15
test.txt.bak
Normal file
15
test.txt.bak
Normal file
@@ -0,0 +1,15 @@
|
||||
hello
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
world it is me
|
||||
but I am not me
|
||||
Reference in New Issue
Block a user