]> git.sur5r.net Git - i3/i3/blobdiff - i3-save-tree
Merge pull request #3433 from orestisf1993/janitorial
[i3/i3] / i3-save-tree
index 6ac3e1b1a2564b83e3dffa522fc01f9b657b2681..da5e6deddedb4bd1078f2b9c091fd8d9c3a0d626 100755 (executable)
@@ -13,11 +13,13 @@ use POSIX qw(locale_h);
 use File::Find;
 use File::Basename qw(basename);
 use File::Temp qw(tempfile);
 use File::Find;
 use File::Basename qw(basename);
 use File::Temp qw(tempfile);
+use List::Util qw(first);
 use Getopt::Long;
 use Pod::Usage;
 use AnyEvent::I3;
 use JSON::XS;
 use List::Util qw(first);
 use Getopt::Long;
 use Pod::Usage;
 use AnyEvent::I3;
 use JSON::XS;
 use List::Util qw(first);
+use Encode qw(decode);
 use v5.10;
 use utf8;
 use open ':encoding(UTF-8)';
 use v5.10;
 use utf8;
 use open ':encoding(UTF-8)';
@@ -40,19 +42,27 @@ my $result = GetOptions(
 
 die "Could not parse command line options" unless $result;
 
 
 die "Could not parse command line options" unless $result;
 
-if (!defined($workspace) && !defined($output)) {
-    die "One of --workspace or --output need to be specified";
-}
-
-unless (defined($workspace) ^ defined($output)) {
+if (defined($workspace) && defined($output)) {
     die "Only one of --workspace or --output can be specified";
 }
 
     die "Only one of --workspace or --output can be specified";
 }
 
+$workspace = decode('utf-8', $workspace);
+$output = decode('utf-8', $output);
+
 my $i3 = i3();
 if (!$i3->connect->recv) {
     die "Could not connect to i3";
 }
 
 my $i3 = i3();
 if (!$i3->connect->recv) {
     die "Could not connect to i3";
 }
 
+sub get_current_workspace {
+    my $current = first { $_->{focused} } @{$i3->get_workspaces->recv};
+    return $current->{name};
+}
+
+if (!defined($workspace) && !defined($output)) {
+    $workspace = get_current_workspace();
+}
+
 sub filter_containers {
     my ($tree, $pred) = @_;
 
 sub filter_containers {
     my ($tree, $pred) = @_;
 
@@ -88,6 +98,8 @@ my %allowed_keys = map { ($_, 1) } qw(
     name
     geometry
     window_properties
     name
     geometry
     window_properties
+    marks
+    rect
 );
 
 sub strip_containers {
 );
 
 sub strip_containers {
@@ -105,12 +117,13 @@ sub strip_containers {
 
     delete $tree->{geometry} if zero_rect($tree->{geometry});
 
 
     delete $tree->{geometry} if zero_rect($tree->{geometry});
 
+    # Retain the rect for floating containers to keep their positions.
+    delete $tree->{rect} unless $tree->{type} eq 'floating_con';
+
     delete $tree->{current_border_width} if $tree->{current_border_width} == -1;
 
     for my $key (keys %$tree) {
     delete $tree->{current_border_width} if $tree->{current_border_width} == -1;
 
     for my $key (keys %$tree) {
-        next if exists($allowed_keys{$key});
-
-        delete $tree->{$key};
+        delete $tree->{$key} unless exists($allowed_keys{$key});
     }
 
     for my $key (qw(nodes floating_nodes)) {
     }
 
     for my $key (qw(nodes floating_nodes)) {
@@ -149,12 +162,16 @@ sub dump_containers {
         say "$ws// $desc with " . @{$tree->{nodes}} . " children";
     }
 
         say "$ws// $desc with " . @{$tree->{nodes}} . " children";
     }
 
-    # Turn “window_properties” into “swallows” expressions.
-    my $swallows = {};
-    for my $property (keys %{$tree->{window_properties}}) {
-        $swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$';
+    # Turn “window_properties” into “swallows” expressions, but only for leaf
+    # nodes. It only makes sense for leaf nodes to swallow anything.
+    if (leaf_node($tree)) {
+        my $swallows = {};
+        for my $property (keys %{$tree->{window_properties}}) {
+            $swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$'
+                if $property ne 'transient_for';
+        }
+        $tree->{swallows} = [ $swallows ];
     }
     }
-    $tree->{swallows} = [ $swallows ];
     delete $tree->{window_properties};
 
     my @keys = sort keys %$tree;
     delete $tree->{window_properties};
 
     my @keys = sort keys %$tree;
@@ -208,7 +225,7 @@ my $tree = $i3->get_tree->recv;
 my $dump;
 if (defined($workspace)) {
     $dump = filter_containers($tree, sub {
 my $dump;
 if (defined($workspace)) {
     $dump = filter_containers($tree, sub {
-        $_->{type} eq 'workspace' && $_->{name} eq $workspace
+        $_->{type} eq 'workspace' && ($_->{name} eq $workspace || ($workspace =~ /^\d+$/ && $_->{num} eq $workspace))
     });
 } else {
     $dump = filter_containers($tree, sub {
     });
 } else {
     $dump = filter_containers($tree, sub {
@@ -238,7 +255,7 @@ for my $key (qw(nodes floating_nodes)) {
 
 =head1 SYNOPSIS
 
 
 =head1 SYNOPSIS
 
-    i3-save-tree [--workspace=name] [--output=name]
+    i3-save-tree [--workspace=name|number] [--output=name]
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -251,19 +268,20 @@ specification. When a window is mapped (made visible on the screen) that
 matches the specification, i3 will put it into that place and kill the
 placeholder.
 
 matches the specification, i3 will put it into that place and kill the
 placeholder.
 
+If neither argument is specified, the currently focused workspace will be used.
+
 =head1 OPTIONS
 
 =over
 
 =head1 OPTIONS
 
 =over
 
-=item B<--workspace=name>
+=item B<--workspace=name|number>
 
 
-Specifies the workspace that should be dumped, e.g. 1. Either this or --output
-need to be specified.
+Specifies the workspace that should be dumped, e.g. 1. This can either be a
+name or the number of a workspace.
 
 =item B<--output=name>
 
 
 =item B<--output=name>
 
-Specifies the output that should be dumped, e.g. LVDS-1. Either this or
---workspace need to be specified.
+Specifies the output that should be dumped, e.g. LVDS-1.
 
 =back
 
 
 =back