Function: hack-local-variables--find-variables

hack-local-variables--find-variables is a byte-compiled function defined in files.el.gz.

Signature

(hack-local-variables--find-variables &optional HANDLE-MODE)

Documentation

Return all local variables in the current buffer.

If HANDLE-MODE is nil, we gather all the specified local variables. If HANDLE-MODE is neither nil nor t, we do the same, except that any settings of mode are ignored.

If HANDLE-MODE is t, all we do is check whether a "mode:" is specified, and return the corresponding mode symbol, or nil. In this case, we try to ignore minor-modes, and return only a major-mode.

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun hack-local-variables--find-variables (&optional handle-mode)
  "Return all local variables in the current buffer.
If HANDLE-MODE is nil, we gather all the specified local
variables.  If HANDLE-MODE is neither nil nor t, we do the same,
except that any settings of `mode' are ignored.

If HANDLE-MODE is t, all we do is check whether a \"mode:\"
is specified, and return the corresponding mode symbol, or nil.
In this case, we try to ignore minor-modes, and return only a
major-mode."
  (let ((result nil))
    ;; Look for "Local variables:" line in last page.
    (save-excursion
      (goto-char (point-max))
      (search-backward "\n\^L" (max (- (point-max) 3000) (point-min))
		       'move)
      (when (let ((case-fold-search t))
	      (search-forward "Local Variables:" nil t))
        (skip-chars-forward " \t")
        ;; suffix is what comes after "local variables:" in its line.
        ;; prefix is what comes before "local variables:" in its line.
        (let ((suffix
	       (concat
                (regexp-quote (buffer-substring (point)
                                                (line-end-position)))
                "$"))
	      (prefix
	       (concat "^" (regexp-quote
			    (buffer-substring (line-beginning-position)
					      (match-beginning 0))))))

	  (forward-line 1)
	  (let ((startpos (point))
                endpos
                (selective-p (eq selective-display t))
                (thisbuf (current-buffer)))
	    (save-excursion
	      (unless (let ((case-fold-search t))
                        (re-search-forward
                         (concat prefix "[ \t]*End:[ \t]*" suffix)
                         nil t))
                ;; This used to be an error, but really all it means is
                ;; that this may simply not be a local-variables section,
                ;; so just ignore it.
                (message "Local variables list is not properly terminated"))
	      (beginning-of-line)
	      (setq endpos (point)))

	    (with-temp-buffer
	      (insert-buffer-substring thisbuf startpos endpos)
	      (goto-char (point-min))
              (if selective-p
                  (subst-char-in-region (point) (point-max) ?\r ?\n))
	      (while (not (eobp))
                ;; Discard the prefix.
                (if (looking-at prefix)
		    (delete-region (point) (match-end 0))
		  (user-error "Local variables entry is missing the prefix"))
                (end-of-line)
                ;; Discard the suffix.
                (if (looking-back suffix (line-beginning-position))
		    (delete-region (match-beginning 0) (point))
		  (user-error "Local variables entry is missing the suffix"))
                (forward-line 1))
	      (goto-char (point-min))

	      (while (not (eobp))
                ;; Find the variable name;
                (unless (looking-at hack-local-variable-regexp)
                  (user-error "Malformed local variable line: %S"
                              (buffer-substring-no-properties
                               (point) (line-end-position))))
                (goto-char (match-end 1))
                (let* ((str (match-string 1))
		       (var (intern str))
		       val val2)
		  (and (equal (downcase (symbol-name var)) "mode")
		       (setq var 'mode))
		  ;; Read the variable value.
		  (skip-chars-forward "^:")
		  (forward-char 1)
                  ;; As a defensive measure, we do not allow
                  ;; circular data in the file-local data.
		  (let ((read-circle nil))
		    (setq val (read (current-buffer))))
		  (if (eq handle-mode t)
		      (and (eq var 'mode)
			   ;; Specifying minor-modes via mode: is
			   ;; deprecated, but try to reject them anyway.
			   (not (string-match
                                 "-minor\\'"
                                 (setq val2 (downcase (symbol-name val)))))
			   (let ((mode (intern (concat val2 "-mode"))))
                             (when (fboundp (major-mode-remap mode))
                               (setq result mode))))
		    (cond ((eq var 'coding))
			  ((eq var 'lexical-binding)
			   (unless hack-local-variables--warned-lexical
			     (setq hack-local-variables--warned-lexical t)
			     (display-warning
                              'files
                              (format-message
                               "%s: `lexical-binding' at end of file unreliable"
                               (file-name-nondirectory
                                ;; We are called from
                                ;; 'with-temp-buffer', so we need
                                ;; to use 'thisbuf's name in the
                                ;; warning message.
                                (or (buffer-file-name thisbuf) ""))))))
                          ((eq var 'read-symbol-shorthands)
                           ;; Sort automatically by shorthand length
                           ;; in descending order.
                           (setq val (sort val
                                           (lambda (sh1 sh2) (> (length (car sh1))
                                                                (length (car sh2))))))
                           (push (cons 'read-symbol-shorthands val) result))
                          ((and (eq var 'mode) handle-mode))
			  (t
			   (ignore-errors
			     (push (cons (if (eq var 'eval)
					     'eval
					   (indirect-variable var))
                                         val)
                                   result))))))
                (forward-line 1)))))))
    result))