Commit | Line | Data |
---|---|---|
4d902e6f CY |
1 | ;;; srecode/table.el --- Tables of Semantic Recoders |
2 | ||
3 | ;; Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. | |
4 | ||
5 | ;; Author: Eric M. Ludlam <eric@siege-engine.com> | |
6 | ||
7 | ;; This file is part of GNU Emacs. | |
8 | ||
9 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation, either version 3 of the License, or | |
12 | ;; (at your option) any later version. | |
13 | ||
14 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ;;; Commentary: | |
23 | ;; | |
24 | ;; Semantic Recoder tables manage lists of templates and the major | |
25 | ;; modes they are associated with. | |
26 | ;; | |
27 | ||
28 | (require 'eieio) | |
29 | (require 'eieio-base) | |
30 | (require 'mode-local) | |
31 | (require 'srecode) | |
32 | ||
33 | (declare-function srecode-load-tables-for-mode "srecode/find") | |
34 | ||
35 | ;;; Code: | |
36 | ||
37 | ;;; TEMPLATE TABLE | |
38 | ;; | |
39 | (defclass srecode-template-table () | |
40 | (;; | |
41 | ;; Raw file tracking | |
42 | ;; | |
43 | (file :initarg :file | |
44 | :type string | |
45 | :documentation | |
46 | "The name of the file this table was built from.") | |
47 | (filesize :initarg :filesize | |
48 | :type number | |
49 | :documentation | |
50 | "The size of the file when it was parsed.") | |
51 | (filedate :initarg :filedate | |
52 | :type cons | |
53 | :documentation | |
54 | "Date from the inode of the file when it was last edited. | |
55 | Format is from the `file-attributes' function.") | |
56 | (major-mode :initarg :major-mode | |
57 | :documentation | |
58 | "The major mode this table of templates is associated with.") | |
59 | ;; | |
60 | ;; Template file sorting data | |
61 | ;; | |
62 | (application :initarg :application | |
63 | :type symbol | |
64 | :documentation | |
65 | "Tracks the name of the application these templates belong to. | |
66 | If this is nil, then this template table belongs to a set of generic | |
67 | templates that can be used with no additional dictionary values. | |
68 | When it is non-nil, it is assumed the template macros need specialized | |
69 | Emacs Lisp code to fill in the dictoinary.") | |
70 | (priority :initarg :priority | |
71 | :type number | |
72 | :documentation | |
73 | "For file of this Major Mode, what is the priority of this file. | |
74 | When there are multiple template files with similar names, templates with | |
75 | the highest priority are scanned last, allowing them to override values in | |
76 | previous template files.") | |
77 | ;; | |
78 | ;; Parsed Data from the template file | |
79 | ;; | |
80 | (templates :initarg :templates | |
81 | :type list | |
82 | :documentation | |
83 | "The list of templates compiled into this table.") | |
84 | (namehash :initarg :namehash | |
85 | :documentation | |
86 | "Hash table containing the names of all the templates.") | |
87 | (contexthash :initarg :contexthash | |
88 | :documentation | |
89 | "") | |
90 | (variables :initarg :variables | |
91 | :documentation | |
92 | "AList of variables. | |
93 | These variables are used to initialize dictionaries.") | |
94 | ) | |
95 | "Semantic recoder template table. | |
96 | A Table contains all templates from a single .srt file. | |
97 | Tracks various lookup hash tables.") | |
98 | ||
99 | ;;; MODE TABLE | |
100 | ;; | |
101 | (defvar srecode-mode-table-list nil | |
102 | "List of all the SRecode mode table classes that have been built.") | |
103 | ||
104 | (defclass srecode-mode-table (eieio-instance-tracker) | |
105 | ((tracking-symbol :initform 'srecode-mode-table-list) | |
106 | (major-mode :initarg :major-mode | |
107 | :documentation | |
108 | "Table of template tables for this major-mode.") | |
109 | (tables :initarg :tables | |
110 | :documentation | |
111 | "All the tables that have been defined for this major mode.") | |
112 | ) | |
113 | "Track template tables for a particular major mode. | |
114 | Tracks all the template-tables for a specific major mode.") | |
115 | ||
116 | (defun srecode-get-mode-table (mode) | |
117 | "Get the SRecoder mode table for the major mode MODE. | |
118 | Optional argument SOFT indicates to not make a new one if a table | |
119 | was not found." | |
120 | (let ((ans nil)) | |
121 | (while (and (not ans) mode) | |
122 | (setq ans (eieio-instance-tracker-find | |
123 | mode 'major-mode 'srecode-mode-table-list) | |
124 | mode (get-mode-local-parent mode))) | |
125 | ans)) | |
126 | ||
127 | (defun srecode-make-mode-table (mode) | |
128 | "Get the SRecoder mode table for the major mode MODE." | |
129 | (let ((old (eieio-instance-tracker-find | |
130 | mode 'major-mode 'srecode-mode-table-list))) | |
131 | (if old | |
132 | old | |
133 | (let* ((ms (if (stringp mode) mode (symbol-name mode))) | |
134 | (new (srecode-mode-table ms | |
135 | :major-mode mode | |
136 | :tables nil))) | |
137 | ;; Save this new mode table in that mode's variable. | |
138 | (eval `(setq-mode-local ,mode srecode-table ,new)) | |
139 | ||
140 | new)))) | |
141 | ||
142 | (defmethod srecode-mode-table-find ((mt srecode-mode-table) file) | |
143 | "Look in the mode table MT for a template table from FILE. | |
144 | Return nil if there was none." | |
145 | (object-assoc file 'file (oref mt tables))) | |
146 | ||
147 | (defun srecode-mode-table-new (mode file &rest init) | |
148 | "Create a new template table for MODE in FILE. | |
149 | INIT are the initialization parametrs for the new template table." | |
150 | (let* ((mt (srecode-make-mode-table mode)) | |
151 | (old (srecode-mode-table-find mt file)) | |
152 | (attr (file-attributes file)) | |
153 | (new (apply 'srecode-template-table | |
154 | (file-name-nondirectory file) | |
155 | :file file | |
156 | :filesize (nth 7 attr) | |
157 | :filedate (nth 5 attr) | |
158 | :major-mode mode | |
159 | init | |
160 | ))) | |
161 | ;; Whack the old table. | |
162 | (when old (object-remove-from-list mt 'tables old)) | |
163 | ;; Add the new table | |
164 | (object-add-to-list mt 'tables new) | |
165 | ;; Sort the list in reverse order. When other routines | |
166 | ;; go front-to-back, the highest priority items are put | |
167 | ;; into the search table first, allowing lower priority items | |
168 | ;; to be the items found in the search table. | |
169 | (object-sort-list mt 'tables (lambda (a b) | |
170 | (> (oref a :priority) | |
171 | (oref b :priority)))) | |
172 | ;; Return it. | |
173 | new)) | |
174 | ||
175 | (defun object-sort-list (object slot predicate) | |
176 | "Sort the items in OBJECT's SLOT. | |
177 | Use PREDICATE is the same as for the `sort' function." | |
178 | (when (slot-boundp object slot) | |
179 | (when (listp (eieio-oref object slot)) | |
180 | (eieio-oset object slot (sort (eieio-oref object slot) predicate))))) | |
181 | ||
182 | ;;; DEBUG | |
183 | ;; | |
184 | ;; Dump out information about the current srecoder compiled templates. | |
185 | ;; | |
186 | (defun srecode-dump-templates (mode) | |
187 | "Dump a list of the current templates for MODE." | |
188 | (interactive "sMode: ") | |
189 | (require 'srecode/find) | |
190 | (let ((modesym (cond ((string= mode "") | |
191 | major-mode) | |
192 | ((not (string-match "-mode" mode)) | |
193 | (intern-soft (concat mode "-mode"))) | |
194 | (t | |
195 | (intern-soft mode))))) | |
196 | (srecode-load-tables-for-mode modesym) | |
197 | (let ((tmp (srecode-get-mode-table modesym)) | |
198 | ) | |
199 | (if (not tmp) | |
200 | (error "No table found for mode %S" modesym)) | |
201 | (with-output-to-temp-buffer "*SRECODE DUMP*" | |
202 | (srecode-dump tmp)) | |
203 | ))) | |
204 | ||
205 | (defmethod srecode-dump ((tab srecode-mode-table)) | |
206 | "Dump the contents of the SRecode mode table TAB." | |
207 | (princ "MODE TABLE FOR ") | |
208 | (princ (oref tab :major-mode)) | |
209 | (princ "\n--------------------------------------------\n\nNumber of tables: ") | |
210 | (let ((subtab (oref tab :tables))) | |
211 | (princ (length subtab)) | |
212 | (princ "\n\n") | |
213 | (while subtab | |
214 | (srecode-dump (car subtab)) | |
215 | (setq subtab (cdr subtab))) | |
216 | )) | |
217 | ||
218 | (defmethod srecode-dump ((tab srecode-template-table)) | |
219 | "Dump the contents of the SRecode template table TAB." | |
220 | (princ "Template Table for ") | |
221 | (princ (object-name-string tab)) | |
222 | (princ "\nPriority: ") | |
223 | (prin1 (oref tab :priority)) | |
224 | (when (oref tab :application) | |
225 | (princ "\nApplication: ") | |
226 | (princ (oref tab :application))) | |
227 | (princ "\n\nVariables:\n") | |
228 | (let ((vars (oref tab variables))) | |
229 | (while vars | |
230 | (princ (car (car vars))) | |
231 | (princ "\t") | |
232 | (if (< (length (car (car vars))) 9) | |
233 | (princ "\t")) | |
234 | (prin1 (cdr (car vars))) | |
235 | (princ "\n") | |
236 | (setq vars (cdr vars)))) | |
237 | (princ "\n\nTemplates:\n") | |
238 | (let ((temp (oref tab templates))) | |
239 | (while temp | |
240 | (srecode-dump (car temp)) | |
241 | (setq temp (cdr temp)))) | |
242 | ) | |
243 | ||
244 | ||
245 | (provide 'srecode/table) | |
246 | ||
247 | ;;; srecode/table.el ends here | |
248 |