commit d52bc534d799c255f24ff2a56e8bed830d8f68ca (HEAD, refs/remotes/origin/master) Author: Phillip Lord Date: Wed Jan 23 22:52:23 2019 +0000 ; Fix typos in NEWS diff --git a/etc/NEWS b/etc/NEWS index b15b167469..fe816ef0ec 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1192,12 +1192,12 @@ removed. * Lisp Changes in Emacs 27.1 - ++++ ** 'self-insert-command' takes the char to insert as (optional) argument. ** 'lookup-key' can take a list of keymaps as argument. -** New hook `input-event-functions` run whenever a user-input is read. +** New hook 'input-event-functions' run whenever a user-input is read. +++ ** 'condition-case' now accepts 't' to match any error symbol. commit 95b2f1a0c05fa72248afd87ebf79d0667dba0278 Author: Stefan Monnier Date: Wed Jan 23 17:27:21 2019 -0500 doc-view-presentation, doc-view-fit-window-to-page, and use mutool * lisp/doc-view.el (doc-view-pdfdraw-program): Use "mutool" if available. (doc-view-mode-map): Keep default 'g' binding of 'revert-buffer'. Change 'r' binding to 'revert-buffer'. (doc-view-revert-buffer): Make it an obsolete alias. (doc-view--revert-buffer): Rename from doc-view-revert-buffer, change calling convention for use in add-function. (doc-view-fit-window-to-page): New command. (doc-view-pdf->png-converter-mupdf): Make it work with "mutool". (doc-view-mode): Use add-function for revert-buffer-function. (doc-view-presentation-mode-map, doc-view-presentation--src-data): New vars. (doc-view-presentation-exit, doc-view-presentation-mode) (doc-view-presentation--propagate-pn, doc-view-presentation): New functions. diff --git a/etc/NEWS b/etc/NEWS index b0bbaeb6b0..b15b167469 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -334,6 +334,9 @@ the node "(emacs) Directory Variables" of the user manual. * Changes in Specialized Modes and Packages in Emacs 27.1 +** doc-view-mode +*** New commands doc-view-presentation and doc-view-fit-window-to-page + ** map.el *** Now also understands plists. *** Now defined via generic functions that can be extended via 'cl-defmethod'. diff --git a/lisp/doc-view.el b/lisp/doc-view.el index af025ec997..df8a9fc70f 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -155,12 +155,13 @@ (defcustom doc-view-ghostscript-program "gs" "Program to convert PS and PDF files to PNG." - :type 'file - :group 'doc-view) + :type 'file) (defcustom doc-view-pdfdraw-program (cond ((executable-find "pdfdraw") "pdfdraw") + ((executable-find "mudraw") "mudraw") + ((executable-find "mutool") "mutool") (t "mudraw")) "Name of MuPDF's program to convert PDF files to PNG." :type 'file @@ -185,14 +186,12 @@ "-dNOPAUSE" "-sDEVICE=png16m" "-dTextAlphaBits=4" "-dBATCH" "-dGraphicsAlphaBits=4" "-dQUIET") "A list of options to give to ghostscript." - :type '(repeat string) - :group 'doc-view) + :type '(repeat string)) (defcustom doc-view-resolution 100 "Dots per inch resolution used to render the documents. Higher values result in larger images." - :type 'number - :group 'doc-view) + :type 'number) (defcustom doc-view-scale-internally t "Whether we should try to rescale images ourselves. @@ -207,8 +206,7 @@ scaling." Has only an effect if `doc-view-scale-internally' is non-nil and support for scaling is compiled into emacs." :version "24.1" - :type 'number - :group 'doc-view) + :type 'number) (defcustom doc-view-dvipdfm-program "dvipdfm" "Program to convert DVI files to PDF. @@ -218,8 +216,7 @@ converted to PNG. If this and `doc-view-dvipdf-program' are set, `doc-view-dvipdf-program' will be preferred." - :type 'file - :group 'doc-view) + :type 'file) (defcustom doc-view-dvipdf-program "dvipdf" "Program to convert DVI files to PDF. @@ -229,8 +226,7 @@ converted to PNG. If this and `doc-view-dvipdfm-program' are set, `doc-view-dvipdf-program' will be preferred." - :type 'file - :group 'doc-view) + :type 'file) (define-obsolete-variable-alias 'doc-view-unoconv-program 'doc-view-odf->pdf-converter-program @@ -245,8 +241,7 @@ If this and `doc-view-dvipdfm-program' are set, Needed for viewing OpenOffice.org (and MS Office) files." :version "24.4" - :type 'file - :group 'doc-view) + :type 'file) (defcustom doc-view-odf->pdf-converter-function (cond @@ -267,22 +262,19 @@ Needed for viewing OpenOffice.org (and MS Office) files." "Program to convert PS files to PDF. PS files will be converted to PDF before searching is possible." - :type 'file - :group 'doc-view) + :type 'file) (defcustom doc-view-pdftotext-program "pdftotext" "Program to convert PDF files to plain text. Needed for searching." - :type 'file - :group 'doc-view) + :type 'file) (defcustom doc-view-cache-directory (expand-file-name (format "docview%d" (user-uid)) temporary-file-directory) "The base directory, where the PNG images will be saved." - :type 'directory - :group 'doc-view) + :type 'directory) (defvar doc-view-conversion-buffer " *doc-view conversion output*" "The buffer where messages from the converter programs go to.") @@ -293,8 +285,7 @@ After such a refresh newly converted pages will be available for viewing. If set to nil there won't be any refreshes and the pages won't be displayed before conversion of the whole document has finished." - :type 'integer - :group 'doc-view) + :type 'integer) (defcustom doc-view-continuous nil "In Continuous mode reaching the page edge advances to next/previous page. @@ -302,7 +293,6 @@ When non-nil, scrolling a line upward at the bottom edge of the page moves to the next page, and scrolling a line downward at the top edge of the page moves to the previous page." :type 'boolean - :group 'doc-view :version "23.2") ;;;; Internal Variables @@ -412,6 +402,7 @@ Typically \"page-%s.png\".") (define-key map "W" 'doc-view-fit-width-to-window) (define-key map "H" 'doc-view-fit-height-to-window) (define-key map "P" 'doc-view-fit-page-to-window) + (define-key map "F" 'doc-view-fit-window-to-page) ;F = frame ;; Killing the buffer (and the process) (define-key map (kbd "K") 'doc-view-kill-proc) ;; Slicing the image @@ -429,22 +420,20 @@ Typically \"page-%s.png\".") (define-key map (kbd "C-c C-c") 'doc-view-toggle-display) ;; Open a new buffer with doc's text contents (define-key map (kbd "C-c C-t") 'doc-view-open-text) - ;; Reconvert the current document. Don't just use revert-buffer - ;; because that resets the scale factor, the page number, ... - (define-key map (kbd "g") 'doc-view-revert-buffer) - (define-key map (kbd "r") 'doc-view-revert-buffer) + (define-key map (kbd "r") 'revert-buffer) map) "Keymap used by `doc-view-mode' when displaying a doc as a set of images.") -(defun doc-view-revert-buffer (&optional ignore-auto noconfirm) - "Like `revert-buffer', but preserves the buffer's current modes." - (interactive (list (not current-prefix-arg))) +(define-obsolete-function-alias 'doc-view-revert-buffer #'revert-buffer "27.1") +(defvar revert-buffer-preserve-modes) +(defun doc-view--revert-buffer (orig-fun &rest args) + "Preserve the buffer's current mode and check PDF sanity." (if (< undo-outer-limit (* 2 (buffer-size))) ;; It's normal for this operation to result in a very large undo entry. (setq-local undo-outer-limit (* 2 (buffer-size)))) (cl-labels ((revert () - (let (revert-buffer-function) - (revert-buffer ignore-auto noconfirm 'preserve-modes)))) + (let ((revert-buffer-preserve-modes t)) + (apply orig-fun args)))) (if (and (eq 'pdf doc-view-doc-type) (executable-find "pdfinfo")) ;; We don't want to revert if the PDF file is corrupted which @@ -492,6 +481,8 @@ Typically \"page-%s.png\".") ;;;; Navigation Commands +;; FIXME: The doc-view-current-* definitions below are macros because they +;; map to accessors which we want to use via `setf' as well! (defmacro doc-view-current-page (&optional win) `(image-mode-window-get 'page ,win)) (defmacro doc-view-current-info () '(image-mode-window-get 'info)) @@ -683,7 +674,7 @@ at the top edge of the page moves to the previous page." (file-error (error (format "Unable to use temporary directory %s: %s" - dir (mapconcat 'identity (cdr error) " ")))))))) + dir (mapconcat #'identity (cdr error) " ")))))))) (defun doc-view--current-cache-dir () "Return the directory where the png files of the current doc should be saved. @@ -872,6 +863,38 @@ min {(window-width / image-width), (window-height / image-height)} times." (setf (doc-view-current-slice) new-slice) (doc-view-goto-page (doc-view-current-page)))))) +(defun doc-view-fit-window-to-page () + "Resize selected window so it just fits the current page. +Resize the containing frame if needed." + (interactive) + (let* ((slice (doc-view-current-slice)) + (img-width (if slice (nth 2 slice) + (car (image-display-size + (image-get-display-property) t)))) + (img-height (if slice (nth 3 slice) + (cdr (image-display-size + (image-get-display-property) t)))) + (win-width (- (nth 2 (window-inside-pixel-edges)) + (nth 0 (window-inside-pixel-edges)))) + (win-height (- (nth 3 (window-inside-pixel-edges)) + (nth 1 (window-inside-pixel-edges)))) + (width-diff (- img-width win-width)) + (height-diff (- img-height win-height)) + (new-frame-params + (append + (if (= (window-width) (frame-width)) + `((width . (text-pixels + . ,(+ (frame-text-width) width-diff)))) + (enlarge-window (/ width-diff (frame-char-width)) 'horiz) + nil) + (if (= (window-height) (frame-height)) + `((height . (text-pixels + . ,(+ (frame-text-height) height-diff)))) + (enlarge-window (/ height-diff (frame-char-height)) nil) + nil)))) + (when new-frame-params + (modify-frame-parameters (selected-frame) new-frame-params)))) + (defun doc-view-reconvert-doc () "Reconvert the current document. Should be invoked when the cached images aren't up-to-date." @@ -906,7 +929,7 @@ Should be invoked when the cached images aren't up-to-date." (let* ((default-directory (or (unhandled-file-name-directory default-directory) (expand-file-name "~/"))) - (proc (apply 'start-process name doc-view-conversion-buffer + (proc (apply #'start-process name doc-view-conversion-buffer program args))) (push proc doc-view--current-converter-processes) (setq mode-line-process (list (format ":%s" proc))) @@ -960,7 +983,10 @@ If PAGE is nil, convert the whole document." (defun doc-view-pdf->png-converter-mupdf (pdf png page callback) (doc-view-start-process "pdf->png" doc-view-pdfdraw-program - `(,(concat "-o" png) + ;; FIXME: Ugly hack: recent mupdf distribution replaced "mudraw" with + ;; "mutool draw". + `(,@(if (string-match "mutool[^/\\]*$" doc-view-pdfdraw-program) '("draw")) + ,(concat "-o" png) ,(format "-r%d" (round doc-view-resolution)) ,pdf ,@(if page `(,(format "%d" page)))) @@ -1217,7 +1243,8 @@ dragging it to its bottom-right corner. See also (save-match-data (when (string-match (concat "%%BoundingBox: " "\\([[:digit:]]+\\) \\([[:digit:]]+\\) " - "\\([[:digit:]]+\\) \\([[:digit:]]+\\)") o) + "\\([[:digit:]]+\\) \\([[:digit:]]+\\)") + o) (mapcar #'string-to-number (list (match-string 1 o) (match-string 2 o) @@ -1301,10 +1328,10 @@ ARGS is a list of image descriptors." (let* ((image (if (and file (file-readable-p file)) (if (not (and doc-view-scale-internally (fboundp 'imagemagick-types))) - (apply 'create-image file doc-view--image-type nil args) + (apply #'create-image file doc-view--image-type nil args) (unless (member :width args) (setq args `(,@args :width ,doc-view-image-width))) - (apply 'create-image file 'imagemagick nil args)))) + (apply #'create-image file 'imagemagick nil args)))) (slice (doc-view-current-slice)) (img-width (and image (car (image-size image)))) (displayed-img-width (if (and image slice) @@ -1725,7 +1752,7 @@ If BACKWARD is non-nil, jump to the previous match." ;; window-parameters in the window-state(s) and then restoring this ;; window-state should call us back (to interpret/use those parameters). (doc-view-goto-page page) - (when slice (apply 'doc-view-set-slice slice)) + (when slice (apply #'doc-view-set-slice slice)) (current-buffer)))) (add-to-list 'desktop-buffer-mode-handlers @@ -1789,22 +1816,22 @@ toggle between displaying the document or editing it as text. (when (not (string= doc-view--buffer-file-name buffer-file-name)) (write-region nil nil doc-view--buffer-file-name)) - (setq-local revert-buffer-function #'doc-view-revert-buffer) + (add-function :around (local 'revert-buffer-function) #'doc-view--revert-buffer) (add-hook 'change-major-mode-hook (lambda () (doc-view-kill-proc) (remove-overlays (point-min) (point-max) 'doc-view t)) nil t) - (add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t) - (add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t) - (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer) + (add-hook 'clone-indirect-buffer-hook #'doc-view-clone-buffer-hook nil t) + (add-hook 'kill-buffer-hook #'doc-view-kill-proc nil t) + (setq-local desktop-save-buffer #'doc-view-desktop-save-buffer) (remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case. ;; Keep track of display info ([vh]scroll, page number, overlay, ;; ...) for each window in which this document is shown. (add-hook 'image-mode-new-window-functions - 'doc-view-new-window-function nil t) + #'doc-view-new-window-function nil t) (image-mode-setup-winprops) (setq-local mode-line-position @@ -1820,7 +1847,7 @@ toggle between displaying the document or editing it as text. #'doc-view-scroll-down-or-previous-page)) (setq-local cursor-type nil) (use-local-map doc-view-mode-map) - (add-hook 'after-revert-hook 'doc-view-reconvert-doc nil t) + (add-hook 'after-revert-hook #'doc-view-reconvert-doc nil t) (setq-local bookmark-make-record-function #'doc-view-bookmark-make-record) (setq mode-name "DocView" @@ -1862,8 +1889,7 @@ to the next best mode." "Toggle displaying buffer via Doc View (Doc View minor mode). See the command `doc-view-mode' for more information on this mode." - nil " DocView" doc-view-minor-mode-map - :group 'doc-view + :lighter " DocView" (when doc-view-minor-mode (add-hook 'change-major-mode-hook (lambda () (doc-view-minor-mode -1)) nil t) (message @@ -1881,6 +1907,84 @@ See the command `doc-view-mode' for more information on this mode." (interactive) (dired doc-view-cache-directory)) +;;;; Presentation mode + +(defvar doc-view-presentation-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\e" 'doc-view-presentation-exit) + (define-key map "q" 'doc-view-presentation-exit) + ;; (define-key map "C" 'doc-view-convert-all-pages) + map)) + +(defvar-local doc-view-presentation--src-data nil) + +(defun doc-view-presentation-exit () + "Leave Doc-View's presentation mode." + (interactive) + (doc-view-presentation-mode -1)) + +(define-minor-mode doc-view-presentation-mode + "Minor mode used while in presentation mode." + :init-value nil :keymap doc-view-presentation-mode-map + (if doc-view-presentation-mode + (progn + (set (make-local-variable 'mode-line-format) nil) + (doc-view-fit-page-to-window) + ;; (doc-view-convert-all-pages) + ) + (kill-local-variable 'mode-line-format) + (let ((pn (doc-view-current-page)) + (win (selected-window))) + (doc-view-presentation--propagate-pn doc-view-presentation--src-data pn) + (setq doc-view-presentation--src-data nil) + (with-selected-window win + (if (and (one-window-p) (window-dedicated-p)) + (delete-frame)))))) + +(defun doc-view-presentation--propagate-pn (src-data pn) + (when src-data + (let ((win (car src-data))) + (when (and (window-live-p win) + (eq (current-buffer) (window-buffer win))) + (select-window win)) + (when (eq (doc-view-current-page) (cdr src-data)) + (doc-view-goto-page pn))))) + +(defun doc-view-presentation () + "Put Doc-View in presentation mode." + (interactive) + (let* ((src-data (cons (selected-window) (doc-view-current-page))) + (mal (display-monitor-attributes-list)) + (monitor-top 0) + (monitor-left 0) + (monitor-height (display-pixel-height)) + (monitor-width (display-pixel-width))) + (dolist (attrs mal) + (when (memq (selected-frame) (alist-get 'frames attrs)) + (let ((geom (alist-get 'geometry attrs))) + (when geom + (setq monitor-top (nth 0 geom)) + (setq monitor-left (nth 1 geom)) + (setq monitor-width (nth 2 geom)) + (setq monitor-height (nth 3 geom)))))) + (let ((frame (make-frame + `((minibuffer . nil) + (fullscreen . fullboth) + (height . ,(ceiling monitor-height (frame-char-height))) + ;; Don't use `ceiling' here since doc-view will center the + ;; image instead. + (width . ,(ceiling monitor-width (frame-char-width))) + (name . "Doc-View-Presentation") + (top . ,monitor-top) (left . ,monitor-left) (user-position . t) + (vertical-scroll-bars . nil) + (left-fringe . 0) (right-fringe . 0) + (menu-bar-lines . 0) + (tool-bar-lines . 0))))) + (select-window (frame-root-window frame)) + (setq doc-view-presentation--src-data src-data) + (set-window-dedicated-p (selected-window) t) + (doc-view-presentation-mode 1)))) + ;;;; Bookmark integration commit dbc48d758ac90748df4befc677b2d21c5cd06d3b Author: Stefan Monnier Date: Wed Jan 23 16:02:11 2019 -0500 Avoid having to build src/emacs when we just want to `make tags` * Makefile.in (TAGS tags): Remove `src` from the dependencies. * src/Makefile.in (ctagsfiles1): Strip macuvs.h and fingerprint.c. diff --git a/Makefile.in b/Makefile.in index b6cd04d1f3..53703638c4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -944,7 +944,9 @@ extraclean: $(extraclean_dirs:=_extraclean) # The src subdir knows how to do the right thing # even when the build directory and source dir are different. .PHONY: TAGS tags -TAGS tags: lib lib-src src +# FIXME: We used to include `src` in the dependencies, not sure why. +# I removed it because it causes `make tags` to build Emacs. +TAGS tags: lib lib-src # src $(MAKE) -C src tags .PHONY: have-tests diff --git a/src/Makefile.in b/src/Makefile.in index 7eb5873267..5890eac8c6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -720,7 +720,10 @@ ETAGS = ../lib-src/etags${EXEEXT} ${ETAGS}: FORCE ${MAKE} -C ../lib-src $(notdir $@) -ctagsfiles1 = $(wildcard ${srcdir}/*.[hc]) +# Remove macuvs.h and fingerprint.c since they'd cause `src/emacs` +# to be built before we can get TAGS. +ctagsfiles1 = $(filter-out ${srcdir}/macuvs.h ${srcdir}/fingerprint.c, \ + $(wildcard ${srcdir}/*.[hc])) ctagsfiles2 = $(wildcard ${srcdir}/*.m) ## In out-of-tree builds, TAGS are generated in the build dir, like commit 191394276a4c455edd65e7f827fe8bc8317e8348 Author: Eli Zaretskii Date: Wed Jan 23 21:54:51 2019 +0200 ; * src/Makefile.in: Fix wording of comment in last change. diff --git a/src/Makefile.in b/src/Makefile.in index 48552908e4..7eb5873267 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -521,7 +521,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \ $(JSON_LIBS) $(GMP_LIB) -## FORCE it so that admin/unidata can decide whether these files are +## FORCE it so that admin/unidata can decide whether this file is ## up-to-date. Although since charprop depends on bootstrap-emacs, ## and emacs depends on charprop, in practice this rule was always run ## anyway. commit d39a9692d275b2d168fdbfd94b58b15899fe0027 Author: Eli Zaretskii Date: Wed Jan 23 21:53:29 2019 +0200 Fix build errors with pdump fingerprint on macOS * src/Makefile.in ($(lispsource)/international/charprop.el): Remove macuvs.h from the target list, to avoid circular dependency on macOS. Reported by Alan Third . diff --git a/src/Makefile.in b/src/Makefile.in index e0b7e3d1ef..48552908e4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -521,12 +521,12 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \ $(JSON_LIBS) $(GMP_LIB) -## FORCE it so that admin/unidata can decide whether these files -## are up-to-date. Although since charprop depends on bootstrap-emacs, -## and emacs (which recreates bootstrap-emacs) depends on charprop, -## in practice this rule was always run anyway. -$(srcdir)/macuvs.h $(lispsource)/international/charprop.el: \ - bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp) FORCE +## FORCE it so that admin/unidata can decide whether these files are +## up-to-date. Although since charprop depends on bootstrap-emacs, +## and emacs depends on charprop, in practice this rule was always run +## anyway. +$(lispsource)/international/charprop.el: \ + FORCE | bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp) $(MAKE) -C ../admin/unidata all EMACS="../$(bootstrap_exe)" ## We require charprop.el to exist before ucs-normalize.el is @@ -565,7 +565,6 @@ ifeq ($(DUMPING),unexec) cp -f $@ bootstrap-emacs$(EXEEXT) else rm -f $@ && cp -f temacs$(EXEEXT) $@ - cp -f $@ bootstrap-emacs$(EXEEXT) endif ifeq ($(DUMPING),pdumper) commit 3b75c5acd4de3cfbbc4612e01b91fce0fd3ba453 Author: Michael Albinus Date: Wed Jan 23 19:16:36 2019 +0100 ; More instrumentation of tramp-tests.el for hydra * test/lisp/net/tramp-tests.el (tramp--test-instrument-test-case): Adapt docstring. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 9278c2254b..c9532f54b7 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -3806,7 +3806,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-sh-p)) - (tramp--test-instrument-test-case 0 + (tramp--test-instrument-test-case 10 (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil))) (let ((default-directory tramp-test-temporary-file-directory) (tmp-name (tramp--test-make-temp-name nil quoted)) @@ -3873,7 +3873,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (skip-unless (tramp--test-sh-p)) (skip-unless (tramp--test-emacs27-p)) - (tramp--test-instrument-test-case 0 + (tramp--test-instrument-test-case 10 (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil))) (let ((default-directory tramp-test-temporary-file-directory) (tmp-name (tramp--test-make-temp-name nil quoted)) commit 42732e2f8d963f0ce97caf6172d146b0119f5e06 Author: Stefan Monnier Date: Wed Jan 23 12:30:54 2019 -0500 Rework last commit to icomplete and minibuffer.el. Rather than let minibuffer-force-complete set up cycling and then undoing it, better tell it directly not to setup cycling. Also be a bit more careful to remove the transient map. Additionally to bug#34077 and bug#34116, this also relates to bug#25644. * lisp/minibuffer.el (completion--flush-all-sorted-completions): Also take down the transient cycling map if applicable. (minibuffer-force-complete): New arg dont-cycle. Set completion-cycling to the actual function that takes down the transient map rather than just t. (minibuffer-force-complete-and-exit): * lisp/icomplete.el (icomplete-force-complete): Use new dont-cycle arg. diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 128fe6688b..10fd3a698c 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -165,17 +165,8 @@ the default otherwise." (defun icomplete-force-complete () "Complete the icomplete minibuffer." (interactive) - (let ((retval (minibuffer-force-complete))) - ;; FIXME: What's this, you ask? To deal with a cycling corner - ;; case, `minibuffer-force-complete' will transiently replace the - ;; keybinding that this command was called with, but at least - ;; returns a function which we can call to disable that, since - ;; we're not at all interested in cycling here (bug#34077). - (when (and completion-cycling (functionp retval)) (funcall retval))) - ;; Again, since we're not interested in cycling, we don't want - ;; prospects to be recalculted from a cache of rotated completions. - (setq completion-cycling nil) - (setq completion-all-sorted-completions nil)) + ;; We're not at all interested in cycling here (bug#34077). + (minibuffer-force-complete nil nil 'dont-cycle)) (defun icomplete-forward-completions () "Step forward completions by one entry. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 99cb66926b..c8b84b0e94 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -676,9 +676,9 @@ for use at QPOS." ;; (defmacro complete-in-turn (a b) `(completion-table-in-turn ,a ,b)) ;; (defmacro dynamic-completion-table (fun) `(completion-table-dynamic ,fun)) (define-obsolete-function-alias - 'complete-in-turn 'completion-table-in-turn "23.1") + 'complete-in-turn #'completion-table-in-turn "23.1") (define-obsolete-function-alias - 'dynamic-completion-table 'completion-table-dynamic "23.1") + 'dynamic-completion-table #'completion-table-dynamic "23.1") ;;; Minibuffer completion @@ -696,7 +696,7 @@ If ARGS are provided, then pass MESSAGE through `format-message'." (if (not (minibufferp (current-buffer))) (progn (if args - (apply 'message message args) + (apply #'message message args) (message "%s" message)) (prog1 (sit-for (or minibuffer-message-timeout 1000000)) (message nil))) @@ -1003,7 +1003,7 @@ completion candidates than this number." (defvar-local completion-all-sorted-completions nil) (defvar-local completion--all-sorted-completions-location nil) -(defvar completion-cycling nil) +(defvar completion-cycling nil) ;Function that takes down the cycling map. (defvar completion-fail-discreetly nil "If non-nil, stay quiet when there is no match.") @@ -1035,7 +1035,7 @@ when the buffer's text is already an exact match." (let* ((string (buffer-substring beg end)) (md (completion--field-metadata beg)) (comp (funcall (or try-completion-function - 'completion-try-completion) + #'completion-try-completion) string minibuffer-completion-table minibuffer-completion-predicate @@ -1188,7 +1188,7 @@ scroll the window of possible completions." (defun completion--cache-all-sorted-completions (beg end comps) (add-hook 'after-change-functions - 'completion--flush-all-sorted-completions nil t) + #'completion--flush-all-sorted-completions nil t) (setq completion--all-sorted-completions-location (cons (copy-marker beg) (copy-marker end))) (setq completion-all-sorted-completions comps)) @@ -1198,8 +1198,10 @@ scroll the window of possible completions." (or (> start (cdr completion--all-sorted-completions-location)) (< end (car completion--all-sorted-completions-location)))) (remove-hook 'after-change-functions - 'completion--flush-all-sorted-completions t) - (setq completion-cycling nil) + #'completion--flush-all-sorted-completions t) + ;; Remove the transient map if applicable. + (when completion-cycling + (funcall (prog1 completion-cycling (setq completion-cycling nil)))) (setq completion-all-sorted-completions nil))) (defun completion--metadata (string base md-at-point table pred) @@ -1263,16 +1265,17 @@ scroll the window of possible completions." ;; unnecessary call would mess up the final result value ;; (bug#34116). (unless completion-cycling - (minibuffer-force-complete)) + (minibuffer-force-complete nil nil 'dont-cycle)) (completion--complete-and-exit (minibuffer-prompt-end) (point-max) #'exit-minibuffer ;; If the previous completion completed to an element which fails ;; test-completion, then we shouldn't exit, but that should be rare. (lambda () (minibuffer-message "Incomplete")))) -(defun minibuffer-force-complete (&optional start end) +(defun minibuffer-force-complete (&optional start end dont-cycle) "Complete the minibuffer to an exact match. -Repeated uses step through the possible completions." +Repeated uses step through the possible completions. +DONT-CYCLE tells the function not to setup cycling." (interactive) (setq minibuffer-scroll-window nil) ;; FIXME: Need to deal with the extra-size issue here as well. @@ -1285,7 +1288,7 @@ Repeated uses step through the possible completions." (base (+ start (or (cdr (last all)) 0)))) (cond ((not (consp all)) - (completion--message + (completion--message (if all "No more completions" "No completions"))) ((not (consp (cdr all))) (let ((done (equal (car all) (buffer-substring-no-properties base end)))) @@ -1296,33 +1299,34 @@ Repeated uses step through the possible completions." (completion--replace base end (car all)) (setq end (+ base (length (car all)))) (completion--done (buffer-substring-no-properties start (point)) 'sole) - ;; Set cycling after modifying the buffer since the flush hook resets it. - (setq completion-cycling t) (setq this-command 'completion-at-point) ;For completion-in-region. - ;; If completing file names, (car all) may be a directory, so we'd now - ;; have a new set of possible completions and might want to reset - ;; completion-all-sorted-completions to nil, but we prefer not to, - ;; so that repeated calls minibuffer-force-complete still cycle - ;; through the previous possible completions. - (let ((last (last all))) - (setcdr last (cons (car all) (cdr last))) - (completion--cache-all-sorted-completions start end (cdr all))) - ;; Make sure repeated uses cycle, even though completion--done might - ;; have added a space or something that moved us outside of the field. - ;; (bug#12221). - (let* ((table minibuffer-completion-table) - (pred minibuffer-completion-predicate) - (extra-prop completion-extra-properties) - (cmd - (lambda () "Cycle through the possible completions." - (interactive) - (let ((completion-extra-properties extra-prop)) - (completion-in-region start (point) table pred))))) - (set-transient-map - (let ((map (make-sparse-keymap))) - (define-key map [remap completion-at-point] cmd) - (define-key map (vector last-command-event) cmd) - map))))))) + ;; Set cycling after modifying the buffer since the flush hook resets it. + (unless dont-cycle + ;; If completing file names, (car all) may be a directory, so we'd now + ;; have a new set of possible completions and might want to reset + ;; completion-all-sorted-completions to nil, but we prefer not to, + ;; so that repeated calls minibuffer-force-complete still cycle + ;; through the previous possible completions. + (let ((last (last all))) + (setcdr last (cons (car all) (cdr last))) + (completion--cache-all-sorted-completions start end (cdr all))) + ;; Make sure repeated uses cycle, even though completion--done might + ;; have added a space or something that moved us outside of the field. + ;; (bug#12221). + (let* ((table minibuffer-completion-table) + (pred minibuffer-completion-predicate) + (extra-prop completion-extra-properties) + (cmd + (lambda () "Cycle through the possible completions." + (interactive) + (let ((completion-extra-properties extra-prop)) + (completion-in-region start (point) table pred))))) + (setq completion-cycling + (set-transient-map + (let ((map (make-sparse-keymap))) + (define-key map [remap completion-at-point] cmd) + (define-key map (vector last-command-event) cmd) + map))))))))) (defvar minibuffer-confirm-exit-commands '(completion-at-point minibuffer-complete @@ -1540,7 +1544,7 @@ horizontally in alphabetical order, rather than down the screen." Uses columns to keep the listing readable but compact. It also eliminates runs of equal strings." (when (consp strings) - (let* ((length (apply 'max + (let* ((length (apply #'max (mapcar (lambda (s) (if (consp s) (+ (string-width (car s)) @@ -2329,7 +2333,7 @@ same as `substitute-in-file-name'." (match-beginning 0))))))) (t (if (eq (aref string (1- beg)) ?{) - (setq table (apply-partially 'completion-table-with-terminator + (setq table (apply-partially #'completion-table-with-terminator "}" table))) ;; Even if file-name completion is case-insensitive, we want ;; envvar completion to be case-sensitive. @@ -2463,7 +2467,7 @@ except that it passes the file name through `substitute-in-file-name'.") #'completion--file-name-table) "Internal subroutine for `read-file-name'. Do not call this.") -(defvar read-file-name-function 'read-file-name-default +(defvar read-file-name-function #'read-file-name-default "The function called by `read-file-name' to do its work. It should accept the same arguments as `read-file-name'.") @@ -2738,8 +2742,8 @@ See `read-file-name' for the meaning of the arguments." BUFFER nil or omitted means use the current buffer. Like `internal-complete-buffer', but removes BUFFER from the completion list." (let ((except (if (stringp buffer) buffer (buffer-name buffer)))) - (apply-partially 'completion-table-with-predicate - 'internal-complete-buffer + (apply-partially #'completion-table-with-predicate + #'internal-complete-buffer (lambda (name) (not (equal (if (consp name) (car name) name) except))) nil))) @@ -3409,7 +3413,7 @@ the same set of elements." (when newstr (completion-pcm-try-completion newstr table pred (length newstr))))) -(defvar completing-read-function 'completing-read-default +(defvar completing-read-function #'completing-read-default "The function called by `completing-read' to do its work. It should accept the same arguments as `completing-read'.") commit b3dfcf3e9f217919903f3469323fcd1386a16893 Author: Michael Albinus Date: Wed Jan 23 18:07:40 2019 +0100 ; Instrument tramp-tests.el for hydra. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 58860c7161..9278c2254b 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -3806,6 +3806,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-sh-p)) + (tramp--test-instrument-test-case 0 (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil))) (let ((default-directory tramp-test-temporary-file-directory) (tmp-name (tramp--test-make-temp-name nil quoted)) @@ -3863,7 +3864,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (should (string-equal (buffer-string) "foo"))) ;; Cleanup. - (ignore-errors (delete-process proc)))))) + (ignore-errors (delete-process proc))))))) (ert-deftest tramp-test30-make-process () "Check `make-process'." commit b9add0a5a7eddcf80a189c478b39a5cb7a12befe Author: João Távora Date: Wed Jan 23 16:30:41 2019 +0000 Force completion in icomplete with C-M-i, but don't cycle (bug#34077) Cycling after forcing a completion with C-M-i in icomplete can be confusing, as it leaves rotated prospects in the minibuffer. In C-x C-f, for example it is very difficult to understand if the prospects refer to subdirectories of the directory being completed to, which happens naturally when the completion is unique; or if they are a cycled version of prospects that match the new completion pattern, in case the completion happens to still match other items. To resolve this confusion, never cycle with C-M-i in icomplete: non-ambiguous cycling can be achieved with C-. and C-, The former behaviour can still be restored with: (define-key icomplete-minibuffer-map (kbd "C-M-i") 'minibuffer-force-complete) * lisp/icomplete.el (icomplete-force-complete): New command. (icomplete-minibuffer-map): Bind C-M-i to icomplete-force-complete. diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 6d77c0649a..128fe6688b 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -145,7 +145,7 @@ icompletion is occurring." (defvar icomplete-minibuffer-map (let ((map (make-sparse-keymap))) - (define-key map [?\M-\t] 'minibuffer-force-complete) + (define-key map [?\M-\t] 'icomplete-force-complete) (define-key map [?\C-j] 'icomplete-force-complete-and-exit) (define-key map [?\C-.] 'icomplete-forward-completions) (define-key map [?\C-,] 'icomplete-backward-completions) @@ -162,6 +162,21 @@ the default otherwise." (minibuffer-force-complete-and-exit) (minibuffer-complete-and-exit))) +(defun icomplete-force-complete () + "Complete the icomplete minibuffer." + (interactive) + (let ((retval (minibuffer-force-complete))) + ;; FIXME: What's this, you ask? To deal with a cycling corner + ;; case, `minibuffer-force-complete' will transiently replace the + ;; keybinding that this command was called with, but at least + ;; returns a function which we can call to disable that, since + ;; we're not at all interested in cycling here (bug#34077). + (when (and completion-cycling (functionp retval)) (funcall retval))) + ;; Again, since we're not interested in cycling, we don't want + ;; prospects to be recalculted from a cache of rotated completions. + (setq completion-cycling nil) + (setq completion-all-sorted-completions nil)) + (defun icomplete-forward-completions () "Step forward completions by one entry. Second entry becomes the first and can be selected with commit 210e592e55ade154c8d58bd467711fb69368f6cb Author: João Távora Date: Wed Jan 23 16:17:03 2019 +0000 Avoid cycling in minibuffer-force-complete-and-exit (bug#34116) * lisp/minibuffer.el (minibuffer-force-complete-and-exit): Check completion-cycling before minibuffer-force-complete. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 5760a2e49d..99cb66926b 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1257,7 +1257,13 @@ scroll the window of possible completions." (defun minibuffer-force-complete-and-exit () "Complete the minibuffer with first of the matches and exit." (interactive) - (minibuffer-force-complete) + ;; If `completion-cycling' is t, then surely a + ;; `minibuffer-force-complete' has already executed. This is not + ;; just for speed: the extra rotation caused by the second + ;; unnecessary call would mess up the final result value + ;; (bug#34116). + (unless completion-cycling + (minibuffer-force-complete)) (completion--complete-and-exit (minibuffer-prompt-end) (point-max) #'exit-minibuffer ;; If the previous completion completed to an element which fails commit d9779c377dabcbc3a002069084d72191ce059496 Author: Paul Eggert Date: Wed Jan 23 08:01:37 2019 -0800 * src/keyboard.c (read_char): Use CALLN. diff --git a/src/keyboard.c b/src/keyboard.c index 838dc242dd..b3b55e73b6 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2919,7 +2919,7 @@ read_char (int commandflag, Lisp_Object map, if (! NILP (also_record)) record_char (also_record); - Frun_hook_with_args (2, ((Lisp_Object []) {Qinput_event_functions, c})); + CALLN (Frun_hook_with_args, Qinput_event_functions, c); /* Wipe the echo area. But first, if we are about to use an input method, commit 3a0c7b1e60066a10ebe666e24e437918b971d1e2 Author: Stefan Monnier Date: Wed Jan 23 10:56:26 2019 -0500 * src/emacs.c (load_pdump): Minor simplification. diff --git a/src/emacs.c b/src/emacs.c index b9f5039724..2738c7ca3f 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -732,14 +732,15 @@ load_pdump (int argc, char **argv) result = PDUMPER_NOT_LOADED; if (dump_file) - result = pdumper_load (dump_file); - - if (dump_file && result != PDUMPER_LOAD_SUCCESS) - fatal ("could not load dump file \"%s\": %s", - dump_file, dump_error_to_string (result)); + { + result = pdumper_load (dump_file); - if (result == PDUMPER_LOAD_SUCCESS) - goto out; + if (result != PDUMPER_LOAD_SUCCESS) + fatal ("could not load dump file \"%s\": %s", + dump_file, dump_error_to_string (result)); + else + goto out; + } /* Look for a dump file in the same directory as the executable; it should have the same basename. */ commit 43cf9b968a1745ae559f8c93db50008d31fcc281 Author: Eli Zaretskii Date: Wed Jan 23 17:40:10 2019 +0200 Fix compilation of pdumper.c with old buggy GCC * src/pdumper.c (emacs_ptr_at): Renamed from emacs_ptr, to avoid compilation errors with GCC 4.7. Reported by Martin Rudalics . All callers changed. diff --git a/src/pdumper.c b/src/pdumper.c index 6be26dc816..976d35d47d 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -707,7 +707,7 @@ emacs_basis (void) } static void * -emacs_ptr (const ptrdiff_t offset) +emacs_ptr_at (const ptrdiff_t offset) { /* TODO: assert somehow that the result is actually in the Emacs image. */ @@ -5330,24 +5330,24 @@ dump_do_emacs_relocation ( { case RELOC_EMACS_COPY_FROM_DUMP: eassume (reloc.length > 0); - memcpy (emacs_ptr (reloc.emacs_offset), + memcpy (emacs_ptr_at (reloc.emacs_offset), dump_ptr (dump_base, reloc.u.dump_offset), reloc.length); break; case RELOC_EMACS_IMMEDIATE: eassume (reloc.length > 0); eassume (reloc.length <= sizeof (reloc.u.immediate)); - memcpy (emacs_ptr (reloc.emacs_offset), + memcpy (emacs_ptr_at (reloc.emacs_offset), &reloc.u.immediate, reloc.length); break; case RELOC_EMACS_DUMP_PTR_RAW: pval = reloc.u.dump_offset + dump_base; - memcpy (emacs_ptr (reloc.emacs_offset), &pval, sizeof (pval)); + memcpy (emacs_ptr_at (reloc.emacs_offset), &pval, sizeof (pval)); break; case RELOC_EMACS_EMACS_PTR_RAW: pval = reloc.u.emacs_offset2 + emacs_basis (); - memcpy (emacs_ptr (reloc.emacs_offset), &pval, sizeof (pval)); + memcpy (emacs_ptr_at (reloc.emacs_offset), &pval, sizeof (pval)); break; case RELOC_EMACS_DUMP_LV: case RELOC_EMACS_EMACS_LV: @@ -5356,12 +5356,12 @@ dump_do_emacs_relocation ( eassume (reloc.length <= Lisp_Float); void *obj_ptr = reloc.type == RELOC_EMACS_DUMP_LV ? dump_ptr (dump_base, reloc.u.dump_offset) - : emacs_ptr (reloc.u.emacs_offset2); + : emacs_ptr_at (reloc.u.emacs_offset2); if (reloc.length == Lisp_Symbol) lv = make_lisp_symbol (obj_ptr); else lv = make_lisp_ptr (obj_ptr, reloc.length); - memcpy (emacs_ptr (reloc.emacs_offset), &lv, sizeof (lv)); + memcpy (emacs_ptr_at (reloc.emacs_offset), &lv, sizeof (lv)); break; } default: commit 927d9f12173aab413868bd8d5abd42887b000e4e Author: Michael Albinus Date: Wed Jan 23 15:23:57 2019 +0100 * lisp/net/tramp.el (tramp-set-file-uid-gid): Fix thinko. * test/lisp/net/tramp-tests.el (tramp--test-instrument-test-case): Adapt docstring. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 6428e18331..3c7770af87 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -4355,9 +4355,11 @@ depending whether FILENAME is remote or local. Both parameters must be non-negative integers. The setgid bit of the upper directory is respected. If FILENAME is remote, a file name handler is called." - (unless (zerop (logand #o2000 (file-modes (file-name-directory filename)))) - (setq gid (tramp-compat-file-attribute-group-id - (file-attributes (file-name-directory filename) 'integer)))) + (let* ((dir (file-name-directory filename)) + (modes (file-modes dir))) + (when (and modes (not (zerop (logand modes #o2000)))) + (setq gid (tramp-compat-file-attribute-group-id (file-attributes dir))))) + (let ((handler (find-file-name-handler filename 'tramp-set-file-uid-gid))) (if handler (funcall handler 'tramp-set-file-uid-gid filename uid gid) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 9deb794f40..58860c7161 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -161,9 +161,9 @@ This shall used dynamically bound only.") (defmacro tramp--test-instrument-test-case (verbose &rest body) "Run BODY with `tramp-verbose' equal VERBOSE. -Print the content of the Tramp debug buffer, if BODY does not -eval properly in `should' or `should-not'. `should-error' is not -handled properly. BODY shall not contain a timeout." +Print the content of the Tramp connection and debug buffers, if +`tramp-verbose' is greater than 3. `should-error' is not handled +properly. BODY shall not contain a timeout." (declare (indent 1) (debug (natnump body))) `(let ((tramp-verbose (max (or ,verbose 0) (or tramp-verbose 0))) (tramp-message-show-message t) @@ -2251,7 +2251,6 @@ This checks also `file-name-as-directory', `file-name-directory', "Check `copy-file'." (skip-unless (tramp--test-enabled)) - (tramp--test-instrument-test-case (if (getenv "EMACS_EMBA_CI") 10 0) ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579. (dolist (quoted (if (and (tramp--test-expensive-test) (tramp--test-emacs27-p)) '(nil t) '(nil))) @@ -2278,10 +2277,10 @@ This checks also `file-name-as-directory', `file-name-directory', (with-temp-buffer (insert-file-contents target) (should (string-equal (buffer-string) "foo"))) - ;; (when (tramp--test-expensive-test) - ;; (should-error - ;; (copy-file source target) - ;; :type 'file-already-exists)) + (when (tramp--test-expensive-test) + (should-error + (copy-file source target) + :type 'file-already-exists)) (copy-file source target 'ok)) ;; Cleanup. @@ -2297,11 +2296,11 @@ This checks also `file-name-as-directory', `file-name-directory', (should (file-exists-p source)) (make-directory target) (should (file-directory-p target)) - ;; ;; This has been changed in Emacs 26.1. - ;; (when (and (tramp--test-expensive-test) (tramp--test-emacs26-p)) - ;; (should-error - ;; (copy-file source target) - ;; :type 'file-already-exists)) + ;; This has been changed in Emacs 26.1. + (when (and (tramp--test-expensive-test) (tramp--test-emacs26-p)) + (should-error + (copy-file source target) + :type 'file-already-exists)) (copy-file source (file-name-as-directory target)) (should (file-exists-p @@ -2358,7 +2357,7 @@ This checks also `file-name-as-directory', `file-name-directory', ;; Cleanup. (ignore-errors (delete-directory source 'recursive)) - (ignore-errors (delete-directory target 'recursive))))))))) + (ignore-errors (delete-directory target 'recursive)))))))) (ert-deftest tramp-test12-rename-file () "Check `rename-file'."