#!/usr/bin/env perl
# vim:ts=4:sw=4:expandtab
#
-# © 2013-2014 Michael Stapelberg
+# © 2013 Michael Stapelberg
#
# Requires perl ≥ v5.10, AnyEvent::I3 and JSON::XS
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 Encode qw(decode);
use v5.10;
use utf8;
use open ':encoding(UTF-8)';
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";
}
+$workspace = decode('utf-8', $workspace);
+$output = decode('utf-8', $output);
+
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) = @_;
name
geometry
window_properties
+ marks
+ rect
);
sub strip_containers {
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) {
- next if exists($allowed_keys{$key});
-
- delete $tree->{$key};
+ delete $tree->{$key} unless exists($allowed_keys{$key});
}
for my $key (qw(nodes floating_nodes)) {
if (leaf_node($tree)) {
my $swallows = {};
for my $property (keys %{$tree->{window_properties}}) {
- $swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$';
+ $swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$'
+ if $property ne 'transient_for';
}
$tree->{swallows} = [ $swallows ];
}
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 {
=head1 SYNOPSIS
- i3-save-tree [--workspace=name] [--output=name]
+ i3-save-tree [--workspace=name|number] [--output=name]
=head1 DESCRIPTION
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
-=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>
-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