25901
|
1 ;;; @(#) ada-prj.el --- Easy editing of project files for the ada-mode
|
|
2
|
26227
|
3 ;; Copyright (C) 1998,1999 Free Software Foundation, Inc.
|
25901
|
4
|
|
5 ;; Author: Emmanuel Briot <briot@gnat.com>
|
|
6 ;; Ada Core Technologies's version: $Revision: 1.30 $
|
|
7 ;; Keywords: languages, ada, project file
|
|
8
|
|
9 ;; This file is not part of GNU Emacs.
|
|
10
|
|
11 ;; This program is free software; you can redistribute it and/or modify
|
|
12 ;; it under the terms of the GNU General Public License as published by
|
|
13 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
14 ;; any later version.
|
|
15
|
|
16 ;; This program is distributed in the hope that it will be useful,
|
|
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19 ;; GNU General Public License for more details.
|
|
20
|
|
21 ;; You should have received a copy of the GNU General Public License
|
|
22 ;; along with GNU Emacs; see the file COPYING. If not, write to
|
|
23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
24
|
|
25 ;;; Commentary:
|
|
26 ;;; This package provides a set of functions to easily edit the project
|
|
27 ;;; files used by the ada-mode.
|
|
28 ;;; The only function publicly available here is `ada-prj-customize'.
|
|
29 ;;; Please ada-mode.el and its documentation for more information about the
|
|
30 ;;; project files.
|
|
31 ;;;
|
|
32 ;;; You need Emacs >= 20.2 to run this package
|
|
33
|
|
34 ;; Code:
|
|
35
|
|
36
|
|
37 ;; ----- Requirements -----------------------------------------------------
|
|
38
|
|
39 (require 'cus-edit)
|
|
40
|
|
41
|
|
42 ;; ----- Buffer local variables -------------------------------------------
|
|
43 ;; if non nil, then all the widgets will have the default values, instead
|
|
44 ;; of reading them from the project file
|
|
45 (make-variable-buffer-local (defvar ada-prj-edit-use-default-values nil))
|
|
46
|
|
47 ;; List of the default values used for the field in the project file
|
|
48 ;; Mainly used to save only the modified fields into the file itself
|
|
49 ;; The values are hold in the properties of this variable
|
|
50 (make-variable-buffer-local (defvar ada-prj-default nil))
|
|
51
|
|
52 (make-variable-buffer-local (defvar ada-prj-widget-prj-dir nil))
|
|
53 (make-variable-buffer-local (defvar ada-prj-widget-src-dir nil))
|
|
54 (make-variable-buffer-local (defvar ada-prj-widget-obj-dir nil))
|
|
55 (make-variable-buffer-local (defvar ada-prj-widget-main nil))
|
|
56 (make-variable-buffer-local (defvar ada-prj-widget-comp-opt nil))
|
|
57 (make-variable-buffer-local (defvar ada-prj-widget-bind-opt nil))
|
|
58 (make-variable-buffer-local (defvar ada-prj-widget-link-opt nil))
|
|
59 (make-variable-buffer-local (defvar ada-prj-widget-remote-machine nil))
|
|
60 (make-variable-buffer-local (defvar ada-prj-widget-comp-cmd nil))
|
|
61 (make-variable-buffer-local (defvar ada-prj-widget-make-cmd nil))
|
|
62 (make-variable-buffer-local (defvar ada-prj-widget-run-cmd nil))
|
|
63 (make-variable-buffer-local (defvar ada-prj-widget-debug-cmd nil))
|
|
64 (make-variable-buffer-local (defvar ada-prj-widget-cross-prefix nil))
|
|
65
|
|
66 ;; ------ Functions -------------------------------------------------------
|
|
67
|
|
68 (defun ada-prj-add-ada-menu ()
|
26227
|
69 "Add a new submenu to the Ada menu."
|
25901
|
70 (interactive)
|
|
71
|
|
72 (if ada-xemacs
|
|
73 (progn
|
|
74 (add-menu-button '("Ada" "Project") ["New/Edit" ada-customize t] "Associate")
|
|
75 )
|
|
76 (let ((prj-menu (lookup-key ada-mode-map [menu-bar Ada Project])))
|
|
77 (define-key prj-menu [New] '("New/Edit" . ada-customize)))
|
|
78 ))
|
|
79
|
|
80 (defun ada-prj-add-keymap ()
|
26227
|
81 "Add new keybindings for ada-prj."
|
25901
|
82 (define-key ada-mode-map "\C-cu" 'ada-customize))
|
|
83
|
|
84 (defun ada-customize (&optional new-file)
|
26227
|
85 "Edit the project file associated with the current buffer.
|
|
86 If there is none or NEW-FILE is non-nil, make a new one."
|
25901
|
87 (interactive)
|
|
88 (if new-file
|
|
89 (progn
|
|
90 (setq ada-prj-edit-use-default-values t)
|
|
91 (kill-local-variable 'ada-prj-prj-file)
|
|
92 (ada-prj-customize)
|
|
93 (setq ada-prj-edit-use-default-values nil))
|
|
94 (ada-prj-customize)))
|
|
95
|
|
96 (defun ada-prj-save ()
|
26227
|
97 "Save the currently edited project file."
|
25901
|
98 (interactive)
|
|
99 (let ((file-name (widget-value ada-prj-widget-prj-dir))
|
|
100 value output)
|
|
101 (setq output
|
|
102 (concat
|
|
103 (ada-prj-set-list "src_dir" (widget-value ada-prj-widget-src-dir))
|
|
104 "\n"
|
|
105 (ada-prj-set-list "obj_dir" (widget-value ada-prj-widget-obj-dir))
|
|
106 "\n"
|
|
107 (unless (string= (setq value (widget-value ada-prj-widget-comp-opt))
|
|
108 (get 'ada-prj-default 'comp_opt))
|
|
109 (concat "comp_opt=" value "\n"))
|
|
110 (unless (string= (setq value (widget-value ada-prj-widget-bind-opt))
|
|
111 (get 'ada-prj-default 'bind_opt))
|
|
112 (concat "bind_opt=" value "\n"))
|
|
113 (unless (string= (setq value (widget-value ada-prj-widget-link-opt))
|
|
114 (get 'ada-prj-default 'link_opt))
|
|
115 (concat "link_opt=" value "\n"))
|
|
116 (unless (string= (setq value (widget-value ada-prj-widget-main))
|
|
117 (get 'ada-prj-default 'main))
|
|
118 (concat "main=" value "\n"))
|
|
119 (unless (string= (setq value (widget-value ada-prj-widget-cross-prefix))
|
|
120 (get 'ada-prj-default 'cross-prefix))
|
|
121 (concat "cross_prefix=" value "\n"))
|
|
122 (unless (string= (setq value (widget-value ada-prj-widget-remote-machine))
|
|
123 (get 'ada-prj-default 'remote-machine))
|
|
124 (concat "remote_machine=" value "\n"))
|
|
125 (unless (string= (setq value (widget-value ada-prj-widget-comp-cmd))
|
|
126 (get 'ada-prj-default 'comp_cmd))
|
|
127 (concat "comp_cmd=" value "\n"))
|
|
128 (unless (string= (setq value (widget-value ada-prj-widget-make-cmd))
|
|
129 (get 'ada-prj-default 'make_cmd))
|
|
130 (concat "make_cmd=" value "\n"))
|
|
131 (unless (string= (setq value (widget-value ada-prj-widget-run-cmd))
|
|
132 (get 'ada-prj-default 'run_cmd))
|
|
133 (concat "run_cmd=" value "\n"))
|
|
134 (unless (string= (setq value (widget-value ada-prj-widget-debug-cmd))
|
|
135 (get 'ada-prj-default 'debug_cmd))
|
|
136 (concat "debug_cmd=" value "\n"))
|
|
137 ))
|
|
138 (find-file file-name)
|
|
139 (erase-buffer)
|
|
140 (insert output)
|
|
141 (save-buffer)
|
|
142 ;; kill the project buffer
|
|
143 (kill-buffer nil)
|
|
144
|
|
145 ;; kill the editor buffer
|
|
146 (kill-buffer "*Customize Ada Mode*")
|
|
147
|
|
148 ;; automatically associates the current buffer with the
|
|
149 ;; new project file
|
|
150 (make-local-variable 'ada-prj-prj-file)
|
|
151 (setq ada-prj-prj-file file-name)
|
|
152
|
|
153 ;; force emacs to reread the project files
|
|
154 (ada-reread-prj-file t)
|
|
155 )
|
|
156 )
|
|
157
|
|
158 (defun ada-prj-customize ()
|
26227
|
159 "Edit the project file associated with the current Ada buffer."
|
25901
|
160 (let* ((old-name (buffer-file-name))
|
|
161 prj-file)
|
|
162
|
|
163 (unless old-name
|
|
164 (error
|
|
165 "No file name given for this buffer ! You need to open a file first"))
|
|
166
|
|
167 ;; Find the project file associated with the buffer
|
|
168 (setq prj-file (ada-prj-get-prj-dir old-name))
|
|
169
|
|
170 (switch-to-buffer "*Customize Ada Mode*")
|
|
171 (kill-all-local-variables)
|
|
172
|
|
173 ;; Find the default values
|
|
174 (setq ada-prj-default nil)
|
|
175 (put 'ada-prj-default 'src_dir (list (file-name-directory old-name)))
|
|
176 (put 'ada-prj-default 'obj_dir (list (file-name-directory old-name)))
|
|
177 (put 'ada-prj-default 'comp_opt "")
|
|
178 (put 'ada-prj-default 'bind_opt "")
|
|
179 (put 'ada-prj-default 'link_opt "")
|
|
180 (put 'ada-prj-default 'main "")
|
|
181 (put 'ada-prj-default 'cross_prefix "")
|
|
182 (put 'ada-prj-default 'remote_machine "")
|
|
183 (put 'ada-prj-default 'comp_cmd
|
|
184 (concat "cd " (file-name-directory old-name) " && "
|
|
185 ada-prj-default-comp-cmd))
|
|
186 (put 'ada-prj-default 'make_cmd
|
|
187 (concat "cd " (file-name-directory old-name) " && "
|
|
188 ada-prj-default-make-cmd))
|
|
189 (put 'ada-prj-default 'run_cmd (if is-windows "${main}.exe" "${main}"))
|
|
190 (put 'ada-prj-default 'debug_cmd
|
|
191 (if is-windows "${cross_prefix}gdb ${main}.exe"
|
|
192 "${cross_prefix}gdb ${main}"))
|
|
193
|
|
194 (let ((inhibit-read-only t))
|
|
195 (erase-buffer))
|
|
196
|
|
197 ;;; Overlay-lists is not defined on XEmacs
|
|
198 (if (fboundp 'overlay-lists)
|
|
199 (let ((all (overlay-lists)))
|
|
200 ;; Delete all the overlays.
|
|
201 (mapcar 'delete-overlay (car all))
|
|
202 (mapcar 'delete-overlay (cdr all))))
|
|
203
|
26227
|
204 (use-local-map (copy-keymap custom-mode-map))
|
25901
|
205 (local-set-key "\C-x\C-s" 'ada-prj-save)
|
|
206
|
|
207 (widget-insert "
|
|
208 ----------------------------------------------------------------
|
26227
|
209 -- Customize your Emacs Ada mode for the current application --
|
25901
|
210 ----------------------------------------------------------------
|
|
211 This buffer will allow you to create easily a project file for your application.
|
26227
|
212 This file will tell Emacs where to find the ada sources, the cross-referencing
|
25901
|
213 informations, how to compile and run your application, ...
|
|
214
|
|
215 Please use the RETURN key, or middle mouse button to activate the fields.\n\n")
|
|
216
|
|
217 ;; Reset Button
|
|
218 (widget-create 'push-button
|
|
219 :notify (lambda (&rest ignore)
|
|
220 (setq ada-prj-edit-use-default-values t)
|
|
221 (kill-buffer nil)
|
|
222 (ada-prj-customize)
|
|
223 (setq ada-prj-edit-use-default-values nil)
|
|
224 )
|
|
225 "Reset to Default Values")
|
|
226 (widget-insert "\n")
|
|
227
|
|
228
|
|
229 ;; Create local variables with their initial value
|
|
230 (setq ada-prj-widget-prj-dir
|
|
231 (ada-prj-new 'ada-prj-widget-prj-dir nil "" prj-file
|
|
232 "\nName and directory of the project file.
|
|
233 Put a new name here if you want to create a new project file\n"))
|
|
234
|
|
235 (setq ada-prj-widget-src-dir
|
|
236 (ada-prj-list 'ada-prj-widget-src-dir prj-file "src_dir"
|
|
237 (get 'ada-prj-default 'src_dir)
|
26227
|
238 "\nYou should enter below all the directories where Emacs
|
25901
|
239 will find your ada sources for the current application\n"))
|
|
240
|
|
241 (setq ada-prj-widget-obj-dir
|
|
242 (ada-prj-list 'ada-prj-widget-obj-dir prj-file "obj_dir"
|
|
243 (get 'ada-prj-default 'obj_dir)
|
|
244 "\nBelow are the directories where the object files generated
|
|
245 by the compiler will be found. This files are required for the cross-referencing
|
26227
|
246 capabilities of the Emacs' Ada-mode.\n"))
|
25901
|
247
|
|
248 (setq ada-prj-widget-comp-opt
|
|
249 (ada-prj-new 'ada-prj-widget-comp-opt prj-file "comp_opt"
|
|
250 (get 'ada-prj-default 'comp_opt)
|
|
251 "\nPut below the compiler switches.\n"))
|
|
252
|
|
253 (setq ada-prj-widget-bind-opt
|
|
254 (ada-prj-new 'ada-prj-widget-bind-opt prj-file "bind_opt"
|
|
255 (get 'ada-prj-default 'bind_opt)
|
|
256 "\nPut below the binder switches.\n"))
|
|
257
|
|
258 (setq ada-prj-widget-link-opt
|
|
259 (ada-prj-new 'ada-prj-widget-link-opt prj-file "link_opt"
|
|
260 (get 'ada-prj-default 'link_opt)
|
|
261 "\nPut below the linker switches.\n"))
|
|
262
|
|
263 (setq ada-prj-widget-main
|
|
264 (ada-prj-new 'ada-prj-widget-main prj-file "main"
|
|
265 (file-name-sans-extension old-name)
|
|
266 "\nPut below the name of the main program for your application\n"))
|
|
267
|
|
268 (setq ada-prj-widget-cross-prefix
|
|
269 (ada-prj-new 'ada-prj-widget-cross-prefix prj-file "cross_prefix"
|
|
270 (get 'ada-prj-default 'cross_prefix)
|
|
271 "\nIf you are using a cross compiler, you might want to
|
|
272 set the following variable so that the correct compiler is used by default\n"))
|
|
273
|
|
274 (setq ada-prj-widget-remote-machine
|
|
275 (ada-prj-new 'ada-prj-widget-remote-machine prj-file "remote_machine"
|
|
276 (get 'ada-prj-default 'remote_machine)
|
|
277 "\nName of the machine to log on before a compilation.
|
|
278 Leave an empty field if you want to compile on the local machine.
|
|
279 This will not work on Windows NT, since we only do a 'rsh' to the
|
|
280 remote machine and then issue the command. \n"))
|
|
281
|
|
282 (widget-insert "\n
|
|
283 -------------------------------------------------------------------------------
|
|
284 / \\ !! Advanced Users !! : For the following commands, you may use
|
|
285 / | \\ a somewhat more complicated syntax to describe them. If you
|
|
286 / | \\ use some special fields, they will be replaced at run-time by
|
|
287 / | \\ the variables defined above.
|
|
288 / | \\ These special fields are : ${remote_machine}
|
|
289 / o \\ -aI${src_dir} -I${src_dir} -aO${obj_dir} ${comp_opt}
|
|
290 ------------- ${bind_opt} ${link_opt} ${main} ${cross_prefix}
|
|
291
|
|
292 The easiest way is to ignore this possibility. These fields are intended only
|
|
293 for user who really understand what `variable substitution' means.
|
|
294 -------------------------------------------------------------------------------\n")
|
|
295
|
|
296 (setq ada-prj-widget-comp-cmd
|
|
297 (ada-prj-new 'ada-prj-widget-comp-cmd prj-file "comp_cmd"
|
|
298 (get 'ada-prj-default 'comp_cmd)
|
|
299 "\nPut below the command used to compile ONE file.
|
|
300 The name of the file to compile will be added at the end of the command.
|
|
301 This command will also be used to check the file.\n"))
|
|
302
|
|
303 (setq ada-prj-widget-make-cmd
|
|
304 (ada-prj-new 'ada-prj-widget-make-cmd prj-file "make_cmd"
|
|
305 (get 'ada-prj-default 'make_cmd)
|
|
306 "\nPut below the command used to compile the whole application.\n"))
|
|
307
|
|
308 (setq ada-prj-widget-run-cmd
|
|
309 (ada-prj-new 'ada-prj-widget-run-cmd prj-file "run_cmd"
|
|
310 (get 'ada-prj-default 'run_cmd)
|
|
311 "\nPut below the command used to run your application.\n"))
|
|
312
|
|
313 (setq ada-prj-widget-debug-cmd
|
|
314 (ada-prj-new 'ada-prj-widget-run-cmd prj-file "debug_cmd"
|
|
315 (get 'ada-prj-default 'debug_cmd)
|
|
316 "\nPut below the command used to launch the debugger on your application.\n"))
|
|
317
|
|
318 ;; the two buttons to validate or cancel the modification
|
|
319 (widget-insert "\nWhen you have finish completing the above fields, choose one of the two buttons
|
|
320 below, to validate or cancel your modifications.
|
|
321 If you choose `OK', your settings will be saved to the file whose name is given above.\n")
|
|
322
|
|
323 (widget-create 'push-button
|
|
324 :notify (lambda (&rest ignore) (ada-prj-save))
|
|
325 "OK")
|
|
326
|
|
327 (widget-insert " ")
|
|
328 (widget-create 'push-button
|
|
329 :notify (lambda (&rest ignore)
|
|
330 (kill-buffer nil))
|
|
331 "Cancel")
|
|
332 (widget-insert "\n")
|
|
333
|
|
334
|
|
335 ;; if it exists, kill the project file buffer
|
|
336 (if (and prj-file
|
|
337 (get-file-buffer prj-file))
|
|
338 (kill-buffer (get-file-buffer prj-file)))
|
|
339
|
|
340 (widget-setup)
|
|
341 (beginning-of-buffer)
|
|
342 )
|
|
343 )
|
|
344
|
|
345
|
|
346 ;; ---------------- Utilities --------------------------------
|
|
347
|
|
348 (defun ada-prj-new (variable prj-file text default message)
|
26227
|
349 "Create a buffer-local variable with name VARIABLE.
|
|
350 If PRJ-FILE exists, read its value from that file, otherwise set it to
|
|
351 DEFAULT.
|
|
352 It also creates a widget in the current buffer to edit this variable,
|
|
353 which MESSAGE explaning what the variable is supposed to do.
|
|
354 TEXT is put just before the editable field, and should display the name
|
|
355 of the variable."
|
25901
|
356
|
|
357 ;; create local variable
|
|
358 (make-local-variable variable)
|
|
359 (let ((value default)
|
|
360 (regexp (concat "^" text "=\\(.*\\)")))
|
|
361 ;; if the project file exists
|
|
362 (if (and prj-file (not ada-prj-edit-use-default-values)
|
|
363 (file-readable-p prj-file))
|
|
364 ;; find the value
|
|
365 (save-excursion
|
|
366 (find-file prj-file)
|
|
367 (beginning-of-buffer)
|
|
368 (if (re-search-forward regexp nil t)
|
|
369 (setq value (match-string 1)))
|
|
370 ))
|
|
371 ;; assign a new value to the variable
|
|
372 (setq variable value))
|
|
373
|
|
374 (widget-insert message)
|
|
375
|
|
376 (widget-create 'editable-field
|
|
377 :format (if (string= text "") "%v"
|
|
378 (concat text "= %v"))
|
|
379 :keymap widget-keymap
|
|
380 variable))
|
|
381
|
|
382
|
|
383 (defun ada-prj-list (variable prj-file text default message)
|
26227
|
384 "Create a buffer-local list variable with name VARIABLE.
|
|
385 If PRJ-FILE exists, read its value from that file, otherwise set it to
|
|
386 DEFAULT.
|
|
387 It also creates a widget in the current buffer to edit this variable,
|
|
388 which MESSAGE explaning what the variable is supposed to do.
|
|
389 TEXT is put just before the editable field, and should display the name
|
|
390 of the variable."
|
25901
|
391
|
|
392 ;; create local variable
|
|
393 (make-local-variable variable)
|
|
394 (let ((value nil)
|
|
395 (regexp (concat "^" text "=\\(.*\\)")))
|
|
396 ;; if the project file exists
|
|
397 (if (and prj-file (not ada-prj-edit-use-default-values)
|
|
398 (file-readable-p prj-file))
|
|
399 ;; find the value
|
|
400 (save-excursion
|
|
401 (find-file prj-file)
|
|
402 (goto-char (point-min))
|
|
403 ;; for each line, add its value
|
|
404 (while
|
|
405 (re-search-forward regexp nil t)
|
|
406 (progn
|
|
407 (setq value (cons (match-string 1) value)))
|
|
408 )))
|
|
409
|
|
410 ;; assign a new value to the variable
|
|
411 (setq variable
|
|
412 (if value (reverse value) default)))
|
|
413
|
|
414 (widget-insert message)
|
|
415 (widget-create 'editable-list
|
|
416 :entry-format (concat text "= %i %d %v")
|
|
417 :value variable
|
|
418 (list 'editable-field :keymap widget-keymap)))
|
|
419
|
26227
|
420 (defsubst ada-prj-set-list (string ada-dir-list)
|
|
421 "Join the strings in ADA-DIR-LIST into a single string. Each name is put
|
|
422 on a separate line that begins with STRING."
|
25901
|
423 (mapconcat (lambda (x)
|
26227
|
424 (concat string "=" x
|
|
425 (unless (string= (substring x -1) "/")
|
25901
|
426 "/")))
|
|
427 ada-dir-list "\n"))
|
|
428
|
|
429 (defun ada-prj-get-prj-dir (&optional ada-file)
|
26227
|
430 "Returns the directory/name of the project file for ADA-FILE.
|
|
431 If ADA-FILE is nil, returns the project file for the current buffer."
|
25901
|
432 (unless ada-file
|
|
433 (setq ada-file (buffer-file-name)))
|
|
434
|
|
435 (save-excursion
|
|
436 (set-buffer (get-file-buffer ada-file))
|
|
437 (if ada-prj-edit-use-default-values
|
|
438 (concat (file-name-sans-extension ada-file)
|
|
439 ada-project-file-extension)
|
|
440
|
|
441 (let ((prj-file (ada-prj-find-prj-file t)))
|
|
442 (if (or (not prj-file)
|
|
443 (not (file-exists-p prj-file))
|
|
444 )
|
|
445 (setq prj-file
|
|
446 (concat (file-name-sans-extension ada-file)
|
|
447 ada-project-file-extension)))
|
|
448 prj-file)
|
|
449 ))
|
|
450 )
|
|
451
|
|
452
|
|
453 ;; Initializations for the package
|
|
454 (add-hook 'ada-mode-hook 'ada-prj-add-ada-menu)
|
|
455
|
|
456 ;; Set the keymap once and for all, so that the keys set by the user in his
|
|
457 ;; config file are not overwritten every time we open a new file.
|
|
458 (ada-prj-add-keymap)
|
|
459
|
|
460 (provide 'ada-prj)
|
|
461 ;;; package ada-prj.el ends here
|
|
462
|
|
463
|
|
464
|