emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

request for reviewing the updated version of cc-guess.el


From: Masatake YAMATO
Subject: request for reviewing the updated version of cc-guess.el
Date: Sun, 27 Mar 2011 23:43:41 +0900 (JST)

On Fri, 25 Mar 2011 13:26:44 +0000, Alan Mackenzie <address@hidden> wrote
> Hi, Masatake.
> 
> On Thu, Mar 24, 2011 at 09:07:33PM +0900, Masatake YAMATO wrote:
>> Hi,
> 
>> Yes, I'll write.  [A patch for the menus]
> 
> Thanks!
> 
>> > One other thing: there doesn't seem to be a mechanism for dumping out
>> > a guessed style so that it can be used in a future Emacs session.
>> > Something like M-x c-dump-guessed-style which would print out the
>> > style a bit like c-submit-but-report (C-c C-b) dumps the entire
>> > configuration.  Do you think something like this is needed?
> 
>> I agree about the requirement if I understand the requirement correctly. 
> 
> 
>> `cc-guess-view-guessed-style' in my patch
>> is not enough? It is just do `pp' guessed style like:
> 
> My apologies: I hadn't seen cc-guess-view-guessed-style.  I don't think
> the function as it is does quite the right thing, though.
> 
>>    (with-output-to-temp-buffer "*Guessed Style*"
>>       (pp style))
> 
>> I can change the code like:
> 
>>    (with-output-to-temp-buffer "*Guessed Style*"
>>       (pp `(c-add-style ,(cc-guess-style-name) ,style ,t)))
> 
> That would be much better.
> 
>> Do you think this code satisfies the requirement?
> 
> Not quite: the guessed style only includes two style variables.  I think
> it should be printed out as inheriting from the default style.  Something
> like:
> 
>     (c-add-style "*cc-guess*<filename>"
>      '("gnu"
>        <guessed style>
>       ))
> 
> What do you think?  Would it perhaps be better to make the *Guessed
> Style* buffer R/W, allowing the user to edit the new style before copying
> it to his .emacs?  I'm not sure on this one.

I agree. It is nice. I've replace all the prefix of function name 
"cc-guess-view-"
with new prefix "cc-guess-dump-". Instead I've introduce new function named 
`cc-guess-view'. It does what you suggested.

I've pasted the diff to this mail.
To avoid a trouble in applying the patch, I attach cc-guess.el itself 
I've worked on to this mail.

Masatake YAMATO



The summary of changes:

    - Added Style... menu item to C pull-down menu.
    - `cc-guess-view' emits emacs lisp code which defines
      guessed style. Suggested by Alan Mackenzie.

The changed files:

    - cc-guess.el: This is the main program file.
    - cc-lang.el: The menu definition is changes.
    - cc-style.el: `cc-choose-style-for-mode' is newly defined here.
                   This function is used from both cc-guess.el
                   and cc-mode.el.
    - cc-mode.el: Some lines are replaced with `cc-choose-style-for-mode'.
    - Makefile: This is part of official cc-mode source tree, not emacs 
                source tree. cc-guess.el is added to ELISPFILES macro.
 

Detail of changes:

2011-03-27  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-region-no-install)
        (cc-guess-make-basic-offset): Use `copy-tree'
        instead of `copy-list'.

2011-03-27  Masatake YAMATO  <address@hidden>

        * cc-langs.el (c-mode-menu): Use `cc-guess-view'.

2011-03-27  Masatake YAMATO  <address@hidden>

        * cc-styles.el (cc-choose-style-for-mode): New function
        dereived from `c-basic-common-init'.

        * cc-mode.el (c-basic-common-init): Use
        `cc-choose-style-for-mode'.

        * cc-guess.el (cc-styles): Require cc-styles to use
        `cc-choose-style-for-mode'.

        * cc-guess.el (cc-guess-dump-*): Renamed from
        cc-guess-view-*.
        (cc-guess-view-guessed-style): Take a printer
        function as a parameter.
        (cc-guess-view): New function for emitting
        .emacs ready code. Suggested by Alan Mackenzie.

2011-03-27  Masatake YAMATO  <address@hidden>

        * cc-langs.el (c-mode-menu): Added "Style..." menu entries.

2011-03-25  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-install): Report the
        name of installed style.

2011-03-25  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-empty-line-p): Define
        this subst befine it was used.
        (cc-guess-reset-accumulator): Fix a typo.
        Set `cc-guess-accumulator' to nil.

2011-03-25  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-guessed-offsets-alist):
        (cc-guess-guessed-basic-offset):
        (cc-guess):
        (cc-guess-no-install):
        (cc-guess-buffer):
        (cc-guess-buffer-no-install):
        (cc-guess-region):
        (cc-guess-region-no-install):
        (cc-guess-install): Added ;;;####autoload marks.

        * Makefile (ELISPFILES): Move cc-guess.el from
        EXTRAFILES dist to ELISPFILES.

        * cc-mode.el (cc-guess): Required.

2011-02-11  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess): Don't limit the region
        if `cc-guess-region-max' is nil.
        (cc-guess-no-install): Ditto.

2011-01-18  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-make-basic-offset): Don't use sort
        to find the majority.

2011-01-18  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-style-name-p): New function.

2011-01-16  Masatake YAMATO  <address@hidden>

        * cc-guess.el: Use `+', `-', `++', `--', `*', or `/'.
        (cc-guess-symbolize-offsets-alist): New function.
        (cc-guess-symbolize-integer): New function.
        (cc-guess-make-style): New function.
        (cc-guess-view-guessed-style): New function.

2011-01-16  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-no-install): New function.
        (cc-guess-buffer-no-install): New function.
        (cc-guess-region-no-install): New function.
        (cc-guess-make-basic-offset): Ignore `c' syntax-symbol.
        (cc-guess-style-name): New function.
        (cc-guess-install): Don't set `c-offsets-alist'. Instead
        define a style and use it.
        (cc-guess-view-guessed-values): Renamed from
        `cc-guess-view-offsets-alist'.
        Print also `basic-offset'.

