dictionary.el 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. ;;; srecode/dictionary.el --- Dictionary code for the semantic recoder.
  2. ;; Copyright (C) 2007-2012 Free Software Foundation, Inc.
  3. ;; Author: Eric M. Ludlam <eric@siege-engine.com>
  4. ;; This file is part of GNU Emacs.
  5. ;; GNU Emacs is free software: you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;
  17. ;; Dictionaries contain lists of names and their associated values.
  18. ;; These dictionaries are used to fill in macros from recoder templates.
  19. ;;; Code:
  20. ;;; CLASSES
  21. (eval-when-compile (require 'cl))
  22. (require 'eieio)
  23. (require 'srecode)
  24. (require 'srecode/table)
  25. (eval-when-compile (require 'semantic))
  26. (declare-function srecode-compile-parse-inserter "srecode/compile")
  27. (declare-function srecode-dump-code-list "srecode/compile")
  28. (declare-function srecode-load-tables-for-mode "srecode/find")
  29. (declare-function srecode-template-table-in-project-p "srecode/find")
  30. (declare-function srecode-insert-code-stream "srecode/insert")
  31. (declare-function data-debug-new-buffer "data-debug")
  32. (declare-function data-debug-insert-object-slots "eieio-datadebug")
  33. (declare-function srecode-field "srecode/fields")
  34. (defclass srecode-dictionary ()
  35. ((namehash :initarg :namehash
  36. :documentation
  37. "Hash table containing the names of all the templates.")
  38. (buffer :initarg :buffer
  39. :documentation
  40. "The buffer this dictionary was initialized with.")
  41. (parent :initarg :parent
  42. :type (or null srecode-dictionary)
  43. :documentation
  44. "The parent dictionary.
  45. Symbols not appearing in this dictionary will be checked against the
  46. parent dictionary.")
  47. (origin :initarg :origin
  48. :type string
  49. :documentation
  50. "A string representing the origin of this dictionary.
  51. Useful only while debugging.")
  52. )
  53. "Dictionary of symbols and what they mean.
  54. Dictionaries are used to look up named symbols from
  55. templates to decide what to do with those symbols.")
  56. (defclass srecode-dictionary-compound-value ()
  57. ()
  58. "A compound dictionary value.
  59. Values stored in a dictionary must be a STRING,
  60. a dictionary for showing sections, or an instance of a subclass
  61. of this class.
  62. Compound dictionary values derive from this class, and must
  63. provide a sequence of method implementations to convert into
  64. a string."
  65. :abstract t)
  66. (defclass srecode-dictionary-compound-variable
  67. (srecode-dictionary-compound-value)
  68. ((value :initarg :value
  69. :documentation
  70. "The value of this template variable.
  71. Variables in template files are usually a single string
  72. which can be inserted into a dictionary directly.
  73. Some variables may be more complex and involve dictionary
  74. lookups, strings, concatenation, or the like.
  75. The format of VALUE is determined by current template
  76. formatting rules.")
  77. (compiled :initarg :compiled
  78. :type list
  79. :documentation
  80. "The compiled version of VALUE.")
  81. )
  82. "A compound dictionary value for template file variables.
  83. You can declare a variable in a template like this:
  84. set NAME \"str\" macro \"OTHERNAME\"
  85. with appending various parts together in a list.")
  86. (defmethod initialize-instance ((this srecode-dictionary-compound-variable)
  87. &optional fields)
  88. "Initialize the compound variable THIS.
  89. Makes sure that :value is compiled."
  90. (let ((newfields nil)
  91. (state nil))
  92. (while fields
  93. ;; Strip out :state
  94. (if (eq (car fields) :state)
  95. (setq state (car (cdr fields)))
  96. (setq newfields (cons (car (cdr fields))
  97. (cons (car fields) newfields))))
  98. (setq fields (cdr (cdr fields))))
  99. (when (not state)
  100. (error "Cannot create compound variable without :state"))
  101. (call-next-method this (nreverse newfields))
  102. (when (not (slot-boundp this 'compiled))
  103. (let ((val (oref this :value))
  104. (comp nil))
  105. (while val
  106. (let ((nval (car val))
  107. )
  108. (cond ((stringp nval)
  109. (setq comp (cons nval comp)))
  110. ((and (listp nval)
  111. (equal (car nval) 'macro))
  112. (require 'srecode/compile)
  113. (setq comp (cons
  114. (srecode-compile-parse-inserter
  115. (cdr nval)
  116. state)
  117. comp)))
  118. (t
  119. (error "Don't know how to handle variable value %S" nval)))
  120. )
  121. (setq val (cdr val)))
  122. (oset this :compiled (nreverse comp))))))
  123. ;;; DICTIONARY METHODS
  124. ;;
  125. (defun srecode-create-dictionary (&optional buffer-or-parent)
  126. "Create a dictionary for BUFFER.
  127. If BUFFER-OR-PARENT is not specified, assume a buffer, and
  128. use the current buffer.
  129. If BUFFER-OR-PARENT is another dictionary, then remember the
  130. parent within the new dictionary, and assume that BUFFER
  131. is the same as belongs to the parent dictionary.
  132. The dictionary is initialized with variables setup for that
  133. buffer's table.
  134. If BUFFER-OR-PARENT is t, then this dictionary should not be
  135. associated with a buffer or parent."
  136. (save-excursion
  137. ;; Handle the parent
  138. (let ((parent nil)
  139. (buffer nil)
  140. (origin nil)
  141. (initfrombuff nil))
  142. (cond
  143. ;; Parent is a buffer
  144. ((bufferp buffer-or-parent)
  145. (set-buffer buffer-or-parent)
  146. (setq buffer buffer-or-parent
  147. origin (buffer-name buffer-or-parent)
  148. initfrombuff t))
  149. ;; Parent is another dictionary
  150. ((srecode-dictionary-child-p buffer-or-parent)
  151. (setq parent buffer-or-parent
  152. buffer (oref buffer-or-parent buffer)
  153. origin (concat (object-name buffer-or-parent) " in "
  154. (if buffer (buffer-name buffer)
  155. "no buffer")))
  156. (when buffer
  157. (set-buffer buffer)))
  158. ;; No parent
  159. ((eq buffer-or-parent t)
  160. (setq buffer nil
  161. origin "Unspecified Origin"))
  162. ;; Default to unspecified parent
  163. (t
  164. (setq buffer (current-buffer)
  165. origin (concat "Unspecified. Assume "
  166. (buffer-name buffer))
  167. initfrombuff t)))
  168. ;; Create the new dictionary object.
  169. (let ((dict (srecode-dictionary
  170. major-mode
  171. :buffer buffer
  172. :parent parent
  173. :namehash (make-hash-table :test 'equal
  174. :size 20)
  175. :origin origin)))
  176. ;; Only set up the default variables if we are being built
  177. ;; directly for a particular buffer.
  178. (when initfrombuff
  179. ;; Variables from the table we are inserting from.
  180. ;; @todo - get a better tree of tables.
  181. (let ((mt (srecode-get-mode-table major-mode))
  182. (def (srecode-get-mode-table 'default)))
  183. ;; Each table has multiple template tables.
  184. ;; Do DEF first so that MT can override any values.
  185. (srecode-dictionary-add-template-table dict def)
  186. (srecode-dictionary-add-template-table dict mt)
  187. ))
  188. dict))))
  189. (defmethod srecode-dictionary-add-template-table ((dict srecode-dictionary)
  190. tpl)
  191. "Insert into DICT the variables found in table TPL.
  192. TPL is an object representing a compiled template file."
  193. (when tpl
  194. (let ((tabs (oref tpl :tables)))
  195. (require 'srecode/find) ; For srecode-template-table-in-project-p
  196. (while tabs
  197. (when (srecode-template-table-in-project-p (car tabs))
  198. (let ((vars (oref (car tabs) variables)))
  199. (while vars
  200. (srecode-dictionary-set-value
  201. dict (car (car vars)) (cdr (car vars)))
  202. (setq vars (cdr vars)))))
  203. (setq tabs (cdr tabs))))))
  204. (defmethod srecode-dictionary-set-value ((dict srecode-dictionary)
  205. name value)
  206. "In dictionary DICT, set NAME to have VALUE."
  207. ;; Validate inputs
  208. (unless (stringp name)
  209. (signal 'wrong-type-argument (list name 'stringp)))
  210. ;; Add the value.
  211. (with-slots (namehash) dict
  212. (puthash name value namehash))
  213. )
  214. (defmethod srecode-dictionary-add-section-dictionary ((dict srecode-dictionary)
  215. name &optional show-only force)
  216. "In dictionary DICT, add a section dictionary for section macro NAME.
  217. Return the new dictionary.
  218. You can add several dictionaries to the same section entry.
  219. For each dictionary added to a variable, the block of codes in
  220. the template will be repeated.
  221. If optional argument SHOW-ONLY is non-nil, then don't add a new dictionary
  222. if there is already one in place. Also, don't add FIRST/LAST entries.
  223. These entries are not needed when we are just showing a section.
  224. Each dictionary added will automatically get values for positional macros
  225. which will enable SECTIONS to be enabled.
  226. * FIRST - The first entry in the table.
  227. * NOTFIRST - Not the first entry in the table.
  228. * LAST - The last entry in the table
  229. * NOTLAST - Not the last entry in the table.
  230. Adding a new dictionary will alter these values in previously
  231. inserted dictionaries."
  232. ;; Validate inputs
  233. (unless (stringp name)
  234. (signal 'wrong-type-argument (list name 'stringp)))
  235. (let ((new (srecode-create-dictionary dict))
  236. (ov (srecode-dictionary-lookup-name dict name t)))
  237. (when (not show-only)
  238. ;; Setup the FIRST/NOTFIRST and LAST/NOTLAST entries.
  239. (if (null ov)
  240. (progn
  241. (srecode-dictionary-show-section new "FIRST")
  242. (srecode-dictionary-show-section new "LAST"))
  243. ;; Not the very first one. Let's clean up CAR.
  244. (let ((tail (car (last ov))))
  245. (srecode-dictionary-hide-section tail "LAST")
  246. (srecode-dictionary-show-section tail "NOTLAST")
  247. )
  248. (srecode-dictionary-show-section new "NOTFIRST")
  249. (srecode-dictionary-show-section new "LAST"))
  250. )
  251. (when (or force
  252. (not show-only)
  253. (null ov))
  254. (srecode-dictionary-set-value dict name (append ov (list new))))
  255. ;; Return the new sub-dictionary.
  256. new))
  257. (defmethod srecode-dictionary-show-section ((dict srecode-dictionary) name)
  258. "In dictionary DICT, indicate that the section NAME should be exposed."
  259. ;; Validate inputs
  260. (unless (stringp name)
  261. (signal 'wrong-type-argument (list name 'stringp)))
  262. ;; Showing a section is just like making a section dictionary, but
  263. ;; with no dictionary values to add.
  264. (srecode-dictionary-add-section-dictionary dict name t)
  265. nil)
  266. (defmethod srecode-dictionary-hide-section ((dict srecode-dictionary) name)
  267. "In dictionary DICT, indicate that the section NAME should be hidden."
  268. ;; We need to find the has value, and then delete it.
  269. ;; Validate inputs
  270. (unless (stringp name)
  271. (signal 'wrong-type-argument (list name 'stringp)))
  272. ;; Add the value.
  273. (with-slots (namehash) dict
  274. (remhash name namehash))
  275. nil)
  276. (defmethod srecode-dictionary-add-entries ((dict srecode-dictionary)
  277. entries &optional state)
  278. "Add ENTRIES to DICT.
  279. ENTRIES is a list of even length of dictionary entries to
  280. add. ENTRIES looks like this:
  281. (NAME_1 VALUE_1 NAME_2 VALUE_2 ...)
  282. The following rules apply:
  283. * NAME_N is a string
  284. and for values
  285. * If VALUE_N is t, the section NAME_N is shown.
  286. * If VALUE_N is a string, an ordinary value is inserted.
  287. * If VALUE_N is a dictionary, it is inserted as entry NAME_N.
  288. * Otherwise, a compound variable is created for VALUE_N.
  289. The optional argument STATE has to non-nil when compound values
  290. are inserted. An error is signaled if ENTRIES contains compound
  291. values but STATE is nil."
  292. (while entries
  293. (let ((name (nth 0 entries))
  294. (value (nth 1 entries)))
  295. (cond
  296. ;; Value is t; show a section.
  297. ((eq value t)
  298. (srecode-dictionary-show-section dict name))
  299. ;; Value is a simple string; create an ordinary dictionary
  300. ;; entry
  301. ((stringp value)
  302. (srecode-dictionary-set-value dict name value))
  303. ;; Value is a dictionary; insert as child dictionary.
  304. ((srecode-dictionary-child-p value)
  305. (srecode-dictionary-merge
  306. (srecode-dictionary-add-section-dictionary dict name)
  307. value t))
  308. ;; Value is some other object; create a compound value.
  309. (t
  310. (unless state
  311. (error "Cannot insert compound values without state."))
  312. (srecode-dictionary-set-value
  313. dict name
  314. (srecode-dictionary-compound-variable
  315. name :value value :state state)))))
  316. (setq entries (nthcdr 2 entries)))
  317. dict)
  318. (defmethod srecode-dictionary-merge ((dict srecode-dictionary) otherdict
  319. &optional force)
  320. "Merge into DICT the dictionary entries from OTHERDICT.
  321. Unless the optional argument FORCE is non-nil, values in DICT are
  322. not modified, even if there are values of the same names in
  323. OTHERDICT."
  324. (when otherdict
  325. (maphash
  326. (lambda (key entry)
  327. ;; The new values is only merged in if there was no old value
  328. ;; or FORCE is non-nil.
  329. ;;
  330. ;; This protects applications from being whacked, and basically
  331. ;; makes these new section dictionary entries act like
  332. ;; "defaults" instead of overrides.
  333. (when (or force
  334. (not (srecode-dictionary-lookup-name dict key t)))
  335. (cond
  336. ;; A list of section dictionaries. We need to merge them in.
  337. ((and (listp entry)
  338. (srecode-dictionary-p (car entry)))
  339. (dolist (sub-dict entry)
  340. (srecode-dictionary-merge
  341. (srecode-dictionary-add-section-dictionary
  342. dict key t t)
  343. sub-dict force)))
  344. ;; Other values can be set directly.
  345. (t
  346. (srecode-dictionary-set-value dict key entry)))))
  347. (oref otherdict namehash))))
  348. (defmethod srecode-dictionary-lookup-name ((dict srecode-dictionary)
  349. name &optional non-recursive)
  350. "Return information about DICT's value for NAME.
  351. DICT is a dictionary, and NAME is a string that is treated as the
  352. name of an entry in the dictionary. If such an entry exists, its
  353. value is returned. Otherwise, nil is returned. Normally, the
  354. lookup is recursive in the sense that the parent of DICT is
  355. searched for NAME if it is not found in DICT. This recursive
  356. lookup can be disabled by the optional argument NON-RECURSIVE.
  357. This function derives values for some special NAMEs, such as
  358. 'FIRST' and 'LAST'."
  359. (if (not (slot-boundp dict 'namehash))
  360. nil
  361. ;; Get the value of this name from the dictionary or its parent
  362. ;; unless the lookup should be non-recursive.
  363. (with-slots (namehash parent) dict
  364. (or (gethash name namehash)
  365. (and (not non-recursive)
  366. (not (member name '("FIRST" "LAST" "NOTFIRST" "NOTLAST")))
  367. parent
  368. (srecode-dictionary-lookup-name parent name)))))
  369. )
  370. (defmethod srecode-root-dictionary ((dict srecode-dictionary))
  371. "For dictionary DICT, return the root dictionary.
  372. The root dictionary is usually for a current or active insertion."
  373. (let ((ans dict))
  374. (while (oref ans parent)
  375. (setq ans (oref ans parent)))
  376. ans))
  377. ;;; COMPOUND VALUE METHODS
  378. ;;
  379. ;; Compound values must provide at least the toString method
  380. ;; for use in converting the compound value into something insertable.
  381. (defmethod srecode-compound-toString ((cp srecode-dictionary-compound-value)
  382. function
  383. dictionary)
  384. "Convert the compound dictionary value CP to a string.
  385. If FUNCTION is non-nil, then FUNCTION is somehow applied to an aspect
  386. of the compound value. The FUNCTION could be a fraction
  387. of some function symbol with a logical prefix excluded.
  388. If you subclass `srecode-dictionary-compound-value' then this
  389. method could return nil, but if it does that, it must insert
  390. the value itself using `princ', or by detecting if the current
  391. standard out is a buffer, and using `insert'."
  392. (object-name cp))
  393. (defmethod srecode-dump ((cp srecode-dictionary-compound-value)
  394. &optional indent)
  395. "Display information about this compound value."
  396. (princ (object-name cp))
  397. )
  398. (defmethod srecode-compound-toString ((cp srecode-dictionary-compound-variable)
  399. function
  400. dictionary)
  401. "Convert the compound dictionary variable value CP into a string.
  402. FUNCTION and DICTIONARY are as for the baseclass."
  403. (require 'srecode/insert)
  404. (srecode-insert-code-stream (oref cp compiled) dictionary))
  405. (defmethod srecode-dump ((cp srecode-dictionary-compound-variable)
  406. &optional indent)
  407. "Display information about this compound value."
  408. (require 'srecode/compile)
  409. (princ "# Compound Variable #\n")
  410. (let ((indent (+ 4 (or indent 0)))
  411. (cmp (oref cp compiled))
  412. )
  413. (srecode-dump-code-list cmp (make-string indent ? ))
  414. ))
  415. ;;; FIELD EDITING COMPOUND VALUE
  416. ;;
  417. ;; This is an interface to using field-editing objects
  418. ;; instead of asking questions. This provides the basics
  419. ;; behind this compound value.
  420. (defclass srecode-field-value (srecode-dictionary-compound-value)
  421. ((firstinserter :initarg :firstinserter
  422. :documentation
  423. "The inserter object for the first occurrence of this field.")
  424. (defaultvalue :initarg :defaultvalue
  425. :documentation
  426. "The default value for this inserter.")
  427. )
  428. "When inserting values with editable field mode, a dictionary value.
  429. Compound values allow a field to be stored in the dictionary for when
  430. it is referenced a second time. This compound value can then be
  431. inserted with a new editable field.")
  432. (defmethod srecode-compound-toString((cp srecode-field-value)
  433. function
  434. dictionary)
  435. "Convert this field into an insertable string."
  436. (require 'srecode/fields)
  437. ;; If we are not in a buffer, then this is not supported.
  438. (when (not (bufferp standard-output))
  439. (error "FIELDS invoked while inserting template to non-buffer"))
  440. (if function
  441. (error "@todo: Cannot mix field insertion with functions")
  442. ;; No function. Perform a plain field insertion.
  443. ;; We know we are in a buffer, so we can perform the insertion.
  444. (let* ((dv (oref cp defaultvalue))
  445. (sti (oref cp firstinserter))
  446. (start (point))
  447. (name (oref sti :object-name)))
  448. (cond
  449. ;; No default value.
  450. ((not dv) (insert name))
  451. ;; A compound value as the default? Recurse.
  452. ((srecode-dictionary-compound-value-child-p dv)
  453. (srecode-compound-toString dv function dictionary))
  454. ;; A string that is empty? Use the name.
  455. ((and (stringp dv) (string= dv ""))
  456. (insert name))
  457. ;; Insert strings
  458. ((stringp dv) (insert dv))
  459. ;; Some other issue
  460. (t
  461. (error "Unknown default value for value %S" name)))
  462. ;; Create a field from the inserter.
  463. (srecode-field name :name name
  464. :start start
  465. :end (point)
  466. :prompt (oref sti prompt)
  467. :read-fcn (oref sti read-fcn)
  468. )
  469. ))
  470. ;; Returning nil is a signal that we have done the insertion ourselves.
  471. nil)
  472. ;;; Higher level dictionary functions
  473. ;;
  474. (defun srecode-create-section-dictionary (sectiondicts STATE)
  475. "Create a dictionary with section entries for a template.
  476. The format for SECTIONDICTS is what is emitted from the template parsers.
  477. STATE is the current compiler state."
  478. (when sectiondicts
  479. (let ((new (srecode-create-dictionary t)))
  480. ;; Loop over each section. The section is a macro w/in the
  481. ;; template.
  482. (while sectiondicts
  483. (let* ((sect (car (car sectiondicts)))
  484. (entries (cdr (car sectiondicts)))
  485. (subdict (srecode-dictionary-add-section-dictionary new sect))
  486. )
  487. ;; Loop over each entry. This is one variable in the
  488. ;; section dictionary.
  489. (while entries
  490. (let ((tname (semantic-tag-name (car entries)))
  491. (val (semantic-tag-variable-default (car entries))))
  492. (if (eq val t)
  493. (srecode-dictionary-show-section subdict tname)
  494. (cond
  495. ((and (stringp (car val))
  496. (= (length val) 1))
  497. (setq val (car val)))
  498. (t
  499. (setq val (srecode-dictionary-compound-variable
  500. tname :value val :state STATE))))
  501. (srecode-dictionary-set-value
  502. subdict tname val))
  503. (setq entries (cdr entries))))
  504. )
  505. (setq sectiondicts (cdr sectiondicts)))
  506. new)))
  507. (defun srecode-create-dictionaries-from-tags (tags state)
  508. "Create a dictionary with entries according to TAGS.
  509. TAGS should be in the format produced by the template file
  510. grammar. That is
  511. TAGS = (ENTRY_1 ENTRY_2 ...)
  512. where
  513. ENTRY_N = (NAME ENTRY_N_1 ENTRY_N_2 ...) | TAG
  514. where TAG is a semantic tag of class 'variable. The (NAME ... )
  515. form creates a child dictionary which is stored under the name
  516. NAME. The TAG form creates a value entry or section dictionary
  517. entry whose name is the name of the tag.
  518. STATE is the current compiler state."
  519. (let ((dict (srecode-create-dictionary t))
  520. (entries (apply #'append
  521. (mapcar
  522. (lambda (entry)
  523. (cond
  524. ;; Entry is a tag
  525. ((semantic-tag-p entry)
  526. (let ((name (semantic-tag-name entry))
  527. (value (semantic-tag-variable-default entry)))
  528. (list name
  529. (if (and (listp value)
  530. (= (length value) 1)
  531. (stringp (car value)))
  532. (car value)
  533. value))))
  534. ;; Entry is a nested dictionary
  535. (t
  536. (let ((name (car entry))
  537. (entries (cdr entry)))
  538. (list name
  539. (srecode-create-dictionaries-from-tags
  540. entries state))))))
  541. tags))))
  542. (srecode-dictionary-add-entries
  543. dict entries state)
  544. dict)
  545. )
  546. ;;; DUMP DICTIONARY
  547. ;;
  548. ;; Make a dictionary, and dump it's contents.
  549. (defun srecode-adebug-dictionary ()
  550. "Run data-debug on this mode's dictionary."
  551. (interactive)
  552. (require 'eieio-datadebug)
  553. (require 'semantic)
  554. (require 'srecode/find)
  555. (let* ((modesym major-mode)
  556. (start (current-time))
  557. (junk (or (progn (srecode-load-tables-for-mode modesym)
  558. (srecode-get-mode-table modesym))
  559. (error "No table found for mode %S" modesym)))
  560. (dict (srecode-create-dictionary (current-buffer)))
  561. (end (current-time))
  562. )
  563. (message "Creating a dictionary took %.2f seconds."
  564. (semantic-elapsed-time start end))
  565. (data-debug-new-buffer "*SRECODE ADEBUG*")
  566. (data-debug-insert-object-slots dict "*")))
  567. (defun srecode-dictionary-dump ()
  568. "Dump a typical fabricated dictionary."
  569. (interactive)
  570. (require 'srecode/find)
  571. (let ((modesym major-mode))
  572. ;; This load allows the dictionary access to inherited
  573. ;; and stacked dictionary entries.
  574. (srecode-load-tables-for-mode modesym)
  575. (let ((tmp (srecode-get-mode-table modesym))
  576. )
  577. (if (not tmp)
  578. (error "No table found for mode %S" modesym))
  579. ;; Now make the dictionary.
  580. (let ((dict (srecode-create-dictionary (current-buffer))))
  581. (with-output-to-temp-buffer "*SRECODE DUMP*"
  582. (princ "DICTIONARY FOR ")
  583. (princ major-mode)
  584. (princ "\n--------------------------------------------\n")
  585. (srecode-dump dict))
  586. ))))
  587. (defmethod srecode-dump ((dict srecode-dictionary) &optional indent)
  588. "Dump a dictionary."
  589. (if (not indent) (setq indent 0))
  590. (maphash (lambda (key entry)
  591. (princ (make-string indent ? ))
  592. (princ " ")
  593. (princ key)
  594. (princ " ")
  595. (cond ((and (listp entry)
  596. (srecode-dictionary-p (car entry)))
  597. (let ((newindent (if indent
  598. (+ indent 4)
  599. 4)))
  600. (while entry
  601. (princ " --> SUBDICTIONARY ")
  602. (princ (object-name dict))
  603. (princ "\n")
  604. (srecode-dump (car entry) newindent)
  605. (setq entry (cdr entry))
  606. ))
  607. (princ "\n")
  608. )
  609. ((srecode-dictionary-compound-value-child-p entry)
  610. (srecode-dump entry indent)
  611. (princ "\n")
  612. )
  613. (t
  614. (prin1 entry)
  615. ;(princ "\n")
  616. ))
  617. (terpri)
  618. )
  619. (oref dict namehash))
  620. )
  621. (provide 'srecode/dictionary)
  622. ;;; srecode/dictionary.el ends here