diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index d0476ea..ab97d6d 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -122,10 +122,13 @@ At least one tag must always be focused and each view must be assigned at least one tag. Operations that would violate either of these requirements are ignored by river. -*set-focused-tags* _tags_ +*set-focused-tags* [*-alternate*] _tags_ Show views with tags corresponding to the set bits of _tags_ on the currently focused output. + - *-alternate*: If the currently focused tags are equal to _tags_, focus + the previous tags (see *focus-previous-tags*). + *set-view-tags* _tags_ Assign the currently focused view the tags corresponding to the set bits of _tags_. diff --git a/river/command/tags.zig b/river/command/tags.zig index d1ac8da..52e9db8 100644 --- a/river/command/tags.zig +++ b/river/command/tags.zig @@ -16,6 +16,7 @@ const std = @import("std"); const mem = std.mem; +const flags = @import("flags"); const server = &@import("../main.zig").server; const util = @import("../util.zig"); @@ -29,12 +30,26 @@ pub fn setFocusedTags( args: []const [:0]const u8, out: *?[]const u8, ) Error!void { - const tags = try parseTags(args, out); + if (args.len < 2) return Error.NotEnoughArguments; + const result = flags.parser([:0]const u8, &.{ + .{ .name = "alternate", .kind = .boolean }, + }).parse(args[1..]) catch { + return error.InvalidOption; + }; + if (result.args.len < 1) return Error.NotEnoughArguments; + if (result.args.len > 1) return Error.TooManyArguments; + + const tags = try parseTagsAt(result.args[0], out); + const output = seat.focused_output orelse return; if (output.pending.tags != tags) { output.previous_tags = output.pending.tags; output.pending.tags = tags; server.root.applyPending(); + } else if (output.pending.tags == tags and result.flags.alternate) { + output.pending.tags = output.previous_tags; + output.previous_tags = tags; + server.root.applyPending(); } } @@ -133,7 +148,14 @@ fn parseTags( if (args.len < 2) return Error.NotEnoughArguments; if (args.len > 2) return Error.TooManyArguments; - const tags = try std.fmt.parseInt(u32, args[1], 10); + return parseTagsAt(args[1], out); +} + +fn parseTagsAt( + arg: [:0]const u8, + out: *?[]const u8, +) Error!u32 { + const tags = try std.fmt.parseInt(u32, arg, 10); if (tags == 0) { out.* = try std.fmt.allocPrint(util.gpa, "tags may not be 0", .{});