#!/usr/bin/env perl # Convert my Openbox 2 menu file to Openbox 3 format. (I hate editing XML by # hand.) use strict; my $home = $ENV{"HOME"}; sub read_line () { my $line = ; return [] unless defined $line; chomp $line; return [] if $line eq ""; $line =~ s/^\s*\[([^\]]*)\]\s*// or die "No command on '$line'\n"; my $command = $1; $line =~ s/^\(([^\)]*)\)\s*// or return [$command]; my $first = $1; $line =~ s/^{([^}]*)}// or return [$command, $first]; return [$command, $first, $1]; } open F, "<$home/.openbox/menu" or die "Can't open ob2 menu file\n"; my %menus = (); my $id = 0; my @stack = (); my $menu = undef; while (my @line = @{read_line()}) { my $c = $line[0]; if (($c eq "begin") or ($c eq "submenu")) { push @stack, [$menu, $line[1]]; $menu = []; } elsif ($c eq "end") { my $n; my ($omenu, $title) = @{pop @stack}; if (!defined $omenu) { $n = "root-menu"; } else { $n = "menu" . ($id++); } # Don't bother with empty menus -- they're probably styles # lists. my $isempty = (scalar(@$menu) == 0); unshift @$menu, "\n"; push @$menu, "\n"; $menus{$n} = $menu unless $isempty; last unless defined $omenu; $menu = $omenu; push @$menu, "\n" unless $isempty; } elsif ($c eq "exec") { push @$menu, "$line[2]\n"; } elsif ($c eq "workspaces") { push @$menu, "\n"; } elsif ($c eq "config") { push @$menu, "obconf\n"; } elsif ($c eq "stylesdir") { # No equivalent. } elsif ($c eq "reconfig") { push @$menu, "\n"; } elsif ($c eq "restart") { # No equivalent. } elsif ($c eq "exit") { push @$menu, "\n"; } else { die "Unknown command $c\n"; } } close F; open OUT, ">$home/.config/openbox/menu.xml" or die "can't open output"; print OUT < EOF # We have to do this because OB3 isn't clever enough to deal with using a menu # before it's been defined. sub num ($) { my ($id) = @_; $id =~ /(\d+)$/ or return -1; return int($1); } foreach my $id (sort { num($b) <=> num($a) } keys %menus) { print OUT join "", @{$menus{$id}}; } print OUT < EOF