can also prefix this command and display a custom prompt for the input dialog.
The additional +--toggle+ option will remove the mark if the window already has
-this mark, add it if the window has none or replace the current mark if it has
-another mark.
+this mark or add it otherwise. Note that you may need to use this in
+combination with +--add+ (see below) as any other marks will otherwise be
+removed.
+
+By default, a window can only have one mark. You can use the +--add+ flag to
+put more than one mark on a window.
Refer to <<show_marks>> if you don't want marks to be shown in the window decoration.
*Syntax*:
-------------------------------
-mark [--toggle] <identifier>
+----------------------------------------------
+mark [--add|--replace] [--toggle] <identifier>
[con_mark="identifier"] focus
unmark <identifier>
-------------------------------
+----------------------------------------------
*Example (in a terminal)*:
------------------------------
void cmd_workspace_name(I3_CMD, const char *name);
/**
- * Implementation of 'mark [--toggle] <mark>'
+ * Implementation of 'mark [--add|--replace] [--toggle] <mark>'
*
*/
-void cmd_mark(I3_CMD, const char *mark, const char *toggle);
+void cmd_mark(I3_CMD, const char *mark, const char *mode, const char *toggle);
/**
* Implementation of 'unmark [mark]'
* Otherwise, the mark is assigned to the container.
*
*/
-void con_mark_toggle(Con *con, const char *mark);
+void con_mark_toggle(Con *con, const char *mark, mark_mode_t mode);
/**
* Assigns a mark to the container.
*
*/
-void con_mark(Con *con, const char *mark);
+void con_mark(Con *con, const char *mark, mark_mode_t mode);
/**
* If mark is NULL, this removes all existing marks.
ADJ_UPPER_SCREEN_EDGE = (1 << 2),
ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t;
+typedef enum { MM_REPLACE,
+ MM_ADD } mark_mode_t;
+
/**
* Container layouts. See Con::layout.
*/
floating = 'enable', 'disable', 'toggle'
-> call cmd_floating($floating)
-# mark [--toggle] <mark>
+# mark [--add|--replace] [--toggle] <mark>
state MARK:
+ mode = '--add', '--replace'
+ ->
toggle = '--toggle'
->
mark = string
- -> call cmd_mark($mark, $toggle)
+ -> call cmd_mark($mark, $mode, $toggle)
# unmark [mark]
state UNMARK:
}
/*
- * Implementation of 'mark [--toggle] <mark>'
+ * Implementation of 'mark [--add|--replace] [--toggle] <mark>'
*
*/
-void cmd_mark(I3_CMD, const char *mark, const char *toggle) {
+void cmd_mark(I3_CMD, const char *mark, const char *mode, const char *toggle) {
HANDLE_EMPTY_MATCH;
owindow *current = TAILQ_FIRST(&owindows);
}
DLOG("matching: %p / %s\n", current->con, current->con->name);
+
+ mark_mode_t mark_mode = (mode == NULL || strcmp(mode, "--replace") == 0) ? MM_REPLACE : MM_ADD;
if (toggle != NULL) {
- con_mark_toggle(current->con, mark);
+ con_mark_toggle(current->con, mark, mark_mode);
} else {
- con_mark(current->con, mark);
+ con_mark(current->con, mark, mark_mode);
}
cmd_output->needs_tree_render = true;
* Otherwise, the mark is assigned to the container.
*
*/
-void con_mark_toggle(Con *con, const char *mark) {
+void con_mark_toggle(Con *con, const char *mark, mark_mode_t mode) {
assert(con != NULL);
DLOG("Toggling mark \"%s\" on con = %p.\n", mark, con);
if (con_has_mark(con, mark)) {
con_unmark(mark);
} else {
- con_mark(con, mark);
+ con_mark(con, mark, mode);
}
}
* Assigns a mark to the container.
*
*/
-void con_mark(Con *con, const char *mark) {
+void con_mark(Con *con, const char *mark, mark_mode_t mode) {
assert(con != NULL);
DLOG("Setting mark \"%s\" on con = %p.\n", mark, con);
con_unmark(mark);
+ if (mode == MM_REPLACE) {
+ DLOG("Removing all existing marks on con = %p.\n", con);
+
+ mark_t *current;
+ TAILQ_FOREACH(current, &(con->marks_head), marks) {
+ con_unmark(current->name);
+ }
+ }
mark_t *new = scalloc(1, sizeof(mark_t));
new->name = sstrdup(mark);
char *mark;
sasprintf(&mark, "%.*s", (int)len, val);
- con_mark(json_node, mark);
+ con_mark(json_node, mark, MM_ADD);
} else {
if (strcasecmp(last_key, "name") == 0) {
json_node->name = scalloc(len + 1, 1);
char *buf = NULL;
sasprintf(&buf, "%.*s", (int)len, val);
- con_mark(json_node, buf);
+ con_mark(json_node, buf, MM_REPLACE);
} else if (strcasecmp(last_key, "floating") == 0) {
char *buf = NULL;
sasprintf(&buf, "%.*s", (int)len, val);
is_deeply(get_mark_for_window_on_workspace($tmp, $con), [ 'important' ], 'container now has the mark');
##############################################################
-# 7: mark a con, toggle the mark on another con,
+# 7: mark a con, toggle a different mark, check it is marked
+# with the new mark
+##############################################################
+
+$con = open_window;
+cmd 'mark boring';
+cmd 'mark --replace --toggle important';
+is_deeply(get_mark_for_window_on_workspace($tmp, $con), [ 'important' ], 'container has the most recent mark');
+
+##############################################################
+# 8: mark a con, toggle the mark on another con,
# check only the latter has the mark
##############################################################
ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr no longer has the mark');
##############################################################
-# 8: try to mark two cons with the same mark and check that
+# 9: try to mark two cons with the same mark and check that
# it fails
##############################################################
$ws = fresh_workspace;
$con = open_window;
-cmd 'mark A';
-cmd 'mark B';
+cmd 'mark --add A';
+cmd 'mark --add B';
is_deeply(sort(get_marks()), [ 'A', 'B' ], 'both marks exist');
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
$con = open_window;
cmd 'mark A';
-cmd 'mark --toggle B';
+cmd 'mark --add --toggle B';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
-cmd 'mark --toggle B';
+cmd 'mark --add --toggle B';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A' ], 'only mark B has been removed');
cmd 'unmark';
$ws = fresh_workspace;
$con = open_window;
-cmd 'mark A';
-cmd 'mark B';
-cmd 'mark C';
+cmd 'mark --add A';
+cmd 'mark --add B';
+cmd 'mark --add C';
cmd 'unmark B';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'C' ], 'only mark B has been removed');
$ws = fresh_workspace;
$con = open_window;
-cmd 'mark A';
-cmd 'mark B';
+cmd 'mark --add A';
+cmd 'mark --add B';
open_window;
-cmd '[con_mark=B] mark C';
+cmd '[con_mark=B] mark --add C';
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B', 'C' ], 'matching on a mark works with multiple marks');
cmd 'unmark';