commit f9cbe8ee63f911650dcd273cb980eed5b8f58396 (HEAD, refs/remotes/origin/master) Author: Sam Steingold Date: Sat Oct 15 23:27:46 2016 -0400 use full time objects (lists) instead of floats when possible * midnight.el (midnight-buffer-display-time): Remove (clean-buffer-list): Use float time only for time comparison diff --git a/lisp/midnight.el b/lisp/midnight.el index 878c5a7..814621f 100644 --- a/lisp/midnight.el +++ b/lisp/midnight.el @@ -60,13 +60,6 @@ the time when it is run.") (when (timerp midnight-timer) (cancel-timer midnight-timer)) (if midnight-mode (timer-activate midnight-timer))) -;;; time conversion - -(defun midnight-buffer-display-time (buffer) - "Return the time-stamp of BUFFER, or current buffer, as float." - (with-current-buffer buffer - (when buffer-display-time (float-time buffer-display-time)))) - ;;; clean-buffer-list stuff (defcustom clean-buffer-list-delay-general 3 @@ -167,25 +160,28 @@ the current date/time, buffer name, how many seconds ago it was displayed (can be nil if the buffer was never displayed) and its lifetime, i.e., its \"age\" when it will be purged." (interactive) - (let ((tm (float-time)) bts (ts (format-time-string "%Y-%m-%d %T")) + (let ((tm (current-time)) bts (ts (format-time-string "%Y-%m-%d %T")) delay cbld bn) (dolist (buf (buffer-list)) (when (buffer-live-p buf) - (setq bts (midnight-buffer-display-time buf) bn (buffer-name buf) - delay (if bts (- tm bts) 0) cbld (clean-buffer-list-delay bn)) - (message "[%s] `%s' [%s %d]" ts bn (if bts (round delay)) cbld) - (unless (or (cl-find bn clean-buffer-list-kill-never-regexps + (setq bts (with-current-buffer buf buffer-display-time) + bn (buffer-name buf) + delay (if bts (round (float-time (time-subtract tm bts))) 0) + cbld (clean-buffer-list-delay bn)) + (message "[%s] `%s' [%s %d]" ts bn delay cbld) + (unless (or (cl-find bn clean-buffer-list-kill-never-regexps :test (lambda (bn re) (if (functionp re) (funcall re bn) (string-match re bn)))) - (cl-find bn clean-buffer-list-kill-never-buffer-names + (cl-find bn clean-buffer-list-kill-never-buffer-names :test #'string-equal) - (get-buffer-process buf) - (and (buffer-file-name buf) (buffer-modified-p buf)) - (get-buffer-window buf 'visible) (< delay cbld)) - (message "[%s] killing `%s'" ts bn) - (kill-buffer buf)))))) + (get-buffer-process buf) + (and (buffer-file-name buf) (buffer-modified-p buf)) + (get-buffer-window buf 'visible) + (< delay cbld)) + (message "[%s] killing `%s'" ts bn) + (kill-buffer buf)))))) ;;; midnight hook commit cd726ef68ece4fff6772bd08c0051c294e925505 Author: Sam Steingold Date: Sat Oct 15 23:14:48 2016 -0400 Save and restore buffer-display-time * desktop.el (desktop-locals-to-save): Add `buffer-display-time' (desktop-read): Set `desktop-file-modtime' before loading the desktop file (desktop-create-buffer): Adjust `buffer-display-time' for the downtime diff --git a/lisp/desktop.el b/lisp/desktop.el index df4ff55..9fb8393 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el @@ -367,6 +367,7 @@ these won't be deleted." column-number-mode size-indication-mode buffer-file-coding-system + buffer-display-time indent-tabs-mode tab-width indicate-buffer-boundaries @@ -1233,8 +1234,8 @@ Using it may cause conflicts. Use it anyway? " owner))))) (memq 'desktop-auto-save-set-timer window-configuration-change-hook)) (desktop-auto-save-disable) ;; Evaluate desktop buffer and remember when it was modified. - (load (desktop-full-file-name) t t t) (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name)))) + (load (desktop-full-file-name) t t t) ;; If it wasn't already, mark it as in-use, to bother other ;; desktop instances. (unless (eq (emacs-pid) owner) @@ -1536,6 +1537,19 @@ and try to load that." ;; An entry of the form `symbol'. (make-local-variable this) (makunbound this))) + ;; adjust `buffer-display-time' for the downtime. e.g., + ;; * if `buffer-display-time' was 8:00 + ;; * and emacs stopped at `desktop-file-modtime' == 11:00 + ;; * and we are loading the desktop file at (current-time) 12:30, + ;; -> then we restore `buffer-display-time' as 9:30, + ;; for the sake of `clean-buffer-list': preserving the invariant + ;; "how much time the user spent in Emacs without looking at this buffer". + (setq buffer-display-time + (if buffer-display-time + (time-add buffer-display-time + (time-subtract (current-time) + desktop-file-modtime)) + (current-time))) (unless (< desktop-file-version 208) ; Don't misinterpret any old custom args (dolist (record compacted-vars) (let* commit cf566b46a6cf85c6d54d0b0db80e32ed6ae8d1ca Author: Philipp Stephani Date: Sat Oct 15 15:19:56 2016 +0200 Disable bracketed paste in a terminal in char mode In char mode, a terminal doesn't accept bracketed paste events, therefore we should disable them; see Bug#24639. To decouple the XTerm management from term.el, introduce a per-buffer setting to disable bracketed paste for that buffer. If bracketed paste is inhiited for at least one buffer in a terminal, it is disabled for the whole terminal. * term/xterm.el (xterm-inhibit-bracketed-paste-mode): New mode to inhibit XTerm bracketed paste per buffer. (xterm--buffer-terminals, xterm--update-bracketed-paste) (xterm--bracketed-paste-possible, xterm--is-xterm): New helper functions. (xterm--init-bracketed-paste-mode): Remove unused helper function. (terminal-init-xterm): Update bracketed paste status when initializing an XTerm and on window configuration change. * term.el (term-char-mode, term-line-mode): Inhibit XTerm bracketed paste in char mode. diff --git a/lisp/term.el b/lisp/term.el index 87f600c..1adeae2 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1243,6 +1243,11 @@ intervention from Emacs, except for the escape character (usually C-c)." (end-of-line) (term-send-input)) (setq term-input-sender save-input-sender)))) + + ;; Turn off XTerm bracketed paste (Bug#24639). + (when (fboundp 'xterm-inhibit-bracketed-paste-mode) + (xterm-inhibit-bracketed-paste-mode)) + (term-update-mode-line))) (defun term-line-mode () @@ -1252,6 +1257,8 @@ you type \\[term-send-input] which sends the current line to the inferior." (interactive) (when (term-in-char-mode) (use-local-map term-old-mode-map) + (when (fboundp 'xterm-inhibit-bracketed-paste-mode) + (xterm-inhibit-bracketed-paste-mode 0)) (term-update-mode-line))) (defun term-update-mode-line () diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index 01c0113..78646e4 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el @@ -765,6 +765,78 @@ We run the first FUNCTION whose STRING matches the input events." basemap (make-composed-keymap map (keymap-parent basemap)))) +(define-minor-mode xterm-inhibit-bracketed-paste-mode + "Toggle whether XTerm bracketed paste should be allowed in this bugger. +With a prefix argument ARG, forbid bracketed paste if ARG is +positive, and allow it otherwise. If called from Lisp, forbid +bracketed paste if ARG is omitted or nil, and toggle the state of +ARG is `toggle'. If XTerm bracketed paste is allowed (the +default), it will be used to paste text from an X selection upon +reception of the `xterm-paste' event. Otherwise the selection +will be inserted character by character, which is much slower. +Therefore, bracketed paste should only be disabled in buffers +that can't deal with the `xterm-paste' event, such as terminal +emulation buffers." + :group xterm + ;; Update the bracketed paste flag in all terminals that display the + ;; current buffer. + (mapc #'xterm--update-bracketed-paste (xterm--buffer-terminals))) + +(defun xterm--buffer-terminals (&optional buffer) + "Return all terminals that contain a window that displays BUFFER. +BUFFER defaults to the current buffer." + (cl-delete-duplicates + (cl-loop for window in (get-buffer-window-list buffer nil t) + for terminal = (frame-terminal (window-frame window)) + collect terminal) + :test 'eq)) + +(defun xterm--update-bracketed-paste (&optional terminal) + "Enable or disable bracketed paste for TERMINAL. +TERMINAL must be a live terminal; it defaults to the terminal +displaying the selected frame. If any buffer displayed on the +frames of TERMINAL inhibits bracketed paste by enabling +`xterm-inhibit-bracketed-paste-mode', disable bracketed paste for +TERMINAL. If there is no such buffer, enable bracketed paste." + (unless terminal (setq terminal (frame-terminal))) + (cl-check-type terminal terminal-live) + (when (xterm--is-xterm terminal) + (cl-symbol-macrolet + ((enabled-param (terminal-parameter terminal 'xterm--bracketed-paste)) + (set-strings-param (terminal-parameter terminal 'tty-mode-set-strings)) + (reset-strings-param + (terminal-parameter terminal 'tty-mode-reset-strings))) + (let ((is-enabled enabled-param) + (should-enable (xterm--bracketed-paste-possible terminal)) + (enable-seq "\e[?2004h") + (disable-seq "\e[?2004l")) + (cond + ;; Unconditionally send terminal sequences: terminals that + ;; don't support bracketed paste just ignore the sequences. + ((and (not is-enabled) should-enable) + (send-string-to-terminal enable-seq terminal) + (push disable-seq reset-strings-param) + (push enable-seq set-strings-param) + (setq enabled-param t)) + ((and is-enabled (not should-enable)) + (send-string-to-terminal disable-seq) + (cl-callf2 delete disable-seq reset-strings-param) + (cl-callf2 delete enable-seq set-strings-param) + (setq enabled-param nil))))))) + +(defun xterm--bracketed-paste-possible (terminal) + "Return non-nil if bracketed paste could be enabled on TERMINAL. +If any buffer displayed on the frames of TERMINAL inhibits +bracketed paste by enabling `xterm-inhibit-bracketed-paste-mode', +return nil. If there is no such buffer, return non-nil." + (cl-check-type terminal terminal-live) + (cl-loop for frame being the frames + if (eq (frame-terminal frame) terminal) + always (cl-loop + for window being the windows of frame + never (buffer-local-value 'xterm-inhibit-bracketed-paste-mode + (window-buffer window))))) + (defun terminal-init-xterm () "Terminal initialization function for xterm." ;; rxvt terminals sometimes set the TERM variable to "xterm", but @@ -802,9 +874,8 @@ We run the first FUNCTION whose STRING matches the input events." (when (memq 'setSelection xterm-extra-capabilities) (xterm--init-activate-set-selection))) - ;; Unconditionally enable bracketed paste mode: terminals that don't - ;; support it just ignore the sequence. - (xterm--init-bracketed-paste-mode) + (add-hook 'window-configuration-change-hook #'xterm--update-bracketed-paste) + (xterm--update-bracketed-paste) (run-hooks 'terminal-init-xterm-hook)) @@ -814,12 +885,6 @@ We run the first FUNCTION whose STRING matches the input events." (push "\e[>4m" (terminal-parameter nil 'tty-mode-reset-strings)) (push "\e[>4;1m" (terminal-parameter nil 'tty-mode-set-strings))) -(defun xterm--init-bracketed-paste-mode () - "Terminal initialization for bracketed paste mode." - (send-string-to-terminal "\e[?2004h") - (push "\e[?2004l" (terminal-parameter nil 'tty-mode-reset-strings)) - (push "\e[?2004h" (terminal-parameter nil 'tty-mode-set-strings))) - (defun xterm--init-activate-get-selection () "Terminal initialization for `gui-get-selection'." (set-terminal-parameter nil 'xterm--get-selection t)) @@ -1000,6 +1065,11 @@ versions of xterm." (set-terminal-parameter nil 'background-mode 'dark) t)) +(defun xterm--is-xterm (&optional terminal) + "Return non-nil if TERMINAL is an XTerm-like terminal. +TERMINAL defaults to the terminal of the selected frame." + (eq (terminal-parameter terminal 'terminal-initted) 'terminal-init-xterm)) + (provide 'xterm) ;Backward compatibility. (provide 'term/xterm) ;;; xterm.el ends here commit f68b463d1b05c7cd45b66a5cb0977c21016f5ea5 Author: Eli Zaretskii Date: Sat Oct 15 17:21:49 2016 +0300 ; * src/keyboard.c (make_lispy_event): Fix code formatting in last change. diff --git a/src/keyboard.c b/src/keyboard.c index 87a6851..bb411e7 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -5422,26 +5422,26 @@ make_lispy_event (struct input_event *event) /* Caps-lock shouldn't affect interpretation of key chords: Control+s should produce C-s whether caps-lock is on or not. And Control+Shift+s should produce C-S-s whether - caps-lock is on or not. */ + caps-lock is on or not. */ if (event->modifiers & ~shift_modifier) { - /* this is a key chord: some non-shift modifier is - depressed */ + /* This is a key chord: some non-shift modifier is + depressed. */ if (uppercasep (c) && !(event->modifiers & shift_modifier)) { /* Got a capital letter without a shift. The caps - lock is on. Un-capitalize the letter */ - c = downcase(c); + lock is on. Un-capitalize the letter. */ + c = downcase (c); } else if (lowercasep (c) && (event->modifiers & shift_modifier)) { /* Got a lower-case letter even though shift is depressed. The caps lock is on. Capitalize the - letter */ - c = upcase(c); + letter. */ + c = upcase (c); } } commit a38096f8e2978a14f3bc8fa0dc3e0c9d0f753c3c Author: Dima Kogan Date: Sat Oct 15 17:18:40 2016 +0300 Undo the effect of CapsLock when other modifiers are present * src/keyboard.c (make_lispy_event): Effectively undo the effect of CapsLock if any modifiers other than Shift are present in a key. (Bug#24456) diff --git a/src/keyboard.c b/src/keyboard.c index ca40c6e..87a6851 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -5417,6 +5417,36 @@ make_lispy_event (struct input_event *event) { c &= 0377; eassert (c == event->code); + } + + /* Caps-lock shouldn't affect interpretation of key chords: + Control+s should produce C-s whether caps-lock is on or + not. And Control+Shift+s should produce C-S-s whether + caps-lock is on or not. */ + if (event->modifiers & ~shift_modifier) + { + /* this is a key chord: some non-shift modifier is + depressed */ + + if (uppercasep (c) && + !(event->modifiers & shift_modifier)) + { + /* Got a capital letter without a shift. The caps + lock is on. Un-capitalize the letter */ + c = downcase(c); + } + else if (lowercasep (c) && + (event->modifiers & shift_modifier)) + { + /* Got a lower-case letter even though shift is + depressed. The caps lock is on. Capitalize the + letter */ + c = upcase(c); + } + } + + if (event->kind == ASCII_KEYSTROKE_EVENT) + { /* Turn ASCII characters into control characters when proper. */ if (event->modifiers & ctrl_modifier) commit 07c0db4344072895726101e39eb92a26e1d2d3d1 Author: Simen Heggestøyl Date: Sat Oct 15 11:23:26 2016 +0200 Add tests for foreign completions in CSS mode * test/lisp/textmodes/css-mode-tests.el (css-test-foreign-completions): New test for `css--foreign-completions'. (css-test-complete-selector-tag): Rename test. (css-test-complete-selector-class): New test testing completion of class names in selectors. (css-test-complete-selector-id): New test testing completion of IDs in selectors. diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el index d281787..f92ac11 100644 --- a/test/lisp/textmodes/css-mode-tests.el +++ b/test/lisp/textmodes/css-mode-tests.el @@ -161,7 +161,23 @@ (should (member "filter" completions)) (should-not (member "position" completions))))) -(ert-deftest css-test-complete-selector () +(ert-deftest css-test-foreign-completions () + (let ((other-buffer-1 (generate-new-buffer "1")) + (other-buffer-2 (generate-new-buffer "2"))) + (with-current-buffer other-buffer-1 + (setq-local css-class-list-function (lambda () '("foo" "bar")))) + (with-current-buffer other-buffer-2 + (setq-local css-class-list-function (lambda () '("bar" "baz")))) + (let ((completions + (css--foreign-completions 'css-class-list-function))) + ;; Completions from `other-buffer-1' and `other-buffer-2' should + ;; be merged. + (should (equal (seq-sort #'string-lessp completions) + '("bar" "baz" "foo")))) + (kill-buffer other-buffer-1) + (kill-buffer other-buffer-2))) + +(ert-deftest css-test-complete-selector-tag () (with-temp-buffer (css-mode) (insert "b") @@ -169,6 +185,24 @@ (should (member "body" completions)) (should-not (member "article" completions))))) +(ert-deftest css-test-complete-selector-class () + (with-temp-buffer + (setq-local css-class-list-function (lambda () '("foo" "bar"))) + (with-temp-buffer + (css-mode) + (insert ".f") + (let ((completions (css-mode-tests--completions))) + (should (equal completions '("foo"))))))) + +(ert-deftest css-test-complete-selector-id () + (with-temp-buffer + (setq-local css-id-list-function (lambda () '("foo" "bar"))) + (with-temp-buffer + (css-mode) + (insert "#b") + (let ((completions (css-mode-tests--completions))) + (should (equal completions '("bar"))))))) + (ert-deftest css-test-complete-nested-selector () (with-temp-buffer (css-mode)