|
|
1.1 ! root 1: ;; Rectangle functions for GNU Emacs. ! 2: ;; Copyright (C) 1985 Free Software Foundation, Inc. ! 3: ! 4: ;; This file is part of GNU Emacs. ! 5: ! 6: ;; GNU Emacs is free software; you can redistribute it and/or modify ! 7: ;; it under the terms of the GNU General Public License as published by ! 8: ;; the Free Software Foundation; either version 1, or (at your option) ! 9: ;; any later version. ! 10: ! 11: ;; GNU Emacs is distributed in the hope that it will be useful, ! 12: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: ;; GNU General Public License for more details. ! 15: ! 16: ;; You should have received a copy of the GNU General Public License ! 17: ;; along with GNU Emacs; see the file COPYING. If not, write to ! 18: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 19: ! 20: ! 21: (defun operate-on-rectangle (function start end coerce-tabs) ! 22: "Call FUNCTION for each line of rectangle with corners at START, END. ! 23: If COERCE-TABS is non-nil, convert multi-column characters ! 24: that span the starting or ending columns on any line ! 25: to multiple spaces before calling FUNCTION. ! 26: FUNCTION is called with three arguments: ! 27: position of start of segment of this line within the rectangle, ! 28: number of columns that belong to rectangle but are before that position, ! 29: number of columns that belong to rectangle but are after point. ! 30: Point is at the end of the segment of this line within the rectangle." ! 31: (let (startcol startlinepos endcol endlinepos) ! 32: (save-excursion ! 33: (goto-char start) ! 34: (setq startcol (current-column)) ! 35: (beginning-of-line) ! 36: (setq startlinepos (point))) ! 37: (save-excursion ! 38: (goto-char end) ! 39: (setq endcol (current-column)) ! 40: (forward-line 1) ! 41: (setq endlinepos (point-marker))) ! 42: (if (< endcol startcol) ! 43: (let ((tem startcol)) ! 44: (setq startcol endcol endcol tem))) ! 45: (if (/= endcol startcol) ! 46: (save-excursion ! 47: (goto-char startlinepos) ! 48: (while (< (point) endlinepos) ! 49: (let (startpos begextra endextra) ! 50: (move-to-column startcol) ! 51: (and coerce-tabs ! 52: (> (current-column) startcol) ! 53: (rectangle-coerce-tab startcol)) ! 54: (setq begextra (- (current-column) startcol)) ! 55: (setq startpos (point)) ! 56: (move-to-column endcol) ! 57: (if (> (current-column) endcol) ! 58: (if coerce-tabs ! 59: (rectangle-coerce-tab endcol) ! 60: (forward-char -1))) ! 61: (setq endextra (- endcol (current-column))) ! 62: (if (< begextra 0) ! 63: (setq endextra (+ endextra begextra) ! 64: begextra 0)) ! 65: (funcall function startpos begextra endextra)) ! 66: (forward-line 1)))) ! 67: (- endcol startcol))) ! 68: ! 69: (defun delete-rectangle-line (startdelpos ignore ignore) ! 70: (delete-region startdelpos (point))) ! 71: ! 72: (defun delete-extract-rectangle-line (startdelpos begextra endextra) ! 73: (save-excursion ! 74: (extract-rectangle-line startdelpos begextra endextra)) ! 75: (delete-region startdelpos (point))) ! 76: ! 77: (defun extract-rectangle-line (startdelpos begextra endextra) ! 78: (let ((line (buffer-substring startdelpos (point))) ! 79: (end (point))) ! 80: (goto-char startdelpos) ! 81: (while (search-forward "\t" end t) ! 82: (let ((width (- (current-column) ! 83: (save-excursion (forward-char -1) ! 84: (current-column))))) ! 85: (setq line (concat (substring line 0 (- (point) end 1)) ! 86: (spaces-string width) ! 87: (substring line (+ (length line) (- (point) end))))))) ! 88: (if (or (> begextra 0) (> endextra 0)) ! 89: (setq line (concat (spaces-string begextra) ! 90: line ! 91: (spaces-string endextra)))) ! 92: (setq lines (cons line lines)))) ! 93: ! 94: (defconst spaces-strings ! 95: '["" " " " " " " " " " " " " " " " "]) ! 96: ! 97: (defun spaces-string (n) ! 98: (if (<= n 8) (aref spaces-strings n) ! 99: (let ((val "")) ! 100: (while (> n 8) ! 101: (setq val (concat " " val) ! 102: n (- n 8))) ! 103: (concat val (aref spaces-strings n))))) ! 104: ! 105: (defun delete-rectangle (start end) ! 106: "Delete (don't save) text in rectangle with point and mark as corners. ! 107: The same range of columns is deleted in each line ! 108: starting with the line where the region begins ! 109: and ending with the line where the region ends." ! 110: (interactive "r") ! 111: (operate-on-rectangle 'delete-rectangle-line start end t)) ! 112: ! 113: (defun delete-extract-rectangle (start end) ! 114: "Return and delete contents of rectangle with corners at START and END. ! 115: Value is list of strings, one for each line of the rectangle." ! 116: (let (lines) ! 117: (operate-on-rectangle 'delete-extract-rectangle-line ! 118: start end t) ! 119: (nreverse lines))) ! 120: ! 121: (defun extract-rectangle (start end) ! 122: "Return contents of rectangle with corners at START and END. ! 123: Value is list of strings, one for each line of the rectangle." ! 124: (let (lines) ! 125: (operate-on-rectangle 'extract-rectangle-line start end nil) ! 126: (nreverse lines))) ! 127: ! 128: (defvar killed-rectangle nil ! 129: "Rectangle for yank-rectangle to insert.") ! 130: ! 131: (defun kill-rectangle (start end) ! 132: "Delete rectangle with corners at point and mark; save as last killed one. ! 133: Calling from program, supply two args START and END, buffer positions. ! 134: But in programs you might prefer to use delete-extract-rectangle." ! 135: (interactive "r") ! 136: (setq killed-rectangle (delete-extract-rectangle start end))) ! 137: ! 138: (defun yank-rectangle () ! 139: "Yank the last killed rectangle with upper left corner at point." ! 140: (interactive) ! 141: (insert-rectangle killed-rectangle)) ! 142: ! 143: (defun insert-rectangle (rectangle) ! 144: "Insert text of RECTANGLE with upper left corner at point. ! 145: RECTANGLE's first line is inserted at point, ! 146: its second line is inserted at a point vertically under point, etc. ! 147: RECTANGLE should be a list of strings." ! 148: (let ((lines rectangle) ! 149: (insertcolumn (current-column)) ! 150: (first t)) ! 151: (while lines ! 152: (or first ! 153: (progn ! 154: (forward-line 1) ! 155: (or (bolp) (insert ?\n)) ! 156: (move-to-column insertcolumn) ! 157: (if (> (current-column) insertcolumn) ! 158: (rectangle-coerce-tab insertcolumn)) ! 159: (if (< (current-column) insertcolumn) ! 160: (indent-to insertcolumn)))) ! 161: (setq first nil) ! 162: (insert (car lines)) ! 163: (setq lines (cdr lines))))) ! 164: ! 165: (defun open-rectangle (start end) ! 166: "Blank out rectangle with corners at point and mark, shifting text right. ! 167: The text previously in the region is not overwritten by the blanks, ! 168: but insted winds up to the right of the rectangle." ! 169: (interactive "r") ! 170: (operate-on-rectangle 'open-rectangle-line start end nil)) ! 171: ! 172: (defun open-rectangle-line (startpos begextra endextra) ! 173: (let ((column (+ (current-column) begextra endextra))) ! 174: (goto-char startpos) ! 175: (let ((ocol (current-column))) ! 176: (skip-chars-forward " \t") ! 177: (setq column (+ column (- (current-column) ocol)))) ! 178: (delete-region (point) ! 179: (progn (skip-chars-backward " \t") ! 180: (point))) ! 181: (indent-to column))) ! 182: ! 183: (defun clear-rectangle (start end &optional preserve-position) ! 184: "Blank out rectangle with corners at point and mark. ! 185: The text previously in the region is overwritten by the blanks." ! 186: (interactive "r") ! 187: (operate-on-rectangle 'clear-rectangle-line start end t)) ! 188: ! 189: (defun clear-rectangle-line (startpos begextra endextra) ! 190: (skip-chars-forward " \t") ! 191: (let ((column (+ (current-column) endextra))) ! 192: (delete-region (point) ! 193: (progn (goto-char startpos) ! 194: (or preserve-position ! 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.