Finish chapter 5
This commit is contained in:
parent
01dbed5e6c
commit
bfb47723af
9 changed files with 80 additions and 17 deletions
|
@ -25,7 +25,7 @@ struct buffer *buffer_create(void);
|
||||||
void buffer_read_file(struct buffer *buffer, const char *filename);
|
void buffer_read_file(struct buffer *buffer, const char *filename);
|
||||||
void buffer_insert_row(struct buffer *buffer, const char *chars, int n_chars, int at);
|
void buffer_insert_row(struct buffer *buffer, const char *chars, int n_chars, int at);
|
||||||
void buffer_delete_row(struct buffer *buffer, int at);
|
void buffer_delete_row(struct buffer *buffer, int at);
|
||||||
ERRCODE buffer_write_file(struct buffer *buffer);
|
ERRCODE buffer_write_file(struct buffer *buffer, int *bytes_written);
|
||||||
|
|
||||||
void erow_update_rendering(struct erow *erow);
|
void erow_update_rendering(struct erow *erow);
|
||||||
void erow_append_string(struct erow *erow, const char *s, size_t s_len);
|
void erow_append_string(struct erow *erow, const char *s, size_t s_len);
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
enum KEYS {
|
enum KEYS {
|
||||||
TAB = 9,
|
TAB = 9,
|
||||||
|
ENTER = 13,
|
||||||
|
ESCAPE = 27,
|
||||||
BACKSPACE = 127,
|
BACKSPACE = 127,
|
||||||
HOME = 0x100,
|
HOME = 0x100,
|
||||||
DEL,
|
DEL,
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct editor_state {
|
||||||
};
|
};
|
||||||
extern struct editor_state E;
|
extern struct editor_state E;
|
||||||
|
|
||||||
void editor_set_message(const char *, ...);
|
void editor_set_message(const char *fmt, ...);
|
||||||
|
char *editor_prompt(const char *prompt);
|
||||||
|
|
||||||
#endif // KILO_H
|
#endif // KILO_H
|
||||||
|
|
5
progress_log.md
Normal file
5
progress_log.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Progress log
|
||||||
|
- (4/9/2023) Finished 5 chapters out of 7, basic text editing is fully
|
||||||
|
possible. It has fun been working on this, but semester is starting now and I
|
||||||
|
might not get to work on this a lot anymore. It might have lots of bugs, and
|
||||||
|
there's lots of things I don't like, there are TODOs everywhere.
|
|
@ -62,7 +62,7 @@ void buffer_read_file(struct buffer *buffer, const char *filename) { // TODO: Ad
|
||||||
buffer->modified = false;
|
buffer->modified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERRCODE buffer_write_file(struct buffer *buffer) {
|
ERRCODE buffer_write_file(struct buffer *buffer, int *bytes_written) {
|
||||||
ERRCODE errcode = 0;
|
ERRCODE errcode = 0;
|
||||||
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
@ -78,7 +78,8 @@ ERRCODE buffer_write_file(struct buffer *buffer) {
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
RETURN(-2);
|
RETURN(-2);
|
||||||
|
|
||||||
if (write(fd, write_buffer, len) != (ssize_t) len)
|
*bytes_written = write(fd, write_buffer, len);
|
||||||
|
if (*bytes_written != (ssize_t) len)
|
||||||
RETURN(-3);
|
RETURN(-3);
|
||||||
|
|
||||||
END:
|
END:
|
||||||
|
|
|
@ -74,7 +74,6 @@ void command_move_cursor(KEY key) {
|
||||||
void command_insert_line(void) {
|
void command_insert_line(void) {
|
||||||
if (E.cy == E.current_buf->n_rows) {
|
if (E.cy == E.current_buf->n_rows) {
|
||||||
buffer_insert_row(E.current_buf, NULL, 0, E.cy);
|
buffer_insert_row(E.current_buf, NULL, 0, E.cy);
|
||||||
E.cy++;
|
|
||||||
} else {
|
} else {
|
||||||
buffer_insert_row(E.current_buf, NULL, 0, E.cy + 1);
|
buffer_insert_row(E.current_buf, NULL, 0, E.cy + 1);
|
||||||
|
|
||||||
|
@ -86,11 +85,12 @@ void command_insert_line(void) {
|
||||||
c_row->chars = realloc(c_row->chars, E.cx);
|
c_row->chars = realloc(c_row->chars, E.cx);
|
||||||
c_row->n_chars = E.cx;
|
c_row->n_chars = E.cx;
|
||||||
erow_update_rendering(c_row);
|
erow_update_rendering(c_row);
|
||||||
|
|
||||||
E.cx = 0;
|
|
||||||
E.rx = 0;
|
|
||||||
E.cy++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
E.cx = E.rx = 0;
|
||||||
|
E.cy++;
|
||||||
|
|
||||||
|
cursor_adjust_viewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_insert_char(char c) {
|
void command_insert_char(char c) {
|
||||||
|
@ -99,6 +99,8 @@ void command_insert_char(char c) {
|
||||||
|
|
||||||
erow_insert_char(E.current_buf->rows+E.cy, E.cx++, c);
|
erow_insert_char(E.current_buf->rows+E.cy, E.cx++, c);
|
||||||
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
||||||
|
|
||||||
|
cursor_adjust_viewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_delete_char(void) { // TODO
|
void command_delete_char(void) { // TODO
|
||||||
|
@ -125,13 +127,24 @@ void command_delete_char(void) { // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
||||||
|
|
||||||
|
cursor_adjust_viewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_save_buffer(void) {
|
void command_save_buffer(void) {
|
||||||
ERRCODE errcode = buffer_write_file(E.current_buf);
|
if (E.current_buf->filename == NULL) {
|
||||||
|
E.current_buf->filename = editor_prompt("Save as: %s (ESC to cancel)");
|
||||||
|
if (E.current_buf->filename == NULL) {
|
||||||
|
editor_set_message("Save aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytes_written;
|
||||||
|
ERRCODE errcode = buffer_write_file(E.current_buf, &bytes_written);
|
||||||
|
|
||||||
if (errcode == 0)
|
if (errcode == 0)
|
||||||
editor_set_message("Saved file %s", E.current_buf->filename);
|
editor_set_message("%d bytes written", bytes_written);
|
||||||
else
|
else
|
||||||
editor_set_message("Save failed: ERRCODE %d: %s", errcode, strerror(errno));
|
editor_set_message("Save failed: ERRCODE %d: %s", errcode, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
11
src/input.c
11
src/input.c
|
@ -21,15 +21,11 @@ void input_process_key(void) {
|
||||||
command_move_cursor(c);
|
command_move_cursor(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_KEY('Q'):
|
|
||||||
command_quit();
|
|
||||||
return;
|
|
||||||
|
|
||||||
case CTRL_KEY('S'):
|
case CTRL_KEY('S'):
|
||||||
command_save_buffer();
|
command_save_buffer();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\r':
|
case ENTER:
|
||||||
command_insert_line();
|
command_insert_line();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -46,6 +42,11 @@ void input_process_key(void) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
command_insert_char(c);
|
command_insert_char(c);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CTRL_KEY('Q'):
|
||||||
|
command_quit();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
E.quit_times = 3;
|
E.quit_times = 3;
|
||||||
|
|
37
src/kilo.c
37
src/kilo.c
|
@ -58,3 +58,40 @@ void editor_set_message(const char *fmt, ...) {
|
||||||
|
|
||||||
E.message_time = time(NULL);
|
E.message_time = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement a fully featured line editor
|
||||||
|
char *editor_prompt(const char *prompt) {
|
||||||
|
size_t buffer_size = 64;
|
||||||
|
char *buffer = malloc(buffer_size);
|
||||||
|
|
||||||
|
size_t buffer_len = 0;
|
||||||
|
buffer[buffer_len] = '\0';
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
editor_set_message(prompt, buffer);
|
||||||
|
ui_draw_screen();
|
||||||
|
|
||||||
|
KEY key = terminal_read_key();
|
||||||
|
if (key == ESCAPE) {
|
||||||
|
editor_set_message("");
|
||||||
|
free(buffer);
|
||||||
|
return NULL;
|
||||||
|
} else if (key == ENTER) {
|
||||||
|
if (buffer_len > 0) {
|
||||||
|
editor_set_message("");
|
||||||
|
buffer = realloc(buffer, buffer_len + 1);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
} else if (isprint(key)) {
|
||||||
|
if (buffer_len >= buffer_size - 1) {
|
||||||
|
buffer_size *= 2;
|
||||||
|
buffer = realloc(buffer, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[buffer_len++] = key;
|
||||||
|
buffer[buffer_len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
|
@ -96,7 +96,10 @@ KEY terminal_read_key(void) {
|
||||||
char buf[8] = { '\0' };
|
char buf[8] = { '\0' };
|
||||||
|
|
||||||
for (int i = 0; i < (int) sizeof(buf); i++) {
|
for (int i = 0; i < (int) sizeof(buf); i++) {
|
||||||
if (read(STDIN_FILENO, buf+i, 1) == 0) break;
|
if (read(STDIN_FILENO, buf+i, 1) == 0) {
|
||||||
|
if (i == 0) return ESCAPE;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
char escape_char;
|
char escape_char;
|
||||||
int escape_int;
|
int escape_int;
|
||||||
|
|
Reference in a new issue