Commit | Line | Data |
---|---|---|
cb85c0d8 EL |
1 | ;;; ede/base.el --- Baseclasses for EDE. |
2 | ||
5df4f04c | 3 | ;; Copyright (C) 2010, 2011 Free Software Foundation, Inc. |
cb85c0d8 EL |
4 | |
5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
6 | ||
7 | ;; This file is part of GNU Emacs. | |
8 | ||
9 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation, either version 3 of the License, or | |
12 | ;; (at your option) any later version. | |
13 | ||
14 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ;;; Commentary: | |
23 | ;; | |
24 | ;; Baseclasses for EDE. | |
25 | ;; | |
26 | ;; Contains all the base structures needed by EDE. | |
27 | ||
28 | ;;; Code: | |
29 | (require 'eieio) | |
30 | (require 'eieio-speedbar) | |
31 | (require 'ede/auto) | |
32 | ||
33 | ;; Defined in ede.el: | |
34 | (defvar ede-projects) | |
35 | (defvar ede-object) | |
36 | (defvar ede-object-root-project) | |
37 | ||
38 | (declare-function data-debug-new-buffer "data-debug") | |
39 | (declare-function data-debug-insert-object-slots "eieio-datadebug") | |
40 | (declare-function ede-parent-project "ede" (&optional obj)) | |
41 | (declare-function ede-current-project "ede" (&optional dir)) | |
42 | ||
43 | ;;; TARGET | |
44 | ;; | |
45 | ;; The TARGET is an entity in a project that knows about files | |
46 | ;; and features of those files. | |
47 | ||
48 | (defclass ede-target (eieio-speedbar-directory-button) | |
49 | ((buttonface :initform speedbar-file-face) ;override for superclass | |
50 | (name :initarg :name | |
51 | :type string | |
52 | :custom string | |
53 | :label "Name" | |
54 | :group (default name) | |
55 | :documentation "Name of this target.") | |
56 | ;; @todo - I think this should be "dir", and not "path". | |
57 | (path :initarg :path | |
58 | :type string | |
59 | ;:custom string | |
60 | ;:label "Path to target" | |
61 | ;:group (default name) | |
62 | :documentation "The path to the sources of this target. | |
63 | Relative to the path of the project it belongs to.") | |
64 | (source :initarg :source | |
65 | :initform nil | |
66 | ;; I'd prefer a list of strings. | |
67 | :type list | |
68 | :custom (repeat (string :tag "File")) | |
69 | :label "Source Files" | |
70 | :group (default source) | |
71 | :documentation "Source files in this target.") | |
72 | (versionsource :initarg :versionsource | |
73 | :initform nil | |
74 | :type list | |
75 | :custom (repeat (string :tag "File")) | |
76 | :label "Source Files with Version String" | |
77 | :group (source) | |
78 | :documentation | |
79 | "Source files with a version string in them. | |
80 | These files are checked for a version string whenever the EDE version | |
81 | of the master project is changed. When strings are found, the version | |
82 | previously there is updated.") | |
83 | ;; Class level slots | |
84 | ;; | |
85 | (sourcetype :allocation :class | |
86 | :type list ;; list of symbols | |
87 | :documentation | |
88 | "A list of `ede-sourcecode' objects this class will handle. | |
89 | This is used to match target objects with the compilers they can use, and | |
90 | which files this object is interested in." | |
91 | :accessor ede-object-sourcecode) | |
92 | (keybindings :allocation :class | |
93 | :initform (("D" . ede-debug-target)) | |
94 | :documentation | |
95 | "Keybindings specialized to this type of target." | |
96 | :accessor ede-object-keybindings) | |
97 | (menu :allocation :class | |
98 | :initform ( [ "Debug target" ede-debug-target | |
99 | (ede-buffer-belongs-to-target-p) ] | |
100 | [ "Run target" ede-run-target | |
101 | (ede-buffer-belongs-to-target-p) ] | |
102 | ) | |
103 | :documentation "Menu specialized to this type of target." | |
104 | :accessor ede-object-menu) | |
105 | ) | |
106 | "A target is a structure that describes a file set that produces something. | |
107 | Targets, as with 'Make', is an entity that will manage a file set | |
108 | and knows how to compile or otherwise transform those files into some | |
109 | other desired outcome.") | |
110 | ||
111 | ;;; PROJECT/PLACEHOLDER | |
112 | ;; | |
113 | ;; Project placeholders are minimum parts of a project used | |
114 | ;; by the project cache. The project cache can refer to these placeholders, | |
115 | ;; and swap them out with the real-deal when that project is loaded. | |
116 | ;; | |
117 | (defclass ede-project-placeholder (eieio-speedbar-directory-button) | |
118 | ((name :initarg :name | |
119 | :initform "Untitled" | |
120 | :type string | |
121 | :custom string | |
122 | :label "Name" | |
123 | :group (default name) | |
124 | :documentation "The name used when generating distribution files.") | |
125 | (version :initarg :version | |
126 | :initform "1.0" | |
127 | :type string | |
128 | :custom string | |
129 | :label "Version" | |
130 | :group (default name) | |
131 | :documentation "The version number used when distributing files.") | |
132 | (directory :type string | |
133 | :initarg :directory | |
134 | :documentation "Directory this project is associated with.") | |
135 | (dirinode :documentation "The inode id for :directory.") | |
136 | (file :type string | |
137 | :initarg :file | |
138 | :documentation "File name where this project is stored.") | |
139 | (rootproject ; :initarg - no initarg, don't save this slot! | |
140 | :initform nil | |
141 | :type (or null ede-project-placeholder-child) | |
142 | :documentation "Pointer to our root project.") | |
143 | ) | |
144 | "Placeholder object for projects not loaded into memory. | |
145 | Projects placeholders will be stored in a user specific location | |
146 | and querying them will cause the actual project to get loaded.") | |
147 | ||
148 | ;;; PROJECT | |
149 | ;; | |
150 | ;; An EDE project controls a set of TARGETS, and can also contain | |
151 | ;; multiple SUBPROJECTS. | |
152 | ;; | |
153 | ;; The project defines a set of features that need to be built from | |
154 | ;; files, in addition as to controlling what to do with the file set, | |
155 | ;; such as creating distributions, compilation, and web sites. | |
156 | ;; | |
157 | ;; Projects can also affect how EDE works, by changing what appears in | |
158 | ;; the EDE menu, or how some keys are bound. | |
159 | ;; | |
160 | (defclass ede-project (ede-project-placeholder) | |
161 | ((subproj :initform nil | |
162 | :type list | |
163 | :documentation "Sub projects controlled by this project. | |
164 | For Automake based projects, each directory is treated as a project.") | |
165 | (targets :initarg :targets | |
166 | :type list | |
167 | :custom (repeat (object :objectcreatefcn ede-new-target-custom)) | |
168 | :label "Local Targets" | |
169 | :group (targets) | |
170 | :documentation "List of top level targets in this project.") | |
171 | (locate-obj :type (or null ede-locate-base-child) | |
172 | :documentation | |
173 | "A locate object to use as a backup to `ede-expand-filename'.") | |
174 | (tool-cache :initarg :tool-cache | |
175 | :type list | |
176 | :custom (repeat object) | |
177 | :label "Tool: " | |
178 | :group tools | |
179 | :documentation "List of tool cache configurations in this project. | |
180 | This allows any tool to create, manage, and persist project-specific settings.") | |
181 | (mailinglist :initarg :mailinglist | |
182 | :initform "" | |
183 | :type string | |
184 | :custom string | |
185 | :label "Mailing List Address" | |
186 | :group name | |
187 | :documentation | |
188 | "An email address where users might send email for help.") | |
189 | (web-site-url :initarg :web-site-url | |
190 | :initform "" | |
191 | :type string | |
192 | :custom string | |
193 | :label "Web Site URL" | |
194 | :group name | |
195 | :documentation "URL to this projects web site. | |
196 | This is a URL to be sent to a web site for documentation.") | |
197 | (web-site-directory :initarg :web-site-directory | |
198 | :initform "" | |
199 | :custom string | |
200 | :label "Web Page Directory" | |
201 | :group name | |
202 | :documentation | |
203 | "A directory where web pages can be found by Emacs. | |
204 | For remote locations use a path compatible with ange-ftp or EFS. | |
205 | You can also use TRAMP for use with rcp & scp.") | |
206 | (web-site-file :initarg :web-site-file | |
207 | :initform "" | |
208 | :custom string | |
209 | :label "Web Page File" | |
210 | :group name | |
211 | :documentation | |
212 | "A file which contains the home page for this project. | |
213 | This file can be relative to slot `web-site-directory'. | |
214 | This can be a local file, use ange-ftp, EFS, or TRAMP.") | |
215 | (ftp-site :initarg :ftp-site | |
216 | :initform "" | |
217 | :type string | |
218 | :custom string | |
219 | :label "FTP site" | |
220 | :group name | |
221 | :documentation | |
222 | "FTP site where this project's distribution can be found. | |
223 | This FTP site should be in Emacs form, as needed by `ange-ftp', but can | |
224 | also be of a form used by TRAMP for use with scp, or rcp.") | |
225 | (ftp-upload-site :initarg :ftp-upload-site | |
226 | :initform "" | |
227 | :type string | |
228 | :custom string | |
229 | :label "FTP Upload site" | |
230 | :group name | |
231 | :documentation | |
232 | "FTP Site to upload new distributions to. | |
233 | This FTP site should be in Emacs form as needed by `ange-ftp'. | |
234 | If this slot is nil, then use `ftp-site' instead.") | |
235 | (configurations :initarg :configurations | |
236 | :initform ("debug" "release") | |
237 | :type list | |
238 | :custom (repeat string) | |
239 | :label "Configuration Options" | |
240 | :group (settings) | |
241 | :documentation "List of available configuration types. | |
242 | Individual target/project types can form associations between a configuration, | |
243 | and target specific elements such as build variables.") | |
244 | (configuration-default :initarg :configuration-default | |
245 | :initform "debug" | |
246 | :custom string | |
247 | :label "Current Configuration" | |
248 | :group (settings) | |
249 | :documentation "The default configuration.") | |
250 | (local-variables :initarg :local-variables | |
251 | :initform nil | |
252 | :custom (repeat (cons (sexp :tag "Variable") | |
253 | (sexp :tag "Value"))) | |
254 | :label "Project Local Variables" | |
255 | :group (settings) | |
256 | :documentation "Project local variables") | |
257 | (keybindings :allocation :class | |
258 | :initform (("D" . ede-debug-target) | |
259 | ("R" . ede-run-target)) | |
260 | :documentation "Keybindings specialized to this type of target." | |
261 | :accessor ede-object-keybindings) | |
262 | (menu :allocation :class | |
263 | :initform | |
264 | ( | |
265 | [ "Update Version" ede-update-version ede-object ] | |
266 | [ "Version Control Status" ede-vc-project-directory ede-object ] | |
267 | [ "Edit Project Homepage" ede-edit-web-page | |
268 | (and ede-object (oref (ede-toplevel) web-site-file)) ] | |
269 | [ "Browse Project URL" ede-web-browse-home | |
270 | (and ede-object | |
271 | (not (string= "" (oref (ede-toplevel) web-site-url)))) ] | |
272 | "--" | |
273 | [ "Rescan Project Files" ede-rescan-toplevel t ] | |
274 | [ "Edit Projectfile" ede-edit-file-target | |
275 | (ede-buffer-belongs-to-project-p) ] | |
276 | ) | |
277 | :documentation "Menu specialized to this type of target." | |
278 | :accessor ede-object-menu) | |
279 | ) | |
280 | "Top level EDE project specification. | |
281 | All specific project types must derive from this project." | |
282 | :method-invocation-order :depth-first) | |
283 | ||
284 | ;;; Important macros for doing commands. | |
285 | ;; | |
286 | (defmacro ede-with-projectfile (obj &rest forms) | |
287 | "For the project in which OBJ resides, execute FORMS." | |
288 | (list 'save-window-excursion | |
289 | (list 'let* (list | |
290 | (list 'pf | |
291 | (list 'if (list 'obj-of-class-p | |
292 | obj 'ede-target) | |
293 | ;; @todo -I think I can change | |
294 | ;; this to not need ede-load-project-file | |
295 | ;; but I'm not sure how to test well. | |
296 | (list 'ede-load-project-file | |
297 | (list 'oref obj 'path)) | |
298 | obj)) | |
299 | '(dbka (get-file-buffer (oref pf file)))) | |
300 | '(if (not dbka) (find-file (oref pf file)) | |
301 | (switch-to-buffer dbka)) | |
302 | (cons 'progn forms) | |
303 | '(if (not dbka) (kill-buffer (current-buffer)))))) | |
304 | (put 'ede-with-projectfile 'lisp-indent-function 1) | |
305 | ||
306 | ;;; The EDE persistent cache. | |
307 | ;; | |
308 | ;; The cache is a way to mark where all known projects live without | |
309 | ;; loading those projects into memory, or scanning for them each time | |
310 | ;; emacs starts. | |
311 | ;; | |
312 | (defcustom ede-project-placeholder-cache-file | |
313 | (locate-user-emacs-file "ede-projects.el" ".projects.ede") | |
314 | "File containing the list of projects EDE has viewed." | |
315 | :group 'ede | |
316 | :type 'file) | |
317 | ||
318 | (defvar ede-project-cache-files nil | |
319 | "List of project files EDE has seen before.") | |
320 | ||
321 | (defun ede-save-cache () | |
322 | "Save a cache of EDE objects that Emacs has seen before." | |
323 | (interactive) | |
324 | (let ((p ede-projects) | |
325 | (c ede-project-cache-files) | |
326 | (recentf-exclude '( (lambda (f) t) )) | |
327 | ) | |
328 | (condition-case nil | |
329 | (progn | |
330 | (set-buffer (find-file-noselect ede-project-placeholder-cache-file t)) | |
331 | (erase-buffer) | |
332 | (insert ";; EDE project cache file. | |
333 | ;; This contains a list of projects you have visited.\n(") | |
334 | (while p | |
335 | (when (and (car p) (ede-project-p p)) | |
336 | (let ((f (oref (car p) file))) | |
337 | (when (file-exists-p f) | |
338 | (insert "\n \"" f "\"")))) | |
339 | (setq p (cdr p))) | |
340 | (while c | |
341 | (insert "\n \"" (car c) "\"") | |
342 | (setq c (cdr c))) | |
343 | (insert "\n)\n") | |
344 | (condition-case nil | |
345 | (save-buffer 0) | |
346 | (error | |
347 | (message "File %s could not be saved." | |
348 | ede-project-placeholder-cache-file))) | |
349 | (kill-buffer (current-buffer)) | |
350 | ) | |
351 | (error | |
352 | (message "File %s could not be read." | |
353 | ede-project-placeholder-cache-file)) | |
354 | ||
355 | ))) | |
356 | ||
357 | (defun ede-load-cache () | |
358 | "Load the cache of EDE projects." | |
359 | (save-excursion | |
360 | (let ((cachebuffer nil)) | |
361 | (condition-case nil | |
362 | (progn | |
363 | (setq cachebuffer | |
364 | (find-file-noselect ede-project-placeholder-cache-file t)) | |
365 | (set-buffer cachebuffer) | |
366 | (goto-char (point-min)) | |
367 | (let ((c (read (current-buffer))) | |
368 | (new nil) | |
369 | (p ede-projects)) | |
370 | ;; Remove loaded projects from the cache. | |
371 | (while p | |
372 | (setq c (delete (oref (car p) file) c)) | |
373 | (setq p (cdr p))) | |
374 | ;; Remove projects that aren't on the filesystem | |
375 | ;; anymore. | |
376 | (while c | |
377 | (when (file-exists-p (car c)) | |
378 | (setq new (cons (car c) new))) | |
379 | (setq c (cdr c))) | |
380 | ;; Save it | |
381 | (setq ede-project-cache-files (nreverse new)))) | |
382 | (error nil)) | |
383 | (when cachebuffer (kill-buffer cachebuffer)) | |
384 | ))) | |
385 | ||
386 | ;;; Get the cache usable. | |
387 | ||
388 | ;; @TODO - Remove this cache setup, or use this for something helpful. | |
389 | ;;(add-hook 'kill-emacs-hook 'ede-save-cache) | |
390 | ;;(when (not noninteractive) | |
391 | ;; ;; No need to load the EDE cache if we aren't interactive. | |
392 | ;; ;; This occurs during batch byte-compiling of other tools. | |
393 | ;; (ede-load-cache)) | |
394 | ||
395 | \f | |
396 | ;;; METHODS | |
397 | ;; | |
398 | ;; The methods in ede-base handle project related behavior, and DO NOT | |
399 | ;; related to EDE mode commands directory, such as keybindings. | |
400 | ;; | |
401 | ;; Mode related methods are in ede.el. These methods are related | |
402 | ;; project specific activities not directly tied to a keybinding. | |
403 | (defmethod ede-subproject-relative-path ((proj ede-project) &optional parent-in) | |
404 | "Get a path name for PROJ which is relative to the parent project. | |
405 | If PARENT is specified, then be relative to the PARENT project. | |
406 | Specifying PARENT is useful for sub-sub projects relative to the root project." | |
407 | (let* ((parent (or parent-in (ede-parent-project proj))) | |
408 | (dir (file-name-directory (oref proj file)))) | |
409 | (if (and parent (not (eq parent proj))) | |
410 | (file-relative-name dir (file-name-directory (oref parent file))) | |
411 | ""))) | |
412 | ||
413 | (defmethod ede-subproject-p ((proj ede-project)) | |
414 | "Return non-nil if PROJ is a sub project." | |
415 | ;; @TODO - Use this in more places, and also pay attention to | |
416 | ;; metasubproject in ede-proj.el | |
417 | (ede-parent-project proj)) | |
418 | ||
419 | \f | |
420 | ;;; Default descriptive methods for EDE classes | |
421 | ;; | |
422 | ;; These are methods which you might want to override, but there is | |
423 | ;; no need to in most situations because they are either a) simple, or | |
424 | ;; b) cosmetic. | |
425 | ||
426 | (defmethod ede-name ((this ede-target)) | |
427 | "Return the name of THIS target." | |
428 | (oref this name)) | |
429 | ||
430 | (defmethod ede-target-name ((this ede-target)) | |
431 | "Return the name of THIS target, suitable for make or debug style commands." | |
432 | (oref this name)) | |
433 | ||
434 | (defmethod ede-name ((this ede-project)) | |
435 | "Return a short-name for THIS project file. | |
436 | Do this by extracting the lowest directory name." | |
437 | (oref this name)) | |
438 | ||
439 | (defmethod ede-description ((this ede-project)) | |
440 | "Return a description suitable for the minibuffer about THIS." | |
441 | (format "Project %s: %d subprojects, %d targets." | |
442 | (ede-name this) (length (oref this subproj)) | |
443 | (length (oref this targets)))) | |
444 | ||
445 | (defmethod ede-description ((this ede-target)) | |
446 | "Return a description suitable for the minibuffer about THIS." | |
447 | (format "Target %s: with %d source files." | |
448 | (ede-name this) (length (oref this source)))) | |
449 | ||
450 | ;;; HEADERS/DOC | |
451 | ;; | |
452 | ;; Targets and projects are often associated with other files, such as | |
453 | ;; header files, documentation files and the like. Have strong | |
454 | ;; associations can make useful user commands to quickly navigate | |
c0943d3d | 455 | ;; between the files based on their associations. |
cb85c0d8 EL |
456 | ;; |
457 | (defun ede-header-file () | |
458 | "Return the header file for the current buffer. | |
459 | Not all buffers need headers, so return nil if no applicable." | |
460 | (if ede-object | |
461 | (ede-buffer-header-file ede-object (current-buffer)) | |
462 | nil)) | |
463 | ||
464 | (defmethod ede-buffer-header-file ((this ede-project) buffer) | |
465 | "Return nil, projects don't have header files." | |
466 | nil) | |
467 | ||
468 | (defmethod ede-buffer-header-file ((this ede-target) buffer) | |
469 | "There are no default header files in EDE. | |
470 | Do a quick check to see if there is a Header tag in this buffer." | |
471 | (with-current-buffer buffer | |
472 | (if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t) | |
473 | (buffer-substring-no-properties (match-beginning 1) | |
474 | (match-end 1)) | |
475 | (let ((src (ede-target-sourcecode this)) | |
476 | (found nil)) | |
477 | (while (and src (not found)) | |
478 | (setq found (ede-buffer-header-file (car src) (buffer-file-name)) | |
479 | src (cdr src))) | |
480 | found)))) | |
481 | ||
482 | (defun ede-documentation-files () | |
483 | "Return the documentation files for the current buffer. | |
484 | Not all buffers need documentations, so return nil if no applicable. | |
485 | Some projects may have multiple documentation files, so return a list." | |
486 | (if ede-object | |
487 | (ede-buffer-documentation-files ede-object (current-buffer)) | |
488 | nil)) | |
489 | ||
490 | (defmethod ede-buffer-documentation-files ((this ede-project) buffer) | |
491 | "Return all documentation in project THIS based on BUFFER." | |
492 | ;; Find the info node. | |
493 | (ede-documentation this)) | |
494 | ||
495 | (defmethod ede-buffer-documentation-files ((this ede-target) buffer) | |
496 | "Check for some documentation files for THIS. | |
497 | Also do a quick check to see if there is a Documentation tag in this BUFFER." | |
498 | (with-current-buffer buffer | |
499 | (if (re-search-forward "::Documentation:: \\([a-zA-Z0-9.]+\\)" nil t) | |
500 | (buffer-substring-no-properties (match-beginning 1) | |
501 | (match-end 1)) | |
502 | ;; Check the master project | |
503 | (let ((cp (ede-toplevel))) | |
504 | (ede-buffer-documentation-files cp (current-buffer)))))) | |
505 | ||
506 | (defmethod ede-documentation ((this ede-project)) | |
507 | "Return a list of files that provide documentation. | |
508 | Documentation is not for object THIS, but is provided by THIS for other | |
509 | files in the project." | |
510 | (let ((targ (oref this targets)) | |
511 | (proj (oref this subproj)) | |
512 | (found nil)) | |
513 | (while targ | |
514 | (setq found (append (ede-documentation (car targ)) found) | |
515 | targ (cdr targ))) | |
516 | (while proj | |
517 | (setq found (append (ede-documentation (car proj)) found) | |
518 | proj (cdr proj))) | |
519 | found)) | |
520 | ||
521 | (defmethod ede-documentation ((this ede-target)) | |
522 | "Return a list of files that provide documentation. | |
523 | Documentation is not for object THIS, but is provided by THIS for other | |
524 | files in the project." | |
525 | nil) | |
526 | ||
527 | (defun ede-html-documentation-files () | |
528 | "Return a list of HTML documentation files associated with this project." | |
529 | (ede-html-documentation (ede-toplevel)) | |
530 | ) | |
531 | ||
532 | (defmethod ede-html-documentation ((this ede-project)) | |
533 | "Return a list of HTML files provided by project THIS." | |
534 | ||
535 | ) | |
536 | ||
537 | ;;; Default "WANT" methods. | |
538 | ;; | |
539 | ;; These methods are used to determine if a target "wants", or could | |
540 | ;; somehow handle a file, or some source type. | |
541 | ;; | |
542 | (defmethod ede-want-file-p ((this ede-target) file) | |
543 | "Return non-nil if THIS target wants FILE." | |
544 | ;; By default, all targets reference the source object, and let it decide. | |
545 | (let ((src (ede-target-sourcecode this))) | |
546 | (while (and src (not (ede-want-file-p (car src) file))) | |
547 | (setq src (cdr src))) | |
548 | src)) | |
549 | ||
550 | (defmethod ede-want-file-source-p ((this ede-target) file) | |
551 | "Return non-nil if THIS target wants FILE." | |
552 | ;; By default, all targets reference the source object, and let it decide. | |
553 | (let ((src (ede-target-sourcecode this))) | |
554 | (while (and src (not (ede-want-file-source-p (car src) file))) | |
555 | (setq src (cdr src))) | |
556 | src)) | |
557 | ||
558 | (defmethod ede-target-sourcecode ((this ede-target)) | |
559 | "Return the sourcecode objects which THIS permits." | |
560 | (let ((sc (oref this sourcetype)) | |
561 | (rs nil)) | |
562 | (while (and (listp sc) sc) | |
563 | (setq rs (cons (symbol-value (car sc)) rs) | |
564 | sc (cdr sc))) | |
565 | rs)) | |
566 | ||
567 | \f | |
568 | ;;; Debugging. | |
569 | ;; | |
570 | (defun ede-adebug-project () | |
571 | "Run adebug against the current EDE project. | |
572 | Display the results as a debug list." | |
573 | (interactive) | |
574 | (require 'data-debug) | |
575 | (when (ede-current-project) | |
576 | (data-debug-new-buffer "*Analyzer ADEBUG*") | |
577 | (data-debug-insert-object-slots (ede-current-project) "") | |
578 | )) | |
579 | ||
580 | (defun ede-adebug-project-parent () | |
581 | "Run adebug against the current EDE parent project. | |
582 | Display the results as a debug list." | |
583 | (interactive) | |
584 | (require 'data-debug) | |
585 | (when (ede-parent-project) | |
586 | (data-debug-new-buffer "*Analyzer ADEBUG*") | |
587 | (data-debug-insert-object-slots (ede-parent-project) "") | |
588 | )) | |
589 | ||
590 | (defun ede-adebug-project-root () | |
591 | "Run adebug against the current EDE parent project. | |
592 | Display the results as a debug list." | |
593 | (interactive) | |
594 | (require 'data-debug) | |
595 | (when (ede-toplevel) | |
596 | (data-debug-new-buffer "*Analyzer ADEBUG*") | |
597 | (data-debug-insert-object-slots (ede-toplevel) "") | |
598 | )) | |
599 | ||
600 | \f | |
601 | ||
602 | ;;; TOPLEVEL PROJECT | |
603 | ;; | |
604 | ;; The toplevel project is a way to identify the EDE structure that belongs | |
605 | ;; to the top of a project. | |
606 | ||
607 | (defun ede-toplevel (&optional subproj) | |
608 | "Return the ede project which is the root of the current project. | |
609 | Optional argument SUBPROJ indicates a subproject to start from | |
610 | instead of the current project." | |
611 | (or ede-object-root-project | |
612 | (let* ((cp (or subproj (ede-current-project)))) | |
613 | (or (and cp (ede-project-root cp)) | |
614 | (progn | |
615 | (while (ede-parent-project cp) | |
616 | (setq cp (ede-parent-project cp))) | |
617 | cp))))) | |
618 | ||
619 | \f | |
620 | ;;; Hooks & Autoloads | |
621 | ;; | |
622 | ;; These let us watch various activities, and respond appropriately. | |
623 | ||
624 | ;; (add-hook 'edebug-setup-hook | |
625 | ;; (lambda () | |
626 | ;; (def-edebug-spec ede-with-projectfile | |
627 | ;; (form def-body)))) | |
628 | ||
629 | (provide 'ede/base) | |
630 | ||
631 | ;; Local variables: | |
632 | ;; generated-autoload-file: "loaddefs.el" | |
633 | ;; generated-autoload-load-name: "ede/base" | |
634 | ;; End: | |
635 | ||
636 | ;;; ede/base.el ends here |