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 int main(string[] args) 29 { 30 int run(string[] args) 31 { 32 static if (is(typeof(realMain()))) 33 static if (is(typeof(realMain()) == void)) 34 { realMain(); return 0; } 35 else 36 return realMain(); 37 else 38 static if (is(typeof(realMain(args)) == void)) 39 { realMain(args); return 0; } 40 else 41 return realMain(args); 42 } 43 44 int runCatchingException(E, string message)(string[] args) 45 { 46 try 47 return run(args); 48 catch (E e) 49 { 50 version (Windows) 51 { 52 import core.sys.windows.windows; 53 auto h = GetStdHandle(STD_ERROR_HANDLE); 54 if (!h || h == INVALID_HANDLE_VALUE) 55 { 56 import ae.sys.windows : messageBox; 57 messageBox(e.msg, message, MB_ICONERROR); 58 return 1; 59 } 60 } 61 62 import std.stdio : stderr; 63 stderr.writefln("%s: %s", message, e.msg); 64 return 1; 65 } 66 } 67 68 debug 69 static if(is(std.getopt.GetOptException)) 70 return runCatchingException!(std.getopt.GetOptException, "Usage error")(args); 71 else 72 return run(args); 73 else 74 return runCatchingException!(Throwable, "Fatal error")(args); 75 } 76 }