Merge pull request #1599 from Airblader/feature-toggle-mark

Added a --toggle switch to the mark command
This commit is contained in:
Michael Stapelberg 2015-03-29 23:02:27 +02:00
commit a99d5463ad
5 changed files with 105 additions and 19 deletions

View File

@ -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
------------------------------

View File

@ -109,10 +109,10 @@ void cmd_workspace_back_and_forth(I3_CMD);
void cmd_workspace_name(I3_CMD, char *name);
/**
* Implementation of 'mark <mark>'
* Implementation of 'mark [--toggle] <mark>'
*
*/
void cmd_mark(I3_CMD, char *mark);
void cmd_mark(I3_CMD, char *mark, char *toggle);
/**
* Implementation of 'unmark [mark]'

View File

@ -189,10 +189,12 @@ state FLOATING:
floating = 'enable', 'disable', 'toggle'
-> call cmd_floating($floating)
# mark <mark>
# mark [--toggle] <mark>
state MARK:
toggle = '--toggle'
->
mark = string
-> call cmd_mark($mark)
-> call cmd_mark($mark, $toggle)
# unmark [mark]
state UNMARK:

View File

@ -1037,26 +1037,41 @@ void cmd_workspace_name(I3_CMD, char *name) {
}
/*
* Implementation of 'mark <mark>'
* Implementation of 'mark [--toggle] <mark>'
*
*/
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;

View File

@ -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;