river: add tags rule
This commit is contained in:
		| @ -62,8 +62,8 @@ function __riverctl_completion () | ||||
| 			"focus-output"|"focus-view"|"send-to-output"|"swap") OPTS="next previous" ;; | ||||
| 			"move"|"snap") OPTS="up down left right" ;; | ||||
| 			"resize") OPTS="horizontal vertical" ;; | ||||
| 			"rule-add"|"rule-del") OPTS="float no-float ssd csd" ;; | ||||
| 			"list-rules") OPTS="float ssd" ;; | ||||
| 			"rule-add"|"rule-del") OPTS="float no-float ssd csd tag" ;; | ||||
| 			"list-rules") OPTS="float ssd tag" ;; | ||||
| 			"map") OPTS="-release -repeat -layout" ;; | ||||
| 			"unmap") OPTS="-release" ;; | ||||
| 			"attach-mode") OPTS="top bottom" ;; | ||||
|  | ||||
| @ -83,9 +83,9 @@ complete -c riverctl -x -n '__fish_seen_subcommand_from unmap'                -a | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from attach-mode'          -a 'top bottom' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from focus-follows-cursor' -a 'disabled normal always' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from set-cursor-warp'      -a 'disabled on-output-change on-focus-change' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from rule-add'             -a 'float no-float ssd csd' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from rule-del'             -a 'float no-float ssd csd' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from list-rules'           -a 'float ssd' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from rule-add'             -a 'float no-float ssd csd tag' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from rule-del'             -a 'float no-float ssd csd tag' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from list-rules'           -a 'float ssd tag' | ||||
|  | ||||
| # Subcommands for 'input' | ||||
| complete -c riverctl -x -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 2' -a "(__riverctl_list_input_devices)" | ||||
|  | ||||
| @ -183,9 +183,9 @@ _riverctl() | ||||
|                 focus-follows-cursor) _alternative 'arguments:args:(disabled normal always)' ;; | ||||
|                 set-cursor-warp) _alternative 'arguments:args:(disabled on-output-change on-focus-change)' ;; | ||||
|                 hide-cursor) _riverctl_hide_cursor ;; | ||||
|                 rule-add) _alternative 'arguments:args:(float no-float ssd csd)' ;; | ||||
|                 rule-del) _alternative 'arguments:args:(float no-float ssd csd)' ;; | ||||
|                 list-rules) _alternative 'arguments:args:(float ssd)' ;; | ||||
|                 rule-add) _alternative 'arguments:args:(float no-float ssd csd tag)' ;; | ||||
|                 rule-del) _alternative 'arguments:args:(float no-float ssd csd tag)' ;; | ||||
|                 list-rules) _alternative 'arguments:args:(float ssd tag)' ;; | ||||
|                 *) return 0 ;; | ||||
|             esac | ||||
|         ;; | ||||
|  | ||||
| @ -258,10 +258,11 @@ For example, _abc_ is matched by _a\*_, _\*a\*_, _\*b\*_, _\*c_, _abc_, and | ||||
| _\*_ but not matched by _\*a_, _b\*_, _\*b_, _c\*_, or _ab_. Note that _\*_ | ||||
| matches everything while _\*\*_ and the empty string are invalid. | ||||
|  | ||||
| *rule-add* _action_ [*-app-id* _glob_|*-title* _glob_] | ||||
| *rule-add* _action_ [*-app-id* _glob_|*-title* _glob_] [_argument_] | ||||
| 	Add a rule that applies an _action_ to views with *app-id* and *title* | ||||
| 	matched by the respective _glob_. Omitting *-app-id* or *-title* | ||||
| 	is equivalent to passing *-app-id* _\*_ or *-title* _\*_. | ||||
| 	Some actions require an _argument_. | ||||
|  | ||||
| 	The supported _action_ types are: | ||||
|  | ||||
| @ -272,6 +273,8 @@ matches everything while _\*\*_ and the empty string are invalid. | ||||
| 	  and existing views. | ||||
| 	- *csd*: Use client-side decorations for the view. Applies to new | ||||
| 	  and existing views. | ||||
| 	- *tag*: Set the initial tags of the view. Requires the tags as | ||||
| 	  an argument. Applies only to new views. | ||||
|  | ||||
| 	Both *float* and *no-float* rules are added to the same list, | ||||
| 	which means that adding a *no-float* rule with the same arguments | ||||
| @ -300,7 +303,7 @@ matches everything while _\*\*_ and the empty string are invalid. | ||||
| *rule-del* _action_ [*-app-id* _glob_|*-title* _glob_] | ||||
| 	Delete a rule created using *rule-add* with the given arguments. | ||||
|  | ||||
| *list-rules* *float*|*ssd* | ||||
| *list-rules* *float*|*ssd*|*tag* | ||||
| 	Print the specified rule list. The output is ordered from most specific | ||||
| 	to least specific, the same order in which views are checked against | ||||
| 	when searching for a match. Only the first matching rule in the list | ||||
|  | ||||
| @ -75,6 +75,7 @@ modes: std.ArrayListUnmanaged(Mode), | ||||
|  | ||||
| float_rules: RuleList(bool) = .{}, | ||||
| ssd_rules: RuleList(bool) = .{}, | ||||
| tag_rules: RuleList(u32) = .{}, | ||||
|  | ||||
| /// The selected focus_follows_cursor mode | ||||
| focus_follows_cursor: FocusFollowsCursorMode = .disabled, | ||||
| @ -150,6 +151,7 @@ pub fn deinit(self: *Self) void { | ||||
|  | ||||
|     self.float_rules.deinit(); | ||||
|     self.ssd_rules.deinit(); | ||||
|     self.tag_rules.deinit(); | ||||
|  | ||||
|     util.gpa.free(self.default_layout_namespace); | ||||
|  | ||||
|  | ||||
| @ -508,6 +508,7 @@ pub fn map(view: *Self) !void { | ||||
|         view.pending.box.y = @divTrunc(math.max(0, output.usable_box.height - view.pending.box.height), 2); | ||||
|  | ||||
|         view.pending.tags = blk: { | ||||
|             if (server.config.tag_rules.match(view)) |tags| break :blk tags; | ||||
|             const tags = output.pending.tags & server.config.spawn_tagmask; | ||||
|             break :blk if (tags != 0) tags else output.pending.tags; | ||||
|         }; | ||||
|  | ||||
| @ -32,6 +32,7 @@ const Action = enum { | ||||
|     @"no-float", | ||||
|     ssd, | ||||
|     csd, | ||||
|     tag, | ||||
| }; | ||||
|  | ||||
| pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void { | ||||
| @ -44,9 +45,14 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void | ||||
|         return error.InvalidValue; | ||||
|     }; | ||||
|  | ||||
|     if (result.args.len > 0) return Error.TooManyArguments; | ||||
|  | ||||
|     const action = std.meta.stringToEnum(Action, args[1]) orelse return Error.UnknownOption; | ||||
|  | ||||
|     const positional_arguments_count: u8 = switch (action) { | ||||
|         .float, .@"no-float", .ssd, .csd => 0, | ||||
|         .tag => 1, | ||||
|     }; | ||||
|     if (result.args.len > positional_arguments_count) return Error.TooManyArguments; | ||||
|  | ||||
|     const app_id_glob = result.flags.@"app-id" orelse "*"; | ||||
|     const title_glob = result.flags.title orelse "*"; | ||||
|  | ||||
| @ -70,6 +76,14 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void | ||||
|             apply_ssd_rules(); | ||||
|             server.root.applyPending(); | ||||
|         }, | ||||
|         .tag => { | ||||
|             const tag = try fmt.parseInt(u32, result.args[0], 10); | ||||
|             try server.config.tag_rules.add(.{ | ||||
|                 .app_id_glob = app_id_glob, | ||||
|                 .title_glob = title_glob, | ||||
|                 .value = tag, | ||||
|             }); | ||||
|         }, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -104,6 +118,12 @@ pub fn ruleDel(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void | ||||
|             apply_ssd_rules(); | ||||
|             server.root.applyPending(); | ||||
|         }, | ||||
|         .tag => { | ||||
|             server.config.tag_rules.del(.{ | ||||
|                 .app_id_glob = app_id_glob, | ||||
|                 .title_glob = title_glob, | ||||
|             }); | ||||
|         }, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -120,10 +140,15 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error! | ||||
|     if (args.len < 2) return error.NotEnoughArguments; | ||||
|     if (args.len > 2) return error.TooManyArguments; | ||||
|  | ||||
|     const list = std.meta.stringToEnum(enum { float, ssd }, args[1]) orelse return Error.UnknownOption; | ||||
|     const list = std.meta.stringToEnum(enum { | ||||
|         float, | ||||
|         ssd, | ||||
|         tag, | ||||
|     }, args[1]) orelse return Error.UnknownOption; | ||||
|     const max_glob_len = switch (list) { | ||||
|         .float => server.config.float_rules.getMaxGlobLen(), | ||||
|         .ssd => server.config.ssd_rules.getMaxGlobLen(), | ||||
|         .tag => server.config.tag_rules.getMaxGlobLen(), | ||||
|     }; | ||||
|     const app_id_column_max = 2 + @max("app-id".len, max_glob_len.app_id); | ||||
|     const title_column_max = 2 + @max("title".len, max_glob_len.title); | ||||
| @ -140,6 +165,7 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error! | ||||
|             const rules = switch (list) { | ||||
|                 .float => server.config.float_rules.rules.items, | ||||
|                 .ssd => server.config.ssd_rules.rules.items, | ||||
|                 else => unreachable, | ||||
|             }; | ||||
|             for (rules) |rule| { | ||||
|                 try fmt.formatBuf(rule.title_glob, .{ .width = title_column_max, .alignment = .Left }, writer); | ||||
| @ -147,9 +173,18 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error! | ||||
|                 try writer.print("{s}\n", .{switch (list) { | ||||
|                     .float => if (rule.value) "float" else "no-float", | ||||
|                     .ssd => if (rule.value) "ssd" else "csd", | ||||
|                     else => unreachable, | ||||
|                 }}); | ||||
|             } | ||||
|         }, | ||||
|         .tag => { | ||||
|             const rules = server.config.tag_rules.rules.items; | ||||
|             for (rules) |rule| { | ||||
|                 try fmt.formatBuf(rule.title_glob, .{ .width = title_column_max, .alignment = .Left }, writer); | ||||
|                 try fmt.formatBuf(rule.app_id_glob, .{ .width = app_id_column_max, .alignment = .Left }, writer); | ||||
|                 try writer.print("{b}\n", .{rule.value}); | ||||
|             } | ||||
|         }, | ||||
|     } | ||||
|  | ||||
|     out.* = buffer.toOwnedSlice(); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user