This repository has been archived by the owner on Dec 27, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
iy-go-to-char.el
470 lines (401 loc) · 17.1 KB
/
iy-go-to-char.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
;;; iy-go-to-char.el --- Go to next CHAR which is similar to "f" and "t" in vim
;; Copyright (C) 2009 Ian Yang
;; Author: Ian Yang <doit dot ian (at) gmail dot com>
;; Keywords: navigation, search
;; Filename: iy-go-to-char.el
;; Description: Go to char
;; Created: 2009-08-23 01:27:34
;; Version: 3.2.2
;; Last-Updated: 2014-10-29 22:39:29
;; URL: https://github.com/doitian/iy-go-to-char
;; Compatibility: GNU Emacs 23.1.1
;;; License:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; This package defines the function `iy-go-to-char' which behaves like "f" in
;; vim, and `iy-go-up-to-char` like "t" in vim. It reads a char and go the
;; next Nth occurence of the char. User can continue such search using that
;; char key.
;; To use, make sure this file is on your `load-path' and put the
;; following in your .emacs file:
;;
;; (require 'iy-go-to-char)
;;
;; To make `iy-go-to-char' works better with `multiple-cursors', add
;; `iy-go-to-char-start-pos' to `mc/cursor-specific-vars' when mc is loaded:
;;
;; (add-to-list 'mc/cursor-specific-vars 'iy-go-to-char-start-pos)
;;
;; Then you can bind functions like:
;;
;; (global-set-key (kbd "C-c f") 'iy-go-to-char)
;; (global-set-key (kbd "C-c F") 'iy-go-to-char-backward)
;; (global-set-key (kbd "C-c ;") 'iy-go-to-or-up-to-continue)
;; (global-set-key (kbd "C-c ,") 'iy-go-to-or-up-to-continue-backward)
;;
;; Or if you prefer up-to (vim "t") versions:
;;
;; (global-set-key (kbd "C-c f") 'iy-go-up-to-char)
;; (global-set-key (kbd "C-c F") 'iy-go-up-to-char-backward)
;;
;; You also can bind go-to methods and up-to methods to different keys.
;;
;; Except repeating the char key, followings keys are defined before
;; quitting the search (which can be disabled by setting
;; `iy-go-to-char-override-local-map' to nil):
;;
;; X -- where X is the char to be searched. Repeating it will search
;; forward the char. Can be disabled through
;; `iy-go-to-char-continue-when-repeating'
;;
;; ; -- search forward the char, customizable:
;; `iy-go-to-char-key-forward', `iy-go-to-char-use-key-forward'
;;
;; , -- search backward the char, customizable:
;; `iy-go-to-char-key-backward', `iy-go-to-char-use-key-backward'
;;
;; C-g -- quit
;;
;; C-s -- start `isearch-forward' using char as initial search
;; string
;;
;; C-r -- start `isearch-backward' using char as initial search
;; string
;;
;; C-w -- quit and kill region between start and current point. If region is
;; activated before search, then use the original mark instead of the
;; start position.
;;
;; M-w -- quit and save region between start and current point. If region is
;; activated before search, use the mark instead of start position.
;;
;; All other keys will quit the search. Then the key event is
;; intepreted in the original environment before search.
;;
;; if the search quits because of error or using "C-g", point is set
;; back to the start position. Otherwise, point is not change and the
;; start position is set as marker. So you can use "C-x C-x" back to
;; that position.
;; `iy-go-to-char-backward' search backward by default. Also the search can
;; cross lines. To continue search last char, use `iy-go-to-char-continue' and
;; `iy-go-to-char-continue-backward'.
;;; Change Log:
;; 2014-10-29 (3.2.2)
;;
;; - Add options `iy-go-to-char-use-key-forward',
;; `iy-go-to-char-use-key-backward' and
;; `iy-go-to-char-continue-when-repeating' to toggle the feature that
;; continuing search by repeat typing a single key.
;; - Add option `iy-go-to-char-override-local-map' to disable the temporary
;; map after activate `iy-go-to-char'.
;;
;; 2013-04-28 (3.2.1)
;;
;; - Fix documentations.
;; - Add up-to versions: `iy-go-up-to-char', `iy-go-up-to-char-backward',
;; `iy-go-up-to-char-continue' and `iy-go-up-to-char-continue-backward'.
;;
;; 2013-04-28 (3.1)
;;
;; - Better integration with `multiple-cursors'.
;; - Refactoring documentations.
;;
;; 2013-04-08 (3.0)
;;
;; - When jump is started backward (with negative parameter, or
;; `iy-go-to-char-backward'). Repeating continues the search
;; backward. Also `iy-go-to-char-key-forward' jumps with the same
;; direction when jump is started, and `iy-go-to-char-key-backward' jumps
;; to reverse direction.
;;
;; 2013-03-25 (2.1)
;; - Fix a but that I forget to set `mc--this-command'
;;
;; 2013-03-25 (2.0)
;; - Use overriding-local-map to setup keymap
;; - multiple-cursors compatible
;;
;; 2012-04-16 (1.1)
;; - fix C-s/C-r to enter isearch
;;; Code:
(defgroup iy-go-to-char nil
"go to char like f in vim."
:link '(emacs-commentary-link "iy-go-to-char")
:prefix "iy-go-to-char-"
:group 'matching)
(defcustom iy-go-to-char-key-forward ?\;
"Default key used to go to next occurrence of the char."
:type 'character
:group 'iy-go-to-char)
(defcustom iy-go-to-char-use-key-forward t
"Whether bind `iy-go-to-char-key-forward' to go to next occurrence of the char."
:type 'boolean
:group 'iy-go-to-char)
(defcustom iy-go-to-char-key-backward ?\,
"Default key used to go to previous occurrence of the char."
:type 'character
:group 'iy-go-to-char)
(defcustom iy-go-to-char-use-key-backward t
"Whether bind `iy-go-to-char-key-backward' to go to next occurrence of the char."
:type 'boolean
:group 'iy-go-to-char)
(defcustom iy-go-to-char-continue-when-repeating t
"Whether continue the search by repeating the search char."
:type 'boolean
:group 'iy-go-to-char)
(defcustom iy-go-to-char-override-local-map t
"Whether use the temporary key bindings following `iy-go-to-char'."
:type 'boolean
:group 'iy-go-to-char)
(defvar iy-go-to-char-start-pos nil
"Position where go to char mode is enabled.")
(defvar iy-go-to-char-start-dir 1
"Jump start direction.")
(defvar iy-go-to-char-last-char nil
"Last char used in iy-go-to-char.")
(defvar iy-go-to-char-last-step 1
"Last jump step used in iy-go-to-char.")
(defvar iy-go-to-char-stop-position 'include
"Control where to place the point after found a match.
Set to `include' so the next matched char is included in the
region between start search position and current point.
Set to `exclude' so the next matched char is excluded in the region.")
(defvar iy-go-to-char-keymap (let ((map (make-sparse-keymap)))
(define-key map (kbd "C-s") 'iy-go-to-char-isearch)
(define-key map (kbd "C-r") 'iy-go-to-char-isearch-backward)
(define-key map (kbd "C-w") 'iy-go-to-char-kill-region)
(define-key map (kbd "M-w") 'iy-go-to-char-kill-ring-save)
(define-key map (kbd "C-g") 'iy-go-to-char-quit)
map)
"Keymap used when iy-go-to-char is ongoing.")
(defun iy-go-to-char--set-mc-command (command)
"Set COMMAND as multiple cursors this command."
(when (and (boundp 'multiple-cursors-mode) multiple-cursors-mode (boundp 'mc--this-command))
(setq mc--this-command command)))
(defun iy-go-to-char--set-mc-specific-vars ()
"Add `iy-go-to-char-start-pos' to `mc/cursor-specific-vars'."
(when (boundp 'mc/cursor-specific-vars)
(add-to-list 'mc/cursor-specific-vars 'iy-go-to-char-start-pos))
(remove-hook 'multiple-cursors-mode-hook 'iy-go-to-char--set-mc-specific-vars))
(add-hook 'multiple-cursors-mode-hook 'iy-go-to-char--set-mc-specific-vars)
(defun iy-go-to-char--isearch-setup ()
"Setup jump char as initial string for isearch."
(remove-hook 'isearch-mode-hook 'iy-go-to-char--isearch-setup)
(setq isearch-string (if iy-go-to-char-last-char (string iy-go-to-char-last-char) ""))
(isearch-search-and-update))
(defun iy-go-to-char--override-local-map (char)
"Override the local key map for jump char CHAR."
(when iy-go-to-char-override-local-map
(setq overriding-local-map
(let ((map (copy-keymap iy-go-to-char-keymap)))
(when iy-go-to-char-continue-when-repeating
(define-key map (string char) 'iy-go-to-or-up-to-continue))
(when iy-go-to-char-use-key-forward
(define-key map (string iy-go-to-char-key-forward) 'iy-go-to-or-up-to-continue))
(when iy-go-to-char-use-key-backward
(define-key map (string iy-go-to-char-key-backward) 'iy-go-to-or-up-to-continue-backward))
(define-key map [t] 'iy-go-to-char-pass-through)
map))))
(defun iy-go-to-char-done ()
"Finish iy-go-to-char-mode."
(interactive)
(push-mark iy-go-to-char-start-pos t)
(setq iy-go-to-char-start-pos nil)
(setq overriding-local-map nil))
(defun iy-go-to-char-quit ()
"Quit iy-go-to-char-mode."
(interactive)
(goto-char iy-go-to-char-start-pos)
(setq iy-go-to-char-start-pos nil)
(setq overriding-local-map nil))
(defun iy-go-to-char-pass-through ()
"Finish iy-go-to-char-mode and invoke the corresponding command."
(interactive)
(iy-go-to-char-done)
(let* ((keys (progn
(setq unread-command-events
(append (this-single-command-raw-keys)
unread-command-events))
(read-key-sequence-vector "")))
(command (and keys (key-binding keys))))
(when (commandp command)
(setq this-command command
this-original-command command)
(iy-go-to-char--set-mc-command `(lambda ()
(interactive)
(push-mark iy-go-to-char-start-pos t)
(setq iy-go-to-char-start-pos nil)
(call-interactively ',command)))
(call-interactively command))))
(defun iy-go-to-char-isearch ()
"Start isearch using the char."
(interactive)
(iy-go-to-char-done)
(add-hook 'isearch-mode-hook 'iy-go-to-char--isearch-setup)
(isearch-forward))
(defun iy-go-to-char-isearch-backward ()
"Start isearch backward using the char."
(interactive)
(iy-go-to-char-done)
(add-hook 'isearch-mode-hook 'iy-go-to-char--isearch-setup)
(isearch-backward))
(defun iy-go-to-char-kill-region ()
"Kill region between jump start position and current position."
(interactive)
(iy-go-to-char-done)
(iy-go-to-char--set-mc-command (lambda ()
(interactive)
(kill-region (point) iy-go-to-char-start-pos)
(setq iy-go-to-char-start-pos nil)))
(kill-region (point) (mark)))
(defun iy-go-to-char-kill-ring-save ()
"Save region between jump start position and current position."
(interactive)
(iy-go-to-char-done)
(iy-go-to-char--set-mc-command (lambda ()
(interactive)
(kill-ring-save (point) iy-go-to-char-start-pos)
(setq iy-go-to-char-start-pos nil)))
(kill-ring-save (point) (mark)))
(defun iy-go-to-char--command ()
"Repeatable command to really move cursor."
(interactive)
(setq iy-go-to-char-start-pos (or iy-go-to-char-start-pos (point)))
(let* ((pos (point))
(n (if (< iy-go-to-char-start-dir 0)
(- iy-go-to-char-last-step)
iy-go-to-char-last-step))
(dir (if (< n 0) -1 1)))
(condition-case err
(progn
(unless (or (eq iy-go-to-char-stop-position 'include)
(if (< dir 0) (bobp) (eobp)))
(forward-char dir))
(search-forward (string iy-go-to-char-last-char) nil nil n)
(unless (eq iy-go-to-char-stop-position 'include)
(forward-char (- dir))))
(error (goto-char pos)
(signal (car err) (cdr err))))))
(defun iy-go-to-char--internal (n char stop-position)
"Store jump step N and jump CHAR for `iy-go-to-char--command'.
If STOP-POSITION is not `include', jump up to char but excluding the char."
(interactive "p\ncGo to char: ")
(setq iy-go-to-char-last-step n)
(setq iy-go-to-char-last-char char)
(setq iy-go-to-char-stop-position stop-position)
(unless iy-go-to-char-start-pos
(setq iy-go-to-char-start-pos (point))
(iy-go-to-char--override-local-map char))
(setq this-original-command 'iy-go-to-char--command
this-command 'iy-go-to-char--command)
(iy-go-to-char--set-mc-command 'iy-go-to-char--command)
(call-interactively 'iy-go-to-char--command))
;;;###autoload
(defun iy-go-to-char (n char)
"Move forward to N occurrences of CHAR.
\\<iy-go-to-char-keymap>
Typing key of CHAR will move to the next occurence of CHAR.
Typing `iy-go-to-char-key-forward' will move to the next
occurence of CHAR.
Typing `iy-go-to-char-key-backward', will move to the previous
occurence of CHAR.
Typing \\[iy-go-to-char-quit] will quit and return to the
original point.
Typing \\[iy-go-to-char-isearch] or
\\[iy-go-to-char-isearch-backward]] will start `isearch` using
CHAR.
Typing \\[iy-go-to-char-kill-region] or
\\[iy-go-to-char-kill-ring-save] will kill/copy between current
point and the start point.
Unless quit using \\[iy-go-to-char-quit] or the region is
activated before searching, the start point is set as mark."
(interactive "p\ncGo to char: ")
(setq iy-go-to-char-start-dir (if (< n 0) -1 1))
(iy-go-to-char--internal n char 'include))
;;;###autoload
(defun iy-go-to-char-backward (n char)
"Move backward to N occurence of CHAR.
\\<iy-go-to-char-keymap>
Typing key of CHAR will move to the previous occurence of CHAR.
Typing `iy-go-to-char-key-forward' moves to the next occurrence
of CHAR.
Typing `iy-go-to-char-key-backward', moves to the previous
occurrence of CHAR.
Typing \\[iy-go-to-char-quit] will quit and return to the
original point.
Typing \\[iy-go-to-char-isearch] or
\\[iy-go-to-char-isearch-backward]] will start `isearch` using
CHAR."
(interactive "p\ncGo back to char: ")
(setq iy-go-to-char-start-dir (if (< n 0) 1 -1))
(iy-go-to-char--internal n char 'include))
;;;###autoload
(defun iy-go-up-to-char (n char)
"Move forward to N occurrences of CHAR.
Like `iy-go-to-char' but jump up to the CHAR so it is
not included in the region between search start position and
current point."
(interactive "p\ncGo up to char: ")
(setq iy-go-to-char-start-dir (if (< n 0) -1 1))
(iy-go-to-char--internal n char 'exclude))
;;;###autoload
(defun iy-go-up-to-char-backward (n char)
"Move backward to N occurrences of CHAR.
Like `iy-go-to-char-backward' but jump up to the CHAR so it is
not included in the region between search start position and
current point."
(interactive "p\ncGo back up to char: ")
(setq iy-go-to-char-start-dir (if (< n 0) 1 -1))
(iy-go-to-char--internal n char 'exclude))
;;;###autoload
(defun iy-go-to-or-up-to-continue (n &optional stop-position)
"Continue last `iy-go-to-char' or `iy-go-to-char-backward' by N steps.
Set `STOP-POSITION' to overwrite the last used stop position strategy."
(interactive "p")
(when iy-go-to-char-last-char
(iy-go-to-char--internal n iy-go-to-char-last-char (or stop-position
iy-go-to-char-stop-position
'include))))
;;;###autoload
(defun iy-go-to-or-up-to-continue-backward (n &optional stop-position)
"Continue last `iy-go-to-char' or `iy-go-to-char-backward' by N steps.
Set `STOP-POSITION' to overwrite the last used stop position strategy."
(interactive "p")
(when iy-go-to-char-last-char
(iy-go-to-char--internal (- n) iy-go-to-char-last-char (or stop-position
iy-go-to-char-stop-position
'include))))
;;;###autoload
(defun iy-go-to-char-continue (n)
"Continue last `iy-go-to-char' or `iy-go-to-char-backward' by N steps."
(interactive "p")
(iy-go-to-or-up-to-continue n 'include))
;;;###autoload
(defun iy-go-to-char-continue-backward (n)
"Continue last `iy-go-to-char' or `iy-go-to-char-backward' by N steps."
(interactive "p")
(iy-go-to-or-up-to-continue-backward n 'include))
;;;###autoload
(defun iy-go-up-to-char-continue (n)
"Continue last `iy-go-up-to-char' or `iy-go-up-to-char-backward' by N steps."
(interactive "p")
(iy-go-to-or-up-to-continue n 'exclude))
;;;###autoload
(defun iy-go-up-to-char-continue-backward (n)
"Continue last `iy-go-up-to-char' or `iy-go-up-to-char-backward' by N steps."
(interactive "p")
(iy-go-to-or-up-to-continue-backward n 'exclude))
(provide 'iy-go-to-char)
;;; iy-go-to-char.el ends here
;; LocalWords: customizable