From 43024eee0fbb28a6c47411d1dc84fa17795242de Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Mon, 22 Dec 2025 18:25:22 +0100 Subject: [PATCH] update helm * bba.org: point to new version * elpa/helm-20251212.555, elpa/helm-core-20251211.709 --- bba.org | 2 +- .../emacs-helm.sh | 2 + .../helm-adaptive.el | 2 +- .../helm-autoloads.el | 37 +- .../helm-bookmark.el | 11 +- .../helm-buffers.el | 25 +- .../helm-color.el | 21 +- .../helm-command.el | 38 +- .../helm-dabbrev.el | 0 .../helm-easymenu.el | 0 .../helm-elisp.el | 35 +- .../helm-epa.el | 25 +- .../helm-eshell.el | 3 +- .../helm-eval.el | 0 .../helm-external.el | 0 .../helm-fd.el | 7 +- .../helm-files.el | 495 ++++---- .../helm-find.el | 3 +- .../helm-font.el | 2 +- .../helm-for-files.el | 40 +- .../helm-global-bindings.el | 0 .../helm-grep.el | 101 +- .../helm-help.el | 18 +- .../helm-id-utils.el | 19 +- .../helm-imenu.el | 4 +- .../helm-info.el | 3 +- .../helm-locate.el | 10 +- .../helm-man.el | 53 +- .../helm-misc.el | 1 + .../helm-mode.el | 140 ++- .../helm-net.el | 66 +- .../helm-occur.el | 44 +- .../helm-packages.el | 246 +++- .../helm-pkg.el | 8 +- .../helm-regexp.el | 0 .../helm-ring.el | 0 .../helm-semantic.el | 0 .../helm-sys.el | 2 + .../helm-tags.el | 0 .../helm-types.el | 2 +- .../helm-utils.el | 258 ++-- .../helm-x-files.el | 0 .../helm-x-icons.el | 21 +- .../helm.el | 6 +- .../helm-core-autoloads.el | 0 .../helm-core-pkg.el | 6 +- .../helm-core.el | 1068 ++++++++++------- .../helm-lib.el | 94 +- .../helm-multi-match.el | 168 +-- .../helm-source.el | 55 +- 50 files changed, 1928 insertions(+), 1213 deletions(-) rename elpa/{helm-20250515.548 => helm-20251212.555}/emacs-helm.sh (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-adaptive.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-autoloads.el (97%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-bookmark.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-buffers.el (98%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-color.el (92%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-command.el (92%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-dabbrev.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-easymenu.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-elisp.el (96%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-epa.el (93%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-eshell.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-eval.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-external.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-fd.el (97%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-files.el (96%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-find.el (98%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-font.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-for-files.el (92%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-global-bindings.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-grep.el (96%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-help.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-id-utils.el (88%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-imenu.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-info.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-locate.el (98%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-man.el (69%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-misc.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-mode.el (96%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-net.el (88%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-occur.el (95%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-packages.el (62%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-pkg.el (74%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-regexp.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-ring.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-semantic.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-sys.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-tags.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-types.el (99%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-utils.el (87%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-x-files.el (100%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm-x-icons.el (93%) rename elpa/{helm-20250515.548 => helm-20251212.555}/helm.el (94%) rename elpa/{helm-core-20250514.1025 => helm-core-20251211.709}/helm-core-autoloads.el (100%) rename elpa/{helm-core-20250514.1025 => helm-core-20251211.709}/helm-core-pkg.el (70%) rename elpa/{helm-core-20250514.1025 => helm-core-20251211.709}/helm-core.el (91%) rename elpa/{helm-core-20250514.1025 => helm-core-20251211.709}/helm-lib.el (97%) rename elpa/{helm-core-20250514.1025 => helm-core-20251211.709}/helm-multi-match.el (74%) rename elpa/{helm-core-20250514.1025 => helm-core-20251211.709}/helm-source.el (95%) diff --git a/bba.org b/bba.org index a92ec5aa..47999711 100644 --- a/bba.org +++ b/bba.org @@ -2500,7 +2500,7 @@ Some links you might check out: (if (>= emacs-major-version 24) (progn (add-to-list 'load-path - "~/.emacs.d/elpa/helm-20250515.548") + "~/.emacs.d/elpa/helm-20251212.555") (require 'helm) (helm-mode 1) (global-set-key (kbd "M-y") 'helm-show-kill-ring) diff --git a/elpa/helm-20250515.548/emacs-helm.sh b/elpa/helm-20251212.555/emacs-helm.sh similarity index 99% rename from elpa/helm-20250515.548/emacs-helm.sh rename to elpa/helm-20251212.555/emacs-helm.sh index 9bd07fde..1bd32f30 100755 --- a/elpa/helm-20250515.548/emacs-helm.sh +++ b/elpa/helm-20251212.555/emacs-helm.sh @@ -156,6 +156,8 @@ fi cat > $CONF_FILE < -and -. + +. (fn ARG)" t) (autoload 'helm-find-files "helm-files" "\ @@ -379,6 +380,12 @@ Preconfigured `helm' for grepping with AG in `default-directory'. With prefix arg prompt for type if available with your AG version. +(fn ARG)" t) +(autoload 'helm-do-grep-ag-project "helm-grep" "\ +Preconfigured `helm' for grepping with AG from the current project root. +If no project found use `default-directory'. +With prefix arg prompt for type if available with your AG version. + (fn ARG)" t) (autoload 'helm-grep-do-git-grep "helm-grep" "\ Preconfigured `helm' for git-grepping `default-directory'. @@ -825,7 +832,23 @@ NOTE: Probably not supported on some systems (e.g., Windows). (fn URL &optional IGNORE)" t) (autoload 'helm-browse-url-chromium "helm-net" "\ -Browse URL with Google Chrome browser. +Same as `browse-url-chromium' but detach from emacs. + +So when you quit Emacs you can keep your Chromium session open and +not be prompted to kill the Chromium process. + +NOTE: Probably not supported on some systems (e.g., Windows). + +(fn URL &optional IGNORE)" t) +(autoload 'helm-browse-url-brave "helm-net" "\ +Browse URL with Brave browser and detach from emacs. + +Brave browser executable is determined by `helm-browse-url-brave-program'. + +So when you quit Emacs you can keep your Opera session open and +not be prompted to kill the Opera process. + +NOTE: Probably not supported on some systems (e.g., Windows). (fn URL &optional IGNORE)" t) (autoload 'helm-browse-url-uzbl "helm-net" "\ diff --git a/elpa/helm-20250515.548/helm-bookmark.el b/elpa/helm-20251212.555/helm-bookmark.el similarity index 99% rename from elpa/helm-20250515.548/helm-bookmark.el rename to elpa/helm-20251212.555/helm-bookmark.el index 10c90ba7..98e6d7f8 100644 --- a/elpa/helm-20250515.548/helm-bookmark.el +++ b/elpa/helm-20251212.555/helm-bookmark.el @@ -63,9 +63,7 @@ Don't use `setq' to set this." :type 'boolean :set (lambda (var val) - (if (require helm-x-icons-provider nil t) - (set var val) - (set var nil)))) + (set var (and (require helm-x-icons-provider nil t) val)))) (defcustom helm-bookmark-default-sort-method 'adaptive "Sort method for `helm-filtered-bookmarks'. @@ -119,19 +117,19 @@ will be honored." (defface helm-bookmark-man `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Orange4")) + :foreground "orange4")) "Face used for Woman/man bookmarks." :group 'helm-bookmark-faces) (defface helm-bookmark-file `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Deepskyblue2")) + :foreground "DeepSkyBlue2")) "Face used for file bookmarks." :group 'helm-bookmark-faces) (defface helm-bookmark-file-not-found `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Slategray4")) + :foreground "SlateGray4")) "Face used for file bookmarks." :group 'helm-bookmark-faces) @@ -585,7 +583,6 @@ If `browse-url-browser-function' is set to something else than (cl-defmethod helm--setup-source ((source helm-bookmark-find-files-class)) ;; Ensure `helm-source-in-buffer' method is called. - (cl-call-next-method) (setf (slot-value source 'action) (helm-append-at-nth (cl-loop for (name . action) in helm-type-bookmark-actions diff --git a/elpa/helm-20250515.548/helm-buffers.el b/elpa/helm-20251212.555/helm-buffers.el similarity index 98% rename from elpa/helm-20250515.548/helm-buffers.el rename to elpa/helm-20251212.555/helm-buffers.el index 6cfc6575..40d7595f 100644 --- a/elpa/helm-20250515.548/helm-buffers.el +++ b/elpa/helm-20251212.555/helm-buffers.el @@ -176,9 +176,7 @@ you want to keep the recentest order when narrowing candidates." Don't use `setq' to set this." :type 'boolean :set (lambda (var val) - (if (require helm-x-icons-provider nil t) - (set var val) - (set var nil)))) + (set var (and (require helm-x-icons-provider nil t) val)))) ;;; Faces @@ -198,7 +196,7 @@ Don't use `setq' to set this." (defface helm-buffer-not-saved `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Indianred2")) + :foreground "IndianRed2")) "Face used for buffer files not already saved on disk." :group 'helm-buffers-faces) @@ -231,7 +229,7 @@ Don't use `setq' to set this." (defface helm-buffer-process `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Sienna3")) + :foreground "sienna3")) "Face used for process status in buffer." :group 'helm-buffers-faces) @@ -249,7 +247,7 @@ Don't use `setq' to set this." (defface helm-buffer-archive `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Gold")) + :foreground "gold")) "Face for archive file names in `helm-buffers-list'." :group 'helm-buffers-faces) @@ -850,11 +848,16 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (helm-aif (get-buffer-window "*Diff*" 'visible) (progn (kill-buffer "*Diff*") (set-window-buffer it helm-current-buffer)) - (let ((buf (get-buffer candidate))) - (if (buffer-file-name buf) - (diff-buffer-with-file buf) - (user-error "Buffer `%s' is not associated to a file" - (buffer-name buf)))))) + ;; Expect the prop at pos 2 because of icon at 1. + (let* ((type (get-text-property 2 'type (helm-get-selection nil 'withprop))) + (buf (helm-aif (get-buffer candidate) + (or (buffer-base-buffer it) it))) + (file (buffer-file-name buf))) + (cl-assert file nil (format "Buffer `%s' is not associated to a file" + (buffer-name buf))) + (if (eq type 'modout) + (diff buf file) ; Buffer modified externally. + (diff file buf))))) ; Buffer modified inside emacs and not saved. (helm-make-persistent-command-from-action helm-buffer-diff-persistent "Toggle diff buffer without quitting helm." diff --git a/elpa/helm-20250515.548/helm-color.el b/elpa/helm-20251212.555/helm-color.el similarity index 92% rename from elpa/helm-20250515.548/helm-color.el rename to elpa/helm-20251212.555/helm-color.el index 8a0b6e89..de505472 100644 --- a/elpa/helm-20250515.548/helm-color.el +++ b/elpa/helm-20251212.555/helm-color.el @@ -28,17 +28,16 @@ ;; (defun helm-custom-faces-init () "Initialize buffer for `helm-source-customize-face'." - (unless (helm-candidate-buffer) - (save-selected-window - (list-faces-display) - (message nil)) - (helm-init-candidates-in-buffer - 'global - (with-current-buffer (get-buffer "*Faces*") - (buffer-substring - (next-single-char-property-change (point-min) 'category) - (point-max)))) - (kill-buffer "*Faces*"))) + (save-selected-window + (list-faces-display) + (message nil)) + (helm-init-candidates-in-buffer + 'global + (with-current-buffer (get-buffer "*Faces*") + (buffer-substring + (next-single-char-property-change (point-min) 'category) + (point-max)))) + (kill-buffer "*Faces*")) (defvar helm-source-customize-face (helm-build-in-buffer-source "Customize Face" diff --git a/elpa/helm-20250515.548/helm-command.el b/elpa/helm-20251212.555/helm-command.el similarity index 92% rename from elpa/helm-20250515.548/helm-command.el rename to elpa/helm-20251212.555/helm-command.el index ae276a13..cb6b6425 100644 --- a/elpa/helm-20250515.548/helm-command.el +++ b/elpa/helm-20251212.555/helm-command.el @@ -86,9 +86,19 @@ Helm will never appear in `helm-M-x' whatever the value of this var is." "Face used in helm-M-x to show keybinding." :group 'helm-command-faces) -(defface helm-command-active-mode +(defface helm-command-major-active-mode '((t :inherit font-lock-builtin-face)) - "Face used by `helm-M-x' for activated modes." + "Face used by `helm-M-x' for activated major modes." + :group 'helm-command-faces) + +(defface helm-command-minor-active-mode + '((t :inherit font-lock-type-face)) + "Face used by `helm-M-x' for activated minor modes." + :group 'helm-command-faces) + +(defface helm-command-debug-active + '((t :inherit font-lock-warning-face)) + "Face used by `helm-M-x' for activated toggle-debug-on-* commands." :group 'helm-command-faces) (defface helm-M-x-short-doc @@ -156,13 +166,19 @@ algorithm." for sym = (intern (if (consp cand) (car cand) cand)) for doc = (when helm-M-x-show-short-doc (helm-get-first-line-documentation (intern-soft cand))) - for disp = (if (or (eq sym major-mode) - (and (memq sym minor-mode-list) - (boundp sym) - (buffer-local-value - sym helm-current-buffer))) - (propertize cand 'face 'helm-command-active-mode) - cand) + for disp = (cond ((eq sym major-mode) + (propertize cand 'face 'helm-command-major-active-mode)) + ((and (memq sym minor-mode-list) + (boundp sym) + (buffer-local-value + sym helm-current-buffer)) + (propertize cand 'face 'helm-command-minor-active-mode)) + ((or (and (eq sym 'toggle-debug-on-error) + debug-on-error) + (and (eq sym 'toggle-debug-on-quit) + debug-on-quit)) + (propertize cand 'face 'helm-command-debug-active)) + (t cand)) unless (and (null ignore-props) (or (get sym 'helm-only) (get sym 'no-helm-mx) (eq sym 'helm-M-x))) @@ -331,6 +347,7 @@ Arg HISTORY default to `extended-command-history'." :fuzzy-match helm-M-x-fuzzy-match))) (prompt (concat (helm-acase helm-M-x-prefix-argument (- "-") + ;; Why &rest? isn't this always a list of one arg? ((dst* (l &rest args)) (if (eq l 4) "C-u " (format "%d " l))) ((guard* (integerp it)) (format "%d " it))) @@ -445,7 +462,8 @@ You can get help on each command by persistent action." (list current-prefix-arg))) (if (or defining-kbd-macro executing-kbd-macro) (helm-M-x--vanilla-M-x) - (let ((lmm-modes (buffer-local-value 'local-minor-modes (current-buffer))) + (let ((lmm-modes (and (boundp 'local-minor-modes) ; Only 28+ (issue#2719) + (buffer-local-value 'local-minor-modes (current-buffer)))) (mj-mode major-mode)) (helm-M-x-read-extended-command obarray (if (and (fboundp 'command-modes) diff --git a/elpa/helm-20250515.548/helm-dabbrev.el b/elpa/helm-20251212.555/helm-dabbrev.el similarity index 100% rename from elpa/helm-20250515.548/helm-dabbrev.el rename to elpa/helm-20251212.555/helm-dabbrev.el diff --git a/elpa/helm-20250515.548/helm-easymenu.el b/elpa/helm-20251212.555/helm-easymenu.el similarity index 100% rename from elpa/helm-20250515.548/helm-easymenu.el rename to elpa/helm-20251212.555/helm-easymenu.el diff --git a/elpa/helm-20250515.548/helm-elisp.el b/elpa/helm-20251212.555/helm-elisp.el similarity index 96% rename from elpa/helm-20250515.548/helm-elisp.el rename to elpa/helm-20251212.555/helm-elisp.el index 3ad1ea36..d0ea96b4 100644 --- a/elpa/helm-20250515.548/helm-elisp.el +++ b/elpa/helm-20251212.555/helm-elisp.el @@ -439,13 +439,13 @@ the same time to variable and a function." finally return (sort lst #'helm-generic-sort-fn))) ;;;###autoload -(cl-defun helm-get-first-line-documentation (sym &optional - (name "describe-function") - (end-column 72)) +(defun helm-get-first-line-documentation (sym &optional name end-column) "Return first line documentation of symbol SYM truncated at END-COLUMN. If SYM is not documented, return \"Not documented\". Argument NAME allows specifiying what function to use to display documentation when SYM name is the same for function and variable." + (unless name (setq name "describe-function")) + (unless end-column (setq end-column 72)) (let ((doc (condition-case _err (helm-acase sym ((guard* (stringp it)) @@ -757,7 +757,8 @@ is only used to test DEFAULT." :keymap helm-apropos-map :action '(("Describe Class" . helm-describe-class) ("Find Class (C-u for source)" . helm-find-function) - ("Info lookup" . helm-info-lookup-symbol)))) + ("Info lookup" . helm-info-lookup-symbol) + ("Describe slots" . helm-elisp-describe-slots)))) (defun helm-def-source--eieio-generic (&optional default) (helm-build-in-buffer-source "Generic functions" @@ -822,6 +823,32 @@ is only used to test DEFAULT." ;; (run-with-idle-timer 0.01 nil #'helm-info-lookup-symbol-1 candidate) (helm-info-lookup-symbol-1 candidate)) +(defun helm-elisp-describe-slots (class) + (helm :sources (helm-build-sync-source "Class slots" + :header-name (lambda (name) (format "%s in `%s'" name class)) + :candidates (helm-elisp-collect-slots-in-class + (intern-soft class)) + :candidate-transformer + (lambda (candidates) + (cl-loop for (disp . real) in candidates + collect (cons (propertize + disp 'face 'font-lock-keyword-face + 'display (concat ":" disp)) + real))) + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate + #'helm-elisp--describe-slot)) + :persistent-help "Describe slot" + :popup-info (lambda (c) (caddr (split-string c "\n" t))) + :action (helm-make-actions + "Describe slot" 'helm-elisp--describe-slot)) + :buffer "*helm class slots*")) + +(defun helm-elisp--describe-slot (slot) + (with-output-to-temp-buffer (help-buffer) + (princ slot))) + (defun helm-apropos-toggle-details () "Toggle details in `helm-apropos'." (interactive) diff --git a/elpa/helm-20250515.548/helm-epa.el b/elpa/helm-20251212.555/helm-epa.el similarity index 93% rename from elpa/helm-20250515.548/helm-epa.el rename to elpa/helm-20251212.555/helm-epa.el index 4e938b8d..3bd03dbf 100644 --- a/elpa/helm-20250515.548/helm-epa.el +++ b/elpa/helm-20251212.555/helm-epa.el @@ -86,19 +86,20 @@ uid 'face 'font-lock-warning-face)) key))) -(cl-defun helm-epa--select-keys (prompt keys) +(defun helm-epa--select-keys (prompt keys) "A helm replacement for `epa--select-keys'." - (let ((result (helm :sources (helm-make-source "Epa select keys" 'helm-epa - :candidates (lambda () - (helm-epa-get-key-list keys)) - :action (lambda (_candidate) - (helm-marked-candidates))) - :prompt (and prompt (helm-epa--format-prompt prompt)) - :buffer "*helm epa*"))) - (if (or (equal result "") (null result)) - (cl-return-from helm-epa--select-keys - (error "No keys selected, aborting")) - result))) + (catch 'nokey + (let ((result (helm :sources (helm-make-source "Epa select keys" 'helm-epa + :candidates (lambda () + (helm-epa-get-key-list keys)) + :action (lambda (_candidate) + (helm-marked-candidates))) + :prompt (and prompt (helm-epa--format-prompt prompt)) + :buffer "*helm epa*"))) + (if (or (equal result "") (null result)) + (throw 'nokey + (error "No keys selected, aborting")) + result)))) (defun helm-epa--format-prompt (prompt) (let ((split (split-string prompt "\n"))) diff --git a/elpa/helm-20250515.548/helm-eshell.el b/elpa/helm-20251212.555/helm-eshell.el similarity index 99% rename from elpa/helm-20250515.548/helm-eshell.el rename to elpa/helm-20251212.555/helm-eshell.el index 332c745f..8916cadf 100644 --- a/elpa/helm-20250515.548/helm-eshell.el +++ b/elpa/helm-20251212.555/helm-eshell.el @@ -437,8 +437,9 @@ See `helm-eshell-prompts-list'." (defun helm-eshell-prompts-all-transformer (candidates) (helm-eshell-prompts-transformer candidates t)) -(cl-defun helm-eshell-prompts-goto (candidate &optional (action 'switch-to-buffer)) +(defun helm-eshell-prompts-goto (candidate &optional action) ;; Candidate format: ("ls" 162 "*eshell*" 3) + (unless action (setq action #'switch-to-buffer)) (let ((buf (nth 2 candidate))) (unless (and (string= (buffer-name) buf) (eq action 'switch-to-buffer)) diff --git a/elpa/helm-20250515.548/helm-eval.el b/elpa/helm-20251212.555/helm-eval.el similarity index 100% rename from elpa/helm-20250515.548/helm-eval.el rename to elpa/helm-20251212.555/helm-eval.el diff --git a/elpa/helm-20250515.548/helm-external.el b/elpa/helm-20251212.555/helm-external.el similarity index 100% rename from elpa/helm-20250515.548/helm-external.el rename to elpa/helm-20251212.555/helm-external.el diff --git a/elpa/helm-20250515.548/helm-fd.el b/elpa/helm-20251212.555/helm-fd.el similarity index 97% rename from elpa/helm-20250515.548/helm-fd.el rename to elpa/helm-20251212.555/helm-fd.el index 0a08000b..895e2f30 100644 --- a/elpa/helm-20250515.548/helm-fd.el +++ b/elpa/helm-20251212.555/helm-fd.el @@ -38,7 +38,7 @@ (defface helm-fd-finish `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Green")) + :foreground "green")) "Face used in mode line when fd process ends." :group 'helm-grep-faces) @@ -100,8 +100,9 @@ (prog1 proc (set-process-sentinel - proc (lambda (_process event) - (if (string= event "finished\n") + proc (lambda (process event) + (if (or (string= event "finished\n") + (process-get process 'reach-limit)) (with-helm-window (when helm-fd-mode-line-function (funcall helm-fd-mode-line-function start-time fd-version) diff --git a/elpa/helm-20250515.548/helm-files.el b/elpa/helm-20251212.555/helm-files.el similarity index 96% rename from elpa/helm-20250515.548/helm-files.el rename to elpa/helm-20251212.555/helm-files.el index 3ad0b897..81a0573e 100644 --- a/elpa/helm-20250515.548/helm-files.el +++ b/elpa/helm-20251212.555/helm-files.el @@ -50,6 +50,7 @@ (declare-function eshell-resume-eval "esh-cmd") (declare-function helm-ls-git "ext:helm-ls-git") (declare-function helm-hg-find-files-in-project "ext:helm-ls-hg") +(declare-function helm-ls-svn-ls "ext:helm-ls-svn") (declare-function helm-gid "helm-id-utils.el") (declare-function helm-find-1 "helm-find") (declare-function helm-fd-1 "helm-fd") @@ -98,6 +99,7 @@ (declare-function async-byte-compile-file "async-bytecomp.el") (declare-function async-byte-recompile-directory "async-bytecomp.el") (declare-function dnd-begin-drag-files "dnd.el") +(declare-function vc-deduce-backend "vc") (defvar term-char-mode-point-at-process-mark) (defvar term-char-mode-buffer-read-only) @@ -115,6 +117,7 @@ (defvar wfnames-buffer) (defvar Info-current-file) (defvar generated-autoload-file) +(defvar recentf-max-saved-items) ;;; Internal vars ;; @@ -217,6 +220,11 @@ Should not be used among other sources.") (define-key map (kbd "M-K") 'helm-ff-run-kill-buffer-persistent) (define-key map (kbd "M-T") 'helm-ff-run-touch-files) (define-key map (kbd "M-M") 'helm-ff-run-chmod) + ;; M-O in ttys is a prefix key. + (define-key map (if (display-graphic-p) + (kbd "M-O") (kbd "M-O O")) + 'helm-ff-run-chown) + (define-key map (kbd "M-G") 'helm-ff-run-chgrp) (define-key map (kbd "C-c z") 'helm-ff-persistent-compress) (define-key map (kbd "M-Z") 'helm-ff-run-compress-marked-files) (define-key map (kbd "M-c") 'helm-ff-run-compress-to) @@ -254,7 +262,7 @@ Should not be used among other sources.") (define-key map (kbd "C-l") 'helm-find-files-up-one-level) (define-key map (kbd "C-:") 'helm-ff-complete-tramp-methods) (define-key map (kbd "C-_") 'helm-ff-undo) - (define-key map (kbd "C-r") 'helm-find-files-down-last-level) + (define-key map (kbd "C-;") 'helm-find-files-down-last-level) (define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root) (define-key map (kbd "C-x C-v") 'helm-ff-run-find-alternate-file) (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link) @@ -283,7 +291,7 @@ Should not be used among other sources.") (define-key map (kbd "C-l") 'helm-find-files-up-one-level) (define-key map (kbd "C-:") 'helm-ff-complete-tramp-methods) (define-key map (kbd "C-_") 'helm-ff-undo) - (define-key map (kbd "C-r") 'helm-find-files-down-last-level) + (define-key map (kbd "C-;") 'helm-find-files-down-last-level) (define-key map (kbd "C-c h") 'helm-ff-file-name-history) (define-key map (kbd "C-x r b") 'helm-ff-bookmark-insert-location) (define-key map (kbd "C-") 'helm-ff-run-toggle-auto-update) @@ -395,10 +403,6 @@ a whole tree." "Hide tooltips automatically after this many seconds." :type 'integer) -(defcustom helm-ff-file-name-history-use-recentf nil - "Use `recentf-list' instead of `file-name-history' in `helm-find-files'." - :type 'boolean) - (defcustom helm-ff-skip-boring-files nil "Non-nil to skip boring files. I.e. the files matching regexps in `helm-boring-file-regexp-list'. @@ -415,7 +419,7 @@ Note that when non-nil this will slow down slightly `helm-find-files'." :type 'boolean) -(defcustom helm-ff-candidate-number-limit 5000 +(defcustom helm-ff-candidate-number-limit 500 "The `helm-candidate-number-limit' for `helm-find-files' and friends. Note that when going one level up with `\\\\[helm-find-files-up-one-level]' the @@ -425,28 +429,25 @@ directory/file if this one is situated lower than `helm-ff-candidate-number-limit' num candidate." :type 'integer) -(defcustom helm-ff-preselect-ignore-large-dirs nil - "Preselect directory belonging to current-buffer even if large." - :type 'boolean) - -(defcustom helm-ff-up-one-level-preselect t - "Always preselect previous directory when going one level up. - -When non-nil `candidate-number-limit' source value is modified -dynamically when going one level up if the position of previous -candidate in its directory is > to -`helm-ff-candidate-number-limit'. - -It can be helpful to disable this and reduce -`helm-ff-candidate-number-limit' if you often navigate across -very large directories." +(defvar helm-ff-preselect-ignore-large-dirs nil + "This variable has no effect, use `helm-ff-dynamic-candidate-number-limit'.") +(make-obsolete-variable 'helm-ff-preselect-ignore-large-dirs + 'helm-ff-dynamic-candidate-number-limit + "4.0.6") + +(defvaralias 'helm-ff-up-one-level-preselect 'helm-ff-dynamic-candidate-number-limit) +(defcustom helm-ff-dynamic-candidate-number-limit t + " When non-nil `candidate-number-limit' source value is modified dynamically. +This when going one level up if the position of previous candidate in +its directory is > to `helm-ff-candidate-number-limit' This ensure +preselection on previous directory when going one level up possible. It +can be helpful to disable this and reduce +`helm-ff-candidate-number-limit' if you often navigate across very large +directories." :type 'boolean) - -(defcustom helm-files-save-history-extra-sources - '("Find" "Fd" "Locate" "Recentf" - "Files from Current Directory" "File Cache" "Etags") - "Extras source that save candidate to `file-name-history'." - :type '(repeat (choice string))) +(make-obsolete-variable 'helm-ff-up-one-level-preselect + 'helm-ff-dynamic-candidate-number-limit + "4.0.6") (defcustom helm-find-files-before-init-hook nil "Hook that run before initialization of `helm-find-files'." @@ -861,6 +862,8 @@ want to use it, helm is still providing "Compress file(s) to archive `M-c'" 'helm-find-files-compress-to "Compress or uncompress file(s) `M-Z'" 'helm-ff-compress-marked-files "Change mode on file(s) `M-M'" 'helm-ff-chmod + "Change owner on file(s) `M-O' or `M-O O' in ttys" 'helm-ff-chown + "Change group on file(s) `M-G'" 'helm-ff-chgrp "Find file other window `C-c o'" 'helm-find-files-other-window "Find file other frame `C-c C-o'" 'find-file-other-frame (lambda () (and (fboundp 'tab-bar-mode) @@ -916,13 +919,6 @@ to nil to avoid error messages when using `helm-find-files'." "Delay in seconds between each image in slideshow." :type 'integer) -(defcustom helm-file-name-history-hide-deleted nil - "Hide deleted files in file-name-history when non nil. - -This can be toggled at any time from `helm-ff-file-name-history' with \ -\\\\[helm-file-name-history-show-or-hide-deleted]." - :type 'boolean) - (defcustom helm-file-name-history-max-length 72 "Max length of candidates in helm file name history before truncating." :type 'integer) @@ -959,6 +955,24 @@ working only when dropping on an external application (only thunar tested)." (const :tag "Copy" copy) (const :tag "Move" move) (const :tag "Link" link))) + +(defcustom helm-find-files-ignore-diacritics nil + "Ignore diacritics on basename of files when non nil. +Note that this happens only when switching to multimatch, i.e. adding spaces in +pattern, this may slowdown a little matching of candidates when non nil. +Setting this with `setq' may have no effect on this variable, use +`customize-set-variable'. This variable affects as well `read-file-name'." + :type 'boolean + :set (lambda (var val) + (set var val) + ;; Force rebuilding the source to pass diacritics fn to diacritics + ;; slot. + (setq helm-source-find-files nil))) + +(defcustom helm-turn-on-recentf t + "Automatically turn on `recentf-mode' when non-nil." + :group 'helm-files + :type 'boolean) ;;; Faces ;; @@ -1085,7 +1099,7 @@ Used when showing tramp host completions." (defface helm-history-remote `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Indianred1")) + :foreground "IndianRed1")) "Face used for remote files in `file-name-history'." :group 'helm-files-faces) @@ -1147,6 +1161,16 @@ Used when showing tramp host completions." (remhash helm-ff-default-directory helm-ff--list-directory-cache))) (match-on-real :initform t) + ;; We don't want to have here matchfns loaded uselessly. + ;; By using diacritics :match should expand to: + ;; '(helm-mm-exact-match helm-mm-3f-match-on-diacritics helm-mm-3-migemo-match) + ;; If helm-find-files-ignore-diacritics is nil we should fallback to: + ;; '(helm-mm-exact-match helm-mm-3f-match helm-mm-3-migemo-match) + ;; See `helm-source-mm-get-search-or-match-fns'. + (match :initform (unless helm-find-files-ignore-diacritics + 'helm-mm-3f-match)) + (diacritics :initform (and helm-find-files-ignore-diacritics + 'helm-mm-3f-match-on-diacritics)) (filtered-candidate-transformer :initform '(helm-ff-fct helm-ff-maybe-show-thumbnails @@ -1534,8 +1558,7 @@ DEST must be a directory. SWITCHES when unspecified default to (setq helm-rsync-progress-str-alist (delete (assoc process helm-rsync-progress-str-alist) helm-rsync-progress-str-alist)) - (helm-rsync-restore-mode-line process) - (force-mode-line-update))) + (helm-rsync-restore-mode-line process))) (set-process-filter proc #'helm-rsync-process-filter))) (defun helm-rsync-process-filter (proc output) @@ -1699,6 +1722,50 @@ the car of marked files i.e. the first marked file." (message "Changed file mode to `%s' on %s file(s)" smode (length candidates)))))) +(defun helm-ff--dired-marked-files (&rest _args) + ;; Internally dired-do-chxxx needs basenames. + (cl-loop for f in (helm-marked-candidates :with-wildcard t) + collect (helm-basename f))) + +(defun helm-ff--dired-get-filename (&rest _args) + ;; Internally dired-do-chxxx needs basenames. + (helm-aif (helm-get-selection) (helm-basename it))) + +(defun helm-ff-dired-do-chxxx (&rest args) + "Variation of `dired-do-chxxx' for helm." + (require 'dired-aux) + (cl-letf (((symbol-function 'dired-get-marked-files) + #'helm-ff--dired-marked-files) + ((symbol-function 'dired-do-redisplay) + #'ignore) + ((symbol-function 'dired-get-filename) + #'helm-ff--dired-get-filename)) + ;; dired-aux is requiring dired so dired-click-to-select-mode should be + ;; also available. + (let (dired-click-to-select-mode) + (apply #'dired-do-chxxx args)))) + +(defun helm-ff-chown (_candidate) + "Variation of `dired-do-chown' for helm." + (with-helm-default-directory helm-ff-default-directory + (when (and (memq system-type '(ms-dos windows-nt)) + (not (file-remote-p default-directory))) + (error "chown not supported on this system")) + (helm-ff-dired-do-chxxx "Owner" dired-chown-program 'chown nil))) + +(defun helm-ff-chgrp (_candidate) + "Variation of `dired-do-chgrp' for helm." + (with-helm-default-directory helm-ff-default-directory + (when (and (memq system-type '(ms-dos windows-nt)) + (not (file-remote-p default-directory))) + (error "chown not supported on this system")) + (helm-ff-dired-do-chxxx "Group" "chgrp" 'chgrp nil))) + +(helm-make-command-from-action helm-ff-run-chown "Change owner on file(s)." 'helm-ff-chown) +(helm-make-command-from-action helm-ff-run-chgrp "Change group on file(s)." 'helm-ff-chgrp) +(put 'helm-ff-run-chown 'helm-only t) +(put 'helm-ff-run-chgrp 'helm-only t) + (defun helm-find-files-other-window (_candidate) "Keep current-buffer and open files in separate windows. When a prefix arg is detected files are opened in a vertical @@ -2579,8 +2646,7 @@ at end of pattern using \\\\[backward-char] and (setq helm-ff--deleting-char-backward t) (call-interactively (lookup-key (current-global-map) - (read-kbd-macro "DEL"))) - (helm--update-header-line)))) + (read-kbd-macro "DEL")))))) (put 'helm-ff-delete-char-backward 'helm-only t) (defun helm-ff-delete-char-backward--exit-fn () @@ -2588,29 +2654,30 @@ at end of pattern using \\\\[backward-char] and (setq helm-ff--deleting-char-backward nil)) (defvar helm-ff--RET-disabled nil) -(defun helm-ff-RET-1 (&optional must-match) - "Used for RET action in `helm-find-files'. -See `helm-ff-RET' for details. -If MUST-MATCH is specified exit with -`helm-confirm-and-exit-minibuffer' which handle must-match mechanism." - (let ((sel (helm-get-selection)) - ;; Ensure `file-directory-p' works on remote files. - non-essential) - (cl-assert sel nil "Trying to exit with no candidates") - (if (and (or (file-directory-p sel) - (helm-ff--invalid-tramp-name-p sel)) - ;; Allows exiting with default action when a prefix arg - ;; is specified. - (null current-prefix-arg) - (null helm-ff--RET-disabled) - (or (and (file-remote-p sel) - (string= "." (helm-basename sel)) - (string-match-p "\\`[/].*:.*:\\'" - helm-pattern)) - (not (string= "." (helm-basename sel))))) - (helm-execute-persistent-action) - (if must-match - (helm-confirm-and-exit-minibuffer) +(defun helm-ff-RET-1 () + "Used for RET action in `helm-find-files' and `helm-read-file-name'. +See `helm-ff-RET' for details." + (catch 'must-match + (let ((sel (helm-get-selection)) + ;; Ensure `file-directory-p' works on remote files. + non-essential) + ;; `helm--minibuffer-completing-file-name' is non nil that's mean we are + ;; in `helm-read-file-name'. + (if (and helm--minibuffer-completing-file-name (null sel)) + (throw 'must-match (minibuffer-message "[No match]")) + (cl-assert sel nil "Trying to exit with no candidates")) + (if (and (or (file-directory-p sel) + (helm-ff--invalid-tramp-name-p sel)) + ;; Allows exiting with default action when a prefix arg + ;; is specified. + (null current-prefix-arg) + (null helm-ff--RET-disabled) + (or (and (file-remote-p sel) + (string= "." (helm-basename sel)) + (string-match-p "\\`[/].*:.*:\\'" + helm-pattern)) + (not (string= "." (helm-basename sel))))) + (helm-execute-persistent-action) (helm-maybe-exit-minibuffer))))) (defun helm-ff-RET () @@ -2648,11 +2715,6 @@ Called with a prefix arg open menu unconditionally." (helm-ff-TAB-1 arg)) (put 'helm-ff-TAB 'helm-only t) -(defun helm-ff-RET-must-match () - "Same as `helm-ff-RET' but used in must-match map." - (interactive) - (helm-ff-RET-1 t)) - (helm-make-command-from-action helm-ff-run-grep "Run Grep action from `helm-source-find-files'." 'helm-find-files-grep) @@ -3005,7 +3067,7 @@ If prefix numeric arg is given go ARG level up." ;; predicate is used e.g. images and the default is a non ;; file image. (helm-set-attr 'candidate-number-limit - (if helm-ff-up-one-level-preselect + (if helm-ff-dynamic-candidate-number-limit (max (gethash new-pattern helm-ff--directory-files-length helm-ff-candidate-number-limit) @@ -3187,38 +3249,31 @@ when `helm-pattern' is equal to \"~/\"." (run-at-time helm-input-idle-delay nil #'undo-boundary) (helm-check-minibuffer-input))))))) -(cl-defun helm-ff-auto-expand-to-home-or-root (&optional (pattern helm-pattern spattern)) - "Allow expanding to $HOME or \"/\" or text yanked after pattern. - -Argument PATTERN default to `helm-pattern' and should _not_ be used for -other purpose than debugging the second cond clause of this function. -When PATTERN is specified, specific helm functions are not called to -avoid errors when called outside helm for debugging purpose." - (when (or spattern - (and (helm-file-completion-source-p) - (with-current-buffer (window-buffer (minibuffer-window)) (eolp)) - (not (string-match helm-ff-url-regexp pattern)))) - (cond ((and (not (file-remote-p pattern)) - (null (file-exists-p pattern)) +(defun helm-ff-auto-expand-to-home-or-root () + "Allow expanding to $HOME or \"/\" or text yanked after minibuffer input." + (when (and (helm-file-completion-source-p) + (with-current-buffer (window-buffer (minibuffer-window)) (eolp)) + (not (string-match helm-ff-url-regexp helm-pattern))) + (cond ((and (not (file-remote-p helm-pattern)) + (null (file-exists-p helm-pattern)) (string-match-p "\\`\\([.]\\)\\{2\\}[^/]+" - (helm-basename pattern)) - (string-match-p "/\\'" pattern) - (null spattern)) - (helm-ff-recursive-dirs pattern) + (helm-basename helm-pattern)) + (string-match-p "/\\'" helm-pattern)) + (helm-ff-recursive-dirs helm-pattern) (helm-ff--maybe-set-pattern-and-update)) ((string-match "\\(?:\\`~/\\)\\|/?\\$.*/\\|/\\./\\|/\\.\\./\\|/~.*/\\|//\\|\\(/[[:alpha:]]:/\\)" - pattern) - (let* ((match (match-string 0 pattern)) + helm-pattern) + (let* ((match (match-string 0 helm-pattern)) (input (cond ((string= match "/./") (expand-file-name default-directory)) - ((string= pattern "/../") "/") + ((string= helm-pattern "/../") "/") ((string-match-p "\\`/\\$" match) (let ((sub (substitute-in-file-name match))) (if (file-directory-p sub) sub (replace-regexp-in-string "/\\'" "" sub)))) - (t (helm-ff--expand-substitued-pattern pattern))))) + (t (helm-ff--expand-substitued-pattern helm-pattern))))) ;; `file-directory-p' returns t on "/home/me/." (Bug#1844). (if (and (file-directory-p input) (not (string-match-p "[^.]\\.\\'" input))) @@ -3229,10 +3284,10 @@ avoid errors when called outside helm for debugging purpose." (helm-ff-after-persistent-show-all)) (setq helm-ff-default-directory (file-name-as-directory (file-name-directory input)))) - (if spattern input (helm-ff--maybe-set-pattern-and-update input)))) - ((and (string-match "\\`/\\(-\\):.*" pattern) (null spattern)) + (helm-ff--maybe-set-pattern-and-update input))) + ((string-match "\\`/\\(-\\):.*" helm-pattern) (helm-ff--maybe-set-pattern-and-update - (replace-match tramp-default-method t t pattern 1)))))) + (replace-match tramp-default-method t t helm-pattern 1)))))) (defun helm-ff--maybe-set-pattern-and-update (&optional str) (with-helm-window @@ -3334,27 +3389,6 @@ editing absolute fnames in previous Emacs versions." "Execute `helm-ff-edit-marked-files' interactively." 'helm-ff-edit-marked-files) -(defun helm-ff--create-tramp-name (fname) - "Build filename from `helm-pattern' like /su:: or /sudo::." - ;; `tramp-make-tramp-file-name' takes 7 args on emacs-26 whereas it - ;; takes only 5 args in emacs-24/25. - (apply #'tramp-make-tramp-file-name - ;; `tramp-dissect-file-name' returns a list in emacs-26 - ;; whereas in 24.5 it returns a vector, thus the car is a - ;; symbol (`tramp-file-name') which is not needed as argument - ;; for `tramp-make-tramp-file-name' so transform the cdr in - ;; vector, and for 24.5 use directly the returned value. - (cl-loop with v = (helm-ff--tramp-cons-or-vector - (tramp-dissect-file-name fname)) - for i across v collect i))) - -(defun helm-ff--tramp-cons-or-vector (vector-or-cons) - "Return VECTOR-OR-CONS as a vector." - (helm-acase vector-or-cons - ((guard* (and (consp it) (cdr it))) (vconcat guard)) - ((guard* (vectorp it)) it) - (t (error "Wrong type argument: %s" it)))) - (defun helm-ff--get-tramp-methods () "Return a list of the car of `tramp-methods'." (or helm-ff--tramp-methods @@ -3384,7 +3418,7 @@ Return nil on valid file name remote or not." ;; solution apart disabling tramp-mode when a file/dir located at / ;; is matching helm-tramp-file-name-regexp; This would prevent usage ;; of tramp if one have such a directory at / (who would want to - ;; have such a dir at / ???) See emacs-bug#31489. + ;; have such a dir at / ???) See https://debbugs.gnu.org/31489. (when (string-match-p helm-tramp-file-name-regexp fname) (let* ((bn (helm-basename fname)) (bd (replace-regexp-in-string (regexp-quote bn) "" fname)) @@ -3504,7 +3538,7 @@ debugging purpose." (setq cur-method (match-string 1 pattern)) (member cur-method methods)) (setq tramp-name (expand-file-name - (helm-ff--create-tramp-name + (file-remote-p (match-string 0 pattern)))) (replace-match tramp-name nil t pattern)) ;; Match "/method:maybe_hostname:" @@ -3512,7 +3546,7 @@ debugging purpose." postfixed (setq cur-method (match-string 1 pattern)) (member cur-method methods)) - (setq tramp-name (helm-ff--create-tramp-name + (setq tramp-name (file-remote-p (match-string 0 pattern))) (replace-match tramp-name nil t pattern)) ;; Match "/hostname:" @@ -3520,7 +3554,7 @@ debugging purpose." postfixed (setq cur-method (match-string 1 pattern)) (and cur-method (not (member cur-method methods)))) - (setq tramp-name (helm-ff--create-tramp-name + (setq tramp-name (file-remote-p (match-string 0 pattern))) (replace-match tramp-name nil t pattern)) ;; Match "/method:" in this case don't try to connect. @@ -3714,7 +3748,10 @@ Add a `helm-ff-dir' property on each fname ending with \"/\"." (cl-loop with files = (helm-file-name-all-completions-internal directory) for f in (sort files (or sort-method 'string-lessp)) for split = (split-string f "->" t) - for fname = (replace-regexp-in-string " $" "" (car split)) + ;; For some reasons adb (or tramp) add a "*" at end of fnames, but + ;; the real name is without the ending "*". + for fname = (helm-aand (replace-regexp-in-string " $" "" (car split)) + (replace-regexp-in-string "\\*\\'" "" it)) for truename = (cadr split) collect (cond ((string-match "/\\'" fname) (propertize (helm--dir-file-name fname directory) @@ -3905,9 +3942,9 @@ This is meant to run in `tramp-cleanup-connection-hook'." if (assq i bad) concat (cdr it) else concat (string i))) -(defun helm-ff-fuzzy-matching-p () - (and helm-ff-fuzzy-matching - (not (memq helm-mm-matching-method '(multi1 multi3p))))) +;; Keep it like this i.e. a function for evaluation in source definition. +(defun helm-ff--fuzzy-matching-p () + helm-ff-fuzzy-matching) (defun helm-ff--transform-pattern-for-completion (pattern) "Maybe return PATTERN with it's basename modified as a regexp. @@ -3943,7 +3980,7 @@ If PATTERN is a valid directory name, return PATTERN unchanged." ;; This allow showing all files/dirs matching BN (Bug#518). ;; FIXME: some multi-match methods may not work here. (dir-p (concat (regexp-quote bd) " " (regexp-quote bn))) - ((or (not (helm-ff-fuzzy-matching-p)) + ((or (not (helm-ff--fuzzy-matching-p)) (string-match "[ !]" bn)) ; Fall back to multi-match. (concat (regexp-quote bd) " " bn)) ((or (string-match "[*][.]?.*" bn) ; Allow entering wildcard. @@ -3960,9 +3997,14 @@ If PATTERN is a valid directory name, return PATTERN unchanged." ;; bn as well. (regexp-quote bn))) (t (concat (regexp-quote bd) - (if (>= (length bn) 2) ; wait 2nd char before concating. + ;; wait 2nd char before transforming to fuzzy. + (if (>= (length bn) 2) (helm--mapconcat-pattern bn) - (concat ".*" (regexp-quote bn)))))))) + ;; Here BN length is 1, we were previously matching + ;; everything before BN i.e. (concat ".*" (regexp-quote bn)) + ;; but it is too slow on large directories. We could use + ;; previous clause for this but keep it here for clarity. + (regexp-quote bn))))))) (defalias 'helm-dir-is-dot 'helm-ff-dot-file-p) (make-obsolete 'helm-dir-is-dot 'helm-ff-dot-file-p "3.8.8") @@ -4564,7 +4606,7 @@ Arg FILE is the real part of candidate, a filename with no props." (lambda (f) (string-match "autoloads\\|loaddefs" f))))) (if (fboundp 'loaddefs-generate) - (loaddefs-generate default-directory file) + (loaddefs-generate default-directory file nil nil nil t) (let ((generated-autoload-file file)) (update-directory-autoloads default-directory))))) @@ -4924,16 +4966,15 @@ This affects directly file CANDIDATE." (helm-ff-display-image-native-p)) nil "Resizing image not available") (if (> arg 0) - (run-with-idle-timer - 0.3 nil - (lambda () - (with-selected-window (helm-persistent-action-display-window) - (image--change-size 1.2)))) - (run-with-idle-timer - 0.3 nil - (lambda () - (with-selected-window (helm-persistent-action-display-window) - (image--change-size 0.8)))))) + (helm-ff--image-change-size 1.2) + (helm-ff--image-change-size 0.8))) + +(defun helm-ff--image-change-size (factor) + (run-with-idle-timer + 0.3 nil + (lambda () + (with-selected-window (helm-persistent-action-display-window) + (image--change-size factor))))) (defun helm-ff-increase-image-size (_candidate) (helm-ff-resize-image-1 1)) @@ -5002,7 +5043,10 @@ file." (delete-minibuffer-contents) (set-text-properties 0 (length fname) nil fname) - (insert fname)))))) + ;; Backup files have "!" to replace "/" + ;; in their basenames. + (insert (replace-regexp-in-string + "/!" "/\\\\!" fname))))))) (helm-set-attr 'candidate-number-limit helm-ff-candidate-number-limit) (unless (helm-ff--maybe-follow candidate) (when follow @@ -5577,7 +5621,7 @@ Show the first `helm-ff-history-max-length' elements of (if comp-read (let ((src (helm-build-sync-source "Helm Find Files History" :candidates helm-ff-history - :fuzzy-match (helm-ff-fuzzy-matching-p) + :fuzzy-match (helm-ff--fuzzy-matching-p) :persistent-action 'ignore :migemo t :action (lambda (candidate) @@ -5701,17 +5745,13 @@ Use it for non-interactive calls of `helm-find-files'." (helm-set-attr 'follow -1 helm-source-find-files)) ;; If preselected candidate is further than `helm-ff-candidate-number-limit' ;; in the directory file list, we have to increase `candidate-number-limit' - ;; attr to have this candidate visible for preselection. NOTE: - ;; When HFF has yet not been launched in this directory the maximum length - ;; of this directory is unknown and candidate will NOT be selected until - ;; next time we call HFF on this same buffer. - (helm-aif (and preselect - (not helm-ff-preselect-ignore-large-dirs) - (gethash fname helm-ff--directory-files-length - helm-ff-candidate-number-limit)) - (helm-set-attr 'candidate-number-limit - (max it helm-ff-candidate-number-limit) - helm-source-find-files)) + ;; attr to have this candidate visible for preselection. + (when (and preselect helm-ff-dynamic-candidate-number-limit) + (helm-set-attr 'candidate-number-limit + (helm-aif (gethash fname helm-ff--directory-files-length) + (max it helm-ff-candidate-number-limit) + 99999) + helm-source-find-files)) (helm-ff-setup-update-hook) (add-hook 'helm-resume-after-hook 'helm-ff--update-resume-after-hook) (unwind-protect @@ -5733,7 +5773,8 @@ Use it for non-interactive calls of `helm-find-files'." (helm-build-dummy-source "New file or directory" :filtered-candidate-transformer (lambda (_candidates _source) - (unless (file-exists-p helm-pattern) + ;; Unquote helm-pattern maybe quoted by PA. + (unless (file-exists-p (replace-regexp-in-string "\\s\\" "" helm-pattern)) (list (helm-ff-filter-candidate-one-by-one helm-pattern nil t)))) :all-marked t :keymap 'helm-find-files-map @@ -6783,66 +6824,29 @@ be existing directories." (helm-make-command-from-action helm-ff-run-mcp "Copy the car of marked candidates to the remaining marked candidates." 'helm-ff-mcp) + ;;; File name history ;; ;; -(defun helm-files-save-file-name-history (&optional force) - "Save marked files to `file-name-history'." - (let* ((src (helm-get-current-source)) - (src-name (assoc-default 'name src))) - (when (or force (helm-file-completion-source-p src) - (member src-name helm-files-save-history-extra-sources)) - (let ((mkd (helm-marked-candidates :with-wildcard t)) - (history-delete-duplicates t)) - (cl-loop for sel in mkd - when (and sel - (stringp sel) - ;; If file was one of HFF candidates assume it - ;; is an existing file, so no need to call - ;; file-exists-p which is costly on remote candidates. - ;; (file-exists-p sel) - (not (helm-ff--file-directory-p sel)) - ;; When creating a new directory previous test - ;; check for file-directory-p BEFORE its - ;; creation, so check for ending slash as - ;; well to know if it is a future directory. - (not (string-match "/\\'" sel))) - do - ;; we use `abbreviate-file-name' here because - ;; other parts of Emacs seems to, - ;; and we don't want to introduce duplicates. - (add-to-history 'file-name-history - (abbreviate-file-name - (expand-file-name - ;; See comments in `helm-recentf-source' - ;; about bug#2709. - (substring-no-properties sel))))))))) -(add-hook 'helm-exit-minibuffer-hook 'helm-files-save-file-name-history) - (defvar helm-source-file-name-history (helm-build-sync-source "File Name History" :candidates 'file-name-history :persistent-action #'ignore ;; See comments in `helm-recentf-source' about bug#2709. + ;; This is probably not needed as long as we use + ;; `helm-file-name-history-transformer' which uses only propertize. :coerce 'substring-no-properties - :filtered-candidate-transformer #'helm-file-name-history-transformer + :match-on-real t + :candidate-transformer #'helm-file-name-history-transformer :action 'helm-type-file-actions)) -(defun helm-file-name-history-show-or-hide-deleted () - (interactive) - (setq helm-file-name-history-hide-deleted - (not helm-file-name-history-hide-deleted)) - (helm-update)) -(put 'helm-file-name-history-show-or-hide-deleted 'helm-only t) - (defvar helm-file-name-history-map (let ((map (make-sparse-keymap))) (set-keymap-parent map helm-map) - (define-key map (kbd "C-c d") 'helm-file-name-history-show-or-hide-deleted) (define-key map (kbd "C-x C-f") 'helm-ff-file-name-history-run-ff) map)) -(defun helm-file-name-history-transformer (candidates _source) +(defun helm-file-name-history-transformer (candidates) (cl-loop with lgst = helm-file-name-history-max-length for elm in candidates for c = (truncate-string-to-width @@ -6854,13 +6858,11 @@ be existing directories." ((file-exists-p elm) (let ((last-access (format-time-string "%d/%m/%Y %X" (nth 4 (file-attributes elm))))) - (propertize - elm 'display - (concat (propertize c 'face 'helm-ff-file) - (make-string (1+ (- lgst (length c))) ? ) - last-access)))) - (t (unless helm-file-name-history-hide-deleted - (propertize c 'face 'helm-history-deleted)))) + (concat (propertize c 'face 'helm-ff-file) + (make-string (1+ (- lgst (length c))) ? ) + last-access))) + ;; Should not happen as long as we use recentf. + (t (propertize c 'face 'helm-history-deleted))) when disp collect (cons (if helm-ff-icon-mode (concat (helm-x-icons-icon-for-file @@ -6877,44 +6879,32 @@ be existing directories." "Switch back to current HFF session with selection as preselect." 'helm-ff-file-name-history-ff) -(defun helm-ff-file-name-history-delete-item (_candidate) - (let ((files (helm-marked-candidates))) - (with-helm-display-marked-candidates - helm-marked-buffer-name - (helm-ff--count-and-collect-dups files) - (when (y-or-n-p "Delete file(s) from history? ") - (cl-loop for f in files do - (setq file-name-history (delete f file-name-history)))) - (message nil)))) - (defun helm-ff-file-name-history () - "Switch to `file-name-history' without quitting `helm-find-files'." + "Switch to `recentf' without quitting `helm-find-files'." (interactive) + (when helm-turn-on-recentf (recentf-mode 1)) (let ((src (helm-build-sync-source "File name history" - :init (lambda () - (with-helm-alive-p - (when helm-ff-file-name-history-use-recentf - (require 'recentf) - (or recentf-mode (recentf-mode 1))))) - :candidate-number-limit (helm-aand (or (get 'file-name-history 'history-length) - history-length) - (and (numberp it) it)) - :candidates (lambda () - (if helm-ff-file-name-history-use-recentf - recentf-list - file-name-history)) + :candidate-number-limit + (helm-aand + (or + (and (boundp 'recentf-max-saved-items) + recentf-max-saved-items) + (get 'file-name-history 'history-length) + history-length) + (and (numberp it) it)) + :candidates (lambda () recentf-list) :help-message 'helm-file-name-history-help-message :fuzzy-match t + :match-on-real t :persistent-action 'ignore :migemo t - :filtered-candidate-transformer 'helm-file-name-history-transformer + :candidate-transformer 'helm-file-name-history-transformer :action (helm-make-actions "Find file" (lambda (candidate) (helm-set-pattern (expand-file-name candidate)) (with-helm-after-update-hook (helm-exit-minibuffer))) - "Find file in helm" 'helm-ff-file-name-history-ff - "Delete candidate(s)" 'helm-ff-file-name-history-delete-item) + "Find file in helm" 'helm-ff-file-name-history-ff) :keymap helm-file-name-history-map))) (with-helm-alive-p (helm :sources src @@ -7063,11 +7053,12 @@ by git or hg, otherwise it has no effect." (interactive "P") (setq helm-browse-project-history (cl-loop for p in helm-browse-project-history - when (file-directory-p p) + when (and (stringp p) (file-directory-p p)) collect p)) (helm :sources (helm-build-sync-source "Project history" :candidates helm-browse-project-history + :filtered-candidate-transformer 'helm-adaptive-sort :action (helm-make-actions "Browse project" (lambda (candidate) @@ -7087,9 +7078,10 @@ by git or hg, otherwise it has no effect." (defun helm-browse-project (arg) "Preconfigured helm to browse projects. Browse files and see status of project with its VCS. -Only HG and GIT are supported for now. +GIT, HG and SVN are supported for now, but only git is fully featured with +`helm-ls-git' package. Fall back to `helm-browse-project-find-files' if current -directory is not under control of one of those VCS. +directory is not under control or one of those VCS. With a prefix ARG browse files recursively, with two prefix ARG rebuild the cache. If the current directory is found in the cache, start @@ -7097,37 +7089,48 @@ If the current directory is found in the cache, start NOTE: The prefix ARG have no effect on the VCS controlled directories. -Needed dependencies for VCS: +Needed dependencies for VCS (not mandatory, pickup what you need): -and -." + +." (interactive "P") (require 'helm-x-files) - (let ((helm-type-buffer-actions - (remove (assoc "Browse project from buffer" - helm-type-buffer-actions) - helm-type-buffer-actions)) - (helm-buffers-in-project-p t)) + (require 'vc) + (let* ((helm-type-buffer-actions + (remove (assoc "Browse project from buffer" + helm-type-buffer-actions) + helm-type-buffer-actions)) + (helm-buffers-in-project-p t) + (git-project (and (require 'helm-ls-git nil t) + (fboundp 'helm-ls-git-root-dir) + (helm-ls-git-root-dir))) + (hg-project (and (require 'helm-ls-hg nil t) + (fboundp 'helm-hg-root) + (helm-hg-root))) + (svn-project (and (require 'helm-ls-svn nil t) + (fboundp 'helm-ls-svn-root-dir) + (helm-ls-svn-root-dir))) + ;; handle nested projects (Hg inside Git or vice versa) issue#2723. + (project-type (vc-deduce-backend))) (cl-flet ((push-to-hist (root) (setq helm-browse-project-history (cons root (delete root helm-browse-project-history))))) - (helm-acond ((and (require 'helm-ls-git nil t) - (fboundp 'helm-ls-git-root-dir) - (helm-ls-git-root-dir)) + (helm-acond ((and (equal project-type 'Git) git-project) (push-to-hist it) (helm-ls-git)) - ((and (require 'helm-ls-hg nil t) - (fboundp 'helm-hg-root) - (helm-hg-root)) + ((and (equal project-type 'Hg) hg-project) (push-to-hist it) (helm-hg-find-files-in-project)) + ((and (equal project-type 'Svn) svn-project) + (push-to-hist it) + (helm-ls-svn-ls)) ((helm-browse-project-get--root-dir (helm-current-directory)) (if (or arg (gethash it helm--browse-project-cache)) (progn - (push-to-hist it) + (push-to-hist (abbreviate-file-name it)) (helm-browse-project-find-files it (equal arg '(16)))) - (helm :sources (helm-browse-project-build-buffers-source it) - :buffer "*helm browse project*"))))))) + (helm :sources (helm-browse-project-build-buffers-source it) + :buffer "*helm browse project*"))))))) (defun helm-browse-project-get--root-dir (directory) (cl-loop with dname = (file-name-as-directory directory) diff --git a/elpa/helm-20250515.548/helm-find.el b/elpa/helm-20251212.555/helm-find.el similarity index 98% rename from elpa/helm-20250515.548/helm-find.el rename to elpa/helm-20251212.555/helm-find.el index 26005339..dc81c262 100644 --- a/elpa/helm-20250515.548/helm-find.el +++ b/elpa/helm-20251212.555/helm-find.el @@ -134,7 +134,8 @@ separator." (lambda (process event) (helm-process-deferred-sentinel-hook process event (helm-default-directory)) - (if (string= event "finished\n") + (if (or (string= event "finished\n") + (process-get process 'reach-limit)) (helm-locate-update-mode-line "Find") (helm-log "helm-find-shell-command-fn sentinel" "Error: Find %s" (replace-regexp-in-string "\n" "" event)))))))) diff --git a/elpa/helm-20250515.548/helm-font.el b/elpa/helm-20251212.555/helm-font.el similarity index 99% rename from elpa/helm-20250515.548/helm-font.el rename to elpa/helm-20251212.555/helm-font.el index 6e3cef5d..92875d24 100644 --- a/elpa/helm-20250515.548/helm-font.el +++ b/elpa/helm-20251212.555/helm-font.el @@ -60,7 +60,7 @@ (defface helm-ucs-char `((((class color) (background dark)) ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Gold")) + :foreground "gold")) "Face used to display ucs characters." :group 'helm-font) diff --git a/elpa/helm-20250515.548/helm-for-files.el b/elpa/helm-20251212.555/helm-for-files.el similarity index 92% rename from elpa/helm-20250515.548/helm-for-files.el rename to elpa/helm-20251212.555/helm-for-files.el index e5c3beef..4868f6cd 100644 --- a/elpa/helm-20250515.548/helm-for-files.el +++ b/elpa/helm-20251212.555/helm-for-files.el @@ -99,7 +99,6 @@ Be aware that a nil value will make tramp display very slow." ;; ;; (defvar helm-recentf--basename-flag nil) -(defvar helm-recentf-cache nil) (defun helm-recentf-pattern-transformer (pattern) (let ((pattern-no-flag (replace-regexp-in-string " -b" "" pattern))) @@ -113,19 +112,11 @@ Be aware that a nil value will make tramp display very slow." (t (setq helm-recentf--basename-flag nil) pattern)))) -(defcustom helm-turn-on-recentf t - "Automatically turn on `recentf-mode' when non-nil." - :group 'helm-files - :type 'boolean) - (defclass helm-recentf-source (helm-source-sync helm-type-file) ((init :initform (lambda () (require 'recentf) - (when helm-turn-on-recentf (recentf-mode 1)) - ;; Use a copy of not recentf-list itself but the of its - ;; elements to not corrupt them with text props. - (setq helm-recentf-cache (helm-copy-sequence recentf-list)))) - (candidates :initform 'helm-recentf-cache) + (when helm-turn-on-recentf (recentf-mode 1)))) + (candidates :initform 'recentf-list) (pattern-transformer :initform 'helm-recentf-pattern-transformer) (match-part :initform (lambda (candidate) (if (or helm-ff-transformer-show-only-basename @@ -183,16 +174,21 @@ Colorize only symlinks, directories and files." 'identity) with sname = (helm-get-attr 'name source) for i in files - for disp = (if (or (and (not helm-ff-show-dot-file-path) - (helm-ff-dot-file-p i)) - (and helm-ff-transformer-show-only-basename - (not (member sname - helm-sources-for-files-no-basename)) - (not (helm-ff-dot-file-p i)) - (not (and helm--url-regexp - (string-match helm--url-regexp i))) - (not (string-match helm-ff-url-regexp i)))) - (helm-basename i) (abbreviate-file-name i)) + ;; As long as we use this transformer on file lists like recentf that + ;; are printed and saved to a file we make a copy of the display + ;; string and add text props to it, this to not corrupt the elemnts + ;; of the original list (Bug#2709). + for disp = (copy-sequence + (if (or (and (not helm-ff-show-dot-file-path) + (helm-ff-dot-file-p i)) + (and helm-ff-transformer-show-only-basename + (not (member sname + helm-sources-for-files-no-basename)) + (not (helm-ff-dot-file-p i)) + (not (and helm--url-regexp + (string-match helm--url-regexp i))) + (not (string-match helm-ff-url-regexp i)))) + (helm-basename i) (abbreviate-file-name i))) for isremote = (or (file-remote-p i) (helm-file-on-mounted-network-p i)) ;; file-attributes is too slow on remote files, @@ -239,7 +235,7 @@ Colorize only symlinks, directories and files." (invalid-regexp nil)) (add-face-text-property (match-beginning 1) (match-end 1) - 'helm-ff-file-extension t disp))) + 'helm-ff-file-extension nil disp))) (cons (helm-ff-prefix-filename disp i) i))))) diff --git a/elpa/helm-20250515.548/helm-global-bindings.el b/elpa/helm-20251212.555/helm-global-bindings.el similarity index 100% rename from elpa/helm-20250515.548/helm-global-bindings.el rename to elpa/helm-20251212.555/helm-global-bindings.el diff --git a/elpa/helm-20250515.548/helm-grep.el b/elpa/helm-20251212.555/helm-grep.el similarity index 96% rename from elpa/helm-20250515.548/helm-grep.el rename to elpa/helm-20251212.555/helm-grep.el index 6bd54d58..41841b69 100644 --- a/elpa/helm-20250515.548/helm-grep.el +++ b/elpa/helm-20251212.555/helm-grep.el @@ -22,6 +22,7 @@ (require 'helm) (require 'helm-help) (require 'helm-regexp) +(require 'project) ;;; load wgrep proxy if it's available (require 'wgrep-helm nil t) @@ -427,13 +428,13 @@ Have no effect when grep backend use \"--color=\"." (defface helm-grep-lineno `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Darkorange1")) + :foreground "DarkOrange1")) "Face used to highlight grep number lines." :group 'helm-grep-faces) (defface helm-grep-finish `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "Green")) + :foreground "green")) "Face used in mode line when grep is finish." :group 'helm-grep-faces) @@ -659,6 +660,7 @@ Have no effect when grep backend use \"--color=\"." ,proc-name) 'face 'helm-grep-finish)))))) ((or (string= event "finished\n") + (process-get process 'reach-limit) (and noresult ;; This is a workaround for zgrep ;; that exit with code 1 @@ -668,7 +670,7 @@ Have no effect when grep backend use \"--color=\"." proc-name (helm-get-candidate-number) (- (float-time) start-time)) - (helm-maybe-show-help-echo) + (helm-maybe-show-popup-tip-info) (with-helm-window (setq mode-line-format `(" " mode-line-buffer-identification " " @@ -1203,7 +1205,6 @@ of grep." It is currently used only as an internal flag and doesn't set the backend by itself. You probably don't want to modify this.") - (candidate-number-limit :initform 9999) (help-message :initform 'helm-grep-help-message) (history :initform 'helm-grep-history) (action :initform 'helm-grep-actions) @@ -1217,17 +1218,8 @@ of grep." (defvar helm-source-grep nil) -(cl-defmethod helm--setup-source ((source helm-grep-class)) - (cl-call-next-method) - (helm-aif (and helm-follow-mode-persistent - (if (eq (slot-value source 'backend) 'git) - helm-source-grep-git - helm-source-grep)) - (setf (slot-value source 'follow) - (assoc-default 'follow it)))) - -(cl-defun helm-do-grep-1 (targets &optional recurse backend exts - default-input input (source 'helm-source-grep)) +(defun helm-do-grep-1 (targets &optional recurse backend exts + default-input input source) "Launch helm using backend BACKEND on a list of TARGETS files. When RECURSE is given and BACKEND is \\='grep' use -r option of @@ -1251,6 +1243,7 @@ It is used currently to specify \\='zgrep' or \\='git'. When BACKEND \\='zgrep' is used don't prompt for a choice in recurse, and ignore EXTS, search being made recursively on files matching `helm-zgrep-file-extension-regexp' only." + (unless source (setq source 'helm-source-grep)) (let* (non-essential (ack-rec-p (helm-grep-use-ack-p :where 'recursive)) (exts (and recurse @@ -1304,6 +1297,12 @@ matching `helm-zgrep-file-extension-regexp' only." 'default-directory helm-ff-default-directory) ;; [1] ;; Setup the source. (set source (helm-make-source src-name 'helm-grep-class + :header-name (and (eq backend 'git) + (lambda (name) + (format "%s [%s]" + name + (abbreviate-file-name + helm-ff-default-directory)))) :backend backend :pcre (string-match-p "\\`ack" com))) (helm @@ -1525,8 +1524,9 @@ non-file buffers." (message nil) (set-process-sentinel (get-buffer-process helm-buffer) - (lambda (_process event) - (if (string= event "finished\n") + (lambda (process event) + (if (or (string= event "finished\n") + (process-get process 'reach-limit)) (with-helm-window (setq mode-line-format '(" " mode-line-buffer-identification " " @@ -1565,7 +1565,6 @@ non-file buffers." :nohighlight t :nomark t :filter-one-by-one #'helm-grep-filter-one-by-one - :candidate-number-limit 9999 :history 'helm-grep-history :keymap helm-pdfgrep-map :help-message 'helm-pdfgrep-help-message @@ -1640,19 +1639,22 @@ returns if available with current AG version." (defun helm-grep-ag-init (directory &optional type) "Start AG process in DIRECTORY maybe searching only files of type TYPE." - (let ((default-directory (or helm-ff-default-directory - (helm-default-directory) - default-directory)) - (cmd-line (helm-grep-ag-prepare-cmd-line - ;; NOTE Encode directory name and pattern, - ;; or it may not work with Chinese and maybe other non-utf8 - ;; characters on MSWindows systems issue#2677 and issue#2678. - (encode-coding-string helm-pattern locale-coding-system) - (or (file-remote-p directory 'localname) - (encode-coding-string directory locale-coding-system)) - type)) - (start-time (float-time)) - (proc-name (helm-grep--ag-command))) + (let* ((default-directory (or helm-ff-default-directory + (helm-default-directory) + default-directory)) + (cmd-line (helm-grep-ag-prepare-cmd-line + ;; NOTE Encode directory name and pattern, + ;; or it may not work with Chinese and maybe other non-utf8 + ;; characters on MSWindows systems issue#2677 and issue#2678. + (encode-coding-string helm-pattern locale-coding-system) + (or (file-remote-p directory 'localname) + (encode-coding-string directory locale-coding-system)) + type)) + (start-time (float-time)) + (proc-name (helm-grep--ag-command)) + ;; Fix error in MacOS with process-buffer deleted resulting in a nil + ;; helm-window (with-helm-window) in sentinel see issue#2741. + (process-connection-type (string= proc-name "ag"))) (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line) (helm-log "helm-grep-ag-init" "Starting %s process in directory `%s'" proc-name directory) @@ -1680,12 +1682,13 @@ returns if available with current AG version." "[%s process finished - (no results)] " ,(upcase proc-name)) 'face 'helm-grep-finish)))))) - ((string= event "finished\n") + ((or (string= event "finished\n") + (process-get process 'reach-limit)) (helm-log "helm-grep-ag-init" "%s process finished with %s results in %fs" proc-name (helm-get-candidate-number) (- (float-time) start-time)) - (helm-maybe-show-help-echo) + (helm-maybe-show-popup-tip-info) (with-helm-window (setq mode-line-format `(" " mode-line-buffer-identification " " @@ -1719,7 +1722,7 @@ grep ag." (point-min) (point-max)) "\n"))) (transfo (helm-get-attr 'filtered-candidate-transformer src)) - (actions (helm-get-attr 'action src)) + (actions helm-grep-actions) (name (helm-get-attr 'name src)) (directory (helm-get-attr 'directory src))) (helm :sources (helm-build-sync-source (format "Search in %s" name) @@ -1755,7 +1758,6 @@ grep ag." (popup-info :initform #'helm-grep-popup-info-fn) (persistent-action :initform 'helm-grep-persistent-action) (persistent-help :initform "Jump to line (`C-u' Record in mark ring)") - (candidate-number-limit :initform 99999) (directory :initarg :directory :initform nil :documentation " Directory currently searched.") @@ -1767,16 +1769,10 @@ grep ag." (defvar helm-source-grep-ag nil) -(cl-defmethod helm--setup-source ((source helm-grep-ag-class)) - (cl-call-next-method) - (helm-aif (and helm-follow-mode-persistent - helm-source-grep-ag - (assoc-default 'follow helm-source-grep-ag)) - (setf (slot-value source 'follow) it))) - -(defun helm-grep-ag-1 (directory &optional type input) +(defun helm-grep-ag-1 (directory &optional type input default) "Start helm ag in DIRECTORY maybe searching in files of type TYPE. -If INPUT is provided, use it as the search string." +Arg DEFAULT is what you will have with `next-history-element', +arg INPUT is what you will have by default at prompt on startup." (setq helm-source-grep-ag (helm-make-source (upcase (helm-grep--ag-command)) 'helm-grep-ag-class :header-name (lambda (name) @@ -1796,6 +1792,7 @@ If INPUT is provided, use it as the search string." (helm :sources 'helm-source-grep-ag :history 'helm-grep-ag-history :input input + :default default :truncate-lines helm-grep-truncate-lines :buffer (format "*helm %s*" (helm-grep--ag-command)))) @@ -1857,6 +1854,22 @@ version." (require 'helm-files) (helm-grep-ag (expand-file-name default-directory) arg)) +;;;###autoload +(defun helm-do-grep-ag-project (arg) + "Preconfigured `helm' for grepping with AG from the current project root. +If no project found use `default-directory'. +With prefix arg prompt for type if available with your AG version." + (interactive "P") + (require 'helm-files) + (require 'project) + (let ((project-root (helm-acase (project-current) + ;; vc returns (type backend path). + ((dst* (_type _backend path)) path) + ;; projectile returns (type . path). + ((dst* (_type . path)) path) + (t default-directory)))) + (helm-grep-ag (expand-file-name project-root) arg))) + ;;;###autoload (defun helm-grep-do-git-grep (arg) "Preconfigured `helm' for git-grepping `default-directory'. diff --git a/elpa/helm-20250515.548/helm-help.el b/elpa/helm-20251212.555/helm-help.el similarity index 99% rename from elpa/helm-20250515.548/helm-help.el rename to elpa/helm-20251212.555/helm-help.el index 45b4c52d..3708ff3c 100644 --- a/elpa/helm-20250515.548/helm-help.el +++ b/elpa/helm-20251212.555/helm-help.el @@ -1183,6 +1183,13 @@ mode or letters, see 'chmod' man page for more infos. NOTE: Another way to change modes on files in helm-find-files is running `\\\\[helm-ff-run-switch-to-shell]' and use 'chmod' directly. +*** Change owner and/or group on files + +Change owner of marked files with `\\\\[helm-ff-run-chown]' and group with `\\\\[helm-ff-run-chgrp]'. +To change both at the same time use e.g. \"user:user\" at prompt. +If you have not the rights to do this, you may have an error (see dired-log), in this case +open the directory as root with tramp methods sudo or su to operate. + *** Delete files You can delete files without quitting helm with @@ -1308,6 +1315,8 @@ If `all-the-icons' package is installed, turning on |\\[helm-ff-run-hardlink-file]|Hardlink files. |\\[helm-ff-run-relsymlink-file]|Relative symlink Files. |\\[helm-ff-run-chmod]|Change mode on Files. +|\\[helm-ff-run-chown]|Change owner on Files. +|\\[helm-ff-run-chgrp]|Change group on Files. |\\[helm-ff-run-delete-file]|Delete Files. |\\[helm-ff-run-touch-files]|Touch files. |\\[helm-ff-run-kill-buffer-persistent]|Kill buffer candidate without leaving Helm. @@ -1361,14 +1370,15 @@ If `all-the-icons' package is installed, turning on "* Helm file name history ** Tips -You can open directly the selected file and exit helm or preselect the file in helm-find-files, -see actions in action menu. -You can toggle the view of deleted files, see commands below. +Helm is turning on `recentf-mode' for you only when calling this command +and if `helm-turn-on-recentf' is non nil. That's mean that the files +opened prior calling this command would not be saved if you didn't +enable `recentf-mode' yourself in your init file or manually. ** Commands \\ -\\[helm-file-name-history-show-or-hide-deleted]|Toggle deleted files view.") +\\[helm-ff-file-name-history-run-ff]|Preselect file in helm-find-files.") ;;; Help for `helm-read-file-name' ;; diff --git a/elpa/helm-20250515.548/helm-id-utils.el b/elpa/helm-20251212.555/helm-id-utils.el similarity index 88% rename from elpa/helm-20250515.548/helm-id-utils.el rename to elpa/helm-20251212.555/helm-id-utils.el index 01469762..e62fe5d7 100644 --- a/elpa/helm-20250515.548/helm-id-utils.el +++ b/elpa/helm-20251212.555/helm-id-utils.el @@ -48,23 +48,25 @@ MacPorts to install id-utils, it should be `gid32'." concat (format " | grep --color=always %s" (shell-quote-argument p)))) default-com)) + (start-time (float-time)) (proc (start-process-shell-command "gid" helm-buffer cmd))) (set (make-local-variable 'helm-grep-last-cmd-line) cmd) (prog1 proc (set-process-sentinel - proc (lambda (_process event) - (when (string= event "finished\n") - (helm-maybe-show-help-echo) + proc (lambda (process event) + (when (or (string= event "finished\n") + (process-get process 'reach-limit)) + (helm-maybe-show-popup-tip-info) (with-helm-window (setq mode-line-format - '(" " mode-line-buffer-identification " " + `(" " mode-line-buffer-identification " " (:eval (format "L%s" (helm-candidate-number-at-point))) " " (:eval (propertize - (format "[Helm Gid process finished - (%s results)]" - (max (1- (count-lines - (point-min) (point-max))) - 0)) + (format "[%s process finished in %.2fs - (%s results)] " + ,(upcase (process-name process)) + ,(- (float-time) start-time) + (helm-get-candidate-number)) 'face 'helm-locate-finish)))) (force-mode-line-update)) (helm-log "helm-gid-candidates-process" "Error: Gid %s" @@ -88,7 +90,6 @@ MacPorts to install id-utils, it should be `gid32'." (filtered-candidate-transformer :initform #'helm-gid-filtered-candidate-transformer) (popup-info :initform #'helm-grep-popup-info-fn) - (candidate-number-limit :initform 99999) (action :initform (helm-make-actions "Find File" 'helm-grep-action "Find file other frame" 'helm-grep-other-frame diff --git a/elpa/helm-20250515.548/helm-imenu.el b/elpa/helm-20251212.555/helm-imenu.el similarity index 99% rename from elpa/helm-20250515.548/helm-imenu.el rename to elpa/helm-20251212.555/helm-imenu.el index 1073134f..07826c5f 100644 --- a/elpa/helm-20250515.548/helm-imenu.el +++ b/elpa/helm-20251212.555/helm-imenu.el @@ -110,9 +110,7 @@ Don't use `setq' to set this." :group 'helm-imenu :type 'boolean :set (lambda (var val) - (if (require helm-x-icons-provider nil t) - (set var val) - (set var nil)))) + (set var (and (require helm-x-icons-provider nil t) val)))) (defcustom helm-imenu-icon-type-alist '(("Array" . (helm-x-icons-generic "crop" :face font-lock-builtin-face)) diff --git a/elpa/helm-20250515.548/helm-info.el b/elpa/helm-20251212.555/helm-info.el similarity index 99% rename from elpa/helm-20250515.548/helm-info.el rename to elpa/helm-20251212.555/helm-info.el index df0fd7b3..b6575fcb 100644 --- a/elpa/helm-20250515.548/helm-info.el +++ b/elpa/helm-20251212.555/helm-info.el @@ -59,10 +59,11 @@ files with `helm-info-at-point'." ;;; Build info-index sources with `helm-info-source' class. -(cl-defun helm-info-init (&optional (file (helm-get-attr 'info-file))) +(defun helm-info-init (&optional file) "Initialize candidates for info FILE. If FILE have nodes, loop through all nodes and accumulate candidates found in each node, otherwise scan only the current info buffer." + (unless file (setq file (helm-get-attr 'info-file))) ;; Allow reinit candidate buffer when using edebug. (helm-aif (and debug-on-error (helm-candidate-buffer)) diff --git a/elpa/helm-20250515.548/helm-locate.el b/elpa/helm-20251212.555/helm-locate.el similarity index 98% rename from elpa/helm-20250515.548/helm-locate.el rename to elpa/helm-20251212.555/helm-locate.el index 7e5aea07..1be9d1a0 100644 --- a/elpa/helm-20250515.548/helm-locate.el +++ b/elpa/helm-20251212.555/helm-locate.el @@ -297,10 +297,10 @@ See also `helm-locate'." (:eval (format "L%s" (helm-candidate-number-at-point))) " " (:eval (propertize (format "[%s process finished - (%s results)]" + ,process-name (max (1- (count-lines (point-min) (point-max))) - 0) - ,process-name) + 0)) 'face 'helm-locate-finish)))) (force-mode-line-update))) @@ -344,7 +344,8 @@ See also `helm-locate'." (mapconcat 'identity it " ")) (shell-quote-argument (car args))))) (default-directory (if (file-directory-p default-directory) - default-directory "/"))) + default-directory "/")) + process-connection-type) (helm-log "helm-locat-init" "Starting helm-locate process") (helm-log "helm-locat-init" "Command line used was:\n\n%s" (concat ">>> " (propertize cmd 'face 'font-lock-comment-face) "\n\n")) @@ -363,7 +364,8 @@ See also `helm-locate'." (insert (concat "* Exit with code 1, no result found," " command line was:\n\n " cmd))))) - ((string= event "finished\n") + ((or (string= event "finished\n") + (process-get process 'reach-limit)) (when (and helm-locate-fuzzy-match (not (string-match-p "\\s-" helm-pattern))) (helm-redisplay-buffer)) diff --git a/elpa/helm-20250515.548/helm-man.el b/elpa/helm-20251212.555/helm-man.el similarity index 69% rename from elpa/helm-20250515.548/helm-man.el rename to elpa/helm-20251212.555/helm-man.el index 06b18103..1174a36f 100644 --- a/elpa/helm-20250515.548/helm-man.el +++ b/elpa/helm-20251212.555/helm-man.el @@ -25,6 +25,7 @@ (defvar woman-manpath) (defvar woman-path) (defvar woman-expanded-directory-path) +(defvar warning-suppress-log-types) (declare-function woman-file-name "woman.el" (topic &optional re-cache)) (declare-function woman-file-name-all-completions "woman.el" (topic)) (declare-function Man-getpage-in-background "man.el" (topic)) @@ -60,6 +61,8 @@ source.") (defvar helm-source-man-pages nil) +(defvar helm-man--tldr-cache nil) + (defun helm-man-default-action (candidate) "Default action for jumping to a woman or man page from Helm." (let ((wfiles (mapcar #'car (woman-file-name-all-completions candidate)))) @@ -82,8 +85,13 @@ source.") (Man-getpage-in-background candidate))))) (defun helm-man--init () - (require 'woman) + "Init caches for helm-man." + (require 'warnings) + (let ((warning-suppress-log-types '((defvaralias)))) + (require 'woman)) (require 'helm-utils) + (unless helm-man--tldr-cache + (setq helm-man--tldr-cache (helm-man--tldr-cache))) (unless helm-man--pages (setq woman-expanded-directory-path (woman-expand-directory-path woman-manpath woman-path)) @@ -93,11 +101,50 @@ source.") (helm-init-candidates-in-buffer 'global helm-man--pages)) (defun helm-man-popup-info (candidate) + "The popup-info function for `helm-man-pages-class'." + ;; On some systems mandb don't run automatically, in this case whatis or man + ;; -f may return nothing. (let ((output (shell-command-to-string (format "man -f '%s'" candidate)))) (when (string-match (format "\\(%s ?([^(]+)\\) *- ?\\(.*\\)\n" candidate) output) (match-string 2 output)))) +(defun helm-man-tldr-render (command) + "Display the output of `tldr' command." + (with-current-buffer-window "*tldr*" '(display-buffer-full-frame) nil + (let ((status (call-process "tldr" nil t nil "--color" "always" command)) + map) + (when (zerop status) + (ansi-color-apply-on-region (point-min) (point-max)) + (goto-char (point-min)) + (setq map (let ((m (make-sparse-keymap))) + (define-key m (kbd "") #'browse-url-at-point) + (define-key m [mouse-1] #'browse-url-at-point) + m)) + (save-excursion + (while (re-search-forward "http[s]://" nil t) + (let* ((pos (bounds-of-thing-at-point 'url)) + (ov (make-overlay (car pos) (cdr pos)))) + (overlay-put ov 'face 'font-lock-keyword-face) + (overlay-put ov 'keymap map) + (overlay-put ov 'mouse-face 'highlight) + (overlay-put ov 'help-echo "mouse-1: Browse url")))) + (local-set-key "q" 'quit-window))))) + +(defun helm-man--tldr-cache () + "Return the output of tldr -l as a list." + (when (executable-find "tldr") + (with-temp-buffer + (call-process "tldr" nil t nil "-l") + (split-string (buffer-string) "\n")))) + +(defun helm-man-action-transformer (actions _candidate) + "The action transformer fn for `helm-man-woman'." + (let ((disp (helm-get-selection nil t))) + (if (member disp helm-man--tldr-cache) + (append actions '(("Tldr" . helm-man-tldr-render))) + actions))) + (defclass helm-man-pages-class (helm-source-in-buffer) ((popup-info :initform #'helm-man-popup-info))) @@ -108,7 +155,8 @@ With a prefix ARG reinitialize the cache. To have a popup showing a basic description of selected candidate, turn on `helm-popup-tip-mode'." (interactive "P") - (when arg (setq helm-man--pages nil)) + (when arg (setq helm-man--pages nil + helm-man--tldr-cache nil)) (unless helm-source-man-pages (setq helm-source-man-pages (helm-make-source "Manual Pages" 'helm-man-pages-class @@ -117,6 +165,7 @@ showing a basic description of selected candidate, turn on :filtered-candidate-transformer (lambda (candidates _source) (sort candidates #'helm-generic-sort-fn)) + :action-transformer 'helm-man-action-transformer :action '(("Display Man page" . helm-man-default-action)) :group 'helm-man))) (helm :sources 'helm-source-man-pages diff --git a/elpa/helm-20250515.548/helm-misc.el b/elpa/helm-20251212.555/helm-misc.el similarity index 99% rename from elpa/helm-20250515.548/helm-misc.el rename to elpa/helm-20251212.555/helm-misc.el index 53d0505b..e708e7c5 100644 --- a/elpa/helm-20250515.548/helm-misc.el +++ b/elpa/helm-20251212.555/helm-misc.el @@ -379,6 +379,7 @@ Default action change TZ environment variable locally to emacs." (defun helm-outline (&optional arg) "Basic helm navigation tool for outline buffers." (interactive "P") + (require 'outline) (let ((outline-regexp (if arg (read-regexp "Outline regexp") outline-regexp))) (helm :sources (helm-build-sync-source "helm outline" :candidates diff --git a/elpa/helm-20250515.548/helm-mode.el b/elpa/helm-20251212.555/helm-mode.el similarity index 96% rename from elpa/helm-20250515.548/helm-mode.el rename to elpa/helm-20251212.555/helm-mode.el index 5b2cce3b..32a68112 100644 --- a/elpa/helm-20250515.548/helm-mode.el +++ b/elpa/helm-20251212.555/helm-mode.el @@ -299,6 +299,12 @@ Where FUNCTION is a function suitable for `helm-quit-and-find-file'.") '((t :inherit font-lock-property-name-face)) "Face used to highlight annotations in completion." :group 'helm-mode) + +(defface helm-completions-key-binding + '((t :inherit font-lock-constant-face)) + "Face used to highlight key binding in completion." + :group 'helm-mode) + (defvar helm-comp-read-map (let ((map (make-sparse-keymap))) @@ -468,9 +474,8 @@ to use a list as return value when `helm-mode' is enabled, e.g. (let ((debug-on-quit nil)) (signal 'quit nil))) -(cl-defun helm-comp-read-get-candidates (collection &optional - test sort-fn alistp - (input helm-pattern)) +(defun helm-comp-read-get-candidates (collection + &optional test sort-fn alistp input) "Convert COLLECTION to list removing elements that don't match TEST. See `helm-comp-read' about supported COLLECTION arguments. @@ -510,6 +515,7 @@ with an empty string as value for `helm-pattern' because data would not be fully collected at init time. If COLLECTION is an `obarray', a TEST should be needed. See `obarray'." + (unless input (setq input helm-pattern)) ;; Ensure COLLECTION is computed from `helm-current-buffer' ;; because some functions used as COLLECTION work ;; only in the context of current-buffer (Bug#1030) . @@ -572,7 +578,8 @@ If COLLECTION is an `obarray', a TEST should be needed. See `obarray'." (t (all-completions input collection test))))) (if sort-fn (sort cands sort-fn) cands)))) -(cl-defun helm-cr--pattern-in-candidates-p (candidates &optional (pattern helm-pattern)) +(defun helm-cr--pattern-in-candidates-p (candidates &optional pattern) + (unless pattern (setq pattern helm-pattern)) (or (assoc pattern candidates) (assoc (concat " " pattern) candidates) (assq (intern pattern) candidates) @@ -1046,9 +1053,11 @@ that use `helm-comp-read'. See `helm-M-x' for example." (flags . (helm-completing-read--buffer-lgst-mode)))) (symbol-help . (metadata (affixation-function . helm-symbol-completion-table-affixation) + (persistent-fn . t) (category . symbol-help))) (command-help . (metadata (prefix-arg . t) + (persistent-fn . t) (affixation-function . helm-symbol-completion-table-affixation) (category . symbol-help))) (eww-help . (metadata ;; Emacs-30 only @@ -1077,12 +1086,18 @@ that use `helm-comp-read'. See `helm-M-x' for example." (category . man))) (info . (metadata (affixation-function . helm-completion-info-file-affixation) - (category . info)))) + (category . info))) + (bookmark . (metadata + (affixation-function . helm-completion-bookmark-affixation) + (category . bookmark)))) "Extra metadatas for completing-read. It is used to add `affixation-function' or `annotation-function' if original metadata doesn't have some or to override existing metadata according to the category extracted from current metadata. +Helm provides as well an extra property called `popup-info-function' for +categories where it would be too costly to extract informations for all +candidates (See \\='man' category). It is an alist composed of (CATEGORY . METADATA) elements. CATEGORY is a symbol specifying the category according @@ -1100,6 +1115,7 @@ FLAGS is a list of variables to renitialize to nil when exiting or quitting.") (defvar helm-completing-read-command-categories '(("man" . man) + ("manual-entry" . man) ("customize-variable" . symbol-help) ("customize-set-variable" . symbol-help) ("customize-set-value" . symbol-help) @@ -1116,6 +1132,7 @@ FLAGS is a list of variables to renitialize to nil when exiting or quitting.") ("trace-function-foreground" . symbol-help) ("trace-function-background" . symbol-help) ("describe-minor-mode" . symbol-help) + ("toggle-option" . symbol-help) ("where-is" . symbol-help) ("execute-extended-command" . symbol-help) ("execute-extended-command-for-buffer" . command-help) @@ -1149,7 +1166,8 @@ FLAGS is a list of variables to renitialize to nil when exiting or quitting.") ("list-charset-chars" . charset) ("info-display-manual" . info) ;; Emacs-30 only - ("eww" . eww-help)) + ("eww" . eww-help) + ("bookmark-jump" . bookmark)) "An alist to specify metadata category by command. Some commands provide a completion-table with no category @@ -1160,6 +1178,8 @@ should be specified as a string and the category as a symbol.") ;; We can't reuse the function from helm-man.el because the candidates are here ;; differents e.g. apt vs apt(8). (defun helm-completion-man-popup-info (candidate) + "Popup-info function for `man' category. +See `helm-completing-read-extra-metadata'." ;; Man has the stupid habit to use symbol at point as default, try to not ;; match it. (let* ((com (if (string-match "\\(.*\\) ?([^()]+)" candidate) @@ -1172,6 +1192,8 @@ should be specified as a string and the category as a symbol.") (defvar helm-completing-read--buffer-lgst-mode nil) (defun helm-completing-read-buffer-affixation (completions) + "Affixation function for `buffer' category. +See `helm-completing-read-extra-metadata'." (let ((len-mode (or helm-completing-read--buffer-lgst-mode (setq helm-completing-read--buffer-lgst-mode (cl-loop for bn in completions @@ -1221,7 +1243,10 @@ should be specified as a string and the category as a symbol.") (propertize " " 'display suffix)))))) (defun helm-symbol-completion-table-affixation (_completions) - "Override `help--symbol-completion-table-affixation'. + "Affixation function for `symbol-help' category. +See `helm-completing-read-extra-metadata'. + +Override `help--symbol-completion-table-affixation'. Normally affixation functions use COMPLETIONS as arg, and return a list of modified COMPLETIONS. Now we allow affixations functions to return a @@ -1261,7 +1286,8 @@ is used." ;; Not already defined function. To test add an advice on a non ;; existing function. (propertize comp 'face 'helm-completion-invalid)) - ;; Prefixes. + ;; Prefixes meaning: (see `help--symbol-class' which returns such strings for a + ;; given symbol). ;; " c " command ;; " - " obsolete, 'byte-obsolete-info ;; " v " var, not a defcustom @@ -1294,9 +1320,11 @@ is used." (let* ((key (and (commandp sym) (where-is-internal sym nil 'first-only))) (binding (and key (key-description key)))) (when binding - (propertize (format " (%s)" binding) 'face 'shadow))))) + (propertize (format " (%s)" binding) 'face 'helm-completions-key-binding))))) (defun helm-completion-package-affixation (_completions) + "Affixation function for `package' category. +See `helm-completing-read-extra-metadata'." (lambda (comp) (let* ((sym (intern-soft comp)) (id (package-get-descriptor sym)) @@ -1317,7 +1345,20 @@ is used." (propertize " " 'display (concat sep it))) ""))))) +(defun helm-completion-bookmark-affixation (_completions) + "Affixation function for `bookmark' category. +See `helm-completing-read-extra-metadata'." + (lambda (comp) + (let* ((sep (helm-make-separator comp)) + (loc (bookmark-location comp))) + (list (propertize comp 'face 'bookmark-menu-bookmark) + "" + (helm-aand (propertize loc 'face 'helm-completions-detailed) + (propertize " " 'display (concat sep it))))))) + (defun helm-completion-theme-affixation (_completions) + "Affixation function for `theme' category. +See `helm-completing-read-extra-metadata'." (lambda (comp) (let* ((sym (intern-soft comp)) (sep (helm-make-separator comp)) @@ -1362,6 +1403,8 @@ is used." (buffer-substring beg end)))) (defun helm-completion-coding-system-affixation (_comps) + "Affixation function for `coding-system' category. +See `helm-completing-read-extra-metadata'." (require 'mule-diag) (lambda (comp) (let ((doc (with-output-to-string @@ -1374,6 +1417,8 @@ is used." (propertize " " 'display (concat sep it))))))) (defun helm-completion-charset-affixation (_comps) + "Affixation function for `charset' category. +See `helm-completing-read-extra-metadata'." (lambda (comp) (let ((doc (charset-description (intern comp))) (sep (helm-make-separator comp))) @@ -1381,6 +1426,8 @@ is used." (propertize " " 'display (concat sep it))))))) (defun helm-completion-color-affixation (_comps) + "Affixation function for `color' category. +See `helm-completing-read-extra-metadata'." (lambda (comp) (let ((sep (helm-make-separator comp)) (rgb (condition-case nil @@ -1399,6 +1446,8 @@ is used." (propertize " " 'display (concat sep it))))))) (defun helm-completion-library-affixation (_comps) + "Affixation function for `library' category. +See `helm-completing-read-extra-metadata'." ;; We share here the same cache as `helm-locate-library'. (require 'helm-elisp) (lambda (comp) @@ -1422,6 +1471,8 @@ is used." (propertize " " 'display (concat sep it)))))))) (defun helm-completion-eww-affixation (_completions) + "Affixation function for `eww-help' category. +See `helm-completing-read-extra-metadata'." (lambda (comp) (let* ((title (or (cl-loop for bmk in eww-bookmarks for title = (plist-get bmk :title) @@ -1437,6 +1488,8 @@ is used." "")))) (defun helm-completion-info-file-affixation (_completions) + "Affixation function for `info' category. +See `helm-completing-read-extra-metadata'." ;; We share here the same cache as `helm-info'. (require 'info) (require 'helm-info) @@ -1519,7 +1572,7 @@ dynamically otherwise use `helm-completing-read-default-2'." metadata 'display-sort-function) (lambda (candidates) (sort candidates #'helm-generic-sort-fn))))) - popup-info flags pref-arg keymap) + popup-info flags pref-arg pers-fn keymap) (helm-aif (and (null category) (assoc-default name helm-completing-read-command-categories)) (setq metadata `(metadata (category . ,it)) @@ -1533,6 +1586,8 @@ dynamically otherwise use `helm-completing-read-default-2'." afix (completion-metadata-get metadata 'affixation-function) ;; prefix-arg metadata is only in command-help category. pref-arg (completion-metadata-get metadata 'prefix-arg) + pers-fn (and (completion-metadata-get metadata 'persistent-fn) + (helm-mode--get-persistent-fn name)) popup-info (completion-metadata-get metadata 'popup-info-function) flags (completion-metadata-get metadata 'flags)))) (setq keymap (if pref-arg @@ -1544,7 +1599,8 @@ dynamically otherwise use `helm-completing-read-default-2'." prompt (if pref-arg (concat (helm-acase helm-M-x-prefix-argument (- "-") - ((dst* l &rest args) + ;; Why &rest? isn't this always a list of one arg? + ((dst* (l &rest args)) (if (eq l 4) "C-u " (format "%d " l))) ((guard* (integerp it)) (format "%d " it))) prompt) @@ -1574,8 +1630,8 @@ dynamically otherwise use `helm-completing-read-default-2'." :alistp alistp :diacritics helm-mode-ignore-diacritics :help-message #'helm-comp-read-help-message - :persistent-action (and pref-arg #'helm-M-x-persistent-action) - :persistent-help (if pref-arg "Toggle Describe command" "DoNothing") + :persistent-action pers-fn + :persistent-help (if pers-fn (format "Toggle %s" name) "DoNothing") :name name :requires-pattern (if (and (stringp default) (string= default "") @@ -1614,6 +1670,16 @@ dynamically otherwise use `helm-completing-read-default-2'." (when pref-arg (helm-M-x--unwind-forms)) (dolist (f flags) (set f nil))))) +(defun helm-mode--get-persistent-fn (name) + "Return a lambda to use in symbol-help persistent-action for NAME." + (lambda (candidate) + (helm-elisp--persistent-help + candidate + (helm-acase name + ("describe-symbol" 'helm-describe-symbol) + ("describe-variable" 'helm-describe-variable) + (t 'helm-describe-function))))) + (defun helm--advice-command-execute (old--fn &rest args) (helm-M-x--unwind-forms 'done) ;; `command-execute' is wrapped in a let with `prefix-arg' bound to the argument @@ -2157,8 +2223,8 @@ Keys description: (unless (eq must-match t) ;; Non existing file or dir source. (helm-build-dummy-source "New file or directory" - :keymap 'helm-read-file-map - :must-match must-match + :keymap helm-read-file-map + :must-match must-match ; Merge must-match-map and helm-read-file-map. :all-marked all-marked :nomark nomark :filtered-candidate-transformer @@ -2181,7 +2247,6 @@ Keys description: :persistent-action-if persistent-action-if :persistent-help persistent-help :keymap helm-read-file-map - :must-match must-match :nomark nomark :action action-fn) ;; List files source. @@ -2213,6 +2278,10 @@ Keys description: (remhash helm-ff-default-directory helm-ff--list-directory-cache)) :match-on-real t + :match (unless helm-find-files-ignore-diacritics + 'helm-mm-3f-match) + :diacritics (and helm-find-files-ignore-diacritics + 'helm-mm-3f-match-on-diacritics) :filtered-candidate-transformer '(helm-ff-fct helm-ff-maybe-show-thumbnails helm-ff-sort-candidates) @@ -2220,8 +2289,12 @@ Keys description: :persistent-action-if persistent-action-if :persistent-help persistent-help :volatile t + ;; Because we don't use :must-match in this source, + ;; helm-read-file-map is NOT merged with must-match map, this to + ;; not override helm-ff-RET, so MUST-MATCH == t is handled by + ;; helm-ff-RET, otherwise the dummy source enter in action and + ;; handle the other possible values of MUST-MATCH. :keymap helm-read-file-map - :must-match must-match :cleanup 'helm-find-files-cleanup :nomark nomark :action action-fn))) @@ -2241,7 +2314,8 @@ Keys description: :default default :buffer buffer :full-frame nil - :preselect preselect))) + :preselect preselect)) + (helm-mm-matching-method 'multi3f)) (or (cond ((and result (stringp result) (string= result "") "")) @@ -2266,18 +2340,19 @@ Keys description: (setq fname (expand-file-name (or initial buffer-file-name dir) dir))) + ;; completing-read default maybe a list of defaults. (if (and fname (consp fname)) - (setq fname (cl-loop for f in fname - collect (if (file-name-absolute-p fname) - (expand-file-name - f (helm-mode-root-dir dir)) - (expand-file-name fname dir)))) - (if (file-name-absolute-p fname) - (if (file-remote-p fname) - fname - (substitute-in-file-name - (concat (helm-mode-root-dir dir) fname))) - (expand-file-name fname dir)))) + (cl-loop for f in fname + collect (helm-mode--resolve-fname f dir)) + (helm-mode--resolve-fname fname dir))) + +(defun helm-mode--resolve-fname (fname dir) + (if (file-name-absolute-p fname) + (if (file-remote-p fname) + fname + (substitute-in-file-name + (concat (helm-mode-root-dir dir) fname))) + (expand-file-name fname dir))) (defun helm-mode-root-dir (dir) (if (file-remote-p dir) @@ -2786,6 +2861,13 @@ is non-nil." Can be used for `completion-in-region-function' by advicing it with an :around advice to allow passing the old `completion-in-region-function' value in ORIGFUN." + ;; This error may happen when user hits quickly twice e.g. TAB for + ;; completion-at-point which start a second time this function because the + ;; first helm-buffer with its keymap is not ready yet (this happen when helm is + ;; displayed in a frame which is slower to popup than a window). FIXME: Should + ;; I prevent this at a lower level as well? + (cl-assert (not (get-buffer-window helm-buffer 'visible)) nil + "Error: Trying to run helm while a helm session is already running") (if (memq major-mode helm-mode-no-completion-in-region-in-modes) (funcall origfun start end collection predicate) (advice-add diff --git a/elpa/helm-20250515.548/helm-net.el b/elpa/helm-20251212.555/helm-net.el similarity index 88% rename from elpa/helm-20250515.548/helm-net.el rename to elpa/helm-20251212.555/helm-net.el index 98baa667..0540c828 100644 --- a/elpa/helm-20250515.548/helm-net.el +++ b/elpa/helm-20251212.555/helm-net.el @@ -260,6 +260,7 @@ Can be \"--new-tab\" (default), \"--new-window\" or \"--private-window\"." ;; also `helm-browse-url-default-browser-alist'. (defvar helm-browse-url-chromium-program "chromium-browser") +(defvar helm-browse-url-brave-program "brave-browser") (defvar helm-browse-url-uzbl-program "uzbl-browser") (defvar helm-browse-url-nyxt-program "nyxt") (defvar helm-browse-url-conkeror-program "conkeror") @@ -270,6 +271,7 @@ Can be \"--new-tab\" (default), \"--new-window\" or \"--private-window\"." '((helm-browse-url-w3m-program . w3m-browse-url) (browse-url-firefox-program . browse-url-firefox) (helm-browse-url-chromium-program . helm-browse-url-chromium) + (helm-browse-url-brave-program . helm-browse-url-brave) (helm-browse-url-conkeror-program . helm-browse-url-conkeror) (helm-browse-url-opera-program . helm-browse-url-opera) (helm-browse-url-uzbl-program . helm-browse-url-uzbl) @@ -283,7 +285,7 @@ Can be \"--new-tab\" (default), \"--new-window\" or \"--private-window\"." ("emacs" . eww-browse-url)) "Alist of (browse_url_variable . function) to try to find a suitable url browser.") -(cl-defun helm-generic-browser (url cmd-name &rest args) +(defun helm-generic-browser (url cmd-name &rest args) "Browse URL with NAME browser." (let ((proc (concat cmd-name " " url))) (message "Starting %s..." cmd-name) @@ -295,6 +297,24 @@ Can be \"--new-tab\" (default), \"--new-window\" or \"--private-window\"." (when (string= event "finished\n") (message "%s process %s" process event)))))) +(defun helm-browse-url-detached (cmd url &optional new-tab) + "Browse URL with browser CMD and detach it from Emacs. + +NEW-TAB is the command line argument supported by CMD e.g. \"--new-tab\". + +So when you quit Emacs you can keep your browser session open and +not be prompted to kill the browser process. + +NOTE: Probably not supported on some systems (e.g., Windows)." + (setq url (browse-url-encode-url url)) + (setq new-tab (if (stringp new-tab) + (concat " " (replace-regexp-in-string + " " "" new-tab)) + "")) + (let ((process-environment (browse-url-process-environment))) + (call-process-shell-command + (format "(%s%s %s &)" cmd new-tab (shell-quote-argument url))))) + ;;;###autoload (defun helm-browse-url-firefox (url &optional _ignore) "Same as `browse-url-firefox' but detach from Emacs. @@ -305,13 +325,8 @@ not be prompted to kill the Firefox process. NOTE: Probably not supported on some systems (e.g., Windows)." (interactive (list (read-string "URL: " (browse-url-url-at-point)) nil)) - (setq url (browse-url-encode-url url)) - (let ((process-environment (browse-url-process-environment))) - (call-process-shell-command - (format "(%s %s %s &)" - browse-url-firefox-program - helm-browse-url-firefox-new-window - (shell-quote-argument url))))) + (helm-browse-url-detached browse-url-firefox-program url + helm-browse-url-firefox-new-window)) ;;;###autoload (defun helm-browse-url-opera (url &optional _ignore) @@ -323,18 +338,35 @@ not be prompted to kill the Opera process. NOTE: Probably not supported on some systems (e.g., Windows)." (interactive (list (read-string "URL: " (browse-url-url-at-point)) nil)) - (setq url (browse-url-encode-url url)) - (let ((process-environment (browse-url-process-environment))) - (call-process-shell-command - (format "(%s %s &)" - helm-browse-url-opera-program (shell-quote-argument url))))) + (helm-browse-url-detached helm-browse-url-opera-program url)) ;;;###autoload (defun helm-browse-url-chromium (url &optional _ignore) - "Browse URL with Google Chrome browser." - (interactive "sURL: ") - (helm-generic-browser - url helm-browse-url-chromium-program)) + "Same as `browse-url-chromium' but detach from emacs. + +So when you quit Emacs you can keep your Chromium session open and +not be prompted to kill the Chromium process. + +NOTE: Probably not supported on some systems (e.g., Windows)." + (interactive (list (read-string "URL: " (browse-url-url-at-point)) + nil)) + (helm-browse-url-detached + helm-browse-url-chromium-program url)) + +;;;###autoload +(defun helm-browse-url-brave (url &optional _ignore) + "Browse URL with Brave browser and detach from emacs. + +Brave browser executable is determined by `helm-browse-url-brave-program'. + +So when you quit Emacs you can keep your Opera session open and +not be prompted to kill the Opera process. + +NOTE: Probably not supported on some systems (e.g., Windows)." + (interactive (list (read-string "URL: " (browse-url-url-at-point)) + nil)) + (helm-browse-url-detached + helm-browse-url-brave-program url "--new-tab")) ;;;###autoload (defun helm-browse-url-uzbl (url &optional _ignore) diff --git a/elpa/helm-20250515.548/helm-occur.el b/elpa/helm-20251212.555/helm-occur.el similarity index 95% rename from elpa/helm-20250515.548/helm-occur.el rename to elpa/helm-20251212.555/helm-occur.el index 931ecf5b..f523b0f1 100644 --- a/elpa/helm-20250515.548/helm-occur.el +++ b/elpa/helm-20251212.555/helm-occur.el @@ -172,20 +172,24 @@ This happen only in `helm-source-occur' which is always related to (string-equal helm-pattern "")) (with-helm-window (let ((lst '()) + ;; `helm-source-occur' name is "Helm occur" when using `helm-occur' + ;; command (searching and starting from current-buffer), whereas it + ;; has the name of current-buffer when using `helm-multi-occur-1'. (name (helm-get-attr 'name helm-source-occur)) closest beg end) (while-no-input (goto-char (point-min)) - (if (string= name "Helm occur") - (setq beg (point) - end (point-max)) - (helm-awhile (helm-get-next-header-pos) - (when (string= name (buffer-substring-no-properties - (pos-bol) (pos-eol))) - (forward-line 1) - (setq beg (point) - end (or (helm-get-next-header-pos) (point-max))) - (cl-return)))) + (cond ((string= name "Helm occur") + (setq beg (point) + end (point-max))) + ;; The source corresponding to helm-current-buffer should be + ;; always on top, so no need to search for it by looping in + ;; helm-buffer. + ((string= name (buffer-substring-no-properties + (pos-bol) (pos-eol))) + (forward-line 1) + (setq beg (point) + end (or (helm-get-next-header-pos) (point-max))))) (save-excursion (when (and beg end) (goto-char beg) @@ -410,8 +414,18 @@ helm-occur will start immediately with DEFAULT as INPUT. Always prefer using DEFAULT instead of INPUT, they have the same effect but DEFAULT keep the minibuffer empty, allowing the user to write immediately without having to delete its contents before." - (let* ((curbuf (current-buffer)) - (bufs (if helm-occur-always-search-in-current + (let* ((curbuf (get-buffer (if helm-alive-p + ;; We are starting from a helm session listing + ;; buffers, presumably helm-buffers-list or + ;; helm-mini. If we don't check for + ;; helm-alive-p and helm-multi-occur-1 is + ;; launched from e.g. isl or isearch we may + ;; reuse a old helm-current-buffer value from + ;; last helm-session. + helm-current-buffer + (current-buffer)))) + (bufs (if (or helm-occur-always-search-in-current + (memql curbuf buffers)) (cons curbuf (remove curbuf buffers)) buffers)) (helm-sources-using-default-as-input @@ -431,7 +445,7 @@ without having to delete its contents before." (cl-loop for b in bufs collect (buffer-chars-modified-tick (get-buffer b)))) - (when (and helm-occur-always-search-in-current + (when (and (eql (car bufs) curbuf) helm-occur-keep-closest-position) (setq helm-source-occur (cl-loop for s in sources @@ -453,11 +467,11 @@ without having to delete its contents before." ;;; Actions ;; -(cl-defun helm-occur-action (lineno - &optional (method (quote buffer))) +(defun helm-occur-action (lineno &optional method) "Jump to line number LINENO with METHOD. METHOD can be one of buffer, buffer-other-window, buffer-other-frame." (require 'helm-grep) + (unless method (setq method 'buffer)) (let ((buf (if (eq major-mode 'helm-occur-mode) (get-text-property (point) 'buffer-name) (helm-get-attr 'buffer-name))) diff --git a/elpa/helm-20250515.548/helm-packages.el b/elpa/helm-20251212.555/helm-packages.el similarity index 62% rename from elpa/helm-20250515.548/helm-packages.el rename to elpa/helm-20251212.555/helm-packages.el index 181c128f..e0e8af5d 100644 --- a/elpa/helm-20250515.548/helm-packages.el +++ b/elpa/helm-20251212.555/helm-packages.el @@ -27,6 +27,21 @@ (declare-function dired-async-mode-line-message "ext:dired-async.el") + +;; Urls for cloning. +(defvar helm-packages-recipes-alist '(("melpa" . "https://melpa.org/packages/elpa-packages.eld") + ("gnu" . "https://elpa.gnu.org/packages/elpa-packages.eld") + ("nongnu" . "https://elpa.nongnu.org/nongnu/elpa-packages.eld")) + "Adresses where to find recipes or urls for packages.") + +;; Caches for recipes (elpa-packages.eld contents). +(defvar helm-packages--gnu-elpa-recipes-cache nil) +(defvar helm-packages--nongnu-elpa-recipes-cache nil) +(defvar helm-packages--melpa-recipes-cache nil) + +;; EmacsMirror +(defvar helm-packages-fallback-url-for-cloning "https://github.com/emacsmirror/%s") + (defgroup helm-packages nil "Helm interface for package.el." @@ -58,6 +73,15 @@ "The function to isolate package. `package-isolate' is available only in emacs-30+." :type 'function) + +(defcustom helm-packages-default-clone-directory nil + "Default directory where to clone packages." + :type 'string) + +(defcustom helm-packages-clone-after-hook nil + "Hook that run after cloning a package. +It is called with two args respectively PACKAGE as a string and DIRECTORY." + :type 'hook) ;;; Actions ;; @@ -80,17 +104,18 @@ "Helm action for describing package CANDIDATE." (describe-package candidate)) +(defun helm-packages-get-homepage-url (candidate) + "Get package CANDIDATE home page url." + (let* ((id (package-get-descriptor candidate)) + (extras (package-desc-extras id))) + (and (listp extras) (cdr-safe (assoc :url extras))))) + (defun helm-packages-visit-homepage (candidate) "Helm action for visiting package CANDIDATE home page." - (let* ((id (package-get-descriptor candidate)) - (name (package-desc-name id)) - (extras (package-desc-extras id)) - (url (and (listp extras) (cdr-safe (assoc :url extras))))) + (let ((url (helm-packages-get-homepage-url candidate))) (if (stringp url) (browse-url url) - (message "Package %s has no homepage" - (propertize (symbol-name name) - 'face 'font-lock-keyword-face))))) + (message "Package `%s' has no homepage" candidate)))) (defun helm-packages-package-reinstall (_candidate) "Helm action for reinstalling marked packages." @@ -211,6 +236,132 @@ Arg PACKAGES is a list of strings." (expand-file-name (package-desc-dir pkg)) package-user-dir))) +;;; Cloning packages +;; +(defun helm-packages-fetch-recipe (url) + "Fetch package recipes from URL. +They are generally contained in a file named elpa-packages.eld on remote which +contains the urls needed for cloning packages, each entry is like +\(foo :url \"somewhere\") and may contain as well :branch." + (with-temp-buffer + (url-insert-file-contents url) + (goto-char (point-min)) + (let ((data (read (current-buffer)))) + ;; Recipes do not have the same form depending from + ;; where we fetch them, they may be like + ;; ((foo :url "somewhere") + ;; (bar :url "somewhere")) + ;; or + ;; (((foo :url "somewhere") + ;; (bar :url "somewhere")) + ;; :version "1" :else "") + (if (keywordp (cadr data)) (car data) data)))) + +(defun helm-packages-get-package-url (package provider) + "Get PACKAGE url from PROVIDER's recipe. +Returns a plist like (:url :branch ). +PROVIDER can be one of \"melpa\", \"gnu\" or \"nongnu\"." + (let* ((address (assoc-default provider helm-packages-recipes-alist)) + (cache (helm-acase provider + ("gnu" 'helm-packages--gnu-elpa-recipes-cache) + ("nongnu" 'helm-packages--nongnu-elpa-recipes-cache) + ("melpa" 'helm-packages--melpa-recipes-cache))) + (recipe (or (symbol-value cache) + (set cache (helm-packages-fetch-recipe address)))) + (package-recipe (assq package recipe)) + (core (plist-get (cdr package-recipe) :core)) + (url (or (plist-get (cdr package-recipe) :url) + ;; Assume that when :url = nil the package is maintained in + ;; elpa or nongnu. When recipe is fetched from package-archives + ;; addresses the url is always specified or the package if not + ;; clonable not present at all e.g. cond-star. + (helm-acase provider + ("gnu" "https://git.sv.gnu.org/git/emacs/elpa.git") + ("nongnu" "https://git.sv.gnu.org/git/emacs/nongnu.git")))) + (branch (plist-get (cdr package-recipe) :branch))) + (cl-assert package-recipe nil (format "Couldn't find package '%s'" package)) + (cl-assert (null core) nil + (format "Package '%s' already provided in Emacs at '%s'" + package core)) + (unless (stringp url) + ;; Sometimes the recipe for a package refers to the same url as another + ;; package by setting :url to the name of this package (symbol) e.g. + ;; In nongnu recipe, we have: + ;; (helm :url "https://...") and (helm-core :url helm) + (setq url (and url (plist-get (cdr (assq url recipe)) :url)))) + `(:url ,url :branch ,branch))) + +(defun helm-packages-get-provider (package) + (let ((desc (assq package package-archive-contents))) + (package-desc-archive (cadr desc)))) + +(defun helm-packages-get-recipe-for-cloning (package) + (let ((provider (helm-packages-get-provider package))) + (helm-packages-get-package-url package provider))) + +(defun helm-packages-clone-package (package) + "Git clone PACKAGE." + (let* ((name (symbol-name package)) + (directory (read-directory-name + "Clone in directory: " + helm-packages-default-clone-directory nil t)) + (recipe (helm-packages-get-recipe-for-cloning package)) + (url (plist-get recipe :url)) + (branch (plist-get recipe :branch)) + (fix-url (if (or (string-match "\\.git\\'" url) + ;; For git-remote-hg. + (string-match "\\`hg::" url)) + url + (concat url ".git"))) + ;; In gnu archive all packages maintained on Elpa are pointing to + ;; "https://git.sv.gnu.org/git/emacs/elpa.git", to be able to clone a + ;; package from such url we have to use: + ;; git clone --single-branch -b externals/ URL PACKAGE-NAME. + ;; This create a directory named PACKAGE-NAME with only PACKAGE inside. + ;; If PACKAGE-NAME is ommited this create a repo named elpa which clash if + ;; such a dir already exists. Another case is packages coming either + ;; from nongnu or melpa giving the nongnu url as :url and specifying a + ;; branch, example: + ;; (ws-butler :url "https://git.savannah.gnu.org/git/emacs/nongnu.git" + ;; :branch "elpa/ws-butler") + (switches (append + (if (string-match "\\(elpa\\|nongnu\\)\\.git\\'" url) + `("clone" "--single-branch" + "-b" ,(or branch (format "externals/%s" package))) + (delq nil `("clone" ,(and branch "-b") ,branch))) + `(,fix-url ,name)))) + (cl-assert (not (file-directory-p (expand-file-name name directory))) + nil (format "Package already exists in %s" directory)) + (with-helm-default-directory directory + (let* (process-connection-type + (proc (apply #'start-process + "git" "*helm packages clone*" + "git" switches))) + (save-selected-window + (display-buffer (process-buffer proc) + '(display-buffer-below-selected + (window-height . fit-window-to-buffer) + (preserve-size . (nil . t))))) + (set-process-filter proc #'helm-packages--clone-filter-process) + (set-process-sentinel + proc (lambda (proc event) + (let ((status (process-exit-status proc))) + (if (string= event "finished\n") + (message "Cloning package %s done" package) + (message "Cloning package %s failed" package)) + (when (= status 0) + (quit-window t (get-buffer-window (process-buffer proc))) + (run-hook-with-args + 'helm-packages-clone-after-hook + (symbol-name package) directory))))) + (message "Cloning package %s..." package))))) + +(defun helm-packages--clone-filter-process (proc string) + (when (buffer-live-p (process-buffer proc)) + (with-current-buffer (process-buffer proc) + (erase-buffer) + (insert (car (split-string string " ")))))) + ;;; Transformers ;; ;; @@ -280,7 +431,14 @@ Arg PACKAGES is a list of strings." (defvar helm-packages--updated nil) (defun helm-packages--refresh-contents () - (unless helm-packages--updated (package-refresh-contents)) + (unless helm-packages--updated + (setq helm-packages--gnu-elpa-recipes-cache nil + helm-packages--nongnu-elpa-recipes-cache nil + helm-packages--melpa-recipes-cache nil) + (setq package-menu--old-archive-contents package-archive-contents) + (setq package-menu--new-package-list nil) + (package-refresh-contents) + (package-menu--populate-new-package-list)) (helm-set-local-variable 'helm-packages--updated t)) (defun helm-finder--list-matches (key) @@ -318,7 +476,8 @@ Arg PACKAGES is a list of strings." '(("Install packages(s)" . helm-packages-install))))) :action '(("Describe package" . helm-packages-describe) - ("Visit homepage" . helm-packages-visit-homepage))) + ("Visit homepage" . helm-packages-visit-homepage) + ("Clone package" . helm-packages-clone-package))) :buffer "*helm finder results*"))) (defun helm-package--upgradeable-packages (&optional include-builtins) @@ -338,6 +497,7 @@ Arg PACKAGES is a list of strings." for available = (and pkg (not (package-disabled-p sym cversion)) pkg) ;; Exclude packages installed with package-vc (issue#2692). when (and available + (not (package-vc-p desc)) (or (and include-builtins (not cversion)) (and cversion (version-list-< @@ -358,7 +518,11 @@ to avoid errors with outdated packages no more availables." (when arg (helm-packages--refresh-contents)) (let ((upgrades (helm-package--upgradeable-packages helm-package-install-upgrade-built-in)) - (removables (package--removable-packages))) + (removables (package--removable-packages)) + (standard-actions '(("Describe package" . helm-packages-describe) + ("Visit homepage" . helm-packages-visit-homepage) + ("Install packages(s)" . helm-packages-install) + ("Clone package" . helm-packages-clone-package)))) (helm :sources (list (helm-make-source "Availables for upgrade" 'helm-packages-class :init (lambda () @@ -381,33 +545,41 @@ to avoid errors with outdated packages no more availables." . helm-packages-package-reinstall) ("Recompile package(s)" . helm-packages-recompile) ("Uninstall package(s)" . helm-packages-uninstall) - ("Isolate package(s)" . helm-packages-isolate))) + ("Isolate package(s)" . helm-packages-isolate) + ("Clone package" . helm-packages-clone-package))) + (helm-make-source "New packages" 'helm-packages-class + :data (lambda () + (cl-loop for p in package-archive-contents + for sym = (car p) + for id = (package-get-descriptor sym) + for status = (and id (package-desc-status id)) + when (equal status "new") + nconc (list (car p)))) + :action standard-actions) (helm-make-source "Available external packages" 'helm-packages-class - :data (cl-loop for p in package-archive-contents - for sym = (car p) - for id = (package-get-descriptor sym) - for status = (package-desc-status id) - unless (or (and id (member - status - '("installed" "dependency" "source"))) - (and id (assoc sym package--builtins))) - nconc (list (car p))) - :action '(("Describe package" . helm-packages-describe) - ("Visit homepage" . helm-packages-visit-homepage) - ("Install packages(s)" - . helm-packages-install))) + :data (lambda () + (cl-loop for p in package-archive-contents + for sym = (car p) + for id = (package-get-descriptor sym) + for status = (package-desc-status id) + unless (or (and id (member + status + '("new" "installed" + "dependency" "source"))) + (and id (assoc sym package--builtins))) + nconc (list (car p)))) + :action standard-actions) (helm-make-source "Available built-in packages" 'helm-packages-class - :data (cl-loop for p in package--builtins - ;; Show only builtins that are available as - ;; well on (m)elpa. Other builtins don't - ;; have a package-descriptor, the format is - ;; (sym . [version reqs summary]). - when (package-desc-p (package-get-descriptor (car p))) - collect (car p)) - :action '(("Describe package" . helm-packages-describe) - ("Visit homepage" . helm-packages-visit-homepage) - ("Install packages(s)" - . helm-packages-install)))) + :data (lambda () + (cl-loop for p in package--builtins + ;; Show only builtins that are available as + ;; well on (m)elpa. Other builtins don't + ;; have a package-descriptor, the format is + ;; (sym . [version reqs summary]). + when (package-desc-p (package-get-descriptor (car p))) + collect (car p))) + :action (remove (assoc "Clone package" standard-actions) + standard-actions))) :buffer "*helm packages*"))) ;;;###autoload @@ -415,8 +587,8 @@ to avoid errors with outdated packages no more availables." "Helm interface to find packages by keywords with `finder'. To have more actions on packages, use `helm-packages'." (interactive "P") - (when arg (package-refresh-contents)) - (package-initialize) ; needed to feed package-archive-contents. + (package-initialize) + (when arg (helm-packages--refresh-contents)) (helm :sources (helm-build-in-buffer-source "helm finder" :data (cl-loop for p in package-archive-contents diff --git a/elpa/helm-20250515.548/helm-pkg.el b/elpa/helm-20251212.555/helm-pkg.el similarity index 74% rename from elpa/helm-20250515.548/helm-pkg.el rename to elpa/helm-20251212.555/helm-pkg.el index 5e95654f..f7d8822a 100644 --- a/elpa/helm-20250515.548/helm-pkg.el +++ b/elpa/helm-20251212.555/helm-pkg.el @@ -1,11 +1,11 @@ ;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "helm" "20250515.548" +(define-package "helm" "20251212.555" "Helm is an Emacs incremental and narrowing framework." - '((helm-core "4.0.3") + '((helm-core "4.0.6") (wfnames "1.2")) :url "https://emacs-helm.github.io/helm/" - :commit "387b8c8c5ae83150151672979d432e9cd790b79a" - :revdesc "387b8c8c5ae8" + :commit "08fb63fab625e90b699999151dada80232a7c81b" + :revdesc "08fb63fab625" :keywords '("helm" "convenience" "files" "buffers" "grep" "completion" "lisp" "matching" "tools" "help") :authors '(("Thierry Volpiatto" . "thievol@posteo.net")) :maintainers '(("Thierry Volpiatto" . "thievol@posteo.net"))) diff --git a/elpa/helm-20250515.548/helm-regexp.el b/elpa/helm-20251212.555/helm-regexp.el similarity index 100% rename from elpa/helm-20250515.548/helm-regexp.el rename to elpa/helm-20251212.555/helm-regexp.el diff --git a/elpa/helm-20250515.548/helm-ring.el b/elpa/helm-20251212.555/helm-ring.el similarity index 100% rename from elpa/helm-20250515.548/helm-ring.el rename to elpa/helm-20251212.555/helm-ring.el diff --git a/elpa/helm-20250515.548/helm-semantic.el b/elpa/helm-20251212.555/helm-semantic.el similarity index 100% rename from elpa/helm-20250515.548/helm-semantic.el rename to elpa/helm-20251212.555/helm-semantic.el diff --git a/elpa/helm-20250515.548/helm-sys.el b/elpa/helm-20251212.555/helm-sys.el similarity index 99% rename from elpa/helm-20250515.548/helm-sys.el rename to elpa/helm-20251212.555/helm-sys.el index e382bdd3..18c60492 100644 --- a/elpa/helm-20250515.548/helm-sys.el +++ b/elpa/helm-20251212.555/helm-sys.el @@ -22,6 +22,8 @@ (require 'helm-help) (require 'helm-utils) +(declare-function helm-comp-read "helm-mode") + (defgroup helm-sys nil "System related helm library." diff --git a/elpa/helm-20250515.548/helm-tags.el b/elpa/helm-20251212.555/helm-tags.el similarity index 100% rename from elpa/helm-20250515.548/helm-tags.el rename to elpa/helm-20251212.555/helm-tags.el diff --git a/elpa/helm-20250515.548/helm-types.el b/elpa/helm-20251212.555/helm-types.el similarity index 99% rename from elpa/helm-20250515.548/helm-types.el rename to elpa/helm-20251212.555/helm-types.el index 1de00334..c7be1efb 100644 --- a/elpa/helm-20250515.548/helm-types.el +++ b/elpa/helm-20251212.555/helm-types.el @@ -31,7 +31,7 @@ (declare-function helm-make-actions "helm-lib") (declare-function helm-ediff-marked-buffers "helm-buffers") (declare-function helm-make-type "helm-source") - +(declare-function helm-marked-candidates "helm-core") ;; Files (defclass helm-type-file (helm-source) diff --git a/elpa/helm-20250515.548/helm-utils.el b/elpa/helm-20251212.555/helm-utils.el similarity index 87% rename from elpa/helm-20250515.548/helm-utils.el rename to elpa/helm-20251212.555/helm-utils.el index f6496fbf..fed5c2ee 100644 --- a/elpa/helm-20250515.548/helm-utils.el +++ b/elpa/helm-20251212.555/helm-utils.el @@ -388,10 +388,12 @@ buffers vertically according to `helm-window-show-buffers-function'." (defun helm-window-decide-split-fn (candidates &optional other-window-fn) "Try to find the best split window fn according to the number of CANDIDATES." (let ((fn (cond (;; 4 or more. - (>= (length candidates) 4) + (>= (length candidates) + (if other-window-fn 3 4)) #'helm-window-mosaic-fn) ;; 3 only. - ((= (length candidates) 3) + ((= (length candidates) + (if other-window-fn 2 3)) #'helm-window-alternate-split-fn) ;; 2 or less. (t #'helm-window-default-split-fn)))) @@ -600,11 +602,10 @@ after running winner-undo/redo." (cl-pushnew helm-buffer winner-boring-buffers :test 'equal)) (add-hook 'helm-cleanup-hook #'helm-handle-winner-boring-buffers) -(defun helm-quit-and-find-file () +(defun helm-quit-and-find-file-1 () "Drop into `helm-find-files' from `helm'. If current selection is a buffer or a file, `helm-find-files' from its directory." - (interactive) (with-helm-alive-p (require 'helm-grep) (require 'helm-elisp) @@ -625,7 +626,6 @@ from its directory." (helm-basename f) f)))) (helm-find-files-1 f)))) (helm--quit-and-find-file-default-file src))))) -(put 'helm-quit-and-find-file 'helm-only t) (defun helm--quit-and-find-file-default-file (source) (let ((target-fn (or (helm-get-attr 'find-file-target source) @@ -700,11 +700,12 @@ that is sorting is done against real value of candidate." (< (length str1) (length str2))) (t (> sc3 sc4))))) -(cl-defun helm-file-human-size (size &optional (kbsize helm-default-kbsize)) +(defun helm-file-human-size (size &optional kbsize) "Return a string showing SIZE of a file in human readable form. SIZE can be an integer or a float depending on it's value. `file-attributes' will take care of that to avoid overflow error. KBSIZE is a floating point number, defaulting to `helm-default-kbsize'." + (unless kbsize (setq kbsize helm-default-kbsize)) (cl-loop with result = (cons "B" size) for i in '("k" "M" "G" "T" "P" "E" "Z" "Y") while (>= (cdr result) kbsize) @@ -908,7 +909,7 @@ Inlined here for compatibility." (defvar helm-match-line-overlay nil) (defvar helm--match-item-overlays nil) -(cl-defun helm-highlight-current-line (&optional start end buf face) +(defun helm-highlight-current-line (&optional start end buf face) "Highlight current line and all matching items around it. The number of lines around matched line where the matching items are @@ -917,83 +918,84 @@ When the variable `helm-highlight-only-all-matches' is non nil only the lines containing all matches (in case of multi match) are highlighted. Optional arguments START, END and FACE are only here for debugging purpose." - (let* ((start (or start (line-beginning-position))) - (end (or end (1+ (line-end-position)))) - start-match end-match - (args (list start end buf)) - (case-fold-search (if helm-alive-p - (helm-set-case-fold-search) - case-fold-search))) - ;; Highlight the current line. - (if (not helm-match-line-overlay) - (setq helm-match-line-overlay (apply 'make-overlay args)) - (apply 'move-overlay helm-match-line-overlay args)) - (overlay-put helm-match-line-overlay - 'face (or face 'helm-selection-line)) - ;; Now highlight matches only if we are in helm session, we are - ;; maybe coming from helm-grep-mode or helm-moccur-mode buffers. - (when helm-alive-p - (helm-acase helm-highlight-matches-around-point-max-lines - ;; Next 2 clauses must precede others otherwise - ;; `helm-highlight-matches-around-point-max-lines' is - ;; compared as a number by other clauses and return an error. - (never (cl-return-from helm-highlight-current-line)) - ((dst* (x . y)) - (setq start-match (save-excursion (forward-line (- x)) (pos-bol)) - end-match (save-excursion (forward-line y) (pos-bol)))) - ((guard* (or (null it) (zerop it))) - (setq start-match start - end-match end)) - ((guard* (< it 0)) - (setq start-match (save-excursion (forward-line it) (pos-bol)) - end-match start)) - ((guard* (> it 0)) - (setq start-match start - end-match (save-excursion (forward-line it) (pos-bol))))) - (catch 'empty-line - (let* ((regex-list (helm-remove-if-match - "\\`!" (helm-mm-split-pattern - (if (with-helm-buffer - ;; Needed for highlighting AG matches. - (assq 'pcre (helm-get-current-source))) - (helm--translate-pcre-to-elisp helm-input) - helm-input)))) - (num-regex (length regex-list))) - (save-excursion - (goto-char start-match) - (while (< (point) end-match) - (let* ((start-line (line-beginning-position)) - (end-line (line-end-position)) - all-matches) - (dolist (r regex-list) - (let ((match-list '())) - (save-excursion - (goto-char start-line) - (while (condition-case _err - (and (not (= start-line end-line)) - (if helm-migemo-mode - (helm-mm-migemo-forward r end-line t) - (re-search-forward r end-line t))) - (invalid-regexp nil)) - (let ((s (match-beginning 0)) - (e (match-end 0))) - (if (= s e) - (throw 'empty-line nil) - (push (cons s e) match-list))))) - (when match-list - (push match-list all-matches)))) - (when (and all-matches - (or (not helm-highlight-only-all-matches) - (eql (length all-matches) num-regex))) - (cl-loop for ml in all-matches - do (cl-loop for (s . e) in ml - for ov = (make-overlay s e) - do (progn - (push ov helm--match-item-overlays) - (overlay-put ov 'face 'helm-match-item) - (overlay-put ov 'priority 1)))))) - (forward-line 1)))))) - (recenter))) + (catch 'never + (let* ((start (or start (line-beginning-position))) + (end (or end (1+ (line-end-position)))) + start-match end-match + (args (list start end buf)) + (case-fold-search (if helm-alive-p + (helm-set-case-fold-search) + case-fold-search))) + ;; Highlight the current line. + (if (not helm-match-line-overlay) + (setq helm-match-line-overlay (apply 'make-overlay args)) + (apply 'move-overlay helm-match-line-overlay args)) + (overlay-put helm-match-line-overlay + 'face (or face 'helm-selection-line)) + ;; Now highlight matches only if we are in helm session, we are + ;; maybe coming from helm-grep-mode or helm-moccur-mode buffers. + (when helm-alive-p + (helm-acase helm-highlight-matches-around-point-max-lines + ;; Next 2 clauses must precede others otherwise + ;; `helm-highlight-matches-around-point-max-lines' is + ;; compared as a number by other clauses and return an error. + (never (throw 'never nil)) + ((dst* (x . y)) + (setq start-match (save-excursion (forward-line (- x)) (pos-bol)) + end-match (save-excursion (forward-line y) (pos-bol)))) + ((guard* (or (null it) (zerop it))) + (setq start-match start + end-match end)) + ((guard* (< it 0)) + (setq start-match (save-excursion (forward-line it) (pos-bol)) + end-match start)) + ((guard* (> it 0)) + (setq start-match start + end-match (save-excursion (forward-line it) (pos-bol))))) + (catch 'empty-line + (let* ((regex-list (helm-remove-if-match + "\\`!" (helm-mm-split-pattern + (if (with-helm-buffer + ;; Needed for highlighting AG matches. + (assq 'pcre (helm-get-current-source))) + (helm--translate-pcre-to-elisp helm-input) + helm-input)))) + (num-regex (length regex-list))) + (save-excursion + (goto-char start-match) + (while (< (point) end-match) + (let* ((start-line (line-beginning-position)) + (end-line (line-end-position)) + all-matches) + (dolist (r regex-list) + (let ((match-list '())) + (save-excursion + (goto-char start-line) + (while (condition-case _err + (and (not (= start-line end-line)) + (if helm-migemo-mode + (helm-mm-migemo-forward r end-line t) + (re-search-forward r end-line t))) + (invalid-regexp nil)) + (let ((s (match-beginning 0)) + (e (match-end 0))) + (if (= s e) + (throw 'empty-line nil) + (push (cons s e) match-list))))) + (when match-list + (push match-list all-matches)))) + (when (and all-matches + (or (not helm-highlight-only-all-matches) + (eql (length all-matches) num-regex))) + (cl-loop for ml in all-matches + do (cl-loop for (s . e) in ml + for ov = (make-overlay s e) + do (progn + (push ov helm--match-item-overlays) + (overlay-put ov 'face 'helm-match-item) + (overlay-put ov 'priority 1)))))) + (forward-line 1)))))) + (recenter)))) (defun helm--translate-pcre-to-elisp (regexp) "Should translate pcre REGEXP to elisp regexp. @@ -1050,62 +1052,62 @@ Assume regexp is a pcre based regexp." ;;; Popup-info ;; -(defvar helm--show-help-echo-timer nil) -(defvar helm--maybe-show-help-echo-overlay nil) +(defvar helm--show-popup-info-timer nil) +(defvar helm--maybe-show-popup-info-overlay nil) (defface helm-tooltip '((((type tty pc)) :background "yellow" :foreground "black") - (t :background "Goldenrod" :foreground "black")) - "Face used by `helm-tooltip-show'." + (t :background "goldenrod" :foreground "black")) + "Face used by `helm-popup-tip-show'." :group 'helm-grep-faces) -(defun helm-cancel-help-echo-timer () - (when helm--show-help-echo-timer - (cancel-timer helm--show-help-echo-timer) - (setq helm--show-help-echo-timer nil)) - (when helm--maybe-show-help-echo-overlay - (delete-overlay helm--maybe-show-help-echo-overlay) - (setq helm--maybe-show-help-echo-overlay nil))) +(defun helm-cancel-popup-tip-timer () + (when helm--show-popup-info-timer + (cancel-timer helm--show-popup-info-timer) + (setq helm--show-popup-info-timer nil)) + (when helm--maybe-show-popup-info-overlay + (delete-overlay helm--maybe-show-popup-info-overlay) + (setq helm--maybe-show-popup-info-overlay nil))) -(defun helm-tooltip-show (text pos) +(defun helm-popup-tip-show (text pos) "Display TEXT at POS in an overlay." - (setq helm--maybe-show-help-echo-overlay + (setq helm--maybe-show-popup-info-overlay (make-overlay pos (1+ pos))) - (overlay-put helm--maybe-show-help-echo-overlay + (overlay-put helm--maybe-show-popup-info-overlay 'display (propertize (concat text "\n") 'face 'helm-tooltip))) -(defun helm-maybe-show-help-echo () - (when helm--show-help-echo-timer - (cancel-timer helm--show-help-echo-timer) - (setq helm--show-help-echo-timer nil)) - (when helm--maybe-show-help-echo-overlay - (delete-overlay helm--maybe-show-help-echo-overlay)) +(defun helm-maybe-show-popup-tip-info () + (when helm--maybe-show-popup-info-overlay + (delete-overlay helm--maybe-show-popup-info-overlay)) (let* ((src (helm-get-current-source)) (popup-info-fn (assoc-default 'popup-info src))) (when (and helm-alive-p helm-popup-tip-mode popup-info-fn) - (setq helm--show-help-echo-timer - (run-with-idle-timer - 1 nil - (lambda () - ;; We may have an error (wrong-type-argument window-live-p nil) - ;; when switching to help window, the error may occur in the - ;; small lap of time where the helm-window is deleted and the - ;; help buffer not already displayed. - (ignore-error wrong-type-argument - (save-selected-window - (with-helm-window - (let ((pos (save-excursion (end-of-visual-line) (point))) - (str (and popup-info-fn - (funcall popup-info-fn (helm-get-selection))))) - (when (and str (not (string= str ""))) - (helm-tooltip-show - (concat " " str) - pos)))))))))))) + (unless (timerp helm--show-popup-info-timer) + (setq helm--show-popup-info-timer + (run-with-idle-timer + 1 nil + (lambda () + (cancel-timer helm--show-popup-info-timer) + (setq helm--show-popup-info-timer nil) + ;; We may have an error (wrong-type-argument window-live-p nil) + ;; when switching to help window, the error may occur in the + ;; small lap of time where the helm-window is deleted and the + ;; help buffer not already displayed. + (ignore-error wrong-type-argument + (save-selected-window + (with-helm-window + (let ((pos (save-excursion (end-of-visual-line) (point))) + (str (and popup-info-fn + (funcall popup-info-fn (helm-get-selection))))) + (when (and str (not (string= str ""))) + (helm-popup-tip-show + (concat " " str) + pos))))))))))))) ;;;###autoload (define-minor-mode helm-popup-tip-mode @@ -1117,12 +1119,12 @@ this source to fetch infos on candidate." :global t (if helm-popup-tip-mode (progn - (add-hook 'helm-move-selection-after-hook 'helm-maybe-show-help-echo) - (add-hook 'helm-help-mode-after-hook 'helm-maybe-show-help-echo) - (add-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer)) - (remove-hook 'helm-move-selection-after-hook 'helm-maybe-show-help-echo) - (remove-hook 'helm-help-mode-after-hook 'helm-maybe-show-help-echo) - (remove-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer))) + (add-hook 'helm-move-selection-after-hook 'helm-maybe-show-popup-tip-info) + (add-hook 'helm-help-mode-after-hook 'helm-maybe-show-popup-tip-info) + (add-hook 'helm-cleanup-hook 'helm-cancel-popup-tip-timer)) + (remove-hook 'helm-move-selection-after-hook 'helm-maybe-show-popup-tip-info) + (remove-hook 'helm-help-mode-after-hook 'helm-maybe-show-popup-tip-info) + (remove-hook 'helm-cleanup-hook 'helm-cancel-popup-tip-timer))) (defun helm-open-file-with-default-tool (file) "Open FILE with the default tool on this platform." diff --git a/elpa/helm-20250515.548/helm-x-files.el b/elpa/helm-20251212.555/helm-x-files.el similarity index 100% rename from elpa/helm-20250515.548/helm-x-files.el rename to elpa/helm-20251212.555/helm-x-files.el diff --git a/elpa/helm-20250515.548/helm-x-icons.el b/elpa/helm-20251212.555/helm-x-icons.el similarity index 93% rename from elpa/helm-20250515.548/helm-x-icons.el rename to elpa/helm-20251212.555/helm-x-icons.el index 708ec21e..6f13efa9 100644 --- a/elpa/helm-20250515.548/helm-x-icons.el +++ b/elpa/helm-20251212.555/helm-x-icons.el @@ -23,7 +23,8 @@ "Compatibility functions between icons provider packages." :group 'helm) -(defcustom helm-x-icons-provider 'all-the-icons +(defcustom helm-x-icons-provider (if (display-graphic-p) + 'all-the-icons 'nerd-icons) "The icons provider package. The currently supported providers are `all-the-icons' and `nerd-icons'. Do not use setq to set this variable but customize." @@ -31,7 +32,7 @@ Do not use setq to set this variable but customize." (const :tag "Use `all-the-icons' package" all-the-icons) (const :tag "Use `nerd-icons' package" nerd-icons)) :set (lambda (var val) - (when val (require val nil t)) + (when val (setq val (require val nil t))) (set var val))) (defun helm-x-icons-match-to-alist (file type) @@ -60,8 +61,12 @@ The returned alist is computed according to `helm-x-icons-provider'." "Compatibility function for `*-icon-for-file'." (let ((fn (helm-acase helm-x-icons-provider (all-the-icons 'all-the-icons-icon-for-file) - (nerd-icons 'nerd-icons-icon-for-file)))) - (when fn (apply fn args)))) + (nerd-icons 'nerd-icons-icon-for-file))) + icon) + (when fn + (setq icon (apply fn args)) + (add-text-properties 0 1 `(icon ,(length icon)) icon) + icon))) (defvar helm-x-icons-nerd-icons-compat-alist '(("file-symlink-directory" . (nerd-icons-codicon . "nf-cod-file_symlink_directory")) @@ -143,7 +148,7 @@ Run an `all-the-icons' or `nerd-icons' function according to `helm-x-icons-provider'and ICON-NAME. Functions and icon names are found in `helm-x-icons-all-the-icons-compat-alist' and `helm-x-icons-nerd-icons-compat-alist'." - (let (fn) + (let (fn icon) (helm-acase helm-x-icons-provider (nerd-icons (helm-acase (assoc-default icon-name helm-x-icons-nerd-icons-compat-alist) @@ -153,8 +158,10 @@ and `helm-x-icons-nerd-icons-compat-alist'." (helm-acase (assoc-default icon-name helm-x-icons-all-the-icons-compat-alist) ((dst* (sym . name)) (setq fn sym icon-name name))))) - (when fn (apply fn icon-name args)))) - + (when fn + (setq icon (apply fn icon-name args)) + (add-text-properties 0 1 `(icon ,(length icon)) icon) + icon))) (provide 'helm-x-icons) diff --git a/elpa/helm-20250515.548/helm.el b/elpa/helm-20251212.555/helm.el similarity index 94% rename from elpa/helm-20250515.548/helm.el rename to elpa/helm-20251212.555/helm.el index b9191cd4..ac8ca346 100644 --- a/elpa/helm-20250515.548/helm.el +++ b/elpa/helm-20251212.555/helm.el @@ -11,10 +11,10 @@ ;; Thierry Volpiatto ;; Author: Thierry Volpiatto -;; Package-Version: 20250515.548 -;; Package-Revision: 387b8c8c5ae8 +;; Package-Version: 20251212.555 +;; Package-Revision: 08fb63fab625 ;; URL: https://emacs-helm.github.io/helm/ -;; Package-Requires: ((helm-core "4.0.3") (wfnames "1.2")) +;; Package-Requires: ((helm-core "4.0.6") (wfnames "1.2")) ;; Keywords: helm, convenience, files, buffers, grep, completion, lisp, matching, tools, help ;; This program is free software; you can redistribute it and/or modify diff --git a/elpa/helm-core-20250514.1025/helm-core-autoloads.el b/elpa/helm-core-20251211.709/helm-core-autoloads.el similarity index 100% rename from elpa/helm-core-20250514.1025/helm-core-autoloads.el rename to elpa/helm-core-20251211.709/helm-core-autoloads.el diff --git a/elpa/helm-core-20250514.1025/helm-core-pkg.el b/elpa/helm-core-20251211.709/helm-core-pkg.el similarity index 70% rename from elpa/helm-core-20250514.1025/helm-core-pkg.el rename to elpa/helm-core-20251211.709/helm-core-pkg.el index 43fb7e38..dab0ad61 100644 --- a/elpa/helm-core-20250514.1025/helm-core-pkg.el +++ b/elpa/helm-core-20251211.709/helm-core-pkg.el @@ -1,10 +1,10 @@ ;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "helm-core" "20250514.1025" +(define-package "helm-core" "20251211.709" "Development files for Helm." '((emacs "25.1") (async "1.9.9")) :url "https://emacs-helm.github.io/helm/" - :commit "e03edf775af41053c8a4de98f370689d4525077b" - :revdesc "e03edf775af4" + :commit "c9a6c2542e5ec48700d1a72632cef009e5ee3253" + :revdesc "c9a6c2542e5e" :authors '(("Thierry Volpiatto" . "thievol@posteo.net")) :maintainers '(("Thierry Volpiatto" . "thievol@posteo.net"))) diff --git a/elpa/helm-core-20250514.1025/helm-core.el b/elpa/helm-core-20251211.709/helm-core.el similarity index 91% rename from elpa/helm-core-20250514.1025/helm-core.el rename to elpa/helm-core-20251211.709/helm-core.el index 43a1008b..8bdd2cbf 100644 --- a/elpa/helm-core-20250514.1025/helm-core.el +++ b/elpa/helm-core-20251211.709/helm-core.el @@ -4,8 +4,8 @@ ;; Author: Thierry Volpiatto ;; URL: https://emacs-helm.github.io/helm/ -;; Package-Version: 20250514.1025 -;; Package-Revision: e03edf775af4 +;; Package-Version: 20251211.709 +;; Package-Revision: c9a6c2542e5e ;; Package-Requires: ((emacs "25.1") (async "1.9.9")) ;; This program is free software; you can redistribute it and/or modify @@ -35,17 +35,22 @@ (require 'helm-multi-match) (require 'helm-source) +(defun helm-acase-extra-fontifications () + (font-lock-add-keywords nil '(("\\<\\(guard\\|dst\\)\\>\\*" . font-lock-type-face)))) +(add-hook 'emacs-lisp-mode-hook #'helm-acase-extra-fontifications) + ;; Setup completion styles for helm-mode (helm--setup-completion-styles-alist) (declare-function helm-comp-read "helm-mode.el") (declare-function custom-unlispify-tag-name "cus-edit.el") -(declare-function helm-quit-and-find-file "helm-utils.el") +(declare-function helm-quit-and-find-file-1 "helm-utils.el") (declare-function linum-mode "linum.el") (declare-function minibuffer-depth-setup "mb-depth.el") (declare-function transient--delete-window "ext:transient" ()) (declare-function transient--preserve-window-p "ext:transient" (&optional nohide)) +(declare-function helm-maybe-show-popup-tip-info "helm-utils") (defvar helm-marked-buffer-name) (defvar display-buffer-function) @@ -196,9 +201,11 @@ window handling a buffer, it is this one we store.") "[INTERNAL] Recenter when deleting minibuffer-contents and preselecting. This is a flag used internally.") (defvar helm--minibuffer-completing-file-name nil - "A flag notifying Helm is in file completion. + "[INTERNAL] A flag notifying Helm is in file completion. It is let-bounded in `helm-read-file-name'. Same as -`minibuffer-completing-file-name' but doesn't affect `file-directory-p'.") +`minibuffer-completing-file-name' but doesn't affect `file-directory-p' when +called on remote files. +WARN: Use this only in `helm-read-file-name'.") ;;; Multi keys ;; @@ -268,13 +275,6 @@ DELAY seconds." delay nil (lambda () (setcar iterator nil)))))) -(helm-multi-key-defun helm-toggle-resplit-and-swap-windows - "Multi key command to re-split and swap Helm window. -First call runs `helm-toggle-resplit-window', -and second call within 1s runs `helm-swap-windows'." - '(helm-toggle-resplit-window helm-swap-windows) 1) -(put 'helm-toggle-resplit-and-swap-windows 'helm-only t) - (defun helm-command-with-subkeys (map subkey command &optional other-subkeys prompt exit-fn delay) "Build a command that run COMMAND when SUBKEY is read. @@ -446,6 +446,8 @@ i.e. the loop is not entered after running COMMAND." (define-key map (kbd "C-r") #'undefined) (define-key map (kbd "C-M-r") #'undefined) (define-key map (kbd "C-M-s") #'undefined) + (define-key map (kbd "C-M-i") #'undefined) + (define-key map (kbd "C-;") #'undefined) (define-key map (kbd "C-}") #'helm-narrow-window) (define-key map (kbd "C-{") #'helm-enlarge-window) (define-key map (kbd "C-c -") #'helm-swap-windows) @@ -469,8 +471,8 @@ i.e. the loop is not entered after running COMMAND." (helm-define-key-with-subkeys map (kbd "C-c n") ?n #'helm-run-cycle-resume) ;; Disable `file-cache-minibuffer-complete'. (define-key map (kbd "") #'undefined) - ;; Multi keys - (define-key map (kbd "C-t") #'helm-toggle-resplit-and-swap-windows) + (define-key map (kbd "C-t") #'helm-resplit-window-clockwise) + (define-key map (kbd "C-r") #'helm-resplit-window-counterclockwise) ;; Debugging command (define-key map (kbd "C-h C-d") #'helm-enable-or-switch-to-debug) (define-key map (kbd "C-h c") #'helm-customize-group) @@ -513,17 +515,23 @@ i.e. the loop is not entered after running COMMAND." Default to Helm group when group is not defined in source." (interactive) (let ((source (or (helm-get-current-source) - (helm-comp-read - "Customize variables for: " - (cl-loop for src in (with-helm-buffer helm-sources) - collect `(,(assoc-default 'name src) . - ,src)) - :allow-nest t - :exec-when-only-one t)))) + (and (fboundp 'helm-comp-read) + (helm-comp-read + "Customize variables for: " + (cl-loop for src in (with-helm-buffer helm-sources) + collect `(,(assoc-default 'name src) . + ,src)) + :allow-nest t + :exec-when-only-one t)) + ;; No completion on sources when only helm-core package is + ;; used. + (car helm-sources)))) (helm-run-after-exit 'helm-customize-group-1 (helm-get-attr 'group source)))) (put 'helm-customize-group 'helm-only t) -(defun helm--action-at-nth-set-fn-1 (value &optional negative) +(defun helm--action-at-nth-set-fn-1 (value &optional negative unset) + "Bind VALUE to (+-)nth candidate depending of NEGATIVE arg value. +If UNSET is specified unbind VALUE instead." (dotimes (n 9) (let ((key (format value (1+ n))) (fn (lambda () @@ -531,45 +539,43 @@ Default to Helm group when group is not defined in source." (helm-execute-selection-action-at-nth (if negative (- (1+ n)) (1+ n)))))) (define-key helm-map (kbd key) nil) - (define-key helm-map (kbd key) fn)))) + (unless unset + (define-key helm-map (kbd key) fn))))) -(defun helm--action-at-nth-set-fn- (var val) - (set var val) - (helm--action-at-nth-set-fn-1 val 'negative)) +(defun helm--action-at-nth-set-fn- (val &optional unset) + ;; Bind `helm-action-at-nth-negative-prefix-key' to `helm-map'. + (helm--action-at-nth-set-fn-1 val 'negative unset)) -(defun helm--action-at-nth-set-fn+ (var val) - (set var val) - (helm--action-at-nth-set-fn-1 val)) +(defun helm--action-at-nth-set-fn+ (val &optional unset) + ;; Bind `helm-action-at-nth-positive-prefix-key' to `helm-map'. + (helm--action-at-nth-set-fn-1 val nil unset)) -(defcustom helm-action-at-nth-negative-prefix-key "C-x %d" +(defcustom helm-action-at-nth-negative-prefix-key "M-%d" "The prefix key to execute default action on nth <-n> candidate. This is a format spec where %d will be replaced by the candidate number. -This is useful when `helm-display-line-numbers-mode' is turned on. - -NOTE: `setq' have no effect until you restart Emacs, use -customize for immediate effect." +This is activated only when `helm-display-line-numbers-mode' is turned on. +Note that default value `M-' defeat the usage of `M-' as prefix argument +in `helm-M-x'." :group 'helm - :type 'string - :set #'helm--action-at-nth-set-fn-) + :type 'string) -(defcustom helm-action-at-nth-positive-prefix-key "C-c %d" +(defcustom helm-action-at-nth-positive-prefix-key "C-%d" "The prefix key to execute default action on nth <+n> candidate. This is a format spec where %d will be replaced by the candidate number. -This is useful when `helm-display-line-numbers-mode' is turned on. - -NOTE: `setq' have no effect until you restart Emacs, use -customize for immediate effect." +This is activated only when `helm-display-line-numbers-mode' is turned on. +Note that default value `C-' defeat the usage of `C-' as prefix argument +in `helm-M-x'." :group 'helm - :type 'string - :set #'helm--action-at-nth-set-fn+) + :type 'string) +;;; User variables (defgroup helm nil "Open Helm." :prefix "helm-" :group 'convenience) @@ -614,7 +620,7 @@ Set this value to nil for no limit." :group 'helm :type '(choice (const :tag "Disabled" nil) integer)) -(defcustom helm-input-idle-delay 0.01 +(defcustom helm-input-idle-delay (if (display-graphic-p) 0.01 0.05) ; Issue #2730. "Idle time before updating, specified in seconds." :group 'helm :type 'float) @@ -706,7 +712,7 @@ See `helm-case-fold-search' for more info." (defcustom helm-reuse-last-window-split-state nil "Use the same state of window split, vertical or horizontal. -`helm-toggle-resplit-window' for the next helm session will use +For the next helm session `helm-resplit-window-clockwise' will use the same window scheme as the previous session unless `helm-split-window-default-side' is \\='same or \\='other." :group 'helm @@ -1130,13 +1136,32 @@ Set this to an empty string if you don't want prefix in margin when marking." :group 'helm :type 'string) +(defcustom helm-kill-real-or-display-selection 'display + "What to kill with `\\\\[helm-kill-selection-and-quit]'. +A prefix arg reverse the behavior of this variable." + :group 'helm + :type '(choice + (const :tag "Kill display" display) + (const :tag "Kill real" real))) + +(defcustom helm-follow-input-idle-delay 0.5 + "`helm-follow-mode' will execute action after this delay once idle. +Note that if the `follow-delay' attr is present in source, it +will take precedence over this." + :group 'helm + :type 'float) + (defvar helm-update-edebug nil - "Development feature. + "Development feature, make easier Edebug usage while in Helm. If set to true then all functions invoked after `helm-update' can be instrumented by `edebug' for stepping. `helm--maybe-use-while-no-input' then doesn't use `while-no-input', because `while-no-input' throws on -`edebug' command key input.") +`edebug' command key input. NOTE: This may hang helm a few seconds +while you are typing so use it only for debugging purpose, not +permanently.") +(defvar helm-default-output-filter #'helm-output-filter + "The `process-filter' function for Helm async sources.") ;;; Faces ;; @@ -1658,7 +1683,13 @@ Only simple bindings are available and they are defined in `helm-help-hkmap', which is a simple alist of (key . function). You can define or redefine bindings in help with `helm-help-define-key' or by adding/removing entries directly in -`helm-help-hkmap'. +`helm-help-hkmap'. For example if you want to replace isearch by [[https://github.com/thierryvolpiatto/isearch-light][isl-search]] +to have multi match like helm use: + + (helm-help-define-key \"C-s\" nil) + (helm-help-define-key \"C-r\" nil) + (helm-help-define-key \"C-s\" 'isl-search)) + See `helm-help-hkmap' for restrictions on bindings and functions. The documentation of default bindings are: @@ -1748,7 +1779,8 @@ and are by the way not compatible with Helm. | \\[helm-next-source]| Next source | | \\[helm-delete-minibuffer-contents]| Delete pattern (with prefix arg delete from point to end or all [2]) | | \\[helm-execute-persistent-action]| Persistent action (Execute and keep Helm session) | -|\\[helm-toggle-resplit-and-swap-windows]|Rotate or swap windows. | +|\\[helm-resplit-window-clockwise]|Resplit helm window clockwise. | +|\\[helm-resplit-window-counterclockwise]||Resplit helm window counterclockwise. | |\\[helm-exchange-minibuffer-and-header-line]|Exchange minibuffer and header-line. | |\\[helm-quit-and-find-file]|Drop into `helm-find-files'. | |\\[helm-kill-selection-and-quit]|Kill display value of candidate and quit (with prefix arg, kill the real value). | @@ -1810,7 +1842,7 @@ You can also toggle line numbers with buffer. Of course when enabling `global-display-line-numbers-mode' Helm -buffers will have line numbers as well. \(Don't forget to +buffers will have line numbers as well. (Don't forget to customize `display-line-numbers-type' to relative). In Emacs versions < to 26 you will have to use @@ -1818,19 +1850,19 @@ In Emacs versions < to 26 you will have to use package and `helm-linum-relative-mode'. Then when line numbers are enabled with one of the methods above -the following keys are available([1]): +the following keys are available: -C-x : Execute default action on the n-th candidate before + : Execute default action on the n-th candidate before currently selected candidate. -C-c : Execute default action on the n-th candidate after -current selected candidate. + : Execute default action on the n-th candidate after +currently selected candidate. -\"n\" is limited to 1-9. For larger jumps use other navigation -keys. +Where and are respectively the value of +the customizable variables `helm-action-at-nth-negative-prefix-key' and +`helm-action-at-nth-positive-prefix-key'. -\[1] Note that the key bindings are always available even if line -numbers are not displayed. They are just useless in this case. + is limited to 1-9. ** Mouse control in Helm @@ -2042,7 +2074,7 @@ Do not set this globally. Do not use this in async sources or in commands using an async source in their sources. Use this either let-bounded or helm buffer local.") -;; Utility: logging +;; logging (defun helm-log (from format-string &rest args) "Log message if `helm-debug' is non-nil. Messages are written to the `helm-debug-buffer' buffer. @@ -2244,9 +2276,7 @@ ATTRIBUTE-NAME." (defalias 'helm-attr 'helm-get-attr) (make-obsolete 'helm-attr 'helm-get-attr "3.7.0") -(cl-defun helm-set-attr (attribute-name value - &optional - (src (helm-get-current-source))) +(defun helm-set-attr (attribute-name value &optional src) "Set the value of ATTRIBUTE-NAME of source SRC to VALUE. If ATTRIBUTE-NAME doesn't exists in source it is created with @@ -2254,6 +2284,7 @@ value VALUE. If SRC is omitted, use current source. If operation succeed, return value, otherwise nil. Using this function is same as using `setf' on `helm-get-attr'." + (unless src (setq src (helm-get-current-source))) (setf (helm-get-attr attribute-name src) value)) (defalias 'helm-attrset 'helm-set-attr) @@ -2288,8 +2319,7 @@ function associated to name." (assoc action-or-name actions)))) (helm-set-attr 'action (delete del-action actions) source))) -(cl-defun helm-add-action-to-source-if (name fn source predicate - &optional (index 4) test-only) +(defun helm-add-action-to-source-if (name fn source predicate &optional index test-only) "Add new action NAME linked to function FN to SOURCE. Action NAME will be available when the current candidate matches PREDICATE. @@ -2314,6 +2344,7 @@ when predicate helm-ff-candidates-lisp-p returns non-nil: \\='async-byte-compile-file helm-source-find-files \\='helm-ff-candidates-lisp-p)." + (unless index (setq index 4)) (let* ((actions (helm-get-attr 'action source 'ignorefn)) (action-transformers (helm-get-attr 'action-transformer source)) (new-action (list (cons name fn))) @@ -2393,25 +2424,39 @@ If NO-UPDATE is non-nil, skip executing `helm-update'." (unless no-init (helm-compute-attr-in-sources 'init)) (unless no-update (helm-update))) +(defun helm--get-candidate-number-limit-value (arg) + "Return a suitable value for candidate-number-limit according to pref ARG." + (helm-acase arg + ;; Using a large number instead of nil allows always having a value with + ;; helm-get-attr. + ((guard* (consp arg)) 9999999) + ((guard* (numberp arg)) it) + (t (default-value 'helm-candidate-number-limit)))) + (defun helm-show-all-candidates-in-source (arg) "Toggle all sources or only current source visibility. With a prefix arg show all candidates in current source disregarding candidate-number-limit and with a numeric prefix arg -show ARG number of candidates." +show ARG number of candidates. With no prefix arg candidate-number-limit is +reset to default value." (interactive "P") (with-helm-alive-p (with-helm-buffer (if helm-source-filter (progn - (setq-local helm-candidate-number-limit - (default-value 'helm-candidate-number-limit)) + (if (helm-get-attr 'candidate-number-limit) + (helm-set-attr 'candidate-number-limit + (helm--get-candidate-number-limit-value arg)) + (setq-local helm-candidate-number-limit + (default-value 'helm-candidate-number-limit))) (helm-set-source-filter nil)) + ;; FIXME: What default-directory has to do with this? (with-helm-default-directory (helm-default-directory) - (setq-local helm-candidate-number-limit - (helm-acase arg - ((guard* (consp arg)) nil) - ((guard* (numberp arg)) it) - (t (default-value 'helm-candidate-number-limit)))) + (if (helm-get-attr 'candidate-number-limit) + (helm-set-attr 'candidate-number-limit + (helm--get-candidate-number-limit-value arg)) + (setq-local helm-candidate-number-limit + (helm--get-candidate-number-limit-value arg))) (helm-set-source-filter (list (helm-get-current-source)))))))) (put 'helm-show-all-candidates-in-source 'helm-only t) @@ -2431,18 +2476,22 @@ This is a toggle command, when hit a second time reset to all sources." (with-helm-buffer (if (null helm-source-filter) (when (cdr helm-sources) - (let ((headers (helm-comp-read - "Limit to source(s): " - (mapcar - (lambda (s) - (let* ((name (assoc-default 'name s)) - (disp (helm-aif (assoc-default 'header-name s) - (funcall it name) name))) - (cons disp name))) - helm-sources) - :marked-candidates t - :allow-nest t - :buffer "*helm sources*"))) + (let ((headers (if (fboundp 'helm-comp-read) + (helm-comp-read + "Limit to source(s): " + (mapcar + (lambda (s) + (let* ((name (assoc-default 'name s)) + (disp (helm-aif (assoc-default 'header-name s) + (funcall it name) name))) + (cons disp name))) + helm-sources) + :marked-candidates t + :allow-nest t + :buffer "*helm sources*") + ;; No completion on sources when only helm-core package is + ;; used. + (list (assoc-default 'name (helm-get-current-source)))))) (helm-set-source-filter headers))) (helm-set-source-filter nil))))) (put 'helm-limit-to-sources 'helm-only t) @@ -2459,6 +2508,9 @@ If FORCE-DISPLAY-PART is non-nil, return the display part of candidate. If FORCE-DISPLAY-PART value is `withprop' the display part of candidate is returned with its properties. +If FORCE-DISPLAY-PART value is `noicon' return the display part with its +properties but without its leading icon if some. + When FORCE-DISPLAY-PART is nil the real part of candidate is returned. SOURCE default to current-source when unspecified but it is better to @@ -2473,7 +2525,7 @@ when you want the `display-to-real' function(s) to be applied." (helm-pos-header-line-p)) (let* ((beg (overlay-start helm-selection-overlay)) (end (overlay-end helm-selection-overlay)) - (disp-fn (if (eq force-display-part 'withprop) + (disp-fn (if (memq force-display-part '(withprop noicon)) 'buffer-substring 'buffer-substring-no-properties)) ;; If there is no selection at point, the @@ -2482,7 +2534,13 @@ when you want the `display-to-real' function(s) to be applied." ;; is not empty but have no selection yet, ;; this happen with grep sentinel sending an ;; error message in helm-buffer when no matches. - (disp (unless (= beg end) (funcall disp-fn beg (1- end)))) + (disp (unless (= beg end) + (helm-acase (funcall disp-fn beg (1- end)) + ((guard* (and (eq force-display-part 'noicon) + (get-text-property 0 'icon it))) + ;; Remove icon if some from display see issue#2743. + (substring it (1+ guard))) ; icon length + one space. + (t it)))) (src (or source (helm-get-current-source))) (selection (helm-acond (force-display-part disp) ;; helm-realvalue always takes precedence @@ -2602,10 +2660,19 @@ i.e. functions called with RET." ;; If no helm based action run within 0.5 seconds, the next helm ;; session will have to resolve again those variable values. (run-with-idle-timer 0.5 nil - (lambda () (helm-set-local-variable 'helm-display-function nil - 'helm--last-frame-parameters nil)))) + (lambda () + (helm-set-local-variable + 'helm-display-function nil + 'helm--last-frame-parameters nil)))) (helm-exit-minibuffer)) +(defun helm-quit-and-find-file () + (interactive) + (if (fboundp 'helm-quit-and-find-file-1) + (helm-quit-and-find-file-1) + (error "No rules to find file, please install helm package for this"))) +(put 'helm-quit-and-find-file 'helm-only t) + (defun helm--get-frame-parameters (&optional frame) (cl-loop with params = (frame-parameters frame) for p in helm--frame-default-attributes @@ -2677,9 +2744,10 @@ IOW Don't use VALUE of previous VAR to set the VALUE of next VAR. ;; API helper -(cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer)) +(defun helm-empty-buffer-p (&optional buffer) "Check if BUFFER have candidates. Default value for BUFFER is `helm-buffer'." + (unless buffer (setq buffer helm-buffer)) (zerop (buffer-size (and buffer (get-buffer buffer))))) (defun helm-empty-source-p () @@ -3031,7 +3099,6 @@ HISTORY args see `helm'." (helm-log "helm-internal" "prompt = %S" prompt) (helm-log "helm-internal" "preselect = %S" preselect) (helm-log "helm-internal" "buffer = %S" buffer) - (helm-log "helm-internal" "keymap = %S" keymap) (helm-log "helm-internal" "default = %S" default) (helm-log "helm-internal" "history = %S" history) (setq helm--prompt (or prompt "pattern: ")) @@ -3316,9 +3383,14 @@ Don't use this directly, use instead `helm' with the keyword (orig-helm-last-frame-or-window-configuration helm-last-frame-or-window-configuration) (orig-one-window-p helm-onewindow-p) - (helm--nested (if helm--buffer-in-new-frame-p 'share t))) - ;; FIXME Using helm-full-frame here allow showing the new - ;; helm-buffer in the same window as old helm-buffer, why? + (helm--nested (if helm--buffer-in-new-frame-p 'share t)) + ;; Prevent reusing the underlying value of + ;; `helm-execute-action-at-once-if-one' particularly if it is a function. + helm-execute-action-at-once-if-one) + ;; Using helm-full-frame here allow showing the new + ;; helm-buffer in the same window as old helm-buffer by forcing the usage + ;; of switch-to-buffer in `helm-default-display-buffer', using the flag + ;; `helm--nested' would have the same effect and be more explicit. (helm-set-local-variable 'helm-full-frame t) (unwind-protect (let (helm-current-position @@ -3700,6 +3772,11 @@ version < emacs-28." buffer `(display-buffer-pop-up-frame . ((pop-up-frame-parameters . ,frame-alist)))))) +(defun helm--frame () + (cl-loop for f in (frame-list) + when (equal (frame-parameter f 'title) "Helm") + return f)) + ;; Ensure to quit helm when user delete helm frame manually. ;; If user deletes another frame keep session running. (defun helm--delete-frame-function (frame) @@ -4220,13 +4297,14 @@ WARNING: Do not use this mode yourself, it is internal to Helm." ;; so fallback to selected-window in such cases. (or (get-buffer-window helm-buffer) (selected-window)) - (let ((frame (selected-frame))) + (let ((frame (helm--frame))) (setq cursor-type (default-value 'cursor-type)) ;; Ensure restoring default-value of mode-line to allow user ;; using the mouse when helm is inactive (Bug#1517,Bug#2377). (setq mode-line-format (default-value 'mode-line-format)) (remove-hook 'post-command-hook 'helm--maybe-update-keymap) (remove-hook 'post-command-hook 'helm--update-header-line) + (helm-display-line-numbers-mode -1) ;; Be sure we call cleanup functions from helm-buffer. (helm-compute-attr-in-sources 'cleanup) ;; Delete or make invisible helm frame. @@ -4237,7 +4315,12 @@ WARNING: Do not use this mode yourself, it is internal to Helm." ;; i.e. helm--nested == t => delete ;; helm--nested == nil => delete ;; helm--nested == share => don't delete - (not (eq helm--nested 'share))) + (not (eq helm--nested 'share)) + ;; Do not delete inadvertently the main frame, this may happen + ;; when hitting quickly twice the same command + ;; e.g. completion-at-point. Should not happen now we use + ;; `helm--frame'. + (not (eql frame helm-initial-frame))) (progn (setq-local helm--last-frame-parameters (helm--get-frame-parameters)) @@ -4397,7 +4480,7 @@ Cache the candidates if there is no cached value yet." (list (cons 'item-count 0) (cons 'incomplete-line "")))) helm-async-processes) - (set-process-filter candidates 'helm-output-filter) + (set-process-filter candidates helm-default-output-filter) (setq candidates nil)) ((not (assq 'volatile source)) (puthash name candidates helm-candidate-cache))) @@ -4834,12 +4917,12 @@ useful when the order of the candidates is meaningful, e.g. with (setq display (if mp (concat beg-str (buffer-string) end-str) (buffer-string)))) (if real (cons display real) display)))) -(cl-defun helm-fuzzy-default-highlight-match (candidate - &optional (pattern helm-pattern) diacritics file-comp) +(defun helm-fuzzy-default-highlight-match (candidate &optional pattern diacritics file-comp) "The default function to highlight matches in fuzzy matching. Highlight elements in CANDIDATE matching PATTERN according to the matching method in use. When DIACRITICS is specified, ignore diacritics, see `char-fold-to-regexp' for more infos." + (unless pattern (setq pattern helm-pattern)) (if (string= pattern "") ;; Empty pattern, do nothing. This is needed when this function ;; is used outside of helm-fuzzy-highlight-matches like in *buffers-list. @@ -4935,6 +5018,14 @@ emacs-27 to provide such scoring in emacs<27." searchfns (list searchfns)))) (defun helm-match-from-candidates (cands matchfns match-part-fn limit source) + "Filter CANDS list in SOURCE with functions in MATCHFNS. +If MATCH-PART-FN is a valid function, use it to determine in each +candidate of CANDS the part of candidate we want to match on (see the +:match-part documentation in `helm-source'). When LIMIT in CANDS is +reached, stop and return the filtered list. This function is used only +by sync sources, i.e. sources built with `helm-source-sync', see +`helm-search-from-candidate-buffer' for `helm-source-in-buffer' sources +and `helm-output-filter' for async sources." (when cands ; nil in async sources. (condition-case-unless-debug err (cl-loop with hash = (make-hash-table :test 'equal) @@ -5031,25 +5122,21 @@ emacs-27 to provide such scoring in emacs<27." (defun helm-render-source (source matches) "Display MATCHES from SOURCE according to its settings." - (helm-log "helm-render-source" "Source = %S" (remove (assq 'keymap source) source)) (when matches (helm-insert-header-from-source source) - (cl-loop with separate = nil - with start = (point) - with singleline = (null (assq 'multiline source)) - for m in matches - for count from 1 - if singleline - do (helm-insert-match m 'insert count source) - else - do (progn - (if separate - (helm-insert-candidate-separator) - (setq separate t)) - (helm-insert-match m 'insert count source)) - finally (and (null singleline) - (put-text-property start (point) - 'helm-multiline t))))) + (let ((start (point)) + (multiline (assq 'multiline source)) + (count 1) + separate) + (dolist (m matches) + (when multiline + (if separate + (helm-insert-candidate-separator) + (setq separate t))) + (helm-insert-match m 'insert count source) + (cl-incf count)) + (when multiline + (put-text-property start (point) 'helm-multiline t))))) (defmacro helm-while-no-input (&rest body) "Same as `while-no-input' but returns either BODY or nil. @@ -5071,10 +5158,15 @@ Unlike `while-no-input' this macro ensure to not returns `t'." (defmacro helm--maybe-use-while-no-input (&rest body) "Wrap BODY in `helm-while-no-input' unless initializing a remote connection." `(progn + ;; Tramp would ask for passwd, so don't use `helm-while-no-input' until + ;; connected to remote. (if (or (and (file-remote-p helm-pattern) (not (file-remote-p helm-pattern nil t))) - helm-update-edebug) - ;; Tramp will ask for passwd, don't use `helm-while-no-input'. + helm-update-edebug + ;; Don't use while-no-input on initial helm-update before minibuffer + ;; is not ready (Issue #2729), this happen in + ;; `helm-read-from-minibuffer'. + (not (helm-active-minibuffer-window))) ,@body (helm-log "helm--maybe-use-while-no-input" "Using here `helm-while-no-input'") @@ -5087,6 +5179,10 @@ Unlike `while-no-input' this macro ensure to not returns `t'." (cons 'dbus-event while-no-input-ignore-events)))) (helm-while-no-input ,@body))))) +(defun helm-active-minibuffer-window () + "Check if helm-window has an active minibuffer." + (and (helm-window) (minibuffer-window-active-p (minibuffer-window)))) + (defun helm--collect-matches (src-list) "Return a list of matches for each source in SRC-LIST. @@ -5105,10 +5201,11 @@ candidates in display." ;;; Case fold search ;; ;; -(cl-defun helm-set-case-fold-search (&optional (pattern helm-pattern)) +(defun helm-set-case-fold-search (&optional pattern) "Used to set the value of `case-fold-search' in Helm. Return t or nil depending on the value of `helm-case-fold-search' and `helm-pattern'." + (unless pattern (setq pattern helm-pattern)) (if helm-alive-p (let ((helm-case-fold-search (helm-aif (assq 'case-fold-search (helm-get-current-source)) @@ -5177,10 +5274,9 @@ without recomputing them, it should be a list of lists." ;; Compute matches without rendering the sources. ;; This prevent the helm-buffer flickering when constantly ;; updating. - (helm-log "helm-update" "Matches: %S" - (setq matches (or candidates (helm--collect-matches sources)))) + (setq matches (or candidates (helm--collect-matches sources))) ;; If computing matches finished and is not interrupted - ;; erase the helm-buffer and render results (Fix #1157). + ;; erase the helm-buffer and render results (Fix bug#1157). (when matches ;; nil only when interrupted by while-no-input. (erase-buffer) (cl-loop for src in sources @@ -5457,7 +5553,7 @@ specified as respectively `helm-cand-num' and `helm-cur-source'." (forward-line 1))) (helm-mark-current-line) (when helm-popup-tip-mode - (helm-maybe-show-help-echo)) + (helm-maybe-show-popup-tip-info)) (helm-follow-execute-persistent-action-maybe)) (select-window (minibuffer-window)) (set-buffer (window-buffer window))))) @@ -5518,101 +5614,119 @@ This will work only in Emacs-26+, i.e. Emacs versions that have "`display-line-numbers' not available") (if helm-display-line-numbers-mode (with-helm-buffer - (setq display-line-numbers 'relative)) + (setq display-line-numbers 'relative) + (helm--action-at-nth-set-fn+ + helm-action-at-nth-positive-prefix-key) + (helm--action-at-nth-set-fn- + helm-action-at-nth-negative-prefix-key)) (with-helm-buffer - (setq display-line-numbers nil))))) + (setq display-line-numbers nil) + (helm--action-at-nth-set-fn+ + helm-action-at-nth-positive-prefix-key 'unset) + (helm--action-at-nth-set-fn- + helm-action-at-nth-negative-prefix-key 'unset))))) (put 'helm-display-line-numbers-mode 'helm-only t) ;;; Async process ;; -(defun helm-output-filter (process output-string) - "The `process-filter' function for Helm async sources." +(defun helm-output-filter (process output) + "The default `process-filter' function for Helm async sources. +See `helm-default-output-filter'." (with-local-quit - (helm-output-filter-1 (assoc process helm-async-processes) output-string))) - -(defun helm-output-filter-1 (process-assoc output-string) - (helm-log "helm-output-filter-1" "output-string = %S" output-string) - (with-current-buffer helm-buffer - (let ((source (cdr process-assoc))) - (save-excursion - (helm-aif (assoc-default 'insertion-marker source) - (goto-char it) - (goto-char (point-max)) - (helm-insert-header-from-source source) - (setcdr process-assoc - (append source `((insertion-marker . ,(point-marker)))))) - (helm-output-filter--process-source - (car process-assoc) output-string source - (helm-candidate-number-limit source)))) + (let* ((process-assoc (assoc process helm-async-processes)) + (source (cdr process-assoc)) + (insertion-marker (cdr (assq 'insertion-marker source))) + (incomplete-line-info (assq 'incomplete-line source)) + (item-count-info (assq 'item-count source)) + (multiline (assq 'multiline source))) + (with-helm-buffer + (save-excursion + (if insertion-marker + (prog1 + ;; Marker position is constantly updated while + ;; text is inserted by `insert-before-markers' which ignore + ;; its type. + (goto-char insertion-marker) + (helm-log "helm-output-filter" + "Goto insertion marker at %S" insertion-marker)) + (goto-char (point-max)) + (helm-insert-header-from-source source) + (helm-log "helm-output-filter" + "Inserting source header name = %S" (assq 'name source)) + (setcdr process-assoc + (append source `((insertion-marker . ,(point-marker)))))) + ;; Split output and treat incomplete lines one by one. We don't use + ;; OMIT-NULLS deliberately to have ("output" "") when splitting + ;; "output\n". + (let ((lines (split-string output "\n")) + candidates) + (while lines + (if (not (cdr lines)) ; An incomplete line. + ;; store it until new output arrives. + (setcdr incomplete-line-info (pop lines)) + (helm-aif (cdr incomplete-line-info) + (let ((head (pop lines))) + (helm-log "helm-output-filter" + "incomplete-line-info(1) = %S" it) + (helm-log "helm-output-filter" + "incomplete-line-info(2) = %S" head) + (push (concat it head) candidates) + ;; Previously we were setting incomplete-line-info to line + ;; and later to (concat incomplete-line-info line) to fix + ;; Bug#1187, it seems both were wrong. + (setcdr incomplete-line-info nil)) + (push (pop lines) candidates)))) + ;; Transform candidates. + (setq candidates (helm-transform-candidates + (nreverse candidates) source t)) + ;; Now insert each candidate in helm buffer. + (catch 'reach-limit + (dolist (candidate candidates) + (setq candidate (helm--maybe-process-filter-one-by-one-candidate + candidate source)) + (let ((start (point))) + (unless (or (not multiline) + (zerop (cdr (assq 'item-count source)))) + (helm-insert-candidate-separator)) + (helm-insert-match candidate 'insert-before-markers + (1+ (cdr (assq 'item-count source))) + source) + (when multiline + (put-text-property start (point) 'helm-multiline t))) + (cl-incf (cdr item-count-info)) + ;; Exit when we reach candidate-number-limit. + (when (>= (cdr item-count-info) (helm-candidate-number-limit source)) + (process-put process 'reach-limit t) + (helm-kill-async-process process #'kill-process) ; SIGKILL (9). + (helm-log-run-hook "helm-output-filter" + 'helm-async-outer-limit-hook) + (throw 'reach-limit nil)))))))) (helm-output-filter--post-process))) -(defun helm-output-filter--process-source (process output-string source limit) - (cl-dolist (candidate (helm-transform-candidates - (helm-output-filter--collect-candidates - (split-string output-string - helm-process-output-split-string-separator) - (assq 'incomplete-line source)) - source t)) - (setq candidate - (helm--maybe-process-filter-one-by-one-candidate candidate source)) - (if (assq 'multiline source) - (let ((start (point))) - (helm-insert-candidate-separator) - (helm-insert-match candidate 'insert-before-markers - (1+ (cdr (assq 'item-count source))) - source) - (put-text-property start (point) 'helm-multiline t)) - (helm-insert-match candidate 'insert-before-markers - (1+ (cdr (assq 'item-count source))) - source)) - (cl-incf (cdr (assq 'item-count source))) - (when (>= (assoc-default 'item-count source) limit) - (helm-kill-async-process process) - (helm-log-run-hook "helm-output-filter--process-source" - 'helm-async-outer-limit-hook) - (cl-return)))) - -(defun helm-output-filter--collect-candidates (lines incomplete-line-info) - "Collect LINES maybe completing the truncated first and last lines." - ;; The output of process may come in chunks of any size, so the last - ;; line of LINES could be truncated, this truncated line is stored - ;; in INCOMPLETE-LINE-INFO to be concatenated with the first - ;; incomplete line of the next arriving chunk. INCOMPLETE-LINE-INFO - ;; is an attribute of source; it is created with an empty string - ;; when the source is computed => (incomplete-line . "") - (helm-log "helm-output-filter--collect-candidates" - "incomplete-line-info = %S" (cdr incomplete-line-info)) - (butlast - (cl-loop for line in lines - ;; On start `incomplete-line-info' value is empty string. - for newline = (helm-aif (cdr incomplete-line-info) - (prog1 - (concat it line) - (setcdr incomplete-line-info nil)) - line) - collect newline - ;; Store last incomplete line (last chunk truncated) until - ;; new output arrives. Previously storing 'line' in - ;; incomplete-line-info assumed output was truncated in - ;; only two chunks. But output could be large and - ;; truncated in more than two chunks. Therefore store - ;; 'newline' to contain the previous chunks (Bug#1187). - finally do (setcdr incomplete-line-info newline)))) - (defun helm-output-filter--post-process () (helm-aif (get-buffer-window helm-buffer 'visible) (with-selected-window it (helm-skip-noncandidate-line 'next) (helm-mark-current-line nil 'nomouse) - ;; FIXME Don't hardcode follow delay. - (helm-follow-execute-persistent-action-maybe 0.5) + (helm-follow-execute-persistent-action-maybe) (helm-display-mode-line (helm-get-current-source)) (helm-log-run-hook "helm-output-filter--post-process" 'helm-after-update-hook) (helm--reset-update-flag)))) +(defun helm-kill-async-processes () + "Kill all asynchronous processes registered in `helm-async-processes'." + (cl-loop for (proc . _src) in helm-async-processes + do (helm-kill-async-process proc) + finally (setq helm-async-processes nil))) + +(defun helm-kill-async-process (process &optional kill-fn) + "Stop output from `helm-output-filter' and kill associated PROCESS." + (set-process-filter process t) + (funcall (or kill-fn #'delete-process) process)) + (defun helm-process-deferred-sentinel-hook (process event file) "Defer remote processes in sentinels. Meant to be called at the beginning of a sentinel process @@ -5641,18 +5755,6 @@ function." (when helm-alive-p ; Don't run timer fn after quit. (setq helm-suspend-update-flag nil) (helm-check-minibuffer-input)))))) - -(defun helm-kill-async-processes () - "Kill all asynchronous processes registered in `helm-async-processes'." - (while helm-async-processes - (helm-kill-async-process (caar helm-async-processes)) - (setq helm-async-processes (cdr helm-async-processes)))) - -(defun helm-kill-async-process (process) - "Stop output from `helm-output-filter' and kill associated PROCESS." - (set-process-filter process nil) - (delete-process process)) - ;;; Actions ;; @@ -6033,8 +6135,8 @@ This is a toggle command." (put 'helm-exchange-minibuffer-and-header-line 'helm-only t) (defun helm--update-header-line () - ;; This should be used in `post-command-hook', - ;; nowhere else. + ;; This is already called in `post-command-hook', + ;; so it should not be called elsewhere. (when (with-helm-buffer helm-echo-input-in-header-line) (helm--set-header-line t))) @@ -6082,9 +6184,10 @@ is \"Candidate(s)\" by default." 'helm-candidate-number-suspended 'helm-candidate-number)))))) -(cl-defun helm-move-selection-common (&key where direction (follow t)) - "Move the selection marker to a new position. +(defun helm-move-selection-common (&rest args) + "Move the selection marker to a new position. Position is determined by WHERE and DIRECTION. +When FOLLOW is specified execute `helm-follow-execute-persistent-action-maybe'. Key arg WHERE can be one of: - line - page @@ -6093,7 +6196,16 @@ Key arg WHERE can be one of: Key arg DIRECTION can be one of: - previous - next - - A source or a source name when used with :WHERE \\='source." + - A source or a source name when used with :WHERE \\='source. + +\(fn &key WHERE DIRECTION FOLLOW)" + (apply #'helm-move-selection-common-1 + (mapcar (lambda (kw) + (plist-get args kw)) + '(:where :direction :follow)))) + +(defun helm-move-selection-common-1 (where direction follow) + (unless follow (setq follow t)) (let ((move-func (cl-case where (line (cl-ecase direction (previous 'helm-move--previous-line-fn) @@ -6484,14 +6596,19 @@ message \\='no match'." (defun helm--set-minibuffer-completion-confirm (src) "Return the value of a REQUIRE-MATCH arg in a `completing-read'." - ;; Set `minibuffer-completion-confirm' to 'noexit or - ;; 'exit, according to MUST-MATCH value (possibly a function). + ;; Set `minibuffer-completion-confirm' to 'noexit,'exit or 'confirm according + ;; to MUST-MATCH value (possibly a function). (with-helm-buffer (setq minibuffer-completion-confirm (helm-acase (helm-get-attr 'must-match src) ((guard* (and (functionp it) - (helm-get-selection nil nil src))) - (if (funcall it guard) 'exit 'noexit)) + (helm-get-selection nil nil src))) + (helm-acase (funcall it guard) + ;; Alow using 'confirm as the output of a REQUIRE-MATCH fn even + ;; if this feature is not available in Emacs. + ((confirm confirm-after-completion) it) + ((guard* (eq nil it)) 'noexit) + (t 'exit))) (t it))))) (defun helm-read-string (prompt &optional initial-input history @@ -6503,10 +6620,10 @@ message \\='no match'." (defun helm--updating-p () ;; helm timer is between two cycles. - ;; IOW `helm-check-minibuffer-input' haven't yet compared input + ;; IOW `helm-check-minibuffer-input' hasn't yet compared input ;; and `helm-pattern'. (or (not (equal (minibuffer-contents) helm-pattern)) - ;; `helm-check-minibuffer-input' have launched `helm-update'. + ;; `helm-check-minibuffer-input' has launched `helm-update'. helm--in-update)) (defun helm-maybe-exit-minibuffer () @@ -6594,8 +6711,7 @@ If action buffer is displayed, kill it." (defun helm-default-debug-function () "Collect sources of helm current session without their keymap. This is the default function for `helm-debug-function'." - (cl-loop for source in (with-helm-buffer helm-sources) - collect (remove (assq 'keymap source) source))) + (with-helm-buffer helm-sources)) (defun helm-debug-output-function () (let ((local-vars (buffer-local-variables (get-buffer helm-buffer))) @@ -6742,25 +6858,23 @@ Used generally to modify current selection." (helm-reset-yank-point) (unless (zerop (length input)) ;; minibuffer is not empty, delete contents from end - ;; of FROM-STR and update. + ;; or FROM-STR and update. (helm-set-pattern from-str t) + (setq helm-input from-str) ; Needed by helm-fuzzy-matching-highlight-fn. (helm-update presel src)))) (defun helm-delete-minibuffer-contents (&optional arg) "Delete minibuffer contents. When `helm-delete-minibuffer-contents-from-point' is non-nil, delete -minibuffer contents from point instead of deleting all. With a prefix -ARG reverse this behaviour. When at the end of minibuffer, delete all -but if a prefix ARG were given also preselect current selection when -updating if possible (selection may be beyond candidate-number-limit)." +minibuffer contents from point instead of deleting all. When at the end +of minibuffer, delete all but if a prefix ARG were given also preselect +current selection when updating if possible (selection may be beyond +candidate-number-limit, or display may have completely changed e.g. HFF)." (interactive "P") (with-helm-alive-p - (let ((str (if helm-delete-minibuffer-contents-from-point - (if (or arg (eobp)) - "" (helm-minibuffer-completion-contents)) - (if (and arg (not (eobp))) - (helm-minibuffer-completion-contents) ""))) - (presel (and arg (eobp) + (let ((str (if (or (eobp) (not helm-delete-minibuffer-contents-from-point)) + "" (helm-minibuffer-completion-contents))) + (presel (and arg (concat "^" (regexp-quote (helm-get-selection nil t)) "$")))) (helm--delete-minibuffer-contents-from str presel)))) (put 'helm-delete-minibuffer-contents 'no-helm-mx t) @@ -6944,7 +7058,7 @@ To customize `helm-candidates-in-buffer' behaviour, use `search', (not (consp pos-lst))) ;; If match-part attr is present, or if SEARCHER fn ;; returns a cons cell, collect PATTERN only if it - ;; match the part of CAND specified by + ;; matches the part of CAND specified by ;; the match-part func. (helm-search-match-part cand pattern diacritics))) do (progn @@ -6969,14 +7083,17 @@ computed by match-part-fn and stored in the match-part property." (t 'string-match)))) (condition-case _err (if (string-match " " pattern) + ;; FIXME use helm-mm-3-match here. (cl-loop for i in (helm-mm-split-pattern pattern) always (if (string-match "\\`!" i) (not (funcall matchfn (substring i 1) part)) (funcall matchfn i part))) + ;; A pattern with no spaces that starts with "!". (if (string-match "\\`!" pattern) (if helm--in-fuzzy ;; Fuzzy regexp have already been - ;; computed with substring 1. + ;; computed with substring 1 i.e. the leading "!" has been + ;; removed. (not (string-match fuzzy-regexp part)) (not (funcall matchfn (substring pattern 1) part))) (funcall matchfn (if helm--in-fuzzy fuzzy-regexp pattern) part))) @@ -7208,55 +7325,86 @@ unless FORCE-LONGEST is non nil." max))) -;;; Resplit helm window +;;; Actions on helm window ;; ;; -(defun helm-toggle-resplit-window () - "Toggle resplit helm window, vertically or horizontally." +(defvar helm--resplit-window-iterator nil) +(defun helm-resplit-window-clockwise () + "Change the window split to move Helm window clockwise w.r.t the main window. +See `helm-resplit-window-1'." + (interactive) + (helm-resplit-window-1 1)) +(put 'helm-resplit-window-clockwise 'helm-only t) + +(defun helm-resplit-window-counterclockwise () + "Change the window split to move Helm window counterclockwise. +See `helm-resplit-window-1'." (interactive) + (helm-resplit-window-1 -1)) +(put 'helm-resplit-window-counterclockwise 'helm-only t) + +(defun helm-resplit-window-1 (arg) + "Change the window split to move Helm window. + +At each call of this function, change the window split w.r.t the main +window to left, above, right or below direction remembering your +previous movement, this when there is only two windows. Split direction +is clockwise if ARG is positive and counterclockwise if +negative. Otherwise when there is more than two windows and the helm +buffer is displayed in one of those windows i.e. `helm-always-two-windows' is +nil, the helm buffer is moved in the next or previous window according to ARG +value." (with-helm-alive-p - (if (and (= (length (window-list nil 1)) 2) - (not (window-dedicated-p - (get-buffer-window helm-current-buffer)))) - (progn - (when helm-prevent-escaping-from-minibuffer - (helm-prevent-switching-other-window :enabled nil)) - (unwind-protect - (with-helm-window - (cond ((or helm-full-frame (one-window-p t)) - (user-error "Attempt to resplit a single window")) - ((helm-action-window) - (user-error "Can't resplit while selecting actions")) - (t - (let ((before-height (window-height))) - (delete-window) - (set-window-buffer - (select-window - (if (= (window-height) before-height) ; initial split was horizontal. - ;; Split window vertically with `helm-buffer' placed - ;; on the good side according to actual value of - ;; `helm-split-window-default-side'. - (prog1 - (cond ((or (eq helm-split-window-default-side 'above) - (eq helm-split-window-default-side 'left)) - (split-window - (selected-window) nil 'above)) - (t (split-window-vertically))) - (setq helm-split-window-state 'vertical)) - ;; Split window vertically, same comment as above. - (setq helm-split-window-state 'horizontal) - (cond ((or (eq helm-split-window-default-side 'left) - (eq helm-split-window-default-side 'above)) - (split-window (selected-window) nil 'left)) - (t (split-window-horizontally))))) - helm-buffer)))) - (setq helm--window-side-state (helm--get-window-side-state))) - (when helm-prevent-escaping-from-minibuffer - (helm-prevent-switching-other-window :enabled t)))) - (error "current window configuration not suitable for splitting")))) -(put 'helm-toggle-resplit-window 'helm-only t) - -;; Utility: Resize helm window. + (cond ((> (length (window-list nil 1)) 2) + (helm-swap-windows arg)) + ((and (= (length (window-list nil 1)) 2) + (not (window-dedicated-p + (get-buffer-window helm-current-buffer)))) + (when helm-prevent-escaping-from-minibuffer + (helm-prevent-switching-other-window :enabled nil)) + (unwind-protect + (with-helm-window + (cond ((or helm-full-frame (one-window-p t)) + (user-error "Attempt to resplit a single window")) + ((helm-action-window) + (user-error "Can't resplit while selecting actions")) + ((window-parameter + (get-buffer-window helm-current-buffer) 'window-slot) + (user-error "Can't resplit a side window")) + (t (helm--resplit-window arg)))) + (when helm-prevent-escaping-from-minibuffer + (helm-prevent-switching-other-window :enabled t)))) + (t (error "current window configuration not suitable for splitting"))))) + +(defun helm--resplit-window (arg) + (let ((current-state (helm--get-window-side-state)) + new-state) + (unless (and (eq last-command this-command) + (eq current-state helm--window-side-state)) + (setq helm--resplit-window-iterator + (helm-iter-circular (helm--resplit-window-sides + current-state arg)))) + (setq new-state (helm-iter-next helm--resplit-window-iterator) + helm-split-window-state (helm-acase new-state + ((right left) 'horizontal) + ((below above) 'vertical))) + (delete-window) + (set-window-buffer + (select-window + (split-window (selected-window) nil new-state)) + helm-buffer) + (setq helm--window-side-state (helm--get-window-side-state)))) + +(defun helm--resplit-window-sides (state arg) + (let ((clockwise (helm-acase state + (right '(below left above)) + (left '(above right below)) + (below '(left above right)) + (above '(right below left))))) + (append (if (< arg 0) (reverse clockwise) clockwise) + (list state)))) + +;; Resize helm window. (defun helm-enlarge-window-1 (n) "Enlarge or narrow helm window. If N is positive enlarge, if negative narrow." @@ -7303,62 +7451,79 @@ If N is positive enlarge, if negative narrow." (setq helm-onewindow-p t)))) (put 'helm-toggle-full-frame 'helm-only t) -(defun helm-swap-windows () - "Swap window holding `helm-buffer' with other window." - (interactive) +(defun helm-swap-windows (&optional arg) + "Swap window holding `helm-buffer' with other windows. +Start swapping in the same order of windows as window-list." + (interactive "p") (with-helm-alive-p - (if (= (length (window-list nil 1)) 2) - (cond ((and helm-full-frame (one-window-p t)) - (user-error "Can't swap windows in a single window")) - ((helm-action-window) - (user-error "Can't resplit while selecting actions")) - (t - (let* ((w1 (helm-window)) - (split-state (eq helm-split-window-state 'horizontal)) - (w1size (window-total-size w1 split-state)) - (b1 (window-buffer w1)) ; helm-buffer - (s1 (window-start w1)) - (cur-frame (window-frame w1)) - (w2 (with-selected-window (helm-window) - ;; Don't try to display helm-buffer - ;; in a dedicated window. - (get-window-with-predicate - (lambda (w) (not (window-dedicated-p w))) - 1 cur-frame))) - (w2size (window-total-size w2 split-state)) - (b2 (window-buffer w2)) ; probably helm-current-buffer - (s2 (window-start w2)) - resize) - (with-selected-frame (window-frame w1) - (helm-replace-buffer-in-window w1 b1 b2) - (helm-replace-buffer-in-window w2 b2 b1) - (setq resize - (cond ( ;; helm-window is smaller than other window. - (< w1size w2size) - (- (- (max w2size w1size) - (min w2size w1size)))) - ( ;; helm-window is larger than other window. - (> w1size w2size) - (- (max w2size w1size) - (min w2size w1size))) - ( ;; windows have probably same size. - t nil))) - ;; Maybe resize the window holding helm-buffer. - (and resize (window-resize w2 resize split-state)) - (set-window-start w1 s2 t) - (set-window-start w2 s1 t)) - (setq helm--window-side-state (helm--get-window-side-state))))) - (error "current window configuration not suitable for splitting")))) + (cond ((and helm-full-frame (one-window-p t)) + (user-error "Can't swap windows in a single window")) + ((helm-action-window) + (user-error "Can't swap windows while selecting actions")) + ((window-parameter (get-buffer-window helm-current-buffer) 'window-slot) + (user-error "Can't swap with a side window")) + (t + (let* ((w1 (helm-window)) + (split-state (eq helm-split-window-state 'horizontal)) + (w1size (window-total-size w1 split-state)) + (b1 (window-buffer w1)) ; helm-buffer + (s1 (window-start w1)) + (cur-frame (window-frame w1)) + (w2 (with-selected-window (helm-window) + ;; Don't try to display helm-buffer + ;; in a dedicated window. + (helm--get-window-with-predicate + (lambda (w) (not (window-dedicated-p w))) + 1 cur-frame nil arg))) + (w2size (window-total-size w2 split-state)) + (b2 (window-buffer w2)) ; probably helm-current-buffer + (s2 (window-start w2)) + resize) + (with-selected-frame (window-frame w1) + (helm-replace-buffer-in-window w1 b1 b2) + (helm-replace-buffer-in-window w2 b2 b1) + (setq resize + (cond (;; helm-window is smaller than other window. + (< w1size w2size) + (- (- (max w2size w1size) + (min w2size w1size)))) + (;; helm-window is larger than other window. + (> w1size w2size) + (- (max w2size w1size) + (min w2size w1size))) + (;; windows have probably same size. + t nil))) + ;; Maybe resize the window holding helm-buffer. + (and resize (window-resize w2 resize split-state)) + (set-window-start w1 s2 t) + (set-window-start w2 s1 t)) + (setq helm--window-side-state (helm--get-window-side-state) + helm--resplit-window-iterator nil)))))) (put 'helm-swap-windows 'helm-only t) +(defun helm--get-window-with-predicate (predicate &optional minibuf all-frames default arg) + "Same as `get-window-with-predicate' but allow changing direction with ARG." + (catch 'found + (dolist (window (window-list-1 + (if (< arg 0) + (previous-window nil minibuf all-frames) + (next-window nil minibuf all-frames)) + minibuf all-frames)) + (when (funcall predicate window) + (throw 'found window))) + default)) + (defun helm--get-window-side-state () - "Return the position of `helm-window' from `helm-current-buffer'. + "Return the position of `helm-window' w.r.t main window. +Main window can be the window handling `helm-current-buffer' but also the +persistent action window. Possible values are \\='left \\='right \\='below or \\='above." (let ((side-list '(left right below above))) (cl-loop for side in side-list thereis (and (equal (helm-window) (window-in-direction - side (get-buffer-window helm-current-buffer t) + side (or (get-buffer-window helm-current-buffer t) + (helm-persistent-action-display-window)) t)) side)))) @@ -7367,8 +7532,8 @@ Possible values are \\='left \\='right \\='below or \\='above." (when (get-buffer-window buffer1) (unrecord-window-buffer window buffer1) (set-window-buffer window buffer2))) - -;; Utility: select another action by key + +;; select another action by key (defun helm-select-nth-action (n) "Select the N nth action for the currently selected candidate." (let ((src (helm-get-current-source))) @@ -7410,7 +7575,7 @@ Argument ACTION can be a symbol or a list of actions." (defun helm-initialize-persistent-action () (set (make-local-variable 'helm-persistent-action-display-window) nil)) -(cl-defun helm-execute-persistent-action (&optional attr split) +(defun helm-execute-persistent-action (&optional attr split) "Perform the associated action ATTR without quitting helm. Arg ATTR default will be `persistent-action' or @@ -7426,72 +7591,73 @@ in only one window, the helm window is split to display maintain visibility. The argument SPLIT can be used to force splitting inconditionally, it is unused currently." (interactive) - (with-suppressed-warnings ((obsolete special-display-regexps) - (obsolete special-display-buffer-names)) - (with-helm-alive-p - (let ((source (helm-get-current-source))) - (unless attr - (setq attr (or (car (assq 'persistent-action source)) - (car (assq 'persistent-action-if source))))) - (helm-log "helm-execute-persistent-action" "executing persistent-action") - (let* ((selection (and source (helm-get-selection nil nil source))) - (attr-val (if (eq attr 'persistent-action-if) - (funcall (assoc-default attr source) selection) - (assoc-default attr source))) - ;; If attr value is a cons, use its car as persistent function. - (fn (if (and (consp attr-val) - ;; maybe a lambda. - (not (functionp attr-val))) - (car attr-val) attr-val)) - ;; And its cdr to decide if helm window should be splitted. - (no-split (and (consp attr-val) - (not (functionp attr-val)) - (cdr attr-val))) - ;; Is next-window (from helm-window) a suitable window for PA? - (no-suitable-win - (helm-aand (not helm--buffer-in-new-frame-p) - (get-buffer-window helm-current-buffer) - (or (window-dedicated-p it) - (window-parameter it 'window-side)))) - (cursor-in-echo-area t) - mode-line-in-non-selected-windows) - (progn - (when (and helm-onewindow-p (null no-split) - (null helm--buffer-in-new-frame-p)) - (helm-toggle-full-frame)) - (when (eq fn 'ignore) - (cl-return-from helm-execute-persistent-action nil)) - (when source - (with-helm-window - (save-selected-window - ;; FIXME: Simplify SPLIT behavior, it is a mess currently. - (if no-split - (helm-select-persistent-action-window :split 'never) - (helm-select-persistent-action-window - :split (or split helm-onewindow-p no-suitable-win))) - (helm-log "helm-execute-persistent-action" - "current-buffer = %S" (current-buffer)) - (let ((helm-in-persistent-action t) - (display-buffer-alist '((".*" (display-buffer-same-window)))) - display-buffer-function pop-up-windows pop-up-frames - special-display-regexps special-display-buffer-names) - (helm-execute-selection-action-1 - selection (or fn (helm-get-actions-from-current-source source)) t) - (unless (helm-action-window) - (helm-log-run-hook "helm-execute-persistent-action" - 'helm-after-persistent-action-hook))) - ;; A typical case is when a persistent action delete - ;; the buffer already displayed in - ;; `helm-persistent-action-display-window' and `helm-full-frame' - ;; is enabled, we end up with the `helm-buffer' - ;; displayed in two windows. - (when (and helm-onewindow-p - (> (length (window-list)) 1) - (equal (buffer-name - (window-buffer - helm-persistent-action-display-window)) - (helm-buffer-get))) - (delete-other-windows))))))))))) + (catch 'ignore + (with-suppressed-warnings ((obsolete special-display-regexps) + (obsolete special-display-buffer-names)) + (with-helm-alive-p + (let ((source (helm-get-current-source))) + (unless attr + (setq attr (or (car (assq 'persistent-action source)) + (car (assq 'persistent-action-if source))))) + (helm-log "helm-execute-persistent-action" "executing persistent-action") + (let* ((selection (and source (helm-get-selection nil nil source))) + (attr-val (if (eq attr 'persistent-action-if) + (funcall (assoc-default attr source) selection) + (assoc-default attr source))) + ;; If attr value is a cons, use its car as persistent function. + (fn (if (and (consp attr-val) + ;; maybe a lambda. + (not (functionp attr-val))) + (car attr-val) attr-val)) + ;; And its cdr to decide if helm window should be splitted. + (no-split (and (consp attr-val) + (not (functionp attr-val)) + (cdr attr-val))) + ;; Is next-window (from helm-window) a suitable window for PA? + (no-suitable-win + (helm-aand (not helm--buffer-in-new-frame-p) + (get-buffer-window helm-current-buffer) + (or (window-dedicated-p it) + (window-parameter it 'window-side)))) + (cursor-in-echo-area t) + mode-line-in-non-selected-windows) + (progn + (when (and helm-onewindow-p (null no-split) + (null helm--buffer-in-new-frame-p)) + (helm-toggle-full-frame)) + (when (eq fn 'ignore) + (throw 'ignore nil)) + (when source + (with-helm-window + (save-selected-window + ;; FIXME: Simplify SPLIT behavior, it is a mess currently. + (if no-split + (helm-select-persistent-action-window :split 'never) + (helm-select-persistent-action-window + :split (or split helm-onewindow-p no-suitable-win))) + (helm-log "helm-execute-persistent-action" + "current-buffer = %S" (current-buffer)) + (let ((helm-in-persistent-action t) + (display-buffer-alist '((".*" (display-buffer-same-window)))) + display-buffer-function pop-up-windows pop-up-frames + special-display-regexps special-display-buffer-names) + (helm-execute-selection-action-1 + selection (or fn (helm-get-actions-from-current-source source)) t) + (unless (helm-action-window) + (helm-log-run-hook "helm-execute-persistent-action" + 'helm-after-persistent-action-hook))) + ;; A typical case is when a persistent action delete + ;; the buffer already displayed in + ;; `helm-persistent-action-display-window' and `helm-full-frame' + ;; is enabled, we end up with the `helm-buffer' + ;; displayed in two windows. + (when (and helm-onewindow-p + (> (length (window-list)) 1) + (equal (buffer-name + (window-buffer + helm-persistent-action-display-window)) + (helm-buffer-get))) + (delete-other-windows)))))))))))) (put 'helm-execute-persistent-action 'helm-only t) (cl-defun helm-persistent-action-display-window (&key split) @@ -7574,7 +7740,7 @@ Meaning of prefix ARG is the same as in `reposition-window'." (put 'helm-reposition-window-other-window 'helm-only t) -;; Utility: Visible Mark +;; Visible Mark (defun helm-clear-visible-mark () (with-current-buffer (helm-buffer-get) @@ -7654,13 +7820,15 @@ If ARG is negative toggle backward." helm-left-margin-width))))))) (put 'helm-toggle-visible-mark 'helm-only t) -(defun helm-toggle-visible-mark-forward () - (interactive) - (helm-toggle-visible-mark 1)) +(defun helm-toggle-visible-mark-forward (&optional arg) + "Toggle visible mark forward ARG times." + (interactive "p") + (helm-toggle-visible-mark arg)) -(defun helm-toggle-visible-mark-backward () - (interactive) - (helm-toggle-visible-mark -1)) +(defun helm-toggle-visible-mark-backward (&optional arg) + "Toggle visible mark backward ARG times." + (interactive "p") + (helm-toggle-visible-mark (- arg))) (defun helm-file-completion-source-p (&optional source) "Return non-nil if current source is a file completion source." @@ -7810,10 +7978,12 @@ ALL-SOURCES key value is non-nil returns marked candidates of all sources." (with-current-buffer helm-buffer (let* ((current-src (helm-get-current-source)) + (src-name (assq 'name current-src)) + (dummy (equal (helm-get-attr 'candidates current-src) '("dummy"))) (candidates (cl-loop for (source . real) in (reverse helm-marked-candidates) for use-wc = (and with-wildcard - (string-match-p "\\*" real) + (string-match-p "[[*?]" real) (null (file-exists-p real))) when (or all-sources (and @@ -7821,10 +7991,8 @@ sources." ;; dummy sources (or more) should share their ;; (unique) marked candidate only when ;; :all-marked is non nil. - (not (equal (helm-get-attr 'candidates) - '("dummy"))) - (equal (assq 'name source) - (assq 'name current-src)))) + (not dummy) + (equal (assq 'name source) src-name))) nconc (helm--compute-marked real source use-wc) into mkds finally return (if (and with-wildcard all-sources) @@ -7833,8 +8001,7 @@ sources." sel) (unless candidates (setq sel (helm-get-selection - nil (helm-get-attr 'marked-with-props - current-src) + nil (helm-get-attr 'marked-with-props current-src) current-src)) (setq candidates (helm--compute-marked @@ -7954,19 +8121,22 @@ With a prefix arg set to real value of current selection." (defun helm-kill-selection-and-quit (arg) "Store display value of current selection to kill ring. -With a prefix arg use real value of current selection. -Display value is shown in `helm-buffer' and real value is used to -perform actions." +Kill \\='display or \\='real value of candidate according to the value of +`helm-kill-real-or-display-selection'. A prefix arg reverse the behavior of +this variable." (interactive "P") (with-helm-alive-p (helm-run-after-exit (lambda (sel) (kill-new sel) ;; Return nil to force `helm-mode--keyboard-quit' - ;; in `helm-comp-read' otherwise the value "Saved to kill-ring: foo" + ;; in `helm-comp-read' otherwise the message itself ;; is used as exit value for `helm-comp-read'. (prog1 nil (message "Saved to kill-ring: %s" sel) (sit-for 1))) - (format "%s" (helm-get-selection nil (not arg)))))) + (format "%s" (helm-get-selection + nil (helm-acase helm-kill-real-or-display-selection + (real arg) + (display (and (not arg) 'noicon)))))))) (put 'helm-kill-selection-and-quit 'helm-only t) (defun helm-insert-or-copy (&optional arg) @@ -7990,11 +8160,6 @@ The real value of each candidate is used." ;;; Follow-mode: Automatic execution of persistent-action ;; ;; -(defvar helm-follow-input-idle-delay nil - "`helm-follow-mode' will execute its persistent action after this delay. -Note that if the `follow-delay' attr is present in source, it -will take precedence over this.") - (defun helm-follow-mode (&optional arg) "Execute persistent action every time the cursor is moved. @@ -8075,15 +8240,8 @@ They are bound by default to \\[helm-follow-action-forward] and "Execute persistent action in mode `helm-follow-mode'. This happen after: DELAY or the \\='follow-attr value of current -source or `helm-follow-input-idle-delay' or -`helm-input-idle-delay' secs." +source or `helm-follow-input-idle-delay'." (let* ((src (helm-get-current-source)) - (at (or delay - (assoc-default 'follow-delay src) - helm-follow-input-idle-delay - (or (and helm-input-idle-delay - (max helm-input-idle-delay 0.01)) - 0.01))) (suspend (and helm--in-update ;; Specific to helm-find-files. (assoc-default 'suspend-follow-in-update src)))) @@ -8097,9 +8255,35 @@ source or `helm-follow-input-idle-delay' or (null (eq (assoc-default 'follow src) 'never)) (helm-get-selection nil nil src)) (helm-follow-mode-set-source 1 src) - (run-with-idle-timer at nil (lambda () - (when helm-alive-p - (helm-execute-persistent-action))))))) + (helm--execute-persistent-action-when-idle delay src)))) + +;; We could use a simple idle timer here as before with a delay fixed at minimum +;; 0.5, the effect is the same but it creates a timer at each call, with this +;; code a new timer is created only after being idle 0.5 and restarting +;; scrolling. That's mean that when hitting C-n continuously no new timer is +;; created, we reuse `helm--execute-persistent-action-timer' until it is not +;; consumed i.e. the PA is executed because we are idle. +(defvar helm--execute-persistent-action-timer nil) +(defun helm--execute-persistent-action-when-idle (&optional delay src) + "Call persistent action only once idle DELAY that many seconds. +SRC is used to check if there is a delay specified for this source. +Also avoid creating needlessly a timer at each call." + ;; More or less similar to what the debounce fn in timeout package does, + ;; except the timer is stored in a global var instead of beeing stored in a + ;; closure and there is no default output, we just execute + ;; helm-execute-persistent-action once emacs is idle. + (when helm-alive-p + (let ((at (or delay + (assoc-default 'follow-delay src) + helm-follow-input-idle-delay))) + (unless (timerp helm--execute-persistent-action-timer) + (setq helm--execute-persistent-action-timer + (run-with-idle-timer + at nil + (lambda () + (cancel-timer helm--execute-persistent-action-timer) + (setq helm--execute-persistent-action-timer nil) + (helm-execute-persistent-action)))))))) (defun helm-follow-mode-p (&optional source) (with-helm-buffer @@ -8150,16 +8334,20 @@ message explaining this is added instead. The global `helm-help-message' is always added after this local help." (interactive) - (require 'helm-mode) ; for helm-comp-read. + (require 'helm-mode nil t) ; for helm-comp-read. (with-helm-alive-p - (let ((source (or (helm-get-current-source) - (helm-comp-read - "Help for: " - (cl-loop for src in (with-helm-buffer helm-sources) - collect `(,(assoc-default 'name src) . - ,src)) - :allow-nest t - :exec-when-only-one t)))) + (let ((source (or (helm-get-current-source) ; nil when helm-buffer is empty. + (and (fboundp 'helm-comp-read) + (helm-comp-read + "Help for: " + (cl-loop for src in (with-helm-buffer helm-sources) + collect `(,(assoc-default 'name src) . + ,src)) + :allow-nest t + :exec-when-only-one t)) + ;; No completion on sources when only helm-core package is + ;; used. + (car helm-sources)))) (save-selected-window (helm-help-internal helm-help-buffer-name diff --git a/elpa/helm-core-20250514.1025/helm-lib.el b/elpa/helm-core-20251211.709/helm-lib.el similarity index 97% rename from elpa/helm-core-20250514.1025/helm-lib.el rename to elpa/helm-core-20251211.709/helm-lib.el index 05f03973..b89372b9 100644 --- a/elpa/helm-core-20250514.1025/helm-lib.el +++ b/elpa/helm-core-20251211.709/helm-lib.el @@ -56,6 +56,8 @@ (declare-function helm-read-file-name "helm-mode.el") (declare-function find-function-library "find-func.el") (declare-function find-library-name "find-func.el") +(declare-function cl--describe-class-slots "cl-extra.el") +(declare-function cl--find-class "cl-macs.el") (defvar helm-sources) (defvar helm-initial-frame) @@ -459,7 +461,7 @@ Like `this-command' but return the real command, and not ;; (defun helm-iter-list (seq &optional cycle) "Return an iterator object from SEQ. -The iterator die and return nil when it reach end of SEQ. +The iterator dies and returns nil when it reaches end of SEQ. When CYCLE is specified the iterator never ends." (let ((lis seq)) (lambda () @@ -1474,16 +1476,29 @@ If object is a lambda, return \"Anonymous\"." (defun helm-describe-class (class) "Display documentation of Eieio CLASS, a symbol or a string." - (let ((advicep (advice-member-p #'helm-source--cl--print-table 'cl--print-table))) - (unless advicep - (advice-add 'cl--print-table :override #'helm-source--cl--print-table '((depth . 100)))) - (unwind-protect - (if (fboundp 'cl-describe-type) - (cl-describe-type (helm-symbolify class)) - (let ((helm-describe-function-function 'describe-function)) - (helm-describe-function (helm-symbolify class)))) - (unless advicep - (advice-remove 'cl--print-table #'helm-source--cl--print-table))))) + (cl-letf (((symbol-function 'cl--print-table) + #'helm-source--cl--print-table)) + (if (fboundp 'cl-describe-type) + (cl-describe-type (helm-symbolify class)) + (let ((helm-describe-function-function 'describe-function)) + (helm-describe-function (helm-symbolify class)))))) + +(defun helm-elisp-collect-slots-in-class (class) + (with-temp-buffer + (cl-letf (((symbol-function 'cl--print-table) + #'helm-source--cl--print-table)) + (cl--describe-class-slots (cl--find-class class)) + (goto-char (point-min)) + (cl-loop while (re-search-forward "^\\* \\(.*\\)" nil t) + for name = (match-string 1) + for doc = (save-excursion + (forward-line 1) + (let ((beg (point)) + (end (when (re-search-forward "^\\*" nil t) + (1- (match-beginning 0))))) + (when (and beg end) + (buffer-substring beg end)))) + collect (cons name (concat "* " name "\n" doc)))))) (defun helm-describe-function (func) "Display documentation of FUNC, a symbol or string." @@ -1495,6 +1510,12 @@ If object is a lambda, return \"Anonymous\"." (cl-letf (((symbol-function 'message) #'ignore)) (funcall helm-describe-variable-function (helm-symbolify var)))) +(defun helm-describe-symbol (sym) + "Display documentation of SYM, a symbol or a string." + (cl-letf (((symbol-function 'message) #'ignore)) + (let ((helm-describe-function-function 'describe-symbol)) + (funcall helm-describe-function-function (helm-symbolify sym))))) + (defun helm-describe-face (face) "Display documentation of FACE, a symbol or a string." (let ((faces (helm-marked-candidates))) @@ -2024,7 +2045,10 @@ Directories expansion is not supported." (goto-char (point-min)) (when (re-search-forward "^;;;?\\(.*\\) ---? \\(.*\\)" (pos-eol) t) (setq desc (match-string-no-properties 2))) - (if (or (null desc) (string= "" desc) (string-match "\\`-\\*-" desc)) + (if (or (null desc) (string= "" desc) + ;; Fix issue#2716 with an header line like + ;; ";; foo --- -*-[...]" i.e. desc is not provided. + (string-match "\\`-\\*-" desc)) "Not documented" (car (split-string desc "-\\*-" nil "[ \t\n\r-]+")))))) @@ -2042,19 +2066,24 @@ Take same args as `directory-files'." ;; at least 27.1, see bug#2662. (apply #'directory-files directory args))) -(defun helm-common-dir-1 (files) - "Find the common directories of FILES." +(defun helm-common-str-1 (files &optional dirp) + "Find the common string or directory in FILES. +When DIRP is non nil return the common part which is a directory." (if (cdr files) (cl-loop with base = (car files) with others = nil for file in files - for cpart = (fill-common-string-prefix base file) + for cpart = (if dirp + (helm-acase (fill-common-string-prefix base file) + ((guard* (and it (file-directory-p it))) it) + (t (and it (file-name-directory it)))) + (fill-common-string-prefix base file)) if cpart do (setq base cpart) else do (push file others) finally return (if (and others base) (nconc (list (directory-file-name base)) - (helm-common-dir-1 others)) + (helm-common-str-1 others)) (list (and base (directory-file-name base))))) (and files (list (directory-file-name (file-name-directory (car files))))))) @@ -2063,7 +2092,7 @@ Take same args as `directory-files'." "Return the longest common directory path of FILES list. If FILES are not all common to the same drive (Windows) a list of common directory is returned." - (let ((result (helm-common-dir-1 files))) + (let ((result (helm-common-str-1 files t))) (if (cdr result) result (car result)))) ;; Tests: @@ -2086,8 +2115,12 @@ common directory is returned." "Set minibuffer contents to PATTERN. If optional NOUPDATE is non-nil, the Helm buffer is not changed." (with-selected-window (or (active-minibuffer-window) (minibuffer-window)) - (delete-minibuffer-contents) - (insert pattern)) + ;; Minibuffer may have a read-only string when using completion-in-region, + ;; which prevent inserting in minibuffer. see + ;; `helm-mode--completion-in-region-initial-input'. + (let ((inhibit-read-only t)) + (delete-minibuffer-contents) + (insert pattern))) (when noupdate (setq helm-pattern pattern))) @@ -2271,6 +2304,7 @@ flex or helm-flex completion style if present." (add-hook 'helm-cleanup-hook 'helm-reset-yank-point) (add-hook 'helm-after-initialize-hook 'helm-reset-yank-point) + ;;; Ansi ;; ;; @@ -2325,28 +2359,6 @@ broken." (when (< emacs-major-version 26) (advice-add 'ansi-color-apply :override #'helm--ansi-color-apply)) - -;;; Fontlock -(dolist (mode '(emacs-lisp-mode lisp-interaction-mode)) - (font-lock-add-keywords - mode - '(("(\\<\\(with-helm-after-update-hook\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-temp-hook\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-window\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-current-buffer\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-buffer\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-show-completion\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-default-directory\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(with-helm-restore-variables\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-multi-key-defun\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-while-no-input\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-aif\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-awhile\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-acond\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-aand\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-with-gensyms\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-read-answer-dolist-with-action\\)\\>" 1 font-lock-keyword-face) - ("(\\<\\(helm-read-answer\\)\\>" 1 font-lock-keyword-face)))) (provide 'helm-lib) diff --git a/elpa/helm-core-20250514.1025/helm-multi-match.el b/elpa/helm-core-20251211.709/helm-multi-match.el similarity index 74% rename from elpa/helm-core-20250514.1025/helm-multi-match.el rename to elpa/helm-core-20251211.709/helm-multi-match.el index 903bd9b5..1a1a1d7f 100644 --- a/elpa/helm-core-20250514.1025/helm-multi-match.el +++ b/elpa/helm-core-20251211.709/helm-multi-match.el @@ -31,26 +31,22 @@ "Helm multi match." :group 'helm) -(defcustom helm-mm-matching-method 'multi3 +(defvar helm-mm-matching-method 'multi3 "Matching method for helm match plugin. You can set here different methods to match candidates in helm. Here are the possible value of this symbol and their meaning: - multi1: Respect order, prefix of pattern must match. - multi2: Same but with partial match. - multi3: The best, multiple regexp match, allow negation. +- multi3f: Same as multi3 but for files only (HFF and friends). - multi3p: Same but prefix must match. Default is multi3, you should keep this for a better experience. -Note that multi1 and multi3p are incompatible with fuzzy matching -in file completion and by the way fuzzy matching will be disabled there -when these options are used." - :type '(radio :tag "Matching methods for helm" - (const :tag "Multiple regexp 1 ordered with prefix match" multi1) - (const :tag "Multiple regexp 2 ordered with partial match" multi2) - (const :tag "Multiple regexp 3 matching no order, partial, best." multi3) - (const :tag "Multiple regexp 3p matching with prefix match" multi3p)) - :group 'helm-multi-match) +The multi3f method is meant to be used within `helm-find-files' or at +least when matching on a list of files or strings with a leading common +part like the basedir of an absolute filename from the same directory +but never globally.") ;; Internal @@ -98,7 +94,8 @@ If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"." helm-mm--exact-pattern-real) -(cl-defun helm-mm-exact-match (candidate &optional (pattern helm-pattern)) +(defun helm-mm-exact-match (candidate &optional pattern) + (unless pattern (setq pattern helm-pattern)) (if case-fold-search (string= (downcase candidate) (downcase pattern)) (string= candidate pattern))) @@ -106,36 +103,10 @@ If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"." (defun helm-mm-exact-search (pattern &rest _ignore) (helm-re-search-forward (helm-mm-exact-get-pattern pattern) nil t)) - -;;; Prefix match -;; -;; -;; Internal -(defvar helm-mm--prefix-pattern-str nil) -(defvar helm-mm--prefix-pattern-real nil) - -(defun helm-mm-prefix-get-pattern (pattern) - (unless (equal pattern helm-mm--prefix-pattern-str) - (setq helm-mm--prefix-pattern-str pattern - helm-mm--prefix-pattern-real (concat "\n" pattern))) - helm-mm--prefix-pattern-real) - -(defun helm-mm-prefix-match (candidate &optional pattern) - ;; In filename completion basename and basedir may be - ;; quoted, unquote them for string comparison (Bug#1283). - (setq pattern (replace-regexp-in-string - "\\\\" "" (or pattern helm-pattern))) - (let ((len (length pattern))) - (and (<= len (length candidate)) - (string= (substring candidate 0 len) pattern )))) - -(defun helm-mm-prefix-search (pattern &rest _ignore) - (search-forward (helm-mm-prefix-get-pattern pattern) nil t)) - ;;; Multiple regexp patterns 1 (order is preserved / prefix). ;; -;; +;; Same as "^foo.*bar.*baz" ;; Internal (defvar helm-mm--1-pattern-str nil) (defvar helm-mm--1-pattern-real nil) @@ -147,7 +118,8 @@ If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"." (concat "^" (helm-mm-1-make-regexp pattern)))) helm-mm--1-pattern-real) -(cl-defun helm-mm-1-match (candidate &optional (pattern helm-pattern)) +(defun helm-mm-1-match (candidate &optional pattern) + (unless pattern (setq pattern helm-pattern)) (string-match (helm-mm-1-get-pattern pattern) candidate)) (defun helm-mm-1-search (pattern &rest _ignore) @@ -156,7 +128,7 @@ If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"." ;;; Multiple regexp patterns 2 (order is preserved / partial). ;; -;; +;; Same as "^.*foo.*bar.*baz" ;; Internal (defvar helm-mm--2-pattern-str nil) (defvar helm-mm--2-pattern-real nil) @@ -168,7 +140,8 @@ If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"." (concat "^.*" (helm-mm-1-make-regexp pattern)))) helm-mm--2-pattern-real) -(cl-defun helm-mm-2-match (candidate &optional (pattern helm-pattern)) +(defun helm-mm-2-match (candidate &optional pattern) + (unless pattern (setq pattern helm-pattern)) (string-match (helm-mm-2-get-pattern pattern) candidate)) (defun helm-mm-2-search (pattern &rest _ignore) @@ -207,7 +180,7 @@ E.g., ((identity . \"foo\") (not . \"bar\"))." (defvar helm-mm--match-on-diacritics nil) -(cl-defun helm-mm-3-match (candidate &optional (pattern helm-pattern)) +(defun helm-mm-3-match (candidate &optional pattern) "Check if PATTERN match CANDIDATE. When PATTERN contains a space, it is splitted and matching is done with the several resulting regexps against CANDIDATE. @@ -218,7 +191,7 @@ E.g., \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")). Then each predicate of cons cell(s) is called with the regexp of the same cons cell against CANDIDATE. I.e. (identity (string-match \"foo\" \"foo bar\")) => t." - (let ((pat (helm-mm-3-get-patterns pattern))) + (let ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))) (cl-loop for (predicate . regexp) in pat for re = (if (and helm-mm--match-on-diacritics (not (helm-mm-regexp-p regexp))) @@ -247,27 +220,36 @@ i.e (identity (re-search-forward \"foo\" (pos-eol) t)) => t." (not (helm-mm-regexp-p regex))) (char-fold-to-regexp regex) regex) + with prefix-search = (eq searchfn1 'helm-mm-prefix-search) + ;; First pattern is a negation. when (eq (caar pat) 'not) return ;; Pass the job to `helm-search-match-part'. - ;; We now forward-line from helm-search-from-candidate-buffer, see + ;; We now forward-line from `helm-search-from-candidate-buffer', see ;; comments about bug#2650 there. (list (pos-bol) (pos-eol)) + ;; Start searching the first pattern [1]. while (condition-case _err (funcall searchfn1 (or regex1 "") nil t) (invalid-regexp nil)) for bol = (pos-bol) for eol = (pos-eol) + for end = (and prefix-search (+ bol (match-end 0))) ; End of prefix. + ;; Now search subsequent patterns on this line. if (cl-loop for (pred . str) in (cdr pat) for regexp = (if (and helm-mm--match-on-diacritics (not (helm-mm-regexp-p str))) (char-fold-to-regexp str) str) always - (progn (goto-char bol) + ;; Search from end of initial match (prefix) or from bol. + (progn (goto-char (or end bol)) (funcall pred (condition-case _err (funcall searchfn2 regexp eol t) (invalid-regexp nil))))) + ;; When all patterns match on line move at eol or next line and exit + ;; with t. do (helm-mm-3--search-move-forward bol eol) and return t + ;; if no matches continue [1] until the next matching line and so on. else do (helm-mm-3--search-move-forward bol eol) finally return nil)) @@ -283,8 +265,70 @@ Forward line on empty lines, otherwise goto eol." (defun helm-mm-3-search-on-diacritics (pattern &rest _ignore) (let ((helm-mm--match-on-diacritics t)) (helm-mm-3-search pattern))) + + +;;; mm-3f (match on filenames) +;; +;; +;; When this is called by HFF, the pattern is transformed like this: +;; "/home/you/foo/foo bar" => "/home/you/foo/ foo bar" so the prefix is always +;; the basedir. +(defun helm-mm-3f-match (candidate &optional pattern) + "Same as `helm-mm-3-match' but for files or prefix matching. +Once the first pattern is matched, the subsequent patterns match on the part of +CANDIDATE starting at end of first match. +Diacritics regexp is never used on the first pattern, the basedir." + ;; When matching a filename like "/home/you/github/foo-bar.txt" there is no + ;; problems with `helm-mm-3-match' as long as one of the patterns doesn't + ;; match the basedir of filename but as soon as you try to match a file with a + ;; name matching basedir we would match all the file of directory instead of + ;; just the files we want e.g. with a pattern like "/home/you/github/ foo git" + ;; you would match all files of directory instead of matching only + ;; "/home/you/github/foo-git.el" because "git" will always match "github". + (let ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))) + (cl-loop with end = nil + for (predicate . regexp) in pat + for re = (if (and helm-mm--match-on-diacritics + (not (helm-mm-regexp-p regexp))) + (char-fold-to-regexp regexp) + regexp) + ;; Use `char-fold-to-regexp' on subsequent patterns only. + for pref-re = (if end re (concat "\\`" regexp)) + always (funcall predicate + (prog1 (condition-case _err + (string-match pref-re candidate end) + (invalid-regexp nil)) + (unless end + (setq end (match-end 0)))))))) + +(defun helm-mm-3f-match-on-diacritics (candidate &optional pattern) + "Ignore diacritics in basename of files. +This happens as soon as you enter multi matching i.e. you add space(s) after +basedir." + (let ((helm-mm--match-on-diacritics t)) + (helm-mm-3f-match candidate (or pattern helm-pattern)))) + +;;; multiple regexp pattern 3 with prefix search +;; +;; +(defalias 'helm-mm-3p-match #'helm-mm-3f-match + "Check if PATTERN match CANDIDATE. +Same as `helm-mm-3-match' but only for the cdr of patterns, the car of +patterns must always match CANDIDATE prefix. +E.g. \"bar foo baz\" will match \"barfoobaz\" or \"barbazfoo\" but not +\"foobarbaz\" whereas `helm-mm-3-match' would match all.") + +;; This is just a wrapper around helm-re-search-forward but we need it in +;; helm-mm-3-search-base to decide if we use prefix search or not by comparing +;; symbols. +(defun helm-mm-prefix-search (pattern &rest _ignore) + (helm-re-search-forward pattern nil t)) + +(defun helm-mm-3p-search (pattern &rest _ignore) + (helm-mm-3-search-base + pattern 'helm-mm-prefix-search 'helm-re-search-forward)) -;;; mp-3 with migemo +;;; mm-3 with migemo ;; Needs https://github.com/emacs-jp/migemo ;; (defvar helm-mm--previous-migemo-info nil @@ -336,7 +380,8 @@ sources." (char-fold-to-regexp pattern)) str)) -(cl-defun helm-mm-3-migemo-match (candidate &optional (pattern helm-pattern)) +(defun helm-mm-3-migemo-match (candidate &optional pattern) + (unless pattern (setq pattern helm-pattern)) (and helm-migemo-mode (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern) always (funcall pred (helm-mm-migemo-string-match re candidate))))) @@ -357,41 +402,24 @@ sources." (helm-mm-3-search-base pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward))) - -;;; mp-3p- (multiple regexp pattern 3 with prefix search) -;; -;; -(defun helm-mm-3p-match (candidate &optional pattern) - "Check if PATTERN match CANDIDATE. -Same as `helm-mm-3-match' but only for the cdr of patterns, the car of -patterns must always match CANDIDATE prefix. -E.g. \"bar foo baz\" will match \"barfoobaz\" or \"barbazfoo\" but not -\"foobarbaz\" whereas `helm-mm-3-match' would match all." - (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern))) - (first (car pat))) - (and (funcall (car first) (helm-mm-prefix-match candidate (cdr first))) - (cl-loop for (predicate . regexp) in (cdr pat) - always (funcall predicate (string-match regexp candidate)))))) - -(defun helm-mm-3p-search (pattern &rest _ignore) - (helm-mm-3-search-base - pattern 'helm-mm-prefix-search 're-search-forward)) - ;;; Generic multi-match/search functions ;; ;; -(cl-defun helm-mm-match (candidate &optional (pattern helm-pattern)) +(defun helm-mm-match (candidate &optional pattern) "Call `helm-mm-matching-method' function against CANDIDATE." + (unless pattern (setq pattern helm-pattern)) (let ((fun (cl-ecase helm-mm-matching-method (multi1 #'helm-mm-1-match) (multi2 #'helm-mm-2-match) (multi3 #'helm-mm-3-match) + (multi3f #'helm-mm-3f-match) (multi3p #'helm-mm-3p-match)))) (funcall fun candidate pattern))) -(cl-defun helm-mm-3-match-on-diacritics (candidate &optional (pattern helm-pattern)) +(defun helm-mm-3-match-on-diacritics (candidate &optional pattern) "Same as `helm-mm-3-match' but match on diacritics if possible." + (unless pattern (setq pattern helm-pattern)) (let ((helm-mm--match-on-diacritics t)) (helm-mm-match candidate pattern))) @@ -401,7 +429,7 @@ E.g. \"bar foo baz\" will match \"barfoobaz\" or \"barbazfoo\" but not (multi1 #'helm-mm-1-search) (multi2 #'helm-mm-2-search) (multi3 #'helm-mm-3-search) - (multi3p #'helm-mm-3p-search)))) + ((multi3p multi3f) #'helm-mm-3p-search)))) (funcall fun pattern))) diff --git a/elpa/helm-core-20250514.1025/helm-source.el b/elpa/helm-core-20251211.709/helm-source.el similarity index 95% rename from elpa/helm-core-20250514.1025/helm-source.el rename to elpa/helm-core-20251211.709/helm-source.el index e7b3ead1..392eb8d2 100644 --- a/elpa/helm-core-20250514.1025/helm-source.el +++ b/elpa/helm-core-20251211.709/helm-source.el @@ -481,14 +481,24 @@ :initform nil :custom boolean :documentation - " Ignore diacritics when searching.") + " Ignore diacritics when searching or matching. + + If it is a function, use that function that takes CANDIDATE as single + argument, otherwise, if non-nil use one of the default functions + depending of the method in use, either searching or matching.") (match-on-real :initarg :match-on-real :initform nil :custom boolean :documentation - " Match the real value of candidates when non nil.") + "Match the real value of candidates when non nil. +Note that this assume you are using (DISPLAY . REAL) candidates and +these candidates are computed as cons cell _before_ +`helm-match-from-candidates' run. This mean you have to compute your +candidates as cons cell either in the :candidates or :init function or +in a :candidate-transformer. Expect an error if you compute your +candidates as cons cell in a :filtered-candidate-transformer.") (fuzzy-match :initarg :fuzzy-match @@ -625,7 +635,7 @@ :documentation " `helm-follow-mode' will execute persistent-action after this delay. Otherwise value of `helm-follow-input-idle-delay' is used if non--nil, - If none of these are found fallback to `helm-input-idle-delay'.") + Fall back to 0.5 when none of these are found.") (multimatch :initarg :multimatch @@ -1012,6 +1022,11 @@ Arguments ARGS are keyword value pairs as defined in CLASS." Argument METHOD is the matching method used by SOURCE either `match' or `search'." (let* ((diacritics (slot-value source 'diacritics)) + (diacritics-fn (if (functionp diacritics) + diacritics + (helm-acase method + (match #'helm-mm-3-match-on-diacritics) + (search #'helm-mm-3-search-on-diacritics)))) (defmatch (helm-aif (slot-value source 'match) (helm-mklist it))) (defmatch-strict (helm-aif (and (eq method 'match) @@ -1023,20 +1038,36 @@ or `search'." (defsearch-strict (helm-aif (and (eq method 'search-strict) (slot-value source 'search-strict)) (helm-mklist it))) - (migemo (slot-value source 'migemo))) + (migemo (slot-value source 'migemo)) + ;; Ensure helm-mm-match/search is not used when one of the helm-mm-* + ;; fns is specified directly in source. + (helm-mm-default-match-functions + (if (cl-loop for fn in defmatch + thereis (memq fn '(helm-mm-3f-match + helm-mm-3p-match + helm-mm-3-match + helm-mm-2-match + helm-mm-1-match))) + (remove 'helm-mm-match helm-mm-default-match-functions) + helm-mm-default-match-functions)) + (helm-mm-default-search-functions + (if (cl-loop for fn in defsearch + thereis (memq fn '(helm-mm-3p-search + helm-mm-3-search + helm-mm-2-search + helm-mm-1-search))) + (remove 'helm-mm-search helm-mm-default-search-functions) + helm-mm-default-search-functions))) (cl-case method (match (cond (defmatch-strict) ((and migemo diacritics) - (append (list 'helm-mm-exact-match - 'helm-mm-3-match-on-diacritics) + (append (list 'helm-mm-exact-match diacritics-fn) defmatch '(helm-mm-3-migemo-match))) (migemo (append helm-mm-default-match-functions defmatch '(helm-mm-3-migemo-match))) (diacritics - (delq nil - `(helm-mm-exact-match - ,@defmatch helm-mm-3-match-on-diacritics))) + (delq nil `(helm-mm-exact-match ,@defmatch ,diacritics-fn))) (defmatch (append helm-mm-default-match-functions defmatch)) (t helm-mm-default-match-functions))) @@ -1044,15 +1075,13 @@ or `search'." ((and migemo diacritics) (append '(helm-mm-exact-search) defsearch - '(helm-mm-3-migemo-search - helm-mm-3-search-on-diacritics))) + `(helm-mm-3-migemo-search ,diacritics-fn))) (migemo (append helm-mm-default-search-functions defsearch '(helm-mm-3-migemo-search))) (diacritics (delq nil - `(helm-mm-exact-search - ,@defsearch helm-mm-3-search-on-diacritics))) + `(helm-mm-exact-search ,@defsearch ,diacritics-fn))) (defsearch (append helm-mm-default-search-functions defsearch)) (t helm-mm-default-search-functions)))))) -- 2.47.3