Path: utzoo!telly!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!ucsd!tut.cis.ohio-state.edu!UUNET.UU.NET!telotech!bsa%hal From: telotech!bsa%hal@UUNET.UU.NET (Brandon S. Allbery) Newsgroups: gnu.emacs Subject: (repost) simple-indent mode Message-ID: <8910030848.AA03962@telotech.UUCP> Date: 2 Oct 89 12:19:33 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 142 I sent this out yesterday, but something seems to have broken suddenly in the kluge that forces smail and mh to work in a rational way on a Xenix-descended system that is more a hybrid of everything than compatible with any one. So here it is again, via another mailer. Someone was looking for a perl mode. I don't have one, but I have a major mode I whipped up to handle random script-like languages: shell, perl, Makefiles, SQL, Accell/Language, etc. To use it, put (load "sindent") in your .emacs and set up your auto-mode-alist to invoke simple-indent-mode on whatever files. It's not perfect, but it works far better than just text mode and uses a rigid indent, unlike indented-text mode. ++Brandon ------------------------------------------------------------------------------ ;;; Major mode to do simple indentation ;;; based on text mode, but redefines TAB to use tab-stop ;;; obeys left-margin (defvar tab-stop 8 "*Size of a TAB in simple-indent mode.") (make-variable-buffer-local 'tab-stop) (defvar sindent-obey-all-tabs nil "*If non-nil, all TABs in simple-indent mode use tab-stop.") (defvar sindent-mode-syntax-table nil "Syntax table used while in simple-indent mode.") (defvar sindent-mode-abbrev-table nil "Abbrev table used while in sindent mode.") (define-abbrev-table 'sindent-mode-abbrev-table ()) (if sindent-mode-syntax-table () (setq sindent-mode-syntax-table (make-syntax-table)) (modify-syntax-entry ?\" ". " sindent-mode-syntax-table) (modify-syntax-entry ?\\ ". " sindent-mode-syntax-table) (modify-syntax-entry ?' "w " sindent-mode-syntax-table)) (defvar sindent-mode-map nil "") (if sindent-mode-map () (setq sindent-mode-map (make-sparse-keymap)) (define-key sindent-mode-map "\t" 'simple-tab) (define-key sindent-mode-map "\177" 'sindent-backward-delete-char) (define-key sindent-mode-map "\es" 'center-line) (define-key sindent-mode-map "\eS" 'center-paragraph)) (defun simple-indent-mode () "Major mode to do simple indentation. Based on Text mode. In this mode, TAB moves tab-width spaces in the indentation area of a line, compacting spaces to real tabs as it goes. Commands:\\{sindent-mode-map} Turning on this mode runs text-mode-hook and sindent-mode-hook." (interactive) (kill-all-local-variables) (use-local-map sindent-mode-map) (setq mode-name "Simple") (setq major-mode 'simple-indent-mode) (setq local-abbrev-table sindent-mode-abbrev-table) (set (make-local-variable 'indent-line-function) 'simple-indent-line) (set-syntax-table sindent-mode-syntax-table) (run-hooks 'text-mode-hook 'sindent-mode-hook)) ;;; Indent this line to the previous line's indentation. (defun simple-indent-line () "Indent current line like the previous line, provided that it is empty." (and (bolp) (eolp) (not (bobp)) (indent-to (save-excursion (forward-line -1) (skip-chars-forward " \t") (current-column))))) ;;; Indent to the next tab stop, as defined by the tab-stop variable (defun simple-tab (arg) "Indent to the next tab-stop, as defined by the `tab-stop' variable." (interactive "P") (if arg (let ((count (prefix-numeric-value arg))) (and (< count 0) (error "Can't tab by negative amount")) (while (/= count 0) (simple-tab-1) (setq count (1- count)))) (simple-tab-1))) ;;; Do a single tab. (defun simple-tab-1 () "Perform a single simple tab." (if (or sindent-obey-all-tabs (save-excursion (skip-chars-backward " \t") (bolp))) (let (goal here) (skip-chars-forward " \t") (setq here (point)) (setq goal (+ (- (current-column) left-margin) tab-stop)) (setq goal (+ (- goal (% goal tab-stop)) left-margin)) (skip-chars-backward " \t") (delete-region (point) here) (indent-to goal)) (tab-to-tab-stop))) ;;; Delete backwards as (delete-backward-char), but if in indent only back ;;; to previous tab stop (defun sindent-backward-delete-char (arg &optional killp) "Delete charaters backward, obeying simple-indent's tab stops. Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil. Interactively, ARG is the prefix arg (default 1) and KILLP is t if prefix arg is was specified." (interactive "*p\nP") (let ((count arg) (del-count arg)) (save-excursion (while (and (> count 0) (not (bobp))) (if (and (not (bolp)) (save-excursion (skip-chars-backward " \t") (bolp))) (progn (and (= (preceding-char) ?\t) (let ((col (current-column))) (forward-char -1) (setq col (- col (current-column))) (insert-char ?\ col) (delete-char 1))) (if (= (current-column) left-margin) (progn (setq del-count (+ del-count left-margin -2)) (forward-char (- (+ 2 left-margin)))) (let ((cols (% (- (current-column) left-margin) tab-stop))) (and (= cols 0) (setq cols tab-stop)) (forward-char (- cols)) (setq del-count (+ del-count (1- cols)))))) (forward-char -1)) (setq count (1- count)))) (delete-backward-char del-count killp))) (provide 'sindent)