29
29
(require 'compile )
30
30
(require 'haskell-cabal )
31
31
(require 'ansi-color )
32
+ (eval-when-compile (require 'subr-x ))
32
33
33
34
;;;### autoload
34
35
(defgroup haskell-compile nil
37
38
:group 'haskell )
38
39
39
40
(defcustom haskell-compile-cabal-build-command
40
- " cd %s && cabal build --ghc-option=-ferror-spans"
41
+ " cabal build --ghc-option=-ferror-spans"
41
42
" Default build command to use for `haskell-cabal-build' when a cabal file is detected.
42
- The `%s' placeholder is replaced by the cabal package top folder."
43
+ For legacy compat, `%s' is replaced by the cabal package top folder."
43
44
:group 'haskell-compile
44
45
:type 'string )
45
46
46
47
(defcustom haskell-compile-cabal-build-alt-command
47
- " cd %s && cabal clean -s && cabal build --ghc-option=-ferror-spans"
48
+ " cabal clean -s && cabal build --ghc-option=-ferror-spans"
48
49
" Alternative build command to use when `haskell-cabal-build' is called with a negative prefix argument.
49
- The `%s' placeholder is replaced by the cabal package top folder."
50
+ For legacy compat, `%s' is replaced by the cabal package top folder."
51
+ :group 'haskell-compile
52
+ :type 'string )
53
+
54
+ (defcustom haskell-compile-stack-build-command
55
+ " stack build --fast"
56
+ " Default build command to use for `haskell-stack-build' when a stack file is detected.
57
+ For legacy compat, `%s' is replaced by the stack package top folder."
58
+ :group 'haskell-compile
59
+ :type 'string )
60
+
61
+ (defcustom haskell-compile-stack-build-alt-command
62
+ " stack clean && stack build --fast"
63
+ " Alternative build command to use when `haskell-stack-build' is called with a negative prefix argument.
64
+ For legacy compat, `%s' is replaced by the stack package top folder."
50
65
:group 'haskell-compile
51
66
:type 'string )
52
67
@@ -63,6 +78,13 @@ The `%s' placeholder is replaced by the current buffer's filename."
63
78
:group 'haskell-compile
64
79
:type 'boolean )
65
80
81
+ (defcustom haskell-compile-ignore-cabal nil
82
+ " Ignore cabal build definitions files for this buffer when detecting the build tool."
83
+ :group 'haskell-compile
84
+ :type 'boolean )
85
+ (make-variable-buffer-local 'haskell-compile-ignore-cabal )
86
+ (put 'haskell-compile-ignore-cabal 'safe-local-variable #'booleanp )
87
+
66
88
(defconst haskell-compilation-error-regexp-alist
67
89
`((,(concat
68
90
" ^ *\\ (?1:[^\t\r\n ]+?\\ ):"
@@ -121,42 +143,76 @@ messages pointing to additional source locations."
121
143
122
144
;;;### autoload
123
145
(defun haskell-compile (&optional edit-command )
124
- " Compile the Haskell program including the current buffer.
125
- Tries to locate the next cabal description in current or parent
126
- folders via `haskell-cabal-find-dir' and if found, invoke
127
- `haskell-compile-cabal-build-command' from the cabal package root
128
- folder. If no cabal package could be detected,
129
- `haskell-compile-command' is used instead.
146
+ " Run a compile command for the current Haskell buffer.
130
147
131
- If prefix argument EDIT-COMMAND is non-nil (and not a negative
132
- prefix `-' ), `haskell-compile' prompts for custom compile
133
- command.
134
-
135
- If EDIT-COMMAND contains the negative prefix argument `-' ,
136
- `haskell-compile' calls the alternative command defined in
137
- `haskell-compile-cabal-build-alt-command' if a cabal package was
138
- detected.
148
+ Locates stack or cabal definitions and, if found, invokes the
149
+ default build command for that build tool. Cabal is preferred
150
+ but may be ignored with `haskell-compile-ignore-cabal' .
139
151
140
- `haskell-compile' uses `haskell-compilation-mode' which is
141
- derived from `compilation-mode' . See Info
142
- node `(haskell-mode)compilation' for more details."
152
+ If prefix argument EDIT-COMMAND is non-nil (and not a negative
153
+ prefix `-' ), prompt for a custom compile command.
154
+
155
+ If EDIT-COMMAND contains the negative prefix argument `-' , call
156
+ the alternative command defined in
157
+ `haskell-compile-stack-build-alt-command' /
158
+ `haskell-compile-cabal-build-alt-command' .
159
+
160
+ If there is no prefix argument, the most recent custom compile
161
+ command is used, falling back to
162
+ `haskell-compile-stack-build-command' for stack builds
163
+ `haskell-compile-cabal-build-command' for cabal builds, and
164
+ `haskell-compile-command' otherwise.
165
+
166
+ '% characters in the `-command' templates are replaced by the
167
+ base directory for build tools, or the current buffer for
168
+ `haskell-compile-command' ."
143
169
(interactive " P" )
144
170
(save-some-buffers (not compilation-ask-about-save)
145
- compilation-save-buffers-predicate)
146
- (let* ((cabdir (haskell-cabal-find-dir))
147
- (command1 (if (eq edit-command '- )
148
- haskell-compile-cabal-build-alt-command
149
- haskell-compile-cabal-build-command))
150
- (srcname (buffer-file-name ))
151
- (command (if cabdir
152
- (format command1 cabdir)
153
- (if (and srcname (derived-mode-p 'haskell-mode ))
154
- (format haskell-compile-command srcname)
155
- command1))))
156
- (when (and edit-command (not (eq edit-command '- )))
157
- (setq command (compilation-read-command command)))
158
-
159
- (compilation-start command 'haskell-compilation-mode )))
171
+ compilation-save-buffers-predicate)
172
+ (if-let ((cabaldir (and
173
+ (not haskell-compile-ignore-cabal)
174
+ (or (haskell-cabal-find-dir)
175
+ (locate-dominating-file default-directory " cabal.project" )
176
+ (locate-dominating-file default-directory " cabal.project.local" )))))
177
+ (haskell--compile cabaldir edit-command
178
+ 'haskell--compile-cabal-last
179
+ haskell-compile-cabal-build-command
180
+ haskell-compile-cabal-build-alt-command)
181
+ (if-let ((stackdir (and haskell-compile-ignore-cabal
182
+ (locate-dominating-file default-directory " stack.yaml" ))))
183
+ (haskell--compile stackdir edit-command
184
+ 'haskell--compile-stack-last
185
+ haskell-compile-stack-build-command
186
+ haskell-compile-stack-build-alt-command)
187
+ (let ((srcfile (buffer-file-name )))
188
+ (haskell--compile srcfile edit-command
189
+ 'haskell--compile-ghc-last
190
+ haskell-compile-command
191
+ haskell-compile-command)))))
192
+
193
+ (defvar haskell--compile-stack-last nil )
194
+ (defvar haskell--compile-cabal-last nil )
195
+ (defvar haskell--compile-ghc-last nil )
196
+ (defun haskell--compile (dir-or-file edit last-sym fallback alt )
197
+ (let* ((default (or (symbol-value last-sym) fallback))
198
+ (template (pcase edit
199
+ ('nil default )
200
+ ('- alt)
201
+ (_ (compilation-read-command default ))))
202
+ (command (format template dir-or-file))
203
+ (dir (if (directory-name-p dir-or-file)
204
+ dir-or-file
205
+ default-directory))
206
+ (name (if (directory-name-p dir-or-file)
207
+ (file-name-base (directory-file-name dir-or-file))
208
+ (file-name-nondirectory dir-or-file))))
209
+ (unless (eq edit'- )
210
+ (set last-sym template))
211
+ (let ((default-directory dir))
212
+ (compilation-start
213
+ command
214
+ 'haskell-compilation-mode
215
+ (lambda (mode ) (format " *%s * <%s > " mode name))))))
160
216
161
217
(provide 'haskell-compile )
162
218
; ;; haskell-compile.el ends here
0 commit comments