1 /** 2 * A sensible main() function. 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.utils.main; 15 16 /** 17 * Mix in a main function, which should be adequate 18 * for most end-user programs. 19 * 20 * In debug mode (-debug), this is a pass-through. 21 * Otherwise, this will catch uncaught exceptions, 22 * and display only the message (sans stack trace) 23 * to the user - on standard error, or, for Windows 24 * GUI programs, in a message box. 25 */ 26 mixin template main(alias realMain) 27 { 28 version (unittest_only) 29 { 30 shared static this() 31 { 32 import core.runtime : Runtime, UnitTestResult; 33 Runtime.extendedModuleUnitTester = { 34 foreach (m; ModuleInfo) 35 if (m) 36 if (auto fp = m.unitTest) 37 fp(); 38 return UnitTestResult(); 39 }; 40 } 41 } 42 else 43 int main(string[] args) 44 { 45 int run(string[] args) 46 { 47 static if (is(typeof(realMain()))) 48 static if (is(typeof(realMain()) == void)) 49 { realMain(); return 0; } 50 else 51 return realMain(); 52 else 53 static if (is(typeof(realMain(args)) == void)) 54 { realMain(args); return 0; } 55 else 56 return realMain(args); 57 } 58 59 int runCatchingException(E, string message)(string[] args) 60 { 61 try 62 return run(args); 63 catch (E e) 64 { 65 version (Windows) 66 { 67 import core.sys.windows.windows; 68 auto h = GetStdHandle(STD_ERROR_HANDLE); 69 if (!h || h == INVALID_HANDLE_VALUE) 70 { 71 import ae.sys.windows : messageBox; 72 messageBox(e.msg, message, MB_ICONERROR); 73 return 1; 74 } 75 } 76 77 import std.stdio : stderr; 78 stderr.writefln("%s: %s", message, e.msg); 79 return 1; 80 } 81 } 82 83 debug 84 static if(is(std.getopt.GetOptException)) 85 return runCatchingException!(std.getopt.GetOptException, "Usage error")(args); 86 else 87 return run(args); 88 else 89 return runCatchingException!(Throwable, "Fatal error")(args); 90 } 91 }