forked from nflath/hungry-delete
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hungry-delete.el
218 lines (182 loc) · 7.95 KB
/
hungry-delete.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
;;; hungry-delete.el --- hungry delete minor mode
;; Copyright (C) 2009 - 2014 Nathaniel Flath <[email protected]>
;; Author: Nathaniel Flath <[email protected]>
;; URL: http://github.com/nflath/hungry-delete
;; Version: 1.1.6
;; This file is not part of GNU Emacs.
;;; Commentary:
;; cc-mode implements hungry deletion for its programming modes. This
;; package borrows its implementation in a minor mode, so that hungry
;; deletion can be used in all modes.
;;; Installation
;; To use this mode, put the following in your init.el:
;; (require 'hungry-delete)
;; You then need to enable hungry-delete-mode, either in
;; relevant hooks, with turn-on-hungry-delete-mode, or with
;; global-hungry-delete-mode.
;;; 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 3
;; of the License, 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 GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Code:
(defvar hungry-delete-mode-map (make-keymap)
"Keymap for hungry-delete-minor-mode.")
(if (fboundp 'delete-forward-char)
(define-key hungry-delete-mode-map [remap delete-forward-char] 'hungry-delete-forward))
(if (fboundp 'delete-char)
(define-key hungry-delete-mode-map [remap delete-char] 'hungry-delete-forward))
(define-key hungry-delete-mode-map [remap delete-backward-char] 'hungry-delete-backward)
(define-key hungry-delete-mode-map [remap backward-delete-char-untabify] 'hungry-delete-backward)
(define-key hungry-delete-mode-map [remap c-electric-backspace] 'hungry-delete-backward)
(define-key hungry-delete-mode-map [remap c-electric-delete-forward] 'hungry-delete-forward)
(defvar hungry-delete-chars-to-skip " \t\n\r\f\v"
"String of characters to skip.")
(defvar hungry-delete-except-modes '(help-mode minibuffer-inactive-mode calc-mode)
"List of modes hungry-delete will not be turned on in.")
(defun hungry-delete-skip-ws-forward ()
"Skip over any whitespace following point.
This function skips over horizontal and vertical whitespace and
line continuations."
(while (and
(> (skip-chars-forward hungry-delete-chars-to-skip) 0)
(eq (char-after) ?\\)
(progn
(forward-char)
(or (eolp) (backward-char)))))
(while (get-text-property (point) 'read-only)
(backward-char)))
(defun hungry-delete-skip-ws-backward ()
"Skip over any whitespace preceding point.
This function skips over horizontal and vertical whitespace and
line continuations."
(skip-chars-backward hungry-delete-chars-to-skip)
(while (and
(eolp)
(eq (char-before) ?\\)
(progn
(backward-char)
(or
(= (point) (point-min))
(< (skip-chars-backward hungry-delete-chars-to-skip) 0)
(forward-char)))))
(while (get-text-property (point) 'read-only)
(forward-char)))
;;;###autoload
(defun hungry-delete-forward (n &optional killflag)
"Delete the following character, or all of the following
whitespace, up to the next non-whitespace character. See
\\[c-hungry-delete-forward].
hungry-delete-backward tries to mimic delete-backward-char's
behavior in several ways: if the region is activate, it deletes
the text in the region. If a prefix argument is given, delete
the following N characters (previous if N is negative).
Optional second arg KILLFLAG non-nil means to kill (save in kill
ring) instead of delete. Interactively, N is the prefix arg, and
KILLFLAG is set if N was explicitly specified."
(interactive "p\nP")
(unless (integerp n)
(signal 'wrong-type-argument (list 'integerp n)))
(if (bound-and-true-p rectangle-mark-mode)
(delete-forward-char n killflag)
(cond ((and
(use-region-p)
delete-active-region
(= n 1))
;; If a region is active, kill or delete it.
(if (eq delete-active-region 'kill)
(kill-region (region-beginning) (region-end))
(delete-region (region-beginning) (region-end))))
;; If a prefix argument has been given, delete n characters.
(current-prefix-arg (delete-char n killflag))
;; Otherwise, call hungry-delete-forward-impl.
(t (hungry-delete-forward-impl)))))
;;;###autoload
(defun hungry-delete-backward (n &optional killflag)
"Delete the preceding character or all preceding whitespace
back to the previous non-whitespace character. See also
\\[c-hungry-delete-backward].
hungry-delete-backward tries to mimic delete-backward-char's
behavior in several ways: if the region is activate, it deletes
the text in the region. If a prefix argument is given, delete
the previous N characters (following if N is negative).
In Overwrite mode, single character backward deletion may replace
tabs with spaces so as to back over columns, unless point is at
the end of the line.
Optional second arg KILLFLAG, if non-nil, means to kill (save in
kill ring) instead of delete. Interactively, N is the prefix
arg, and KILLFLAG is set if N is explicitly specified."
(interactive "p\nP")
(unless (integerp n)
(signal 'wrong-type-argument (list 'integerp n)))
(if (bound-and-true-p rectangle-mark-mode)
(delete-backward-char n killflag)
(cond ((and
(use-region-p)
delete-active-region
(= n 1))
;; If a region is active, kill or delete it.
(if (eq delete-active-region 'kill)
(kill-region (region-beginning) (region-end))
(delete-region (region-beginning) (region-end))))
;; In Overwrite mode, maybe untabify while deleting
((null (or (null overwrite-mode)
(<= n 0)
(memq (char-before) '(?\t ?\n))
(eobp)
(eq (char-after) ?\n)))
(let ((ocol (current-column)))
(delete-char (- n) killflag)
(save-excursion
(insert-char ?\s (- ocol (current-column)) nil))))
;; If a prefix has been given, delete n characters backwards.
(current-prefix-arg (delete-char (- n) killflag))
;; Otherwise, call hungry-delete-backward-impl.
(t (hungry-delete-backward-impl)))))
(defun hungry-delete-impl (fn n)
"Implementation of hungry-delete functionality.
FN is the function to call to go to the end of whitespace (will
be either hungry-delete-skip-ws-forward or
hungry-delete-skip-ws-backwards by default). N is the number of
characters to delete if there is no whitespace (will be either 1
or -1 by default)."
(let ((here (point)))
(funcall fn)
(if (/= (point) here)
(delete-region (point) here)
(let ((hungry-delete-mode nil))
(delete-char n)))))
(defun hungry-delete-forward-impl ()
"Do the dirty work of calling hungry-delete-forward."
(hungry-delete-impl 'hungry-delete-skip-ws-forward 1))
(defun hungry-delete-backward-impl ()
"Do the dirty work of calling hungry-delete-backward."
(hungry-delete-impl 'hungry-delete-skip-ws-backward -1))
;;;###autoload
(define-minor-mode hungry-delete-mode
"Minor mode to enable hungry deletion. This will delete all
whitespace after or before point when the deletion command is
executed."
:init-value nil
:group 'hungry-delete
:lighter " h")
;;;###autoload
(defun turn-on-hungry-delete-mode ()
"Turn on hungry delete mode if the buffer is appropriate."
(interactive)
(unless (member major-mode hungry-delete-except-modes)
(hungry-delete-mode t)))
;;;###autoload
(define-globalized-minor-mode global-hungry-delete-mode hungry-delete-mode turn-on-hungry-delete-mode)
(provide 'hungry-delete)
;;; hungry-delete.el ends here