2011-01-16  Masatake YAMATO  <address@hidden>

        * cc-guess.el: Use term `offset' instead of `delta'.
        Temorary don't use the term `style'. Instead use term
        `basic-offset' or `offset-alist'.
        (cc-guess-offset-threshold): Renamed from `cc-guess-delta-threshold'.
        (cc-guess-accumulate-offset): Renamed from `cc-guess-accumulate-delta'.
        (cc-guess-guessed-style): Removed.
        (cc-guess-make-offsets-alist): Renamed from `cc-guess-make-style'.
        (cc-guess-merge-offsets-alists): Renamed from `cc-guess-merge-styles'.
        (cc-guess-make-basic-offset): New function.
        (cc-guess-guessed-offsets-alist): New variable.
        (cc-guess-guessed-basic-offset): New variable.
        (cc-guess-view-accumulator): New function for debugging.
        (cc-guess-reset-accumulator): New function.
        (cc-guess-view-offsets-alist): Renamed from `cc-guess-view-style'.

2011-01-13  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-region-max): New option.
        (cc-guess-buffer): New function.
        (cc-guess): Limit the region for examining indentation
        by `cc-guess-region-max'.

2011-01-13  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-accumulate): New function.
        (cc-guess-region): Use `cc-guess-accumulate'.

2011-01-13  Masatake YAMATO  <address@hidden>

        * cc-guess.el: s/delta-accumulator/accumulator/g.

2011-01-13  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-empty-line-p): New subroutine.
        (cc-guess-region): Handle multiple symbols returned from
        `c-guess-basic-syntax'. Use `cc-guess-empty-line-p'.

2011-01-13  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-guessed-style): Renamed from
        `cc-guessed-style'.

2011-01-13  Masatake YAMATO  <address@hidden>

        * cc-guess.el (cc-guess-delta-threshold): New option.
        (cc-guess-current-delta): New function derived from
        `cc-guess-region'.
        (cc-guess-region): Don't accumulate a sampled indentation if
        it is greater than `cc-guess-delta-threshold'.


Local Variables:
mode: change-log
End:


The patch:

diff --git a/Makefile b/Makefile
index 0730662..694d459 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ ELISPFILES=\
  cc-defs.el \
  cc-engine.el \
  cc-fonts.el \
+ cc-guess.el \
  cc-langs.el \
  cc-menus.el \
  cc-mode.el \
@@ -26,7 +27,6 @@ EXTRAFILES=\
  MANIFEST \
  README \
  COPYING \
- cc-guess.el \
  cc-lobotomy.el \
  cc-fix.el
 
diff --git a/cc-guess.el b/cc-guess.el
index 55c36c7..9891829 100644
--- a/cc-guess.el
+++ b/cc-guess.el
@@ -15,12 +15,12 @@
 ;; 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,
@@ -29,12 +29,41 @@
 ;;; 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!
+;; particular region/buffer.  Here style means `offsets-alist' and
+;; `basic-offset'.
+;;
+;; The main entry point of this program is `cc-guess' command but there
+;; are some variants.
+;;
+;; Consider the major mode for the current buffer is one of the modes
+;; provided by cc-mode. `cc-guess' guesses the indentation style by
+;; examining the indentation in a region which started from buffer
+;; beginning to the point limited by `cc-guess-offset-threshold' and
+;; installs the guessed style. The name for installed style is given
+;; by `cc-guess-style-name'.
+;;
+;; `cc-guess-buffer' does the same but in a whole the buffer.
+;; `cc-guess-region' does the same but in a region between the point
+;; and the mark.
 ;;
-;; 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'.
+;; `cc-guess-no-install', `cc-guess-buffer-no-install'
+;; and `cc-guess-region-no-install' guess the indentation style but
+;; don't install. You can review a guessed style with `cc-guess-view'.
+;; After reviewing use `cc-guess-install' to install the style
+;; if you prefer it.
+;;
+;; If you want to reuse the guessed style in other buffer,
+;; run `c-set-style' command with the name of the guessed style:
+;; "*cc-guess*:<name-of-file-which-examined-when-guessing>".
+;; Once guessed style is installed explicitly with `cc-guess-install'
+;; or implicitly with `cc-guess', `cc-guess-buffer', or `cc-guess-region',
+;; a style name is given by `cc-guess-style-name' with above form.
+;;
+;; If you want to reuse the guessed style in next emacs sessions,
+;; you may want to put it to your .emacs. `cc-guess-view' is for
+;; you. It emits emacs lisp code which defines the last guessed
+;; style on a temporary buffer. You can put the emitted code to
+;; your .emacs. This command is suggested by Alan Mackenzie.
 
 ;;; Code:
 
@@ -48,24 +77,48 @@
 
 (cc-require 'cc-defs)
 (cc-require 'cc-engine)
+(cc-require 'cc-styles)
 
 
-(defvar cc-guessed-style nil
-  "Currently guessed style.")
 
-(defvar cc-guess-delta-accumulator nil)
-;; Accumulated sampled indent information.  Information is represented
+(defcustom cc-guess-offset-threshold 10
+  "Threshold of acceptable offset when examining indent information.
+Discard a examined offset if its absolute value is greater than this.
+
+The offset of the a line included in the indent information returned
+by `c-guess-basic-syntax'."
+  :type 'integer
+  :group 'c)
+
+(defcustom cc-guess-region-max 50000
+  "The maximum point of region for examining indent information with 
`cc-guess'.
+It takes long time for examining indent information from large region.
+This option helps you limit the examining time. `nil' means no limit."
+  :type 'integer
+  :group 'c)
+
+
+;;;###autoload
+(defvar cc-guess-guessed-offsets-alist nil
+  "Currently guessed offsets-alist. Buffer local.")
+;;;###autoload
+(defvar cc-guess-guessed-basic-offset nil
+  "Currently guessed basic-offset. Buffer local.")
+
+(defvar cc-guess-accumulator nil)
+;; Accumulated examined 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
+;;
+;; (syntactic-symbol ((indentation-offset1 . number-of-times1)
+;;                    (indentation-offset2 . number-of-times2)
+;;                    ...))
+;;
+;; This structure is built by `cc-guess-accumulate-offset'.
+;;
+;; Here we call the pair (indentation-offset1 . number-of-times1) a
+;; counter.  `cc-guess-sort-accumulator' sorts the order of
 ;; counters by number-of-times.
+;; Use `cc-guess-dump-accumulator' to see the value.
 
 (defconst cc-guess-conversions
   '((c . c-lineup-C-comments)
@@ -75,131 +128,194 @@
     (arglist-cont-nonempty . c-lineup-arglist)
     (arglist-close . c-lineup-close-paren)
     (cpp-macro . -1000)))
-  
 
+
+;;;###autoload
 (defun cc-guess (&optional accumulate)
-  "Apply `cc-guess-region' on the whole current buffer.
+  "Apply `cc-guess-region' on the region limited by `cc-guess-region-max'.
 
 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))
