1 /** 2 * Copyright: Copyright (c) 2010-2011 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Aug 15, 2010 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module dvm.dvm.Application; 8 9 import tango.core.Exception; 10 import tango.io.device.File; 11 import tango.io.Stdout; 12 import tango.net.http.HttpGet; 13 import tango.stdc.stdlib : EXIT_SUCCESS, EXIT_FAILURE; 14 import tango.text.Arguments; 15 import tango.text.convert.Format : Format; 16 17 import dvm.dvm._; 18 import dvm.util._; 19 import mambo.core._; 20 import mambo.util._; 21 22 static import dvm.commands._; 23 24 version (Windows) 25 { 26 pragma(lib, "zlib.lib"); 27 pragma(lib, "Advapi32.lib"); 28 } 29 30 class Application 31 { 32 private static Application instance_; 33 34 private 35 { 36 alias Format format; 37 string[] args; 38 Options options; 39 CommandManager commandManager; 40 } 41 42 static Application instance () 43 { 44 if (instance_) 45 return instance_; 46 47 return instance_ = new Application; 48 } 49 50 private this () 51 { 52 options = Options.instance; 53 commandManager = CommandManager.instance; 54 55 registerCommands; 56 } 57 58 int run (string[] args) 59 { 60 this.args = args; 61 62 return handleExceptions in { 63 parseOptions(); 64 return EXIT_SUCCESS; 65 }; 66 } 67 68 Use!(int delegate ()) handleExceptions () 69 { 70 Use!(int delegate ()) use; 71 72 use.args[0] = (int delegate () dg) { 73 try 74 return dg(); 75 76 catch (DvmException e) 77 { 78 stderr.format("An error occurred: {}", e).newline.flush; 79 return EXIT_FAILURE; 80 } 81 82 catch (Exception e) 83 { 84 stderr.format("An unknown error occurred:").newline; 85 throw e; 86 } 87 }; 88 89 return use; 90 } 91 92 Use!(int delegate ()) debugHandleExceptions () 93 { 94 Use!(int delegate ()) use; 95 96 use.args[0] = (int delegate () dg) { 97 return dg(); 98 }; 99 100 return use; 101 } 102 103 private void registerCommands () 104 { 105 commandManager.register("dvm.commands.Install.Install"); 106 commandManager.register("dvm.commands.Fetch.Fetch"); 107 commandManager.register("dvm.commands.Use.Use"); 108 commandManager.register("dvm.commands.List.List"); 109 commandManager.register("dvm.commands.Compile.Compile"); 110 commandManager.register("dvm.commands.Uninstall.Uninstall"); 111 } 112 113 void handleArgs (string[] args) 114 { 115 if (args.length > 0) 116 { 117 string command; 118 119 switch (args[0]) 120 { 121 case "install": command = "dvm.commands.Install.Install"; break; 122 case "fetch": command = "dvm.commands.Fetch.Fetch"; break; 123 case "use": command = "dvm.commands.Use.Use"; break; 124 case "list": command = "dvm.commands.List.List"; break; 125 case "compile": command = "dvm.commands.Compile.Compile"; break; 126 case "uninstall": command = "dvm.commands.Uninstall.Uninstall"; break; 127 default: 128 return unhandledCommand(args[0]); 129 } 130 131 handleCommand(command, args[1 .. $]); 132 } 133 } 134 135 void handleCommand (string command, string[] args) 136 { 137 commandManager[command].invoke(args); 138 } 139 140 void unhandledCommand (string command) 141 { 142 throw new DvmException("unrecognized command " ~ `"` ~ command ~ `"` ~ "\n", __FILE__, __LINE__); 143 } 144 145 void parseOptions () 146 { 147 auto helpMessage = "Use the `-h' flag for help."; 148 auto opts = new OptionParser; 149 auto commands = CommandManager.instance.summary; 150 auto help = false; 151 auto version_ = false; 152 153 opts.banner = "Usage: dvm [options] command [arg]"; 154 opts.separator("Version " ~ dvm.dvm.Version.Version); 155 opts.separator(""); 156 opts.separator("Commands:"); 157 opts.separator(commands); 158 opts.separator("Options:"); 159 160 opts.on('d', "default", "Sets the default D compiler for new shells.", { 161 options.isDefault = true; 162 }); 163 164 opts.on('l', "latest", "Gets the latest D compiler.", { 165 options.latest = true; 166 }); 167 168 version (Posix) 169 { 170 opts.on("64bit", "Installs the 64bit version of the compiler.", { 171 options.is64bit = true; 172 }); 173 174 opts.on("32bit", "Installs the 32bit version of the compiler.", { 175 options.is64bit = false; 176 }); 177 } 178 179 opts.on('t', "tango", "Installs Tango as the standard library.", { 180 options.tango = true; 181 }); 182 183 opts.on('v', "verbose", "Show additional output.", { 184 options.verbose = true; 185 }); 186 187 opts.on("force", "Answer 'yes' to all prompts.", { 188 options.force = true; 189 }); 190 191 opts.on("decline", "Answer 'no' to all prompts.", { 192 options.decline = true; 193 }); 194 195 opts.on("debug", "Compile DMD in debug mode.", { 196 options.compileDebug = true; 197 }); 198 199 opts.on('V', "version", "Print the version of DVM and exit.", { 200 version_ = true; 201 }); 202 203 opts.on('h', "help", "Show this message and exit.", { 204 help = true; 205 }); 206 207 opts.on((string[] args) { 208 if (options.force && options.decline) 209 throw new InvalidOptionException("Cannot use both --force and --decline", __FILE__, __LINE__); 210 211 else if (!help) 212 handleArgs(args); 213 }); 214 215 opts.parse(args[1 .. $]); 216 217 if (version_) 218 println(dvm.dvm.Version.Version); 219 220 else if (args.length == 1 || help) 221 { 222 println(opts); 223 println(helpMessage); 224 } 225 } 226 }