aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/parser.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.h')
-rw-r--r--src/parser.h86
1 files changed, 47 insertions, 39 deletions
diff --git a/src/parser.h b/src/parser.h
index 5477150..0c389cc 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2025 Robin Haberkorn
+ * Copyright (C) 2012-2026 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -75,7 +75,9 @@ void undo__remove_index__teco_loop_stack(guint);
* FIXME: Maybe use TECO_DECLARE_VTABLE_METHOD()?
*/
typedef const struct {
+ /** whether string building characters are enabled by default */
guint string_building : 1;
+ /** whether this string argument is the last of the command */
guint last : 1;
/**
@@ -83,7 +85,7 @@ typedef const struct {
*
* Can be NULL if no interactive feedback is required.
*/
- gboolean (*process_cb)(teco_machine_main_t *ctx, const teco_string_t *str,
+ gboolean (*process_cb)(teco_machine_main_t *ctx, teco_string_t str,
gsize new_chars, GError **error);
/**
@@ -91,7 +93,7 @@ typedef const struct {
* Commands that don't give interactive feedback can use this callback
* to perform their main processing.
*/
- teco_state_t *(*done_cb)(teco_machine_main_t *ctx, const teco_string_t *str, GError **error);
+ teco_state_t *(*done_cb)(teco_machine_main_t *ctx, teco_string_t str, GError **error);
} teco_state_expectstring_t;
typedef const struct {
@@ -108,7 +110,7 @@ typedef gboolean (*teco_state_refresh_cb_t)(teco_machine_t *ctx, GError **error)
typedef gboolean (*teco_state_end_of_macro_cb_t)(teco_machine_t *ctx, GError **error);
typedef gboolean (*teco_state_process_edit_cmd_cb_t)(teco_machine_t *ctx, teco_machine_t *parent_ctx,
gunichar key, GError **error);
-typedef gboolean (*teco_state_insert_completion_cb_t)(teco_machine_t *ctx, const teco_string_t *str, GError **error);
+typedef gboolean (*teco_state_insert_completion_cb_t)(teco_machine_t *ctx, teco_string_t str, GError **error);
typedef enum {
TECO_KEYMACRO_MASK_START = (1 << 0),
@@ -246,15 +248,18 @@ gboolean teco_state_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent
* @implements teco_state_t
* @ingroup states
*
- * @todo Should we eliminate required callbacks, this could be turned into a
- * struct initializer TECO_INIT_STATE() and TECO_DECLARE_STATE() would become pointless.
- * This would also ease declaring static states.
+ * Base class of all states.
+ *
+ * Since states are constant, you can append static assertions for required callbacks
+ * and other conditions.
+ * You should use TECO_ASSERT_SAFE(), but it won't be checked on all supported compilers.
+ * You should not put anything in front of the definition, though, so you
+ * can write `static TECO_DEFINE_STATE(...)`.
*/
#define TECO_DEFINE_STATE(NAME, ...) \
/** @ingroup states */ \
teco_state_t NAME = { \
.initial_cb = NULL, /* do nothing */ \
- .input_cb = (teco_state_input_cb_t)NAME##_input, /* always required */ \
.refresh_cb = NULL, /* do nothing */ \
.end_of_macro_cb = teco_state_end_of_macro, \
.process_edit_cmd_cb = teco_state_process_edit_cmd, \
@@ -263,11 +268,8 @@ gboolean teco_state_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent
.keymacro_mask = TECO_KEYMACRO_MASK_DEFAULT, \
.style = SCE_SCITECO_DEFAULT, \
##__VA_ARGS__ \
- }
-
-/** @ingroup states */
-#define TECO_DECLARE_STATE(NAME) \
- extern teco_state_t NAME
+ }; \
+ TECO_ASSERT_SAFE(NAME.input_cb != NULL)
/* in cmdline.c */
gboolean teco_state_caseinsensitive_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gunichar chr, GError **error);
@@ -332,7 +334,8 @@ gboolean teco_machine_input(teco_machine_t *ctx, gunichar chr, GError **error);
typedef enum {
TECO_STRINGBUILDING_MODE_NORMAL = 0,
TECO_STRINGBUILDING_MODE_UPPER,
- TECO_STRINGBUILDING_MODE_LOWER
+ TECO_STRINGBUILDING_MODE_LOWER,
+ TECO_STRINGBUILDING_MODE_DISABLED
} teco_stringbuilding_mode_t;
/**
@@ -383,6 +386,13 @@ typedef struct teco_machine_stringbuilding_t {
* the buffer's or Q-Register's encoding.
*/
guint codepage;
+
+ /**
+ * String to collect code from `^E<...>` constructs.
+ * This could waste some memory for string arguments with nested Q-Reg specs,
+ * but we better keep it here than adding another global variable.
+ */
+ teco_string_t code;
} teco_machine_stringbuilding_t;
void teco_machine_stringbuilding_init(teco_machine_stringbuilding_t *ctx, gunichar escape_char,
@@ -484,6 +494,9 @@ struct teco_machine_main_t {
* This is tracked even in parse-only mode.
*/
guint modifier_at : 1;
+
+ /** whether <EB> command accepts a filename */
+ guint allow_filename : 1;
} flags;
/** The nesting level of braces */
@@ -506,17 +519,19 @@ struct teco_machine_main_t {
/*
* teco_state_t-dependent state.
*
- * Some of these cannot be used concurrently and are therefore
- * grouped into unions.
- * We could further optimize memory usage by dynamically allocating
- * some of these structures on demand.
+ * Some cannot theoretically be used at the same time
+ * but it's hard to prevent memory leaks if putting them into
+ * a common union.
*/
- teco_machine_expectstring_t expectstring;
- union {
- teco_string_t goto_label;
- teco_machine_qregspec_t *expectqreg;
- teco_machine_scintilla_t scintilla;
- };
+ teco_machine_expectstring_t expectstring;
+ /**
+ * State machine for parsing Q-reg specifications.
+ * This could theoretically be inlined, but it would introduce
+ * a recursive dependency between qreg.h and parser.h.
+ */
+ teco_machine_qregspec_t *expectqreg;
+ teco_string_t goto_label;
+ teco_machine_scintilla_t scintilla;
};
typedef struct teco_machine_main_flags_t teco_machine_main_flags_t;
@@ -584,7 +599,7 @@ gboolean teco_state_expectstring_refresh(teco_machine_main_t *ctx, GError **erro
/* in cmdline.c */
gboolean teco_state_expectstring_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx,
gunichar key, GError **error);
-gboolean teco_state_expectstring_insert_completion(teco_machine_main_t *ctx, const teco_string_t *str,
+gboolean teco_state_expectstring_insert_completion(teco_machine_main_t *ctx, teco_string_t str,
GError **error);
/**
@@ -595,18 +610,11 @@ gboolean teco_state_expectstring_insert_completion(teco_machine_main_t *ctx, con
* Super-class for states accepting string arguments
* Opaquely cares about alternative-escape characters,
* string building commands and accumulation into a string
- *
- * @note Generating the input_cb could be avoided if there were a default
- * implementation.
*/
#define TECO_DEFINE_STATE_EXPECTSTRING(NAME, ...) \
- static teco_state_t * \
- NAME##_input(teco_machine_main_t *ctx, gunichar chr, GError **error) \
- { \
- return teco_state_expectstring_input(ctx, chr, error); \
- } \
TECO_DEFINE_STATE(NAME, \
.initial_cb = (teco_state_initial_cb_t)teco_state_expectstring_initial, \
+ .input_cb = (teco_state_input_cb_t)teco_state_expectstring_input, \
.refresh_cb = (teco_state_refresh_cb_t)teco_state_expectstring_refresh, \
.process_edit_cmd_cb = (teco_state_process_edit_cmd_cb_t) \
teco_state_expectstring_process_edit_cmd, \
@@ -616,17 +624,17 @@ gboolean teco_state_expectstring_insert_completion(teco_machine_main_t *ctx, con
.style = SCE_SCITECO_STRING, \
.expectstring.string_building = TRUE, \
.expectstring.last = TRUE, \
- .expectstring.process_cb = NULL, /* do nothing */ \
- .expectstring.done_cb = NAME##_done, /* always required */ \
+ .expectstring.process_cb = NULL, /* do nothing */ \
##__VA_ARGS__ \
- )
+ ); \
+ TECO_ASSERT_SAFE(NAME.expectstring.done_cb != NULL)
-gboolean teco_state_expectfile_process(teco_machine_main_t *ctx, const teco_string_t *str,
+gboolean teco_state_expectfile_process(teco_machine_main_t *ctx, teco_string_t str,
gsize new_chars, GError **error);
/* in cmdline.c */
gboolean teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error);
-gboolean teco_state_expectfile_insert_completion(teco_machine_main_t *ctx, const teco_string_t *str, GError **error);
+gboolean teco_state_expectfile_insert_completion(teco_machine_main_t *ctx, teco_string_t str, GError **error);
/**
* @interface TECO_DEFINE_STATE_EXPECTFILE
@@ -645,7 +653,7 @@ gboolean teco_state_expectfile_insert_completion(teco_machine_main_t *ctx, const
/* in cmdline.c */
gboolean teco_state_expectdir_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error);
-gboolean teco_state_expectdir_insert_completion(teco_machine_main_t *ctx, const teco_string_t *str, GError **error);
+gboolean teco_state_expectdir_insert_completion(teco_machine_main_t *ctx, teco_string_t str, GError **error);
/**
* @interface TECO_DEFINE_STATE_EXPECTDIR