Function: smie-config--guess

smie-config--guess is a byte-compiled function defined in smie.el.gz.

Signature

(smie-config--guess BEG END)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/smie.el.gz
(defun smie-config--guess (beg end)
  (let ((otraces (make-hash-table :test #'equal))
        (smie-config--buffer-local nil)
        (smie-config--mode-local nil)
        (pr (make-progress-reporter "Analyzing the buffer" beg end)))

    ;; First, lets get the indentation traces and offsets for the region.
    (save-excursion
      (goto-char beg)
      (forward-line 0)
      (while (< (point) end)
        (skip-chars-forward " \t")
        (unless (eolp)                  ;Skip empty lines.
          (progress-reporter-update pr (point))
          (let* ((itrace (smie-config--get-trace))
                 (nindent (car itrace))
                 (trace (mapcar #'cdr (cdr itrace)))
                 (cur (current-indentation)))
            (when (numberp nindent)     ;Skip `noindent' and friends.
              (incf (gethash (cons (- cur nindent) trace) otraces 0)))))
        (forward-line 1)))
    (progress-reporter-done pr)

    ;; Second, compile the data.  Our algorithm only knows how to adjust rules
    ;; where the smie-rules-function returns an integer.  We call those
    ;; "adjustable sigs".  We build a table mapping each adjustable sig
    ;; to its data, describing the total number of times we encountered it,
    ;; the offsets found, and the traces in which it was found.
    (message "Guessing...")
    (let ((sigs (make-hash-table :test #'equal)))
      (maphash (lambda (otrace count)
                 (let ((offset (car otrace))
                       (trace (cdr otrace))
                       (double nil))
                   (let ((sigs trace))
                     (while sigs
                       (let ((sig (pop sigs)))
                         (if (and (integerp (nth 2 sig)) (member sig sigs))
                             (setq double t)))))
                   (if double
                       ;; Disregard those traces where an adjustable sig
                       ;; appears twice, because the rest of the code assumes
                       ;; that adding a rule to add an offset N will change the
                       ;; end result by N rather than 2*N or more.
                       nil
                     (dolist (sig trace)
                       (if (not (integerp (nth 2 sig)))
                           ;; Disregard those sigs that return nil or a column,
                           ;; because our algorithm doesn't know how to adjust
                           ;; them anyway.
                           nil
                         (let ((sig-data (or (gethash sig sigs)
                                             (let ((data (list 0 nil nil)))
                                               (puthash sig data sigs)
                                               data))))
                           (incf (nth 0 sig-data) count)
                           (push (cons count otrace) (nth 2 sig-data))
                           (let ((sig-off-data
                                  (or (assq offset (nth 1 sig-data))
                                      (let ((off-data (cons offset 0)))
                                        (push off-data (nth 1 sig-data))
                                        off-data))))
                             (incf (cdr sig-off-data) count))))))))
               otraces)

      ;; Finally, guess the indentation rules.
      (prog1
	  (smie-config--guess-1 sigs)
        (message "Guessing...done")))))