;;------------------------------------------------------------------------------
;; Automatic insertion of matching missing parenthetic characters.
;; Author: Martin Blais <blais@furius.ca>
;; Date: 2010-10-24
;;
;; Credits:
;; Bill Smith (william m smith gmail com) : submitted close-matching-all.


;; An assoc-list of mappings for matching parenthetic characters.
(defvar close-matching-chars
  '( (?( . ?))
     (?[ . ?])
     (?{ . ?})
     (?< . >})
     (?" . ?")
     (?* . ?*)
     ))

(defun close-matching-one ()
  "Close one matching paren with the most appropriate balanced character."
  (interactive)
  ;; (let ((parse-sexp-ignore-comments t))

  ;; Scan backwards until it stops.
  (let* ((c (save-excursion
	      ;; Note: scan-sexp doesn't match beginnings with (= and ('
	      (if nil
		  (progn
		    (while (ignore-errors (forward-sexp -1) (not (<= (point) 1))))
		    (re-search-backward "[^ \n]" nil nil nil))
		;; Note: scan-lists doesn't work with "
		(goto-char (scan-lists (point) -1 1)))

	      (string-to-char (thing-at-point 'char))
	      ))
	 (ichar (assoc c close-matching-chars))
	 )
    (if ichar
	(progn (insert-char (cdr ichar) 1) c)
      (error "Error: No matching opening character found."))
    ))

(defun close-matching-all ()
  "Close as many matching parens as we can."
  (interactive)
  (condition-case nil
      (while (close-matching-one))
    ((error) nil)))

(defun close-matching ()
  "Close one matching paren, or all (if a prefix arg is present)"
  (interactive)
  (if current-prefix-arg
      (close-matching-all)
    (close-matching-one)))

(defun close-matching-install-bindings (map)
  "Install the default key bindings."
  (define-key map [(control \))] 'close-matching))

(provide 'close-matching)
