Codebase list xcscope-el / a1d6608
New upstream version 1.3 tony mancill 6 years ago
2 changed file(s) with 3354 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 * Overview
1
2 This is an emacs interface to the 'cscope' source cross-referencing tool
3 (http://cscope.sf.net). It can answer such questions as
4
5 - Where is this variable used?
6 - What is the value of this preprocessor symbol?
7 - Where is this function in the source files?
8 - What functions call this function?
9 - What functions are called by this function?
10 - Where does the message "out of space" come from?
11 - Where is this source file in the directory structure?
12 - What files include this header file?
13 - Where was this variable assigned-to?
14
15 The 'cscope' tool does the actual searching and lookup, while xcscope.el
16 provides a convenient interface.
17
18 * GNU Global support
19
20 GNU global (http://www.gnu.org/s/global/) is another source indexer much like
21 cscope. It's better than cscope in some ways and worse in others. It also
22 provides a compatibility interface to allow it to be used just like cscope. This
23 means that xcscope.el can be used as a front-end to GNU Global. To do that,
24 simply evaluate
25
26 (setq cscope-program "gtags-cscope")
27
28 * Usage
29
30 ** Quick-start
31
32 1. Install xcscope.el through your system package manager or MELPA, or simply
33 evaluate xcscope.el.
34
35 2. Evaluate
36
37 - (require 'xcscope)
38 - (cscope-setup)
39
40 Done! cscope-minor-mode is now hooked to C, C++ and dired modes. Default
41 bindings are all prefixed with C-c s. So, for instance, to find a symbol do C-c
42 s s. This is analogous to the M-. of tags. All results are shown in a new
43 *cscope* buffer which pops up when needed.
44
45 ** More-detailed usage instructions
46
47 When xcscope.el is active, you can just use the keybindings (described below)
48 when looking at source. You can also use the *Cscope* menu or a mouse pop-up
49 menu (button 3).
50
51 When a search is performend, by default xcscope.el will traverse the directory
52 hierarchy upwards, looking for the cscope database. If it doesn't find it, a new
53 database will be made in the *current* directory. To create the database in a
54 different (higher) directory, explicitly invoke C-c s I. A currently-existing
55 database can be removed simply by deleting cscope.*. By default, cscope updates
56 the database with every search. This is very convenient, but can be too slow for
57 very large source trees.
58
59 The third mouse button is bound to a popup menu for cscope. Shift-mouse
60 button 3 invokes the last find command again. E.g. if you look for the symbol
61 'main' and afterwards you want to look for another symbol, just press Shift
62 and click the third button.
63
64 Search results are displayed in a *cscope* buffer, which pops up when results
65 are available. You can then use button 2 (the middle button) on the mouse to
66 edit the selected file, or you can move the text cursor over a selection and
67 press [Enter]. You can also press [space] to show the result in the other window
68 (*cscope* buffer stays focused). Alternately, the navigation commands invoked
69 with n/p, show the results too.
70
71 Each cscope search adds its results to the *cscope* buffer. Thus this buffer
72 contains a history of all past searches. These sets of results can be navigated
73 and manupulated similar to patches in diff-mode:
74
75 - n/p navigates over individual results
76 - k kills individual results
77
78 - N/P or M-n/M-p navigates over file results
79 - M-k kills file results
80
81 - M-N/M-P navigates over result sets
82 - M-K kills result sets
83
84 - Navigation from outside the *cscope* buffer (C-c s n/p/N/P) is restricted to
85 the result set at (point)
86
87 Any result set in the *cscope* buffer can be re-run with the 'r' key. This is
88 useful if the sources changed
89
90 ** Keybindings:
91
92 All keybindings use the "C-c s" prefix:
93
94 | C-c s s | Find symbol. |
95 | C-c s = | Find assignments to this symbol |
96 | C-c s d | Find global definition. |
97 | C-c s g | Find global definition (alternate binding). |
98 | C-c s G | Find global definition without prompting. |
99 | C-c s c | Find functions calling a function. |
100 | C-c s C | Find called functions (list functions called from a function). |
101 | C-c s t | Find text string. |
102 | C-c s e | Find egrep pattern. |
103 | C-c s f | Find a file. |
104 | C-c s i | Find files #including a file. |
105
106 These pertain to navigation through the search results:
107
108 | C-c s b | Display *cscope* buffer. |
109 | C-c s B | Auto display *cscope* buffer toggle. |
110 | C-c s n | Next symbol. |
111 | C-c s N | Next file. |
112 | C-c s p | Previous symbol. |
113 | C-c s P | Previous file. |
114 | C-c s u | Pop mark. |
115
116 These pertain to setting and unsetting the variable,
117 `cscope-initial-directory', (location searched for the cscope database
118 directory):
119
120 | C-c s a | Set initial directory. |
121 | C-c s A | Unset initial directory. |
122
123 These pertain to cscope database maintenance:
124
125 | C-c s L | Create list of files to index. |
126 | C-c s I | Create list and index. |
127 | C-c s E | Edit list of files to index. |
128 | C-c s W | Locate this buffer's cscope directory ("W" --> "where"). |
129 | C-c s S | Locate this buffer's cscope directory. (alternate binding: "S" --> "show"). |
130 | C-c s T | Locate this buffer's cscope directory. (alternate binding: "T" --> "tell"). |
131 | C-c s D | Dired this buffer's directory. |
132
133 ** Interesting configuration variables:
134
135 - cscope-truncate-lines
136
137 This is the value of `truncate-lines' to use in cscope
138 buffers; the default is the current setting of
139 `truncate-lines'. This variable exists because it can be
140 easier to read cscope buffers with truncated lines, while
141 other buffers do not have truncated lines.
142
143 - cscope-use-relative-paths
144
145 If non-nil, use relative paths when creating the list of files
146 to index. The path is relative to the directory in which the
147 cscope database will be created. If nil, absolute paths will
148 be used. Absolute paths are good if you plan on moving the
149 database to some other directory (if you do so, you'll
150 probably also have to modify `cscope-database-regexps').
151 Absolute paths may also be good if you share the database file
152 with other users (you'll probably want to specify some
153 automounted network path for this).
154
155 - cscope-index-recursively
156
157 If non-nil, index files in the current directory and all
158 subdirectories. If nil, only files in the current directory
159 are indexed. This variable is only used when creating the
160 list of files to index, or when creating the list of files and
161 the corresponding cscope database.
162
163 - cscope-name-line-width
164
165 The width of the combined "function name:line number" field in
166 the cscope results buffer. If negative, the field is
167 left-justified.
168
169 - cscope-option-....
170
171 Various options passed to the 'cscope' process. Controls things like include
172 directories, database compression, database type, etc.
173
174 - cscope-display-cscope-buffer
175
176 If non-nil, display the *cscope* buffer after each search (default). This
177 variable can be set in order to reduce the number of keystrokes required to
178 navigate through the matches.
179
180 * Provenance
181
182 This is a continuation of the xcscope.el (by Darryl Okahata) that ships in the
183 CVS tree of cscope itself. The code in the cscope tree is stable, so /this/ tree
184 expands on the original source, fixing various bugs and adding features.
185
186 * New features relative to the cscope CVS tree
187
188 - *(cscope-setup) must be called to enable cscope-minor-mode in C and C++ major
189 modes*
190
191 - New searches are appended to the *cscope* buffer, instead of overwriting. The
192 user thus sees a history of cscope search results in this buffer, and is able
193 to navigate through all of them. There is a size limit to keep the buffer from
194 growing out of control.
195
196 - The *cscope* buffer can be navigated and edited similarly to emacs Diff buffers:
197
198 - n/p navigates over individual results
199 - k kills individual results
200
201 - N/P or M-n/M-p navigates over file results
202 - M-k kills file results
203
204 - M-N/M-P navigates over result sets
205 - M-K kills result sets
206
207 - Navigation from outside the *cscope* buffer (C-c s n/p/N/P) is restricted to
208 the result set at (point)
209
210 - Previous searches can be re-run with the 'r' key in the *cscope* buffer. These
211 are written in-place, overwriting the older results.
212
213 - Fuzzy matching is now enabled/disabled for specific types of searches. This
214 was implemented earlier, but the implementation had a bug and wasn't working
215
216 - xcscope.el can now work remotely over TRAMP
217
218 - The cscope-index output now goes to the echo area instead of an explicit new
219 buffer that the user must deal with
220
221 - Fuzzy searching now works for non-trivial regex searches
222
223 - The mouse face respects cscope-use-face
224
225 - Better mouse support:
226 - button3 opens a popup menu that runs prompt-less searches
227 - shift-button3 reruns the last search on the point. This is thus even more
228 prompt-less
229
230 - Shift-return or Shift-mouse2 now open the result in the same window as the
231 *cscope* buffer
232
233 - Some bold highlighting in the *cscope* results: the sought term, the search
234 directory
235
236 - Removed the external 'cscope-indexer' script; this is now handled inside
237 xcscope.el. Additionally the list of source directories to ignore and the list
238 of filename extensions to index are now customizable in the emacs
239 customization interface
240
241 - Various cscope options (kernel mode, inverted index, etc) can now be accessed
242 through the emacs variables
243
244 * License and authorship
245
246 xcscope.el was written by Darryl Okahata, with patches contributed by Triet H.
247 Lai and Steven Elliott. Dima Kogan added some features.
248
249 xcscope.el is distributed under the terms of version 2 (or later) of the GNU
250 General Public License
251
252 * Contact
253
254 The maintainer is Dima Kogan <dima@secretsauce.net>
0 ;;; xcscope.el --- cscope interface for (X)Emacs
1
2 ;; Copyright (C) 2000-2002 Darryl Okahata
3 ;; 2001 Triet H. Lai
4 ;; 2001 Steven Elliott
5 ;; 2013 Dima Kogan
6
7 ;; Author: Darryl Okahata <darrylo@sonic.net>
8 ;; Dima Kogan <dima@secretsauce.net>
9 ;; Maintainer: Dima Kogan <dima@secretsauce.net>
10 ;; Keywords: languages c
11 ;; Homepage: https://github.com/dkogan/xcscope.el
12 ;; Package-Version: 1.0
13
14 ;; This file is not part of GNU Emacs.
15
16 ;;
17 ;; This program is free software; you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; any later version.
21 ;;
22 ;; This program is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 ;; GNU General Public License for more details.
26 ;;
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with GNU Emacs; see the file COPYING. If not, write to
29 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30 ;;
31
32 ;;; Commentary:
33 ;;
34 ;; This is a cscope interface for (X)Emacs.
35 ;; It currently runs under Unix only.
36 ;;
37 ;; Using cscope, you can easily search for where symbols are used and defined.
38 ;; Cscope is designed to answer questions like:
39 ;;
40 ;; Where is this variable used?
41 ;; What is the value of this preprocessor symbol?
42 ;; Where is this function in the source files?
43 ;; What functions call this function?
44 ;; What functions are called by this function?
45 ;; Where does the message "out of space" come from?
46 ;; Where is this source file in the directory structure?
47 ;; What files include this header file?
48 ;; Where was this variable assigned-to?
49 ;;
50 ;; Send comments to dima@secretsauce.net
51 ;;
52 ;;
53 ;;
54 ;; ***** INSTALLATION *****
55 ;;
56 ;; * NOTE: this interface currently runs under Unix only.
57 ;;
58 ;; Installation steps:
59 ;;
60 ;; 0. (It is, of course, assumed that cscope is already properly
61 ;; installed on the current system.)
62 ;;
63 ;; 1. Install xcscope.el through your system package manager, MELPA or by
64 ;; loading the file with
65 ;;
66 ;; (require 'xcscope)
67 ;;
68 ;; 2. Call (cscope-setup). This can go into the .emacs to always enable
69 ;; xcscope.el at emacs startup
70 ;;
71 ;; 3. If you intend to use xcscope.el often you can optionally edit your
72 ;; ~/.emacs file to add keybindings that reduce the number of keystrokes
73 ;; required. For example, the following will add "C-f#" keybindings, which
74 ;; are easier to type than the usual "C-c s" prefixed keybindings. Note
75 ;; that specifying "global-map" instead of "cscope-minor-mode-keymap" makes the
76 ;; keybindings available in all buffers:
77 ;;
78 ;; (define-key global-map [(control f3)] 'cscope-set-initial-directory)
79 ;; (define-key global-map [(control f4)] 'cscope-unset-initial-directory)
80 ;; (define-key global-map [(control f5)] 'cscope-find-this-symbol)
81 ;; (define-key global-map [(control f6)] 'cscope-find-global-definition)
82 ;; (define-key global-map [(control f7)]
83 ;; 'cscope-find-global-definition-no-prompting)
84 ;; (define-key global-map [(control f8)] 'cscope-pop-mark)
85 ;; (define-key global-map [(control f9)] 'cscope-history-forward-line)
86 ;; (define-key global-map [(control f10)] 'cscope-history-forward-file)
87 ;; (define-key global-map [(control f11)] 'cscope-history-backward-line)
88 ;; (define-key global-map [(control f12)] 'cscope-history-backward-file)
89 ;; (define-key global-map [(meta f9)] 'cscope-display-buffer)
90 ;; (define-key global-map [(meta f10)] 'cscope-display-buffer-toggle)
91 ;;
92 ;; 6. Restart (X)Emacs. That's it.
93 ;;
94 ;;
95 ;;
96 ;;
97 ;; ***** USING THIS MODULE *****
98 ;;
99 ;; * Basic usage:
100 ;;
101 ;; If all of your C/C++/lex/yacc source files are in the same
102 ;; directory, you can just start using this module. If your files are
103 ;; spread out over multiple directories, see "Advanced usage", below.
104 ;;
105 ;; Just edit a source file, and use the pull-down or pop-up (button 3)
106 ;; menus to select one of:
107 ;;
108 ;; Find symbol
109 ;; Find global definition
110 ;; Find called functions
111 ;; Find functions calling a function
112 ;; Find text string
113 ;; Find egrep pattern
114 ;; Find a file
115 ;; Find files #including a file
116 ;;
117 ;; The cscope database will be automatically created in the same
118 ;; directory as the source files (assuming that you've never used
119 ;; cscope before), and a buffer will pop-up displaying the results.
120 ;; You can then use button 2 (the middle button) on the mouse to edit
121 ;; the selected file, or you can move the text cursor over a selection
122 ;; and press [Enter].
123 ;;
124 ;; The third mouse button is bound to a popup menu for cscope. Shift-mouse
125 ;; button 3 invokes the last find command again. E.g. if you look for the symbol
126 ;; 'main' and afterwards you want to look for another symbol, just press Shift
127 ;; and click the third button.
128 ;;
129 ;; Each cscope search adds its results to the *cscope* buffer. These sets of
130 ;; results can be navigated and manupulated similar to patches in diff-mode.:
131 ;;
132 ;; - n/p navigates over individual results
133 ;; - k kills individual results
134 ;;
135 ;; - N/P or M-n/M-p navigates over file results
136 ;; - M-k kills file results
137 ;;
138 ;; - M-N/M-P navigates over result sets
139 ;; - M-K kills result sets
140 ;;
141 ;; - Navigation from outside the *cscope* buffer (C-c s n/p/N/P) is restricted to
142 ;; the result set at (point)
143 ;;
144 ;; Any result set in the *cscope* buffer can be re-run with the 'r' key.
145 ;;
146 ;;
147 ;; * Locating the cscope databases:
148 ;;
149 ;; This module will first use the variable, `cscope-database-regexps', to search
150 ;; for a suitable database directory. If a database location cannot be found
151 ;; using this variable then a search is begun at the variable,
152 ;; `cscope-initial-directory', if set. If not set and we're running this search
153 ;; from the *cscope* buffer, the search is begun from the directory of the
154 ;; search at point. Otherwise, the current directory is used. If the directory
155 ;; is not a cscope database directory then the directory's parent, parent's
156 ;; parent, etc. is searched until a cscope database directory is found, or the
157 ;; root directory is reached. If the root directory is reached, the current
158 ;; directory will be used.
159 ;;
160 ;; A cscope database directory is one in which EITHER a cscope database
161 ;; file (e.g., "cscope.out") OR a cscope file list (e.g.,
162 ;; "cscope.files") exists. If only "cscope.files" exists, the
163 ;; corresponding "cscope.out" will be automatically created by cscope
164 ;; when a search is done. By default, the cscope database file is called
165 ;; "cscope.out", but this can be changed (on a global basis) via the
166 ;; variable, `cscope-database-file'. There is limited support for cscope
167 ;; databases that are named differently than that given by
168 ;; `cscope-database-file', using the variable, `cscope-database-regexps'.
169 ;;
170 ;; Note that the variable, `cscope-database-regexps', is generally not
171 ;; needed, as the normal hierarchical database search is sufficient
172 ;; for placing and/or locating the cscope databases. However, there
173 ;; may be cases where it makes sense to place the cscope databases
174 ;; away from where the source files are kept; in this case, this
175 ;; variable is used to determine the mapping. One use for this
176 ;; variable is when you want to share the database file with other
177 ;; users; in this case, the database may be located in a directory
178 ;; separate from the source files.
179 ;;
180 ;; Setting the variable, `cscope-initial-directory', is useful when a
181 ;; search is to be expanded by specifying a cscope database directory
182 ;; that is a parent of the directory that this module would otherwise
183 ;; use. For example, consider a project that contains the following
184 ;; cscope database directories:
185 ;;
186 ;; /users/jdoe/sources
187 ;; /users/jdoe/sources/proj1
188 ;; /users/jdoe/sources/proj2
189 ;;
190 ;; If a search is initiated from a .c file in /users/jdoe/sources/proj1
191 ;; then (assuming the variable, `cscope-database-regexps', is not set)
192 ;; /users/jdoe/sources/proj1 will be used as the cscope data base directory.
193 ;; Only matches in files in /users/jdoe/sources/proj1 will be found. This
194 ;; can be remedied by typing "C-c s a" and then "M-del" to remove single
195 ;; path element in order to use a cscope database directory of
196 ;; /users/jdoe/sources. Normal searching can be restored by typing "C-c s A".
197 ;;
198 ;;
199 ;; * Keybindings:
200 ;;
201 ;; All keybindings use the "C-c s" prefix, but are usable only while
202 ;; editing a source file, or in the cscope results buffer:
203 ;;
204 ;; C-c s s Find symbol.
205 ;; C-c s = Find assignments to this symbol
206 ;; C-c s d Find global definition.
207 ;; C-c s g Find global definition (alternate binding).
208 ;; C-c s G Find global definition without prompting.
209 ;; C-c s c Find functions calling a function.
210 ;; C-c s C Find called functions (list functions called
211 ;; from a function).
212 ;; C-c s t Find text string.
213 ;; C-c s e Find egrep pattern.
214 ;; C-c s f Find a file.
215 ;; C-c s i Find files #including a file.
216 ;;
217 ;; These pertain to navigation through the search results:
218 ;;
219 ;; C-c s b Display *cscope* buffer.
220 ;; C-c s B Auto display *cscope* buffer toggle.
221 ;; C-c s n Next symbol.
222 ;; C-c s N Next file.
223 ;; C-c s p Previous symbol.
224 ;; C-c s P Previous file.
225 ;; C-c s u Pop mark.
226 ;;
227 ;; These pertain to setting and unsetting the variable,
228 ;; `cscope-initial-directory', (location searched for the cscope database
229 ;; directory):
230 ;;
231 ;; C-c s a Set initial directory.
232 ;; C-c s A Unset initial directory.
233 ;;
234 ;; These pertain to cscope database maintenance:
235 ;;
236 ;; C-c s L Create list of files to index.
237 ;; C-c s I Create list and index.
238 ;; C-c s E Edit list of files to index.
239 ;; C-c s W Locate this buffer's cscope directory
240 ;; ("W" --> "where").
241 ;; C-c s S Locate this buffer's cscope directory.
242 ;; (alternate binding: "S" --> "show").
243 ;; C-c s T Locate this buffer's cscope directory.
244 ;; (alternate binding: "T" --> "tell").
245 ;; C-c s D Dired this buffer's directory.
246 ;;
247 ;;
248 ;; * Advanced usage:
249 ;;
250 ;; If the source files are spread out over multiple directories,
251 ;; you've got a few choices:
252 ;;
253 ;; 1. If all of the directories exist below a common directory
254 ;; (without any extraneous, unrelated subdirectories), you can tell
255 ;; this module to place the cscope database into the top-level,
256 ;; common directory. This assumes that you do not have any cscope
257 ;; databases in any of the subdirectories. If you do, you should
258 ;; delete them; otherwise, they will take precedence over the
259 ;; top-level database.
260 ;;
261 ;; If you do have cscope databases in any subdirectory, the
262 ;; following instructions may not work right.
263 ;;
264 ;; It's pretty easy to tell this module to use a top-level, common
265 ;; directory:
266 ;;
267 ;; a. Make sure that the menu pick, "Cscope/Index recursively", is
268 ;; checked (the default value).
269 ;;
270 ;; b. Select the menu pick, "Cscope/Create list and index", and
271 ;; specify the top-level directory. This will index the sources
272 ;; in the background, so you can do other things if indexing
273 ;; takes a long time. A list of files to index will be created in
274 ;; "cscope.files", and the cscope database will be created in
275 ;; "cscope.out".
276 ;;
277 ;; Once this has been done, you can then use the menu picks
278 ;; (described in "Basic usage", above) to search for symbols.
279 ;;
280 ;; Note, however, that, if you add or delete source files, you'll
281 ;; have to either rebuild the database using the above procedure,
282 ;; or edit the file, "cscope.files" to add/delete the names of the
283 ;; source files. To edit this file, you can use the menu pick,
284 ;; "Cscope/Edit list of files to index".
285 ;;
286 ;;
287 ;; 2. If most of the files exist below a common directory, but a few
288 ;; are outside, you can use the menu pick, "Cscope/Create list of
289 ;; files to index", and specify the top-level directory. Make sure
290 ;; that "Cscope/Index recursively", is checked before you do so,
291 ;; though. You can then edit the list of files to index using the
292 ;; menu pick, "Cscope/Edit list of files to index". Just edit the
293 ;; list to include any additional source files not already listed.
294 ;;
295 ;; Once you've created, edited, and saved the list, you can then
296 ;; use the menu picks described under "Basic usage", above, to
297 ;; search for symbols. The first time you search, you will have to
298 ;; wait a while for cscope to fully index the source files, though.
299 ;; If you have a lot of source files, you may want to manually run
300 ;; cscope to build the database:
301 ;;
302 ;; cd top-level-directory # or wherever
303 ;; rm -f cscope.out # not always necessary
304 ;; cscope -b
305 ;;
306 ;;
307 ;; 3. If the source files are scattered in many different, unrelated
308 ;; places, you'll have to manually create cscope.files and put a
309 ;; list of all pathnames into it. Then build the database using:
310 ;;
311 ;; cd some-directory # wherever cscope.files exists
312 ;; rm -f cscope.out # not always necessary
313 ;; cscope -b
314 ;;
315 ;; Next, read the documentation for the variable,
316 ;; "cscope-database-regexps", and set it appropriately, such that
317 ;; the above-created cscope database will be referenced when you
318 ;; edit a related source file.
319 ;;
320 ;; Once this has been done, you can then use the menu picks
321 ;; described under "Basic usage", above, to search for symbols.
322 ;;
323 ;;
324 ;; * Interesting configuration variables:
325 ;;
326 ;; "cscope-truncate-lines"
327 ;; This is the value of `truncate-lines' to use in cscope
328 ;; buffers; the default is the current setting of
329 ;; `truncate-lines'. This variable exists because it can be
330 ;; easier to read cscope buffers with truncated lines, while
331 ;; other buffers do not have truncated lines.
332 ;;
333 ;; "cscope-use-relative-paths"
334 ;; If non-nil, use relative paths when creating the list of files
335 ;; to index. The path is relative to the directory in which the
336 ;; cscope database will be created. If nil, absolute paths will
337 ;; be used. Absolute paths are good if you plan on moving the
338 ;; database to some other directory (if you do so, you'll
339 ;; probably also have to modify `cscope-database-regexps').
340 ;; Absolute paths may also be good if you share the database file
341 ;; with other users (you'll probably want to specify some
342 ;; automounted network path for this).
343 ;;
344 ;; "cscope-index-recursively"
345 ;; If non-nil, index files in the current directory and all
346 ;; subdirectories. If nil, only files in the current directory
347 ;; are indexed. This variable is only used when creating the
348 ;; list of files to index, or when creating the list of files and
349 ;; the corresponding cscope database.
350 ;;
351 ;; "cscope-name-line-width"
352 ;; The width of the combined "function name:line number" field in
353 ;; the cscope results buffer. If negative, the field is
354 ;; left-justified.
355 ;;
356 ;; "cscope-option-...." Various options passed to the 'cscope' process. Controls
357 ;; things like include directories, database compression, database type,
358 ;; etc.
359 ;;
360 ;; "cscope-display-cscope-buffer"
361 ;; If non-nil, display the *cscope* buffer after each search
362 ;; (default). This variable can be set in order to reduce the
363 ;; number of keystrokes required to navigate through the matches.
364 ;;
365 ;; "cscope-database-regexps"
366 ;; List to force directory-to-cscope-database mappings.
367 ;; This is a list of `(REGEXP DBLIST [ DBLIST ... ])', where:
368 ;;
369 ;; REGEXP is a regular expression matched against the current buffer's
370 ;; current directory. The current buffer is typically some source file,
371 ;; and you're probably searching for some symbol in or related to this
372 ;; file. Basically, this regexp is used to relate the current directory
373 ;; to a cscope database. You need to start REGEXP with "^" if you want
374 ;; to match from the beginning of the current directory.
375 ;;
376 ;; DBLIST is a list that contains one or more of:
377 ;;
378 ;; ( DBDIR )
379 ;; ( DBDIR ( OPTIONS ) )
380 ;; ( t )
381 ;; t
382 ;;
383 ;; Here, DBDIR is a directory (or a file) that contains a cscope
384 ;; database. If DBDIR is a directory, then it is expected that the
385 ;; cscope database, if present, has the filename given by the variable,
386 ;; `cscope-database-file'; if DBDIR is a file, then DBDIR is the path
387 ;; name to a cscope database file (which does not have to be the same as
388 ;; that given by `cscope-database-file'). If only DBDIR is specified,
389 ;; then that cscope database will be searched without any additional
390 ;; cscope command-line options. If OPTIONS is given, then OPTIONS is a
391 ;; list of strings, where each string is a separate cscope command-line
392 ;; option.
393 ;;
394 ;; In the case of "( t )", this specifies that the search is to use the
395 ;; normal hierarchical database search. This option is used to
396 ;; explicitly search using the hierarchical database search either before
397 ;; or after other cscope database directories.
398 ;;
399 ;; If "t" is specified (not inside a list), this tells the searching
400 ;; mechanism to stop searching if a match has been found (at the point
401 ;; where "t" is encountered). This is useful for those projects that
402 ;; consist of many subprojects. You can specify the most-used
403 ;; subprojects first, followed by a "t", and then followed by a master
404 ;; cscope database directory that covers all subprojects. This will
405 ;; cause the most-used subprojects to be searched first (hopefully
406 ;; quickly), and the search will then stop if a match was found. If not,
407 ;; the search will continue using the master cscope database directory.
408 ;;
409 ;; Here, `cscope-database-regexps' is generally not used, as the normal
410 ;; hierarchical database search is sufficient for placing and/or locating
411 ;; the cscope databases. However, there may be cases where it makes
412 ;; sense to place the cscope databases away from where the source files
413 ;; are kept; in this case, this variable is used to determine the
414 ;; mapping.
415 ;;
416 ;; This module searches for the cscope databases by first using this
417 ;; variable; if a database location cannot be found using this variable,
418 ;; then the current directory is searched, then the parent, then the
419 ;; parent's parent, until a cscope database directory is found, or the
420 ;; root directory is reached. If the root directory is reached, the
421 ;; current directory will be used.
422 ;;
423 ;; A cscope database directory is one in which EITHER a cscope database
424 ;; file (e.g., "cscope.out") OR a cscope file list (e.g.,
425 ;; "cscope.files") exists. If only "cscope.files" exists, the
426 ;; corresponding "cscope.out" will be automatically created by cscope
427 ;; when a search is done. By default, the cscope database file is called
428 ;; "cscope.out", but this can be changed (on a global basis) via the
429 ;; variable, `cscope-database-file'. There is limited support for cscope
430 ;; databases that are named differently than that given by
431 ;; `cscope-database-file', using the variable, `cscope-database-regexps'.
432 ;;
433 ;; Here is an example of `cscope-database-regexps':
434 ;;
435 ;; (setq cscope-database-regexps
436 ;; '(
437 ;; ( "^/users/jdoe/sources/proj1"
438 ;; ( t )
439 ;; ( "/users/jdoe/sources/proj2")
440 ;; ( "/users/jdoe/sources/proj3/mycscope.out")
441 ;; ( "/users/jdoe/sources/proj4")
442 ;; t
443 ;; ( "/some/master/directory" ("-d" "-I/usr/local/include") )
444 ;; )
445 ;; ( "^/users/jdoe/sources/gnome/"
446 ;; ( "/master/gnome/database" ("-d") )
447 ;; )
448 ;; ))
449 ;;
450 ;; If the current buffer's directory matches the regexp,
451 ;; "^/users/jdoe/sources/proj1", then the following search will be
452 ;; done:
453 ;;
454 ;; 1. First, the normal hierarchical database search will be used to
455 ;; locate a cscope database.
456 ;;
457 ;; 2. Next, searches will be done using the cscope database
458 ;; directories, "/users/jdoe/sources/proj2",
459 ;; "/users/jdoe/sources/proj3/mycscope.out", and
460 ;; "/users/jdoe/sources/proj4". Note that, instead of the file,
461 ;; "cscope.out", the file, "mycscope.out", will be used in the
462 ;; directory "/users/jdoe/sources/proj3".
463 ;;
464 ;; 3. If a match was found, searching will stop.
465 ;;
466 ;; 4. If a match was not found, searching will be done using
467 ;; "/some/master/directory", and the command-line options "-d"
468 ;; and "-I/usr/local/include" will be passed to cscope.
469 ;;
470 ;; If the current buffer's directory matches the regexp,
471 ;; "^/users/jdoe/sources/gnome", then the following search will be
472 ;; done:
473 ;;
474 ;; The search will be done only using the directory,
475 ;; "/master/gnome/database". The "-d" option will be passed to
476 ;; cscope.
477 ;;
478 ;; If the current buffer's directory does not match any of the above
479 ;; regexps, then only the normal hierarchical database search will be
480 ;; done.
481 ;;
482 ;;
483 ;; * Other notes:
484 ;;
485 ;; 1. This module is called, "xcscope", because someone else has
486 ;; already written a "cscope.el" (although it's quite old).
487 ;;
488 ;;
489 ;; * KNOWN BUGS:
490 ;;
491 ;; 1. Cannot handle whitespace in directory or file names.
492 ;;
493 ;; 2. The support for cscope databases different from that specified by
494 ;; `cscope-database-file' is quirky. If the file does not exist, it
495 ;; will not be auto-created (unlike files names by
496 ;; `cscope-database-file'). You can manually force the file to be
497 ;; created by using touch(1) to create a zero-length file; the
498 ;; database will be created the next time a search is done.
499 ;;
500 ;;; Code:
501
502 (require 'easymenu)
503
504
505 (defgroup cscope nil
506 "Cscope interface for (X)Emacs.
507 Using cscope, you can easily search for where symbols are used and defined.
508 It is designed to answer questions like:
509
510 Where is this variable used?
511 What is the value of this preprocessor symbol?
512 Where is this function in the source files?
513 What functions call this function?
514 What functions are called by this function?
515 Where does the message \"out of space\" come from?
516 Where is this source file in the directory structure?
517 What files include this header file?
518 "
519 :prefix "cscope-"
520 :group 'tools)
521
522 (defconst cscope-database-directory-prompt "Database directory")
523
524 (defconst cscope-running-in-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
525
526 (defcustom cscope-option-include-directories nil
527 "The -I option in cscope: add these directories to the list of
528 search paths for #include, similar to the -I gcc option"
529 :type '(repeat directory)
530 :group 'cscope)
531
532 (defcustom cscope-option-disable-compression nil
533 "The -c option in cscope: use an uncompressed, ASCII database"
534 :type 'boolean
535 :group 'cscope)
536
537 (defcustom cscope-option-kernel-mode nil
538 "The -k option in cscope: use no system-wide include paths.
539 Useful for self-contained codebases, such as a kernel"
540 :type 'boolean
541 :group 'cscope)
542
543 (defcustom cscope-option-use-inverted-index nil
544 "The -q option in cscope: use an inverted database index. Takes
545 longer to build, but results in faster lookups. Useful for very
546 large codebases"
547 :type 'boolean
548 :group 'cscope)
549
550 (defcustom cscope-option-do-not-update-database nil
551 "The -d option in cscope: never check and/or update the cscope
552 database when searching. Beware of setting this to non-nil, as
553 this will disable automatic database creation, updating, and
554 maintenance."
555 :type 'boolean
556 :group 'cscope)
557
558 (defcustom cscope-option-other nil
559 "Any indexing/lookup options to pass to cscope. These are used
560 both when building the database and when searching. Note that the
561 most common options have specific customization in the
562 cscope-option-* variables, and it is preferable to use those"
563 :type '(repeat string)
564 :group 'cscope)
565
566
567 (defcustom cscope-database-regexps nil
568 "List to force directory-to-cscope-database mappings.
569 This is a list of `(REGEXP DBLIST [ DBLIST ... ])', where:
570
571 REGEXP is a regular expression matched against the current buffer's
572 current directory. The current buffer is typically some source file,
573 and you're probably searching for some symbol in or related to this
574 file. Basically, this regexp is used to relate the current directory
575 to a cscope database. You need to start REGEXP with \"^\" if you want
576 to match from the beginning of the current directory.
577
578 DBLIST is a list that contains one or more of:
579
580 ( DBDIR )
581 ( DBDIR ( OPTIONS ) )
582 ( t )
583 t
584
585 Here, DBDIR is a directory (or a file) that contains a cscope database.
586 If DBDIR is a directory, then it is expected that the cscope database,
587 if present, has the filename given by the variable,
588 `cscope-database-file'; if DBDIR is a file, then DBDIR is the path name
589 to a cscope database file (which does not have to be the same as that
590 given by `cscope-database-file'). If only DBDIR is specified, then that
591 cscope database will be searched without any additional cscope
592 command-line options. If OPTIONS is given, then OPTIONS is a list of
593 strings, where each string is a separate cscope command-line option.
594
595 In the case of \"( t )\", this specifies that the search is to use the
596 normal hierarchical database search. This option is used to
597 explicitly search using the hierarchical database search either before
598 or after other cscope database directories.
599
600 If \"t\" is specified (not inside a list), this tells the searching
601 mechanism to stop searching if a match has been found (at the point
602 where \"t\" is encountered). This is useful for those projects that
603 consist of many subprojects. You can specify the most-used
604 subprojects first, followed by a \"t\", and then followed by a master
605 cscope database directory that covers all subprojects. This will
606 cause the most-used subprojects to be searched first (hopefully
607 quickly), and the search will then stop if a match was found. If not,
608 the search will continue using the master cscope database directory.
609
610 Here, `cscope-database-regexps' is generally not used, as the normal
611 hierarchical database search is sufficient for placing and/or locating
612 the cscope databases. However, there may be cases where it makes
613 sense to place the cscope databases away from where the source files
614 are kept; in this case, this variable is used to determine the
615 mapping.
616
617 This module searches for the cscope databases by first using this
618 variable; if a database location cannot be found using this variable,
619 then the current directory is searched, then the parent, then the
620 parent's parent, until a cscope database directory is found, or the
621 root directory is reached. If the root directory is reached, the
622 current directory will be used.
623
624 A cscope database directory is one in which EITHER a cscope database
625 file (e.g., \"cscope.out\") OR a cscope file list (e.g.,
626 \"cscope.files\") exists. If only \"cscope.files\" exists, the
627 corresponding \"cscope.out\" will be automatically created by cscope
628 when a search is done. By default, the cscope database file is called
629 \"cscope.out\", but this can be changed (on a global basis) via the
630 variable, `cscope-database-file'. There is limited support for cscope
631 databases that are named differently than that given by
632 `cscope-database-file', using the variable, `cscope-database-regexps'.
633
634 Here is an example of `cscope-database-regexps':
635
636 (setq cscope-database-regexps
637 '(
638 ( \"^/users/jdoe/sources/proj1\"
639 ( t )
640 ( \"/users/jdoe/sources/proj2\")
641 ( \"/users/jdoe/sources/proj3/mycscope.out\")
642 ( \"/users/jdoe/sources/proj4\")
643 t
644 ( \"/some/master/directory\" (\"-d\" \"-I/usr/local/include\") )
645 )
646 ( \"^/users/jdoe/sources/gnome/\"
647 ( \"/master/gnome/database\" (\"-d\") )
648 )
649 ))
650
651 If the current buffer's directory matches the regexp,
652 \"^/users/jdoe/sources/proj1\", then the following search will be
653 done:
654
655 1. First, the normal hierarchical database search will be used to
656 locate a cscope database.
657
658 2. Next, searches will be done using the cscope database
659 directories, \"/users/jdoe/sources/proj2\",
660 \"/users/jdoe/sources/proj3/mycscope.out\", and
661 \"/users/jdoe/sources/proj4\". Note that, instead of the file,
662 \"cscope.out\", the file, \"mycscope.out\", will be used in the
663 directory \"/users/jdoe/sources/proj3\".
664
665 3. If a match was found, searching will stop.
666
667 4. If a match was not found, searching will be done using
668 \"/some/master/directory\", and the command-line options \"-d\"
669 and \"-I/usr/local/include\" will be passed to cscope.
670
671 If the current buffer's directory matches the regexp,
672 \"^/users/jdoe/sources/gnome\", then the following search will be
673 done:
674
675 The search will be done only using the directory,
676 \"/master/gnome/database\". The \"-d\" option will be passed to
677 cscope.
678
679 If the current buffer's directory does not match any of the above
680 regexps, then only the normal hierarchical database search will be
681 done.
682
683 "
684 :type '(repeat (list :format "%v"
685 (choice :value ""
686 (regexp :tag "Buffer regexp")
687 string)
688 (choice :value ""
689 (directory :tag "Cscope database directory")
690 string)
691 (string :value ""
692 :tag "Optional cscope command-line arguments")
693 ))
694 :group 'cscope)
695 (defcustom cscope-name-line-width -30
696 "The width of the combined \"function name:line number\" field in the
697 cscope results buffer. If negative, the field is left-justified."
698 :type 'integer
699 :group 'cscope)
700
701
702 (defcustom cscope-truncate-lines truncate-lines
703 "The value of `truncate-lines' to use in cscope buffers.
704 This variable exists because it can be easier to read cscope buffers
705 with truncated lines, while other buffers do not have truncated lines."
706 :type 'boolean
707 :group 'cscope)
708
709
710 (defcustom cscope-display-times t
711 "If non-nil, display how long each search took.
712 The elasped times are in seconds. Floating-point support is required
713 for this to work."
714 :type 'boolean
715 :group 'cscope)
716
717 (defcustom cscope-max-cscope-buffer-size 1000000
718 "If >0, limit the size of the *cscope* buffer. Only the
719 'cscope-max-cscope-buffer-size' bytes at the end are kept,
720 rounded up to keep whole sets of cscope output"
721 :type 'integer
722 :group 'cscope)
723
724 (defcustom cscope-program "cscope"
725 "The pathname of the cscope executable to use. This could be a
726 string, or a function. If a function, then this is called every
727 time the program path is needed to retrieve the path. The
728 function takes no arguments, but can use variables such as
729 `default-directory'. This is useful to find cscope in different
730 places on different machines when using TRAMP."
731 :type '(choice
732 (string :tag "Program path")
733 (function :tag "Function that returns the program path"))
734 :group 'cscope)
735
736
737 (defcustom cscope-index-file "cscope.files"
738 "The name of the cscope file list file."
739 :type 'string
740 :group 'cscope)
741
742
743 (defcustom cscope-database-file "cscope.out"
744 "The name of the cscope database file."
745 :type 'string
746 :group 'cscope)
747
748
749 (defcustom cscope-edit-single-match t
750 "If non-nil and only one match is output, edit the matched location."
751 :type 'boolean
752 :group 'cscope)
753
754
755 (defcustom cscope-display-cscope-buffer t
756 "If non-nil automatically display the *cscope* buffer after each search."
757 :type 'boolean
758 :group 'cscope)
759
760
761 (defcustom cscope-stop-at-first-match-dir nil
762 "If non-nil, stop searching through multiple databases if a match is found.
763 This option is useful only if multiple cscope database directories are being
764 used. When multiple databases are searched, setting this variable to non-nil
765 will cause searches to stop when a search outputs anything; no databases after
766 this one will be searched."
767 :type 'boolean
768 :group 'cscope)
769
770
771 (defcustom cscope-use-relative-paths t
772 "If non-nil, use relative paths when creating the list of files to index.
773 The path is relative to the directory in which the cscope database
774 will be created. If nil, absolute paths will be used. Absolute paths
775 are good if you plan on moving the database to some other directory
776 (if you do so, you'll probably also have to modify
777 \`cscope-database-regexps\'). Absolute paths may also be good if you
778 share the database file with other users (you\'ll probably want to
779 specify some automounted network path for this)."
780 :type 'boolean
781 :group 'cscope)
782
783
784 (defcustom cscope-index-recursively t
785 "If non-nil, index files in the current directory and all subdirectories.
786 If nil, only files in the current directory are indexed. This
787 variable is only used when creating the list of files to index, or
788 when creating the list of files and the corresponding cscope database."
789 :type 'boolean
790 :group 'cscope)
791
792 (defcustom cscope-indexer-ignored-directories '("CVS"
793 "RCS"
794 "SCCS"
795 ".git"
796 ".hg"
797 ".bzr"
798 ".cdv"
799 ".pc"
800 ".svn"
801 "_MTN"
802 "_darcs"
803 "_sgbak"
804 "debian")
805 "List of directory names that should be ignored when building a
806 cscope index. These are mostly version-control directories"
807 :type '(repeat string)
808 :group 'cscope)
809
810 (defcustom cscope-indexer-suffixes '("*.[chly]"
811 "*.[ch]xx"
812 "*.[ch]pp"
813 "*.cc"
814 "*.hh")
815 "List of file suffixes to index. By default these are C, C++,
816 Lex and Yacc source. These are globs accepted by 'find -iname'"
817 :type '(repeat string)
818 :group 'cscope)
819
820 (defcustom cscope-symbol-chars "A-Za-z0-9_"
821 "A string containing legal characters in a symbol.
822 The current syntax table should really be used for this."
823 :type 'string
824 :group 'cscope)
825
826
827 (defcustom cscope-filename-chars "-.,/A-Za-z0-9_~!@#$%&+=\\\\"
828 "A string containing legal characters in a symbol.
829 The current syntax table should really be used for this."
830 :type 'string
831 :group 'cscope)
832
833
834 (defcustom cscope-allow-arrow-overlays t
835 "If non-nil, use an arrow overlay to show target lines.
836 Arrow overlays are only used when the following functions are used:
837
838 cscope-show-entry-other-window
839 cscope-show-next-entry-other-window
840 cscope-show-prev-entry-other-window
841
842 The arrow overlay is removed when other cscope functions are used.
843 Note that the arrow overlay is not an actual part of the text, and can
844 be removed by quitting the cscope buffer."
845 :type 'boolean
846 :group 'cscope)
847
848
849 (defcustom cscope-overlay-arrow-string "=>"
850 "The overlay string to use when displaying arrow overlays."
851 :type 'string
852 :group 'cscope)
853
854
855 (defcustom cscope-close-window-after-select nil
856 "If non-nil close the window showing the cscope buffer after an entry has been selected."
857 :type 'boolean
858 :group 'cscope)
859
860
861 (defvar cscope-minor-mode-hooks nil
862 "List of hooks to call when entering cscope-minor-mode.")
863
864 (defvar cscope-display-buffer-args
865 (and (not cscope-running-in-xemacs)
866 (>= emacs-major-version 24)
867 '((display-buffer-use-some-window (inhibit-same-window . t))))
868 "Default arguments to `display-buffer'. This applies to ACTION
869 and FRAME arguments of the newer `display-buffer' in >= GNU Emacs
870 24. This controls how and where the *cscope* buffer is popped up.
871 By default I do not use the current window (so the *cscope*
872 buffer stays active) and I try not to make new windows.")
873
874 (defun cscope--get-cscope-program ()
875 "Retrieves the path to the cscope program. This is the value of
876 the `cscope-program' variable, if it is a string, or the value
877 returned by the `cscope-program' function, if it is a function."
878 (let ((program
879 (cond
880 ((stringp cscope-program) cscope-program)
881 ((functionp cscope-program) (funcall cscope-program))
882 (t (error "cscope-program must be a string or function: %s"
883 cscope-program)))))
884 (or program (error "cscope-program is nil!"))))
885
886
887 (defun cscope-display-buffer-wrapper (buffer)
888 "Calls `display-buffer' using
889 `cscope-display-buffer-args'"
890 (apply 'display-buffer buffer cscope-display-buffer-args))
891
892
893 (defconst cscope-result-separator
894 "===============================================================================\n"
895 "Line of text to use as a visual separator.
896 Must end with a newline. Must work as a regex without quoting")
897
898 (defconst cscope-file-separator-start-regex
899 "\\*\\*\\* .*:\n"
900 "Regex to match a file-start separator. This has to match the
901 '***' that xcscope.el normally outputs. This is assumed to appear
902 at the start of a line, so the leading ^ must be omitted")
903
904 (defconst cscope-file-separator-end-regex
905 "\n"
906 "Regex to match a file-end separator. This is just an empty
907 line, and this has to match what xcscope.el normally outputs in
908 its 'cscope-process-filter'. This is assumed to appear at the
909 start of a line, so the leading ^ must be omitted")
910
911 ;;;;
912 ;;;; Faces for fontification
913 ;;;;
914
915 (defcustom cscope-use-face t
916 "Whether to use text highlighting (like font-lock) or not."
917 :group 'cscope
918 :type '(boolean))
919
920
921 (defface cscope-file-face
922 '((((class color) (background dark))
923 (:foreground "yellow"))
924 (((class color) (background light))
925 (:foreground "blue"))
926 (t (:bold t)))
927 "Face used to highlight file name in the *cscope* buffer."
928 :group 'cscope)
929
930
931 (defface cscope-function-face
932 '((((class color) (background dark))
933 (:foreground "cyan"))
934 (((class color) (background light))
935 (:foreground "magenta"))
936 (t (:bold t)))
937 "Face used to highlight function name in the *cscope* buffer."
938 :group 'cscope)
939
940
941 (defface cscope-line-number-face
942 '((((class color) (background dark))
943 (:foreground "red"))
944 (((class color) (background light))
945 (:foreground "red"))
946 (t (:bold t)))
947 "Face used to highlight line number in the *cscope* buffer."
948 :group 'cscope)
949
950 (defface cscope-mouse-face
951 '((((class color) (background dark))
952 (:foreground "white" :background "blue"))
953 (((class color) (background light))
954 (:foreground "white" :background "blue"))
955 (t (:bold nil)))
956 "Face used when mouse pointer is within the region of an entry."
957 :group 'cscope)
958
959 (defface cscope-separator-face
960 '((((class color) (background dark))
961 (:bold t :overline t :underline t :foreground "red"))
962 (((class color) (background light))
963 (:bold t :overline t :underline t :foreground "red"))
964 (t (:bold t)))
965 "Face used to highlight the separator in the *cscope* buffer."
966 :group 'cscope)
967
968 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
969 ;; Probably, nothing user-customizable past this point.
970 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
971 (defconst cscope-start-file-process (if cscope-running-in-xemacs 'start-process 'start-file-process)
972 "The function used to launch external processes. Xemacs doesn't
973 have full TRAMP support here, so the less featureful function is
974 selected for it")
975
976 (defvar cscope-list-entry-keymap
977 (let ((map (make-keymap)))
978 (suppress-keymap map)
979 ;; The following section does not appear in the "Cscope" menu.
980 (if cscope-running-in-xemacs
981 (progn
982 (define-key map [button2] 'cscope-mouse-select-entry-other-window)
983 (define-key map [(shift button2)] 'cscope-mouse-select-entry-inplace))
984 (define-key map [mouse-2] 'cscope-mouse-select-entry-other-window)
985 (define-key map [S-mouse-2] 'cscope-mouse-select-entry-inplace))
986
987 ;; \r is for the text-mode console emacs
988 (define-key map [return] 'cscope-select-entry-other-window)
989 (define-key map "\r" 'cscope-select-entry-other-window)
990
991 ;; this works for the graphics emacsen-only. Default xterm on Debian does
992 ;; not know how to see this key combination
993 (define-key map (kbd "<S-return>") 'cscope-select-entry-inplace)
994
995 (define-key map " " 'cscope-show-entry-other-window)
996 (define-key map "o" 'cscope-select-entry-one-window)
997 (define-key map "q" 'cscope-bury-buffer)
998 (define-key map "Q" 'cscope-quit)
999 (define-key map "h" 'cscope-help)
1000 (define-key map "?" 'cscope-help)
1001 ;; The following line corresponds to be beginning of the "Cscope" menu.
1002 (define-key map "s" 'cscope-find-this-symbol)
1003 (define-key map "d" 'cscope-find-this-symbol)
1004 (define-key map "g" 'cscope-find-global-definition)
1005 (define-key map "G" 'cscope-find-global-definition-no-prompting)
1006 (define-key map "=" 'cscope-find-assignments-to-this-symbol)
1007 (define-key map "c" 'cscope-find-functions-calling-this-function)
1008 (define-key map "C" 'cscope-find-called-functions)
1009 (define-key map "t" 'cscope-find-this-text-string)
1010 (define-key map "e" 'cscope-find-egrep-pattern)
1011 (define-key map "f" 'cscope-find-this-file)
1012 (define-key map "i" 'cscope-find-files-including-file)
1013 ;; --- (The '---' indicates that this line corresponds to a menu separator.)
1014 (define-key map (kbd "p") 'cscope-history-backward-line)
1015 (define-key map (kbd "M-p") 'cscope-history-backward-file)
1016 (define-key map (kbd "P") 'cscope-history-backward-file)
1017 (define-key map (kbd "M-P") 'cscope-history-backward-result)
1018 (define-key map (kbd "n") 'cscope-history-forward-line)
1019 (define-key map (kbd "M-n") 'cscope-history-forward-file)
1020 (define-key map (kbd "N") 'cscope-history-forward-file)
1021 (define-key map (kbd "M-N") 'cscope-history-forward-result)
1022 (define-key map (kbd "k") 'cscope-history-kill-line)
1023 (define-key map (kbd "M-k") 'cscope-history-kill-file)
1024 (define-key map (kbd "M-K") 'cscope-history-kill-result)
1025 (define-key map "u" 'cscope-pop-mark)
1026 ;; ---
1027 (define-key map "r" 'cscope-rerun-search-at-point)
1028 ;; ---
1029 (define-key map "a" 'cscope-set-initial-directory)
1030 (define-key map "A" 'cscope-unset-initial-directory)
1031 ;; ---
1032 (define-key map "L" 'cscope-create-list-of-files-to-index)
1033 (define-key map "I" 'cscope-index-files)
1034 (define-key map "E" 'cscope-edit-list-of-files-to-index)
1035 (define-key map "W" 'cscope-tell-user-about-directory)
1036 (define-key map "S" 'cscope-tell-user-about-directory)
1037 (define-key map "T" 'cscope-tell-user-about-directory)
1038 (define-key map "D" 'cscope-dired-directory)
1039 ;; The previous line corresponds to be end of the "Cscope" menu.
1040 map)
1041 "The *cscope* buffer keymap")
1042
1043
1044 (defvar cscope-list-entry-hook nil
1045 "Hook run after cscope-list-entry-mode entered.")
1046
1047
1048 (defun cscope-list-entry-mode ()
1049 "Major mode for jumping/showing entry from the list in the *cscope* buffer.
1050
1051 \\{cscope-list-entry-keymap}"
1052 (use-local-map cscope-list-entry-keymap)
1053 (easy-menu-add cscope-buffer-menu cscope-list-entry-keymap)
1054 (setq mode-name "cscope"
1055 major-mode 'cscope-list-entry-mode
1056 overlay-arrow-string cscope-overlay-arrow-string)
1057
1058 (add-hook 'kill-buffer-hook 'cscope-cleanup-overlay-arrow)
1059 (run-hooks 'cscope-list-entry-hook))
1060
1061 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1062
1063 (defvar cscope-output-buffer-name "*cscope*"
1064 "The name of the cscope output buffer.")
1065
1066
1067 (defvar cscope-info-buffer-name "*cscope-info*"
1068 "The name of the cscope information buffer.")
1069
1070
1071 (defvar cscope-process nil
1072 "The current cscope process.")
1073 (make-variable-buffer-local 'cscope-process)
1074
1075
1076 (defvar cscope-process-output nil
1077 "A buffer for holding partial cscope process output.")
1078 (make-variable-buffer-local 'cscope-process-output)
1079
1080 (defvar cscope-last-output-point nil
1081 "Location of the last output from the process filter. Normally
1082 this is equivalent to (process-mark cscope-process), but this is
1083 broken in xemacs in the sentinel after the process has
1084 terminated. Also, this is (point-max) unless we're re-running a
1085 search in the middle of the *cscope* buffer")
1086
1087
1088 (defvar cscope-command-args nil
1089 "Internal variable for holding major command args to pass to cscope.")
1090 (make-variable-buffer-local 'cscope-command-args)
1091
1092
1093 (defvar cscope-start-directory nil
1094 "Internal variable used to save the initial start directory.
1095 The results buffer gets reset to this directory when a search has
1096 completely finished.")
1097 (make-variable-buffer-local 'cscope-start-directory)
1098
1099
1100 (defvar cscope-search-list nil
1101 "A list of (DIR . FLAGS) entries.
1102 This is a list of database directories to search. Each entry in the list
1103 is a (DIR . FLAGS) cell. DIR is the directory to search, and FLAGS are the
1104 flags to pass to cscope when using this database directory. FLAGS can be
1105 nil (meaning, \"no flags\").")
1106 (make-variable-buffer-local 'cscope-search-list)
1107
1108
1109 (defvar cscope-searched-dirs nil
1110 "The list of database directories already searched.")
1111 (make-variable-buffer-local 'cscope-searched-dirs)
1112
1113 (defvar cscope-last-file nil
1114 "The file referenced by the last line of cscope process output.")
1115 (make-variable-buffer-local 'cscope-last-file)
1116
1117
1118 (defvar cscope-start-time nil
1119 "The search start time, in seconds.")
1120 (make-variable-buffer-local 'cscope-start-time)
1121
1122
1123 (defvar cscope-first-match-point nil
1124 "Buffer location of the first match.")
1125 (make-variable-buffer-local 'cscope-first-match-point)
1126
1127
1128 (defvar cscope-output-start nil
1129 "The point location of the start of a search's output.")
1130 (make-variable-buffer-local 'cscope-output-start)
1131
1132
1133 (defvar cscope-matched-multiple nil
1134 "Non-nil if cscope output multiple matches.")
1135 (make-variable-buffer-local 'cscope-matched-multiple)
1136
1137
1138 (defvar cscope-stop-at-first-match-dir-meta nil
1139 "")
1140 (make-variable-buffer-local 'cscope-stop-at-first-match-dir-meta)
1141
1142
1143 (defvar cscope-fuzzy-search-range 1000
1144 "How far the point should be adjusted if the symbol is not on the line
1145 specified by the cscope database.")
1146
1147 (defvar cscope-previous-user-search nil
1148 "A form that describes the last search that was executed. For
1149 instance if the last search was to find all uses of the symbol
1150 \"N\", this variable would be set to '(cscope-find-this-symbol
1151 \"N\")")
1152
1153 (defvar cscope-marker nil
1154 "The location from which cscope was invoked.")
1155
1156
1157 (defvar cscope-marker-window nil
1158 "The window which should contain cscope-marker. This is the window from
1159 which cscope-marker is set when searches are launched from the *cscope*
1160 buffer.")
1161
1162
1163 (defvar cscope-marker-ring-length 16
1164 "Length of the cscope marker ring.")
1165
1166
1167 (defvar cscope-marker-ring (make-ring cscope-marker-ring-length)
1168 "Ring of markers which are locations from which cscope was invoked.")
1169
1170
1171 (defvar cscope-initial-directory nil
1172 "When set the directory in which searches for the cscope database
1173 directory should begin.")
1174
1175 (defvar cscope-prompt-minibuffer-history nil
1176 "The history of terms we searched for. This is one common
1177 history for ALL search types.")
1178
1179 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1180
1181 (defvar cscope-command-map
1182 (let ((map (make-sparse-keymap)))
1183 ;; The following line corresponds to be beginning of the "Cscope" menu.
1184 (define-key map "s" 'cscope-find-this-symbol)
1185 (define-key map "d" 'cscope-find-global-definition)
1186 (define-key map "g" 'cscope-find-global-definition)
1187 (define-key map "G" 'cscope-find-global-definition-no-prompting)
1188 (define-key map "=" 'cscope-find-assignments-to-this-symbol)
1189 (define-key map "c" 'cscope-find-functions-calling-this-function)
1190 (define-key map "C" 'cscope-find-called-functions)
1191 (define-key map "t" 'cscope-find-this-text-string)
1192 (define-key map "e" 'cscope-find-egrep-pattern)
1193 (define-key map "f" 'cscope-find-this-file)
1194 (define-key map "i" 'cscope-find-files-including-file)
1195 ;; --- (The '---' indicates that this line corresponds to a menu separator.)
1196 (define-key map "b" 'cscope-display-buffer)
1197 (define-key map "B" 'cscope-display-buffer-toggle)
1198 (define-key map "n" 'cscope-history-forward-line-current-result)
1199 (define-key map "N" 'cscope-history-forward-file-current-result)
1200 (define-key map "p" 'cscope-history-backward-line-current-result)
1201 (define-key map "P" 'cscope-history-backward-file-current-result)
1202 (define-key map "u" 'cscope-pop-mark)
1203 ;; ---
1204 (define-key map "a" 'cscope-set-initial-directory)
1205 (define-key map "A" 'cscope-unset-initial-directory)
1206 ;; ---
1207 (define-key map "L" 'cscope-create-list-of-files-to-index)
1208 (define-key map "I" 'cscope-index-files)
1209 (define-key map "E" 'cscope-edit-list-of-files-to-index)
1210 (define-key map "W" 'cscope-tell-user-about-directory)
1211 (define-key map "S" 'cscope-tell-user-about-directory)
1212 (define-key map "T" 'cscope-tell-user-about-directory)
1213 (define-key map "D" 'cscope-dired-directory)
1214 ;; The previous line corresponds to be end of the "Cscope" menu.
1215 map)
1216 "The keymap used by cscope. This is defined relative to
1217 `cscope-keymap-prefix'")
1218
1219 (defcustom cscope-keymap-prefix "\C-cs"
1220 "Prefix for key bindings of `cscope-minor-mode'.
1221
1222 Changing this variable outside Customize does not have any
1223 effect. To change the keymap prefix from Lisp, you need to
1224 explicitly re-define the prefix key:
1225
1226 (define-key cscope-minor-mode-keymap cscope-keymap-prefix nil)
1227 (setq cscope-keymap-prefix (kbd \"C-c ,\"))
1228 (define-key cscope-minor-mode-keymap cscope-keymap-prefix
1229 cscope-command-map)"
1230 :group 'cscope
1231 :type 'string
1232 :risky t
1233 :set
1234 (lambda (variable key)
1235 (when (and (boundp variable) (boundp 'cscope-minor-mode-keymap))
1236 (define-key cscope-minor-mode-keymap (symbol-value variable) nil)
1237 (define-key cscope-minor-mode-keymap key cscope-command-map))
1238 (set-default variable key)))
1239
1240 (defvar cscope-minor-mode-keymap
1241 (let ((map (make-sparse-keymap)))
1242
1243 ;; xemacs has various issues with (cscope-mouse-popup-menu-or-search), so I
1244 ;; don't use that function for xemacs. Its popup menu support won't be as
1245 ;; good (cscope will still prompt for the search term)
1246 (if cscope-running-in-xemacs
1247 (progn
1248 (define-key map [(shift button3)] 'cscope-mouse-search-again))
1249 (define-key map [mouse-3] 'cscope-mouse-popup-menu-or-search)
1250 (define-key map [S-mouse-3] 'cscope-mouse-search-again))
1251
1252 (define-key map cscope-keymap-prefix cscope-command-map)
1253
1254 map)
1255 "The global cscope keymap")
1256
1257 (let ((menu-before
1258 '([ "Find symbol" cscope-find-this-symbol t ]
1259 [ "Find global definition" cscope-find-global-definition t ]
1260 [ "Find global definition no prompting"
1261 cscope-find-global-definition-no-prompting t ]
1262 [ "Find assignments to symbol"
1263 cscope-find-assignments-to-this-symbol t ]
1264 [ "Find functions calling a function"
1265 cscope-find-functions-calling-this-function t ]
1266 [ "Find called functions" cscope-find-called-functions t ]
1267 [ "Find text string" cscope-find-this-text-string t ]
1268 [ "Find egrep pattern" cscope-find-egrep-pattern t ]
1269 [ "Find a file" cscope-find-this-file t ]
1270 [ "Find files #including a file"
1271 cscope-find-files-including-file t ]
1272 "-----------"))
1273
1274 (menu-only-global
1275 '([ "Display *cscope* buffer" cscope-display-buffer t ]
1276 "-----------"
1277 [ "Next symbol" cscope-history-forward-line-current-result t ]
1278 [ "Next file" cscope-history-forward-file-current-result t ]
1279 [ "Previous symbol" cscope-history-backward-line-current-result t ]
1280 [ "Previous file" cscope-history-backward-file-current-result t ]
1281 [ "Pop mark" cscope-pop-mark t ]
1282 "-----------"
1283 ))
1284
1285 (menu-only-cscope
1286 '([ "Next symbol" cscope-history-forward-line t ]
1287 [ "Next file" cscope-history-forward-file t ]
1288 [ "Next result" cscope-history-forward-result t ]
1289 [ "Previous symbol" cscope-history-backward-line t ]
1290 [ "Previous file" cscope-history-backward-file t ]
1291 [ "Previous result" cscope-history-backward-result t ]
1292 [ "Kill symbol" cscope-history-kill-line t ]
1293 [ "Kill file" cscope-history-kill-file t ]
1294 [ "Kill result" cscope-history-kill-result t ]
1295 [ "Pop mark" cscope-pop-mark t ]
1296 "-----------"
1297 [ "Rerun search at point" cscope-rerun-search-at-point t ]
1298 "-----------"
1299 ))
1300
1301 (menu-after
1302 '(( "Cscope Database"
1303 [ "Set initial directory"
1304 cscope-set-initial-directory t ]
1305 [ "Unset initial directory"
1306 cscope-unset-initial-directory t ]
1307 "-----------"
1308 [ "Create list of files to index"
1309 cscope-create-list-of-files-to-index t ]
1310 [ "Create list and index"
1311 cscope-index-files t ]
1312 [ "Edit list of files to index"
1313 cscope-edit-list-of-files-to-index t ]
1314 [ "Locate this buffer's cscope directory"
1315 cscope-tell-user-about-directory t ]
1316 [ "Dired this buffer's cscope directory"
1317 cscope-dired-directory t ]
1318 )
1319 "-----------"
1320 ( "Options"
1321 [ "Auto close *cscope* buffer"
1322 (setq cscope-close-window-after-select
1323 (not cscope-close-window-after-select))
1324 :style toggle :selected cscope-close-window-after-select ]
1325 [ "Auto edit single match"
1326 (setq cscope-edit-single-match
1327 (not cscope-edit-single-match))
1328 :style toggle :selected cscope-edit-single-match ]
1329 [ "Auto display *cscope* buffer"
1330 (setq cscope-display-cscope-buffer
1331 (not cscope-display-cscope-buffer))
1332 :style toggle :selected cscope-display-cscope-buffer ]
1333 [ "Stop at first matching database"
1334 (setq cscope-stop-at-first-match-dir
1335 (not cscope-stop-at-first-match-dir))
1336 :style toggle
1337 :selected cscope-stop-at-first-match-dir ]
1338 [ "Never update cscope database"
1339 (setq cscope-option-do-not-update-database
1340 (not cscope-option-do-not-update-database))
1341 :style toggle :selected cscope-option-do-not-update-database ]
1342 [ "Disable cscope database compression"
1343 (setq cscope-option-disable-compression
1344 (not cscope-option-disable-compression))
1345 :style toggle :selected cscope-option-disable-compression ]
1346 [ "Index using 'kernel mode'"
1347 (setq cscope-option-kernel-mode
1348 (not cscope-option-kernel-mode))
1349 :style toggle :selected cscope-option-kernel-mode ]
1350 [ "Build an inverted index"
1351 (setq cscope-option-use-inverted-index
1352 (not cscope-option-use-inverted-index))
1353 :style toggle :selected cscope-option-use-inverted-index ]
1354 [ "Index recursively"
1355 (setq cscope-index-recursively
1356 (not cscope-index-recursively))
1357 :style toggle :selected cscope-index-recursively ]
1358 [ "Use relative paths"
1359 (setq cscope-use-relative-paths
1360 (not cscope-use-relative-paths))
1361 :style toggle :selected cscope-use-relative-paths ]
1362 )
1363 )))
1364
1365 (easy-menu-define cscope-global-menu
1366 cscope-minor-mode-keymap
1367 "cscope menu"
1368 `("Cscope" ,@menu-before ,@menu-only-global ,@menu-after))
1369
1370 (easy-menu-define cscope-buffer-menu
1371 cscope-list-entry-keymap
1372 "cscope menu"
1373 `("Cscope" ,@menu-before ,@menu-only-cscope ,@menu-after)))
1374
1375
1376 (defun cscope-mouse-popup-menu-or-search (event)
1377 "Pop-up the menu or rerun the last search when double-clicked.
1378 EVENT is the mouse event."
1379 (interactive "e")
1380 (mouse-set-point event)
1381 (let ((click-count (event-click-count event)))
1382 (cond
1383 ((eq click-count 1) (cscope-popup-menu event))
1384 ((eq click-count 2) (cscope-run-last-search-noprompt)))))
1385
1386 (defun cscope-mouse-search-again (event)
1387 "Run the last search type again on the symbol the user clicked
1388 on. EVENT is the mouse event."
1389 (interactive "e")
1390 (mouse-set-point event)
1391 (cscope-run-last-search-noprompt))
1392
1393 (defun cscope-popup-menu (event)
1394 "Pop up MENU and perform an action if something was selected.
1395 EVENT is the mouse event."
1396 (save-selected-window
1397 (select-window (posn-window (event-start event)))
1398 (let ((selection (x-popup-menu event cscope-global-menu))
1399 binding)
1400 (while selection
1401 (setq binding (lookup-key (or binding cscope-global-menu) (vector (car selection)))
1402 selection (cdr selection)))
1403 (when binding
1404 (let (cscope-suppress-user-symbol-prompt)
1405 (call-interactively binding))))))
1406
1407 (defun cscope-run-last-search-noprompt ()
1408 "Run the last search type off of the symbol at point without
1409 prompting the user. This is mostly for mouse-initiated searches."
1410 (when cscope-previous-user-search
1411 (let (cscope-suppress-user-symbol-prompt)
1412 (call-interactively (car cscope-previous-user-search)))))
1413
1414
1415 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1416 ;; Internal functions and variables
1417 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1418
1419 (defun cscope-insert-with-text-properties (text filename &optional line-number line)
1420 "Insert an entry with given TEXT, add entry attributes as text
1421 properties. Unlike 'cscope-make-entry-line' this function is
1422 called both for cscope entry lines and cscope file lines
1423
1424 The text properties to be added:
1425 - common property: mouse-face,
1426 - properties are used to open target file and its location: cscope-file,
1427 cscope-line-number"
1428 (let (plist beg end)
1429
1430 (when cscope-use-face
1431 (setq plist (plist-put plist 'mouse-face 'cscope-mouse-face)))
1432
1433 (setq beg (point))
1434 (insert text)
1435 (setq end (point)
1436 plist (plist-put plist 'cscope-file filename))
1437 (when line-number
1438 (when (stringp line-number)
1439 (setq line-number (string-to-number line-number)))
1440 (setq plist (plist-put plist 'cscope-line-number line-number)))
1441
1442 (add-text-properties beg end plist)
1443 ))
1444
1445
1446 (if cscope-running-in-xemacs
1447 (progn
1448 (defalias 'cscope-event-window 'event-window)
1449 (defalias 'cscope-event-point 'event-point)
1450 (defalias 'cscope-recenter 'recenter)
1451 )
1452 (defun cscope-event-window (event)
1453 "Return the window at which the mouse EVENT occurred."
1454 (posn-window (event-start event)))
1455 (defun cscope-event-point (event)
1456 "Return the point at which the mouse EVENT occurred."
1457 (posn-point (event-start event)))
1458 (defun cscope-recenter (&optional n window)
1459 "Center point in WINDOW and redisplay frame. With N, put point on line N."
1460 (save-selected-window
1461 (if (windowp window)
1462 (select-window window))
1463 (recenter n)))
1464 )
1465
1466
1467 (defun cscope-show-entry-internal (navprops
1468 &optional save-mark-p window arrow-p)
1469 "Display the buffer corresponding to FILE and LINE-NUMBER
1470 in some window. If optional argument WINDOW is given,
1471 display the buffer in that WINDOW instead. The window is
1472 not selected. Save point on mark ring before goto
1473 LINE-NUMBER if optional argument SAVE-MARK-P is non-nil.
1474 Put `overlay-arrow-string' if arrow-p is non-nil.
1475 Returns the window displaying BUFFER."
1476 (let ( (file (elt navprops 0))
1477 (line-number (or (elt navprops 1) -1))
1478 (fuzzy-search-text-regexp (elt navprops 2))
1479 buffer old-pos old-point new-point forward-point backward-point
1480 line-end line-length)
1481 (if (and (stringp file)
1482 (integerp line-number))
1483 (progn
1484 (unless (file-readable-p file)
1485 (error "%s is not readable or exists" file))
1486 (setq buffer (find-file-noselect file))
1487 (if (windowp window)
1488 (set-window-buffer window buffer)
1489 (setq window (cscope-display-buffer-wrapper buffer)))
1490 (set-buffer buffer)
1491 (if (> line-number 0)
1492 (progn
1493 (setq old-pos (point))
1494
1495 ;; this is recommended instead of (goto-line line-number)
1496 (save-restriction
1497 (widen)
1498 (goto-char (point-min))
1499 (forward-line (1- line-number)))
1500
1501 (setq old-point (point))
1502
1503 ;; Here I perform a fuzzy search. If the user has edited the
1504 ;; sources after building the cscope database, cscope may have
1505 ;; the wrong line numbers. Here I try to correct for this by
1506 ;; finding the cscope results in the text around where cscope
1507 ;; said they should appear. There is a choice here: I could look
1508 ;; for the original string the user searched for, or I can look
1509 ;; for the longer string that cscope has found. I do the latter
1510 (if (and fuzzy-search-text-regexp cscope-fuzzy-search-range)
1511 (progn
1512 ;; Calculate the length of the line specified by cscope.
1513 (end-of-line)
1514 (setq line-end (point))
1515 (goto-char old-point)
1516 (setq line-length (- line-end old-point))
1517
1518 ;; Search forward and backward for the pattern.
1519 (setq forward-point (re-search-forward
1520 fuzzy-search-text-regexp
1521 (+ old-point
1522 cscope-fuzzy-search-range) t))
1523 (goto-char old-point)
1524 (setq backward-point (re-search-backward
1525 fuzzy-search-text-regexp
1526 (- old-point
1527 cscope-fuzzy-search-range) t))
1528 (if forward-point
1529 (progn
1530 (if backward-point
1531 (setq new-point
1532 ;; Use whichever of forward-point or
1533 ;; backward-point is closest to old-point.
1534 ;; Give forward-point a line-length advantage
1535 ;; so that if the symbol is on the current
1536 ;; line the current line is chosen.
1537 (if (<= (- (- forward-point line-length)
1538 old-point)
1539 (- old-point backward-point))
1540 forward-point
1541 backward-point))
1542 (setq new-point forward-point)))
1543 (if backward-point
1544 (setq new-point backward-point)
1545 (setq new-point old-point)))
1546 (goto-char new-point)
1547 (beginning-of-line)
1548 (setq new-point (point)))
1549 (setq new-point old-point))
1550 (set-window-point window new-point)
1551
1552 ;; if we're using an arrow overlay....
1553 (if (and cscope-allow-arrow-overlays arrow-p)
1554 (set-marker
1555
1556 ;; ... set the existing marker if there is one, or make a
1557 ;; new one ...
1558 (or overlay-arrow-position
1559 (setq overlay-arrow-position (make-marker)))
1560
1561 ;; ... at point
1562 (point))
1563
1564 ;; if we need to remove a marker, do that if there is one
1565 (when overlay-arrow-position
1566 (set-marker overlay-arrow-position nil)))
1567
1568 (or (not save-mark-p)
1569 (= old-pos (point))
1570 (push-mark old-pos))
1571 ))
1572
1573 (if cscope-marker
1574 (progn ;; The search was successful. Save the marker so it
1575 ;; can be returned to by cscope-pop-mark.
1576 (ring-insert cscope-marker-ring cscope-marker)
1577 ;; Unset cscope-marker so that moving between matches does not
1578 ;; fill cscope-marker-ring.
1579 (setq cscope-marker nil)))
1580 (setq cscope-marker-window window)
1581 )
1582 (message "No entry found at point."))
1583 )
1584 window)
1585
1586 (defun cscope-find-this-separator-start (separator-regex from &optional strict)
1587 "Finds the start of the given separator before FROM.
1588 If FROM is anywhere in a separator string, this separator is
1589 used. If STRICT is non-nil this function returns nil if no
1590 separator is found. Otherwise '(point-min)' is returned"
1591
1592 ;; if we're below (point-min), give up. This can happen when trying to search
1593 ;; before eob. For instance, trying to find the prev result from eob
1594 (if (< from (point-min))
1595 (if strict nil (point-min))
1596
1597 (let ((separator-regex-at-bol (concat "^" separator-regex)))
1598 (save-excursion
1599 (goto-char from)
1600 (beginning-of-line)
1601
1602 ;; if we're at the separator, use it
1603 (if (looking-at separator-regex) (point)
1604
1605 ;; otherwise, find the previous separator
1606 (or
1607 (re-search-backward separator-regex-at-bol nil t nil)
1608
1609 ;; if there isn't one, use the start of the buffer
1610 (if strict nil (point-min))))))))
1611
1612 (defun cscope-find-next-separator-start (separator-regex from &optional strict)
1613 "Finds the next start of the given separator after FROM.
1614 If FROM is anywhere in a separator string, the next separator is
1615 used. If STRICT is non-nil this function returns nil if no
1616 separator is found. Otherwise '(point-min)' is returned"
1617
1618 (let ((separator-regex-at-bol (concat "^" separator-regex)))
1619 (save-excursion
1620 (goto-char from)
1621
1622 ;; try to find the next separator (start a bit forward to not find
1623 ;; the current one).
1624 (if (progn (forward-char)
1625 (re-search-forward separator-regex-at-bol nil t nil))
1626
1627 ;; if there is a next one, navigate to its start, and use it
1628 (progn
1629 (forward-line -1)
1630 (beginning-of-line)
1631 (point))
1632
1633 ;; otherwise, use the end of the buffer
1634 (if strict nil (point-max))))))
1635
1636 (defun cscope-get-history-bounds-this-result-internal (start-regex &optional end-regex)
1637 "Returns a list of the beginning and the end of the results
1638 at (point). If END-REGEX is nil, the START-REGEX is used for both
1639 the start and end bounds; the region then contains the start
1640 separator, but not the end separator. If END-REGEX is non-nil, it
1641 is used to find the end bound, and the region then contains both
1642 separators. If some error has occured or if (point) isn't within
1643 the computed bounds then nil is returned"
1644
1645 (let* ((beg (cscope-find-this-separator-start start-regex (point)))
1646 (end
1647 (if end-regex
1648 ;; we have an end regex
1649 (save-excursion
1650 (goto-char beg)
1651 (re-search-forward (concat "^" end-regex) nil t nil))
1652
1653 ;; no end regex given. use the start regex
1654 (cscope-find-next-separator-start start-regex beg))))
1655
1656 ;; return the list if both bounds exist, and the original point is
1657 ;; within those bounds
1658 (if (and beg
1659 end
1660 (>= (point) beg)
1661 (or (< (point) end)
1662 (and (eobp) (= (point) end))))
1663 (list beg end)
1664 nil)))
1665
1666 (defun cscope-get-history-bounds-this-result (which)
1667 "Convenience wrapper around
1668 'cscope-get-history-bounds-this-result-internal'. WHICH is
1669 'result to ask for result bounds or 'file to ask for file bounds"
1670 (cond
1671 ((eq which 'result) (cscope-get-history-bounds-this-result-internal cscope-result-separator))
1672 ((eq which 'file) (cscope-get-history-bounds-this-result-internal cscope-file-separator-start-regex
1673 cscope-file-separator-end-regex))
1674 (t (error "cscope-get-history-bounds-this-result knows only about 'result and 'file"))))
1675
1676
1677 (defun cscope-get-navigation-properties (&optional at buffer)
1678 "Reads the cscope navigation properties on this line. The
1679 properties themselves are read from the beginning of the line,
1680 since the trailing newline is NOT propertized."
1681 (with-current-buffer (or buffer (current-buffer))
1682 (save-excursion
1683 (when at (goto-char at))
1684 (beginning-of-line)
1685 (vector (get-text-property (point) 'cscope-file)
1686 (get-text-property (point) 'cscope-line-number)
1687 (get-text-property (point) 'cscope-fuzzy-search-text-regexp)))))
1688
1689 (defun cscope-get-directory (&optional beg-end)
1690 "In a *cscope* buffer, searches for the
1691
1692 Database directory:
1693
1694 string to get the directory of the search at point."
1695
1696 (save-excursion
1697
1698 (when (not beg-end)
1699 (setq beg-end (cscope-get-history-bounds-this-result 'result)))
1700
1701 (end-of-line)
1702 (let ((case-fold-search nil))
1703 (and
1704 (or
1705 (re-search-backward (concat
1706 "^" cscope-database-directory-prompt
1707 "[a-z/]*: \\(.+\\)$")
1708 (car beg-end) t)
1709 (progn
1710 (goto-char (car beg-end))
1711 (re-search-forward (concat
1712 "^" cscope-database-directory-prompt
1713 "[a-z/]*: \\(.+\\)$")
1714 (cadr beg-end) t)))
1715 (match-string-no-properties 1)))))
1716
1717 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1718 ;; functions in *cscope* buffer which lists the search results
1719 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1720
1721 (defun cscope-select-entry-other-window ()
1722 "Display the entry at point in other window, select the window.
1723 Push current point on mark ring and select the entry window."
1724 (interactive)
1725 (let ((navprops (cscope-get-navigation-properties))
1726 window)
1727 (setq window (cscope-show-entry-internal navprops t))
1728 (if (windowp window)
1729 (select-window window))
1730 )
1731 (if cscope-close-window-after-select
1732 (delete-windows-on cscope-output-buffer-name)))
1733
1734 (defun cscope-select-entry-inplace ()
1735 "Display the entry in the window currently occupied by the
1736 *cscope* buffer"
1737 (interactive)
1738
1739 (let ((navprops (cscope-get-navigation-properties))
1740 window)
1741 (cscope-show-entry-internal navprops t (selected-window))))
1742
1743 (defun cscope-select-entry-one-window ()
1744 "Display the entry at point in one window, select the window."
1745 (interactive)
1746 (let ((navprops (cscope-get-navigation-properties))
1747 window)
1748 (setq window (cscope-show-entry-internal navprops t))
1749 (if (windowp window)
1750 (progn
1751 (select-window window)
1752 (sit-for 0) ;; Redisplay hack to allow delete-other-windows
1753 ;; to continue displaying the correct location.
1754 (delete-other-windows window)
1755 ))
1756 ))
1757
1758
1759 (defun cscope-select-entry-specified-window (window)
1760 "Display the entry at point in a specified window, select the window."
1761 (interactive)
1762 (let ((navprops (cscope-get-navigation-properties)))
1763 (setq window (cscope-show-entry-internal navprops t window))
1764 (if (windowp window)
1765 (select-window window))
1766 ))
1767
1768
1769 (defun cscope-mouse-select-entry-other-window (event)
1770 "Display the entry over which the mouse event occurred, select the window."
1771 (interactive "e")
1772 (let ((ep (cscope-event-point event))
1773 (win (cscope-event-window event))
1774 window)
1775 (if ep
1776 (progn
1777 (let ((navprops (cscope-get-navigation-properties ep (window-buffer win))))
1778 (select-window win)
1779 (setq window (cscope-show-entry-internal navprops t)))
1780 (if (windowp window)
1781 (select-window window)))
1782 (message "No entry found at point.")
1783 )
1784 ))
1785
1786 (defun cscope-mouse-select-entry-inplace (event)
1787 "Display the entry over which the mouse event occurred, select the window."
1788 (interactive "e")
1789 (let ((ep (cscope-event-point event))
1790 (win (cscope-event-window event)))
1791 (if ep
1792 (progn
1793 (let ((navprops (cscope-get-navigation-properties ep (window-buffer win))))
1794 (select-window win)
1795 (cscope-show-entry-internal navprops t win)))
1796 (message "No entry found at point.")
1797 )
1798 ))
1799
1800
1801 (defun cscope-show-entry-other-window ()
1802 "Display the entry at point in other window.
1803 Point is not saved on mark ring."
1804 (interactive)
1805 (let ((navprops (cscope-get-navigation-properties)))
1806 (cscope-show-entry-internal navprops nil nil t)
1807 ))
1808
1809
1810 (defun cscope-display-buffer ()
1811 "Display the *cscope* buffer."
1812 (interactive)
1813 (let ((buffer (get-buffer cscope-output-buffer-name)))
1814 (if buffer
1815 (pop-to-buffer buffer)
1816 (error "The *cscope* buffer does not exist yet"))))
1817
1818
1819 (defun cscope-display-buffer-toggle ()
1820 "Toggle cscope-display-cscope-buffer, which corresponds to
1821 \"Auto display *cscope* buffer\"."
1822 (interactive)
1823 (setq cscope-display-cscope-buffer (not cscope-display-cscope-buffer))
1824 (message "The cscope-display-cscope-buffer variable is now %s."
1825 (if cscope-display-cscope-buffer "set" "unset")))
1826
1827 (defun cscope-navigate-and-show (forms &optional no-show)
1828 "This evaluates the navigation FORMS. These FORMS move the
1829 point in the *cscope* buffer, and this function shows the result
1830 in the source"
1831
1832 (let* (old-point
1833 point
1834 (old-buffer (current-buffer))
1835 (old-buffer-window (get-buffer-window old-buffer))
1836 (cscope-buffer (get-buffer cscope-output-buffer-name))
1837 (buffer-window (get-buffer-window (or cscope-buffer (error "The *cscope* buffer does not exist yet"))))
1838 )
1839 (set-buffer cscope-buffer)
1840 (setq old-point (point))
1841
1842 ;; I can now evaluate the forms
1843 (let ((forms-result
1844
1845 ;; if we're limiting to this result then ...
1846 (if limit-to-current-result
1847 (let ((bounds (cscope-get-history-bounds-this-result 'result)))
1848 (unless bounds (error "Couldn't find result bounds"))
1849
1850 ;; ... narrow to this result before evaluating ...
1851 (save-restriction
1852 (apply 'narrow-to-region bounds)
1853 (eval forms)))
1854
1855 ;; ... otherwise just evaluate
1856 (eval forms))))
1857
1858 (unless forms-result
1859 (goto-char old-point)
1860 (error "Can't move further")))
1861
1862 (setq point (point))
1863
1864 (unless no-show
1865 (if (eq old-buffer cscope-buffer) ;; In the *cscope* buffer.
1866 (cscope-show-entry-other-window)
1867 (cscope-select-entry-specified-window old-buffer-window) ;; else
1868 (if (windowp buffer-window)
1869 (set-window-point buffer-window point))))
1870 (set-buffer old-buffer)))
1871
1872 (defun cscope-history-forward-backward (separator-regex do-next)
1873 "Body for 'cscope-history-forward-result'/'cscope-history-backward-result'
1874 and 'cscope-history-forward-file'/'cscope-history-backward-file'"
1875 (let ((target-point
1876 (cond
1877 (do-next (cscope-find-next-separator-start separator-regex (point) t))
1878 (t (cscope-find-this-separator-start separator-regex
1879 (- (point) (if (looking-at separator-regex) 1 0)) t)))))
1880 (when target-point (goto-char target-point))))
1881
1882 (defun cscope-history-forward-result ( &optional limit-to-current-result )
1883 "Navigate to the next stored search results in the *cscope*
1884 buffer."
1885 (interactive)
1886 (cscope-navigate-and-show
1887 '(cscope-history-forward-backward cscope-result-separator t) t))
1888
1889 (defun cscope-history-backward-result ( &optional limit-to-current-result )
1890 "Navigate to the previous stored search results in the *cscope*
1891 buffer."
1892 (interactive)
1893 (cscope-navigate-and-show
1894 '(cscope-history-forward-backward cscope-result-separator nil) t))
1895
1896 (defun cscope-history-kill-result ()
1897 "Delete a cscope result from the *cscope* buffer."
1898 (interactive)
1899 (let ((bounds (cscope-get-history-bounds-this-result 'result)))
1900 (if bounds (apply 'delete-region bounds)
1901 (error "Nothing to kill"))))
1902
1903 (defun cscope-history-forward-file ( &optional limit-to-current-result )
1904 "Navigate to the next file results in the *cscope* buffer."
1905 (interactive)
1906 (cscope-navigate-and-show
1907 '(cscope-history-forward-backward cscope-file-separator-start-regex t)))
1908
1909 (defun cscope-history-forward-file-current-result ()
1910 "Like (cscope-history-forward-file), but limited to the current
1911 result only. This exists for blind navigation. If the user isn't
1912 looking at the *cscope* buffer, they shouldn't be jumping between
1913 results"
1914 (interactive)
1915 (cscope-history-forward-file t))
1916
1917 (defun cscope-history-backward-file ( &optional limit-to-current-result )
1918 "Navigate to the previous file results in the *cscope* buffer."
1919 (interactive)
1920 (cscope-navigate-and-show
1921 '(cscope-history-forward-backward cscope-file-separator-start-regex nil)))
1922
1923 (defun cscope-history-backward-file-current-result ()
1924 "Like (cscope-history-backward-file), but limited to the current
1925 result only. This exists for blind navigation. If the user isn't
1926 looking at the *cscope* buffer, they shouldn't be jumping between
1927 results"
1928 (interactive)
1929 (cscope-history-backward-file t))
1930
1931 (defun cscope-history-kill-file ()
1932 "Delete a cscope file set from the *cscope* buffer."
1933 (interactive)
1934 (let ((bounds (cscope-get-history-bounds-this-result 'file)))
1935 (if bounds
1936 (progn
1937 (apply 'delete-region bounds)
1938 (cscope-history-kill-if-empty 'result))
1939 (error "Nothing to kill"))))
1940
1941 (defun cscope-history-forward-line ( &optional limit-to-current-result )
1942 "Navigate to the next result line in the *cscope* buffer."
1943 (interactive)
1944
1945 (cscope-navigate-and-show
1946 '(let ((target
1947 (let ((at (save-excursion
1948 (end-of-line)
1949 (point))))
1950 (next-single-property-change at 'cscope-line-number))))
1951 (when target (goto-char target)))))
1952
1953 (defun cscope-history-forward-line-current-result ()
1954 "Like (cscope-history-forward-line), but limited to the current
1955 result only. This exists for blind navigation. If the user isn't
1956 looking at the *cscope* buffer, they shouldn't be jumping between
1957 results"
1958 (interactive)
1959 (cscope-history-forward-line t))
1960
1961 (defun cscope-history-backward-line ( &optional limit-to-current-result )
1962 "Navigate to the previous result line in the *cscope* buffer."
1963 (interactive)
1964
1965 (cscope-navigate-and-show
1966 '(let ((target
1967 (let ((at (save-excursion
1968 (beginning-of-line)
1969 (previous-single-property-change (point) 'cscope-line-number))))
1970 (and at (previous-single-property-change at 'cscope-line-number)))))
1971 (when target (goto-char target)))))
1972
1973 (defun cscope-history-backward-line-current-result ()
1974 "Like (cscope-history-backward-line), but limited to the current
1975 result only. This exists for blind navigation. If the user isn't
1976 looking at the *cscope* buffer, they shouldn't be jumping between
1977 results"
1978 (interactive)
1979 (cscope-history-backward-line t))
1980
1981 (defun cscope-history-kill-line ()
1982 "Delete a cscope line from the *cscope* buffer."
1983 (interactive)
1984 (save-excursion
1985 (beginning-of-line)
1986 (if (get-text-property (point) 'cscope-line-number)
1987 (progn
1988 (delete-region (point) (progn (forward-line 1) (point)))
1989 (cscope-history-kill-if-empty 'file))
1990 (error "Nothing to kill"))))
1991
1992 (defun cscope-history-kill-if-empty (which)
1993 "Kills object specified by WHICH, if it is empty. WHICH is
1994 either 'result or 'file"
1995 (let ((bounds (cscope-get-history-bounds-this-result which)))
1996 (unless
1997 ;; not-empty condition computed here; different depending on WHICH
1998 (cond
1999 ((eq which 'file)
2000 (let ((nextpropchange (next-single-property-change (car bounds) 'cscope-line-number nil (cadr bounds))))
2001 (and nextpropchange
2002 (/= nextpropchange (cadr bounds)))))
2003 ((eq which 'result)
2004
2005 (save-excursion
2006 (goto-char (car bounds))
2007 (re-search-forward (concat "^" cscope-file-separator-start-regex) (cadr bounds) t nil)))
2008 (t (error "cscope-history-kill-if-empty given unknown argument")))
2009
2010 (apply 'delete-region bounds)
2011 (when (eq which 'file)
2012 (cscope-history-kill-if-empty 'result)))))
2013
2014 (defun cscope-pop-mark ()
2015 "Pop back to where cscope was last invoked."
2016 (interactive)
2017
2018 ;; This function is based on pop-tag-mark, which can be found in
2019 ;; lisp/progmodes/etags.el.
2020
2021 (if (ring-empty-p cscope-marker-ring)
2022 (error "There are no marked buffers in the cscope-marker-ring yet"))
2023 (let* ( (marker (ring-remove cscope-marker-ring 0))
2024 (old-buffer (current-buffer))
2025 (marker-buffer (marker-buffer marker))
2026 marker-window
2027 (marker-point (marker-position marker))
2028 (cscope-buffer (get-buffer cscope-output-buffer-name)) )
2029
2030 ;; After the following both cscope-marker-ring and cscope-marker will be
2031 ;; in the state they were immediately after the last search. This way if
2032 ;; the user now makes a selection in the previously generated *cscope*
2033 ;; buffer things will behave the same way as if that selection had been
2034 ;; made immediately after the last search.
2035 (setq cscope-marker marker)
2036
2037 (if marker-buffer
2038 (if (eq old-buffer cscope-buffer)
2039 (progn ;; In the *cscope* buffer.
2040 (set-buffer marker-buffer)
2041 (setq marker-window (cscope-display-buffer-wrapper marker-buffer))
2042 (set-window-point marker-window marker-point)
2043 (select-window marker-window))
2044 (switch-to-buffer marker-buffer))
2045 (error "The marked buffer has been deleted"))
2046 (goto-char marker-point)
2047 (set-buffer old-buffer)))
2048
2049 (defun cscope-rerun-search-at-point ()
2050 "Re-runs the search at the point of the *cscope* buffer. Result
2051 modified in-place"
2052 (interactive)
2053
2054 (unless (eq (get-buffer cscope-output-buffer-name) (current-buffer))
2055 (error "(cscope-rerun-search-at-point) only makes sense from a *cscope* buffer"))
2056
2057 (when cscope-process
2058 (error "A cscope search is still in progress -- only one at a time is allowed"))
2059
2060 ;; move to where we were after the search is done??
2061 (let ((beg-end (cscope-get-history-bounds-this-result 'result)))
2062 (unless beg-end (error "No result at point"))
2063
2064 (let* ((beg (elt beg-end 0))
2065 (end (elt beg-end 1))
2066 (search (get-text-property beg 'cscope-stored-search))
2067
2068 ;; try to rerun the search in the same directory as before
2069 (cscope-initial-directory
2070 (or cscope-initial-directory
2071 (cscope-get-directory beg-end)))
2072 cscope-rerunning-search ;; this is bound here to tell cscope-call to not move the point
2073 )
2074 (delete-region beg end)
2075 (goto-char beg)
2076 (eval search))))
2077
2078 (defun cscope-set-initial-directory (cs-id)
2079 "Set the cscope-initial-directory variable. The
2080 cscope-initial-directory variable, when set, specifies the directory
2081 where searches for the cscope database directory should begin. This
2082 overrides the current directory, which would otherwise be used."
2083 (interactive "DCscope Initial Directory: ")
2084 (setq cscope-initial-directory cs-id))
2085
2086
2087 (defun cscope-unset-initial-directory ()
2088 "Unset the cscope-initial-directory variable."
2089 (interactive)
2090 (setq cscope-initial-directory nil)
2091 (message "The cscope-initial-directory variable is now unset."))
2092
2093
2094 (defun cscope-help ()
2095 (interactive)
2096 (message
2097 (format "RET=%s, SPC=%s, o=%s, n=%s, p=%s, q=%s, h=%s"
2098 "Select"
2099 "Show"
2100 "SelectOneWin"
2101 "ShowNext"
2102 "ShowPrev"
2103 "Quit"
2104 "Help")))
2105
2106 (defun cscope-cleanup-overlay-arrow ()
2107 (when overlay-arrow-position
2108 (set-marker overlay-arrow-position nil)
2109 (setq overlay-arrow-position nil
2110 overlay-arrow-string nil)))
2111
2112 (defun cscope-bury-buffer ()
2113 "Clean up cscope, if necessary, and bury the buffer."
2114 (interactive)
2115 (cscope-cleanup-overlay-arrow)
2116 (bury-buffer))
2117
2118
2119
2120 (defun cscope-quit ()
2121 (interactive)
2122 (cscope-bury-buffer)
2123 (kill-buffer cscope-output-buffer-name)
2124 )
2125
2126
2127 (defun cscope-boldify-if-needed (&rest args)
2128 "Returns a string in a bold face that's a concatenation of ARGS.
2129 This is done if 'cscope-use-face' is non-nil. Otherwise a plain
2130 concatenation of ARGS is returned"
2131 (let ((str (apply 'concat args)))
2132 (if cscope-use-face
2133 (propertize str 'face 'bold)
2134 str)))
2135
2136 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2137
2138 (defun cscope-canonicalize-directory (dir)
2139 (or dir
2140 (setq dir default-directory))
2141 (setq dir (file-name-as-directory
2142 (expand-file-name (substitute-in-file-name dir))))
2143 dir
2144 )
2145
2146 (defun cscope-construct-custom-options-list ()
2147 "Returns a list of cscope options defined by the
2148 cscope-option-* variables"
2149 (append
2150 (mapcar (lambda (dir) (concat "-I" dir)) cscope-option-include-directories)
2151 (when cscope-option-disable-compression '("-c"))
2152 (when cscope-option-kernel-mode '("-k"))
2153 (when cscope-option-use-inverted-index '("-q"))
2154 cscope-option-other))
2155
2156 (defun cscope-search-directory-hierarchy (directory)
2157 "Look for a cscope database in the directory hierarchy.
2158 Starting from DIRECTORY, look upwards for a cscope database."
2159 (let (this-directory database-dir)
2160 (catch 'done
2161 (if (file-regular-p directory)
2162 (throw 'done directory))
2163 (setq directory (cscope-canonicalize-directory directory)
2164 this-directory directory)
2165 (while this-directory
2166 (if (or (file-exists-p (concat this-directory cscope-database-file))
2167 (file-exists-p (concat this-directory cscope-index-file)))
2168 (progn
2169 (setq database-dir this-directory)
2170 (throw 'done database-dir)
2171 ))
2172
2173 (let ((parent-directory (file-name-as-directory
2174 (file-name-directory
2175 (directory-file-name this-directory)))))
2176 (if (string= this-directory parent-directory)
2177 (throw 'done directory)
2178 (setq this-directory parent-directory)))))))
2179
2180
2181 (defun cscope-find-info (top-directory)
2182 "Locate a suitable cscope database directory.
2183 First, `cscope-database-regexps' is used to search for a suitable
2184 database directory. If a database location cannot be found using this
2185 variable, then the current directory is searched, then the parent,
2186 then the parent's parent, until a cscope database directory is found,
2187 or the root directory is reached. If the root directory is reached,
2188 the current directory will be used."
2189 (let (info regexps dir-regexp this-directory)
2190 (setq top-directory (cscope-canonicalize-directory
2191 (or top-directory cscope-initial-directory)))
2192 (catch 'done
2193 ;; Try searching using `cscope-database-regexps' ...
2194 (setq regexps cscope-database-regexps)
2195 (while regexps
2196 (setq dir-regexp (car (car regexps)))
2197 (cond
2198 ( (stringp dir-regexp)
2199 (if (string-match dir-regexp top-directory)
2200 (progn
2201 (setq info (cdr (car regexps)))
2202 (throw 'done t)
2203 )) )
2204 ( (and (symbolp dir-regexp) dir-regexp)
2205 (progn
2206 (setq info (cdr (car regexps)))
2207 (throw 'done t)
2208 ) ))
2209 (setq regexps (cdr regexps))
2210 )
2211
2212 ;; Try looking in the directory hierarchy ...
2213 (if (setq this-directory
2214 (cscope-search-directory-hierarchy top-directory))
2215 (progn
2216 (setq info (list (list this-directory)))
2217 (throw 'done t)
2218 ))
2219
2220 ;; Should we add any more places to look?
2221
2222 ) ;; end catch
2223 (if (not info)
2224 (setq info (list (list top-directory))))
2225 info
2226 ))
2227
2228
2229 (defun cscope-make-entry-line (func-name line-number line)
2230 "Makes a propertized line containing a single cscope result.
2231 This function sets up face and the fuzzy-search string"
2232
2233 ;; The format of entry line:
2234 ;; func-name[line-number]______line
2235 ;; <- cscope-name-line-width ->
2236 ;; `format' of Emacs doesn't have "*s" spec.
2237 (let ((str (format (format "%%%ds %%s" cscope-name-line-width)
2238 (format "%s[%s]" func-name line-number) line))
2239 (search-type (car cscope-previous-user-search))
2240 (search-symbol (cadr cscope-previous-user-search))
2241 beg end)
2242
2243 ;; I set up the 'cscope-fuzzy-search-text-regexp property to allow fuzzy
2244 ;; searches to work. cscope collapses spaces for some reason, so I explictly
2245 ;; look for an arbitrary amounts of whitespace
2246 (unless (string= line "<unknown>")
2247 (let ((fuzzy-search-text-regexp
2248 (mapconcat 'regexp-quote
2249 (split-string line "[ \f\t\n\r\v]+\\|\\b" t) "\\s-*")))
2250
2251 (put-text-property 0 (length str) 'cscope-fuzzy-search-text-regexp fuzzy-search-text-regexp str)))
2252
2253 ;; now I set up the face properties
2254 (when cscope-use-face
2255 (setq end (length func-name))
2256 (put-text-property 0 end 'face 'cscope-function-face str)
2257 (setq beg (1+ end)
2258 end (+ beg (length line-number)))
2259 (put-text-property beg end 'face 'cscope-line-number-face str)
2260
2261 (when (not (string= line "<unknown>"))
2262 (let* ((search-type (car cscope-previous-user-search))
2263 (search-symbol (cadr cscope-previous-user-search))
2264
2265 ;; nothing to highlight for search types where the sought symbol isn't
2266 ;; expected to appear at a matched result line.
2267 ;;
2268 ;; test-strings aren't regexes, so quote those. Everything else
2269 ;; is a regex, so pass that right on through
2270 (highlight-search-re
2271 (if (or (eq search-type 'cscope-find-this-file)
2272 (eq search-type 'cscope-find-called-functions))
2273 nil
2274 (if (eq search-type 'cscope-find-this-text-string)
2275 (regexp-quote search-symbol)
2276 search-symbol))))
2277
2278 (when highlight-search-re
2279
2280 ;; unless we're searching for arbitrary text strings, the tokens we
2281 ;; seek are full words. Furthermore, any '.' wildcard in those has
2282 ;; to match a C symbol
2283 (unless (or (eq search-type 'cscope-find-egrep-pattern)
2284 (eq search-type 'cscope-find-this-text-string))
2285
2286 (setq highlight-search-re
2287 (replace-regexp-in-string "\\([^\\\\]\\)\\." "\\1[a-zA-Z0-9_]"
2288 (concat "\\b" highlight-search-re "\\b"))))
2289 (let* ((case-fold-search nil)
2290 (start (string-match
2291 highlight-search-re
2292 str (1+ end))))
2293 (when start
2294 (put-text-property start (match-end 0) 'face 'bold str)))))))
2295
2296 str))
2297
2298
2299 (defun cscope-process-filter (process output)
2300 "Accept cscope process output and reformat it for human readability.
2301 Magic text properties are added to allow the user to select lines
2302 using the mouse."
2303 (let ( (old-buffer (current-buffer)) )
2304 (with-current-buffer (process-buffer process)
2305 (let (line file function-name line-number)
2306 (save-excursion
2307 (goto-char cscope-last-output-point)
2308 ;; Get the output thus far ...
2309 (if cscope-process-output
2310 (setq cscope-process-output (concat cscope-process-output
2311 output))
2312 (setq cscope-process-output output))
2313 ;; Slice and dice it into lines.
2314 ;; While there are whole lines left ...
2315 (while (and cscope-process-output
2316 (string-match "\\([^\n]+\n\\)\\(\\(.\\|\n\\)*\\)"
2317 cscope-process-output))
2318 (setq file nil
2319 glimpse-stripped-directory nil
2320 )
2321 ;; Get a line
2322 (setq line (substring cscope-process-output
2323 (match-beginning 1) (match-end 1)))
2324 (setq cscope-process-output (substring cscope-process-output
2325 (match-beginning 2)
2326 (match-end 2)))
2327 (if (= (length cscope-process-output) 0)
2328 (setq cscope-process-output nil))
2329
2330 ;; This should always match.
2331 (if (string-match
2332 "^\\([^ \t]+\\)[ \t]+\\([^ \t]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\(.*\\)\n"
2333 line)
2334 (progn
2335 (let (str)
2336 (setq file (substring line (match-beginning 1)
2337 (match-end 1))
2338 function-name (substring line (match-beginning 2)
2339 (match-end 2))
2340 line-number (substring line (match-beginning 3)
2341 (match-end 3))
2342 line (substring line (match-beginning 4)
2343 (match-end 4))
2344 )
2345 ;; If the current file is not the same as the previous
2346 ;; one ...
2347 (if (not (and cscope-last-file
2348 (string= file cscope-last-file)))
2349 (progn
2350 ;; The current file is different.
2351
2352 ;; Insert a separating blank line if
2353 ;; necessary.
2354 (if cscope-last-file (insert "\n"))
2355 ;; Insert the file name
2356 (setq str (concat "*** " file ":"))
2357 (if cscope-use-face
2358 (put-text-property 0 (length str)
2359 'face 'cscope-file-face
2360 str))
2361 (cscope-insert-with-text-properties
2362 str
2363 (expand-file-name file))
2364 (insert "\n")))
2365
2366 (if cscope-first-match-point
2367 (setq cscope-matched-multiple t)
2368 (setq cscope-first-match-point (point)))
2369
2370 ;; ... and insert the line, with the
2371 ;; appropriate indentation.
2372 (cscope-insert-with-text-properties
2373 (cscope-make-entry-line function-name
2374 line-number
2375 line)
2376 (expand-file-name file)
2377 line-number
2378 line)
2379 (insert "\n")
2380 (setq cscope-last-file file)
2381 ))
2382 (insert line "\n")
2383 ))
2384 (setq cscope-last-output-point (point)))
2385 (set-buffer-modified-p nil)))))
2386
2387
2388 (defun cscope-process-sentinel (process event)
2389 "Sentinel for when the cscope process dies."
2390 (let* ((buffer (process-buffer process)) window update-window
2391 (done t)
2392 (old-buffer (current-buffer))
2393 (old-buffer-window (get-buffer-window old-buffer)) )
2394
2395 (with-current-buffer buffer
2396 (let (continue
2397 (directory-this-search default-directory))
2398 (save-excursion
2399 (goto-char cscope-last-output-point)
2400
2401 (if (or (and (setq window (get-buffer-window buffer))
2402 (= (window-point window) (point-max)))
2403 (= (point) (point-max)))
2404 (setq update-window t))
2405 (delete-process process)
2406
2407 (when (= cscope-output-start (point))
2408 (insert " --- No matches were found ---\n"))
2409
2410 (when (not cscope-start-directory)
2411 (setq cscope-start-directory default-directory))
2412
2413 (setq continue
2414 (and cscope-search-list
2415 (not (and cscope-first-match-point
2416 cscope-stop-at-first-match-dir
2417 (not cscope-stop-at-first-match-dir-meta)))))
2418 (when continue
2419 (setq continue (cscope-search-one-database)))
2420 (if continue
2421 (setq done nil)
2422 (insert "\nSearch complete.")
2423 (if cscope-display-times
2424 (let ( (times (current-time)) cscope-stop elapsed-time )
2425 (setq cscope-stop (+ (* (car times) 65536.0)
2426 (cadr times)
2427 (* (cadr (cdr times)) 1.0E-6)))
2428 (setq elapsed-time (- cscope-stop cscope-start-time))
2429 (insert (format " Search time = %.2f seconds."
2430 elapsed-time))
2431 ))
2432 (insert "\n")
2433 (setq cscope-process nil)
2434 (if cscope-running-in-xemacs
2435 (setq modeline-process ": Search complete"))
2436 (when cscope-start-directory
2437 (setq default-directory cscope-start-directory)))
2438
2439
2440
2441
2442
2443 (set-buffer-modified-p nil))
2444
2445 (if (and done cscope-first-match-point update-window)
2446 (if window
2447 (set-window-point window cscope-first-match-point)
2448 (goto-char cscope-first-match-point))
2449 )
2450
2451 (when cscope-first-match-point
2452 (if cscope-display-cscope-buffer
2453 (if (and cscope-edit-single-match (not cscope-matched-multiple))
2454 (cscope-show-entry-internal
2455 (cscope-get-navigation-properties cscope-first-match-point (process-buffer process))
2456 t))
2457 (cscope-select-entry-specified-window old-buffer-window)))
2458
2459 ;; if the *cscope* buffer is too long, truncate it
2460 (with-current-buffer (process-buffer process)
2461 (when (and done
2462 (> cscope-max-cscope-buffer-size 0)
2463 (> (- (point-max) (point-min)) cscope-max-cscope-buffer-size))
2464
2465 (save-excursion
2466 (goto-char (point-max))
2467 (let ((cut-at-point (cscope-find-this-separator-start
2468 cscope-result-separator
2469 (- (point-max) cscope-max-cscope-buffer-size)
2470 t)))
2471 (when cut-at-point
2472 (delete-region (point-min) cut-at-point))))))
2473
2474 (if (and done (eq old-buffer buffer) cscope-first-match-point)
2475 (cscope-help))))))
2476
2477
2478
2479 (defun cscope-search-one-database ()
2480 "Pop a database entry from `cscope-search-list' and do a search there."
2481
2482 (let ( next-item options cscope-directory database-file outbuf done
2483 base-database-file-name)
2484 (setq outbuf (get-buffer-create cscope-output-buffer-name))
2485 (save-excursion
2486 (catch 'finished
2487 (set-buffer outbuf)
2488 (setq options '("-L"))
2489 (while (and (not done) cscope-search-list)
2490 (setq next-item (car cscope-search-list)
2491 cscope-search-list (cdr cscope-search-list)
2492 base-database-file-name cscope-database-file
2493 )
2494 (if (listp next-item)
2495 (progn
2496 (setq cscope-directory (car next-item))
2497 (if (not (stringp cscope-directory))
2498 (setq cscope-directory
2499 (cscope-search-directory-hierarchy
2500 default-directory)))
2501 (if (file-regular-p cscope-directory)
2502 (progn
2503 ;; Handle the case where `cscope-directory' is really
2504 ;; a full path name to a cscope database.
2505 (setq base-database-file-name
2506 (file-name-nondirectory cscope-directory)
2507 cscope-directory
2508 (file-name-directory cscope-directory))
2509 ))
2510 (setq cscope-directory
2511 (file-name-as-directory cscope-directory))
2512 (when (not (member cscope-directory cscope-searched-dirs))
2513 (push cscope-directory cscope-searched-dirs)
2514 (setq done t))
2515 )
2516 (progn
2517 (if (and cscope-first-match-point
2518 cscope-stop-at-first-match-dir
2519 cscope-stop-at-first-match-dir-meta)
2520 (throw 'finished nil))
2521 ))
2522 )
2523 (if (not done)
2524 (throw 'finished nil))
2525
2526 (when (cadr next-item)
2527 (let ((newopts (cadr next-item)))
2528 (unless (listp newopts)
2529 (error (format "Cscope options must be a list: %s" newopts)))
2530 (setq options (append options newopts))))
2531 (if cscope-command-args
2532 (setq options (append options cscope-command-args))
2533 (error "Tried to do a search without 'cscope-command-args' set. Something is wrong..."))
2534
2535
2536 (setq database-file (concat cscope-directory base-database-file-name)
2537 cscope-searched-dirs (cons cscope-directory
2538 cscope-searched-dirs)
2539 )
2540
2541 ;; The database file and the directory containing the database file
2542 ;; must both be writable.
2543 (if (or (not (file-writable-p database-file))
2544 (not (file-writable-p (file-name-directory database-file)))
2545 cscope-option-do-not-update-database)
2546 (setq options (cons "-d" options)))
2547
2548
2549 ;; is this require for multiple databases?
2550 ;; (goto-char (point-max))
2551 (if (string= base-database-file-name cscope-database-file)
2552 (insert (concat "\n" cscope-database-directory-prompt ": ")
2553 (cscope-boldify-if-needed cscope-directory)
2554 "\n\n")
2555 (insert (concat "\n" cscope-database-directory-prompt "/file: ")
2556 (cscope-boldify-if-needed cscope-directory base-database-file-name)
2557 "\n\n"))
2558 ;; Add the correct database file to search
2559 (setq options (cons base-database-file-name options))
2560 (setq options (cons "-f" options))
2561 (setq cscope-output-start (point))
2562 (setq default-directory cscope-directory)
2563
2564 (setq cscope-process-output nil
2565 cscope-last-file nil
2566 )
2567 (setq cscope-process
2568 ;; Communicate with a pipe. Slightly more efficient than
2569 ;; a TTY
2570 (let ((process-connection-type nil))
2571 (apply cscope-start-file-process "cscope" outbuf
2572 (cscope--get-cscope-program)
2573 (append (cscope-construct-custom-options-list) options))))
2574 (set-process-filter cscope-process 'cscope-process-filter)
2575 (set-process-sentinel cscope-process 'cscope-process-sentinel)
2576 (setq cscope-last-output-point (point))
2577 (process-kill-without-query cscope-process)
2578 (if cscope-running-in-xemacs
2579 (setq modeline-process ": Searching ..."))
2580 t
2581 ))
2582 ))
2583
2584 (defun cscope-call (basemsg search-id symbol)
2585 "Generic function to call to process cscope requests.
2586 BASEMSG is a message describing this search; SEARCH-ID is a
2587 numeric id indicating to the cscope backend what kind of search
2588 this is."
2589 (let* ( (outbuf (get-buffer-create cscope-output-buffer-name))
2590 (old-buffer (current-buffer))
2591 (directory
2592 (cscope-canonicalize-directory
2593
2594 ;; if we have an initial directory, use it. Otherwise if we're in
2595 ;; *cscope*, try to use the directory of the search at point
2596 (or cscope-initial-directory
2597 (and (eq outbuf old-buffer)
2598 (cscope-get-directory)))))
2599 (msg (concat basemsg " "
2600 (cscope-boldify-if-needed symbol)))
2601 (args (list (format "-%d" search-id) symbol)))
2602 (if cscope-process
2603 (error "A cscope search is still in progress -- only one at a time is allowed"))
2604 (if (eq outbuf old-buffer) ;; In the *cscope* buffer.
2605 (let ((marker-buf (window-buffer cscope-marker-window)))
2606 (when marker-buf
2607 ;; Assume that cscope-marker-window is the window, from the
2608 ;; users perspective, from which the search was launched and the
2609 ;; window that should be returned to upon cscope-pop-mark.
2610 (with-current-buffer marker-buf
2611 (setq cscope-marker (point-marker)))))
2612
2613 ;; Not in the *cscope buffer.
2614 ;; Set the cscope-marker-window to whichever window this search
2615 ;; was launched from.
2616 (setq cscope-marker-window (get-buffer-window old-buffer))
2617 (setq cscope-marker (point-marker)))
2618 (with-current-buffer outbuf
2619 (if cscope-display-times
2620 (let ( (times (current-time)) )
2621 (setq cscope-start-time (+ (* (car times) 65536.0) (cadr times)
2622 (* (cadr (cdr times)) 1.0E-6)))))
2623 (setq default-directory directory
2624 cscope-start-directory nil
2625 cscope-search-list (cscope-find-info directory)
2626 cscope-searched-dirs nil
2627 cscope-command-args args
2628 cscope-first-match-point nil
2629 cscope-stop-at-first-match-dir-meta (memq t cscope-search-list)
2630 cscope-matched-multiple nil)
2631 (setq truncate-lines cscope-truncate-lines)
2632
2633 ;; insert the separator at the start of the result set
2634 (unless (boundp 'cscope-rerunning-search) (goto-char (point-max)))
2635 (when (not (bolp))
2636 (insert "\n"))
2637
2638 ;; don't apply the face to the trailing newline in the separator
2639 (let ((separator-start (point)))
2640 (insert cscope-result-separator)
2641 (when cscope-use-face
2642 (put-text-property separator-start (1- (point)) 'face 'cscope-separator-face)
2643 (put-text-property separator-start (1- (point)) 'cscope-stored-search cscope-previous-user-search)))
2644
2645 (insert msg)
2646 (cscope-search-one-database))
2647
2648 (if cscope-display-cscope-buffer
2649 (progn
2650 (pop-to-buffer outbuf)
2651 (cscope-help))
2652 (set-buffer outbuf))
2653 (cscope-list-entry-mode)
2654 ))
2655
2656
2657 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2658
2659 (defvar cscope-unix-index-process nil
2660 "The current indexing process.")
2661
2662 (defvar cscope-indexing-status-string nil
2663 "The string returned by the indexer. This receives the indexer
2664 output as it comes over time")
2665
2666 (defun cscope-display-message-or-buffer (message buffer)
2667 "Calls `display-message-or-buffer' in GNU emacs. In xemacs this
2668 isn't available, so it simply displays the MESSAGE in the BUFFER"
2669
2670 (if (not cscope-running-in-xemacs) (display-message-or-buffer message buffer)
2671 (with-current-buffer (get-buffer-create buffer)
2672 (erase-buffer)
2673 (insert message)
2674 (goto-char (point-min))
2675 (cscope-display-buffer-wrapper (current-buffer)))))
2676
2677
2678 (defun cscope-unix-index-files-filter (process output)
2679 "Called when the indexing process says 'output'. I pop up a
2680 message in a buffer or the echo area"
2681
2682 ;; add the new string
2683 (setq cscope-indexing-status-string
2684 (concat cscope-indexing-status-string output))
2685
2686 ;; and display
2687 (cscope-display-message-or-buffer cscope-indexing-status-string "*cscope-indexing-buffer*"))
2688
2689 (defun cscope-unix-index-files-sentinel (process event)
2690 "Simple sentinel to print a message saying that indexing is finished."
2691 (setq cscope-indexing-status-string
2692 (concat cscope-indexing-status-string
2693 cscope-result-separator
2694 "\n"
2695 (if (equal event "finished\n")
2696 "Indexing finished\n"
2697 (concat "Indexing process received signal: " event "Stopping indexing"))))
2698
2699 (cscope-display-message-or-buffer cscope-indexing-status-string "*cscope-indexing-buffer*")
2700 (delete-process process)
2701 (setq cscope-unix-index-process nil)
2702 (setq cscope-indexing-status-string nil))
2703
2704 (defun cscope-make-index-command (dir only-create-list-of-files)
2705 "Return a string that is a shell script that runs the cscope
2706 indexer"
2707
2708 (let ((findargs
2709
2710 ;; This is really ugly. GNU emacs has find-cmd.el to make things just like
2711 ;; this less ugly, but I want to support xemacs too, and thus I just live with
2712 ;; the uglyness
2713 (mapcar 'shell-quote-argument
2714 `(,dir
2715
2716 ;; limit the search depth if we're not searching recursively
2717 ,@(when (not cscope-index-recursively)
2718 '("-maxdepth" "1"))
2719
2720 ;; apply -prune to any directory we're supposed to ignore
2721 "(" "-type" "d" "("
2722 ,@(apply 'append (mapcar (lambda (dir) (list "-name" dir "-o") )
2723 cscope-indexer-ignored-directories))
2724 "-false"
2725 ")" "-prune" ")" "-o"
2726
2727 ;; accept only files that match the patterns we want
2728 "("
2729 ,@(apply 'append (mapcar (lambda (suffix) (list "-iname" suffix "-o"))
2730 cscope-indexer-suffixes))
2731 "-false"
2732 ")"
2733
2734 ;; accept files and symlinks
2735 "(" "-type" "f" "-o" "-type" "l" ")"
2736
2737 ;; if we made it here, take the result
2738 "-print"))))
2739
2740 (let ((findcmds
2741 (concat "echo 'Creating list of files to index ...'\n"
2742
2743 "find "
2744 (mapconcat 'identity findargs " ") " > "
2745 (shell-quote-argument cscope-index-file) "\n"
2746
2747 "echo 'Creating list of files to index ... done'\n"))
2748
2749 (indexcmds
2750 (concat "echo 'Indexing files ...'\n"
2751
2752 (shell-quote-argument (cscope--get-cscope-program))
2753 " "
2754 (mapconcat 'shell-quote-argument
2755 (cscope-construct-custom-options-list)
2756 " ")
2757 " -b -i "
2758 (shell-quote-argument cscope-index-file)
2759 " -f " (shell-quote-argument cscope-database-file) "\n"
2760
2761 "echo 'Indexing files ... done'\n")))
2762
2763 (if only-create-list-of-files
2764 findcmds
2765 (concat findcmds indexcmds)))))
2766
2767 (defun cscope-unix-index-files-internal (top-directory header-text only-create-list-of-files)
2768 "Core function to call the indexing script."
2769 (save-excursion
2770 (setq cscope-indexing-status-string
2771 (or header-text ""))
2772 (setq cscope-unix-index-process
2773 (let* ((default-directory (cscope-canonicalize-directory top-directory))
2774 (index-command
2775 (cscope-make-index-command (if cscope-use-relative-paths
2776 "." default-directory)
2777 only-create-list-of-files)))
2778 ;; Communicate with a pipe. Slightly more efficient than
2779 ;; a TTY
2780 (let ((process-connection-type nil))
2781 (funcall cscope-start-file-process "cscope-indexer"
2782 nil
2783 "sh" "-c" index-command))))
2784 (set-process-filter cscope-unix-index-process 'cscope-unix-index-files-filter)
2785 (set-process-sentinel cscope-unix-index-process
2786 'cscope-unix-index-files-sentinel)
2787 (process-kill-without-query cscope-unix-index-process)))
2788
2789
2790 (defun cscope-index-files (top-directory)
2791 "Index files in a directory.
2792 This function creates a list of files to index, and then indexes
2793 the listed files.
2794 The variable, \"cscope-index-recursively\", controls whether or not
2795 subdirectories are indexed."
2796 (interactive "DIndex files in directory: ")
2797 (let ()
2798 (cscope-unix-index-files-internal
2799 top-directory
2800 (format "Creating cscope index `%s' in:\n\t%s\n\n%s"
2801 cscope-database-file top-directory cscope-result-separator)
2802 nil)
2803 ))
2804
2805
2806 (defun cscope-create-list-of-files-to-index (top-directory)
2807 "Create a list of files to index.
2808 The variable, \"cscope-index-recursively\", controls whether or not
2809 subdirectories are indexed."
2810 (interactive "DCreate file list in directory: ")
2811 (let ()
2812 (cscope-unix-index-files-internal
2813 top-directory
2814 (format "Creating cscope file list `%s' in:\n\t%s\n\n"
2815 cscope-index-file top-directory)
2816 t)
2817 ))
2818
2819
2820 (defun cscope-edit-list-of-files-to-index ()
2821 "Search for and edit the list of files to index.
2822 If this functions causes a new file to be edited, that means that a
2823 cscope.out file was found without a corresponding cscope.files file."
2824 (interactive)
2825 (let (info directory file)
2826 (setq info (cscope-find-info nil))
2827 (if (/= (length info) 1)
2828 (error "There is no unique cscope database directory!"))
2829 (setq directory (car (car info)))
2830 (if (not (stringp directory))
2831 (setq directory
2832 (cscope-search-directory-hierarchy default-directory)))
2833 (setq file (concat (file-name-as-directory directory) cscope-index-file))
2834 (find-file file)
2835 (message (concat "File: " file))
2836 ))
2837
2838
2839 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2840
2841 (defun cscope-tell-user-about-directory ()
2842 "Display the name of the directory containing the cscope database."
2843 (interactive)
2844 (let (info directory)
2845 (setq info (cscope-find-info nil))
2846 (if (= (length info) 1)
2847 (progn
2848 (setq directory (car (car info)))
2849 (message (concat "Cscope directory: " directory))
2850 )
2851 (let ( (outbuf (get-buffer-create cscope-info-buffer-name)) )
2852 (cscope-display-buffer-wrapper outbuf)
2853 (with-current-buffer outbuf
2854 (buffer-disable-undo)
2855 (erase-buffer)
2856 (insert "Cscope search directories:\n")
2857 (while info
2858 (if (listp (car info))
2859 (progn
2860 (setq directory (car (car info)))
2861 (if (not (stringp directory))
2862 (setq directory
2863 (cscope-search-directory-hierarchy
2864 default-directory)))
2865 (insert "\t" directory "\n")
2866 ))
2867 (setq info (cdr info))))))))
2868
2869
2870 (defun cscope-dired-directory ()
2871 "Run dired upon the cscope database directory.
2872 If possible, the cursor is moved to the name of the cscope database
2873 file."
2874 (interactive)
2875 (let (info directory buffer p1 p2 pos)
2876 (setq info (cscope-find-info nil))
2877 (if (/= (length info) 1)
2878 (error "There is no unique cscope database directory!"))
2879 (setq directory (car (car info)))
2880 (if (not (stringp directory))
2881 (setq directory
2882 (cscope-search-directory-hierarchy default-directory)))
2883 (setq buffer (dired-noselect directory nil))
2884 (switch-to-buffer buffer)
2885 (set-buffer buffer)
2886 (save-excursion
2887 (goto-char (point-min))
2888 (setq p1 (search-forward cscope-index-file nil t))
2889 (if p1
2890 (setq p1 (- p1 (length cscope-index-file))))
2891 )
2892 (save-excursion
2893 (goto-char (point-min))
2894 (setq p2 (search-forward cscope-database-file nil t))
2895 (if p2
2896 (setq p2 (- p2 (length cscope-database-file))))
2897 )
2898 (cond
2899 ( (and p1 p2)
2900 (if (< p1 p2)
2901 (setq pos p1)
2902 (setq pos p2))
2903 )
2904 ( p1
2905 (setq pos p1)
2906 )
2907 ( p2
2908 (setq pos p2)
2909 )
2910 )
2911 (if pos
2912 (set-window-point (get-buffer-window buffer) pos))
2913 ))
2914
2915
2916 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2917
2918 (defun cscope-extract-symbol-at-cursor (extract-filename try-to-use-region)
2919 (if (and try-to-use-region (use-region-p))
2920
2921 ;; We have a region and we were asked to use it. This usually happens when
2922 ;; looking for text strings or regular expressions
2923 (buffer-substring-no-properties (region-beginning) (region-end))
2924
2925 ;; Try to infer symbol from the text
2926 (let* ( (symbol-chars (if extract-filename
2927 cscope-filename-chars
2928 cscope-symbol-chars))
2929 (symbol-char-regexp (concat "[" symbol-chars "]"))
2930 )
2931 (save-excursion
2932 (buffer-substring-no-properties
2933 (progn
2934 (if (not (looking-at symbol-char-regexp))
2935 (re-search-backward "\\w" nil t))
2936 (skip-chars-backward symbol-chars)
2937 (point))
2938 (progn
2939 (skip-chars-forward symbol-chars)
2940 (point)
2941 )))
2942 )))
2943
2944
2945 (defun cscope-prompt-for-symbol (prompt extract-filename try-to-use-region is-regex)
2946 "Prompt the user for a cscope symbol."
2947 (let ((sym (cscope-extract-symbol-at-cursor extract-filename try-to-use-region)))
2948 (if (or (not sym)
2949 (string= sym "")
2950 (not (boundp 'cscope-suppress-user-symbol-prompt))
2951
2952 ;; Always prompt for symbol in dired mode.
2953 (eq major-mode 'dired-mode))
2954 (let ((full-prompt (concat prompt
2955 (when sym
2956 (concat "("
2957 (when is-regex "regex; ")
2958 "default '"
2959 sym
2960 "'): ")))))
2961 (setq sym (read-string full-prompt nil 'cscope-prompt-minibuffer-history sym)))
2962 sym)
2963 ))
2964
2965
2966 (defun cscope-find-this-symbol (symbol)
2967 "Locate a symbol in source code."
2968 (interactive (list
2969 (cscope-prompt-for-symbol "Find this symbol " nil nil t)
2970 ))
2971 (setq cscope-previous-user-search `(cscope-find-this-symbol ,symbol))
2972 (cscope-call "Finding symbol:" 0 symbol)
2973 )
2974
2975
2976 (defun cscope-find-global-definition (symbol)
2977 "Find a symbol's global definition."
2978 (interactive (list
2979 (cscope-prompt-for-symbol "Find this global definition " nil nil t)
2980 ))
2981 (setq cscope-previous-user-search `(cscope-find-global-definition ,symbol))
2982 (cscope-call "Finding global definition:" 1 symbol)
2983 )
2984
2985
2986 (defun cscope-find-global-definition-no-prompting ()
2987 "Find a symbol's global definition without prompting."
2988 (interactive)
2989 (let ( (symbol (cscope-extract-symbol-at-cursor nil nil)))
2990 (setq cscope-previous-user-search `(cscope-find-global-definition-no-prompting ,symbol))
2991 (cscope-call "Finding global definition:" 1 symbol)
2992 ))
2993
2994
2995 (defun cscope-find-called-functions (symbol)
2996 "Display functions called by a function."
2997 (interactive (list
2998 (cscope-prompt-for-symbol
2999 "Find functions called by this function " nil nil t)
3000 ))
3001 (setq cscope-previous-user-search `(cscope-find-called-functions ,symbol))
3002 (cscope-call "Finding functions called by:" 2 symbol)
3003 )
3004
3005
3006 (defun cscope-find-functions-calling-this-function (symbol)
3007 "Display functions calling a function."
3008 (interactive (list
3009 (cscope-prompt-for-symbol
3010 "Find functions calling this function " nil nil t)
3011 ))
3012 (setq cscope-previous-user-search `(cscope-find-functions-calling-this-function ,symbol))
3013 (cscope-call "Finding functions calling:" 3 symbol)
3014 )
3015
3016
3017 (defun cscope-find-this-text-string (symbol)
3018 "Locate where a text string occurs."
3019 (interactive (list
3020 (cscope-prompt-for-symbol "Find this text string " nil t nil)
3021 ))
3022 (setq cscope-previous-user-search `(cscope-find-this-text-string ,symbol))
3023 (cscope-call "Finding text string:" 4 symbol)
3024 )
3025
3026
3027 (defun cscope-find-egrep-pattern (symbol)
3028 "Run egrep over the cscope database."
3029 (interactive (list
3030 (let (cscope-no-mouse-prompts)
3031 (cscope-prompt-for-symbol "Find this egrep pattern " nil t t))
3032 ))
3033 (setq cscope-previous-user-search `(cscope-find-egrep-pattern ,symbol))
3034 (cscope-call "Finding egrep pattern:" 6 symbol)
3035 )
3036
3037
3038 (defun cscope-find-this-file (symbol)
3039 "Locate a file."
3040 (interactive (list
3041 (let (cscope-no-mouse-prompts)
3042 (cscope-prompt-for-symbol "Find this file " t nil t))
3043 ))
3044
3045 (setq cscope-previous-user-search `(cscope-find-this-file ,symbol))
3046 (cscope-call "Finding file:" 7 symbol)
3047 )
3048
3049
3050 (defun cscope-find-files-including-file (symbol)
3051 "Locate all files #including a file."
3052 (interactive (list
3053 (let (cscope-no-mouse-prompts)
3054 (cscope-prompt-for-symbol
3055 "Find files #including this file " t nil nil))
3056 ))
3057 (setq cscope-previous-user-search `(cscope-find-files-including-file ,symbol))
3058 (cscope-call "Finding files #including file:" 8 symbol)
3059 )
3060
3061
3062 (defun cscope-find-assignments-to-this-symbol (symbol)
3063 "Locate assignments to a symbol in the source code."
3064 (interactive (list
3065 (cscope-prompt-for-symbol "Find assignments to this symbol " nil nil t)
3066 ))
3067 (setq cscope-previous-user-search `(cscope-find-assignments-to-this-symbol ,symbol))
3068 (cscope-call "Finding assignments to symbol:" 9 symbol)
3069 )
3070
3071
3072
3073 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3074
3075 ;;;###autoload
3076 (define-minor-mode cscope-minor-mode
3077 "This cscope minor mode maps cscope keybindings to make cscope
3078 functions more accessible.
3079
3080 Key bindings:
3081 \\{cscope-minor-mode-keymap}"
3082 nil nil cscope-minor-mode-keymap
3083 (when cscope-minor-mode
3084 (easy-menu-add cscope-global-menu cscope-minor-mode-keymap)
3085 (run-hooks 'cscope-minor-mode-hooks)))
3086
3087 ;;;###autoload
3088 (defun cscope-setup ()
3089 "Automatically turns on cscope-minor-mode when editing C and
3090 C++ sources"
3091 (interactive)
3092 (add-hook 'c-mode-hook (function cscope-minor-mode))
3093 (add-hook 'c++-mode-hook (function cscope-minor-mode))
3094 (add-hook 'dired-mode-hook (function cscope-minor-mode)))
3095
3096 (provide 'xcscope)
3097
3098 ;;; xcscope.el ends here