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