summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcflip <cflip@cflip.net>2023-01-31 13:31:21 -0700
committercflip <cflip@cflip.net>2023-01-31 14:00:17 -0700
commit1b8261071ef3ad3b8d1c2db6e712b0e590c563b3 (patch)
treeca7e8528b37ccd1d7748b5c70582239b506f8b6a
parent264c4186ed8e3d2e3275a6514c8714903036cb26 (diff)
Reimplement editor_prompt and 'Save as' using the new prompt modeHEADmaster
Now there there is a new way to prompt for text, we can reimplement the long abandoned editor_prompt function and use it to allow saving to new files. The new editor_prompt function takes a callback that will be called after the user presses enter on the prompt.
-rw-r--r--editor.c67
-rw-r--r--editor.h5
-rw-r--r--file.c48
-rw-r--r--file.h2
-rw-r--r--input.c2
5 files changed, 76 insertions, 48 deletions
diff --git a/editor.c b/editor.c
index 8e0f6a6..16f8152 100644
--- a/editor.c
+++ b/editor.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <unistd.h>
+#include "file.h"
#include "input.h"
#include "syntax.h"
#include "window.h"
@@ -49,22 +50,56 @@ void editor_set_status_message(struct editor_state* editor, const char* format,
editor->status_message_time = time(NULL);
}
-char* editor_prompt(struct editor_state* editor, char* prompt, void (*callback)(struct editor_state*, char*, int))
+static prompt_callback_t saved_prompt_callback;
+
+void editor_prompt(struct editor_state* editor, char* prompt, prompt_callback_t callback)
{
- /* TODO: The previous implementation of this function relied on reading
- * input from the terminal, but now that we get input through window events
- * it's no longer possible to sit in an infinite loop waiting for keys here.
- */
- printf("TODO: editor_prompt unimplemented\n");
- return NULL;
+ saved_prompt_callback = callback;
+ editor_set_mode(editor, EDITOR_MODE_PROMPT);
}
void editor_run_command(struct editor_state *editor)
{
- /* TODO: Do something here */
+ textbuf_append(&editor->cmdline, "\0", 1);
+
+ if (saved_prompt_callback) {
+ saved_prompt_callback(editor, editor->cmdline.buffer, editor->cmdline.length);
+ }
+
+ /* TODO: Parse and run a command by its name */
editor_set_mode(editor, EDITOR_MODE_NORMAL);
}
+static void save_callback(struct editor_state *editor, char *filename, size_t namelen)
+{
+ if (filename == NULL)
+ return;
+
+ editor->filename = malloc(namelen);
+ memcpy(editor->filename, filename, namelen);
+
+ editor_select_syntax_highlight(editor);
+ window_set_filename(editor->filename);
+
+ editor_try_save(editor);
+}
+
+void editor_try_save(struct editor_state *editor)
+{
+ /*
+ * If there is no filename, set a callback to change the filename and
+ * come back here later once it is set.
+ */
+ if (editor->filename == NULL) {
+ editor_prompt(editor, "Save as: ", save_callback);
+ return;
+ }
+
+ int saverr = file_save_current_file(editor);
+ if (saverr != 0)
+ editor_set_status_message(editor, "Failed to save file: %s", strerror(saverr));
+}
+
void editor_try_quit(struct editor_state *editor)
{
if (editor->dirty && quit_message_time == 0) {
@@ -191,6 +226,7 @@ void editor_set_mode(struct editor_state *editor, enum editor_mode mode)
/* Clear the command line if we are leaving prompt mode. */
if (last_mode == EDITOR_MODE_PROMPT) {
textbuf_clear(&editor->cmdline);
+ saved_prompt_callback = NULL;
}
/* Ignore the extra first letter if we are entering a typing mode. */
@@ -263,20 +299,7 @@ static void editor_find_callback(struct editor_state* editor, char* query, int k
void editor_find(struct editor_state* editor)
{
- int saved_cursor_x = editor->cursor_x;
- int saved_cursor_y = editor->cursor_y;
- int saved_col_offset = editor->col_offset;
- int saved_line_offset = editor->line_offset;
-
- char* query = editor_prompt(editor, "Search: %s (Use Esc/Arrows/Enter)", editor_find_callback);
- if (query) {
- free(query);
- } else {
- editor->cursor_x = saved_cursor_x;
- editor->cursor_y = saved_cursor_y;
- editor->col_offset = saved_col_offset;
- editor->line_offset = saved_line_offset;
- }
+ /* TODO: Unimplemented */
}
void editor_scroll(struct editor_state* editor)
diff --git a/editor.h b/editor.h
index e530956..2c64013 100644
--- a/editor.h
+++ b/editor.h
@@ -36,11 +36,14 @@ struct editor_state {
struct textbuf cmdline;
};
+typedef void (*prompt_callback_t)(struct editor_state*, char*, size_t);
+
void init_editor(struct editor_state* editor);
void editor_set_status_message(struct editor_state* editor, const char* format, ...);
-char* editor_prompt(struct editor_state* editor, char* prompt, void (*callback)(struct editor_state*, char*, int));
+void editor_prompt(struct editor_state* editor, char* prompt, prompt_callback_t callback);
void editor_run_command(struct editor_state *editor);
+void editor_try_save(struct editor_state *editor);
void editor_try_quit(struct editor_state *editor);
void editor_move_left(struct editor_state *);
diff --git a/file.c b/file.c
index 88f789e..59e8179 100644
--- a/file.c
+++ b/file.c
@@ -10,6 +10,7 @@
#include "error.h"
#include "line.h"
#include "syntax.h"
+#include "window.h"
static char *lines_to_string(struct editor_state *editor, int *buffer_length)
{
@@ -70,34 +71,35 @@ void editor_open(struct editor_state* editor, char* filename)
editor->dirty = 0;
}
-void editor_save(struct editor_state* editor)
+int file_save_current_file(struct editor_state *editor)
{
- if (editor->filename == NULL) {
- editor->filename = editor_prompt(editor, "Save as: %s", NULL);
-
- if (editor->filename == NULL)
- return;
-
- editor_select_syntax_highlight(editor);
- window_set_filename(editor->filename);
- }
+ /* Assume that the editor has already prompted the user for a name */
+ if (editor->filename == NULL)
+ return EINVAL;
int length;
char *buffer = lines_to_string(editor, &length);
int fd = open(editor->filename, O_RDWR | O_CREAT, 0644);
- if (fd != -1) {
- if (ftruncate(fd, length) != -1) {
- if (write(fd, buffer, length) == length) {
- close(fd);
- free(buffer);
- editor_set_status_message(editor, "%d bytes written to disk", length);
- editor->dirty = 0;
- return;
- }
- }
- close(fd);
- }
+ if (fd == -1)
+ goto fail;
+
+ if (ftruncate(fd, length) == -1)
+ goto fail;
+
+ if (write(fd, buffer, length) != length)
+ goto fail;
+
+ close(fd);
+ free(buffer);
+ editor_set_status_message(editor, "%d bytes written to disk", length);
+ editor->dirty = 0;
+
+ return 0;
+
+fail:
+ int saved_errno = errno;
+ close(fd);
free(buffer);
- editor_set_status_message(editor, "Failed to write to disk: %s", strerror(errno));
+ return saved_errno;
}
diff --git a/file.h b/file.h
index 70889ac..d0ba218 100644
--- a/file.h
+++ b/file.h
@@ -4,6 +4,6 @@
#include "editor.h"
void editor_open(struct editor_state* editor, char* filename);
-void editor_save(struct editor_state* editor);
+int file_save_current_file(struct editor_state *editor);
#endif
diff --git a/input.c b/input.c
index c695cb9..2f93ce7 100644
--- a/input.c
+++ b/input.c
@@ -56,7 +56,7 @@ void editor_process_keypress(struct editor_state *editor, SDL_Keysym *keysym)
break;
case SDLK_s:
if (keysym->mod & KMOD_CTRL) {
- editor_save(editor);
+ editor_try_save(editor);
break;
}
editor_move_down(editor);