Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0110f82705 | |||
| a62a8e50fa | |||
| 33e19e7d76 | |||
| fd01e3593f | |||
| 47bbc5339c | |||
| 2962a6c92e | |||
| 7fa887273b | |||
| fb02f37512 | |||
| 1722dbee0b | |||
| 14199afeb5 | |||
| 9f3558c430 | |||
| ce64e4637d | |||
| 36013e42e4 | |||
| dd667c1ef5 | |||
| c9977b0fc0 | |||
| dd2c888766 | |||
| 2967998893 | |||
| a400cdf5ad | |||
| c8a43fb328 | |||
| 3ea7c31cba | |||
| 115091e517 | |||
| 1b9b618e3a | |||
| 527759de09 |
37
.github/workflows/release.yml
vendored
Normal file
37
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
homebrew:
|
||||||
|
name: Bump Homebrew formula
|
||||||
|
# Skip this job in case of git pushes to prerelease tags
|
||||||
|
if: ${{ github.event_name != 'push' || !contains(github.ref, '-') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Extract version
|
||||||
|
id: extract-version
|
||||||
|
run: |
|
||||||
|
echo "tag-name=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- uses: mislav/bump-homebrew-formula-action@v3
|
||||||
|
with:
|
||||||
|
formula-name: ke
|
||||||
|
formula-path: Formula/ke.rb
|
||||||
|
homebrew-tap: kisom/homebrew-tap
|
||||||
|
base-branch: master
|
||||||
|
commit-message: |
|
||||||
|
{{formulaName}} {{version}}
|
||||||
|
|
||||||
|
Created by https://github.com/mislav/bump-homebrew-formula-action
|
||||||
|
env:
|
||||||
|
COMMITTER_TOKEN: ${{ secrets.GH_CPAT }}
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.log
|
||||||
|
build
|
||||||
@@ -2,20 +2,29 @@ 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.0")
|
set(KE_VERSION "1.1.0")
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
|
# 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
|
||||||
add_executable(ke main.c)
|
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}")
|
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)
|
||||||
|
|
||||||
# Set output properties
|
|
||||||
set_target_properties(ke PROPERTIES
|
|
||||||
FOLDER bin
|
|
||||||
RUNTIME_OUTPUT_DIRECTORY bin
|
|
||||||
)
|
|
||||||
17
Makefile
Normal file
17
Makefile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
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)
|
||||||
|
|
||||||
|
$(TARGET): main.c
|
||||||
|
$(CC) $(CFLAGS) -o $(TARGET) $(LDFLAGS) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET)
|
||||||
@@ -6,4 +6,13 @@ used fairly often.
|
|||||||
|
|
||||||
See the man page for more info.
|
See the man page for more info.
|
||||||
|
|
||||||
|
It should be available via homebrew, even:
|
||||||
|
|
||||||
|
brew tap kisom/homebrew-tap
|
||||||
|
brew install ke
|
||||||
|
|
||||||
|
To get verbose ASAN messages:
|
||||||
|
|
||||||
|
export LSAN_OPTIONS=verbosity=1:log_threads=1
|
||||||
|
|
||||||
Released under an ISC license.
|
Released under an ISC license.
|
||||||
4
ke.1
4
ke.1
@@ -24,10 +24,10 @@ 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 C-d
|
||||||
|
Delete the entire link.
|
||||||
.It C-k e
|
.It C-k e
|
||||||
Edit a new file. Also C-k C-e.
|
Edit a new file. Also C-k C-e.
|
||||||
.It C-k f
|
.It C-k f
|
||||||
|
|||||||
286
main.c
286
main.c
@@ -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,6 +47,41 @@
|
|||||||
#define TAB_STOP 8
|
#define TAB_STOP 8
|
||||||
|
|
||||||
|
|
||||||
|
#define INITIAL_CAPACITY 64
|
||||||
|
|
||||||
|
int
|
||||||
|
next_power_of_2(int n)
|
||||||
|
{
|
||||||
|
if (n < 2) {
|
||||||
|
n = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
n--;
|
||||||
|
n |= n >> 1;
|
||||||
|
n |= n >> 2;
|
||||||
|
n |= n >> 4;
|
||||||
|
n |= n >> 8;
|
||||||
|
n |= n >> 16;
|
||||||
|
|
||||||
|
return n + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
cap_growth(int cap, int sz)
|
||||||
|
{
|
||||||
|
if (cap == 0) {
|
||||||
|
cap = INITIAL_CAPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cap <= sz) {
|
||||||
|
cap = next_power_of_2(cap + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function and struct declarations.
|
* Function and struct declarations.
|
||||||
*/
|
*/
|
||||||
@@ -67,21 +105,29 @@ struct erow {
|
|||||||
|
|
||||||
int size;
|
int size;
|
||||||
int rsize;
|
int rsize;
|
||||||
|
|
||||||
|
int cap;
|
||||||
};
|
};
|
||||||
|
|
||||||
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, ...);
|
||||||
|
|
||||||
/* miscellaneous */
|
/* miscellaneous */
|
||||||
void die(const char *s);
|
void die(const char *s);
|
||||||
|
int iswspace(const char c);
|
||||||
int get_winsz(int *rows, int *cols);
|
int get_winsz(int *rows, int *cols);
|
||||||
void goto_line(void);
|
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 delete_row(int at);
|
||||||
void row_append_row(struct erow *row, char *s, int len);
|
void row_append_row(struct erow *row, char *s, int len);
|
||||||
void row_insert_ch(struct erow *row, int at, int16_t c);
|
void row_insert_ch(struct erow *row, int at, int16_t c);
|
||||||
@@ -102,7 +148,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);
|
||||||
@@ -181,7 +226,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 */
|
||||||
@@ -202,8 +247,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)
|
||||||
@@ -225,37 +269,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 = buf->len + len;
|
||||||
int sz;
|
|
||||||
|
|
||||||
assert((delta >= 0 && buf->len < INT_MAX - delta));
|
|
||||||
sz = buf->len + delta;
|
|
||||||
|
|
||||||
if (sz >= buf->cap) {
|
if (sz >= buf->cap) {
|
||||||
if (buf->cap == 0) {
|
|
||||||
buf->cap = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (sz > buf->cap) {
|
while (sz > buf->cap) {
|
||||||
if (buf->cap < INT_MAX/2) {
|
if (buf->cap == 0) {
|
||||||
buf->cap *= INT_MAX;
|
buf->cap = 1;
|
||||||
break;
|
} else {
|
||||||
|
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 += len; /* DANGER: overflow */
|
||||||
buf->len += delta;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -339,7 +370,7 @@ erow_update(struct erow *row)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row->rsize) {
|
if (row->rsize || row->render != NULL) {
|
||||||
free(row->render);
|
free(row->render);
|
||||||
row->rsize = 0;
|
row->rsize = 0;
|
||||||
}
|
}
|
||||||
@@ -373,8 +404,9 @@ erow_init(struct erow *row, int len)
|
|||||||
row->rsize = 0;
|
row->rsize = 0;
|
||||||
row->render = NULL;
|
row->render = NULL;
|
||||||
row->line = NULL;
|
row->line = NULL;
|
||||||
|
row->cap = cap_growth(0, len);
|
||||||
|
|
||||||
row->line = malloc(len+1);
|
row->line = malloc(row->cap);
|
||||||
assert(row->line != NULL);
|
assert(row->line != NULL);
|
||||||
if (row->line == NULL) {
|
if (row->line == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -425,18 +457,24 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
iswspace(const char c)
|
||||||
|
{
|
||||||
|
return isspace(c) || c == '\t';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_winsz uses the TIOCGWINSZ to get the window size.
|
* get_winsz uses the TIOCGWINSZ to get the window size.
|
||||||
*
|
*
|
||||||
@@ -482,6 +520,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 (!iswspace(editor.row[editor.cury].line[editor.curx]) && !cursor_at_eol()) {
|
||||||
|
move_cursor(ARROW_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iswspace(editor.row[editor.cury].line[editor.curx])) {
|
||||||
|
while (iswspace(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 (!iswspace(editor.row[editor.cury].line[editor.curx]) && !cursor_at_eol()) {
|
||||||
|
move_cursor(ARROW_RIGHT);
|
||||||
|
deletech();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iswspace(editor.row[editor.cury].line[editor.curx])) {
|
||||||
|
while (iswspace(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() || iswspace(editor.row[editor.cury].line[editor.curx])) {
|
||||||
|
if (editor.cury == 0 && editor.curx == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
move_cursor(ARROW_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (editor.curx > 0 && !iswspace(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 (!iswspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deletech();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (editor.curx > 0) {
|
||||||
|
if (iswspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deletech();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_row(int at)
|
delete_row(int at)
|
||||||
{
|
{
|
||||||
@@ -562,6 +715,9 @@ insertch(int16_t c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* deletech
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
deletech(void)
|
deletech(void)
|
||||||
{
|
{
|
||||||
@@ -645,14 +801,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);
|
||||||
@@ -710,7 +861,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;
|
||||||
@@ -956,11 +1107,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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -968,7 +1115,7 @@ void
|
|||||||
move_cursor(int16_t c)
|
move_cursor(int16_t c)
|
||||||
{
|
{
|
||||||
struct erow *row;
|
struct erow *row;
|
||||||
int reps;
|
int reps;
|
||||||
|
|
||||||
row = (editor.cury >= editor.nrows) ? NULL : &editor.row[editor.cury];
|
row = (editor.cury >= editor.nrows) ? NULL : &editor.row[editor.cury];
|
||||||
|
|
||||||
@@ -1178,26 +1325,6 @@ process_normal(int16_t c)
|
|||||||
void
|
void
|
||||||
process_escape(int16_t c)
|
process_escape(int16_t c)
|
||||||
{
|
{
|
||||||
struct erow *row = NULL;
|
|
||||||
|
|
||||||
/* 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");
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -1209,21 +1336,17 @@ process_escape(int16_t c)
|
|||||||
editor.cury = 0;
|
editor.cury = 0;
|
||||||
editor.curx = 0;
|
editor.curx = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'b':
|
||||||
|
find_prev_word();
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
delete_next_word();
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
find_next_word();
|
||||||
|
break;
|
||||||
case BACKSPACE:
|
case BACKSPACE:
|
||||||
row = &editor.row[editor.cury]; /* cury may have changed */
|
delete_prev_word();
|
||||||
if (editor.curx == 0 || editor.curx < row->size) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unsigned char)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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
editor_set_status("unknown ESC key: %04x", c);
|
editor_set_status("unknown ESC key: %04x", c);
|
||||||
@@ -1344,8 +1467,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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user