Commit | Line | Data |
---|---|---|
acc33231 CY |
1 | ;;; ede/locate.el --- Locate support |
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 | ;; Support for various LOCATE type functions. | |
25 | ;; | |
26 | ;; A key feature of EDE is `ede-expand-filename', which allows a | |
27 | ;; project to expand a filename reference in one file to some actual | |
28 | ;; filename. | |
29 | ;; | |
30 | ;; In that way, you may #include <foo.h>, and without knowing how to | |
31 | ;; read a Makefile, find it in <root>/include/foo.h. | |
32 | ;; | |
33 | ;; Some projects are regular, such as the Emacs project. Some | |
34 | ;; projects are completely controlled by EDE, such sh the Project.ede | |
35 | ;; based projects. | |
36 | ;; | |
8bea2dbd | 37 | ;; For other projects, having a "quick hack" to support these location |
acc33231 CY |
38 | ;; routines is handy. |
39 | ;; | |
40 | ;; The baseclass `ede-locate-base' provides the abstract interface to | |
41 | ;; finding files in a project. | |
42 | ;; | |
43 | ;; New location routines will subclass `ede-locate-base'. | |
44 | ;; | |
45 | ;; How to use: | |
46 | ;; | |
47 | ;; Configure `ede-locate-setup-options' to add the types of locate | |
48 | ;; features you have available. EDE will then enable the correct one | |
49 | ;; when it is available. | |
50 | ||
51 | (require 'ede) | |
52 | (eval-when-compile (require 'data-debug) | |
53 | (require 'eieio-datadebug) | |
54 | (require 'cedet-global) | |
55 | (require 'cedet-idutils) | |
56 | (require 'cedet-cscope)) | |
57 | ||
58 | (require 'locate) | |
59 | ||
60 | ;;; Code: | |
61 | (defcustom ede-locate-setup-options | |
62 | '(ede-locate-base) | |
63 | "List of locate objects to try out by default. | |
64 | Listed in order of preference. If the first item cannot be used in | |
65 | a particular project, then the next one is tried. | |
66 | It is always assumed that `ede-locate-base' is at end of the list." | |
67 | :group 'ede | |
68 | :type '(repeat | |
69 | (choice (const :tag "None" ede-locate-base) | |
70 | (const :tag "locate" ede-locate-locate) | |
71 | (const :tag "GNU Global" ede-locate-global) | |
72 | (const :tag "ID Utils" ede-locate-idutils) | |
73 | (const :tag "CScope" ede-locate-cscope))) | |
74 | ) | |
75 | ||
76 | ;;;###autoload | |
77 | (defun ede-enable-locate-on-project (&optional project) | |
78 | "Enable an EDE locate feature on PROJECT. | |
79 | Attempt to guess which project locate style to use | |
80 | based on `ede-locate-setup-options'." | |
81 | (interactive) | |
82 | (let* ((proj (or project (ede-toplevel))) | |
83 | (root (ede-project-root-directory proj)) | |
84 | (opts ede-locate-setup-options) | |
85 | (ans nil)) | |
86 | (while (and opts (not ans)) | |
87 | (when (ede-locate-ok-in-project (car opts) root) | |
88 | ;; If interactive, check with the user. | |
89 | (when (or (not (interactive-p)) | |
90 | (y-or-n-p (format "Set project locator to %s? " (car opts)))) | |
91 | (setq ans (car opts)))) | |
92 | (setq opts (cdr opts))) | |
93 | ;; No match? Always create the baseclass for the hashing tool. | |
94 | (when (not ans) | |
95 | (when (interactive-p) | |
96 | (message "Setting locator to ede-locate-base")) | |
97 | (setq ans 'ede-locate-base)) | |
98 | (oset proj locate-obj (make-instance ans "Loc" :root root)) | |
99 | (when (interactive-p) | |
100 | (message "Satting locator to %s." ans)) | |
101 | )) | |
102 | ||
103 | ;;; LOCATE BASECLASS | |
104 | ;; | |
105 | ;; The baseclass for all location style queries. | |
106 | (defclass ede-locate-base () | |
107 | ((root :initarg :root | |
108 | :documentation | |
109 | "The root of these locat searches.") | |
110 | (file :documentation | |
111 | "The last file search for with EDE locate.") | |
112 | (lastanswer :documentation | |
113 | "The last answer provided by the locator.") | |
114 | (hash :documentation | |
115 | "Hash table of previously found files.") | |
116 | ) | |
117 | "Baseclass for LOCATE feature in EDE.") | |
118 | ||
119 | (defmethod initialize-instance ((loc ede-locate-base) &rest fields) | |
120 | "Make sure we have a hash table." | |
121 | ;; Basic setup. | |
122 | (call-next-method) | |
123 | ;; Make sure we have a hash table. | |
124 | (oset loc hash (make-hash-table :test 'equal)) | |
125 | ) | |
126 | ||
127 | (defmethod ede-locate-ok-in-project :static ((loc ede-locate-base) | |
128 | root) | |
129 | "Is it ok to use this project type under ROOT." | |
130 | t) | |
131 | ||
132 | (defmethod ede-locate-file-in-hash ((loc ede-locate-base) | |
133 | filestring) | |
134 | "For LOC, is the file FILESTRING in our hashtable?" | |
135 | (gethash filestring (oref loc hash))) | |
136 | ||
137 | (defmethod ede-locate-add-file-to-hash ((loc ede-locate-base) | |
138 | filestring fullfilename) | |
139 | "For LOC, add FILESTR to the hash with FULLFILENAME." | |
140 | (puthash filestring fullfilename (oref loc hash))) | |
141 | ||
142 | (defmethod ede-locate-file-in-project ((loc ede-locate-base) | |
143 | filesubstring | |
144 | ) | |
145 | "Locate with LOC occurances of FILESUBSTRING. | |
146 | Searches are done under the current root of the EDE project | |
147 | that crated this ede locat object." | |
148 | (let ((ans (ede-locate-file-in-project-impl loc filesubstring)) | |
149 | ) | |
150 | (oset loc file filesubstring) | |
151 | (oset loc lastanswer ans) | |
152 | ans)) | |
153 | ||
154 | (defmethod ede-locate-file-in-project-impl ((loc ede-locate-base) | |
155 | filesubstring | |
156 | ) | |
157 | "Locate with LOC occurances of FILESUBSTRING. | |
158 | Searches are done under the current root of the EDE project | |
159 | that crated this ede locat object." | |
160 | nil | |
161 | ) | |
162 | ||
163 | ;;; LOCATE | |
164 | ;; | |
165 | ;; Using the standard unix "locate" command. | |
166 | ;; Since locate is system wide, we need to hack the search | |
167 | ;; to restrict it to within just this project. | |
168 | ||
169 | (defclass ede-locate-locate (ede-locate-base) | |
170 | () | |
171 | "EDE Locator using the locate command. | |
172 | Configure the Emacs `locate-program' variable to also | |
173 | configure the use of EDE locate.") | |
174 | ||
175 | (defmethod ede-locate-ok-in-project :static ((loc ede-locate-locate) | |
176 | root) | |
177 | "Is it ok to use this project type under ROOT." | |
178 | (or (featurep 'locate) (locate-library "locate")) | |
179 | ) | |
180 | ||
181 | (defmethod ede-locate-file-in-project-impl ((loc ede-locate-locate) | |
182 | filesubstring) | |
183 | "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. | |
184 | Searches are done under the current root of the EDE project | |
185 | that crated this ede locat object." | |
186 | ;; We want something like: | |
187 | ;; /my/project/root*/filesubstring.c | |
188 | (let* ((searchstr (concat (directory-file-name (oref loc root)) | |
189 | "*/" filesubstring)) | |
190 | (b (get-buffer-create "*LOCATE*")) | |
191 | (cd default-directory) | |
192 | ) | |
0816d744 | 193 | (with-current-buffer b |
acc33231 CY |
194 | (setq default-directory cd) |
195 | (erase-buffer)) | |
196 | (apply 'call-process locate-command | |
197 | nil b nil | |
198 | searchstr nil) | |
0816d744 | 199 | (with-current-buffer b |
acc33231 CY |
200 | (split-string (buffer-string) "\n" t)) |
201 | ) | |
202 | ) | |
203 | ||
204 | ;;; GLOBAL | |
205 | ;; | |
206 | (defclass ede-locate-global (ede-locate-base) | |
207 | () | |
208 | "EDE Locator using GNU Global. | |
209 | Configure EDE's use of GNU Global through the cedet-global.el | |
210 | variable `cedet-global-command'.") | |
211 | ||
212 | (defmethod initialize-instance ((loc ede-locate-global) | |
213 | &rest slots) | |
214 | "Make sure that we can use GNU Global." | |
215 | (require 'cedet-global) | |
216 | ;; Get ourselves initialized. | |
217 | (call-next-method) | |
218 | ;; Do the checks. | |
219 | (cedet-gnu-global-version-check) | |
220 | (let* ((default-directory (oref loc root)) | |
221 | (root (cedet-gnu-global-root))) | |
222 | (when (not root) | |
223 | (error "Cannot use GNU Global in %s" | |
224 | (oref loc root)))) | |
225 | ) | |
226 | ||
227 | (defmethod ede-locate-ok-in-project :static ((loc ede-locate-global) | |
228 | root) | |
229 | "Is it ok to use this project type under ROOT." | |
230 | (require 'cedet-global) | |
231 | (cedet-gnu-global-version-check) | |
232 | (let* ((default-directory root) | |
233 | (newroot (cedet-gnu-global-root))) | |
234 | newroot)) | |
235 | ||
236 | (defmethod ede-locate-file-in-project-impl ((loc ede-locate-global) | |
237 | filesubstring) | |
238 | "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. | |
239 | Searches are done under the current root of the EDE project | |
240 | that crated this ede locat object." | |
241 | (require 'cedet-global) | |
242 | (let ((default-directory (oref loc root))) | |
243 | (cedet-gnu-global-expand-filename filesubstring))) | |
244 | ||
245 | ;;; IDUTILS | |
246 | ;; | |
247 | (defclass ede-locate-idutils (ede-locate-base) | |
248 | () | |
249 | "EDE Locator using IDUtils. | |
250 | Configure EDE's use of IDUtils through the cedet-idutils.el | |
251 | file name searching variable `cedet-idutils-file-command'.") | |
252 | ||
253 | (defmethod initialize-instance ((loc ede-locate-idutils) | |
254 | &rest slots) | |
255 | "Make sure that we can use IDUtils." | |
256 | ;; Get ourselves initialized. | |
257 | (call-next-method) | |
258 | ;; Do the checks. | |
259 | (require 'cedet-idutils) | |
260 | (cedet-idutils-version-check) | |
261 | (when (not (cedet-idutils-support-for-directory (oref loc root))) | |
262 | (error "Cannot use IDUtils in %s" | |
263 | (oref loc root))) | |
264 | ) | |
265 | ||
266 | (defmethod ede-locate-ok-in-project :static ((loc ede-locate-idutils) | |
267 | root) | |
268 | "Is it ok to use this project type under ROOT." | |
269 | (require 'cedet-idutils) | |
270 | (cedet-idutils-version-check) | |
271 | (when (cedet-idutils-support-for-directory root) | |
272 | root)) | |
273 | ||
274 | (defmethod ede-locate-file-in-project-impl ((loc ede-locate-idutils) | |
275 | filesubstring) | |
276 | "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. | |
277 | Searches are done under the current root of the EDE project | |
278 | that crated this ede locat object." | |
279 | (require 'cedet-idutils) | |
280 | (let ((default-directory (oref loc root))) | |
281 | (cedet-idutils-expand-filename filesubstring))) | |
282 | ||
283 | ;;; CSCOPE | |
284 | ;; | |
285 | (defclass ede-locate-cscope (ede-locate-base) | |
286 | () | |
287 | "EDE Locator using Cscope. | |
288 | Configure EDE's use of Cscope through the cedet-cscope.el | |
289 | file name searching variable `cedet-cscope-file-command'.") | |
290 | ||
291 | (defmethod initialize-instance ((loc ede-locate-cscope) | |
292 | &rest slots) | |
293 | "Make sure that we can use Cscope." | |
294 | ;; Get ourselves initialized. | |
295 | (call-next-method) | |
296 | ;; Do the checks. | |
297 | (cedet-cscope-version-check) | |
298 | (when (not (cedet-cscope-support-for-directory (oref loc root))) | |
299 | (error "Cannot use Cscope in %s" | |
300 | (oref loc root))) | |
301 | ) | |
302 | ||
303 | (defmethod ede-locate-ok-in-project :static ((loc ede-locate-cscope) | |
304 | root) | |
305 | "Is it ok to use this project type under ROOT." | |
306 | (cedet-cscope-version-check) | |
307 | (when (cedet-cscope-support-for-directory root) | |
308 | root)) | |
309 | ||
310 | (defmethod ede-locate-file-in-project-impl ((loc ede-locate-cscope) | |
311 | filesubstring) | |
312 | "Locate with LOC occurances of FILESUBSTRING under PROJECTROOT. | |
313 | Searches are done under the current root of the EDE project | |
314 | that crated this ede locat object." | |
315 | (let ((default-directory (oref loc root))) | |
316 | (cedet-cscope-expand-filename filesubstring))) | |
317 | ||
318 | (provide 'ede/locate) | |
319 | ||
320 | ;; Local variables: | |
321 | ;; generated-autoload-file: "loaddefs.el" | |
322 | ;; generated-autoload-feature: ede/loaddefs | |
323 | ;; generated-autoload-load-name: "ede/locate" | |
324 | ;; End: | |
325 | ||
3999968a | 326 | ;; arch-tag: a04cb356-d11c-4f69-bd72-5a8a2aff708c |
acc33231 | 327 | ;;; ede/locate.el ends here |