Init-Files/site-lisp/cc-mode/5.31.2/cc-guess.el
2012-03-22 07:16:09 -07:00

219 lines
7.3 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; cc-guess.el --- guess indentation values by scanning existing code
;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
;; Inc.
;; Author: 1994-1995 Barry A. Warsaw
;; Maintainer: Unmaintained
;; Created: August 1994, split from cc-mode.el
;; Version: See cc-mode.el
;; Keywords: c languages oop
;; This file is not part of GNU Emacs.
;; This program 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 of the License, or
;; (at your option) any later version.
;;
;; This program 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 this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; This file contains routines that help guess the cc-mode style in a
;; particular region/buffer. It is provided for example and
;; experimentation only. It is not supported in anyway. Note that
;; style guessing is lossy!
;;
;; The way this is intended to be run is for you to mark a region of
;; code to guess the style of, then run the command, `cc-guess-region'.
;;; Code:
(eval-when-compile
(let ((load-path
(if (and (boundp 'byte-compile-dest-file)
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
(cc-require 'cc-engine)
(defvar cc-guessed-style nil
"Currently guessed style.")
(defvar cc-guess-delta-accumulator nil)
;; Accumulated sampled indent information. Information is represented
;; in a list. Each element in it has following structure:
;;
;; (syntactic-symbol ((indentation-delta1 . number-of-times1)
;; (indentation-delta2 . number-of-times2)
;; ...))
;;
;; This structure is built by `cc-guess-accumulate-delta'.
;;
;; Here we call the pair (indentation-delta1 . number-of-times1) a
;; counter. `cc-guess-sort-delta-accumulator' sorts the order of
;; counters by number-of-times.
(defconst cc-guess-conversions
'((c . c-lineup-C-comments)
(inher-cont . c-lineup-multi-inher)
(string . -1000)
(comment-intro . c-lineup-comment)
(arglist-cont-nonempty . c-lineup-arglist)
(arglist-close . c-lineup-close-paren)
(cpp-macro . -1000)))
(defun cc-guess (&optional accumulate)
"Apply `cc-guess-region' on the whole current buffer.
If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch."
(interactive "P")
(cc-guess-region (point-min) (point-max) accumulate))
(defun cc-guess-install ()
"Set the indentation style from the last guessed style (`cc-guessed-style')."
(interactive)
(setq c-offsets-alist (cc-guess-merge-styles cc-guessed-style
c-offsets-alist)))
(defun cc-guess-region (start end &optional accumulate)
"Set the indentation style by examining the indentation in a region of code.
Every line of code in the region is examined and the indentation
values of the various syntactic symbols in `c-offset-alist' are
guessed. Frequencies of use are taken into account, so minor
inconsistencies in the indentation style shouldn't produce wrong
guesses.
The guessed style is put into `cc-guessed-style'. It's also merged
into `c-offsets-alist'. Guessed offsets takes precedence over
existing ones on `c-offsets-alist'.
If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch.
Note that the larger the region to guess in, the slower the guessing."
(interactive "r\nP")
(let ((delta-accumulator (when accumulate cc-guess-delta-accumulator))
(reporter (when (fboundp 'make-progress-reporter)
(make-progress-reporter "Sampling Indentation " start end))))
;;
;; Sampling stage
;;
(save-excursion
(goto-char start)
(while (< (point) end)
(c-save-buffer-state
((syntax (c-guess-basic-syntax))
(relpos (car (cdr (car syntax))))
(symbol (car (car syntax))))
;; TBD: for now I can't guess indentation when more than 1
;; symbol is on the list, nor for symbols without relpos's
;;
;; I think it is too stricted for ((topmost-intro) (comment-intro)).
;; -- Masatake
(unless (or ; (/= 1 (length syntax))
(not (numberp relpos))
(eq (line-beginning-position)
(line-end-position)))
(setq delta-accumulator (cc-guess-accumulate-delta
delta-accumulator
symbol
(- (progn (back-to-indentation)
(current-column) )
(save-excursion
(goto-char relpos)
(current-column)))))))
(when reporter (progress-reporter-update reporter (point)))
(forward-line 1)))
(when reporter (progress-reporter-done reporter))
;;
;; Guessing stage
;;
(setq delta-accumulator (cc-guess-sort-delta-accumulator
delta-accumulator)
cc-guess-delta-accumulator delta-accumulator)
(let* ((typical-style (cc-guess-make-style delta-accumulator))
(merged-style (cc-guess-merge-styles
(copy-list cc-guess-conversions)
typical-style)))
(setq cc-guessed-style merged-style
c-offsets-alist (cc-guess-merge-styles
merged-style
c-offsets-alist)))))
(defun cc-guess-accumulate-delta (accumulator symbol delta)
;; Added SYMBOL and DELTA to ACCUMULATOR. See
;; `cc-guess-delta-accumulator' about the structure of ACCUMULATOR.
(let* ((entry (assoc symbol accumulator))
(counters (cdr entry))
counter)
(if entry
(progn
(setq counter (assoc delta counters))
(if counter
(setcdr counter (1+ (cdr counter)))
(setq counters (cons (cons delta 1) counters))
(setcdr entry counters))
accumulator)
(cons (cons symbol (cons (cons delta 1) nil)) accumulator))))
(defun cc-guess-sort-delta-accumulator (accumulator)
;; Sort the each element of ACCUMULATOR by the number-of-times. See
;; `cc-guess-delta-accumulator' for more details.
(mapcar
(lambda (entry)
(let ((symbol (car entry))
(counters (cdr entry)))
(cons symbol (sort counters
(lambda (a b)
(if (> (cdr a) (cdr b))
t
(and
(eq (cdr a) (cdr b))
(< (car a) (car b)))))))))
accumulator))
(defun cc-guess-make-style (accumulator)
;; Throw away the rare cases in accumulator and make a style structure.
(mapcar
(lambda (entry)
(cons (car entry)
(car (car (cdr entry)))))
accumulator))
(defun cc-guess-merge-styles (strong weak)
;; Merge two styles into one. When two styles has the same symbol
;; entry, give STRONG priority over WEAK.
(mapc
(lambda (weak-elt)
(unless (assoc (car weak-elt) strong)
(setq strong (cons weak-elt strong))))
weak)
strong)
(defun cc-guess-view-style ()
"Show `cc-guessed-style'."
(interactive)
(with-output-to-temp-buffer "*Indentation Guessing Result*"
(pp cc-guessed-style)))
(cc-provide 'cc-guess)
;;; cc-guess.el ends here