;;
;; Id: lisp-indent.el,v 1.1 1996/12/03 22:05:14 fgarcia Exp 
;; Source: /projects/cvsroot/elisp/lisp-indent.el,v 
;; Author: fgarcia 
;;
;; Hack to get lisp ) to line up with matching (
;;

(provide 'fg-lisp-indent)
(require 'lisp-mode)

;; function to take care of lining up the clope with the ope

(defun special-indent-line ()
  (let ((indent-special nil)
	(init-marker (point-marker))
       )
    (save-excursion
      (beginning-of-line)
      (setq indent-special (looking-at "[ \t]*)"))
      (if indent-special
	  (let ((column-pos 0)
		(clope-pos (match-end 0))
	       )
	    (goto-char clope-pos)
	    (save-excursion
	      (backward-sexp)
	      (setq column-pos (current-column))
	    )
	    (beginning-of-line)
	    (delete-region (point) (- clope-pos 1))
	    (indent-to column-pos)
	  )
      )
    )
    ;; If initial point was within line's indentation,
    ;; position after the indentation.  Else stay at same point in text.
    (if indent-special
	(progn
	  (goto-char (marker-position init-marker))
	  (if (bolp)
	      (progn
		(re-search-forward ")")
		(backward-char)
	      )
	  )
	)
    )
    (set-marker init-marker nil)
    indent-special
  )
)
	  
;; Redefine lisp-indent-line.  Too bad emacs doesn't give you a decent
;; hook for doing this, since lisp-indent-function is explicitly
;; called in some places in lisp-mode.el instead of calling the
;; function in the local variable indent-line-function (at least for
;; emacs-19.29 this is the case).

(defun new-lisp-indent-line (&optional whole-exp)
  (interactive "P")
  (or (special-indent-line)
      (old-lisp-indent-line whole-exp)
  )
)

(or (fboundp 'old-lisp-indent-line)
    (fset 'old-lisp-indent-line (symbol-function
				 'lisp-indent-line)
    )
)

(fset 'lisp-indent-line 'new-lisp-indent-line)

(defun special-indent-region (max-pt-marker)
  ;; need to go forward one line to work around indent-sexp sillyness
  (let ((max-marker (save-excursion
		      (goto-char (marker-position max-pt-marker))
		      (end-of-line 2)
		      (point-marker)
		    )
	)
       )
    (while (re-search-forward "^[ \t]*)"
			      (marker-position max-marker)
			      t nil)
      (save-excursion
	(goto-char (match-beginning 0))
	(new-lisp-indent-line)
      )
    )
    (setq max-marker nil)
  )
)

;; Redefine indent-sexp.  Again, it's too bad there isn't a cleaner
;; way to do this.

(defun new-indent-sexp (&optional endpos)
  (interactive)
  (let ((end-marker (make-marker))
	(max-marker (make-marker))
       )
    (if endpos
	(progn
	  (set-marker end-marker endpos)
	  (set-marker max-marker endpos)
	)
    )
    (old-indent-sexp endpos)
    (if (not (or endpos (looking-at "[ \t]*)")))
	(save-excursion
	  (forward-sexp)
	  (set-marker max-marker (point))
	)
    )
    (and (marker-position max-marker)
	 (special-indent-region max-marker)
    )
    (setq max-marker nil)
  )
)

(or (fboundp 'old-indent-sexp)
    (fset 'old-indent-sexp (symbol-function
			    'indent-sexp)
    )
)

(fset 'indent-sexp 'new-indent-sexp)

;; Now rebind the paren key so it always aligns properly

(defun electric-close-paren ()
  (interactive)
  (let (;; NOTE: done this way because backward-sexp can't handle ?)
	(clope (string-to-char ")"))
	)
  (insert-char clope 1 t)
  (special-indent-line)
  (blink-matching-open)
  )
)

(define-key shared-lisp-mode-map ")" 'electric-close-paren)

