git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit4aaf1ac3145584526b48fc301f188701b0d94337
parent0ca1788403
authortiosgz <[email protected]>
date2023-10-01 15:49
riverctl: rule-{add,del}: reorder parameters

Previous order was (action, conditions, action argument), current is
(conditions, action, action argument). The old one was an expansion of
(action, conditions), which itself most likely came from the separate
<action>-filter-add commands. On the other hand, the new order keeps
action and its argument together and is in line with the logical flow
(check conditions, apply action).

On shell completions: only bash absolutely needed to be updated. fish
and zsh slightly misbehave regardless of the order.

 completions/bash/riverctl | 21 ++++++++++++++++++++-
 doc/riverctl.1.scd        |  4 ++--
 example/init              |  4 ++--
 river/command/rule.zig    | 23 +++++++++++------------
 4 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/completions/bash/riverctl b/completions/bash/riverctl
index f3d8674..395c6f2 100644
--- a/completions/bash/riverctl
+++ b/completions/bash/riverctl
@@ -1,5 +1,6 @@
 function __riverctl_completion ()
 {
+	local rule_actions="float no-float ssd csd tag"
 	if [ "${COMP_CWORD}" -eq 1 ]
 	then
 		OPTS=" \
@@ -63,7 +64,7 @@ function __riverctl_completion ()
 			"focus-view"|"swap") OPTS="next previous up down left right" ;;
 			"move"|"snap") OPTS="up down left right" ;;
 			"resize") OPTS="horizontal vertical" ;;
-			"rule-add"|"rule-del") OPTS="float no-float ssd csd tag" ;;
+			"rule-add"|"rule-del") OPTS="-app-id -title $rule_actions" ;;
 			"list-rules") OPTS="float ssd tag" ;;
 			"map") OPTS="-release -repeat -layout" ;;
 			"unmap") OPTS="-release" ;;
@@ -114,6 +115,24 @@ function __riverctl_completion ()
 				"scroll-method") OPTS="none two-finger edge button" ;;
 				*) return ;;
 			esac
+		elif [ "${COMP_WORDS[1]:0:5}" == "rule-" ]
+		then
+			case "${COMP_WORDS[2]}" in
+				"-app-id") OPTS="-title $rule_actions" ;;
+				"-title") OPTS="-app-id $rule_actions" ;;
+				*) return ;;
+			esac
+			COMPREPLY=($(compgen -W "${OPTS}" -- "${COMP_WORDS[4]}"))
+		fi
+	elif [ "${COMP_CWORD}" -eq 6 ]
+	then
+		if [ "${COMP_WORDS[1]:0:5}" == "rule-" ]
+		then
+			case "${COMP_WORDS[4]}" in
+				"-app-id"|"-title") OPTS="$rule_actions" ;;
+				*) return ;;
+			esac
+			COMPREPLY=($(compgen -W "${OPTS}" -- "${COMP_WORDS[6]}"))
 		fi
 	else
 		return
diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index e08cd44..b599a90 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -259,7 +259,7 @@ 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_] [_argument_]
+*rule-add* [*-app-id* _glob_|*-title* _glob_] _action_ [_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* _\*_.
@@ -301,7 +301,7 @@ matches everything while _\*\*_ and the empty string are invalid.
 	wishes of the client and may start the view floating based on simple
 	heuristics intended to catch popup-like views.
 
-*rule-del* _action_ [*-app-id* _glob_|*-title* _glob_]
+*rule-del* [*-app-id* _glob_|*-title* _glob_] _action_
 	Delete a rule created using *rule-add* with the given arguments.
 
 *list-rules* *float*|*ssd*|*tag*
diff --git a/example/init b/example/init
index a8e120f..dff995c 100755
--- a/example/init
+++ b/example/init
@@ -151,10 +151,10 @@ riverctl border-color-unfocused 0x586e75
 riverctl set-repeat 50 300
 
 # Make all views with an app-id that starts with "float" and title "foo" start floating.
-riverctl rule-add float -app-id 'float*' -title 'foo'
+riverctl rule-add -app-id 'float*' -title 'foo' float
 
 # Make all views with app-id "bar" and any title use client-side decorations
-riverctl rule-add csd -app-id "bar"
+riverctl rule-add -app-id "bar" csd
 
 # Set the default layout generator to be rivertile and start it.
 # River will send the process group of the init executable SIGTERM on exit.
diff --git a/river/command/rule.zig b/river/command/rule.zig
index 87e7511..33b9b3b 100644
--- a/river/command/rule.zig
+++ b/river/command/rule.zig
@@ -36,20 +36,20 @@ const Action = enum {
 };
 
 pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void {
-    if (args.len < 2) return Error.NotEnoughArguments;
-
     const result = flags.parser([:0]const u8, &.{
         .{ .name = "app-id", .kind = .arg },
         .{ .name = "title", .kind = .arg },
-    }).parse(args[2..]) catch {
+    }).parse(args[1..]) catch {
         return error.InvalidValue;
     };
 
-    const action = std.meta.stringToEnum(Action, args[1]) orelse return Error.UnknownOption;
+    if (result.args.len < 1) return Error.NotEnoughArguments;
+
+    const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption;
 
     const positional_arguments_count: u8 = switch (action) {
-        .float, .@"no-float", .ssd, .csd => 0,
-        .tag => 1,
+        .float, .@"no-float", .ssd, .csd => 1,
+        .tag => 2,
     };
     if (result.args.len > positional_arguments_count) return Error.TooManyArguments;
     if (result.args.len < positional_arguments_count) return Error.NotEnoughArguments;
@@ -78,7 +78,7 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
             server.root.applyPending();
         },
         .tag => {
-            const tag = try fmt.parseInt(u32, result.args[0], 10);
+            const tag = try fmt.parseInt(u32, result.args[1], 10);
             try server.config.tag_rules.add(.{
                 .app_id_glob = app_id_glob,
                 .title_glob = title_glob,
@@ -89,18 +89,17 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
 }
 
 pub fn ruleDel(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void {
-    if (args.len < 2) return Error.NotEnoughArguments;
-
     const result = flags.parser([:0]const u8, &.{
         .{ .name = "app-id", .kind = .arg },
         .{ .name = "title", .kind = .arg },
-    }).parse(args[2..]) catch {
+    }).parse(args[1..]) catch {
         return error.InvalidValue;
     };
 
-    if (result.args.len > 0) return Error.TooManyArguments;
+    if (result.args.len > 1) return Error.TooManyArguments;
+    if (result.args.len < 1) return Error.NotEnoughArguments;
 
-    const action = std.meta.stringToEnum(Action, args[1]) orelse return Error.UnknownOption;
+    const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption;
     const app_id_glob = result.flags.@"app-id" orelse "*";
     const title_glob = result.flags.title orelse "*";