123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577 |
- (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 c-guess-offset-threshold 10
- "Threshold of acceptable offsets when examining indent information.
- Discard an examined offset if its absolute value is greater than this.
- The offset of a line included in the indent information returned by
- `c-guess-basic-syntax'."
- :version "24.1"
- :type 'integer
- :group 'c)
- (defcustom c-guess-region-max 50000
- "The maximum region size for examining indent information with `c-guess'.
- It takes a long time to examine indent information from a large region;
- this option helps you limit that time. `nil' means no limit."
- :version "24.1"
- :type 'integer
- :group 'c)
- (defvar c-guess-guessed-offsets-alist nil
- "Currently guessed offsets-alist.")
- (defvar c-guess-guessed-basic-offset nil
- "Currently guessed basic-offset.")
- (defvar c-guess-accumulator nil)
- (defconst c-guess-conversions
- '((c . c-lineup-C-comments)
- (inher-cont . c-lineup-multi-inher)
- (string . -1000)
- (-intro . c-lineup-comment)
- (arglist-cont-nonempty . c-lineup-arglist)
- (arglist-close . c-lineup-close-paren)
- (cpp-macro . -1000)))
- (defun c-guess (&optional accumulate)
- "Guess the style in the region up to `c-guess-region-max', and install it.
- The style is given a name based on the file's absolute file name.
- 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")
- (c-guess-region (point-min)
- (min (point-max) (or c-guess-region-max
- (point-max)))
- accumulate))
- (defun c-guess-no-install (&optional accumulate)
- "Guess the style in the region up to `c-guess-region-max'; don't install it.
- 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")
- (c-guess-region-no-install (point-min)
- (min (point-max) (or c-guess-region-max
- (point-max)))
- accumulate))
- (defun c-guess-buffer (&optional accumulate)
- "Guess the style on the whole current buffer, and install it.
- The style is given a name based on the file's absolute file name.
- 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")
- (c-guess-region (point-min)
- (point-max)
- accumulate))
- (defun c-guess-buffer-no-install (&optional accumulate)
- "Guess the style on the whole current buffer; don't install it.
- 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")
- (c-guess-region-no-install (point-min)
- (point-max)
- accumulate))
- (defun c-guess-region (start end &optional accumulate)
- "Guess the style on the region and install it.
- The style is given a name based on the file's absolute file name.
- 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 "r\nP")
- (c-guess-region-no-install start end accumulate)
- (c-guess-install))
- (defsubst c-guess-empty-line-p ()
- (eq (line-beginning-position)
- (line-end-position)))
- (defun c-guess-region-no-install (start end &optional accumulate)
- "Guess the style on the region; don't install it.
- Every line of code in the region is examined and values for the following two
- variables are guessed:
- * `c-basic-offset', and
- * the indentation values of the various syntactic symbols in
- `c-offsets-alist'.
- The guessed values are put into `c-guess-guessed-basic-offset' and
- `c-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 `c-guess-region-max'."
- (interactive "r\nP")
- (let ((accumulator (when accumulate c-guess-accumulator)))
- (setq c-guess-accumulator (c-guess-examine start end accumulator))
- (let ((pair (c-guess-guess c-guess-accumulator)))
- (setq c-guess-guessed-basic-offset (car pair)
- c-guess-guessed-offsets-alist (cdr pair)))))
- (defun c-guess-examine (start end accumulator)
- (let ((reporter (when (fboundp 'make-progress-reporter)
- (make-progress-reporter "Examining Indentation "
- start
- end))))
- (save-excursion
- (goto-char start)
- (while (< (point) end)
- (unless (c-guess-empty-line-p)
- (mapc (lambda (s)
- (setq accumulator (or (c-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)))
- (c-guess-sort-accumulator accumulator))
- (defun c-guess-guess (accumulator)
-
-
-
-
- (let* ((basic-offset (c-guess-make-basic-offset accumulator))
- (typical-offsets-alist (c-guess-make-offsets-alist
- accumulator))
- (symbolic-offsets-alist (c-guess-symbolize-offsets-alist
- typical-offsets-alist
- basic-offset))
- (merged-offsets-alist (c-guess-merge-offsets-alists
- (copy-tree c-guess-conversions)
- symbolic-offsets-alist)))
- (cons basic-offset merged-offsets-alist)))
- (defun c-guess-current-offset (relpos)
-
- (- (progn (back-to-indentation)
- (current-column))
- (save-excursion
- (goto-char relpos)
- (current-column))))
- (defun c-guess-accumulate (accumulator syntax-element)
-
- (let ((symbol (car syntax-element))
- (relpos (cadr syntax-element)))
- (when (numberp relpos)
- (let ((offset (c-guess-current-offset relpos)))
- (when (< (abs offset) c-guess-offset-threshold)
- (c-guess-accumulate-offset accumulator
- symbol
- offset))))))
- (defun c-guess-accumulate-offset (accumulator symbol offset)
-
-
- (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 c-guess-sort-accumulator (accumulator)
-
-
- (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 c-guess-make-offsets-alist (accumulator)
-
- (mapcar
- (lambda (entry)
- (cons (car entry)
- (car (car (cdr entry)))))
- accumulator))
- (defun c-guess-merge-offsets-alists (strong weak)
-
-
-
- (mapc
- (lambda (weak-elt)
- (unless (assoc (car weak-elt) strong)
- (setq strong (cons weak-elt strong))))
- weak)
- strong)
- (defun c-guess-make-basic-offset (accumulator)
-
-
- (let* (
-
-
-
-
- (accumulator (assq-delete-all 'c (copy-tree accumulator)))
-
- (alist (apply #'append (mapcar (lambda (elts)
- (mapcar (lambda (elt)
- (cons (abs (car elt))
- (cdr elt)))
- (cdr elts)))
- accumulator)))
-
-
- (offset-list (delete 0
- (delete-dups (mapcar
- (lambda (elt) (car elt))
- alist))))
-
-
- (summed (mapcar (lambda (offset)
- (cons offset
- (apply #'+
- (mapcar (lambda (a)
- (if (eq (car a) offset)
- (cdr a)
- 0))
- alist))))
- offset-list)))
-
-
-
- (let ((majority '(nil . 0)))
- (while summed
- (when (< (cdr majority) (cdr (car summed)))
- (setq majority (car summed)))
- (setq summed (cdr summed)))
- (car majority))))
- (defun c-guess-symbolize-offsets-alist (offsets-alist basic-offset)
-
-
-
-
- (mapcar
- (lambda (elt)
- (let ((s (car elt))
- (v (cdr elt)))
- (cond
- ((integerp v)
- (cons s (c-guess-symbolize-integer v
- basic-offset)))
- (t elt))))
- offsets-alist))
- (defun c-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 c-guess-style-name ()
-
- (format "*c-guess*:%s" (buffer-file-name)))
- (defun c-guess-make-style (basic-offset offsets-alist)
- (when basic-offset
-
- (let* ((offsets-alist (c-guess-merge-offsets-alists
- offsets-alist
- c-offsets-alist)))
- `((c-basic-offset . ,basic-offset)
- (c-offsets-alist . ,offsets-alist)))))
- (defun c-guess-install (&optional style-name)
- "Install the latest guessed style into the current buffer.
- \(This guessed style is a combination of `c-guess-guessed-basic-offset',
- `c-guess-guessed-offsets-alist' and `c-offsets-alist'.)
- The style is entered into CC Mode's style system by
- `c-add-style'. Its name is either STYLE-NAME, or a name based on
- the absolute file name of the file if STYLE-NAME is nil."
- (interactive "sNew style name (empty for default name): ")
- (let* ((style (c-guess-make-style c-guess-guessed-basic-offset
- c-guess-guessed-offsets-alist)))
- (if style
- (let ((style-name (or (if (equal style-name "")
- nil
- style-name)
- (c-guess-style-name))))
- (c-add-style style-name style t)
- (message "Style \"%s\" is installed" style-name))
- (error "Not yet guessed"))))
- (defun c-guess-dump-accumulator ()
- "Show `c-guess-accumulator'."
- (interactive)
- (with-output-to-temp-buffer "*Accumulated Examined Indent Information*"
- (pp c-guess-accumulator)))
- (defun c-guess-reset-accumulator ()
- "Reset `c-guess-accumulator'."
- (interactive)
- (setq c-guess-accumulator nil))
- (defun c-guess-dump-guessed-values ()
- "Show `c-guess-guessed-basic-offset' and `c-guess-guessed-offsets-alist'."
- (interactive)
- (with-output-to-temp-buffer "*Guessed Values*"
- (princ "basic-offset: \n\t")
- (pp c-guess-guessed-basic-offset)
- (princ "\n\n")
- (princ "offsets-alist: \n")
- (pp c-guess-guessed-offsets-alist)
- ))
- (defun c-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 (c-guess-make-style c-guess-guessed-basic-offset
- c-guess-guessed-offsets-alist)))
- (if style
- (with-output-to-temp-buffer "*Guessed Style*"
- (funcall (if printer printer 'pp) style))
- (error "Not yet guessed"))))
- (defun c-guess-guessed-syntactic-symbols ()
-
-
- (let ((alist c-guess-guessed-offsets-alist)
- elt
- (symbols nil))
- (while alist
- (setq elt (car alist)
- alist (cdr alist))
- (unless (assq (car elt) c-guess-conversions)
- (setq symbols (cons (car elt)
- symbols))))
- symbols))
- (defun c-guess-view-reorder-offsets-alist-in-style (style guessed-syntactic-symbols)
-
-
-
- (setq style (copy-tree style))
- (let ((offsets-alist-cell (assq 'c-offsets-alist style))
- (guessed-syntactic-symbols (c-guess-guessed-syntactic-symbols)))
- (setcdr offsets-alist-cell
- (sort (cdr offsets-alist-cell)
- (lambda (a b)
- (let ((a-guessed? (memq (car a) guessed-syntactic-symbols))
- (b-guessed? (memq (car b) guessed-syntactic-symbols)))
- (cond
- ((or (and a-guessed? b-guessed?)
- (not (or a-guessed? b-guessed?)))
- (string-lessp (symbol-name (car a))
- (symbol-name (car b))))
- (a-guessed? t)
- (b-guessed? nil)))))))
- style)
- (defun c-guess-view-mark-guessed-entries (guessed-syntactic-symbols)
-
-
-
- (let ((needs-markers (cons 'c-basic-offset
- guessed-syntactic-symbols)))
- (while needs-markers
- (goto-char (point-min))
- (when (search-forward (concat "("
- (symbol-name (car needs-markers))
- " ") nil t)
- (move-end-of-line 1)
- (-dwim nil)
- (insert " Guessed value"))
- (setq needs-markers
- (cdr needs-markers)))))
- (defun c-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
- "New style name: "))
- (t
- "STYLE NAME HERE")))
- (guessed-style-name (c-guess-style-name))
- (current-style-name c-indentation-style)
- (parent-style-name (if (string-equal guessed-style-name
- current-style-name)
-
-
-
-
- (cc-choose-style-for-mode
- major-mode
- c-default-style)
-
- current-style-name)))
- (c-guess-dump-guessed-style
- (lambda (style)
- (let ((guessed-syntactic-symbols (c-guess-guessed-syntactic-symbols)))
- (pp `(c-add-style ,temporary-style-name
- ',(cons parent-style-name
- (c-guess-view-reorder-offsets-alist-in-style
- style
- guessed-syntactic-symbols))))
- (with-current-buffer standard-output
- (lisp-interaction-mode)
- (c-guess-view-mark-guessed-entries
- guessed-syntactic-symbols)
- (buffer-enable-undo)))))))
- (cc-provide 'cc-guess)
|