forked from tonini/alchemist.el
-
Notifications
You must be signed in to change notification settings - Fork 0
/
alchemist-mix.el
214 lines (169 loc) · 7.72 KB
/
alchemist-mix.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
;;; alchemist-mix.el --- Interface to run Elixir mix tasks inside Emacs
;; Copyright © 2014-2015 Samuel Tonini
;; Author: Samuel Tonini <tonini.samuel@gmail.com
;; This file is not part of GNU Emacs.
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Interface to run Elixir mix tasks inside Emacs.
;;; Code:
(require 'alchemist-utils)
(require 'alchemist-project)
(require 'alchemist-test-mode)
(defgroup alchemist-mix nil
"Emacs integration for Elixir's mix."
:prefix "alchemist-mix-"
:group 'alchemist)
;; Variables
(defvar alchemist-last-run-test nil)
(defcustom alchemist-mix-command "mix"
"The shell command for mix."
:type 'string
:group 'alchemist-mix)
(defcustom alchemist-mix-test-task "test"
"Default task to run tests."
:type 'string
:group 'alchemist-mix)
(defcustom alchemist-mix-test-default-options '("--exclude pending:true")
"Default options for alchemist test command."
:type '(repeat string)
:group 'alchemist-mix)
(defcustom alchemist-mix-env nil
"The default mix env to run mix commands with. If nil, the mix env is
not set explicitly."
:type '(string boolean)
:group 'alchemist-mix)
(defvar alchemist-mix-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "q" #'quit-window)
(define-key map "i" #'alchemist-mix-send-input-to-mix-process)
map))
(defvar alchemist-mix-buffer-name "*mix*"
"Name of the mix output buffer.")
(defvar alchemist-mix--envs '("dev" "prod" "test")
"The list of mix envs to use as defaults.")
;; Private functions
(defun alchemist-mix--completing-read (prompt cmdlist)
(completing-read prompt cmdlist nil t nil nil (car cmdlist)))
(defun alchemist-mix--execute-test (&optional what)
"Execute 'mix test' on the given `WHAT'.
`WHAT' could be a filename, a filename:line string or the empty string (meaning
run all tests)."
(if what
(setq alchemist-last-run-test what)
(setq alchemist-last-run-test ""))
(alchemist-test-execute (list "mix"
alchemist-mix-test-task
what
alchemist-mix-test-default-options)))
(defun alchemist-mix--test-file (filename)
"Run a specific FILENAME as argument for the mix command test."
(when (not (file-exists-p filename))
(error "The given file doesn't exists"))
(alchemist-mix--execute-test (expand-file-name filename)))
;; Public functions
(defun alchemist-mix ()
"Prompt for a specific mix task to run.
If the command `universal-argument' is called before `alchemist-mix',
a prompt for a specific mix environment in which the task will be
executed, gets called."
(interactive)
(alchemist-server--mix))
(defun alchemist-mix-display-mix-buffer ()
"Display the mix buffer when exists."
(interactive)
(when (get-buffer alchemist-mix-buffer-name)
(display-buffer alchemist-mix-buffer-name)))
(defun alchemist-mix-test ()
"Run the whole elixir test suite."
(interactive)
(alchemist-mix--execute-test))
(defun alchemist-mix-test-this-buffer ()
"Run the current buffer through mix test."
(interactive)
(alchemist-mix--test-file buffer-file-name))
(defun alchemist-mix-test-file (filename)
"Run `alchemist-mix--test-file' with the FILENAME."
(interactive "Fmix test: ")
(alchemist-mix--test-file (expand-file-name filename)))
(defun alchemist-mix-test-at-point ()
"Run the test at point."
(interactive)
(let* ((line (line-number-at-pos (point)))
(file-and-line (format "%s:%s" buffer-file-name line)))
(alchemist-mix--execute-test file-and-line)))
(defun alchemist-mix-rerun-last-test ()
"Rerun the last test that was run by alchemist.
When no tests had been run before calling this function, do nothing."
(interactive)
(if alchemist-last-run-test
(alchemist-mix--execute-test alchemist-last-run-test)
(message "No tests have been run yet")))
(defun alchemist-mix-compile (command &optional prefix)
"Compile the whole elixir project. Prompt for the mix env if the prefix
arg is set."
(interactive "Mmix compile: \nP")
(alchemist-mix-execute (list "compile" command) prefix))
(defun alchemist-mix-run (command &optional prefix)
"Runs the given file or expression in the context of the application."
(interactive "Mmix run: \nP")
(alchemist-mix-execute (list "run" command) prefix))
(defun alchemist-mix-send-input-to-mix-process (input)
"Send INPUT to the current running mix task process."
(interactive "MSend to running mix task: ")
(let* ((buffer (get-buffer alchemist-mix-buffer-name))
(process (get-buffer-process buffer)))
(if (and process (eq (process-status process) 'run))
(with-current-buffer buffer
(let ((inhibit-read-only t))
(end-of-buffer)
(insert (concat input "\n\n"))
(set-marker (process-mark process) (point)))
(comint-send-string process (concat input "\n")))
(error "No %s process is running" alchemist-mix-buffer-name))))
(defun alchemist-mix-help () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-help" "alchemist-mix"))
(defun alchemist-mix-new () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-new" "alchemist-mix"))
(defun alchemist-mix-deps () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-deps" "alchemist-mix"))
(defun alchemist-mix-deps-with-prompt () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-deps-with-prompt" "alchemist-mix"))
(defun alchemist-mix-local-with-prompt () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-local-with-prompt" "alchemist-mix"))
(defun alchemist-mix-local () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-local" "alchemist-mix"))
(defun alchemist-mix-local-install () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-local-install" "alchemist-mix"))
(defun alchemist-mix-local-with-url () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-local-with-url" "alchemist-mix"))
(defun alchemist-mix-local-with-path () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-local-with-path" "alchemist-mix"))
(defun alchemist-mix-hex-search () (interactive)
(alchemist-utils-deprecated-message "alchemist-mix-local-hex-search" "alchemist-mix"))
(define-derived-mode alchemist-mix-mode fundamental-mode "Mix Mode"
"Major mode for presenting Mix tasks.
\\{alchemist-mix-mode-map}"
(setq buffer-read-only t)
(setq-local truncate-lines t)
(setq-local electric-indent-chars nil))
(defun alchemist-mix-execute (command-list &optional prefix)
"Run a mix task specified by COMMAND-LIST.
If PREFIX is non-nil, prompt for a mix environment variable."
(let* ((mix-env (if prefix
(completing-read "mix env: " alchemist-mix--envs nil nil alchemist-mix-env)
alchemist-mix-env))
(command (alchemist-utils--build-command
(list (when mix-env (concat "MIX_ENV=" mix-env))
alchemist-mix-command command-list))))
(alchemist-report-run command "alchemist-mix-report" alchemist-mix-buffer-name 'alchemist-mix-mode)))
(provide 'alchemist-mix)
;;; alchemist-mix.el ends here