ada-prj.el 23 KB

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