aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2023-07-06 18:53:23 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2023-07-06 18:53:23 +0300
commitf1fec09d2d38f759d940dabbeab26a6ab7839c8b (patch)
treefbf2b6e6e344464f31199a4fadbc830e0fee3ceb
parent5546c501850b54c5a466a3448374d3b354952088 (diff)
downloadsciteco-f1fec09d2d38f759d940dabbeab26a6ab7839c8b.tar.gz
fixed ]$ and ]~ (pop from Q-Reg stack to special Q-Registers)
* This was setting only the teco_doc but wasn't calling the necessary set_string() methods. * The idiom [$ FG...$ ]$ to change the working directory temporarily now works. * Similarily you can now write [~ ^U~...$ ]~ to change the clipboard temporarily. * Added test suite cases. The clipboard is not tested since it's not supported everywhere and would interfer with the host system. * Resolved lots of redundancies in qreg.c. The clipboard and workingdir Q-Regs have lots in common. This is now abstracted in the "external" Q-Reg base "class" (ie. via initializer TECO_INIT_QREG_EXTERNAL()). It uses vtable calls which is slightly more inefficient than per register implementations, but avoiding redundancies is probably more important.
-rw-r--r--src/qreg.c248
-rw-r--r--tests/testsuite.at6
2 files changed, 90 insertions, 164 deletions
diff --git a/src/qreg.c b/src/qreg.c
index 14cd331..40e1c2e 100644
--- a/src/qreg.c
+++ b/src/qreg.c
@@ -319,6 +319,10 @@ teco_qreg_plain_undo_edit(teco_qreg_t *qreg, GError **error)
return TRUE;
}
+/**
+ * Initializer for vtables of Q-Registers with "plain" storage of strings.
+ * These store their string part as teco_docs.
+ */
#define TECO_INIT_QREG(...) { \
.set_integer = teco_qreg_plain_set_integer, \
.undo_set_integer = teco_qreg_plain_undo_set_integer, \
@@ -345,6 +349,78 @@ teco_qreg_plain_new(const gchar *name, gsize len)
return teco_qreg_new(&vtable, name, len);
}
+static gboolean
+teco_qreg_external_edit(teco_qreg_t *qreg, GError **error)
+{
+ g_auto(teco_string_t) str = {NULL, 0};
+
+ if (!teco_qreg_plain_edit(qreg, error) ||
+ !qreg->vtable->get_string(qreg, &str.data, &str.len, error))
+ return FALSE;
+
+ teco_view_ssm(teco_qreg_view, SCI_BEGINUNDOACTION, 0, 0);
+ teco_view_ssm(teco_qreg_view, SCI_CLEARALL, 0, 0);
+ teco_view_ssm(teco_qreg_view, SCI_ADDTEXT, str.len, (sptr_t)str.data);
+ teco_view_ssm(teco_qreg_view, SCI_ENDUNDOACTION, 0, 0);
+
+ undo__teco_view_ssm(teco_qreg_view, SCI_UNDO, 0, 0);
+ return TRUE;
+}
+
+static gboolean
+teco_qreg_external_exchange_string(teco_qreg_t *qreg, teco_doc_t *src, GError **error)
+{
+ g_auto(teco_string_t) other_str, own_str = {NULL, 0};
+
+ teco_doc_get_string(src, &other_str.data, &other_str.len);
+
+ if (!qreg->vtable->get_string(qreg, &own_str.data, &own_str.len, error) ||
+ !qreg->vtable->set_string(qreg, other_str.data, other_str.len, error))
+ return FALSE;
+
+ teco_doc_set_string(src, own_str.data, own_str.len);
+ return TRUE;
+}
+
+static gboolean
+teco_qreg_external_undo_exchange_string(teco_qreg_t *qreg, teco_doc_t *src, GError **error)
+{
+ if (!qreg->vtable->undo_set_string(qreg, error))
+ return FALSE;
+ if (qreg->must_undo) // FIXME
+ teco_doc_undo_set_string(src);
+ return TRUE;
+}
+
+static gint
+teco_qreg_external_get_character(teco_qreg_t *qreg, guint position, GError **error)
+{
+ g_auto(teco_string_t) str = {NULL, 0};
+
+ if (!qreg->vtable->get_string(qreg, &str.data, &str.len, error))
+ return -1;
+
+ if (position >= str.len) {
+ g_set_error(error, TECO_ERROR, TECO_ERROR_RANGE,
+ "Position %u out of range", position);
+ return -1;
+ }
+
+ return str.data[position];
+}
+
+/**
+ * Initializer for vtables of Q-Registers with "external" storage of strings.
+ * These rely on custom implementations of get_string() and set_string().
+ */
+#define TECO_INIT_QREG_EXTERNAL(...) TECO_INIT_QREG( \
+ .exchange_string = teco_qreg_external_exchange_string, \
+ .undo_exchange_string = teco_qreg_external_undo_exchange_string, \
+ .edit = teco_qreg_external_edit, \
+ .get_character = teco_qreg_external_get_character, \
+ ##__VA_ARGS__ \
+)
+
/*
* NOTE: The integer-component is currently unused on the "*" special register.
*/
@@ -368,8 +444,8 @@ teco_qreg_bufferinfo_get_integer(teco_qreg_t *qreg, teco_int_t *ret, GError **er
}
/*
- * FIXME: These operations can and should be implemented.
- * Setting the "*" register could for instance rename the file.
+ * FIXME: Something could be implemented here. There are 2 possibilities:
+ * Either it renames the current buffer, or opens a file (alternative to EB).
*/
static gboolean
teco_qreg_bufferinfo_set_string(teco_qreg_t *qreg, const gchar *str, gsize len, GError **error)
@@ -436,26 +512,6 @@ teco_qreg_bufferinfo_get_character(teco_qreg_t *qreg, guint position, GError **e
return teco_ring_current->filename[position];
}
-static gboolean
-teco_qreg_bufferinfo_edit(teco_qreg_t *qreg, GError **error)
-{
- if (!teco_qreg_plain_edit(qreg, error))
- return FALSE;
-
- g_auto(teco_string_t) str = {NULL, 0};
-
- if (!teco_qreg_bufferinfo_get_string(qreg, &str.data, &str.len, error))
- return FALSE;
-
- teco_view_ssm(teco_qreg_view, SCI_BEGINUNDOACTION, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_CLEARALL, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_ADDTEXT, str.len, (sptr_t)str.data);
- teco_view_ssm(teco_qreg_view, SCI_ENDUNDOACTION, 0, 0);
-
- undo__teco_view_ssm(teco_qreg_view, SCI_UNDO, 0, 0);
- return TRUE;
-}
-
/** @static @memberof teco_qreg_t */
teco_qreg_t *
teco_qreg_bufferinfo_new(void)
@@ -470,7 +526,8 @@ teco_qreg_bufferinfo_new(void)
.undo_append_string = teco_qreg_bufferinfo_undo_append_string,
.get_string = teco_qreg_bufferinfo_get_string,
.get_character = teco_qreg_bufferinfo_get_character,
- .edit = teco_qreg_bufferinfo_edit
+ /* we don't want to inherit all the other stuff from TECO_INIT_QREG_EXTERNAL(). */
+ .edit = teco_qreg_external_edit
);
return teco_qreg_new(&vtable, "*", 1);
@@ -549,80 +606,16 @@ teco_qreg_workingdir_get_string(teco_qreg_t *qreg, gchar **str, gsize *len, GErr
return TRUE;
}
-static gint
-teco_qreg_workingdir_get_character(teco_qreg_t *qreg, guint position, GError **error)
-{
- g_auto(teco_string_t) str = {NULL, 0};
-
- if (!teco_qreg_workingdir_get_string(qreg, &str.data, &str.len, error))
- return -1;
-
- if (position >= str.len) {
- g_set_error(error, TECO_ERROR, TECO_ERROR_RANGE,
- "Position %u out of range", position);
- return -1;
- }
-
- return str.data[position];
-}
-
-static gboolean
-teco_qreg_workingdir_edit(teco_qreg_t *qreg, GError **error)
-{
- g_auto(teco_string_t) str = {NULL, 0};
-
- if (!teco_qreg_plain_edit(qreg, error) ||
- !teco_qreg_workingdir_get_string(qreg, &str.data, &str.len, error))
- return FALSE;
-
- teco_view_ssm(teco_qreg_view, SCI_BEGINUNDOACTION, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_CLEARALL, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_ADDTEXT, str.len, (sptr_t)str.data);
- teco_view_ssm(teco_qreg_view, SCI_ENDUNDOACTION, 0, 0);
-
- undo__teco_view_ssm(teco_qreg_view, SCI_UNDO, 0, 0);
- return TRUE;
-}
-
-static gboolean
-teco_qreg_workingdir_exchange_string(teco_qreg_t *qreg, teco_doc_t *src, GError **error)
-{
- g_auto(teco_string_t) other_str, own_str = {NULL, 0};
-
- teco_doc_get_string(src, &other_str.data, &other_str.len);
-
- if (!teco_qreg_workingdir_get_string(qreg, &own_str.data, &own_str.len, error) ||
- /* FIXME: Why is teco_qreg_plain_set_string() sufficient? */
- !teco_qreg_plain_set_string(qreg, other_str.data, other_str.len, error))
- return FALSE;
-
- teco_doc_set_string(src, own_str.data, own_str.len);
- return TRUE;
-}
-
-static gboolean
-teco_qreg_workingdir_undo_exchange_string(teco_qreg_t *qreg, teco_doc_t *src, GError **error)
-{
- teco_undo_change_dir_to_current();
- if (qreg->must_undo) // FIXME
- teco_doc_undo_set_string(src);
- return TRUE;
-}
-
/** @static @memberof teco_qreg_t */
teco_qreg_t *
teco_qreg_workingdir_new(void)
{
- static teco_qreg_vtable_t vtable = TECO_INIT_QREG(
+ static teco_qreg_vtable_t vtable = TECO_INIT_QREG_EXTERNAL(
.set_string = teco_qreg_workingdir_set_string,
.undo_set_string = teco_qreg_workingdir_undo_set_string,
.append_string = teco_qreg_workingdir_append_string,
.undo_append_string = teco_qreg_workingdir_undo_append_string,
- .get_string = teco_qreg_workingdir_get_string,
- .get_character = teco_qreg_workingdir_get_character,
- .edit = teco_qreg_workingdir_edit,
- .exchange_string = teco_qreg_workingdir_exchange_string,
- .undo_exchange_string = teco_qreg_workingdir_undo_exchange_string
+ .get_string = teco_qreg_workingdir_get_string
);
/*
@@ -760,89 +753,16 @@ teco_qreg_clipboard_get_string(teco_qreg_t *qreg, gchar **str, gsize *len, GErro
return TRUE;
}
-static gint
-teco_qreg_clipboard_get_character(teco_qreg_t *qreg, guint position, GError **error)
-{
- g_auto(teco_string_t) str = {NULL, 0};
-
- if (!teco_qreg_clipboard_get_string(qreg, &str.data, &str.len, error))
- return -1;
-
- if (position >= str.len) {
- g_set_error(error, TECO_ERROR, TECO_ERROR_RANGE,
- "Position %u out of range", position);
- return -1;
- }
-
- return str.data[position];
-}
-
-static gboolean
-teco_qreg_clipboard_edit(teco_qreg_t *qreg, GError **error)
-{
- if (!teco_qreg_plain_edit(qreg, error))
- return FALSE;
-
- g_auto(teco_string_t) str = {NULL, 0};
-
- if (!teco_qreg_clipboard_get_string(qreg, &str.data, &str.len, error))
- return FALSE;
-
- teco_view_ssm(teco_qreg_view, SCI_BEGINUNDOACTION, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_CLEARALL, 0, 0);
- teco_view_ssm(teco_qreg_view, SCI_APPENDTEXT, str.len, (sptr_t)str.data);
- teco_view_ssm(teco_qreg_view, SCI_ENDUNDOACTION, 0, 0);
-
- undo__teco_view_ssm(teco_qreg_view, SCI_UNDO, 0, 0);
- return TRUE;
-}
-
-/*
- * FIXME: Very similar to teco_qreg_workingdir_exchange_string().
- */
-static gboolean
-teco_qreg_clipboard_exchange_string(teco_qreg_t *qreg, teco_doc_t *src, GError **error)
-{
- g_auto(teco_string_t) other_str, own_str = {NULL, 0};
-
- teco_doc_get_string(src, &other_str.data, &other_str.len);
-
- if (!teco_qreg_clipboard_get_string(qreg, &own_str.data, &own_str.len, error) ||
- /* FIXME: Why is teco_qreg_plain_set_string() sufficient? */
- !teco_qreg_plain_set_string(qreg, other_str.data, other_str.len, error))
- return FALSE;
-
- teco_doc_set_string(src, own_str.data, own_str.len);
- return TRUE;
-}
-
-/*
- * FIXME: Very similar to teco_qreg_workingdir_undo_exchange_string().
- */
-static gboolean
-teco_qreg_clipboard_undo_exchange_string(teco_qreg_t *qreg, teco_doc_t *src, GError **error)
-{
- if (!teco_qreg_clipboard_undo_set_string(qreg, error))
- return FALSE;
- if (qreg->must_undo) // FIXME
- teco_doc_undo_set_string(src);
- return TRUE;
-}
-
/** @static @memberof teco_qreg_t */
teco_qreg_t *
teco_qreg_clipboard_new(const gchar *name)
{
- static teco_qreg_vtable_t vtable = TECO_INIT_QREG(
+ static teco_qreg_vtable_t vtable = TECO_INIT_QREG_EXTERNAL(
.set_string = teco_qreg_clipboard_set_string,
.undo_set_string = teco_qreg_clipboard_undo_set_string,
.append_string = teco_qreg_clipboard_append_string,
.undo_append_string = teco_qreg_clipboard_undo_append_string,
- .get_string = teco_qreg_clipboard_get_string,
- .get_character = teco_qreg_clipboard_get_character,
- .edit = teco_qreg_clipboard_edit,
- .exchange_string = teco_qreg_clipboard_exchange_string,
- .undo_exchange_string = teco_qreg_clipboard_undo_exchange_string
+ .get_string = teco_qreg_clipboard_get_string
);
teco_qreg_t *qreg = teco_qreg_new(&vtable, "~", 1);
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 20a72ca..e5b001a 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -63,6 +63,12 @@ AT_CHECK([$SCITECO -e '0U[[AB^Q@:>@(0/0)]]'], 0, ignore, ignore)
# TODO: String building in Q-Register definitions
AT_CLEANUP
+AT_SETUP([Q-Register stack])
+AT_CHECK([$SCITECO -e "[[a 23Ub ]]b Qb\"N(0/0)'"], 0, ignore, ignore)
+# FG will temporarily change the working directory to tests/testsuite.dir.
+AT_CHECK([$SCITECO -e "[[\$ @FG'..' ]]\$ :Q\$-1Q\$-^^r\"=(0/0)'"], 0, ignore, ignore)
+AT_CLEANUP
+
AT_SETUP([8-bit cleanlyness])
AT_CHECK([$SCITECO -e "0:@EUa/f^@^@/ :Qa-4\"N(0/0)' Ga Z= Z-4\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP