|
|
1.1 root 1: ;; Rectangle functions for GNU Emacs.
2: ;; Copyright (C) 1985 Richard M. Stallman.
3:
4: ;; This file is part of GNU Emacs.
5:
6: ;; GNU Emacs is distributed in the hope that it will be useful,
7: ;; but WITHOUT ANY WARRANTY. No author or distributor
8: ;; accepts responsibility to anyone for the consequences of using it
9: ;; or for whether it serves any particular purpose or works at all,
10: ;; unless he says so in writing. Refer to the GNU Emacs General Public
11: ;; License for full details.
12:
13: ;; Everyone is granted permission to copy, modify and redistribute
14: ;; GNU Emacs, but only under the conditions described in the
15: ;; GNU Emacs General Public License. A copy of this license is
16: ;; supposed to have been given to you along with GNU Emacs so you
17: ;; can know your rights and responsibilities. It should be in a
18: ;; file named COPYING. Among other things, the copyright notice
19: ;; and this notice must be preserved on all copies.
20:
21:
22: (defun operate-on-rectangle (function start end coerce-tabs)
23: "Call FUNCTION for each line of rectangle with corners at START, END.
24: If COERCE-TABS is non-nil, convert multi-column characters
25: that span the starting or ending columns on any line
26: to multiple spaces before calling FUNCTION.
27: FUNCTION is called with three arguments:
28: position of start of segment of this line within the rectangle,
29: number of columns that belong to rectangle but are before that position,
30: number of columns that belong to rectangle but are after point.
31: Point is at the end of the segment of this line within the rectangle."
32: (let (startcol startlinepos endcol endlinepos)
33: (save-excursion
34: (goto-char start)
35: (setq startcol (current-column))
36: (beginning-of-line)
37: (setq startlinepos (point)))
38: (save-excursion
39: (goto-char end)
40: (setq endcol (current-column))
41: (forward-line 1)
42: (setq endlinepos (point-marker)))
43: (if (< endcol startcol)
44: (let ((tem startcol))
45: (setq startcol endcol endcol tem)))
46: (if (/= endcol startcol)
47: (save-excursion
48: (goto-char startlinepos)
49: (while (< (point) endlinepos)
50: (let (startpos begextra endextra)
51: (move-to-column startcol)
52: (and coerce-tabs
53: (> (current-column) startcol)
54: (rectangle-coerce-tab startcol))
55: (setq begextra (- (current-column) startcol))
56: (setq startpos (point))
57: (move-to-column endcol)
58: (if (> (current-column) endcol)
59: (if coerce-tabs
60: (rectangle-coerce-tab endcol)
61: (forward-char -1)))
62: (setq endextra (- endcol (current-column)))
63: (if (< begextra 0)
64: (setq endextra (+ endextra begextra)
65: begextra 0))
66: (funcall function startpos begextra endextra))
67: (forward-line 1))))
68: (- endcol startcol)))
69:
70: (defun delete-rectangle-line (startdelpos ignore ignore)
71: (delete-region startdelpos (point)))
72:
73: (defun delete-extract-rectangle-line (startdelpos begextra endextra)
74: (save-excursion
75: (extract-rectangle-line startdelpos begextra endextra))
76: (delete-region startdelpos (point)))
77:
78: (defun extract-rectangle-line (startdelpos begextra endextra)
79: (let ((line (buffer-substring startdelpos (point)))
80: (end (point)))
81: (goto-char startdelpos)
82: (while (search-forward "\t" end t)
83: (let ((width (- (current-column)
84: (save-excursion (forward-char -1)
85: (current-column)))))
86: (setq line (concat (substring line 0 (- (point) end 1))
87: (spaces-string width)
88: (substring line (+ (length line) (- (point) end)))))))
89: (if (or (> begextra 0) (> endextra 0))
90: (setq line (concat (spaces-string begextra)
91: line
92: (spaces-string endextra))))
93: (setq lines (cons line lines))))
94:
95: (defconst spaces-strings
96: '["" " " " " " " " " " " " " " " " "])
97:
98: (defun spaces-string (n)
99: (if (<= n 8) (aref spaces-strings n)
100: (let ((val ""))
101: (while (> n 8)
102: (setq val (concat " " val)
103: n (- n 8)))
104: (concat val (aref spaces-strings n)))))
105:
106: (defun delete-rectangle (start end)
107: "Delete (don't save) text in rectangle with point and mark as corners.
108: The same range of columns is deleted in each line
109: starting with the line where the region begins
110: and ending with the line where the region ends."
111: (interactive "r")
112: (operate-on-rectangle 'delete-rectangle-line start end t))
113:
114: (defun delete-extract-rectangle (start end)
115: "Return and delete contents of rectangle with corners at START and END.
116: Value is list of strings, one for each line of the rectangle."
117: (let (lines)
118: (operate-on-rectangle 'delete-extract-rectangle-line
119: start end t)
120: (nreverse lines)))
121:
122: (defun extract-rectangle (start end)
123: "Return contents of rectangle with corners at START and END.
124: Value is list of strings, one for each line of the rectangle."
125: (let (lines)
126: (operate-on-rectangle 'extract-rectangle-line start end nil)
127: (nreverse lines)))
128:
129: (defvar killed-rectangle nil
130: "Rectangle for yank-rectangle to insert.")
131:
132: (defun kill-rectangle (start end)
133: "Delete rectangle with corners at point and mark; save as last killed one.
134: Calling from program, supply two args START and END, buffer positions.
135: But in programs you might prefer to use delete-extract-rectangle."
136: (interactive "r")
137: (setq killed-rectangle (delete-extract-rectangle start end)))
138:
139: (defun yank-rectangle ()
140: "Yank the last killed rectangle with upper left corner at point."
141: (interactive)
142: (insert-rectangle killed-rectangle))
143:
144: (defun insert-rectangle (rectangle)
145: "Insert text of RECTANGLE with upper left corner at point.
146: RECTANGLE's first line is inserted at point,
147: its second line is inserted at a point vertically under point, etc.
148: RECTANGLE should be a list of strings."
149: (let ((lines rectangle)
150: (insertcolumn (current-column))
151: (first t))
152: (while lines
153: (or first
154: (progn
155: (forward-line 1)
156: (or (bolp) (insert ?\n))
157: (move-to-column insertcolumn)
158: (if (> (current-column) insertcolumn)
159: (rectangle-coerce-tab insertcolumn))
160: (if (< (current-column) insertcolumn)
161: (indent-to insertcolumn))))
162: (setq first nil)
163: (insert (car lines))
164: (setq lines (cdr lines)))))
165:
166: (defun open-rectangle (start end)
167: "Blank out rectangle with corners at point and mark, shifting text right.
168: The text previously in the region is not overwritten by the blanks,
169: but insted winds up to the right of the rectangle."
170: (interactive "r")
171: (operate-on-rectangle 'open-rectangle-line start end nil))
172:
173: (defun open-rectangle-line (startpos begextra endextra)
174: (let ((column (+ (current-column) begextra endextra)))
175: (goto-char startpos)
176: (let ((ocol (current-column)))
177: (skip-chars-forward " \t")
178: (setq column (+ column (- (current-column) ocol))))
179: (delete-region (point)
180: (progn (skip-chars-backward " \t")
181: (point)))
182: (indent-to column)))
183:
184: (defun clear-rectangle (start end)
185: "Blank out rectangle with corners at point and mark.
186: The text previously in the region is overwritten by the blanks."
187: (interactive "r")
188: (operate-on-rectangle 'clear-rectangle-line start end t))
189:
190: (defun clear-rectangle-line (startpos begextra endextra)
191: (skip-chars-forward " \t")
192: (let ((column (+ (current-column) endextra)))
193: (delete-region (point)
194: (progn (goto-char startpos)
195: (skip-chars-backward " \t")
196: (point)))
197: (indent-to column)))
198:
199: (defun rectangle-coerce-tab (column)
200: (let ((aftercol (current-column))
201: (indent-tabs-mode nil))
202: (delete-char -1)
203: (indent-to aftercol)
204: (backward-char (- aftercol column))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.