-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathflex-compile-manage.el
187 lines (158 loc) · 6.78 KB
/
flex-compile-manage.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
;;; flex-compile-manage.el --- Manager for flexible compilers -*- lexical-binding: t; -*-
;; Copyright (C) 2015 - 2023 Paul Landes
;; Author: Paul Landes
;; Maintainer: Paul Landes
;; Keywords: compilation integration 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:
;; This file contains the manager object and all requires for concrete compiler
;; implementations. For this reason, each concreate compiler should need to
;; only require this library for implementations.
;;; Code:
(require 'cl-lib)
(require 'comint)
(require 'eieio)
(require 'eieio-base)
(require 'dash)
(require 'time-stamp)
(require 'config-manage)
(require 'choice-program-complete)
(require 'flex-compile-base)
(require 'flex-compile-config)
(require 'flex-compile-single-buffer)
(require 'flex-compile-repl)
;;; compiler shared configuration
(defcustom flex-compile-manage-load-libraries-entry 'activate
"When to load the compiler's libraries.
This invokes a method that `require's all the libraries needed for the compiler
to run."
:type '(choice (const :tag "When the compiler is activated" activate)
(const :tag "When the compiler is accessed" assert-ready))
:group 'flex-compile)
;;; compiler manager/orchestration
(defclass flex-compile-manager (config-manager config-persistable)
()
:documentation "\
Concrete instances of *flexible* compilers that provide a common interface.
Each is an implementation of glue code to the respective compilation method.
Note that all compilers that extend from `conf-file-flex-compiler', which
include `make', `script', `xml-validate', `org-mode', `python', `clojure', and
`ess' have their `start-directory' property unset each time the `config-file'
is set.")
(cl-defmethod initialize-instance ((this flex-compile-manager) &optional slots)
"Initialize instance THIS with arguments SLOTS."
(with-slots (entries) this
(setq entries (list (no-op-flex-compiler nil))))
(cl-call-next-method this slots))
(cl-defmethod config-persistable-load ((this flex-compile-manager))
"Restore the state of THIS instance persistable object."
(with-slots (entries) this
(let ((old-entries entries)
(old-emap (mapcar #'(lambda (entry)
(cons (config-entry-name entry) entry))
entries)))
(cl-call-next-method this)
(let ((new-emap (mapcar #'(lambda (entry)
(cons (config-entry-name entry) entry))
entries)))
(setq entries
(remove nil
(mapcar #'(lambda (entry)
(let* ((name (config-entry-name entry))
(new-entry (cdr (assoc name new-emap))))
(if new-entry
(if (assoc name old-emap)
new-entry)
entry)))
old-entries))))
(dolist (compiler entries)
;; since all compilers are persistable (via `config-entry inhertiance)
;; set the manager so we can save the state
(setf (slot-value compiler 'manager) this)))))
(cl-defmethod config-manager-entry-default-name ((this flex-compile-manager))
"Return `flexible-compiler'.
THIS is the object instance."
(ignore this)
"flexible-compiler")
(cl-defmethod flex-compile-manager-register ((this flex-compile-manager)
compiler)
"Register COMPILER instance with the manager \(compilation framework).
THIS is the object instance."
(with-slots (entries) this
(setq entries
(cl-delete compiler entries
:test #'(lambda (a b)
(equal (config-entry-name a)
(config-entry-name b)))))
(setq entries (append entries (cons compiler nil)))
(setf (slot-value compiler 'manager) this)
(message "Registered %s compiler" (config-entry-name compiler))))
(cl-defmethod config-manager-entry-names ((this flex-compile-manager))
"Return the names of all registered compilers.
THIS is the object instance."
(with-slots (entries) this
(mapcar #'config-entry-name entries)))
(cl-defmethod flex-compile-manager-active ((this flex-compile-manager))
"Return the currently selected or active manager.
THIS is the object instance."
(car (slot-value this 'entries)))
(cl-defmethod config-manager-activate ((this flex-compile-manager) criteria)
"Switch to a `flex-compiler’ in THIS manager.
CRITERIA, see the `config-manager’ method ‘config-manager-activate’."
(let ((compiler (cl-call-next-method this criteria)))
(message "Active compiler is now %s" (config-entry-name compiler))
(when (eq flex-compile-manage-load-libraries-entry 'activate)
(flex-compiler-load-libraries compiler))
compiler))
(cl-defmethod flex-compile-manager-assert-ready ((this flex-compile-manager))
"Make sure the active/selected compiler is ready and libraries loaded.
THIS is the object instance."
(let ((active (flex-compile-manager-active this)))
(when (eq flex-compile-manage-load-libraries-entry 'assert-ready)
(flex-compiler-load-libraries active))))
(cl-defmethod config-manager-remove-entry ((this flex-compile-manager) entry)
"Disallow ENTRY deletion since it is nonsensical for this implementation.
THIS is the object instance."
(ignore this entry)
(config-persistent--unimplemented this "remove-entry"))
(cl-defmethod flex-compile-clear ((this flex-compile-manager))
"Clear all compiler's state.
This is done by simply re-instantiating all current registered compilers.
THIS is the object instance."
(let ((entries (slot-value this 'entries)))
(setf (slot-value this 'entries) nil)
(dolist (compiler entries)
(->> (eieio-object-class compiler)
funcall
(flex-compile-manager-register this)))))
;; library configuration
(defvar flex-compile-manage-inst
(flex-compile-manager :object-name "compiler")
"The singleton manager instance.")
(defcustom flex-compile-manage-persistency-file-name
(expand-file-name "flex-compile" user-emacs-directory)
"File containing the Flex compile configuration data."
:type 'file
:group 'flex-compile
:set (lambda (sym val)
(set-default sym val)
(if (and (boundp 'flex-compile-manage-inst)
flex-compile-manage-inst)
(setf (slot-value flex-compile-manage-inst 'file) val))))
(provide 'flex-compile-manage)
;;; flex-compile-manage.el ends here