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