+  (cc-guess-region (point-min)
+                  (min (point-max) (or cc-guess-region-max
+                                       (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)))
+;;;###autoload
+(defun cc-guess-no-install (&optional accumulate)
+  "Apply `cc-guess-region-no-install' on the region limited by 
`cc-guess-region-max'.
+
+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-no-install (point-min)
+                             (min (point-max) (or cc-guess-region-max
+                                                  (point-max)))
+                             accumulate))
+
+;;;###autoload
+(defun cc-guess-buffer (&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))
+
+;;;###autoload
+(defun cc-guess-buffer-no-install (&optional accumulate)
+  "Apply `cc-guess-region-no-install' 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-no-install (point-min)
+                             (point-max)
+                             accumulate))
+
+;;;###autoload
 (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.
+  "Call `cc-guess-region-no-install' and install the guessed style."
+  (interactive "r\nP")
+  (cc-guess-region-no-install start end accumulate)
+  (cc-guess-install))
+
+
+(defsubst cc-guess-empty-line-p ()
+  (eq (line-beginning-position)
+      (line-end-position)))
 
-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'.
+;;;###autoload
+(defun cc-guess-region-no-install (start end &optional accumulate)
+  "Guess the indentation style by examining the indentation in a region of 
code.
+Every line of code in the region is examined and the values for following
+two variabels are guessed:
+
+* `c-basic-offset', and
+* the indentation values of the various syntactic symbols in
+  `c-offsets-alist'.
+
+The guessed values are put into `cc-guess-guessed-basic-offset' and
+`cc-guess-guessed-offsets-alist'.
+
+Frequencies of use are taken into account when guessing, so minor
+inconsistencies in the indentation style shouldn't produce wrong guesses.
 
 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.
+non-nil) then the previous examination is extended, otherwise a new
+guess is made from scratch.
 
-Note that the larger the region to guess in, the slower the guessing."
+Note that the larger the region to guess in, the slower the guessing.
+So you can limit the region with `cc-guess-region-max'."
   (interactive "r\nP")
-  (let ((delta-accumulator (when accumulate cc-guess-delta-accumulator))
+  ;;
+  ;; Examining stage
+  ;;
+  (let ((accumulator (when accumulate cc-guess-accumulator))
        (reporter (when (fboundp 'make-progress-reporter)
-                   (make-progress-reporter "Sampling Indentation " start 
end))))
-    ;;
-    ;; Sampling stage
-    ;;
+                   (make-progress-reporter "Examining Indentation "
+                                           start
+                                           end))))
     (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)))))))
+       (unless (cc-guess-empty-line-p)
+         (mapc (lambda (s)
+                 (setq accumulator (or (cc-guess-accumulate accumulator s)
+                                       accumulator)))
+               (c-save-buffer-state () (c-guess-basic-syntax))))
        (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.
+    (setq cc-guess-accumulator (cc-guess-sort-accumulator accumulator)))
+  ;;
+  ;; Guessing stage
+  ;;
+  (let* ((basic-offset (cc-guess-make-basic-offset cc-guess-accumulator))
+        (typical-offsets-alist (cc-guess-make-offsets-alist
+                                cc-guess-accumulator))
+        (symbolic-offsets-alist (cc-guess-symbolize-offsets-alist
+                                 typical-offsets-alist
+                                 basic-offset))
+        (merged-offsets-alist (cc-guess-merge-offsets-alists
+                               (copy-tree cc-guess-conversions)
+                               symbolic-offsets-alist)))
+    (set (make-local-variable 'cc-guess-guessed-basic-offset)
+        basic-offset)
+    (set (make-local-variable 'cc-guess-guessed-offsets-alist)
+        merged-offsets-alist))
+  )
+
+(defun cc-guess-current-offset (relpos)
+  ;; Calculate relative indentation (point) to RELPOS.
+  (- (progn (back-to-indentation)
+           (current-column))
+     (save-excursion
+       (goto-char relpos)
+       (current-column))))
+
+(defun cc-guess-accumulate (accumulator syntax-element)
+  ;; Added SYNTAX-ELEMENT to ACCUMULATOR.
+  (let ((symbol (car syntax-element))
+       (relpos (cadr syntax-element)))
+    (when (numberp relpos)
+      (let ((offset (cc-guess-current-offset relpos)))
+       (when (< (abs offset) cc-guess-offset-threshold)
+         (cc-guess-accumulate-offset accumulator
+                                     symbol
+                                     offset))))))
+
+(defun cc-guess-accumulate-offset (accumulator symbol offset)
+  ;; Added SYMBOL and OFFSET to ACCUMULATOR.  See
+  ;; `cc-guess-accumulator' about the structure of ACCUMULATOR.
   (let* ((entry    (assoc symbol accumulator))
         (counters (cdr entry))
         counter)
     (if entry
        (progn
-         (setq counter (assoc delta counters))
+         (setq counter (assoc offset counters))
          (if counter
              (setcdr counter (1+ (cdr counter)))
-           (setq counters (cons (cons delta 1) counters))
+           (setq counters (cons (cons offset 1) counters))
            (setcdr entry counters))
          accumulator)
-      (cons (cons symbol (cons (cons delta 1) nil)) accumulator))))
+      (cons (cons symbol (cons (cons offset 1) nil)) accumulator))))
 
