]> git.sur5r.net Git - i3/i3/blob - contrib/dump-asy.pl
c183db338a461a8ac2422be5a995cc900fb72330
[i3/i3] / contrib / dump-asy.pl
1 #!/usr/bin/env perl
2 # vim:ts=4:sw=4:expandtab
3
4 use strict;
5 use warnings;
6 use Data::Dumper;
7 use Getopt::Long;
8 use Pod::Usage;
9 use AnyEvent::I3;
10 use File::Temp;
11 use File::Spec;
12 use File::Basename;
13 use v5.10;
14 use IPC::Cmd qw[can_run];
15
16 my %options = (
17     gv => 1,
18     save => undef,
19     help => 0,
20 );
21 my $result = GetOptions(
22     "gv!" => \$options{gv},
23     "save=s" => \$options{save},
24     "help|?" => \$options{help},
25 );
26
27 pod2usage(-verbose => 2, -exitcode => 0) if $options{help};
28
29 # prerequisites check so we can be specific about failures caused
30 # by not having these tools in the path
31 can_run('asy') or die 'Please install asymptote';
32 can_run('gv') or die 'Please install gv' unless !$options{gv};
33
34 my $i3 = i3();
35
36 my $tree = $i3->get_tree->recv;
37
38 my $tmp = File::Temp->new(UNLINK => 0, SUFFIX => '.asy');
39
40 say $tmp "import drawtree;";
41
42 say $tmp "treeLevelStep = 2cm;";
43
44 sub dump_node {
45         my ($n, $parent) = @_;
46
47     my $o = ($n->{orientation} eq 'none' ? "u" : ($n->{orientation} eq 'horizontal' ? "h" : "v"));
48     my $w = (defined($n->{window}) ? $n->{window} : "N");
49     my $na = ($n->{name} or "[Empty]");
50     $na =~ s/#/\\#/g;
51     $na =~ s/\$/\\\$/g;
52     $na =~ s/&/\\&/g;
53     $na =~ s/_/\\_/g;
54     $na =~ s/~/\\textasciitilde{}/g;
55     my $type = 'leaf';
56     if (!defined($n->{window})) {
57         $type = $n->{layout};
58     }
59     my $name = qq|``$na'' ($type)|;
60
61     print $tmp "TreeNode n" . $n->{id} . " = makeNode(";
62
63     print $tmp "n" . $parent->{id} . ", " if defined($parent);
64     print $tmp "\"" . $name . "\");\n";
65
66         dump_node($_, $n) for @{$n->{nodes}};
67 }
68
69 sub find_node_with_name {
70     my ($node, $name) = @_;
71
72     return $node if ($node->{name} eq $name);
73     for my $child (@{$node->{nodes}}) {
74         my $res = find_node_with_name($child, $name);
75         return $res if defined($res);
76     }
77     return undef;
78 }
79
80 my $start = shift;
81 my $root;
82 if ($start) {
83     # Find the specified node in the tree
84     $root = find_node_with_name($tree, $start);
85 } else {
86     $root = $tree;
87 }
88 dump_node($root);
89 say $tmp "draw(n" . $root->{id} . ", (0, 0));";
90
91 close($tmp);
92 my $rep = "$tmp";
93 $rep =~ s/asy$/eps/;
94 if ($options{gv}) {
95     my $tmp_dir = dirname($rep);
96     $options{save} = File::Spec->rel2abs($options{save}) if $options{save};
97     chdir($tmp_dir);
98 } else {
99     $rep = basename($rep);  # Output in current dir.
100 }
101 system("asy $tmp");  # Create the .eps file.
102 system("gv --scale=-1000 --noresize --widgetless $rep") if $options{gv};
103 if ($options{save}) {
104     system("mv $rep ${options{save}}");
105 } elsif ($options{gv}) {
106     system("rm $rep");
107 }
108 system("rm $tmp");
109
110 __END__
111
112 =head1 NAME
113
114 dump-asy.pl - Render the layout tree using asymptote
115
116 =head1 SYNOPSIS
117
118 dump-asy.pl [workspace]
119
120 =head1 EXAMPLE
121
122 Render the entire tree, run:
123
124   ./dump-asy.pl
125
126 Render the tree starting from the node with the specified name, run:
127
128   ./dump-asy.pl 'name'
129
130 Render the entire tree, save in file 'file.eps' and show using gv, run:
131
132   ./dump-asy.pl --save file.eps
133
134 =head1 OPTIONS
135
136 =over 8
137
138 =item B<--gv>
139
140 =item B<--no-gv>
141
142 Enable or disable showing the result through gv. If disabled, an .eps file will
143 be saved in the current working directory. Enabled by default.
144
145 =item B<--save>
146
147 Save result using the specified file-name. If omitted, no file will be saved
148 when using '--gv' or a random name will be used when using '--no-gv'.
149
150 =back