aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/lexers/sciteco.tesbin774 -> 809 bytes
-rw-r--r--src/core-commands.h1
-rw-r--r--src/file-utils.c13
-rw-r--r--src/file-utils.h4
-rw-r--r--src/lexer.c17
-rw-r--r--src/lexer.h14
-rw-r--r--src/view.c19
7 files changed, 48 insertions, 20 deletions
diff --git a/lib/lexers/sciteco.tes b/lib/lexers/sciteco.tes
index ae9b281..0e7db64 100644
--- a/lib/lexers/sciteco.tes
+++ b/lib/lexers/sciteco.tes
Binary files differ
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);
diff --git a/src/view.c b/src/view.c
index 702c5b6..53199bd 100644
--- a/src/view.c
+++ b/src/view.c
@@ -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;
}