1;;; tabify.el --- tab conversion commands for Emacs 2 3;; Copyright (C) 1985, 1994, 2001, 2002, 2003, 2004, 4;; 2005, 2006, 2007 Free Software Foundation, Inc. 5 6;; Maintainer: FSF 7 8;; This file is part of GNU Emacs. 9 10;; GNU Emacs is free software; you can redistribute it and/or modify 11;; it under the terms of the GNU General Public License as published by 12;; the Free Software Foundation; either version 2, or (at your option) 13;; any later version. 14 15;; GNU Emacs is distributed in the hope that it will be useful, 16;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18;; GNU General Public License for more details. 19 20;; You should have received a copy of the GNU General Public License 21;; along with GNU Emacs; see the file COPYING. If not, write to the 22;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23;; Boston, MA 02110-1301, USA. 24 25;;; Commentary: 26 27;; Commands to optimize spaces to tabs or expand tabs to spaces in a region 28;; (`tabify' and `untabify'). The variable tab-width does the obvious. 29 30;;; Code: 31 32;;;###autoload 33(defun untabify (start end) 34 "Convert all tabs in region to multiple spaces, preserving columns. 35Called non-interactively, the region is specified by arguments 36START and END, rather than by the position of point and mark. 37The variable `tab-width' controls the spacing of tab stops." 38 (interactive "r") 39 (save-excursion 40 (save-restriction 41 (narrow-to-region (point-min) end) 42 (goto-char start) 43 (while (search-forward "\t" nil t) ; faster than re-search 44 (forward-char -1) 45 (let ((tab-beg (point)) 46 (indent-tabs-mode nil) 47 column) 48 (skip-chars-forward "\t") 49 (setq column (current-column)) 50 (delete-region tab-beg (point)) 51 (indent-to column)))))) 52 53(defvar tabify-regexp " [ \t]+" 54 "Regexp matching whitespace that tabify should consider. 55Usually this will be \" [ \\t]+\" to match a space followed by whitespace. 56\"^\\t* [ \\t]+\" is also useful, for tabifying only initial whitespace.") 57 58;;;###autoload 59(defun tabify (start end) 60 "Convert multiple spaces in region to tabs when possible. 61A group of spaces is partially replaced by tabs 62when this can be done without changing the column they end at. 63Called non-interactively, the region is specified by arguments 64START and END, rather than by the position of point and mark. 65The variable `tab-width' controls the spacing of tab stops." 66 (interactive "r") 67 (save-excursion 68 (save-restriction 69 ;; Include the beginning of the line in the narrowing 70 ;; since otherwise it will throw off current-column. 71 (goto-char start) 72 (beginning-of-line) 73 (narrow-to-region (point) end) 74 (goto-char start) 75 (let ((indent-tabs-mode t)) 76 (while (re-search-forward tabify-regexp nil t) 77 ;; The region between (match-beginning 0) and (match-end 0) is just 78 ;; spacing which we want to adjust to use TABs where possible. 79 (let ((end-col (current-column)) 80 (beg-col (save-excursion (goto-char (match-beginning 0)) 81 (skip-chars-forward "\t") 82 (current-column)))) 83 (if (= (/ end-col tab-width) (/ beg-col tab-width)) 84 ;; The spacing (after some leading TABs which we wouldn't 85 ;; want to touch anyway) does not straddle a TAB boundary, 86 ;; so it neither contains a TAB, nor will we be able to use 87 ;; a TAB here anyway: there's nothing to do. 88 nil 89 (delete-region (match-beginning 0) (point)) 90 (indent-to end-col)))))))) 91 92(provide 'tabify) 93 94;; arch-tag: c83893b1-e0cc-4e57-8a09-73fd03466416 95;;; tabify.el ends here 96