commit 5f22c090b1ae87b516b132b36a5908a5e18c2d11 (HEAD, refs/remotes/origin/master) Author: Visuwesh Date: Thu Oct 17 09:40:34 2024 +0530 Make djvused emit UTF-8 encoded text * lisp/doc-view.el (doc-view--djvu-outline): Pass -u to djvused to make it emit UTF-8 encoded text rather than using octal escapes for non-ASCII string. (bug#73846) diff --git a/lisp/doc-view.el b/lisp/doc-view.el index bbfbbdec925..4d7d36c8a16 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -2026,13 +2026,16 @@ name. For the format, see `doc-view--pdf-outline'." (unless file-name (setq file-name (buffer-file-name))) (with-temp-buffer - (call-process doc-view-djvused-program nil (current-buffer) nil - "-e" "print-outline" file-name) - (goto-char (point-min)) - (when (eobp) - (setq doc-view--outline 'unavailable) - (imenu-unavailable-error "Unable to create imenu index using `djvused'")) - (nreverse (doc-view--parse-djvu-outline (read (current-buffer)))))) + (let ((coding-system-for-read 'utf-8)) + ;; Pass "-u" to make `djvused' emit UTF-8 encoded text to avoid + ;; unescaping octal escapes for non-ASCII text. + (call-process doc-view-djvused-program nil (current-buffer) nil + "-u" "-e" "print-outline" file-name) + (goto-char (point-min)) + (when (eobp) + (setq doc-view--outline 'unavailable) + (imenu-unavailable-error "Unable to create imenu index using `djvused'")) + (nreverse (doc-view--parse-djvu-outline (read (current-buffer))))))) (defun doc-view--parse-djvu-outline (bookmark &optional level) "Return a list describing the djvu outline from BOOKMARK. commit 09e586b38352e1661ef96a47b89d835f0ff30bd2 Author: Eli Zaretskii Date: Fri Oct 18 08:52:02 2024 +0300 ; Fix documentation of recent changes in mpc.el * etc/NEWS: Fix entry for 'mpc-notifications'. * lisp/mpc.el (mpc-status-callbacks, mpc-format) (mpc-cover-image-find, mpc-cover-image-p, mpc-notifications) (mpc-notifications-title, mpc-notifications-body): Doc fixes. diff --git a/etc/NEWS b/etc/NEWS index 3d3cb0e5fc7..10d86173235 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -562,9 +562,11 @@ or behaves like 'widen' if not in a fold. --- *** New user option 'mpc-notifications'. -When non-nil MPC displays a desktop notification when the song changes. -The notification’s title and body can be customized with -'mpc-notifications-title' and 'mpc-notifications-body'. +When non-nil, MPC (the Emacs front-end to Music Player Daemon) displays +a desktop notification when the song changes, using +'notifications-notify'. The notification's title and body can be +customized using the new user options 'mpc-notifications-title' and +'mpc-notifications-body'. * New Modes and Packages in Emacs 31.1 diff --git a/lisp/mpc.el b/lisp/mpc.el index 9c0bbaaa0f2..4cc3d96d898 100644 --- a/lisp/mpc.el +++ b/lisp/mpc.el @@ -469,8 +469,8 @@ which will be concatenated with proper quoting before passing them to MPD." (t . mpc-current-refresh)) "Alist associating properties to the functions that care about them. Each entry has the form (PROP . FUN) to call FUN (without arguments) -whenever property PROP changes. PROP can be t to mean -to call FUN for any change whatsoever.") +whenever property PROP changes. PROP can be t, which means to call +FUN for any change whatsoever.") (defun mpc--status-callback () (let ((old-status mpc-status)) @@ -998,11 +998,11 @@ If PLAYLIST is t or nil or missing, use the main playlist." FORMAT-SPEC is a string that includes elements of the form '%-WIDTH{NAME-POST}' that get expanded to the value of -property NAME, +property NAME. The first '-', WIDTH, and -POST are optional. % followed by the optional '-' means to right align the output. -WIDTH limits the output to the specified number of characters by replacing -any further output with a horizontal ellipsis. +WIDTH limits the output to the specified number of characters by +replacing any further output with a horizontal ellipsis. The optional -POST means to use the empty string if NAME is absent or else use the concatenation of the content of NAME with the string POST." @@ -1132,7 +1132,7 @@ string POST." (put-text-property start (point) 'mpc--uptodate-p pred))) (defun mpc-cover-image-find (file) - "Find cover image for FILE." + "Find cover image for FILE in suitable MPC directory." (when-let* ((default-directory mpc-mpd-music-directory) (dir (mpc-file-local-copy (file-name-directory file))) (files (directory-files dir)) @@ -1140,7 +1140,7 @@ string POST." (expand-file-name cover dir))) (defun mpc-cover-image-p (file) - "Check if FILE is a cover image." + "Check if FILE is a cover image suitable for MPC." (let ((covers '(".folder.png" "folder.png" "cover.jpg" "folder.jpg"))) (or (member-ignore-case file covers) (and mpc-cover-image-re (string-match-p mpc-cover-image-re file))))) @@ -2794,7 +2794,7 @@ If stopped, start playback." (declare-function notifications-notify "notifications") (defcustom mpc-notifications nil - "Non-nil means to display notifications when the song changes." + "Non-nil means MPC should display notifications when the song changes." :version "31.1" :type 'boolean) @@ -2802,8 +2802,8 @@ If stopped, start playback." '("%{Title}" "Unknown Title") "List of FORMAT-SPECs used in the notification title. -The first element that expands to a non-empty string is used. -See `mpc-format' for the definition of FORMAT-SPEC." +The first element in the list that expands to a non-empty string +will be used. See `mpc-format' for the definition of FORMAT-SPEC." :version "31.1" :type '(repeat string)) @@ -2811,8 +2811,8 @@ See `mpc-format' for the definition of FORMAT-SPEC." '("%{Artist}" "%{AlbumArtist}" "Unknown Artist") "List of FORMAT-SPEC used in the notification body. -The first element that returns a non-emtpy string is used. -See `mpc-format' for the definition of FORMAT-SPEC." +The first element in the list that expands to a non-empty string +will be used. See `mpc-format' for the definition of FORMAT-SPEC." :version "31.1" :type '(repeat string)) commit d6ea735af8ed5e74f1cbc6d3e8285c6c7700239e Author: Sean Whitton Date: Fri Oct 18 12:33:20 2024 +0800 ; * etc/NEWS: Shorten find-function-mode entry back to single line. diff --git a/etc/NEWS b/etc/NEWS index a8ece5c3dc9..3d3cb0e5fc7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -62,8 +62,7 @@ The 'find-function', 'find-library', 'find-face-definition', and usual minibuffer history commands. Each command has a separate history. --- -** New minor mode 'find-function-mode'. -It replaces the old 'find-function-setup-keys'. +** New minor mode 'find-function-mode' replaces 'find-function-setup-keys'. ** Minibuffer and Completions commit 83e3ed651dca46214855552aa062cfbde019b04a Author: Jim Porter Date: Thu Oct 17 14:30:31 2024 -0700 ; Mark interactive Eshell output as such after inserting into the buffer This avoids adding the "output" text properties to strings that may live past the call to 'eshell-interactive-filter'. * lisp/eshell/esh-mode.el (eshell-interactive-output-filter): New function... (eshell-interactive-print): ... call it. (eshell-interactive-filter): Update docstring. * lisp/eshell/esh-proc.el (eshell-interactive-process-filter) (eshell-sentinel): Call 'eshell-interactive-output-filter'. diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index 34ce82cfbc4..ead5a20bec8 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -530,8 +530,7 @@ Putting this function on `eshell-pre-command-hook' will mimic Plan 9's (defun eshell-interactive-print (string) "Print STRING to the eshell display buffer." (when string - (eshell--mark-as-output 0 (length string) string) - (eshell-interactive-filter nil string))) + (eshell-interactive-output-filter nil string))) (defsubst eshell-begin-on-new-line () "This function outputs a newline if not at beginning of line." @@ -685,7 +684,7 @@ newline." (custom-add-option 'eshell-input-filter-functions 'eshell-kill-new) (defun eshell-interactive-filter (buffer string) - "Send output (STRING) to the interactive display, using BUFFER. + "Send STRING to the interactive display, using BUFFER. This is done after all necessary filtering has been done." (unless buffer (setq buffer (current-buffer))) @@ -725,6 +724,17 @@ This is done after all necessary filtering has been done." (goto-char opoint) (eshell-run-output-filters)))))) +(defun eshell-interactive-output-filter (buffer string) + "Send STRING to the interactive display as command output, using BUFFER. +This is like `eshell-interactive-filter', but marks the inserted string +as command output (see `eshell--mark-as-output')." + (let ((eshell-output-filter-functions + (cons (lambda () + (eshell--mark-as-output eshell-last-output-start + eshell-last-output-end)) + eshell-output-filter-functions))) + (eshell-interactive-filter buffer string))) + (defun eshell-run-output-filters () "Run the `eshell-output-filter-functions' on the current output." (save-current-buffer diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index b579a93e14c..87c95d39603 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el @@ -128,7 +128,7 @@ To add or remove elements of this list, see (declare-function eshell-reset "esh-mode" (&optional no-hooks)) (declare-function eshell-send-eof-to-process "esh-mode") -(declare-function eshell-interactive-filter "esh-mode" (buffer string)) +(declare-function eshell-interactive-output-filter "esh-mode" (buffer string)) (declare-function eshell-set-exit-info "esh-cmd" (status result)) (declare-function eshell-tail-process "esh-cmd") @@ -483,10 +483,9 @@ This is done after all necessary filtering has been done." (when string (eshell-debug-command 'process "received output from process `%s'\n\n%s" process string) - (eshell--mark-as-output 0 (length string) string) - (eshell-interactive-filter (if process (process-buffer process) - (current-buffer)) - string))) + (eshell-interactive-output-filter (if process (process-buffer process) + (current-buffer)) + string))) (define-obsolete-function-alias 'eshell-output-filter #'eshell-interactive-process-filter "30.1") @@ -559,8 +558,7 @@ PROC is the process that's exiting. STRING is the exit message." (eshell-interactive-output-p eshell-error-handle handles) (not (string-match "^\\(finished\\|exited\\)" string))) - (eshell--mark-as-output 0 (length string) string) - (eshell-interactive-filter (process-buffer proc) string)) + (eshell-interactive-output-filter (process-buffer proc) string)) (process-put proc :eshell-pending nil) ;; If we're in the middle of handling output from this ;; process then schedule the EOF for later. commit f994154d0895b3bbd4a763e379a90328b5e3d87d Author: Stefan Monnier Date: Thu Oct 17 12:54:04 2024 -0400 * lisp/emacs-lisp/track-changes.el (track-changes--backtrace): Fix prefix diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el index 1b0f64f544d..7d1c928c92a 100644 --- a/lisp/emacs-lisp/track-changes.el +++ b/lisp/emacs-lisp/track-changes.el @@ -395,7 +395,7 @@ returned to a consistent state." ;;;; Auxiliary functions. -(defun track-change--backtrace (n &optional base) +(defun track-changes--backtrace (n &optional base) (let ((frames nil)) (catch 'done (mapbacktrace (lambda (&rest frame) @@ -403,7 +403,7 @@ returned to a consistent state." (push frame frames) (push '... frames) (throw 'done nil))) - (or base #'track-change--backtrace))) + (or base #'track-changes--backtrace))) (nreverse frames))) (defun track-changes--trace () @@ -415,7 +415,7 @@ returned to a consistent state." (setq track-changes--trace (make-ring 10))) (ring-insert track-changes--trace (cons (buffer-name) - (track-change--backtrace + (track-changes--backtrace 10 #'track-changes--trace))))) (defun track-changes--clean-state () @@ -487,7 +487,7 @@ backtraces have the deepest frame first.") (warn "Missing/incorrect calls to `before/after-change-functions'!! Details logged to `track-changes--error-log'") (push (vector (buffer-name) info - (track-change--backtrace + (track-changes--backtrace 50 #'track-changes--recover-from-error) (let ((rk (recent-keys 'include-cmds))) (if (< (length rk) 20) rk (substring rk -20))) commit 4690f2f44d38d64d8ebfea98c085844a5723df0f Author: Stefan Monnier Date: Thu Oct 17 12:38:18 2024 -0400 mpc.el: Misc tweaks. * lisp/mpc.el: Require `cl-lib` at run-time. Don't require `subr-x` any more. (mpc-status-callbacks): Improve docstring. (mpc-cover-image-find): Avoid `and-let*`. (mpc-cover-image-p): Use `member-ignore-case` to recover the behavior before last patch. (mpc-cover-image-find, mpc-cover-image-p): Move to later in the file to avoid compiler warning. (mpc-format, mpc-notifications-title, mpc-notifications-body): Tweak docstring. (mpc--notifications-format): Create only one temp buffer and use the faster `cl-some` since we know the arg is a list. (mpc-notifications-notify): Prefer `when-let*` since all the other `*-let` we use are also of the `let*`family. diff --git a/lisp/mpc.el b/lisp/mpc.el index a4b576cbd1b..9c0bbaaa0f2 100644 --- a/lisp/mpc.el +++ b/lisp/mpc.el @@ -91,9 +91,7 @@ ;; UI-commands : mpc- ;; internal : mpc-- -(eval-when-compile - (require 'cl-lib) - (require 'subr-x)) +(require 'cl-lib) (require 'notifications) @@ -470,7 +468,8 @@ which will be concatenated with proper quoting before passing them to MPD." (updating_db . mpc--status-timers-refresh) (t . mpc-current-refresh)) "Alist associating properties to the functions that care about them. -Each entry has the form (PROP . FUN) where PROP can be t to mean +Each entry has the form (PROP . FUN) to call FUN (without arguments) +whenever property PROP changes. PROP can be t to mean to call FUN for any change whatsoever.") (defun mpc--status-callback () @@ -961,20 +960,6 @@ If PLAYLIST is t or nil or missing, use the main playlist." ;; aux) )) -(defun mpc-cover-image-find (file) - "Find cover image for FILE." - (and-let* ((default-directory mpc-mpd-music-directory) - (dir (mpc-file-local-copy (file-name-directory file))) - (files (directory-files dir)) - (cover (seq-find #'mpc-cover-image-p files)) - ((expand-file-name cover dir))))) - -(defun mpc-cover-image-p (file) - "Check if FILE is a cover image." - (let ((covers '(".folder.png" "folder.png" "cover.jpg" "folder.jpg"))) - (or (seq-find (lambda (cover) (string= file cover)) covers) - (and mpc-cover-image-re (string-match-p mpc-cover-image-re file))))) - ;;; Formatter ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defcustom mpc-cover-image-re nil ; (rx (or ".jpg" ".jpeg" ".png") string-end) @@ -1011,11 +996,14 @@ If PLAYLIST is t or nil or missing, use the main playlist." (defun mpc-format (format-spec info &optional hscroll) "Format the INFO according to FORMAT-SPEC, inserting the result at point. -FORMAT-SPEC is a string of the format '%-WIDTH{NAME-POST}' where the first -'-', WIDTH and -POST are optional. % followed by the optional '-' means -to right align the output. WIDTH limits the output to the specified -number of characters by replacing any further output with a horizontal -ellipsis. The optional -POST means to use the empty string if NAME is +FORMAT-SPEC is a string that includes elements of the form +'%-WIDTH{NAME-POST}' that get expanded to the value of +property NAME, +The first '-', WIDTH, and -POST are optional. +% followed by the optional '-' means to right align the output. +WIDTH limits the output to the specified number of characters by replacing +any further output with a horizontal ellipsis. +The optional -POST means to use the empty string if NAME is absent or else use the concatenation of the content of NAME with the string POST." (let* ((pos 0) @@ -1143,6 +1131,20 @@ string POST." (insert (substring format-spec pos)) (put-text-property start (point) 'mpc--uptodate-p pred))) +(defun mpc-cover-image-find (file) + "Find cover image for FILE." + (when-let* ((default-directory mpc-mpd-music-directory) + (dir (mpc-file-local-copy (file-name-directory file))) + (files (directory-files dir)) + (cover (seq-find #'mpc-cover-image-p files))) + (expand-file-name cover dir))) + +(defun mpc-cover-image-p (file) + "Check if FILE is a cover image." + (let ((covers '(".folder.png" "folder.png" "cover.jpg" "folder.jpg"))) + (or (member-ignore-case file covers) + (and mpc-cover-image-re (string-match-p mpc-cover-image-re file))))) + ;;; The actual UI code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar-keymap mpc-mode-map @@ -2798,21 +2800,19 @@ If stopped, start playback." (defcustom mpc-notifications-title '("%{Title}" "Unknown Title") - "FORMAT-SPEC used in the notification title. + "List of FORMAT-SPECs used in the notification title. -The first element that returns a non-emtpy string is used. The last -element is a plain string to use as fallback for when none of the tags -are found. See `mpc-format' for the definition of FORMAT-SPEC." +The first element that expands to a non-empty string is used. +See `mpc-format' for the definition of FORMAT-SPEC." :version "31.1" :type '(repeat string)) (defcustom mpc-notifications-body '("%{Artist}" "%{AlbumArtist}" "Unknown Artist") - "FORMAT-SPEC used in the notification body. + "List of FORMAT-SPEC used in the notification body. -The first element that returns a non-emtpy string is used. The last -element is a plain string to use as fallback for when none of the tags -are found. See `mpc-format' for the definition of FORMAT-SPEC." +The first element that returns a non-emtpy string is used. +See `mpc-format' for the definition of FORMAT-SPEC." :version "31.1" :type '(repeat string)) @@ -2820,32 +2820,29 @@ are found. See `mpc-format' for the definition of FORMAT-SPEC." (defun mpc--notifications-format (format-specs) "Use FORMAT-SPECS to get string for use in notification." - (seq-some - (lambda (spec) - (let ((text (with-temp-buffer - (mpc-format spec mpc-status) - (buffer-string)))) - (if (string= "" text) nil text))) - format-specs)) + (with-temp-buffer + (cl-some + (lambda (spec) + (mpc-format spec mpc-status) + (if (< (point-min) (point-max)) + (buffer-string))) + format-specs))) (defun mpc-notifications-notify () "Display a notification with information about the current song." - (when-let ((mpc-notifications) - ((notifications-get-server-information)) - ((string= "play" (alist-get 'state mpc-status))) - (title (mpc--notifications-format mpc-notifications-title)) - (body (mpc--notifications-format mpc-notifications-body)) - (icon (or (mpc-cover-image-find (alist-get 'file mpc-status)) - notifications-application-icon))) + (when-let* ((mpc-notifications) + ((notifications-get-server-information)) + ((string= "play" (alist-get 'state mpc-status))) + (title (mpc--notifications-format mpc-notifications-title)) + (body (mpc--notifications-format mpc-notifications-body)) + (icon (or (mpc-cover-image-find (alist-get 'file mpc-status)) + notifications-application-icon))) (setq mpc--notifications-id (notifications-notify :title title :body body :app-icon icon :replaces-id mpc--notifications-id)))) - - - ;;; Toplevel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defcustom mpc-frame-alist '((name . "MPC") (tool-bar-lines . 1) commit 49084bad7990a614bdd3ea7a24ebab0fc89627e3 Author: john muhl Date: Sun Sep 15 19:52:25 2024 -0500 Add notifications support to 'mpc' (Bug#73538) * lisp/mpc.el (mpc-notifications, mpc-notifications-title) (mpc-notifications-body): New option. (mpc--notifications-id): New variable. (mpc-notifications-notify, mpc-cover-image-find) (mpc-cover-image-p, mpc--notifications-format): New function. (mpc-format): Use 'mpc-cover-find' and expand docstring to include details about the FORMAT-SPEC. (mpc-status-callbacks): Add file callback for notifications. diff --git a/etc/NEWS b/etc/NEWS index f9ba659ed86..a8ece5c3dc9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -559,6 +559,14 @@ The hardcoded '^' shortcut gets you back to the previous menu. This command widens the view to the current fold level when in a fold, or behaves like 'widen' if not in a fold. +** MPC + +--- +*** New user option 'mpc-notifications'. +When non-nil MPC displays a desktop notification when the song changes. +The notification’s title and body can be customized with +'mpc-notifications-title' and 'mpc-notifications-body'. + * New Modes and Packages in Emacs 31.1 diff --git a/lisp/mpc.el b/lisp/mpc.el index 768c70c2e3a..a4b576cbd1b 100644 --- a/lisp/mpc.el +++ b/lisp/mpc.el @@ -95,6 +95,8 @@ (require 'cl-lib) (require 'subr-x)) +(require 'notifications) + (defgroup mpc () "Client for the Music Player Daemon (mpd)." :prefix "mpc-" @@ -460,6 +462,7 @@ which will be concatenated with proper quoting before passing them to MPD." (state . mpc--faster-toggle-refresh) ;Only ffwd/rewind while play/pause. (volume . mpc-volume-refresh) (file . mpc-songpointer-refresh) + (file . mpc-notifications-notify) ;; The song pointer may need updating even if the file doesn't change, ;; if the same song appears multiple times in a row. (song . mpc-songpointer-refresh) @@ -958,6 +961,20 @@ If PLAYLIST is t or nil or missing, use the main playlist." ;; aux) )) +(defun mpc-cover-image-find (file) + "Find cover image for FILE." + (and-let* ((default-directory mpc-mpd-music-directory) + (dir (mpc-file-local-copy (file-name-directory file))) + (files (directory-files dir)) + (cover (seq-find #'mpc-cover-image-p files)) + ((expand-file-name cover dir))))) + +(defun mpc-cover-image-p (file) + "Check if FILE is a cover image." + (let ((covers '(".folder.png" "folder.png" "cover.jpg" "folder.jpg"))) + (or (seq-find (lambda (cover) (string= file cover)) covers) + (and mpc-cover-image-re (string-match-p mpc-cover-image-re file))))) + ;;; Formatter ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defcustom mpc-cover-image-re nil ; (rx (or ".jpg" ".jpeg" ".png") string-end) @@ -992,7 +1009,15 @@ If PLAYLIST is t or nil or missing, use the main playlist." (push file mpc-tempfiles)) (defun mpc-format (format-spec info &optional hscroll) - "Format the INFO according to FORMAT-SPEC, inserting the result at point." + "Format the INFO according to FORMAT-SPEC, inserting the result at point. + +FORMAT-SPEC is a string of the format '%-WIDTH{NAME-POST}' where the first +'-', WIDTH and -POST are optional. % followed by the optional '-' means +to right align the output. WIDTH limits the output to the specified +number of characters by replacing any further output with a horizontal +ellipsis. The optional -POST means to use the empty string if NAME is +absent or else use the concatenation of the content of NAME with the +string POST." (let* ((pos 0) (start (point)) (col (if hscroll (- hscroll) 0)) @@ -1026,7 +1051,8 @@ If PLAYLIST is t or nil or missing, use the main playlist." (substring time (match-end 0)) time))))) ('Cover - (let ((dir (file-name-directory (cdr (assq 'file info))))) + (let* ((file (alist-get 'file info)) + (dir (file-name-directory file))) ;; (debug) (setq pred ;; We want the closure to capture the current @@ -1037,12 +1063,7 @@ If PLAYLIST is t or nil or missing, use the main playlist." (and (funcall oldpred info) (equal dir (file-name-directory (cdr (assq 'file info)))))))) - (if-let* ((covers '(".folder.png" "folder.png" "cover.jpg" "folder.jpg")) - (cover (cl-loop for file in (directory-files (mpc-file-local-copy dir)) - if (or (member (downcase file) covers) - (and mpc-cover-image-re - (string-match mpc-cover-image-re file))) - return (concat dir file))) + (if-let* ((cover (mpc-cover-image-find file)) (file (with-demoted-errors "MPC: %s" (mpc-file-local-copy cover)))) (let (image) @@ -2766,6 +2787,65 @@ If stopped, start playback." (t (error "Unsupported drag'n'drop gesture")))))) +;;; Notifications ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(declare-function notifications-notify "notifications") + +(defcustom mpc-notifications nil + "Non-nil means to display notifications when the song changes." + :version "31.1" + :type 'boolean) + +(defcustom mpc-notifications-title + '("%{Title}" "Unknown Title") + "FORMAT-SPEC used in the notification title. + +The first element that returns a non-emtpy string is used. The last +element is a plain string to use as fallback for when none of the tags +are found. See `mpc-format' for the definition of FORMAT-SPEC." + :version "31.1" + :type '(repeat string)) + +(defcustom mpc-notifications-body + '("%{Artist}" "%{AlbumArtist}" "Unknown Artist") + "FORMAT-SPEC used in the notification body. + +The first element that returns a non-emtpy string is used. The last +element is a plain string to use as fallback for when none of the tags +are found. See `mpc-format' for the definition of FORMAT-SPEC." + :version "31.1" + :type '(repeat string)) + +(defvar mpc--notifications-id nil) + +(defun mpc--notifications-format (format-specs) + "Use FORMAT-SPECS to get string for use in notification." + (seq-some + (lambda (spec) + (let ((text (with-temp-buffer + (mpc-format spec mpc-status) + (buffer-string)))) + (if (string= "" text) nil text))) + format-specs)) + +(defun mpc-notifications-notify () + "Display a notification with information about the current song." + (when-let ((mpc-notifications) + ((notifications-get-server-information)) + ((string= "play" (alist-get 'state mpc-status))) + (title (mpc--notifications-format mpc-notifications-title)) + (body (mpc--notifications-format mpc-notifications-body)) + (icon (or (mpc-cover-image-find (alist-get 'file mpc-status)) + notifications-application-icon))) + (setq mpc--notifications-id + (notifications-notify :title title + :body body + :app-icon icon + :replaces-id mpc--notifications-id)))) + + + + ;;; Toplevel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defcustom mpc-frame-alist '((name . "MPC") (tool-bar-lines . 1) commit 38071e39892fe0270f91746bd5f55c056cb00921 Author: Sean Whitton Date: Thu Oct 17 21:14:45 2024 +0800 ; * lisp/vc/vc.el: Drop some old notes Firstly, we are unlikely to do any unifying, because both amend capabilities have been around for a long time now and we don't want to break people's usage. Secondly, there is now a plan for dealing with dangerous git operations described in bug#64055. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 5d7ebc05d4c..9fb1fc6c4a4 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -704,22 +704,6 @@ ;; ;; - Add the ability to list tags and branches. ;; -;;;; Unify two different versions of the amend capability -;; -;; - Some back ends (SCCS/RCS/SVN/SRC), have an amend capability that can -;; be invoked from log-view. -;; -;; - The git backend supports amending, but in a different -;; way (press `C-c C-e' in log-edit buffer, when making a new commit). -;; -;; - Doing message editing in log-view might be a natural way to go -;; about it, but editing any but the last commit (and even it, if it's -;; been pushed) is a dangerous operation in Git, which we shouldn't make -;; too easy for users to perform. -;; -;; There should be a check that the given comment is not reachable -;; from any of the "remote" refs? -;; ;;;; Other ;; ;; - asynchronous checkin and commit, so you can keep working in other commit 8d7d9dd42a6c2bf1f941108148d9df91bce857fa Author: Sean Whitton Date: Thu Oct 17 21:06:58 2024 +0800 log-view-modify-change-comment: Prepend Summary header * lisp/vc/log-view.el (log-edit): Require. (log-view-modify-change-comment): When log-edit-hook would insert an empty Summary header, prepend one to the old comment. diff --git a/lisp/vc/log-view.el b/lisp/vc/log-view.el index 0533af62343..647a7dc569f 100644 --- a/lisp/vc/log-view.el +++ b/lisp/vc/log-view.el @@ -111,6 +111,7 @@ (require 'pcvs-util) (require 'easy-mmode) +(require 'log-edit) (autoload 'vc-find-revision "vc") (autoload 'vc-diff-internal "vc") @@ -553,6 +554,17 @@ If called interactively, visit the version at point." (vc-call-backend log-view-vc-backend 'get-change-comment files rev) (vc-not-supported (log-view-extract-comment))))) + (when (memq 'log-edit-insert-message-template log-edit-hook) + (let* ((first-newline (string-match "\n" comment)) + (summary (substring comment 0 first-newline)) + (rest (and first-newline + (substring comment (1+ first-newline))))) + (setq comment + ;; As we are part of the VC subsystem I think we are + ;; entitled to call a \\`log-edit--' function. + ;; --spwhitton + (concat (log-edit--make-header-line "Summary" summary) + (if (length> rest 0) rest "\n"))))) (vc-modify-change-comment files rev comment))) (defun log-view-annotate-version (pos) commit 01c8f31a54df511913ad88cb6138a01390faafbe Author: Sean Whitton Date: Thu Oct 17 21:04:38 2024 +0800 New get-change-comment VC backend action This gets us closer to using log-view-modify-change-comment with modern VCS. What remains is implementing the modify-change-comment backend action for those VCS. * lisp/vc/vc.el: New get-change-comment backend action. (vc-modify-change-comment): Pass the backend to vc-start-logentry. * lisp/vc/log-view.el (log-view-extract-comment): Use new get-change-comment action. * lisp/vc/vc-git.el (vc-git-get-change-comment): Factor out of vc-git-log-edit-toggle-amend. diff --git a/lisp/vc/log-view.el b/lisp/vc/log-view.el index e9e6602e414..0533af62343 100644 --- a/lisp/vc/log-view.el +++ b/lisp/vc/log-view.el @@ -543,11 +543,17 @@ If called interactively, visit the version at point." (defun log-view-modify-change-comment () "Edit the change comment displayed at point." (interactive) - (vc-modify-change-comment (list (if log-view-per-file-logs - (log-view-current-file) - (car log-view-vc-fileset))) - (log-view-current-tag) - (log-view-extract-comment))) + (let* ((files (list (if log-view-per-file-logs + (log-view-current-file) + (car log-view-vc-fileset)))) + (rev (log-view-current-tag)) + ;; `log-view-extract-comment' is the legacy code for this; the + ;; `get-change-comment' backend action is the new way to do it. + (comment (condition-case _ + (vc-call-backend log-view-vc-backend + 'get-change-comment files rev) + (vc-not-supported (log-view-extract-comment))))) + (vc-modify-change-comment files rev comment))) (defun log-view-annotate-version (pos) "Annotate the version at POS. diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 5a7ffeffc9d..f77bf0cc5ff 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -67,6 +67,7 @@ ;; - merge-news (file) see `merge-file' ;; - mark-resolved (files) OK ;; - steal-lock (file &optional revision) NOT NEEDED +;; - get-change-comment (files rev) OK ;; HISTORY FUNCTIONS ;; * print-log (files buffer &optional shortlog start-revision limit) OK ;; * log-outgoing (buffer remote-location) OK @@ -1037,12 +1038,8 @@ See `vc-git-log-edit-summary-max-len'.") "Toggle whether this will amend the previous commit. If toggling on, also insert its message into the buffer." (interactive) - (log-edit--toggle-amend - (lambda () - (with-output-to-string - (vc-git-command - standard-output 1 nil - "log" "--max-count=1" "--pretty=format:%B" "HEAD"))))) + (log-edit--toggle-amend (lambda () + (vc-git-get-change-comment nil "HEAD")))) (defvar-keymap vc-git-log-edit-mode-map :name "Git-Log-Edit" @@ -1958,6 +1955,11 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"." (defun vc-git-mark-resolved (files) (vc-git-command nil 0 files "add")) +(defun vc-git-get-change-comment (_files rev) + (with-output-to-string + (vc-git-command standard-output 1 nil + "log" "--max-count=1" "--pretty=format:%B" rev))) + (defvar vc-git-extra-menu-map (let ((map (make-sparse-keymap))) (define-key map [git-grep] diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index a30ba06aec3..5d7ebc05d4c 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -309,6 +309,12 @@ ;; used for files under this backend, and if files can indeed be ;; locked by other users. ;; +;; - get-change-comment (files rev) +;; +;; Return the change comments associated with the files at the given +;; revision. The FILES argument it for forward-compatibility; +;; existing implementations care only about REV. +;; ;; - modify-change-comment (files rev comment) ;; ;; Modify the change comments associated with the files at the @@ -706,12 +712,7 @@ ;; - The git backend supports amending, but in a different ;; way (press `C-c C-e' in log-edit buffer, when making a new commit). ;; -;; - Second, `log-view-modify-change-comment' doesn't seem to support -;; modern backends at all because `log-view-extract-comment' -;; unconditionally calls `log-view-current-file'. This should be easy to -;; fix. -;; -;; - Third, doing message editing in log-view might be a natural way to go +;; - Doing message editing in log-view might be a natural way to go ;; about it, but editing any but the last commit (and even it, if it's ;; been pushed) is a dangerous operation in Git, which we shouldn't make ;; too easy for users to perform. @@ -2440,7 +2441,8 @@ the variable `vc-BACKEND-header'." (lambda () (vc-call-backend backend 'log-edit-mode)) (lambda (files comment) (vc-call-backend backend - 'modify-change-comment files rev comment))))) + 'modify-change-comment files rev comment)) + nil backend))) ;;;###autoload (defun vc-merge () commit 475a33adb9134990fa05be8a6308216f12ed4ef7 Author: Sean Whitton Date: Thu Oct 17 20:57:07 2024 +0800 vc-start-logentry: Use current buffer as parent buffer more often * lisp/vc/vc-dispatcher.el (vc-start-logentry): When determining the parent buffer, if get-file-buffer returns nil, use the current buffer. Also, if the first file is a directory, don't try to call get-file-buffer, just use the current buffer. diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index 998cef649ff..892e4df9a6c 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -741,14 +741,11 @@ MODE, defaulting to `log-edit-mode' if MODE is nil. AFTER-HOOK specifies the local value for `vc-log-after-operation-hook'. BACKEND, if non-nil, specifies a VC backend for the Log Edit buffer. PATCH-STRING is a patch to check in." - (let ((parent - (if (vc-dispatcher-browsing) - ;; If we are called from a directory browser, the parent buffer is - ;; the current buffer. - (current-buffer) - (if (and files (equal (length files) 1)) - (get-file-buffer (car files)) - (current-buffer))))) + (let ((parent (or (and (not (vc-dispatcher-browsing)) + (length= files 1) + (not (file-directory-p (car files))) + (get-file-buffer (car files))) + (current-buffer)))) (if (and comment (not initial-contents)) (set-buffer (get-buffer-create logbuf)) (pop-to-buffer (get-buffer-create logbuf))) commit b9eb7f194526f654e4cc4d69f6a1632a5e92b18c Merge: 4c0d69cbff1 ee265922a0d Author: Eli Zaretskii Date: Thu Oct 17 16:22:58 2024 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 4c0d69cbff14e25fa7489804102ac416cb3590b0 Author: Eli Zaretskii Date: Thu Oct 17 16:21:49 2024 +0300 Improve coverage of scripts by the default fontset * lisp/international/fontset.el (setup-default-fontset): Add missing "simple" scripts. diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 2d91a5f2329..9743782a672 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -868,6 +868,17 @@ pahawh-hmong medefaidrin znamenny-musical-notation + khudawadi + khojki + mahajani + sogdian + old-sogdian + nabataean + palmyrene + linear-a + linear-b + caucasian-albanian + elbasan byzantine-musical-symbol musical-symbol ancient-greek-musical-notation @@ -878,6 +889,15 @@ wancho nag-mundari mende-kikakui + nyiakeng-puachue-hmong + mro + masaram-gondi + pau-cin-hau + soyombo + zanabazar-square + warang-citi + dogra + takri adlam tifinagh tai-tham commit ee265922a0df68893f4d2b23a9190f524b745b6a Author: Sean Whitton Date: Thu Oct 17 20:11:53 2024 +0800 More consistently propertize Log Edit headers as fields * lisp/vc/log-edit.el (log-edit--make-header-line): Factor out of log-edit-insert-message-template. (log-edit-set-header): Call log-edit--make-header-line so that the Log Edit header is propertized as a field. diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index d61a108b195..7ec394a263d 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -890,6 +890,14 @@ different header separator appropriate for `log-edit-mode'." (zerop (forward-line 1)))) (eobp)))) +(defun log-edit--make-header-line (header &optional value) + ;; Make \\`C-a' work like it does in other buffers with header names. + (concat (propertize (concat header ": ") + 'field 'header + 'rear-nonsticky t) + value + "\n")) + (defun log-edit-insert-message-template () "Insert the default VC commit log template with Summary and Author." (interactive) @@ -897,11 +905,8 @@ different header separator appropriate for `log-edit-mode'." (log-edit-empty-buffer-p)) (dolist (header (append '("Summary") (and log-edit-setup-add-author '("Author")))) - ;; Make `C-a' work like in other buffers with header names. - (insert (propertize (concat header ": ") - 'field 'header - 'rear-nonsticky t) - "\n")) + + (insert (log-edit--make-header-line header))) (insert "\n") (message-position-point))) @@ -1315,7 +1320,7 @@ If TOGGLE is non-nil, and the value of HEADER already is VALUE, clear it. Make sure there is an empty line after the headers. Return t if toggled on (or TOGGLE is nil), otherwise nil." (let ((val t) - (line (concat header ": " value "\n"))) + (line (log-edit--make-header-line header value))) (save-excursion (save-restriction (rfc822-goto-eoh)