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