From: Masatake Y. <je...@gy...> - 2005-03-09 07:05:45
|
> After writing cc-learn.el, http://www.gyve.org/~jet/ChangeLog, > I've found cc-guess.el in cc-mode CVS repository. > I am surprised that none has worked on such useful feature > after Barry A. Warsaw's work. > > I have merged my effort on cc-learn.el into cc-guess.el. > Comments and docstring are still poor. But I'd like to hear > your comments. > > The weakness of original cc-guess.el is that in some case the original > cc-guess.el guesses clearly wrong indentation if a target c file's not > consistent. > > With my patch, cc-guess.el guesses with taking frequency of > indentation into account. Therefore if the target c file's not > consistent enough, cc-guess.el guesses better indentation than > the original. > > I think it is worth to define a key bind and a menu item for cc-guess. I've updated my patch for cc-guess.el. It seems that my last post was ignored. If you like this patch, give a feedback here. Masatake YAMATO Index: cc-guess.el =================================================================== RCS file: /cvsroot/cc-mode/cc-mode/cc-guess.el,v retrieving revision 5.34 diff -u -r5.34 cc-guess.el --- cc-guess.el 17 Jun 2003 14:01:43 -0000 5.34 +++ cc-guess.el 9 Mar 2005 07:01:47 -0000 @@ -28,7 +28,7 @@ ;;; Commentary: ;; ;; This file contains routines that help guess the cc-mode style in a -;; particular region of C, C++, or Objective-C code. It is provided +;; particular region/buffer of C, C++, or Objective-C code. It is provided ;; for example and experimentation only. It is not supported in ;; anyway. Some folks have asked for a style guesser and the best way ;; to show my thoughts on the subject is with this sample code. Feel @@ -36,7 +36,9 @@ ;; results. 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 to guess the style of, then run the command, `cc-guess-region'. +;; +;; In addition... ;;; Code: @@ -54,6 +56,20 @@ (defvar cc-guessed-style nil "Currently guessed style.") +(defvar cc-guess-delta-accumulator nil + "A variable accumulated sampled indent information. +Information is represented in a list. Each element of +list has following strcture: + + (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.") (defvar cc-guess-conversions '((c . c-lineup-C-comments) @@ -64,51 +80,138 @@ (cpp-macro . -1000))) +(defun cc-guess (&optional accumulate) + "Apply `cc-guess-region' on the whole current buffer; +and set the guessed results to `cc-offsets-alist'. +If optional argument ACCUMULATE is non-nil, use the value +of `cc-guess-delta-accumulator' as the base syntactic information +for guessing." + (interactive "P") + (cc-guess-region (point-min) (point-max) (not accumulate)) + (cc-guess-install)) + +(defun cc-guess-install () + "Set guessed style(`cc-guessed-style') to `c-offsets-alist'" + (interactive) + (message "Set: %S" (pp cc-guessed-style)) + (setq c-offsets-alist cc-guessed-style)) + (defun cc-guess-region (start end &optional reset) "Sets `c-offset-alist' indentation values based on 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' is -guessed. The first such positively identified indentation is used, so +guessed. Frequencies in use is taken into account. Therefore, if an inconsistent style exists in the C code, the guessed indentation -may be incorrect. +may be correct in some case. Note that the larger the region to guess in, the slower the -guessing. Previous guesses can be concatenated together, unless the +guessing. Previous guesses can be take into account, unless the optional RESET is provided. See `cc-guess-write-style' to find out how to save the guessed style, and `cc-guess-view-style' for viewing the guessed style." (interactive "r\nP") - (if (consp reset) - (setq cc-guessed-style nil)) - (save-excursion - (goto-char start) - (while (< (point) end) - (c-save-buffer-state + (let ((delta-accumulator (unless reset 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 (cdr (car syntax))) - (symbol (car (car syntax))) - point-indent relpos-indent) - ;; TBD: for now I can't guess indentation when more than 1 - ;; symbol is on the list, nor for symbols without relpos's - (if (or (/= 1 (length syntax)) - (not (numberp relpos)) - ;; also, don't try to reguess an already guessed - ;; symbol - (assq symbol cc-guessed-style)) - nil - (back-to-indentation) - (setq point-indent (current-column) - relpos-indent (save-excursion - (goto-char relpos) - (current-column))) - ;; guessed indentation is the difference between point's and - ;; relpos's current-column indentation - (setq cc-guessed-style - (cons (cons symbol (- point-indent relpos-indent)) - cc-guessed-style)) - )) - (forward-line 1)))) + (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)))) + +(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) |