diff --git a/include/buffer.h b/include/buffer.h index 38cbfd3..03656a5 100644 --- a/include/buffer.h +++ b/include/buffer.h @@ -25,7 +25,7 @@ struct buffer *buffer_create(void); 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_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_append_string(struct erow *erow, const char *s, size_t s_len); diff --git a/include/input.h b/include/input.h index 6ed4d55..2c0381a 100644 --- a/include/input.h +++ b/include/input.h @@ -5,6 +5,8 @@ enum KEYS { TAB = 9, + ENTER = 13, + ESCAPE = 27, BACKSPACE = 127, HOME = 0x100, DEL, diff --git a/include/kilo.h b/include/kilo.h index 4018fb3..0127fd6 100644 --- a/include/kilo.h +++ b/include/kilo.h @@ -21,6 +21,7 @@ struct editor_state { }; 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 diff --git a/progress_log.md b/progress_log.md new file mode 100644 index 0000000..c023641 --- /dev/null +++ b/progress_log.md @@ -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. diff --git a/src/buffer.c b/src/buffer.c index 7965d11..12210b4 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -62,7 +62,7 @@ void buffer_read_file(struct buffer *buffer, const char *filename) { // TODO: Ad buffer->modified = false; } -ERRCODE buffer_write_file(struct buffer *buffer) { +ERRCODE buffer_write_file(struct buffer *buffer, int *bytes_written) { ERRCODE errcode = 0; int fd = -1; @@ -78,7 +78,8 @@ ERRCODE buffer_write_file(struct buffer *buffer) { if (fd == -1) 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); END: diff --git a/src/commands.c b/src/commands.c index d1c24ef..5655dec 100644 --- a/src/commands.c +++ b/src/commands.c @@ -74,7 +74,6 @@ void command_move_cursor(KEY key) { void command_insert_line(void) { if (E.cy == E.current_buf->n_rows) { buffer_insert_row(E.current_buf, NULL, 0, E.cy); - E.cy++; } else { 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->n_chars = E.cx; 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) { @@ -99,6 +99,8 @@ void command_insert_char(char 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); + + cursor_adjust_viewport(); } 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); + + cursor_adjust_viewport(); } 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) - editor_set_message("Saved file %s", E.current_buf->filename); + editor_set_message("%d bytes written", bytes_written); else editor_set_message("Save failed: ERRCODE %d: %s", errcode, strerror(errno)); } diff --git a/src/input.c b/src/input.c index 37fec91..7812aee 100644 --- a/src/input.c +++ b/src/input.c @@ -21,15 +21,11 @@ void input_process_key(void) { command_move_cursor(c); break; - case CTRL_KEY('Q'): - command_quit(); - return; - case CTRL_KEY('S'): command_save_buffer(); break; - case '\r': + case ENTER: command_insert_line(); break; @@ -46,6 +42,11 @@ void input_process_key(void) { default: command_insert_char(c); + break; + + case CTRL_KEY('Q'): + command_quit(); + return; } E.quit_times = 3; diff --git a/src/kilo.c b/src/kilo.c index 3e1324b..3ac8f0f 100644 --- a/src/kilo.c +++ b/src/kilo.c @@ -58,3 +58,40 @@ void editor_set_message(const char *fmt, ...) { 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; +} diff --git a/src/terminal.c b/src/terminal.c index 21dc5e4..d65398a 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -96,7 +96,10 @@ KEY terminal_read_key(void) { char buf[8] = { '\0' }; 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; int escape_int;