add command to remove marks
Patch status: needinfo
Patch by koebi
To apply this patch, use:
curl http://cr.i3wm.org/patch/191/raw.patch | git am
b/docs/ipc
21 |
@@ -458,9 +458,7 @@ JSON dump: |
22 |
=== MARKS reply |
23 |
|
24 |
The reply consists of a single array of strings for each container that has a |
25 |
-mark. The order of that array is undefined. If more than one container has the |
26 |
-same mark, it will be represented multiple times in the reply (the array |
27 |
-contents are not unique). |
28 |
+mark. The order of that array is undefined. |
29 |
|
30 |
If no window has a mark the response will be the empty array []. |
31 |
|
b/docs/userguide
36 |
@@ -1679,9 +1679,10 @@ bindsym $mod+a [class="urxvt" title="VIM"] focus |
37 |
This feature is like the jump feature: It allows you to directly jump to a |
38 |
specific window (this means switching to the appropriate workspace and setting |
39 |
focus to the windows). However, you can directly mark a specific window with |
40 |
-an arbitrary label and use it afterwards. You do not need to ensure that your |
41 |
-windows have unique classes or titles, and you do not need to change your |
42 |
-configuration file. |
43 |
+an arbitrary label and use it afterwards. You can unmark the label in the same |
44 |
+way, using the unmark command. If you don't specify a label, unmark removes all |
45 |
+marks. You do not need to ensure that your windows have unique classes or |
46 |
+titles, and you do not need to change your configuration file. |
47 |
|
48 |
As the command needs to include the label with which you want to mark the |
49 |
window, you cannot simply bind it to a key. +i3-input+ is a tool created |
50 |
@@ -1692,12 +1693,14 @@ can also prefix this command and display a custom prompt for the input dialog. |
51 |
------------------------------ |
52 |
mark identifier |
53 |
[con_mark="identifier"] focus |
54 |
+unmark identifier |
55 |
------------------------------ |
56 |
|
57 |
*Example (in a terminal)*: |
58 |
------------------------------ |
59 |
$ i3-msg mark irssi |
60 |
$ i3-msg '[con_mark="irssi"] focus' |
61 |
+$ i3-msg unmark irssi |
62 |
------------------------------ |
63 |
|
64 |
/////////////////////////////////////////////////////////////////// |
b/include/commands.h
69 |
@@ -116,6 +116,12 @@ void cmd_workspace_name(I3_CMD, char *name); |
70 |
void cmd_mark(I3_CMD, char *mark); |
71 |
|
72 |
/** |
73 |
+ * Implementation of 'unmark [mark]' |
74 |
+ * |
75 |
+ */ |
76 |
+void cmd_unmark(I3_CMD, char *mark); |
77 |
+ |
78 |
+/** |
79 |
* Implementation of 'mode <string>'. |
80 |
* |
81 |
*/ |
b/parser-specs/commands.spec
86 |
@@ -32,6 +32,7 @@ state INITIAL: |
87 |
'split' -> SPLIT |
88 |
'floating' -> FLOATING |
89 |
'mark' -> MARK |
90 |
+ 'unmark' -> UNMARK |
91 |
'resize' -> RESIZE |
92 |
'rename' -> RENAME |
93 |
'nop' -> NOP |
94 |
@@ -177,6 +178,13 @@ state MARK: |
95 |
mark = string |
96 |
-> call cmd_mark($mark) |
97 |
|
98 |
+# unmark [mark] |
99 |
+state UNMARK: |
100 |
+ end |
101 |
+ -> call cmd_unmark($mark) |
102 |
+ mark = string |
103 |
+ -> call cmd_unmark($mark) |
104 |
+ |
105 |
# resize |
106 |
state RESIZE: |
107 |
way = 'grow', 'shrink' |
b/src/commands.c
112 |
@@ -1032,6 +1032,31 @@ void cmd_mark(I3_CMD, char *mark) { |
113 |
} |
114 |
|
115 |
/* |
116 |
+ * Implementation of 'unmark [mark]' |
117 |
+ * |
118 |
+ */ |
119 |
+void cmd_unmark(I3_CMD, char *mark) { |
120 |
+ if (mark == NULL) { |
121 |
+ Con *con; |
122 |
+ TAILQ_FOREACH(con, &all_cons, all_cons) { |
123 |
+ FREE(con->mark); |
124 |
+ } |
125 |
+ DLOG("removed all window marks"); |
126 |
+ } else { |
127 |
+ Con *con; |
128 |
+ TAILQ_FOREACH(con, &all_cons, all_cons) { |
129 |
+ if (con->mark && strcmp(con->mark, mark) == 0) |
130 |
+ FREE(con->mark); |
131 |
+ } |
132 |
+ DLOG("removed window mark %s\n", mark); |
133 |
+ } |
134 |
+ |
135 |
+ cmd_output->needs_tree_render = true; |
136 |
+ // XXX: default reply for now, make this a better reply |
137 |
+ ysuccess(true); |
138 |
+} |
139 |
+ |
140 |
+/* |
141 |
* Implementation of 'mode <string>'. |
142 |
* |
143 |
*/ |
b/testcases/t/173-get-marks.t
148 |
@@ -46,6 +46,6 @@ is_deeply(get_marks(), [ 'foo' ], 'mark foo set'); |
149 |
|
150 |
cmd 'kill'; |
151 |
|
152 |
-is_deeply(get_marks(), [ ], 'mark gone'); |
153 |
+is_deeply(get_marks(), [], 'mark gone'); |
154 |
|
155 |
done_testing; |
b/testcases/t/187-commands-parser.t
160 |
@@ -144,7 +144,7 @@ is(parser_calls("\nworkspace test"), |
161 |
################################################################################ |
162 |
|
163 |
is(parser_calls('unknown_literal'), |
164 |
- "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" . |
165 |
+ "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" . |
166 |
"ERROR: Your command: unknown_literal\n" . |
167 |
"ERROR: ^^^^^^^^^^^^^^^", |
168 |
'error for unknown literal ok'); |
b/testcases/t/210-mark-unmark.t
174 |
@@ -0,0 +1,79 @@ |
175 |
+#!perl |
176 |
+# vim:ts=4:sw=4:expandtab |
177 |
+# |
178 |
+# Please read the following documents before working on tests: |
179 |
+# • http://build.i3wm.org/docs/testsuite.html |
180 |
+# (or docs/testsuite) |
181 |
+# |
182 |
+# • http://build.i3wm.org/docs/lib-i3test.html |
183 |
+# (alternatively: perldoc ./testcases/lib/i3test.pm) |
184 |
+# |
185 |
+# • http://build.i3wm.org/docs/ipc.html |
186 |
+# (or docs/ipc) |
187 |
+# |
188 |
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf |
189 |
+# (unless you are already familiar with Perl) |
190 |
+# |
191 |
+# checks if mark and unmark work correctly |
192 |
+use i3test; |
193 |
+ |
194 |
+sub get_marks { |
195 |
+ return i3(get_socket_path())->get_marks->recv; |
196 |
+} |
197 |
+ |
198 |
+############################################################## |
199 |
+# 1: check that there are no marks set yet |
200 |
+############################################################## |
201 |
+ |
202 |
+my $tmp = fresh_workspace; |
203 |
+ |
204 |
+cmd 'split h'; |
205 |
+ |
206 |
+is_deeply(get_marks(), [], 'no marks set yet'); |
207 |
+ |
208 |
+ |
209 |
+############################################################## |
210 |
+# 2: mark a con, check that it's marked, unmark it, check that |
211 |
+############################################################## |
212 |
+ |
213 |
+my $one = open_window; |
214 |
+cmd 'mark foo'; |
215 |
+ |
216 |
+is_deeply(get_marks(), ["foo"], 'mark foo set'); |
217 |
+ |
218 |
+cmd 'unmark foo'; |
219 |
+ |
220 |
+is_deeply(get_marks(), [], 'mark foo removed'); |
221 |
+ |
222 |
+############################################################## |
223 |
+# 3: mark three cons, check that they are marked |
224 |
+# unmark one con, check that it's unmarked |
225 |
+# unmark all cons, check that they are unmarked |
226 |
+############################################################## |
227 |
+ |
228 |
+my $left = open_window; |
229 |
+my $middle = open_window; |
230 |
+my $right = open_window; |
231 |
+ |
232 |
+cmd 'mark right'; |
233 |
+cmd 'focus left'; |
234 |
+cmd 'mark middle'; |
235 |
+cmd 'focus left'; |
236 |
+cmd 'mark left'; |
237 |
+ |
238 |
+# |
239 |
+# get_marks replys an array of marks, whose order is undefined, |
240 |
+# so we use sort to be able to compare the output |
241 |
+# |
242 |
+ |
243 |
+is_deeply(sort(get_marks()), ["left","middle","right"], 'all three marks set'); |
244 |
+ |
245 |
+cmd 'unmark right'; |
246 |
+ |
247 |
+is_deeply(sort(get_marks()), ["left","middle"], 'mark right removed'); |
248 |
+ |
249 |
+cmd 'unmark'; |
250 |
+ |
251 |
+is_deeply(get_marks(), [], 'all marks removed'); |
252 |
+ |
253 |
+done_testing; |