diff options
| -rw-r--r-- | lib/lexers/sciteco.tes | bin | 774 -> 809 bytes | |||
| -rw-r--r-- | src/core-commands.h | 1 | ||||
| -rw-r--r-- | src/file-utils.c | 13 | ||||
| -rw-r--r-- | src/file-utils.h | 4 | ||||
| -rw-r--r-- | src/lexer.c | 17 | ||||
| -rw-r--r-- | src/lexer.h | 14 | ||||
| -rw-r--r-- | src/view.c | 19 |
7 files changed, 48 insertions, 20 deletions
diff --git a/lib/lexers/sciteco.tes b/lib/lexers/sciteco.tes Binary files differindex ae9b281..0e7db64 100644 --- a/lib/lexers/sciteco.tes +++ b/lib/lexers/sciteco.tes diff --git a/src/core-commands.h b/src/core-commands.h index cb28dce..4cc8747 100644 --- a/src/core-commands.h +++ b/src/core-commands.h @@ -125,6 +125,7 @@ TECO_DECLARE_STATE(teco_state_insert_indent); teco_state_t *teco_state_start_input(teco_machine_main_t *ctx, gunichar chr, GError **error); TECO_DECLARE_STATE(teco_state_start); +TECO_DECLARE_STATE(teco_state_control); TECO_DECLARE_STATE(teco_state_escape); TECO_DECLARE_STATE(teco_state_ctlc); TECO_DECLARE_STATE(teco_state_ctlc_control); diff --git a/src/file-utils.c b/src/file-utils.c index 75bcb48..db06ff3 100644 --- a/src/file-utils.c +++ b/src/file-utils.c @@ -109,6 +109,14 @@ teco_file_set_attributes(const gchar *filename, teco_file_attributes_t attrs) #ifdef G_OS_UNIX +/* + * NOTE: This version does not resolve symlinks to non-existing paths. + * It could be improved by repeating readlink() and g_canonicalize_filename(), + * but it would require glib v2.58.0. + * Alternatively we could also iteratively resolve all path components. + * Currently, we simply do not rely on successful canonicalization of + * yet non-existing paths. + */ gchar * teco_file_get_absolute_path(const gchar *path) { @@ -137,13 +145,12 @@ teco_file_is_visible(const gchar *path) #if GLIB_CHECK_VERSION(2,58,0) /* - * FIXME: This should perhaps be preferred on any platform. - * But it will complicate preprocessing. + * NOTE: Does not resolve symlinks. */ gchar * teco_file_get_absolute_path(const gchar *path) { - return g_canonicalize_filename(path, NULL); + return path ? g_canonicalize_filename(path, NULL) : NULL; } #else /* !GLIB_CHECK_VERSION(2,58,0) */ diff --git a/src/file-utils.h b/src/file-utils.h index 12a9b83..9a2f8d6 100644 --- a/src/file-utils.h +++ b/src/file-utils.h @@ -32,9 +32,7 @@ void teco_file_set_attributes(const gchar *filename, teco_file_attributes_t attr /** * Get absolute/full version of a possibly relative path. * The path is tried to be canonicalized so it does - * not contain relative components. - * Works with existing and non-existing paths (in the latter case, - * heuristics may be applied). + * not contain relative components and symlinks. * Depending on platform and existence of the path, * canonicalization might fail, but the path returned is * always absolute. diff --git a/src/lexer.c b/src/lexer.c index 02a6636..787fe89 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -26,6 +26,7 @@ #include "sciteco.h" #include "view.h" #include "parser.h" +#include "core-commands.h" #include "lexer.h" static teco_style_t @@ -37,16 +38,21 @@ teco_lexer_getstyle(teco_view_t *view, teco_machine_main_t *machine, /* * FIXME: At least this special workaround for numbers might be * unnecessary once we get a special parser state for parsing numbers. - * - * FIXME: What about ^* and ^/? - * They are currently highlighted as commands. */ if (machine->parent.current->keymacro_mask & TECO_KEYMACRO_MASK_START && chr <= 0xFF) { if (g_ascii_isdigit(chr)) style = SCE_SCITECO_NUMBER; - else if (strchr(",+-*/#&", chr)) + else if (strchr(",+-*/#&()", chr)) style = SCE_SCITECO_OPERATOR; + } else if (machine->parent.current == &teco_state_control) { + /* + * Two-character operators must always begin with caret + * They get a separate style, so we can extend it back to + * the caret in teco_lexter_step. + */ + if (strchr("*/#", chr)) + style = SCE_SCITECO_OPERATOR2; } /* @@ -174,8 +180,9 @@ teco_lexer_step(teco_view_t *view, teco_machine_main_t *machine, /* * True comments begin with `!*` or `!!`, but only the second character gets * the correct style by default, so we extend it backwards. + * The same is true for two-letter operators. */ - if (style == SCE_SCITECO_COMMENT) + if (style == SCE_SCITECO_COMMENT || style == SCE_SCITECO_OPERATOR2) old_pc--; teco_view_ssm(view, SCI_STARTSTYLING, start+old_pc, 0); diff --git a/src/lexer.h b/src/lexer.h index 2b011be..e91cdd1 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -25,12 +25,14 @@ typedef enum { SCE_SCITECO_DEFAULT = 0, SCE_SCITECO_COMMAND = 1, SCE_SCITECO_OPERATOR = 2, - SCE_SCITECO_QREG = 3, - SCE_SCITECO_STRING = 4, - SCE_SCITECO_NUMBER = 5, - SCE_SCITECO_LABEL = 6, - SCE_SCITECO_COMMENT = 7, - SCE_SCITECO_INVALID = 8 + /** two-character operators */ + SCE_SCITECO_OPERATOR2 = 3, + SCE_SCITECO_QREG = 4, + SCE_SCITECO_STRING = 5, + SCE_SCITECO_NUMBER = 6, + SCE_SCITECO_LABEL = 7, + SCE_SCITECO_COMMENT = 8, + SCE_SCITECO_INVALID = 9 } teco_style_t; void teco_lexer_style(teco_view_t *view, gsize end); @@ -550,16 +550,16 @@ teco_view_save_to_file(teco_view_t *ctx, const gchar *filename, GError **error) file_stat.st_gid = -1; #endif teco_file_attributes_t attributes = TECO_FILE_INVALID_ATTRIBUTES; + gboolean undo_remove_file = FALSE; if (teco_undo_enabled) { - if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + undo_remove_file = !g_file_test(filename, G_FILE_TEST_IS_REGULAR); + if (!undo_remove_file) { #ifdef G_OS_UNIX g_stat(filename, &file_stat); #endif attributes = teco_file_get_attributes(filename); teco_make_savepoint(filename); - } else { - teco_undo_remove_file_push(filename); } } @@ -568,6 +568,18 @@ teco_view_save_to_file(teco_view_t *ctx, const gchar *filename, GError **error) if (!channel) return FALSE; + if (undo_remove_file) { + /* + * The file is new, so has to be removed on undo. + * If `filename` is a symlink, it's crucial to resolve it now, + * since early canonicalization may have failed (for non-existent + * path segments). + * Now, `filename` is guaranteed to exist. + */ + g_autofree gchar *filename_canon = teco_file_get_absolute_path(filename); + teco_undo_remove_file_push(filename_canon); + } + /* * teco_view_save_to_channel() expects a buffered and blocking channel */ @@ -576,6 +588,7 @@ teco_view_save_to_file(teco_view_t *ctx, const gchar *filename, GError **error) if (!teco_view_save_to_channel(ctx, channel, error)) { g_prefix_error(error, "Error writing file \"%s\": ", filename); + /* file might also be removed (in interactive mode) */ return FALSE; } |
