* . (svn:ignore), Test (svn:ignore): Ignore generated files.
[mono.git] / mcs / tools / mdoc / Mono.Documentation / mdoc.cs
1 // Part of the mdoc(7) suite of tools.
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using Mono.Options;
6
7 namespace Mono.Documentation {
8         class MDoc {
9
10                 private static bool debug;
11
12                 private static void Main (string[] args)
13                 {
14                         MDoc d = new MDoc ();
15                         try {
16                                 d.Run (args);
17                         }
18                         catch (Exception e) {
19                                 if (debug) {
20                                         Console.Error.WriteLine ("mdoc: {0}", e.ToString ());
21                                 }
22                                 else {
23                                         Console.Error.WriteLine ("mdoc: {0}", e.Message);
24                                 }
25                                 Console.Error.WriteLine ("See `mdoc help' for more information.");
26                         }
27                 }
28
29                 Dictionary<string, Action<List<string>>> subcommands;
30
31                 private void Run (string[] args)
32                 {
33                         subcommands = new Dictionary<string, Action<List<string>>> () {
34                                 { "assemble",         Assemble },
35                                 { "export-html",      ExportHtml },
36                                 { "export-msxdoc",    ExportMSXDoc},
37                                 { "help",             Help },
38                                 { "update",           Update },
39                                 { "validate",         Validate },
40                         };
41
42                         bool showVersion = false;
43                         bool showHelp    = false;
44                         var p = new OptionSet () {
45                                 { "version",  v => showVersion = v != null },
46                                 { "debug",    v => debug = v != null },
47                                 { "h|?|help", v => showHelp = v != null },
48                         };
49
50                         List<string> extra = p.Parse (args);
51
52                         if (showVersion) {
53                                 Console.WriteLine ("mdoc 0.1.0");
54                                 return;
55                         }
56                         if (extra.Count == 0) {
57                                 Help (null);
58                                 return;
59                         }
60                         if (showHelp) {
61                                 extra.Add ("--help");
62                         }
63                         GetCommand (extra [0]) (extra);
64                 }
65
66                 private Action<List<string>> GetCommand (string command)
67                 {
68                         Action<List<string>> h;
69                         if (!subcommands.TryGetValue (command, out h)) {
70                                 Error ("Unknown command: {0}.", command);
71                         }
72                         return h;
73                 }
74
75                 private void Help (List<string> args)
76                 {
77                         if (args != null && args.Count > 1) {
78                                 for (int i = 1; i < args.Count; ++i) {
79                                         GetCommand (args [i]) (new List<string>(){args [i], "--help"});
80                                 }
81                                 return;
82                         }
83                         Console.WriteLine (
84                                 "usage: mdoc COMMAND [OPTIONS]\n" +
85                                 "Use `mdoc help COMMAND' for help on a specific command.\n" +
86                                 "\n" + 
87                                 "Available commands:\n\n   " +
88                                 string.Join ("\n   ", subcommands.Keys.OrderBy (v => v).ToArray()) +
89                                 "\n\n" + 
90                                 "mdoc is a tool for documentation management.\n" +
91                                 "For additional information, see http://www.mono-project.com/"
92                         );
93                 }
94
95                 private static void Error (string format, params object[] args)
96                 {
97                         throw new Exception (string.Format (format, args));
98                 }
99
100                 private List<string> Parse (OptionSet p, List<string> args, string command,
101                                 string prototype, string description, ref bool showHelp)
102                 {
103                         List<string> extra = null;
104                         if (args != null) {
105                                 extra = p.Parse (args.Skip (1));
106                         }
107                         if (args == null || showHelp) {
108                                 Console.WriteLine ("usage: mdoc {0} {1}", 
109                                                 args == null ? command : args [0], prototype);
110                                 Console.WriteLine ();
111                                 Console.WriteLine (description);
112                                 Console.WriteLine ();
113                                 Console.WriteLine ("Available Options:");
114                                 p.WriteOptionDescriptions (Console.Out);
115                                 return null;
116                         }
117                         return extra;
118                 }
119
120                 private void Assemble (List<string> args)
121                 {
122                         string[] validFormats = {
123                                 "ecma", 
124                                 "ecmaspec", 
125                                 "error", 
126                                 "hb", 
127                                 "man", 
128                                 "simple", 
129                                 "xhtml"
130                         };
131                         var formats = new Dictionary<string, List<string>> ();
132                         string prefix = "tree";
133                         bool showHelp = false;
134                         string format = "ecma";
135                         var p = new OptionSet () {
136                                 { "f|format=",
137                                         "The documentation {FORMAT} used in DIRECTORIES.  " + 
138                                                 "Valid formats include:\n  " +
139                                                 string.Join ("\n  ", validFormats) + "\n" +
140                                                 "If not specified, the default format is `ecma'.",
141                                         v => {
142                                                 if (Array.IndexOf (validFormats, v) < 0)
143                                                         Error ("Invalid documentation format: {0}.", v);
144                                                 format = v;
145                                         } },
146                                 { "o|out=",
147                                         "Provides the output file prefix; the files {PREFIX}.zip and " + 
148                                                 "{PREFIX}.tree will be created.\n" +
149                                                 "If not specified, `tree' is the default PREFIX.",
150                                         v => prefix = v },
151                                 { "h|?|help",
152                                         "Show this message and exit.",
153                                         v => showHelp = v != null },
154                                 { "<>", v => AddFormat (formats, format, v) },
155                         };
156                         List<string> extra = Parse (p, args, "assemble", 
157                                         "[OPTIONS]+ DIRECTORIES",
158                                         "Assemble documentation within DIRECTORIES for use within the monodoc browser.", 
159                                         ref showHelp);
160                         if (extra == null)
161                                 return;
162                         MDocAssembler.Run (prefix, formats);
163                 }
164
165                 private static void AddFormat (Dictionary<string, List<string>> d, string format, string file)
166                 {
167                         if (format == null)
168                                 Error ("No format specified.");
169                         List<string> l;
170                         if (!d.TryGetValue (format, out l)) {
171                                 l = new List<string> ();
172                                 d.Add (format, l);
173                         }
174                         l.Add (file);
175                 }
176
177                 private void ExportHtml (List<string> args)
178                 {
179                         var opts = new MDocToHtmlConverterOptions ();
180                         bool showHelp = false;
181                         var p = new OptionSet () {
182                                 { "ext=",
183                                         "The file {EXTENSION} to use for created files.  "+
184                                                 "This defaults to \"html\".",
185                                         v => opts.ext = v },
186                                 { "template=",
187                                         "An XSLT {FILE} to use to generate the created " + 
188                                                 "files.  If not specified, uses the template generated by --dump-template.",
189                                         v => opts.template = v },
190                                 { "default-template",
191                                         "Writes the default XSLT to stdout.",
192                                         v => opts.dumptemplate = v != null },
193                                 { "o|out=",
194                                         "The {DIRECTORY} to place the generated files and directories.",
195                                         v => opts.dest = v },
196                                 { "h|?|help", 
197                                         "Show this message and exit.",
198                                         v => showHelp = v != null },
199                         };
200                         List<string> extra = Parse (p, args, "export-html", 
201                                         "[OPTIONS]+ DIRECTORIES",
202                                         "Export mdoc documentation within DIRECTORIES to HTML.", ref showHelp);
203                         if (extra == null)
204                                 return;
205                         if (extra.Count == 0)
206                                 MDocToHtmlConverter.Run (opts);
207                         foreach (var source in extra) {
208                                 opts.source = source;
209                                 MDocToHtmlConverter.Run (opts);
210                         }
211                 }
212
213                 private void ExportMSXDoc (List<string> args)
214                 {
215                         string file = null;
216                         bool showHelp = false;
217                         var p = new OptionSet () {
218                                 { "o|out=", 
219                                         "The XML {FILE} to generate.\n" + 
220                                         "If not specified, will create a set of files in the curent directory " +
221                                         "based on the //AssemblyInfo/AssemblyName values within the documentation.\n" +
222                                         "Use '-' to write to standard output.",
223                                         v => file = v },
224                                 { "h|?|help", 
225                                         "Show this message and exit.",
226                                         v => showHelp = v != null },
227                         };
228                         List<string> directories = Parse (p, args, "export-slashdoc", 
229                                         "[OPTIONS]+ DIRECTORIES",
230                                         "Export mdoc(5) documentation within DIRECTORIES into \n" +
231                                                 "Microsoft XML Documentation format files.",
232                                         ref showHelp);
233                         if (directories == null)
234                                 return;
235                         MDocToMSXDocConverter.Run (file, directories);
236                 }
237
238                 private void Update (List<string> args)
239                 {
240                         var opts = new MDocUpdaterOptions {
241                                 overrides        = true,
242                                 pretty           = true,
243                                 show_exceptions  = debug,
244                         };
245
246                         bool showHelp = false;
247                         var  types = new List<string> ();
248                         var p = new OptionSet () {
249                                 { "o|out=",
250                                         "Root {DIRECTORY} to generate/update documentation.",
251                                         v => opts.path = v },
252                                 { "i|import=", 
253                                         "Import documentation from {FILE}.",
254                                         v => opts.import = v },
255                                 { "delete",
256                                         "Delete removed members from the XML files.",
257                                         v => opts.delete = v != null },
258                                 { "since=",
259                                         "Manually specify the assembly version that new members were added in.",
260                                         v => opts.since = v },
261                                 { "type=",
262                                   "Only update documentation for {TYPE}.",
263                                         v => types.Add (v) },
264                                 { "h|?|help",
265                                         "Show this message and exit.",
266                                         v => showHelp = v != null },
267                         };
268                         List<string> extra = Parse (p, args, "update", 
269                                         "[OPTIONS]+ ASSEMBLIES",
270                                         "Create or update documentation from ASSEMBLIES.", ref showHelp);
271                         if (extra == null)
272                                 return;
273                         if (extra.Count == 0)
274                                 Error ("No assemblies specified.");
275                         opts.assembly = extra.ToArray ();
276                         if (types.Count > 0)
277                                 opts.type = types.ToArray ();
278                         MDocUpdater.Run (opts);
279                 }
280
281                 private void Validate (List<string> args)
282                 {
283                         string[] validFormats = {
284                                 "ecma",
285                         };
286                         string format = "ecma";
287                         bool showHelp = false;
288                         var p = new OptionSet () {
289                                 { "f|format=",
290                                         "The documentation {0:FORMAT} used within PATHS.  " + 
291                                                 "Valid formats include:\n  " +
292                                                 string.Join ("\n  ", validFormats) + "\n" +
293                                                 "If no format provided, `ecma' is used.",
294                                         v => format = v },
295                                 { "h|?|help",
296                                         "Show this message and exit.",
297                                         v => showHelp = v != null },
298                         };
299                         List<string> extra = Parse (p, args, "validate", 
300                                         "[OPTIONS]+ PATHS",
301                                         "Validate PATHS against the specified format schema.", ref showHelp);
302                         if (extra == null)
303                                 return;
304                         if (Array.IndexOf (validFormats, format) < 0)
305                                 Error ("Invalid documentation format: {0}.", format);
306                         MDocValidator.Run (format, extra);
307                 }
308         }
309 }
310