obmenu-generator 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. #!/usr/bin/perl
  2. # Copyright (C) 2011-2013 Trizen <echo dHJpemVueEBnbWFpbC5jb20K | base64 -d>.
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #
  17. # Openbox Menu Generator
  18. # A fast pipe/static menu generator for the Openbox Window Manager.
  19. # It used to be even faster about a year ago, but now it's older and wiser :)
  20. #
  21. # License: GPLv3
  22. # Created on: 25 March 2011
  23. # Latest edit on: 29 August 2013
  24. # Website: http://trizen.googlecode.com
  25. #use strict;
  26. #use warnings;
  27. require Linux::DesktopFiles;
  28. my $pkgname = 'obmenu-generator';
  29. our $VERSION = '0.55';
  30. our ($CONFIG, $SCHEMA);
  31. my $output_h = *STDOUT;
  32. my ($pipe, $static, $icons, $reconfigure, $stdout_config, $update_config);
  33. my $home_dir =
  34. $ENV{HOME}
  35. || $ENV{LOGDIR}
  36. || (getpwuid($<))[7]
  37. || `echo -n ~`;
  38. my $xdg_config_home = $ENV{XDG_CONFIG_HOME} || "$home_dir/.config";
  39. my $config_dir = "$xdg_config_home/obmenu-generator";
  40. my $schema_file = "$config_dir/schema.pl";
  41. my $config_file = "$config_dir/config.pl";
  42. my $openbox_conf = "$xdg_config_home/openbox";
  43. my $menufile = "$openbox_conf/menu.xml";
  44. my $icons_db = "$config_dir/icons.db";
  45. sub usage {
  46. print <<"HELP";
  47. usage: $0 [options]\n
  48. Options:
  49. -p : (re)generate a pipe menu
  50. -s : (re)generate a static menu
  51. -d : (re)generate icons.db (with -i)
  52. -r : (re)generate config file
  53. -i : use icons in menus
  54. -u : update the configuration file
  55. -R : reconfigure openbox
  56. Others:
  57. -h : print this message
  58. -S : print the schema file to STDOUT
  59. -H : print help message for config files
  60. Examples:
  61. ** Static menu without icons:
  62. $0 -s
  63. ** Pipe menu with icons:
  64. $0 -p -i
  65. ** Reconfigure openbox:
  66. $0 -R
  67. NOTE: After a pipe menu is generated, '-p' it's not needed anymore.
  68. ** Config file: $config_file
  69. ** Schema file: $schema_file
  70. HELP
  71. exit 0;
  72. }
  73. my $config_help = <<'HELP';
  74. categories_case_sensitive => BOOL
  75. - True (1) to make the categories case sensitive;
  76. - By default, "XFCE-4" is equivalent with "xfce_4".
  77. clean_command_name_re => REGEX
  78. - Remove from every command anything matched by the regex.
  79. skip_app_command_re => REGEX
  80. - Skip the application if its command matches the regex.
  81. skip_app_name_re => REGEX
  82. - Skip the application if its name matches the regex.
  83. skip_file_content_re => REGEX
  84. - Skip the application if the content of the *.desktop
  85. file matches the regex.
  86. skip_file_name_re => REGEX
  87. - Skip the application if its file name matches the regex.
  88. Name is from the last slash to the end. (example: name.desktop)
  89. skip_svg_icons => BOOL
  90. - True (1) to skip the SVG icons.
  91. desktop_files_paths => ARRAY REF
  92. - Paths which contains the desktop files.
  93. wine_desktop_files_paths => ARRAY REF
  94. - Directories which contains desktop files generated by the wine app.
  95. wine_skip_exec_re => REGEX
  96. - Skip the wine application if its command matches the regex.
  97. wine_skip_name_re => REGEX
  98. - Skip the wine application if its name matches the regex.
  99. editor => STRING
  100. - Text editor command.
  101. terminal => STRING
  102. - Terminal command.
  103. gtk_rc_filename => STRING
  104. - Absolute path to the GTK configuration file.
  105. icon_dirs_first => ARRAY REF
  106. - When looking for full icon paths, look in this directories first,
  107. before looking in the directories of the current icon theme.
  108. icon_dirs_second => ARRAY REF
  109. - When looking for full icon paths, look in this directories as a
  110. second icon theme. (Before /usr/share/pixmaps)
  111. icon_dirs_last => ARRAY REF
  112. - Look in this directories at the very last, after looked in
  113. /usr/share/pixmaps, /usr/share/icons/hicolor and some other
  114. directories.
  115. use_only_my_icon_dirs => BOOL
  116. - True (1) to look only in directories specified in the above ARRAY REF's.
  117. - False (0) to look in other directories. (example: /usr/share/pixmaps)
  118. missing_icon => STRING
  119. - When an icon is not found, use this icon instead.
  120. VERSION => NUMBER
  121. - The current version of obmenu-generator.
  122. HELP
  123. my $schema_help = <<'HELP';
  124. item: add an item into the menu
  125. {item => ["command", "label", "icon"]}
  126. cat: add a category into the menu
  127. {cat => ["name", "label", "icon"]}
  128. begin_cat: begin of a category
  129. {begin_cat => ["name", "icon"]}
  130. end_cat: end of a category
  131. {end_cat => undef}
  132. sep: menu line separator
  133. {sep => undef}
  134. {sep => "label"}
  135. exit: default "Exit" action
  136. {exit => ["label", "icon"]}
  137. raw: any valid Openbox XML string
  138. {raw => q(xml string)},
  139. obgenmenu: category provided by obmenu-generator
  140. {obgenmenu => "label"}
  141. scripts: executable scripts from a directory
  142. {scripts => ["/my/dir", BOOL, "icon"]}
  143. BOOL - can be either true or false (1 or 0)
  144. 0 => to open the script in background
  145. 1 => to open the script in a new terminal
  146. wine_apps: windows applications installed via wine
  147. {wine_apps => ["label", "icon"]}
  148. HELP
  149. sub full_help {
  150. print <<"HELP";
  151. =>> Schema file:
  152. $schema_help
  153. ====================================================
  154. =>> Config file:
  155. $config_help
  156. HELP
  157. exit 0;
  158. }
  159. if (@ARGV) {
  160. foreach my $arg (@ARGV) {
  161. if ($arg eq '-i') {
  162. $icons = 1;
  163. }
  164. elsif ($arg eq '-S') {
  165. $stdout_config = 1;
  166. }
  167. elsif ($arg eq '-p') {
  168. $pipe = 1;
  169. }
  170. elsif ($arg eq '-r') {
  171. $reconfigure = 1;
  172. }
  173. elsif ($arg eq '-s') {
  174. $static = 1;
  175. }
  176. elsif ($arg eq '-d') {
  177. unlink $icons_db;
  178. }
  179. elsif ($arg eq '-h') {
  180. usage();
  181. }
  182. elsif ($arg eq '-H') {
  183. full_help();
  184. }
  185. elsif ($arg eq '-u') {
  186. $update_config = 1;
  187. }
  188. elsif ($arg eq '-v') {
  189. print "$pkgname $VERSION\n";
  190. exit 0;
  191. }
  192. elsif ($arg eq '-R') {
  193. exec 'openbox', '--reconfigure';
  194. }
  195. }
  196. }
  197. if (not -d $config_dir) {
  198. require File::Path;
  199. File::Path::make_path($config_dir)
  200. or die "Can't create directory '${config_dir}': $!";
  201. }
  202. my $config_documentation = <<"EOD";
  203. #!/usr/bin/perl
  204. # $pkgname - configuration file
  205. # This file is updated automatically every time when is needed.
  206. # Any additional comment and/or indentation will be lost.
  207. =for comment
  208. $config_help
  209. =cut
  210. # For regular expressions
  211. # * is better to use qr/REGEX/ instead of 'REGEX'
  212. # * for case insensitive mode, use: qr/REGEX/i
  213. # NOTE: Once an icon is found, it will *NOT* be replaced by another.
  214. EOD
  215. my %CONFIG = (
  216. desktop_files_paths => ['/usr/share/applications'],
  217. wine_desktop_files_paths => ["$home_dir/.local/share/applications/wine"],
  218. gtk_rc_filename => undef,
  219. skip_file_name_re => undef,
  220. skip_app_name_re => undef,
  221. skip_app_command_re => undef,
  222. skip_file_content_re => undef,
  223. clean_command_name_re => undef,
  224. wine_skip_name_re => qr{^(?:Uninstall|Readme|Help|Visit|Register|Technical Support)\b}i,
  225. wine_skip_exec_re => undef,
  226. icon_dirs_first => [],
  227. icon_dirs_second => [],
  228. icon_dirs_last => [],
  229. missing_icon => 'gtk-missing-image',
  230. use_only_my_icon_dirs => 0,
  231. skip_svg_icons => 1,
  232. categories_case_sensitive => 0,
  233. terminal => $ENV{TERM} || 'xterm',
  234. editor => 'geany',
  235. VERSION => $VERSION,
  236. );
  237. sub dump_configuration {
  238. require Data::Dump;
  239. open my $config_fh, '>', $config_file
  240. or die "Can't open file '${config_file}' for write: $!";
  241. my $dumped_config = q{our $CONFIG = } . Data::Dump::dump(\%CONFIG);
  242. print $config_fh $config_documentation, $dumped_config;
  243. close $config_fh;
  244. }
  245. if (not -e $config_file or $reconfigure) {
  246. dump_configuration();
  247. }
  248. if (not -e $schema_file or $reconfigure or $stdout_config) {
  249. my $schema_fh = $stdout_config ? \*STDOUT : do {
  250. open my $fh, '>', $schema_file
  251. or die "Can't open file '${schema_file}' for write: $!";
  252. $fh;
  253. };
  254. print $schema_fh <<"SCHEMA_FILE";
  255. #!/usr/bin/perl
  256. # $pkgname - schema file
  257. =for comment
  258. $schema_help
  259. =cut
  260. # NOTE:
  261. # * Keys and values are case sensitive. Keep all keys lowercase.
  262. # * ICON can be a either a direct path to an icon or a valid icon name
  263. require '${config_file}';
  264. our \$SCHEMA = [
  265. # COMMAND LABEL ICON
  266. {item => ['pcmanfm', 'File Manager', 'file-manager']},
  267. {item => ['xterm', 'Terminal', 'terminal']},
  268. {item => ['geany', 'Editor', 'text-editor']},
  269. {item => ['google-chrome', 'Web Browser', 'web-browser']},
  270. {item => ['gmrun', 'Run command', 'system-run']},
  271. {item => ['pidgin', 'Instant messaging', 'system-users']},
  272. {sep => 'Applications'},
  273. # NAME LABEL ICON
  274. {cat => ['utility', 'Accessories', 'applications-utilities']},
  275. {cat => ['development', 'Development', 'applications-development']},
  276. {cat => ['education', 'Education', 'applications-science']},
  277. {cat => ['game', 'Games', 'applications-games']},
  278. {cat => ['graphics', 'Graphics', 'applications-graphics']},
  279. {cat => ['audiovideo', 'Multimedia', 'applications-multimedia']},
  280. {cat => ['network', 'Network', 'applications-internet']},
  281. {cat => ['office', 'Office', 'applications-office']},
  282. {cat => ['settings', 'Settings', 'applications-accessories']},
  283. {cat => ['system', 'System', 'applications-system']},
  284. #{cat => ['qt', 'QT Applications', 'qtlogo']},
  285. #{cat => ['gtk', 'GTK Applications', 'gnome-applications']},
  286. #{cat => ['x_xfce', 'XFCE Applications', 'applications-other']},
  287. #{cat => ['gnome', 'GNOME Applications', 'gnome-applications']},
  288. #{cat => ['consoleonly', 'CLI Applications', 'applications-utilities']},
  289. # LABEL ICON
  290. #{begin_cat => ['My category', 'cat-icon']},
  291. # ... some items ...
  292. #{end_cat => undef},
  293. # LABEL ICON
  294. #{wine_apps => ['Wine apps', 'applications-other']},
  295. # DIR BOOL ICON
  296. #{scripts => ['/my/path', 1, 'text-x-script']},
  297. {sep => undef},
  298. {obgenmenu => ['Openbox Settings', 'applications-engineering']},
  299. {sep => undef},
  300. {item => ['xscreensaver-command -lock', 'Lock', 'lock']},
  301. # This options uses the default OpenBox action "Exit"
  302. {exit => ['Exit', 'exit']},
  303. ]
  304. SCHEMA_FILE
  305. exit if $stdout_config;
  306. close $schema_fh;
  307. }
  308. require $schema_file; # Load the configuration files
  309. # Remove the user defined values
  310. #my @valid_keys = grep exists $CONFIG{$_}, keys %{$CONFIG};
  311. #@CONFIG{@valid_keys} = @{$CONFIG}{@valid_keys};
  312. # Keep the user defined values
  313. @CONFIG{keys %{$CONFIG}} = values %{$CONFIG};
  314. if ($CONFIG{VERSION} != $VERSION) {
  315. $update_config = 1;
  316. $CONFIG{VERSION} = $VERSION;
  317. }
  318. my $desk_obj = Linux::DesktopFiles->new(
  319. home_dir => $home_dir,
  320. terminal => $CONFIG{terminal},
  321. gtk_rc_filename => $CONFIG{gtk_rc_filename},
  322. icon_db_filename => $icons_db,
  323. desktop_files_paths => $CONFIG{desktop_files_paths},
  324. with_icons => $icons,
  325. skip_svg_icons => $CONFIG{skip_svg_icons},
  326. full_icon_paths => 1,
  327. terminalize => 1,
  328. keep_empty_categories => 1,
  329. icon_dirs_first => $CONFIG{icon_dirs_first},
  330. icon_dirs_second => $CONFIG{icon_dirs_second},
  331. icon_dirs_last => $CONFIG{icon_dirs_last},
  332. use_only_my_icon_dirs => $CONFIG{use_only_my_icon_dirs},
  333. skip_file_name_re => $CONFIG{skip_file_name_re},
  334. skip_app_name_re => $CONFIG{skip_app_name_re},
  335. skip_app_command_re => $CONFIG{skip_app_command_re},
  336. skip_file_content_re => $CONFIG{skip_file_content_re},
  337. clean_command_name_re => $CONFIG{subst_command_name_re},
  338. categories => [map $_->{cat}[0], grep exists $_->{cat}, @$SCHEMA],
  339. categories_case_sensitive => $CONFIG{categories_case_sensitive},
  340. );
  341. if ($pipe or $static) {
  342. my $menu_backup = $menufile . '.bak';
  343. if (not -e $menu_backup and -e $menufile) {
  344. require File::Copy;
  345. File::Copy::copy($menufile, $menu_backup);
  346. }
  347. if ($static) {
  348. open $output_h, '>', $menufile
  349. or die "Can't open file '${menufile}' for write: $!";
  350. }
  351. elsif ($pipe) {
  352. if (not -d $openbox_conf) {
  353. require File::Path;
  354. File::Path::make_path($openbox_conf)
  355. or die "Can't create directory '${openbox_conf}': $!";
  356. }
  357. require Cwd;
  358. my $exec_name = Cwd::abs_path($0) . ($icons ? q{ -i} : q{});
  359. open my $fh, '>', $menufile
  360. or die "Can't open file '${menufile}' for write: $!";
  361. print $fh <<"PIPE_MENU_HEADER";
  362. <?xml version="1.0" encoding="utf-8"?>
  363. <openbox_menu xmlns="http://openbox.org/"
  364. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  365. xsi:schemaLocation="http://openbox.org/">
  366. <menu id="root-menu" label="obmenu-generator" execute="$exec_name" />
  367. </openbox_menu>
  368. PIPE_MENU_HEADER
  369. close $fh;
  370. }
  371. }
  372. my $generated_menu = $static
  373. ? <<'STATIC_MENU_HEADER'
  374. <?xml version="1.0" encoding="utf-8"?>
  375. <openbox_menu xmlns="http://openbox.org/"
  376. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  377. xsi:schemaLocation="http://openbox.org/">
  378. <menu id="root-menu" label="Applications">
  379. STATIC_MENU_HEADER
  380. : "<openbox_pipe_menu>\n";
  381. sub prepare_item {
  382. $icons
  383. ? <<"ITEM_WITH_ICON"
  384. <item label="$_[1]" icon="${\($desk_obj->get_icon_path($_[2]) || $desk_obj->get_icon_path($CONFIG{missing_icon}))}"><action name="Execute"><execute>$_[0]</execute></action></item>
  385. ITEM_WITH_ICON
  386. : <<"ITEM";
  387. <item label="$_[1]"><action name="Execute"><execute>$_[0]</execute></action></item>
  388. ITEM
  389. }
  390. sub begin_category {
  391. $icons
  392. ? <<"MENU_WITH_ICON"
  393. <menu id="$_[0]" icon="${\$desk_obj->get_icon_path($_[1])}" label="$_[0]">
  394. MENU_WITH_ICON
  395. : <<"MENU"
  396. <menu id="$_[0]" label="$_[0]">
  397. MENU
  398. }
  399. my $categories = $desk_obj->parse_desktop_files();
  400. foreach my $schema (@$SCHEMA) {
  401. if (exists $schema->{cat}) {
  402. next unless defined $categories->{$schema->{cat}[0]};
  403. $generated_menu .= begin_category($schema->{cat}[1], ($icons ? $schema->{cat}[2] : ())) . join(
  404. q{},
  405. (
  406. map $_->[1],
  407. sort { $a->[0] cmp $b->[0] }
  408. map [lc($_) => $_],
  409. map {
  410. if ($_->{Name} =~ tr/"&//) {
  411. $_->{Name} =~ s/&/&amp;/g;
  412. $_->{Name} =~ s/"/&quot;/g;
  413. }
  414. $icons
  415. ? <<"ITEM_WITH_ICON"
  416. <item label="$_->{Name}" icon="$_->{Icon}"><action name="Execute"><execute>$_->{Exec}</execute></action></item>
  417. ITEM_WITH_ICON
  418. : <<"ITEM";
  419. <item label="$_->{Name}"><action name="Execute"><execute>$_->{Exec}</execute></action></item>
  420. ITEM
  421. } @{$categories->{$schema->{cat}[0]}}
  422. )
  423. )
  424. . qq[ </menu>\n];
  425. }
  426. elsif (exists $schema->{item}) {
  427. $generated_menu .= prepare_item(@{$schema->{item}});
  428. }
  429. elsif (exists $schema->{sep}) {
  430. $generated_menu .=
  431. defined $schema->{sep}
  432. ? qq[ <separator label="$schema->{sep}"/>\n]
  433. : qq[ <separator/>\n];
  434. }
  435. elsif (exists $schema->{wine_apps}) {
  436. my @output;
  437. my @dirs = @{$CONFIG{wine_desktop_files_paths}};
  438. while (@dirs) {
  439. my $dir = shift @dirs;
  440. opendir(my $dir_h, $dir) or next;
  441. while (defined(my $file = readdir $dir_h)) {
  442. if (substr($file, -8) eq '.desktop') {
  443. sysopen my $fh, "$dir/$file", 0 or next;
  444. sysread $fh, $_, -s "$dir/$file";
  445. close $fh;
  446. my ($exec) = (/^Exec=(.+)/m ? $1 : next);
  447. my ($name) = (/^Name=(.+)/m ? $1 : "Unknown name");
  448. if (defined $CONFIG{wine_skip_name_re}) {
  449. next if $name =~ $CONFIG{wine_skip_name_re};
  450. }
  451. if (defined $CONFIG{wine_skip_exec_re}) {
  452. next if $exec =~ $CONFIG{wine_skip_exec_re};
  453. }
  454. $exec =~ s{\\(.)}{$1}g;
  455. if ($name =~ tr/"&//) {
  456. $name =~ s{&}{&amp;}g;
  457. $name =~ s{"}{&quot;}g;
  458. }
  459. push @output,
  460. scalar {item => [$exec, $name, ($icons ? (/^Icon=(.+)/m ? $1 : $CONFIG{missing_icon}) : ())]};
  461. }
  462. elsif ($file eq '.' or $file eq '..') {
  463. next;
  464. }
  465. elsif (-d "$dir/$file") {
  466. push @dirs, "$dir/$file";
  467. }
  468. }
  469. closedir $dir_h;
  470. }
  471. $generated_menu .=
  472. begin_category(@{$schema->{wine_apps}})
  473. . join('', map prepare_item(@{$_->{item}}), sort { lc $a->{item}[1] cmp lc $b->{item}[1] } @output)
  474. . qq[ </menu>\n];
  475. }
  476. elsif (exists $schema->{scripts}) {
  477. my @scripts;
  478. my $dir = $schema->{scripts}[0];
  479. opendir(my $dir_h, $dir) or next;
  480. foreach my $file (sort readdir $dir_h) {
  481. if (-f "$dir/$file" and -x _ and not -z _) {
  482. $generated_menu .=
  483. prepare_item(($schema->{scripts}[1] ? qq{$CONFIG{terminal} -e '$dir/$file'} : "$dir/$file"),
  484. $file, ($icons ? $schema->{scripts}[2] : ()));
  485. }
  486. }
  487. closedir $dir_h;
  488. }
  489. elsif (exists $schema->{begin_cat}) {
  490. $generated_menu .= begin_category(@{$schema->{begin_cat}});
  491. }
  492. elsif (exists $schema->{end_cat}) {
  493. $generated_menu .= qq[ </menu>\n];
  494. }
  495. elsif (exists $schema->{exit}) {
  496. $generated_menu .= $icons
  497. ? <<"EXIT_WITH_ICON"
  498. <item label="Exit" icon="${\$desk_obj->get_icon_path($schema->{exit}[1])}"><action name="Exit" /></item>
  499. EXIT_WITH_ICON
  500. : <<'EXIT';
  501. <item label="Exit"><action name="Exit" /></item>
  502. EXIT
  503. }
  504. elsif (exists $schema->{raw}) {
  505. $generated_menu .= qq[ $schema->{raw}\n];
  506. }
  507. elsif (exists $schema->{obgenmenu}) {
  508. my ($name, $icon) = ref($schema->{obgenmenu}) eq 'ARRAY' ? (@{$schema->{obgenmenu}}) : $schema->{obgenmenu};
  509. $generated_menu .= ($icons ? <<"CONFIG_MENU_WITH_ICON" : <<"CONFIG_MENU") . <<'RECONFIGURE';
  510. <menu id="$name" label="$name" icon="${\$desk_obj->get_icon_path($icon)}">>
  511. CONFIG_MENU_WITH_ICON
  512. <menu id="$name" label="$name">
  513. CONFIG_MENU
  514. <item label="Reconfigure Openbox"><action name="Reconfigure" /></item>
  515. RECONFIGURE
  516. -e '/usr/bin/obconf' && ($generated_menu .= <<'EOL');
  517. <item label="Openbox Configuration Manager"><action name="Execute"><execute>obconf</execute></action></item>
  518. EOL
  519. $generated_menu .= <<"CONFIG_MENU";
  520. <item label="Configure autostarted apps"><action name="Execute"><execute>$CONFIG{editor} $openbox_conf/autostart</execute></action></item>
  521. <item label="Edit rc.xml"><action name="Execute"><execute>$CONFIG{editor} $openbox_conf/rc.xml</execute></action></item>
  522. <separator />
  523. <item label="Generate a pipe menu"><action name="Execute"><execute>$0 -p</execute></action></item>
  524. <item label="Generate a static menu"><action name="Execute"><execute>$0 -s</execute></action></item>
  525. <item label="Generate a pipe menu with icons"><action name="Execute"><execute>$0 -p -i</execute></action></item>
  526. <item label="Generate a static menu with icons"><action name="Execute"><execute>$0 -s -i</execute></action></item>
  527. <separator />
  528. <item label="Edit menu.xml"><action name="Execute"><execute>$CONFIG{editor} $menufile</execute></action></item>
  529. <item label="Edit the schema file"><action name="Execute"><execute>$CONFIG{editor} $schema_file</execute></action></item>
  530. <item label="Edit the configuration file"><action name="Execute"><execute>$CONFIG{editor} $config_file</execute></action></item>
  531. <separator />
  532. <item label="Regenerate configuration file"><action name="Execute"><execute>$0 -r</execute></action></item>
  533. </menu>
  534. CONFIG_MENU
  535. }
  536. }
  537. print $output_h $generated_menu, $static
  538. ? qq[ </menu>\n</openbox_menu>\n]
  539. : qq[</openbox_pipe_menu>\n];
  540. dump_configuration() if $update_config;