;; -*- emacs-lisp -*-
;;; mst-guess-indentation.el --- guess the indentation of a buffer

;; Author: Mark Triggs <mst@dishevelled.net>
;; $Id: mst-guess-indentation.el,v 1.24 2004/09/26 07:40:23 mst Exp $

;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; This is kind of a first attempt at guessing other people's code settings.
;; It tries to be vaguely clever by trying to guess whether or not tabs should
;; be used, or how wide indentation should be otherwise.
;;
;; You can use this by using the return value from (grok-buffer-settings) to
;; set the appropriate variables for your favourite major mode.

;;; Code:

(defvar indent-guess-possible-indents (loop for i from 2 to 8 collect i))


(defun guess-indentation ()
  "Guess the level of indentation appropriate for the current buffer"
  (let* ((comment (subseq comment-start 0 1))
         (regexp (format "\\(^ +\\)[^%s]" comment))
         (whitespace '()))
    (save-excursion
      (goto-char (point-min))
      (while (search-forward-regexp regexp nil t)
        (push (- (match-end 1) (match-beginning 1))
              whitespace)))
    (if (< (length whitespace) 10)
        nil
      (caar (sort (mapcar (lambda (guess)
                            (cons guess
                                  (loop for i from 1 to 4
                                        sum (count (* guess i)
                                                   whitespace))))
                          indent-guess-possible-indents)
                  (lambda (a b) (if (= (cdr b) (cdr a))
                                    (< (car b) (car a))
                                  (< (cdr b) (cdr a)))))))))


(defun buffer-has-tabs-p ()
  "A buffer 'has tabs' if more than a quarter of the lines have a leading tab"
  (save-excursion
    (goto-char (point-max))
    (beginning-of-line)
    (let ((lines (current-line-number))
          (count 0))
      (while (and (not (bobp)) (< count (/ lines 4)))
        (when (looking-at "^\t")
          (incf count))
        (forward-line -1)))
    (not (bobp))))

(defun my-code-p ()
  (save-excursion (goto-char (point-min))
                  (search-forward-regexp
                   (concat "Author *: " user-full-name) nil t)))

(defun grok-buffer-settings ()
  "Return the settings of the current buffer as a list of the form:
 (TABS INDENT-WIDTH)"
  (if (buffer-has-tabs-p)
      (list t 8)
    (let ((indentation (guess-indentation)))
      (if indentation
          (list nil indentation)
        nil))))

(provide 'mst-guess-indentation)
;;; mst-guess-indentation.el ends here