-(defun cc-guess-sort-delta-accumulator (accumulator)
+(defun cc-guess-sort-accumulator (accumulator)
   ;; Sort the each element of ACCUMULATOR by the number-of-times.  See
-  ;; `cc-guess-delta-accumulator' for more details.
+  ;; `cc-guess-accumulator' for more details.
   (mapcar
    (lambda (entry)
      (let ((symbol (car entry))
           (counters (cdr entry)))
-       (cons symbol (sort counters 
+       (cons symbol (sort counters
                          (lambda (a b)
                            (if (> (cdr a) (cdr b))
                                t
-                             (and 
+                             (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 
+
+(defun cc-guess-make-offsets-alist (accumulator)
+  ;; Throw away the rare cases in accumulator
+  ;; and make a offsets-alist structure.
+  (mapcar
    (lambda (entry)
-     (cons (car 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
+(defun cc-guess-merge-offsets-alists (strong weak)
+  ;; Merge two offsets-alists into one.
+  ;; When two offsets-alists have the same symbol
   ;; entry, give STRONG priority over WEAK.
   (mapc
    (lambda (weak-elt)
@@ -208,11 +324,184 @@ Note that the larger the region to guess in, the slower 
the guessing."
    weak)
   strong)
 
-(defun cc-guess-view-style ()
-  "Show `cc-guessed-style'."
+(defun cc-guess-make-basic-offset (accumulator)
+  ;; As `basic-offset' find the most frequently appeared indentation-offset
+  ;; from ACCUMULATOR.
+  (let* (;; Drop the value related to `c' syntactic-symbol.
+        ;; (`c': Inside a multiline C style block comment.)
+        ;; The impact for values of `c' is too large for guessing
+        ;; `basic-offset' if the target source file is small and its license
+        ;; notice is at top of the file.
+        (accumulator (assq-delete-all 'c (copy-tree accumulator)))
+        ;; Drop syntactic-symbols from ACCUMULATOR.
+        (alist (apply #'append (mapcar (lambda (elts)
+                                         (mapcar (lambda (elt)
+                                                   (cons (abs (car elt))
+                                                         (cdr elt)))
+                                                 (cdr elts)))
+                                       accumulator)))
+        ;; Gather all indentation-offsets other than 0.
+        ;; 0 is meaningless as `basic-offset'.
+        (offset-list (delete 0
+                             (delete-dups (mapcar
+                                           (lambda (elt) (car elt))
+                                           alist))))
+        ;; Sum of number-of-times for offset:
+        ;;  (offset . sum)
+        (summed (mapcar (lambda (offset)
+                          (cons offset
+                                (apply #'+
+                                       (mapcar (lambda (a)
+                                                 (if (eq (car a) offset)
+                                                     (cdr a)
+                                                   0))
+                                               alist))))
+                        offset-list)))
+    ;;
+    ;; Find the majority.
+    ;;
+    (let ((majority '(nil . 0)))
+      (while summed
+       (when (< (cdr majority) (cdr (car summed)))
+         (setq majority (car summed)))
+       (setq summed (cdr summed)))
+      (car majority))))
+
+(defun cc-guess-symbolize-offsets-alist (offsets-alist basic-offset)
+  ;; Convert the representation of OFFSETS-ALIST to an alist using
+  ;; `+', `-', `++', `--', `*', or `/'. These symbols represents
+  ;; a value relative to BASIC-OFFSET. See info of CC mode about
+  ;; the detail of the symbols.
+  (mapcar
+   (lambda (elt)
+     (let ((s (car elt))
+          (v (cdr elt)))
+       (cond
+       ((integerp v)
+        (cons s (cc-guess-symbolize-integer v
+                                            basic-offset)))
+       (t elt))))
+   offsets-alist))
+
+(defun cc-guess-symbolize-integer (int basic-offset)
+  (let ((aint (abs int)))
+    (cond
+     ((eq int basic-offset) '+)
+     ((eq aint basic-offset) '-)
+     ((eq int (* 2 basic-offset)) '++)
+     ((eq aint (* 2 basic-offset)) '--)
+     ((eq (* 2 int) basic-offset) '*)
+     ((eq (* 2 aint) basic-offset) '-)
+     (t int))))
+
+(defun cc-guess-style-name-p (name)
+  "Return t if NAME is name of a style created by cc-guess."
+  (string-prefix-p "*cc-guess*:" name))
+(defun cc-guess-style-name ()
+  ;; Make a style name for the guessed style.
+  (format "*cc-guess*:%s" (buffer-file-name)))
+
+(defun cc-guess-make-style ()
+  ;; Make a style from guessed values.
+  (when cc-guess-guessed-offsets-alist
+    (let*      ((basic-offset cc-guess-guessed-basic-offset)
+                (offsets-alist (cc-guess-merge-offsets-alists
+                                cc-guess-guessed-offsets-alist
+                                c-offsets-alist)))
+      `((c-basic-offset . ,basic-offset)
+       (c-offsets-alist . ,offsets-alist)))))
+
+;;;###autoload
+(defun cc-guess-install ()
+  "Define the indentation style from the last guessed values and use it.
+Here guessed values mean `cc-guess-guessed-basic-offset' and
+`cc-guess-guessed-offsets-alist'.
+
+When defining the style from `cc-guess-guessed-offsets-alist',
+`c-offsets-alist' is also merged into the style.  However,
+`cc-guess-guessed-offsets-alist' takes precedence over
+`c-offsets-alist'.
+
+The style name is given by `cc-guess-style-name'."
+  (interactive)
+  (let ((style (cc-guess-make-style)))
+    (if style
+       (let ((style-name (cc-guess-style-name)))
+         (c-add-style style-name style t)
+         (message "Style \"%s\" is installed" style-name))
+      (error "Not yet guessed"))))
+
+(defun cc-guess-dump-accumulator ()
+  "Show `cc-guess-accumulator'."
   (interactive)
-  (with-output-to-temp-buffer "*Indentation Guessing Result*"
-    (pp cc-guessed-style)))
+  (with-output-to-temp-buffer "*Accumulated Examined Indent Information*"
+    (pp cc-guess-accumulator)))
+
+(defun cc-guess-reset-accumulator ()
+  "Reset `cc-guess-accumulator'."
+  (interactive)
+  (setq cc-guess-accumulator nil))
+
+(defun cc-guess-dump-guessed-values ()
+  "Show `cc-guess-guessed-basic-offset' and `cc-guess-guessed-offsets-alist'."
+  (interactive)
+  (with-output-to-temp-buffer "*Guessed Values*"
+    (princ "basic-offset: \n\t")
+    (pp cc-guess-guessed-basic-offset)
+    (princ "\n\n")
+    (princ "offsets-alist: \n")
+    (pp cc-guess-guessed-offsets-alist)
+    ))
+
+(defun cc-guess-dump-guessed-style (&optional printer)
+  "Show the guessed style.
+`pp' is used to print the style but if PRINTER is given,
+PRINTER is used instead. If PRINTER is not `nil', it
+is called with one argument, the guessed style."
+  (interactive)
+  (let ((style (cc-guess-make-style)))
+    (if style
+       (with-output-to-temp-buffer "*Guessed Style*"
+         (funcall (if printer printer 'pp) style))
+      (error "Not yet guessed"))))
+
+(defun cc-guess-view (&optional with-name)
+  "Emit emacs lisp code which defines the last guessed style.
+So you can put the code into .emacs if you prefer the
+guessed code.
+\"STYLE NAME HERE\" is used as the name for the style in the
+emitted code. If WITH-NAME is given, it is used instead.
+WITH-NAME is expected as a string but if this function
+called interactively with prefix argument, the value for
+WITH-NAME is asked to the user."
+  (interactive "P")
+  (let* ((temporary-style-name (cond
+                               ((stringp with-name) with-name)
+                               (with-name (read-from-minibuffer
+                                           "Style name: "))
+                               (t
+                                "STYLE NAME HERE")))
+        (guessed-style-name (cc-guess-style-name))
+        (current-style-name c-indentation-style)
+        (parent-style-name (if (string-equal guessed-style-name
+                                             current-style-name)
+                               ;; The guessed style is already installed.
+                               ;; It cannot be used as the parent style.
+                               ;; Use the default style for the current
+                               ;; major mode as the parent style.
+                               (cc-choose-style-for-mode
+                                major-mode
+                                c-default-style)
+                             ;; The guessed style is not installed yet.
+                             current-style-name)))
+    (cc-guess-dump-guessed-style
+     (lambda (style)
+       (pp `(c-add-style ,temporary-style-name
+                        ',(cons parent-style-name
+                                style)))
+       (with-current-buffer standard-output
+        (lisp-interaction-mode))
+       ))))
 
 
 (cc-provide 'cc-guess)
diff --git a/cc-langs.el b/cc-langs.el
index 0cf6131..0b92ab6 100644
--- a/cc-langs.el
+++ b/cc-langs.el
@@ -287,6 +287,19 @@ the evaluated constant value at compile time."
            ["Backslashify"           c-backslash-region
             (c-fn-region-is-active-p)]))
       "----"
+      ("Style..."
+       ["Set Style..."                   c-set-style t]
+       ["Show Current Style Name"        (message
+                                         "Style Name: %s"
+                                         c-indentation-style) t]
+       ["Guess Style from this Buffer"   cc-guess-buffer-no-install t]
+       ["Install the Last Guessed Style" cc-guess-install
+       (and cc-guess-guessed-offsets-alist
+            cc-guess-guessed-basic-offset) ]
+       ["View the Last Guessed Style"    cc-guess-view
+       (and cc-guess-guessed-offsets-alist
+            cc-guess-guessed-basic-offset) ])
+      "----"
       ("Toggle..."
        ["Syntactic indentation" c-toggle-syntactic-indentation t]
        ["Electric mode"                c-toggle-electric-state t]
diff --git a/cc-mode.el b/cc-mode.el
index fe35f28..6b59e6e 100644
--- a/cc-mode.el
+++ b/cc-mode.el
@@ -92,6 +92,7 @@
 (cc-require 'cc-cmds)
 (cc-require 'cc-align)
 (cc-require 'cc-menus)
+(cc-require 'cc-guess)
 
 ;; Silence the compiler.
 (cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
@@ -563,11 +564,7 @@ that requires a literal mode spec at compile time."
   (c-clear-found-types)
 
   ;; now set the mode style based on default-style
-  (let ((style (if (stringp default-style)
-                  default-style
-                (or (cdr (assq mode default-style))
-                    (cdr (assq 'other default-style))
-                    "gnu"))))
+  (let ((style (cc-choose-style-for-mode mode default-style)))
     ;; Override style variables if `c-old-style-variable-behavior' is
     ;; set.  Also override if we are using global style variables,
     ;; have already initialized a style once, and are switching to a
diff --git a/cc-styles.el b/cc-styles.el
index 18f0afa..6c3218b 100644
--- a/cc-styles.el
+++ b/cc-styles.el
@@ -655,6 +655,15 @@ any reason to call this function directly."
       (setq c-style-variables-are-local-p t))
     ))
 
+(defun cc-choose-style-for-mode (mode default-style)
+  "Return suitable style for MODE from DEFAULT-STYLE.
+DEFAULT-STYLE has the same format as `c-default-style'."
+  (if (stringp default-style)
+      default-style
+    (or (cdr (assq mode default-style))
+       (cdr (assq 'other default-style))
+       "gnu")))
+
 
 
 (cc-provide 'cc-styles)
;;; cc-guess.el --- guess indentation values by scanning existing code

;; Copyright (C) 1985,1987,1992-2003, 2004, 2005, 2006 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.  Here style means `offsets-alist' and
;; `basic-offset'.
;;
;; The main entry point of this program is `cc-guess' command but there
;; are some variants.
;;
;; Consider the major mode for the current buffer is one of the modes
;; provided by cc-mode. `cc-guess' guesses the indentation style by
;; examining the indentation in a region which started from buffer
;; beginning to the point limited by `cc-guess-offset-threshold' and
;; installs the guessed style. The name for installed style is given
;; by `cc-guess-style-name'.
;;
;; `cc-guess-buffer' does the same but in a whole the buffer.
;; `cc-guess-region' does the same but in a region between the point
;; and the mark.
;;
;; `cc-guess-no-install', `cc-guess-buffer-no-install'
;; and `cc-guess-region-no-install' guess the indentation style but
;; don't install. You can review a guessed style with `cc-guess-view'.
;; After reviewing use `cc-guess-install' to install the style
;; if you prefer it.
;;
;; If you want to reuse the guessed style in other buffer,
;; run `c-set-style' command with the name of the guessed style:
;; "*cc-guess*:<name-of-file-which-examined-when-guessing>".
;; Once guessed style is installed explicitly with `cc-guess-install'
;; or implicitly with `cc-guess', `cc-guess-buffer', or `cc-guess-region',
;; a style name is given by `cc-guess-style-name' with above form.
;;
;; If you want to reuse the guessed style in next emacs sessions,
;; you may want to put it to your .emacs. `cc-guess-view' is for
;; you. It emits emacs lisp code which defines the last guessed
;; style on a temporary buffer. You can put the emitted code to
;; your .emacs. This command is suggested by Alan Mackenzie.

;;; 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)
(cc-require 'cc-styles)



(defcustom cc-guess-offset-threshold 10
  "Threshold of acceptable offset when examining indent information.
Discard a examined offset if its absolute value is greater than this.

The offset of the a line included in the indent information returned
by `c-guess-basic-syntax'."
  :type 'integer
  :group 'c)

(defcustom cc-guess-region-max 50000
  "The maximum point of region for examining indent information with `cc-guess'.
It takes long time for examining indent information from large region.
This option helps you limit the examining time. `nil' means no limit."
  :type 'integer
  :group 'c)


;;;###autoload
(defvar cc-guess-guessed-offsets-alist nil
  "Currently guessed offsets-alist. Buffer local.")
;;;###autoload
(defvar cc-guess-guessed-basic-offset nil
  "Currently guessed basic-offset. Buffer local.")

(defvar cc-guess-accumulator nil)
;; Accumulated examined indent information.  Information is represented
;; in a list.  Each element in it has following structure:
;;
;; (syntactic-symbol ((indentation-offset1 . number-of-times1)
;;                     (indentation-offset2 . number-of-times2)
;;                     ...))
;;
;; This structure is built by `cc-guess-accumulate-offset'.
;;
;; Here we call the pair (indentation-offset1 . number-of-times1) a
;; counter.  `cc-guess-sort-accumulator' sorts the order of
;; counters by number-of-times.
;; Use `cc-guess-dump-accumulator' to see the value.

(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)))


;;;###autoload
(defun cc-guess (&optional accumulate)
  "Apply `cc-guess-region' on the region limited by `cc-guess-region-max'.

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)
                   (min (point-max) (or cc-guess-region-max
                                        (point-max)))
                   accumulate))

;;;###autoload
(defun cc-guess-no-install (&optional accumulate)
  "Apply `cc-guess-region-no-install' on the region limited by 
`cc-guess-region-max'.

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-no-install (point-min)
                              (min (point-max) (or cc-guess-region-max
                                                   (point-max)))
                              accumulate))

;;;###autoload
(defun cc-guess-buffer (&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))

;;;###autoload
(defun cc-guess-buffer-no-install (&optional accumulate)
  "Apply `cc-guess-region-no-install' 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-no-install (point-min)
                              (point-max)
                              accumulate))

;;;###autoload
(defun cc-guess-region (start end &optional accumulate)
  "Call `cc-guess-region-no-install' and install the guessed style."
  (interactive "r\nP")
  (cc-guess-region-no-install start end accumulate)
  (cc-guess-install))


(defsubst cc-guess-empty-line-p ()
  (eq (line-beginning-position)
      (line-end-position)))

;;;###autoload
(defun cc-guess-region-no-install (start end &optional accumulate)
  "Guess the indentation style by examining the indentation in a region of code.
Every line of code in the region is examined and the values for following
two variabels are guessed:

* `c-basic-offset', and
* the indentation values of the various syntactic symbols in
  `c-offsets-alist'.

The guessed values are put into `cc-guess-guessed-basic-offset' and
`cc-guess-guessed-offsets-alist'.

Frequencies of use are taken into account when guessing, so minor
inconsistencies in the indentation style shouldn't produce wrong guesses.

If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous examination is extended, otherwise a new
guess is made from scratch.

Note that the larger the region to guess in, the slower the guessing.
So you can limit the region with `cc-guess-region-max'."
  (interactive "r\nP")
  ;;
  ;; Examining stage
  ;;
  (let ((accumulator (when accumulate cc-guess-accumulator))
        (reporter (when (fboundp 'make-progress-reporter)
                    (make-progress-reporter "Examining Indentation "
                                            start
                                            end))))
    (save-excursion
      (goto-char start)
      (while (< (point) end)
        (unless (cc-guess-empty-line-p)
          (mapc (lambda (s)
                  (setq accumulator (or (cc-guess-accumulate accumulator s)
                                        accumulator)))
                (c-save-buffer-state () (c-guess-basic-syntax))))
        (when reporter (progress-reporter-update reporter (point)))
        (forward-line 1)))
    (when reporter (progress-reporter-done reporter))
    (setq cc-guess-accumulator (cc-guess-sort-accumulator accumulator)))
  ;;
  ;; Guessing stage
  ;;
  (let* ((basic-offset (cc-guess-make-basic-offset cc-guess-accumulator))
         (typical-offsets-alist (cc-guess-make-offsets-alist
                                 cc-guess-accumulator))
         (symbolic-offsets-alist (cc-guess-symbolize-offsets-alist
                                  typical-offsets-alist
                                  basic-offset))
         (merged-offsets-alist (cc-guess-merge-offsets-alists
                                (copy-tree cc-guess-conversions)
                                symbolic-offsets-alist)))
    (set (make-local-variable 'cc-guess-guessed-basic-offset)
         basic-offset)
    (set (make-local-variable 'cc-guess-guessed-offsets-alist)
         merged-offsets-alist))
  )

(defun cc-guess-current-offset (relpos)
  ;; Calculate relative indentation (point) to RELPOS.
  (- (progn (back-to-indentation)
            (current-column))
     (save-excursion
       (goto-char relpos)
       (current-column))))

(defun cc-guess-accumulate (accumulator syntax-element)
  ;; Added SYNTAX-ELEMENT to ACCUMULATOR.
  (let ((symbol (car syntax-element))
        (relpos (cadr syntax-element)))
    (when (numberp relpos)
      (let ((offset (cc-guess-current-offset relpos)))
        (when (< (abs offset) cc-guess-offset-threshold)
          (cc-guess-accumulate-offset accumulator
                                      symbol
                                      offset))))))

(defun cc-guess-accumulate-offset (accumulator symbol offset)
  ;; Added SYMBOL and OFFSET to ACCUMULATOR.  See
  ;; `cc-guess-accumulator' about the structure of ACCUMULATOR.
  (let* ((entry    (assoc symbol accumulator))
         (counters (cdr entry))
         counter)
    (if entry
        (progn
          (setq counter (assoc offset counters))
          (if counter
              (setcdr counter (1+ (cdr counter)))
            (setq counters (cons (cons offset 1) counters))
            (setcdr entry counters))
          accumulator)
      (cons (cons symbol (cons (cons offset 1) nil)) accumulator))))

(defun cc-guess-sort-accumulator (accumulator)
  ;; Sort the each element of ACCUMULATOR by the number-of-times.  See
  ;; `cc-guess-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-offsets-alist (accumulator)
  ;; Throw away the rare cases in accumulator
  ;; and make a offsets-alist structure.
  (mapcar
   (lambda (entry)
     (cons (car entry)
           (car (car (cdr entry)))))
   accumulator))

(defun cc-guess-merge-offsets-alists (strong weak)
  ;; Merge two offsets-alists into one.
  ;; When two offsets-alists have 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-make-basic-offset (accumulator)
  ;; As `basic-offset' find the most frequently appeared indentation-offset
  ;; from ACCUMULATOR.
  (let* (;; Drop the value related to `c' syntactic-symbol.
         ;; (`c': Inside a multiline C style block comment.)
         ;; The impact for values of `c' is too large for guessing
         ;; `basic-offset' if the target source file is small and its license
         ;; notice is at top of the file.
         (accumulator (assq-delete-all 'c (copy-tree accumulator)))
         ;; Drop syntactic-symbols from ACCUMULATOR.
         (alist (apply #'append (mapcar (lambda (elts)
                                          (mapcar (lambda (elt)
                                                    (cons (abs (car elt))
                                                          (cdr elt)))
                                                  (cdr elts)))
                                        accumulator)))
         ;; Gather all indentation-offsets other than 0.
         ;; 0 is meaningless as `basic-offset'.
         (offset-list (delete 0
                              (delete-dups (mapcar
                                            (lambda (elt) (car elt))
                                            alist))))
         ;; Sum of number-of-times for offset:
         ;;  (offset . sum)
         (summed (mapcar (lambda (offset)
                           (cons offset
                                 (apply #'+
                                        (mapcar (lambda (a)
                                                  (if (eq (car a) offset)
                                                      (cdr a)
                                                    0))
                                                alist))))
                         offset-list)))
    ;;
    ;; Find the majority.
    ;;
    (let ((majority '(nil . 0)))
      (while summed
        (when (< (cdr majority) (cdr (car summed)))
          (setq majority (car summed)))
        (setq summed (cdr summed)))
      (car majority))))

(defun cc-guess-symbolize-offsets-alist (offsets-alist basic-offset)
  ;; Convert the representation of OFFSETS-ALIST to an alist using
  ;; `+', `-', `++', `--', `*', or `/'. These symbols represents
  ;; a value relative to BASIC-OFFSET. See info of CC mode about
  ;; the detail of the symbols.
  (mapcar
   (lambda (elt)
     (let ((s (car elt))
           (v (cdr elt)))
       (cond
        ((integerp v)
         (cons s (cc-guess-symbolize-integer v
                                             basic-offset)))
        (t elt))))
   offsets-alist))

(defun cc-guess-symbolize-integer (int basic-offset)
  (let ((aint (abs int)))
    (cond
     ((eq int basic-offset) '+)
     ((eq aint basic-offset) '-)
     ((eq int (* 2 basic-offset)) '++)
     ((eq aint (* 2 basic-offset)) '--)
     ((eq (* 2 int) basic-offset) '*)
     ((eq (* 2 aint) basic-offset) '-)
     (t int))))

(defun cc-guess-style-name-p (name)
  "Return t if NAME is name of a style created by cc-guess."
  (string-prefix-p "*cc-guess*:" name))
(defun cc-guess-style-name ()
  ;; Make a style name for the guessed style.
  (format "*cc-guess*:%s" (buffer-file-name)))

(defun cc-guess-make-style ()
  ;; Make a style from guessed values.
  (when cc-guess-guessed-offsets-alist
    (let*       ((basic-offset cc-guess-guessed-basic-offset)
                 (offsets-alist (cc-guess-merge-offsets-alists
                                 cc-guess-guessed-offsets-alist
                                 c-offsets-alist)))
      `((c-basic-offset . ,basic-offset)
        (c-offsets-alist . ,offsets-alist)))))

;;;###autoload
(defun cc-guess-install ()
  "Define the indentation style from the last guessed values and use it.
Here guessed values mean `cc-guess-guessed-basic-offset' and
`cc-guess-guessed-offsets-alist'.

When defining the style from `cc-guess-guessed-offsets-alist',
`c-offsets-alist' is also merged into the style.  However,
`cc-guess-guessed-offsets-alist' takes precedence over
`c-offsets-alist'.

The style name is given by `cc-guess-style-name'."
  (interactive)
  (let ((style (cc-guess-make-style)))
    (if style
        (let ((style-name (cc-guess-style-name)))
          (c-add-style style-name style t)
          (message "Style \"%s\" is installed" style-name))
      (error "Not yet guessed"))))

(defun cc-guess-dump-accumulator ()
  "Show `cc-guess-accumulator'."
  (interactive)
  (with-output-to-temp-buffer "*Accumulated Examined Indent Information*"
    (pp cc-guess-accumulator)))

(defun cc-guess-reset-accumulator ()
  "Reset `cc-guess-accumulator'."
  (interactive)
  (setq cc-guess-accumulator nil))

(defun cc-guess-dump-guessed-values ()
  "Show `cc-guess-guessed-basic-offset' and `cc-guess-guessed-offsets-alist'."
  (interactive)
  (with-output-to-temp-buffer "*Guessed Values*"
    (princ "basic-offset: \n\t")
    (pp cc-guess-guessed-basic-offset)
    (princ "\n\n")
    (princ "offsets-alist: \n")
    (pp cc-guess-guessed-offsets-alist)
    ))

(defun cc-guess-dump-guessed-style (&optional printer)
  "Show the guessed style.
`pp' is used to print the style but if PRINTER is given,
PRINTER is used instead. If PRINTER is not `nil', it
is called with one argument, the guessed style."
  (interactive)
  (let ((style (cc-guess-make-style)))
    (if style
        (with-output-to-temp-buffer "*Guessed Style*"
          (funcall (if printer printer 'pp) style))
      (error "Not yet guessed"))))

(defun cc-guess-view (&optional with-name)
  "Emit emacs lisp code which defines the last guessed style.
So you can put the code into .emacs if you prefer the
guessed code.
\"STYLE NAME HERE\" is used as the name for the style in the
emitted code. If WITH-NAME is given, it is used instead.
WITH-NAME is expected as a string but if this function
called interactively with prefix argument, the value for
WITH-NAME is asked to the user."
  (interactive "P")
  (let* ((temporary-style-name (cond
                                ((stringp with-name) with-name)
                                (with-name (read-from-minibuffer
                                            "Style name: "))
                                (t
                                 "STYLE NAME HERE")))
         (guessed-style-name (cc-guess-style-name))
         (current-style-name c-indentation-style)
         (parent-style-name (if (string-equal guessed-style-name
                                              current-style-name)
                                ;; The guessed style is already installed.
                                ;; It cannot be used as the parent style.
                                ;; Use the default style for the current
                                ;; major mode as the parent style.
                                (cc-choose-style-for-mode
                                 major-mode
                                 c-default-style)
                              ;; The guessed style is not installed yet.
                              current-style-name)))
    (cc-guess-dump-guessed-style
     (lambda (style)
       (pp `(c-add-style ,temporary-style-name
                         ',(cons parent-style-name
                                 style)))
       (with-current-buffer standard-output
         (lisp-interaction-mode))
       ))))


(cc-provide 'cc-guess)
;;; cc-guess.el ends here

reply via email to

[Prev in Thread] Current Thread [Next in Thread]