Commit | Line | Data |
---|---|---|
55b522b2 | 1 | ;;; semantic/texi.el --- Semantic details for Texinfo files |
9573e58b | 2 | |
95df8112 | 3 | ;; Copyright (C) 2001-2005, 2007-2011 Free Software Foundation, Inc. |
9573e58b CY |
4 | |
5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
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 | ;; Parse Texinfo buffers using regular expressions. The core parser | |
25 | ;; engine is the function `semantic-texi-parse-headings'. The | |
26 | ;; parser plug-in is the function `semantic-texi-parse-region' that | |
27 | ;; overrides `semantic-parse-region'. | |
28 | ||
29 | (require 'semantic) | |
30 | (require 'semantic/format) | |
31 | (require 'texinfo) | |
32 | ||
33 | (eval-when-compile | |
34 | (require 'semantic/db) | |
35 | (require 'semantic/db-find) | |
36 | (require 'semantic/ctxt) | |
55b522b2 | 37 | (require 'semantic/find) |
abe6fcf1 | 38 | (require 'semantic/doc)) |
9573e58b | 39 | |
a4556861 | 40 | (defvar ede-minor-mode) |
55b522b2 | 41 | (declare-function lookup-words "ispell") |
a4556861 | 42 | (declare-function ede-current-project "ede") |
55b522b2 | 43 | |
9573e58b CY |
44 | (defvar semantic-texi-super-regex |
45 | "^@\\(top\\|chapter\\|\\(sub\\)*section\\|unnumbered\\(\\(sub\\)*sec\\)?\\|\ | |
46 | \\(chap\\|\\(sub\\)+\\|major\\)?heading\\|appendix\\(\\(sub\\)*sec\\)?\\|\ | |
47 | centerchap\\|def\\(var\\|un\\|fn\\|opt\\)x?\\)" | |
48 | "Regular expression used to find special sections in a Texinfo file.") | |
49 | ||
50 | (defvar semantic-texi-name-field-list | |
51 | '( ("defvar" . 1) | |
52 | ("defvarx" . 1) | |
53 | ("defun" . 1) | |
54 | ("defunx" . 1) | |
55 | ("defopt" . 1) | |
56 | ("deffn" . 2) | |
57 | ("deffnx" . 2) | |
58 | ) | |
59 | "List of definition commands, and the field position. | |
60 | The field position is the field number (based at 1) where the | |
61 | name of this section is.") | |
62 | ||
63 | ;;; Code: | |
64 | (defun semantic-texi-parse-region (&rest ignore) | |
65 | "Parse the current texinfo buffer for semantic tags. | |
66 | IGNORE any arguments, always parse the whole buffer. | |
67 | Each tag returned is of the form: | |
68 | (\"NAME\" section (:members CHILDREN)) | |
69 | or | |
70 | (\"NAME\" def) | |
71 | ||
72 | It is an override of 'parse-region and must be installed by the | |
73 | function `semantic-install-function-overrides'." | |
74 | (mapcar 'semantic-texi-expand-tag | |
75 | (semantic-texi-parse-headings))) | |
76 | ||
77 | (defun semantic-texi-parse-changes () | |
78 | "Parse changes in the current texinfo buffer." | |
79 | ;; NOTE: For now, just schedule a full reparse. | |
80 | ;; To be implemented later. | |
81 | (semantic-parse-tree-set-needs-rebuild)) | |
82 | ||
83 | (defun semantic-texi-expand-tag (tag) | |
84 | "Expand the texinfo tag TAG." | |
85 | (let ((chil (semantic-tag-components tag))) | |
86 | (if chil | |
87 | (semantic-tag-put-attribute | |
88 | tag :members (mapcar 'semantic-texi-expand-tag chil))) | |
89 | (car (semantic--tag-expand tag)))) | |
90 | ||
91 | (defun semantic-texi-parse-headings () | |
92 | "Parse the current texinfo buffer for all semantic tags now." | |
93 | (let ((pass1 nil)) | |
94 | ;; First search and snarf. | |
95 | (save-excursion | |
96 | (goto-char (point-min)) | |
97 | (let ((semantic--progress-reporter | |
98 | (make-progress-reporter | |
99 | (format "Parsing %s..." | |
100 | (file-name-nondirectory buffer-file-name)) | |
101 | (point-min) (point-max)))) | |
102 | (while (re-search-forward semantic-texi-super-regex nil t) | |
103 | (setq pass1 (cons (match-beginning 0) pass1)) | |
104 | (progress-reporter-update semantic--progress-reporter (point))) | |
105 | (progress-reporter-done semantic--progress-reporter))) | |
106 | (setq pass1 (nreverse pass1)) | |
107 | ;; Now, make some tags while creating a set of children. | |
108 | (car (semantic-texi-recursive-combobulate-list pass1 0)) | |
109 | )) | |
110 | ||
111 | (defsubst semantic-texi-new-section-tag (name members start end) | |
112 | "Create a semantic tag of class section. | |
113 | NAME is the name of this section. | |
114 | MEMBERS is a list of semantic tags representing the elements that make | |
115 | up this section. | |
116 | START and END define the location of data described by the tag." | |
117 | (append (semantic-tag name 'section :members members) | |
118 | (list start end))) | |
119 | ||
120 | (defsubst semantic-texi-new-def-tag (name start end) | |
121 | "Create a semantic tag of class def. | |
122 | NAME is the name of this definition. | |
123 | START and END define the location of data described by the tag." | |
124 | (append (semantic-tag name 'def) | |
125 | (list start end))) | |
126 | ||
127 | (defun semantic-texi-set-endpoint (metataglist pnt) | |
128 | "Set the end point of the first section tag in METATAGLIST to PNT. | |
129 | METATAGLIST is a list of tags in the intermediate tag format used by the | |
130 | texinfo parser. PNT is the new point to set." | |
131 | (let ((metatag nil)) | |
132 | (while (and metataglist | |
133 | (not (eq (semantic-tag-class (car metataglist)) 'section))) | |
134 | (setq metataglist (cdr metataglist))) | |
135 | (setq metatag (car metataglist)) | |
136 | (when metatag | |
137 | (setcar (nthcdr (1- (length metatag)) metatag) pnt) | |
138 | metatag))) | |
139 | ||
140 | (defun semantic-texi-recursive-combobulate-list (sectionlist level) | |
141 | "Rearrange SECTIONLIST to be a hierarchical tag list starting at LEVEL. | |
142 | Return the rearranged new list, with all remaining tags from | |
143 | SECTIONLIST starting at ELT 2. Sections not are not dealt with as soon as a | |
144 | tag with greater section value than LEVEL is found." | |
145 | (let ((newl nil) | |
146 | (oldl sectionlist) | |
147 | tag | |
148 | ) | |
149 | (save-excursion | |
150 | (catch 'level-jump | |
151 | (while oldl | |
152 | (goto-char (car oldl)) | |
153 | (if (looking-at "@\\(\\w+\\)") | |
154 | (let* ((word (match-string 1)) | |
155 | (levelmatch (assoc word texinfo-section-list)) | |
156 | text begin tmp | |
157 | ) | |
158 | ;; Set begin to the right location | |
159 | (setq begin (point)) | |
160 | ;; Get out of here if there if we made it that far. | |
161 | (if (and levelmatch (<= (car (cdr levelmatch)) level)) | |
162 | (progn | |
163 | (when newl | |
164 | (semantic-texi-set-endpoint newl begin)) | |
165 | (throw 'level-jump t))) | |
166 | ;; Recombobulate | |
167 | (if levelmatch | |
168 | (let ((end (match-end 1))) | |
169 | ;; Levels sometimes have a @node just in front. | |
170 | ;; That node statement should be included in the space | |
171 | ;; for this entry. | |
172 | (save-excursion | |
173 | (skip-chars-backward "\n \t") | |
174 | (beginning-of-line) | |
175 | (when (looking-at "@node\\>") | |
176 | (setq begin (point)))) | |
177 | ;; When there is a match, the descriptive text | |
178 | ;; consists of the rest of the line. | |
179 | (goto-char end) | |
180 | (skip-chars-forward " \t") | |
181 | (setq text (buffer-substring-no-properties | |
182 | (point) | |
183 | (progn (end-of-line) (point)))) | |
184 | ;; Next, recurse into the body to find the end. | |
185 | (setq tmp (semantic-texi-recursive-combobulate-list | |
186 | (cdr oldl) (car (cdr levelmatch)))) | |
187 | ;; Build a tag | |
188 | (setq tag (semantic-texi-new-section-tag | |
189 | text (car tmp) begin (point))) | |
190 | ;; Before appending the newtag, update the previous tag | |
191 | ;; if it is a section tag. | |
192 | (when newl | |
193 | (semantic-texi-set-endpoint newl begin)) | |
194 | ;; Append new tag to our master list. | |
195 | (setq newl (cons tag newl)) | |
196 | ;; continue | |
197 | (setq oldl (cdr tmp)) | |
198 | ) | |
199 | ;; No match means we have a def*, so get the name from | |
200 | ;; it based on the type of thingy we found. | |
201 | (setq levelmatch (assoc word semantic-texi-name-field-list) | |
202 | tmp (or (cdr levelmatch) 1)) | |
203 | (forward-sexp tmp) | |
204 | (skip-chars-forward " \t") | |
205 | (setq text (buffer-substring-no-properties | |
206 | (point) | |
207 | (progn (forward-sexp 1) (point)))) | |
208 | ;; Seek the end of this definition | |
209 | (goto-char begin) | |
210 | (semantic-texi-forward-deffn) | |
211 | (setq tag (semantic-texi-new-def-tag text begin (point)) | |
212 | newl (cons tag newl)) | |
213 | ;; continue | |
214 | (setq oldl (cdr oldl))) | |
215 | ) | |
216 | (error "Problem finding section in semantic/texi parser")) | |
217 | ;; (setq oldl (cdr oldl)) | |
218 | ) | |
219 | ;; When oldl runs out, force a new endpoint as point-max | |
220 | (when (not oldl) | |
221 | (semantic-texi-set-endpoint newl (point-max))) | |
222 | )) | |
223 | (cons (nreverse newl) oldl))) | |
224 | ||
225 | (defun semantic-texi-forward-deffn () | |
226 | "Move forward over one deffn type definition. | |
227 | The cursor should be on the @ sign." | |
228 | (when (looking-at "@\\(\\w+\\)") | |
229 | (let* ((type (match-string 1)) | |
230 | (seek (concat "^@end\\s-+" (regexp-quote type)))) | |
231 | (re-search-forward seek nil t)))) | |
232 | ||
233 | (define-mode-local-override semantic-tag-components | |
234 | texinfo-mode (tag) | |
235 | "Return components belonging to TAG." | |
236 | (semantic-tag-get-attribute tag :members)) | |
237 | ||
238 | \f | |
239 | ;;; Overrides: Context Parsing | |
240 | ;; | |
241 | ;; How to treat texi as a language? | |
242 | ;; | |
243 | (defvar semantic-texi-environment-regexp | |
244 | (if (string-match texinfo-environment-regexp "@menu") | |
245 | ;; Make sure our Emacs has menus in it. | |
246 | texinfo-environment-regexp | |
247 | ;; If no menus, then merge in the menu concept. | |
248 | (when (string-match "cartouche" texinfo-environment-regexp) | |
249 | (concat (substring texinfo-environment-regexp | |
250 | 0 (match-beginning 0)) | |
251 | "menu\\|" | |
252 | (substring texinfo-environment-regexp | |
253 | (match-beginning 0))))) | |
9bf6c65c | 254 | "Regular expression for matching texinfo environments. |
9573e58b CY |
255 | uses `texinfo-environment-regexp', but makes sure that it |
256 | can handle the @menu environment.") | |
257 | ||
258 | (define-mode-local-override semantic-up-context texinfo-mode () | |
259 | "Handle texinfo constructs which do not use parenthetical nesting." | |
260 | (let ((done nil)) | |
261 | (save-excursion | |
262 | (let ((parenthetical (semantic-up-context-default)) | |
263 | ) | |
264 | (when (not parenthetical) | |
265 | ;; We are in parenthises. Are they the types of parens | |
266 | ;; belonging to a texinfo construct? | |
267 | (forward-word -1) | |
268 | (when (looking-at "@\\w+{") | |
269 | (setq done (point)))))) | |
270 | ;; If we are not in a parenthetical node, then find a block instead. | |
271 | ;; Use the texinfo support to find block start/end constructs. | |
272 | (save-excursion | |
273 | (while (and (not done) | |
274 | (re-search-backward semantic-texi-environment-regexp nil t)) | |
275 | ;; For any hit, if we find an @end foo, then jump to the | |
276 | ;; matching @foo. If it is not an end, then we win! | |
277 | (if (not (looking-at "@end\\s-+\\(\\w+\\)")) | |
278 | (setq done (point)) | |
279 | ;; Skip over this block | |
280 | (let ((env (match-string 1))) | |
281 | (re-search-backward (concat "@" env)))) | |
282 | )) | |
283 | ;; All over, post what we find. | |
284 | (if done | |
285 | ;; We found something, so use it. | |
286 | (progn (goto-char done) | |
287 | nil) | |
288 | t))) | |
289 | ||
290 | (define-mode-local-override semantic-beginning-of-context texinfo-mode (&optional point) | |
291 | "Move to the beginning of the context surrounding POINT." | |
292 | (if (semantic-up-context point) | |
293 | ;; If we can't go up, we can't do this either. | |
294 | t | |
295 | ;; We moved, so now we need to skip into whatever this thing is. | |
296 | (forward-word 1) ;; skip the command | |
297 | (if (looking-at "\\s-*{") | |
298 | ;; In a short command. Go in. | |
299 | (down-list 1) | |
300 | ;; An environment. Go to the next line. | |
301 | (end-of-line) | |
302 | (forward-char 1)) | |
303 | nil)) | |
304 | ||
305 | (define-mode-local-override semantic-ctxt-current-class-list | |
306 | texinfo-mode (&optional point) | |
307 | "Determine the class of tags that can be used at POINT. | |
308 | For texinfo, there two possibilities returned. | |
309 | 1) 'function - for a call to a texinfo function | |
310 | 2) 'word - indicates an english word. | |
311 | It would be nice to know function arguments too, but not today." | |
312 | (let ((sym (semantic-ctxt-current-symbol))) | |
313 | (if (and sym (= (aref (car sym) 0) ?@)) | |
314 | '(function) | |
315 | '(word)))) | |
316 | ||
317 | \f | |
318 | ;;; Overrides : Formatting | |
319 | ;; | |
320 | ;; Various override to better format texi tags. | |
321 | ;; | |
322 | ||
323 | (define-mode-local-override semantic-format-tag-abbreviate | |
324 | texinfo-mode (tag &optional parent color) | |
325 | "Texinfo tags abbreviation." | |
326 | (let ((class (semantic-tag-class tag)) | |
327 | (name (semantic-format-tag-name tag parent color)) | |
328 | ) | |
329 | (cond ((eq class 'function) | |
330 | (concat name "{ }")) | |
331 | (t (semantic-format-tag-abbreviate-default tag parent color))) | |
332 | )) | |
333 | ||
334 | (define-mode-local-override semantic-format-tag-prototype | |
335 | texinfo-mode (tag &optional parent color) | |
336 | "Texinfo tags abbreviation." | |
337 | (semantic-format-tag-abbreviate tag parent color)) | |
338 | ||
339 | \f | |
340 | ;;; Texi Unique Features | |
341 | ;; | |
342 | (defun semantic-tag-texi-section-text-bounds (tag) | |
343 | "Get the bounds to the text of TAG. | |
344 | The text bounds is the text belonging to this node excluding | |
345 | the text of any child nodes, but including any defuns." | |
346 | (let ((memb (semantic-tag-components tag))) | |
347 | ;; Members.. if one is a section, check it out. | |
348 | (while (and memb (not (semantic-tag-of-class-p (car memb) 'section))) | |
349 | (setq memb (cdr memb))) | |
350 | ;; No members? ... then a simple problem! | |
351 | (if (not memb) | |
352 | (semantic-tag-bounds tag) | |
353 | ;; Our end is their beginning... | |
354 | (list (semantic-tag-start tag) (semantic-tag-start (car memb)))))) | |
355 | ||
356 | (defun semantic-texi-current-environment (&optional point) | |
357 | "Return as a string the type of the current environment. | |
358 | Optional argument POINT is where to look for the environment." | |
359 | (save-excursion | |
360 | (when point (goto-char (point))) | |
361 | (while (and (or (not (looking-at semantic-texi-environment-regexp)) | |
362 | (looking-at "@end")) | |
363 | (not (semantic-up-context))) | |
364 | ) | |
365 | (when (looking-at semantic-texi-environment-regexp) | |
366 | (match-string 1)))) | |
367 | ||
368 | \f | |
369 | ;;; Analyzer | |
370 | ;; | |
371 | (eval-when-compile | |
372 | (require 'semantic/analyze)) | |
373 | ||
374 | (define-mode-local-override semantic-analyze-current-context | |
375 | texinfo-mode (point) | |
376 | "Analysis context makes no sense for texinfo. Return nil." | |
377 | (let* ((prefixandbounds (semantic-ctxt-current-symbol-and-bounds (point))) | |
378 | (prefix (car prefixandbounds)) | |
379 | (bounds (nth 2 prefixandbounds)) | |
380 | (prefixclass (semantic-ctxt-current-class-list)) | |
381 | ) | |
382 | (when prefix | |
55b522b2 | 383 | (require 'semantic/analyze) |
9573e58b CY |
384 | (semantic-analyze-context |
385 | "Context-for-texinfo" | |
386 | :buffer (current-buffer) | |
387 | :scope nil | |
388 | :bounds bounds | |
389 | :prefix prefix | |
390 | :prefixtypes nil | |
391 | :prefixclass prefixclass) | |
392 | ) | |
393 | )) | |
394 | ||
395 | (defvar semantic-texi-command-completion-list | |
396 | (append (mapcar (lambda (a) (car a)) texinfo-section-list) | |
397 | (condition-case nil | |
398 | texinfo-environments | |
399 | (error | |
400 | ;; XEmacs doesn't use the above. Split up its regexp | |
401 | (split-string texinfo-environment-regexp "\\\\|\\|\\^@\\\\(\\|\\\\)") | |
402 | )) | |
403 | ;; Is there a better list somewhere? Here are few | |
404 | ;; of the top of my head. | |
405 | "anchor" "asis" | |
406 | "bullet" | |
407 | "code" "copyright" | |
408 | "defun" "deffn" "defoption" "defvar" "dfn" | |
409 | "emph" "end" | |
410 | "ifinfo" "iftex" "inforef" "item" "itemx" | |
411 | "kdb" | |
412 | "node" | |
413 | "ref" | |
414 | "set" "setfilename" "settitle" | |
415 | "value" "var" | |
416 | "xref" | |
417 | ) | |
418 | "List of commands that we might bother completing.") | |
419 | ||
420 | (define-mode-local-override semantic-analyze-possible-completions | |
421 | texinfo-mode (context) | |
422 | "List smart completions at point. | |
423 | Since texinfo is not a programming language the default version is not | |
f6b1b0a8 | 424 | useful. Instead, look at the current symbol. If it is a command |
9573e58b CY |
425 | do primitive texinfo built ins. If not, use ispell to lookup words |
426 | that start with that symbol." | |
427 | (let ((prefix (car (oref context :prefix))) | |
428 | ) | |
429 | (cond ((member 'function (oref context :prefixclass)) | |
430 | ;; Do completion for texinfo commands | |
431 | (let* ((cmd (substring prefix 1)) | |
432 | (lst (all-completions | |
433 | cmd semantic-texi-command-completion-list))) | |
434 | (mapcar (lambda (f) (semantic-tag (concat "@" f) 'function)) | |
435 | lst)) | |
436 | ) | |
437 | ((member 'word (oref context :prefixclass)) | |
438 | ;; Do completion for words via ispell. | |
439 | (require 'ispell) | |
440 | (let ((word-list (lookup-words prefix))) | |
441 | (mapcar (lambda (f) (semantic-tag f 'word)) word-list)) | |
442 | ) | |
443 | (t nil)) | |
444 | )) | |
445 | ||
446 | \f | |
447 | ;;; Parser Setup | |
448 | ;; | |
07a79ce4 | 449 | ;; In semantic/imenu.el, not part of Emacs. |
f3628edd GM |
450 | (defvar semantic-imenu-expandable-tag-classes) |
451 | (defvar semantic-imenu-bucketize-file) | |
452 | (defvar semantic-imenu-bucketize-type-members) | |
453 | ||
9573e58b CY |
454 | (defun semantic-default-texi-setup () |
455 | "Set up a buffer for parsing of Texinfo files." | |
456 | ;; This will use our parser. | |
457 | (semantic-install-function-overrides | |
458 | '((parse-region . semantic-texi-parse-region) | |
459 | (parse-changes . semantic-texi-parse-changes))) | |
460 | (setq semantic-parser-name "TEXI" | |
461 | ;; Setup a dummy parser table to enable parsing! | |
462 | semantic--parse-table t | |
463 | imenu-create-index-function 'semantic-create-imenu-index | |
464 | semantic-command-separation-character "@" | |
465 | semantic-type-relation-separator-character '(":") | |
466 | semantic-symbol->name-assoc-list '((section . "Section") | |
467 | (def . "Definition") | |
468 | ) | |
469 | semantic-imenu-expandable-tag-classes '(section) | |
470 | semantic-imenu-bucketize-file nil | |
471 | semantic-imenu-bucketize-type-members nil | |
472 | senator-step-at-start-end-tag-classes '(section) | |
473 | semantic-stickyfunc-sticky-classes '(section) | |
474 | ) | |
996bc9bf | 475 | ;; (local-set-key [(f9)] 'semantic-texi-update-doc-from-texi) |
9573e58b CY |
476 | ) |
477 | ||
478 | (add-hook 'texinfo-mode-hook 'semantic-default-texi-setup) | |
479 | ||
480 | \f | |
481 | ;;; Special features of Texinfo tag streams | |
482 | ;; | |
483 | ;; This section provides specialized access into texinfo files. | |
484 | ;; Because texinfo files often directly refer to functions and programs | |
485 | ;; it is useful to access the texinfo file from the C code for document | |
486 | ;; maintainance. | |
487 | (defun semantic-texi-associated-files (&optional buffer) | |
488 | "Find texinfo files associated with BUFFER." | |
489 | (save-excursion | |
490 | (if buffer (set-buffer buffer)) | |
491 | (cond ((and (fboundp 'ede-documentation-files) | |
492 | ede-minor-mode (ede-current-project)) | |
493 | ;; When EDE is active, ask it. | |
494 | (ede-documentation-files) | |
495 | ) | |
55b522b2 | 496 | ((and (featurep 'semantic/db) (semanticdb-minor-mode-p)) |
9573e58b CY |
497 | ;; See what texinfo files we have loaded in the database |
498 | (let ((tabs (semanticdb-get-database-tables | |
499 | semanticdb-current-database)) | |
500 | (r nil)) | |
501 | (while tabs | |
502 | (if (eq (oref (car tabs) major-mode) 'texinfo-mode) | |
503 | (setq r (cons (oref (car tabs) file) r))) | |
504 | (setq tabs (cdr tabs))) | |
505 | r)) | |
506 | (t | |
507 | (directory-files default-directory nil "\\.texi$")) | |
508 | ))) | |
509 | ||
510 | ;; Turns out this might not be useful. | |
511 | ;; Delete later if that is true. | |
512 | (defun semantic-texi-find-documentation (name &optional type) | |
513 | "Find the function or variable NAME of TYPE in the texinfo source. | |
514 | NAME is a string representing some functional symbol. | |
515 | TYPE is a string, such as \"variable\" or \"Command\" used to find | |
516 | the correct definition in case NAME qualifies as several things. | |
517 | When this function exists, POINT is at the definition. | |
518 | If the doc was not found, an error is thrown. | |
519 | Note: TYPE not yet implemented." | |
520 | (let ((f (semantic-texi-associated-files)) | |
521 | stream match) | |
522 | (while (and f (not match)) | |
523 | (unless stream | |
524 | (with-current-buffer (find-file-noselect (car f)) | |
525 | (setq stream (semantic-fetch-tags)))) | |
526 | (setq match (semantic-find-first-tag-by-name name stream)) | |
527 | (when match | |
528 | (set-buffer (semantic-tag-buffer match)) | |
529 | (goto-char (semantic-tag-start match))) | |
530 | (setq f (cdr f))))) | |
531 | ||
996bc9bf CY |
532 | ;; (defun semantic-texi-update-doc-from-texi (&optional tag) |
533 | ;; "Update the documentation in the texinfo deffn class tag TAG. | |
534 | ;; The current buffer must be a texinfo file containing TAG. | |
535 | ;; If TAG is nil, determine a tag based on the current position." | |
536 | ;; (interactive) | |
537 | ;; (unless (or (featurep 'semantic/db) | |
538 | ;; (require 'semantic/db-mode) | |
539 | ;; (semanticdb-minor-mode-p)) | |
540 | ;; (error "Texinfo updating only works when `semanticdb' is being used")) | |
541 | ;; (semantic-fetch-tags) | |
542 | ;; (unless tag | |
543 | ;; (beginning-of-line) | |
544 | ;; (setq tag (semantic-current-tag))) | |
545 | ;; (unless (semantic-tag-of-class-p tag 'def) | |
546 | ;; (error "Only deffns (or defun or defvar) can be updated")) | |
547 | ;; (let* ((name (semantic-tag-name tag)) | |
548 | ;; (tags (semanticdb-strip-find-results | |
549 | ;; (semanticdb-with-match-any-mode | |
550 | ;; (semanticdb-brute-deep-find-tags-by-name name)) | |
551 | ;; 'name)) | |
552 | ;; (docstring nil) | |
553 | ;; (docstringproto nil) | |
554 | ;; (docstringvar nil) | |
555 | ;; (doctag nil) | |
556 | ;; (doctagproto nil) | |
557 | ;; (doctagvar nil) | |
558 | ;; ) | |
559 | ;; (save-excursion | |
560 | ;; (while (and tags (not docstring)) | |
561 | ;; (let ((sourcetag (car tags))) | |
562 | ;; ;; There could be more than one! Come up with a better | |
563 | ;; ;; solution someday. | |
564 | ;; (when (semantic-tag-buffer sourcetag) | |
565 | ;; (set-buffer (semantic-tag-buffer sourcetag)) | |
566 | ;; (unless (eq major-mode 'texinfo-mode) | |
567 | ;; (cond ((semantic-tag-get-attribute sourcetag :prototype-flag) | |
568 | ;; ;; If we found a match with doc that is a prototype, then store | |
569 | ;; ;; that, but don't exit till we find the real deal. | |
570 | ;; (setq docstringproto (semantic-documentation-for-tag sourcetag) | |
571 | ;; doctagproto sourcetag)) | |
572 | ;; ((eq (semantic-tag-class sourcetag) 'variable) | |
573 | ;; (setq docstringvar (semantic-documentation-for-tag sourcetag) | |
574 | ;; doctagvar sourcetag)) | |
575 | ;; ((semantic-tag-get-attribute sourcetag :override-function-flag) | |
576 | ;; nil) | |
577 | ;; (t | |
578 | ;; (setq docstring (semantic-documentation-for-tag sourcetag)))) | |
579 | ;; (setq doctag (if docstring sourcetag nil)))) | |
580 | ;; (setq tags (cdr tags))))) | |
581 | ;; ;; If we found a prototype of the function that has some doc, but not the | |
c7015153 | 582 | ;; ;; actual function, let's make due with that. |
996bc9bf CY |
583 | ;; (if (not docstring) |
584 | ;; (cond ((stringp docstringvar) | |
585 | ;; (setq docstring docstringvar | |
586 | ;; doctag doctagvar)) | |
587 | ;; ((stringp docstringproto) | |
588 | ;; (setq docstring docstringproto | |
589 | ;; doctag doctagproto)))) | |
590 | ;; ;; Test for doc string | |
591 | ;; (unless docstring | |
592 | ;; (error "Could not find documentation for %s" (semantic-tag-name tag))) | |
dd9af436 CY |
593 | ;; |
594 | ;; (require 'srecode) | |
07a79ce4 | 595 | ;; (require 'srecode/texi) |
dd9af436 | 596 | ;; |
996bc9bf CY |
597 | ;; ;; If we have a string, do the replacement. |
598 | ;; (delete-region (semantic-tag-start tag) | |
599 | ;; (semantic-tag-end tag)) | |
4c36be58 | 600 | ;; ;; Use useful functions from the document library. |
dd9af436 CY |
601 | ;; (srecode-texi-insert-tag-as-doc doctag) |
602 | ;; ;(semantic-insert-foreign-tag doctag) | |
996bc9bf CY |
603 | ;; )) |
604 | ||
605 | ;; (defun semantic-texi-update-doc-from-source (&optional tag) | |
606 | ;; "Update the documentation for the source TAG. | |
607 | ;; The current buffer must be a non-texinfo source file containing TAG. | |
608 | ;; If TAG is nil, determine the tag based on the current position. | |
609 | ;; The current buffer must include TAG." | |
610 | ;; (interactive) | |
611 | ;; (when (eq major-mode 'texinfo-mode) | |
612 | ;; (error "Not a source file")) | |
613 | ;; (semantic-fetch-tags) | |
614 | ;; (unless tag | |
615 | ;; (setq tag (semantic-current-tag))) | |
616 | ;; (unless (semantic-documentation-for-tag tag) | |
617 | ;; (error "Cannot find interesting documentation to use for %s" | |
618 | ;; (semantic-tag-name tag))) | |
619 | ;; (let* ((name (semantic-tag-name tag)) | |
620 | ;; (texi (semantic-texi-associated-files)) | |
621 | ;; (doctag nil) | |
622 | ;; (docbuff nil)) | |
623 | ;; (while (and texi (not doctag)) | |
624 | ;; (set-buffer (find-file-noselect (car texi))) | |
625 | ;; (setq doctag (car (semantic-deep-find-tags-by-name | |
626 | ;; name (semantic-fetch-tags))) | |
627 | ;; docbuff (if doctag (current-buffer) nil)) | |
628 | ;; (setq texi (cdr texi))) | |
629 | ;; (unless doctag | |
630 | ;; (error "Tag %s is not yet documented. Use the `document' command" | |
631 | ;; name)) | |
632 | ;; ;; Ok, we should have everything we need. Do the deed. | |
633 | ;; (if (get-buffer-window docbuff) | |
634 | ;; (set-buffer docbuff) | |
635 | ;; (switch-to-buffer docbuff)) | |
636 | ;; (goto-char (semantic-tag-start doctag)) | |
637 | ;; (delete-region (semantic-tag-start doctag) | |
638 | ;; (semantic-tag-end doctag)) | |
639 | ;; ;; Use useful functions from the document library. | |
640 | ;; (require 'document) | |
641 | ;; (document-insert-texinfo tag (semantic-tag-buffer tag)) | |
642 | ;; )) | |
643 | ||
644 | ;; (defun semantic-texi-update-doc (&optional tag) | |
645 | ;; "Update the documentation for TAG. | |
646 | ;; If the current buffer is a texinfo file, then find the source doc, and | |
647 | ;; update it. If the current buffer is a source file, then get the | |
648 | ;; documentation for this item, find the existing doc in the associated | |
649 | ;; manual, and update that." | |
650 | ;; (interactive) | |
651 | ;; (cond ;;((eq major-mode 'texinfo-mode) | |
652 | ;; ;; (semantic-texi-update-doc-from-texi tag)) | |
653 | ;; (t | |
654 | ;; (semantic-texi-update-doc-from-source tag)))) | |
9573e58b CY |
655 | |
656 | (defun semantic-texi-goto-source (&optional tag) | |
657 | "Jump to the source for the definition in the texinfo file TAG. | |
658 | If TAG is nil, it is derived from the deffn under POINT." | |
659 | (interactive) | |
55b522b2 | 660 | (unless (or (featurep 'semantic/db) (semanticdb-minor-mode-p)) |
9573e58b CY |
661 | (error "Texinfo updating only works when `semanticdb' is being used")) |
662 | (semantic-fetch-tags) | |
663 | (unless tag | |
664 | (beginning-of-line) | |
665 | (setq tag (semantic-current-tag))) | |
666 | (unless (semantic-tag-of-class-p tag 'def) | |
667 | (error "Only deffns (or defun or defvar) can be updated")) | |
668 | (let* ((name (semantic-tag-name tag)) | |
669 | (tags (semanticdb-fast-strip-find-results | |
670 | (semanticdb-with-match-any-mode | |
671 | (semanticdb-brute-deep-find-tags-by-name name nil 'name)) | |
672 | )) | |
673 | ||
674 | (done nil) | |
675 | ) | |
676 | (save-excursion | |
677 | (while (and tags (not done)) | |
678 | (set-buffer (semantic-tag-buffer (car tags))) | |
679 | (unless (eq major-mode 'texinfo-mode) | |
680 | (switch-to-buffer (semantic-tag-buffer (car tags))) | |
681 | (goto-char (semantic-tag-start (car tags))) | |
682 | (setq done t)) | |
683 | (setq tags (cdr tags))) | |
684 | (if (not done) | |
685 | (error "Could not find tag for %s" (semantic-tag-name tag))) | |
686 | ))) | |
687 | ||
688 | (provide 'semantic/texi) | |
689 | ||
55b522b2 | 690 | ;;; semantic/texi.el ends here |