summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2024-04-10 18:33:20 +0800
committerSean Whitton <spwhitton@spwhitton.name>2024-04-10 18:33:20 +0800
commit08192cb0e667cb9eeb8e5760f57f97509490d871 (patch)
treec363530c74a82a7723fe9187f37d8032cd03d752
parentc0317dd8fce1df1374a60bbb9f67b71c5ed5fbcc (diff)
downloaddotfiles-08192cb0e667cb9eeb8e5760f57f97509490d871.tar.gz
i3status-wrapper: refactor: move processing user commands into a sub
-rwxr-xr-xscripts/desktop/i3status-wrapper382
1 files changed, 190 insertions, 192 deletions
diff --git a/scripts/desktop/i3status-wrapper b/scripts/desktop/i3status-wrapper
index 8cde0a94..054e804a 100755
--- a/scripts/desktop/i3status-wrapper
+++ b/scripts/desktop/i3status-wrapper
@@ -220,198 +220,7 @@ unless (fork // warn "couldn't fork command pipe reader") {
while (my $cmd = <$cmdpipe_r>) {
tied(%info)->lock;
-
- my $ws = $info{paper_ws}{$info{focused_ws}};
- my $cols = $ws->{cols};
- my $col_rows = $info{col_rows}{$ws->{focused_col}};
- my $i = first { $cols->[$_] == $ws->{focused_col} } 0..$#$cols;
-
- my $mv = sub {
- my ($j, $move) = @_;
- if (@$cols > $j >= 0) {
- if ($move) {
- # This does not trigger any events.
- $wmipc->cmd(
-"[con_id=@$cols[$i]] swap container with con_id @$cols[$j]"
- );
- @$cols[$i, $j] = @$cols[$j, $i];
- } else {
- $wmipc->cmd($j > $i ? "focus right" : "focus left");
- }
- } elsif ($move && $ws->{monocle}) {
- if ($j > $i && $ws->{off_right}->@*) {
- push $ws->{off_left}->@*, pop $ws->{off_right}->@*;
- } elsif ($j < $i && $ws->{off_left}->@*) {
- push $ws->{off_right}->@*, pop $ws->{off_left}->@*;
- }
- } elsif ($j == @$cols && $ws->{off_right}->@*) {
- my $pushed = shift @$cols;
- my $pulled = pop $ws->{off_right}->@*;
- my @cmds = show_con($pulled);
- push $ws->{off_left}->@*, $pushed;
-
- if ($move) {
- if ($col_rows || @$cols) {
- push @cmds, $col_rows
- ? "move left"
- : "swap container with con_id @$cols[-1]";
- push @cmds, "focus right";
- }
- if (@$cols) {
- my $tem = pop @$cols;
- push @$cols, $pulled, $tem;
- } else {
- push @$cols, $pulled;
- }
- } else {
- $ws->{focused_col} = $pulled;
- push @cmds, "move right" if $col_rows;
- push @$cols, $pulled;
- push @cmds, "focus child" if $info{col_rows}{$pulled};
- }
-
- with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) };
- kill USR1 => $i3status;
- } elsif ($j == -1 && $ws->{off_left}->@*) {
- my $pushed = pop @$cols;
- my $pulled = pop $ws->{off_left}->@*;
- my @cmds = show_con($pulled);
-
- push $ws->{off_right}->@*, $pushed;
-
- if ($move) {
- if (@$cols) {
- push @cmds, "move right" if $col_rows;
- push @cmds, "focus left";
- my $tem = shift @$cols;
- unshift @$cols, $tem, $pulled;
- } else {
- unshift @$cols, $pulled;
- }
- } else {
- if ($col_rows) {
- push @cmds, "move left";
- } elsif (@$cols) {
- push @cmds, "swap container with con_id @$cols[0]";
- }
- $ws->{focused_col} = $pulled;
- unshift @$cols, $pulled;
- push @cmds, "focus child" if $info{col_rows}{$pulled};
- }
-
- with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) };
- kill USR1 => $i3status;
- }
- $ws->{last_dir} = $j > $i ? 1 : -1;
- };
-
- # Command dispatch
-
- if ($cmd =~ /^(focus|move) (left|right)$/) {
- $mv->($2 eq "right" ? $i+1 : $i-1, $1 eq "move");
- } elsif ($cmd =~ /^cols (incr|decr)$/) {
- $ws->{ncols} += $1 eq "incr" ? 1 : -1;
- normalise_ws_cols();
- kill USR1 => $i3status;
- }
-
- elsif ($cmd =~ /^other column$/) {
- # This is meant to be similar to my custom Emacs C-x o.
- if ($i == 0 || $ws->{last_dir} == -1 && $i < $#$cols) {
- $mv->($i+1);
- } elsif ($i == $#$cols || $ws->{last_dir} == 1) {
- $mv->($i-1);
- }
- } elsif ($cmd eq "monocle toggle\n") {
- unless (ensure_disable_monocle($ws)) {
- $ws->{monocle} = -$i-1;
- normalise_ws_cols();
- }
- kill USR1 => $i3status;
- }
-
- elsif ($cmd =~ /^fresh-workspace ?(take|send)?$/) {
- fresh_workspace(do {
- if ($1 && $1 eq "take") {
- go => 1, send => 1;
- } elsif ($1 && $1 eq "send") {
- send => 1;
- } else {
- go => 1;
- }
- });
- }
-
- elsif ($cmd =~ /^absorb_expel ?(left|right)?$/) {
- my $dir = $1 eq "right" ? 1 : -1;
- if ($col_rows > 1) { # expel
- # If the column to the right or left also has rows, we'll just
- # move the container into that column instead of expelling it.
- # Possibly we could float the container, select the
- # appropriate full column and unfloat it into place?
- $wmipc->cmd(sprintf "move %s", $dir > 0 ? "right" : "left");
- $ws->{last_dir} = $dir;
- } else { # absorb
- my @cmds;
- if ($i == 0 && $dir < 0 && $ws->{off_left}->@*) {
- my $pulled = pop $ws->{off_left}->@*;
- push @cmds, show_con($pulled), "move left";
- push @cmds, "splitv" unless $info{col_rows}{$pulled};
- push @cmds, "focus right", "move left";
-
- with_ignored_events { $wmipc->cmd(@cmds) };
- normalise_ws_cols();
- } elsif ($i == $#$cols && $dir > 0 && $ws->{off_right}->@*) {
- my $pulled = pop $ws->{off_right}->@*;
- push @cmds, show_con($pulled);
- push @cmds, "move right" if $col_rows;
- push @cmds, "splitv" unless $info{col_rows}{$pulled};
- push @cmds, "focus left", "move right";
-
- with_ignored_events { $wmipc->cmd(@cmds) };
- normalise_ws_cols();
- } elsif ($i == $#$cols && $dir < 0
- || $#$cols > $i > 0
- || $i == 0 && $dir > 0) {
- push @cmds, $dir > 0
- ? ("focus right", "splitv", "focus left")
- : ("focus left", "splitv", "focus right")
- unless $info{col_rows}{ @$cols[$i+$dir] };
- push @cmds, $dir > 0 ? "move right" : "move left";
-
- with_ignored_events { $wmipc->cmd(@cmds) };
- normalise_ws_cols($ws->{off_left}->@* && $dir > 0
- || $ws->{off_right}->@* && $dir < 0
- ? min($#$cols, max 0, $i+$dir) : $i);
- }
- if (@cmds) {
- $ws->{last_dir} = $dir;
- kill USR1 => $i3status;
- }
- }
- }
-
- # Basic purpose of this wrapper command is to prevent accidentally
- # moving to one of the holding workspaces using Sway's own commands.
- elsif ($cmd =~ /^(move_)?workspace (prev|next)$/) {
- my ($move, $dir) = (!!$1, $2);
- $move && ensure_disable_monocle($ws);
- my @keys = sorted_paper_ws();
- my $k = first { $keys[$_] == $info{focused_ws} } 0..$#keys;
- if ($dir eq "next" && $k < $#keys || $dir eq "prev" && $k > 0) {
- my @cmds = "workspace $dir";
- $info{focused_ws} = $keys[$dir eq "next" ? $k+1 : $k-1];
- if ($move) {
- push @cmds, show_con($ws->{focused_col});
- push @cmds, "move right"
- if $info{col_rows}
- { $info{paper_ws}{$info{focused_ws}}{focused_col} };
- push @cmds, "focus child" if $col_rows;
- }
- $wmipc->cmd(@cmds);
- }
- }
-
+ process_msg($cmd);
tied(%info)->unlock;
}
}
@@ -670,6 +479,195 @@ sub normalise_ws_cols {
}
}
+sub process_msg {
+ my $cmd = shift;
+
+ my $ws = $info{paper_ws}{$info{focused_ws}};
+ my $cols = $ws->{cols};
+ my $col_rows = $info{col_rows}{$ws->{focused_col}};
+ my $i = first { $cols->[$_] == $ws->{focused_col} } 0..$#$cols;
+
+ my $mv = sub {
+ my ($j, $move) = @_;
+ if (@$cols > $j >= 0) {
+ if ($move) {
+ # This does not trigger any events.
+ $wmipc->cmd(
+"[con_id=@$cols[$i]] swap container with con_id @$cols[$j]"
+ );
+ @$cols[$i, $j] = @$cols[$j, $i];
+ } else {
+ $wmipc->cmd($j > $i ? "focus right" : "focus left");
+ }
+ } elsif ($move && $ws->{monocle}) {
+ if ($j > $i && $ws->{off_right}->@*) {
+ push $ws->{off_left}->@*, pop $ws->{off_right}->@*;
+ } elsif ($j < $i && $ws->{off_left}->@*) {
+ push $ws->{off_right}->@*, pop $ws->{off_left}->@*;
+ }
+ } elsif ($j == @$cols && $ws->{off_right}->@*) {
+ my $pushed = shift @$cols;
+ my $pulled = pop $ws->{off_right}->@*;
+ my @cmds = show_con($pulled);
+ push $ws->{off_left}->@*, $pushed;
+
+ if ($move) {
+ if ($col_rows || @$cols) {
+ push @cmds, $col_rows
+ ? "move left"
+ : "swap container with con_id @$cols[-1]";
+ push @cmds, "focus right";
+ }
+ if (@$cols) {
+ my $tem = pop @$cols;
+ push @$cols, $pulled, $tem;
+ } else {
+ push @$cols, $pulled;
+ }
+ } else {
+ $ws->{focused_col} = $pulled;
+ push @cmds, "move right" if $col_rows;
+ push @$cols, $pulled;
+ push @cmds, "focus child" if $info{col_rows}{$pulled};
+ }
+
+ with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) };
+ kill USR1 => $i3status;
+ } elsif ($j == -1 && $ws->{off_left}->@*) {
+ my $pushed = pop @$cols;
+ my $pulled = pop $ws->{off_left}->@*;
+ my @cmds = show_con($pulled);
+
+ push $ws->{off_right}->@*, $pushed;
+
+ if ($move) {
+ if (@$cols) {
+ push @cmds, "move right" if $col_rows;
+ push @cmds, "focus left";
+ my $tem = shift @$cols;
+ unshift @$cols, $tem, $pulled;
+ } else {
+ unshift @$cols, $pulled;
+ }
+ } else {
+ if ($col_rows) {
+ push @cmds, "move left";
+ } elsif (@$cols) {
+ push @cmds, "swap container with con_id @$cols[0]";
+ }
+ $ws->{focused_col} = $pulled;
+ unshift @$cols, $pulled;
+ push @cmds, "focus child" if $info{col_rows}{$pulled};
+ }
+
+ with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) };
+ kill USR1 => $i3status;
+ }
+ $ws->{last_dir} = $j > $i ? 1 : -1;
+ };
+
+ # Command dispatch
+
+ if ($cmd =~ /^(focus|move) (left|right)$/) {
+ $mv->($2 eq "right" ? $i+1 : $i-1, $1 eq "move");
+ } elsif ($cmd =~ /^cols (incr|decr)$/) {
+ $ws->{ncols} += $1 eq "incr" ? 1 : -1;
+ normalise_ws_cols();
+ kill USR1 => $i3status;
+ } elsif ($cmd =~ /^other column$/) {
+ # This is meant to be similar to my custom Emacs C-x o.
+ if ($i == 0 || $ws->{last_dir} == -1 && $i < $#$cols) {
+ $mv->($i+1);
+ } elsif ($i == $#$cols || $ws->{last_dir} == 1) {
+ $mv->($i-1);
+ }
+ } elsif ($cmd eq "monocle toggle\n") {
+ unless (ensure_disable_monocle($ws)) {
+ $ws->{monocle} = -$i-1;
+ normalise_ws_cols();
+ }
+ kill USR1 => $i3status;
+ } elsif ($cmd =~ /^fresh-workspace ?(take|send)?$/) {
+ fresh_workspace(do {
+ if ($1 && $1 eq "take") {
+ go => 1, send => 1;
+ } elsif ($1 && $1 eq "send") {
+ send => 1;
+ } else {
+ go => 1;
+ }
+ });
+ } elsif ($cmd =~ /^absorb_expel ?(left|right)?$/) {
+ my $dir = $1 eq "right" ? 1 : -1;
+ if ($col_rows > 1) { # expel
+ # If the column to the right or left also has rows, we'll just
+ # move the container into that column instead of expelling it.
+ # Possibly we could float the container, select the
+ # appropriate full column and unfloat it into place?
+ $wmipc->cmd(sprintf "move %s", $dir > 0 ? "right" : "left");
+ $ws->{last_dir} = $dir;
+ } else { # absorb
+ my @cmds;
+ if ($i == 0 && $dir < 0 && $ws->{off_left}->@*) {
+ my $pulled = pop $ws->{off_left}->@*;
+ push @cmds, show_con($pulled), "move left";
+ push @cmds, "splitv" unless $info{col_rows}{$pulled};
+ push @cmds, "focus right", "move left";
+
+ with_ignored_events { $wmipc->cmd(@cmds) };
+ normalise_ws_cols();
+ } elsif ($i == $#$cols && $dir > 0 && $ws->{off_right}->@*) {
+ my $pulled = pop $ws->{off_right}->@*;
+ push @cmds, show_con($pulled);
+ push @cmds, "move right" if $col_rows;
+ push @cmds, "splitv" unless $info{col_rows}{$pulled};
+ push @cmds, "focus left", "move right";
+
+ with_ignored_events { $wmipc->cmd(@cmds) };
+ normalise_ws_cols();
+ } elsif ($i == $#$cols && $dir < 0
+ || $#$cols > $i > 0
+ || $i == 0 && $dir > 0) {
+ push @cmds, $dir > 0
+ ? ("focus right", "splitv", "focus left")
+ : ("focus left", "splitv", "focus right")
+ unless $info{col_rows}{ @$cols[$i+$dir] };
+ push @cmds, $dir > 0 ? "move right" : "move left";
+
+ with_ignored_events { $wmipc->cmd(@cmds) };
+ normalise_ws_cols($ws->{off_left}->@* && $dir > 0
+ || $ws->{off_right}->@* && $dir < 0
+ ? min($#$cols, max 0, $i+$dir) : $i);
+ }
+ if (@cmds) {
+ $ws->{last_dir} = $dir;
+ kill USR1 => $i3status;
+ }
+ }
+ }
+
+ # Basic purpose of this wrapper command is to prevent accidentally
+ # moving to one of the holding workspaces using Sway's own commands.
+ elsif ($cmd =~ /^(move_)?workspace (prev|next)$/) {
+ my ($move, $dir) = (!!$1, $2);
+ $move && ensure_disable_monocle($ws);
+ my @keys = sorted_paper_ws();
+ my $k = first { $keys[$_] == $info{focused_ws} } 0..$#keys;
+ if ($dir eq "next" && $k < $#keys || $dir eq "prev" && $k > 0) {
+ my @cmds = "workspace $dir";
+ $info{focused_ws} = $keys[$dir eq "next" ? $k+1 : $k-1];
+ if ($move) {
+ push @cmds, show_con($ws->{focused_col});
+ push @cmds, "move right"
+ if $info{col_rows}
+ { $info{paper_ws}{$info{focused_ws}}{focused_col} };
+ push @cmds, "focus child" if $col_rows;
+ }
+ $wmipc->cmd(@cmds);
+ }
+ }
+}
+
=head fresh_workspace(%opts)
Switch to the next free workspace, if any. Return the name of that workspace,