1 /**
2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved.
3 License: MPL-2
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 This Source Code Form is subject to the terms of the Mozilla Public License,
7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain
8 one at http://mozilla.org/MPL/2.0/.
9 
10 This file contains the integration needed for using dfmt to format D code.
11 */
12 module autoformat.format_d;
13 
14 import std.algorithm;
15 import std.array;
16 import std.exception;
17 import std.file;
18 import std.string : join;
19 import std.process;
20 import logger = std.experimental.logger;
21 
22 import std.typecons : Flag;
23 
24 import autoformat.types;
25 
26 private immutable string[] dfmtConf = import("dfmt.conf").splitter("\n")
27     .filter!(a => a.length > 0).array();
28 
29 // Thread local optimization that reduced the console spam when the program
30 // isn't installed.
31 bool installed = true;
32 
33 // TODO dry_run not supported.
34 auto runDfmt(AbsolutePath fname, Flag!"backup" backup, Flag!"dryRun" dry_run) nothrow {
35     if (dry_run || !installed) {
36         return FormatterResult(Unchanged.init);
37     }
38 
39     string[] opts = dfmtConf.map!(a => a.idup).array();
40 
41     auto rval = FormatterResult(FormatError.init);
42 
43     try {
44         if (backup) {
45             copy(fname, fname.toString ~ ".orig");
46         }
47 
48         auto arg = ["dfmt"] ~ opts ~ [cast(string) fname];
49         logger.trace(arg.join(" "));
50         auto res = execute(arg);
51         logger.trace(res.output);
52 
53         rval = FormatterResult(FormattedOk.init);
54     } catch (ProcessException ex) {
55         // dfmt isn't installed
56         rval = FormatterResult(FailedWithUserMsg(ex.msg));
57         installed = false;
58     } catch (Exception ex) {
59         rval = FormatterResult(FailedWithUserMsg(ex.msg));
60     }
61 
62     return rval;
63 }