From d51d6d730eb9e832e56ca1558b1a945dbf88869f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 28 Mar 2015 19:12:25 +0100 Subject: [PATCH 1/3] Added a --toggle switch to "mark [--toggle] " This option allows toggling marks on a window without knowing whether the mark is already set or not. It behaves as follows: 1) If the matched window has no mark, the new mark is set. 2) If the matched window has another mark, the old mark is removed and the new mark is set. 3) If the matched window already has the mark, the mark is removed. The behavior that all non-matched windows have this mark removed is kept. fixes #1463 --- include/commands.h | 4 ++-- parser-specs/commands.spec | 6 ++++-- src/commands.c | 42 +++++++++++++++++++++++++------------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/include/commands.h b/include/commands.h index 780a9e8e..0f7e3635 100644 --- a/include/commands.h +++ b/include/commands.h @@ -109,10 +109,10 @@ void cmd_workspace_back_and_forth(I3_CMD); void cmd_workspace_name(I3_CMD, char *name); /** - * Implementation of 'mark ' + * Implementation of 'mark [--toggle] ' * */ -void cmd_mark(I3_CMD, char *mark); +void cmd_mark(I3_CMD, char *mark, char *toggle); /** * Implementation of 'unmark [mark]' diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index 315a9218..87db6cf0 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -189,10 +189,12 @@ state FLOATING: floating = 'enable', 'disable', 'toggle' -> call cmd_floating($floating) -# mark +# mark [--toggle] state MARK: + toggle = '--toggle' + -> mark = string - -> call cmd_mark($mark) + -> call cmd_mark($mark, $toggle) # unmark [mark] state UNMARK: diff --git a/src/commands.c b/src/commands.c index 9b51b3ec..46c75c43 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1037,26 +1037,40 @@ void cmd_workspace_name(I3_CMD, char *name) { } /* - * Implementation of 'mark ' + * Implementation of 'mark [--toggle] ' * */ -void cmd_mark(I3_CMD, char *mark) { - DLOG("Clearing all windows which have that mark first\n"); - - Con *con; - TAILQ_FOREACH(con, &all_cons, all_cons) { - if (con->mark && strcmp(con->mark, mark) == 0) - FREE(con->mark); - } - - DLOG("marking window with str %s\n", mark); - owindow *current; - +void cmd_mark(I3_CMD, char *mark, char *toggle) { HANDLE_EMPTY_MATCH; + owindow *current; TAILQ_FOREACH(current, &owindows, owindows) { DLOG("matching: %p / %s\n", current->con, current->con->name); - current->con->mark = sstrdup(mark); + if (toggle != NULL && current->con->mark && strcmp(current->con->mark, mark) == 0) { + DLOG("removing window mark %s\n", mark); + FREE(current->con->mark); + } else { + DLOG("marking window with str %s\n", mark); + FREE(current->con->mark); + current->con->mark = sstrdup(mark); + } + } + + DLOG("Clearing all non-matched windows with this mark\n"); + Con *con; + TAILQ_FOREACH(con, &all_cons, all_cons) { + /* Skip matched windows, we took care of them already. */ + bool matched = false; + TAILQ_FOREACH(current, &owindows, owindows) + if (current->con == con) { + matched = true; + break; + } + if (matched) + continue; + + if (con->mark && strcmp(con->mark, mark) == 0) + FREE(con->mark); } cmd_output->needs_tree_render = true; From 47222ab2610db8cec9f6549ff00823effd47c008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 28 Mar 2015 19:12:31 +0100 Subject: [PATCH 2/3] Updated docs for #1463 --- docs/userguide | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/userguide b/docs/userguide index 3d935e40..d6dbde00 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1857,9 +1857,13 @@ window, you cannot simply bind it to a key. +i3-input+ is a tool created for this purpose: It lets you input a command and sends the command to i3. It 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. + *Syntax*: ------------------------------ -mark identifier +mark [--toggle] identifier [con_mark="identifier"] focus unmark identifier ------------------------------ From 7a75cb7e0ba20f373e9340f6c75ad873fa4b75fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 28 Mar 2015 23:14:59 +0100 Subject: [PATCH 3/3] Added test cases for 'mark --toggle' (#1463) --- src/commands.c | 9 ++--- testcases/t/210-mark-unmark.t | 65 +++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/commands.c b/src/commands.c index 46c75c43..ea0b9032 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1061,10 +1061,11 @@ void cmd_mark(I3_CMD, char *mark, char *toggle) { TAILQ_FOREACH(con, &all_cons, all_cons) { /* Skip matched windows, we took care of them already. */ bool matched = false; - TAILQ_FOREACH(current, &owindows, owindows) - if (current->con == con) { - matched = true; - break; + TAILQ_FOREACH(current, &owindows, owindows) { + if (current->con == con) { + matched = true; + break; + } } if (matched) continue; diff --git a/testcases/t/210-mark-unmark.t b/testcases/t/210-mark-unmark.t index f285338b..0083547f 100644 --- a/testcases/t/210-mark-unmark.t +++ b/testcases/t/210-mark-unmark.t @@ -16,11 +16,19 @@ # # checks if mark and unmark work correctly use i3test; +use List::Util qw(first); sub get_marks { return i3(get_socket_path())->get_marks->recv; } +sub get_mark_for_window_on_workspace { + my ($ws, $con) = @_; + + my $current = first { $_->{window} == $con->{id} } @{get_ws_content($ws)}; + return $current->{mark}; +} + ############################################################## # 1: check that there are no marks set yet ############################################################## @@ -76,4 +84,61 @@ cmd 'unmark'; is_deeply(get_marks(), [], 'all marks removed'); +############################################################## +# 4: mark a con, use same mark to mark another con, +# check that only the latter is marked +############################################################## + +my $first = open_window; +my $second = open_window; + +cmd 'mark important'; +cmd 'focus left'; +cmd 'mark important'; + +is(get_mark_for_window_on_workspace($tmp, $first), 'important', 'first container now has the mark'); +ok(!get_mark_for_window_on_workspace($tmp, $second), 'second container lost the mark'); + +############################################################## +# 5: mark a con, toggle the mark, check that the mark is gone +############################################################## + +my $con = open_window; +cmd 'mark important'; +cmd 'mark --toggle important'; +ok(!get_mark_for_window_on_workspace($tmp, $con), 'container no longer has the mark'); + +############################################################## +# 6: toggle a mark on an unmarked con, check it is marked +############################################################## + +my $con = open_window; +cmd 'mark --toggle important'; +is(get_mark_for_window_on_workspace($tmp, $con), 'important', 'container now has the mark'); + +############################################################## +# 7: mark a con, toggle a different mark, check it is marked +# with the new mark +############################################################## + +my $con = open_window; +cmd 'mark boring'; +cmd 'mark --toggle important'; +is(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 +############################################################## + +my $first = open_window; +my $second = open_window; + +cmd 'mark important'; +cmd 'focus left'; +cmd 'mark --toggle important'; + +is(get_mark_for_window_on_workspace($tmp, $first), 'important', 'left container has the mark now'); +ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr no longer has the mark'); + done_testing;