-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathflex-compile-clojure.el
176 lines (147 loc) · 6.29 KB
/
flex-compile-clojure.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
;;; flex-compile-clojure.el --- Clojure compile functions -*- lexical-binding: t; -*-
;; Copyright (C) 2015 - 2023 Paul Landes
;; Author: Paul Landes
;; Maintainer: Paul Landes
;; Keywords: clojure cider compilation processes
;; URL: https://github.com/plandes/flex-compile
;; Package-Requires: ((emacs "26.1"))
;; Package-Version: 0
;; 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 2, 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, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Implementation compiler for Clojure with Cider integration
;;; Code:
(require 'dash)
(require 'flex-compile-manage)
(declare-function cider-repl-return "cider")
(declare-function cider-connect "cider")
(declare-function cider-current-connection "cider")
(declare-function cider-current-session "cider")
(declare-function cider-current-ns "cider")
(declare-function cider-load-file "cider")
(declare-function cider-last-sexp "cider")
(declare-function cider-quit "cider")
(declare-function cider-jack-in "cider")
(declare-function nrepl-dict-get "nrepl-dict")
(declare-function nrepl-sync-request:eval "nrepl-client")
(config-manage-declare-variables
cider-repl-display-in-current-window)
(defclass clojure-flex-compiler (repl-flex-compiler)
((repl-host :initarg :repl-host
:type string
:initform "localhost"
:documentation "The host running the REPL; default: localhost")
(repl-port :initarg :repl-port
:type integer
:initform 32345
:documentation "The port running the REPL; default: 32345")
(connect-mode :initarg :connect-mode
:type symbol
:initform 'jack-in
:documentation "\
Defines how to connect to a Clojure REPL.
The connection modes include:
- 'jack-in local mode, which invokes `cider-jack-in'
- 'connect remote mode, which invokes `cider-connect' using slots:
`repl-host' and `repl-port'"))
:method-invocation-order :c3
:documentation "\
This is a REPL based compiler that allows for evaluation Clojure
buffers, expressions and starting the REPL using
\[Cider](https://github.com/clojure-emacs/cider).
The Clojure compiler connects using two Cider modes: the default `jack-in'
mode or connecting to a host and port remotely with `cider-connect'. You can
switch betwee these two methods with the [given keybindings](#key-bindings):
`M-x 1 C-u C-x C-u'
See documetation with `M-h f flex-compiler-query-eval' method for more
inforamtion (and current binding).
Todo: support multiple Cider buffers as this implementation currently does
not.")
(cl-defmethod initialize-instance ((this clojure-flex-compiler) &optional slots)
"Initialize THIS instance using SLOTS as initial values."
(let ((props (list (config-choice-prop :object-name 'connect-mode
:prop-entry this
:prompt "Connection mode"
:choices '(jack-in connect)
:input-type 'toggle)
(config-number-prop :object-name 'repl-port
:prop-entry this
:prompt "REPL port"
:input-type 'last))))
(setq slots (plist-put slots :object-name "clojure")
slots (plist-put slots :validate-modes '(clojure-mode))
slots (plist-put slots :repl-buffer-regexp
"^\\(\\*cider-repl \\|nrepl-server\\)")
;; also see `nrepl-sync-request-timeout'
slots (plist-put slots :repl-buffer-start-timeout 0)
slots (plist-put slots
:props (append (plist-get slots :props) props))))
(cl-call-next-method this slots))
(cl-defmethod flex-compiler-load-libraries ((this clojure-flex-compiler))
"Load the `cider' library for THIS compiler.
This also sets `cider-repl-display-in-current-window' to nil"
(ignore this)
(require 'cider)
;; allow flex-compile to manage windows and frame
(setq cider-repl-display-in-current-window nil))
(cl-defmethod flex-compiler-send-input ((this clojure-flex-compiler)
&optional command)
"Send a COMMAND (input) to THIS compiler’s Cider REPL."
(ignore this)
(goto-char (point-max))
(insert command)
(cider-repl-return))
(cl-defmethod flex-compiler-eval-form-impl ((this clojure-flex-compiler) form)
"Evaluate the FORM and return the Cider REPL's response for THIS compiler."
(ignore this)
(let* ((res (nrepl-sync-request:eval
form
(cider-current-connection)
(cider-current-ns))))
(or (nrepl-dict-get res "err")
(nrepl-dict-get res "value"))))
(cl-defmethod flex-compiler-repl-compile ((this clojure-flex-compiler) file)
"Send the contents of FILE to the Cider REPL buffer of THIS compiler."
(ignore this)
(save-excursion
(set-buffer (list (find-file-noselect file)))
(cider-load-file file)))
(cl-defmethod flex-compiler-eval-initial-at-point
((this clojure-flex-compiler))
"Return the Clojure form at the current point to the REPL for THIS compiler."
(ignore this)
(cider-last-sexp))
(cl-defmethod flex-compiler-kill-repl ((this clojure-flex-compiler))
"Use `cider-quit' to stop the Cider REPL for THIS compiler."
(condition-case err
(cider-quit t)
(error "Warning: %S" err))
(cl-call-next-method this))
(cl-defmethod flex-compiler-repl-start ((this clojure-flex-compiler))
"Start the Cider REPL using THIS compiler."
(with-slots (connect-mode repl-host repl-port) this
(with-current-buffer (flex-compiler-conf-file-buffer this)
(cl-case connect-mode
;; hack to fix some pathology with nrepl window management and custom
;; `display-buffer-alists' settings
(connect (let ((wc (current-window-configuration)))
(save-excursion
(cider-connect (list :host repl-host :port repl-port)))
(set-window-configuration wc)))
(jack-in (cider-jack-in nil))
(t (error "No such connection mode supported: %S" connect-mode))))))
(flex-compile-manager-register flex-compile-manage-inst
(clojure-flex-compiler))
(provide 'flex-compile-clojure)
;;; flex-compile-clojure.el ends here