=== MARKS reply
The reply consists of a single array of strings for each container that has a
-mark. The order of that array is undefined. If more than one container has the
-same mark, it will be represented multiple times in the reply (the array
-contents are not unique).
+mark. A mark can only be set on one container, so the array is unique.
+The order of that array is undefined.
If no window has a mark the response will be the empty array [].
This feature is like the jump feature: It allows you to directly jump to a
specific window (this means switching to the appropriate workspace and setting
focus to the windows). However, you can directly mark a specific window with
-an arbitrary label and use it afterwards. You do not need to ensure that your
-windows have unique classes or titles, and you do not need to change your
-configuration file.
+an arbitrary label and use it afterwards. You can unmark the label in the same
+way, using the unmark command. If you don't specify a label, unmark removes all
+marks. You do not need to ensure that your windows have unique classes or
+titles, and you do not need to change your configuration file.
As the command needs to include the label with which you want to mark the
window, you cannot simply bind it to a key. +i3-input+ is a tool created
------------------------------
mark identifier
[con_mark="identifier"] focus
+unmark identifier
------------------------------
*Example (in a terminal)*:
------------------------------
$ i3-msg mark irssi
$ i3-msg '[con_mark="irssi"] focus'
+$ i3-msg unmark irssi
------------------------------
///////////////////////////////////////////////////////////////////
*/
void cmd_mark(I3_CMD, char *mark);
+/**
+ * Implementation of 'unmark [mark]'
+ *
+ */
+void cmd_unmark(I3_CMD, char *mark);
+
/**
* Implementation of 'mode <string>'.
*
'split' -> SPLIT
'floating' -> FLOATING
'mark' -> MARK
+ 'unmark' -> UNMARK
'resize' -> RESIZE
'rename' -> RENAME
'nop' -> NOP
mark = string
-> call cmd_mark($mark)
+# unmark [mark]
+state UNMARK:
+ end
+ -> call cmd_unmark($mark)
+ mark = string
+ -> call cmd_unmark($mark)
+
# resize
state RESIZE:
way = 'grow', 'shrink'
ysuccess(true);
}
+/*
+ * Implementation of 'unmark [mark]'
+ *
+ */
+void cmd_unmark(I3_CMD, char *mark) {
+ if (mark == NULL) {
+ Con *con;
+ TAILQ_FOREACH(con, &all_cons, all_cons) {
+ FREE(con->mark);
+ }
+ DLOG("removed all window marks");
+ } else {
+ Con *con;
+ TAILQ_FOREACH(con, &all_cons, all_cons) {
+ if (con->mark && strcmp(con->mark, mark) == 0)
+ FREE(con->mark);
+ }
+ DLOG("removed window mark %s\n", mark);
+ }
+
+ cmd_output->needs_tree_render = true;
+ // XXX: default reply for now, make this a better reply
+ ysuccess(true);
+}
+
/*
* Implementation of 'mode <string>'.
*
################################################################################
is(parser_calls('unknown_literal'),
- "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" .
+ "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" .
"ERROR: Your command: unknown_literal\n" .
"ERROR: ^^^^^^^^^^^^^^^",
'error for unknown literal ok');
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# checks if mark and unmark work correctly
+use i3test;
+
+sub get_marks {
+ return i3(get_socket_path())->get_marks->recv;
+}
+
+##############################################################
+# 1: check that there are no marks set yet
+##############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+is_deeply(get_marks(), [], 'no marks set yet');
+
+
+##############################################################
+# 2: mark a con, check that it's marked, unmark it, check that
+##############################################################
+
+my $one = open_window;
+cmd 'mark foo';
+
+is_deeply(get_marks(), ["foo"], 'mark foo set');
+
+cmd 'unmark foo';
+
+is_deeply(get_marks(), [], 'mark foo removed');
+
+##############################################################
+# 3: mark three cons, check that they are marked
+# unmark one con, check that it's unmarked
+# unmark all cons, check that they are unmarked
+##############################################################
+
+my $left = open_window;
+my $middle = open_window;
+my $right = open_window;
+
+cmd 'mark right';
+cmd 'focus left';
+cmd 'mark middle';
+cmd 'focus left';
+cmd 'mark left';
+
+#
+# get_marks replys an array of marks, whose order is undefined,
+# so we use sort to be able to compare the output
+#
+
+is_deeply(sort(get_marks()), ["left","middle","right"], 'all three marks set');
+
+cmd 'unmark right';
+
+is_deeply(sort(get_marks()), ["left","middle"], 'mark right removed');
+
+cmd 'unmark';
+
+is_deeply(get_marks(), [], 'all marks removed');
+
+done_testing;