1#! /usr/bin/perl
2
3# Copyright (C) 2010, 2011 Richard Levitte <richard@levitte.org>
4#
5# This program is made available under the GNU GPL version 2.0 or
6# greater. See the accompanying file COPYING for details.
7#
8# This program is distributed WITHOUT ANY WARRANTY; without even the
9# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10# PURPOSE.
11
12use warnings;
13use strict;
14
15my $mtn = $ENV{'MTN'} || 'mtn';
16$ENV{'LANG'} = 'C';
17
18open MANPAGE,"$mtn manpage|" || die "Couldn't start 'mtn manpage': $!\n";
19
20my $current_command = "mtn";
21my %options_noarg = ();
22my %options_arg = ();
23my %command_options = ();
24my %command_args = ();
25my %commands = ( $current_command => {} );
26
27while (<MANPAGE>) {
28    chomp;
29    next if ! m|^\.IP\s|;
30
31    # Because the manpage has a lot of dashes escaped, let's unescape them.
32    s/\\-/-/g;
33
34    if (m|^\.IP "(--[^"]*)"|) {
35	my $opts = $1;
36	$opts =~ s|\[\s*(-[a-zA-Z\@])\s*\](\s*<arg>\s*)|$2/ $1$2|g;
37	$opts =~ s|\[\s*(-[a-zA-Z\@])\s*\]|/ $1 |g;
38	foreach (split(m|\s*/\s*|, $opts)) {
39#	    print STDERR "DEBUG[$current_command]: opt = $_\n";
40	    my $current_option;
41	    if (m|^\s*(-[-a-zA-Z\@]*)\s+\<arg\>\s*$|) {
42		$current_option = $1;
43		$options_arg{$current_option} = 1;
44	    } elsif (m|^\s*(-[-a-zA-Z\@]*)\s*$|) {
45		$current_option = $1;
46		$options_noarg{$current_option} = 1;
47	    }
48	    $command_options{$current_command} = []
49		if (!defined $command_options{$current_command});
50	    push @{$command_options{$current_command}}, $current_option;
51	}
52    } elsif (m|^\.IP "\\fB(.*)\s\\fP ([^"]*)"|) {
53	$current_command = "mtn $1";
54	$commands{$current_command} = {};
55	my $current_command_args = $2;
56	$current_command_args =~ s|[\[\]]||g;
57	$current_command_args =~ s|\.\.\.\s*$| \.\.\.|;
58	$command_args{$current_command} =
59	    [ split(m|\s+|,$current_command_args) ];
60
61	my $parent_command = "";
62	for my $commandlet (split(m|\s+|,$current_command)) {
63#	    print STDERR "DEBUG[$current_command]: parent command = $parent_command\n";
64#	    print STDERR "DEBUG[$current_command]: commandlet = $commandlet\n";
65	    if ($parent_command eq "") {
66		$parent_command = $commandlet;
67	    } else {
68		$commands{$parent_command} = {}
69		    if !defined $commands{$parent_command};
70		$commands{$parent_command}->{$commandlet} = 1;
71		$parent_command .= " " . $commandlet;
72	    }
73	}
74    } elsif (m|^\.IP "\\fB(.*)\s\\fP"|) {
75	$current_command = "mtn $1";
76	$commands{$current_command} = {};
77
78	my $parent_command = "";
79	for my $commandlet (split(m|\s+|,$current_command)) {
80#	    print STDERR "DEBUG[$current_command]: parent command = $parent_command\n";
81#	    print STDERR "DEBUG[$current_command]: commandlet = $commandlet\n";
82	    if ($parent_command eq "") {
83		$parent_command = $commandlet;
84	    } else {
85		$commands{$parent_command} = {}
86		    if !defined $commands{$parent_command};
87		$commands{$parent_command}->{$commandlet} = 1;
88		$parent_command .= " " . $commandlet;
89	    }
90	}
91    }
92}
93
94#print STDERR "DEBUG: command keys: \n  ",join("\n  ", sort keys %commands),"\n";
95
96print "declare -a _monotone_options_noarg\n";
97print "_monotone_options_noarg=(\n    "
98    ,join("\n    ", sort keys %options_noarg),"\n)\n";
99
100print "declare -a _monotone_options_arg\n";
101print "_monotone_options_arg=(\n    "
102    ,join("\n    ", sort keys %options_arg),"\n)\n";
103
104print "declare -A _monotone_options_arg_fns\n";
105print "_monotone_options_arg_fns=(\n";
106print "    [--authors-file]=_monotone_files\n";
107print "    [--bind]=_monotone_address_port\n";
108print "    [--branch]=_monotone_branches [-b]=_monotone_branches\n";
109print "    [--branches-file]=_monotone_files\n";
110print "    [--confdir]=_monotone_dirs\n";
111print "    [--conflicts-file]=_monotone_files\n";
112print "    [--db]=_monotone_databases [-d]=_monotone_databases\n";
113print "    [--dump]=_monotone_files\n";
114print "    [--export-marks]=_monotone_files\n";
115print "    [--from]=_monotone_revisions\n";
116print "    [--import-marks]=_monotone_files\n";
117print "    [--keydir]=_monotone_dirs\n";
118print "    [--key]=_monotone_key [-k]=_monotone_public_key\n";
119print "    [--key-to-push]=_monotone_public_key\n";
120print "    [--log]=_monotone_files\n";
121print "    [--message_file]=_monotone_files\n";
122print "    [--pid-file]=_monotone_files\n";
123print "    [--rcfile]=_monotone_files\n";
124print "    [--refs]=_monotone_refs\n";
125print "    [--remote-stdio-host]=_monotone_address_port\n";
126print "    [--resolve-conflicts-file]=_monotone_files\n";
127print "    [--revision]=_monotone_revisions [-r]=_monotone_revisions\n";
128print "    [--root]=_monotone_dirs\n";
129print "    [--ssh-sign]=_monotone_ssh_sign\n";
130print "    [--ticker]=_monotone_ticker\n";
131print "    [--xargs]=_monotone_files\n";
132print "    [-@]=_monotone_files\n";
133print ")\n";
134
135print "declare -A _monotone_aliases\n";
136
137print "_monotone_aliases['mtn au']='mtn automate'\n";
138print "_monotone_aliases['mtn di']='mtn diff'\n";
139print "_monotone_aliases['mtn ls']='mtn list'\n";
140print "_monotone_aliases['mtn list dbs']='mtn list databases'\n";
141
142print "declare -A _monotone_command_options\n";
143print "declare -A _monotone_command_args\n";
144print "declare -A _monotone_commands\n";
145
146foreach my $key (sort keys %commands) {
147#    print STDERR "DEBUG: key = $key\n";
148    print "_monotone_commands['$key']='"
149	,join(" ",sort keys %{$commands{$key}})
150	,"'\n" if %{$commands{$key}};
151    print "_monotone_command_args['$key']='"
152	,join(" ",@{$command_args{$key}})
153	,"'\n" if $command_args{$key};
154    print "_monotone_command_options['$key']='"
155	,join(" ",sort @{$command_options{$key}}),"'\n"
156	if $command_options{$key};
157    print "### Missing $key\n"
158	if (!%{$commands{$key}} &&
159	    !$command_args{$key} &&
160	    !$command_options{$key});
161}
162