aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog447
-rw-r--r--lisp/autoinsert.el5
-rw-r--r--lisp/autorevert.el158
-rw-r--r--lisp/buff-menu.el10
-rw-r--r--lisp/calendar/todo-mode.el539
-rw-r--r--lisp/cedet/ChangeLog2
-rw-r--r--lisp/desktop.el39
-rw-r--r--lisp/doc-view.el14
-rw-r--r--lisp/edmacro.el73
-rw-r--r--lisp/emacs-lisp/.gitignore2
-rw-r--r--lisp/emacs-lisp/cl-macs.el12
-rw-r--r--lisp/emacs-lisp/edebug.el26
-rw-r--r--lisp/emacs-lisp/ert.el173
-rw-r--r--lisp/emacs-lisp/map-ynp.el5
-rw-r--r--lisp/emacs-lisp/pcase.el17
-rw-r--r--lisp/emulation/viper-cmd.el101
-rw-r--r--lisp/emulation/viper-keym.el2
-rw-r--r--lisp/emulation/viper.el66
-rw-r--r--lisp/faces.el7
-rw-r--r--lisp/filenotify.el324
-rw-r--r--lisp/files.el10
-rw-r--r--lisp/filesets.el6
-rw-r--r--lisp/frame.el28
-rw-r--r--lisp/gnus/ChangeLog57
-rw-r--r--lisp/gnus/auth-source.el4
-rw-r--r--lisp/gnus/gnus-art.el3
-rw-r--r--lisp/gnus/gnus-msg.el1
-rw-r--r--lisp/gnus/gnus-registry.el23
-rw-r--r--lisp/gnus/gnus-start.el5
-rw-r--r--lisp/gnus/gnus-sum.el27
-rw-r--r--lisp/gnus/gnus.el4
-rw-r--r--lisp/gnus/message.el2
-rw-r--r--lisp/gnus/mm-view.el22
-rw-r--r--lisp/gnus/nnir.el6
-rw-r--r--lisp/gnus/nnml.el5
-rw-r--r--lisp/ibuffer.el1
-rw-r--r--lisp/ido.el152
-rw-r--r--lisp/info-xref.el23
-rw-r--r--lisp/info.el43
-rw-r--r--lisp/international/mule.el24
-rw-r--r--lisp/net/shr.el1
-rw-r--r--lisp/net/tramp-cache.el6
-rw-r--r--lisp/net/tramp-gvfs.el3
-rw-r--r--lisp/net/tramp-sh.el175
-rw-r--r--lisp/net/tramp.el147
-rw-r--r--lisp/progmodes/cc-engine.el32
-rw-r--r--lisp/progmodes/cfengine.el4
-rw-r--r--lisp/progmodes/ebrowse.el23
-rw-r--r--lisp/progmodes/gdb-mi.el23
-rw-r--r--lisp/progmodes/python.el9
-rw-r--r--lisp/progmodes/ruby-mode.el108
-rw-r--r--lisp/shadowfile.el23
-rw-r--r--lisp/simple.el202
-rw-r--r--lisp/subr.el56
-rw-r--r--lisp/thumbs.el18
-rw-r--r--lisp/vc/ediff.el73
-rw-r--r--lisp/wid-edit.el11
-rw-r--r--lisp/window.el19
58 files changed, 2337 insertions, 1064 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 86a27f9b5bd..5451abc2119 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,441 @@
12013-07-13 Dmitry Gutov <dgutov@yandex.ru>
2
3 * progmodes/ruby-mode.el (ruby-font-lock-keywords): Highlight
4 conversion methods on Kernel.
5
62013-07-13 Alan Mackenzie <acm@muc.de>
7
8 * progmodes/cc-engine.el (c-forward-decl-or-cast-1): Label CASE 13
9 and comment it out. This out-commenting enables certain C++
10 declarations to be parsed correctly.
11
122013-07-13 Eli Zaretskii <eliz@gnu.org>
13
14 * international/mule.el (define-coding-system): Doc fix.
15
16 * simple.el (default-font-height): Don't call font-info if the
17 frame's default font didn't change since the frame was created.
18 (Bug#14838)
19
202013-07-13 Leo Liu <sdl.web@gmail.com>
21
22 * ido.el (ido-read-file-name): Guard against non-symbol value.
23
242013-07-13 Fabián Ezequiel Gallina <fgallina@gnu.org>
25
26 * progmodes/python.el (python-imenu--build-tree): Fix corner case
27 in nested defuns.
28
292013-07-13 Leo Liu <sdl.web@gmail.com>
30
31 * ido.el (ido-exhibit): Handle ido-enter-matching-directory before
32 ido-set-matches call. (Bug#6852)
33
342013-07-12 Dmitry Gutov <dgutov@yandex.ru>
35
36 * progmodes/ruby-mode.el (ruby-percent-literals-beg-re):
37 (ruby-syntax-expansion-allowed-p): Support array of symbols, for
38 Ruby 2.0.
39 (ruby-font-lock-keywords): Distinguish calls to functions with
40 module-like names from module references. Highlight character
41 literals.
42
432013-07-12 Sergio Durigan Junior <sergiodj@riseup.net> (tiny change)
44
45 * progmodes/gdb-mi.el (gdb-strip-string-backslash): New function.
46 (gdb-send): Handle continued commands. (Bug#14847)
47
482013-07-12 Juanma Barranquero <lekktu@gmail.com>
49
50 * desktop.el (desktop--v2s): Remove unused local variable.
51 (desktop-save-buffer): Make defvar-local; adjust docstring.
52 (desktop-auto-save-timeout, desktop-owner): Use ignore-errors.
53 (desktop-clear, desktop-save-buffer-p): Use string-match-p.
54
552013-07-12 Andreas Schwab <schwab@linux-m68k.org>
56
57 * emacs-lisp/map-ynp.el (map-y-or-n-p): Fix last change.
58
592013-07-12 Eli Zaretskii <eliz@gnu.org>
60
61 * simple.el (next-line, previous-line): Document TRY-VSCROLL and ARG.
62 (Bug#14842)
63
642013-07-12 Glenn Morris <rgm@gnu.org>
65
66 * doc-view.el: Require cl-lib at runtime too.
67 (doc-view-remove-if): Remove.
68 (doc-view-search-next-match, doc-view-search-previous-match):
69 Use cl-remove-if.
70
71 * edmacro.el: Require cl-lib at runtime too.
72 (edmacro-format-keys, edmacro-parse-keys): Use cl-mismatch, cl-subseq.
73 (edmacro-mismatch, edmacro-subseq): Remove.
74
75 * shadowfile.el: Require cl-lib.
76 (shadow-remove-if): Remove.
77 (shadow-set-cluster, shadow-shadows-of-1, shadow-remove-from-todo):
78 Use cl-remove-if.
79
80 * wid-edit.el: Require cl-lib.
81 (widget-choose): Use cl-remove-if.
82 (widget-remove-if): Remove.
83
84 * progmodes/ebrowse.el: Require cl-lib at runtime too.
85 (ebrowse-delete-if-not): Remove.
86 (ebrowse-browser-buffer-list, ebrowse-member-buffer-list)
87 (ebrowse-tree-buffer-list, ebrowse-same-tree-member-buffer-list):
88 Use cl-delete-if-not.
89
902013-07-12 Juanma Barranquero <lekktu@gmail.com>
91
92 * emacs-lisp/cl-macs.el (cl-multiple-value-bind, cl-multiple-value-setq)
93 (cl-the, cl-declare, cl-defstruct): Fix typos in docstrings.
94
952013-07-12 Leo Liu <sdl.web@gmail.com>
96
97 * ido.el (dired-do-copy, dired): Set 'ido property. (Bug#11954)
98
992013-07-11 Glenn Morris <rgm@gnu.org>
100
101 * emacs-lisp/edebug.el: Require cl-lib at run-time too.
102 (edebug-gensym-index, edebug-gensym):
103 Remove reimplementation of cl-gensym.
104 (edebug-make-enter-wrapper, edebug-make-form-wrapper): Use cl-gensym.
105
106 * thumbs.el: Require cl-lib at run-time too.
107 (thumbs-gensym-counter, thumbs-gensym):
108 Remove reimplementation of cl-gensym.
109 (thumbs-temp-file): Use cl-gensym.
110
111 * emacs-lisp/ert.el: Require cl-lib at runtime too.
112 (ert--cl-do-remf, ert--remprop, ert--remove-if-not)
113 (ert--intersection, ert--set-difference, ert--set-difference-eq)
114 (ert--union, ert--gensym-counter, ert--gensym-counter)
115 (ert--coerce-to-vector, ert--remove*, ert--string-position)
116 (ert--mismatch, ert--subseq): Remove reimplementations of cl funcs.
117 (ert-make-test-unbound, ert--expand-should-1)
118 (ert--expand-should, ert--should-error-handle-error)
119 (should-error, ert--explain-equal-rec)
120 (ert--plist-difference-explanation, ert-select-tests)
121 (ert--make-stats, ert--remove-from-list, ert--string-first-line):
122 Use cl-lib functions rather than reimplementations.
123
1242013-07-11 Michael Albinus <michael.albinus@gmx.de>
125
126 * net/tramp.el (tramp-methods): Extend docstring.
127 (tramp-connection-timeout): New defcustom.
128 (tramp-error-with-buffer): Reset timestamp only when appropriate.
129 (with-tramp-progress-reporter): Simplify.
130 (tramp-process-actions): Improve messages.
131
132 * net/tramp-gvfs.el (tramp-gvfs-maybe-open-connection):
133 * net/tramp-sh.el (tramp-maybe-open-connection):
134 Use `tramp-connection-timeout'.
135 (tramp-methods) [su, sudo, ksu]: Add method specific timeouts.
136 (Bug#14808)
137
1382013-07-11 Leo Liu <sdl.web@gmail.com>
139
140 * ido.el (ido-read-file-name): Conform to the requirements of
141 read-file-name. (Bug#11861)
142 (ido-read-directory-name): Conform to the requirements of
143 read-directory-name.
144
1452013-07-11 Juanma Barranquero <lekktu@gmail.com>
146
147 * subr.el (delay-warning): New function.
148
1492013-07-10 Eli Zaretskii <eliz@gnu.org>
150
151 * simple.el (default-line-height): New function.
152 (line-move-partial, line-move): Use it instead of computing the
153 line height inline.
154 (line-move-partial): Always compute ROWH. If the last line is
155 partially-visible, but its text is completely visible, allow
156 cursor to enter such a partially-visible line.
157
1582013-07-10 Michael Albinus <michael.albinus@gmx.de>
159
160 Improve error messages. (Bug#14808)
161
162 * net/tramp.el (tramp-current-connection): New defvar, moved from
163 tramp-sh.el.
164 (tramp-message-show-progress-reporter-message): Removed, not
165 needed anymore.
166 (tramp-error-with-buffer): Show message in minibuffer. Discard
167 input before waiting. Reset connection timestamp.
168 (with-tramp-progress-reporter): Improve messages.
169 (tramp-process-actions): Use progress reporter. Delete process in
170 case of error. Improve messages.
171
172 * net/tramp-sh.el (tramp-barf-if-no-shell-prompt): Use
173 condition-case. Call `tramp-error-with-buffer' with vector and buffer.
174 (tramp-current-connection): Removed.
175 (tramp-maybe-open-connection): The car of
176 `tramp-current-connection' are the first 3 slots of the vector.
177
1782013-07-10 Teodor Zlatanov <tzz@lifelogs.com>
179
180 * progmodes/cfengine.el (cfengine3-indent-line): Do not indent
181 inside continued strings.
182
1832013-07-10 Paul Eggert <eggert@cs.ucla.edu>
184
185 Timestamp fixes for undo (Bug#14824).
186 * files.el (clear-visited-file-modtime): Move here from fileio.c.
187
1882013-07-10 Leo Liu <sdl.web@gmail.com>
189
190 * files.el (require-final-newline): Allow safe local value.
191 (Bug#14834)
192
1932013-07-09 Leo Liu <sdl.web@gmail.com>
194
195 * ido.el (ido-read-directory-name): Handle fallback.
196 (ido-read-file-name): Update DIR to ido-current-directory.
197 (Bug#1516)
198 (ido-add-virtual-buffers-to-list): Robustify. (Bug#14552)
199
2002013-07-09 Dmitry Gutov <dgutov@yandex.ru>
201
202 * progmodes/ruby-mode.el (ruby-font-lock-keywords): Remove extra
203 "autoload". Remove "warn lower camel case" section, previously
204 commented out. Highlight negation char. Do not highlight the
205 target in singleton method definitions.
206
2072013-07-08 Stefan Monnier <monnier@iro.umontreal.ca>
208
209 * faces.el (tty-setup-hook): Declare the hook.
210
211 * emacs-lisp/pcase.el (pcase--split-pred): Add `vars' argument to try
212 and detect when a guard/pred depends on local vars (bug#14773).
213 (pcase--u1): Adjust caller.
214
2152013-07-08 Eli Zaretskii <eliz@gnu.org>
216
217 * simple.el (line-move-partial, line-move): Account for
218 line-spacing.
219 (line-move-partial): Avoid setting vscroll when the last
220 partially-visible line in window is of default height.
221
2222013-07-08 Lars Magne Ingebrigtsen <larsi@gnus.org>
223
224 * net/shr.el (shr-map): Reinstate the `u' key binding, since it's
225 been used a while.
226
2272013-07-07 Juanma Barranquero <lekktu@gmail.com>
228
229 * subr.el (read-quoted-char): Remove unused local variable `char'.
230
2312013-07-07 Michael Kifer <kifer@cs.stonybrook.edu>
232
233 * ediff.el (ediff-version): Version update.
234 (ediff-files-command, ediff3-files-command, ediff-merge-command)
235 (ediff-merge-with-ancestor-command, ediff-directories-command)
236 (ediff-directories3-command, ediff-merge-directories-command)
237 (ediff-merge-directories-with-ancestor-command): New functions.
238 All are command-line interfaces to ediff: to facilitate calling
239 Emacs with the appropriate ediff functions invoked.
240
241 * viper-cmd.el (viper-del-forward-char-in-insert): New function.
242 (viper-save-kill-buffer): Check if buffer is modified.
243
244 * viper.el (viper-version): Version update.
245 (viper-emacs-state-mode-list): Add egg-status-buffer-mode.
246
2472013-07-07 Stefan Monnier <monnier@iro.umontreal.ca>
248
249 * faces.el (tty-run-terminal-initialization): Run new tty-setup-hook.
250 * viper-cmd.el (viper-envelop-ESC-key): Remove function.
251 (viper-intercept-ESC-key): Simplify.
252 * viper-keym.el (viper-ESC-key): Make it a constant, don't use kbd.
253 * viper.el (viper--tty-ESC-filter, viper--lookup-key)
254 (viper-catch-tty-ESC, viper-uncatch-tty-ESC)
255 (viper-setup-ESC-to-escape): New functions.
256 (viper-go-away, viper-set-hooks): Call viper-setup-ESC-to-escape.
257 (viper-set-hooks): Do not modify flyspell-mode-hook. (Bug#13793)
258
2592013-07-07 Eli Zaretskii <eliz@gnu.org>
260
261 * simple.el (default-font-height, window-screen-lines):
262 New functions.
263 (line-move, line-move-partial): Use them instead of
264 frame-char-height and window-text-height. This makes scrolling
265 text smoother when the buffer's default face uses a font that is
266 different from the frame's default font.
267
2682013-07-06 Jan Djärv <jan.h.d@swipnet.se>
269
270 * files.el (write-file): Do not display confirm dialog for NS,
271 it does its own dialog, which can't be cancelled (Bug#14578).
272
2732013-07-06 Eli Zaretskii <eliz@gnu.org>
274
275 * simple.el (line-move-partial): Adjust the row returned by
276 posn-at-point for the current window-vscroll. (Bug#14567)
277
2782013-07-06 Michael Albinus <michael.albinus@gmx.de>
279
280 * net/tramp-sh.el (tramp-sh-file-gvfs-monitor-dir-process-filter):
281 (tramp-sh-file-inotifywait-process-filter): Handle file names with
282 spaces.
283
2842013-07-06 Martin Rudalics <rudalics@gmx.at>
285
286 * window.el (window-state-put-stale-windows): New variable.
287 (window--state-put-2): Save list of windows without matching buffer.
288 (window-state-put): Remove "bufferless" windows if possible.
289
2902013-07-06 Juanma Barranquero <lekktu@gmail.com>
291
292 * simple.el (alternatives-define): Remove leftover :group keyword.
293 Tweak docstring.
294
2952013-07-06 Leo Liu <sdl.web@gmail.com>
296
297 * ido.el (ido-use-virtual-buffers): Allow new value 'auto.
298 (ido-enable-virtual-buffers): New variable.
299 (ido-buffer-internal, ido-toggle-virtual-buffers)
300 (ido-make-buffer-list): Use it.
301 (ido-exhibit): Support turning on and off virtual buffers
302 automatically.
303
3042013-07-06 Juanma Barranquero <lekktu@gmail.com>
305
306 * simple.el (alternatives-define): New macro.
307
3082013-07-06 Stefan Monnier <monnier@iro.umontreal.ca>
309
310 * subr.el (read-quoted-char): Use read-key.
311 (sit-for): Let read-event decode tty input (bug#14782).
312
3132013-07-05 Stephen Berman <stephen.berman@gmx.net>
314
315 * calendar/todo-mode.el: Add handling of file deletion, both by
316 mode command and externally. Fix various related bugs.
317 Clarify Commentary and improve some documentation strings and code.
318 (todo-delete-file): New command.
319 (todo-check-file): New function.
320 (todo-show): Handle external deletion of the file we're trying to
321 show (bug#14688). Replace called-interactively-p by an optional
322 prefix argument to avoid problematic interaction with catch form
323 when byte compiled (bug#14702).
324 (todo-quit): Handle external deletion of the archive's todo file.
325 Make sure the buffer that was visiting the archive file is still
326 live before trying to bury it.
327 (todo-category-completions): Handle external deletion of any
328 category completion files.
329 (todo-jump-to-category, todo-basic-insert-item): Recalculate list
330 of todo files, in case of external deletion.
331 (todo-add-file): Replace unnecessary setq by let-binding.
332 (todo-find-archive): Check whether there are any archives.
333 Replace unnecessary setq by let-binding.
334 (todo-archive-done-item): Use find-file-noselect to get the
335 archive buffer whether or not the archive already exists.
336 Remove superfluous code. Use file size instead of buffer-file-name to
337 check if the archive is new; if it is, update list of archives.
338 (todo-default-todo-file): Allow nil to be a valid value for when
339 there are no todo files.
340 (todo-reevaluate-default-file-defcustom): Use corrected definition
341 of todo-default-todo-file.
342 (todo-key-bindings-t+a+f): Add key binding for todo-delete-file.
343 (todo-delete-category, todo-show-categories-table)
344 (todo-category-number): Clarify comment.
345 (todo-filter-items): Clarify documentation string.
346 (todo-show-current-file, todo-display-as-todo-file)
347 (todo-reset-and-enable-done-separator): Tweak documentation string.
348 (todo-done-separator): Make separator length window-width, since
349 bug#2749 is now fixed.
350
3512013-07-05 Michael Albinus <michael.albinus@gmx.de>
352
353 * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch):
354 Support both "gvfs-monitor-dir" and "inotifywait".
355 (tramp-sh-file-inotifywait-process-filter): Rename from
356 `tramp-sh-file-notify-process-filter'.
357 (tramp-sh-file-gvfs-monitor-dir-process-filter)
358 (tramp-get-remote-gvfs-monitor-dir): New defuns.
359
3602013-07-05 Leo Liu <sdl.web@gmail.com>
361
362 * autoinsert.el (auto-insert-alist): Default to lexical-binding.
363
3642013-07-04 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
365
366 * frame.el (display-pixel-height, display-pixel-width)
367 (display-mm-height, display-mm-width): Mention behavior on
368 multi-monitor setups in docstrings.
369 (w32-display-monitor-attributes-list): Declare function.
370 (display-monitor-attributes-list): Use it.
371
3722013-07-04 Michael Albinus <michael.albinus@gmx.de>
373
374 * filenotify.el: New package.
375
376 * autorevert.el (top): Require filenotify.el.
377 (auto-revert-notify-enabled): Remove. Use `file-notify-support'
378 instead.
379 (auto-revert-notify-rm-watch, auto-revert-notify-add-watch)
380 (auto-revert-notify-handler): Use `file-notify-*' functions.
381
382 * subr.el (file-notify-handle-event): Move function to filenotify.el.
383
384 * net/tramp.el (tramp-file-name-for-operation):
385 Handle `file-notify-add-watch' and `file-notify-rm-watch'.
386
387 * net/tramp-sh.el (tramp-sh-file-name-handler-alist): Add handler
388 for `file-notify-add-watch' and `file-notify-rm-watch'.
389 (tramp-process-sentinel): Improve trace.
390 (tramp-sh-handle-file-notify-add-watch)
391 (tramp-sh-file-notify-process-filter)
392 (tramp-sh-handle-file-notify-rm-watch)
393 (tramp-get-remote-inotifywait): New defuns.
394
3952013-07-03 Juri Linkov <juri@jurta.org>
396
397 * buff-menu.el (Buffer-menu-multi-occur): Add args and move the
398 call of `occur-read-primary-args' to interactive spec.
399
400 * ibuffer.el (ibuffer-mode-map): Bind "M-s a C-o" to
401 `ibuffer-do-occur' like in buff-menu.el. (Bug#14673)
402
4032013-07-03 Matthias Meulien <orontee@gmail.com>
404
405 * buff-menu.el (Buffer-menu-mode-map): Bind "M-s a C-o" to
406 `Buffer-menu-multi-occur'. Add it to the menu.
407 (Buffer-menu-mode): Document it in docstring.
408 (Buffer-menu-multi-occur): New command. (Bug#14673)
409
4102013-07-03 Dmitry Gutov <dgutov@yandex.ru>
411
412 * progmodes/ruby-mode.el (ruby-font-lock-keywords): Highlight more
413 keywords and built-ins.
414
4152013-07-03 Glenn Morris <rgm@gnu.org>
416
417 * subr.el (y-or-n-p): Handle empty prompts. (Bug#14770)
418
419 Make info-xref checks case-sensitive by default
420 * info.el (Info-find-node, Info-find-in-tag-table)
421 (Info-find-node-in-buffer, Info-find-node-2, Info-goto-node):
422 Add option for exact case matching of nodes.
423 * info-xref.el (info-xref): New custom group.
424 (info-xref-case-fold): New option.
425 (info-xref-goto-node-p): Pass info-xref-case-fold to Info-goto-node.
426
4272013-07-03 Leo Liu <sdl.web@gmail.com>
428
429 * ido.el (ido-delete-file-at-head): Respect delete-by-moving-to-trash.
430
4312013-07-03 Dmitry Gutov <dgutov@yandex.ru>
432
433 * progmodes/ruby-mode.el (ruby-move-to-block): When we're at a
434 middle of block statement initially, lower the depth. Remove
435 FIXME comment, not longer valid. Remove middle of block statement
436 detection, no need to do that anymore since we've been using
437 `ruby-parse-region' here.
438
12013-07-02 Jan Djärv <jan.h.d@swipnet.se> 4392013-07-02 Jan Djärv <jan.h.d@swipnet.se>
2 440
3 * term/ns-win.el (display-format-alist): Use .* (Bug#14765). 441 * term/ns-win.el (display-format-alist): Use .* (Bug#14765).
@@ -255,12 +693,12 @@
255 693
2562013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> 6942013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
257 695
258 * lisp/textmodes/bibtex.el (bibtex-generate-url-list): Add support 696 * textmodes/bibtex.el (bibtex-generate-url-list): Add support
259 for DOI URLs. 697 for DOI URLs.
260 698
2612013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de> 6992013-06-25 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
262 700
263 * lisp/textmodes/bibtex.el (bibtex-mode, bibtex-set-dialect): 701 * textmodes/bibtex.el (bibtex-mode, bibtex-set-dialect):
264 Update imenu-support when dialect changes. 702 Update imenu-support when dialect changes.
265 703
2662013-06-25 Leo Liu <sdl.web@gmail.com> 7042013-06-25 Leo Liu <sdl.web@gmail.com>
@@ -361,7 +799,7 @@
361 * emacs-lock.el (emacs-lock-mode, emacs-lock--old-mode) 799 * emacs-lock.el (emacs-lock-mode, emacs-lock--old-mode)
362 (emacs-lock--try-unlocking): Make defvar-local. 800 (emacs-lock--try-unlocking): Make defvar-local.
363 801
3642013-06-22 Glenn Morris <rgm@fencepost.gnu.org> 8022013-06-22 Glenn Morris <rgm@gnu.org>
365 803
366 * play/cookie1.el (cookie-apropos): Minor simplification. 804 * play/cookie1.el (cookie-apropos): Minor simplification.
367 805
@@ -827,7 +1265,7 @@
827 1265
828 * net/shr.el (shr-map): Bind [down-mouse-1] to browse URLs. 1266 * net/shr.el (shr-map): Bind [down-mouse-1] to browse URLs.
829 1267
8302013-06-19 Glenn Morris <rgm@fencepost.gnu.org> 12682013-06-19 Glenn Morris <rgm@gnu.org>
831 1269
832 * emacs-lisp/eieio.el (defclass): Make it eval-and-compile once more. 1270 * emacs-lisp/eieio.el (defclass): Make it eval-and-compile once more.
833 1271
@@ -970,6 +1408,7 @@
9702013-06-18 Matthias Meulien <orontee@gmail.com> 14082013-06-18 Matthias Meulien <orontee@gmail.com>
971 1409
972 * tabify.el (untabify, tabify): With prefix, apply to entire buffer. 1410 * tabify.el (untabify, tabify): With prefix, apply to entire buffer.
1411 <http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00545.html>
973 1412
9742013-06-18 Glenn Morris <rgm@gnu.org> 14132013-06-18 Glenn Morris <rgm@gnu.org>
975 1414
diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el
index c45d64e1cd9..daa654889b6 100644
--- a/lisp/autoinsert.el
+++ b/lisp/autoinsert.el
@@ -164,7 +164,10 @@ If this contains a %s, that will be replaced by the matching rule."
164 164
165 (("\\.el\\'" . "Emacs Lisp header") 165 (("\\.el\\'" . "Emacs Lisp header")
166 "Short description: " 166 "Short description: "
167 ";;; " (file-name-nondirectory (buffer-file-name)) " --- " str " 167 ";;; " (file-name-nondirectory (buffer-file-name)) " --- " str
168 (make-string (max 2 (- 80 (current-column) 27)) ?\s)
169 "-*- lexical-binding: t; -*-"
170 "
168 171
169;; Copyright (C) " (format-time-string "%Y") " " 172;; Copyright (C) " (format-time-string "%Y") " "
170 (getenv "ORGANIZATION") | (progn user-full-name) " 173 (getenv "ORGANIZATION") | (progn user-full-name) "
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index 4a6d4cb4cc0..00e88fc4a3d 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -103,6 +103,7 @@
103 103
104(eval-when-compile (require 'cl-lib)) 104(eval-when-compile (require 'cl-lib))
105(require 'timer) 105(require 'timer)
106(require 'filenotify)
106 107
107;; Custom Group: 108;; Custom Group:
108;; 109;;
@@ -270,21 +271,17 @@ This variable becomes buffer local when set in any fashion.")
270 :type 'boolean 271 :type 'boolean
271 :version "24.4") 272 :version "24.4")
272 273
273(defconst auto-revert-notify-enabled 274(defcustom auto-revert-use-notify (and file-notify-support t)
274 (or (featurep 'gfilenotify) (featurep 'inotify) (featurep 'w32notify))
275 "Non-nil when Emacs has been compiled with file notification support.")
276
277(defcustom auto-revert-use-notify auto-revert-notify-enabled
278 "If non-nil Auto Revert Mode uses file notification functions. 275 "If non-nil Auto Revert Mode uses file notification functions.
279This requires Emacs being compiled with file notification 276This requires Emacs being compiled with file notification
280support (see `auto-revert-notify-enabled'). You should set this 277support (see `file-notify-support'). You should set this variable
281variable through Custom." 278through Custom."
282 :group 'auto-revert 279 :group 'auto-revert
283 :type 'boolean 280 :type 'boolean
284 :set (lambda (variable value) 281 :set (lambda (variable value)
285 (set-default variable (and auto-revert-notify-enabled value)) 282 (set-default variable (and file-notify-support value))
286 (unless (symbol-value variable) 283 (unless (symbol-value variable)
287 (when auto-revert-notify-enabled 284 (when file-notify-support
288 (dolist (buf (buffer-list)) 285 (dolist (buf (buffer-list))
289 (with-current-buffer buf 286 (with-current-buffer buf
290 (when (symbol-value 'auto-revert-notify-watch-descriptor) 287 (when (symbol-value 'auto-revert-notify-watch-descriptor)
@@ -502,12 +499,7 @@ will use an up-to-date value of `auto-revert-interval'"
502 (puthash key value auto-revert-notify-watch-descriptor-hash-list) 499 (puthash key value auto-revert-notify-watch-descriptor-hash-list)
503 (remhash key auto-revert-notify-watch-descriptor-hash-list) 500 (remhash key auto-revert-notify-watch-descriptor-hash-list)
504 (ignore-errors 501 (ignore-errors
505 (funcall 502 (file-notify-rm-watch auto-revert-notify-watch-descriptor)))))
506 (cond
507 ((fboundp 'gfile-rm-watch) 'gfile-rm-watch)
508 ((fboundp 'inotify-rm-watch) 'inotify-rm-watch)
509 ((fboundp 'w32notify-rm-watch) 'w32notify-rm-watch))
510 auto-revert-notify-watch-descriptor)))))
511 auto-revert-notify-watch-descriptor-hash-list) 503 auto-revert-notify-watch-descriptor-hash-list)
512 (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch)) 504 (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch))
513 (setq auto-revert-notify-watch-descriptor nil 505 (setq auto-revert-notify-watch-descriptor nil
@@ -522,100 +514,58 @@ will use an up-to-date value of `auto-revert-interval'"
522 514
523 (when (and buffer-file-name auto-revert-use-notify 515 (when (and buffer-file-name auto-revert-use-notify
524 (not auto-revert-notify-watch-descriptor)) 516 (not auto-revert-notify-watch-descriptor))
525 (let ((func 517 (setq auto-revert-notify-watch-descriptor
526 (cond 518 (ignore-errors
527 ((fboundp 'gfile-add-watch) 'gfile-add-watch) 519 (file-notify-add-watch
528 ((fboundp 'inotify-add-watch) 'inotify-add-watch) 520 (expand-file-name buffer-file-name default-directory)
529 ((fboundp 'w32notify-add-watch) 'w32notify-add-watch))) 521 '(change attribute-change) 'auto-revert-notify-handler)))
530 (aspect 522 (if auto-revert-notify-watch-descriptor
531 (cond 523 (progn
532 ((fboundp 'gfile-add-watch) '(watch-mounts)) 524 (puthash
533 ;; `attrib' is needed for file modification time. 525 auto-revert-notify-watch-descriptor
534 ((fboundp 'inotify-add-watch) '(attrib create modify moved-to)) 526 (cons (current-buffer)
535 ((fboundp 'w32notify-add-watch) '(size last-write-time)))) 527 (gethash auto-revert-notify-watch-descriptor
536 (file (if (or (fboundp 'gfile-add-watch) (fboundp 'inotify-add-watch)) 528 auto-revert-notify-watch-descriptor-hash-list))
537 (directory-file-name (expand-file-name default-directory)) 529 auto-revert-notify-watch-descriptor-hash-list)
538 (buffer-file-name)))) 530 (add-hook (make-local-variable 'kill-buffer-hook)
539 (setq auto-revert-notify-watch-descriptor 531 'auto-revert-notify-rm-watch))
540 (ignore-errors 532 ;; Fallback to file checks.
541 (funcall func file aspect 'auto-revert-notify-handler))) 533 (set (make-local-variable 'auto-revert-use-notify) nil))))
542 (if auto-revert-notify-watch-descriptor
543 (progn
544 (puthash
545 auto-revert-notify-watch-descriptor
546 (cons (current-buffer)
547 (gethash auto-revert-notify-watch-descriptor
548 auto-revert-notify-watch-descriptor-hash-list))
549 auto-revert-notify-watch-descriptor-hash-list)
550 (add-hook (make-local-variable 'kill-buffer-hook)
551 'auto-revert-notify-rm-watch))
552 ;; Fallback to file checks.
553 (set (make-local-variable 'auto-revert-use-notify) nil)))))
554
555(defun auto-revert-notify-event-p (event)
556 "Check that event is a file notification event."
557 (and (listp event)
558 (cond ((featurep 'gfilenotify)
559 (and (>= (length event) 3) (stringp (nth 2 event))))
560 ((featurep 'inotify)
561 (= (length event) 4))
562 ((featurep 'w32notify)
563 (and (= (length event) 3) (stringp (nth 2 event)))))))
564
565(defun auto-revert-notify-event-descriptor (event)
566 "Return watch descriptor of file notification event, or nil."
567 (and (auto-revert-notify-event-p event) (car event)))
568
569(defun auto-revert-notify-event-action (event)
570 "Return action of file notification event, or nil."
571 (and (auto-revert-notify-event-p event) (nth 1 event)))
572
573(defun auto-revert-notify-event-file-name (event)
574 "Return file name of file notification event, or nil."
575 (and (auto-revert-notify-event-p event)
576 (cond ((featurep 'gfilenotify) (nth 2 event))
577 ((featurep 'inotify) (nth 3 event))
578 ((featurep 'w32notify) (nth 2 event)))))
579 534
580(defun auto-revert-notify-handler (event) 535(defun auto-revert-notify-handler (event)
581 "Handle an EVENT returned from file notification." 536 "Handle an EVENT returned from file notification."
582 (when (auto-revert-notify-event-p event) 537 (ignore-errors
583 (let* ((descriptor (auto-revert-notify-event-descriptor event)) 538 (let* ((descriptor (car event))
584 (action (auto-revert-notify-event-action event)) 539 (action (nth 1 event))
585 (file (auto-revert-notify-event-file-name event)) 540 (file (nth 2 event))
541 (file1 (nth 3 event)) ;; Target of `renamed'.
586 (buffers (gethash descriptor 542 (buffers (gethash descriptor
587 auto-revert-notify-watch-descriptor-hash-list))) 543 auto-revert-notify-watch-descriptor-hash-list)))
588 (ignore-errors 544 ;; Check, that event is meant for us.
589 ;; Check, that event is meant for us. 545 (cl-assert descriptor)
590 ;; TODO: Filter events which stop watching, like `move' or `removed'. 546 ;; We do not handle `deleted', because nothing has to be refreshed.
591 (cl-assert descriptor) 547 (cl-assert (memq action '(attribute-changed changed created renamed)) t)
592 (cond 548 ;; Since we watch a directory, a file name must be returned.
593 ((featurep 'gfilenotify) 549 (cl-assert (stringp file))
594 (cl-assert (memq action '(attribute-changed changed created deleted 550 (when (eq action 'renamed) (cl-assert (stringp file1)))
595 ;; FIXME: I keep getting this action, so I 551 ;; Loop over all buffers, in order to find the intended one.
596 ;; added it here, but I have no idea what 552 (dolist (buffer buffers)
597 ;; I'm doing. --Stef 553 (when (buffer-live-p buffer)
598 changes-done-hint)) 554 (with-current-buffer buffer
599 t)) 555 (when (and (stringp buffer-file-name)
600 ((featurep 'inotify) 556 (or
601 (cl-assert (or (memq 'attrib action) 557 (and (memq action '(attribute-changed changed created))
602 (memq 'create action) 558 (string-equal
603 (memq 'modify action) 559 (file-name-nondirectory file)
604 (memq 'moved-to action)))) 560 (file-name-nondirectory buffer-file-name)))
605 ((featurep 'w32notify) (cl-assert (eq 'modified action)))) 561 (and (eq action 'renamed)
606 ;; Since we watch a directory, a file name must be returned. 562 (string-equal
607 (cl-assert (stringp file)) 563 (file-name-nondirectory file1)
608 (dolist (buffer buffers) 564 (file-name-nondirectory buffer-file-name)))))
609 (when (buffer-live-p buffer) 565 ;; Mark buffer modified.
610 (with-current-buffer buffer 566 (setq auto-revert-notify-modified-p t)
611 (when (and (stringp buffer-file-name) 567 ;; No need to check other buffers.
612 (string-equal 568 (cl-return))))))))
613 (file-name-nondirectory file)
614 (file-name-nondirectory buffer-file-name)))
615 ;; Mark buffer modified.
616 (setq auto-revert-notify-modified-p t)
617 ;; No need to check other buffers.
618 (cl-return)))))))))
619 569
620(defun auto-revert-active-p () 570(defun auto-revert-active-p ()
621 "Check if auto-revert is active (in current buffer or globally)." 571 "Check if auto-revert is active (in current buffer or globally)."
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index 6c02233e1e2..1db9b7229f3 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -129,6 +129,7 @@ commands.")
129 (define-key map "T" 'Buffer-menu-toggle-files-only) 129 (define-key map "T" 'Buffer-menu-toggle-files-only)
130 (define-key map (kbd "M-s a C-s") 'Buffer-menu-isearch-buffers) 130 (define-key map (kbd "M-s a C-s") 'Buffer-menu-isearch-buffers)
131 (define-key map (kbd "M-s a M-C-s") 'Buffer-menu-isearch-buffers-regexp) 131 (define-key map (kbd "M-s a M-C-s") 'Buffer-menu-isearch-buffers-regexp)
132 (define-key map (kbd "M-s a C-o") 'Buffer-menu-multi-occur)
132 133
133 (define-key map [mouse-2] 'Buffer-menu-mouse-select) 134 (define-key map [mouse-2] 'Buffer-menu-mouse-select)
134 (define-key map [follow-link] 'mouse-face) 135 (define-key map [follow-link] 'mouse-face)
@@ -169,6 +170,9 @@ commands.")
169 (bindings--define-key menu-map [ir] 170 (bindings--define-key menu-map [ir]
170 '(menu-item "Isearch Marked Buffers..." Buffer-menu-isearch-buffers 171 '(menu-item "Isearch Marked Buffers..." Buffer-menu-isearch-buffers
171 :help "Search for a string through all marked buffers using Isearch")) 172 :help "Search for a string through all marked buffers using Isearch"))
173 (bindings--define-key menu-map [mo]
174 '(menu-item "Multi Occur Marked Buffers..." Buffer-menu-multi-occur
175 :help "Show lines matching a regexp in marked buffers using Occur"))
172 (bindings--define-key menu-map [s3] menu-bar-separator) 176 (bindings--define-key menu-map [s3] menu-bar-separator)
173 (bindings--define-key menu-map [by] 177 (bindings--define-key menu-map [by]
174 '(menu-item "Bury" Buffer-menu-bury 178 '(menu-item "Bury" Buffer-menu-bury
@@ -226,6 +230,7 @@ In Buffer Menu mode, the following commands are defined:
226 buffer selected before this one in another window. 230 buffer selected before this one in another window.
227\\[Buffer-menu-isearch-buffers] Incremental search in the marked buffers. 231\\[Buffer-menu-isearch-buffers] Incremental search in the marked buffers.
228\\[Buffer-menu-isearch-buffers-regexp] Isearch for regexp in the marked buffers. 232\\[Buffer-menu-isearch-buffers-regexp] Isearch for regexp in the marked buffers.
233\\[Buffer-menu-multi-occur] Show lines matching regexp in the marked buffers.
229\\[Buffer-menu-visit-tags-table] visit-tags-table this buffer. 234\\[Buffer-menu-visit-tags-table] visit-tags-table this buffer.
230\\[Buffer-menu-not-modified] Clear modified-flag on that buffer. 235\\[Buffer-menu-not-modified] Clear modified-flag on that buffer.
231\\[Buffer-menu-save] Mark that buffer to be saved, and move down. 236\\[Buffer-menu-save] Mark that buffer to be saved, and move down.
@@ -477,6 +482,11 @@ If UNMARK is non-nil, unmark them."
477 (interactive) 482 (interactive)
478 (multi-isearch-buffers-regexp (Buffer-menu-marked-buffers))) 483 (multi-isearch-buffers-regexp (Buffer-menu-marked-buffers)))
479 484
485(defun Buffer-menu-multi-occur (regexp &optional nlines)
486 "Show all lines in marked buffers containing a match for a regexp."
487 (interactive (occur-read-primary-args))
488 (multi-occur (Buffer-menu-marked-buffers) regexp nlines))
489
480 490
481(defun Buffer-menu-visit-tags-table () 491(defun Buffer-menu-visit-tags-table ()
482 "Visit the tags table in the buffer on this line. See `visit-tags-table'." 492 "Visit the tags table in the buffer on this line. See `visit-tags-table'."
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index a497f759e87..934dfb92a57 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -37,11 +37,14 @@
37;; can edit todo items, reprioritize them within their category, move 37;; can edit todo items, reprioritize them within their category, move
38;; them to another category, delete them, or mark items as done and 38;; them to another category, delete them, or mark items as done and
39;; store them separately from the not yet done items in a category. 39;; store them separately from the not yet done items in a category.
40;; You can add new todo files and categories, rename categories, move 40;; You can add new todo files, edit and delete them. You can add new
41;; them to another file or delete them. You can also display summary 41;; categories, rename and delete them, move categories to another file
42;; tables of the categories in a file and the types of items they 42;; and merge the items of two categories. You can also reorder the
43;; contain. And you can build cross-category lists of items that 43;; sequence of categories in a todo file for the purpose of
44;; satisfy various criteria. 44;; navigation. You can display summary tables of the categories in a
45;; file and the types of items they contain. And you can compile
46;; lists of existing items from multiple categories in one or more
47;; todo files, which are filtered by various criteria.
45 48
46;; To get started, load this package and type `M-x todo-show'. This 49;; To get started, load this package and type `M-x todo-show'. This
47;; will prompt you for the name of the first todo file, its first 50;; will prompt you for the name of the first todo file, its first
@@ -169,12 +172,7 @@ the value of `todo-done-separator'."
169 "Return string used as value of variable `todo-done-separator'." 172 "Return string used as value of variable `todo-done-separator'."
170 (let ((sep todo-done-separator-string)) 173 (let ((sep todo-done-separator-string))
171 (propertize (if (= 1 (length sep)) 174 (propertize (if (= 1 (length sep))
172 ;; Until bug#2749 is fixed, if separator's length 175 (make-string (window-width) (string-to-char sep))
173 ;; is window-width and todo-wrap-lines is
174 ;; non-nil, an indented empty line appears between
175 ;; the separator and the first done item.
176 ;; (make-string (window-width) (string-to-char sep))
177 (make-string (1- (window-width)) (string-to-char sep))
178 todo-done-separator-string) 176 todo-done-separator-string)
179 'face 'todo-done-sep))) 177 'face 'todo-done-sep)))
180 178
@@ -578,11 +576,12 @@ This lacks the extension and directory components."
578 (file-name-sans-extension (file-name-nondirectory file)))) 576 (file-name-sans-extension (file-name-nondirectory file))))
579 577
580(defcustom todo-default-todo-file (todo-short-file-name 578(defcustom todo-default-todo-file (todo-short-file-name
581 (car (funcall todo-files-function))) 579 (car (funcall todo-files-function)))
582 "Todo file visited by first session invocation of `todo-show'." 580 "Todo file visited by first session invocation of `todo-show'."
583 :type `(radio ,@(mapcar (lambda (f) (list 'const f)) 581 :type (when todo-files
584 (mapcar 'todo-short-file-name 582 `(radio ,@(mapcar (lambda (f) (list 'const f))
585 (funcall todo-files-function)))) 583 (mapcar 'todo-short-file-name
584 (funcall todo-files-function)))))
586 :group 'todo) 585 :group 'todo)
587 586
588(defcustom todo-show-current-file t 587(defcustom todo-show-current-file t
@@ -630,7 +629,7 @@ Otherwise, `todo-show' always visits `todo-default-todo-file'."
630 :group 'todo) 629 :group 'todo)
631 630
632;;;###autoload 631;;;###autoload
633(defun todo-show (&optional solicit-file) 632(defun todo-show (&optional solicit-file interactive)
634 "Visit a todo file and display one of its categories. 633 "Visit a todo file and display one of its categories.
635 634
636When invoked in Todo mode, prompt for which todo file to visit. 635When invoked in Todo mode, prompt for which todo file to visit.
@@ -668,117 +667,124 @@ and done items are always shown on visiting a category.
668 667
669Invoking this command in Todo Archive mode visits the 668Invoking this command in Todo Archive mode visits the
670corresponding todo file, displaying the corresponding category." 669corresponding todo file, displaying the corresponding category."
671 (interactive "P") 670 (interactive "P\np")
671 (when todo-default-todo-file
672 (todo-check-file (todo-absolute-file-name todo-default-todo-file)))
672 (catch 'shown 673 (catch 'shown
673 ;; If there is a legacy todo file but no todo file in the current 674 ;; Before initializing the first todo first, check if there is a
674 ;; format, offer to convert the legacy file and show it. 675 ;; legacy todo file and if so, offer to convert to the current
676 ;; format and make it the first new todo file.
675 (unless todo-default-todo-file 677 (unless todo-default-todo-file
676 (let ((legacy-todo-file (if (boundp 'todo-file-do) 678 (let ((legacy-todo-file (if (boundp 'todo-file-do)
677 todo-file-do 679 todo-file-do
678 (locate-user-emacs-file "todo-do" ".todo-do")))) 680 (locate-user-emacs-file "todo-do" ".todo-do"))))
679 (when (and (file-exists-p legacy-todo-file) 681 (when (and (file-exists-p legacy-todo-file)
680 (y-or-n-p (concat "Do you want to convert a copy of your " 682 (y-or-n-p (concat "Do you want to convert a copy of your "
681 "old todo file to the new format? "))) 683 "old todo file to the new format? ")))
682 (when (todo-convert-legacy-files) 684 (when (todo-convert-legacy-files)
683 (throw 'shown nil))))) 685 (throw 'shown nil)))))
684 (let* ((cat) 686 (catch 'end
685 (show-first todo-show-first) 687 (let* ((cat)
686 (file (cond ((or solicit-file 688 (show-first todo-show-first)
687 (and (called-interactively-p 'any) 689 (file (cond ((or solicit-file
688 (memq major-mode '(todo-mode 690 (and interactive
689 todo-archive-mode 691 (memq major-mode '(todo-mode
690 todo-filtered-items-mode)))) 692 todo-archive-mode
691 (if (funcall todo-files-function) 693 todo-filtered-items-mode))))
692 (todo-read-file-name "Choose a todo file to visit: " 694 (if (funcall todo-files-function)
693 nil t) 695 (todo-read-file-name "Choose a todo file to visit: "
694 (user-error "There are no todo files"))) 696 nil t)
695 ((and (eq major-mode 'todo-archive-mode) 697 (user-error "There are no todo files")))
696 ;; Called noninteractively via todo-quit 698 ((and (eq major-mode 'todo-archive-mode)
697 ;; to jump to corresponding category in 699 ;; Called noninteractively via todo-quit
698 ;; todo file. 700 ;; to jump to corresponding category in
699 (not (called-interactively-p 'any))) 701 ;; todo file.
700 (setq cat (todo-current-category)) 702 (not interactive))
701 (concat (file-name-sans-extension 703 (setq cat (todo-current-category))
702 todo-current-todo-file) ".todo")) 704 (concat (file-name-sans-extension
703 (t 705 todo-current-todo-file) ".todo"))
704 (or todo-current-todo-file 706 (t
705 (and todo-show-current-file 707 (or todo-current-todo-file
706 todo-global-current-todo-file) 708 (and todo-show-current-file
707 (todo-absolute-file-name todo-default-todo-file) 709 todo-global-current-todo-file)
708 (todo-add-file))))) 710 (todo-absolute-file-name todo-default-todo-file)
709 add-item first-file) 711 (todo-add-file)))))
710 (unless todo-default-todo-file 712 add-item first-file)
711 ;; We just initialized the first todo file, so make it the default. 713 (unless todo-default-todo-file
712 (setq todo-default-todo-file (todo-short-file-name file) 714 ;; We just initialized the first todo file, so make it the default.
713 first-file t) 715 (setq todo-default-todo-file (todo-short-file-name file)
714 (todo-reevaluate-default-file-defcustom)) 716 first-file t)
715 (unless (member file todo-visited) 717 (todo-reevaluate-default-file-defcustom))
716 ;; Can't setq t-c-t-f here, otherwise wrong file shown when 718 (unless (member file todo-visited)
717 ;; todo-show is called from todo-show-categories-table. 719 ;; Can't setq t-c-t-f here, otherwise wrong file shown when
718 (let ((todo-current-todo-file file)) 720 ;; todo-show is called from todo-show-categories-table.
719 (cond ((eq todo-show-first 'table) 721 (let ((todo-current-todo-file file))
720 (todo-show-categories-table)) 722 (cond ((eq todo-show-first 'table)
721 ((memq todo-show-first '(top diary regexp)) 723 (todo-show-categories-table))
722 (let* ((shortf (todo-short-file-name file)) 724 ((memq todo-show-first '(top diary regexp))
723 (fi-file (todo-absolute-file-name 725 (let* ((shortf (todo-short-file-name file))
724 shortf todo-show-first))) 726 (fi-file (todo-absolute-file-name
725 (when (eq todo-show-first 'regexp) 727 shortf todo-show-first)))
726 (let ((rxfiles (directory-files todo-directory t 728 (when (eq todo-show-first 'regexp)
727 ".*\\.todr$" t))) 729 (let ((rxfiles (directory-files todo-directory t
728 (when (and rxfiles (> (length rxfiles) 1)) 730 ".*\\.todr$" t)))
729 (let ((rxf (mapcar 'todo-short-file-name rxfiles))) 731 (when (and rxfiles (> (length rxfiles) 1))
730 (setq fi-file (todo-absolute-file-name 732 (let ((rxf (mapcar 'todo-short-file-name rxfiles)))
731 (completing-read 733 (setq fi-file (todo-absolute-file-name
732 "Choose a regexp items file: " 734 (completing-read
733 rxf) 'regexp)))))) 735 "Choose a regexp items file: "
734 (if (file-exists-p fi-file) 736 rxf) 'regexp))))))
735 (set-window-buffer 737 (if (file-exists-p fi-file)
736 (selected-window) 738 (set-window-buffer
737 (set-buffer (find-file-noselect fi-file 'nowarn))) 739 (selected-window)
738 (message "There is no %s file for %s" 740 (set-buffer (find-file-noselect fi-file 'nowarn)))
739 (cond ((eq todo-show-first 'top) 741 (message "There is no %s file for %s"
740 "top priorities") 742 (cond ((eq todo-show-first 'top)
741 ((eq todo-show-first 'diary) 743 "top priorities")
742 "diary items") 744 ((eq todo-show-first 'diary)
743 ((eq todo-show-first 'regexp) 745 "diary items")
744 "regexp items")) 746 ((eq todo-show-first 'regexp)
745 shortf) 747 "regexp items"))
746 (setq todo-show-first 'first))))))) 748 shortf)
747 (when (or (member file todo-visited) 749 (setq todo-show-first 'first)))))))
748 (eq todo-show-first 'first)) 750 (when (or (member file todo-visited)
749 (set-window-buffer (selected-window) 751 (eq todo-show-first 'first))
750 (set-buffer (find-file-noselect file 'nowarn))) 752 (unless (todo-check-file file) (throw 'end nil))
751 ;; When quitting an archive file, show the corresponding 753 (set-window-buffer (selected-window)
752 ;; category in the corresponding todo file, if it exists. 754 (set-buffer (find-file-noselect file 'nowarn)))
753 (when (assoc cat todo-categories) 755 ;; When quitting an archive file, show the corresponding
754 (setq todo-category-number (todo-category-number cat))) 756 ;; category in the corresponding todo file, if it exists.
755 ;; If this is a new todo file, add its first category. 757 (when (assoc cat todo-categories)
756 (when (zerop (buffer-size)) 758 (setq todo-category-number (todo-category-number cat)))
757 (let (cat-added) 759 ;; If this is a new todo file, add its first category.
758 (unwind-protect 760 (when (zerop (buffer-size))
759 (setq todo-category-number 761 (let (cat-added)
760 (todo-add-category todo-current-todo-file "") 762 (unwind-protect
761 add-item todo-add-item-if-new-category 763 (setq todo-category-number
762 cat-added t) 764 (todo-add-category todo-current-todo-file "")
763 (if cat-added 765 add-item todo-add-item-if-new-category
764 ;; If the category was added, save the file now, so we 766 cat-added t)
765 ;; don't risk having an empty todo file, which would 767 (if cat-added
766 ;; signal an error if we tried to visit it later, 768 ;; If the category was added, save the file now, so we
767 ;; since doing that looks for category boundaries. 769 ;; don't risk having an empty todo file, which would
768 (save-buffer 0) 770 ;; signal an error if we tried to visit it later,
769 ;; If user cancels before adding the category, clean up 771 ;; since doing that looks for category boundaries.
770 ;; and exit, so we have a fresh slate the next time. 772 (save-buffer 0)
771 (delete-file file) 773 ;; If user cancels before adding the category, clean up
772 (setq todo-files (delete file todo-files)) 774 ;; and exit, so we have a fresh slate the next time.
773 (when first-file 775 (delete-file file)
774 (setq todo-default-todo-file nil 776 ;; (setq todo-files (funcall todo-files-function))
775 todo-current-todo-file nil)) 777 (setq todo-files (delete file todo-files))
776 (kill-buffer) 778 (when first-file
777 (keyboard-quit))))) 779 (setq todo-default-todo-file nil
778 (save-excursion (todo-category-select)) 780 todo-current-todo-file nil)
779 (when add-item (todo-basic-insert-item))) 781 (todo-reevaluate-default-file-defcustom))
780 (setq todo-show-first show-first) 782 (kill-buffer)
781 (add-to-list 'todo-visited file)))) 783 (keyboard-quit)))))
784 (save-excursion (todo-category-select))
785 (when add-item (todo-basic-insert-item)))
786 (setq todo-show-first show-first)
787 (add-to-list 'todo-visited file)))))
782 788
783(defun todo-save () 789(defun todo-save ()
784 "Save the current todo file." 790 "Save the current todo file."
@@ -814,8 +820,15 @@ buries it and restores state as needed."
814 ;; Have to write a newly created archive to file to avoid 820 ;; Have to write a newly created archive to file to avoid
815 ;; subsequent errors. 821 ;; subsequent errors.
816 (todo-save) 822 (todo-save)
817 (todo-show) 823 (let ((todo-file (concat todo-directory
818 (bury-buffer buf)) 824 (todo-short-file-name todo-current-todo-file)
825 ".todo")))
826 (if (todo-check-file todo-file)
827 (todo-show)
828 (message "There is no todo file for this archive")))
829 ;; When todo-check-file runs in todo-show, it kills the
830 ;; buffer if the archive file was deleted externally.
831 (when (buffer-live-p buf) (bury-buffer buf)))
819 ((eq major-mode 'todo-mode) 832 ((eq major-mode 'todo-mode)
820 (todo-save) 833 (todo-save)
821 ;; If we just quit archive mode, just burying the buffer 834 ;; If we just quit archive mode, just burying the buffer
@@ -893,7 +906,7 @@ Categories mode."
893 (interactive "P") 906 (interactive "P")
894 ;; If invoked outside of Todo mode and there is not yet any Todo 907 ;; If invoked outside of Todo mode and there is not yet any Todo
895 ;; file, initialize one. 908 ;; file, initialize one.
896 (if (null todo-files) 909 (if (null (funcall todo-files-function))
897 (todo-show) 910 (todo-show)
898 (let* ((archive (eq where 'archive)) 911 (let* ((archive (eq where 'archive))
899 (cat (unless archive where)) 912 (cat (unless archive where))
@@ -1069,10 +1082,9 @@ option `todo-add-item-if-new-category' is non-nil (the default),
1069prompt for the first item. 1082prompt for the first item.
1070Noninteractively, return the name of the new file." 1083Noninteractively, return the name of the new file."
1071 (interactive) 1084 (interactive)
1072 (let ((prompt (concat "Enter name of new todo file " 1085 (let* ((prompt (concat "Enter name of new todo file "
1073 "(TAB or SPC to see current names): ")) 1086 "(TAB or SPC to see current names): "))
1074 file) 1087 (file (todo-read-file-name prompt)))
1075 (setq file (todo-read-file-name prompt))
1076 (with-current-buffer (get-buffer-create file) 1088 (with-current-buffer (get-buffer-create file)
1077 (erase-buffer) 1089 (erase-buffer)
1078 (write-region (point-min) (point-max) file nil 'nomessage nil t) 1090 (write-region (point-min) (point-max) file nil 'nomessage nil t)
@@ -1087,6 +1099,55 @@ Noninteractively, return the name of the new file."
1087 (todo-show)) 1099 (todo-show))
1088 file))) 1100 file)))
1089 1101
1102(defun todo-delete-file ()
1103 "Delete the current todo, archive or filtered items file.
1104If the todo file has a corresponding archive file, or vice versa,
1105prompt whether to delete that as well. Also kill the buffers
1106visiting the deleted files."
1107 (interactive)
1108 (let* ((file1 (buffer-file-name))
1109 (todo (eq major-mode 'todo-mode))
1110 (archive (eq major-mode 'todo-archive-mode))
1111 (filtered (eq major-mode 'todo-filtered-items-mode))
1112 (file1-sn (todo-short-file-name file1))
1113 (file2 (concat todo-directory file1-sn (cond (todo ".toda")
1114 (archive ".todo"))))
1115 (buf1 (current-buffer))
1116 (buf2 (when file2 (find-buffer-visiting file2)))
1117 (prompt1 (concat "Delete " (cond (todo "todo")
1118 (archive "archive")
1119 (filtered "filtered items"))
1120 " file \"%s\"? "))
1121 (prompt2 (concat "Also delete the corresponding "
1122 (cond (todo "archive") (archive "todo")) " file "
1123 (when buf2 "and kill the buffer visiting it? ")))
1124 (delete1 (yes-or-no-p (format prompt1 file1-sn)))
1125 (delete2 (when (and delete1 (or (file-exists-p file2) buf2))
1126 (yes-or-no-p prompt2))))
1127 (when delete1
1128 (when (file-exists-p file1) (delete-file file1))
1129 (setq todo-visited (delete file1 todo-visited))
1130 (kill-buffer buf1)
1131 (when delete2
1132 (when (file-exists-p file2) (delete-file file2))
1133 (setq todo-visited (delete file2 todo-visited))
1134 (and buf2 (kill-buffer buf2)))
1135 (setq todo-files (funcall todo-files-function)
1136 todo-archives (funcall todo-files-function t))
1137 (when (or (string= file1-sn todo-default-todo-file)
1138 (and delete2 (string= file1-sn todo-default-todo-file)))
1139 (setq todo-default-todo-file (todo-short-file-name (car todo-files))))
1140 (when (or (string= file1 todo-global-current-todo-file)
1141 (and delete2 (string= file2 todo-global-current-todo-file)))
1142 (setq todo-global-current-todo-file nil))
1143 (todo-reevaluate-filelist-defcustoms)
1144 (message (concat (cond (todo "Todo") (archive "Archive")) " file \"%s\" "
1145 (when delete2
1146 (concat "and its "
1147 (cond (todo "archive") (archive "todo"))
1148 " file "))
1149 "deleted") file1-sn))))
1150
1090(defvar todo-edit-buffer "*Todo Edit*" 1151(defvar todo-edit-buffer "*Todo Edit*"
1091 "Name of current buffer in Todo Edit mode.") 1152 "Name of current buffer in Todo Edit mode.")
1092 1153
@@ -1190,9 +1251,9 @@ category there as well."
1190 (save-excursion (todo-category-select))) 1251 (save-excursion (todo-category-select)))
1191 1252
1192(defun todo-delete-category (&optional arg) 1253(defun todo-delete-category (&optional arg)
1193 "Delete current todo category provided it is empty. 1254 "Delete current todo category provided it contains no items.
1194With ARG non-nil delete the category unconditionally, 1255With prefix ARG delete the category even if it does contain
1195i.e. including all existing todo and done items." 1256todo or done items."
1196 (interactive "P") 1257 (interactive "P")
1197 (let* ((file todo-current-todo-file) 1258 (let* ((file todo-current-todo-file)
1198 (cat (todo-current-category)) 1259 (cat (todo-current-category))
@@ -1723,7 +1784,7 @@ the new item:
1723 the item accordingly." 1784 the item accordingly."
1724 ;; If invoked outside of Todo mode and there is not yet any Todo 1785 ;; If invoked outside of Todo mode and there is not yet any Todo
1725 ;; file, initialize one. 1786 ;; file, initialize one.
1726 (if (null todo-files) 1787 (if (null (funcall todo-files-function))
1727 (todo-show) 1788 (todo-show)
1728 (let ((region (eq region-or-here 'region)) 1789 (let ((region (eq region-or-here 'region))
1729 (here (eq region-or-here 'here))) 1790 (here (eq region-or-here 'here)))
@@ -2958,31 +3019,32 @@ first visit in a session displays the first category in the
2958archive, subsequent visits return to the last category 3019archive, subsequent visits return to the last category
2959displayed." 3020displayed."
2960 (interactive) 3021 (interactive)
2961 (let* ((cat (todo-current-category)) 3022 (if (null (funcall todo-files-function t))
2962 (count (todo-get-count 'archived cat)) 3023 (message "There are no archive files")
2963 (archive (concat (file-name-sans-extension todo-current-todo-file) 3024 (let* ((cat (todo-current-category))
2964 ".toda")) 3025 (count (todo-get-count 'archived cat))
2965 place) 3026 (archive (concat (file-name-sans-extension todo-current-todo-file)
2966 (setq place (cond (ask 'other-archive) 3027 ".toda"))
2967 ((file-exists-p archive) 'this-archive) 3028 (place (cond (ask 'other-archive)
2968 (t (when (todo-y-or-n-p 3029 ((file-exists-p archive) 'this-archive)
2969 (concat "This file has no archive; " 3030 (t (when (todo-y-or-n-p
2970 "visit another archive? ")) 3031 (concat "This file has no archive; "
2971 'other-archive)))) 3032 "visit another archive? "))
2972 (when (eq place 'other-archive) 3033 'other-archive)))))
2973 (setq archive (todo-read-file-name "Choose a todo archive: " t t))) 3034 (when (eq place 'other-archive)
2974 (when (and (eq place 'this-archive) (zerop count)) 3035 (setq archive (todo-read-file-name "Choose a todo archive: " t t)))
2975 (setq place (when (todo-y-or-n-p 3036 (when (and (eq place 'this-archive) (zerop count))
2976 (concat "This category has no archived items;" 3037 (setq place (when (todo-y-or-n-p
2977 " visit archive anyway? ")) 3038 (concat "This category has no archived items;"
2978 'other-cat))) 3039 " visit archive anyway? "))
2979 (when place 3040 'other-cat)))
2980 (set-window-buffer (selected-window) 3041 (when place
2981 (set-buffer (find-file-noselect archive))) 3042 (set-window-buffer (selected-window)
2982 (if (member place '(other-archive other-cat)) 3043 (set-buffer (find-file-noselect archive)))
2983 (setq todo-category-number 1) 3044 (if (member place '(other-archive other-cat))
2984 (todo-category-number cat)) 3045 (setq todo-category-number 1)
2985 (todo-category-select)))) 3046 (todo-category-number cat))
3047 (todo-category-select)))))
2986 3048
2987(defun todo-choose-archive () 3049(defun todo-choose-archive ()
2988 "Choose an archive and visit it." 3050 "Choose an archive and visit it."
@@ -3010,9 +3072,7 @@ this category does not exist in the archive, it is created."
3010 (marked (assoc cat todo-categories-with-marks)) 3072 (marked (assoc cat todo-categories-with-marks))
3011 (afile (concat (file-name-sans-extension 3073 (afile (concat (file-name-sans-extension
3012 todo-current-todo-file) ".toda")) 3074 todo-current-todo-file) ".toda"))
3013 (archive (if (file-exists-p afile) 3075 (archive (find-file-noselect afile t))
3014 (find-file-noselect afile t)
3015 (get-buffer-create afile)))
3016 (item (and (todo-done-item-p) 3076 (item (and (todo-done-item-p)
3017 (concat (todo-item-string) "\n"))) 3077 (concat (todo-item-string) "\n")))
3018 (count 0) 3078 (count 0)
@@ -3056,7 +3116,6 @@ this category does not exist in the archive, it is created."
3056 (if (not (or marked all item)) 3116 (if (not (or marked all item))
3057 (throw 'end (message "Only done items can be archived")) 3117 (throw 'end (message "Only done items can be archived"))
3058 (with-current-buffer archive 3118 (with-current-buffer archive
3059 (unless buffer-file-name (erase-buffer))
3060 (let (buffer-read-only) 3119 (let (buffer-read-only)
3061 (widen) 3120 (widen)
3062 (goto-char (point-min)) 3121 (goto-char (point-min))
@@ -3076,11 +3135,13 @@ this category does not exist in the archive, it is created."
3076 (item))) 3135 (item)))
3077 (todo-update-count 'done (if (or marked all) count 1) cat) 3136 (todo-update-count 'done (if (or marked all) count 1) cat)
3078 (todo-update-categories-sexp) 3137 (todo-update-categories-sexp)
3079 ;; If archive is new, save to file now (using write-region in 3138 ;; If archive is new, save to file now (with
3080 ;; order not to get prompted for file to save to), to let 3139 ;; write-region to avoid prompt for file to save to)
3081 ;; auto-mode-alist take effect below. 3140 ;; to update todo-archives, and to let auto-mode-alist
3082 (unless buffer-file-name 3141 ;; take effect below on visiting the archive.
3083 (write-region nil nil afile) 3142 (unless (nth 7 (file-attributes afile))
3143 (write-region nil nil afile t t)
3144 (setq todo-archives (funcall todo-files-function t))
3084 (kill-buffer)))) 3145 (kill-buffer))))
3085 (with-current-buffer tbuf 3146 (with-current-buffer tbuf
3086 (cond 3147 (cond
@@ -3286,19 +3347,24 @@ categories display according to priority."
3286(defun todo-show-categories-table () 3347(defun todo-show-categories-table ()
3287 "Display a table of the current file's categories and item counts. 3348 "Display a table of the current file's categories and item counts.
3288 3349
3289In the initial display the categories are numbered, indicating 3350In the initial display the lines of the table are numbered,
3290their current order for navigating by \\[todo-forward-category] 3351indicating the current order of the categories when sequentially
3291and \\[todo-backward-category]. You can permanently change the 3352navigating through the todo file with `\\[todo-forward-category]'
3292order of the category at point by typing 3353and `\\[todo-backward-category]'. You can reorder the lines, and
3293\\[todo-set-category-number], \\[todo-raise-category] or 3354hence the category sequence, by typing `\\[todo-raise-category]'
3294\\[todo-lower-category]. 3355or `\\[todo-lower-category]' to raise or lower the category at
3356point, or by typing `\\[todo-set-category-number]' and entering a
3357number at the prompt or by typing `\\[todo-set-category-number]'
3358with a numeric prefix. If you save the todo file after
3359reordering the categories, the new order persists in subsequent
3360Emacs sessions.
3295 3361
3296The labels above the category names and item counts are buttons, 3362The labels above the category names and item counts are buttons,
3297and clicking these changes the display: sorted by category name 3363and clicking these changes the display: sorted by category name
3298or by the respective item counts (alternately descending or 3364or by the respective item counts (alternately descending or
3299ascending). In these displays the categories are not numbered 3365ascending). In these displays the categories are not numbered
3300and \\[todo-set-category-number], \\[todo-raise-category] and 3366and `\\[todo-set-category-number]', `\\[todo-raise-category]' and
3301\\[todo-lower-category] are disabled. (Programmatically, the 3367`\\[todo-lower-category]' are disabled. (Programmatically, the
3302sorting is triggered by passing a non-nil SORTKEY argument.) 3368sorting is triggered by passing a non-nil SORTKEY argument.)
3303 3369
3304In addition, the lines with the category names and item counts 3370In addition, the lines with the category names and item counts
@@ -4019,15 +4085,15 @@ regexp items."
4019 "Buffer type string for `todo-filter-items'.") 4085 "Buffer type string for `todo-filter-items'.")
4020 4086
4021(defun todo-filter-items (filter &optional new multifile) 4087(defun todo-filter-items (filter &optional new multifile)
4022 "Display a cross-category list of items filtered by FILTER. 4088 "Display a list of items filtered by FILTER.
4023The values of FILTER can be `top' for top priority items, a cons 4089The values of FILTER can be `top' for top priority items, a cons
4024of `top' and a number passed by the caller, `diary' for diary 4090of `top' and a number passed by the caller, `diary' for diary
4025items, or `regexp' for items matching a regular expression entered 4091items, or `regexp' for items matching a regular expression
4026by the user. The items can be from any categories in the current 4092entered by the user. The items can come from any categories in
4027todo file or, with non-nil MULTIFILE, from several files. If NEW 4093the current todo file or, with non-nil MULTIFILE, from several
4028is nil, visit an appropriate file containing the list of filtered 4094files. If NEW is nil, visit an appropriate file containing the
4029items; if there is no such file, or with non-nil NEW, build the 4095list of filtered items; if there is no such file, or with non-nil
4030list and display it. 4096NEW, build the list and display it.
4031 4097
4032See the documentation strings of the commands 4098See the documentation strings of the commands
4033`todo-filter-top-priorities', `todo-filter-diary-items', 4099`todo-filter-top-priorities', `todo-filter-diary-items',
@@ -4699,14 +4765,57 @@ short todo archive or top priorities file name, respectively."
4699 ((eq type 'regexp) ".todr") 4765 ((eq type 'regexp) ".todr")
4700 (t ".todo")))))) 4766 (t ".todo"))))))
4701 4767
4768(defun todo-check-file (file)
4769 "Check the state associated with FILE and update it if necessary.
4770If FILE exists, return t. If it does not exist and there is no
4771live buffer with its content, return nil; if there is such a
4772buffer and the user tries to show it, ask whether to restore
4773FILE, and if confirmed, do so and return t; else delete the
4774buffer, clean up the state and return nil."
4775 (setq todo-files (funcall todo-files-function))
4776 (setq todo-archives (funcall todo-files-function t))
4777 (if (file-exists-p file)
4778 t
4779 (setq todo-visited (delete file todo-visited))
4780 (let ((buf (find-buffer-visiting file)))
4781 (if (and buf
4782 (y-or-n-p
4783 (concat
4784 (format (concat "Todo file \"%s\" has been deleted but "
4785 "its content is still in a buffer!\n")
4786 (todo-short-file-name file))
4787 "Save that buffer and restore the todo file? ")))
4788 (progn
4789 (with-current-buffer buf (save-buffer))
4790 (setq todo-files (funcall todo-files-function))
4791 (setq todo-archives (funcall todo-files-function t))
4792 t)
4793 (let* ((files (append todo-files todo-archives))
4794 (tctf todo-current-todo-file)
4795 (tgctf todo-global-current-todo-file)
4796 (tdtf (todo-absolute-file-name todo-default-todo-file)))
4797 (unless (or (not todo-current-todo-file)
4798 (member todo-current-todo-file files))
4799 (setq todo-current-todo-file nil))
4800 (unless (or (not todo-global-current-todo-file)
4801 (member todo-global-current-todo-file files))
4802 (setq todo-global-current-todo-file nil))
4803 (unless (or (not todo-default-todo-file)
4804 (member todo-default-todo-file files))
4805 (setq todo-default-todo-file (todo-short-file-name
4806 (car todo-files))))
4807 (todo-reevaluate-filelist-defcustoms)
4808 (when buf (kill-buffer buf))
4809 nil)))))
4810
4702(defun todo-category-number (cat) 4811(defun todo-category-number (cat)
4703 "Return the number of category CAT in this todo file. 4812 "Return the number of category CAT in this todo file.
4704The buffer-local variable `todo-category-number' holds this 4813The buffer-local variable `todo-category-number' holds this
4705number as its value." 4814number as its value."
4706 (let ((categories (mapcar 'car todo-categories))) 4815 (let ((categories (mapcar 'car todo-categories)))
4707 (setq todo-category-number 4816 (setq todo-category-number
4708 ;; Increment by one, so that the highest priority category in Todo 4817 ;; Increment by one, so that the number of the first
4709 ;; Categories mode is numbered one rather than zero. 4818 ;; category is one rather than zero.
4710 (1+ (- (length categories) 4819 (1+ (- (length categories)
4711 (length (member cat categories))))))) 4820 (length (member cat categories)))))))
4712 4821
@@ -5384,7 +5493,27 @@ Each element of the list is a cons of a category name and the
5384file or list of files (as short file names) it is in. The files 5493file or list of files (as short file names) it is in. The files
5385are either the current (or if there is none, the default) todo 5494are either the current (or if there is none, the default) todo
5386file plus the files listed in `todo-category-completions-files', 5495file plus the files listed in `todo-category-completions-files',
5387or, with non-nil ARCHIVE, the current archive file." 5496or, with non-nil ARCHIVE, the current archive file.
5497
5498Before calculating the completions, update the value of
5499`todo-category-completions-files' in case any files named in it
5500have been removed."
5501 (let (deleted)
5502 (dolist (f todo-category-completions-files)
5503 (unless (file-exists-p (todo-absolute-file-name f))
5504 (setq todo-category-completions-files
5505 (delete f todo-category-completions-files))
5506 (push f deleted)))
5507 (when deleted
5508 (let ((pl (> (length deleted) 1))
5509 (names (mapconcat (lambda (f) (concat "\"" f "\"")) deleted ", ")))
5510 (message (concat "File" (if pl "s" "") " " names " ha" (if pl "ve" "s")
5511 " been deleted and removed from\n"
5512 "the list of category completion files")))
5513 (todo-reevaluate-category-completions-files-defcustom)
5514 (custom-set-default 'todo-category-completions-files
5515 (symbol-value 'todo-category-completions-files))
5516 (sleep-for 1.5)))
5388 (let* ((curfile (or todo-current-todo-file 5517 (let* ((curfile (or todo-current-todo-file
5389 (and todo-show-current-file 5518 (and todo-show-current-file
5390 todo-global-current-todo-file) 5519 todo-global-current-todo-file)
@@ -5435,6 +5564,7 @@ MUSTMATCH the name of an existing file must be chosen;
5435otherwise, a new file name is allowed." 5564otherwise, a new file name is allowed."
5436 (let* ((completion-ignore-case todo-completion-ignore-case) 5565 (let* ((completion-ignore-case todo-completion-ignore-case)
5437 (files (mapcar 'todo-short-file-name 5566 (files (mapcar 'todo-short-file-name
5567 ;; (funcall todo-files-function archive)))
5438 (if archive todo-archives todo-files))) 5568 (if archive todo-archives todo-files)))
5439 (file (completing-read prompt files nil mustmatch nil nil 5569 (file (completing-read prompt files nil mustmatch nil nil
5440 (if files 5570 (if files
@@ -5529,7 +5659,7 @@ categories from `todo-category-completions-files'."
5529 ;; Validate only against completion categories. 5659 ;; Validate only against completion categories.
5530 (let ((todo-categories categories)) 5660 (let ((todo-categories categories))
5531 (setq cat (todo-validate-name cat 'category))) 5661 (setq cat (todo-validate-name cat 'category)))
5532 ;; When user enters a nonexistest category name by jumping or 5662 ;; When user enters a nonexistent category name by jumping or
5533 ;; moving, confirm that it should be added, then validate. 5663 ;; moving, confirm that it should be added, then validate.
5534 (unless add 5664 (unless add
5535 (if (todo-y-or-n-p (format "Add new category \"%s\" to file \"%s\"? " 5665 (if (todo-y-or-n-p (format "Add new category \"%s\" to file \"%s\"? "
@@ -5867,13 +5997,24 @@ the empty string (i.e., no time string)."
5867 5997
5868(defun todo-reevaluate-default-file-defcustom () 5998(defun todo-reevaluate-default-file-defcustom ()
5869 "Reevaluate defcustom of `todo-default-todo-file'. 5999 "Reevaluate defcustom of `todo-default-todo-file'.
5870Called after adding or deleting a todo file." 6000Called after adding or deleting a todo file. If the value of
5871 (eval (defcustom todo-default-todo-file (car (funcall todo-files-function)) 6001`todo-default-todo-file' before calling this function was
5872 "Todo file visited by first session invocation of `todo-show'." 6002associated with an existing file, keep that value."
5873 :type `(radio ,@(mapcar (lambda (f) (list 'const f)) 6003 ;; (let ((curval todo-default-todo-file))
5874 (mapcar 'todo-short-file-name 6004 (eval
5875 (funcall todo-files-function)))) 6005 (defcustom todo-default-todo-file (todo-short-file-name
5876 :group 'todo))) 6006 (car (funcall todo-files-function)))
6007 "Todo file visited by first session invocation of `todo-show'."
6008 :type (when todo-files
6009 `(radio ,@(mapcar (lambda (f) (list 'const f))
6010 (mapcar 'todo-short-file-name
6011 (funcall todo-files-function)))))
6012 :group 'todo))
6013 ;; (when (and curval (file-exists-p (todo-absolute-file-name curval)))
6014 ;; (custom-set-default 'todo-default-todo-file curval)
6015 ;; ;; (custom-reevaluate-setting 'todo-default-todo-file)
6016 ;; )))
6017 )
5877 6018
5878(defun todo-reevaluate-category-completions-files-defcustom () 6019(defun todo-reevaluate-category-completions-files-defcustom ()
5879 "Reevaluate defcustom of `todo-category-completions-files'. 6020 "Reevaluate defcustom of `todo-category-completions-files'.
@@ -6060,6 +6201,7 @@ Filtered Items mode following todo (not done) items."
6060 ("Cu" todo-unmark-category) 6201 ("Cu" todo-unmark-category)
6061 ("Fh" todo-toggle-item-header) 6202 ("Fh" todo-toggle-item-header)
6062 ("h" todo-toggle-item-header) 6203 ("h" todo-toggle-item-header)
6204 ("Fk" todo-delete-file)
6063 ("Fe" todo-edit-file) 6205 ("Fe" todo-edit-file)
6064 ("FH" todo-toggle-item-highlighting) 6206 ("FH" todo-toggle-item-highlighting)
6065 ("H" todo-toggle-item-highlighting) 6207 ("H" todo-toggle-item-highlighting)
@@ -6226,12 +6368,13 @@ Filtered Items mode following todo (not done) items."
6226 6368
6227(defun todo-show-current-file () 6369(defun todo-show-current-file ()
6228 "Visit current instead of default todo file with `todo-show'. 6370 "Visit current instead of default todo file with `todo-show'.
6229This function is added to `pre-command-hook' when user option 6371Added to `pre-command-hook' in Todo mode when user option
6230`todo-show-current-file' is set to non-nil." 6372`todo-show-current-file' is set to non-nil."
6231 (setq todo-global-current-todo-file todo-current-todo-file)) 6373 (setq todo-global-current-todo-file todo-current-todo-file))
6232 6374
6233(defun todo-display-as-todo-file () 6375(defun todo-display-as-todo-file ()
6234 "Show todo files correctly when visited from outside of Todo mode." 6376 "Show todo files correctly when visited from outside of Todo mode.
6377Added to `find-file-hook' in Todo mode and Todo Archive mode."
6235 (and (member this-command todo-visit-files-commands) 6378 (and (member this-command todo-visit-files-commands)
6236 (= (- (point-max) (point-min)) (buffer-size)) 6379 (= (- (point-max) (point-min)) (buffer-size))
6237 (member major-mode '(todo-mode todo-archive-mode)) 6380 (member major-mode '(todo-mode todo-archive-mode))
@@ -6265,7 +6408,7 @@ This function is added to `kill-buffer-hook' in Todo mode."
6265 6408
6266(defun todo-reset-and-enable-done-separator () 6409(defun todo-reset-and-enable-done-separator ()
6267 "Show resized done items separator overlay after window change. 6410 "Show resized done items separator overlay after window change.
6268Added to `window-configuration-change-hook' in `todo-mode'." 6411Added to `window-configuration-change-hook' in Todo mode."
6269 (when (= 1 (length todo-done-separator-string)) 6412 (when (= 1 (length todo-done-separator-string))
6270 (let ((sep todo-done-separator)) 6413 (let ((sep todo-done-separator))
6271 (setq todo-done-separator (todo-done-separator)) 6414 (setq todo-done-separator (todo-done-separator))
diff --git a/lisp/cedet/ChangeLog b/lisp/cedet/ChangeLog
index 7a2c5755cc0..705277c97a0 100644
--- a/lisp/cedet/ChangeLog
+++ b/lisp/cedet/ChangeLog
@@ -2,7 +2,7 @@
2 2
3 * data-debug.el, cedet-idutils.el: Neuter the "Version:" header. 3 * data-debug.el, cedet-idutils.el: Neuter the "Version:" header.
4 4
52013-06-19 Glenn Morris <rgm@fencepost.gnu.org> 52013-06-19 Glenn Morris <rgm@gnu.org>
6 6
7 * semantic/idle.el (define-semantic-idle-service): 7 * semantic/idle.el (define-semantic-idle-service):
8 No need to use eval-and-compile, progn will do. 8 No need to use eval-and-compile, progn will do.
diff --git a/lisp/desktop.el b/lisp/desktop.el
index db77d7c3f5a..fcd032a64d0 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -196,9 +196,7 @@ Zero or nil means disable timer-based auto-saving."
196 (integer :tag "Seconds")) 196 (integer :tag "Seconds"))
197 :set (lambda (symbol value) 197 :set (lambda (symbol value)
198 (set-default symbol value) 198 (set-default symbol value)
199 (condition-case nil 199 (ignore-errors (desktop-auto-save-set-timer)))
200 (desktop-auto-save-set-timer)
201 (error nil)))
202 :group 'desktop 200 :group 'desktop
203 :version "24.4") 201 :version "24.4")
204 202
@@ -416,9 +414,8 @@ See `desktop-restore-eager'."
416 :version "22.1") 414 :version "22.1")
417 415
418;;;###autoload 416;;;###autoload
419(defvar desktop-save-buffer nil 417(defvar-local desktop-save-buffer nil
420 "When non-nil, save buffer status in desktop file. 418 "When non-nil, save buffer status in desktop file.
421This variable becomes buffer local when set.
422 419
423If the value is a function, it is called by `desktop-save' with argument 420If the value is a function, it is called by `desktop-save' with argument
424DESKTOP-DIRNAME to obtain auxiliary information to save in the desktop 421DESKTOP-DIRNAME to obtain auxiliary information to save in the desktop
@@ -430,7 +427,6 @@ When file names are returned, they should be formatted using the call
430Later, when `desktop-read' evaluates the desktop file, auxiliary information 427Later, when `desktop-read' evaluates the desktop file, auxiliary information
431is passed as the argument DESKTOP-BUFFER-MISC to functions in 428is passed as the argument DESKTOP-BUFFER-MISC to functions in
432`desktop-buffer-mode-handlers'.") 429`desktop-buffer-mode-handlers'.")
433(make-variable-buffer-local 'desktop-save-buffer)
434(make-obsolete-variable 'desktop-buffer-modes-to-save 430(make-obsolete-variable 'desktop-buffer-modes-to-save
435 'desktop-save-buffer "22.1") 431 'desktop-save-buffer "22.1")
436(make-obsolete-variable 'desktop-buffer-misc-functions 432(make-obsolete-variable 'desktop-buffer-misc-functions
@@ -582,15 +578,15 @@ Used to detect desktop file conflicts.")
582 "Return the PID of the Emacs process that owns the desktop file in DIRNAME. 578 "Return the PID of the Emacs process that owns the desktop file in DIRNAME.
583Return nil if no desktop file found or no Emacs process is using it. 579Return nil if no desktop file found or no Emacs process is using it.
584DIRNAME omitted or nil means use `desktop-dirname'." 580DIRNAME omitted or nil means use `desktop-dirname'."
585 (let (owner) 581 (let (owner
586 (and (file-exists-p (desktop-full-lock-name dirname)) 582 (file (desktop-full-lock-name dirname)))
587 (condition-case nil 583 (and (file-exists-p file)
588 (with-temp-buffer 584 (ignore-errors
589 (insert-file-contents-literally (desktop-full-lock-name dirname)) 585 (with-temp-buffer
590 (goto-char (point-min)) 586 (insert-file-contents-literally file)
591 (setq owner (read (current-buffer))) 587 (goto-char (point-min))
592 (integerp owner)) 588 (setq owner (read (current-buffer)))
593 (error nil)) 589 (integerp owner)))
594 owner))) 590 owner)))
595 591
596(defun desktop-claim-lock (&optional dirname) 592(defun desktop-claim-lock (&optional dirname)
@@ -636,7 +632,7 @@ Furthermore, it clears the variables listed in `desktop-globals-to-clear'."
636 (let ((bufname (buffer-name (car buffers)))) 632 (let ((bufname (buffer-name (car buffers))))
637 (or 633 (or
638 (null bufname) 634 (null bufname)
639 (string-match preserve-regexp bufname) 635 (string-match-p preserve-regexp bufname)
640 ;; Don't kill buffers made for internal purposes. 636 ;; Don't kill buffers made for internal purposes.
641 (and (not (equal bufname "")) (eq (aref bufname 0) ?\s)) 637 (and (not (equal bufname "")) (eq (aref bufname 0) ?\s))
642 (kill-buffer (car buffers)))) 638 (kill-buffer (car buffers))))
@@ -758,8 +754,7 @@ QUOTE may be `may' (value may be quoted),
758 ((consp value) 754 ((consp value)
759 (let ((p value) 755 (let ((p value)
760 newlist 756 newlist
761 use-list* 757 use-list*)
762 anynil)
763 (while (consp p) 758 (while (consp p)
764 (let ((q.sexp (desktop--v2s (car p)))) 759 (let ((q.sexp (desktop--v2s (car p))))
765 (push q.sexp newlist)) 760 (push q.sexp newlist))
@@ -841,17 +836,17 @@ MODE is the major mode.
841 dired-skip) 836 dired-skip)
842 (and (not (and (stringp desktop-buffers-not-to-save) 837 (and (not (and (stringp desktop-buffers-not-to-save)
843 (not filename) 838 (not filename)
844 (string-match desktop-buffers-not-to-save bufname))) 839 (string-match-p desktop-buffers-not-to-save bufname)))
845 (not (memq mode desktop-modes-not-to-save)) 840 (not (memq mode desktop-modes-not-to-save))
846 ;; FIXME this is broken if desktop-files-not-to-save is nil. 841 ;; FIXME this is broken if desktop-files-not-to-save is nil.
847 (or (and filename 842 (or (and filename
848 (stringp desktop-files-not-to-save) 843 (stringp desktop-files-not-to-save)
849 (not (string-match desktop-files-not-to-save filename))) 844 (not (string-match-p desktop-files-not-to-save filename)))
850 (and (memq mode '(dired-mode vc-dir-mode)) 845 (and (memq mode '(dired-mode vc-dir-mode))
851 (with-current-buffer bufname 846 (with-current-buffer bufname
852 (not (setq dired-skip 847 (not (setq dired-skip
853 (string-match desktop-files-not-to-save 848 (string-match-p desktop-files-not-to-save
854 default-directory))))) 849 default-directory)))))
855 (and (null filename) 850 (and (null filename)
856 (null dired-skip) ; bug#5755 851 (null dired-skip) ; bug#5755
857 (with-current-buffer bufname desktop-save-buffer)))))) 852 (with-current-buffer bufname desktop-save-buffer))))))
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index e4434c3a0d8..10968f7f8dd 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -136,7 +136,7 @@
136 136
137;;; Code: 137;;; Code:
138 138
139(eval-when-compile (require 'cl-lib)) 139(require 'cl-lib)
140(require 'dired) 140(require 'dired)
141(require 'image-mode) 141(require 'image-mode)
142(require 'jka-compr) 142(require 'jka-compr)
@@ -698,14 +698,6 @@ It's a subdirectory of `doc-view-cache-directory'."
698 (md5 (current-buffer))))) 698 (md5 (current-buffer)))))
699 doc-view-cache-directory))))) 699 doc-view-cache-directory)))))
700 700
701(defun doc-view-remove-if (predicate list)
702 "Return LIST with all items removed that satisfy PREDICATE."
703 (let (new-list)
704 (dolist (item list)
705 (when (not (funcall predicate item))
706 (setq new-list (cons item new-list))))
707 (nreverse new-list)))
708
709;;;###autoload 701;;;###autoload
710(defun doc-view-mode-p (type) 702(defun doc-view-mode-p (type)
711 "Return non-nil if document type TYPE is available for `doc-view'. 703 "Return non-nil if document type TYPE is available for `doc-view'.
@@ -1488,7 +1480,7 @@ If BACKWARD is non-nil, jump to the previous match."
1488(defun doc-view-search-next-match (arg) 1480(defun doc-view-search-next-match (arg)
1489 "Go to the ARGth next matching page." 1481 "Go to the ARGth next matching page."
1490 (interactive "p") 1482 (interactive "p")
1491 (let* ((next-pages (doc-view-remove-if 1483 (let* ((next-pages (cl-remove-if
1492 (lambda (i) (<= (car i) (doc-view-current-page))) 1484 (lambda (i) (<= (car i) (doc-view-current-page)))
1493 doc-view--current-search-matches)) 1485 doc-view--current-search-matches))
1494 (page (car (nth (1- arg) next-pages)))) 1486 (page (car (nth (1- arg) next-pages))))
@@ -1502,7 +1494,7 @@ If BACKWARD is non-nil, jump to the previous match."
1502(defun doc-view-search-previous-match (arg) 1494(defun doc-view-search-previous-match (arg)
1503 "Go to the ARGth previous matching page." 1495 "Go to the ARGth previous matching page."
1504 (interactive "p") 1496 (interactive "p")
1505 (let* ((prev-pages (doc-view-remove-if 1497 (let* ((prev-pages (cl-remove-if
1506 (lambda (i) (>= (car i) (doc-view-current-page))) 1498 (lambda (i) (>= (car i) (doc-view-current-page)))
1507 doc-view--current-search-matches)) 1499 doc-view--current-search-matches))
1508 (page (car (nth (1- arg) (nreverse prev-pages))))) 1500 (page (car (nth (1- arg) (nreverse prev-pages)))))
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 6ef2e29dc83..67992d16527 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -62,9 +62,8 @@
62;; macro in a more concise way that omits the comments. 62;; macro in a more concise way that omits the comments.
63 63
64;;; Code: 64;;; Code:
65
66(eval-when-compile (require 'cl-lib))
67 65
66(require 'cl-lib)
68(require 'kmacro) 67(require 'kmacro)
69 68
70;;; The user-level commands for editing macros. 69;;; The user-level commands for editing macros.
@@ -444,14 +443,14 @@ doubt, use whitespace."
444 (let* ((prefix 443 (let* ((prefix
445 (or (and (integerp (aref rest-mac 0)) 444 (or (and (integerp (aref rest-mac 0))
446 (memq (aref rest-mac 0) mdigs) 445 (memq (aref rest-mac 0) mdigs)
447 (memq (key-binding (edmacro-subseq rest-mac 0 1)) 446 (memq (key-binding (cl-subseq rest-mac 0 1))
448 '(digit-argument negative-argument)) 447 '(digit-argument negative-argument))
449 (let ((i 1)) 448 (let ((i 1))
450 (while (memq (aref rest-mac i) (cdr mdigs)) 449 (while (memq (aref rest-mac i) (cdr mdigs))
451 (cl-incf i)) 450 (cl-incf i))
452 (and (not (memq (aref rest-mac i) pkeys)) 451 (and (not (memq (aref rest-mac i) pkeys))
453 (prog1 (vconcat "M-" (edmacro-subseq rest-mac 0 i) " ") 452 (prog1 (vconcat "M-" (cl-subseq rest-mac 0 i) " ")
454 (cl-callf edmacro-subseq rest-mac i))))) 453 (cl-callf cl-subseq rest-mac i)))))
455 (and (eq (aref rest-mac 0) ?\C-u) 454 (and (eq (aref rest-mac 0) ?\C-u)
456 (eq (key-binding [?\C-u]) 'universal-argument) 455 (eq (key-binding [?\C-u]) 'universal-argument)
457 (let ((i 1)) 456 (let ((i 1))
@@ -459,7 +458,7 @@ doubt, use whitespace."
459 (cl-incf i)) 458 (cl-incf i))
460 (and (not (memq (aref rest-mac i) pkeys)) 459 (and (not (memq (aref rest-mac i) pkeys))
461 (prog1 (cl-loop repeat i concat "C-u ") 460 (prog1 (cl-loop repeat i concat "C-u ")
462 (cl-callf edmacro-subseq rest-mac i))))) 461 (cl-callf cl-subseq rest-mac i)))))
463 (and (eq (aref rest-mac 0) ?\C-u) 462 (and (eq (aref rest-mac 0) ?\C-u)
464 (eq (key-binding [?\C-u]) 'universal-argument) 463 (eq (key-binding [?\C-u]) 'universal-argument)
465 (let ((i 1)) 464 (let ((i 1))
@@ -469,18 +468,18 @@ doubt, use whitespace."
469 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)) 468 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
470 (cl-incf i)) 469 (cl-incf i))
471 (and (not (memq (aref rest-mac i) pkeys)) 470 (and (not (memq (aref rest-mac i) pkeys))
472 (prog1 (vconcat "C-u " (edmacro-subseq rest-mac 1 i) " ") 471 (prog1 (vconcat "C-u " (cl-subseq rest-mac 1 i) " ")
473 (cl-callf edmacro-subseq rest-mac i))))))) 472 (cl-callf cl-subseq rest-mac i)))))))
474 (bind-len (apply 'max 1 473 (bind-len (apply 'max 1
475 (cl-loop for map in maps 474 (cl-loop for map in maps
476 for b = (lookup-key map rest-mac) 475 for b = (lookup-key map rest-mac)
477 when b collect b))) 476 when b collect b)))
478 (key (edmacro-subseq rest-mac 0 bind-len)) 477 (key (cl-subseq rest-mac 0 bind-len))
479 (fkey nil) tlen tkey 478 (fkey nil) tlen tkey
480 (bind (or (cl-loop for map in maps for b = (lookup-key map key) 479 (bind (or (cl-loop for map in maps for b = (lookup-key map key)
481 thereis (and (not (integerp b)) b)) 480 thereis (and (not (integerp b)) b))
482 (and (setq fkey (lookup-key local-function-key-map rest-mac)) 481 (and (setq fkey (lookup-key local-function-key-map rest-mac))
483 (setq tlen fkey tkey (edmacro-subseq rest-mac 0 tlen) 482 (setq tlen fkey tkey (cl-subseq rest-mac 0 tlen)
484 fkey (lookup-key local-function-key-map tkey)) 483 fkey (lookup-key local-function-key-map tkey))
485 (cl-loop for map in maps 484 (cl-loop for map in maps
486 for b = (lookup-key map fkey) 485 for b = (lookup-key map fkey)
@@ -507,7 +506,7 @@ doubt, use whitespace."
507 (> first 32) (<= first maxkey) (/= first 92) 506 (> first 32) (<= first maxkey) (/= first 92)
508 (progn 507 (progn
509 (if (> text 30) (setq text 30)) 508 (if (> text 30) (setq text 30))
510 (setq desc (concat (edmacro-subseq rest-mac 0 text))) 509 (setq desc (concat (cl-subseq rest-mac 0 text)))
511 (when (string-match "^[ACHMsS]-." desc) 510 (when (string-match "^[ACHMsS]-." desc)
512 (setq text 2) 511 (setq text 2)
513 (cl-callf substring desc 0 2)) 512 (cl-callf substring desc 0 2))
@@ -524,7 +523,7 @@ doubt, use whitespace."
524 (> text bind-len) 523 (> text bind-len)
525 (memq (aref rest-mac text) '(return 13)) 524 (memq (aref rest-mac text) '(return 13))
526 (progn 525 (progn
527 (setq desc (concat (edmacro-subseq rest-mac bind-len text))) 526 (setq desc (concat (cl-subseq rest-mac bind-len text)))
528 (commandp (intern-soft desc)))) 527 (commandp (intern-soft desc))))
529 (if (commandp (intern-soft desc)) (setq bind desc)) 528 (if (commandp (intern-soft desc)) (setq bind desc))
530 (setq desc (format "<<%s>>" desc)) 529 (setq desc (format "<<%s>>" desc))
@@ -562,14 +561,14 @@ doubt, use whitespace."
562 (setq desc (concat (edmacro-sanitize-for-string prefix) desc))) 561 (setq desc (concat (edmacro-sanitize-for-string prefix) desc)))
563 (unless (string-match " " desc) 562 (unless (string-match " " desc)
564 (let ((times 1) (pos bind-len)) 563 (let ((times 1) (pos bind-len))
565 (while (not (edmacro-mismatch rest-mac rest-mac 564 (while (not (cl-mismatch rest-mac rest-mac
566 0 bind-len pos (+ bind-len pos))) 565 0 bind-len pos (+ bind-len pos)))
567 (cl-incf times) 566 (cl-incf times)
568 (cl-incf pos bind-len)) 567 (cl-incf pos bind-len))
569 (when (> times 1) 568 (when (> times 1)
570 (setq desc (format "%d*%s" times desc)) 569 (setq desc (format "%d*%s" times desc))
571 (setq bind-len (* bind-len times))))) 570 (setq bind-len (* bind-len times)))))
572 (setq rest-mac (edmacro-subseq rest-mac bind-len)) 571 (setq rest-mac (cl-subseq rest-mac bind-len))
573 (if verbose 572 (if verbose
574 (progn 573 (progn
575 (unless (equal res "") (cl-callf concat res "\n")) 574 (unless (equal res "") (cl-callf concat res "\n"))
@@ -590,50 +589,6 @@ doubt, use whitespace."
590 (cl-incf len (length desc))))) 589 (cl-incf len (length desc)))))
591 res)) 590 res))
592 591
593(defun edmacro-mismatch (cl-seq1 cl-seq2 cl-start1 cl-end1 cl-start2 cl-end2)
594 "Compare SEQ1 with SEQ2, return index of first mismatching element.
595Return nil if the sequences match. If one sequence is a prefix of the
596other, the return value indicates the end of the shorted sequence.
597\n(fn SEQ1 SEQ2 START1 END1 START2 END2)"
598 (or cl-end1 (setq cl-end1 (length cl-seq1)))
599 (or cl-end2 (setq cl-end2 (length cl-seq2)))
600 (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1)))
601 (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2))))
602 (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
603 (eql (if cl-p1 (car cl-p1)
604 (aref cl-seq1 cl-start1))
605 (if cl-p2 (car cl-p2)
606 (aref cl-seq2 cl-start2))))
607 (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)
608 cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2)))
609 (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
610 cl-start1)))
611
612(defun edmacro-subseq (seq start &optional end)
613 "Return the subsequence of SEQ from START to END.
614If END is omitted, it defaults to the length of the sequence.
615If START or END is negative, it counts from the end."
616 (if (stringp seq) (substring seq start end)
617 (let (len)
618 (and end (< end 0) (setq end (+ end (setq len (length seq)))))
619 (if (< start 0) (setq start (+ start (or len (setq len (length seq))))))
620 (cond ((listp seq)
621 (if (> start 0) (setq seq (nthcdr start seq)))
622 (if end
623 (let ((res nil))
624 (while (>= (setq end (1- end)) start)
625 (push (pop seq) res))
626 (nreverse res))
627 (copy-sequence seq)))
628 (t
629 (or end (setq end (or len (length seq))))
630 (let ((res (make-vector (max (- end start) 0) nil))
631 (i 0))
632 (while (< start end)
633 (aset res i (aref seq start))
634 (setq i (1+ i) start (1+ start)))
635 res))))))
636
637(defun edmacro-sanitize-for-string (seq) 592(defun edmacro-sanitize-for-string (seq)
638 "Convert a key sequence vector SEQ into a string. 593 "Convert a key sequence vector SEQ into a string.
639The string represents the same events; Meta is indicated by bit 7. 594The string represents the same events; Meta is indicated by bit 7.
@@ -760,7 +715,7 @@ This function assumes that the events can be stored in a string."
760 (eq (aref res 1) ?\() 715 (eq (aref res 1) ?\()
761 (eq (aref res (- (length res) 2)) ?\C-x) 716 (eq (aref res (- (length res) 2)) ?\C-x)
762 (eq (aref res (- (length res) 1)) ?\))) 717 (eq (aref res (- (length res) 1)) ?\)))
763 (setq res (edmacro-subseq res 2 -2))) 718 (setq res (cl-subseq res 2 -2)))
764 (if (and (not need-vector) 719 (if (and (not need-vector)
765 (cl-loop for ch across res 720 (cl-loop for ch across res
766 always (and (characterp ch) 721 always (and (characterp ch)
diff --git a/lisp/emacs-lisp/.gitignore b/lisp/emacs-lisp/.gitignore
deleted file mode 100644
index 133e79e817a..00000000000
--- a/lisp/emacs-lisp/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1!*-loaddefs.el
2
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 3cf744f1245..c47c9b61030 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -1957,7 +1957,7 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
1957 "Collect multiple return values. 1957 "Collect multiple return values.
1958FORM must return a list; the BODY is then executed with the first N elements 1958FORM must return a list; the BODY is then executed with the first N elements
1959of this list bound (`let'-style) to each of the symbols SYM in turn. This 1959of this list bound (`let'-style) to each of the symbols SYM in turn. This
1960is analogous to the Common Lisp `cl-multiple-value-bind' macro, using lists to 1960is analogous to the Common Lisp `multiple-value-bind' macro, using lists to
1961simulate true multiple return values. For compatibility, (cl-values A B C) is 1961simulate true multiple return values. For compatibility, (cl-values A B C) is
1962a synonym for (list A B C). 1962a synonym for (list A B C).
1963 1963
@@ -1975,7 +1975,7 @@ a synonym for (list A B C).
1975 "Collect multiple return values. 1975 "Collect multiple return values.
1976FORM must return a list; the first N elements of this list are stored in 1976FORM must return a list; the first N elements of this list are stored in
1977each of the symbols SYM in turn. This is analogous to the Common Lisp 1977each of the symbols SYM in turn. This is analogous to the Common Lisp
1978`cl-multiple-value-setq' macro, using lists to simulate true multiple return 1978`multiple-value-setq' macro, using lists to simulate true multiple return
1979values. For compatibility, (cl-values A B C) is a synonym for (list A B C). 1979values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
1980 1980
1981\(fn (SYM...) FORM)" 1981\(fn (SYM...) FORM)"
@@ -2002,7 +2002,7 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
2002 (cons 'progn body)) 2002 (cons 'progn body))
2003;;;###autoload 2003;;;###autoload
2004(defmacro cl-the (_type form) 2004(defmacro cl-the (_type form)
2005 "At present this ignores _TYPE and is simply equivalent to FORM." 2005 "At present this ignores TYPE and is simply equivalent to FORM."
2006 (declare (indent 1) (debug (cl-type-spec form))) 2006 (declare (indent 1) (debug (cl-type-spec form)))
2007 form) 2007 form)
2008 2008
@@ -2059,7 +2059,7 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
2059 "Declare SPECS about the current function while compiling. 2059 "Declare SPECS about the current function while compiling.
2060For instance 2060For instance
2061 2061
2062 \(cl-declare (warn 0)) 2062 (cl-declare (warn 0))
2063 2063
2064will turn off byte-compile warnings in the function. 2064will turn off byte-compile warnings in the function.
2065See Info node `(cl)Declarations' for details." 2065See Info node `(cl)Declarations' for details."
@@ -2279,8 +2279,8 @@ KEYWORD can be one of :conc-name, :constructor, :copier, :predicate,
2279Each SLOT may instead take the form (SNAME SDEFAULT SOPTIONS...), where 2279Each SLOT may instead take the form (SNAME SDEFAULT SOPTIONS...), where
2280SDEFAULT is the default value of that slot and SOPTIONS are keyword-value 2280SDEFAULT is the default value of that slot and SOPTIONS are keyword-value
2281pairs for that slot. 2281pairs for that slot.
2282Currently, only one keyword is supported, `:read-only'. If this has a non-nil 2282Currently, only one keyword is supported, `:read-only'. If this has a
2283value, that slot cannot be set via `setf'. 2283non-nil value, that slot cannot be set via `setf'.
2284 2284
2285\(fn NAME SLOTS...)" 2285\(fn NAME SLOTS...)"
2286 (declare (doc-string 2) (indent 1) 2286 (declare (doc-string 2) (indent 1)
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index 319af588eac..36c72f3a3bd 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -53,7 +53,7 @@
53;;; Code: 53;;; Code:
54 54
55(require 'macroexp) 55(require 'macroexp)
56(eval-when-compile (require 'cl-lib)) 56(require 'cl-lib)
57(eval-when-compile (require 'pcase)) 57(eval-when-compile (require 'pcase))
58 58
59;;; Options 59;;; Options
@@ -263,26 +263,6 @@ An extant spec symbol is a symbol that is not a function and has a
263 263
264;;; Utilities 264;;; Utilities
265 265
266;; Define edebug-gensym - from old cl.el
267(defvar edebug-gensym-index 0
268 "Integer used by `edebug-gensym' to produce new names.")
269
270(defun edebug-gensym (&optional prefix)
271 "Generate a fresh uninterned symbol.
272There is an optional argument, PREFIX. PREFIX is the string
273that begins the new name. Most people take just the default,
274except when debugging needs suggest otherwise."
275 (if (null prefix)
276 (setq prefix "G"))
277 (let ((newsymbol nil)
278 (newname ""))
279 (while (not newsymbol)
280 (setq newname (concat prefix (int-to-string edebug-gensym-index)))
281 (setq edebug-gensym-index (+ edebug-gensym-index 1))
282 (if (not (intern-soft newname))
283 (setq newsymbol (make-symbol newname))))
284 newsymbol))
285
286(defun edebug-lambda-list-keywordp (object) 266(defun edebug-lambda-list-keywordp (object)
287 "Return t if OBJECT is a lambda list keyword. 267 "Return t if OBJECT is a lambda list keyword.
288A lambda list keyword is a symbol that starts with `&'." 268A lambda list keyword is a symbol that starts with `&'."
@@ -1186,7 +1166,7 @@ Maybe clear the markers and delete the symbol's edebug property?"
1186 ;; Uses the dynamically bound vars edebug-def-name and edebug-def-args. 1166 ;; Uses the dynamically bound vars edebug-def-name and edebug-def-args.
1187 ;; Do this after parsing since that may find a name. 1167 ;; Do this after parsing since that may find a name.
1188 (setq edebug-def-name 1168 (setq edebug-def-name
1189 (or edebug-def-name edebug-old-def-name (edebug-gensym "edebug-anon"))) 1169 (or edebug-def-name edebug-old-def-name (cl-gensym "edebug-anon")))
1190 `(edebug-enter 1170 `(edebug-enter
1191 (quote ,edebug-def-name) 1171 (quote ,edebug-def-name)
1192 ,(if edebug-inside-func 1172 ,(if edebug-inside-func
@@ -1299,7 +1279,7 @@ expressions; a `progn' form will be returned enclosing these forms."
1299 1279
1300 ;; Set the name here if it was not set by edebug-make-enter-wrapper. 1280 ;; Set the name here if it was not set by edebug-make-enter-wrapper.
1301 (setq edebug-def-name 1281 (setq edebug-def-name
1302 (or edebug-def-name edebug-old-def-name (edebug-gensym "edebug-anon"))) 1282 (or edebug-def-name edebug-old-def-name (cl-gensym "edebug-anon")))
1303 1283
1304 ;; Add this def as a dependent of containing def. Buggy. 1284 ;; Add this def as a dependent of containing def. Buggy.
1305 '(if (and edebug-containing-def-name 1285 '(if (and edebug-containing-def-name
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 656cb0a6a14..1f5edefea08 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -54,7 +54,7 @@
54 54
55;;; Code: 55;;; Code:
56 56
57(eval-when-compile (require 'cl-lib)) 57(require 'cl-lib)
58(require 'button) 58(require 'button)
59(require 'debug) 59(require 'debug)
60(require 'easymenu) 60(require 'easymenu)
@@ -87,127 +87,6 @@
87 87
88;;; Copies/reimplementations of cl functions. 88;;; Copies/reimplementations of cl functions.
89 89
90(defun ert--cl-do-remf (plist tag)
91 "Copy of `cl-do-remf'. Modify PLIST by removing TAG."
92 (let ((p (cdr plist)))
93 (while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p))))
94 (and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t))))
95
96(defun ert--remprop (sym tag)
97 "Copy of `cl-remprop'. Modify SYM's plist by removing TAG."
98 (let ((plist (symbol-plist sym)))
99 (if (and plist (eq tag (car plist)))
100 (progn (setplist sym (cdr (cdr plist))) t)
101 (ert--cl-do-remf plist tag))))
102
103(defun ert--remove-if-not (ert-pred ert-list)
104 "A reimplementation of `remove-if-not'.
105
106ERT-PRED is a predicate, ERT-LIST is the input list."
107 (cl-loop for ert-x in ert-list
108 if (funcall ert-pred ert-x)
109 collect ert-x))
110
111(defun ert--intersection (a b)
112 "A reimplementation of `intersection'. Intersect the sets A and B.
113
114Elements are compared using `eql'."
115 (cl-loop for x in a
116 if (memql x b)
117 collect x))
118
119(defun ert--set-difference (a b)
120 "A reimplementation of `set-difference'. Subtract the set B from the set A.
121
122Elements are compared using `eql'."
123 (cl-loop for x in a
124 unless (memql x b)
125 collect x))
126
127(defun ert--set-difference-eq (a b)
128 "A reimplementation of `set-difference'. Subtract the set B from the set A.
129
130Elements are compared using `eq'."
131 (cl-loop for x in a
132 unless (memq x b)
133 collect x))
134
135(defun ert--union (a b)
136 "A reimplementation of `union'. Compute the union of the sets A and B.
137
138Elements are compared using `eql'."
139 (append a (ert--set-difference b a)))
140
141(eval-and-compile
142 (defvar ert--gensym-counter 0))
143
144(eval-and-compile
145 (defun ert--gensym (&optional prefix)
146 "Only allows string PREFIX, not compatible with CL."
147 (unless prefix (setq prefix "G"))
148 (make-symbol (format "%s%s"
149 prefix
150 (prog1 ert--gensym-counter
151 (cl-incf ert--gensym-counter))))))
152
153(defun ert--coerce-to-vector (x)
154 "Coerce X to a vector."
155 (when (char-table-p x) (error "Not supported"))
156 (if (vectorp x)
157 x
158 (vconcat x)))
159
160(cl-defun ert--remove* (x list &key key test)
161 "Does not support all the keywords of remove*."
162 (unless key (setq key #'identity))
163 (unless test (setq test #'eql))
164 (cl-loop for y in list
165 unless (funcall test x (funcall key y))
166 collect y))
167
168(defun ert--string-position (c s)
169 "Return the position of the first occurrence of C in S, or nil if none."
170 (cl-loop for i from 0
171 for x across s
172 when (eql x c) return i))
173
174(defun ert--mismatch (a b)
175 "Return index of first element that differs between A and B.
176
177Like `mismatch'. Uses `equal' for comparison."
178 (cond ((or (listp a) (listp b))
179 (ert--mismatch (ert--coerce-to-vector a)
180 (ert--coerce-to-vector b)))
181 ((> (length a) (length b))
182 (ert--mismatch b a))
183 (t
184 (let ((la (length a))
185 (lb (length b)))
186 (cl-assert (arrayp a) t)
187 (cl-assert (arrayp b) t)
188 (cl-assert (<= la lb) t)
189 (cl-loop for i below la
190 when (not (equal (aref a i) (aref b i))) return i
191 finally (cl-return (if (/= la lb)
192 la
193 (cl-assert (equal a b) t)
194 nil)))))))
195
196(defun ert--subseq (seq start &optional end)
197 "Return a subsequence of SEQ from START to END."
198 (when (char-table-p seq) (error "Not supported"))
199 (let ((vector (substring (ert--coerce-to-vector seq) start end)))
200 (cl-etypecase seq
201 (vector vector)
202 (string (concat vector))
203 (list (append vector nil))
204 (bool-vector (cl-loop with result
205 = (make-bool-vector (length vector) nil)
206 for i below (length vector) do
207 (setf (aref result i) (aref vector i))
208 finally (cl-return result)))
209 (char-table (cl-assert nil)))))
210
211(defun ert-equal-including-properties (a b) 90(defun ert-equal-including-properties (a b)
212 "Return t if A and B have similar structure and contents. 91 "Return t if A and B have similar structure and contents.
213 92
@@ -258,7 +137,7 @@ Emacs bug 6581 at URL `http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6581'."
258 137
259(defun ert-make-test-unbound (symbol) 138(defun ert-make-test-unbound (symbol)
260 "Make SYMBOL name no test. Return SYMBOL." 139 "Make SYMBOL name no test. Return SYMBOL."
261 (ert--remprop symbol 'ert--test) 140 (cl-remprop symbol 'ert--test)
262 symbol) 141 symbol)
263 142
264(defun ert--parse-keys-and-body (keys-and-body) 143(defun ert--parse-keys-and-body (keys-and-body)
@@ -396,8 +275,8 @@ DATA is displayed to the user and should state the reason of the failure."
396 cl-macro-environment))))) 275 cl-macro-environment)))))
397 (cond 276 (cond
398 ((or (atom form) (ert--special-operator-p (car form))) 277 ((or (atom form) (ert--special-operator-p (car form)))
399 (let ((value (ert--gensym "value-"))) 278 (let ((value (cl-gensym "value-")))
400 `(let ((,value (ert--gensym "ert-form-evaluation-aborted-"))) 279 `(let ((,value (cl-gensym "ert-form-evaluation-aborted-")))
401 ,(funcall inner-expander 280 ,(funcall inner-expander
402 `(setq ,value ,form) 281 `(setq ,value ,form)
403 `(list ',whole :form ',form :value ,value) 282 `(list ',whole :form ',form :value ,value)
@@ -410,10 +289,10 @@ DATA is displayed to the user and should state the reason of the failure."
410 (and (consp fn-name) 289 (and (consp fn-name)
411 (eql (car fn-name) 'lambda) 290 (eql (car fn-name) 'lambda)
412 (listp (cdr fn-name))))) 291 (listp (cdr fn-name)))))
413 (let ((fn (ert--gensym "fn-")) 292 (let ((fn (cl-gensym "fn-"))
414 (args (ert--gensym "args-")) 293 (args (cl-gensym "args-"))
415 (value (ert--gensym "value-")) 294 (value (cl-gensym "value-"))
416 (default-value (ert--gensym "ert-form-evaluation-aborted-"))) 295 (default-value (cl-gensym "ert-form-evaluation-aborted-")))
417 `(let ((,fn (function ,fn-name)) 296 `(let ((,fn (function ,fn-name))
418 (,args (list ,@arg-forms))) 297 (,args (list ,@arg-forms)))
419 (let ((,value ',default-value)) 298 (let ((,value ',default-value))
@@ -450,7 +329,7 @@ FORM-DESCRIPTION-FORM before it has called INNER-FORM."
450 (ert--expand-should-1 329 (ert--expand-should-1
451 whole form 330 whole form
452 (lambda (inner-form form-description-form value-var) 331 (lambda (inner-form form-description-form value-var)
453 (let ((form-description (ert--gensym "form-description-"))) 332 (let ((form-description (cl-gensym "form-description-")))
454 `(let (,form-description) 333 `(let (,form-description)
455 ,(funcall inner-expander 334 ,(funcall inner-expander
456 `(unwind-protect 335 `(unwind-protect
@@ -491,7 +370,7 @@ and aborts the current test as failed if it doesn't."
491 (list type) 370 (list type)
492 (symbol (list type))))) 371 (symbol (list type)))))
493 (cl-assert signaled-conditions) 372 (cl-assert signaled-conditions)
494 (unless (ert--intersection signaled-conditions handled-conditions) 373 (unless (cl-intersection signaled-conditions handled-conditions)
495 (ert-fail (append 374 (ert-fail (append
496 (funcall form-description-fn) 375 (funcall form-description-fn)
497 (list 376 (list
@@ -528,8 +407,8 @@ failed."
528 `(should-error ,form ,@keys) 407 `(should-error ,form ,@keys)
529 form 408 form
530 (lambda (inner-form form-description-form value-var) 409 (lambda (inner-form form-description-form value-var)
531 (let ((errorp (ert--gensym "errorp")) 410 (let ((errorp (cl-gensym "errorp"))
532 (form-description-fn (ert--gensym "form-description-fn-"))) 411 (form-description-fn (cl-gensym "form-description-fn-")))
533 `(let ((,errorp nil) 412 `(let ((,errorp nil)
534 (,form-description-fn (lambda () ,form-description-form))) 413 (,form-description-fn (lambda () ,form-description-form)))
535 (condition-case -condition- 414 (condition-case -condition-
@@ -591,7 +470,7 @@ Returns nil if they are."
591 `(proper-lists-of-different-length ,(length a) ,(length b) 470 `(proper-lists-of-different-length ,(length a) ,(length b)
592 ,a ,b 471 ,a ,b
593 first-mismatch-at 472 first-mismatch-at
594 ,(ert--mismatch a b)) 473 ,(cl-mismatch a b :test 'equal))
595 (cl-loop for i from 0 474 (cl-loop for i from 0
596 for ai in a 475 for ai in a
597 for bi in b 476 for bi in b
@@ -611,7 +490,7 @@ Returns nil if they are."
611 ,a ,b 490 ,a ,b
612 ,@(unless (char-table-p a) 491 ,@(unless (char-table-p a)
613 `(first-mismatch-at 492 `(first-mismatch-at
614 ,(ert--mismatch a b)))) 493 ,(cl-mismatch a b :test 'equal))))
615 (cl-loop for i from 0 494 (cl-loop for i from 0
616 for ai across a 495 for ai across a
617 for bi across b 496 for bi across b
@@ -656,8 +535,8 @@ key/value pairs in each list does not matter."
656 ;; work, so let's punt on it for now. 535 ;; work, so let's punt on it for now.
657 (let* ((keys-a (ert--significant-plist-keys a)) 536 (let* ((keys-a (ert--significant-plist-keys a))
658 (keys-b (ert--significant-plist-keys b)) 537 (keys-b (ert--significant-plist-keys b))
659 (keys-in-a-not-in-b (ert--set-difference-eq keys-a keys-b)) 538 (keys-in-a-not-in-b (cl-set-difference keys-a keys-b :test 'eq))
660 (keys-in-b-not-in-a (ert--set-difference-eq keys-b keys-a))) 539 (keys-in-b-not-in-a (cl-set-difference keys-b keys-a :test 'eq)))
661 (cl-flet ((explain-with-key (key) 540 (cl-flet ((explain-with-key (key)
662 (let ((value-a (plist-get a key)) 541 (let ((value-a (plist-get a key))
663 (value-b (plist-get b key))) 542 (value-b (plist-get b key)))
@@ -1090,7 +969,7 @@ contained in UNIVERSE."
1090 (cl-etypecase universe 969 (cl-etypecase universe
1091 ((member t) (mapcar #'ert-get-test 970 ((member t) (mapcar #'ert-get-test
1092 (apropos-internal selector #'ert-test-boundp))) 971 (apropos-internal selector #'ert-test-boundp)))
1093 (list (ert--remove-if-not (lambda (test) 972 (list (cl-remove-if-not (lambda (test)
1094 (and (ert-test-name test) 973 (and (ert-test-name test)
1095 (string-match selector 974 (string-match selector
1096 (ert-test-name test)))) 975 (ert-test-name test))))
@@ -1123,13 +1002,13 @@ contained in UNIVERSE."
1123 (not 1002 (not
1124 (cl-assert (eql (length operands) 1)) 1003 (cl-assert (eql (length operands) 1))
1125 (let ((all-tests (ert-select-tests 't universe))) 1004 (let ((all-tests (ert-select-tests 't universe)))
1126 (ert--set-difference all-tests 1005 (cl-set-difference all-tests
1127 (ert-select-tests (car operands) 1006 (ert-select-tests (car operands)
1128 all-tests)))) 1007 all-tests))))
1129 (or 1008 (or
1130 (cl-case (length operands) 1009 (cl-case (length operands)
1131 (0 (ert-select-tests 'nil universe)) 1010 (0 (ert-select-tests 'nil universe))
1132 (t (ert--union (ert-select-tests (car operands) universe) 1011 (t (cl-union (ert-select-tests (car operands) universe)
1133 (ert-select-tests `(or ,@(cdr operands)) 1012 (ert-select-tests `(or ,@(cdr operands))
1134 universe))))) 1013 universe)))))
1135 (tag 1014 (tag
@@ -1141,7 +1020,7 @@ contained in UNIVERSE."
1141 universe))) 1020 universe)))
1142 (satisfies 1021 (satisfies
1143 (cl-assert (eql (length operands) 1)) 1022 (cl-assert (eql (length operands) 1))
1144 (ert--remove-if-not (car operands) 1023 (cl-remove-if-not (car operands)
1145 (ert-select-tests 't universe)))))))) 1024 (ert-select-tests 't universe))))))))
1146 1025
1147(defun ert--insert-human-readable-selector (selector) 1026(defun ert--insert-human-readable-selector (selector)
@@ -1285,7 +1164,7 @@ Also changes the counters in STATS to match."
1285 "Create a new `ert--stats' object for running TESTS. 1164 "Create a new `ert--stats' object for running TESTS.
1286 1165
1287SELECTOR is the selector that was used to select TESTS." 1166SELECTOR is the selector that was used to select TESTS."
1288 (setq tests (ert--coerce-to-vector tests)) 1167 (setq tests (cl-coerce tests 'vector))
1289 (let ((map (make-hash-table :size (length tests)))) 1168 (let ((map (make-hash-table :size (length tests))))
1290 (cl-loop for i from 0 1169 (cl-loop for i from 0
1291 for test across tests 1170 for test across tests
@@ -1548,10 +1427,10 @@ This can be used as an inverse of `add-to-list'."
1548 (unless key (setq key #'identity)) 1427 (unless key (setq key #'identity))
1549 (unless test (setq test #'equal)) 1428 (unless test (setq test #'equal))
1550 (setf (symbol-value list-var) 1429 (setf (symbol-value list-var)
1551 (ert--remove* element 1430 (cl-remove element
1552 (symbol-value list-var) 1431 (symbol-value list-var)
1553 :key key 1432 :key key
1554 :test test))) 1433 :test test)))
1555 1434
1556 1435
1557;;; Some basic interactive functions. 1436;;; Some basic interactive functions.
@@ -1810,7 +1689,7 @@ BEGIN and END specify a region in the current buffer."
1810 "Return the first line of S, or S if it contains no newlines. 1689 "Return the first line of S, or S if it contains no newlines.
1811 1690
1812The return value does not include the line terminator." 1691The return value does not include the line terminator."
1813 (substring s 0 (ert--string-position ?\n s))) 1692 (substring s 0 (cl-position ?\n s)))
1814 1693
1815(defun ert-face-for-test-result (expectedp) 1694(defun ert-face-for-test-result (expectedp)
1816 "Return a face that shows whether a test result was expected or unexpected. 1695 "Return a face that shows whether a test result was expected or unexpected.
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index 1919d47687b..56bfe04f9ce 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -131,8 +131,9 @@ Returns the number of actions taken."
131 (unwind-protect 131 (unwind-protect
132 (progn 132 (progn
133 (if (stringp prompter) 133 (if (stringp prompter)
134 (setq prompter (lambda (object) 134 (setq prompter (let ((prompter prompter))
135 (format prompter object)))) 135 (lambda (object)
136 (format prompter object)))))
136 (while (funcall next) 137 (while (funcall next)
137 (setq prompt (funcall prompter elt)) 138 (setq prompt (funcall prompter elt))
138 (cond ((stringp prompt) 139 (cond ((stringp prompt)
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index e000c343721..511f1480099 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -482,12 +482,19 @@ MATCH is the pattern that needs to be matched, of the form:
482 all)) 482 all))
483 '(:pcase--succeed . nil)))) 483 '(:pcase--succeed . nil))))
484 484
485(defun pcase--split-pred (upat pat) 485(defun pcase--split-pred (vars upat pat)
486 ;; FIXME: For predicates like (pred (> a)), two such predicates may
487 ;; actually refer to different variables `a'.
488 (let (test) 486 (let (test)
489 (cond 487 (cond
490 ((equal upat pat) '(:pcase--succeed . :pcase--fail)) 488 ((and (equal upat pat)
489 ;; For predicates like (pred (> a)), two such predicates may
490 ;; actually refer to different variables `a'.
491 (or (and (eq 'pred (car upat)) (symbolp (cadr upat)))
492 ;; FIXME: `vars' gives us the environment in which `upat' will
493 ;; run, but we don't have the environment in which `pat' will
494 ;; run, so we can't do a reliable verification. But let's try
495 ;; and catch at least the easy cases such as (bug#14773).
496 (not (pcase--fgrep (mapcar #'car vars) (cadr upat)))))
497 '(:pcase--succeed . :pcase--fail))
491 ((and (eq 'pred (car upat)) 498 ((and (eq 'pred (car upat))
492 (eq 'pred (car-safe pat)) 499 (eq 'pred (car-safe pat))
493 (or (member (cons (cadr upat) (cadr pat)) 500 (or (member (cons (cadr upat) (cadr pat))
@@ -589,7 +596,7 @@ Otherwise, it defers to REST which is a list of branches of the form
589 (if (eq (car upat) 'pred) (pcase--mark-used sym)) 596 (if (eq (car upat) 'pred) (pcase--mark-used sym))
590 (let* ((splitrest 597 (let* ((splitrest
591 (pcase--split-rest 598 (pcase--split-rest
592 sym (lambda (pat) (pcase--split-pred upat pat)) rest)) 599 sym (lambda (pat) (pcase--split-pred vars upat pat)) rest))
593 (then-rest (car splitrest)) 600 (then-rest (car splitrest))
594 (else-rest (cdr splitrest))) 601 (else-rest (cdr splitrest)))
595 (pcase--if (if (and (eq (car upat) 'pred) (symbolp (cadr upat))) 602 (pcase--if (if (and (eq (car upat) 'pred) (symbolp (cadr upat)))
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index e7b371365e4..c39d896f3d3 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -996,93 +996,7 @@ as a Meta key and any number of multiple escapes are allowed."
996 (suspend-emacs)) 996 (suspend-emacs))
997 (viper-change-state-to-emacs))) 997 (viper-change-state-to-emacs)))
998 998
999
1000;; Intercept ESC sequences on dumb terminals.
1001;; Based on the idea contributed by Marcelino Veiga Tuimil <mveiga@dit.upm.es>
1002
1003;; Check if last key was ESC and if so try to reread it as a function key.
1004;; But only if there are characters to read during a very short time.
1005;; Returns the last event, if any.
1006(defun viper-envelop-ESC-key ()
1007 (let ((event last-input-event)
1008 (keyseq [nil])
1009 (inhibit-quit t))
1010 (if (viper-ESC-event-p event)
1011 (progn
1012 ;; Some versions of Emacs (eg., 22.50.8 (?)) have a bug, which makes
1013 ;; even a single ESC into a fast keyseq. To guard against this, we
1014 ;; added a check if there are other events as well. Keep the next
1015 ;; line for the next time the bug reappears, so that will remember to
1016 ;; report it.
1017 ;;(if (and (viper-fast-keysequence-p) unread-command-events)
1018 (if (viper-fast-keysequence-p) ;; for Emacsen without the above bug
1019 (progn
1020 (let (minor-mode-map-alist emulation-mode-map-alists)
1021 (viper-set-unread-command-events event)
1022 (setq keyseq (read-key-sequence nil 'continue-echo))
1023 ) ; let
1024 ;; If keyseq translates into something that still has ESC
1025 ;; at the beginning, separate ESC from the rest of the seq.
1026 ;; In XEmacs we check for events that are keypress meta-key
1027 ;; and convert them into [escape key]
1028 ;;
1029 ;; This is needed for the following reason:
1030 ;; If ESC is the first symbol, we interpret it as if the
1031 ;; user typed ESC and then quickly some other symbols.
1032 ;; If ESC is not the first one, then the key sequence
1033 ;; entered was apparently translated into a function key or
1034 ;; something (e.g., one may have
1035 ;; (define-key function-key-map "\e[192z" [f11])
1036 ;; which would translate the escape-sequence generated by
1037 ;; f11 in an xterm window into the symbolic key f11.
1038 ;;
1039 ;; If `first-key' is not an ESC event, we make it into the
1040 ;; last-command-event in order to pretend that this key was
1041 ;; pressed. This is needed to allow arrow keys to be bound to
1042 ;; macros. Otherwise, viper-exec-mapped-kbd-macro will think
1043 ;; that the last event was ESC and so it'll execute whatever is
1044 ;; bound to ESC. (Viper macros can't be bound to
1045 ;; ESC-sequences).
1046 (let* ((first-key (elt keyseq 0))
1047 (key-mod (event-modifiers first-key)))
1048 (cond ((and (viper-ESC-event-p first-key)
1049 (not (viper-translate-all-ESC-keysequences)))
1050 ;; put keys following ESC on the unread list
1051 ;; and return ESC as the key-sequence
1052 (viper-set-unread-command-events (viper-subseq keyseq 1))
1053 (setq last-input-event event
1054 keyseq (if (featurep 'emacs)
1055 "\e"
1056 (vector (character-to-event ?\e)))))
1057 ((and (featurep 'xemacs)
1058 (key-press-event-p first-key)
1059 (equal '(meta) key-mod))
1060 (viper-set-unread-command-events
1061 (vconcat (vector
1062 (character-to-event (event-key first-key)))
1063 (viper-subseq keyseq 1)))
1064 (setq last-input-event event
1065 keyseq (vector (character-to-event ?\e))))
1066 ((eventp first-key)
1067 (setq last-command-event
1068 (viper-copy-event first-key)))
1069 ))
1070 ) ; end progn
1071
1072 ;; this is escape event with nothing after it
1073 ;; put in unread-command-event and then re-read
1074 (viper-set-unread-command-events event)
1075 (setq keyseq (read-key-sequence nil))
1076 ))
1077 ;; not an escape event
1078 (setq keyseq (vector event)))
1079 keyseq))
1080
1081
1082
1083;; Listen to ESC key. 999;; Listen to ESC key.
1084;; If a sequence of keys starting with ESC is issued with very short delays,
1085;; interpret these keys in Emacs mode, so ESC won't be interpreted as a Vi key.
1086(defun viper-intercept-ESC-key () 1000(defun viper-intercept-ESC-key ()
1087 "Function that implements ESC key in Viper emulation of Vi." 1001 "Function that implements ESC key in Viper emulation of Vi."
1088 (interactive) 1002 (interactive)
@@ -1090,13 +1004,7 @@ as a Meta key and any number of multiple escapes are allowed."
1090 ;; minor-mode map(s) have been temporarily disabled so the ESC 1004 ;; minor-mode map(s) have been temporarily disabled so the ESC
1091 ;; binding to viper-intercept-ESC-key doesn't hide the binding we're 1005 ;; binding to viper-intercept-ESC-key doesn't hide the binding we're
1092 ;; looking for (Bug#9146): 1006 ;; looking for (Bug#9146):
1093 (let* ((event (viper-envelop-ESC-key)) 1007 (let* ((cmd 'viper-intercept-ESC-key))
1094 (cmd (cond ((equal event viper-ESC-key)
1095 'viper-intercept-ESC-key)
1096 ((let ((emulation-mode-map-alists nil))
1097 (key-binding event)))
1098 (t
1099 (error "Viper bell")))))
1100 1008
1101 ;; call the actual function to execute ESC (if no other symbols followed) 1009 ;; call the actual function to execute ESC (if no other symbols followed)
1102 ;; or the key bound to the ESC sequence (if the sequence was issued 1010 ;; or the key bound to the ESC sequence (if the sequence was issued
@@ -4289,6 +4197,11 @@ cursor move past the beginning of line."
4289 (t 4197 (t
4290 (backward-char 1)))) 4198 (backward-char 1))))
4291 4199
4200(defun viper-del-forward-char-in-insert ()
4201 "Delete 1 char forward if in insert or replace state."
4202 (interactive)
4203 ;; don't put on kill ring
4204 (delete-char 1 nil))
4292 4205
4293 4206
4294;; join lines. 4207;; join lines.
@@ -4947,7 +4860,7 @@ Please, specify your level now: ")
4947 (interactive) 4860 (interactive)
4948 (if (< viper-expert-level 2) 4861 (if (< viper-expert-level 2)
4949 (save-buffers-kill-emacs) 4862 (save-buffers-kill-emacs)
4950 (save-buffer) 4863 (if (buffer-modified-p) (save-buffer))
4951 (kill-buffer (current-buffer)))) 4864 (kill-buffer (current-buffer))))
4952 4865
4953 4866
diff --git a/lisp/emulation/viper-keym.el b/lisp/emulation/viper-keym.el
index 0d9d300ab1a..d33b5f4ed58 100644
--- a/lisp/emulation/viper-keym.el
+++ b/lisp/emulation/viper-keym.el
@@ -192,7 +192,7 @@ Enter as a sexp. Examples: \"\\C-z\", [(control ?z)]."
192 :type 'string 192 :type 'string
193 :group 'viper) 193 :group 'viper)
194 194
195(defvar viper-ESC-key (kbd "ESC") 195(defconst viper-ESC-key [escape]
196 "Key used to ESC.") 196 "Key used to ESC.")
197 197
198 198
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 7f432cdc143..266af1abf2b 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -14,7 +14,7 @@
14;; filed in the Emacs bug reporting system against this file, a copy 14;; filed in the Emacs bug reporting system against this file, a copy
15;; of the bug report be sent to the maintainer's email address. 15;; of the bug report be sent to the maintainer's email address.
16 16
17(defconst viper-version "3.14.1 of August 15, 2009" 17(defconst viper-version "3.14.2 of July 4, 2013"
18 "The current version of Viper") 18 "The current version of Viper")
19 19
20;; This file is part of GNU Emacs. 20;; This file is part of GNU Emacs.
@@ -411,6 +411,7 @@ widget."
411 dired-mode 411 dired-mode
412 efs-mode 412 efs-mode
413 tar-mode 413 tar-mode
414 egg-status-buffer-mode
414 415
415 browse-kill-ring-mode 416 browse-kill-ring-mode
416 recentf-mode 417 recentf-mode
@@ -660,7 +661,7 @@ user customization, unrelated to Viper. For instance, if the user advised
660undone. 661undone.
661It also can't undo some Viper settings." 662It also can't undo some Viper settings."
662 (interactive) 663 (interactive)
663 664 (viper-setup-ESC-to-escape nil)
664 ;; restore non-viper vars 665 ;; restore non-viper vars
665 (setq-default 666 (setq-default
666 next-line-add-newlines 667 next-line-add-newlines
@@ -825,6 +826,58 @@ It also can't undo some Viper settings."
825 (add-hook 'viper-post-command-hooks 'set-viper-state-in-major-mode t)) 826 (add-hook 'viper-post-command-hooks 'set-viper-state-in-major-mode t))
826 827
827 828
829;;; Handling of tty's ESC event
830
831;; On a tty, an ESC event can either be the user hitting the escape key, or
832;; some element of a byte sequence used to encode for example cursor keys.
833;; So we try to recognize those events that correspond to the escape key and
834;; turn them into `escape' events (same as used under GUIs). The heuristic we
835;; use to distinguish the two cases is based, as usual, on a timeout, and on
836;; the fact that the special ESC=>escape mapping only takes place if the whole
837;; last key-sequence so far is just [?\e], i.e. either we're still in
838;; read-key-sequence, or the last read-key-sequence only read [?\e], which
839;; should ideally never happen because it should have been mapped to [escape].
840
841(defun viper--tty-ESC-filter (map)
842 (if (and (equal (this-single-command-keys) [?\e])
843 (sit-for (/ viper-fast-keyseq-timeout 1000)))
844 [escape] map))
845
846(defun viper--lookup-key (map key)
847 "Kind of like `lookup-key'.
848Two differences:
849- KEY is a single key, not a sequence.
850- the result is the \"raw\" binding, so it can be a `menu-item', rather than the
851 binding contained in that menu item."
852 (catch 'found
853 (map-keymap (lambda (k b) (if (equal key k) (throw 'found b))) map)))
854
855(defun viper-catch-tty-ESC ()
856 "Setup key mappings of current terminal to turn a tty's ESC into `escape'."
857 (when (memq (terminal-live-p (frame-terminal)) '(t pc))
858 (let ((esc-binding (viper-uncatch-tty-ESC)))
859 (define-key input-decode-map
860 [?\e] `(menu-item "" ,esc-binding :filter viper--tty-ESC-filter)))))
861
862(defun viper-uncatch-tty-ESC ()
863 "Don't hack ESC into `escape' any more."
864 (let ((b (viper--lookup-key input-decode-map ?\e)))
865 (and (eq 'menu-item (car-safe b))
866 (eq 'viper--tty-ESC-filter (nth 4 b))
867 (define-key input-decode-map [?\e] (setq b (nth 2 b))))
868 b))
869
870(defun viper-setup-ESC-to-escape (enable)
871 (if enable
872 (add-hook 'tty-setup-hook 'viper-catch-tty-ESC)
873 (remove-hook 'tty-setup-hook 'viper-catch-tty-ESC))
874 (let ((seen ()))
875 (dolist (frame (frame-list))
876 (let ((terminal (frame-terminal frame)))
877 (unless (memq terminal seen)
878 (push terminal seen)
879 (with-selected-frame frame
880 (if enable (viper-catch-tty-ESC) (viper-uncatch-tty-ESC))))))))
828 881
829;; This sets major mode hooks to make them come up in vi-state. 882;; This sets major mode hooks to make them come up in vi-state.
830(defun viper-set-hooks () 883(defun viper-set-hooks ()
@@ -837,6 +890,8 @@ It also can't undo some Viper settings."
837 (if (eq (default-value 'major-mode) 'fundamental-mode) 890 (if (eq (default-value 'major-mode) 'fundamental-mode)
838 (setq-default major-mode 'viper-mode)) 891 (setq-default major-mode 'viper-mode))
839 892
893 (viper-setup-ESC-to-escape t)
894
840 (add-hook 'change-major-mode-hook 'viper-major-mode-change-sentinel) 895 (add-hook 'change-major-mode-hook 'viper-major-mode-change-sentinel)
841 (add-hook 'find-file-hooks 'set-viper-state-in-major-mode) 896 (add-hook 'find-file-hooks 'set-viper-state-in-major-mode)
842 897
@@ -847,13 +902,6 @@ It also can't undo some Viper settings."
847 (defvar emerge-startup-hook) 902 (defvar emerge-startup-hook)
848 (add-hook 'emerge-startup-hook 'viper-change-state-to-emacs) 903 (add-hook 'emerge-startup-hook 'viper-change-state-to-emacs)
849 904
850 ;; Zap bad bindings in flyspell-mouse-map, which prevent ESC from working
851 ;; over misspelled words (due to the overlay keymaps)
852 (defvar flyspell-mode-hook)
853 (defvar flyspell-mouse-map)
854 (add-hook 'flyspell-mode-hook
855 (lambda ()
856 (define-key flyspell-mouse-map viper-ESC-key nil)))
857 ;; if viper is started from .emacs, it might be impossible to get certain 905 ;; if viper is started from .emacs, it might be impossible to get certain
858 ;; info about the display and windows until emacs initialization is complete 906 ;; info about the display and windows until emacs initialization is complete
859 ;; So do it via the window-setup-hook 907 ;; So do it via the window-setup-hook
diff --git a/lisp/faces.el b/lisp/faces.el
index 0a3f0551325..9a34aec2549 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2097,6 +2097,10 @@ the above example."
2097 nil)))) 2097 nil))))
2098 type) 2098 type)
2099 2099
2100(defvar tty-setup-hook nil
2101 "Hook run after running the initialization function of a new text terminal.
2102This can be used to fine tune the `input-decode-map', for example.")
2103
2100(defun tty-run-terminal-initialization (frame &optional type) 2104(defun tty-run-terminal-initialization (frame &optional type)
2101 "Run the special initialization code for the terminal type of FRAME. 2105 "Run the special initialization code for the terminal type of FRAME.
2102The optional TYPE parameter may be used to override the autodetected 2106The optional TYPE parameter may be used to override the autodetected
@@ -2122,7 +2126,8 @@ terminal type to a different value."
2122 type) 2126 type)
2123 (when (fboundp term-init-func) 2127 (when (fboundp term-init-func)
2124 (funcall term-init-func)) 2128 (funcall term-init-func))
2125 (set-terminal-parameter frame 'terminal-initted term-init-func))))) 2129 (set-terminal-parameter frame 'terminal-initted term-init-func)
2130 (run-hooks 'tty-setup-hook)))))
2126 2131
2127;; Called from C function init_display to initialize faces of the 2132;; Called from C function init_display to initialize faces of the
2128;; dumped terminal frame on startup. 2133;; dumped terminal frame on startup.
diff --git a/lisp/filenotify.el b/lisp/filenotify.el
new file mode 100644
index 00000000000..e170db2dd5f
--- /dev/null
+++ b/lisp/filenotify.el
@@ -0,0 +1,324 @@
1;;; filenotify.el --- watch files for changes on disk
2
3;; Copyright (C) 2013 Free Software Foundation, Inc.
4
5;; Author: Michael Albinus <michael.albinus@gmx.de>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Commentary
23
24;; This package is an abstraction layer from the different low-level
25;; file notification packages `gfilenotify', `inotify' and
26;; `w32notify'.
27
28;;; Code:
29
30;;;###autoload
31(defconst file-notify-support
32 (cond
33 ((featurep 'gfilenotify) 'gfilenotify)
34 ((featurep 'inotify) 'inotify)
35 ((featurep 'w32notify) 'w32notify))
36 "Non-nil when Emacs has been compiled with file notification support.
37The value is the name of the low-level file notification package
38to be used for local file systems. Remote file notifications
39could use another implementation.")
40
41(defvar file-notify-descriptors (make-hash-table :test 'equal)
42 "Hash table for registered file notification descriptors.
43A key in this hash table is the descriptor as returned from
44`gfilenotify', `inotify', `w32notify' or a file name handler.
45The value in the hash table is the cons cell (DIR FILE CALLBACK).")
46
47;; This function is used by `gfilenotify', `inotify' and `w32notify' events.
48;;;###autoload
49(defun file-notify-handle-event (event)
50 "Handle file system monitoring event.
51If EVENT is a filewatch event, call its callback.
52Otherwise, signal a `file-notify-error'."
53 (interactive "e")
54 (if (and (eq (car event) 'file-notify)
55 (>= (length event) 3))
56 (funcall (nth 2 event) (nth 1 event))
57 (signal 'file-notify-error
58 (cons "Not a valid file-notify event" event))))
59
60(defvar file-notify--pending-events nil
61 "List of pending file notification events for a future `renamed' action.
62The entries are a list (DESCRIPTOR ACTION FILE COOKIE). ACTION
63is either `moved-from' or `renamed-from'.")
64
65(defun file-notify--event-file-name (event)
66 "Return file name of file notification event, or nil."
67 (expand-file-name
68 (or (and (stringp (nth 2 event)) (nth 2 event)) "")
69 (car (gethash (car event) file-notify-descriptors))))
70
71;; Only `gfilenotify' could return two file names.
72(defun file-notify--event-file1-name (event)
73 "Return second file name of file notification event, or nil.
74This is available in case a file has been moved."
75 (and (stringp (nth 3 event))
76 (expand-file-name
77 (nth 3 event) (car (gethash (car event) file-notify-descriptors)))))
78
79;; Cookies are offered by `inotify' only.
80(defun file-notify--event-cookie (event)
81 "Return cookie of file notification event, or nil.
82This is available in case a file has been moved."
83 (nth 3 event))
84
85;; The callback function used to map between specific flags of the
86;; respective file notifications, and the ones we return.
87(defun file-notify-callback (event)
88 "Handle an EVENT returned from file notification.
89EVENT is the same one as in `file-notify-handle-event' except the
90car of that event, which is the symbol `file-notify'."
91 (let* ((desc (car event))
92 (registered (gethash desc file-notify-descriptors))
93 (pending-event (assoc desc file-notify--pending-events))
94 (actions (nth 1 event))
95 (file (file-notify--event-file-name event))
96 file1 cookie callback)
97
98 ;; Make actions a list.
99 (unless (consp actions) (setq actions (cons actions nil)))
100
101 ;; Check, that event is meant for us.
102 (unless (setq callback (nth 2 registered))
103 (setq actions nil))
104
105 ;; Loop over actions. In fact, more than one action happens only
106 ;; for `inotify'.
107 (dolist (action actions)
108
109 ;; Send pending event, if it doesn't match.
110 (when (and pending-event
111 ;; The cookie doesn't match.
112 (not (eq (file-notify--event-cookie pending-event)
113 (file-notify--event-cookie event)))
114 (or
115 ;; inotify.
116 (and (eq (nth 1 pending-event) 'moved-from)
117 (not (eq action 'moved-to)))
118 ;; w32notify.
119 (and (eq (nth 1 pending-event) 'renamed-from)
120 (not (eq action 'renamed-to)))))
121 (funcall callback
122 (list desc 'deleted
123 (file-notify--event-file-name pending-event)))
124 (setq file-notify--pending-events
125 (delete pending-event file-notify--pending-events)))
126
127 ;; Map action. We ignore all events which cannot be mapped.
128 (setq action
129 (cond
130 ;; gfilenotify.
131 ((memq action '(attribute-changed changed created deleted)) action)
132 ((eq action 'moved)
133 (setq file1 (file-notify--event-file1-name event))
134 'renamed)
135
136 ;; inotify.
137 ((eq action 'attrib) 'attribute-changed)
138 ((eq action 'create) 'created)
139 ((eq action 'modify) 'changed)
140 ((memq action '(delete 'delete-self move-self)) 'deleted)
141 ;; Make the event pending.
142 ((eq action 'moved-from)
143 (add-to-list 'file-notify--pending-events
144 (list desc action file
145 (file-notify--event-cookie event)))
146 nil)
147 ;; Look for pending event.
148 ((eq action 'moved-to)
149 (if (null pending-event)
150 'created
151 (setq file1 file
152 file (file-notify--event-file-name pending-event)
153 file-notify--pending-events
154 (delete pending-event file-notify--pending-events))
155 'renamed))
156
157 ;; w32notify.
158 ((eq action 'added) 'created)
159 ((eq action 'modified) 'changed)
160 ((eq action 'removed) 'deleted)
161 ;; Make the event pending.
162 ((eq 'renamed-from action)
163 (add-to-list 'file-notify--pending-events
164 (list desc action file
165 (file-notify--event-cookie event)))
166 nil)
167 ;; Look for pending event.
168 ((eq 'renamed-to action)
169 (if (null pending-event)
170 'created
171 (setq file1 file
172 file (file-notify--event-file-name pending-event)
173 file-notify--pending-events
174 (delete pending-event file-notify--pending-events))
175 'renamed))))
176
177 ;; Apply callback.
178 (when (and action
179 (or
180 ;; If there is no relative file name for that watch,
181 ;; we watch the whole directory.
182 (null (nth 1 registered))
183 ;; File matches.
184 (string-equal
185 (nth 1 registered) (file-name-nondirectory file))
186 ;; File1 matches.
187 (and (stringp file1)
188 (string-equal
189 (nth 1 registered) (file-name-nondirectory file1)))))
190 (if file1
191 (funcall callback (list desc action file file1))
192 (funcall callback (list desc action file)))))))
193
194(defun file-notify-add-watch (file flags callback)
195 "Add a watch for filesystem events pertaining to FILE.
196This arranges for filesystem events pertaining to FILE to be reported
197to Emacs. Use `file-notify-rm-watch' to cancel the watch.
198
199The returned value is a descriptor for the added watch. If the
200file cannot be watched for some reason, this function signals a
201`file-notify-error' error.
202
203FLAGS is a list of conditions to set what will be watched for. It can
204include the following symbols:
205
206 `change' -- watch for file changes
207 `attribute-change' -- watch for file attributes changes, like
208 permissions or modification time
209
210If FILE is a directory, 'change' watches for file creation or
211deletion in that directory.
212
213When any event happens, Emacs will call the CALLBACK function passing
214it a single argument EVENT, which is of the form
215
216 (DESCRIPTOR ACTION FILE [FILE1])
217
218DESCRIPTOR is the same object as the one returned by this function.
219ACTION is the description of the event. It could be any one of the
220following:
221
222 `created' -- FILE was created
223 `deleted' -- FILE was deleted
224 `changed' -- FILE has changed
225 `renamed' -- FILE has been renamed to FILE1
226 `attribute-changed' -- a FILE attribute was changed
227
228FILE is the name of the file whose event is being reported."
229 ;; Check arguments.
230 (unless (stringp file)
231 (signal 'wrong-type-argument (list file)))
232 (setq file (expand-file-name file))
233 (unless (and (consp flags)
234 (null (delq 'change (delq 'attribute-change (copy-tree flags)))))
235 (signal 'wrong-type-argument (list flags)))
236 (unless (functionp callback)
237 (signal 'wrong-type-argument (list callback)))
238
239 (let* ((handler (find-file-name-handler file 'file-notify-add-watch))
240 (dir (directory-file-name
241 (if (or (and (not handler) (eq file-notify-support 'w32notify))
242 (file-directory-p file))
243 file
244 (file-name-directory file))))
245 desc func l-flags)
246
247 ;; Check, whether this has been registered already.
248; (maphash
249; (lambda (key value)
250; (when (equal (cons file callback) value) (setq desc key)))
251; file-notify-descriptors)
252
253 (unless desc
254 (if handler
255 ;; A file name handler could exist even if there is no local
256 ;; file notification support.
257 (setq desc (funcall
258 handler 'file-notify-add-watch dir flags callback))
259
260 ;; Check, whether Emacs has been compiled with file
261 ;; notification support.
262 (unless file-notify-support
263 (signal 'file-notify-error
264 '("No file notification package available")))
265
266 ;; Determine low-level function to be called.
267 (setq func (cond
268 ((eq file-notify-support 'gfilenotify) 'gfile-add-watch)
269 ((eq file-notify-support 'inotify) 'inotify-add-watch)
270 ((eq file-notify-support 'w32notify) 'w32notify-add-watch)))
271
272 ;; Determine respective flags.
273 (if (eq file-notify-support 'gfilenotify)
274 (setq l-flags '(watch-mounts send-moved))
275 (when (memq 'change flags)
276 (setq
277 l-flags
278 (cond
279 ((eq file-notify-support 'inotify) '(create modify move delete))
280 ((eq file-notify-support 'w32notify)
281 '(file-name directory-name size last-write-time)))))
282 (when (memq 'attribute-change flags)
283 (add-to-list
284 'l-flags
285 (cond
286 ((eq file-notify-support 'inotify) 'attrib)
287 ((eq file-notify-support 'w32notify) 'attributes)))))
288
289 ;; Call low-level function.
290 (setq desc (funcall func dir l-flags 'file-notify-callback))))
291
292 ;; Return descriptor.
293 (puthash desc
294 (list (directory-file-name
295 (if (file-directory-p dir) dir (file-name-directory dir)))
296 (unless (file-directory-p file)
297 (file-name-nondirectory file))
298 callback)
299 file-notify-descriptors)
300 desc))
301
302(defun file-notify-rm-watch (descriptor)
303 "Remove an existing watch specified by its DESCRIPTOR.
304DESCRIPTOR should be an object returned by `file-notify-add-watch'."
305 (let ((file (car (gethash descriptor file-notify-descriptors)))
306 handler)
307
308 (when (stringp file)
309 (setq handler (find-file-name-handler file 'file-notify-rm-watch))
310 (if handler
311 (funcall handler 'file-notify-rm-watch descriptor)
312 (funcall
313 (cond
314 ((eq file-notify-support 'gfilenotify) 'gfile-rm-watch)
315 ((eq file-notify-support 'inotify) 'inotify-rm-watch)
316 ((eq file-notify-support 'w32notify) 'w32notify-rm-watch))
317 descriptor)))
318
319 (remhash descriptor file-notify-descriptors)))
320
321;; The end:
322(provide 'filenotify)
323
324;;; filenotify.el ends here
diff --git a/lisp/files.el b/lisp/files.el
index e59a9acb7b9..ff4ccec2279 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -316,6 +316,7 @@ A value of nil means don't add newlines.
316 316
317Certain major modes set this locally to the value obtained 317Certain major modes set this locally to the value obtained
318from `mode-require-final-newline'." 318from `mode-require-final-newline'."
319 :safe #'symbolp
319 :type '(choice (const :tag "When visiting" visit) 320 :type '(choice (const :tag "When visiting" visit)
320 (const :tag "When saving" t) 321 (const :tag "When saving" t)
321 (const :tag "When visiting or saving" visit-save) 322 (const :tag "When visiting or saving" visit-save)
@@ -3878,6 +3879,10 @@ Interactively, confirmation is required unless you supply a prefix argument."
3878 (or buffer-file-name (buffer-name)))))) 3879 (or buffer-file-name (buffer-name))))))
3879 (and confirm 3880 (and confirm
3880 (file-exists-p filename) 3881 (file-exists-p filename)
3882 ;; NS does its own confirm dialog.
3883 (not (and (eq (framep-on-display) 'ns)
3884 (listp last-nonmenu-event)
3885 use-dialog-box))
3881 (or (y-or-n-p (format "File `%s' exists; overwrite? " filename)) 3886 (or (y-or-n-p (format "File `%s' exists; overwrite? " filename))
3882 (error "Canceled"))) 3887 (error "Canceled")))
3883 (set-visited-file-name filename (not confirm)))) 3888 (set-visited-file-name filename (not confirm))))
@@ -4912,6 +4917,11 @@ change the additional actions you can take on files."
4912 (length autosaved-buffers) 4917 (length autosaved-buffers)
4913 (mapconcat 'identity autosaved-buffers ", ")))))))) 4918 (mapconcat 'identity autosaved-buffers ", "))))))))
4914 4919
4920(defun clear-visited-file-modtime ()
4921 "Clear out records of last mod time of visited file.
4922Next attempt to save will certainly not complain of a discrepancy."
4923 (set-visited-file-modtime 0))
4924
4915(defun not-modified (&optional arg) 4925(defun not-modified (&optional arg)
4916 "Mark current buffer as unmodified, not needing to be saved. 4926 "Mark current buffer as unmodified, not needing to be saved.
4917With prefix ARG, mark buffer as modified, so \\[save-buffer] will save. 4927With prefix ARG, mark buffer as modified, so \\[save-buffer] will save.
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 978512bd3a4..fbf28dbecbc 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -149,7 +149,7 @@ is loaded before custom.el, set this variable to t.")
149(defun filesets-filter-list (lst cond-fn) 149(defun filesets-filter-list (lst cond-fn)
150 "Remove all elements not conforming to COND-FN from list LST. 150 "Remove all elements not conforming to COND-FN from list LST.
151COND-FN takes one argument: the current element." 151COND-FN takes one argument: the current element."
152; (remove* 'dummy lst :test (lambda (dummy elt) 152; (cl-remove 'dummy lst :test (lambda (dummy elt)
153; (not (funcall cond-fn elt))))) 153; (not (funcall cond-fn elt)))))
154 (let ((rv nil)) 154 (let ((rv nil))
155 (dolist (elt lst rv) 155 (dolist (elt lst rv)
@@ -175,7 +175,7 @@ Like `some', return the first value of FSS-PRED that is non-nil."
175 (let ((fss-rv (funcall fss-pred fss-this))) 175 (let ((fss-rv (funcall fss-pred fss-this)))
176 (when fss-rv 176 (when fss-rv
177 (throw 'exit fss-rv)))))) 177 (throw 'exit fss-rv))))))
178;(fset 'filesets-some 'some) ;; or use the cl function 178;(fset 'filesets-some 'cl-some) ;; or use the cl function
179 179
180(defun filesets-member (fsm-item fsm-lst &rest fsm-keys) 180(defun filesets-member (fsm-item fsm-lst &rest fsm-keys)
181 "Find the first occurrence of FSM-ITEM in FSM-LST. 181 "Find the first occurrence of FSM-ITEM in FSM-LST.
@@ -186,7 +186,7 @@ key is supported."
186 (filesets-ormap (lambda (fsm-this) 186 (filesets-ormap (lambda (fsm-this)
187 (funcall fsm-test fsm-item fsm-this)) 187 (funcall fsm-test fsm-item fsm-this))
188 fsm-lst))) 188 fsm-lst)))
189;(fset 'filesets-member 'member*) ;; or use the cl function 189;(fset 'filesets-member 'cl-member) ;; or use the cl function
190 190
191(defun filesets-sublist (lst beg &optional end) 191(defun filesets-sublist (lst beg &optional end)
192 "Get the sublist of LST from BEG to END - 1." 192 "Get the sublist of LST from BEG to END - 1."
diff --git a/lisp/frame.el b/lisp/frame.el
index 0f8fc523a1b..3ac24a509a0 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1365,7 +1365,11 @@ frame's display)."
1365 1365
1366(defun display-pixel-height (&optional display) 1366(defun display-pixel-height (&optional display)
1367 "Return the height of DISPLAY's screen in pixels. 1367 "Return the height of DISPLAY's screen in pixels.
1368For character terminals, each character counts as a single pixel." 1368For character terminals, each character counts as a single pixel.
1369For graphical terminals, note that on \"multi-monitor\" setups this
1370refers to the pixel height for all physical monitors associated
1371with DISPLAY. To get information for each physical monitor, use
1372`display-monitor-attributes-list'."
1369 (let ((frame-type (framep-on-display display))) 1373 (let ((frame-type (framep-on-display display)))
1370 (cond 1374 (cond
1371 ((memq frame-type '(x w32 ns)) 1375 ((memq frame-type '(x w32 ns))
@@ -1377,7 +1381,11 @@ For character terminals, each character counts as a single pixel."
1377 1381
1378(defun display-pixel-width (&optional display) 1382(defun display-pixel-width (&optional display)
1379 "Return the width of DISPLAY's screen in pixels. 1383 "Return the width of DISPLAY's screen in pixels.
1380For character terminals, each character counts as a single pixel." 1384For character terminals, each character counts as a single pixel.
1385For graphical terminals, note that on \"multi-monitor\" setups this
1386refers to the pixel width for all physical monitors associated
1387with DISPLAY. To get information for each physical monitor, use
1388`display-monitor-attributes-list'."
1381 (let ((frame-type (framep-on-display display))) 1389 (let ((frame-type (framep-on-display display)))
1382 (cond 1390 (cond
1383 ((memq frame-type '(x w32 ns)) 1391 ((memq frame-type '(x w32 ns))
@@ -1408,7 +1416,11 @@ displays not explicitly specified."
1408(defun display-mm-height (&optional display) 1416(defun display-mm-height (&optional display)
1409 "Return the height of DISPLAY's screen in millimeters. 1417 "Return the height of DISPLAY's screen in millimeters.
1410System values can be overridden by `display-mm-dimensions-alist'. 1418System values can be overridden by `display-mm-dimensions-alist'.
1411If the information is unavailable, value is nil." 1419If the information is unavailable, value is nil.
1420For graphical terminals, note that on \"multi-monitor\" setups this
1421refers to the height in millimeters for all physical monitors
1422associated with DISPLAY. To get information for each physical
1423monitor, use `display-monitor-attributes-list'."
1412 (and (memq (framep-on-display display) '(x w32 ns)) 1424 (and (memq (framep-on-display display) '(x w32 ns))
1413 (or (cddr (assoc (or display (frame-parameter nil 'display)) 1425 (or (cddr (assoc (or display (frame-parameter nil 'display))
1414 display-mm-dimensions-alist)) 1426 display-mm-dimensions-alist))
@@ -1420,7 +1432,11 @@ If the information is unavailable, value is nil."
1420(defun display-mm-width (&optional display) 1432(defun display-mm-width (&optional display)
1421 "Return the width of DISPLAY's screen in millimeters. 1433 "Return the width of DISPLAY's screen in millimeters.
1422System values can be overridden by `display-mm-dimensions-alist'. 1434System values can be overridden by `display-mm-dimensions-alist'.
1423If the information is unavailable, value is nil." 1435If the information is unavailable, value is nil.
1436For graphical terminals, note that on \"multi-monitor\" setups this
1437refers to the width in millimeters for all physical monitors
1438associated with DISPLAY. To get information for each physical
1439monitor, use `display-monitor-attributes-list'."
1424 (and (memq (framep-on-display display) '(x w32 ns)) 1440 (and (memq (framep-on-display display) '(x w32 ns))
1425 (or (cadr (assoc (or display (frame-parameter nil 'display)) 1441 (or (cadr (assoc (or display (frame-parameter nil 'display))
1426 display-mm-dimensions-alist)) 1442 display-mm-dimensions-alist))
@@ -1495,6 +1511,8 @@ The value is one of the symbols `static-gray', `gray-scale',
1495 1511
1496(declare-function x-display-monitor-attributes-list "xfns.c" 1512(declare-function x-display-monitor-attributes-list "xfns.c"
1497 (&optional terminal)) 1513 (&optional terminal))
1514(declare-function w32-display-monitor-attributes-list "w32fns.c"
1515 (&optional display))
1498(declare-function ns-display-monitor-attributes-list "nsfns.m" 1516(declare-function ns-display-monitor-attributes-list "nsfns.m"
1499 (&optional terminal)) 1517 (&optional terminal))
1500 1518
@@ -1530,6 +1548,8 @@ monitors."
1530 (cond 1548 (cond
1531 ((eq frame-type 'x) 1549 ((eq frame-type 'x)
1532 (x-display-monitor-attributes-list display)) 1550 (x-display-monitor-attributes-list display))
1551 ((eq frame-type 'w32)
1552 (w32-display-monitor-attributes-list display))
1533 ((eq frame-type 'ns) 1553 ((eq frame-type 'ns)
1534 (ns-display-monitor-attributes-list display)) 1554 (ns-display-monitor-attributes-list display))
1535 (t 1555 (t
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index 49b45380575..eade6273e95 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -1,3 +1,58 @@
12013-07-10 David Engster <deng@randomsample.de>
2
3 * gnus-start.el (gnus-clean-old-newsrc): Always remove 'unexist' marks
4 if `gnus-newsrc-file-version' does not match `gnus-version'. This
5 fixes a bug in Emacs trunk where the 'unexist' marks were always
6 removed at startup because "Gnus v5.13" was considered smaller than "Ma
7 Gnus v0.03".
8
92013-07-10 Tassilo Horn <tsdh@gnu.org>
10
11 * gnus.el (gnus-summary-line-format): Reference
12 `gnus-user-date-format-alist' for the &user-date; format, not
13 `gnus-summary-user-date-format-alist'.
14
152013-07-08 Lars Magne Ingebrigtsen <larsi@gnus.org>
16
17 * nnml.el (nnml-request-compact-group): Don't bug out if we can't
18 delete files (bug#13481).
19
202013-07-08 Tassilo Horn <tsdh@gnu.org>
21
22 * gnus-registry.el (gnus-registry-remove-extra-data): New function.
23
242013-07-06 Lars Ingebrigtsen <larsi@gnus.org>
25
26 * gnus-art.el (gnus-block-private-groups): Allow `global' methods to
27 display images.
28
29 * gnus.el (gnus-valid-select-methods): Mark nnrss as global.
30
31 * message.el (message-cancel-news): According to
32 <mailman.216.1372942181.12400.help-gnu-emacs@gnu.org>, "cancel" is
33 preferred over "cmsg cancel" in the Subject.
34
35 * nnir.el (nnir-engines): Note that the group specs are regexps
36 (bug#13238).
37
38 * gnus-msg.el (gnus-copy-article-buffer): If the article buffer has
39 gotten read-only text properties, ensure that those aren't heeded when
40 copying stuff over (bug#13434).
41
42 * mm-view.el (mm-inline-text-html): Don't bug out on multipart messages
43 (bug#13762).
44
452013-07-05 David Kastrup <dak@gnu.org>
46
47 * auth-source.el (auth-source-netrc-parse-one): Allow empty strings in
48 authinfo file again (important for blank passwords). This had been
49 broken with 2013-06-15 change.
50
512013-07-03 Katsumi Yamaoka <yamaoka@jpl.org>
52
53 * gnus-sum.el (gnus-summary-from-or-to-or-newsgroups):
54 Revert 2013-01-14 change.
55
12013-07-02 David Engster <deng@randomsample.de> 562013-07-02 David Engster <deng@randomsample.de>
2 57
3 * gnus-sum.el (gnus-update-marks): Do not remove empty 'unexist' 58 * gnus-sum.el (gnus-update-marks): Do not remove empty 'unexist'
@@ -88,7 +143,7 @@
882013-07-02 Lars Magne Ingebrigtsen <larsi@gnus.org> 1432013-07-02 Lars Magne Ingebrigtsen <larsi@gnus.org>
89 144
90 * gnus-sum.el (gnus-summary-insert-old-articles): 145 * gnus-sum.el (gnus-summary-insert-old-articles):
91 Don't include unexistent messages. 146 Don't include unexisting messages.
92 147
932013-07-02 Lars Magne Ingebrigtsen <larsi@gnus.org> 1482013-07-02 Lars Magne Ingebrigtsen <larsi@gnus.org>
94 149
diff --git a/lisp/gnus/auth-source.el b/lisp/gnus/auth-source.el
index 8cef741cda2..54429b5cfda 100644
--- a/lisp/gnus/auth-source.el
+++ b/lisp/gnus/auth-source.el
@@ -1048,8 +1048,8 @@ Note that the MAX parameter is used so we can exit the parse early."
1048 "Read one thing from the current buffer." 1048 "Read one thing from the current buffer."
1049 (auth-source-netrc-parse-next-interesting) 1049 (auth-source-netrc-parse-next-interesting)
1050 1050
1051 (when (or (looking-at "'\\([^']+\\)'") 1051 (when (or (looking-at "'\\([^']*\\)'")
1052 (looking-at "\"\\([^\"]+\\)\"") 1052 (looking-at "\"\\([^\"]*\\)\"")
1053 (looking-at "\\([^ \t\n]+\\)")) 1053 (looking-at "\\([^ \t\n]+\\)"))
1054 (forward-char (length (match-string 0))) 1054 (forward-char (length (match-string 0)))
1055 (auth-source-netrc-parse-next-interesting) 1055 (auth-source-netrc-parse-next-interesting)
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index 5840aacd7a3..b41ff9c0550 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -6947,7 +6947,8 @@ If given a prefix, show the hidden text instead."
6947 (set-buffer buf)))))) 6947 (set-buffer buf))))))
6948 6948
6949(defun gnus-block-private-groups (group) 6949(defun gnus-block-private-groups (group)
6950 (if (gnus-news-group-p group) 6950 (if (or (gnus-news-group-p group)
6951 (gnus-member-of-valid 'global group))
6951 ;; Block nothing in news groups. 6952 ;; Block nothing in news groups.
6952 nil 6953 nil
6953 ;; Block everything anywhere else. 6954 ;; Block everything anywhere else.
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index fce9a3633c2..e3f18662af4 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -920,6 +920,7 @@ header line with the old Message-ID."
920 (with-current-buffer article-buffer 920 (with-current-buffer article-buffer
921 (let ((gnus-newsgroup-charset (or gnus-article-charset 921 (let ((gnus-newsgroup-charset (or gnus-article-charset
922 gnus-newsgroup-charset)) 922 gnus-newsgroup-charset))
923 (inhibit-read-only t)
923 (gnus-newsgroup-ignored-charsets 924 (gnus-newsgroup-ignored-charsets
924 (or gnus-article-ignored-charsets 925 (or gnus-article-ignored-charsets
925 gnus-newsgroup-ignored-charsets))) 926 gnus-newsgroup-ignored-charsets)))
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index 5a7dfd82d28..6f2fe78c3d8 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -1186,6 +1186,29 @@ data stored in the registry."
1186 (gnus-select-group-with-message-id group message-id) t) 1186 (gnus-select-group-with-message-id group message-id) t)
1187 (throw 'found t)))))))) 1187 (throw 'found t))))))))
1188 1188
1189(defun gnus-registry-remove-extra-data (extra)
1190 "Remove tracked EXTRA data from the gnus registry.
1191EXTRA is a list of symbols. Valid symbols are those contained in
1192the docs of `gnus-registry-track-extra'. This command is useful
1193when you stop tracking some extra data and now want to purge it
1194from your existing entries."
1195 (interactive (list (mapcar 'intern
1196 (completing-read-multiple
1197 "Extra data: "
1198 '("subject" "sender" "recipient")))))
1199 (when extra
1200 (let ((db gnus-registry-db))
1201 (registry-reindex db)
1202 (loop for k being the hash-keys of (oref db :data)
1203 using (hash-value v)
1204 do (let ((newv (delq nil (mapcar #'(lambda (entry)
1205 (unless (member (car entry) extra)
1206 entry))
1207 v))))
1208 (registry-delete db (list k) nil)
1209 (gnus-registry-insert db k newv)))
1210 (registry-reindex db))))
1211
1189;; TODO: a few things 1212;; TODO: a few things
1190 1213
1191(provide 'gnus-registry) 1214(provide 'gnus-registry)
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 084af884930..94803800e0b 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -2314,8 +2314,9 @@ If FORCE is non-nil, the .newsrc file is read."
2314 (gnus-info-set-marks 2314 (gnus-info-set-marks
2315 info (delete exist (gnus-info-marks info)))))) 2315 info (delete exist (gnus-info-marks info))))))
2316 (when (or force 2316 (when (or force
2317 (< (gnus-continuum-version gnus-newsrc-file-version) 2317 (not (string= gnus-newsrc-file-version gnus-version)))
2318 (gnus-continuum-version "Ma Gnus v0.03"))) 2318 (message (concat "Removing unexist marks because newsrc "
2319 "version does not match Gnus version."))
2319 ;; Remove old `exist' marks from old nnimap groups. 2320 ;; Remove old `exist' marks from old nnimap groups.
2320 (dolist (info (cdr gnus-newsrc-alist)) 2321 (dolist (info (cdr gnus-newsrc-alist))
2321 (let ((exist (assoc 'unexist (gnus-info-marks info)))) 2322 (let ((exist (assoc 'unexist (gnus-info-marks info))))
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index e136d4f8173..f3918b0a215 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -1525,7 +1525,7 @@ This list will always be a subset of gnus-newsgroup-undownloaded.")
1525 "Range of seen articles in the current newsgroup.") 1525 "Range of seen articles in the current newsgroup.")
1526 1526
1527(defvar gnus-newsgroup-unexist nil 1527(defvar gnus-newsgroup-unexist nil
1528 "Range of unexistent articles in the current newsgroup.") 1528 "Range of unexisting articles in the current newsgroup.")
1529 1529
1530(defvar gnus-newsgroup-articles nil 1530(defvar gnus-newsgroup-articles nil
1531 "List of articles in the current newsgroup.") 1531 "List of articles in the current newsgroup.")
@@ -3657,18 +3657,17 @@ buffer that was in action when the last article was fetched."
3657 (or (car (funcall gnus-extract-address-components from)) 3657 (or (car (funcall gnus-extract-address-components from))
3658 from)) 3658 from))
3659 3659
3660(defun gnus-summary-from-or-to-or-newsgroups (header from) 3660(defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from)
3661 (let ((mail-parse-charset gnus-newsgroup-charset) 3661 (let ((mail-parse-charset gnus-newsgroup-charset)
3662 (ignored-from-addresses (gnus-ignored-from-addresses)) 3662 (ignored-from-addresses (gnus-ignored-from-addresses))
3663 ;; Is it really necessary to do this next part for each summary line? 3663 ;; Is it really necessary to do this next part for each summary line?
3664 ;; Luckily, doesn't seem to slow things down much. 3664 ;; Luckily, doesn't seem to slow things down much.
3665 (mail-parse-ignored-charsets 3665 (mail-parse-ignored-charsets
3666 (with-current-buffer gnus-summary-buffer 3666 (with-current-buffer gnus-summary-buffer
3667 gnus-newsgroup-ignored-charsets)) 3667 gnus-newsgroup-ignored-charsets)))
3668 (address (cadr (gnus-extract-address-components from))))
3669 (or 3668 (or
3670 (and ignored-from-addresses 3669 (and ignored-from-addresses
3671 (string-match ignored-from-addresses address) 3670 (string-match ignored-from-addresses gnus-tmp-from)
3672 (let ((extra-headers (mail-header-extra header)) 3671 (let ((extra-headers (mail-header-extra header))
3673 to 3672 to
3674 newsgroups) 3673 newsgroups)
@@ -3683,11 +3682,13 @@ buffer that was in action when the last article was fetched."
3683 (cdr (assq 'Newsgroups extra-headers)) 3682 (cdr (assq 'Newsgroups extra-headers))
3684 (and 3683 (and
3685 (memq 'Newsgroups gnus-extra-headers) 3684 (memq 'Newsgroups gnus-extra-headers)
3686 (eq (car (gnus-find-method-for-group 3685 (eq (car (gnus-find-method-for-group
3687 gnus-newsgroup-name)) 'nntp) 3686 gnus-newsgroup-name)) 'nntp)
3688 (gnus-group-real-name gnus-newsgroup-name)))) 3687 (gnus-group-real-name gnus-newsgroup-name))))
3689 (concat gnus-summary-newsgroup-prefix newsgroups))))) 3688 (concat gnus-summary-newsgroup-prefix newsgroups)))))
3690 (gnus-string-mark-left-to-right (gnus-summary-extract-address-component from))))) 3689 (gnus-string-mark-left-to-right
3690 (inline
3691 (gnus-summary-extract-address-component gnus-tmp-from))))))
3691 3692
3692(defun gnus-summary-insert-line (gnus-tmp-header 3693(defun gnus-summary-insert-line (gnus-tmp-header
3693 gnus-tmp-level gnus-tmp-current 3694 gnus-tmp-level gnus-tmp-current
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 9a927a1cfab..8741a03b54d 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1628,7 +1628,7 @@ slower."
1628 ("nnfolder" mail respool address) 1628 ("nnfolder" mail respool address)
1629 ("nngateway" post-mail address prompt-address physical-address) 1629 ("nngateway" post-mail address prompt-address physical-address)
1630 ("nnweb" none) 1630 ("nnweb" none)
1631 ("nnrss" none) 1631 ("nnrss" none global)
1632 ("nnagent" post-mail) 1632 ("nnagent" post-mail)
1633 ("nnimap" post-mail address prompt-address physical-address respool 1633 ("nnimap" post-mail address prompt-address physical-address respool
1634 server-marks) 1634 server-marks)
@@ -3007,7 +3007,7 @@ with some simple extensions.
3007 summary just like information from any other summary 3007 summary just like information from any other summary
3008 specifier. 3008 specifier.
3009&user-date; Age sensitive date format. Various date format is 3009&user-date; Age sensitive date format. Various date format is
3010 defined in `gnus-summary-user-date-format-alist'. 3010 defined in `gnus-user-date-format-alist'.
3011 3011
3012 3012
3013The %U (status), %R (replied) and %z (zcore) specs have to be handled 3013The %U (status), %R (replied) and %z (zcore) specs have to be handled
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index c6f5d904677..b35eb9dca12 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -7145,7 +7145,7 @@ If ARG, allow editing of the cancellation message."
7145 (erase-buffer) 7145 (erase-buffer)
7146 (insert "Newsgroups: " newsgroups "\n" 7146 (insert "Newsgroups: " newsgroups "\n"
7147 "From: " from "\n" 7147 "From: " from "\n"
7148 "Subject: cmsg cancel " message-id "\n" 7148 "Subject: cancel " message-id "\n"
7149 "Control: cancel " message-id "\n" 7149 "Control: cancel " message-id "\n"
7150 (if distribution 7150 (if distribution
7151 (concat "Distribution: " distribution "\n") 7151 (concat "Distribution: " distribution "\n")
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index b1cba27c335..9512a411d81 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -419,16 +419,18 @@
419 (buffer-string))))) 419 (buffer-string)))))
420 420
421(defun mm-inline-text-html (handle) 421(defun mm-inline-text-html (handle)
422 (let* ((func mm-text-html-renderer) 422 (if (stringp (car handle))
423 (entry (assq func mm-text-html-renderer-alist)) 423 (mapcar 'mm-inline-text-html (cdr handle))
424 (inhibit-read-only t)) 424 (let* ((func mm-text-html-renderer)
425 (if entry 425 (entry (assq func mm-text-html-renderer-alist))
426 (setq func (cdr entry))) 426 (inhibit-read-only t))
427 (cond 427 (if entry
428 ((functionp func) 428 (setq func (cdr entry)))
429 (funcall func handle)) 429 (cond
430 (t 430 ((functionp func)
431 (apply (car func) handle (cdr func)))))) 431 (funcall func handle))
432 (t
433 (apply (car func) handle (cdr func)))))))
432 434
433(defun mm-inline-text-vcard (handle) 435(defun mm-inline-text-vcard (handle)
434 (let ((inhibit-read-only t)) 436 (let ((inhibit-read-only t))
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 22dee30e8fa..4dd123bf2c7 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -548,15 +548,15 @@ that it is for notmuch, not Namazu."
548 (gmane nnir-run-gmane 548 (gmane nnir-run-gmane
549 ((gmane-author . "Gmane Author: "))) 549 ((gmane-author . "Gmane Author: ")))
550 (swish++ nnir-run-swish++ 550 (swish++ nnir-run-swish++
551 ((swish++-group . "Swish++ Group spec: "))) 551 ((swish++-group . "Swish++ Group spec (regexp): ")))
552 (swish-e nnir-run-swish-e 552 (swish-e nnir-run-swish-e
553 ((swish-e-group . "Swish-e Group spec: "))) 553 ((swish-e-group . "Swish-e Group spec (regexp): ")))
554 (namazu nnir-run-namazu 554 (namazu nnir-run-namazu
555 ()) 555 ())
556 (notmuch nnir-run-notmuch 556 (notmuch nnir-run-notmuch
557 ()) 557 ())
558 (hyrex nnir-run-hyrex 558 (hyrex nnir-run-hyrex
559 ((hyrex-group . "Hyrex Group spec: "))) 559 ((hyrex-group . "Hyrex Group spec (regexp): ")))
560 (find-grep nnir-run-find-grep 560 (find-grep nnir-run-find-grep
561 ((grep-options . "Grep options: ")))) 561 ((grep-options . "Grep options: "))))
562 "Alist of supported search engines. 562 "Alist of supported search engines.
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 64e1ee11977..05d0c902340 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -1094,7 +1094,10 @@ Use the nov database for the current group if available."
1094 (concat group ":" new-number-string))) 1094 (concat group ":" new-number-string)))
1095 ;; Save to the new file: 1095 ;; Save to the new file:
1096 (nnmail-write-region (point-min) (point-max) newfile)) 1096 (nnmail-write-region (point-min) (point-max) newfile))
1097 (funcall nnmail-delete-file-function oldfile)) 1097 (condition-case ()
1098 (funcall nnmail-delete-file-function oldfile)
1099 (file-error
1100 (message "Couldn't delete %s" oldfile))))
1098 ;; 2/ Update all marks for this article: 1101 ;; 2/ Update all marks for this article:
1099 ;; #### NOTE: it is possible that the new article number 1102 ;; #### NOTE: it is possible that the new article number
1100 ;; #### already belongs to a range, whereas the corresponding 1103 ;; #### already belongs to a range, whereas the corresponding
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 8f7d584d00b..a4f18201a3f 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -462,6 +462,7 @@ directory, like `default-directory'."
462 (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer) 462 (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer)
463 (define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch) 463 (define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch)
464 (define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp) 464 (define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp)
465 (define-key map (kbd "M-s a C-o") 'ibuffer-do-occur)
465 (define-key map (kbd "DEL") 'ibuffer-unmark-backward) 466 (define-key map (kbd "DEL") 'ibuffer-unmark-backward)
466 (define-key map (kbd "M-DEL") 'ibuffer-unmark-all) 467 (define-key map (kbd "M-DEL") 'ibuffer-unmark-all)
467 (define-key map (kbd "* *") 'ibuffer-unmark-all) 468 (define-key map (kbd "* *") 'ibuffer-unmark-all)
diff --git a/lisp/ido.el b/lisp/ido.el
index 4a4ecdcdb1a..43a0cc0a665 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -782,21 +782,29 @@ remaining completion. If absent, elements 5 and 6 are used instead."
782 :group 'ido) 782 :group 'ido)
783 783
784(defcustom ido-use-virtual-buffers nil 784(defcustom ido-use-virtual-buffers nil
785 "If non-nil, refer to past buffers as well as existing ones. 785 "Specify how virtual buffers should be used.
786The value can be one of the following:
787
788 nil: No virtual buffers are used.
789 auto: Use virtual bufferw when the current input matches no
790 existing buffers.
791 t: Always use virtual buffers.
792
786Essentially it works as follows: Say you are visiting a file and 793Essentially it works as follows: Say you are visiting a file and
787the buffer gets cleaned up by midnight.el. Later, you want to 794the buffer gets cleaned up by midnight.el. Later, you want to
788switch to that buffer, but find it's no longer open. With 795switch to that buffer, but find it's no longer open. With virtual
789virtual buffers enabled, the buffer name stays in the buffer 796buffers enabled, the buffer name stays in the buffer list (using
790list (using the `ido-virtual' face, and always at the end), and if 797the `ido-virtual' face, and always at the end), and if you select
791you select it, it opens the file back up again. This allows you 798it, it opens the file back up again. This allows you to think
792to think less about whether recently opened files are still open 799less about whether recently opened files are still open or not.
793or not. Most of the time you can quit Emacs, restart, and then 800Most of the time you can quit Emacs, restart, and then switch to
794switch to a file buffer that was previously open as if it still 801a file buffer that was previously open as if it still were. This
795were. 802feature relies upon the `recentf' package, which will be enabled
796 This feature relies upon the `recentf' package, which will be 803if this variable is configured to a non-nil value."
797enabled if this variable is configured to a non-nil value." 804 :version "24.4"
798 :version "24.1" 805 :type '(choice (const :tag "Always" t)
799 :type 'boolean 806 (const :tag "Automatic" auto)
807 (const :tag "Never" nil))
800 :group 'ido) 808 :group 'ido)
801 809
802(defcustom ido-use-faces t 810(defcustom ido-use-faces t
@@ -1103,6 +1111,9 @@ Only used if `ido-use-virtual-buffers' is non-nil.")
1103;; Don't process ido-ignore- lists once. 1111;; Don't process ido-ignore- lists once.
1104(defvar ido-process-ignore-lists-inhibit) 1112(defvar ido-process-ignore-lists-inhibit)
1105 1113
1114;; Is ido using virtual buffers?
1115(defvar ido-enable-virtual-buffers)
1116
1106;; Buffer from which ido was entered. 1117;; Buffer from which ido was entered.
1107(defvar ido-entry-buffer) 1118(defvar ido-entry-buffer)
1108 1119
@@ -2202,7 +2213,8 @@ If cursor is not at the end of the user input, move to end of input."
2202 (ido-current-directory nil) 2213 (ido-current-directory nil)
2203 (ido-directory-nonreadable nil) 2214 (ido-directory-nonreadable nil)
2204 (ido-directory-too-big nil) 2215 (ido-directory-too-big nil)
2205 (ido-use-virtual-buffers ido-use-virtual-buffers) 2216 (ido-enable-virtual-buffers (and ido-use-virtual-buffers
2217 (not (eq ido-use-virtual-buffers 'auto))))
2206 (require-match (confirm-nonexistent-file-or-buffer)) 2218 (require-match (confirm-nonexistent-file-or-buffer))
2207 (buf (ido-read-internal 'buffer (or prompt "Buffer: ") 'ido-buffer-history default 2219 (buf (ido-read-internal 'buffer (or prompt "Buffer: ") 'ido-buffer-history default
2208 require-match initial)) 2220 require-match initial))
@@ -2243,7 +2255,8 @@ If cursor is not at the end of the user input, move to end of input."
2243 (ido-visit-buffer buf method t))) 2255 (ido-visit-buffer buf method t)))
2244 2256
2245 ;; check for a virtual buffer reference 2257 ;; check for a virtual buffer reference
2246 ((and ido-use-virtual-buffers ido-virtual-buffers 2258 ((and ido-enable-virtual-buffers
2259 ido-virtual-buffers
2247 (setq filename (assoc buf ido-virtual-buffers))) 2260 (setq filename (assoc buf ido-virtual-buffers)))
2248 (ido-visit-buffer (find-file-noselect (cdr filename)) method t)) 2261 (ido-visit-buffer (find-file-noselect (cdr filename)) method t))
2249 2262
@@ -2734,7 +2747,11 @@ C-x C-f ... C-d enter `dired' on current directory."
2734See `ido-use-virtual-buffers' for explanation of virtual buffer." 2747See `ido-use-virtual-buffers' for explanation of virtual buffer."
2735 (interactive) 2748 (interactive)
2736 (when (and ido-mode (eq ido-cur-item 'buffer)) 2749 (when (and ido-mode (eq ido-cur-item 'buffer))
2737 (setq ido-use-virtual-buffers (not ido-use-virtual-buffers)) 2750 (setq ido-enable-virtual-buffers
2751 (if ido-enable-virtual-buffers
2752 nil
2753 ;; Use `always' instead of t for `ido-exhibit'.
2754 'always))
2738 (setq ido-text-init ido-text) 2755 (setq ido-text-init ido-text)
2739 (setq ido-exit 'refresh) 2756 (setq ido-exit 'refresh)
2740 (exit-minibuffer))) 2757 (exit-minibuffer)))
@@ -3427,9 +3444,9 @@ it is put to the start of the list."
3427 (nconc ido-temp-list ido-current-buffers) 3444 (nconc ido-temp-list ido-current-buffers)
3428 (setq ido-temp-list ido-current-buffers)) 3445 (setq ido-temp-list ido-current-buffers))
3429 (if default 3446 (if default
3430 (setq ido-temp-list 3447 (setq ido-temp-list
3431 (cons default (delete default ido-temp-list)))) 3448 (cons default (delete default ido-temp-list))))
3432 (if ido-use-virtual-buffers 3449 (if (bound-and-true-p ido-enable-virtual-buffers)
3433 (ido-add-virtual-buffers-to-list)) 3450 (ido-add-virtual-buffers-to-list))
3434 (run-hooks 'ido-make-buffer-list-hook) 3451 (run-hooks 'ido-make-buffer-list-hook)
3435 ido-temp-list)) 3452 ido-temp-list))
@@ -3444,8 +3461,14 @@ This is to make them appear as if they were \"virtual buffers\"."
3444 (setq ido-virtual-buffers nil) 3461 (setq ido-virtual-buffers nil)
3445 (let (name) 3462 (let (name)
3446 (dolist (head recentf-list) 3463 (dolist (head recentf-list)
3447 (and (setq name (file-name-nondirectory head)) 3464 (setq name (file-name-nondirectory head))
3448 (null (get-file-buffer head)) 3465 ;; In case HEAD is a directory with trailing /. See bug#14552.
3466 (when (equal name "")
3467 (setq name (file-name-nondirectory (directory-file-name head))))
3468 (when (equal name "")
3469 (setq name head))
3470 (and (not (equal name ""))
3471 (null (get-file-buffer head))
3449 (not (assoc name ido-virtual-buffers)) 3472 (not (assoc name ido-virtual-buffers))
3450 (not (member name ido-temp-list)) 3473 (not (member name ido-temp-list))
3451 (not (ido-ignore-item-p name ido-ignore-buffers)) 3474 (not (ido-ignore-item-p name ido-ignore-buffers))
@@ -3986,6 +4009,7 @@ If cursor is not at the end of the user input, delete to end of input."
3986;;; DELETE CURRENT FILE 4009;;; DELETE CURRENT FILE
3987(defun ido-delete-file-at-head () 4010(defun ido-delete-file-at-head ()
3988 "Delete the file at the head of `ido-matches'. 4011 "Delete the file at the head of `ido-matches'.
4012Trash the file if `delete-by-moving-to-trash' is non-nil.
3989If cursor is not at the end of the user input, delete to end of input." 4013If cursor is not at the end of the user input, delete to end of input."
3990 (interactive) 4014 (interactive)
3991 (if (not (eobp)) 4015 (if (not (eobp))
@@ -3998,8 +4022,9 @@ If cursor is not at the end of the user input, delete to end of input."
3998 (file-exists-p file) 4022 (file-exists-p file)
3999 (not (file-directory-p file)) 4023 (not (file-directory-p file))
4000 (file-writable-p ido-current-directory) 4024 (file-writable-p ido-current-directory)
4001 (yes-or-no-p (concat "Delete " file "? "))) 4025 (or delete-by-moving-to-trash
4002 (delete-file file) 4026 (yes-or-no-p (concat "Delete " file "? "))))
4027 (delete-file file 'trash)
4003 ;; Check if file still exists. 4028 ;; Check if file still exists.
4004 (if (file-exists-p file) 4029 (if (file-exists-p file)
4005 ;; file could not be deleted 4030 ;; file could not be deleted
@@ -4457,11 +4482,6 @@ For details of keybindings, see `ido-find-file'."
4457 (setq ido-exit 'refresh) 4482 (setq ido-exit 'refresh)
4458 (exit-minibuffer)) 4483 (exit-minibuffer))
4459 4484
4460 ;; Update the list of matches
4461 (setq ido-text contents)
4462 (ido-set-matches)
4463 (ido-trace "new " ido-matches)
4464
4465 (when (and ido-enter-matching-directory 4485 (when (and ido-enter-matching-directory
4466 ido-matches 4486 ido-matches
4467 (or (eq ido-enter-matching-directory 'first) 4487 (or (eq ido-enter-matching-directory 'first)
@@ -4475,6 +4495,32 @@ For details of keybindings, see `ido-find-file'."
4475 (setq ido-exit 'refresh) 4495 (setq ido-exit 'refresh)
4476 (exit-minibuffer)) 4496 (exit-minibuffer))
4477 4497
4498 ;; Update the list of matches
4499 (setq ido-text contents)
4500 (ido-set-matches)
4501 (ido-trace "new " ido-matches)
4502
4503 (when (and (boundp 'ido-enable-virtual-buffers)
4504 (not (eq ido-enable-virtual-buffers 'always))
4505 (eq ido-cur-item 'buffer)
4506 (eq ido-use-virtual-buffers 'auto))
4507
4508 (when (and (not ido-enable-virtual-buffers)
4509 (not ido-matches))
4510 (setq ido-text-init ido-text)
4511 (setq ido-enable-virtual-buffers t)
4512 (setq ido-exit 'refresh)
4513 (exit-minibuffer))
4514
4515 ;; If input matches real buffers turn off virtual buffers.
4516 (when (and ido-enable-virtual-buffers
4517 ido-matches
4518 (ido-set-matches-1 (ido-make-buffer-list-1)))
4519 (setq ido-enable-virtual-buffers nil)
4520 (setq ido-text-init ido-text)
4521 (setq ido-exit 'refresh)
4522 (exit-minibuffer)))
4523
4478 (when (and (not ido-matches) 4524 (when (and (not ido-matches)
4479 (not ido-directory-nonreadable) 4525 (not ido-directory-nonreadable)
4480 (not ido-directory-too-big) 4526 (not ido-directory-too-big)
@@ -4681,9 +4727,12 @@ Modified from `icomplete-completions'."
4681 4727
4682;;; Helper functions for other programs 4728;;; Helper functions for other programs
4683 4729
4684(put 'dired-do-rename 'ido 'ignore)
4685(put 'ibuffer-find-file 'ido 'find-file) 4730(put 'ibuffer-find-file 'ido 'find-file)
4731(put 'dired 'ido 'dir)
4686(put 'dired-other-window 'ido 'dir) 4732(put 'dired-other-window 'ido 'dir)
4733;; See http://debbugs.gnu.org/11954 for reasons.
4734(put 'dired-do-copy 'ido 'ignore)
4735(put 'dired-do-rename 'ido 'ignore)
4687 4736
4688;;;###autoload 4737;;;###autoload
4689(defun ido-read-buffer (prompt &optional default require-match) 4738(defun ido-read-buffer (prompt &optional default require-match)
@@ -4711,18 +4760,20 @@ See `read-file-name' for additional parameters."
4711 (let (filename) 4760 (let (filename)
4712 (cond 4761 (cond
4713 ((or (eq predicate 'file-directory-p) 4762 ((or (eq predicate 'file-directory-p)
4714 (eq (get this-command 'ido) 'dir) 4763 (eq (and (symbolp this-command)
4764 (get this-command 'ido)) 'dir)
4715 (memq this-command ido-read-file-name-as-directory-commands)) 4765 (memq this-command ido-read-file-name-as-directory-commands))
4716 (setq filename 4766 (setq filename
4717 (ido-read-directory-name prompt dir default-filename mustmatch initial)) 4767 (ido-read-directory-name prompt dir default-filename mustmatch initial)))
4718 (if (eq ido-exit 'fallback) 4768 ((and (not (eq (and (symbolp this-command)
4719 (setq filename 'fallback))) 4769 (get this-command 'ido)) 'ignore))
4720 ((and (not (eq (get this-command 'ido) 'ignore))
4721 (not (memq this-command ido-read-file-name-non-ido)) 4770 (not (memq this-command ido-read-file-name-non-ido))
4722 (or (null predicate) (eq predicate 'file-exists-p))) 4771 (or (null predicate) (eq predicate 'file-exists-p)))
4723 (let* (ido-saved-vc-hb 4772 (let* (ido-saved-vc-hb
4724 (ido-context-switch-command 4773 (ido-context-switch-command
4725 (if (eq (get this-command 'ido) 'find-file) nil 'ignore)) 4774 (if (eq (and (symbolp this-command)
4775 (get this-command 'ido)) 'find-file)
4776 nil 'ignore))
4726 (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends)) 4777 (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends))
4727 (minibuffer-completing-file-name t) 4778 (minibuffer-completing-file-name t)
4728 (ido-current-directory (ido-expand-directory dir)) 4779 (ido-current-directory (ido-expand-directory dir))
@@ -4736,7 +4787,15 @@ See `read-file-name' for additional parameters."
4736 (ido-find-literal nil)) 4787 (ido-find-literal nil))
4737 (setq ido-exit nil) 4788 (setq ido-exit nil)
4738 (setq filename 4789 (setq filename
4739 (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial)) 4790 (ido-read-internal 'file prompt 'ido-file-history
4791 (cond ; Bug#11861.
4792 ((stringp default-filename) default-filename)
4793 ((consp default-filename) (car default-filename))
4794 ((and (not default-filename) initial)
4795 (expand-file-name initial dir))
4796 (buffer-file-name buffer-file-name))
4797 mustmatch initial))
4798 (setq dir ido-current-directory) ; See bug#1516.
4740 (cond 4799 (cond
4741 ((eq ido-exit 'fallback) 4800 ((eq ido-exit 'fallback)
4742 (setq filename 'fallback)) 4801 (setq filename 'fallback))
@@ -4768,12 +4827,21 @@ See `read-directory-name' for additional parameters."
4768 (ido-directory-too-big-p ido-current-directory))) 4827 (ido-directory-too-big-p ido-current-directory)))
4769 (ido-work-directory-index -1) 4828 (ido-work-directory-index -1)
4770 (ido-work-file-index -1)) 4829 (ido-work-file-index -1))
4771 (setq filename 4830 (setq filename (ido-read-internal
4772 (ido-read-internal 'dir prompt 'ido-file-history default-dirname mustmatch initial)) 4831 'dir prompt 'ido-file-history
4773 (if filename 4832 (or default-dirname ; Bug#11861.
4774 (if (and (stringp filename) (string-equal filename ".")) 4833 (if initial
4775 ido-current-directory 4834 (expand-file-name initial ido-current-directory)
4776 (concat ido-current-directory filename))))) 4835 ido-current-directory))
4836 mustmatch initial))
4837 (cond
4838 ((eq ido-exit 'fallback)
4839 (let ((read-file-name-function nil))
4840 (run-hook-with-args 'ido-before-fallback-functions 'read-directory-name)
4841 (read-directory-name prompt ido-current-directory
4842 default-dirname mustmatch initial)))
4843 ((equal filename ".") ido-current-directory)
4844 (t (concat ido-current-directory filename)))))
4777 4845
4778;;;###autoload 4846;;;###autoload
4779(defun ido-completing-read (prompt choices &optional _predicate require-match 4847(defun ido-completing-read (prompt choices &optional _predicate require-match
diff --git a/lisp/info-xref.el b/lisp/info-xref.el
index c38e23bab8a..21fb592ff19 100644
--- a/lisp/info-xref.el
+++ b/lisp/info-xref.el
@@ -45,7 +45,25 @@
45;;; Code: 45;;; Code:
46 46
47(require 'info) 47(require 'info)
48(eval-when-compile (require 'cl-lib)) ;; for `incf' 48(eval-when-compile (require 'cl-lib)) ; for `cl-incf'
49
50(defgroup info-xref nil
51 "Check external cross-references in Info documents."
52 :group 'docs) ; FIXME right parent?
53
54;; Should this even be an option?
55(defcustom info-xref-case-fold nil
56 "Non-nil means node checks should ignore case.
57When following cross-references, the Emacs Info reader first tries a
58case-sensitive match, then if that fails a case-insensitive one.
59The standalone Info reader does not do this, nor does this work
60for links in the html versions of Texinfo manuals. Therefore
61to ensure your cross-references work on the widest range of platforms,
62you should set this variable to nil."
63 :group 'info-xref
64 :type 'boolean
65 :version "24.4")
66
49 67
50;;----------------------------------------------------------------------------- 68;;-----------------------------------------------------------------------------
51;; vaguely generic 69;; vaguely generic
@@ -204,7 +222,8 @@ buffer's line and column of point."
204 (Info-goto-node node 222 (Info-goto-node node
205 (when (get-buffer "*info*") 223 (when (get-buffer "*info*")
206 (set-buffer "*info*") 224 (set-buffer "*info*")
207 "xref - temporary")) 225 "xref - temporary")
226 (not info-xref-case-fold))
208 t) 227 t)
209 (error nil)) 228 (error nil))
210 (unless (equal (current-buffer) oldbuf) 229 (unless (equal (current-buffer) oldbuf)
diff --git a/lisp/info.el b/lisp/info.el
index f9851a0c1e8..0e0a11753ba 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -920,10 +920,14 @@ just return nil (no error)."
920 (error "Info file %s does not exist" filename))) 920 (error "Info file %s does not exist" filename)))
921 filename)))) 921 filename))))
922 922
923(defun Info-find-node (filename nodename &optional no-going-back) 923(defun Info-find-node (filename nodename &optional no-going-back strict-case)
924 "Go to an Info node specified as separate FILENAME and NODENAME. 924 "Go to an Info node specified as separate FILENAME and NODENAME.
925NO-GOING-BACK is non-nil if recovering from an error in this function; 925NO-GOING-BACK is non-nil if recovering from an error in this function;
926it says do not attempt further (recursive) error recovery." 926it says do not attempt further (recursive) error recovery.
927
928This function first looks for a case-sensitive match for NODENAME;
929if none is found it then tries a case-insensitive match (unless
930STRICT-CASE is non-nil)."
927 (info-initialize) 931 (info-initialize)
928 (setq filename (Info-find-file filename)) 932 (setq filename (Info-find-file filename))
929 ;; Go into Info buffer. 933 ;; Go into Info buffer.
@@ -933,7 +937,7 @@ it says do not attempt further (recursive) error recovery."
933 Info-current-file 937 Info-current-file
934 (push (list Info-current-file Info-current-node (point)) 938 (push (list Info-current-file Info-current-node (point))
935 Info-history)) 939 Info-history))
936 (Info-find-node-2 filename nodename no-going-back)) 940 (Info-find-node-2 filename nodename no-going-back strict-case))
937 941
938;;;###autoload 942;;;###autoload
939(defun Info-on-current-buffer (&optional nodename) 943(defun Info-on-current-buffer (&optional nodename)
@@ -1010,7 +1014,7 @@ which the match was found."
1010 (+ (point-min) (read (current-buffer))) 1014 (+ (point-min) (read (current-buffer)))
1011 major-mode))))) 1015 major-mode)))))
1012 1016
1013(defun Info-find-in-tag-table (marker regexp) 1017(defun Info-find-in-tag-table (marker regexp &optional strict-case)
1014 "Find a node in a tag table. 1018 "Find a node in a tag table.
1015MARKER specifies the buffer and position to start searching at. 1019MARKER specifies the buffer and position to start searching at.
1016REGEXP is a regular expression matching nodes or references. Its first 1020REGEXP is a regular expression matching nodes or references. Its first
@@ -1020,10 +1024,11 @@ FOUND-ANCHOR is non-nil if a `Ref:' was matched, POS is the position
1020where the match was found, and MODE is `major-mode' of the buffer in 1024where the match was found, and MODE is `major-mode' of the buffer in
1021which the match was found. 1025which the match was found.
1022This function tries to find a case-sensitive match first, then a 1026This function tries to find a case-sensitive match first, then a
1023case-insensitive match is tried." 1027case-insensitive match is tried (unless optional argument STRICT-CASE
1028is non-nil)."
1024 (let ((result (Info-find-in-tag-table-1 marker regexp nil))) 1029 (let ((result (Info-find-in-tag-table-1 marker regexp nil)))
1025 (when (null (car result)) 1030 (or strict-case (car result)
1026 (setq result (Info-find-in-tag-table-1 marker regexp t))) 1031 (setq result (Info-find-in-tag-table-1 marker regexp t)))
1027 result)) 1032 result))
1028 1033
1029(defun Info-find-node-in-buffer-1 (regexp case-fold) 1034(defun Info-find-node-in-buffer-1 (regexp case-fold)
@@ -1046,17 +1051,19 @@ Value is the position at which a match was found, or nil if not found."
1046 (setq found (line-beginning-position))))))) 1051 (setq found (line-beginning-position)))))))
1047 found)) 1052 found))
1048 1053
1049(defun Info-find-node-in-buffer (regexp) 1054(defun Info-find-node-in-buffer (regexp &optional strict-case)
1050 "Find a node or anchor in the current buffer. 1055 "Find a node or anchor in the current buffer.
1051REGEXP is a regular expression matching nodes or references. Its first 1056REGEXP is a regular expression matching nodes or references. Its first
1052group should match `Node:' or `Ref:'. 1057group should match `Node:' or `Ref:'.
1053Value is the position at which a match was found, or nil if not found. 1058Value is the position at which a match was found, or nil if not found.
1054This function looks for a case-sensitive match first. If none is found, 1059This function looks for a case-sensitive match first. If none is found,
1055a case-insensitive match is tried." 1060a case-insensitive match is tried (unless optional argument STRICT-CASE
1061is non-nil)."
1056 (or (Info-find-node-in-buffer-1 regexp nil) 1062 (or (Info-find-node-in-buffer-1 regexp nil)
1057 (Info-find-node-in-buffer-1 regexp t))) 1063 (and (not strict-case)
1064 (Info-find-node-in-buffer-1 regexp t))))
1058 1065
1059(defun Info-find-node-2 (filename nodename &optional no-going-back) 1066(defun Info-find-node-2 (filename nodename &optional no-going-back strict-case)
1060 (buffer-disable-undo (current-buffer)) 1067 (buffer-disable-undo (current-buffer))
1061 (or (eq major-mode 'Info-mode) 1068 (or (eq major-mode 'Info-mode)
1062 (Info-mode)) 1069 (Info-mode))
@@ -1167,7 +1174,7 @@ a case-insensitive match is tried."
1167 ;; First, search a tag table, if any 1174 ;; First, search a tag table, if any
1168 (when (marker-position Info-tag-table-marker) 1175 (when (marker-position Info-tag-table-marker)
1169 (let* ((m Info-tag-table-marker) 1176 (let* ((m Info-tag-table-marker)
1170 (found (Info-find-in-tag-table m regexp))) 1177 (found (Info-find-in-tag-table m regexp strict-case)))
1171 1178
1172 (when found 1179 (when found
1173 ;; FOUND is (ANCHOR POS MODE). 1180 ;; FOUND is (ANCHOR POS MODE).
@@ -1194,7 +1201,7 @@ a case-insensitive match is tried."
1194 ;; buffer) to find the actual node. First, check 1201 ;; buffer) to find the actual node. First, check
1195 ;; whether the node is right where we are, in case the 1202 ;; whether the node is right where we are, in case the
1196 ;; buffer begins with a node. 1203 ;; buffer begins with a node.
1197 (let ((pos (Info-find-node-in-buffer regexp))) 1204 (let ((pos (Info-find-node-in-buffer regexp strict-case)))
1198 (when pos 1205 (when pos
1199 (goto-char pos) 1206 (goto-char pos)
1200 (throw 'foo t))) 1207 (throw 'foo t)))
@@ -1701,7 +1708,7 @@ escaped (\\\",\\\\)."
1701;; Don't autoload this function: the correct entry point for other packages 1708;; Don't autoload this function: the correct entry point for other packages
1702;; to use is `info'. --Stef 1709;; to use is `info'. --Stef
1703;; ;;;###autoload 1710;; ;;;###autoload
1704(defun Info-goto-node (nodename &optional fork) 1711(defun Info-goto-node (nodename &optional fork strict-case)
1705 "Go to Info node named NODENAME. Give just NODENAME or (FILENAME)NODENAME. 1712 "Go to Info node named NODENAME. Give just NODENAME or (FILENAME)NODENAME.
1706If NODENAME is of the form (FILENAME)NODENAME, the node is in the Info file 1713If NODENAME is of the form (FILENAME)NODENAME, the node is in the Info file
1707FILENAME; otherwise, NODENAME should be in the current Info file (or one of 1714FILENAME; otherwise, NODENAME should be in the current Info file (or one of
@@ -1711,7 +1718,11 @@ in the Info file FILENAME after the closing parenthesis in (FILENAME).
1711Empty NODENAME in (FILENAME) defaults to the Top node. 1718Empty NODENAME in (FILENAME) defaults to the Top node.
1712If FORK is non-nil (interactively with a prefix arg), show the node in 1719If FORK is non-nil (interactively with a prefix arg), show the node in
1713a new Info buffer. 1720a new Info buffer.
1714If FORK is a string, it is the name to use for the new buffer." 1721If FORK is a string, it is the name to use for the new buffer.
1722
1723This function first looks for a case-sensitive match for the node part
1724of NODENAME; if none is found it then tries a case-insensitive match
1725\(unless STRICT-CASE is non-nil)."
1715 (interactive (list (Info-read-node-name "Go to node: ") current-prefix-arg)) 1726 (interactive (list (Info-read-node-name "Go to node: ") current-prefix-arg))
1716 (info-initialize) 1727 (info-initialize)
1717 (if fork 1728 (if fork
@@ -1730,7 +1741,7 @@ If FORK is a string, it is the name to use for the new buffer."
1730 (if trim (setq nodename (substring nodename 0 trim)))) 1741 (if trim (setq nodename (substring nodename 0 trim))))
1731 (if transient-mark-mode (deactivate-mark)) 1742 (if transient-mark-mode (deactivate-mark))
1732 (Info-find-node (if (equal filename "") nil filename) 1743 (Info-find-node (if (equal filename "") nil filename)
1733 (if (equal nodename "") "Top" nodename)))) 1744 (if (equal nodename "") "Top" nodename) nil strict-case)))
1734 1745
1735(defvar Info-read-node-completion-table) 1746(defvar Info-read-node-completion-table)
1736 1747
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index 3577e0e9152..28542835a5f 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -672,7 +672,7 @@ is unsuitable for the top-level media type \"text\".
672 672
673VALUE must be a list of symbols that control the ISO-2022 converter. 673VALUE must be a list of symbols that control the ISO-2022 converter.
674Each must be a member of the list `coding-system-iso-2022-flags' 674Each must be a member of the list `coding-system-iso-2022-flags'
675\(which see). This attribute has a meaning only when `:coding-type' 675\(which see). This attribute is meaningful only when `:coding-type'
676is `iso-2022'. 676is `iso-2022'.
677 677
678`:designation' 678`:designation'
@@ -692,7 +692,7 @@ to GN. If the list contains 96, any charsets whose whose ranges are
69296 long can be designated to GN. If the first element is a charset, 69296 long can be designated to GN. If the first element is a charset,
693that charset is initially designated to GN. 693that charset is initially designated to GN.
694 694
695This attribute has a meaning only when `:coding-type' is `iso-2022'. 695This attribute is meaningful only when `:coding-type' is `iso-2022'.
696 696
697`:bom' 697`:bom'
698 698
@@ -712,7 +712,7 @@ are 0xFF 0xFE, use the cdr part coding system of the value.
712Otherwise, treat them as bytes for a normal character. On encoding, 712Otherwise, treat them as bytes for a normal character. On encoding,
713produce BOM bytes according to the value of `:endian'. 713produce BOM bytes according to the value of `:endian'.
714 714
715This attribute has a meaning only when `:coding-type' is `utf-16' or 715This attribute is meaningful only when `:coding-type' is `utf-16' or
716`utf-8'. 716`utf-8'.
717 717
718`:endian' 718`:endian'
@@ -720,37 +720,37 @@ This attribute has a meaning only when `:coding-type' is `utf-16' or
720VALUE must be `big' or `little' specifying big-endian and 720VALUE must be `big' or `little' specifying big-endian and
721little-endian respectively. The default value is `big'. 721little-endian respectively. The default value is `big'.
722 722
723This attribute has a meaning only when `:coding-type' is `utf-16'. 723This attribute is meaningful only when `:coding-type' is `utf-16'.
724 724
725`:ccl-decoder' 725`:ccl-decoder'
726 726
727VALUE is a symbol representing the registered CCL program used for 727VALUE is a symbol representing the registered CCL program used for
728decoding. This attribute has a meaning only when `:coding-type' is 728decoding. This attribute is meaningful only when `:coding-type' is
729`ccl'. 729`ccl'.
730 730
731`:ccl-encoder' 731`:ccl-encoder'
732 732
733VALUE is a symbol representing the registered CCL program used for 733VALUE is a symbol representing the registered CCL program used for
734encoding. This attribute has a meaning only when `:coding-type' is 734encoding. This attribute is meaningful only when `:coding-type' is
735`ccl'. 735`ccl'.
736 736
737:inhibit-null-byte-detection 737`:inhibit-null-byte-detection'
738 738
739VALUE non-nil means Emacs ignore null bytes on code detection. 739VALUE non-nil means Emacs ignore null bytes on code detection.
740See the variable `inhibit-null-byte-detection'. This attribute 740See the variable `inhibit-null-byte-detection'. This attribute
741has a meaning only when `:coding-type' is `undecided'. 741is meaningful only when `:coding-type' is `undecided'.
742 742
743:inhibit-iso-escape-detection 743`:inhibit-iso-escape-detection'
744 744
745VALUE non-nil means Emacs ignores ISO-2022 escape sequences on 745VALUE non-nil means Emacs ignores ISO-2022 escape sequences on
746code detection. See the variable `inhibit-iso-escape-detection'. 746code detection. See the variable `inhibit-iso-escape-detection'.
747This attribute has a meaning only when `:coding-type' is 747This attribute is meaningful only when `:coding-type' is
748`undecided'. 748`undecided'.
749 749
750:prefer-utf-8 750`:prefer-utf-8'
751 751
752VALUE non-nil means Emacs prefers UTF-8 on code detection for 752VALUE non-nil means Emacs prefers UTF-8 on code detection for
753non-ASCII files. This attribute has a meaning only when 753non-ASCII files. This attribute is meaningful only when
754`:coding-type' is `undecided'." 754`:coding-type' is `undecided'."
755 (let* ((common-attrs (mapcar 'list 755 (let* ((common-attrs (mapcar 'list
756 '(:mnemonic 756 '(:mnemonic
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index bdc30bc9292..4506ede8722 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -145,6 +145,7 @@ cid: URL as the argument.")
145 (define-key map [follow-link] 'mouse-face) 145 (define-key map [follow-link] 'mouse-face)
146 (define-key map "I" 'shr-insert-image) 146 (define-key map "I" 'shr-insert-image)
147 (define-key map "w" 'shr-copy-url) 147 (define-key map "w" 'shr-copy-url)
148 (define-key map "u" 'shr-copy-url)
148 (define-key map "v" 'shr-browse-url) 149 (define-key map "v" 'shr-browse-url)
149 (define-key map "o" 'shr-save-contents) 150 (define-key map "o" 'shr-save-contents)
150 (define-key map "\r" 'shr-browse-url) 151 (define-key map "\r" 'shr-browse-url)
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index 4c6141fe42b..f7f570590c8 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -38,9 +38,11 @@
38;; 38;;
39;; - localname is a string. This are temporary properties, which are 39;; - localname is a string. This are temporary properties, which are
40;; related to the file localname is referring to. Examples: 40;; related to the file localname is referring to. Examples:
41;; "file-exists-p" is t or nile, depending on the file existence, or 41;; "file-exists-p" is t or nil, depending on the file existence, or
42;; "file-attributes" caches the result of the function 42;; "file-attributes" caches the result of the function
43;; `file-attributes'. 43;; `file-attributes'. These entries have a timestamp, and they
44;; expire after `remote-file-name-inhibit-cache' seconds if this
45;; variable is set.
44;; 46;;
45;; - The key is a process. This are temporary properties related to 47;; - The key is a process. This are temporary properties related to
46;; an open connection. Examples: "scripts" keeps shell script 48;; an open connection. Examples: "scripts" keeps shell script
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 6ba055b8bb8..c2fdc0491b6 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1539,7 +1539,8 @@ connection if a previous connection has died for some reason."
1539 ;; indicated by the "mounted" signal, i.e. the "fuse-mountpoint" 1539 ;; indicated by the "mounted" signal, i.e. the "fuse-mountpoint"
1540 ;; file property. 1540 ;; file property.
1541 (with-timeout 1541 (with-timeout
1542 (60 1542 ((or (tramp-get-method-parameter method 'tramp-connection-timeout)
1543 tramp-connection-timeout)
1543 (if (zerop (length (tramp-file-name-user vec))) 1544 (if (zerop (length (tramp-file-name-user vec)))
1544 (tramp-error 1545 (tramp-error
1545 vec 'file-error 1546 vec 'file-error
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 387084a807b..281f497692d 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -222,21 +222,24 @@ detected as prompt when being sent on echoing hosts, therefore.")
222 (tramp-login-program "su") 222 (tramp-login-program "su")
223 (tramp-login-args (("-") ("%u"))) 223 (tramp-login-args (("-") ("%u")))
224 (tramp-remote-shell "/bin/sh") 224 (tramp-remote-shell "/bin/sh")
225 (tramp-remote-shell-args ("-c")))) 225 (tramp-remote-shell-args ("-c"))
226 (tramp-connection-timeout 10)))
226;;;###tramp-autoload 227;;;###tramp-autoload
227(add-to-list 'tramp-methods 228(add-to-list 'tramp-methods
228 '("sudo" 229 '("sudo"
229 (tramp-login-program "sudo") 230 (tramp-login-program "sudo")
230 (tramp-login-args (("-u" "%u") ("-s") ("-H") ("-p" "Password:"))) 231 (tramp-login-args (("-u" "%u") ("-s") ("-H") ("-p" "Password:")))
231 (tramp-remote-shell "/bin/sh") 232 (tramp-remote-shell "/bin/sh")
232 (tramp-remote-shell-args ("-c")))) 233 (tramp-remote-shell-args ("-c"))
234 (tramp-connection-timeout 10)))
233;;;###tramp-autoload 235;;;###tramp-autoload
234(add-to-list 'tramp-methods 236(add-to-list 'tramp-methods
235 '("ksu" 237 '("ksu"
236 (tramp-login-program "ksu") 238 (tramp-login-program "ksu")
237 (tramp-login-args (("%u") ("-q"))) 239 (tramp-login-args (("%u") ("-q")))
238 (tramp-remote-shell "/bin/sh") 240 (tramp-remote-shell "/bin/sh")
239 (tramp-remote-shell-args ("-c")))) 241 (tramp-remote-shell-args ("-c"))
242 (tramp-connection-timeout 10)))
240;;;###tramp-autoload 243;;;###tramp-autoload
241(add-to-list 'tramp-methods 244(add-to-list 'tramp-methods
242 '("krlogin" 245 '("krlogin"
@@ -862,7 +865,9 @@ of command line.")
862 (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context) 865 (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
863 (file-acl . tramp-sh-handle-file-acl) 866 (file-acl . tramp-sh-handle-file-acl)
864 (set-file-acl . tramp-sh-handle-set-file-acl) 867 (set-file-acl . tramp-sh-handle-set-file-acl)
865 (vc-registered . tramp-sh-handle-vc-registered)) 868 (vc-registered . tramp-sh-handle-vc-registered)
869 (file-notify-add-watch . tramp-sh-handle-file-notify-add-watch)
870 (file-notify-rm-watch . tramp-sh-handle-file-notify-rm-watch))
866 "Alist of handler functions. 871 "Alist of handler functions.
867Operations not mentioned here will be handled by the normal Emacs functions.") 872Operations not mentioned here will be handled by the normal Emacs functions.")
868 873
@@ -2669,7 +2674,7 @@ the result will be a local, non-Tramp, filename."
2669 (unless (memq (process-status proc) '(run open)) 2674 (unless (memq (process-status proc) '(run open))
2670 (let ((vec (tramp-get-connection-property proc "vector" nil))) 2675 (let ((vec (tramp-get-connection-property proc "vector" nil)))
2671 (when vec 2676 (when vec
2672 (tramp-message vec 5 "Sentinel called: `%s' `%s'" proc event) 2677 (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event)
2673 (tramp-flush-connection-property proc) 2678 (tramp-flush-connection-property proc)
2674 (tramp-flush-directory-property vec ""))))) 2679 (tramp-flush-directory-property vec "")))))
2675 2680
@@ -3376,6 +3381,122 @@ Fall back to normal file name handler if no Tramp handler exists."
3376 ;; Default file name handlers, we don't care. 3381 ;; Default file name handlers, we don't care.
3377 (t (tramp-run-real-handler operation args))))))) 3382 (t (tramp-run-real-handler operation args)))))))
3378 3383
3384(defun tramp-sh-handle-file-notify-add-watch (file-name flags callback)
3385 "Like `file-notify-add-watch' for Tramp files."
3386 (setq file-name (expand-file-name file-name))
3387 (with-parsed-tramp-file-name file-name nil
3388 (let* ((default-directory (file-name-directory file-name))
3389 command events filter p)
3390 (cond
3391 ;; gvfs-monitor-dir.
3392 ((setq command (tramp-get-remote-gvfs-monitor-dir v))
3393 (setq filter 'tramp-sh-file-gvfs-monitor-dir-process-filter
3394 p (start-file-process
3395 "gvfs-monitor-dir" (generate-new-buffer " *gvfs-monitor-dir*")
3396 command localname)))
3397 ;; inotifywait.
3398 ((setq command (tramp-get-remote-inotifywait v))
3399 (setq filter 'tramp-sh-file-inotifywait-process-filter
3400 events
3401 (cond
3402 ((and (memq 'change flags) (memq 'attribute-change flags))
3403 "create,modify,move,delete,attrib")
3404 ((memq 'change flags) "create,modify,move,delete")
3405 ((memq 'attribute-change flags) "attrib"))
3406 p (start-file-process
3407 "inotifywait" (generate-new-buffer " *inotifywait*")
3408 command "-mq" "-e" events localname)))
3409 ;; None.
3410 (t (tramp-error
3411 v 'file-notify-error
3412 "No file notification program found on %s"
3413 (file-remote-p file-name))))
3414 ;; Return the process object as watch-descriptor.
3415 (if (not (processp p))
3416 (tramp-error
3417 v 'file-notify-error "`%s' failed to start on remote host" command)
3418 (tramp-compat-set-process-query-on-exit-flag p nil)
3419 (set-process-filter p filter)
3420 p))))
3421
3422(defun tramp-sh-file-gvfs-monitor-dir-process-filter (proc string)
3423 "Read output from \"gvfs-monitor-dir\" and add corresponding file-notify events."
3424 (let ((remote-prefix
3425 (with-current-buffer (process-buffer proc)
3426 (file-remote-p default-directory)))
3427 (rest-string (tramp-compat-process-get proc 'rest-string)))
3428 (when rest-string
3429 (tramp-message proc 10 (format "Previous string:\n%s" rest-string)))
3430 (tramp-message proc 6 (format "%S\n%s" proc string))
3431 (setq string (concat rest-string string)
3432 ;; Attribute change is returned in unused wording.
3433 string (replace-regexp-in-string
3434 "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string))
3435
3436 (while (string-match
3437 (concat "^[\n\r]*"
3438 "Directory Monitor Event:[\n\r]+"
3439 "Child = \\([^\n\r]+\\)[\n\r]+"
3440 "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?"
3441 "Event = \\([^[:blank:]]+\\)[\n\r]+")
3442 string)
3443 (let ((object
3444 (list
3445 proc
3446 (intern-soft
3447 (replace-regexp-in-string
3448 "_" "-" (downcase (match-string 4 string))))
3449 ;; File names are returned as absolute paths. We must
3450 ;; add the remote prefix.
3451 (concat remote-prefix (match-string 1 string))
3452 (when (match-string 3 string)
3453 (concat remote-prefix (match-string 3 string))))))
3454 (setq string (replace-match "" nil nil string))
3455 ;; Usually, we would add an Emacs event now. Unfortunately,
3456 ;; `unread-command-events' does not accept several events at
3457 ;; once. Therefore, we apply the callback directly.
3458 (tramp-compat-funcall 'file-notify-callback object)))
3459
3460 ;; Save rest of the string.
3461 (when (zerop (length string)) (setq string nil))
3462 (when string (tramp-message proc 10 (format "Rest string:\n%s" string)))
3463 (tramp-compat-process-put proc 'rest-string string)))
3464
3465(defun tramp-sh-file-inotifywait-process-filter (proc string)
3466 "Read output from \"inotifywait\" and add corresponding file-notify events."
3467 (tramp-message proc 6 (format "%S\n%s" proc string))
3468 (dolist (line (split-string string "[\n\r]+" 'omit-nulls))
3469 ;; Check, whether there is a problem.
3470 (unless
3471 (string-match
3472 (concat "^[^[:blank:]]+"
3473 "[[:blank:]]+\\([^[:blank:]]+\\)+"
3474 "\\([[:blank:]]+\\([^\n\r]+\\)\\)?")
3475 line)
3476 (tramp-error proc 'file-notify-error "%s" line))
3477
3478 (let ((object
3479 (list
3480 proc
3481 (mapcar
3482 (lambda (x)
3483 (intern-soft (replace-regexp-in-string "_" "-" (downcase x))))
3484 (split-string (match-string 1 line) "," 'omit-nulls))
3485 (match-string 3 line))))
3486 ;; Usually, we would add an Emacs event now. Unfortunately,
3487 ;; `unread-command-events' does not accept several events at
3488 ;; once. Therefore, we apply the callback directly.
3489 (tramp-compat-funcall 'file-notify-callback object))))
3490
3491(defvar file-notify-descriptors)
3492(defun tramp-sh-handle-file-notify-rm-watch (proc)
3493 "Like `file-notify-rm-watch' for Tramp files."
3494 ;; The descriptor must be a process object.
3495 (unless (and (processp proc) (gethash proc file-notify-descriptors))
3496 (tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc))
3497 (tramp-message proc 6 (format "Kill %S" proc))
3498 (kill-process proc))
3499
3379;;; Internal Functions: 3500;;; Internal Functions:
3380 3501
3381(defun tramp-maybe-send-script (vec script name) 3502(defun tramp-maybe-send-script (vec script name)
@@ -3634,12 +3755,16 @@ file exists and nonzero exit status otherwise."
3634 "Wait for shell prompt and barf if none appears. 3755 "Wait for shell prompt and barf if none appears.
3635Looks at process PROC to see if a shell prompt appears in TIMEOUT 3756Looks at process PROC to see if a shell prompt appears in TIMEOUT
3636seconds. If not, it produces an error message with the given ERROR-ARGS." 3757seconds. If not, it produces an error message with the given ERROR-ARGS."
3637 (unless 3758 (let ((vec (tramp-get-connection-property proc "vector" nil)))
3638 (tramp-wait-for-regexp 3759 (condition-case err
3639 proc timeout 3760 (tramp-wait-for-regexp
3640 (format 3761 proc timeout
3641 "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern)) 3762 (format
3642 (apply 'tramp-error-with-buffer nil proc 'file-error error-args))) 3763 "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern))
3764 (error
3765 (delete-process proc)
3766 (apply 'tramp-error-with-buffer
3767 (tramp-get-connection-buffer vec) vec 'file-error error-args)))))
3643 3768
3644(defun tramp-open-connection-setup-interactive-shell (proc vec) 3769(defun tramp-open-connection-setup-interactive-shell (proc vec)
3645 "Set up an interactive shell. 3770 "Set up an interactive shell.
@@ -4214,9 +4339,6 @@ Gateway hops are already opened."
4214 ;; Result. 4339 ;; Result.
4215 target-alist)) 4340 target-alist))
4216 4341
4217(defvar tramp-current-connection nil
4218 "Last connection timestamp.")
4219
4220(defun tramp-maybe-open-connection (vec) 4342(defun tramp-maybe-open-connection (vec)
4221 "Maybe open a connection VEC. 4343 "Maybe open a connection VEC.
4222Does not do anything if a connection is already open, but re-opens the 4344Does not do anything if a connection is already open, but re-opens the
@@ -4230,7 +4352,7 @@ connection if a previous connection has died for some reason."
4230 ;; If Tramp opens the same connection within a short time frame, 4352 ;; If Tramp opens the same connection within a short time frame,
4231 ;; there is a problem. We shall signal this. 4353 ;; there is a problem. We shall signal this.
4232 (unless (or (and p (processp p) (memq (process-status p) '(run open))) 4354 (unless (or (and p (processp p) (memq (process-status p) '(run open)))
4233 (not (equal (butlast (append vec nil)) 4355 (not (equal (butlast (append vec nil) 2)
4234 (car tramp-current-connection))) 4356 (car tramp-current-connection)))
4235 (> (tramp-time-diff 4357 (> (tramp-time-diff
4236 (current-time) (cdr tramp-current-connection)) 4358 (current-time) (cdr tramp-current-connection))
@@ -4315,7 +4437,7 @@ connection if a previous connection has died for some reason."
4315 (set-process-sentinel p 'tramp-process-sentinel) 4437 (set-process-sentinel p 'tramp-process-sentinel)
4316 (tramp-compat-set-process-query-on-exit-flag p nil) 4438 (tramp-compat-set-process-query-on-exit-flag p nil)
4317 (setq tramp-current-connection 4439 (setq tramp-current-connection
4318 (cons (butlast (append vec nil)) (current-time)) 4440 (cons (butlast (append vec nil) 2) (current-time))
4319 tramp-current-host (system-name)) 4441 tramp-current-host (system-name))
4320 4442
4321 (tramp-message 4443 (tramp-message
@@ -4323,8 +4445,8 @@ connection if a previous connection has died for some reason."
4323 4445
4324 ;; Check whether process is alive. 4446 ;; Check whether process is alive.
4325 (tramp-barf-if-no-shell-prompt 4447 (tramp-barf-if-no-shell-prompt
4326 p 60 4448 p 10
4327 "Couldn't find local shell prompt %s" tramp-encoding-shell) 4449 "Couldn't find local shell prompt for %s" tramp-encoding-shell)
4328 4450
4329 ;; Now do all the connections as specified. 4451 ;; Now do all the connections as specified.
4330 (while target-alist 4452 (while target-alist
@@ -4342,6 +4464,9 @@ connection if a previous connection has died for some reason."
4342 (async-args 4464 (async-args
4343 (tramp-get-method-parameter 4465 (tramp-get-method-parameter
4344 l-method 'tramp-async-args)) 4466 l-method 'tramp-async-args))
4467 (connection-timeout
4468 (tramp-get-method-parameter
4469 l-method 'tramp-connection-timeout))
4345 (gw-args 4470 (gw-args
4346 (tramp-get-method-parameter l-method 'tramp-gw-args)) 4471 (tramp-get-method-parameter l-method 'tramp-gw-args))
4347 (gw (tramp-get-file-property hop "" "gateway" nil)) 4472 (gw (tramp-get-file-property hop "" "gateway" nil))
@@ -4424,7 +4549,8 @@ connection if a previous connection has died for some reason."
4424 (tramp-message vec 3 "Sending command `%s'" command) 4549 (tramp-message vec 3 "Sending command `%s'" command)
4425 (tramp-send-command vec command t t) 4550 (tramp-send-command vec command t t)
4426 (tramp-process-actions 4551 (tramp-process-actions
4427 p vec pos tramp-actions-before-shell 60) 4552 p vec pos tramp-actions-before-shell
4553 (or connection-timeout tramp-connection-timeout))
4428 (tramp-message 4554 (tramp-message
4429 vec 3 "Found remote shell prompt on `%s'" l-host)) 4555 vec 3 "Found remote shell prompt on `%s'" l-host))
4430 ;; Next hop. 4556 ;; Next hop.
@@ -4864,6 +4990,17 @@ Return ATTR."
4864 (tramp-message vec 5 "Finding a suitable `trash' command") 4990 (tramp-message vec 5 "Finding a suitable `trash' command")
4865 (tramp-find-executable vec "trash" (tramp-get-remote-path vec)))) 4991 (tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
4866 4992
4993(defun tramp-get-remote-gvfs-monitor-dir (vec)
4994 (with-tramp-connection-property vec "gvfs-monitor-dir"
4995 (tramp-message vec 5 "Finding a suitable `gvfs-monitor-dir' command")
4996 (tramp-find-executable
4997 vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t)))
4998
4999(defun tramp-get-remote-inotifywait (vec)
5000 (with-tramp-connection-property vec "inotifywait"
5001 (tramp-message vec 5 "Finding a suitable `inotifywait' command")
5002 (tramp-find-executable vec "inotifywait" (tramp-get-remote-path vec) t t)))
5003
4867(defun tramp-get-remote-id (vec) 5004(defun tramp-get-remote-id (vec)
4868 (with-tramp-connection-property vec "id" 5005 (with-tramp-connection-property vec "id"
4869 (tramp-message vec 5 "Finding POSIX `id' command") 5006 (tramp-message vec 5 "Finding POSIX `id' command")
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 4ec3a4b7829..3513701d20e 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -252,6 +252,11 @@ pair of the form (KEY VALUE). The following KEYs are defined:
252 * `tramp-tmpdir' 252 * `tramp-tmpdir'
253 A directory on the remote host for temporary files. If not 253 A directory on the remote host for temporary files. If not
254 specified, \"/tmp\" is taken as default. 254 specified, \"/tmp\" is taken as default.
255 * `tramp-connection-timeout'
256 This is the maximum time to be spent for establishing a connection.
257 In general, the global default value shall be used, but for
258 some methods, like \"su\" or \"sudo\", a shorter timeout
259 might be desirable.
255 260
256What does all this mean? Well, you should specify `tramp-login-program' 261What does all this mean? Well, you should specify `tramp-login-program'
257for all methods; this program is used to log in to the remote site. Then, 262for all methods; this program is used to log in to the remote site. Then,
@@ -1034,6 +1039,13 @@ opening a connection to a remote host."
1034 :group 'tramp 1039 :group 'tramp
1035 :type '(choice (const nil) (const t) (const pty))) 1040 :type '(choice (const nil) (const t) (const pty)))
1036 1041
1042(defcustom tramp-connection-timeout 60
1043 "Defines the max time to wait for establishing a connection (in seconds).
1044This can be overwritten for different connection types in `tramp-methods'."
1045 :group 'tramp
1046 :version "24.4"
1047 :type 'integer)
1048
1037(defcustom tramp-connection-min-time-diff 5 1049(defcustom tramp-connection-min-time-diff 5
1038 "Defines seconds between two consecutive connection attempts. 1050 "Defines seconds between two consecutive connection attempts.
1039This is necessary as self defense mechanism, in order to avoid 1051This is necessary as self defense mechanism, in order to avoid
@@ -1071,6 +1083,9 @@ means to use always cached values for the directory contents."
1071(defvar tramp-current-host nil 1083(defvar tramp-current-host nil
1072 "Remote host for this *tramp* buffer.") 1084 "Remote host for this *tramp* buffer.")
1073 1085
1086(defvar tramp-current-connection nil
1087 "Last connection timestamp.")
1088
1074;;;###autoload 1089;;;###autoload
1075(defconst tramp-completion-file-name-handler-alist 1090(defconst tramp-completion-file-name-handler-alist
1076 '((file-name-all-completions . tramp-completion-handle-file-name-all-completions) 1091 '((file-name-all-completions . tramp-completion-handle-file-name-all-completions)
@@ -1464,10 +1479,6 @@ ARGS to actually emit the message (if applicable)."
1464This variable is used to disable messages from `tramp-error'. 1479This variable is used to disable messages from `tramp-error'.
1465The messages are visible anyway, because an error is raised.") 1480The messages are visible anyway, because an error is raised.")
1466 1481
1467(defvar tramp-message-show-progress-reporter-message t
1468 "Show Tramp progress reporter message in the minibuffer.
1469This variable is used to disable recursive progress reporter messages.")
1470
1471(defsubst tramp-message (vec-or-proc level fmt-string &rest args) 1482(defsubst tramp-message (vec-or-proc level fmt-string &rest args)
1472 "Emit a message depending on verbosity level. 1483 "Emit a message depending on verbosity level.
1473VEC-OR-PROC identifies the Tramp buffer to use. It can be either a 1484VEC-OR-PROC identifies the Tramp buffer to use. It can be either a
@@ -1536,23 +1547,32 @@ signal identifier to be raised, remaining args passed to
1536If BUFFER is nil, show the connection buffer. Wait for 30\", or until 1547If BUFFER is nil, show the connection buffer. Wait for 30\", or until
1537an input event arrives. The other arguments are passed to `tramp-error'." 1548an input event arrives. The other arguments are passed to `tramp-error'."
1538 (save-window-excursion 1549 (save-window-excursion
1539 (unwind-protect 1550 (let* ((buf (or (and (bufferp buffer) buffer)
1540 (apply 'tramp-error vec-or-proc signal fmt-string args) 1551 (and (processp vec-or-proc) (process-buffer vec-or-proc))
1541 (when (and vec-or-proc 1552 (and (vectorp vec-or-proc)
1542 tramp-message-show-message 1553 (tramp-get-connection-buffer vec-or-proc))))
1543 (not (zerop tramp-verbose)) 1554 (vec (or (and (vectorp vec-or-proc) vec-or-proc)
1544 (not (tramp-completion-mode-p))) 1555 (and buf (with-current-buffer buf
1545 (let ((enable-recursive-minibuffers t)) 1556 (tramp-dissect-file-name default-directory))))))
1546 (pop-to-buffer 1557 (unwind-protect
1547 (or (and (bufferp buffer) buffer) 1558 (apply 'tramp-error vec-or-proc signal fmt-string args)
1548 (and (processp vec-or-proc) (process-buffer vec-or-proc)) 1559 ;; Save exit.
1549 (tramp-get-connection-buffer vec-or-proc))) 1560 (when (and buf
1550 (when (string-equal fmt-string "Process died") 1561 tramp-message-show-message
1551 (message 1562 (not (zerop tramp-verbose))
1552 "%s\n %s" 1563 (not (tramp-completion-mode-p)))
1553 "Tramp failed to connect. If this happens repeatedly, try" 1564 (let ((enable-recursive-minibuffers t))
1554 "`M-x tramp-cleanup-this-connection'")) 1565 ;; `tramp-error' does not show messages. So we must do it
1555 (sit-for 30)))))) 1566 ;; ourselves.
1567 (message fmt-string args)
1568 ;; Show buffer.
1569 (pop-to-buffer buf)
1570 (discard-input)
1571 (sit-for 30)))
1572 ;; Reset timestamp. It would be wrong after waiting for a while.
1573 (when (equal (butlast (append vec nil) 2)
1574 (car tramp-current-connection))
1575 (setcdr tramp-current-connection (current-time)))))))
1556 1576
1557(defmacro with-parsed-tramp-file-name (filename var &rest body) 1577(defmacro with-parsed-tramp-file-name (filename var &rest body)
1558 "Parse a Tramp filename and make components available in the body. 1578 "Parse a Tramp filename and make components available in the body.
@@ -1596,16 +1616,15 @@ If VAR is nil, then we bind `v' to the structure and `method', `user',
1596 1616
1597(defmacro with-tramp-progress-reporter (vec level message &rest body) 1617(defmacro with-tramp-progress-reporter (vec level message &rest body)
1598 "Executes BODY, spinning a progress reporter with MESSAGE. 1618 "Executes BODY, spinning a progress reporter with MESSAGE.
1599If LEVEL does not fit for visible messages, or if this is a 1619If LEVEL does not fit for visible messages, there are only traces
1600nested call of the macro, there are only traces without a visible 1620without a visible progress reporter."
1601progress reporter."
1602 (declare (indent 3) (debug t)) 1621 (declare (indent 3) (debug t))
1603 `(let (pr tm) 1622 `(let ((result "failed")
1623 pr tm)
1604 (tramp-message ,vec ,level "%s..." ,message) 1624 (tramp-message ,vec ,level "%s..." ,message)
1605 ;; We start a pulsing progress reporter after 3 seconds. Feature 1625 ;; We start a pulsing progress reporter after 3 seconds. Feature
1606 ;; introduced in Emacs 24.1. 1626 ;; introduced in Emacs 24.1.
1607 (when (and tramp-message-show-progress-reporter-message 1627 (when (and tramp-message-show-message
1608 tramp-message-show-message
1609 ;; Display only when there is a minimum level. 1628 ;; Display only when there is a minimum level.
1610 (<= ,level (min tramp-verbose 3))) 1629 (<= ,level (min tramp-verbose 3)))
1611 (ignore-errors 1630 (ignore-errors
@@ -1613,14 +1632,11 @@ progress reporter."
1613 tm (when pr 1632 tm (when pr
1614 (run-at-time 3 0.1 'tramp-progress-reporter-update pr))))) 1633 (run-at-time 3 0.1 'tramp-progress-reporter-update pr)))))
1615 (unwind-protect 1634 (unwind-protect
1616 ;; Execute the body. Suppress concurrent progress reporter 1635 ;; Execute the body.
1617 ;; messages. 1636 (prog1 (progn ,@body) (setq result "done"))
1618 (let ((tramp-message-show-progress-reporter-message
1619 (and tramp-message-show-progress-reporter-message (not tm))))
1620 ,@body)
1621 ;; Stop progress reporter. 1637 ;; Stop progress reporter.
1622 (if tm (tramp-compat-funcall 'cancel-timer tm)) 1638 (if tm (tramp-compat-funcall 'cancel-timer tm))
1623 (tramp-message ,vec ,level "%s...done" ,message)))) 1639 (tramp-message ,vec ,level "%s...%s" ,message result))))
1624 1640
1625(tramp-compat-font-lock-add-keywords 1641(tramp-compat-font-lock-add-keywords
1626 'emacs-lisp-mode '("\\<with-tramp-progress-reporter\\>")) 1642 'emacs-lisp-mode '("\\<with-tramp-progress-reporter\\>"))
@@ -1964,7 +1980,7 @@ ARGS are the arguments OPERATION has been called with."
1964 ;; Emacs 22+ only. 1980 ;; Emacs 22+ only.
1965 'set-file-times 1981 'set-file-times
1966 ;; Emacs 24+ only. 1982 ;; Emacs 24+ only.
1967 'file-acl 'file-selinux-context 1983 'file-acl 'file-notify-add-watch 'file-selinux-context
1968 'set-file-acl 'set-file-selinux-context 1984 'set-file-acl 'set-file-selinux-context
1969 ;; XEmacs only. 1985 ;; XEmacs only.
1970 'abbreviate-file-name 'create-file-buffer 1986 'abbreviate-file-name 'create-file-buffer
@@ -2018,6 +2034,10 @@ ARGS are the arguments OPERATION has been called with."
2018 ;; XEmacs only. 2034 ;; XEmacs only.
2019 'dired-print-file 'dired-shell-call-process)) 2035 'dired-print-file 'dired-shell-call-process))
2020 default-directory) 2036 default-directory)
2037 ;; PROC.
2038 ((eq operation 'file-notify-rm-watch)
2039 (with-current-buffer (process-buffer (nth 0 args))
2040 default-directory))
2021 ;; Unknown file primitive. 2041 ;; Unknown file primitive.
2022 (t (error "unknown file I/O primitive: %s" operation)))) 2042 (t (error "unknown file I/O primitive: %s" operation))))
2023 2043
@@ -3389,39 +3409,49 @@ The terminal type can be configured with `tramp-terminal-type'."
3389PROC and VEC indicate the remote connection to be used. POS, if 3409PROC and VEC indicate the remote connection to be used. POS, if
3390set, is the starting point of the region to be deleted in the 3410set, is the starting point of the region to be deleted in the
3391connection buffer." 3411connection buffer."
3392 ;; Preserve message for `progress-reporter'. 3412 ;; Enable `auth-source' and `password-cache'. We must use
3393 (tramp-compat-with-temp-message "" 3413 ;; tramp-current-* variables in case we have several hops.
3394 ;; Enable `auth-source' and `password-cache'. We must use 3414 (tramp-set-connection-property
3395 ;; tramp-current-* variables in case we have several hops. 3415 (tramp-dissect-file-name
3396 (tramp-set-connection-property 3416 (tramp-make-tramp-file-name
3397 (tramp-dissect-file-name 3417 tramp-current-method tramp-current-user tramp-current-host ""))
3398 (tramp-make-tramp-file-name 3418 "first-password-request" t)
3399 tramp-current-method tramp-current-user tramp-current-host "")) 3419 (save-restriction
3400 "first-password-request" t) 3420 (with-tramp-progress-reporter
3401 (save-restriction 3421 proc 3 "Waiting for prompts from remote shell"
3402 (let (exit) 3422 (let (exit)
3403 (while (not exit) 3423 (if timeout
3404 (tramp-message proc 3 "Waiting for prompts from remote shell") 3424 (with-timeout (timeout (setq exit 'timeout))
3405 (setq exit 3425 (while (not exit)
3406 (catch 'tramp-action 3426 (setq exit
3407 (if timeout 3427 (catch 'tramp-action
3408 (with-timeout (timeout) 3428 (tramp-process-one-action proc vec actions)))))
3409 (tramp-process-one-action proc vec actions)) 3429 (while (not exit)
3430 (setq exit
3431 (catch 'tramp-action
3410 (tramp-process-one-action proc vec actions))))) 3432 (tramp-process-one-action proc vec actions)))))
3411 (with-current-buffer (tramp-get-connection-buffer vec) 3433 (with-current-buffer (tramp-get-connection-buffer vec)
3412 (widen) 3434 (widen)
3413 (tramp-message vec 6 "\n%s" (buffer-string))) 3435 (tramp-message vec 6 "\n%s" (buffer-string)))
3414 (unless (eq exit 'ok) 3436 (unless (eq exit 'ok)
3415 (tramp-clear-passwd vec) 3437 (tramp-clear-passwd vec)
3438 (delete-process proc)
3416 (tramp-error-with-buffer 3439 (tramp-error-with-buffer
3417 nil vec 'file-error 3440 (tramp-get-connection-buffer vec) vec 'file-error
3418 (cond 3441 (cond
3419 ((eq exit 'permission-denied) "Permission denied") 3442 ((eq exit 'permission-denied) "Permission denied")
3420 ((eq exit 'process-died) "Process died") 3443 ((eq exit 'process-died)
3421 (t "Login failed")))) 3444 (concat
3422 (when (numberp pos) 3445 "Tramp failed to connect. If this happens repeatedly, try\n"
3423 (with-current-buffer (tramp-get-connection-buffer vec) 3446 " `M-x tramp-cleanup-this-connection'"))
3424 (let (buffer-read-only) (delete-region pos (point))))))))) 3447 ((eq exit 'timeout)
3448 (format
3449 "Timeout reached, see buffer `%s' for details"
3450 (tramp-get-connection-buffer vec)))
3451 (t "Login failed")))))
3452 (when (numberp pos)
3453 (with-current-buffer (tramp-get-connection-buffer vec)
3454 (let (buffer-read-only) (delete-region pos (point))))))))
3425 3455
3426:;; Utility functions: 3456:;; Utility functions:
3427 3457
@@ -4156,6 +4186,9 @@ Only works for Bourne-like shells."
4156;; * Run emerge on two remote files. Bug is described here: 4186;; * Run emerge on two remote files. Bug is described here:
4157;; <http://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>. 4187;; <http://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>.
4158;; (Bug#6850) 4188;; (Bug#6850)
4189;; * Use also port to distinguish connections. This is needed for
4190;; different hosts sitting behind a single router (distinguished by
4191;; different port numbers). (Tzvi Edelman)
4159 4192
4160;;; tramp.el ends here 4193;;; tramp.el ends here
4161 4194
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 9077bdbb513..a3bd000a4f3 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -6892,7 +6892,7 @@ comment at the start of cc-engine.el for more info."
6892 (while (and (looking-at c-type-decl-prefix-key) 6892 (while (and (looking-at c-type-decl-prefix-key)
6893 (if (and (c-major-mode-is 'c++-mode) 6893 (if (and (c-major-mode-is 'c++-mode)
6894 (match-beginning 3)) 6894 (match-beginning 3))
6895 ;; If the second submatch matches in C++ then 6895 ;; If the third submatch matches in C++ then
6896 ;; we're looking at an identifier that's a 6896 ;; we're looking at an identifier that's a
6897 ;; prefix only if it specifies a member pointer. 6897 ;; prefix only if it specifies a member pointer.
6898 (when (setq got-identifier (c-forward-name)) 6898 (when (setq got-identifier (c-forward-name))
@@ -7193,19 +7193,23 @@ comment at the start of cc-engine.el for more info."
7193 ;; uncommon (e.g. some placements of "const" in C++) it's not worth 7193 ;; uncommon (e.g. some placements of "const" in C++) it's not worth
7194 ;; the effort to look for them.) 7194 ;; the effort to look for them.)
7195 7195
7196 (unless (or at-decl-end (looking-at "=[^=]")) 7196;;; 2008-04-16: commented out the next form, to allow the function to recognize
7197 ;; If this is a declaration it should end here or its initializer(*) 7197;;; "foo (int bar)" in CC (an implicit type (in class foo) without a semicolon)
7198 ;; should start here, so check for allowed separation tokens. Note 7198;;; as a(n almost complete) declaration, enabling it to be fontified.
7199 ;; that this rule doesn't work e.g. with a K&R arglist after a 7199 ;; CASE 13
7200 ;; function header. 7200 ;; (unless (or at-decl-end (looking-at "=[^=]"))
7201 ;; 7201 ;; If this is a declaration it should end here or its initializer(*)
7202 ;; *) Don't check for C++ style initializers using parens 7202 ;; should start here, so check for allowed separation tokens. Note
7203 ;; since those already have been matched as suffixes. 7203 ;; that this rule doesn't work e.g. with a K&R arglist after a
7204 ;; 7204 ;; function header.
7205 ;; If `at-decl-or-cast' is then we've found some other sign that 7205 ;;
7206 ;; it's a declaration or cast, so then it's probably an 7206 ;; *) Don't check for C++ style initializers using parens
7207 ;; invalid/unfinished one. 7207 ;; since those already have been matched as suffixes.
7208 (throw 'at-decl-or-cast at-decl-or-cast)) 7208 ;;
7209 ;; If `at-decl-or-cast' is then we've found some other sign that
7210 ;; it's a declaration or cast, so then it's probably an
7211 ;; invalid/unfinished one.
7212 ;; (throw 'at-decl-or-cast at-decl-or-cast))
7209 7213
7210 ;; Below are tests that only should be applied when we're certain to 7214 ;; Below are tests that only should be applied when we're certain to
7211 ;; not have parsed halfway through an expression. 7215 ;; not have parsed halfway through an expression.
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 55d5b8b0be7..85a9074760d 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -387,10 +387,10 @@ Intended as the value of `indent-line-function'."
387 (skip-chars-forward " \t") 387 (skip-chars-forward " \t")
388 (current-column))) 388 (current-column)))
389 (error nil))) 389 (error nil)))
390 ;; Inside a string and it starts before this line. 390 ;; Inside a string and it starts before this line: do nothing.
391 ((and (nth 3 parse) 391 ((and (nth 3 parse)
392 (< (nth 8 parse) (save-excursion (beginning-of-line) (point)))) 392 (< (nth 8 parse) (save-excursion (beginning-of-line) (point))))
393 (indent-line-to 0)) 393 )
394 394
395 ;; Inside a defun, but not a nested list (depth is 1). This is 395 ;; Inside a defun, but not a nested list (depth is 1). This is
396 ;; a promise, usually. 396 ;; a promise, usually.
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
index 4957b58d469..6a71ab330a8 100644
--- a/lisp/progmodes/ebrowse.el
+++ b/lisp/progmodes/ebrowse.el
@@ -33,12 +33,12 @@
33 33
34;;; Code: 34;;; Code:
35 35
36(require 'cl-lib)
36(require 'easymenu) 37(require 'easymenu)
37(require 'view) 38(require 'view)
38(require 'ebuff-menu) 39(require 'ebuff-menu)
39 40
40(eval-when-compile 41(eval-when-compile
41 (require 'cl-lib)
42 (require 'helper)) 42 (require 'helper))
43 43
44 44
@@ -233,19 +233,6 @@ Compare items with `eq' or TEST if specified."
233 found)) 233 found))
234 234
235 235
236(defun ebrowse-delete-if-not (predicate list)
237 "Remove elements not satisfying PREDICATE from LIST and return the result.
238This is a destructive operation."
239 (let (result)
240 (while list
241 (let ((next (cdr list)))
242 (when (funcall predicate (car list))
243 (setq result (nconc result list))
244 (setf (cdr list) nil))
245 (setq list next)))
246 result))
247
248
249(defmacro ebrowse-output (&rest body) 236(defmacro ebrowse-output (&rest body)
250 "Eval BODY with a writable current buffer. 237 "Eval BODY with a writable current buffer.
251Preserve buffer's modified state." 238Preserve buffer's modified state."
@@ -1310,17 +1297,17 @@ With PREFIX, insert that many filenames."
1310 1297
1311(defun ebrowse-browser-buffer-list () 1298(defun ebrowse-browser-buffer-list ()
1312 "Return a list of all tree or member buffers." 1299 "Return a list of all tree or member buffers."
1313 (ebrowse-delete-if-not 'ebrowse-buffer-p (buffer-list))) 1300 (cl-delete-if-not 'ebrowse-buffer-p (buffer-list)))
1314 1301
1315 1302
1316(defun ebrowse-member-buffer-list () 1303(defun ebrowse-member-buffer-list ()
1317 "Return a list of all member buffers." 1304 "Return a list of all member buffers."
1318 (ebrowse-delete-if-not 'ebrowse-member-buffer-p (buffer-list))) 1305 (cl-delete-if-not 'ebrowse-member-buffer-p (buffer-list)))
1319 1306
1320 1307
1321(defun ebrowse-tree-buffer-list () 1308(defun ebrowse-tree-buffer-list ()
1322 "Return a list of all tree buffers." 1309 "Return a list of all tree buffers."
1323 (ebrowse-delete-if-not 'ebrowse-tree-buffer-p (buffer-list))) 1310 (cl-delete-if-not 'ebrowse-tree-buffer-p (buffer-list)))
1324 1311
1325 1312
1326(defun ebrowse-known-class-trees-buffer-list () 1313(defun ebrowse-known-class-trees-buffer-list ()
@@ -1341,7 +1328,7 @@ one buffer. Prefer tree buffers over member buffers."
1341 1328
1342(defun ebrowse-same-tree-member-buffer-list () 1329(defun ebrowse-same-tree-member-buffer-list ()
1343 "Return a list of members buffers with same tree as current buffer." 1330 "Return a list of members buffers with same tree as current buffer."
1344 (ebrowse-delete-if-not 1331 (cl-delete-if-not
1345 (lambda (buffer) 1332 (lambda (buffer)
1346 (eq (buffer-local-value 'ebrowse--tree buffer) 1333 (eq (buffer-local-value 'ebrowse--tree buffer)
1347 ebrowse--tree)) 1334 ebrowse--tree))
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 2c4d6a0e3d7..10472ec5815 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1759,6 +1759,9 @@ static char *magick[] = {
1759As long as GDB is in the recursive reading loop, it does not expect 1759As long as GDB is in the recursive reading loop, it does not expect
1760commands to be prefixed by \"-interpreter-exec console\".") 1760commands to be prefixed by \"-interpreter-exec console\".")
1761 1761
1762(defun gdb-strip-string-backslash (string)
1763 (replace-regexp-in-string "\\\\$" "" string))
1764
1762(defun gdb-send (proc string) 1765(defun gdb-send (proc string)
1763 "A comint send filter for gdb." 1766 "A comint send filter for gdb."
1764 (with-current-buffer gud-comint-buffer 1767 (with-current-buffer gud-comint-buffer
@@ -1766,10 +1769,15 @@ commands to be prefixed by \"-interpreter-exec console\".")
1766 (remove-text-properties (point-min) (point-max) '(face)))) 1769 (remove-text-properties (point-min) (point-max) '(face))))
1767 ;; mimic <RET> key to repeat previous command in GDB 1770 ;; mimic <RET> key to repeat previous command in GDB
1768 (if (not (string= "" string)) 1771 (if (not (string= "" string))
1769 (setq gdb-last-command string) 1772 (if gdb-continuation
1770 (if gdb-last-command (setq string gdb-last-command))) 1773 (setq gdb-last-command (concat gdb-continuation
1771 (if (or (string-match "^-" string) 1774 (gdb-strip-string-backslash string)
1772 (> gdb-control-level 0)) 1775 " "))
1776 (setq gdb-last-command (gdb-strip-string-backslash string)))
1777 (if gdb-last-command (setq string gdb-last-command))
1778 (setq gdb-continuation nil))
1779 (if (and (not gdb-continuation) (or (string-match "^-" string)
1780 (> gdb-control-level 0)))
1773 ;; Either MI command or we are feeding GDB's recursive reading loop. 1781 ;; Either MI command or we are feeding GDB's recursive reading loop.
1774 (progn 1782 (progn
1775 (setq gdb-first-done-or-error t) 1783 (setq gdb-first-done-or-error t)
@@ -1779,10 +1787,13 @@ commands to be prefixed by \"-interpreter-exec console\".")
1779 (setq gdb-control-level (1- gdb-control-level)))) 1787 (setq gdb-control-level (1- gdb-control-level))))
1780 ;; CLI command 1788 ;; CLI command
1781 (if (string-match "\\\\$" string) 1789 (if (string-match "\\\\$" string)
1782 (setq gdb-continuation (concat gdb-continuation string "\n")) 1790 (setq gdb-continuation
1791 (concat gdb-continuation (gdb-strip-string-backslash
1792 string)
1793 " "))
1783 (setq gdb-first-done-or-error t) 1794 (setq gdb-first-done-or-error t)
1784 (let ((to-send (concat "-interpreter-exec console " 1795 (let ((to-send (concat "-interpreter-exec console "
1785 (gdb-mi-quote string) 1796 (gdb-mi-quote (concat gdb-continuation string " "))
1786 "\n"))) 1797 "\n")))
1787 (if gdb-enable-debug 1798 (if gdb-enable-debug
1788 (push (cons 'mi-send to-send) gdb-debug-log)) 1799 (push (cons 'mi-send to-send) gdb-debug-log))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 915b52ce04d..62870f9085b 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3091,7 +3091,12 @@ you are doing."
3091 ;; Stop collecting nodes after moving to a position with 3091 ;; Stop collecting nodes after moving to a position with
3092 ;; indentation equaling min-indent. This is specially 3092 ;; indentation equaling min-indent. This is specially
3093 ;; useful for navigating nested definitions recursively. 3093 ;; useful for navigating nested definitions recursively.
3094 tree) 3094 (if (> num-children 0)
3095 tree
3096 ;; When there are no children, the collected tree is a
3097 ;; single node intended to be added in the list of defuns
3098 ;; of its parent.
3099 (car tree)))
3095 (t 3100 (t
3096 (python-imenu--build-tree 3101 (python-imenu--build-tree
3097 min-indent 3102 min-indent
@@ -3131,7 +3136,7 @@ you are doing."
3131 (cons 3136 (cons
3132 (prog1 3137 (prog1
3133 (python-imenu--build-tree 3138 (python-imenu--build-tree
3134 prev-indent indent 1 (list (cons label pos))) 3139 prev-indent indent 0 (list (cons label pos)))
3135 ;; Adjustment: after scanning backwards 3140 ;; Adjustment: after scanning backwards
3136 ;; for all deeper children, we need to 3141 ;; for all deeper children, we need to
3137 ;; continue our scan for a parent from 3142 ;; continue our scan for a parent from
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 0292e40b986..0b83921504b 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -990,13 +990,14 @@ calculating indentation on the lines after it."
990(defun ruby-move-to-block (n) 990(defun ruby-move-to-block (n)
991 "Move to the beginning (N < 0) or the end (N > 0) of the 991 "Move to the beginning (N < 0) or the end (N > 0) of the
992current block, a sibling block, or an outer block. Do that (abs N) times." 992current block, a sibling block, or an outer block. Do that (abs N) times."
993 (back-to-indentation)
993 (let ((signum (if (> n 0) 1 -1)) 994 (let ((signum (if (> n 0) 1 -1))
994 (backward (< n 0)) 995 (backward (< n 0))
995 (depth (or (nth 2 (ruby-parse-region (line-beginning-position) 996 (depth (or (nth 2 (ruby-parse-region (point) (line-end-position))) 0))
996 (line-end-position)))
997 0))
998 case-fold-search 997 case-fold-search
999 down done) 998 down done)
999 (when (looking-at ruby-block-mid-re)
1000 (setq depth (+ depth signum)))
1000 (when (< (* depth signum) 0) 1001 (when (< (* depth signum) 0)
1001 ;; Moving end -> end or beginning -> beginning. 1002 ;; Moving end -> end or beginning -> beginning.
1002 (setq depth 0)) 1003 (setq depth 0))
@@ -1033,22 +1034,16 @@ current block, a sibling block, or an outer block. Do that (abs N) times."
1033 (unless (car state) ; Line ends with unfinished string. 1034 (unless (car state) ; Line ends with unfinished string.
1034 (setq depth (+ (nth 2 state) depth)))) 1035 (setq depth (+ (nth 2 state) depth))))
1035 (cond 1036 (cond
1036 ;; Deeper indentation, we found a block. 1037 ;; Increased depth, we found a block.
1037 ;; FIXME: We can't recognize empty blocks this way.
1038 ((> (* signum depth) 0) 1038 ((> (* signum depth) 0)
1039 (setq down t)) 1039 (setq down t))
1040 ;; Block found, and same indentation as when started, stop. 1040 ;; We're at the same depth as when we started, and we've
1041 ;; encountered a block before. Stop.
1041 ((and down (zerop depth)) 1042 ((and down (zerop depth))
1042 (setq done t)) 1043 (setq done t))
1043 ;; Shallower indentation, means outer block, can stop now. 1044 ;; Lower depth, means outer block, can stop now.
1044 ((< (* signum depth) 0) 1045 ((< (* signum depth) 0)
1045 (setq done t))))) 1046 (setq done t)))))))
1046 (if done
1047 (save-excursion
1048 (back-to-indentation)
1049 ;; Not really at the first or last line of the block, move on.
1050 (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>"))
1051 (setq done nil))))))
1052 (back-to-indentation))) 1047 (back-to-indentation)))
1053 1048
1054(defun ruby-beginning-of-block (&optional arg) 1049(defun ruby-beginning-of-block (&optional arg)
@@ -1356,7 +1351,7 @@ If the result is do-end block, it will always be multiline."
1356 (progn 1351 (progn
1357 (eval-and-compile 1352 (eval-and-compile
1358 (defconst ruby-percent-literal-beg-re 1353 (defconst ruby-percent-literal-beg-re
1359 "\\(%\\)[qQrswWx]?\\([[:punct:]]\\)" 1354 "\\(%\\)[qQrswWxIi]?\\([[:punct:]]\\)"
1360 "Regexp to match the beginning of percent literal.") 1355 "Regexp to match the beginning of percent literal.")
1361 1356
1362 (defconst ruby-syntax-methods-before-regexp 1357 (defconst ruby-syntax-methods-before-regexp
@@ -1392,7 +1387,7 @@ It will be properly highlighted even when the call omits parens.")
1392 (funcall 1387 (funcall
1393 (syntax-propertize-rules 1388 (syntax-propertize-rules
1394 ;; $' $" $` .... are variables. 1389 ;; $' $" $` .... are variables.
1395 ;; ?' ?" ?` are ascii codes. 1390 ;; ?' ?" ?` are character literals (one-char strings in 1.9+).
1396 ("\\([?$]\\)[#\"'`]" 1391 ("\\([?$]\\)[#\"'`]"
1397 (1 (unless (save-excursion 1392 (1 (unless (save-excursion
1398 ;; Not within a string. 1393 ;; Not within a string.
@@ -1523,7 +1518,7 @@ It will be properly highlighted even when the call omits parens.")
1523 (save-match-data 1518 (save-match-data
1524 (save-excursion 1519 (save-excursion
1525 (goto-char (nth 8 parse-state)) 1520 (goto-char (nth 8 parse-state))
1526 (looking-at "%\\(?:[QWrx]\\|\\W\\)"))))))) 1521 (looking-at "%\\(?:[QWrxI]\\|\\W\\)")))))))
1527 1522
1528 (defun ruby-syntax-propertize-expansions (start end) 1523 (defun ruby-syntax-propertize-expansions (start end)
1529 (save-excursion 1524 (save-excursion
@@ -1726,7 +1721,7 @@ See `font-lock-syntax-table'.")
1726(defconst ruby-font-lock-keywords 1721(defconst ruby-font-lock-keywords
1727 (list 1722 (list
1728 ;; functions 1723 ;; functions
1729 '("^\\s *def\\s +\\([^( \t\n]+\\)" 1724 '("^\\s *def\\s +\\(?:[^( \t\n.]*\\.\\)?\\([^( \t\n]+\\)"
1730 1 font-lock-function-name-face) 1725 1 font-lock-function-name-face)
1731 (list (concat 1726 (list (concat
1732 "\\(^\\|[^.@$]\\|\\.\\.\\)\\(" 1727 "\\(^\\|[^.@$]\\|\\.\\.\\)\\("
@@ -1767,31 +1762,66 @@ See `font-lock-syntax-table'.")
1767 "yield") 1762 "yield")
1768 'symbols) 1763 'symbols)
1769 "\\|" 1764 "\\|"
1770 ;; keyword-like methods on Kernel and Module
1771 (regexp-opt 1765 (regexp-opt
1772 '("alias_method" 1766 ;; built-in methods on Kernel
1767 '("__callee__"
1768 "__dir__"
1769 "__method__"
1770 "abort"
1771 "at_exit"
1773 "autoload" 1772 "autoload"
1773 "autoload?"
1774 "binding"
1775 "block_given?"
1776 "caller"
1777 "catch"
1778 "eval"
1779 "exec"
1780 "exit"
1781 "exit!"
1782 "fail"
1783 "fork"
1784 "format"
1785 "lambda"
1786 "load"
1787 "loop"
1788 "open"
1789 "p"
1790 "print"
1791 "printf"
1792 "proc"
1793 "putc"
1794 "puts"
1795 "raise"
1796 "rand"
1797 "readline"
1798 "readlines"
1799 "require"
1800 "require_relative"
1801 "sleep"
1802 "spawn"
1803 "sprintf"
1804 "srand"
1805 "syscall"
1806 "system"
1807 "throw"
1808 "trap"
1809 "warn"
1810 ;; keyword-like private methods on Module
1811 "alias_method"
1774 "attr" 1812 "attr"
1775 "attr_accessor" 1813 "attr_accessor"
1776 "attr_reader" 1814 "attr_reader"
1777 "attr_writer" 1815 "attr_writer"
1778 "catch"
1779 "define_method" 1816 "define_method"
1780 "extend" 1817 "extend"
1781 "fail"
1782 "include" 1818 "include"
1783 "lambda"
1784 "loop"
1785 "module_function" 1819 "module_function"
1820 "prepend"
1786 "private" 1821 "private"
1787 "proc"
1788 "protected" 1822 "protected"
1789 "public" 1823 "public"
1790 "raise"
1791 "refine" 1824 "refine"
1792 "require"
1793 "require_relative"
1794 "throw"
1795 "using") 1825 "using")
1796 'symbols) 1826 'symbols)
1797 "\\)") 1827 "\\)")
@@ -1799,12 +1829,16 @@ See `font-lock-syntax-table'.")
1799 '(if (match-beginning 4) 1829 '(if (match-beginning 4)
1800 font-lock-builtin-face 1830 font-lock-builtin-face
1801 font-lock-keyword-face)) 1831 font-lock-keyword-face))
1832 ;; Perl-ish keywords
1833 "\\_<\\(?:BEGIN\\|END\\)\\_>\\|^__END__$"
1802 ;; here-doc beginnings 1834 ;; here-doc beginnings
1803 `(,ruby-here-doc-beg-re 0 (unless (ruby-singleton-class-p (match-beginning 0)) 1835 `(,ruby-here-doc-beg-re 0 (unless (ruby-singleton-class-p (match-beginning 0))
1804 'font-lock-string-face)) 1836 'font-lock-string-face))
1805 ;; variables 1837 ;; variables
1806 '("\\(^\\|[^.@$]\\|\\.\\.\\)\\_<\\(nil\\|self\\|true\\|false\\)\\>" 1838 '("\\(^\\|[^.@$]\\|\\.\\.\\)\\_<\\(nil\\|self\\|true\\|false\\)\\>"
1807 2 font-lock-variable-name-face) 1839 2 font-lock-variable-name-face)
1840 ;; keywords that evaluate to certain values
1841 '("\\_<__\\(?:LINE\\|ENCODING\\|FILE\\)__\\_>" 0 font-lock-variable-name-face)
1808 ;; symbols 1842 ;; symbols
1809 '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" 1843 '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
1810 2 font-lock-constant-face) 1844 2 font-lock-constant-face)
@@ -1815,14 +1849,22 @@ See `font-lock-syntax-table'.")
1815 0 font-lock-variable-name-face) 1849 0 font-lock-variable-name-face)
1816 ;; constants 1850 ;; constants
1817 '("\\(?:\\_<\\|::\\)\\([A-Z]+\\(\\w\\|_\\)*\\)" 1851 '("\\(?:\\_<\\|::\\)\\([A-Z]+\\(\\w\\|_\\)*\\)"
1818 1 font-lock-type-face) 1852 1 (unless (eq ?\( (char-after)) font-lock-type-face))
1819 '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face) 1853 '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face)
1854 ;; conversion methods on Kernel
1855 (list (concat "\\(?:^\\|[^.@$]\\|\\.\\.\\)"
1856 (regexp-opt '("Array" "Complex" "Float" "Hash"
1857 "Integer" "Rational" "String") 'symbols))
1858 1 font-lock-builtin-face)
1820 ;; expression expansion 1859 ;; expression expansion
1821 '(ruby-match-expression-expansion 1860 '(ruby-match-expression-expansion
1822 2 font-lock-variable-name-face t) 1861 2 font-lock-variable-name-face t)
1823 ;; warn lower camel case 1862 ;; negation char
1824 ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" 1863 '("[^[:alnum:]_]\\(!\\)[^=]"
1825 ; 0 font-lock-warning-face) 1864 1 font-lock-negation-char-face)
1865 ;; character literals
1866 ;; FIXME: Support longer escape sequences.
1867 '("\\?\\\\?\\S " 0 font-lock-string-face)
1826 ) 1868 )
1827 "Additional expressions to highlight in Ruby mode.") 1869 "Additional expressions to highlight in Ruby mode.")
1828 1870
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index ec6e6e7ff10..3e7789069f9 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -74,6 +74,7 @@
74 74
75;;; Code: 75;;; Code:
76 76
77(require 'cl-lib)
77(require 'ange-ftp) 78(require 'ange-ftp)
78 79
79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -180,15 +181,6 @@ created by `shadow-define-regexp-group'.")
180 (setq list (cdr list))) 181 (setq list (cdr list)))
181 (car list)) 182 (car list))
182 183
183(defun shadow-remove-if (func list)
184 "Remove elements satisfying FUNC from LIST.
185Nondestructive; actually returns a copy of the list with the elements removed."
186 (if list
187 (if (funcall func (car list))
188 (shadow-remove-if func (cdr list))
189 (cons (car list) (shadow-remove-if func (cdr list))))
190 nil))
191
192(defun shadow-regexp-superquote (string) 184(defun shadow-regexp-superquote (string)
193 "Like `regexp-quote', but includes the ^ and $. 185 "Like `regexp-quote', but includes the ^ and $.
194This makes sure regexp matches nothing but STRING." 186This makes sure regexp matches nothing but STRING."
@@ -238,9 +230,8 @@ instead."
238Replace old definition, if any. PRIMARY and REGEXP are the 230Replace old definition, if any. PRIMARY and REGEXP are the
239information defining the cluster. For interactive use, call 231information defining the cluster. For interactive use, call
240`shadow-define-cluster' instead." 232`shadow-define-cluster' instead."
241 (let ((rest (shadow-remove-if 233 (let ((rest (cl-remove-if (lambda (x) (equal name (car x)))
242 (function (lambda (x) (equal name (car x)))) 234 shadow-clusters)))
243 shadow-clusters)))
244 (setq shadow-clusters 235 (setq shadow-clusters
245 (cons (shadow-make-cluster name primary regexp) 236 (cons (shadow-make-cluster name primary regexp)
246 rest)))) 237 rest))))
@@ -602,9 +593,8 @@ and to are absolute file names."
602Consider them as regular expressions if third arg REGEXP is true." 593Consider them as regular expressions if third arg REGEXP is true."
603 (if groups 594 (if groups
604 (let ((nonmatching 595 (let ((nonmatching
605 (shadow-remove-if 596 (cl-remove-if (lambda (x) (shadow-file-match x file regexp))
606 (function (lambda (x) (shadow-file-match x file regexp))) 597 (car groups))))
607 (car groups))))
608 (append (cond ((equal nonmatching (car groups)) nil) 598 (append (cond ((equal nonmatching (car groups)) nil)
609 (regexp 599 (regexp
610 (let ((realname (nth 2 (shadow-parse-fullname file)))) 600 (let ((realname (nth 2 (shadow-parse-fullname file))))
@@ -635,8 +625,7 @@ Consider them as regular expressions if third arg REGEXP is true."
635 "Remove PAIR from `shadow-files-to-copy'. 625 "Remove PAIR from `shadow-files-to-copy'.
636PAIR must be `eq' to one of the elements of that list." 626PAIR must be `eq' to one of the elements of that list."
637 (setq shadow-files-to-copy 627 (setq shadow-files-to-copy
638 (shadow-remove-if (function (lambda (s) (eq s pair))) 628 (cl-remove-if (lambda (s) (eq s pair)) shadow-files-to-copy)))
639 shadow-files-to-copy)))
640 629
641(defun shadow-read-files () 630(defun shadow-read-files ()
642 "Visit and load `shadow-info-file' and `shadow-todo-file'. 631 "Visit and load `shadow-info-file' and `shadow-todo-file'.
diff --git a/lisp/simple.el b/lisp/simple.el
index 61f32363dbe..3e3ff485c5e 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -4602,6 +4602,12 @@ for it.")
4602(defun next-line (&optional arg try-vscroll) 4602(defun next-line (&optional arg try-vscroll)
4603 "Move cursor vertically down ARG lines. 4603 "Move cursor vertically down ARG lines.
4604Interactively, vscroll tall lines if `auto-window-vscroll' is enabled. 4604Interactively, vscroll tall lines if `auto-window-vscroll' is enabled.
4605Non-interactively, use TRY-VSCROLL to control whether to vscroll tall
4606lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this
4607function will not vscroll.
4608
4609ARG defaults to 1.
4610
4605If there is no character in the target line exactly under the current column, 4611If there is no character in the target line exactly under the current column,
4606the cursor is positioned after the character in that line which spans this 4612the cursor is positioned after the character in that line which spans this
4607column, or at the end of the line if it is not long enough. 4613column, or at the end of the line if it is not long enough.
@@ -4646,6 +4652,12 @@ and more reliable (no dependence on goal column, etc.)."
4646(defun previous-line (&optional arg try-vscroll) 4652(defun previous-line (&optional arg try-vscroll)
4647 "Move cursor vertically up ARG lines. 4653 "Move cursor vertically up ARG lines.
4648Interactively, vscroll tall lines if `auto-window-vscroll' is enabled. 4654Interactively, vscroll tall lines if `auto-window-vscroll' is enabled.
4655Non-interactively, use TRY-VSCROLL to control whether to vscroll tall
4656lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this
4657function will not vscroll.
4658
4659ARG defaults to 1.
4660
4649If there is no character in the target line exactly over the current column, 4661If there is no character in the target line exactly over the current column,
4650the cursor is positioned after the character in that line which spans this 4662the cursor is positioned after the character in that line which spans this
4651column, or at the end of the line if it is not long enough. 4663column, or at the end of the line if it is not long enough.
@@ -4725,33 +4737,81 @@ lines."
4725 :group 'editing-basics 4737 :group 'editing-basics
4726 :version "23.1") 4738 :version "23.1")
4727 4739
4740(defun default-font-height ()
4741 "Return the height in pixels of the current buffer's default face font."
4742 (let ((default-font (face-font 'default)))
4743 (cond
4744 ((and (display-multi-font-p)
4745 ;; Avoid calling font-info if the frame's default font was
4746 ;; not changed since the frame was created. That's because
4747 ;; font-info is expensive for some fonts, see bug #14838.
4748 (not (string= (frame-parameter nil 'font) default-font)))
4749 (aref (font-info default-font) 3))
4750 (t (frame-char-height)))))
4751
4752(defun default-line-height ()
4753 "Return the pixel height of current buffer's default-face text line.
4754
4755The value includes `line-spacing', if any, defined for the buffer
4756or the frame."
4757 (let ((dfh (default-font-height))
4758 (lsp (if (display-graphic-p)
4759 (or line-spacing
4760 (default-value 'line-spacing)
4761 (frame-parameter nil 'line-spacing)
4762 0)
4763 0)))
4764 (if (floatp lsp)
4765 (setq lsp (* dfh lsp)))
4766 (+ dfh lsp)))
4767
4768(defun window-screen-lines ()
4769 "Return the number of screen lines in the text area of the selected window.
4770
4771This is different from `window-text-height' in that this function counts
4772lines in units of the height of the font used by the default face displayed
4773in the window, not in units of the frame's default font, and also accounts
4774for `line-spacing', if any, defined for the window's buffer or frame.
4775
4776The value is a floating-point number."
4777 (let ((canonical (window-text-height))
4778 (fch (frame-char-height))
4779 (dlh (default-line-height)))
4780 (/ (* (float canonical) fch) dlh)))
4781
4728;; Returns non-nil if partial move was done. 4782;; Returns non-nil if partial move was done.
4729(defun line-move-partial (arg noerror to-end) 4783(defun line-move-partial (arg noerror to-end)
4730 (if (< arg 0) 4784 (if (< arg 0)
4731 ;; Move backward (up). 4785 ;; Move backward (up).
4732 ;; If already vscrolled, reduce vscroll 4786 ;; If already vscrolled, reduce vscroll
4733 (let ((vs (window-vscroll nil t))) 4787 (let ((vs (window-vscroll nil t))
4734 (when (> vs (frame-char-height)) 4788 (dlh (default-line-height)))
4735 (set-window-vscroll nil (- vs (frame-char-height)) t))) 4789 (when (> vs dlh)
4790 (set-window-vscroll nil (- vs dlh) t)))
4736 4791
4737 ;; Move forward (down). 4792 ;; Move forward (down).
4738 (let* ((lh (window-line-height -1)) 4793 (let* ((lh (window-line-height -1))
4794 (rowh (car lh))
4739 (vpos (nth 1 lh)) 4795 (vpos (nth 1 lh))
4740 (ypos (nth 2 lh)) 4796 (ypos (nth 2 lh))
4741 (rbot (nth 3 lh)) 4797 (rbot (nth 3 lh))
4742 (this-lh (window-line-height)) 4798 (this-lh (window-line-height))
4743 (this-height (nth 0 this-lh)) 4799 (this-height (car this-lh))
4744 (this-ypos (nth 2 this-lh)) 4800 (this-ypos (nth 2 this-lh))
4745 (fch (frame-char-height)) 4801 (dlh (default-line-height))
4746 py vs) 4802 (wslines (window-screen-lines))
4803 py vs last-line)
4804 (if (> (mod wslines 1.0) 0.0)
4805 (setq wslines (round (+ wslines 0.5))))
4747 (when (or (null lh) 4806 (when (or (null lh)
4748 (>= rbot fch) 4807 (>= rbot dlh)
4749 (<= ypos (- fch)) 4808 (<= ypos (- dlh))
4750 (null this-lh) 4809 (null this-lh)
4751 (<= this-ypos (- fch))) 4810 (<= this-ypos (- dlh)))
4752 (unless lh 4811 (unless lh
4753 (let ((wend (pos-visible-in-window-p t nil t))) 4812 (let ((wend (pos-visible-in-window-p t nil t)))
4754 (setq rbot (nth 3 wend) 4813 (setq rbot (nth 3 wend)
4814 rowh (nth 4 wend)
4755 vpos (nth 5 wend)))) 4815 vpos (nth 5 wend))))
4756 (unless this-lh 4816 (unless this-lh
4757 (let ((wstart (pos-visible-in-window-p nil nil t))) 4817 (let ((wstart (pos-visible-in-window-p nil nil t)))
@@ -4759,38 +4819,63 @@ lines."
4759 this-height (nth 4 wstart)))) 4819 this-height (nth 4 wstart))))
4760 (setq py 4820 (setq py
4761 (or (nth 1 this-lh) 4821 (or (nth 1 this-lh)
4762 (let ((ppos (posn-at-point))) 4822 (let ((ppos (posn-at-point))
4763 (cdr (or (posn-actual-col-row ppos) 4823 col-row)
4764 (posn-col-row ppos)))))) 4824 (setq col-row (posn-actual-col-row ppos))
4825 (if col-row
4826 (- (cdr col-row) (window-vscroll))
4827 (cdr (posn-col-row ppos))))))
4828 ;; VPOS > 0 means the last line is only partially visible.
4829 ;; But if the part that is visible is at least as tall as the
4830 ;; default font, that means the line is actually fully
4831 ;; readable, and something like line-spacing is hidden. So in
4832 ;; that case we accept the last line in the window as still
4833 ;; visible, and consider the margin as starting one line
4834 ;; later.
4835 (if (and vpos (> vpos 0))
4836 (if (and rowh
4837 (>= rowh (default-font-height))
4838 (< rowh dlh))
4839 (setq last-line (min (- wslines scroll-margin) vpos))
4840 (setq last-line (min (- wslines scroll-margin 1) (1- vpos)))))
4765 (cond 4841 (cond
4766 ;; If last line of window is fully visible, and vscrolling 4842 ;; If last line of window is fully visible, and vscrolling
4767 ;; more would make this line invisible, move forward. 4843 ;; more would make this line invisible, move forward.
4768 ((and (or (< (setq vs (window-vscroll nil t)) fch) 4844 ((and (or (< (setq vs (window-vscroll nil t)) dlh)
4769 (null this-height) 4845 (null this-height)
4770 (<= this-height fch)) 4846 (<= this-height dlh))
4771 (or (null rbot) (= rbot 0))) 4847 (or (null rbot) (= rbot 0)))
4772 nil) 4848 nil)
4773 ;; If cursor is not in the bottom scroll margin, and the 4849 ;; If cursor is not in the bottom scroll margin, and the
4774 ;; current line is is not too tall, move forward. 4850 ;; current line is is not too tall, move forward.
4775 ((and (or (null this-height) (<= this-height fch)) 4851 ((and (or (null this-height) (<= this-height dlh))
4776 vpos 4852 vpos
4777 (> vpos 0) 4853 (> vpos 0)
4778 (< py 4854 (< py last-line))
4779 (min (- (window-text-height) scroll-margin 1) (1- vpos))))
4780 nil) 4855 nil)
4781 ;; When already vscrolled, we vscroll some more if we can, 4856 ;; When already vscrolled, we vscroll some more if we can,
4782 ;; or clear vscroll and move forward at end of tall image. 4857 ;; or clear vscroll and move forward at end of tall image.
4783 ((> vs 0) 4858 ((> vs 0)
4784 (when (or (and rbot (> rbot 0)) 4859 (when (or (and rbot (> rbot 0))
4785 (and this-height (> this-height fch))) 4860 (and this-height (> this-height dlh)))
4786 (set-window-vscroll nil (+ vs fch) t))) 4861 (set-window-vscroll nil (+ vs dlh) t)))
4787 ;; If cursor just entered the bottom scroll margin, move forward, 4862 ;; If cursor just entered the bottom scroll margin, move forward,
4788 ;; but also vscroll one line so redisplay won't recenter. 4863 ;; but also optionally vscroll one line so redisplay won't recenter.
4789 ((and vpos 4864 ((and vpos
4790 (> vpos 0) 4865 (> vpos 0)
4791 (= py (min (- (window-text-height) scroll-margin 1) 4866 (= py last-line))
4792 (1- vpos)))) 4867 ;; Don't vscroll if the partially-visible line at window
4793 (set-window-vscroll nil (frame-char-height) t) 4868 ;; bottom has the default height (a.k.a. "just one more text
4869 ;; line"): in that case, we do want redisplay to behave
4870 ;; normally, i.e. recenter or whatever.
4871 ;;
4872 ;; Note: ROWH + RBOT from the value returned by
4873 ;; pos-visible-in-window-p give the total height of the
4874 ;; partially-visible glyph row at the end of the window. As
4875 ;; we are dealing with floats, we disregard sub-pixel
4876 ;; discrepancies between that and DLH.
4877 (if (and rowh rbot (>= (- (+ rowh rbot) dlh) 1))
4878 (set-window-vscroll nil dlh t))
4794 (line-move-1 arg noerror to-end) 4879 (line-move-1 arg noerror to-end)
4795 t) 4880 t)
4796 ;; If there are lines above the last line, scroll-up one line. 4881 ;; If there are lines above the last line, scroll-up one line.
@@ -4799,7 +4884,7 @@ lines."
4799 t) 4884 t)
4800 ;; Finally, start vscroll. 4885 ;; Finally, start vscroll.
4801 (t 4886 (t
4802 (set-window-vscroll nil (frame-char-height) t))))))) 4887 (set-window-vscroll nil dlh t)))))))
4803 4888
4804 4889
4805;; This is like line-move-1 except that it also performs 4890;; This is like line-move-1 except that it also performs
@@ -4832,11 +4917,14 @@ lines."
4832 (prog1 (line-move-visual arg noerror) 4917 (prog1 (line-move-visual arg noerror)
4833 ;; If we moved into a tall line, set vscroll to make 4918 ;; If we moved into a tall line, set vscroll to make
4834 ;; scrolling through tall images more smooth. 4919 ;; scrolling through tall images more smooth.
4835 (let ((lh (line-pixel-height))) 4920 (let ((lh (line-pixel-height))
4921 (dlh (default-line-height)))
4836 (if (and (< arg 0) 4922 (if (and (< arg 0)
4837 (< (point) (window-start)) 4923 (< (point) (window-start))
4838 (> lh (frame-char-height))) 4924 (> lh dlh))
4839 (set-window-vscroll nil (- lh (frame-char-height)) t)))) 4925 (set-window-vscroll
4926 nil
4927 (- lh dlh) t))))
4840 (line-move-1 arg noerror to-end))))) 4928 (line-move-1 arg noerror to-end)))))
4841 4929
4842;; Display-based alternative to line-move-1. 4930;; Display-based alternative to line-move-1.
@@ -7346,6 +7434,66 @@ warning using STRING as the message.")
7346 (with-eval-after-load pkg 7434 (with-eval-after-load pkg
7347 (bad-package-check pkg)))) 7435 (bad-package-check pkg))))
7348 7436
7437
7438;;; Generic dispatcher commands
7439
7440;; Macro `alternatives-define' is used to create generic commands.
7441;; Generic commands are these (like web, mail, news, encrypt, irc, etc.)
7442;; that can have different alternative implementations where choosing
7443;; among them is exclusively a matter of user preference.
7444
7445;; (alternatives-define COMMAND) creates a new interactive command
7446;; M-x COMMAND and a customizable variable COMMAND-alternatives.
7447;; Typically, the user will not need to customize this variable; packages
7448;; wanting to add alternative implementations should use
7449;;
7450;; ;;;###autoload (push '("My impl name" . my-impl-symbol) COMMAND-alternatives
7451
7452(defmacro alternatives-define (command &rest customizations)
7453 "Define new command `COMMAND'.
7454The variable `COMMAND-alternatives' will contain alternative
7455implementations of COMMAND, so that running `C-u M-x COMMAND'
7456will allow the user to chose among them.
7457CUSTOMIZATIONS, if non-nil, should be composed of alternating
7458`defcustom' keywords and values to add to the declaration of
7459`COMMAND-alternatives' (typically :group and :version)."
7460 (let* ((command-name (symbol-name command))
7461 (varalt-name (concat command-name "-alternatives"))
7462 (varalt-sym (intern varalt-name))
7463 (varimp-sym (intern (concat command-name "--implementation"))))
7464 `(progn
7465
7466 (defcustom ,varalt-sym nil
7467 ,(format "Alist of alternative implementations for the `%s' command.
7468
7469Each entry must be a pair (ALTNAME . ALTFUN), where:
7470ALTNAME - The name shown at user to describe the alternative implementation.
7471ALTFUN - The function called to implement this alternative."
7472 command-name)
7473 :type '(alist :key-type string :value-type function)
7474 ,@customizations)
7475
7476 (defvar ,varimp-sym nil "Internal use only.")
7477
7478 (defun ,command (&optional arg)
7479 ,(format "Run generic command `%s'.
7480If used for the first time, or with interactive ARG, ask the user which
7481implementation to use for `%s'. The variable `%s'
7482contains the list of implementations currently supported for this command."
7483 command-name command-name varalt-name)
7484 (interactive "P")
7485 (when (or arg (null ,varimp-sym))
7486 (let ((val (completing-read
7487 ,(format "Select implementation for command `%s': " command-name)
7488 ,varalt-sym nil t)))
7489 (unless (string-equal val "")
7490 (customize-save-variable ',varimp-sym
7491 (cdr (assoc-string val ,varalt-sym))))))
7492 (if ,varimp-sym
7493 (funcall ,varimp-sym)
7494 (message ,(format "No implementation selected for command `%s'"
7495 command-name)))))))
7496
7349(provide 'simple) 7497(provide 'simple)
7350 7498
7351;;; simple.el ends here 7499;;; simple.el ends here
diff --git a/lisp/subr.el b/lisp/subr.el
index b8a62023805..b6ee96f879e 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1980,7 +1980,7 @@ any other terminator is used itself as input.
1980The optional argument PROMPT specifies a string to use to prompt the user. 1980The optional argument PROMPT specifies a string to use to prompt the user.
1981The variable `read-quoted-char-radix' controls which radix to use 1981The variable `read-quoted-char-radix' controls which radix to use
1982for numeric input." 1982for numeric input."
1983 (let ((message-log-max nil) done (first t) (code 0) char translated) 1983 (let ((message-log-max nil) done (first t) (code 0) translated)
1984 (while (not done) 1984 (while (not done)
1985 (let ((inhibit-quit first) 1985 (let ((inhibit-quit first)
1986 ;; Don't let C-h get the help message--only help function keys. 1986 ;; Don't let C-h get the help message--only help function keys.
@@ -1990,20 +1990,14 @@ for numeric input."
1990or the octal character code. 1990or the octal character code.
1991RET terminates the character code and is discarded; 1991RET terminates the character code and is discarded;
1992any other non-digit terminates the character code and is then used as input.")) 1992any other non-digit terminates the character code and is then used as input."))
1993 (setq char (read-event (and prompt (format "%s-" prompt)) t)) 1993 (setq translated (read-key (and prompt (format "%s-" prompt))))
1994 (if inhibit-quit (setq quit-flag nil))) 1994 (if inhibit-quit (setq quit-flag nil)))
1995 ;; Translate TAB key into control-I ASCII character, and so on.
1996 ;; Note: `read-char' does it using the `ascii-character' property.
1997 ;; We should try and use read-key instead.
1998 (let ((translation (lookup-key local-function-key-map (vector char))))
1999 (setq translated (if (arrayp translation)
2000 (aref translation 0)
2001 char)))
2002 (if (integerp translated) 1995 (if (integerp translated)
2003 (setq translated (char-resolve-modifiers translated))) 1996 (setq translated (char-resolve-modifiers translated)))
2004 (cond ((null translated)) 1997 (cond ((null translated))
2005 ((not (integerp translated)) 1998 ((not (integerp translated))
2006 (setq unread-command-events (list char) 1999 (setq unread-command-events
2000 (listify-key-sequence (this-single-command-raw-keys))
2007 done t)) 2001 done t))
2008 ((/= (logand translated ?\M-\^@) 0) 2002 ((/= (logand translated ?\M-\^@) 0)
2009 ;; Turn a meta-character into a character with the 0200 bit set. 2003 ;; Turn a meta-character into a character with the 0200 bit set.
@@ -2022,7 +2016,8 @@ any other non-digit terminates the character code and is then used as input."))
2022 ((and (not first) (eq translated ?\C-m)) 2016 ((and (not first) (eq translated ?\C-m))
2023 (setq done t)) 2017 (setq done t))
2024 ((not first) 2018 ((not first)
2025 (setq unread-command-events (list char) 2019 (setq unread-command-events
2020 (listify-key-sequence (this-single-command-raw-keys))
2026 done t)) 2021 done t))
2027 (t (setq code translated 2022 (t (setq code translated
2028 done t))) 2023 done t)))
@@ -2186,6 +2181,7 @@ An obsolete, but still supported form is
2186where the optional arg MILLISECONDS specifies an additional wait period, 2181where the optional arg MILLISECONDS specifies an additional wait period,
2187in milliseconds; this was useful when Emacs was built without 2182in milliseconds; this was useful when Emacs was built without
2188floating point support." 2183floating point support."
2184 (declare (advertised-calling-convention (seconds &optional nodisp) "22.1"))
2189 (if (numberp nodisp) 2185 (if (numberp nodisp)
2190 (setq seconds (+ seconds (* 1e-3 nodisp)) 2186 (setq seconds (+ seconds (* 1e-3 nodisp))
2191 nodisp obsolete) 2187 nodisp obsolete)
@@ -2200,7 +2196,10 @@ floating point support."
2200 (or nodisp (redisplay))) 2196 (or nodisp (redisplay)))
2201 (t 2197 (t
2202 (or nodisp (redisplay)) 2198 (or nodisp (redisplay))
2203 (let ((read (read-event nil nil seconds))) 2199 ;; FIXME: we should not read-event here at all, because it's much too
2200 ;; difficult to reliably "undo" a read-event by pushing it onto
2201 ;; unread-command-events.
2202 (let ((read (read-event nil t seconds)))
2204 (or (null read) 2203 (or (null read)
2205 (progn 2204 (progn
2206 ;; If last command was a prefix arg, e.g. C-u, push this event onto 2205 ;; If last command was a prefix arg, e.g. C-u, push this event onto
@@ -2210,7 +2209,6 @@ floating point support."
2210 (setq read (cons t read))) 2209 (setq read (cons t read)))
2211 (push read unread-command-events) 2210 (push read unread-command-events)
2212 nil)))))) 2211 nil))))))
2213(set-advertised-calling-convention 'sit-for '(seconds &optional nodisp) "22.1")
2214 2212
2215(defun y-or-n-p (prompt) 2213(defun y-or-n-p (prompt)
2216 "Ask user a \"y or n\" question. Return t if answer is \"y\". 2214 "Ask user a \"y or n\" question. Return t if answer is \"y\".
@@ -2240,7 +2238,8 @@ is nil and `use-dialog-box' is non-nil."
2240 (cond 2238 (cond
2241 (noninteractive 2239 (noninteractive
2242 (setq prompt (concat prompt 2240 (setq prompt (concat prompt
2243 (if (eq ?\s (aref prompt (1- (length prompt)))) 2241 (if (or (zerop (length prompt))
2242 (eq ?\s (aref prompt (1- (length prompt)))))
2244 "" " ") 2243 "" " ")
2245 "(y or n) ")) 2244 "(y or n) "))
2246 (let ((temp-prompt prompt)) 2245 (let ((temp-prompt prompt))
@@ -2257,7 +2256,8 @@ is nil and `use-dialog-box' is non-nil."
2257 (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip))))) 2256 (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip)))))
2258 (t 2257 (t
2259 (setq prompt (concat prompt 2258 (setq prompt (concat prompt
2260 (if (eq ?\s (aref prompt (1- (length prompt)))) 2259 (if (or (zerop (length prompt))
2260 (eq ?\s (aref prompt (1- (length prompt)))))
2261 "" " ") 2261 "" " ")
2262 "(y or n) ")) 2262 "(y or n) "))
2263 (while 2263 (while
@@ -2449,11 +2449,12 @@ If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there."
2449 (recenter (/ (window-height) 2)))) 2449 (recenter (/ (window-height) 2))))
2450 (message (or message "Type %s to continue editing.") 2450 (message (or message "Type %s to continue editing.")
2451 (single-key-description exit-char)) 2451 (single-key-description exit-char))
2452 (let ((event (read-event))) 2452 (let ((event (read-key)))
2453 ;; `exit-char' can be an event, or an event description list. 2453 ;; `exit-char' can be an event, or an event description list.
2454 (or (eq event exit-char) 2454 (or (eq event exit-char)
2455 (eq event (event-convert-list exit-char)) 2455 (eq event (event-convert-list exit-char))
2456 (setq unread-command-events (list event))))) 2456 (setq unread-command-events
2457 (append (this-single-command-raw-keys))))))
2457 (delete-overlay ol)))) 2458 (delete-overlay ol))))
2458 2459
2459 2460
@@ -3852,6 +3853,7 @@ FILE should be the name of a library, with no directory name."
3852 (declare (obsolete eval-after-load "23.2")) 3853 (declare (obsolete eval-after-load "23.2"))
3853 (eval-after-load file (read))) 3854 (eval-after-load file (read)))
3854 3855
3856
3855(defun display-delayed-warnings () 3857(defun display-delayed-warnings ()
3856 "Display delayed warnings from `delayed-warnings-list'. 3858 "Display delayed warnings from `delayed-warnings-list'.
3857Used from `delayed-warnings-hook' (which see)." 3859Used from `delayed-warnings-hook' (which see)."
@@ -3885,6 +3887,12 @@ By default, this hook contains functions to consolidate the
3885warnings listed in `delayed-warnings-list', display them, and set 3887warnings listed in `delayed-warnings-list', display them, and set
3886`delayed-warnings-list' back to nil.") 3888`delayed-warnings-list' back to nil.")
3887 3889
3890(defun delay-warning (type message &optional level buffer-name)
3891 "Display a delayed warning.
3892Aside from going through `delayed-warnings-list', this is equivalent
3893to `display-warning'."
3894 (push (list type message level buffer-name) delayed-warnings-list))
3895
3888 3896
3889;;;; invisibility specs 3897;;;; invisibility specs
3890 3898
@@ -4494,20 +4502,6 @@ convenience wrapper around `make-progress-reporter' and friends.
4494 nil ,@(cdr (cdr spec))))) 4502 nil ,@(cdr (cdr spec)))))
4495 4503
4496 4504
4497;;;; Support for watching filesystem events.
4498
4499(defun file-notify-handle-event (event)
4500 "Handle file system monitoring event.
4501If EVENT is a filewatch event, call its callback.
4502Otherwise, signal a `filewatch-error'."
4503 (interactive "e")
4504 (if (and (eq (car event) 'file-notify)
4505 (>= (length event) 3))
4506 (funcall (nth 2 event) (nth 1 event))
4507 (signal 'filewatch-error
4508 (cons "Not a valid file-notify event" event))))
4509
4510
4511;;;; Comparing version strings. 4505;;;; Comparing version strings.
4512 4506
4513(defconst version-separator "." 4507(defconst version-separator "."
diff --git a/lisp/thumbs.el b/lisp/thumbs.el
index 3d591303414..8032de85b01 100644
--- a/lisp/thumbs.el
+++ b/lisp/thumbs.el
@@ -57,6 +57,7 @@
57;;; Code: 57;;; Code:
58 58
59(require 'dired) 59(require 'dired)
60(require 'cl-lib) ; for cl-gensym
60 61
61;; CUSTOMIZATIONS 62;; CUSTOMIZATIONS
62 63
@@ -179,21 +180,6 @@ this value can let another user see some of your images."
179(make-variable-buffer-local 'thumbs-marked-list) 180(make-variable-buffer-local 'thumbs-marked-list)
180(put 'thumbs-marked-list 'permanent-local t) 181(put 'thumbs-marked-list 'permanent-local t)
181 182
182(defalias 'thumbs-gensym
183 (if (fboundp 'gensym)
184 'gensym
185 ;; Copied from cl-macs.el
186 (defvar thumbs-gensym-counter 0)
187 (lambda (&optional prefix)
188 "Generate a new uninterned symbol.
189The name is made by appending a number to PREFIX, default \"G\"."
190 (let ((pfix (if (stringp prefix) prefix "G"))
191 (num (if (integerp prefix) prefix
192 (prog1 thumbs-gensym-counter
193 (setq thumbs-gensym-counter
194 (1+ thumbs-gensym-counter))))))
195 (make-symbol (format "%s%d" pfix num))))))
196
197(defsubst thumbs-temp-dir () 183(defsubst thumbs-temp-dir ()
198 (file-name-as-directory (expand-file-name thumbs-temp-dir))) 184 (file-name-as-directory (expand-file-name thumbs-temp-dir)))
199 185
@@ -202,7 +188,7 @@ The name is made by appending a number to PREFIX, default \"G\"."
202 (format "%s%s-%s.jpg" 188 (format "%s%s-%s.jpg"
203 (thumbs-temp-dir) 189 (thumbs-temp-dir)
204 thumbs-temp-prefix 190 thumbs-temp-prefix
205 (thumbs-gensym "T"))) 191 (cl-gensym "T")))
206 192
207(defun thumbs-thumbsdir () 193(defun thumbs-thumbsdir ()
208 "Return the current thumbnails directory (from `thumbs-thumbsdir'). 194 "Return the current thumbnails directory (from `thumbs-thumbsdir').
diff --git a/lisp/vc/ediff.el b/lisp/vc/ediff.el
index 7a8f399a6ce..e9a6a97409c 100644
--- a/lisp/vc/ediff.el
+++ b/lisp/vc/ediff.el
@@ -12,8 +12,8 @@
12;; filed in the Emacs bug reporting system against this file, a copy 12;; filed in the Emacs bug reporting system against this file, a copy
13;; of the bug report be sent to the maintainer's email address. 13;; of the bug report be sent to the maintainer's email address.
14 14
15(defconst ediff-version "2.81.4" "The current version of Ediff") 15(defconst ediff-version "2.81.5" "The current version of Ediff")
16(defconst ediff-date "December 7, 2009" "Date of last update") 16(defconst ediff-date "July 4, 2013" "Date of last update")
17 17
18 18
19;; This file is part of GNU Emacs. 19;; This file is part of GNU Emacs.
@@ -1560,6 +1560,75 @@ With optional NODE, goes to that node."
1560 (add-to-list 'debug-ignored-errors mess)) 1560 (add-to-list 'debug-ignored-errors mess))
1561 1561
1562 1562
1563
1564;;; Command line interface
1565
1566;;;###autoload
1567(defun ediff-files-command ()
1568 (let ((file-a (nth 0 command-line-args-left))
1569 (file-b (nth 1 command-line-args-left)))
1570 (setq command-line-args-left (nthcdr 2 command-line-args-left))
1571 (ediff file-a file-b)))
1572
1573;;;###autoload
1574(defun ediff3-files-command ()
1575 (let ((file-a (nth 0 command-line-args-left))
1576 (file-b (nth 1 command-line-args-left))
1577 (file-c (nth 2 command-line-args-left)))
1578 (setq command-line-args-left (nthcdr 3 command-line-args-left))
1579 (ediff3 file-a file-b file-c)))
1580
1581;;;###autoload
1582(defun ediff-merge-command ()
1583 (let ((file-a (nth 0 command-line-args-left))
1584 (file-b (nth 1 command-line-args-left)))
1585 (setq command-line-args-left (nthcdr 2 command-line-args-left))
1586 (ediff-merge-files file-a file-b)))
1587
1588;;;###autoload
1589(defun ediff-merge-with-ancestor-command ()
1590 (let ((file-a (nth 0 command-line-args-left))
1591 (file-b (nth 1 command-line-args-left))
1592 (ancestor (nth 2 command-line-args-left)))
1593 (setq command-line-args-left (nthcdr 3 command-line-args-left))
1594 (ediff-merge-files-with-ancestor file-a file-b ancestor)))
1595
1596;;;###autoload
1597(defun ediff-directories-command ()
1598 (let ((file-a (nth 0 command-line-args-left))
1599 (file-b (nth 1 command-line-args-left))
1600 (regexp (nth 2 command-line-args-left)))
1601 (setq command-line-args-left (nthcdr 3 command-line-args-left))
1602 (ediff-directories file-a file-b regexp)))
1603
1604;;;###autoload
1605(defun ediff-directories3-command ()
1606 (let ((file-a (nth 0 command-line-args-left))
1607 (file-b (nth 1 command-line-args-left))
1608 (file-c (nth 2 command-line-args-left))
1609 (regexp (nth 3 command-line-args-left)))
1610 (setq command-line-args-left (nthcdr 4 command-line-args-left))
1611 (ediff-directories3 file-a file-b file-c regexp)))
1612
1613;;;###autoload
1614(defun ediff-merge-directories-command ()
1615 (let ((file-a (nth 0 command-line-args-left))
1616 (file-b (nth 1 command-line-args-left))
1617 (regexp (nth 2 command-line-args-left)))
1618 (setq command-line-args-left (nthcdr 3 command-line-args-left))
1619 (ediff-merge-directories file-a file-b regexp)))
1620
1621;;;###autoload
1622(defun ediff-merge-directories-with-ancestor-command ()
1623 (let ((file-a (nth 0 command-line-args-left))
1624 (file-b (nth 1 command-line-args-left))
1625 (ancestor (nth 2 command-line-args-left))
1626 (regexp (nth 3 command-line-args-left)))
1627 (setq command-line-args-left (nthcdr 4 command-line-args-left))
1628 (ediff-merge-directories-with-ancestor file-a file-b ancestor regexp)))
1629
1630
1631
1563(require 'ediff-util) 1632(require 'ediff-util)
1564 1633
1565(run-hooks 'ediff-load-hook) 1634(run-hooks 'ediff-load-hook)
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 2dc1e502171..b351d896911 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -55,6 +55,7 @@
55;; See `widget.el'. 55;; See `widget.el'.
56 56
57;;; Code: 57;;; Code:
58(require 'cl-lib)
58 59
59;;; Compatibility. 60;;; Compatibility.
60 61
@@ -221,7 +222,7 @@ minibuffer."
221 ((or widget-menu-minibuffer-flag 222 ((or widget-menu-minibuffer-flag
222 (> (length items) widget-menu-max-shortcuts)) 223 (> (length items) widget-menu-max-shortcuts))
223 ;; Read the choice of name from the minibuffer. 224 ;; Read the choice of name from the minibuffer.
224 (setq items (widget-remove-if 'stringp items)) 225 (setq items (cl-remove-if 'stringp items))
225 (let ((val (completing-read (concat title ": ") items nil t))) 226 (let ((val (completing-read (concat title ": ") items nil t)))
226 (if (stringp val) 227 (if (stringp val)
227 (let ((try (try-completion val items))) 228 (let ((try (try-completion val items)))
@@ -295,14 +296,6 @@ minibuffer."
295 (error "Canceled")) 296 (error "Canceled"))
296 value)))) 297 value))))
297 298
298(defun widget-remove-if (predicate list)
299 (let (result (tail list))
300 (while tail
301 (or (funcall predicate (car tail))
302 (setq result (cons (car tail) result)))
303 (setq tail (cdr tail)))
304 (nreverse result)))
305
306;;; Widget text specifications. 299;;; Widget text specifications.
307;; 300;;
308;; These functions are for specifying text properties. 301;; These functions are for specifying text properties.
diff --git a/lisp/window.el b/lisp/window.el
index fc50bbb0d49..a2acd2a81b0 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4347,6 +4347,9 @@ value can be also stored on disk and read back in a new session."
4347(defvar window-state-put-list nil 4347(defvar window-state-put-list nil
4348 "Helper variable for `window-state-put'.") 4348 "Helper variable for `window-state-put'.")
4349 4349
4350(defvar window-state-put-stale-windows nil
4351 "Helper variable for `window-state-put'.")
4352
4350(defun window--state-put-1 (state &optional window ignore totals) 4353(defun window--state-put-1 (state &optional window ignore totals)
4351 "Helper function for `window-state-put'." 4354 "Helper function for `window-state-put'."
4352 (let ((type (car state))) 4355 (let ((type (car state)))
@@ -4429,9 +4432,14 @@ value can be also stored on disk and read back in a new session."
4429 (set-window-parameter window (car parameter) (cdr parameter)))) 4432 (set-window-parameter window (car parameter) (cdr parameter))))
4430 ;; Process buffer related state. 4433 ;; Process buffer related state.
4431 (when state 4434 (when state
4432 ;; We don't want to raise an error here so we create a buffer if 4435 ;; We don't want to raise an error in case the buffer does not
4433 ;; there's none. 4436 ;; exist anymore, so we switch to a previous one and save the
4434 (set-window-buffer window (get-buffer-create (car state))) 4437 ;; window with the intention of deleting it later if possible.
4438 (let ((buffer (get-buffer (car state))))
4439 (if buffer
4440 (set-window-buffer window buffer)
4441 (switch-to-prev-buffer window)
4442 (push window window-state-put-stale-windows)))
4435 (with-current-buffer (window-buffer window) 4443 (with-current-buffer (window-buffer window)
4436 (set-window-hscroll window (cdr (assq 'hscroll state))) 4444 (set-window-hscroll window (cdr (assq 'hscroll state)))
4437 (apply 'set-window-fringes 4445 (apply 'set-window-fringes
@@ -4491,6 +4499,7 @@ Optional argument IGNORE non-nil means ignore minimum window
4491sizes and fixed size restrictions. IGNORE equal `safe' means 4499sizes and fixed size restrictions. IGNORE equal `safe' means
4492windows can get as small as `window-safe-min-height' and 4500windows can get as small as `window-safe-min-height' and
4493`window-safe-min-width'." 4501`window-safe-min-width'."
4502 (setq window-state-put-stale-windows nil)
4494 (setq window (window-normalize-window window t)) 4503 (setq window (window-normalize-window window t))
4495 (let* ((frame (window-frame window)) 4504 (let* ((frame (window-frame window))
4496 (head (car state)) 4505 (head (car state))
@@ -4539,6 +4548,10 @@ windows can get as small as `window-safe-min-height' and
4539 (set-window-buffer window (current-buffer)) 4548 (set-window-buffer window (current-buffer))
4540 (window--state-put-1 state window nil totals) 4549 (window--state-put-1 state window nil totals)
4541 (window--state-put-2 ignore)) 4550 (window--state-put-2 ignore))
4551 (while window-state-put-stale-windows
4552 (let ((window (pop window-state-put-stale-windows)))
4553 (when (eq (window-deletable-p window) t)
4554 (delete-window window))))
4542 (window--check frame)))) 4555 (window--check frame))))
4543 4556
4544(defun display-buffer-record-window (type window buffer) 4557(defun display-buffer-record-window (type window buffer)