aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2009-08-29 20:12:41 +0000
committerChong Yidong2009-08-29 20:12:41 +0000
commita4bdf7157468652d2d7730196c142ed234e635ac (patch)
treef822be8eef906e1b6e19ff6975231a5af9f0f96d
parenta6de3d1a7347048f6ef74160583203fbaf323b6b (diff)
downloademacs-a4bdf7157468652d2d7730196c142ed234e635ac.tar.gz
emacs-a4bdf7157468652d2d7730196c142ed234e635ac.zip
cedet/semantic/symref.el, cedet/semantic/symref/cscope.el.
cedet/semantic/symref/global.el, cedet/semantic/symref/idutils.el, cedet/semantic/symref/list.el: New files. cedet/semantic/db-ebrowse.el: Use mapc instead of mapcar.
-rw-r--r--lisp/cedet/semantic/db-ebrowse.el10
-rw-r--r--lisp/cedet/semantic/symref.el485
-rw-r--r--lisp/cedet/semantic/symref/cscope.el84
-rw-r--r--lisp/cedet/semantic/symref/global.el69
-rw-r--r--lisp/cedet/semantic/symref/idutils.el71
-rw-r--r--lisp/cedet/semantic/symref/list.el328
6 files changed, 1042 insertions, 5 deletions
diff --git a/lisp/cedet/semantic/db-ebrowse.el b/lisp/cedet/semantic/db-ebrowse.el
index 3302afd83da..b38e6b0a1ca 100644
--- a/lisp/cedet/semantic/db-ebrowse.el
+++ b/lisp/cedet/semantic/db-ebrowse.el
@@ -115,11 +115,11 @@ is specified by `semanticdb-default-save-directory'."
115 ;; to get the file names. 115 ;; to get the file names.
116 116
117 117
118 (mapcar (lambda (f) 118 (mapc (lambda (f)
119 (when (semanticdb-ebrowse-C-file-p f) 119 (when (semanticdb-ebrowse-C-file-p f)
120 (insert f) 120 (insert f)
121 (insert "\n"))) 121 (insert "\n")))
122 files) 122 files)
123 ;; Cleanup the ebrowse output buffer. 123 ;; Cleanup the ebrowse output buffer.
124 (save-excursion 124 (save-excursion
125 (set-buffer (get-buffer-create "*EBROWSE OUTPUT*")) 125 (set-buffer (get-buffer-create "*EBROWSE OUTPUT*"))
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
new file mode 100644
index 00000000000..acebac032d5
--- /dev/null
+++ b/lisp/cedet/semantic/symref.el
@@ -0,0 +1,485 @@
1;;; semantic/symref.el --- Symbol Reference API
2
3;;; Copyright (C) 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 Symbol Reference API.
25;;
26;; Semantic's native parsing tools do not handle symbol references.
27;; Tracking such information is a task that requires a huge amount of
28;; space and processing not apropriate for an Emacs Lisp program.
29;;
30;; Many desired tools used in refactoring, however, need to have
31;; such references available to them. This API aims to provide a
32;; range of functions that can be used to identify references. The
33;; API is backed by an OO system that is used to allow multiple
34;; external tools to provide the information.
35;;
36;; The default implementation uses a find/grep combination to do a
37;; search. This works ok in small projects. For larger projects, it
38;; is important to find an alternate tool to use as a back-end to
39;; symref.
40;;
41;; See the command: `semantic-symref' for an example app using this api.
42;;
43;; TO USE THIS TOOL
44;;
45;; The following functions can be used to find different kinds of
46;; references.
47;;
48;; `semantic-symref-find-references-by-name'
49;; `semantic-symref-find-file-references-by-name'
50;; `semantic-symref-find-text'
51;;
52;; All the search routines return a class of type
53;; `semantic-symref-result'. You can reference the various slots, but
54;; you will need the following methods to get extended information.
55;;
56;; `semantic-symref-result-get-files'
57;; `semantic-symref-result-get-tags'
58;;
59;; ADD A NEW EXTERNAL TOOL
60;;
61;; To support a new external tool, sublcass `semantic-symref-tool-baseclass'
62;; and implement the methods. The baseclass provides support for
63;; managing external processes that produce parsable output.
64;;
65;; Your tool should then create an instance of `semantic-symref-result'.
66
67(require 'semantic/fw)
68(require 'ede)
69(eval-when-compile (require 'data-debug)
70 (require 'eieio-datadebug))
71
72;;; Code:
73(defvar semantic-symref-tool 'detect
74 "*The active symbol reference tool name.
75The tool symbol can be 'detect, or a symbol that is the name of
76a tool that can be used for symbol referencing.")
77(make-variable-buffer-local 'semantic-symref-tool)
78
79;;; TOOL SETUP
80;;
81(defvar semantic-symref-tool-alist
82 '( ( (lambda (rootdir) (file-exists-p (expand-file-name "GPATH" rootdir))) .
83 global)
84 ( (lambda (rootdir) (file-exists-p (expand-file-name "ID" rootdir))) .
85 idutils)
86 ( (lambda (rootdir) (file-exists-p (expand-file-name "cscope.out" rootdir))) .
87 cscope )
88 )
89 "Alist of tools usable by `semantic-symref'.
90Each entry is of the form:
91 ( PREDICATE . KEY )
92Where PREDICATE is a function that takes a directory name for the
93root of a project, and returns non-nil if the tool represented by KEY
94is supported.
95
96If no tools are supported, then 'grep is assumed.")
97
98(defun semantic-symref-detect-symref-tool ()
99 "Detect the symref tool to use for the current buffer."
100 (if (not (eq semantic-symref-tool 'detect))
101 semantic-symref-tool
102 ;; We are to perform a detection for the right tool to use.
103 (let* ((rootproj (when (and (featurep 'ede) ede-minor-mode)
104 (ede-toplevel)))
105 (rootdir (if rootproj
106 (ede-project-root-directory rootproj)
107 default-directory))
108 (tools semantic-symref-tool-alist))
109 (while (and tools (eq semantic-symref-tool 'detect))
110 (when (funcall (car (car tools)) rootdir)
111 (setq semantic-symref-tool (cdr (car tools))))
112 (setq tools (cdr tools)))
113
114 (when (eq semantic-symref-tool 'detect)
115 (setq semantic-symref-tool 'grep))
116
117 semantic-symref-tool)))
118
119(defun semantic-symref-instantiate (&rest args)
120 "Instantiate a new symref search object.
121ARGS are the initialization arguments to pass to the created class."
122 (let* ((srt (symbol-name (semantic-symref-detect-symref-tool)))
123 (class (intern-soft (concat "semantic-symref-tool-" srt)))
124 (inst nil)
125 )
126 (when (not (class-p class))
127 (error "Unknown symref tool %s" semantic-symref-tool))
128 (setq inst (apply 'make-instance class args))
129 inst))
130
131(defvar semantic-symref-last-result nil
132 "The last calculated symref result.")
133
134(defun semantic-symref-data-debug-last-result ()
135 "Run the last symref data result in Data Debug."
136 (interactive)
137 (if semantic-symref-last-result
138 (progn
139 (data-debug-new-buffer "*Symbol Reference ADEBUG*")
140 (data-debug-insert-object-slots semantic-symref-last-result "]"))
141 (message "Empty results.")))
142
143;;; EXTERNAL API
144;;
145
146(defun semantic-symref-find-references-by-name (name &optional scope tool-return)
147 "Find a list of references to NAME in the current project.
148Optional SCOPE specifies which file set to search. Defaults to 'project.
149Refers to `semantic-symref-tool', to determine the reference tool to use
150for the current buffer.
151Returns an object of class `semantic-symref-result'.
152TOOL-RETURN is an optional symbol, which will be assigned the tool used
153to perform the search. This was added for use by a test harness."
154 (interactive "sName: ")
155 (let* ((inst (semantic-symref-instantiate
156 :searchfor name
157 :searchtype 'symbol
158 :searchscope (or scope 'project)
159 :resulttype 'line))
160 (result (semantic-symref-get-result inst)))
161 (when tool-return
162 (set tool-return inst))
163 (prog1
164 (setq semantic-symref-last-result result)
165 (when (interactive-p)
166 (semantic-symref-data-debug-last-result))))
167 )
168
169(defun semantic-symref-find-tags-by-name (name &optional scope)
170 "Find a list of references to NAME in the current project.
171Optional SCOPE specifies which file set to search. Defaults to 'project.
172Refers to `semantic-symref-tool', to determine the reference tool to use
173for the current buffer.
174Returns an object of class `semantic-symref-result'."
175 (interactive "sName: ")
176 (let* ((inst (semantic-symref-instantiate
177 :searchfor name
178 :searchtype 'tagname
179 :searchscope (or scope 'project)
180 :resulttype 'line))
181 (result (semantic-symref-get-result inst)))
182 (prog1
183 (setq semantic-symref-last-result result)
184 (when (interactive-p)
185 (semantic-symref-data-debug-last-result))))
186 )
187
188(defun semantic-symref-find-tags-by-regexp (name &optional scope)
189 "Find a list of references to NAME in the current project.
190Optional SCOPE specifies which file set to search. Defaults to 'project.
191Refers to `semantic-symref-tool', to determine the reference tool to use
192for the current buffer.
193Returns an object of class `semantic-symref-result'."
194 (interactive "sName: ")
195 (let* ((inst (semantic-symref-instantiate
196 :searchfor name
197 :searchtype 'tagregexp
198 :searchscope (or scope 'project)
199 :resulttype 'line))
200 (result (semantic-symref-get-result inst)))
201 (prog1
202 (setq semantic-symref-last-result result)
203 (when (interactive-p)
204 (semantic-symref-data-debug-last-result))))
205 )
206
207(defun semantic-symref-find-tags-by-completion (name &optional scope)
208 "Find a list of references to NAME in the current project.
209Optional SCOPE specifies which file set to search. Defaults to 'project.
210Refers to `semantic-symref-tool', to determine the reference tool to use
211for the current buffer.
212Returns an object of class `semantic-symref-result'."
213 (interactive "sName: ")
214 (let* ((inst (semantic-symref-instantiate
215 :searchfor name
216 :searchtype 'tagcompletions
217 :searchscope (or scope 'project)
218 :resulttype 'line))
219 (result (semantic-symref-get-result inst)))
220 (prog1
221 (setq semantic-symref-last-result result)
222 (when (interactive-p)
223 (semantic-symref-data-debug-last-result))))
224 )
225
226(defun semantic-symref-find-file-references-by-name (name &optional scope)
227 "Find a list of references to NAME in the current project.
228Optional SCOPE specifies which file set to search. Defaults to 'project.
229Refers to `semantic-symref-tool', to determine the reference tool to use
230for the current buffer.
231Returns an object of class `semantic-symref-result'."
232 (interactive "sName: ")
233 (let* ((inst (semantic-symref-instantiate
234 :searchfor name
235 :searchtype 'regexp
236 :searchscope (or scope 'project)
237 :resulttype 'file))
238 (result (semantic-symref-get-result inst)))
239 (prog1
240 (setq semantic-symref-last-result result)
241 (when (interactive-p)
242 (semantic-symref-data-debug-last-result))))
243 )
244
245(defun semantic-symref-find-text (text &optional scope)
246 "Find a list of occurances of TEXT in the current project.
247TEXT is a regexp formatted for use with egrep.
248Optional SCOPE specifies which file set to search. Defaults to 'project.
249Refers to `semantic-symref-tool', to determine the reference tool to use
250for the current buffer.
251Returns an object of class `semantic-symref-result'."
252 (interactive "sEgrep style Regexp: ")
253 (let* ((inst (semantic-symref-instantiate
254 :searchfor text
255 :searchtype 'regexp
256 :searchscope (or scope 'project)
257 :resulttype 'line))
258 (result (semantic-symref-get-result inst)))
259 (prog1
260 (setq semantic-symref-last-result result)
261 (when (interactive-p)
262 (semantic-symref-data-debug-last-result))))
263 )
264
265;;; RESULTS
266;;
267;; The results class and methods provide features for accessing hits.
268(defclass semantic-symref-result ()
269 ((created-by :initarg :created-by
270 :type semantic-symref-tool-baseclass
271 :documentation
272 "Back-pointer to the symref tool creating these results.")
273 (hit-files :initarg :hit-files
274 :type list
275 :documentation
276 "The list of files hit.")
277 (hit-text :initarg :hit-text
278 :type list
279 :documentation
280 "If the result doesn't provide full lines, then fill in hit-text.
281GNU Global does completion search this way.")
282 (hit-lines :initarg :hit-lines
283 :type list
284 :documentation
285 "The list of line hits.
286Each element is a cons cell of the form (LINE . FILENAME).")
287 (hit-tags :initarg :hit-tags
288 :type list
289 :documentation
290 "The list of tags with hits in them.
291Use the `semantic-symref-hit-tags' method to get this list.")
292 )
293 "The results from a symbol reference search.")
294
295(defmethod semantic-symref-result-get-files ((result semantic-symref-result))
296 "Get the list of files from the symref result RESULT."
297 (if (slot-boundp result :hit-files)
298 (oref result hit-files)
299 (let* ((lines (oref result :hit-lines))
300 (files (mapcar (lambda (a) (cdr a)) lines))
301 (ans nil))
302 (setq ans (list (car files))
303 files (cdr files))
304 (dolist (F files)
305 ;; This algorithm for uniqing the file list depends on the
306 ;; tool in question providing all the hits in the same file
307 ;; grouped together.
308 (when (not (string= F (car ans)))
309 (setq ans (cons F ans))))
310 (oset result hit-files (nreverse ans))
311 )
312 ))
313
314(defmethod semantic-symref-result-get-tags ((result semantic-symref-result)
315 &optional open-buffers)
316 "Get the list of tags from the symref result RESULT.
317Optional OPEN-BUFFERS indicates that the buffers that the hits are
318in should remain open after scanning.
319Note: This can be quite slow if most of the hits are not in buffers
320already."
321 (if (and (slot-boundp result :hit-tags) (oref result hit-tags))
322 (oref result hit-tags)
323 ;; Calculate the tags.
324 (let ((lines (oref result :hit-lines))
325 (txt (oref (oref result :created-by) :searchfor))
326 (searchtype (oref (oref result :created-by) :searchtype))
327 (ans nil)
328 (out nil)
329 (buffs-to-kill nil))
330 (save-excursion
331 (setq
332 ans
333 (mapcar
334 (lambda (hit)
335 (let* ((line (car hit))
336 (file (cdr hit))
337 (buff (get-file-buffer file))
338 (tag nil)
339 )
340 (cond
341 ;; We have a buffer already. Check it out.
342 (buff
343 (set-buffer buff))
344
345 ;; We have a table, but it needs a refresh.
346 ;; This means we should load in that buffer.
347 (t
348 (let ((kbuff
349 (if open-buffers
350 ;; Even if we keep the buffers open, don't
351 ;; let EDE ask lots of questions.
352 (let ((ede-auto-add-method 'never))
353 (find-file-noselect file t))
354 ;; When not keeping the buffers open, then
355 ;; don't setup all the fancy froo-froo features
356 ;; either.
357 (semantic-find-file-noselect file t))))
358 (set-buffer kbuff)
359 (setq buffs-to-kill (cons kbuff buffs-to-kill))
360 (semantic-fetch-tags)
361 ))
362 )
363
364 ;; Too much baggage in goto-line
365 ;; (goto-line line)
366 (goto-char (point-min))
367 (forward-line (1- line))
368
369 ;; Search forward for the matching text
370 (re-search-forward (regexp-quote txt)
371 (point-at-eol)
372 t)
373
374 (setq tag (semantic-current-tag))
375
376 ;; If we are searching for a tag, but bound the tag we are looking
377 ;; for, see if it resides in some other parent tag.
378 ;;
379 ;; If there is no parent tag, then we still need to hang the originator
380 ;; in our list.
381 (when (and (eq searchtype 'symbol)
382 (string= (semantic-tag-name tag) txt))
383 (setq tag (or (semantic-current-tag-parent) tag)))
384
385 ;; Copy the tag, which adds a :filename property.
386 (when tag
387 (setq tag (semantic-tag-copy tag nil t))
388 ;; Ad this hit to the tag.
389 (semantic--tag-put-property tag :hit (list line)))
390 tag))
391 lines)))
392 ;; Kill off dead buffers, unless we were requested to leave them open.
393 (when (not open-buffers)
394 (mapc 'kill-buffer buffs-to-kill))
395 ;; Strip out duplicates.
396 (dolist (T ans)
397 (if (and T (not (semantic-equivalent-tag-p (car out) T)))
398 (setq out (cons T out))
399 (when T
400 ;; Else, add this line into the existing list of lines.
401 (let ((lines (append (semantic--tag-get-property (car out) :hit)
402 (semantic--tag-get-property T :hit))))
403 (semantic--tag-put-property (car out) :hit lines)))
404 ))
405 ;; Out is reversed... twice
406 (oset result :hit-tags (nreverse out)))))
407
408;;; SYMREF TOOLS
409;;
410;; The base symref tool provides something to hang new tools off of
411;; for finding symbol references.
412(defclass semantic-symref-tool-baseclass ()
413 ((searchfor :initarg :searchfor
414 :type string
415 :documentation "The thing to search for.")
416 (searchtype :initarg :searchtype
417 :type symbol
418 :documentation "The type of search to do.
419Values could be `symbol, `regexp, 'tagname, or 'completion.")
420 (searchscope :initarg :searchscope
421 :type symbol
422 :documentation
423 "The scope to search for.
424Can be 'project, 'target, or 'file.")
425 (resulttype :initarg :resulttype
426 :type symbol
427 :documentation
428 "The kind of search results desired.
429Can be 'line, 'file, or 'tag.
430The type of result can be converted from 'line to 'file, or 'line to 'tag,
431but not from 'file to 'line or 'tag.")
432 )
433 "Baseclass for all symbol references tools.
434A symbol reference tool supplies functionality to identify the locations of
435where different symbols are used.
436
437Subclasses should be named `semantic-symref-tool-NAME', where
438NAME is the name of the tool used in the configuration variable
439`semantic-symref-tool'"
440 :abstract t)
441
442(defmethod semantic-symref-get-result ((tool semantic-symref-tool-baseclass))
443 "Calculate the results of a search based on TOOL.
444The symref TOOL should already contain the search criteria."
445 (let ((answer (semantic-symref-perform-search tool))
446 )
447 (when answer
448 (let ((answersym (if (eq (oref tool :resulttype) 'file)
449 :hit-files
450 (if (stringp (car answer))
451 :hit-text
452 :hit-lines))))
453 (semantic-symref-result (oref tool searchfor)
454 answersym
455 answer
456 :created-by tool))
457 )
458 ))
459
460(defmethod semantic-symref-perform-search ((tool semantic-symref-tool-baseclass))
461 "Base search for symref tools should throw an error."
462 (error "Symref tool objects must implement `semantic-symref-perform-search'"))
463
464(defmethod semantic-symref-parse-tool-output ((tool semantic-symref-tool-baseclass)
465 outputbuffer)
466 "Parse the entire OUTPUTBUFFER of a symref tool.
467Calls the method `semantic-symref-parse-tool-output-one-line' over and
468over until it returns nil."
469 (save-excursion
470 (set-buffer outputbuffer)
471 (goto-char (point-min))
472 (let ((result nil)
473 (hit nil))
474 (while (setq hit (semantic-symref-parse-tool-output-one-line tool))
475 (setq result (cons hit result)))
476 (nreverse result)))
477 )
478
479(defmethod semantic-symref-parse-tool-output-one-line ((tool semantic-symref-tool-baseclass))
480 "Base tool output parser is not implemented."
481 (error "Symref tool objects must implement `semantic-symref-parse-tool-output-one-line'"))
482
483(provide 'semantic/symref)
484
485;;; semantic/symref.el ends here
diff --git a/lisp/cedet/semantic/symref/cscope.el b/lisp/cedet/semantic/symref/cscope.el
new file mode 100644
index 00000000000..9d6eda9a5cf
--- /dev/null
+++ b/lisp/cedet/semantic/symref/cscope.el
@@ -0,0 +1,84 @@
1;;; semantic/symref/cscope.el --- Semantic-symref support via cscope.
2
3;;; Copyright (C) 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 symref support via cscope.
25
26(require 'cedet-cscope)
27(require 'semantic/symref)
28
29;;; Code:
30(defclass semantic-symref-tool-cscope (semantic-symref-tool-baseclass)
31 (
32 )
33 "A symref tool implementation using CScope.
34The CScope command can be used to generate lists of tags in a way
35similar to that of `grep'. This tool will parse the output to generate
36the hit list.
37
38See the function `cedet-cscope-search' for more details.")
39
40(defmethod semantic-symref-perform-search ((tool semantic-symref-tool-cscope))
41 "Perform a search with GNU Global."
42 (let* ((rootproj (when (and (featurep 'ede) ede-minor-mode)
43 (ede-toplevel)))
44 (default-directory (if rootproj
45 (ede-project-root-directory rootproj)
46 default-directory))
47 ;; CScope has to be run from the project root where
48 ;; cscope.out is.
49 (b (cedet-cscope-search (oref tool :searchfor)
50 (oref tool :searchtype)
51 (oref tool :resulttype)
52 (oref tool :searchscope)
53 ))
54 )
55 (semantic-symref-parse-tool-output tool b)
56 ))
57
58(defmethod semantic-symref-parse-tool-output-one-line ((tool semantic-symref-tool-cscope))
59 "Parse one line of grep output, and return it as a match list.
60Moves cursor to end of the match."
61 (cond ((eq (oref tool :resulttype) 'file)
62 ;; Search for files
63 (when (re-search-forward "^\\([^\n]+\\)$" nil t)
64 (match-string 1)))
65 ((eq (oref tool :searchtype) 'tagcompletions)
66 ;; Search for files
67 (when (re-search-forward "^[^ ]+ [^ ]+ [^ ]+ \\(.*\\)$" nil t)
68 (let ((subtxt (match-string 1))
69 (searchtxt (oref tool :searchfor)))
70 (if (string-match (concat "\\<" searchtxt "\\(\\w\\|\\s_\\)*\\>")
71 subtxt)
72 (match-string 0 subtxt)
73 ;; We have to return something at this point.
74 subtxt)))
75 )
76 (t
77 (when (re-search-forward "^\\([^ ]+\\) [^ ]+ \\([0-9]+\\) " nil t)
78 (cons (string-to-number (match-string 2))
79 (expand-file-name (match-string 1)))
80 ))))
81
82(provide 'semantic/symref/cscope)
83
84;;; semantic/symref/cscope.el ends here
diff --git a/lisp/cedet/semantic/symref/global.el b/lisp/cedet/semantic/symref/global.el
new file mode 100644
index 00000000000..7a5b8d73efe
--- /dev/null
+++ b/lisp/cedet/semantic/symref/global.el
@@ -0,0 +1,69 @@
1;;; semantic/symref/global.el --- Use GNU Global for symbol references
2
3;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
4
5;; Author: Eric Ludlam <eludlam@mathworks.com>
6
7;; Author: Eric M. Ludlam <eric@siege-engine.com>
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software: you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24;;; Commentary:
25;;
26;; GNU Global use with the semantic-symref system.
27
28(require 'cedet-global)
29(require 'semantic/symref)
30
31;;; Code:
32(defclass semantic-symref-tool-global (semantic-symref-tool-baseclass)
33 (
34 )
35 "A symref tool implementation using GNU Global.
36The GNU Global command can be used to generate lists of tags in a way
37similar to that of `grep'. This tool will parse the output to generate
38the hit list.
39
40See the function `cedet-gnu-global-search' for more details.")
41
42(defmethod semantic-symref-perform-search ((tool semantic-symref-tool-global))
43 "Perform a search with GNU Global."
44 (let ((b (cedet-gnu-global-search (oref tool :searchfor)
45 (oref tool :searchtype)
46 (oref tool :resulttype)
47 (oref tool :searchscope)
48 ))
49 )
50 (semantic-symref-parse-tool-output tool b)
51 ))
52
53(defmethod semantic-symref-parse-tool-output-one-line ((tool semantic-symref-tool-global))
54 "Parse one line of grep output, and return it as a match list.
55Moves cursor to end of the match."
56 (cond ((or (eq (oref tool :resulttype) 'file)
57 (eq (oref tool :searchtype) 'tagcompletions))
58 ;; Search for files
59 (when (re-search-forward "^\\([^\n]+\\)$" nil t)
60 (match-string 1)))
61 (t
62 (when (re-search-forward "^\\([^ ]+\\) +\\([0-9]+\\) \\([^ ]+\\) " nil t)
63 (cons (string-to-number (match-string 2))
64 (match-string 3))
65 ))))
66
67(provide 'semantic/symref/global)
68
69;;; semantic/symref/global.el ends here
diff --git a/lisp/cedet/semantic/symref/idutils.el b/lisp/cedet/semantic/symref/idutils.el
new file mode 100644
index 00000000000..abce2313160
--- /dev/null
+++ b/lisp/cedet/semantic/symref/idutils.el
@@ -0,0 +1,71 @@
1;;; semantic/symref/idutils.el --- Symref implementation for idutils
2
3;;; Copyright (C) 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;; This program is free software; you can redistribute it and/or
10;; modify it under the terms of the GNU General Public License as
11;; published by the Free Software Foundation; either version 2, or (at
12;; your option) any later version.
13
14;; This program is distributed in the hope that it will be useful, but
15;; WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17;; General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with this program; see the file COPYING. If not, write to
21;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22;; Boston, MA 02110-1301, USA.
23
24;;; Commentary:
25;;
26;; Support IDUtils use in the Semantic Symref tool.
27
28(require 'cedet-idutils)
29(require 'semantic-symref)
30
31;;; Code:
32(defclass semantic-symref-tool-idutils (semantic-symref-tool-baseclass)
33 (
34 )
35 "A symref tool implementation using ID Utils.
36The udutils command set can be used to generate lists of tags in a way
37similar to that of `grep'. This tool will parse the output to generate
38the hit list.
39
40See the function `cedet-idutils-search' for more details.")
41
42(defmethod semantic-symref-perform-search ((tool semantic-symref-tool-idutils))
43 "Perform a search with IDUtils."
44 (let ((b (cedet-idutils-search (oref tool :searchfor)
45 (oref tool :searchtype)
46 (oref tool :resulttype)
47 (oref tool :searchscope)
48 ))
49 )
50 (semantic-symref-parse-tool-output tool b)
51 ))
52
53(defmethod semantic-symref-parse-tool-output-one-line ((tool semantic-symref-tool-idutils))
54 "Parse one line of grep output, and return it as a match list.
55Moves cursor to end of the match."
56 (cond ((eq (oref tool :resulttype) 'file)
57 ;; Search for files
58 (when (re-search-forward "^\\([^\n]+\\)$" nil t)
59 (match-string 1)))
60 ((eq (oref tool :searchtype) 'tagcompletions)
61 (when (re-search-forward "^\\([^ ]+\\) " nil t)
62 (match-string 1)))
63 (t
64 (when (re-search-forward "^\\([^ :]+\\):+\\([0-9]+\\):" nil t)
65 (cons (string-to-number (match-string 2))
66 (expand-file-name (match-string 1) default-directory))
67 ))))
68
69(provide 'semantic/symref/idutils)
70
71;;; semantic/symref/idutils.el ends here
diff --git a/lisp/cedet/semantic/symref/list.el b/lisp/cedet/semantic/symref/list.el
new file mode 100644
index 00000000000..74186c754a4
--- /dev/null
+++ b/lisp/cedet/semantic/symref/list.el
@@ -0,0 +1,328 @@
1;;; semantic/symref/list.el --- Symref Output List UI.
2
3;;; Copyright (C) 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;; This program is free software; you can redistribute it and/or
10;; modify it under the terms of the GNU General Public License as
11;; published by the Free Software Foundation; either version 2, or (at
12;; your option) any later version.
13
14;; This program is distributed in the hope that it will be useful, but
15;; WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17;; General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with this program; see the file COPYING. If not, write to
21;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22;; Boston, MA 02110-1301, USA.
23
24;;; Commentary:
25;;
26;; Provide a simple user facing API to finding symbol references.
27;;
28;; This UI will is the base of some refactoring tools. For any
29;; refactor, the user will execture `semantic-symref' in a tag. Once
30;; that data is collected, the output will be listed in a buffer. In
31;; the output buffer, the user can then initiate different refactoring
32;; operations.
33;;
34;; NOTE: Need to add some refactoring tools.
35
36(require 'semantic/symref)
37(require 'pulse)
38
39;;; Code:
40
41(defun semantic-symref ()
42 "Find references to the current tag.
43This command uses the currently configured references tool within the
44current project to find references to the current tag. The
45references are the organized by file and the name of the function
46they are used in.
47Display the references in`semantic-symref-results-mode'"
48 (interactive)
49 (semantic-fetch-tags)
50 (let ((ct (semantic-current-tag))
51 (res nil)
52 )
53 ;; Must have a tag...
54 (when (not ct) (error "Place cursor inside tag to be searched for"))
55 ;; Check w/ user.
56 (when (not (y-or-n-p (format "Find references for %s? " (semantic-tag-name ct))))
57 (error "Quit"))
58 ;; Gather results and tags
59 (message "Gathering References...")
60 (setq res (semantic-symref-find-references-by-name (semantic-tag-name ct)))
61 (semantic-symref-produce-list-on-results res (semantic-tag-name ct))))
62
63(defun semantic-symref-symbol (sym)
64 "Find references to the symbol SYM.
65This command uses the currently configured references tool within the
66current project to find references to the input SYM. The
67references are the organized by file and the name of the function
68they are used in.
69Display the references in`semantic-symref-results-mode'"
70 (interactive (list (car (senator-jump-interactive "Symrefs for: " nil nil t)))
71 )
72 (semantic-fetch-tags)
73 (let ((res nil)
74 )
75 ;; Gather results and tags
76 (message "Gathering References...")
77 (setq res (semantic-symref-find-references-by-name sym))
78 (semantic-symref-produce-list-on-results res sym)))
79
80
81(defun semantic-symref-produce-list-on-results (res str)
82 "Produce a symref list mode buffer on the results RES."
83 (when (not res) (error "No references found"))
84 (semantic-symref-result-get-tags res t)
85 (message "Gathering References...done")
86 ;; Build a refrences buffer.
87 (let ((buff (get-buffer-create
88 (format "*Symref %s" str)))
89 )
90 (switch-to-buffer-other-window buff)
91 (set-buffer buff)
92 (semantic-symref-results-mode res))
93 )
94
95;;; RESULTS MODE
96;;
97(defgroup semantic-symref-results-mode nil
98 "Symref Results group."
99 :group 'semantic)
100
101(defvar semantic-symref-results-mode-map
102 (let ((km (make-sparse-keymap)))
103 (define-key km "\C-i" 'forward-button)
104 (define-key km "\M-C-i" 'backward-button)
105 (define-key km " " 'push-button)
106 (define-key km "-" 'semantic-symref-list-toggle-showing)
107 (define-key km "=" 'semantic-symref-list-toggle-showing)
108 (define-key km "+" 'semantic-symref-list-toggle-showing)
109 (define-key km "n" 'semantic-symref-list-next-line)
110 (define-key km "p" 'semantic-symref-list-prev-line)
111 (define-key km "q" 'semantic-symref-hide-buffer)
112 km)
113 "Keymap used in `semantic-symref-results-mode'.")
114
115(defcustom semantic-symref-results-mode-hook nil
116 "*Hook run when `semantic-symref-results-mode' starts."
117 :group 'semantic-symref
118 :type 'hook)
119
120(defvar semantic-symref-current-results nil
121 "The current results in a results mode buffer.")
122
123(defun semantic-symref-results-mode (results)
124 "Major-mode for displaying Semantic Symbol Reference RESULTS.
125RESULTS is an object of class `semantic-symref-results'."
126 (interactive)
127 (kill-all-local-variables)
128 (setq major-mode 'semantic-symref-results-mode
129 mode-name "Symref"
130 )
131 (use-local-map semantic-symref-results-mode-map)
132 (set (make-local-variable 'semantic-symref-current-results)
133 results)
134 (semantic-symref-results-dump results)
135 (goto-char (point-min))
136 (buffer-disable-undo)
137 (set (make-local-variable 'font-lock-global-modes) nil)
138 (font-lock-mode -1)
139 (run-hooks 'semantic-symref-results-mode-hook)
140 )
141
142(defun semantic-symref-hide-buffer ()
143 "Hide buffer with sematinc-symref results"
144 (interactive)
145 (bury-buffer))
146
147(defcustom semantic-symref-results-summary-function 'semantic-format-tag-prototype
148 "*Function to use when creating items in Imenu.
149Some useful functions are found in `semantic-format-tag-functions'."
150 :group 'semantic-symref
151 :type semantic-format-tag-custom-list)
152
153(defun semantic-symref-results-dump (results)
154 "Dump the RESULTS into the current buffer."
155 ;; Get ready for the insert.
156 (toggle-read-only -1)
157 (erase-buffer)
158
159 ;; Insert the contents.
160 (let ((lastfile nil)
161 )
162 (dolist (T (oref results :hit-tags))
163
164 (when (not (equal lastfile (semantic-tag-file-name T)))
165 (setq lastfile (semantic-tag-file-name T))
166 (insert-button lastfile
167 'mouse-face 'custom-button-pressed-face
168 'action 'semantic-symref-rb-goto-file
169 'tag T
170 )
171 (insert "\n"))
172
173 (insert " ")
174 (insert-button "[+]"
175 'mouse-face 'highlight
176 'face nil
177 'action 'semantic-symref-rb-toggle-expand-tag
178 'tag T
179 'state 'closed)
180 (insert " ")
181 (insert-button (funcall semantic-symref-results-summary-function
182 T nil t)
183 'mouse-face 'custom-button-pressed-face
184 'face nil
185 'action 'semantic-symref-rb-goto-tag
186 'tag T)
187 (insert "\n")
188
189 ))
190
191 ;; Clean up the mess
192 (toggle-read-only 1)
193 (set-buffer-modified-p nil)
194 )
195
196;;; Commands for semantic-symref-results
197;;
198(defun semantic-symref-list-toggle-showing ()
199 "Toggle showing the contents below the current line."
200 (interactive)
201 (beginning-of-line)
202 (when (re-search-forward "\\[[-+]\\]" (point-at-eol) t)
203 (forward-char -1)
204 (push-button)))
205
206(defun semantic-symref-rb-toggle-expand-tag (&optional button)
207 "Go to the file specified in the symref results buffer.
208BUTTON is the button that was clicked."
209 (interactive)
210 (let* ((tag (button-get button 'tag))
211 (buff (semantic-tag-buffer tag))
212 (hits (semantic--tag-get-property tag :hit))
213 (state (button-get button 'state))
214 (text nil)
215 )
216 (cond
217 ((eq state 'closed)
218 (toggle-read-only -1)
219 (save-excursion
220 (set-buffer buff)
221 (dolist (H hits)
222 (goto-char (point-min))
223 (forward-line (1- H))
224 (beginning-of-line)
225 (back-to-indentation)
226 (setq text (cons (buffer-substring (point) (point-at-eol)) text)))
227 (setq text (nreverse text))
228 )
229 (goto-char (button-start button))
230 (forward-char 1)
231 (delete-char 1)
232 (insert "-")
233 (button-put button 'state 'open)
234 (save-excursion
235 (end-of-line)
236 (while text
237 (insert "\n")
238 (insert " ")
239 (insert-button (car text)
240 'mouse-face 'highlight
241 'face nil
242 'action 'semantic-symref-rb-goto-match
243 'tag tag
244 'line (car hits))
245 (setq text (cdr text)
246 hits (cdr hits))))
247 (toggle-read-only 1)
248 )
249 ((eq state 'open)
250 (toggle-read-only -1)
251 (button-put button 'state 'closed)
252 ;; Delete the various bits.
253 (goto-char (button-start button))
254 (forward-char 1)
255 (delete-char 1)
256 (insert "+")
257 (save-excursion
258 (end-of-line)
259 (forward-char 1)
260 (delete-region (point)
261 (save-excursion
262 (forward-char 1)
263 (forward-line (length hits))
264 (point))))
265 (toggle-read-only 1)
266 )
267 ))
268 )
269
270(defun semantic-symref-rb-goto-file (&optional button)
271 "Go to the file specified in the symref results buffer.
272BUTTON is the button that was clicked."
273 (let* ((tag (button-get button 'tag))
274 (buff (semantic-tag-buffer tag))
275 (win (selected-window))
276 )
277 (switch-to-buffer-other-window buff)
278 (pulse-momentary-highlight-one-line (point))
279 (when (eq last-command-char ? ) (select-window win))
280 ))
281
282
283(defun semantic-symref-rb-goto-tag (&optional button)
284 "Go to the file specified in the symref results buffer.
285BUTTON is the button that was clicked."
286 (interactive)
287 (let* ((tag (button-get button 'tag))
288 (buff (semantic-tag-buffer tag))
289 (win (selected-window))
290 )
291 (switch-to-buffer-other-window buff)
292 (semantic-go-to-tag tag)
293 (pulse-momentary-highlight-one-line (point))
294 (when (eq last-command-char ? ) (select-window win))
295 )
296 )
297
298(defun semantic-symref-rb-goto-match (&optional button)
299 "Go to the file specified in the symref results buffer.
300BUTTON is the button that was clicked."
301 (interactive)
302 (let* ((tag (button-get button 'tag))
303 (line (button-get button 'line))
304 (buff (semantic-tag-buffer tag))
305 (win (selected-window))
306 )
307 (switch-to-buffer-other-window buff)
308 (goto-line line)
309 (pulse-momentary-highlight-one-line (point))
310 (when (eq last-command-char ? ) (select-window win))
311 )
312 )
313
314(defun semantic-symref-list-next-line ()
315 "Next line in `semantic-symref-results-mode'."
316 (interactive)
317 (forward-line 1)
318 (back-to-indentation))
319
320(defun semantic-symref-list-prev-line ()
321 "Next line in `semantic-symref-results-mode'."
322 (interactive)
323 (forward-line -1)
324 (back-to-indentation))
325
326(provide 'semantic/symref/list)
327
328;;; semantic/symref/list.el ends here