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