comparison lisp/utils/id-select.el @ 4:b82b59fe008d r19-15b3

Import from CVS: tag r19-15b3
author cvs
date Mon, 13 Aug 2007 08:46:56 +0200
parents
children 441bb1e64a06
comparison
equal deleted inserted replaced
3:30df88044ec6 4:b82b59fe008d
1 ;;!emacs
2 ;;
3 ;; LCD-ENTRY: id-select.el|InfoDock Associates|elisp@infodock.com|Syntactical region selecting|12/02/96|1.4.3|
4 ;;
5 ;; FILE: id-select.el
6 ;; SUMMARY: Select larger and larger syntax-driven regions in a buffer.
7 ;; USAGE: XEmacs and Emacs Lisp Library
8 ;; KEYWORDS: matching, mouse
9 ;;
10 ;; AUTHOR: Bob Weiner
11 ;;
12 ;; ORG: InfoDock Associates. We sell corporate support and development
13 ;; contracts for InfoDock, Emacs and XEmacs.
14 ;; E-mail: <info@infodock.com> Web: http://www.infodock.com
15 ;; Tel: +1 408-243-3300
16 ;;
17 ;; ORIG-DATE: 19-Oct-96 at 02:25:27
18 ;; LAST-MOD: 2-Dec-96 at 19:45:28 by Bob Weiner
19 ;;
20 ;; Copyright (C) 1996 InfoDock Associates
21 ;;
22 ;; This file is part of InfoDock.
23 ;; It is available for use and distribution under the terms of the GNU Public
24 ;; License.
25 ;;
26 ;; DESCRIPTION:
27 ;;
28 ;; This is a radically cool, drop in mouse and keyboard-based library for
29 ;; selecting successively bigger syntactical regions within a buffer.
30 ;; Simply load this library and you are ready to try it out by
31 ;; double-clicking on various kinds of characters in different buffer major
32 ;; modes. You'll quickly get the hang of it. (It also provides a command
33 ;; to jump between beginning and end tags within HTML and SGML buffers.)
34 ;;
35 ;; A great deal of smarts are built-in so that it does the right thing
36 ;; almost all of the time; many other attempts at similar behavior such as
37 ;; thing.el fail to deal with many file format complexities.
38 ;;
39 ;; Double clicks of the Selection Key (left mouse key) at the same point
40 ;; will select bigger and bigger regions with each successive use. The
41 ;; first double click selects a region based upon the character at the
42 ;; point of the click. For example, with the point over an opening or
43 ;; closing grouping character, such as { or }, the whole grouping is
44 ;; selected, e.g. a C function. When on an _ or - within a programming
45 ;; language variable name, the whole name is selected. The type of
46 ;; selection is displayed in the minibuffer as feedback. When using a
47 ;; language based mainly on indenting, like Bourne shell, a double click on
48 ;; the first alpha character of a line, such as an if statement, selects
49 ;; the whole statement.
50 ;;
51 ;; ---------------
52 ;;
53 ;; This whole package is driven by a single function, available in mouse
54 ;; and keyboard forms, that first marks a region based on the syntax
55 ;; category of the character following point. Successive invocations mark
56 ;; larger and larger regions until the whole buffer is marked. See the
57 ;; documentation for the function, id-select-syntactical-region, for the
58 ;; kinds of syntax categories handled.
59 ;;
60 ;; Loading this package automatically installs its functionalty on
61 ;; double-clicks (or higher) of the left mouse key. (See the documentation
62 ;; for the variable, mouse-track-click-hook, for how this is done.) A
63 ;; single click of the left button will remove the region and reset point.
64 ;;
65 ;; The function, id-select-thing, may be bound to a key, {C-c s}, seems to
66 ;; be a reasonable choice, to provide the same syntax-driven region
67 ;; selection functionality. Use {C-g} to unmark the region when done.
68 ;; Use, id-select-thing-with-mouse, if you want to bind this to a mouse key
69 ;; and thereby use single clicks instead of double clicks.
70 ;;
71 ;; Three other commands are also provided:
72 ;; id-select-and-copy-thing - mark and copy the syntactical unit to the
73 ;; kill ring
74 ;; id-select-and-kill-thing - kill the syntactical unit at point
75 ;; id-select-goto-matching-tag - In HTML and SGML modes (actually any
76 ;; listed in the variable, `id-select-markup-modes'), moves point to the
77 ;; start of the tag paired with the closest tag that point is within or
78 ;; which it precedes, so you can quickly jump back and forth between
79 ;; open and close tags.
80 ;;
81 ;; ---------------
82 ;; SETUP:
83 ;;
84 ;; To autoload this package under XEmacs or InfoDock via mouse usage, add
85 ;; the following line to one of your initialization files. (Don't do this
86 ;; for GNU Emacs.)
87 ;;
88 ;; (add-hook 'mouse-track-click-hook 'id-select-double-click-hook)
89 ;;
90 ;; For any version of Emacs you should add the following autoload entries
91 ;; at your site:
92 ;;
93 ;; (autoload 'id-select-and-kill-thing
94 ;; "id-select" "Kill syntactical region selection" t)
95 ;; (autoload 'id-select-and-copy-thing
96 ;; "id-select" "Select and copy syntactical region" t)
97 ;; (autoload 'id-select-double-click-hook
98 ;; "id-select" "Double mouse click syntactical region selection" nil)
99 ;; (autoload 'id-select-thing
100 ;; "id-select" "Keyboard-driven syntactical region selection" t)
101 ;; (autoload 'id-select-thing-with-mouse
102 ;; "id-select" "Single mouse click syntactical region selection" t)
103 ;;
104 ;; If you want to be able to select C++ and Java methods and classes by
105 ;; double-clicking on the first character of a definition or on its opening
106 ;; or closing brace, you may need the following setting (all
107 ;; because Sun programmers can't put their opening braces in the first
108 ;; column):
109 ;;
110 ;; (add-hook 'java-mode-hook
111 ;; (function
112 ;; (lambda ()
113 ;; (setq defun-prompt-regexp
114 ;; "^[ \t]*\\(\\(\\(public\\|protected\\|private\\|const\\|abstract\\|synchronized\\|final\\|static\\|threadsafe\\|transient\\|native\\|volatile\\)\\s-+\\)*\\(\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*[][_$.a-zA-Z0-9]+\\|[[a-zA-Z]\\)\\s-*\\)\\s-+\\)\\)?\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*\\s-+\\)\\s-*\\)?\\([_a-zA-Z][^][ \t:;.,{}()=]*\\|\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)\\)\\s-*\\(([^);{}]*)\\)?\\([] \t]*\\)\\(\\s-*\\<throws\\>\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f]*\\)+\\)?\\s-*"))))
115 ;;
116 ;; (add-hook 'c++-mode-hook
117 ;; (function
118 ;; (lambda ()
119 ;; (setq defun-prompt-regexp
120 ;; "^[ \t]*\\(template[ \t\n\r]*<[^>;.{}]+>[ \t\n\r]*\\)?\\(\\(\\(auto\\|const\\|explicit\\|extern[ \t\n\r]+\"[^\"]+\"\\|extern\\|friend\\|inline\\|mutable\\|overload\\|register\\|static\\|typedef\\|virtual\\)[ \t\n\r]+\\)*\\(\\([[<a-zA-Z][]_a-zA-Z0-9]*\\(::[]_a-zA-Z0-9]+\\)?[ \t\n\r]*<[_<>a-zA-Z0-9 ,]+>[ \t\n\r]*[*&]*\\|[[<a-zA-Z][]_<>a-zA-Z0-9]*\\(::[[<a-zA-Z][]_<>a-zA-Z0-9]+\\)?[ \t\n\r]*[*&]*\\)[*& \t\n\r]+\\)\\)?\\(\\(::\\|[[<a-zA-Z][]_a-zA-Z0-9]*[ \t\n\r]*<[^>;{}]+>[ \t\n\r]*[*&]*::\\|[[<a-zA-Z][]_~<>a-zA-Z0-9]*[ \t\n\r]*[*&]*::\\)[ \t\n\r]*\\)?\\(operator[ \t\n\r]*[^ \t\n\r:;.,?~{}]+\\([ \t\n\r]*\\[\\]\\)?\\|[_~<a-zA-Z][^][ \t:;.,~{}()]*\\|[*&]?\\([_~<a-zA-Z][_a-zA-Z0-9]*[ \t\n\r]*<[^>;{}]+[ \t\n\r>]*>\\|[_~<a-zA-Z][_~<>a-zA-Z0-9]*\\)\\)[ \t\n\r]*\\(([^{;]*)\\(\\([ \t\n\r]+const\\|[ \t\n\r]+mutable\\)?\\([ \t\n\r]*[=:][^;{]+\\)?\\)?\\)\\s-*"))))
121 ;;
122 ;; If you want tags, comments, sentences and text blocks to be selectable
123 ;; in HTML mode, you need to add the following to your personal
124 ;; initializations (You would do something similar for SGML mode.):
125 ;;
126 ;; ;; Make tag begin and end delimiters act like grouping characters,
127 ;; ;; for easy syntactical selection of tags.
128 ;; (add-hook 'html-mode-hook
129 ;; (function
130 ;; (lambda ()
131 ;; (modify-syntax-entry ?< "(>" html-mode-syntax-table)
132 ;; (modify-syntax-entry ?> ")<" html-mode-syntax-table)
133 ;; (modify-syntax-entry ?\" "\"" html-mode-syntax-table)
134 ;; (modify-syntax-entry ?= "." html-mode-syntax-table)
135 ;; (make-local-variable 'comment-start)
136 ;; (make-local-variable 'comment-end)
137 ;; (setq comment-start "<!--" comment-end "-->")
138 ;; (make-local-variable 'sentence-end)
139 ;; (setq sentence-end "\\([^ \t\n\r>]<\\|>\\(<[^>]*>\\)*\\|[.?!][]\"')}]*\\($\\| $\\|\t\\| \\)\\)[ \t\n]*")
140 ;;
141 ;; (define-key html-mode-map "\C-c." 'id-select-goto-matching-tag)
142 ;; )))
143 ;;
144 ;; DESCRIP-END.
145
146 ;;; ************************************************************************
147 ;;; Public variables
148 ;;; ************************************************************************
149
150 (defvar id-select-brace-modes
151 '(c++-mode c-mode java-mode objc-mode perl-mode tcl-mode)
152 "*List of language major modes which define things with brace delimiters.")
153
154 (defvar id-select-markup-modes
155 '(html-mode sgml-mode)
156 "*List of markup language modes that use SGML-style <tag> </tag> pairs.")
157
158 (defvar id-select-text-modes
159 '(fundamental-mode kotl-mode indented-text-mode Info-mode outline-mode text-mode)
160 "*List of textual modes where paragraphs may be outdented or indented.")
161
162 (defvar id-select-indent-modes
163 (append '(asm-mode csh-mode eiffel-mode ksh-mode python-mode pascal-mode
164 sather-mode)
165 id-select-text-modes)
166 "*List of language major modes which use mostly indentation to define syntactic structure.")
167
168 (defvar id-select-indent-non-end-regexp-alist
169 '((csh-mode "\\(\\|then\\|elsif\\|else\\)[ \t]*$")
170 (eiffel-mode "\\(\\|then\\|else if\\|else\\)[ \t]*$")
171 (ksh-mode "\\(\\|then\\|elif\\|else\\)[ \t]*$")
172 (pascal-mode "\\(\\|then\\|else\\)[ \t]*$")
173 (python-mode "[ \t]*$")
174 (sather-mode "\\(\\|then\\|else if\\|else\\)[ \t]*$")
175 ;;
176 (fundamental-mode "[^ \t\n]")
177 (kotl-mode "[^ \t\n]")
178 (indented-text-mode "[^ \t\n]")
179 (Info-mode "[^ \t\n]")
180 (outline-mode "[^\\*]")
181 (text-mode "[^ \t\n]")
182 )
183 "List of (major-mode . non-terminator-line-regexp) elements used to avoid early dropoff when marking indented code.")
184
185 (defvar id-select-indent-end-regexp-alist
186 '((csh-mode "end\\|while")
187 (eiffel-mode "end")
188 (ksh-mode "\\(fi\\|esac\\|until\\|done\\)[ \t\n]")
189 (pascal-mode "end")
190 (sather-mode "end")
191 ;;
192 (fundamental-mode "[ \t]*$")
193 (indented-text-mode "[ \t]*$")
194 (Info-mode "[ \t]*$")
195 (text-mode "[ \t]*$")
196 )
197 "List of (major-mode . terminator-line-regexp) elements used to include a final line when marking indented code.")
198
199 (defvar id-select-char-p t
200 "*If t, return single character boundaries when all else fails.")
201
202 (defvar id-select-display-type t
203 "*If t, display the thing selected with each mouse click.")
204
205 (defvar id-select-whitespace t
206 "*If t, groups of whitespace are considered as things.")
207
208 (if (string-match "XEmacs" emacs-version)
209 (add-hook 'mouse-track-click-hook 'id-select-double-click-hook)
210 (if (string-match "^19\\." emacs-version)
211 (progn (transient-mark-mode 1)
212 (global-set-key [mouse-1] 'mouse-set-point)
213 (global-set-key [double-mouse-1] 'id-select-thing-with-mouse)
214 (global-set-key [triple-mouse-1] 'id-select-thing-with-mouse))))
215
216 ;;; ************************************************************************
217 ;;; Public functions
218 ;;; ************************************************************************
219
220 ;;
221 ;; Commands
222 ;;
223
224 ;;;###autoload
225 (defun id-select-thing ()
226 "Mark the region selected by the syntax of the thing at point.
227 If invoked repeatedly, selects bigger and bigger things.
228 If `id-select-display-type' is non-nil, the type of selection is displayed in
229 the minibuffer."
230 (interactive
231 (cond ((and (fboundp 'region-active-p) (region-active-p))
232 nil)
233 ((and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
234 nil)
235 (t
236 ;; Reset selection based on the syntax of character at point.
237 (id-select-reset)
238 nil)))
239 (let ((region (id-select-boundaries (point))))
240 (if region
241 (progn (goto-char (car region))
242 (set-mark (cdr region))
243 (if (fboundp 'activate-region) (activate-region))
244 (if (and (boundp 'transient-mark-mode)
245 transient-mark-mode)
246 (setq mark-active t))
247 (and (interactive-p) id-select-display-type
248 (message "%s" id-select-previous))
249 (run-hooks 'id-select-thing-hook)
250 t))))
251
252 ;;;###autoload
253 (defun id-select-thing-with-mouse (event)
254 "Select a region based on the syntax of the character from a mouse click.
255 If the click occurs at the same point as the last click, select
256 the next larger syntactic structure. If `id-select-display-type' is non-nil,
257 the type of selection is displayed in the minibuffer."
258 (interactive "@e")
259 (cond ((and (eq id-select-prior-point (point))
260 (eq id-select-prior-buffer (current-buffer)))
261 ;; Prior click was at the same point as before, so enlarge
262 ;; selection to the next bigger item.
263 (if (and (id-select-bigger-thing) id-select-display-type)
264 (progn
265 ;; Conditionally, save selected region for pasting.
266 (cond
267 ;; XEmacs
268 ((fboundp 'x-store-cutbuffer)
269 (x-store-cutbuffer (buffer-substring (point) (mark))))
270 ;; Emacs 19
271 ((and (boundp 'interprogram-cut-function)
272 interprogram-cut-function)
273 (x-set-selection 'PRIMARY (buffer-substring (point) (mark)))))
274 (message "%s" id-select-previous)))
275 t)
276 (t (setq this-command 'mouse-start-selection)
277 (id-select-reset)
278 (id-select-thing-with-mouse event))))
279
280 ;;;###autoload
281 (defun id-select-goto-matching-tag ()
282 "If in a major mode listed in `id-select-markup-modes,' moves point to the start of the tag paired with the closest tag that point is within or precedes.
283 Returns t if point is moved, else nil.
284 Signals an error if no tag is found following point or if the closing tag
285 does not have a `>' terminator character."
286 (interactive)
287 (if (not (memq major-mode id-select-markup-modes))
288 nil
289 (let ((result)
290 ;; Assume case of tag names is irrelevant.
291 (case-fold-search t)
292 (opoint (point))
293 (tag)
294 end-point
295 start-regexp
296 end-regexp)
297
298 ;; Leave point at the start of the tag that point is within or that
299 ;; follows point.
300 (cond
301 ;; Point is at the start of a tag.
302 ((looking-at "<[^<> \t\n\r]"))
303 ;; Point was within a tag.
304 ((and (re-search-backward "[<>]" nil t)
305 (looking-at "<[^<> \t\n\r]")))
306 ;; Move to following tag.
307 ((and (re-search-forward "<" nil t)
308 (progn (backward-char 1)
309 (looking-at "<[^<> \t\n\r]"))))
310 ;; No tag follows point.
311 (t (error "(id-select-goto-matching-tag): No tag found after point.")))
312
313 (if (catch 'done
314 (cond
315 ;; Beginning of a tag pair
316 ((looking-at "<[^/][^<> \t\n\r]*")
317 (setq tag (buffer-substring (match-beginning 0) (match-end 0))
318 start-regexp (regexp-quote tag)
319 end-regexp (concat "</" (substring start-regexp 1)))
320 ;; Skip over nested tags.
321 (let ((count 0)
322 (regexp (concat start-regexp "\\|" end-regexp))
323 match-point)
324 (while (and (>= count 0)
325 (re-search-forward regexp nil t))
326 (setq match-point (match-beginning 0))
327 (if (/= (char-after (1+ (match-beginning 0))) ?/)
328 ;; Start tag
329 (setq count (1+ count))
330 ;; End tag
331 (setq end-point (point))
332 (if (or (not (re-search-forward "[<>]" nil t))
333 (= (preceding-char) ?<))
334 ;; No terminator character `>' for end tag
335 (progn (setq result end-point)
336 (throw 'done nil)))
337 (setq count (1- count))
338 (if (= count 0)
339 (progn
340 (goto-char match-point)
341 (setq result t)
342 (throw 'done result)))))))
343 ;;
344 ;; End of a tag pair
345 ((or (looking-at "</[^> \t\n\r]+")
346 (and (skip-chars-backward "<")
347 (looking-at "</[^> \t\n\r]+")))
348 (goto-char (match-end 0))
349 (setq tag (buffer-substring (match-beginning 0) (match-end 0))
350 end-regexp (regexp-quote tag)
351 start-regexp (concat "<" (substring end-regexp 2)))
352 (setq end-point (point))
353 (if (or (not (re-search-forward "[<>]" nil t))
354 (= (preceding-char) ?<))
355 ;; No terminator character `>' for end tag
356 (progn (setq result end-point)
357 (throw 'done nil)))
358 ;; Skip over nested tags.
359 (let ((count 0)
360 (regexp (concat start-regexp "\\|" end-regexp)))
361 (while (and (>= count 0)
362 (re-search-backward regexp nil t))
363 (if (= (char-after (1+ (point))) ?/)
364 ;; End tag
365 (setq count (1+ count))
366 ;; Start tag
367 (setq count (1- count))
368 (if (= count 0)
369 (progn
370 (setq result t)
371 (throw 'done t)))))))))
372 nil
373 ;; Didn't find matching tag.
374 (goto-char opoint))
375
376 (cond ((integerp result)
377 (goto-char result)
378 (error "(id-select-goto-matching-tag): Add a terminator character for this end <tag>"))
379 ((null tag)
380 (error "(id-select-goto-matching-tag): No <tag> following point"))
381 ((null result)
382 (if (interactive-p)
383 (progn
384 (beep)
385 (message "(id-select-goto-matching-tag): No matching tag for %s>"
386 tag)
387 result)))
388 (t result)))))
389
390 ;;;###autoload
391 (defun id-select-and-copy-thing ()
392 "Copy the region surrounding the syntactical unit at point."
393 (interactive)
394 (let ((bounds (id-select-boundaries (point))))
395 (if bounds (copy-region-as-kill (car bounds) (cdr bounds)))))
396
397 ;;;###autoload
398 (defun id-select-and-kill-thing ()
399 "Kill the region surrounding the syntactical unit at point."
400 (interactive "*")
401 (let ((bounds (id-select-boundaries (point))))
402 (if bounds (kill-region (car bounds) (cdr bounds)))))
403
404
405 ;;
406 ;; Functions
407 ;;
408
409 (defun id-select-boundaries (pos)
410 "Return the (start . end) of a syntactically defined region based upon the last region selected or on position POS.
411 The character at POS is selected if no other thing is matched."
412 (interactive)
413 (setq zmacs-region-stays t)
414 (setcar id-select-old-region (car id-select-region))
415 (setcdr id-select-old-region (cdr id-select-region))
416 (let ((prior-type id-select-previous))
417 (cond
418 ((eq id-select-previous 'char)
419 (id-select-syntactical-region pos))
420 ((and (car id-select-old-region)
421 (memq id-select-previous
422 '(sexp sexp-start sexp-end sexp-up))
423 (id-select-sexp-up pos)
424 (id-select-region-bigger-p id-select-old-region id-select-region))
425 id-select-region)
426 ;;
427 ;; In the general case, we can't know ahead of time what the next
428 ;; biggest type of thing to select is, so we test them all and choose
429 ;; the best fit. This means that dynamically, the order of type
430 ;; selection will change based on the buffer context.
431 (t (let ((min-region (1+ (- (point-max) (point-min))))
432 (result)
433 region region-size)
434 (mapcar
435 (function
436 (lambda (sym-func)
437 (setq region
438 (if (car (cdr sym-func))
439 (funcall (car (cdr sym-func)) pos)))
440 (if (and region (car region)
441 (id-select-region-bigger-p
442 id-select-old-region region)
443 (setq region-size
444 (- (cdr region) (car region)))
445 (< region-size min-region))
446 (setq min-region region-size
447 result
448 (list;; The actual selection type is
449 ;; sometimes different than the one we
450 ;; originally tried, so recompute it here.
451 (car (assq id-select-previous
452 id-select-bigger-alist))
453 (car region) (cdr region))))))
454 id-select-bigger-alist)
455 (if result
456 ;; Returns id-select-region
457 (progn (setq id-select-previous (car result))
458 (id-select-set-region (nth 1 result) (nth 2 result)))
459 ;;
460 ;; Restore prior selection type since we failed to find a
461 ;; new one.
462 (setq id-select-previous prior-type)
463 (beep)
464 (message
465 "(id-select-boundaries): `%s' is the largest selectable region"
466 id-select-previous)
467 nil))))))
468
469 ;;;###autoload
470 (defun id-select-double-click-hook (event click-count)
471 "Select a region based on the syntax of the character wherever the mouse is double-clicked.
472 If the double-click occurs at the same point as the last double-click, select
473 the next larger syntactic structure. If `id-select-display-type' is non-nil,
474 the type of selection is displayed in the minibuffer."
475 (cond ((/= click-count 2)
476 ;; Return nil so any other hooks are performed.
477 nil)
478 (t (id-select-thing-with-mouse event))))
479
480 (defun id-select-syntactical-region (pos)
481 "Return the (start . end) of a syntactically defined region based upon the buffer position POS.
482 Uses `id-select-syntax-alist' and the current buffer's syntax table to
483 determine syntax groups.
484
485 Typically:
486 Open or close grouping character syntax marks an s-expression.
487 Double quotes mark strings.
488 The end of a line marks the line, including its trailing newline.
489 Word syntax marks the current word.
490 Symbol syntax (such as _) marks a symbol.
491 Whitespace marks a span of whitespace.
492 Comment start or end syntax marks the comment.
493 Punctuation syntax marks the words on both sides of the punctuation.
494 The fallback default is to mark the character at POS.
495
496 If an error occurs during syntax scanning, it returns nil."
497 (interactive "d")
498 (setq id-select-previous 'char)
499 (if (save-excursion (goto-char pos) (eolp))
500 (id-select-line pos)
501 (let* ((syntax (char-syntax (if (eobp) (preceding-char) (char-after pos))))
502 (pair (assq syntax id-select-syntax-alist)))
503 (cond ((and pair
504 (or id-select-whitespace
505 (not (eq (car (cdr pair)) 'thing-whitespace))))
506 (funcall (car (cdr pair)) pos))
507 (id-select-char-p
508 (setq id-select-previous 'char)
509 (id-select-set-region pos (1+ pos)))
510 (t
511 nil)))))
512
513 ;;; ************************************************************************
514 ;;; Private functions
515 ;;; ************************************************************************
516
517 (defun id-select-at-blank-line-or-comment ()
518 "Return non-nil if on a blank line or a comment start or end line.
519 Assumes point is befor any non-whitespace character on the line."
520 (let ((comment-end-p (and (stringp comment-end)
521 (not (string-equal comment-end "")))))
522 (if (looking-at
523 (concat "\\s-*$\\|\\s-*\\(//\\|/\\*\\|.*\\*/"
524 (if comment-start
525 (concat
526 "\\|" (regexp-quote comment-start)))
527 (if comment-end-p
528 (concat
529 "\\|.*" (regexp-quote comment-end)))
530 "\\)"))
531 (or (not (and comment-start comment-end-p))
532 ;; Ignore start and end of comments that
533 ;; follow non-commented text.
534 (not (looking-at
535 (format ".*\\S-.*%s.*%s"
536 (regexp-quote comment-start)
537 (regexp-quote comment-end))))))))
538
539 (defun id-select-region-bigger-p (old-region new-region)
540 "Return t if OLD-REGION is smaller than NEW-REGION and NEW-REGION partially overlaps OLD-REGION, or if OLD-REGION is uninitialized."
541 (if (null (car old-region))
542 t
543 (and (> (abs (- (cdr new-region) (car new-region)))
544 (abs (- (cdr old-region) (car old-region))))
545 ;; Ensure the two regions intersect.
546 (or (and (<= (min (cdr new-region) (car new-region))
547 (min (cdr old-region) (car old-region)))
548 (> (max (cdr new-region) (car new-region))
549 (min (cdr old-region) (car old-region))))
550 (and (> (min (cdr new-region) (car new-region))
551 (min (cdr old-region) (car old-region)))
552 (<= (min (cdr new-region) (car new-region))
553 (max (cdr old-region) (car old-region))))))))
554
555 (defun id-select-bigger-thing ()
556 "Select a bigger object where point is."
557 (prog1
558 (id-select-thing)
559 (setq this-command 'select-thing)))
560
561 (defun id-select-reset ()
562 ;; Reset syntactic selection.
563 (setq id-select-prior-point (point)
564 id-select-prior-buffer (current-buffer)
565 id-select-previous 'char)
566 (id-select-set-region nil nil))
567
568 (defun id-select-set-region (beginning end)
569 "Set the cons cell held by the variable `id-select-region' to (BEGINNING . END).
570 Return the updated cons cell."
571 (setcar id-select-region beginning)
572 (setcdr id-select-region end)
573 (if (and (null beginning) (null end))
574 (progn (setcar id-select-old-region nil)
575 (setcdr id-select-old-region nil)))
576 (if (and (not (eq id-select-previous 'buffer))
577 (integerp beginning) (integerp end)
578 (= beginning (point-min)) (= end (point-max)))
579 ;; If we selected the whole buffer, make sure that 'thing' type is 'buffer'.
580 nil
581 id-select-region))
582
583 (defun id-select-string-p (&optional start-delim end-delim)
584 "Returns (start . end) of string whose first line point is within or immediately before.
585 Positions include delimiters. String is delimited by double quotes unless
586 optional START-DELIM and END-DELIM (strings) are given.
587 Returns nil if not within a string."
588 (let ((opoint (point))
589 (count 0)
590 bol start delim-regexp start-regexp end-regexp)
591 (or start-delim (setq start-delim "\""))
592 (or end-delim (setq end-delim "\""))
593 ;; Special case for the empty string.
594 (if (looking-at (concat (regexp-quote start-delim)
595 (regexp-quote end-delim)))
596 (id-select-set-region (point) (match-end 0))
597 (setq start-regexp (concat "\\(^\\|[^\\]\\)\\("
598 (regexp-quote start-delim) "\\)")
599 end-regexp (concat "[^\\]\\(" (regexp-quote end-delim) "\\)")
600 delim-regexp (concat start-regexp "\\|" end-regexp))
601 (save-excursion
602 (beginning-of-line)
603 (setq bol (point))
604 (while (re-search-forward delim-regexp opoint t)
605 (setq count (1+ count))
606 ;; This is so we don't miss the closing delimiter of an empty
607 ;; string.
608 (if (and (= (point) (1+ bol))
609 (looking-at (regexp-quote end-delim)))
610 (setq count (1+ count))
611 (if (bobp) nil (backward-char 1))))
612 (goto-char opoint)
613 ;; If found an even # of starting and ending delimiters before
614 ;; opoint, then opoint is at the start of a string, where we want it.
615 (if (zerop (mod count 2))
616 (if (bobp) nil (backward-char 1))
617 (re-search-backward start-regexp nil t))
618 ;; Point is now before the start of the string.
619 (if (re-search-forward start-regexp nil t)
620 (progn
621 (setq start (match-beginning 2))
622 (if (re-search-forward end-regexp nil t)
623 (id-select-set-region start (point)))))))))
624
625 ;;;
626 ;;; Code selections
627 ;;;
628
629 (defun id-select-brace-def-or-declaration (pos)
630 "If POS is at the first character, opening brace or closing brace of a brace delimited language definition, return (start . end) region, else nil.
631 The major mode for each supported brace language must be included in the
632 list, id-select-brace-modes."
633 (interactive)
634 (if (not (and (featurep 'cc-mode) (memq major-mode id-select-brace-modes)))
635 nil
636 (save-excursion
637 (goto-char pos)
638 (let ((at-def-brace
639 (or (looking-at "^{") (looking-at "^}")
640 ;; Handle stupid old C-style and new Java
641 ;; style of putting braces at the end of
642 ;; lines.
643 (and (= (following-char) ?{)
644 (stringp defun-prompt-regexp)
645 (save-excursion
646 (beginning-of-line)
647 (looking-at defun-prompt-regexp)))
648 (and (= (following-char) ?})
649 (stringp defun-prompt-regexp)
650 (condition-case ()
651 (progn
652 ;; Leave point at opening brace.
653 (goto-char
654 (scan-sexps (1+ (point)) -1))
655 ;; Test if these are defun braces.
656 (save-excursion
657 (beginning-of-line)
658 (looking-at defun-prompt-regexp)))
659 (error nil)))))
660 eod)
661 (if (or at-def-brace
662 ;; At the start of a definition:
663 ;; Must be at the first non-whitespace character in the line.
664 (and (= (point) (save-excursion (back-to-indentation) (point)))
665 ;; Must be on an alpha or symbol-constituent character.
666 ;; Also allow ~ for C++ destructors.
667 (looking-at "[a-zA-z~]\\|\\s_")
668 ;; Previous line, if any, must be blank or a comment
669 ;; start or end or `defun-prompt-regexp' must be defined
670 ;; for this mode.
671 (or (stringp defun-prompt-regexp)
672 (save-excursion
673 (if (/= (forward-line -1) 0)
674 t
675 (id-select-at-blank-line-or-comment))))))
676 (progn
677 (setq id-select-previous 'brace-def-or-declaration)
678 ;; Handle declarations and definitions embedded within classes.
679 (if (and (= (following-char) ?{)
680 (/= (point) (save-excursion (back-to-indentation) (point))))
681 (setq at-def-brace nil))
682 ;;
683 (if at-def-brace nil (beginning-of-line))
684 (if (and (not at-def-brace)
685 (stringp defun-prompt-regexp)
686 (looking-at defun-prompt-regexp))
687 ;; Mark the declaration or definition
688 (id-select-set-region
689 (point)
690 (progn (goto-char (match-end 0))
691 (if (= (following-char) ?{)
692 (forward-list 1)
693 (search-forward ";" nil t))
694 (skip-chars-forward " \t")
695 (skip-chars-forward "\n")
696 (if (looking-at "^\\s-*$")
697 (forward-line 1))
698 (point)))
699 ;; Mark function definitions only
700 (setq eod (save-excursion
701 (condition-case ()
702 (progn
703 (end-of-defun)
704 (if (looking-at "^\\s-*$")
705 (forward-line 1))
706 (point))
707 (error (point-max)))))
708 (if (= (following-char) ?})
709 ;; Leave point at opening brace.
710 (goto-char (scan-sexps (1+ (point)) -1)))
711 (if (= (following-char) ?{)
712 (progn
713 (while (and (zerop (forward-line -1))
714 (not (id-select-at-blank-line-or-comment))))
715 (if (id-select-at-blank-line-or-comment)
716 (forward-line 1))))
717 ;; Mark the whole definition
718 (setq id-select-previous 'brace-def-or-declaration)
719 (id-select-set-region (point) eod))))))))
720
721 (defun id-select-indent-def (pos)
722 "If POS is at the first alpha character on a line, return (start . end) region,
723
724 The major mode for each supported indented language must be included in the
725 list, id-select-indent-modes."
726 (interactive)
727 (if (not (memq major-mode id-select-indent-modes))
728 nil
729 (save-excursion
730 (goto-char pos)
731 (if (and
732 ;; Use this function only if point is on the first non-blank
733 ;; character of a block, whatever a block is for the current
734 ;; mode.
735 (cond ((eq major-mode 'kotl-mode)
736 (and (looking-at "[1-9*]") (not (kview:valid-position-p))))
737 ((or (eq major-mode 'outline-mode) selective-display)
738 (save-excursion (beginning-of-line)
739 (looking-at outline-regexp)))
740 ;; After indent in any other mode, must be on an alpha
741 ;; or symbol-constituent character.
742 (t (looking-at "[a-zA-z]\\|\\s_")))
743 ;; Must be at the first non-whitespace character in the line.
744 (= (point) (save-excursion (back-to-indentation) (point))))
745 (let* ((start-col (current-column))
746 (opoint (if (eq major-mode 'kotl-mode)
747 (progn (kotl-mode:to-valid-position) (point))
748 (beginning-of-line) (point))))
749 (while
750 (and (zerop (forward-line 1))
751 (bolp)
752 (or (progn (back-to-indentation)
753 (> (current-column) start-col))
754 ;; If in a text mode, allow outdenting, otherwise
755 ;; only include special lines here indented to the
756 ;; same point as the original line.
757 (and (or (memq major-mode id-select-text-modes)
758 (= (current-column) start-col))
759 (looking-at
760 (or (car (cdr
761 (assq
762 major-mode
763 id-select-indent-non-end-regexp-alist)))
764 "\\'"))))))
765 (if (and (looking-at
766 (or (car (cdr (assq major-mode
767 id-select-indent-end-regexp-alist)))
768 "\\'"))
769 (or (memq major-mode id-select-text-modes)
770 (= (current-column) start-col)))
771 (forward-line 1))
772 (beginning-of-line)
773 ;; Mark the whole definition
774 (setq id-select-previous 'indent-def)
775 (id-select-set-region opoint (point)))))))
776
777 (defun id-select-symbol (pos)
778 "Return (start . end) of a symbol at POS."
779 (or (id-select-markup-pair pos)
780 ;; Test for indented def here since might be on an '*' representing
781 ;; an outline entry, in which case we mark entries as indented blocks.
782 (id-select-indent-def pos)
783 (save-excursion
784 (if (memq (char-syntax (if (eobp) (preceding-char) (char-after pos)))
785 '(?w ?_))
786 (progn (setq id-select-previous 'symbol)
787 (condition-case ()
788 (let ((end (scan-sexps pos 1)))
789 (id-select-set-region
790 (min pos (scan-sexps end -1)) end))
791 (error nil)))))))
792
793 (defun id-select-sexp-start (pos)
794 "Return (start . end) of sexp starting at POS."
795 (or (id-select-markup-pair pos)
796 (id-select-brace-def-or-declaration pos)
797 (save-excursion
798 (setq id-select-previous 'sexp-start)
799 (condition-case ()
800 (id-select-set-region pos (scan-sexps pos 1))
801 (error nil)))))
802
803 (defun id-select-sexp-end (pos)
804 "Return (start . end) of sexp ending at POS."
805 (or (id-select-brace-def-or-declaration pos)
806 (save-excursion
807 (setq id-select-previous 'sexp-end)
808 (condition-case ()
809 (id-select-set-region (scan-sexps (1+ pos) -1) (1+ pos))
810 (error nil)))))
811
812 (defun id-select-sexp (pos)
813 "Return (start . end) of the sexp that POS is within."
814 (setq id-select-previous 'sexp)
815 (save-excursion
816 (goto-char pos)
817 (condition-case ()
818 (id-select-set-region (progn (backward-up-list 1) (point))
819 (progn (forward-list 1) (point)))
820 (error nil))))
821
822 (defun id-select-sexp-up (pos)
823 "Return (start . end) of the sexp enclosing the selected area or nil."
824 (setq id-select-previous 'sexp-up)
825 ;; Keep going up and backward in sexps. This means that id-select-sexp-up
826 ;; can only be called after id-select-sexp or after itself.
827 (setq pos (or (car id-select-region) pos))
828 (save-excursion
829 (goto-char pos)
830 (condition-case ()
831 (id-select-set-region (progn (backward-up-list 1) (point))
832 (progn (forward-list 1) (point)))
833 (error nil))))
834
835 (defun id-select-preprocessor-def (pos)
836 "Return (start . end) of a preprocessor #definition starting at POS, if any.
837 The major mode for each language that uses # preprocessor notation must be
838 included in the list, id-select-brace-modes."
839 ;; Only applies in brace modes (strictly, this should apply in a subset
840 ;; of brace modes, but doing it this way permits for configurability. In
841 ;; other modes, one doesn't have to use the function on a # symbol.
842 (if (not (memq major-mode id-select-brace-modes))
843 nil
844 (setq id-select-previous 'preprocessor-def)
845 (save-excursion
846 (goto-char pos)
847 (if (and (= (following-char) ?#)
848 ;; Must be at the first non-whitespace character in the line.
849 (= (point) (save-excursion (back-to-indentation) (point))))
850 (progn
851 ;; Skip past continuation lines that end with a backslash.
852 (while (and (looking-at ".*\\\\\\s-*$")
853 (zerop (forward-line 1))))
854 (forward-line 1)
855 ;; Include one trailing blank line, if any.
856 (if (looking-at "^[ \t\n\r]*$") (forward-line 1))
857 (id-select-set-region pos (point)))))))
858
859 ;; Allow punctuation marks not followed by white-space to include
860 ;; the previous and subsequent sexpression. Useful in contexts such as
861 ;; 'foo.bar'.
862 (defun id-select-punctuation (pos)
863 "Return (start . end) region including sexpressions before and after POS, when at a punctuation character."
864 (or (id-select-comment pos)
865 (id-select-preprocessor-def pos)
866 (id-select-brace-def-or-declaration pos) ;; Might be on a C++ ;; destructor ~.
867 (save-excursion
868 (setq id-select-previous 'punctuation)
869 (goto-char (min (1+ pos) (point-max)))
870 (if (= (char-syntax (if (eobp) (preceding-char) (char-after (point))))
871 ?\ )
872 (id-select-set-region pos (1+ pos))
873 (goto-char pos)
874 (id-select-set-region
875 (save-excursion (backward-sexp) (point))
876 (progn (forward-sexp) (point)))))))
877
878 (defun id-select-comment (pos)
879 "Return rest of line from POS to newline."
880 (setq id-select-previous 'comment)
881 (save-excursion
882 (goto-char pos)
883 (let ((start-regexp (if (stringp comment-start)
884 (regexp-quote comment-start)))
885 (end-regexp (if (stringp comment-end)
886 (regexp-quote comment-end)))
887 bolp)
888 (cond
889 ;; Beginning of a comment
890 ((and (stringp comment-start)
891 (or (looking-at start-regexp)
892 (and (skip-chars-backward comment-start)
893 (looking-at start-regexp))))
894 (skip-chars-backward " \t")
895 (setq bolp (bolp)
896 pos (point))
897 (if (equal comment-end "")
898 (progn (end-of-line)
899 (id-select-set-region pos (point)))
900 (if (stringp comment-end)
901 ;; Skip over nested comments.
902 (let ((count 0)
903 (regexp (concat start-regexp "\\|" end-regexp)))
904 (catch 'done
905 (while (re-search-forward regexp nil t)
906 (if (string-equal
907 (buffer-substring (match-beginning 0) (match-end 0))
908 comment-start)
909 (setq count (1+ count))
910 ;; End comment
911 (setq count (1- count))
912 (if (= count 0)
913 (progn
914 (if (looking-at "[ \t]*[\n\r]")
915 ;; Don't include final newline unless the
916 ;; comment is first thing on its line.
917 (goto-char (if bolp (match-end 0)
918 (1- (match-end 0)))))
919 (throw 'done (id-select-set-region
920 pos (point))))))))))))
921 ;; End of a comment
922 ((and (stringp comment-end)
923 (not (string-equal comment-end ""))
924 (or (looking-at end-regexp)
925 (and (skip-chars-backward comment-end)
926 (looking-at end-regexp))))
927 (goto-char (match-end 0))
928 (if (looking-at "[ \t]*[\n\r]")
929 (goto-char (match-end 0)))
930 (setq pos (point))
931 (skip-chars-forward " \t")
932 ;; Skip over nested comments.
933 (let ((count 0)
934 (regexp (concat start-regexp "\\|" end-regexp)))
935 (catch 'done
936 (while (re-search-backward regexp nil t)
937 (if (string-equal
938 (buffer-substring (match-beginning 0) (match-end 0))
939 comment-end)
940 (setq count (1+ count))
941 ;; Begin comment
942 (setq count (1- count))
943 (if (= count 0)
944 (progn
945 (skip-chars-backward " \t")
946 ;; Don't include final newline unless the comment is
947 ;; first thing on its line.
948 (if (bolp) nil (setq pos (1- pos)))
949 (throw 'done (id-select-set-region
950 (point) pos)))))))))))))
951
952 ;;;
953 ;;; Textual selections
954 ;;;
955
956 (defun id-select-word (pos)
957 "Return (start . end) of word at POS."
958 (or (id-select-brace-def-or-declaration pos)
959 (id-select-indent-def pos)
960 (progn (setq id-select-previous 'word)
961 (save-excursion
962 (goto-char pos)
963 (forward-word 1)
964 (let ((end (point)))
965 (forward-word -1)
966 (id-select-set-region (point) end))))))
967
968 (defun id-select-string (pos)
969 "Returns (start . end) of string at POS or nil. Pos include delimiters.
970 Delimiters may be single, double or open and close quotes."
971 (setq id-select-previous 'string)
972 (save-excursion
973 (goto-char pos)
974 (if (and (memq major-mode id-select-markup-modes)
975 (/= (following-char) ?\")
976 (save-excursion
977 (and (re-search-backward "[<>]" nil t)
978 (= (following-char) ?>))))
979 (progn (setq id-select-previous 'text)
980 (search-backward ">" nil t)
981 (id-select-set-region
982 (1+ (point))
983 (progn (if (search-forward "<" nil 'end)
984 (1- (point))
985 (point)))))
986 (or (id-select-string-p) (id-select-string-p "'" "'")
987 (id-select-string-p "`" "'")))))
988
989 (defun id-select-sentence (pos)
990 "Return (start . end) of the sentence at POS."
991 (setq id-select-previous 'sentence)
992 (save-excursion
993 (goto-char pos)
994 (condition-case ()
995 (id-select-set-region (progn (backward-sentence) (point))
996 (progn (forward-sentence) (point)))
997 (error nil))))
998
999 (defun id-select-whitespace (pos)
1000 "Return (start . end) of all but one char of whitespace POS, unless
1001 there is only one character of whitespace or this is leading whitespace on
1002 the line. Then return all of it."
1003 (setq id-select-previous 'whitespace)
1004 (save-excursion
1005 (goto-char pos)
1006 (if (= (following-char) ?\^L)
1007 (id-select-page pos)
1008 (let ((end (progn (skip-chars-forward " \t") (point)))
1009 (start (progn (skip-chars-backward " \t") (point))))
1010 (if (looking-at "[ \t]")
1011 (if (or (bolp) (= (1+ start) end))
1012 (id-select-set-region start end)
1013 (id-select-set-region (1+ start) end)))))))
1014
1015 (defun id-select-markup-pair (pos)
1016 "Return (start . end) of region between the opening and closing of an HTML or SGML tag pair, one of which is at POS.
1017 The major mode for each language that uses such tags must be included in the
1018 list, id-select-markup-modes."
1019 (if (not (memq major-mode id-select-markup-modes))
1020 nil
1021 (setq id-select-previous 'markup-pair)
1022 (let ((pos-with-space)
1023 ;; Assume case of tag names is irrelevant.
1024 (case-fold-search t)
1025 (result)
1026 start-regexp
1027 end-regexp
1028 bolp
1029 opoint)
1030 (save-excursion
1031 (catch 'done
1032 (goto-char pos)
1033 (cond
1034 ;; Beginning of a tag pair
1035 ((looking-at "<[^/][^<> \t\n\r]*")
1036 (setq start-regexp (regexp-quote (buffer-substring
1037 (match-beginning 0) (match-end 0)))
1038 end-regexp (concat "</" (substring start-regexp 1)))
1039 (setq pos (point))
1040 (skip-chars-backward " \t")
1041 (setq bolp (bolp)
1042 pos-with-space (point))
1043 ;; Skip over nested tags.
1044 (let ((count 0)
1045 (regexp (concat start-regexp "\\|" end-regexp)))
1046 (while (and (>= count 0)
1047 (re-search-forward regexp nil t))
1048 (if (/= (char-after (1+ (match-beginning 0))) ?/)
1049 ;; Start tag
1050 (setq count (1+ count))
1051 ;; Move past end tag terminator
1052 (setq opoint (point))
1053 (if (or (not (re-search-forward "[<>]" nil t))
1054 (= (preceding-char) ?<))
1055 (progn (setq result opoint)
1056 (throw 'done nil)))
1057 (setq count (1- count))
1058 (if (= count 0)
1059 (progn
1060 (if (looking-at "[ \t]*[\n\r]")
1061 ;; Don't include final newline unless the
1062 ;; start tag was the first thing on its line.
1063 (if bolp
1064 (progn (goto-char (match-end 0))
1065 ;; Include leading space since the
1066 ;; start and end tags begin and end
1067 ;; lines.
1068 (setq pos pos-with-space))
1069 (goto-char (1- (match-end 0)))))
1070 (setq result (id-select-set-region pos (point)))
1071 (throw 'done nil)))))))
1072 ;;
1073 ;; End of a tag pair
1074 ((or (looking-at "</[^> \t\n\r]+")
1075 (and (skip-chars-backward "<")
1076 (looking-at "</[^> \t\n\r]+")))
1077 (goto-char (match-end 0))
1078 (setq end-regexp (regexp-quote (buffer-substring
1079 (match-beginning 0) (match-end 0)))
1080 start-regexp (concat "<" (substring end-regexp 2)))
1081 (setq opoint (point))
1082 (if (or (not (re-search-forward "[<>]" nil t))
1083 (= (preceding-char) ?<))
1084 (progn (setq result opoint)
1085 (throw 'done nil)))
1086 (setq pos (point))
1087 (if (looking-at "[ \t]*[\n\r]")
1088 (setq pos-with-space (match-end 0)))
1089 ;; Skip over nested tags.
1090 (let ((count 0)
1091 (regexp (concat start-regexp "\\|" end-regexp)))
1092 (while (and (>= count 0)
1093 (re-search-backward regexp nil t))
1094 (if (= (char-after (1+ (point))) ?/)
1095 ;; End tag
1096 (setq count (1+ count))
1097 ;; Start tag
1098 (setq count (1- count))
1099 (if (= count 0)
1100 (progn
1101 (if pos-with-space
1102 ;; Newline found after original end tag.
1103 (progn
1104 (skip-chars-backward " \t")
1105 (if (bolp)
1106 ;; Don't include final newline unless the
1107 ;; start tag is the first thing on its line.
1108 (setq pos pos-with-space)
1109 (setq pos (1- pos-with-space))
1110 ;; Don't include non-leading space.
1111 (skip-chars-forward " \t"))))
1112 (setq result (id-select-set-region (point) pos))
1113 (throw 'done nil))))))))))
1114 (if (integerp result)
1115 (progn (goto-char result)
1116 (error "(id-select-markup-pair): Add a terminator character for this end tag"))
1117 result))))
1118
1119 ;;;
1120 ;;; Document selections
1121 ;;;
1122
1123 (defun id-select-line (pos)
1124 "Return (start . end) of the whole line POS is in, with newline unless at end of buffer."
1125 (setq id-select-previous 'line)
1126 (save-excursion
1127 (goto-char pos)
1128 (let* ((start (progn (beginning-of-line 1) (point)))
1129 (end (progn (forward-line 1) (point))))
1130 (id-select-set-region start end))))
1131
1132 (defun id-select-paragraph (pos)
1133 "Return (start . end) of the paragraph at POS."
1134 (setq id-select-previous 'paragraph)
1135 (save-excursion
1136 (goto-char pos)
1137 (id-select-set-region (progn (backward-paragraph) (point))
1138 (progn (forward-paragraph) (point)))))
1139
1140 (defun id-select-page (pos)
1141 "Return (start . end) of the page preceding POS."
1142 (setq id-select-previous 'page)
1143 (save-excursion
1144 (goto-char pos)
1145 (id-select-set-region (progn (backward-page) (point))
1146 (progn (forward-page) (point)))))
1147
1148 (defun id-select-buffer (pos)
1149 "Return (start . end) of the buffer at POS."
1150 (setq id-select-previous 'buffer)
1151 (id-select-set-region (point-min) (point-max)))
1152
1153 ;;; ************************************************************************
1154 ;;; Private variables
1155 ;;; ************************************************************************
1156
1157 (defvar id-select-bigger-alist
1158 '((char nil)
1159 (whitespace id-select-whitespace)
1160 (word id-select-word)
1161 (symbol id-select-symbol)
1162 (punctuation nil)
1163 (string id-select-string)
1164 (text nil)
1165 (comment id-select-comment)
1166 (markup-pair nil)
1167 (preprocessor-def nil)
1168 (sexp id-select-sexp)
1169 (sexp-start nil)
1170 (sexp-end nil)
1171 (sexp-up id-select-sexp-up)
1172 (line id-select-line)
1173 (sentence id-select-sentence)
1174 (brace-def-or-declaration id-select-brace-def-or-declaration)
1175 (indent-def id-select-indent-def)
1176 (paragraph id-select-paragraph)
1177 (page id-select-page)
1178 (buffer id-select-buffer)
1179 )
1180 "List of (REGION-TYPE-SYMBOL REGION-SELECTION-FUNCTION) pairs.
1181 Used to go from one thing to a bigger thing. See id-select-bigger-thing.
1182 Nil value for REGION-SELECTION-FUNCTION means that region type is skipped
1183 over when trying to grow the region and is only used when a selection is made
1184 with point on a character that triggers that type of selection. Ordering of
1185 entries is largely irrelevant to any code that uses this list.")
1186
1187
1188 (defvar id-select-prior-buffer nil)
1189 (defvar id-select-prior-point nil)
1190
1191 (defvar id-select-previous 'char
1192 "Most recent type of selection. Must be set by all id-select functions.")
1193
1194 (defvar id-select-region (cons 'nil 'nil)
1195 "Cons cell that contains a region (<beginning> . <end>).
1196 The function `id-select-set-region' updates and returns it.")
1197
1198 (defvar id-select-old-region (cons 'nil 'nil)
1199 "Cons cell that contains a region (<beginning> . <end>).")
1200
1201 (defvar id-select-syntax-alist
1202 '((?w id-select-word)
1203 (?_ id-select-symbol)
1204 (?\" id-select-string)
1205 (?\( id-select-sexp-start)
1206 (?\$ id-select-sexp-start)
1207 (?' id-select-sexp-start)
1208 (?\) id-select-sexp-end)
1209 (? id-select-whitespace)
1210 (?< id-select-comment)
1211 (?. id-select-punctuation))
1212 "*List of pairs of the form (SYNTAX-CHAR FUNCTION) used by the function `id-select-syntactical-region'.
1213 Each FUNCTION takes a single position argument and returns a region
1214 (start . end) delineating the boundaries of the thing at that position.
1215 Ordering of entries is largely irrelevant to any code that uses this list.")
1216
1217
1218 (provide 'id-select)