Prepping for mdoc et. al. move from monodoc/tools to mcs/tools/mdoc...
[mono.git] / mcs / tools / mdoc / 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 NDesk.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 = null;
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                         var command = new List<string> ();
163                         foreach (var f in formats.Keys) {
164                                 foreach (var v in formats [f]) {
165                                         command.Add ("--" + f);
166                                         command.Add (v);
167                                 }
168                         }
169                         if (prefix != null) {
170                                 command.Add ("-o");
171                                 command.Add (prefix);
172                         }
173                         Assembler.Main (command.ToArray ());
174                 }
175
176                 private static void AddFormat (Dictionary<string, List<string>> d, string format, string file)
177                 {
178                         if (format == null)
179                                 Error ("No format specified.");
180                         List<string> l;
181                         if (!d.TryGetValue (format, out l)) {
182                                 l = new List<string> ();
183                                 d.Add (format, l);
184                         }
185                         l.Add (file);
186                 }
187
188                 private void ExportHtml (List<string> args)
189                 {
190                         bool dumptemplate = false;
191                         string dest = null, template = null, extension = null;
192                         bool showHelp = false;
193                         var p = new OptionSet () {
194                                 { "ext=",
195                                         "The file {EXTENSION} to use for created files.  "+
196                                                 "This defaults to \"html\".",
197                                         v => extension = v },
198                                 { "template=",
199                                         "An XSLT {FILE} to use to generate the created " + 
200                                                 "files.  If not specified, uses the template generated by --dump-template.",
201                                         v => template = v },
202                                 { "default-template",
203                                         "Writes the default XSLT to stdout.",
204                                         v => dumptemplate = v != null },
205                                 { "o|out=",
206                                         "The {DIRECTORY} to place the generated files and directories.",
207                                         v => dest = v },
208                                 { "h|?|help", 
209                                         "Show this message and exit.",
210                                         v => showHelp = v != null },
211                         };
212                         List<string> extra = Parse (p, args, "export-html", 
213                                         "[OPTIONS]+ DIRECTORIES",
214                                         "Export mdoc documentation within DIRECTORIES to HTML.", ref showHelp);
215                         if (extra == null)
216                                 return;
217                         var command = new List<string> ();
218                         if (dumptemplate)
219                                 command.Add ("-dumptemplate");
220                         if (template != null)
221                                 command.Add ("-template:" + template);
222                         if (extension != null)
223                                 command.Add ("-ext:" + extension);
224                         if (dest != null)
225                                 command.Add ("-dest:" + dest);
226                         if (extra.Count == 0)
227                                 Monodocs2HTML.Main (command.ToArray ());
228                         foreach (var source in extra) {
229                                 command.Add ("-source:" + source);
230                                 Monodocs2HTML.Main (command.ToArray ());
231                                 command.RemoveAt (command.Count-1);
232                         }
233                 }
234
235                 private void ExportMSXDoc (List<string> args)
236                 {
237                         string file = null;
238                         bool showHelp = false;
239                         var p = new OptionSet () {
240                                 { "o|out=", 
241                                         "The XML {FILE} to generate.\n" + 
242                                         "If not specified, will create a set of files in the curent directory " +
243                                         "based on the //AssemblyInfo/AssemblyName values within the documentation.\n" +
244                                         "Use '-' to write to standard output.",
245                                         v => file = v },
246                                 { "h|?|help", 
247                                         "Show this message and exit.",
248                                         v => showHelp = v != null },
249                         };
250                         List<string> extra = Parse (p, args, "export-slashdoc", 
251                                         "[OPTIONS]+ DIRECTORIES",
252                                         "Export mdoc(5) documentation within DIRECTORIES into \n" +
253                                                 "Microsoft XML Documentation format files.",
254                                         ref showHelp);
255                         if (extra == null)
256                                 return;
257                         if (file != null) {
258                                 extra.Add ("-o");
259                                 extra.Add (file);
260                         }
261                         Monodocs2SlashDoc.Main (extra.ToArray ());
262                 }
263
264                 private void Update (List<string> args)
265                 {
266                         string file = null;
267                         bool delete = false, showHelp = false;
268                         string path = null;
269                         var p = new OptionSet () {
270                                 { "i|import=", 
271                                         "Import documentation from {FILE}.",
272                                         v => file = v },
273                                 { "delete",
274                                         "Delete removed members from the XML files.",
275                                         v => delete = v != null },
276                                 { "o|out=",
277                                         "Root {DIRECTORY} to generate/update documentation.",
278                                         v => path = v },
279                                 { "h|?|help",
280                                         "Show this message and exit.",
281                                         v => showHelp = v != null },
282                         };
283                         List<string> extra = Parse (p, args, "update", 
284                                         "[OPTIONS]+ ASSEMBLIES",
285                                         "Create or update documentation from ASSEMBLIES.", ref showHelp);
286                         if (extra == null)
287                                 return;
288                         if (path == null)
289                                 Error ("Missing required parameter --out.");
290                         if (extra.Count == 0)
291                                 Error ("No assemblies specified.");
292                         var command = new List<string> ();
293                         command.AddRange (extra.Select (a => "-assembly:" + a));
294                         if (delete)
295                                 command.Add ("-delete");
296                         command.Add ("-overrides");
297                         command.Add ("-pretty");
298                         if (file != null) {
299                                 command.Add ("-import:" + file);
300                         }
301                         if (path != null)
302                                 command.Add ("-path:" + path);
303                         command.AddRange (extra);
304                         Updater.Main (command.ToArray ());
305                 }
306
307                 private void Validate (List<string> args)
308                 {
309                         string[] validFormats = {
310                                 "ecma",
311                         };
312                         string format = "ecma";
313                         bool showHelp = false;
314                         var p = new OptionSet () {
315                                 { "f|format=",
316                                         "The documentation {0:FORMAT} used within PATHS.  " + 
317                                                 "Valid formats include:\n  " +
318                                                 string.Join ("\n  ", validFormats) + "\n" +
319                                                 "If no format provided, `ecma' is used.",
320                                         v => format = v },
321                                 { "h|?|help",
322                                         "Show this message and exit.",
323                                         v => showHelp = v != null },
324                         };
325                         List<string> extra = Parse (p, args, "validate", 
326                                         "[OPTIONS]+ PATHS",
327                                         "Validate PATHS against the specified format schema.", ref showHelp);
328                         if (extra == null)
329                                 return;
330                         if (Array.IndexOf (validFormats, format) < 0)
331                                 Error ("Invalid documentation format: {0}.", format);
332                         var command = new List<string> ();
333                         command.Add (format);
334                         command.AddRange (extra);
335                         Validater.Main (command.ToArray ());
336                 }
337         }
338 }
339