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