summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command.c3
-rw-r--r--command.h2
-rw-r--r--main.c2
-rw-r--r--node.c39
-rw-r--r--ted.cfg2
5 files changed, 45 insertions, 3 deletions
diff --git a/command.c b/command.c
index e9ffd75..5ee0302 100644
--- a/command.c
+++ b/command.c
@@ -337,5 +337,8 @@ void command_execute(Ted *ted, Command c, i64 argument) {
}
}
break;
+ case CMD_SPLIT_JOIN:
+ node_join(ted, node);
+ break;
}
}
diff --git a/command.h b/command.h
index a74f42a..a8efe35 100644
--- a/command.h
+++ b/command.h
@@ -74,6 +74,7 @@ ENUM_U16 {
CMD_SPLIT_HORIZONTAL,
CMD_SPLIT_VERTICAL,
+ CMD_SPLIT_JOIN,
CMD_ESCAPE, // by default this is the escape key. closes menus, etc.
@@ -145,6 +146,7 @@ static CommandName const command_names[CMD_COUNT] = {
{"goto-line", CMD_GOTO_LINE},
{"split-horizontal", CMD_SPLIT_HORIZONTAL},
{"split-vertical", CMD_SPLIT_VERTICAL},
+ {"split-join", CMD_SPLIT_JOIN},
{"escape", CMD_ESCAPE},
};
diff --git a/main.c b/main.c
index e5b36c2..d7dbc3c 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
// @TODO:
-// - Ctrl+j = :join
// - split depth limit
// - resize split (i.e. change split_pos)
+// - move tabs between nodes
// - Windows installation
// - on crash, output backtrace to log
diff --git a/node.c b/node.c
index 810b657..f2ac41f 100644
--- a/node.c
+++ b/node.c
@@ -34,6 +34,7 @@ static void node_free(Node *node) {
// returns index of parent in ted->nodes, or -1 if this is the root node.
static i32 node_parent(Ted *ted, u16 node_idx) {
+ assert(node_idx < TED_MAX_NODES && ted->nodes_used[node_idx]);
for (u16 i = 0; i < TED_MAX_NODES; ++i) {
if (ted->nodes_used[i]) {
Node *node = &ted->nodes[i];
@@ -46,9 +47,44 @@ static i32 node_parent(Ted *ted, u16 node_idx) {
return -1;
}
+// join this node with its sibling
+static void node_join(Ted *ted, Node *node) {
+ i32 parent_idx = node_parent(ted, (u16)(node - ted->nodes));
+ if (parent_idx >= 0) {
+ Node *parent = &ted->nodes[parent_idx];
+ Node *a = &ted->nodes[parent->split_a];
+ Node *b = &ted->nodes[parent->split_b];
+ if (a->tabs && b->tabs) {
+ if (ted->active_node == a || ted->active_node == b) {
+ ted->active_node = parent;
+ }
+ arr_foreach_ptr(a->tabs, u16, tab) {
+ arr_add(parent->tabs, *tab);
+ }
+ arr_foreach_ptr(b->tabs, u16, tab) {
+ arr_add(parent->tabs, *tab);
+ }
+ if (parent->tabs) {
+ if (node == a) {
+ parent->active_tab = a->active_tab;
+ } else {
+ parent->active_tab = (u16)arr_len(a->tabs) + b->active_tab;
+ }
+ node_free(a);
+ node_free(b);
+ ted->nodes_used[parent->split_a] = false;
+ ted->nodes_used[parent->split_b] = false;
+ }
+ }
+ }
+}
+
static void node_close(Ted *ted, u16 node_idx) {
assert(node_idx < TED_MAX_NODES);
assert(ted->nodes_used[node_idx]);
+ i32 parent_idx = node_parent(ted, node_idx);
+ ted->nodes_used[node_idx] = false;
+
Node *node = &ted->nodes[node_idx];
// delete all associated buffers
@@ -58,9 +94,7 @@ static void node_close(Ted *ted, u16 node_idx) {
}
node_free(node);
- ted->nodes_used[node_idx] = false;
- i32 parent_idx = node_parent(ted, node_idx);
if (parent_idx < 0) {
// no parent; this must be the root node
ted->active_node = NULL;
@@ -90,6 +124,7 @@ static void node_close(Ted *ted, u16 node_idx) {
}
}
+
// close tab, WITHOUT checking for unsaved changes!
// returns true if the node is still open
static bool node_tab_close(Ted *ted, Node *node, u16 index) {
diff --git a/ted.cfg b/ted.cfg
index da4a1a3..1d4e64e 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -123,6 +123,8 @@ Ctrl+g = :goto-line
Ctrl+/ = :split-horizontal
Ctrl+Shift+/ = :split-vertical
+# unsplit
+Ctrl+j = :split-join
Escape = :escape