shell.
When you resume Emacs after a suspension caused by emergency escape,
-it asks two questions before going back to what it had been doing:
+it reports the resumption and asks a question or two before going back
+to what it had been doing:
@example
+Emacs is resuming after an emergency escape.
Auto-save? (y or n)
Abort (and dump core)? (y or n)
@end example
@noindent
-Answer each one with @kbd{y} or @kbd{n} followed by @key{RET}.
+Answer each question with @kbd{y} or @kbd{n} followed by @key{RET}.
Saying @kbd{y} to @samp{Auto-save?} causes immediate auto-saving of
all modified buffers in which auto-saving is enabled. Saying @kbd{n}
-skips this.
+skips this. This question is omitted if Emacs is in a state where
+auto-saving cannot be done safely.
Saying @kbd{y} to @samp{Abort (and dump core)?} causes Emacs to
crash, dumping core. This is to enable a wizard to figure out why
Use @samp{diff -u} to make your diffs. Diffs without context are hard
to install reliably. More than that, they are hard to study; we must
always study a patch to decide whether we want to install it. Context
- format is better than contextless diffs, but we prefer we unified format.
+ format is better than contextless diffs, but we prefer the unified
+ format.
If you have GNU diff, use @samp{diff -u -F'^[_a-zA-Z0-9$]\+ *('} when
making diffs of C code. This shows the name of the function that each
When you add a new item, use the appropriate mark if you are sure it applies,
otherwise leave it unmarked.
+\f
+* Installation Changes in Emacs 25.2
+
+** The new option 'configure --enable-gcc-warnings=warn-only' causes
+GCC to issue warnings without stopping the build. This behavior is
+now the default in developer builds. As before, use
+'--disable-gcc-warnings' to suppress GCC's warnings, and
+'--enable-gcc-warnings' to stop the build if GCC issues warnings.
+
++++
+** The Emacs server now has socket-launching support. This allows
+socket based activation, where an external process like systemd can
+invoke the Emacs server process upon a socket connection event and
+hand the socket over to Emacs. Emacs uses this socket to service
+emacsclient commands. This new functionality can be disabled with the
+configure option '--disable-libsystemd'.
+
+** New configure option '--disable-build-details' attempts to build an
+Emacs that is more likely to be reproducible; that is, if you build
+and install Emacs twice, the second Emacs is a copy of the first.
+Deterministic builds omit the build date from the output of the
+emacs-version and erc-cmd-SV functions, and the leave the following
+variables nil: emacs-build-system, emacs-build-time,
+erc-emacs-build-time.
+
+** Emacs no longer works on IRIX. We expect that Emacs users are not
+affected by this, as SGI stopped supporting IRIX in December 2013.
+
+\f
+* Startup Changes in Emacs 25.2
+
+\f
+* Changes in Emacs 25.2
+
+---
+** 'find-library-name' will now fall back on looking at 'load-history'
+to try to locate libraries that have been loaded with an explicit path
+outside 'load-path'.
+
++++
+** Faces in 'minibuffer-prompt-properties' no longer overwrite properties
+in the text in functions like 'read-from-minibuffer', but instead are
+added to the end of the face list. This allows users to say things
+like '(read-from-minibuffer (propertize "Enter something: " 'face 'bold))'.
+
++++
+** The new variable 'extended-command-suggest-shorter' has been added
+to control whether to suggest shorter 'M-x' commands or not.
+
+---
+** icomplete now respects 'completion-ignored-extensions'.
+
++++
+** Non-breaking hyphens are now displayed with the 'nobreak-hyphen'
+face instead of the 'escape-glyph' face.
+
+---
+** 'C-x h' ('mark-whole-buffer') will now avoid marking the prompt
+part of minibuffers.
+
+---
+** 'find-library' now takes a prefix argument to pop to a different
+window.
+
+** 'find-library', 'help-function-def' and 'help-variable-def' now run
+'find-function-after-hook'.
+
+---
+** 'process-attributes' on Darwin systems now returns more information.
+
++++
+** Several accessors for the value returned by 'file-attributes'
+have been added. They are: 'file-attribute-type',
+'file-attribute-link-number', 'file-attribute-user-id',
+'file-attribute-group-id', 'file-attribute-access-time',
+'file-attribute-modification-time',
+'file-attribute-status-change-time', 'file-attribute-size',
+'file-attribute-modes', 'file-attribute-inode-number', and
+'file-attribute-device-number'.
+
++++
+** The new function 'buffer-hash' computes compute a fast, non-consing
+hash of a buffer's contents.
+
+---
+** 'fill-paragraph' no longer marks the buffer as changed unless it
+actually changed something.
+
+---
+** The locale language name 'ca' is now mapped to the language
+environment 'Catalan', which has been added.
+
+---
+** 'align-regexp' has a separate history for its interactive argument.
+'align-regexp' no longer shares its history with all other
+history-less functions that use 'read-string'.
+
++++
+** The networking code has been reworked so that it's more
+asynchronous than it was (when specifying :nowait t in
+'make-network-process'). How asynchronous it is varies based on the
+capabilities of the system, but on a typical GNU/Linux system the DNS
+resolution, the connection, and (for TLS streams) the TLS negotiation
+are all done without blocking the main Emacs thread. To get
+asynchronous TLS, the TLS boot parameters have to be passed in (see
+the manual for details).
+
+Certain process oriented functions (like 'process-datagram-address')
+will block until socket setup has been performed. The recommended way
+to deal with asynchronous sockets is to avoid interacting with them
+until they have changed status to "run". This is most easily done
+from a process sentinel.
+
+** 'make-network-process' and 'open-network-stream' sometimes allowed
+:service to be an integer string (e.g., :service "993") and sometimes
+required an integer (e.g., :service 993). This difference has been
+eliminated, and integer strings work everywhere.
+
+** It is possible to disable attempted recovery on fatal signals.
+
+Two new variables support disabling attempts to recover from stack
+overflow and to avoid automatic auto-save when Emacs is delivered a
+fatal signal. 'attempt-stack-overflow-recovery', if set to 'nil',
+will disable attempts to recover from C stack overflows; Emacs will
+then crash as with any other fatal signal.
+'attempt-orderly-shutdown-on-fatal-signal', if set to 'nil', will
+disable attempts to auto-save the session and shut down in an orderly
+fashion when Emacs receives a fatal signal; instead, Emacs will
+terminate immediately. Both variables are non-'nil' by default.
+These variables are for users who would like to avoid the small
+probability of data corruption due to techniques Emacs uses to recover
+in these situations.
+
++++
+** File local and directory local variables are now initialized each
+time the major mode is set, not just when the file is first visited.
+These local variables will thus not vanish on setting a major mode.
+
++++
+** A second dir-local file (.dir-locals-2.el) is now accepted.
+See the variable 'dir-locals-file-2' for more information.
+
+---
+** International domain names (IDNA) are now encoded via the new
+puny.el library, so that one can visit web sites with non-ASCII URLs.
+
++++
+** The new 'timer-list' command lists all active timers in a buffer,
+where you can cancel them with the 'c' command.
+
++++
+** The new function 'read-multiple-choice' prompts for multiple-choice
+questions, with a handy way to display help texts.
+
++++
+** 'switch-to-buffer-preserve-window-point' now defaults to t.
+
+\f
+* Editing Changes in Emacs 25.2
+
++++
+** New bindings for 'query-replace-map'.
+'undo', undo the last replacement; bound to 'u'.
+'undo-all', undo all replacements; bound to 'U'.
+
+\f
+* Changes in Specialized Modes and Packages in Emacs 25.2
+
+** Compilation mode
+
+---
+*** Messages from CMake are now recognized.
+
+** Dired
+
++++
+*** In wdired, when editing files to contain slash characters,
+the resulting directories are automatically created. Whether to do
+this is controlled by the 'wdired-create-parent-directories' variable.
+
++++
+*** 'W' is now bound to 'browse-url-of-dired-file', and is useful for
+viewing HTML files and the like.
+
+** Ediff
+
+*** Ediff can be prevented from pausing 1 second after reaching a
+breakpoint (e.g. with "f" and "o") by customizing the new option
+'edebug-sit-on-break'.
+
+** eww
+
++++
+*** A new 's' command for switching to another eww buffer via the minibuffer.
+
+---
+*** The 'o' command ('shr-save-contents') has moved to 'O' to avoid collision
+with the 'o' command from 'image-map'.
+
++++
+*** A new command 'C' ('eww-toggle-colors') can be used to toggle
+whether to use the HTML-specified colors or not. The user can also
+customize the 'shr-use-colors' variable.
+
+---
+*** Images that are being loaded are now marked with gray
+"placeholder" images of the size specified by the HTML. They are then
+replaced by the real images asynchronously, which will also now
+respect width/height HTML specs (unless they specify widths/heights
+bigger than the current window).
+
+** Images
+
++++
+*** Images are automatically scaled before displaying based on the
+'image-scaling-factor' variable (if Emacs supports scaling the images
+in question).
+
++++
+*** Images inserted with 'insert-image' and related functions get a
+keymap put into the text properties (or overlays) that span the
+image. This keymap binds keystrokes for manipulating size and
+rotation, as well as saving the image to a file. These commands are
+also available in 'image-mode'.
+
++++
+*** A new library for creating and manipulating SVG images has been
+added. See the "SVG Images" section in the lispref manual for
+details.
+
++++
+*** New setf-able function to access and set image parameters is
+provided: 'image-property'.
+
+---
+** The default 'Info-default-directory-list' no longer checks some obsolete
+directory suffixes (gnu, gnu/lib, gnu/lib/emacs, emacs, lib, lib/emacs)
+when searching for info directories.
+
++++
+** The commands that add ChangeLog entries now prefer a VCS root directory
+for the ChangeLog file, if none already exists. Customize
+'change-log-directory-files' to nil for the old behavior.
+
+---
+** Support for non-string values of 'time-stamp-format' has been removed.
+
+** Message
+
+---
+*** 'message-use-idna' now defaults to t (because Emacs comes with
+built-in IDNA support now).
+
+---
+*** When sending HTML messages with embedded images, and you have
+exiftool installed, and you rotate images with EXIF data (i.e.,
+JPEGs), the rotational information will be inserted into the outgoing
+image in the message. (The original image will not have its
+orientation affected.)
+
+---
+*** The 'message-valid-fqdn-regexp' variable has been removed, since
+there are now top-level domains added all the time. Message will no
+longer warn about sending emails to top-level domains it hasn't heard
+about.
+
+*** 'message-beginning-of-line' (bound to C-a) understands folded headers.
+In 'visual-line-mode' it will look for the true beginning of a header
+while in non-'visual-line-mode' it will move the point to the indented
+header's value.
+
+** Tramp
+
++++
+*** New connection method "sg", which supports editing files under a
+different group ID.
+
++++
+*** New connection method "doas" for OpenBSD hosts.
+
+---
+** 'auto-revert-use-notify' is set back to t in 'global-auto-revert-mode'.
+
+** CSS mode
+
+---
+*** Support for completing attribute values, at-rules, bang-rules, and
+HTML tags using the 'completion-at-point' command.
+
++++
+** Emacs now supports character name escape sequences in character and
+string literals. The syntax variants \N{character name} and
+\N{U+code} are supported.
+
++++
+** Prog mode has some support for multi-mode indentation.
+This allows better indentation support in modes that support multiple
+programming languages in the same buffer, like literate programming
+environments or ANTLR programs with embedded Python code.
+
+A major mode can provide indentation context for a sub-mode through
+the 'prog-indentation-context' variable. To support this, modes that
+provide indentation should use 'prog-widen' instead of 'widen' and
+'prog-first-column' instead of a literal zero. See the node
+"Mode-Specific Indent" in the ELisp manual for more details.
+
+** ERC
+
+*** New variable 'erc-default-port-tls' used to connect to TLS IRC
+servers.
+
+** URL
+
++++
+*** The new function 'url-cookie-delete-cookie' can be used to
+programmatically delete all cookies, or cookies from a specific
+domain.
+
++++
+*** 'url-retrieve-synchronously' now takes an optional timeout parameter.
+
+---
+*** The URL package now support HTTPS over proxies supporting CONNECT.
+
++++
+*** 'url-user-agent' now defaults to 'default', and the User-Agent
+string is computed dynamically based on 'url-privacy-level'.
+
+** VC and related modes
+
+---
+*** The VC state indicator in the mode line now defaults to more
+colorful faces to make it more obvious to the user what the state is.
+See the 'vc-faces' customization group.
+
+\f
+* New Modes and Packages in Emacs 25.2
+
+** New Elisp data-structure library `radix-tree'.
+
+\f
+* Incompatible Lisp Changes in Emacs 25.2
+
++++
+** Resizing a frame no longer runs 'window-configuration-change-hook'.
+Put your function on 'window-size-change-functions' instead.
+
+** 'C-up', 'C-down', 'C-left' and 'C-right' are now defined in term
+mode to send the same escape sequences that xterm does. This makes
+things like forward-word in readline work.
+
+---
+** hideshow mode got four key bindings that are analogous to outline
+mode bindings: 'C-c @ C-a', 'C-c @ C-t', 'C-c @ C-d', and 'C-c @ C-e.'
+
+** The grep/rgrep/lgrep functions will now ask about saving files
+before running. This is controlled by the 'grep-save-buffers'
+variable.
+
++++
+** The variable 'text-quoting-style' no longer affects the treatment
+of curved quotes in format arguments to functions like 'message' and
+'format-message'. In particular, when this variable's value is
+'grave', all quotes in formats are output as-is.
+
+** Functions like 'check-declare-file' and 'check-declare-directory'
+now generate less chatter and more-compact diagnostics. The auxiliary
+function 'check-declare-errmsg' has been removed.
+
+\f
+* Lisp Changes in Emacs 25.2
+
+** New var `definition-prefixes' is a hashtable mapping prefixes to the
+files where corresponding definitions can be found. This can be used
+to fetch definitions that are not yet loaded, for example for `C-h f'.
+
+** New var syntax-ppss-table to control the syntax-table used in syntax-ppss.
+
++++
+** 'define-derived-mode' can now specify an :after-hook form, which
+gets evaluated after the new mode's hook has run. This can be used to
+incorporate configuration changes made in the mode hook into the
+mode's setup.
+
+** Autoload files can be generated without timestamps,
+by setting 'autoload-timestamps' to nil.
+FIXME As an experiment, nil is the current default.
+If no insurmountable problems before next release, it can stay that way.
+
+** 'ert-with-function-mocked' of 'ert-x package allows mocking of functions
+in unit tests.
+
+---
+** 'gnutls-boot' now takes a parameter :complete-negotiation that says
+that negotiation should complete even on non-blocking sockets.
+
++++
+** New functions 'window-pixel-width-before-size-change' and
+'window-pixel-height-before-size-change' support detecting which
+window changed size when 'window-size-change-functions' are run.
+
++++
+** New function 'display-buffer-reuse-mode-window' is an action function
+suitable for use in 'display-buffer-alist'. For example, to avoid creating
+a new window when opening man pages when there's already one, use
+(add-to-list 'display-buffer-alist
+ '("\\`\\*Man .*\\*\\'" .
+ (display-buffer-reuse-mode-window
+ (inhibit-same-window . nil)
+ (mode . Man-mode))))
+
+---
+** There is now a new variable 'flyspell-sort-corrections-function'
+that allows changing the way corrections are sorted.
+
+---
+** The new command 'fortune-message' has been added, which displays
+fortunes in the echo area.
+
++++
+** New function 'func-arity' returns information about the argument list
+of an arbitrary function. This generalizes 'subr-arity' for functions
+that are not built-in primitives. We recommend using this new
+function instead of 'subr-arity'.
+
++++
+** 'parse-partial-sexp' state has a new element. Element 10 is
+non-nil when the last character scanned might be the first character
+of a two character construct, i.e., a comment delimiter or escaped
+character. Its value is the syntax of that last character.
+
++++
+** 'parse-partial-sexp''s state, element 9, has now been confirmed as
+permanent and documented, and may be used by Lisp programs. Its value
+is a list of currently open parenthesis positions, starting with the
+outermost parenthesis.
+
+---
+** 'read-color' will now display the color names using the color itself
+as the background color.
+
+** The function 'redirect-debugging-output' now works on platforms
+other than GNU/Linux.
+
++++
+** The new function 'string-version-lessp' compares strings by
+interpreting consecutive runs of numerical characters as numbers, and
+compares their numerical values. According to this predicate,
+"foo2.png" is smaller than "foo12.png".
+
++++
+** The new function 'char-from-name' converts a Unicode name string
+to the corresponding character code.
+
++++
+** New functions 'sxhash-eq' and 'sxhash-eql' return hash codes of a
+Lisp object suitable for use with 'eq' and 'eql' correspondingly. If
+two objects are 'eq' ('eql'), then the result of 'sxhash-eq'
+('sxhash-eql') on them will be the same.
+
++++
+** Function 'sxhash' has been renamed to 'sxhash-equal' for
+consistency with the new functions. For compatibility, 'sxhash'
+remains as an alias to 'sxhash-equal'.
+
++++
+** Time conversion functions that accept a time zone rule argument now
+allow it to be OFFSET or a list (OFFSET ABBR), where the integer
+OFFSET is a count of seconds east of Universal Time, and the string
+ABBR is a time zone abbreviation. The affected functions are
+'current-time-string', 'current-time-zone', 'decode-time',
+'format-time-string', and 'set-time-zone-rule'.
+
++++
+*** New basic face 'fixed-pitch-serif', for a fixed-width font with serifs.
+The Info-quoted and tex-verbatim faces now default to inheriting from it.
+
+\f
+* Changes in Emacs 25.2 on Non-Free Operating Systems
+
+** Intercepting hotkeys on Windows 7 and later now works better.
+The new keyboard hooking code properly grabs system hotkeys such as
+Win-* and Alt-TAB, in a way that Emacs can get at them before the
+system. This makes the 'w32-register-hot-key' functionality work
+again on all versions of MS-Windows starting with Windows 7. On
+Windows NT and later you can now register any hotkey combination. (On
+Windows 9X, the previous limitations, spelled out in the Emacs manual,
+still apply.)
+
+** 'convert-standard-filename' no longer mirrors slashes on MS-Windows.
+Previously, on MS-Windows this function converted slash characters in
+file names into backslashes. It no longer does that.
+
\f
* Installation Changes in Emacs 25.1
25.1 (or later). Should you ever need to downgrade your desktop file
to version 206, you can do this with 'C-u C-u M-x desktop-save'.
+ ---
+ *** desktop-restore-in-current-display now defaults to t, not nil.
+ That is, Emacs by default now restores frames into the current display.
+
+++
** New function 'bookmark-set-no-overwrite' bound to 'C-x r M'.
It raises an error if a bookmark of that name already exists,
2015-03-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* net/shr.el (shr-insert): Remove soft hyphens.
- (shr-insert): Also remove soft hypens from non-folded text.
+ (shr-insert): Also remove soft hyphens from non-folded text.
2015-02-28 Eli Zaretskii <eliz@gnu.org>
* net/tramp.el (tramp-read-passwd): Ignore errors from `auth-source-*'.
* net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band): Use "\n"
- as end-of-line delimeter for passwords, when running on MS Windows.
+ as end-of-line delimiter for passwords, when running on MS Windows.
2014-12-27 Stefan Monnier <monnier@iro.umontreal.ca>
;;; Code:
+(require 'seq)
+
;;; User variables:
(defgroup find-function nil
LIBRARY should be a string (the name of the library)."
;; If the library is byte-compiled, try to find a source library by
;; the same name.
- (if (string-match "\\.el\\(c\\(\\..*\\)?\\)\\'" library)
- (setq library (replace-match "" t t library)))
+ (when (string-match "\\.el\\(c\\(\\..*\\)?\\)\\'" library)
+ (setq library (replace-match "" t t library)))
(or
(locate-file library
- (or find-function-source-path load-path)
- (find-library-suffixes))
+ (or find-function-source-path load-path)
+ (find-library-suffixes))
(locate-file library
- (or find-function-source-path load-path)
- load-file-rep-suffixes)
+ (or find-function-source-path load-path)
+ load-file-rep-suffixes)
(when (file-name-absolute-p library)
(let ((rel (find-library--load-name library)))
(when rel
(locate-file rel
(or find-function-source-path load-path)
load-file-rep-suffixes)))))
+ (find-library--from-load-path library)
(error "Can't find library %s" library)))
+(defun find-library--from-load-path (library)
+ ;; In `load-history', the file may be ".elc", ".el", ".el.gz", and
+ ;; LIBRARY may be "foo.el" or "foo", so make sure that we get all
+ ;; potential matches, and then see whether any of them lead us to an
+ ;; ".el" or an ".el.gz" file.
+ (let* ((elc-regexp "\\.el\\(c\\(\\..*\\)?\\)\\'")
+ (suffix-regexp
+ (concat "\\("
+ (mapconcat 'regexp-quote (find-library-suffixes) "\\'\\|")
+ "\\|" elc-regexp "\\)\\'"))
+ (potentials
+ (mapcar
+ (lambda (entry)
+ (if (string-match suffix-regexp (car entry))
+ (replace-match "" t t (car entry))
+ (car entry)))
+ (seq-filter
+ (lambda (entry)
+ (string-match
+ (concat "\\`"
+ (regexp-quote
+ (replace-regexp-in-string suffix-regexp "" library))
+ suffix-regexp)
+ (file-name-nondirectory (car entry))))
+ load-history)))
+ result)
+ (dolist (file potentials)
+ (dolist (suffix (find-library-suffixes))
+ (when (not result)
+ (cond ((file-exists-p file)
+ (setq result file))
+ ((file-exists-p (concat file suffix))
+ (setq result (concat file suffix)))))))
+ result))
+
(defvar find-function-C-source-directory
(let ((dir (expand-file-name "src" source-directory)))
(if (file-accessible-directory-p dir) dir))
(cons (current-buffer) (match-beginning 0))))
;;;###autoload
-(defun find-library (library)
+(defun find-library (library &optional other-window)
"Find the Emacs Lisp source of LIBRARY.
-LIBRARY should be a string (the name of the library)."
+LIBRARY should be a string (the name of the library). If the
+optional OTHER-WINDOW argument (i.e., the command argument) is
+specified, pop to a different window before displaying the
+buffer."
(interactive
(let* ((dirs (or find-function-source-path load-path))
(suffixes (find-library-suffixes))
(when (and def (not (test-completion def table)))
(setq def nil))
(list
- (completing-read (if def (format "Library name (default %s): " def)
+ (completing-read (if def
+ (format "Library name (default %s): " def)
"Library name: ")
- table nil nil nil nil def))))
- (let ((buf (find-file-noselect (find-library-name library))))
- (condition-case nil (switch-to-buffer buf) (error (pop-to-buffer buf)))))
+ table nil nil nil nil def)
+ current-prefix-arg)))
+ (prog1
+ (funcall (if other-window
+ 'pop-to-buffer
+ 'pop-to-buffer-same-window)
+ (find-file-noselect (find-library-name library)))
+ (run-hooks 'find-function-after-hook)))
;;;###autoload
(defun find-function-search-for-symbol (symbol type library)
If VERBOSE is non-nil, and FUNCTION is an alias, display a
message about the whole chain of aliases."
- (let ((def (if (symbolp function)
- (find-function-advised-original function)))
+ (let ((def (when (symbolp function)
+ (or (fboundp function)
+ (signal 'void-function (list function)))
+ (find-function-advised-original function)))
aliases)
;; FIXME for completeness, it might be nice to print something like:
;; foo (which is advised), which is an alias for bar (which is advised).
or from Lisp without specifying the optional argument FIND-FILE;
in that case, this function acts as if `enable-local-variables' were t."
(interactive)
- (fundamental-mode)
+ (kill-all-local-variables)
+ (unless delay-mode-hooks
+ (run-hooks 'change-major-mode-after-body-hook
+ 'after-change-major-mode-hook))
(let ((enable-local-variables (or (not find-file) enable-local-variables)))
;; FIXME this is less efficient than it could be, since both
;; s-a-m and h-l-v may parse the same regions, looking for "mode:".
(with-demoted-errors "File mode specification error: %s"
(set-auto-mode))
- (with-demoted-errors "File local-variables error: %s"
- (hack-local-variables)))
+ ;; `delay-mode-hooks' being non-nil will have prevented the major
+ ;; mode's call to `run-mode-hooks' from calling
+ ;; `hack-local-variables'. In that case, call it now.
+ (when delay-mode-hooks
+ (with-demoted-errors "File local-variables error: %s"
+ (hack-local-variables 'no-mode))))
;; Turn font lock off and on, to make sure it takes account of
;; whatever file local variables are relevant to it.
(when (and font-lock-mode
;; TODO? Warn once per file rather than once per session?
(defvar hack-local-variables--warned-lexical nil)
-(defun hack-local-variables (&optional mode-only)
+(defun hack-local-variables (&optional handle-mode)
"Parse and put into effect this buffer's local variables spec.
Uses `hack-local-variables-apply' to apply the variables.
-If MODE-ONLY is non-nil, all we do is check whether a \"mode:\"
+If HANDLE-MODE is nil, we apply 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 only return a
major-mode.
(let ((enable-local-variables
(and local-enable-local-variables enable-local-variables))
result)
- (unless mode-only
+ (unless (eq handle-mode t)
(setq file-local-variables-alist nil)
(with-demoted-errors "Directory-local variables error: %s"
;; Note this is a no-op if enable-local-variables is nil.
;; This entire function is basically a no-op if enable-local-variables
;; is nil. All it does is set file-local-variables-alist to nil.
(when enable-local-variables
- ;; This part used to ignore enable-local-variables when mode-only
- ;; was non-nil. That was inappropriate, eg consider the
+ ;; This part used to ignore enable-local-variables when handle-mode
+ ;; was t. That was inappropriate, eg consider the
;; (artificial) example of:
;; (setq local-enable-local-variables nil)
;; Open a file foo.txt that contains "mode: sh".
;; It correctly opens in text-mode.
;; M-x set-visited-file name foo.c, and it incorrectly stays in text-mode.
(unless (or (inhibit-local-variables-p)
- ;; If MODE-ONLY is non-nil, and the prop line specifies a
+ ;; If HANDLE-MODE is t, and the prop line specifies a
;; mode, then we're done, and have no need to scan further.
- (and (setq result (hack-local-variables-prop-line mode-only))
- mode-only))
+ (and (setq result (hack-local-variables-prop-line
+ (eq handle-mode t)))
+ (eq handle-mode t)))
;; Look for "Local variables:" line in last page.
(save-excursion
(goto-char (point-max))
(goto-char (point-min))
(while (not (or (eobp)
- (and mode-only result)))
+ (and (eq handle-mode t) result)))
;; Find the variable name;
(unless (looking-at hack-local-variable-regexp)
(error "Malformed local variable line: %S"
(forward-char 1)
(let ((read-circle nil))
(setq val (read (current-buffer))))
- (if mode-only
+ (if (eq handle-mode t)
(and (eq var 'mode)
;; Specifying minor-modes via mode: is
;; deprecated, but try to reject them anyway.
;; to use 'thisbuf's name in the
;; warning message.
(or (buffer-file-name thisbuf) ""))))))
+ ((and (eq var 'mode) handle-mode))
(t
(ignore-errors
(push (cons (if (eq var 'eval)
val) result))))))
(forward-line 1))))))))
;; Now we've read all the local variables.
- ;; If MODE-ONLY is non-nil, return whether the mode was specified.
- (if mode-only result
+ ;; If HANDLE-MODE is t, return whether the mode was specified.
+ (if (eq handle-mode t) result
;; Otherwise, set the variables.
(hack-local-variables-filter result nil)
(hack-local-variables-apply)))))
(error
;; The file's content might be invalid (e.g. have a merge conflict), but
;; that shouldn't prevent the user from opening the file.
- (message ".dir-locals error: %s" (error-message-string err))
+ (message "%s error: %s" dir-locals-file (error-message-string err))
nil))))
(defun dir-locals-set-directory-class (directory class &optional mtime)
(defconst dir-locals-file ".dir-locals.el"
"File that contains directory-local variables.
-It has to be constant to enforce uniform values
-across different environments and users.")
+It has to be constant to enforce uniform values across different
+environments and users.
+See also `dir-locals-file-2', whose values override this one's.
+See Info node `(elisp)Directory Local Variables' for details.")
+
+(defconst dir-locals-file-2 ".dir-locals-2.el"
+ "File that contains directory-local variables.
+This essentially a second file that can be used like
+`dir-locals-file', so that users can have specify their personal
+dir-local variables even if the current directory already has a
+`dir-locals-file' that is shared with other users (such as in a
+git repository).
+See Info node `(elisp)Directory Local Variables' for details.")
+
+(defun dir-locals--all-files (directory)
+ "Return a list of all readable dir-locals files in DIRECTORY.
+The returned list is sorted by increasing priority. That is,
+values specified in the last file should take precedence over
+those in the first."
+ (when (file-readable-p directory)
+ (let* ((file-1 (expand-file-name (if (eq system-type 'ms-dos)
+ (dosified-file-name dir-locals-file)
+ dir-locals-file)
+ directory))
+ (file-2 (when (string-match "\\.el\\'" file-1)
+ (replace-match "-2.el" t nil file-1)))
+ (out nil))
+ ;; The order here is important.
+ (dolist (f (list file-2 file-1))
+ (when (and f
+ (file-readable-p f)
+ (file-regular-p f)
+ (not (file-directory-p f)))
+ (push f out)))
+ out)))
(defun dir-locals-find-file (file)
"Find the directory-local variables for FILE.
time stored in the cache matches the current file modification time.
If not, the cache entry is cleared so that the file will be re-read.
-This function returns either nil (no directory local variables found),
-or the matching entry from `dir-locals-directory-cache' (a list),
-or the full path to the `dir-locals-file' (a string) in the case
-of no valid cache entry."
+This function returns either:
+ - nil (no directory local variables found),
+ - the matching entry from `dir-locals-directory-cache' (a list),
+ - or the full path to the directory (a string) containing at
+ least one `dir-locals-file' in the case of no valid cache
+ entry."
(setq file (expand-file-name file))
- (let* ((dir-locals-file-name
- (if (eq system-type 'ms-dos)
- (dosified-file-name dir-locals-file)
- dir-locals-file))
- (locals-file (locate-dominating-file file dir-locals-file-name))
- (dir-elt nil))
+ (let* ((locals-dir (locate-dominating-file (file-name-directory file)
+ #'dir-locals--all-files))
+ dir-elt)
;; `locate-dominating-file' may have abbreviated the name.
- (and locals-file
- (setq locals-file (expand-file-name dir-locals-file-name locals-file)))
- ;; Let dir-locals-read-from-file inform us via demoted-errors
- ;; about unreadable files, etc.
- ;; Maybe we'd want to keep searching though - that is
- ;; a locate-dominating-file issue.
-;;; (or (not (file-readable-p locals-file))
-;;; (not (file-regular-p locals-file)))
-;;; (setq locals-file nil))
+ (when locals-dir
+ (setq locals-dir (expand-file-name locals-dir)))
;; Find the best cached value in `dir-locals-directory-cache'.
(dolist (elt dir-locals-directory-cache)
(when (and (string-prefix-p (car elt) file
- (memq system-type
- '(windows-nt cygwin ms-dos)))
- (> (length (car elt)) (length (car dir-elt))))
- (setq dir-elt elt)))
+ (memq system-type
+ '(windows-nt cygwin ms-dos)))
+ (> (length (car elt)) (length (car dir-elt))))
+ (setq dir-elt elt)))
(if (and dir-elt
- (or (null locals-file)
- (<= (length (file-name-directory locals-file))
- (length (car dir-elt)))))
- ;; Found a potential cache entry. Check validity.
- ;; A cache entry with no MTIME is assumed to always be valid
- ;; (ie, set directly, not from a dir-locals file).
- ;; Note, we don't bother to check that there is a matching class
- ;; element in dir-locals-class-alist, since that's done by
- ;; dir-locals-set-directory-class.
- (if (or (null (nth 2 dir-elt))
- (let ((cached-file (expand-file-name dir-locals-file-name
- (car dir-elt))))
- (and (file-readable-p cached-file)
- (equal (nth 2 dir-elt)
- (nth 5 (file-attributes cached-file))))))
- ;; This cache entry is OK.
- dir-elt
- ;; This cache entry is invalid; clear it.
- (setq dir-locals-directory-cache
- (delq dir-elt dir-locals-directory-cache))
- ;; Return the first existing dir-locals file. Might be the same
- ;; as dir-elt's, might not (eg latter might have been deleted).
- locals-file)
+ (or (null locals-dir)
+ (<= (length locals-dir)
+ (length (car dir-elt)))))
+ ;; Found a potential cache entry. Check validity.
+ ;; A cache entry with no MTIME is assumed to always be valid
+ ;; (ie, set directly, not from a dir-locals file).
+ ;; Note, we don't bother to check that there is a matching class
+ ;; element in dir-locals-class-alist, since that's done by
+ ;; dir-locals-set-directory-class.
+ (if (or (null (nth 2 dir-elt))
+ (let ((cached-files (dir-locals--all-files (car dir-elt))))
+ ;; The entry MTIME should match the most recent
+ ;; MTIME among matching files.
+ (and cached-files
+ (= (float-time (nth 2 dir-elt))
+ (apply #'max (mapcar (lambda (f)
+ (float-time
+ (nth 5 (file-attributes f))))
+ cached-files))))))
+ ;; This cache entry is OK.
+ dir-elt
+ ;; This cache entry is invalid; clear it.
+ (setq dir-locals-directory-cache
+ (delq dir-elt dir-locals-directory-cache))
+ ;; Return the first existing dir-locals file. Might be the same
+ ;; as dir-elt's, might not (eg latter might have been deleted).
+ locals-dir)
;; No cache entry.
- locals-file)))
-
-(defun dir-locals-read-from-file (file)
- "Load a variables FILE and register a new class and instance.
-FILE is the name of the file holding the variables to apply.
-The new class name is the same as the directory in which FILE
-is found. Returns the new class name."
- (with-temp-buffer
+ locals-dir)))
+
+(defun dir-locals-read-from-dir (dir)
+ "Load all variables files in DIR and register a new class and instance.
+DIR is the absolute name of a directory which must contain at
+least one dir-local file (which is a file holding variables to
+apply).
+Return the new class name, which is a symbol named DIR."
+ (require 'map)
+ (let* ((class-name (intern dir))
+ (files (dir-locals--all-files dir))
+ (read-circle nil)
+ (success nil)
+ (variables))
(with-demoted-errors "Error reading dir-locals: %S"
- (insert-file-contents file)
- (unless (zerop (buffer-size))
- (let* ((dir-name (file-name-directory file))
- (class-name (intern dir-name))
- (variables (let ((read-circle nil))
- (read (current-buffer)))))
- (dir-locals-set-class-variables class-name variables)
- (dir-locals-set-directory-class dir-name class-name
- (nth 5 (file-attributes file)))
- class-name)))))
+ (dolist (file files)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (condition-case-unless-debug nil
+ (setq variables
+ (map-merge-with 'list (lambda (a b) (map-merge 'list a b))
+ variables
+ (read (current-buffer))))
+ (end-of-file nil))))
+ (setq success t))
+ (dir-locals-set-class-variables class-name variables)
+ (dir-locals-set-directory-class
+ dir class-name
+ (seconds-to-time
+ (if success
+ (apply #'max (mapcar (lambda (file)
+ (float-time (nth 5 (file-attributes file))))
+ files))
+ ;; If there was a problem, use the values we could get but
+ ;; don't let the cache prevent future reads.
+ 0)))
+ class-name))
+
+(define-obsolete-function-alias 'dir-locals-read-from-file
+ 'dir-locals-read-from-dir "25.1")
(defcustom enable-remote-dir-locals nil
"Non-nil means dir-local variables will be applied to remote files."
(not (file-remote-p (or (buffer-file-name)
default-directory)))))
;; Find the variables file.
- (let ((variables-file (dir-locals-find-file
- (or (buffer-file-name) default-directory)))
+ (let ((dir-or-cache (dir-locals-find-file
+ (or (buffer-file-name) default-directory)))
(class nil)
(dir-name nil))
(cond
- ((stringp variables-file)
- (setq dir-name (file-name-directory variables-file)
- class (dir-locals-read-from-file variables-file)))
- ((consp variables-file)
- (setq dir-name (nth 0 variables-file))
- (setq class (nth 1 variables-file))))
+ ((stringp dir-or-cache)
+ (setq dir-name dir-or-cache
+ class (dir-locals-read-from-dir dir-or-cache)))
+ ((consp dir-or-cache)
+ (setq dir-name (nth 0 dir-or-cache))
+ (setq class (nth 1 dir-or-cache))))
(when class
(let ((variables
(dir-locals-collect-variables
(defun file-name-sans-extension (filename)
"Return FILENAME sans final \"extension\".
- The extension, in a file name, is the part that follows the last `.',
- except that a leading `.', if any, doesn't count."
+ The extension, in a file name, is the part that begins with the last `.',
+ except that a leading `.' of the file name, if there is one, doesn't count."
(save-match-data
(let ((file (file-name-sans-versions (file-name-nondirectory filename)))
directory)
(defun file-name-extension (filename &optional period)
"Return FILENAME's final \"extension\".
- The extension, in a file name, is the part that follows the last `.',
- excluding version numbers and backup suffixes,
- except that a leading `.', if any, doesn't count.
+ The extension, in a file name, is the part that begins with the last `.',
+ excluding version numbers and backup suffixes, except that a leading `.'
+ of the file name, if there is one, doesn't count.
Return nil for extensionless file names such as `foo'.
Return the empty string for file names such as `foo.'.
- If PERIOD is non-nil, then the returned value includes the period
- that delimits the extension, and if FILENAME has no extension,
- the value is \"\"."
+ By default, the returned value excludes the period that starts the
+ extension, but if the optional argument PERIOD is non-nil, the period
+ is included in the value, and in that case, if FILENAME has no
+ extension, the value is \"\"."
(save-match-data
(let ((file (file-name-sans-versions (file-name-nondirectory filename))))
(if (and (string-match "\\.[^.]*\\'" file)
;; Simulate the message printed by `ls'.
(insert (format "%s: No such file or directory\n" file))))
-(defvar kill-emacs-query-functions nil
+(defcustom kill-emacs-query-functions nil
"Functions to call with no arguments to query about killing Emacs.
If any of these functions returns nil, killing Emacs is canceled.
`save-buffers-kill-emacs' calls these functions, but `kill-emacs',
-the low level primitive, does not. See also `kill-emacs-hook'.")
+the low level primitive, does not. See also `kill-emacs-hook'."
+ :type 'hook
+ :version "25.2"
+ :group 'convenience)
(defcustom confirm-kill-emacs nil
"How to ask for confirmation when leaving Emacs.
(defun save-buffers-kill-terminal (&optional arg)
"Offer to save each buffer, then kill the current connection.
-If the current frame has no client, kill Emacs itself.
+If the current frame has no client, kill Emacs itself using
+`save-buffers-kill-emacs'.
With prefix ARG, silently save all file-visiting buffers, then kill.
(let ((delete-by-moving-to-trash nil))
(rename-file fn new-fn)))))))))
+(defsubst file-attribute-type (attributes)
+ "The type field in ATTRIBUTES returned by `file-attribute'.
+The value is either t for directory, string (name linked to) for
+symbolic link, or nil."
+ (nth 0 attributes))
+
+(defsubst file-attribute-link-number (attributes)
+ "Return the number of links in ATTRIBUTES returned by `file-attribute'."
+ (nth 1 attributes))
+
+(defsubst file-attribute-user-id (attributes)
+ "The UID field in ATTRIBUTES returned by `file-attribute'.
+This is either a string or a number. If a string value cannot be
+looked up, a numeric value, either an integer or a float, is
+returned."
+ (nth 2 attributes))
+
+(defsubst file-attribute-group-id (attributes)
+ "The GID field in ATTRIBUTES returned by `file-attribute'.
+This is either a string or a number. If a string value cannot be
+looked up, a numeric value, either an integer or a float, is
+returned."
+ (nth 3 attributes))
+
+(defsubst file-attribute-access-time (attributes)
+ "The last access time in ATTRIBUTES returned by `file-attribute'.
+This a list of integers (HIGH LOW USEC PSEC) in the same style
+as (current-time)."
+ (nth 4 attributes))
+
+(defsubst file-attribute-modification-time (attributes)
+ "The modification time in ATTRIBUTES returned by `file-attribute'.
+This is the time of the last change to the file's contents, and
+is a list of integers (HIGH LOW USEC PSEC) in the same style
+as (current-time)."
+ (nth 5 attributes))
+
+(defsubst file-attribute-status-change-time (attributes)
+ "The status modification time in ATTRIBUTES returned by `file-attribute'.
+This is the time of last change to the file's attributes: owner
+and group, access mode bits, etc, and is a list of integers (HIGH
+LOW USEC PSEC) in the same style as (current-time)."
+ (nth 6 attributes))
+
+(defsubst file-attribute-size (attributes)
+ "The size (in bytes) in ATTRIBUTES returned by `file-attribute'.
+This is a floating point number if the size is too large for an integer."
+ (nth 7 attributes))
+
+(defsubst file-attribute-modes (attributes)
+ "The file modes in ATTRIBUTES returned by `file-attribute'.
+This is a string of ten letters or dashes as in ls -l."
+ (nth 8 attributes))
+
+(defsubst file-attribute-inode-number (attributes)
+ "The inode number in ATTRIBUTES returned by `file-attribute'.
+If it is larger than what an Emacs integer can hold, this is of
+the form (HIGH . LOW): first the high bits, then the low 16 bits.
+If even HIGH is too large for an Emacs integer, this is instead
+of the form (HIGH MIDDLE . LOW): first the high bits, then the
+middle 24 bits, and finally the low 16 bits."
+ (nth 10 attributes))
+
+(defsubst file-attribute-device-number (attributes)
+ "The file system device number in ATTRIBUTES returned by `file-attribute'.
+If it is larger than what an Emacs integer can hold, this is of
+the form (HIGH . LOW): first the high bits, then the low 16 bits.
+If even HIGH is too large for an Emacs integer, this is instead
+of the form (HIGH MIDDLE . LOW): first the high bits, then the
+middle 24 bits, and finally the low 16 bits."
+ (nth 11 attributes))
+
\f
(define-key ctl-x-map "\C-f" 'find-file)
(define-key ctl-x-map "\C-r" 'find-file-read-only)
;; Font-locking support.
(defun elisp--font-lock-flush-elisp-buffers (&optional file)
- ;; FIXME: Aren't we only ever called from after-load-functions?
- ;; Don't flush during load unless called from after-load-functions.
- ;; In that case, FILE is non-nil. It's somehow strange that
- ;; load-in-progress is t when an after-load-function is called since
- ;; that should run *after* the load...
+ ;; We're only ever called from after-load-functions, load-in-progress can
+ ;; still be t in case of nested loads.
(when (or (not load-in-progress) file)
;; FIXME: If the loaded file did not define any macros, there shouldn't
;; be any need to font-lock-flush all the Elisp buffers.
((or (eq (following-char) ?\')
(eq (preceding-char) ?\'))
(setq left-quote ?\`)))
+
+ ;; When after a named character literal, skip over the entire
+ ;; literal, not only its last word.
+ (when (= (preceding-char) ?})
+ (let ((begin (save-excursion
+ (backward-char)
+ (skip-syntax-backward "w-")
+ (backward-char 3)
+ (when (looking-at-p "\\\\N{") (point)))))
+ (when begin (goto-char begin))))
+
(forward-sexp -1)
;; If we were after `?\e' (or similar case),
;; use the whole thing, not just the `e'.
ARGLIST is either a string, or a list of strings or symbols."
(let ((str (cond ((stringp arglist) arglist)
((not (listp arglist)) nil)
- (t (help--make-usage-docstring 'toto arglist)))))
+ (t (substitute-command-keys
+ (help--make-usage-docstring 'toto arglist))))))
(if (and str (string-match "\\`([^ )]+ ?" str))
(replace-match "(" t t str)
str)))
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-;;; Commentary:
-
-;;; Code:
-
;; Beware: while this file has tag `utf-8', before it's compiled, it gets
;; loaded as "raw-text", so non-ASCII chars won't work right during bootstrap.
-(defmacro declare-function (_fn _file &optional _arglist _fileonly)
+
+;; declare-function's args use &rest, not &optional, for compatibility
+;; with byte-compile-macroexpand-declare-function.
+
+(defmacro declare-function (_fn _file &rest _args)
"Tell the byte-compiler that function FN is defined, in FILE.
-Optional ARGLIST is the argument list used by the function.
The FILE argument is not used by the byte-compiler, but by the
`check-declare' package, which checks that FILE contains a
-definition for FN. ARGLIST is used by both the byte-compiler
-and `check-declare' to check for consistency.
+definition for FN.
FILE can be either a Lisp file (in which case the \".el\"
extension is optional), or a C file. C files are expanded
`check-declare' will check such files if they are found, and skip
them without error if they are not.
-FILEONLY non-nil means that `check-declare' will only check that
-FILE exists, not that it defines FN. This is intended for
-function-definitions that `check-declare' does not recognize, e.g.
-`defstruct'.
+Optional ARGLIST specifies FN's arguments, or is t to not specify
+FN's arguments. An omitted ARGLIST defaults to t, not nil: a nil
+ARGLIST specifies an empty argument list, and an explicit t
+ARGLIST is a placeholder that allows supplying a later arg.
-To specify a value for FILEONLY without passing an argument list,
-set ARGLIST to t. This is necessary because nil means an
-empty argument list, rather than an unspecified one.
+Optional FILEONLY non-nil means that `check-declare' will check
+only that FILE exists, not that it defines FN. This is intended
+for function definitions that `check-declare' does not recognize,
+e.g., `defstruct'.
Note that for the purposes of `check-declare', this statement
must be the first non-whitespace on a line.
For more information, see Info node `(elisp)Declaring Functions'."
+ (declare (advertised-calling-convention
+ (fn file &optional arglist fileonly) nil))
;; Does nothing - byte-compile-declare-function does the work.
nil)
;;;; Basic Lisp macros.
(defalias 'not 'null)
+(defalias 'sxhash 'sxhash-equal)
(defmacro noreturn (form)
"Evaluate FORM, expecting it not to return.
(list from)
(or inc (setq inc 1))
(when (zerop inc) (error "The increment can not be zero"))
- (let (seq (n 0) (next from))
+ (let (seq (n 0) (next from) (last from))
(if (> inc 0)
- (while (<= next to)
+ ;; The (>= next last) condition protects against integer
+ ;; overflow in computing NEXT.
+ (while (and (>= next last) (<= next to))
(setq seq (cons next seq)
n (1+ n)
+ last next
next (+ from (* n inc))))
- (while (>= next to)
+ (while (and (<= next last) (>= next to))
(setq seq (cons next seq)
n (1+ n)
next (+ from (* n inc)))))
Note that if KEY has a local binding in the current buffer,
that local binding will continue to shadow any global binding
that you make with this function."
- (interactive "KSet key globally: \nCSet key %s to command: ")
+ (interactive
+ (let* ((menu-prompting nil)
+ (key (read-key-sequence "Set key globally: ")))
+ (list key
+ (read-command (format "Set key %s to command: "
+ (key-description key))))))
(or (vectorp key) (stringp key)
(signal 'wrong-type-argument (list 'arrayp key)))
(define-key (current-global-map) key command))
(declare (indent 2) (debug (form sexp body))
(obsolete "use a <foo>-function variable modified by `add-function'."
"24.4"))
+ `(subr--with-wrapper-hook-no-warnings ,hook ,args ,@body))
+
+(defmacro subr--with-wrapper-hook-no-warnings (hook args &rest body)
+ "Like (with-wrapper-hook HOOK ARGS BODY), but without warnings."
;; We need those two gensyms because CL's lexical scoping is not available
;; for function arguments :-(
(let ((funs (make-symbol "funs"))
(make-variable-buffer-local 'delayed-mode-hooks)
(put 'delay-mode-hooks 'permanent-local t)
+(defvar delayed-after-hook-forms nil
+ "List of delayed :after-hook forms waiting to be run.
+These forms come from `define-derived-mode'.")
+(make-variable-buffer-local 'delayed-after-hook-forms)
+
(defvar change-major-mode-after-body-hook nil
"Normal hook run in major mode functions, before the mode hooks.")
(defun run-mode-hooks (&rest hooks)
"Run mode hooks `delayed-mode-hooks' and HOOKS, or delay HOOKS.
-If the variable `delay-mode-hooks' is non-nil, does not run any hooks,
+Call `hack-local-variables' to set up file local and directory local
+variables.
+
+If the variable `delay-mode-hooks' is non-nil, does not do anything,
just adds the HOOKS to the list `delayed-mode-hooks'.
Otherwise, runs hooks in the sequence: `change-major-mode-after-body-hook',
-`delayed-mode-hooks' (in reverse order), HOOKS, and finally
-`after-change-major-mode-hook'. Major mode functions should use
-this instead of `run-hooks' when running their FOO-mode-hook."
+`delayed-mode-hooks' (in reverse order), HOOKS, then runs
+`hack-local-variables', runs the hook `after-change-major-mode-hook', and
+finally evaluates the forms in `delayed-after-hook-forms' (see
+`define-derived-mode').
+
+Major mode functions should use this instead of `run-hooks' when
+running their FOO-mode-hook."
(if delay-mode-hooks
;; Delaying case.
(dolist (hook hooks)
(setq hooks (nconc (nreverse delayed-mode-hooks) hooks))
(setq delayed-mode-hooks nil)
(apply 'run-hooks (cons 'change-major-mode-after-body-hook hooks))
- (run-hooks 'after-change-major-mode-hook)))
+ (if (buffer-file-name)
+ (with-demoted-errors "File local-variables error: %s"
+ (hack-local-variables 'no-mode)))
+ (run-hooks 'after-change-major-mode-hook)
+ (dolist (form (nreverse delayed-after-hook-forms))
+ (eval form))
+ (setq delayed-after-hook-forms nil)))
(defmacro delay-mode-hooks (&rest body)
"Execute BODY, but delay any `run-mode-hooks'.
(message "%s%s" prompt (char-to-string char))
char))
+(defun read-multiple-choice (prompt choices)
+ "Ask user a multiple choice question.
+PROMPT should be a string that will be displayed as the prompt.
+
+CHOICES is an alist where the first element in each entry is a
+character to be entered, the second element is a short name for
+the entry to be displayed while prompting (if there's room, it
+might be shortened), and the third, optional entry is a longer
+explanation that will be displayed in a help buffer if the user
+requests more help.
+
+This function translates user input into responses by consulting
+the bindings in `query-replace-map'; see the documentation of
+that variable for more information. In this case, the useful
+bindings are `recenter', `scroll-up', and `scroll-down'. If the
+user enters `recenter', `scroll-up', or `scroll-down' responses,
+perform the requested window recentering or scrolling and ask
+again.
+
+The return value is the matching entry from the CHOICES list.
+
+Usage example:
+
+\(read-multiple-choice \"Continue connecting?\"
+ '((?a \"always\")
+ (?s \"session only\")
+ (?n \"no\")))"
+ (let* ((altered-names nil)
+ (full-prompt
+ (format
+ "%s (%s): "
+ prompt
+ (mapconcat
+ (lambda (elem)
+ (let* ((name (cadr elem))
+ (pos (seq-position name (car elem)))
+ (altered-name
+ (cond
+ ;; Not in the name string.
+ ((not pos)
+ (format "[%c] %s" (car elem) name))
+ ;; The prompt character is in the name, so highlight
+ ;; it on graphical terminals...
+ ((display-supports-face-attributes-p
+ '(:underline t) (window-frame))
+ (setq name (copy-sequence name))
+ (put-text-property pos (1+ pos)
+ 'face 'read-multiple-choice-face
+ name)
+ name)
+ ;; And put it in [bracket] on non-graphical terminals.
+ (t
+ (concat
+ (substring name 0 pos)
+ "["
+ (upcase (substring name pos (1+ pos)))
+ "]"
+ (substring name (1+ pos)))))))
+ (push (cons (car elem) altered-name)
+ altered-names)
+ altered-name))
+ (append choices '((?? "?")))
+ ", ")))
+ tchar buf wrong-char answer)
+ (save-window-excursion
+ (save-excursion
+ (while (not tchar)
+ (message "%s%s"
+ (if wrong-char
+ "Invalid choice. "
+ "")
+ full-prompt)
+ (setq tchar
+ (if (and (display-popup-menus-p)
+ last-input-event ; not during startup
+ (listp last-nonmenu-event)
+ use-dialog-box)
+ (x-popup-dialog
+ t
+ (cons prompt
+ (mapcar
+ (lambda (elem)
+ (cons (capitalize (cadr elem))
+ (car elem)))
+ choices)))
+ (condition-case nil
+ (let ((cursor-in-echo-area t))
+ (read-char))
+ (error nil))))
+ (setq answer (lookup-key query-replace-map (vector tchar) t))
+ (setq tchar
+ (cond
+ ((eq answer 'recenter)
+ (recenter) t)
+ ((eq answer 'scroll-up)
+ (ignore-errors (scroll-up-command)) t)
+ ((eq answer 'scroll-down)
+ (ignore-errors (scroll-down-command)) t)
+ ((eq answer 'scroll-other-window)
+ (ignore-errors (scroll-other-window)) t)
+ ((eq answer 'scroll-other-window-down)
+ (ignore-errors (scroll-other-window-down)) t)
+ (t tchar)))
+ (when (eq tchar t)
+ (setq wrong-char nil
+ tchar nil))
+ ;; The user has entered an invalid choice, so display the
+ ;; help messages.
+ (when (and (not (eq tchar nil))
+ (not (assq tchar choices)))
+ (setq wrong-char (not (memq tchar '(?? ?\C-h)))
+ tchar nil)
+ (when wrong-char
+ (ding))
+ (with-help-window (setq buf (get-buffer-create
+ "*Multiple Choice Help*"))
+ (with-current-buffer buf
+ (erase-buffer)
+ (pop-to-buffer buf)
+ (insert prompt "\n\n")
+ (let* ((columns (/ (window-width) 25))
+ (fill-column 21)
+ (times 0)
+ (start (point)))
+ (dolist (elem choices)
+ (goto-char start)
+ (unless (zerop times)
+ (if (zerop (mod times columns))
+ ;; Go to the next "line".
+ (goto-char (setq start (point-max)))
+ ;; Add padding.
+ (while (not (eobp))
+ (end-of-line)
+ (insert (make-string (max (- (* (mod times columns)
+ (+ fill-column 4))
+ (current-column))
+ 0)
+ ?\s))
+ (forward-line 1))))
+ (setq times (1+ times))
+ (let ((text
+ (with-temp-buffer
+ (insert (format
+ "%c: %s\n"
+ (car elem)
+ (cdr (assq (car elem) altered-names))))
+ (fill-region (point-min) (point-max))
+ (when (nth 2 elem)
+ (let ((start (point)))
+ (insert (nth 2 elem))
+ (unless (bolp)
+ (insert "\n"))
+ (fill-region start (point-max))))
+ (buffer-string))))
+ (goto-char start)
+ (dolist (line (split-string text "\n"))
+ (end-of-line)
+ (if (bolp)
+ (insert line "\n")
+ (insert line))
+ (forward-line 1)))))))))))
+ (when (buffer-live-p buf)
+ (kill-buffer buf))
+ (assq tchar choices)))
+
(defun sit-for (seconds &optional nodisp obsolete)
"Redisplay, then wait for SECONDS seconds. Stop when input is available.
SECONDS may be a floating-point value.
`inhibit-field-text-motion' is non-nil.
This function is like `forward-word', but it is not affected
-by `find-word-boundary-function-table' (as set up by
-e.g. `subword-mode'). It is also not interactive."
+by `find-word-boundary-function-table'. It is also not interactive."
(let ((find-word-boundary-function-table
(if (char-table-p word-move-empty-char-table)
word-move-empty-char-table
If ARG is omitted or nil, move point backward one word.
This function is like `forward-word', but it is not affected
-by `find-word-boundary-function-table' (as set up by
-e.g. `subword-mode'). It is also not interactive."
+by `find-word-boundary-function-table'. It is also not interactive."
(let ((find-word-boundary-function-table
(if (char-table-p word-move-empty-char-table)
word-move-empty-char-table
\f
;;; Misc.
+
+(defvar definition-prefixes (make-hash-table :test 'equal)
+ "Hash table mapping prefixes to the files in which they're used.
+This can be used to automatically fetch not-yet-loaded definitions.
+More specifically, if there is a value of the form (FILES...) for a string PREFIX
+it means that the FILES define variables or functions with names that start
+with PREFIX.
+
+Note that it does not imply that all definitions starting with PREFIX can
+be found in those files. E.g. if prefix is \"gnus-article-\" there might
+still be definitions of the form \"gnus-article-toto-titi\" in other files, which would
+presumably appear in this table under another prefix such as \"gnus-\"
+or \"gnus-article-toto-\".")
+
+(defun register-definition-prefixes (file prefixes)
+ "Register that FILE uses PREFIXES."
+ (dolist (prefix prefixes)
+ (puthash prefix (cons file (gethash prefix definition-prefixes))
+ definition-prefixes)))
+
(defconst menu-bar-separator '("--")
"Separator for menus.")
#include "buffer.h"
#include "coding.h"
#include "regex.h"
-#include "blockinput.h"
#ifdef MSDOS
#include "msdos.h" /* for fstatat */
#endif
+#ifdef WINDOWSNT
+extern int is_slow_fs (const char *);
+#endif
+
static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
static Lisp_Object file_attributes (int, char const *, Lisp_Object);
\f
DIR *d;
int fd, opendir_errno;
- block_input ();
-
#ifdef DOS_NT
/* Directories cannot be opened. The emulation assumes that any
file descriptor other than AT_FDCWD corresponds to the most
}
#endif
- unblock_input ();
-
if (!d)
report_file_errno ("Opening directory", dirname, opendir_errno);
*fdp = fd;
}
#ifdef WINDOWSNT
-void
+static void
directory_files_internal_w32_unwind (Lisp_Object arg)
{
Vw32_get_true_file_attributes = arg;
#endif
static void
-directory_files_internal_unwind (void *dh)
+directory_files_internal_unwind (void *d)
{
- DIR *d = dh;
- block_input ();
closedir (d);
- unblock_input ();
}
/* Return the next directory entry from DIR; DIR's name is DIRNAME.
#ifdef WINDOWSNT
if (attrs)
{
- extern int is_slow_fs (const char *);
-
/* Do this only once to avoid doing it (in w32.c:stat) for each
file in the directory, when we call Ffile_attributes below. */
record_unwind_protect (directory_files_internal_w32_unwind,
{
/* w32.c:stat will notice these bindings and avoid calling
GetDriveType for each file. */
- if (is_slow_fs (SDATA (dirfilename)))
+ if (is_slow_fs (SSDATA (dirfilename)))
Vw32_get_true_file_attributes = Qnil;
else
Vw32_get_true_file_attributes = Qt;
}
}
- block_input ();
closedir (d);
- unblock_input ();
#ifdef WINDOWSNT
if (attrs)
Vw32_get_true_file_attributes = w32_save;
These are all file names in directory DIRECTORY which begin with FILE.
This function ignores some of the possible completions as determined
- by the variables `completion-regexp-list' and
- `completion-ignored-extensions', which see. `completion-regexp-list'
+ by `completion-regexp-list', which see. `completion-regexp-list'
is matched against file and directory names relative to DIRECTORY. */)
(Lisp_Object file, Lisp_Object directory)
{
default, but we plan to change that, so you should specify a non-nil value
for ID-FORMAT if you use the returned uid or gid.
+To access the elements returned, the following access functions are
+provided: `file-attribute-type', `file-attribute-link-number',
+`file-attribute-user-id', `file-attribute-group-id',
+`file-attribute-access-time', `file-attribute-modification-time',
+`file-attribute-status-change-time', `file-attribute-size',
+`file-attribute-modes', `file-attribute-inode-number', and
+`file-attribute-device-number'.
+
Elements of the attribute list are:
0. t for directory, string (name linked to) for symbolic link, or nil.
1. Number of links to file.
if (!(NILP (id_format) || EQ (id_format, Qinteger)))
{
- block_input ();
uname = stat_uname (&s);
gname = stat_gname (&s);
- unblock_input ();
}
filemodestring (&s, modes);
(let (
;; Viper just turns itself off during batch use.
(noninteractive nil)
- ;; Switch off start up message or it will chew the key presses
+ ;; Switch off start up message or it will chew the key presses.
(viper-inhibit-startup-message 't)
;; Select an expert-level for the same reason.
(viper-expert-level 5)
(before-buffer (current-buffer)))
(unwind-protect
(progn
- ;; viper-mode is essentially global, so set it here
+ ;; viper-mode is essentially global, so set it here.
(viper-mode)
;; We must switch to buffer because we are using a keyboard macro
;; which appears to not go to the current-buffer but what ever is
(erase-buffer)
;; The new buffer fails to enter vi state so set it.
(viper-change-state-to-vi)
- ;; Run the macro
+ ;; Run the macro.
(execute-kbd-macro kmacro)
(let ((rtn
(buffer-substring-no-properties
(point-min)
(point-max))))
- ;; Kill the buffer iff the macro succeeds
+ ;; Kill the buffer iff the macro succeeds.
(kill-buffer)
rtn))
- ;; switch everthing off and restore the buffer
+ ;; Switch everything off and restore the buffer.
(toggle-viper-mode)
(switch-to-buffer before-buffer))))
(quote
(0 font-lock-keyword-face))))))))
+ (ert-deftest number-sequence-test ()
+ (should (= (length
+ (number-sequence (1- most-positive-fixnum) most-positive-fixnum))
+ 2))
+ (should (= (length
+ (number-sequence
+ (1+ most-negative-fixnum) most-negative-fixnum -1))
+ 2)))
+
(ert-deftest string-comparison-test ()
(should (string-lessp "abc" "acb"))
(should (string-lessp "aBc" "abc"))