Fix bug #272, and update Ada mode to version 4.0.
[bpt/emacs.git] / lisp / progmodes / ada-prj.el
CommitLineData
d759dcce 1;;; ada-prj.el --- GUI editing of project files for the ada-mode
d41832c5 2
4e643dd2
GM
3;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4;; 2007, 2008 Free Software Foundation, Inc.
d41832c5
GM
5
6;; Author: Emmanuel Briot <briot@gnat.com>
d759dcce 7;; Maintainer: Stephen Leake <stephen_leake@stephe-leake.org>
d41832c5
GM
8;; Keywords: languages, ada, project file
9
874d7995 10;; This file is part of GNU Emacs.
d41832c5 11
b1fc2b50 12;; GNU Emacs is free software: you can redistribute it and/or modify
d41832c5 13;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
d41832c5 16
2be7dabc 17;; GNU Emacs is distributed in the hope that it will be useful,
d41832c5
GM
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
b1fc2b50 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
d41832c5 24
3afbc435
PJ
25;;; Commentary:
26
d41832c5
GM
27;;; This package provides a set of functions to easily edit the project
28;;; files used by the ada-mode.
c6fa13e3
GM
29;;; The only function publicly available here is `ada-customize'.
30;;; See the documentation of the Ada mode for more information on the project
31;;; files.
32;;; Internally, a project file is represented as a property list, with each
33;;; field of the project file matching one property of the list.
d41832c5 34
d759dcce
JB
35
36;;; History:
37;;
38
3afbc435 39;;; Code:
d41832c5
GM
40
41
42;; ----- Requirements -----------------------------------------------------
43
44(require 'cus-edit)
ce20e709 45(require 'ada-xref)
d41832c5 46
6f9a2614
JB
47(eval-when-compile
48 (require 'ada-mode))
49
d41832c5 50;; ----- Buffer local variables -------------------------------------------
d41832c5 51
c6fa13e3 52(defvar ada-prj-current-values nil
6f9a2614 53 "Hold the current value of the fields, This is a property list.")
c6fa13e3
GM
54(make-variable-buffer-local 'ada-prj-current-values)
55
56(defvar ada-prj-default-values nil
6f9a2614 57 "Hold the default value for the fields, This is a property list.")
c6fa13e3
GM
58(make-variable-buffer-local 'ada-prj-default-values)
59
60(defvar ada-prj-ada-buffer nil
61 "Indicates what Ada source file was being edited.")
62
da2a1edf
SM
63(defvar ada-old-cross-prefix nil
64 "The cross-prefix associated with the currently loaded runtime library.")
65
c6fa13e3
GM
66
67;; ----- Functions --------------------------------------------------------
68
69(defun ada-prj-new ()
d759dcce 70 "Open a new project file."
d41832c5 71 (interactive)
c6fa13e3 72 (let* ((prj
da2a1edf
SM
73 (if (and ada-prj-default-project-file
74 (not (string= ada-prj-default-project-file "")))
75 ada-prj-default-project-file
c6fa13e3
GM
76 "default.adp"))
77 (filename (read-file-name "Project file: "
78 (if prj "" nil)
79 nil
80 nil
81 prj)))
82 (if (not (string= (file-name-extension filename t) ".adp"))
83 (error "File name extension for project files must be .adp"))
a1506d29 84
c6fa13e3
GM
85 (ada-customize nil filename)))
86
87(defun ada-prj-edit ()
88 "Editing the project file associated with the current Ada buffer.
89If there is none, opens a new project file"
90 (interactive)
61c08d00
SM
91 (if ada-prj-default-project-file
92 (ada-customize)
93 (ada-prj-new)))
d41832c5 94
ce20e709 95(defun ada-prj-initialize-values (symbol ada-buffer filename)
c6fa13e3
GM
96 "Set SYMBOL to the property list of the project file FILENAME.
97If FILENAME is null, read the file associated with ADA-BUFFER. If no
98project file is found, returns the default values."
d759dcce 99;; FIXME: rationalize arguments; make ada-buffer optional?
ce20e709
JB
100 (if (and filename
101 (not (string= filename ""))
102 (assoc filename ada-xref-project-files))
103 (set symbol (copy-sequence (cdr (assoc filename ada-xref-project-files))))
a1506d29 104
ce20e709
JB
105 ;; Set default values (except for the file name if this was given
106 ;; in the buffer
107 (ada-xref-set-default-prj-values symbol ada-buffer)
108 (if (and filename (not (string= filename "")))
109 (set symbol (plist-put (eval symbol) 'filename filename)))
110 ))
a1506d29 111
d41832c5 112
c6fa13e3 113(defun ada-prj-save-specific-option (field)
d759dcce 114 "Return the string to print in the project file to save FIELD.
c6fa13e3
GM
115If the current value of FIELD is the default value, returns an empty string."
116 (if (string= (plist-get ada-prj-current-values field)
117 (plist-get ada-prj-default-values field))
118 ""
119 (concat (symbol-name field)
120 "=" (plist-get ada-prj-current-values field) "\n")))
d41832c5
GM
121
122(defun ada-prj-save ()
c6fa13e3 123 "Save the edited project file."
d41832c5 124 (interactive)
d5875b25
JB
125 (let ((file-name (or (plist-get ada-prj-current-values 'filename)
126 (read-file-name "Save project as: ")))
c6fa13e3
GM
127 output)
128 (set 'output
129 (concat
130
131 ;; Save the fields that do not depend on the current buffer
132 ;; only if they are different from the default value
a1506d29 133
c6fa13e3
GM
134 (ada-prj-save-specific-option 'comp_opt)
135 (ada-prj-save-specific-option 'bind_opt)
136 (ada-prj-save-specific-option 'link_opt)
137 (ada-prj-save-specific-option 'gnatmake_opt)
da2a1edf 138 (ada-prj-save-specific-option 'gnatfind_opt)
c6fa13e3
GM
139 (ada-prj-save-specific-option 'cross_prefix)
140 (ada-prj-save-specific-option 'remote_machine)
c6fa13e3
GM
141 (ada-prj-save-specific-option 'debug_cmd)
142
143 ;; Always save the fields that depend on the current buffer
da2a1edf 144 "main=" (plist-get ada-prj-current-values 'main) "\n"
da2a1edf
SM
145 "build_dir=" (plist-get ada-prj-current-values 'build_dir) "\n"
146 (ada-prj-set-list "check_cmd"
147 (plist-get ada-prj-current-values 'check_cmd)) "\n"
148 (ada-prj-set-list "make_cmd"
149 (plist-get ada-prj-current-values 'make_cmd)) "\n"
150 (ada-prj-set-list "comp_cmd"
151 (plist-get ada-prj-current-values 'comp_cmd)) "\n"
152 (ada-prj-set-list "run_cmd"
153 (plist-get ada-prj-current-values 'run_cmd)) "\n"
c6fa13e3 154 (ada-prj-set-list "src_dir"
da2a1edf
SM
155 (plist-get ada-prj-current-values 'src_dir)
156 t) "\n"
c6fa13e3 157 (ada-prj-set-list "obj_dir"
da2a1edf
SM
158 (plist-get ada-prj-current-values 'obj_dir)
159 t) "\n"
160 (ada-prj-set-list "debug_pre_cmd"
161 (plist-get ada-prj-current-values 'debug_pre_cmd))
162 "\n"
163 (ada-prj-set-list "debug_post_cmd"
164 (plist-get ada-prj-current-values 'debug_post_cmd))
165 "\n"
c6fa13e3 166 ))
a1506d29 167
d41832c5
GM
168 (find-file file-name)
169 (erase-buffer)
170 (insert output)
171 (save-buffer)
172 ;; kill the project buffer
173 (kill-buffer nil)
174
175 ;; kill the editor buffer
d759dcce 176 (kill-buffer "*Edit Ada Mode Project*")
d41832c5 177
da2a1edf
SM
178 ;; automatically set the new project file as the active one
179 (set 'ada-prj-default-project-file file-name)
d41832c5 180
c6fa13e3
GM
181 ;; force Emacs to reread the project files
182 (ada-reread-prj-file file-name)
d41832c5
GM
183 )
184 )
185
c6fa13e3
GM
186(defun ada-prj-load-from-file (symbol)
187 "Load SYMBOL value from file. One item per line should be found in the file."
188 (save-excursion
189 (let ((file (read-file-name "File name: " nil nil t))
190 (buffer (current-buffer))
191 line
192 list)
193 (find-file file)
194 (widen)
195 (goto-char (point-min))
196 (while (not (eobp))
197 (set 'line (buffer-substring-no-properties
198 (point) (save-excursion (end-of-line) (point))))
199 (add-to-list 'list line)
200 (forward-line 1)
201 )
202 (kill-buffer nil)
203 (set-buffer buffer)
204 (set 'ada-prj-current-values
205 (plist-put ada-prj-current-values
206 symbol
207 (append (plist-get ada-prj-current-values symbol)
208 (reverse list))))
209 )
210 (ada-prj-display-page 2)
211 ))
212
213(defun ada-prj-subdirs-of (dir)
d759dcce 214 "Return a list of all the subdirectories of DIR, recursively."
c6fa13e3
GM
215 (let ((subdirs (directory-files dir t "^[^.].*"))
216 (dirlist (list dir)))
217 (while subdirs
218 (if (file-directory-p (car subdirs))
219 (let ((sub (ada-prj-subdirs-of (car subdirs))))
220 (if sub
221 (set 'dirlist (append sub dirlist)))))
222 (set 'subdirs (cdr subdirs)))
223 dirlist))
224
225(defun ada-prj-load-directory (field &optional file-name)
d759dcce 226 "Append to FIELD in the current project the subdirectories of FILE-NAME.
c6fa13e3 227If FILE-NAME is nil, ask the user for the name."
61c08d00
SM
228
229 ;; Do not use an external dialog for this, since it wouldn't allow
230 ;; the user to select a directory
231 (let ((use-dialog-box nil))
232 (unless file-name
233 (set 'file-name (read-file-name "Root directory: " nil nil t))))
c6fa13e3
GM
234
235 (set 'ada-prj-current-values
236 (plist-put ada-prj-current-values
237 field
238 (append (plist-get ada-prj-current-values field)
239 (reverse (ada-prj-subdirs-of
240 (expand-file-name file-name))))))
241 (ada-prj-display-page 2))
242
243(defun ada-prj-display-page (tab-num)
d759dcce 244 "Display page TAB-NUM in the notebook.
c6fa13e3
GM
245The current buffer must be the project editing buffer."
246
247 (let ((inhibit-read-only t))
248 (erase-buffer))
249
da2a1edf 250 ;; Widget support in Emacs 21 requires that we clear the buffer first
6f9a2614 251 (if (and (not (featurep 'xemacs)) (>= emacs-major-version 21))
da2a1edf
SM
252 (progn
253 (setq widget-field-new nil
254 widget-field-list nil)
88f43129
JB
255 (mapc (lambda (x) (delete-overlay x)) (car (overlay-lists)))
256 (mapc (lambda (x) (delete-overlay x)) (cdr (overlay-lists)))))
a1506d29 257
c6fa13e3 258 ;; Display the tabs
a1506d29 259
d759dcce 260 (widget-insert "\n Project configuration.\n
da2a1edf 261 ___________ ____________ ____________ ____________ ____________\n / ")
c6fa13e3
GM
262 (widget-create 'push-button :notify
263 (lambda (&rest dummy) (ada-prj-display-page 1)) "General")
264 (widget-insert " \\ / ")
265 (widget-create 'push-button :notify
266 (lambda (&rest dummy) (ada-prj-display-page 2)) "Paths")
267 (widget-insert " \\ / ")
268 (widget-create 'push-button :notify
269 (lambda (&rest dummy) (ada-prj-display-page 3)) "Switches")
270 (widget-insert " \\ / ")
271 (widget-create 'push-button :notify
272 (lambda (&rest dummy) (ada-prj-display-page 4)) "Ada Menu")
da2a1edf
SM
273 (widget-insert " \\ / ")
274 (widget-create 'push-button :notify
275 (lambda (&rest dummy) (ada-prj-display-page 5)) "Debugger")
c6fa13e3
GM
276 (widget-insert " \\\n")
277
278 ;; Display the currently selected page
a1506d29 279
c6fa13e3 280 (cond
a1506d29 281
c6fa13e3
GM
282 ;;
283 ;; First page (General)
284 ;;
285 ((= tab-num 1)
da2a1edf 286 (widget-insert "/ \\/______________\\/______________\\/______________\\/______________\\\n")
c6fa13e3
GM
287
288 (widget-insert "Project file name:\n")
289 (widget-insert (plist-get ada-prj-current-values 'filename))
290 (widget-insert "\n\n")
d5875b25
JB
291 (ada-prj-field 'casing "Casing Exceptions"
292"List of files that contain casing exception
293dictionaries. All these files contain one
294identifier per line, with a special casing.
295The first file has the highest priority."
296 t nil
297 (mapconcat (lambda(x)
298 (concat " " x))
299 (ada-xref-get-project-field 'casing)
300 "\n")
301 )
c6fa13e3
GM
302 (ada-prj-field 'main "Executable file name"
303"Name of the executable generated when you
304compile your application. This should include
305the full directory name, using ${build_dir} if
306you wish.")
c6fa13e3
GM
307 (ada-prj-field 'build_dir "Build directory"
308 "Reference directory for relative paths in
309src_dir and obj_dir below. This is also the directory
310where the compilation is done.")
311 (ada-prj-field 'remote_machine "Name of the remote machine (if any)"
312"If you want to remotely compile, debug and
313run your application, specify the name of a
314remote machine here. This capability requires
315the 'rsh' protocol on the remote machine.")
316 (ada-prj-field 'cross_prefix "Prefix used in for the cross tool chain"
317"When working on multiple cross targets, it is
318most convenient to specify the prefix of the
319tool chain here. For instance, on PowerPc
320vxworks, you would enter 'powerpc-wrs-vxworks-'.
321To use JGNAT, enter 'j'.")
322 )
d41832c5 323
a1506d29 324
c6fa13e3
GM
325 ;;
326 ;; Second page (Paths)
327 ;;
328 ((= tab-num 2)
da2a1edf
SM
329 (if (not (equal (plist-get ada-prj-current-values 'cross_prefix)
330 ada-old-cross-prefix))
331 (progn
332 (setq ada-old-cross-prefix
333 (plist-get ada-prj-current-values 'cross_prefix))
334 (ada-initialize-runtime-library ada-old-cross-prefix)))
335
a1506d29 336
da2a1edf 337 (widget-insert "/_____________\\/ \\/______________\\/______________\\/______________\\\n")
c6fa13e3
GM
338 (ada-prj-field 'src_dir "Source directories"
339"Enter the list of directories where your Ada
340sources can be found. These directories will be
341used for the cross-references and for the default
342compilation commands.
343Note that src_dir includes both the build directory
344and the standard runtime."
345 t t
346 (mapconcat (lambda(x)
d759dcce
JB
347 (concat " " x))
348 ada-xref-runtime-library-specs-path
349 "\n")
c6fa13e3
GM
350 )
351 (widget-insert "\n\n")
a1506d29 352
c6fa13e3
GM
353 (ada-prj-field 'obj_dir "Object directories"
354"Enter the list of directories where the GNAT
355library files (ALI files) can be found. These
356files are used for cross-references and by the
357gnatmake command.
358Note that obj_dir includes both the build directory
359and the standard runtime."
360 t t
361 (mapconcat (lambda(x)
d759dcce
JB
362 (concat " " x))
363 ada-xref-runtime-library-ali-path
364 "\n")
c6fa13e3
GM
365 )
366 (widget-insert "\n\n")
367 )
d41832c5 368
c6fa13e3
GM
369 ;;
370 ;; Third page (Switches)
371 ;;
372 ((= tab-num 3)
da2a1edf 373 (widget-insert "/_____________\\/______________\\/ \\/______________\\/______________\\\n")
c6fa13e3
GM
374 (ada-prj-field 'comp_opt "Switches for the compiler"
375"These switches are used in the default
376compilation commands, both for compiling a
377single file and rebuilding the whole project")
378 (ada-prj-field 'bind_opt "Switches for the binder"
379"These switches are used in the default build
380command and are passed to the binder")
381 (ada-prj-field 'link_opt "Switches for the linker"
382"These switches are used in the default build
383command and are passed to the linker")
384 (ada-prj-field 'gnatmake_opt "Switches for gnatmake"
385"These switches are used in the default gnatmake
a1506d29 386command.")
da2a1edf
SM
387 (ada-prj-field 'gnatfind_opt "Switches for gnatfind"
388"The command gnatfind is run every time the Ada/Goto/List_References menu.
389You should for instance add -a if you are working in an environment
390where most ALI files are write-protected, since otherwise they get
391ignored by gnatfind and you don't see the references within.")
c6fa13e3 392 )
d41832c5 393
c6fa13e3
GM
394 ;;
395 ;; Fourth page
396 ;;
397 ((= tab-num 4)
da2a1edf 398 (widget-insert "/_____________\\/______________\\/______________\\/ \\/______________\\\n")
c6fa13e3 399 (widget-insert
da2a1edf
SM
400"All the fields below can use variable substitution The syntax is ${name},
401where name is the name that appears after the Help buttons in this buffer. As
402a special case, ${current} is replaced with the name of the file currently
403edited, with directory name but no extension, whereas ${full_current} is
404replaced with the name of the current file with directory name and
405extension.\n")
c6fa13e3 406 (widget-insert
da2a1edf
SM
407"The environment variables ADA_INCLUDE_PATH and ADA_OBJECTS_PATH are set to
408${src_dir} and ${obj_dir} before running the compilation commands, so that you
409don't need to specify the -aI and -aO switches on the command line\n")
c6fa13e3 410 (widget-insert
da2a1edf
SM
411"You can reference any environment variable using the same ${...} syntax as
412above, and put the name of the variable between the quotes.\n\n")
c6fa13e3
GM
413 (ada-prj-field 'check_cmd
414 "Check syntax of a single file (menu Ada->Check File)"
415"This command is run to check the syntax and semantics of a file.
da2a1edf 416The file name is added at the end of this command." t)
c6fa13e3
GM
417 (ada-prj-field 'comp_cmd
418 "Compiling a single file (menu Ada->Compile File)"
419"This command is run when the recompilation
420of a single file is needed. The file name is
da2a1edf 421added at the end of this command." t)
c6fa13e3
GM
422 (ada-prj-field 'make_cmd "Rebuilding the whole project (menu Ada->Build)"
423"This command is run when you want to rebuild
424your whole application. It is never issues
425automatically and you will need to ask for it.
426If remote_machine has been set, this command
da2a1edf 427will be executed on the remote machine." t)
c6fa13e3
GM
428 (ada-prj-field 'run_cmd "Running the application (menu Ada->Run)"
429"This command specifies how to run the
430application, including any switch you need to
431specify. If remote_machine has been set, this
da2a1edf
SM
432command will be executed on the remote host." t)
433 )
434
435 ;;
436 ;; Fifth page
437 ;;
438 ((= tab-num 5)
439 (widget-insert "/_____________\\/______________\\/______________\\/______________\\/ \\\n")
440 (ada-prj-field 'debug_pre_cmd "Commands to execute before launching the
441debugger"
442"The following commands are executed one after the other before starting
443the debugger. These can be used to set up your environment." t)
a1506d29 444
c6fa13e3
GM
445 (ada-prj-field 'debug_cmd "Debugging the application"
446"Specifies how to debug the application, possibly
447remotely if remote_machine has been set. We
448recommend the following debuggers:
449 > gdb
da2a1edf 450 > gvd --tty
c6fa13e3 451 > ddd --tty -fullname -toolbar")
da2a1edf
SM
452
453 (ada-prj-field 'debug_post_cmd "Commands to execute in the debugger"
454"The following commands are executed one in the debugger once it has been
455started. These can be used to initialize the debugger, for instance to
456connect to the target when working with cross-environments" t)
c6fa13e3 457 )
a1506d29 458
c6fa13e3
GM
459 )
460
461
462 (widget-insert "______________________________________________________________________\n\n ")
463 (widget-create 'push-button
464 :notify (lambda (&rest ignore)
465 (ada-xref-set-default-prj-values
466 'ada-prj-current-values ada-prj-ada-buffer)
467 (ada-prj-display-page 1))
468 "Reset to Default Values")
469 (widget-insert " ")
470 (widget-create 'push-button :notify (lambda (&rest ignore) (kill-buffer nil))
471 "Cancel")
472 (widget-insert " ")
473 (widget-create 'push-button :notify (lambda (&rest ignore) (ada-prj-save))
474 "Save")
475 (widget-insert "\n\n")
476
477 (widget-setup)
300ee850
RS
478 (with-no-warnings
479 (beginning-of-buffer))
c6fa13e3 480 )
d41832c5 481
d41832c5 482
c6fa13e3
GM
483(defun ada-customize (&optional new-file filename)
484 "Edit the project file associated with the current buffer.
485If there is none or NEW-FILE is non-nil, make a new one.
486If FILENAME is given, edit that file."
487 (interactive)
d41832c5 488
c6fa13e3
GM
489 (let ((ada-buffer (current-buffer))
490 (inhibit-read-only t))
d41832c5 491
61c08d00
SM
492 ;; We can only edit interactively the standard ada-mode project files. If
493 ;; the user is using other formats for the project file (through hooks in
494 ;; `ada-load-project-hook', we simply edit the file
a1506d29 495
61c08d00
SM
496 (if (and (not new-file)
497 (or ada-prj-default-project-file filename)
498 (string= (file-name-extension
499 (or filename ada-prj-default-project-file))
500 "gpr"))
501 (progn
502 (find-file ada-prj-default-project-file)
503 (add-hook 'after-save-hook 'ada-reread-prj-file t t)
504 )
da2a1edf 505
ce20e709
JB
506 (if filename
507 (ada-reread-prj-file filename)
508 (if (not (string= ada-prj-default-project-file ""))
509 (ada-reread-prj-file ada-prj-default-project-file)
510 (ada-reread-prj-file)))
511
d759dcce 512 (switch-to-buffer "*Edit Ada Mode Project*")
a1506d29 513
ce20e709
JB
514 (ada-prj-initialize-values 'ada-prj-current-values
515 ada-buffer
516 ada-prj-default-project-file)
a1506d29 517
61c08d00 518 (set (make-local-variable 'ada-prj-ada-buffer) ada-buffer)
a1506d29 519
61c08d00
SM
520 (use-local-map (copy-keymap custom-mode-map))
521 (local-set-key "\C-x\C-s" 'ada-prj-save)
a1506d29 522
61c08d00
SM
523 (make-local-variable 'widget-keymap)
524 (define-key widget-keymap "\C-x\C-s" 'ada-prj-save)
a1506d29 525
61c08d00
SM
526 (set (make-local-variable 'ada-old-cross-prefix)
527 (ada-xref-get-project-field 'cross-prefix))
a1506d29 528
61c08d00
SM
529 (ada-prj-display-page 1)
530 )))
d41832c5
GM
531
532;; ---------------- Utilities --------------------------------
533
da2a1edf 534(defun ada-prj-set-list (string ada-list &optional is-directory)
d759dcce
JB
535 "Prepend STRING to strings in ADA-LIST, return new-line separated string.
536If IS-DIRECTORY is non-nil, each element of ADA-LIST is explicitly
537converted to a directory name."
da2a1edf
SM
538
539 (mapconcat (lambda (x) (concat string "="
540 (if is-directory
541 (file-name-as-directory x)
542 x)))
d759dcce 543 ada-list "\n"))
d41832c5 544
c6fa13e3 545
c6fa13e3 546(defun ada-prj-field-modified (widget &rest dummy)
d759dcce
JB
547 "Callback for modification of WIDGET.
548Remaining args DUMMY are ignored.
549Save the change in `ada-prj-current-values' so that selecting
550another page and coming back keeps the new value."
c6fa13e3
GM
551 (set 'ada-prj-current-values
552 (plist-put ada-prj-current-values
da2a1edf 553 (widget-get widget ':prj-field)
c6fa13e3
GM
554 (widget-value widget))))
555
556(defun ada-prj-display-help (widget widget-modified event)
d759dcce
JB
557 "Callback for help button in WIDGET.
558Parameters WIDGET-MODIFIED, EVENT match :notify for the widget."
c6fa13e3
GM
559 (let ((text (widget-get widget 'prj-help)))
560 (if event
561 ;; If we have a mouse-event, popup a menu
562 (widget-choose "Help"
563 (mapcar (lambda (a) (cons a t))
564 (split-string text "\n"))
565 event)
566 ;; Else display the help string just before the next group of
567 ;; variables
568 (momentary-string-display
569 (concat "*****Help*****\n" text "\n**************\n")
570 (save-excursion (forward-line) (beginning-of-line) (point)))
571 )))
572
573(defun ada-prj-show-value (widget widget-modified event)
d759dcce
JB
574 "Show the current field value in WIDGET.
575Parameters WIDGET-MODIFIED, EVENT match :notify for the widget."
da2a1edf
SM
576 (let* ((field (widget-get widget ':prj-field))
577 (value (plist-get ada-prj-current-values field))
578 (inhibit-read-only t)
579 w)
c6fa13e3
GM
580
581 ;; If the other widget is already visible, delete it
582 (if (widget-get widget 'prj-other-widget)
583 (progn
584 (widget-delete (widget-get widget 'prj-other-widget))
585 (widget-put widget 'prj-other-widget nil)
da2a1edf 586 (widget-put widget ':prj-field field)
c6fa13e3
GM
587 (widget-default-value-set widget "Show Value")
588 )
589
590 ;; Else create it
591 (save-excursion
592 (mouse-set-point event)
593 (forward-line 1)
594 (beginning-of-line)
da2a1edf
SM
595 (setq w (widget-create 'editable-list
596 :entry-format "%i%d %v"
597 :notify 'ada-prj-field-modified
598 :help-echo (widget-get widget 'prj-help)
599 :value value
600 (list 'editable-field :keymap widget-keymap)))
601 (widget-put widget 'prj-other-widget w)
602 (widget-put w ':prj-field field)
603 (widget-put widget ':prj-field field)
c6fa13e3
GM
604 (widget-default-value-set widget "Hide Value")
605 )
606 )
607 (widget-setup)
608 ))
609
610(defun ada-prj-field (field text help-text &optional is-list is-paths after-text)
611 "Create a widget to edit FIELD in the current buffer.
612TEXT is a short explanation of what the field means, whereas HELP-TEXT
613is the text displayed when the user pressed the help button.
614If IS-LIST is non-nil, the field contains a list. Otherwise, it contains
615a single string.
616if IS-PATHS is true, some special buttons are added to load paths,...
617AFTER-TEXT is inserted just after the widget."
618 (let ((value (plist-get ada-prj-current-values field))
619 (inhibit-read-only t)
620 widget)
621 (unless value
622 (set 'value
623 (if is-list '() "")))
624 (widget-insert text)
625 (widget-insert ":")
626 (move-to-column 54 t)
627 (widget-put (widget-create 'push-button
628 :notify 'ada-prj-display-help
629 "Help")
630 'prj-help
631 help-text)
632 (widget-insert (concat " (" (symbol-name field) ")\n"))
633 (if is-paths
634 (progn
635 (widget-create 'push-button
636 :notify
637 (list 'lambda '(&rest dummy) '(interactive)
638 (list 'ada-prj-load-from-file
639 (list 'quote field)))
640 "Load From File")
641 (widget-insert " ")
642 (widget-create 'push-button
643 :notify
644 (list 'lambda '(&rest dummy) '(interactive)
645 (list 'ada-prj-load-directory
646 (list 'quote field)))
647 "Load Recursive Directory")
648 (widget-insert "\n ${build_dir}\n")))
da2a1edf 649
c6fa13e3
GM
650 (set 'widget
651 (if is-list
652 (if (< (length value) 15)
653 (widget-create 'editable-list
654 :entry-format "%i%d %v"
655 :notify 'ada-prj-field-modified
656 :help-echo help-text
657 :value value
658 (list 'editable-field :keymap widget-keymap))
da2a1edf 659
c6fa13e3
GM
660 (let ((w (widget-create 'push-button
661 :notify 'ada-prj-show-value
662 "Show value")))
663 (widget-insert "\n")
c6fa13e3
GM
664 (widget-put w 'prj-help help-text)
665 (widget-put w 'prj-other-widget nil)
666 w)
667 )
668 (widget-create 'editable-field
669 :format "%v"
670 :notify 'ada-prj-field-modified
671 :help-echo help-text
672 :keymap widget-keymap
673 value)))
da2a1edf 674 (widget-put widget ':prj-field field)
c6fa13e3
GM
675 (if after-text
676 (widget-insert after-text))
677 (widget-insert "\n")
678 ))
d41832c5 679
d41832c5 680
d41832c5 681(provide 'ada-prj)
3afbc435 682
cbee283d 683;; arch-tag: 65978c77-816e-49c6-896e-6905605d1b4c
3afbc435 684;;; ada-prj.el ends here