]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
update helm-projectile
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Fri, 24 Apr 2026 16:49:41 +0000 (18:49 +0200)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Fri, 24 Apr 2026 16:49:41 +0000 (18:49 +0200)
elpa/helm-projectile-20250218.1525/helm-projectile-autoloads.el [deleted file]
elpa/helm-projectile-20250218.1525/helm-projectile-pkg.el [deleted file]
elpa/helm-projectile-20250218.1525/helm-projectile.el [deleted file]
elpa/helm-projectile-20250902.830/helm-projectile-autoloads.el [new file with mode: 0644]
elpa/helm-projectile-20250902.830/helm-projectile-pkg.el [new file with mode: 0644]
elpa/helm-projectile-20250902.830/helm-projectile.el [new file with mode: 0644]

diff --git a/elpa/helm-projectile-20250218.1525/helm-projectile-autoloads.el b/elpa/helm-projectile-20250218.1525/helm-projectile-autoloads.el
deleted file mode 100644 (file)
index 3df6960..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-;;; helm-projectile-autoloads.el --- automatically extracted autoloads (do not edit)   -*- lexical-binding: t -*-
-;; Generated by the `loaddefs-generate' function.
-
-;; This file is part of GNU Emacs.
-
-;;; Code:
-
-(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
-
-
-\f
-;;; Generated autoloads from helm-projectile.el
-
-(defvar helm-projectile-fuzzy-match t "\
-Enable fuzzy matching for Helm Projectile commands.
-This needs to be set before loading helm-projectile.el.")
-(custom-autoload 'helm-projectile-fuzzy-match "helm-projectile" t)
-(autoload 'helm-projectile-find-file-dwim "helm-projectile" "\
-Find file at point based on context." t)
-(autoload 'helm-projectile-find-other-file "helm-projectile" "\
-Switch between files with the same name but different extensions using Helm.
-With FLEX-MATCHING, match any file that contains the base name of
-current file.  Other file extensions can be customized with the
-variable `projectile-other-file-alist'.
-
-(fn &optional FLEX-MATCHING)" t)
-(autoload 'helm-projectile-on "helm-projectile" "\
-Turn on `helm-projectile' key bindings." t)
-(autoload 'helm-projectile-off "helm-projectile" "\
-Turn off `helm-projectile' key bindings." t)
-(autoload 'helm-projectile-grep "helm-projectile" "\
-Helm version of `projectile-grep'.
-DIR is the project root, if not set then current directory is used
-
-(fn &optional DIR)" t)
-(autoload 'helm-projectile-ack "helm-projectile" "\
-Helm version of projectile-ack.
-DIR directory where to search
-
-(fn &optional DIR)" t)
-(autoload 'helm-projectile-ag "helm-projectile" "\
-Helm version of `projectile-ag'.
-OPTIONS explicit command line arguments to ag
-
-(fn &optional OPTIONS)" t)
-(autoload 'helm-projectile-rg "helm-projectile" "\
-Projectile version of `helm-rg'." t)
-(autoload 'helm-projectile-toggle "helm-projectile" "\
-Toggle Helm version of Projectile commands.
-
-(fn TOGGLE)")
-(autoload 'helm-projectile "helm-projectile" "\
-Use projectile with Helm instead of ido.
-
-With a prefix ARG invalidates the cache first.
-If invoked outside of a project, displays a list of known projects to jump.
-
-(fn &optional ARG)" t)
-(eval-after-load 'projectile '(progn (define-key projectile-command-map (kbd "h") #'helm-projectile)))
-(register-definition-prefixes "helm-projectile" '("glob-quote" "helm-"))
-\f
-;;; End of scraped data
-
-(provide 'helm-projectile-autoloads)
-
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; no-native-compile: t
-;; coding: utf-8-emacs-unix
-;; End:
-
-;;; helm-projectile-autoloads.el ends here
diff --git a/elpa/helm-projectile-20250218.1525/helm-projectile-pkg.el b/elpa/helm-projectile-20250218.1525/helm-projectile-pkg.el
deleted file mode 100644 (file)
index 67adb9a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-;; -*- no-byte-compile: t; lexical-binding: nil -*-
-(define-package "helm-projectile" "20250218.1525"
-  "Helm integration for Projectile."
-  '((helm       "3.0")
-    (projectile "2.9")
-    (cl-lib     "0.3"))
-  :url "https://github.com/bbatsov/helm-projectile"
-  :commit "041076e35a6663302a91a0fa672f847c7d64bf29"
-  :revdesc "041076e35a66"
-  :keywords '("project" "convenience"))
diff --git a/elpa/helm-projectile-20250218.1525/helm-projectile.el b/elpa/helm-projectile-20250218.1525/helm-projectile.el
deleted file mode 100644 (file)
index 9cd7a12..0000000
+++ /dev/null
@@ -1,1198 +0,0 @@
-;;; helm-projectile.el --- Helm integration for Projectile         -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2011-2025 Bozhidar Batsov
-
-;; Author: Bozhidar Batsov
-;; URL: https://github.com/bbatsov/helm-projectile
-;; Created: 2011-31-07
-;; Keywords: project, convenience
-;; Package-Version: 20250218.1525
-;; Package-Revision: 041076e35a66
-;; Package-Requires: ((helm "3.0") (projectile "2.9") (cl-lib "0.3"))
-
-;; This file is NOT part of GNU Emacs.
-
-;;; License:
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-;;
-;; This library provides easy project management and navigation.  The
-;; concept of a project is pretty basic - just a folder containing
-;; special file.  Currently git, mercurial and bazaar repos are
-;; considered projects by default.  If you want to mark a folder
-;; manually as a project just create an empty .projectile file in
-;; it.  See the README for more details.
-;;
-;;; Code:
-
-;; built-in libraries
-(require 'subr-x)
-(require 'cl-lib)
-(require 'grep) ;; TODO: Probably we should defer this require
-
-(require 'helm-core)
-(require 'helm-global-bindings)
-(require 'helm-types)
-(require 'helm-locate)
-(require 'helm-buffers)
-(require 'helm-files)
-
-(require 'projectile)
-
-(declare-function eshell "eshell")
-(declare-function helm-do-ag "ext:helm-ag")
-(declare-function dired-get-filename "dired")
-(defvar helm-ag-base-command)
-
-(defvar grep-find-ignored-directories)
-(defvar grep-find-ignored-files)
-
-(defgroup helm-projectile nil
-  "Helm support for projectile."
-  :prefix "helm-projectile-"
-  :group 'projectile
-  :group 'helm
-  :link `(url-link :tag "GitHub" "https://github.com/bbatsov/helm-projectile"))
-
-(defvar helm-projectile-current-project-root)
-
-(defcustom helm-projectile-truncate-lines nil
-  "Truncate lines in helm projectile commands when non--nil.
-
-Some `helm-projectile' commands have similar behavior with existing
-Helms.  In these cases their respective custom var for truncation
-of lines will be honored.  E.g. `helm-buffers-truncate-lines'
-dictates the truncation in `helm-projectile-switch-to-buffer'."
-  :group 'helm-projectile
-  :type 'boolean)
-
-;;;###autoload
-(defcustom helm-projectile-fuzzy-match t
-  "Enable fuzzy matching for Helm Projectile commands.
-This needs to be set before loading helm-projectile.el."
-  :group 'helm-projectile
-  :type 'boolean)
-
-(defmacro helm-projectile-define-key (keymap key def &rest bindings)
-  "In KEYMAP, define KEY - DEF sequence KEY1 as DEF1, KEY2 as DEF2 ..."
-  (declare (indent defun))
-  (let ((ret '(progn)))
-    (while key
-      (push
-       `(define-key ,keymap ,key
-          (lambda ()
-            (interactive)
-            (helm-exit-and-execute-action ,def)))
-       ret)
-      (setq key (pop bindings)
-            def (pop bindings)))
-    (reverse ret)))
-
-(defun helm-projectile-hack-actions (actions &rest prescription)
-  "Given a Helm action list and a prescription, return a hacked Helm action list.
-Optionally applies the PRESCRIPTION beforehand.
-
-The Helm action list ACTIONS is of the form:
-
-\(\(DESCRIPTION1 . FUNCTION1\)
- \(DESCRIPTION2 . FUNCTION2\)
- ...
- \(DESCRIPTIONn . FUNCTIONn\)\)
-
-PRESCRIPTION is in the form:
-
-\(INSTRUCTION1 INSTRUCTION2 ... INSTRUCTIONn\)
-
-If an INSTRUCTION is a symbol, the action with function name
-INSTRUCTION is deleted.
-
-If an INSTRUCTION is of the form \(FUNCTION1 . FUNCTION2\), the
-action with function name FUNCTION1 will change it's function to
-FUNCTION2.
-
-If an INSTRUCTION is of the form \(FUNCTION . DESCRIPTION\), and
-if an action with function name FUNCTION exists in the original
-Helm action list, the action in the Helm action list, with
-function name FUNCTION will change it's description to
-DESCRIPTION.  Otherwise, (FUNCTION . DESCRIPTION) will be added to
-the action list.
-
-Please check out how `helm-projectile-file-actions' is defined
-for an example of how this function is being used."
-  (let* ((to-delete (cl-remove-if (lambda (entry) (listp entry)) prescription))
-         (actions (cl-delete-if (lambda (action) (memq (cdr action) to-delete))
-                                (copy-alist actions)))
-         new)
-    (cl-dolist (action actions)
-      (when (setq new (cdr (assq (cdr action) prescription)))
-        (if (stringp new)
-            (setcar action new)
-          (setcdr action new))))
-    ;; Add new actions from PRESCRIPTION
-    (setq new nil)
-    (cl-dolist (instruction prescription)
-      (when (and (listp instruction)
-                 (null (rassq (car instruction) actions))
-                 (symbolp (car instruction)) (stringp (cdr instruction)))
-        (push (cons (cdr instruction) (car instruction)) new)))
-    (append actions (nreverse new))))
-
-(defun helm-projectile-vc (dir)
-  "A Helm action for jumping to project root using `vc-dir' or Magit.
-DIR is a directory to be switched"
-  (let ((projectile-require-project-root nil))
-    (projectile-vc dir)))
-
-(defun helm-projectile-compile-project (dir)
-  "A Helm action for compile a project.
-DIR is the project root."
-  (let ((helm--reading-passwd-or-string t)
-        (default-directory dir))
-    (projectile-compile-project helm-current-prefix-arg)))
-
-(defun helm-projectile-test-project (dir)
-  "A Helm action for test a project.
-DIR is the project root."
-  (let ((helm--reading-passwd-or-string t)
-        (default-directory dir))
-    (projectile-test-project helm-current-prefix-arg)))
-
-(defun helm-projectile-run-project (dir)
-  "A Helm action for run a project.
-DIR is the project root."
-  (let ((helm--reading-passwd-or-string t)
-        (default-directory dir))
-    (projectile-run-project helm-current-prefix-arg)))
-
-(defun helm-projectile-remove-known-project (_ignore)
-  "Remove selected projects from projectile project list.
-_IGNORE means the argument does not matter.
-It is there because Helm requires it."
-  (let* ((projects (helm-marked-candidates :with-wildcard t))
-         (len (length projects)))
-    (with-helm-display-marked-candidates
-      helm-marked-buffer-name
-      projects
-      (if (not (y-or-n-p (format "Remove *%s projects(s)? " len)))
-          (message "(No removal performed)")
-        (progn
-          (mapc (lambda (p)
-                  (setq projectile-known-projects (delete p projectile-known-projects)))
-                projects)
-          (projectile-save-known-projects))
-        (message "%s projects(s) removed" len)))))
-
-(defvar helm-projectile-projects-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map helm-map)
-    (helm-projectile-define-key map
-      (kbd "C-d") #'dired
-      (kbd "M-g") #'helm-projectile-vc
-      (kbd "M-e") #'helm-projectile-switch-to-shell
-      (kbd "C-s") #'helm-projectile-grep
-      (kbd "M-c") #'helm-projectile-compile-project
-      (kbd "M-t") #'helm-projectile-test-project
-      (kbd "M-r") #'helm-projectile-run-project
-      (kbd "M-D") #'helm-projectile-remove-known-project)
-    map)
-  "Mapping for known projectile projects.")
-
-(defcustom helm-source-projectile-projects-actions
-  (helm-make-actions
-   "Switch to project" (lambda (project)
-                         (let ((projectile-completion-system 'helm))
-                           (projectile-switch-project-by-name project)))
-   "Open Dired in project's directory `C-d'" #'dired
-   "Open project root in vc-dir or magit `M-g'" #'helm-projectile-vc
-   "Switch to Eshell `M-e'" #'helm-projectile-switch-to-shell
-   "Grep in projects `C-s'" #'helm-projectile-grep
-   "Compile project `M-c'. With C-u, new compile command" #'helm-projectile-compile-project
-   "Remove project(s) from project list `M-D'" #'helm-projectile-remove-known-project)
-  "Actions for `helm-source-projectile-projects'."
-  :group 'helm-projectile
-  :type '(alist :key-type string :value-type function))
-
-(defclass helm-projectile-projects-source (helm-source-sync helm-type-file)
-  ((candidates :initform (lambda () (with-helm-current-buffer
-                                      (mapcar #'copy-sequence
-                                              (projectile-known-projects)))))
-   (fuzzy-match :initform 'helm-projectile-fuzzy-match)
-   (keymap :initform 'helm-projectile-projects-map)
-   (mode-line :initform 'helm-read-file-name-mode-line-string)
-   (action :initform 'helm-source-projectile-projects-actions))
-  "Helm source for known projectile projects.")
-
-(cl-defmethod helm--setup-source :after ((source helm-projectile-projects-source))
-  "Make SOURCE specific to project switching.
-The `helm-projectile-projects-source` inherits from
-`helm-type-file` (which see), which sets up actions, keymap, and
-help message slots to file specific ones.  Override these slots
-to be specific to `helm-projectile-projects-source'."
-  (setf (slot-value source 'action) 'helm-source-projectile-projects-actions)
-  (setf (slot-value source 'keymap) helm-projectile-projects-map)
-  ;; Use `ignore' as a persistent action, to actually keep `helm' session
-  ;; when `helm-execute-persistent-action' is executed.
-  (setf (slot-value source 'persistent-action) #'ignore)
-  (let ((persistent-help "Do Nothing"))
-    (setf (slot-value source 'persistent-help) persistent-help)
-    (setf (slot-value source 'header-line)
-          (helm-source--persistent-help-string
-           persistent-help
-           source)))
-  (setf (slot-value source 'mode-line)
-        (list "Project(s)" helm-mode-line-string)))
-
-(defvar helm-source-projectile-projects
-  (helm-make-source "Projectile projects" 'helm-projectile-projects-source))
-
-(defvar helm-projectile-dirty-projects-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map helm-map)
-    (helm-projectile-define-key map
-      (kbd "C-d") #'dired
-      (kbd "M-o") #'(lambda (project)
-                      (let ((projectile-completion-system 'helm))
-                        (projectile-switch-project-by-name project)))
-      (kbd "M-e") #'helm-projectile-switch-to-shell
-      (kbd "C-s") #'helm-projectile-grep
-      (kbd "M-c") #'helm-projectile-compile-project
-      (kbd "M-t") #'helm-projectile-test-project
-      (kbd "M-r") #'helm-projectile-run-project
-      (kbd "M-D") #'helm-projectile-remove-known-project)
-    map)
-  "Mapping for dirty projectile projects.")
-
-(defvar helm-source-projectile-dirty-projects
-  (helm-build-sync-source "Projectile dirty projects"
-    :candidates (lambda () (with-helm-current-buffer (helm-projectile-get-dirty-projects)))
-    :fuzzy-match helm-projectile-fuzzy-match
-    :keymap helm-projectile-dirty-projects-map
-    :mode-line helm-read-file-name-mode-line-string
-    :action '(("Open project root in vc-dir or magit" . helm-projectile-vc)
-              ("Switch to project `M-o'" .
-               (lambda (project)
-                 (let ((projectile-completion-system 'helm))
-                   (projectile-switch-project-by-name project))))
-              ("Open Dired in project's directory `C-d'" . dired)
-              ("Switch to Eshell `M-e'" . helm-projectile-switch-to-shell)
-              ("Grep in projects `C-s'" . helm-projectile-grep)
-              ("Compile project `M-c'. With C-u, new compile command"
-               . helm-projectile-compile-project)))
-    "Helm source for dirty version controlled projectile projects.")
-
-(defun helm-projectile-get-dirty-projects ()
-  "Return dirty version controlled known projects as an alist to
-have a nice display in Helm."
-  (message "Checking for dirty known projects...")
-  (let* ((status (projectile-check-vcs-status-of-known-projects))
-         (proj-dir (cl-loop for stat in status
-                            collect (car stat)))
-         (status-display (cl-loop for stat in status collect
-                                  (propertize (format "[%s]" (mapconcat 'identity (car (cdr stat)) ", ")) 'face 'helm-match)))
-         (max-status-display-length (cl-loop for sd in status-display
-                                             maximize (length sd)))
-         (status-display (cl-loop for sd in status-display collect
-                                  (format "%s%s    " sd (make-string (- max-status-display-length (length sd)) ? ))))
-         (full-display (cl-mapcar 'concat status-display proj-dir))
-         (helm-list (cl-pairlis full-display proj-dir)))
-    helm-list))
-
-(define-key helm-etags-map (kbd "C-c p f")
-  (lambda ()
-    (interactive)
-    (helm-run-after-exit 'helm-projectile-find-file nil)))
-
-(defun helm-projectile-file-persistent-action (candidate)
-  "Persistent action for file-related functionality.
-
-Previews the contents of a file in a temporary buffer."
-  (let ((buf (get-buffer-create " *helm-projectile persistent*")))
-    (cl-flet ((preview (candidate)
-                       (switch-to-buffer buf)
-                       (setq inhibit-read-only t)
-                       (erase-buffer)
-                       (insert-file-contents candidate)
-                       (let ((buffer-file-name candidate))
-                         (set-auto-mode))
-                       (font-lock-ensure)
-                       (setq inhibit-read-only nil)))
-      (if (and (helm-get-attr 'previewp)
-               (string= candidate (helm-get-attr 'current-candidate)))
-          (progn
-            (kill-buffer buf)
-            (helm-set-attr 'previewp nil))
-        (preview candidate)
-        (helm-set-attr 'previewp t)))
-    (helm-set-attr 'current-candidate candidate)))
-
-(defun helm-projectile-find-files-eshell-command-on-file-action (candidate)
-  (interactive)
-  (let* ((helm-ff-default-directory (file-name-directory candidate)))
-    (helm-find-files-eshell-command-on-file candidate)))
-
-(defun helm-projectile-ff-etags-select-action (candidate)
-  (interactive)
-  (let* ((helm-ff-default-directory (file-name-directory candidate)))
-    (helm-ff-etags-select candidate)))
-
-(defun helm-projectile-switch-to-shell (dir)
-  "Within DIR, switch to a shell corresponding to `helm-ff-preferred-shell-mode'."
-  (interactive)
-  (let* ((projectile-require-project-root nil)
-         (helm-ff-default-directory (file-name-directory (projectile-expand-root dir))))
-    (helm-ff-switch-to-shell dir)))
-
-(defun helm-projectile-files-in-current-dired-buffer ()
-  "Return a list of files (only) in the current dired buffer."
-  (let (flist)
-    (cl-flet ((fpush (fname) (push fname flist)))
-      (save-excursion
-        (let (file buffer-read-only)
-          (goto-char (point-min))
-          (while (not (eobp))
-            (save-excursion
-              (and (not (eolp))
-                   (setq file (dired-get-filename t t)) ; nil on non-file
-                   (progn (end-of-line)
-                          (funcall #'fpush file))))
-            (forward-line 1)))))
-    (mapcar 'file-truename (nreverse flist))))
-
-(defun helm-projectile-all-dired-buffers ()
-  "Get all current Dired buffers."
-  (mapcar (lambda (b)
-            (with-current-buffer b (buffer-name)))
-          (cl-remove-if-not
-           (lambda (b)
-             (with-current-buffer b
-               (and (eq major-mode 'dired-mode)
-                    (buffer-name))))
-           (buffer-list))))
-
-(defvar helm-projectile-virtual-dired-remote-enable nil
-  "Enable virtual Dired manager on remote host.
-Disabled by default.")
-
-(defun helm-projectile-dired-files-new-action (candidate)
-  "Create a Dired buffer from chosen files.
-CANDIDATE is the selected file, but choose the marked files if available."
-  (if (and (file-remote-p (projectile-project-root))
-           (not helm-projectile-virtual-dired-remote-enable))
-      (message "Virtual Dired manager is disabled in remote host. Enable with %s."
-               (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
-    (let ((files (cl-remove-if-not
-                  (lambda (f)
-                    (not (string= f "")))
-                  (mapcar (lambda (file)
-                            (replace-regexp-in-string (projectile-project-root) "" file))
-                          (helm-marked-candidates :with-wildcard t))))
-          (new-name (completing-read "Select or enter a new buffer name: "
-                                     (helm-projectile-all-dired-buffers)))
-          (helm--reading-passwd-or-string t)
-          (default-directory (projectile-project-root)))
-      ;; create a unique buffer that is unique to any directory in default-directory
-      ;; or opened buffer; when Dired is passed with a non-existence directory name,
-      ;; it only creates a buffer and insert everything. If a new name user supplied
-      ;; exists as default-directory, Dired throws error when insert anything that
-      ;; does not exist in current directory.
-      (with-current-buffer (dired (cons (make-temp-name new-name)
-                                        (if files
-                                            files
-                                          (list candidate))))
-        (when (get-buffer new-name)
-          (kill-buffer new-name))
-        (rename-buffer new-name)))))
-
-(defun helm-projectile-dired-files-add-action (candidate)
-  "Add files to a Dired buffer.
-CANDIDATE is the selected file.  Used when no file is explicitly marked."
-  (if (and (file-remote-p (projectile-project-root))
-           (not helm-projectile-virtual-dired-remote-enable))
-      (message "Virtual Dired manager is disabled in remote host. Enable with %s."
-               (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
-    (if (eq (with-helm-current-buffer major-mode) 'dired-mode)
-        (let* ((marked-files (helm-marked-candidates :with-wildcard t))
-               (helm--reading-passwd-or-string t)
-               (root (projectile-project-root)) ; store root for later use
-               (dired-buffer-name (or (and (eq major-mode 'dired-mode) (buffer-name))
-                                      (completing-read "Select a Dired buffer:"
-                                                       (helm-projectile-all-dired-buffers))))
-               (dired-files (with-current-buffer dired-buffer-name
-                              (helm-projectile-files-in-current-dired-buffer)))
-               (files (sort (mapcar (lambda (file)
-                                      (replace-regexp-in-string (projectile-project-root) "" file))
-                                    (cl-nunion (if marked-files
-                                                   marked-files
-                                                 (list candidate))
-                                               dired-files
-                                               :test #'string-equal))
-                            'string-lessp)))
-          (kill-buffer dired-buffer-name)
-          ;; Rebind default-directory because after killing a buffer, we
-          ;; could be in any buffer and default-directory is set to that
-          ;; random buffer
-          ;;
-          ;; Also use saved root directory, because after killing a buffer,
-          ;; we could be outside of current project
-          (let ((default-directory root))
-            (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
-                                              (if files
-                                                  (mapcar (lambda (file)
-                                                            (replace-regexp-in-string root "" file))
-                                                          files)
-                                                (list candidate))))
-              (rename-buffer dired-buffer-name))))
-      (error "You're not in a Dired buffer to add"))))
-
-(defun helm-projectile-dired-files-delete-action (candidate)
-  "Delete selected entries from a Dired buffer.
-CANDIDATE is the selected file.  Used when no file is explicitly marked."
-  (if (and (file-remote-p (projectile-project-root))
-           (not helm-projectile-virtual-dired-remote-enable))
-      (message "Virtual Dired manager is disabled in remote host. Enable with %s."
-               (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
-    (let* ((helm--reading-passwd-or-string t)
-           (root (projectile-project-root))
-           (dired-buffer-name (with-helm-current-buffer (buffer-name)))
-           (dired-files (with-current-buffer dired-buffer-name
-                          (helm-projectile-files-in-current-dired-buffer)))
-           (files (sort (cl-set-exclusive-or (helm-marked-candidates :with-wildcard t)
-                                             dired-files
-                                             :test #'string-equal) #'string-lessp)))
-      (kill-buffer dired-buffer-name)
-      ;; similar reason to `helm-projectile-dired-files-add-action'
-      (let ((default-directory root))
-        (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
-                                          (if files
-                                              (mapcar (lambda (file)
-                                                        (replace-regexp-in-string root "" file))
-                                                      files)
-                                            (list candidate))))
-          (rename-buffer dired-buffer-name))))))
-
-(defun helm-projectile-run-projectile-hooks-after-find-file (_orig-fun &rest _args)
-  "Run `projectile-find-file-hook' if using projectile."
-  (when (and projectile-mode (projectile-project-p))
-    (run-hooks 'projectile-find-file-hook)))
-
-(advice-add 'helm-find-file-or-marked
-            :after #'helm-projectile-run-projectile-hooks-after-find-file)
-
-(defvar helm-projectile-find-file-map
-  (let ((map (copy-keymap helm-find-files-map)))
-    (helm-projectile-define-key map
-      (kbd "C-c f") #'helm-projectile-dired-files-new-action
-      (kbd "C-c a") #'helm-projectile-dired-files-add-action
-      (kbd "M-e") #'helm-projectile-switch-to-shell
-      (kbd "M-.") #'helm-projectile-ff-etags-select-action
-      (kbd "M-!") #'helm-projectile-find-files-eshell-command-on-file-action)
-    (define-key map (kbd "<left>") #'helm-previous-source)
-    (define-key map (kbd "<right>") #'helm-next-source)
-    (dolist (cmd '(helm-find-files-up-one-level
-                   helm-find-files-down-last-level))
-      (substitute-key-definition cmd nil map))
-    map)
-  "Mapping for file commands in Helm Projectile.")
-
-(defvar helm-projectile-file-actions
-  (helm-projectile-hack-actions
-   helm-find-files-actions
-   ;; Delete these actions
-   'helm-ff-browse-project
-   'helm-insert-file-name-completion-at-point
-   'helm-ff-find-sh-command
-   'helm-ff-cache-add-file
-   ;; Substitute these actions
-   '(helm-ff-switch-to-shell . helm-projectile-switch-to-shell)
-   '(helm-ff-etags-select     . helm-projectile-ff-etags-select-action)
-   '(helm-find-files-eshell-command-on-file
-     . helm-projectile-find-files-eshell-command-on-file-action)
-   ;; Change action descriptions
-   '(helm-find-file-as-root . "Find file as root `C-c r'")
-   ;; New actions
-   '(helm-projectile-dired-files-new-action
-     . "Create Dired buffer from files `C-c f'")
-   '(helm-projectile-dired-files-add-action
-     . "Add files to Dired buffer `C-c a'"))
-  "Action for files.")
-
-(defun helm-projectile--move-selection-p (selection)
-  "Return non-nil if should move Helm selector after SELECTION.
-
-SELECTION should be moved unless it's one of:
-
-- Non-string
-- Existing file
-- Non-remote file that matches `helm-tramp-file-name-regexp'"
-  (not (or (not (stringp selection))
-         (file-exists-p selection)
-         (and (string-match helm-tramp-file-name-regexp selection)
-              (not (file-remote-p selection nil t))))))
-
-(defun helm-projectile--move-to-real ()
-  "Move to first real candidate.
-
-Similar to `helm-ff--move-to-first-real-candidate', but without
-unnecessary complexity."
-  (while (let* ((src (helm-get-current-source))
-                (selection (and (not (helm-empty-source-p))
-                                (helm-get-selection nil nil src))))
-           (and (not (helm-end-of-source-p))
-                (helm-projectile--move-selection-p selection)))
-    (helm-next-line)))
-
-(defun helm-projectile--remove-move-to-real ()
-  "Hook function to remove `helm-projectile--move-to-real'.
-
-Meant to be added to `helm-cleanup-hook', from which it removes
- itself at the end."
-  (remove-hook 'helm-after-update-hook #'helm-projectile--move-to-real)
-  (remove-hook 'helm-cleanup-hook #'helm-projectile--remove-move-to-real))
-
-(defvar helm-source-projectile-files-list-before-init-hook
-  (lambda ()
-    (add-hook 'helm-after-update-hook #'helm-projectile--move-to-real)
-    (add-hook 'helm-cleanup-hook #'helm-projectile--remove-move-to-real)))
-
-(defvar helm-source-projectile-files-list
-  (helm-build-sync-source "Projectile files"
-    :before-init-hook 'helm-source-projectile-files-list-before-init-hook
-    :candidates (lambda ()
-                  (when (projectile-project-p)
-                    (with-helm-current-buffer
-                      (cl-loop with root = (projectile-project-root)
-                               for display in (projectile-current-project-files)
-                               collect (cons display (expand-file-name display root))))))
-    :filtered-candidate-transformer
-    (lambda (files _source)
-      (with-helm-current-buffer
-        (let* ((root (projectile-project-root))
-               (file-at-root (file-relative-name (expand-file-name helm-pattern root))))
-          (if (or (string-empty-p helm-pattern)
-                  (assoc helm-pattern files))
-              files
-            (if (equal helm-pattern file-at-root)
-                (cl-acons (helm-ff-prefix-filename helm-pattern nil t)
-                          (expand-file-name helm-pattern)
-                          files)
-              (cl-pairlis (list (helm-ff-prefix-filename helm-pattern nil t)
-                                (helm-ff-prefix-filename file-at-root nil t))
-                          (list (expand-file-name helm-pattern)
-                                (expand-file-name helm-pattern root))
-                          files))))))
-    :fuzzy-match helm-projectile-fuzzy-match
-    :keymap helm-projectile-find-file-map
-    :help-message 'helm-ff-help-message
-    :mode-line helm-read-file-name-mode-line-string
-    :action helm-projectile-file-actions
-    :persistent-action #'helm-projectile-file-persistent-action
-    :persistent-help "Preview file")
-  "Helm source definition for Projectile files.")
-
-(defvar helm-source-projectile-files-in-all-projects-list
-  (helm-build-sync-source "Projectile files in all Projects"
-    :candidates (lambda ()
-                  (with-helm-current-buffer
-                    (let ((projectile-require-project-root nil))
-                      (projectile-all-project-files))))
-    :keymap helm-projectile-find-file-map
-    :help-message 'helm-ff-help-message
-    :mode-line helm-read-file-name-mode-line-string
-    :action helm-projectile-file-actions
-    :persistent-action #'helm-projectile-file-persistent-action
-    :persistent-help "Preview file")
-  "Helm source definition for all Projectile files in all projects.")
-
-(defvar helm-projectile-dired-file-actions
-  (helm-projectile-hack-actions
-   helm-projectile-file-actions
-   ;; New actions
-   '(helm-projectile-dired-files-delete-action . "Remove entry(s) from Dired buffer `C-c d'")))
-
-(defvar helm-source-projectile-dired-files-list
-  (helm-build-in-buffer-source "Projectile files in current Dired buffer"
-    :data (lambda ()
-            (if (and (file-remote-p (projectile-project-root))
-                     (not helm-projectile-virtual-dired-remote-enable))
-                nil
-              (when (eq major-mode 'dired-mode)
-                (helm-projectile-files-in-current-dired-buffer))))
-    :filter-one-by-one (lambda (file)
-                         (let ((helm-ff-transformer-show-only-basename t))
-                           (helm-ff-filter-candidate-one-by-one file)))
-    :action-transformer 'helm-find-files-action-transformer
-    :keymap (let ((map (copy-keymap helm-projectile-find-file-map)))
-              (helm-projectile-define-key map
-                (kbd "C-c d") 'helm-projectile-dired-files-delete-action)
-              map)
-    :help-message 'helm-ff-help-message
-    :mode-line helm-read-file-name-mode-line-string
-    :action helm-projectile-dired-file-actions)
-  "Helm source definition for Projectile delete files.")
-
-(defun helm-projectile-dired-find-dir (dir)
-  "Jump to a selected directory DIR from `helm-projectile'."
-  (dired (expand-file-name dir (projectile-project-root)))
-  (run-hooks 'projectile-find-dir-hook))
-
-(defun helm-projectile-dired-find-dir-other-window (dir)
-  "Jump to a selected directory DIR from `helm-projectile'."
-  (dired-other-window (expand-file-name dir (projectile-project-root)))
-  (run-hooks 'projectile-find-dir-hook))
-
-(defvar helm-source-projectile-directories-list
-  (helm-build-sync-source "Projectile directories"
-    :candidates (lambda ()
-                  (when (projectile-project-p)
-                    (with-helm-current-buffer
-                      (let ((dirs (if projectile-find-dir-includes-top-level
-                                      (append '("./") (projectile-current-project-dirs))
-                                    (projectile-current-project-dirs))))
-                        (helm-projectile--files-display-real dirs (projectile-project-root))))))
-    :fuzzy-match helm-projectile-fuzzy-match
-    :action-transformer 'helm-find-files-action-transformer
-    :keymap (let ((map (make-sparse-keymap)))
-              (set-keymap-parent map helm-map)
-              (helm-projectile-define-key map
-                (kbd "<left>") #'helm-previous-source
-                (kbd "<right>") #'helm-next-source
-                (kbd "C-c o") #'helm-projectile-dired-find-dir-other-window
-                (kbd "M-e")   #'helm-projectile-switch-to-shell
-                (kbd "C-c f") #'helm-projectile-dired-files-new-action
-                (kbd "C-c a") #'helm-projectile-dired-files-add-action
-                (kbd "C-s")   #'helm-projectile-grep)
-              map)
-    :help-message 'helm-ff-help-message
-    :mode-line helm-read-file-name-mode-line-string
-    :action '(("Open Dired" . helm-projectile-dired-find-dir)
-              ("Open Dired in other window `C-c o'" . helm-projectile-dired-find-dir)
-              ("Switch to Eshell `M-e'" . helm-projectile-switch-to-shell)
-              ("Grep in projects `C-s'" . helm-projectile-grep)
-              ("Create Dired buffer from files `C-c f'" . helm-projectile-dired-files-new-action)
-              ("Add files to Dired buffer `C-c a'" . helm-projectile-dired-files-add-action)))
-  "Helm source for listing project directories.")
-
-(defvar helm-projectile-buffers-list-cache nil)
-
-(defclass helm-source-projectile-buffer (helm-source-sync helm-type-buffer)
-  ((init :initform (lambda ()
-                     ;; Issue #51 Create the list before `helm-buffer' creation.
-                     (setq helm-projectile-buffers-list-cache
-                           (ignore-errors (remove (buffer-name) (projectile-project-buffer-names))))
-                     (let ((result (cl-loop for b in helm-projectile-buffers-list-cache
-                                            maximize (length b) into len-buf
-                                            maximize (length (with-current-buffer b
-                                                               (symbol-name major-mode)))
-                                            into len-mode
-                                            finally return (cons len-buf len-mode))))
-                       (unless helm-buffer-max-length
-                         (setq helm-buffer-max-length (car result)))
-                       (unless helm-buffer-max-len-mode
-                         ;; If a new buffer is longer that this value
-                         ;; this value will be updated
-                         (setq helm-buffer-max-len-mode (cdr result))))))
-   (candidates :initform 'helm-projectile-buffers-list-cache)
-   (matchplugin :initform nil)
-   (match :initform 'helm-buffers-match-function)
-   (persistent-action :initform 'helm-buffers-list-persistent-action)
-   (keymap :initform 'helm-buffer-map)
-   (volatile :initform t)
-   (persistent-help
-    :initform
-    "Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))
-
-(defvar helm-source-projectile-buffers-list (helm-make-source "Project buffers" 'helm-source-projectile-buffer))
-
-(defvar helm-source-projectile-recentf-list
-  (helm-build-sync-source "Projectile recent files"
-    :candidates (lambda ()
-                  (when (projectile-project-p)
-                   (with-helm-current-buffer
-                     (helm-projectile--files-display-real (projectile-recentf-files)
-                                                          (projectile-project-root)))))
-    :fuzzy-match helm-projectile-fuzzy-match
-    :keymap helm-projectile-find-file-map
-    :help-message 'helm-ff-help-message
-    :mode-line helm-read-file-name-mode-line-string
-    :action helm-projectile-file-actions
-    :persistent-action #'helm-projectile-file-persistent-action
-    :persistent-help "Preview file")
-  "Helm source definition for recent files in current project.")
-
-(defvar helm-source-projectile-files-and-dired-list
-  '(helm-source-projectile-dired-files-list
-    helm-source-projectile-files-list))
-
-(defvar helm-source-projectile-directories-and-dired-list
-  '(helm-source-projectile-dired-files-list
-    helm-source-projectile-directories-list))
-
-(defcustom helm-projectile-git-grep-command
-  "git --no-pager grep --no-color -n%c -e %p -- %f"
-  "Command to execute when performing `helm-grep' inside a projectile git project.
-See documentation of `helm-grep-default-command' for the format."
-  :type 'string
-  :group 'helm-projectile
-  )
-
-(defcustom helm-projectile-grep-command
-  "grep -a -r %e -n%cH -e %p %f ."
-  "Command to execute when performing `helm-grep' outside a projectile git project.
-See documentation of `helm-grep-default-command' for the format."
-  :type 'string
-  :group 'helm-projectile
-  )
-
-
-(defcustom helm-projectile-sources-list
-  '(helm-source-projectile-buffers-list
-    helm-source-projectile-files-list
-    helm-source-projectile-projects)
-  "Default sources for `helm-projectile'."
-  :type '(repeat symbol)
-  :group 'helm-projectile)
-
-(defmacro helm-projectile-command (command source prompt &optional not-require-root truncate-lines-var)
-  "Template for generic `helm-projectile' commands.
-COMMAND is a command name to be appended with \"helm-projectile\" prefix.
-SOURCE is a Helm source that should be Projectile specific.
-PROMPT is a string for displaying as a prompt.
-NOT-REQUIRE-ROOT specifies the command doesn't need to be used in a
-project root.
-TRUNCATE-LINES-VAR is the symbol used dictate truncation of lines.
-Defaults is `helm-projectile-truncate-lines'."
-  (unless truncate-lines-var (setq truncate-lines-var 'helm-projectile-truncate-lines))
-  `(defun ,(intern (concat "helm-projectile-" command)) (&optional arg)
-     "Use projectile with Helm for finding files in project
-
-With a prefix ARG invalidates the cache first."
-     (interactive "P")
-     (if (projectile-project-p)
-         (projectile-maybe-invalidate-cache arg)
-       (unless ,not-require-root
-         (error "You're not in a project")))
-     (let ((helm-ff-transformer-show-only-basename nil)
-           ;; for consistency, we should just let Projectile take care of ignored files
-           (helm-boring-file-regexp-list nil))
-       (helm :sources ,source
-             :buffer (concat "*helm projectile: " (projectile-project-name) "*")
-             :truncate-lines ,truncate-lines-var
-             :prompt (projectile-prepend-project-name ,prompt)))))
-
-(helm-projectile-command "switch-project" 'helm-source-projectile-projects "Switch to project: " t)
-(helm-projectile-command "find-file" helm-source-projectile-files-and-dired-list "Find file: ")
-(helm-projectile-command "find-file-in-known-projects" 'helm-source-projectile-files-in-all-projects-list "Find file in projects: " t)
-(helm-projectile-command "find-dir" helm-source-projectile-directories-and-dired-list "Find dir: ")
-(helm-projectile-command "recentf" 'helm-source-projectile-recentf-list "Recently visited file: ")
-(helm-projectile-command "switch-to-buffer" 'helm-source-projectile-buffers-list "Switch to buffer: " nil helm-buffers-truncate-lines)
-(helm-projectile-command "browse-dirty-projects" 'helm-source-projectile-dirty-projects "Select a project: " t)
-
-(defun helm-projectile--files-display-real (files root)
-  "Create (DISPLAY . REAL) pairs with FILES and ROOT.
-
-  DISPLAY is the short file name.  REAL is the full path."
-  (cl-loop for display in files
-           collect (cons display (expand-file-name display root))))
-
-;;;###autoload
-(defun helm-projectile-find-file-dwim ()
-  "Find file at point based on context."
-  (interactive)
-  (let* ((project-root (projectile-project-root))
-         (project-files (projectile-current-project-files))
-         (files (projectile-select-files project-files)))
-    (if (= (length files) 1)
-        (find-file (expand-file-name (car files) (projectile-project-root)))
-      (helm :sources (helm-build-sync-source "Projectile files"
-                       :candidates (if (> (length files) 1)
-                                       (helm-projectile--files-display-real files project-root)
-                                     (helm-projectile--files-display-real project-files project-root))
-                       :fuzzy-match helm-projectile-fuzzy-match
-                       :action-transformer 'helm-find-files-action-transformer
-                       :keymap helm-projectile-find-file-map
-                       :help-message helm-ff-help-message
-                       :mode-line helm-read-file-name-mode-line-string
-                       :action helm-projectile-file-actions
-                       :persistent-action #'helm-projectile-file-persistent-action
-                       :persistent-help "Preview file")
-            :buffer "*helm projectile*"
-            :truncate-lines helm-projectile-truncate-lines
-            :prompt (projectile-prepend-project-name "Find file: ")))))
-
-;;;###autoload
-(defun helm-projectile-find-other-file (&optional flex-matching)
-  "Switch between files with the same name but different extensions using Helm.
-With FLEX-MATCHING, match any file that contains the base name of
-current file.  Other file extensions can be customized with the
-variable `projectile-other-file-alist'."
-  (interactive "P")
-  (let* ((project-root (projectile-project-root))
-         (other-files (projectile-get-other-files (buffer-file-name)
-                                                  flex-matching)))
-    (if other-files
-        (if (= (length other-files) 1)
-            (find-file (expand-file-name (car other-files) project-root))
-          (progn
-            (let* ((helm-ff-transformer-show-only-basename nil))
-              (helm :sources (helm-build-sync-source "Projectile other files"
-                               :candidates (helm-projectile--files-display-real other-files project-root)
-                               :keymap helm-projectile-find-file-map
-                               :help-message helm-ff-help-message
-                               :mode-line helm-read-file-name-mode-line-string
-                               :action helm-projectile-file-actions
-                               :persistent-action #'helm-projectile-file-persistent-action
-                               :persistent-help "Preview file")
-                    :buffer "*helm projectile*"
-                    :truncate-lines helm-projectile-truncate-lines
-                    :prompt (projectile-prepend-project-name "Find other file: ")))))
-      (error "No other file found"))))
-
-(defcustom helm-projectile-ignore-strategy 'projectile
-  "Allow projectile to compute ignored files and directories.
-
-When set to `projectile', the package will compute ignores and
-explicitely add additionally command line arguments to the search
-tool.  Note that this might override search tool specific
-behaviors (for instance ag would not use VCS ignore files).
-
-When set to `search-tool', the above does not happen."
-  :group 'helm-projectile
-  :type '(choice (const :tag "Allow projectile to compute ignores" projectile)
-                 (const :tag "Let the search tool compute ignores" search-tool)))
-
-(defun helm-projectile--projectile-ignore-strategy ()
-  "True if the ignore strategy is `projectile'."
-  (eq 'projectile helm-projectile-ignore-strategy))
-
-(defun helm-projectile--ignored-files ()
-  "Compute ignored files."
-  (cl-union (projectile-ignored-files-rel) grep-find-ignored-files))
-
-(defun helm-projectile--ignored-directories ()
-  "Compute ignored directories."
-  (cl-union (projectile-ignored-directories-rel) grep-find-ignored-directories))
-
-(defcustom helm-projectile-grep-or-ack-actions
-  '("Find file" helm-grep-action
-    "Find file other frame" helm-grep-other-frame
-    (lambda () (and (locate-library "elscreen")
-               "Find file in Elscreen"))
-    helm-grep-jump-elscreen
-    "Save results in grep buffer" helm-grep-save-results
-    "Find file other window" helm-grep-other-window)
-  "Available actions for `helm-projectile-grep-or-ack'.
-The contents of this list are passed as the arguments to `helm-make-actions'."
-  :type 'symbol
-  :group 'helm-projectile)
-
-(defcustom helm-projectile-set-input-automatically t
-  "If non-nil, attempt to set search input automatically.
-Automatic input selection uses the region (if there is an active
-region), otherwise it uses the current symbol at point (if there
-is one).  Applies to `helm-projectile-grep' and
-`helm-projectile-ack' only.  If the `helm-ag' package is
-installed, then automatic input behavior for `helm-projectile-ag'
-can be customized using `helm-ag-insert-at-point'."
-  :group 'helm-projectile
-  :type 'boolean)
-
-(defun helm-projectile-grep-or-ack (&optional dir use-ack-p ack-ignored-pattern ack-executable)
-  "Perform helm-grep at project root.
-DIR directory where to search
-USE-ACK-P indicates whether to use ack or not.
-ACK-IGNORED-PATTERN is a file regex to exclude from searching.
-ACK-EXECUTABLE is the actual ack binary name.
-It is usually \"ack\" or \"ack-grep\".
-If it is nil, or ack/ack-grep not found then use default grep command."
-  (when (helm-projectile--projectile-ignore-strategy)
-    (setq helm-grep-ignored-files (helm-projectile--ignored-files)
-          helm-grep-ignored-directories (mapcar 'directory-file-name (helm-projectile--ignored-directories))))
-
-  (let* ((default-directory (or dir (projectile-project-root)))
-         (helm-ff-default-directory default-directory)
-         (helm-grep-in-recurse t)
-         (helm-grep-default-command (if use-ack-p
-                                        (concat ack-executable " -H --no-group --no-color "
-                                                (when ack-ignored-pattern (concat ack-ignored-pattern " "))
-                                                "%p %f")
-                                      (if (and projectile-use-git-grep (eq (projectile-project-vcs) 'git))
-                                          helm-projectile-git-grep-command
-                                        helm-projectile-grep-command)))
-         (helm-grep-default-recurse-command helm-grep-default-command))
-
-    (setq helm-source-grep
-          (helm-build-async-source
-              (capitalize (helm-grep-command t))
-            :header-name (lambda (_name)
-                           (let ((name (if use-ack-p
-                                           "Helm Projectile Ack"
-                                         "Helm Projectile Grep")))
-                             (concat name " " "(C-c ? Help)")))
-            :candidates-process 'helm-grep-collect-candidates
-            :filter-one-by-one 'helm-grep-filter-one-by-one
-            :candidate-number-limit 9999
-            :nohighlight t
-            ;; We need to specify keymap here and as :keymap arg [1]
-            ;; to make it available in further resuming.
-            :keymap helm-grep-map
-            :history 'helm-grep-history
-            :action (apply #'helm-make-actions helm-projectile-grep-or-ack-actions)
-            :persistent-action 'helm-grep-persistent-action
-            :persistent-help "Jump to line (`C-u' Record in mark ring)"
-            :requires-pattern 2))
-    (helm
-     :sources 'helm-source-grep
-     :input (when helm-projectile-set-input-automatically
-              (if (region-active-p)
-                  (buffer-substring-no-properties (region-beginning) (region-end))
-                (thing-at-point 'symbol)))
-     :buffer (format "*helm %s*" (if use-ack-p
-                                     "ack"
-                                   "grep"))
-     :default-directory default-directory
-     :keymap helm-grep-map
-     :history 'helm-grep-history
-     :truncate-lines helm-grep-truncate-lines)))
-
-;;;###autoload
-(defun helm-projectile-on ()
-  "Turn on `helm-projectile' key bindings."
-  (interactive)
-  (message "Turn on helm-projectile key bindings")
-  (helm-projectile-toggle 1))
-
-;;;###autoload
-(defun helm-projectile-off ()
-  "Turn off `helm-projectile' key bindings."
-  (interactive)
-  (message "Turn off helm-projectile key bindings")
-  (helm-projectile-toggle -1))
-
-;;;###autoload
-(defun helm-projectile-grep (&optional dir)
-  "Helm version of `projectile-grep'.
-DIR is the project root, if not set then current directory is used"
-  (interactive)
-  (let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
-    (funcall 'run-with-timer 0.01 nil
-             #'helm-projectile-grep-or-ack project-root nil)))
-
-;;;###autoload
-(defun helm-projectile-ack (&optional dir)
-  "Helm version of projectile-ack.
-DIR directory where to search"
-  (interactive)
-  (let* ((project-root (or dir (projectile-project-root) (error "You're not in a project")))
-         (ignored (when (helm-projectile--projectile-ignore-strategy)
-                    (mapconcat
-                     'identity
-                     (cl-union (mapcar (lambda (path)
-                                         (concat "--ignore-dir=" (file-name-nondirectory (directory-file-name path))))
-                                       (helm-projectile--ignored-directories))
-                               (mapcar (lambda (path)
-                                         (concat "--ignore-file=match:" (shell-quote-argument path)))
-                                       (append (helm-projectile--ignored-files)
-                                               (projectile-patterns-to-ignore))))
-                     " ")))
-         (helm-ack-grep-executable (cond
-                                    ((executable-find "ack") "ack")
-                                    ((executable-find "ack-grep") "ack-grep")
-                                    (t (error "ack or ack-grep is not available")))))
-    (funcall 'run-with-timer 0.01 nil
-             #'helm-projectile-grep-or-ack project-root t ignored helm-ack-grep-executable)))
-
-;;;###autoload
-
-(defun helm-projectile-ag (&optional options)
-  "Helm version of `projectile-ag'.
-OPTIONS explicit command line arguments to ag"
-  (interactive (if current-prefix-arg (list (helm-read-string "option: " "" 'helm-ag--extra-options-history))))
-  (if (require 'helm-ag nil t)
-      (if (projectile-project-p)
-          (progn
-            (when (helm-projectile--projectile-ignore-strategy)
-              (setq grep-find-ignored-files (helm-projectile--ignored-files)
-                    grep-find-ignored-directories (helm-projectile--ignored-directories)))
-            (let* ((ignored (when (helm-projectile--projectile-ignore-strategy)
-                              (mapconcat (lambda (i)
-                                           (concat "--ignore " i))
-                                         (append grep-find-ignored-files
-                                                 grep-find-ignored-directories
-                                                 (cadr (projectile-parse-dirconfig-file)))
-                                         " ")))
-                   (helm-ag-base-command (concat helm-ag-base-command
-                                                 (when ignored (concat " " ignored))
-                                                 " " options))
-                   (current-prefix-arg nil))
-              (helm-do-ag (projectile-project-root) (car (projectile-parse-dirconfig-file)))))
-        (error "You're not in a project"))
-    (when (yes-or-no-p "`helm-ag' is not installed. Install? ")
-      (condition-case nil
-          (progn
-            (package-install 'helm-ag)
-            (helm-projectile-ag options))
-        (error (error "`helm-ag' is not available.  Is MELPA in your `package-archives'?"))))))
-
-;; Declare/define these to satisfy the byte compiler
-(defvar helm-rg-prepend-file-name-line-at-top-of-matches)
-(defvar helm-rg-include-file-on-every-match-line)
-(declare-function helm-rg "ext:helm-rg")
-(declare-function helm-rg--get-thing-at-pt "ext:helm-rg")
-
-(defun helm-projectile-rg--region-selection ()
-  (when helm-projectile-set-input-automatically
-    (if (region-active-p)
-        (buffer-substring-no-properties (region-beginning) (region-end))
-      (helm-rg--get-thing-at-pt))))
-
-(defun glob-quote (string)
-  "Quote the special glob characters: *, ?, [, and ].
-STRING the string in which to escape special characters."
-  (replace-regexp-in-string "[]*?[]" "\\\\\\&" string))
-
-;;;###autoload
-(defun helm-projectile-rg ()
-  "Projectile version of `helm-rg'."
-  (interactive)
-  (if (require 'helm-rg nil t)
-      (if (projectile-project-p)
-          (let* ((helm-rg-prepend-file-name-line-at-top-of-matches nil)
-                 (helm-rg-include-file-on-every-match-line t)
-                 (default-directory (projectile-project-root)))
-            (when (helm-projectile--projectile-ignore-strategy)
-              (setq helm-rg--extra-args
-                    (mapconcat
-                     'identity
-                     (cl-union (mapcan (lambda (path)
-                                         (list "--glob" (concat "!" (glob-quote path))))
-                                       (helm-projectile--ignored-files))
-                               (mapcan (lambda (path)
-                                         (list "--glob" (concat "!" (glob-quote path) "/**")))
-                                       (mapcar 'directory-file-name (helm-projectile--ignored-directories))))
-                     " ")))
-            (helm-rg (helm-projectile-rg--region-selection)
-                     nil))
-        (error "You're not in a project"))
-    (when (yes-or-no-p "`helm-rg' is not installed. Install? ")
-      (condition-case nil
-          (progn
-            (package-install 'helm-rg)
-            (helm-projectile-rg))
-        (error "`helm-rg' is not available.  Is MELPA in your `package-archives'?")))))
-
-(defun helm-projectile-commander-bindings ()
-  (def-projectile-commander-method ?a
-    "Run ack on project."
-    (call-interactively 'helm-projectile-ack))
-
-  (def-projectile-commander-method ?A
-    "Find ag on project."
-    (call-interactively 'helm-projectile-ag))
-
-  (def-projectile-commander-method ?f
-    "Find file in project."
-    (helm-projectile-find-file))
-
-  (def-projectile-commander-method ?b
-    "Switch to project buffer."
-    (helm-projectile-switch-to-buffer))
-
-  (def-projectile-commander-method ?d
-    "Find directory in project."
-    (helm-projectile-find-dir))
-
-  (def-projectile-commander-method ?g
-    "Run grep on project."
-    (helm-projectile-grep))
-
-  (def-projectile-commander-method ?s
-    "Switch project."
-    (helm-projectile-switch-project))
-
-  (def-projectile-commander-method ?e
-    "Find recently visited file in project."
-    (helm-projectile-recentf))
-
-  (def-projectile-commander-method ?V
-    "Find dirty projects."
-    (helm-projectile-browse-dirty-projects)))
-
-;;;###autoload
-(defun helm-projectile-toggle (toggle)
-  "Toggle Helm version of Projectile commands."
-  (if (> toggle 0)
-      (progn
-        (when (eq projectile-switch-project-action #'projectile-find-file)
-          (setq projectile-switch-project-action #'helm-projectile-find-file))
-        (define-key projectile-mode-map [remap projectile-find-other-file] #'helm-projectile-find-other-file)
-        (define-key projectile-mode-map [remap projectile-find-file] #'helm-projectile-find-file)
-        (define-key projectile-mode-map [remap projectile-find-file-in-known-projects] #'helm-projectile-find-file-in-known-projects)
-        (define-key projectile-mode-map [remap projectile-find-file-dwim] #'helm-projectile-find-file-dwim)
-        (define-key projectile-mode-map [remap projectile-find-dir] #'helm-projectile-find-dir)
-        (define-key projectile-mode-map [remap projectile-switch-project] #'helm-projectile-switch-project)
-        (define-key projectile-mode-map [remap projectile-recentf] #'helm-projectile-recentf)
-        (define-key projectile-mode-map [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer)
-        (define-key projectile-mode-map [remap projectile-grep] #'helm-projectile-grep)
-        (define-key projectile-mode-map [remap projectile-ack] #'helm-projectile-ack)
-        (define-key projectile-mode-map [remap projectile-ag] #'helm-projectile-ag)
-        (define-key projectile-mode-map [remap projectile-ripgrep] #'helm-projectile-rg)
-        (define-key projectile-mode-map [remap projectile-browse-dirty-projects] #'helm-projectile-browse-dirty-projects)
-        (helm-projectile-commander-bindings))
-    (progn
-      (when (eq projectile-switch-project-action #'helm-projectile-find-file)
-        (setq projectile-switch-project-action #'projectile-find-file))
-      (define-key projectile-mode-map [remap projectile-find-other-file] nil)
-      (define-key projectile-mode-map [remap projectile-find-file] nil)
-      (define-key projectile-mode-map [remap projectile-find-file-in-known-projects] nil)
-      (define-key projectile-mode-map [remap projectile-find-file-dwim] nil)
-      (define-key projectile-mode-map [remap projectile-find-dir] nil)
-      (define-key projectile-mode-map [remap projectile-switch-project] nil)
-      (define-key projectile-mode-map [remap projectile-recentf] nil)
-      (define-key projectile-mode-map [remap projectile-switch-to-buffer] nil)
-      (define-key projectile-mode-map [remap projectile-grep] nil)
-      (define-key projectile-mode-map [remap projectile-ag] nil)
-      (define-key projectile-mode-map [remap projectile-ripgrep] nil)
-      (define-key projectile-mode-map [remap projectile-browse-dirty-projects] nil)
-      (projectile-commander-bindings))))
-
-;;;###autoload
-(defun helm-projectile (&optional arg)
-  "Use projectile with Helm instead of ido.
-
-With a prefix ARG invalidates the cache first.
-If invoked outside of a project, displays a list of known projects to jump."
-  (interactive "P")
-  (if (not (projectile-project-p))
-      (helm-projectile-switch-project arg)
-    (projectile-maybe-invalidate-cache arg)
-    (let ((helm-ff-transformer-show-only-basename nil))
-      (helm :sources helm-projectile-sources-list
-            :buffer "*helm projectile*"
-            :truncate-lines helm-projectile-truncate-lines
-            :prompt (projectile-prepend-project-name (if (projectile-project-p)
-                                                         "pattern: "
-                                                       "Switch to project: "))))))
-
-;;;###autoload
-(eval-after-load 'projectile
-  '(progn
-     (define-key projectile-command-map (kbd "h") #'helm-projectile)))
-
-(provide 'helm-projectile)
-
-;;; helm-projectile.el ends here
diff --git a/elpa/helm-projectile-20250902.830/helm-projectile-autoloads.el b/elpa/helm-projectile-20250902.830/helm-projectile-autoloads.el
new file mode 100644 (file)
index 0000000..b520061
--- /dev/null
@@ -0,0 +1,123 @@
+;;; helm-projectile-autoloads.el --- automatically extracted autoloads (do not edit)   -*- lexical-binding: t -*-
+;; Generated by the `loaddefs-generate' function.
+
+;; This file is part of GNU Emacs.
+
+;;; Code:
+
+(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
+
+
+\f
+;;; Generated autoloads from helm-projectile.el
+
+(defvar helm-projectile-fuzzy-match t "\
+Enable fuzzy matching for Helm Projectile commands.
+This needs to be set before loading helm-projectile.el.")
+(custom-autoload 'helm-projectile-fuzzy-match "helm-projectile" t)
+(autoload 'helm-projectile-switch-project "helm-projectile" nil t)
+(autoload 'helm-projectile-switch-project-other-window "helm-projectile" nil t)
+(autoload 'helm-projectile-switch-project-other-frame "helm-projectile" nil t)
+(autoload 'helm-projectile-find-file "helm-projectile" nil t)
+(autoload 'helm-projectile-find-file-other-window "helm-projectile" nil t)
+(autoload 'helm-projectile-find-file-other-frame "helm-projectile" nil t)
+(autoload 'helm-projectile-find-file-in-known-projects "helm-projectile" nil t)
+(autoload 'helm-projectile-find-dir "helm-projectile" nil t)
+(autoload 'helm-projectile-find-dir-other-window "helm-projectile" nil t)
+(autoload 'helm-projectile-find-dir-other-frame "helm-projectile" nil t)
+(autoload 'helm-projectile-recentf "helm-projectile" nil t)
+(autoload 'helm-projectile-switch-to-buffer "helm-projectile" nil t)
+(autoload 'helm-projectile-switch-to-buffer-other-window "helm-projectile" nil t)
+(autoload 'helm-projectile-switch-to-buffer-other-frame "helm-projectile" nil t)
+(autoload 'helm-projectile-browse-dirty-projects "helm-projectile" nil t)
+(autoload 'helm-projectile-find-file-dwim "helm-projectile" "\
+Find file at point based on context." t)
+(autoload 'helm-projectile-find-file-dwim-other-window "helm-projectile" "\
+Find file at point based on context." t)
+(autoload 'helm-projectile-find-file-dwim-other-frame "helm-projectile" "\
+Find file at point based on context." t)
+(autoload 'helm-projectile-find-other-file "helm-projectile" "\
+Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'.
+
+(fn &optional FLEX-MATCHING)" t)
+(autoload 'helm-projectile-find-other-file-other-window "helm-projectile" "\
+Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'.
+
+(fn &optional FLEX-MATCHING)" t)
+(autoload 'helm-projectile-find-other-file-other-frame "helm-projectile" "\
+Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'.
+
+(fn &optional FLEX-MATCHING)" t)
+(autoload 'helm-projectile-on "helm-projectile" "\
+Turn on `helm-projectile' key bindings." t)
+(autoload 'helm-projectile-off "helm-projectile" "\
+Turn off `helm-projectile' key bindings." t)
+(autoload 'helm-projectile-grep "helm-projectile" "\
+Helm version of `projectile-grep'.
+DIR is the project root, if not set then current project root is used.
+FILES is a list of file patterns to search in.  When called with a
+prefix argument then ask for FILES.
+
+(fn &optional DIR FILES)" t)
+(autoload 'helm-projectile-ack "helm-projectile" "\
+Helm version of `projectile-ack'.
+DIR directory where to search, if not set then current project root is
+used.  TYPES is a list of types to include in search.  When called with
+a prefix argument, then ask for TYPES.
+
+(fn &optional DIR TYPES)" t)
+(autoload 'helm-projectile-ag "helm-projectile" "\
+Helm version of `projectile-ag'.
+When called with a single or a triple prefix argument, ask for OPTIONS.
+When called with a double or a triple prefix argument, ask for
+TYPES (see `helm-grep-ag').'
+
+This command uses `helm-grep-ag' to perform the search, so the actual
+searcher used is determined by the value of `helm-grep-ag-command'.
+
+(fn &optional OPTIONS)" t)
+(autoload 'helm-projectile-rg "helm-projectile" "\
+Projectile version of `helm-rg'.
+When package `helm-rg' is not installed and `helm-grep-ag-command' is
+pointing to ripgrep (rg) then use `helm-projectile-ag'.  Otherwise if
+`helm-projectile-ask-to-install-helm-rg' is non nil then ask to install
+package `helm-rg'." t)
+(autoload 'helm-projectile-toggle "helm-projectile" "\
+Toggle Helm version of Projectile commands.
+When TOGGLE is greater than 0 turn Helm version of Projectile commands
+on.  When TOGGLE is is less or equal to 0 turn Helm version of commands
+off.
+
+(fn TOGGLE)")
+(autoload 'helm-projectile "helm-projectile" "\
+Use projectile with Helm instead of ido.
+
+With a prefix ARG invalidates the cache first.
+If invoked outside of a project, displays a list of known projects to jump.
+
+(fn &optional ARG)" t)
+(eval-after-load 'projectile '(progn (define-key projectile-command-map (kbd "h") #'helm-projectile)))
+(register-definition-prefixes "helm-projectile" '("helm-"))
+\f
+;;; End of scraped data
+
+(provide 'helm-projectile-autoloads)
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; no-native-compile: t
+;; coding: utf-8-emacs-unix
+;; End:
+
+;;; helm-projectile-autoloads.el ends here
diff --git a/elpa/helm-projectile-20250902.830/helm-projectile-pkg.el b/elpa/helm-projectile-20250902.830/helm-projectile-pkg.el
new file mode 100644 (file)
index 0000000..118bf5c
--- /dev/null
@@ -0,0 +1,10 @@
+;; -*- no-byte-compile: t; lexical-binding: nil -*-
+(define-package "helm-projectile" "20250902.830"
+  "Helm integration for Projectile."
+  '((emacs      "26.1")
+    (helm       "3.0")
+    (projectile "2.9"))
+  :url "https://github.com/bbatsov/helm-projectile"
+  :commit "0ffb6b5f09c1d65d721c1111ebfa6cec0ba63234"
+  :revdesc "0ffb6b5f09c1"
+  :keywords '("project" "convenience"))
diff --git a/elpa/helm-projectile-20250902.830/helm-projectile.el b/elpa/helm-projectile-20250902.830/helm-projectile.el
new file mode 100644 (file)
index 0000000..bc73ca4
--- /dev/null
@@ -0,0 +1,1819 @@
+;;; helm-projectile.el --- Helm integration for Projectile         -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2011-2025 Bozhidar Batsov
+
+;; Author: Bozhidar Batsov
+;; URL: https://github.com/bbatsov/helm-projectile
+;; Maintainer: PrzemysÅ‚aw Kryger
+;; Created: 2011-31-07
+;; Keywords: project, convenience
+;; Package-Version: 20250902.830
+;; Package-Revision: 0ffb6b5f09c1
+;; Package-Requires: ((emacs "26.1") (helm "3.0") (projectile "2.9"))
+
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; This library provides easy project management and navigation.  The
+;; concept of a project is pretty basic - just a folder containing
+;; special file.  Currently git, mercurial and bazaar repos are
+;; considered projects by default.  If you want to mark a folder
+;; manually as a project just create an empty .projectile file in
+;; it.  See the README for more details.
+;;
+;;; Code:
+
+;; built-in libraries
+(require 'subr-x)
+(require 'cl-lib)
+(require 'grep) ;; TODO: Probably we should defer this require
+
+(require 'helm-core)
+(require 'helm-global-bindings)
+(require 'helm-types)
+(require 'helm-locate)
+(require 'helm-buffers)
+(require 'helm-files)
+(require 'helm-grep)
+
+(require 'projectile)
+
+(declare-function eshell "eshell")
+(declare-function dired-get-filename "dired")
+
+(defvar grep-find-ignored-directories)
+(defvar grep-find-ignored-files)
+
+(defgroup helm-projectile nil
+  "Helm support for projectile."
+  :prefix "helm-projectile-"
+  :group 'projectile
+  :group 'helm
+  :link `(url-link :tag "GitHub" "https://github.com/bbatsov/helm-projectile"))
+
+(defvar helm-projectile-current-project-root)
+
+(defcustom helm-projectile-truncate-lines nil
+  "Truncate lines in helm projectile commands when non--nil.
+
+Some `helm-projectile' commands have similar behavior with existing
+Helms.  In these cases their respective custom var for truncation
+of lines will be honored.  E.g. `helm-buffers-truncate-lines'
+dictates the truncation in `helm-projectile-switch-to-buffer'."
+  :group 'helm-projectile
+  :type 'boolean)
+
+(defcustom helm-projectile-remove-current-buffer nil
+  "Non-nil if current buffer should be removed from buffer sources.
+For example from `helm-projectile' (when invoked from a project) as well
+as from `helm-projectile-switch-to-buffer',
+`helm-projectile-switch-to-buffer-other-window', and
+`helm-projectile-switch-to-buffer-other-frame'."
+  :type 'boolean
+  :group 'helm-projectile)
+
+;;;###autoload
+(defcustom helm-projectile-fuzzy-match t
+  "Enable fuzzy matching for Helm Projectile commands.
+This needs to be set before loading helm-projectile.el."
+  :group 'helm-projectile
+  :type 'boolean)
+
+(defmacro helm-projectile-define-key (keymap &rest bindings)
+  "In KEYMAP, define BINDINGS.
+BINDINS is a list in a form of (KEY1 DEF1 KEY2 DEF2 ...)."
+  (declare (indent defun))
+  (when (or (< (length bindings) 2)
+            (= 1 (% 2 (length bindings))))
+    (error "Expected BINDINGS to be KEY1 DEF1 KEY2 DEF2 ... "))
+  (let ((ret '(progn)))
+    (while-let ((key (car bindings))
+                (def (cadr bindings)))
+      (push
+       `(define-key ,keymap ,key
+                    (lambda ()
+                      (interactive)
+                      (helm-exit-and-execute-action ,def)))
+       ret)
+      (setq bindings (cddr bindings)))
+    (reverse ret)))
+
+(defun helm-projectile-hack-actions (actions &rest prescription)
+  "Given a Helm action list and a prescription, return a hacked Helm action list.
+Optionally applies the PRESCRIPTION beforehand.
+
+The Helm action list ACTIONS is of the form:
+
+\(\(DESCRIPTION1 . FUNCTION1\)
+ \(DESCRIPTION2 . FUNCTION2\)
+ ...
+ \(DESCRIPTIONn . FUNCTIONn\)\)
+
+PRESCRIPTION is in the form:
+
+\(INSTRUCTION1 INSTRUCTION2 ... INSTRUCTIONn\)
+
+If an INSTRUCTION is a symbol, the action with function name
+INSTRUCTION is deleted.
+
+If an INSTRUCTION is of the form \(FUNCTION1 . FUNCTION2\), the
+action with function name FUNCTION1 will change it's function to
+FUNCTION2.
+
+If an INSTRUCTION is of the form \(FUNCTION . DESCRIPTION\), and
+if an action with function name FUNCTION exists in the original
+Helm action list, the action in the Helm action list, with
+function name FUNCTION will change it's description to
+DESCRIPTION.  Otherwise, (FUNCTION . DESCRIPTION) will be added to
+the action list.
+
+If an INSTRUCTION is of the form \(FUNCTION . :make-first\), and if the
+an action with function name FUNCTION exists in the th Helm action list
+concatenated with new actions from PRESCRIPTION, the action will become
+the first (default) action.
+
+Please check out how `helm-projectile-file-actions' is defined
+for an example of how this function is being used."
+  (let* ((to-delete (cl-remove-if (lambda (entry) (listp entry)) prescription))
+         (actions (cl-delete-if (lambda (action) (memq (cdr action) to-delete))
+                                (copy-alist actions)))
+         new)
+    (cl-dolist (action actions)
+      (when (setq new (cdr (assq (cdr action) prescription)))
+        (cond
+         ((stringp new) (setcar action new))
+         ((functionp new) (setcdr action new)))))
+    ;; Add new actions from PRESCRIPTION
+    (setq new nil)
+    (cl-dolist (instruction prescription)
+      (when (and (listp instruction)
+                 (null (rassq (car instruction) actions))
+                 (symbolp (car instruction)) (stringp (cdr instruction)))
+        (push (cons (cdr instruction) (car instruction)) new)))
+    ;; Push to front the desired action
+    (let ((actions (append actions (nreverse new))))
+      (if-let* ((first-function (car (rassq :make-first prescription)))
+                (first-action-p (lambda (action)
+                                  (eq (cdr action)
+                                      first-function)))
+                (first-action (cl-find-if first-action-p actions)))
+          (cons first-action
+                (cl-remove-if first-action-p actions))
+        actions))))
+
+(defun helm-projectile-vc (dir)
+  "A Helm action for jumping to project root using `vc-dir' or Magit.
+DIR is a directory to be switched"
+  (let ((projectile-require-project-root nil))
+    (projectile-vc dir)))
+
+(defun helm-projectile-compile-project (dir)
+  "A Helm action for compile a project.
+DIR is the project root."
+  (let ((helm--reading-passwd-or-string t)
+        (default-directory dir))
+    (projectile-compile-project helm-current-prefix-arg)))
+
+(defun helm-projectile-test-project (dir)
+  "A Helm action for test a project.
+DIR is the project root."
+  (let ((helm--reading-passwd-or-string t)
+        (default-directory dir))
+    (projectile-test-project helm-current-prefix-arg)))
+
+(defun helm-projectile-run-project (dir)
+  "A Helm action for run a project.
+DIR is the project root."
+  (let ((helm--reading-passwd-or-string t)
+        (default-directory dir))
+    (projectile-run-project helm-current-prefix-arg)))
+
+(defun helm-projectile-remove-known-project (_ignore)
+  "Remove selected projects from projectile project list.
+_IGNORE means the argument does not matter.
+It is there because Helm requires it."
+  (let* ((projects (helm-marked-candidates :with-wildcard t))
+         (len (length projects)))
+    (with-helm-display-marked-candidates
+      helm-marked-buffer-name
+      projects
+      (if (not (y-or-n-p (format "Remove *%s projects(s)? " len)))
+          (message "(No removal performed)")
+        (progn
+          (mapc (lambda (p)
+                  (setq projectile-known-projects (delete p projectile-known-projects)))
+                projects)
+          (projectile-save-known-projects))
+        (message "%s projects(s) removed" len)))))
+
+(defun helm-projectile-switch-project-by-name (project)
+  "Switch to PROJECT and execute `projectile-switch-project-action' in it.
+When `projectile-switch-project-action' is `projectile-find-file' a
+`helm-projectile-find-file' will be used instead."
+  (let ((projectile-completion-system 'helm)
+        (projectile-switch-project-action
+         (if (eq projectile-switch-project-action 'projectile-find-file)
+             #'helm-projectile-find-file
+           projectile-switch-project-action)))
+    (projectile-switch-project-by-name project)))
+
+(defun helm-projectile-switch-project-by-name-other-window (project)
+  "Switch to PROJECT and find file in it in other window."
+  (let ((projectile-completion-system 'helm)
+        (projectile-switch-project-action #'helm-projectile-find-file-other-window))
+    (projectile-switch-project-by-name project)))
+
+(defun helm-projectile-switch-project-by-name-other-frame (project)
+  "Switch to PROJECT and find file in it in other frame."
+  (let ((projectile-completion-system 'helm)
+        (projectile-switch-project-action #'helm-projectile-find-file-other-frame))
+    (projectile-switch-project-by-name project)))
+
+(defvar helm-projectile-projects-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map helm-map)
+    (helm-projectile-define-key map
+      (kbd "C-d") #'dired
+      (kbd "C-c o") #'helm-projectile-switch-project-by-name-other-window
+      (kbd "C-c C-o") #'helm-projectile-switch-project-by-name-other-frame
+      (kbd "M-g") #'helm-projectile-vc
+      (kbd "M-e") #'helm-projectile-switch-to-shell
+      (kbd "C-s") #'helm-projectile-grep
+      (kbd "M-c") #'helm-projectile-compile-project
+      (kbd "M-t") #'helm-projectile-test-project
+      (kbd "M-r") #'helm-projectile-run-project
+      (kbd "M-D") #'helm-projectile-remove-known-project
+      (kbd "C-S-a") #'helm-projectile--switch-project-and-ag-action
+      (kbd "C-S-r") #'helm-projectile--switch-project-and-rg-action)
+    map)
+  "Mapping for known projectile projects.")
+
+(defcustom helm-source-projectile-projects-actions
+  (helm-make-actions
+   "Switch to project" #'helm-projectile-switch-project-by-name
+   "Switch to project other window `C-c o'" #'helm-projectile-switch-project-by-name-other-window
+   "Switch to project other frame `C-c C-o'" #'helm-projectile-switch-project-by-name-other-frame
+   "Open Dired in project's directory `C-d'" #'dired
+   "Open project root in vc-dir or magit `M-g'" #'helm-projectile-vc
+   "Switch to Eshell `M-e'" #'helm-projectile-switch-to-shell
+   "Grep in projects `C-s'" #'helm-projectile-grep
+   "Compile project `M-c'. With C-u, new compile command" #'helm-projectile-compile-project
+   "Remove project(s) from project list `M-D'" #'helm-projectile-remove-known-project
+   "Silver searcher (ag) in project `C-S-a'" #'helm-projectile--switch-project-and-ag-action
+   "Ripgrep (rg) in project `C-S-r'" #'helm-projectile--switch-project-and-rg-action)
+  "Actions for `helm-source-projectile-projects'."
+  :group 'helm-projectile
+  :type '(alist :key-type string :value-type function))
+
+(defclass helm-projectile-projects-source (helm-source-sync helm-type-file)
+  ((candidates :initform (lambda () (with-helm-current-buffer
+                                      (mapcar #'copy-sequence
+                                              (projectile-known-projects)))))
+   (fuzzy-match :initform 'helm-projectile-fuzzy-match)
+   (keymap :initform 'helm-projectile-projects-map)
+   (mode-line :initform 'helm-read-file-name-mode-line-string)
+   (action :initform 'helm-source-projectile-projects-actions))
+  "Helm source for known projectile projects.")
+
+(cl-defmethod helm-setup-user-source ((source helm-projectile-projects-source))
+  "Make SOURCE specific to project switching.
+The `helm-projectile-projects-source` inherits from
+`helm-type-file` (which see), which sets up actions, keymap, and
+help message slots to file specific ones.  Override these slots
+to be specific to `helm-projectile-projects-source'."
+  (setf (slot-value source 'action) 'helm-source-projectile-projects-actions)
+  (setf (slot-value source 'keymap) helm-projectile-projects-map)
+  ;; Use `ignore' as a persistent action, to actually keep `helm' session
+  ;; when `helm-execute-persistent-action' is executed.
+  (setf (slot-value source 'persistent-action) #'ignore)
+  (let ((persistent-help "Do Nothing"))
+    (setf (slot-value source 'persistent-help) persistent-help)
+    (setf (slot-value source 'header-line)
+          (helm-source--persistent-help-string
+           persistent-help
+           source)))
+  (setf (slot-value source 'mode-line)
+        (list "Project(s)" helm-mode-line-string)))
+
+(defvar helm-source-projectile-projects
+  (helm-make-source "Projectile projects" 'helm-projectile-projects-source))
+
+(defclass helm-projectile-projects-other-window-source (helm-projectile-projects-source)
+  ())
+
+(cl-defmethod helm-setup-user-source :after ((source helm-projectile-projects-other-window-source))
+  "Set `helm-projectile-switch-project-by-name-other-window' as the first action."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-source-projectile-projects-actions
+         '(helm-projectile-switch-project-by-name-other-window . :make-first))))
+
+(defclass helm-projectile-projects-other-frame-source (helm-projectile-projects-source)
+  ())
+
+(cl-defmethod helm-setup-user-source :after ((source helm-projectile-projects-other-frame-source))
+  "Set `helm-projectile-switch-project-by-name-other-frame' as the first action."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-source-projectile-projects-actions
+         '(helm-projectile-switch-project-by-name-other-frame . :make-first))))
+
+(defvar helm-projectile-dirty-projects-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map helm-map)
+    (helm-projectile-define-key map
+      (kbd "C-d") #'dired
+      (kbd "M-o") #'helm-projectile-switch-project-by-name
+      (kbd "C-c o") #'helm-projectile-switch-project-by-name-other-window
+      (kbd "C-c C-o") #'helm-projectile-switch-project-by-name-other-frame
+      (kbd "M-e") #'helm-projectile-switch-to-shell
+      (kbd "C-s") #'helm-projectile-grep
+      (kbd "M-c") #'helm-projectile-compile-project
+      (kbd "M-t") #'helm-projectile-test-project
+      (kbd "M-r") #'helm-projectile-run-project
+      (kbd "M-D") #'helm-projectile-remove-known-project
+      (kbd "C-S-a") #'helm-projectile--switch-project-and-ag-action
+      (kbd "C-S-r") #'helm-projectile--switch-project-and-rg-action)
+    map)
+  "Mapping for dirty projectile projects.")
+
+(defvar helm-source-projectile-dirty-projects
+  (helm-build-sync-source "Projectile dirty projects"
+    :candidates (lambda () (with-helm-current-buffer (helm-projectile-get-dirty-projects)))
+    :fuzzy-match helm-projectile-fuzzy-match
+    :keymap helm-projectile-dirty-projects-map
+    :mode-line helm-read-file-name-mode-line-string
+    :action '(("Open project root in vc-dir or magit" . helm-projectile-vc)
+              ("Switch to project `M-o'" . helm-projectile-switch-project-by-name)
+              ("Switch to project other window `C-c o'" . helm-projectile-switch-project-by-name-other-window)
+              ("Switch to project other frame `C-c C-o'" . helm-projectile-switch-project-by-name-other-frame)
+              ("Open Dired in project's directory `C-d'" . dired)
+              ("Switch to Eshell `M-e'" . helm-projectile-switch-to-shell)
+              ("Grep in projects `C-s'" . helm-projectile-grep)
+              ("Compile project `M-c'. With C-u, new compile command"
+               . helm-projectile-compile-project)
+              ("Silver searcher (ag) in project `C-S-a'" . helm-projectile--switch-project-and-ag-action)
+              ("Ripgrep (rg) in project `C-S-r'" . helm-projectile--switch-project-and-rg-action)))
+    "Helm source for dirty version controlled projectile projects.")
+
+(defun helm-projectile-get-dirty-projects ()
+  "Return dirty version controlled known projects.
+The value is returned as an alist to have a nice display in Helm."
+  (message "Checking for dirty known projects...")
+  (let* ((status (projectile-check-vcs-status-of-known-projects))
+         (proj-dir (cl-loop for stat in status
+                            collect (car stat)))
+         (status-display (cl-loop for stat in status collect
+                                  (propertize (format "[%s]"
+                                                      (mapconcat 'identity
+                                                                 (car (cdr stat)) ", "))
+                                              'face 'helm-match)))
+         (max-status-display-length (cl-loop for sd in status-display
+                                             maximize (length sd)))
+         (status-display (cl-loop for sd in status-display collect
+                                  (format "%s%s    "
+                                          sd
+                                          (make-string
+                                           (- max-status-display-length (length sd)) ? ))))
+         (full-display (cl-mapcar 'concat
+                                  status-display
+                                  (mapcar (lambda (dir)
+                                            (propertize dir 'face 'helm-ff-directory))
+                                          proj-dir))))
+    (cl-pairlis full-display proj-dir)))
+
+(define-key helm-etags-map (kbd "C-c p f")
+  (lambda ()
+    (interactive)
+    (helm-run-after-exit 'helm-projectile-find-file nil)))
+
+(defun helm-projectile-file-persistent-action (candidate)
+  "Previews the contents of a file CANDIDATE in a temporary buffer.
+This is a persistent action for file-related functionality."
+  (let ((buf (get-buffer-create " *helm-projectile persistent*")))
+    (cl-flet ((preview (candidate)
+                       (switch-to-buffer buf)
+                       (setq inhibit-read-only t)
+                       (erase-buffer)
+                       (insert-file-contents candidate)
+                       (let ((buffer-file-name candidate))
+                         (set-auto-mode))
+                       (font-lock-ensure)
+                       (setq inhibit-read-only nil)))
+      (if (and (helm-get-attr 'previewp)
+               (string= candidate (helm-get-attr 'current-candidate)))
+          (progn
+            (kill-buffer buf)
+            (helm-set-attr 'previewp nil))
+        (preview candidate)
+        (helm-set-attr 'previewp t)))
+    (helm-set-attr 'current-candidate candidate)))
+
+(defun helm-projectile-find-files-eshell-command-on-file-action (candidate)
+  "Execute an eshell command on a file CANDIDATE."
+  (interactive)
+  (let* ((helm-ff-default-directory (file-name-directory candidate)))
+    (helm-find-files-eshell-command-on-file candidate)))
+
+(defun helm-projectile-ff-etags-select-action (candidate)
+  "Jump to etags for file CANDIDATE.
+See also `helm-etags-select'."
+  (interactive)
+  (let* ((helm-ff-default-directory (file-name-directory candidate)))
+    (helm-ff-etags-select candidate)))
+
+(defun helm-projectile-switch-to-shell (dir)
+  "Within DIR, switch to a shell corresponding to `helm-ff-preferred-shell-mode'."
+  (interactive)
+  (let* ((projectile-require-project-root nil)
+         (helm-ff-default-directory (file-name-directory (projectile-expand-root dir))))
+    (helm-ff-switch-to-shell dir)))
+
+(defun helm-projectile-files-in-current-dired-buffer ()
+  "Return a list of files (only) in the current Dired buffer."
+  (let (flist)
+    (cl-flet ((fpush (fname) (push fname flist)))
+      (save-excursion
+        (let (file buffer-read-only)
+          (goto-char (point-min))
+          (while (not (eobp))
+            (save-excursion
+              (and (not (eolp))
+                   (setq file (dired-get-filename t t)) ; nil on non-file
+                   (progn (end-of-line)
+                          (funcall #'fpush file))))
+            (forward-line 1)))))
+    (mapcar 'file-truename (nreverse flist))))
+
+(defun helm-projectile-all-dired-buffers ()
+  "Get all current Dired buffers."
+  (mapcar (lambda (b)
+            (with-current-buffer b (buffer-name)))
+          (cl-remove-if-not
+           (lambda (b)
+             (with-current-buffer b
+               (and (eq major-mode 'dired-mode)
+                    (buffer-name))))
+           (buffer-list))))
+
+(defvar helm-projectile-virtual-dired-remote-enable nil
+  "Enable virtual Dired manager on remote host.
+Disabled by default.")
+
+(defun helm-projectile-dired-files-new-action (candidate)
+  "Create a Dired buffer from chosen files.
+CANDIDATE is the selected file, but choose the marked files if available."
+  (if (and (file-remote-p (projectile-project-root))
+           (not helm-projectile-virtual-dired-remote-enable))
+      (message "Virtual Dired manager is disabled in remote host. Enable with %s."
+               (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
+    (let ((files (cl-remove-if-not
+                  (lambda (f)
+                    (not (string= f "")))
+                  (mapcar (lambda (file)
+                            (replace-regexp-in-string (projectile-project-root) "" file))
+                          (helm-marked-candidates :with-wildcard t))))
+          (new-name (completing-read "Select or enter a new buffer name: "
+                                     (helm-projectile-all-dired-buffers)))
+          (helm--reading-passwd-or-string t)
+          (default-directory (projectile-project-root)))
+      ;; create a unique buffer that is unique to any directory in default-directory
+      ;; or opened buffer; when Dired is passed with a non-existence directory name,
+      ;; it only creates a buffer and insert everything. If a new name user supplied
+      ;; exists as default-directory, Dired throws error when insert anything that
+      ;; does not exist in current directory.
+      (with-current-buffer (dired (cons (make-temp-name new-name)
+                                        (if files
+                                            files
+                                          (list candidate))))
+        (when (get-buffer new-name)
+          (kill-buffer new-name))
+        (rename-buffer new-name)))))
+
+(defun helm-projectile-dired-files-add-action (candidate)
+  "Add files to a Dired buffer.
+CANDIDATE is the selected file.  Used when no file is explicitly marked."
+  (if (and (file-remote-p (projectile-project-root))
+           (not helm-projectile-virtual-dired-remote-enable))
+      (message "Virtual Dired manager is disabled in remote host. Enable with %s."
+               (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
+    (if (eq (with-helm-current-buffer major-mode) 'dired-mode)
+        (let* ((marked-files (helm-marked-candidates :with-wildcard t))
+               (helm--reading-passwd-or-string t)
+               (root (projectile-project-root)) ; store root for later use
+               (dired-buffer-name (or (and (eq major-mode 'dired-mode) (buffer-name))
+                                      (completing-read "Select a Dired buffer:"
+                                                       (helm-projectile-all-dired-buffers))))
+               (dired-files (with-current-buffer dired-buffer-name
+                              (helm-projectile-files-in-current-dired-buffer)))
+               (files (sort (mapcar (lambda (file)
+                                      (replace-regexp-in-string (projectile-project-root) "" file))
+                                    (cl-nunion (if marked-files
+                                                   marked-files
+                                                 (list candidate))
+                                               dired-files
+                                               :test #'string-equal))
+                            'string-lessp)))
+          (kill-buffer dired-buffer-name)
+          ;; Rebind default-directory because after killing a buffer, we
+          ;; could be in any buffer and default-directory is set to that
+          ;; random buffer
+          ;;
+          ;; Also use saved root directory, because after killing a buffer,
+          ;; we could be outside of current project
+          (let ((default-directory root))
+            (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
+                                              (if files
+                                                  (mapcar (lambda (file)
+                                                            (replace-regexp-in-string root "" file))
+                                                          files)
+                                                (list candidate))))
+              (rename-buffer dired-buffer-name))))
+      (error "You're not in a Dired buffer to add"))))
+
+(defun helm-projectile-dired-files-delete-action (candidate)
+  "Delete selected entries from a Dired buffer.
+CANDIDATE is the selected file.  Used when no file is explicitly marked."
+  (if (and (file-remote-p (projectile-project-root))
+           (not helm-projectile-virtual-dired-remote-enable))
+      (message "Virtual Dired manager is disabled in remote host. Enable with %s."
+               (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
+    (let* ((helm--reading-passwd-or-string t)
+           (root (projectile-project-root))
+           (dired-buffer-name (with-helm-current-buffer (buffer-name)))
+           (dired-files (with-current-buffer dired-buffer-name
+                          (helm-projectile-files-in-current-dired-buffer)))
+           (files (sort (cl-set-exclusive-or (helm-marked-candidates :with-wildcard t)
+                                             dired-files
+                                             :test #'string-equal) #'string-lessp)))
+      (kill-buffer dired-buffer-name)
+      ;; similar reason to `helm-projectile-dired-files-add-action'
+      (let ((default-directory root))
+        (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
+                                          (if files
+                                              (mapcar (lambda (file)
+                                                        (replace-regexp-in-string root "" file))
+                                                      files)
+                                            (list candidate))))
+          (rename-buffer dired-buffer-name))))))
+
+(defun helm-projectile-run-projectile-hooks-after-find-file (_orig-fun &rest _args)
+  "Run `projectile-find-file-hook' if using projectile."
+  (when (and projectile-mode (projectile-project-p))
+    (run-hooks 'projectile-find-file-hook)))
+
+(advice-add 'helm-find-file-or-marked
+            :after #'helm-projectile-run-projectile-hooks-after-find-file)
+
+(defvar helm-projectile-find-file-map
+  (let ((map (copy-keymap helm-find-files-map)))
+    (helm-projectile-define-key map
+      (kbd "C-c f") #'helm-projectile-dired-files-new-action
+      (kbd "C-c a") #'helm-projectile-dired-files-add-action
+      (kbd "M-e") #'helm-projectile-switch-to-shell
+      (kbd "M-.") #'helm-projectile-ff-etags-select-action
+      (kbd "M-!") #'helm-projectile-find-files-eshell-command-on-file-action)
+    (define-key map (kbd "<left>") #'helm-previous-source)
+    (define-key map (kbd "<right>") #'helm-next-source)
+    (dolist (cmd '(helm-find-files-up-one-level
+                   helm-find-files-down-last-level))
+      (substitute-key-definition cmd nil map))
+    map)
+  "Mapping for file commands in Helm Projectile.")
+
+(defvar helm-projectile-file-actions
+  (helm-projectile-hack-actions
+   helm-find-files-actions
+   ;; Delete these actions
+   'helm-ff-browse-project
+   'helm-insert-file-name-completion-at-point
+   'helm-ff-find-sh-command
+   'helm-ff-cache-add-file
+   ;; Substitute these actions
+   '(helm-ff-switch-to-shell . helm-projectile-switch-to-shell)
+   '(helm-ff-etags-select     . helm-projectile-ff-etags-select-action)
+   '(helm-find-files-eshell-command-on-file
+     . helm-projectile-find-files-eshell-command-on-file-action)
+   ;; Change action descriptions
+   '(helm-find-file-as-root . "Find file as root `C-c r'")
+   ;; New actions
+   '(helm-projectile-dired-files-new-action
+     . "Create Dired buffer from files `C-c f'")
+   '(helm-projectile-dired-files-add-action
+     . "Add files to Dired buffer `C-c a'"))
+  "Action for files.")
+
+(defun helm-projectile--move-selection-p (selection)
+  "Return non-nil if should move Helm selector after SELECTION.
+
+SELECTION should be moved unless it's one of:
+
+- Non-string
+- Existing file
+- Non-remote file that matches `helm-tramp-file-name-regexp'"
+  (not (or (not (stringp selection))
+         (file-exists-p selection)
+         (and (string-match helm-tramp-file-name-regexp selection)
+              (not (file-remote-p selection nil t))))))
+
+(defun helm-projectile--move-to-real ()
+  "Move to first real candidate.
+
+Similar to `helm-ff--move-to-first-real-candidate', but without
+unnecessary complexity."
+  (while (let* ((src (helm-get-current-source))
+                (selection (and (not (helm-empty-source-p))
+                                (helm-get-selection nil nil src))))
+           (and (not (helm-end-of-source-p))
+                (helm-projectile--move-selection-p selection)))
+    (helm-next-line)))
+
+(defun helm-projectile--remove-move-to-real ()
+  "Hook function to remove `helm-projectile--move-to-real'.
+
+Meant to be added to `helm-cleanup-hook', from which it removes
+ itself at the end."
+  (remove-hook 'helm-after-update-hook #'helm-projectile--move-to-real)
+  (remove-hook 'helm-cleanup-hook #'helm-projectile--remove-move-to-real))
+
+(defvar helm-source-projectile-files-list-before-init-hook
+  (lambda ()
+    (add-hook 'helm-after-update-hook #'helm-projectile--move-to-real)
+    (add-hook 'helm-cleanup-hook #'helm-projectile--remove-move-to-real)))
+
+(defclass helm-source-projectile-file (helm-source-sync)
+  ((before-init-hook :initform 'helm-source-projectile-files-list-before-init-hook)
+   (candidates
+    :initform (lambda ()
+                (when (projectile-project-p)
+                  (with-temp-buffer
+                    (hack-dir-local-variables-non-file-buffer)
+                    (helm-projectile--files-display-real (projectile-current-project-files)
+                                                         (projectile-project-root))))))
+   (filtered-candidate-transformer
+    :initform (lambda (files _source)
+                (with-temp-buffer
+                  (hack-dir-local-variables-non-file-buffer)
+                  (let* ((root (projectile-project-root))
+                         (file-at-root (file-relative-name (expand-file-name helm-pattern root))))
+                    (if (or (string-empty-p helm-pattern)
+                            (assoc helm-pattern files))
+                        files
+                      (if (equal helm-pattern file-at-root)
+                          (cl-acons (helm-ff-prefix-filename helm-pattern nil t)
+                                    (expand-file-name helm-pattern)
+                                    files)
+                        (cl-pairlis (list (helm-ff-prefix-filename helm-pattern nil t)
+                                          (helm-ff-prefix-filename file-at-root nil t))
+                                    (list (expand-file-name helm-pattern)
+                                          (expand-file-name helm-pattern root))
+                                    files)))))))
+   (fuzzy-match :initform 'helm-projectile-fuzzy-match)
+   (keymap :initform 'helm-projectile-find-file-map)
+   (help-message :initform 'helm-ff-help-message)
+   (mode-line :initform 'helm-read-file-name-mode-line-string)
+   (action :initform 'helm-projectile-file-actions)
+   (persistent-action :initform #'helm-projectile-file-persistent-action)
+   (persistent-help :initform "Preview file")))
+
+(defvar helm-source-projectile-files-list
+  (helm-make-source "Projectile files" 'helm-source-projectile-file)
+  "Helm source definition for Projectile files.")
+
+(defclass helm-source-projectile-file-other-window (helm-source-projectile-file)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-file-other-window))
+  "Make `helm-find-files-other-window' the first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-projectile-file-actions
+         '(helm-find-files-other-window . :make-first))))
+
+(defvar helm-source-projectile-files-other-window-list
+  (helm-make-source "Projectile files" 'helm-source-projectile-file-other-window)
+  "Helm source definition for Projectile files.")
+
+(defclass helm-source-projectile-file-other-frame (helm-source-projectile-file)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-file-other-frame))
+  "Make `find-file-other-frame' the first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-projectile-file-actions
+         '(find-file-other-frame . :make-first))))
+
+(defvar helm-source-projectile-files-other-frame-list
+  (helm-make-source "Projectile files" 'helm-source-projectile-file-other-frame)
+  "Helm source definition for Projectile files.")
+
+(defvar helm-source-projectile-files-in-all-projects-list
+  (helm-build-sync-source "Projectile files in all Projects"
+    :candidates (lambda ()
+                  (with-helm-current-buffer
+                    (let ((projectile-require-project-root nil))
+                      (projectile-all-project-files))))
+    :keymap helm-projectile-find-file-map
+    :help-message 'helm-ff-help-message
+    :mode-line helm-read-file-name-mode-line-string
+    :action helm-projectile-file-actions
+    :persistent-action #'helm-projectile-file-persistent-action
+    :persistent-help "Preview file")
+  "Helm source definition for all Projectile files in all projects.")
+
+(defvar helm-projectile-dired-file-actions
+  (helm-projectile-hack-actions
+   helm-projectile-file-actions
+   ;; New actions
+   '(helm-projectile-dired-files-delete-action . "Remove entry(s) from Dired buffer `C-c d'")))
+
+(defclass helm-source-projectile-dired-file (helm-source-in-buffer)
+  ((data :initform (lambda ()
+                     (if (and (file-remote-p (projectile-project-root))
+                              (not helm-projectile-virtual-dired-remote-enable))
+                         nil
+                       (when (eq major-mode 'dired-mode)
+                         (helm-projectile-files-in-current-dired-buffer)))))
+   (filter-one-by-one :initform (lambda (file)
+                                  (let ((helm-ff-transformer-show-only-basename t))
+                                    (helm-ff-filter-candidate-one-by-one file))))
+   (action-transformer :initform (lambda (actions candidate)
+                                   (let ((actions  (helm-find-files-action-transformer actions candidate)))
+                                     (if (file-directory-p candidate)
+                                         (append
+                                          actions
+                                          '(("Silver searcher (ag) in directory `C-S-a'" . helm-projectile--switch-project-and-ag-action)
+                                            ("Ripgrep (rg) in directory `C-S-r'" . helm-projectile--switch-project-and-rg-action)))
+                                       actions))))
+   (keymap :initform (let ((map (copy-keymap helm-projectile-find-file-map)))
+                       (helm-projectile-define-key map
+                         (kbd "C-c d") #'helm-projectile-dired-files-delete-action
+                         (kbd "C-S-a") #'helm-projectile--switch-project-and-ag-action
+                         (kbd "C-S-r") #'helm-projectile--switch-project-and-rg-action)
+                       map))
+    (help-message :initform 'helm-ff-help-message)
+    (mode-line :initform 'helm-read-file-name-mode-line-string)
+    (action :initform 'helm-projectile-dired-file-actions)))
+
+(defvar helm-source-projectile-dired-files-list
+  (helm-make-source "Projectile files in current Dired buffer"
+    'helm-source-projectile-dired-file)
+  "Helm source definition for Projectile delete files.")
+
+(defclass helm-source-projectile-dired-file-other-window (helm-source-projectile-dired-file)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-dired-file-other-window))
+  "Make `helm-find-files-other-window' the first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-projectile-dired-file-actions
+         '(helm-find-files-other-window . :make-first))))
+
+(defvar helm-source-projectile-dired-files-other-window-list
+  (helm-make-source "Projectile files in current Dired buffer"
+    'helm-source-projectile-dired-file-other-window)
+  "Helm source definition for Projectile delete files.")
+
+(defclass helm-source-projectile-dired-file-other-frame (helm-source-projectile-dired-file)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-dired-file-other-frame))
+  "Make `find-file-other-frame' the first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-projectile-dired-file-actions
+         '(find-file-other-frame . :make-first))))
+
+(defvar helm-source-projectile-dired-files-other-frame-list
+  (helm-make-source "Projectile files in current Dired buffer"
+    'helm-source-projectile-dired-file-other-frame)
+  "Helm source definition for Projectile delete files.")
+
+(defun helm-projectile-dired-find-dir (dir)
+  "Jump to a selected directory DIR from `helm-projectile'."
+  (dired (expand-file-name dir (projectile-project-root)))
+  (run-hooks 'projectile-find-dir-hook))
+
+(defun helm-projectile-dired-find-dir-other-window (dir)
+  "Jump to a selected directory DIR from `helm-projectile' (in other window)."
+  (dired-other-window (expand-file-name dir (projectile-project-root)))
+  (run-hooks 'projectile-find-dir-hook))
+
+(defun helm-projectile-dired-find-dir-other-frame (dir)
+  "Jump to a selected directory DIR from `helm-projectile' (in other frame)."
+  (dired-other-frame (expand-file-name dir (projectile-project-root)))
+  (run-hooks 'projectile-find-dir-hook))
+
+(defvar helm-source-projectile-directory-actions
+  '(("Open Dired" . helm-projectile-dired-find-dir)
+    ("Open Dired in other window `C-c o'" . helm-projectile-dired-find-dir-other-window)
+    ("Open Dired in other frame `C-c C-o'" . helm-projectile-dired-find-dir-other-frame)
+    ("Switch to Eshell `M-e'" . helm-projectile-switch-to-shell)
+    ("Grep in projects `C-s'" . helm-projectile-grep)
+    ("Create Dired buffer from files `C-c f'" . helm-projectile-dired-files-new-action)
+    ("Add files to Dired buffer `C-c a'" . helm-projectile-dired-files-add-action)
+    ("Silver searcher (ag) in directory `C-S-a'" . helm-projectile--switch-project-and-ag-action)
+    ("Ripgrep (rg) in directory `C-S-r'" . helm-projectile--switch-project-and-rg-action)))
+
+(defclass helm-source-projectile-directory (helm-source-sync)
+  ((candidates :initform (lambda ()
+                           (when (projectile-project-p)
+                             (with-temp-buffer
+                               (hack-dir-local-variables-non-file-buffer)
+                               (let ((dirs (if projectile-find-dir-includes-top-level
+                                               (append '("./") (projectile-current-project-dirs))
+                                             (projectile-current-project-dirs))))
+                                 (helm-projectile--files-display-real dirs (projectile-project-root)))))))
+   (fuzzy-match :initform 'helm-projectile-fuzzy-match)
+   (action-transformer :initform 'helm-find-files-action-transformer)
+   (keymap :initform (let ((map (make-sparse-keymap)))
+                       (set-keymap-parent map helm-map)
+                       (helm-projectile-define-key map
+                         (kbd "<left>") #'helm-previous-source
+                         (kbd "<right>") #'helm-next-source
+                         (kbd "C-c o") #'helm-projectile-dired-find-dir-other-window
+                         (kbd "C-c C-o") #'helm-projectile-dired-find-dir-other-frame
+                         (kbd "M-e")   #'helm-projectile-switch-to-shell
+                         (kbd "C-c f") #'helm-projectile-dired-files-new-action
+                         (kbd "C-c a") #'helm-projectile-dired-files-add-action
+                         (kbd "C-s")   #'helm-projectile-grep
+                         (kbd "C-S-a") #'helm-projectile--switch-project-and-ag-action
+                         (kbd "C-S-r") #'helm-projectile--switch-project-and-rg-action)
+                       map))
+   (help-message :initform 'helm-ff-help-message)
+   (mode-line :initform 'helm-read-file-name-mode-line-string)
+   (action :initform 'helm-source-projectile-directory-actions)))
+
+(defvar helm-source-projectile-directories-list
+  (helm-make-source "Projectile directories" 'helm-source-projectile-directory)
+  "Helm source for listing project directories.")
+
+(defclass helm-source-projectile-directory-other-window (helm-source-projectile-directory)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-directory-other-window))
+  "Make `helm-projectile-dired-find-dir-other-window' the first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-source-projectile-directory-actions
+         '(helm-projectile-dired-find-dir-other-window . :make-first))))
+
+(defvar helm-source-projectile-directories-other-window-list
+  (helm-make-source "Projectile directories" 'helm-source-projectile-directory-other-window)
+  "Helm source for listing project directories.")
+
+(defclass helm-source-projectile-directory-other-frame (helm-source-projectile-directory)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-directory-other-frame))
+  "Make `helm-projectile-dired-find-dir-other-frame' the first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-source-projectile-directory-actions
+         '(helm-projectile-dired-find-dir-other-frame . :make-first))))
+
+(defvar helm-source-projectile-directories-other-frame-list
+  (helm-make-source "Projectile directories" 'helm-source-projectile-directory-other-frame)
+  "Helm source for listing project directories.")
+
+(defvar helm-projectile-buffers-list-cache nil)
+
+(defclass helm-source-projectile-buffer (helm-source-sync helm-type-buffer)
+  ((init :initform (lambda ()
+                     ;; Issue #51 Create the list before `helm-buffer' creation.
+                     (setq helm-projectile-buffers-list-cache
+                           (ignore-errors
+                             (let* ((buffers (projectile-project-buffer-names))
+                                    (current-buffer (buffer-name)))
+                               (append (remove current-buffer buffers)
+                                       (unless helm-projectile-remove-current-buffer
+                                         ;; Allow current buffer to be shown,
+                                         ;; but push it to the end.
+                                         (list current-buffer))))))
+                     (let ((result (cl-loop for b in helm-projectile-buffers-list-cache
+                                            maximize (length b) into len-buf
+                                            maximize (length (with-current-buffer b
+                                                               (symbol-name major-mode)))
+                                            into len-mode
+                                            finally return (cons len-buf len-mode))))
+                       (unless (default-value 'helm-buffer-max-length)
+                         (helm-set-local-variable 'helm-buffer-max-length (car result)))
+                       (unless (default-value 'helm-buffer-max-len-mode)
+                         ;; If a new buffer is longer that this value
+                         ;; this value will be updated
+                         (helm-set-local-variable 'helm-buffer-max-len-mode (cdr result))))))
+   (candidates :initform 'helm-projectile-buffers-list-cache)
+   (matchplugin :initform nil)
+   (match :initform 'helm-buffers-match-function)
+   (persistent-action :initform 'helm-buffers-list-persistent-action)
+   (keymap :initform 'helm-buffer-map)
+   (volatile :initform t)
+   (persistent-help
+    :initform
+    "Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))
+
+(defvar helm-source-projectile-buffers-list
+  (helm-make-source "Project buffers" 'helm-source-projectile-buffer))
+
+(defclass helm-source-projectile-buffer-other-window (helm-source-projectile-buffer)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-buffer-other-window))
+  "Make `helm-buffer-switch-buffers-other-window' first action in SOURCE."
+  (setf (slot-value source 'action)
+        (helm-projectile-hack-actions
+         helm-type-buffer-actions
+         '(helm-buffer-switch-buffers-other-window . :make-first))))
+
+(defvar helm-source-projectile-buffers-other-window-list
+  (helm-make-source "Project buffers" 'helm-source-projectile-buffer-other-window))
+
+(defclass helm-source-projectile-buffer-other-frame (helm-source-projectile-buffer)
+  ())
+
+(cl-defmethod helm-setup-user-source ((source helm-source-projectile-buffer-other-frame))
+  "Make `helm-buffer-switch-to-buffer-other-frame' first action in SOURCE."
+  (setf
+   (slot-value source 'action)
+   (helm-projectile-hack-actions
+    helm-type-buffer-actions
+    '(helm-buffer-switch-to-buffer-other-frame . :make-first))))
+
+(defvar helm-source-projectile-buffers-other-frame-list
+  (helm-make-source "Project buffers" 'helm-source-projectile-buffer-other-frame))
+
+(defvar helm-source-projectile-recentf-list
+  (helm-build-sync-source "Projectile recent files"
+    :candidates (lambda ()
+                  (when (projectile-project-p)
+                    (with-temp-buffer
+                      (hack-dir-local-variables-non-file-buffer)
+                      (helm-projectile--files-display-real (projectile-recentf-files)
+                                                           (projectile-project-root)))))
+    :fuzzy-match helm-projectile-fuzzy-match
+    :keymap helm-projectile-find-file-map
+    :help-message 'helm-ff-help-message
+    :mode-line helm-read-file-name-mode-line-string
+    :action helm-projectile-file-actions
+    :persistent-action #'helm-projectile-file-persistent-action
+    :persistent-help "Preview file")
+  "Helm source definition for recent files in current project.")
+
+(defcustom helm-projectile-git-grep-command
+  "git --no-pager grep --no-color -n%c -e %p -- %f"
+  "Command to execute when performing `helm-grep' inside a projectile git project.
+See documentation of `helm-grep-default-command' for the format."
+  :type 'string
+  :group 'helm-projectile)
+
+(defcustom helm-projectile-grep-command
+  "grep -a -r %e -n%cH -e %p %f ."
+  "Command to execute when performing `helm-grep' outside a projectile git project.
+See documentation of `helm-grep-default-command' for the format."
+  :type 'string
+  :group 'helm-projectile)
+
+
+(defcustom helm-projectile-sources-list
+  '(helm-source-projectile-buffers-list
+    helm-source-projectile-files-list
+    helm-source-projectile-projects)
+  "Default sources for `helm-projectile'."
+  :type '(repeat symbol)
+  :group 'helm-projectile)
+
+(defmacro helm-projectile-command (command source prompt &optional not-require-root truncate-lines-var)
+  "Template for generic `helm-projectile' commands.
+COMMAND is a command name to be appended with \"helm-projectile\" prefix.
+SOURCE is a Helm source that should be Projectile specific.
+PROMPT is a string for displaying as a prompt.
+NOT-REQUIRE-ROOT specifies the command doesn't need to be used in a
+project root.
+TRUNCATE-LINES-VAR is the symbol used dictate truncation of lines.
+Defaults is `helm-projectile-truncate-lines'."
+  (unless truncate-lines-var (setq truncate-lines-var 'helm-projectile-truncate-lines))
+  `(defun ,(intern (concat "helm-projectile-" command)) (&optional arg)
+     "Use projectile with Helm for finding files in project
+
+With a prefix ARG invalidates the cache first."
+     (interactive "P")
+     (if (projectile-project-p)
+         (projectile-maybe-invalidate-cache arg)
+       (unless ,not-require-root
+         (error "You're not in a project")))
+     (let ((helm-ff-transformer-show-only-basename nil)
+           ;; for consistency, we should just let Projectile take care of ignored files
+           (helm-boring-file-regexp-list nil))
+       (helm :sources ,source
+             :buffer (concat "*helm projectile: " (projectile-project-name) "*")
+             :truncate-lines ,truncate-lines-var
+             :prompt (projectile-prepend-project-name ,prompt)))))
+
+;; You can evaluate the following command to help inserting autoloads for the
+;; `helm-projectile-command' macro. To use: move point to a form that calls
+;; `helm-projectile-command' and type:
+;;
+;;   M-x helm-projectile-command-insert-autoload
+;;
+;; (defun helm-projectile-command-insert-autoload ()
+;;   "Insert autoload for a helm-projectile-command at point."
+;;   (interactive)
+;;   (save-excursion
+;;     (end-of-defun)
+;;     (beginning-of-defun)
+;;     (when-let* ((beg (point))
+;;                 (form (funcall load-read-function (current-buffer)))
+;;                 ((eq (car form) 'helm-projectile-command))
+;;                 (command (concat "helm-projectile-" (cadr form)))
+;;                 (file (file-name-sans-extension
+;;                        (file-name-nondirectory
+;;                         (buffer-file-name)))))
+;;       (goto-char beg)
+;;       (insert ";;;###autoload(autoload '" command " \"" file "\" nil t)\n"))))
+
+;;;###autoload(autoload 'helm-projectile-switch-project "helm-projectile" nil t)
+(helm-projectile-command "switch-project"
+                         'helm-source-projectile-projects
+                         "Switch to project: " t)
+
+;;;###autoload(autoload 'helm-projectile-switch-project-other-window "helm-projectile" nil t)
+(helm-projectile-command "switch-project-other-window"
+                         (helm-make-source
+                             "Projectile projects"
+                             'helm-projectile-projects-other-window-source)
+                         "Switch to project: " t)
+
+;;;###autoload(autoload 'helm-projectile-switch-project-other-frame "helm-projectile" nil t)
+(helm-projectile-command "switch-project-other-frame"
+                         (helm-make-source
+                             "Projectile projects"
+                             'helm-projectile-projects-other-frame-source)
+                         "Switch to project: " t)
+
+;;;###autoload(autoload 'helm-projectile-find-file "helm-projectile" nil t)
+(helm-projectile-command "find-file"
+                         '(helm-source-projectile-dired-files-list
+                           helm-source-projectile-files-list)
+                         "Find file: ")
+;;;###autoload(autoload 'helm-projectile-find-file-other-window "helm-projectile" nil t)
+(helm-projectile-command "find-file-other-window"
+                         '(helm-source-projectile-dired-files-other-window-list
+                           helm-source-projectile-files-other-window-list)
+                         "Find file (other window): ")
+
+;;;###autoload(autoload 'helm-projectile-find-file-other-frame "helm-projectile" nil t)
+(helm-projectile-command "find-file-other-frame"
+                         '(helm-source-projectile-dired-files-other-frame-list
+                           helm-source-projectile-files-other-frame-list)
+                         "Find file (other frame): ")
+
+;;;###autoload(autoload 'helm-projectile-find-file-in-known-projects "helm-projectile" nil t)
+(helm-projectile-command "find-file-in-known-projects" 'helm-source-projectile-files-in-all-projects-list "Find file in projects: " t)
+
+;;;###autoload(autoload 'helm-projectile-find-dir "helm-projectile" nil t)
+(helm-projectile-command "find-dir"
+                         '(helm-source-projectile-dired-files-list
+                           helm-source-projectile-directories-list)
+                         "Find dir: ")
+
+;;;###autoload(autoload 'helm-projectile-find-dir-other-window "helm-projectile" nil t)
+(helm-projectile-command "find-dir-other-window"
+                         '(helm-source-projectile-dired-files-other-window-list
+                           helm-source-projectile-directories-other-window-list)
+                         "Find dir (other window): ")
+
+;;;###autoload(autoload 'helm-projectile-find-dir-other-frame "helm-projectile" nil t)
+(helm-projectile-command "find-dir-other-frame"
+                         '(helm-source-projectile-dired-files-other-frame-list
+                           helm-source-projectile-directories-other-frame-list)
+                         "Find dir (other frame): ")
+
+;;;###autoload(autoload 'helm-projectile-recentf "helm-projectile" nil t)
+(helm-projectile-command "recentf" 'helm-source-projectile-recentf-list "Recently visited file: ")
+
+;;;###autoload(autoload 'helm-projectile-switch-to-buffer "helm-projectile" nil t)
+(helm-projectile-command "switch-to-buffer"
+                         'helm-source-projectile-buffers-list
+                         "Switch to buffer: " nil helm-buffers-truncate-lines)
+
+;;;###autoload(autoload 'helm-projectile-switch-to-buffer-other-window "helm-projectile" nil t)
+(helm-projectile-command "switch-to-buffer-other-window"
+                         'helm-source-projectile-buffers-other-window-list
+                         "Switch to buffer (other window): " nil helm-buffers-truncate-lines)
+
+;;;###autoload(autoload 'helm-projectile-switch-to-buffer-other-frame "helm-projectile" nil t)
+(helm-projectile-command "switch-to-buffer-other-frame"
+                         'helm-source-projectile-buffers-other-frame-list
+                         "Switch to buffer (other frame): " nil helm-buffers-truncate-lines)
+
+;;;###autoload(autoload 'helm-projectile-browse-dirty-projects "helm-projectile" nil t)
+(helm-projectile-command "browse-dirty-projects" 'helm-source-projectile-dirty-projects "Select a project: " t)
+
+(defun helm-projectile--files-display-real (files root)
+  "Create (DISPLAY . REAL) pairs with FILES and ROOT.
+
+  DISPLAY is the short file name.  REAL is the full path."
+  ;; Use `helm-ff-filter-candidate-one-by-one' (just like `helm-find-files-get-candidates' does).
+  ;; With a twist that some of files may contain a directory component.
+  ;; In such a case `helm-ff-filter-candidate-one-by-one' just returns a file component,
+  ;; so we the do a concatenation of file and directory components manually.
+  (cl-loop with default-directory = root
+           for file in files
+           collect (let ((file-res (helm-ff-filter-candidate-one-by-one file nil t)))
+                     (setcdr file-res (expand-file-name file root))
+                     (if-let* ((directory (file-name-directory file)))
+                         (cons (concat (if-let* ((face (get-text-property
+                                                        0 'face (car file-res))))
+                                           (propertize directory 'face face)
+                                         directory)
+                                       (unless (file-directory-p file)
+                                         (car file-res)))
+                               (cdr file-res))
+                       file-res))))
+
+(defun helm-projectile--find-file-dwim-1 (one-candidate-action actions prompt)
+  "Find file at point based on context.
+Execute ONE-CANDIDATE-ACTION when there is a single file returned by
+`projectile-select-files' (which see).  Otherwise display a Helm with
+ACTIONS and PROMPT with other selected files."
+  (let* ((project-root (projectile-project-root))
+         (project-files (projectile-current-project-files))
+         (files (projectile-select-files project-files)))
+    (if (= (length files) 1)
+        (funcall one-candidate-action (expand-file-name (car files) (projectile-project-root)))
+      (helm :sources (helm-build-sync-source "Projectile files"
+                       :candidates (if (> (length files) 1)
+                                       (helm-projectile--files-display-real files project-root)
+                                     (helm-projectile--files-display-real project-files project-root))
+                       :fuzzy-match helm-projectile-fuzzy-match
+                       :action-transformer 'helm-find-files-action-transformer
+                       :keymap helm-projectile-find-file-map
+                       :help-message helm-ff-help-message
+                       :mode-line helm-read-file-name-mode-line-string
+                       :action actions
+                       :persistent-action #'helm-projectile-file-persistent-action
+                       :persistent-help "Preview file")
+            :buffer "*helm projectile*"
+            :truncate-lines helm-projectile-truncate-lines
+            :prompt (projectile-prepend-project-name prompt)))))
+
+;;;###autoload
+(defun helm-projectile-find-file-dwim ()
+  "Find file at point based on context."
+  (interactive)
+  (helm-projectile--find-file-dwim-1
+   #'find-file helm-projectile-file-actions "Find file: "))
+
+;;;###autoload
+(defun helm-projectile-find-file-dwim-other-window ()
+  "Find file at point based on context."
+  (interactive)
+  (helm-projectile--find-file-dwim-1
+   #'find-file-other-window
+   (helm-projectile-hack-actions
+    helm-projectile-file-actions
+    '(helm-find-files-other-window . :make-first))
+   "Find file (other window): "))
+
+;;;###autoload
+(defun helm-projectile-find-file-dwim-other-frame ()
+  "Find file at point based on context."
+  (interactive)
+  (helm-projectile--find-file-dwim-1
+   #'find-file-other-frame
+   (helm-projectile-hack-actions
+    helm-projectile-file-actions
+    '(find-file-other-frame . :make-first))
+   "Find file (other frame): "))
+
+(defun helm-projectile--find-other-file-1 (one-candidate-action actions prompt flex-matching)
+  "Switch between files with the same name but different extensions using Helm.
+Execute ONE-CANDIDATE-ACTION when there is a single file returned by
+`projectile-get-other-files' (which see).  Otherwise display a Helm with
+ACTIONS and PROMPT with other selected files.
+
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'."
+  (interactive "P")
+  (let* ((project-root (projectile-project-root))
+         (other-files (projectile-get-other-files (buffer-file-name)
+                                                  flex-matching)))
+    (if other-files
+        (if (= (length other-files) 1)
+            (funcall one-candidate-action (expand-file-name (car other-files) project-root))
+          (progn
+            (let* ((helm-ff-transformer-show-only-basename nil))
+              (helm :sources (helm-build-sync-source "Projectile other files"
+                               :candidates (helm-projectile--files-display-real other-files project-root)
+                               :keymap helm-projectile-find-file-map
+                               :help-message helm-ff-help-message
+                               :mode-line helm-read-file-name-mode-line-string
+                               :action actions
+                               :persistent-action #'helm-projectile-file-persistent-action
+                               :persistent-help "Preview file")
+                    :buffer "*helm projectile*"
+                    :truncate-lines helm-projectile-truncate-lines
+                    :prompt (projectile-prepend-project-name prompt)))))
+      (error "No other file found"))))
+
+;;;###autoload
+(defun helm-projectile-find-other-file (&optional flex-matching)
+  "Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'."
+  (interactive "P")
+  (helm-projectile--find-other-file-1
+   #'find-file
+   helm-projectile-file-actions
+   "Find other file: "
+   flex-matching))
+
+;;;###autoload
+(defun helm-projectile-find-other-file-other-window (&optional flex-matching)
+  "Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'."
+  (interactive "P")
+  (helm-projectile--find-other-file-1
+   #'find-file-other-window
+   (helm-projectile-hack-actions
+    helm-projectile-file-actions
+    '(helm-find-files-other-window . :make-first))
+   "Find other file (other window): "
+   flex-matching))
+
+;;;###autoload
+(defun helm-projectile-find-other-file-other-frame (&optional flex-matching)
+  "Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of
+current file.  Other file extensions can be customized with the
+variable `projectile-other-file-alist'."
+  (interactive "P")
+  (helm-projectile--find-other-file-1
+   #'find-file-other-frame
+   (helm-projectile-hack-actions
+    helm-projectile-file-actions
+    '(find-file-other-frame . :make-first))
+   "Find other file (other frame): "
+   flex-matching))
+
+(defcustom helm-projectile-ignore-strategy 'projectile
+  "Allow projectile to compute ignored files and directories.
+
+When set to `projectile', the package will compute ignores and
+explicitly add additionally command line arguments to the search
+tool.  Note that this might override search tool specific
+behaviors (for instance ag would not use VCS ignore files).
+
+When set to `search-tool', the above does not happen."
+  :group 'helm-projectile
+  :type '(choice (const :tag "Allow projectile to compute ignores" projectile)
+                 (const :tag "Let the search tool compute ignores" search-tool)))
+
+(defun helm-projectile--projectile-ignore-strategy ()
+  "True if the ignore strategy is `projectile'."
+  (eq 'projectile helm-projectile-ignore-strategy))
+
+(defun helm-projectile--ignored-files ()
+  "Compute ignored files."
+  (cl-union (projectile-ignored-files-rel) grep-find-ignored-files
+            :test #'equal))
+
+(defun helm-projectile--ignored-directories ()
+  "Compute ignored directories."
+  (cl-union (mapcar #'file-name-as-directory (projectile-ignored-directories-rel))
+            (mapcar #'file-name-as-directory grep-find-ignored-directories)
+            :test #'equal))
+
+(defcustom helm-projectile-grep-or-ack-actions
+  '("Find file" helm-grep-action
+    "Find file other frame" helm-grep-other-frame
+    (lambda () (and (locate-library "elscreen")
+               "Find file in Elscreen"))
+    helm-grep-jump-elscreen
+    "Save results in grep buffer" helm-grep-save-results
+    "Find file other window" helm-grep-other-window)
+  "Available actions for `helm-projectile-grep-or-ack'.
+The contents of this list are passed as the arguments to `helm-make-actions'."
+  :type 'symbol
+  :group 'helm-projectile)
+
+(defcustom helm-projectile-set-input-automatically t
+  "If non-nil, attempt to set search input automatically.
+Automatic input selection uses the region (if there is an active
+region), otherwise it uses the current symbol at point (if there is
+one).  Applies to `helm-projectile-grep', `helm-projectile-ack', and
+`helm-projectile-ag'."
+  :group 'helm-projectile
+  :type 'boolean)
+
+(defun helm-projectile-grep-or-ack (&optional dir use-ack-p ack-ignored-pattern ack-executable include)
+  "Perform helm-grep at project root.
+DIR directory where to search.  USE-ACK-P indicates whether to use ack
+or not.  ACK-IGNORED-PATTERN is a file regex to exclude from searching.
+ACK-EXECUTABLE is the actual ack binary name.  It is usually \"ack\" or
+\"ack-grep\".  If it is nil, or ack/ack-grep not found then use default
+grep command.  INCLUDE is a string with patterns (for \"grep\") or
+types (for \"ack\") to include in search."
+  (let* ((default-directory (or dir (projectile-project-root)))
+         (helm-ff-default-directory default-directory)
+         (helm-grep-in-recurse t)
+         (helm-grep-ignored-files (if (helm-projectile--projectile-ignore-strategy)
+                                      (helm-projectile--ignored-files)
+                                    helm-grep-ignored-files))
+         (helm-grep-ignored-directories (if (helm-projectile--projectile-ignore-strategy)
+                                            (mapcar 'directory-file-name
+                                                    (helm-projectile--ignored-directories))
+                                          helm-grep-ignored-directories))
+         (helm-grep-default-command
+          (if use-ack-p
+              (concat ack-executable " -H --no-group --no-color "
+                      (when include "%e ")
+                      (when ack-ignored-pattern (concat ack-ignored-pattern " "))
+                      "%p %f")
+            (if (and projectile-use-git-grep (eq (projectile-project-vcs) 'git))
+                helm-projectile-git-grep-command
+              (if include
+                  (replace-regexp-in-string (rx (one-or-more whitespace)
+                                                "."
+                                                (zero-or-more whitespace)
+                                                string-end)
+                                            ""
+                                            helm-projectile-grep-command)
+                helm-projectile-grep-command))))
+         (helm-grep-default-recurse-command helm-grep-default-command)
+         (helm-grep-include-files include)
+         (helm-source-grep
+          (helm-build-async-source
+              (capitalize (helm-grep-command t))
+            :header-name (lambda (_name)
+                           (let ((name (if use-ack-p
+                                           "Helm Projectile Ack"
+                                         "Helm Projectile Grep")))
+                             (concat name " " "(C-c ? Help)")))
+            :candidates-process 'helm-grep-collect-candidates
+            :filter-one-by-one 'helm-grep-filter-one-by-one
+            :candidate-number-limit 9999
+            :nohighlight t
+            ;; We need to specify keymap here and as :keymap arg [1]
+            ;; to make it available in further resuming.
+            :keymap helm-grep-map
+            :history 'helm-grep-history
+            :action (apply #'helm-make-actions helm-projectile-grep-or-ack-actions)
+            :persistent-action 'helm-grep-persistent-action
+            :persistent-help "Jump to line (`C-u' Record in mark ring)"
+            :requires-pattern 2)))
+    (helm
+     :sources 'helm-source-grep
+     :input (when helm-projectile-set-input-automatically
+              (if (region-active-p)
+                  (buffer-substring-no-properties (region-beginning) (region-end))
+                (thing-at-point 'symbol)))
+     :buffer (format "*helm %s*" (if use-ack-p
+                                     "ack"
+                                   "grep"))
+     :default-directory default-directory
+     :keymap helm-grep-map
+     :history 'helm-grep-history
+     :truncate-lines helm-grep-truncate-lines)))
+
+;;;###autoload
+(defun helm-projectile-on ()
+  "Turn on `helm-projectile' key bindings."
+  (interactive)
+  (message "Turn on helm-projectile key bindings")
+  (helm-projectile-toggle 1))
+
+;;;###autoload
+(defun helm-projectile-off ()
+  "Turn off `helm-projectile' key bindings."
+  (interactive)
+  (message "Turn off helm-projectile key bindings")
+  (helm-projectile-toggle -1))
+
+;;;###autoload
+(defun helm-projectile-grep (&optional dir files)
+  "Helm version of `projectile-grep'.
+DIR is the project root, if not set then current project root is used.
+FILES is a list of file patterns to search in.  When called with a
+prefix argument then ask for FILES."
+  (interactive)
+  (let* ((project-root (or dir (projectile-project-root) (error "You're not in a project")))
+         (include (if (equal current-prefix-arg '(4))
+                      (read-string (projectile-prepend-project-name "Grep in: "))
+                    files)))
+    (funcall 'run-with-timer 0.01 nil
+             #'helm-projectile-grep-or-ack project-root nil nil nil include)))
+
+(defun helm-projectile--wildcard-to-ack-match (wildcard)
+  "Transform WILDCARD into a form expected by \"match:\" filter of \"ack\"."
+  ;; FIXME: Make the following more robust such that [...[!...] won't be
+  ;; changed.
+  (thread-last
+    wildcard
+    (replace-regexp-in-string (rx ".") ;; "." -> "\."
+                              "\\\\.")
+    (replace-regexp-in-string (rx "?") ;; "?" -> "."
+                              ".")
+    (replace-regexp-in-string (rx "*") ;; "*" -> ".*"
+                              ".*")
+    (replace-regexp-in-string (rx (or string-start (not "[")) "[!") ;; [!...] -> [^...], but don't change [[!]
+                              "[^")
+    (replace-regexp-in-string (rx (group (one-or-more any))) ;; Wrap everything in ^...$
+                              "^\\1$")))
+
+;;;###autoload
+(defun helm-projectile-ack (&optional dir types)
+  "Helm version of `projectile-ack'.
+DIR directory where to search, if not set then current project root is
+used.  TYPES is a list of types to include in search.  When called with
+a prefix argument, then ask for TYPES."
+  (interactive)
+  (let* ((project-root (or dir (projectile-project-root) (error "You're not in a project")))
+         (ignored (when (helm-projectile--projectile-ignore-strategy)
+                    (mapconcat
+                     'identity
+                     (cl-union (mapcar (lambda (path)
+                                         (concat "--ignore-dir="
+                                                 (file-name-nondirectory
+                                                  (directory-file-name path))))
+                                       (helm-projectile--ignored-directories))
+                               (mapcar (lambda (path)
+                                         (concat "--ignore-file=match:"
+                                                 (thread-last
+                                                   path
+                                                   (helm-projectile--wildcard-to-ack-match)
+                                                   (shell-quote-argument))))
+                                       (append
+                                        (helm-projectile--ignored-files)
+                                        (projectile-patterns-to-ignore)))
+                               :test #'equal)
+                     " ")))
+         (helm-ack-grep-executable (cond
+                                    ((executable-find "ack") "ack")
+                                    ((executable-find "ack-grep") "ack-grep")
+                                    (t (error "Neither 'ack' nor 'ack-grep' is available"))))
+         (include (if (equal current-prefix-arg '(4))
+                      (let ((helm-grep-default-recurse-command helm-ack-grep-executable)
+                            (helm-grep-default-command helm-ack-grep-executable))
+                        (helm-grep-read-ack-type))
+                    types)))
+    (funcall 'run-with-timer 0.01 nil
+             #'helm-projectile-grep-or-ack project-root t ignored helm-ack-grep-executable include)))
+
+(defvar helm-projectile--ag-input nil
+  "The value of input to be used in a next `helm-projectile-ag' call.")
+
+(defun helm-projectile--ag-automatic-input (args)
+  "Use active region or a symbol at point as a third element in ARGS.
+This function has been designed as an advice to `helm-grep-ag-1'.  Do not
+use directly."
+  (pcase-let ((`(,directory ,type ,input) args))
+    (list directory
+          type
+          (or input helm-projectile--ag-input))))
+
+;; When calling `helm', the function `helm-grep-ag' uses symbol at point as an
+;; argument `:default-input' (via `helm-sources-using-default-as-input').  This
+;; however sets argument `:input' to an empty string.  As a result the shell
+;; command `ag' (or `rg', or `pt') is being run with the active region or a
+;; symbol at point as a search pattern, but typing in minibuffer starts search
+;; from scratch.  This advice will use symbol active region or a symbol point
+;; as an `input' argument to `helm-grep-ag-1', which will ensure both `helm'
+;; arguments `:default-input' and `:input' are populated.
+(advice-add #'helm-grep-ag-1
+            :filter-args #'helm-projectile--ag-automatic-input)
+
+(defun helm-projectile--ag--region-selection ()
+  "Return a default input for `helm-grep-ag'."
+  (when helm-projectile-set-input-automatically
+    (if (region-active-p)
+        (buffer-substring-no-properties (region-beginning) (region-end))
+      (thing-at-point 'symbol))))
+
+(defun helm-projectile--ag-1 (directory input &optional options)
+  "Call `helm-grep-ag' with DIRECTORY.
+DIRECTORY is the directory to search in.  INPUT is the value of default
+input to use for the search.  OPTIONS are explicit command line
+arguments to `helm-grep-ag-command'.  When called with a double or a
+triple prefix argument, ask for TYPES (see `helm-grep-ag')."
+  (let* ((ignored (when (helm-projectile--projectile-ignore-strategy)
+                    (mapconcat (lambda (i)
+                                 (helm-acase (helm-grep--ag-command)
+                                   ;; `helm-grep-ag-command' suggests
+                                   ;; that PT is obsolete, but support
+                                   ;; still persist in Helm. Likely
+                                   ;; remove after Helm drops support.
+                                   (("ag" "pt")
+                                    (concat "--ignore " (shell-quote-argument i)))
+                                   ("rg"
+                                    (concat "--glob !" (shell-quote-argument i)))))
+                               (append (helm-projectile--ignored-files)
+                                       (helm-projectile--ignored-directories))
+                               " ")))
+         (helm-grep-ag-command (format helm-grep-ag-command
+                                       (mapconcat #'identity
+                                                  (delq nil (list ignored options "%s"))
+                                                  " ")
+                                       "%s" "%s"))
+         (with-types (member current-prefix-arg '((16) (64))))
+         (current-prefix-arg nil)
+         (helm-projectile--ag-input input))
+    (helm-grep-ag directory with-types)))
+
+;;;###autoload
+(defun helm-projectile-ag (&optional options)
+  "Helm version of `projectile-ag'.
+When called with a single or a triple prefix argument, ask for OPTIONS.
+When called with a double or a triple prefix argument, ask for
+TYPES (see `helm-grep-ag').'
+
+This command uses `helm-grep-ag' to perform the search, so the actual
+searcher used is determined by the value of `helm-grep-ag-command'."
+  (interactive (if (member current-prefix-arg '((4) (64)))
+                   (list (helm-read-string "option: " ""
+                                           'helm-ag--extra-options-history))))
+  (if (projectile-project-p)
+      (helm-projectile--ag-1 (projectile-project-root)
+                             (helm-projectile--ag--region-selection)
+                             options)
+    (error "You're not in a project")))
+
+(defun helm-projectile--switch-project-and-ag-action (directory)
+  "Switch to a project containing DIRECTORY then run ag in the DIRECTORY."
+  (if (and (file-directory-p directory)
+           (projectile-project-p directory))
+      (let* ((input (helm-projectile--ag--region-selection))
+             (projectile-switch-project-action
+              (lambda ()
+                (helm-projectile--ag-1 (file-truename directory) input))))
+        (projectile-switch-project-by-name (projectile-project-root directory)))
+    (error (if (file-directory-p directory)
+               (format "Directory %s is not in any project!" directory)
+             (format "Not a directory %s" directory)))))
+
+;; Declare/define these to satisfy the byte compiler
+(defvar helm-rg-prepend-file-name-line-at-top-of-matches)
+(defvar helm-rg-include-file-on-every-match-line)
+(defvar helm-rg-default-directory)
+(defvar helm-rg--extra-args)
+(declare-function helm-rg "ext:helm-rg")
+(declare-function helm-rg--get-thing-at-pt "ext:helm-rg")
+
+(defcustom helm-projectile-ask-to-install-helm-rg t
+  "Whether to ask user to install `helm-rg' when searching with ripgrep (rg).
+The question is presented to user when the `helm-grep-ag-command' is not
+pointing to ripgrep (rg) executable and the package `helm-rg' is not
+installed."
+  :type 'boolean
+  :group 'helm-projectile)
+
+(defun helm-projectile-rg--region-selection ()
+  "Return a default input for `helm-rg'."
+  (when helm-projectile-set-input-automatically
+    (if (region-active-p)
+        (buffer-substring-no-properties (region-beginning) (region-end))
+      (helm-rg--get-thing-at-pt))))
+
+(defmacro helm-projectile--with-helm-rg (fallback &rest body)
+  "Execute BODY if package `helm-rg'is installed.
+Otherwise if `helm-grep-ag-command' is pointing to ripgrep (rg) call the
+FALLBACK, which is expected to be some version of `helm-projectile-ag'.
+Otherwise ask to install package`helm-rg' and execute BODY."
+  (declare (indent 1) (debug t))
+  `(cond ((require 'helm-rg nil t)
+          (progn ,@body))
+         ((equal "rg" (helm-grep--ag-command))
+          (funcall ,fallback))
+         ((and
+           helm-projectile-ask-to-install-helm-rg
+           (yes-or-no-p "`helm-rg' is not installed.  Install it? "))
+          (condition-case nil
+              (progn
+                (package-refresh-contents)
+                (package-install 'helm-rg)
+                ,@body)
+            (error "`helm-rg' is not available.  Is MELPA in your `package-archives'?")))
+         (t
+          (error "Cannot execute search with ripgrep (rg)"))))
+
+(defun helm-projectile--rg-1 (directory input)
+  "Call `helm-rg' with DIRECTORY.
+DIRECTORY is the directory to search in.  INPUT is the value of default
+input to use for the search."
+  (let* ((helm-rg-prepend-file-name-line-at-top-of-matches nil)
+         (helm-rg-include-file-on-every-match-line t)
+         (helm-rg-default-directory 'default)
+         (default-directory directory)
+         (helm-rg--extra-args
+          (if (helm-projectile--projectile-ignore-strategy)
+              (mapcan (lambda (path) (list "--glob" path))
+                      (mapcar (lambda (path)
+                                (concat "!" path))
+                              (append (helm-projectile--ignored-files)
+                                      (helm-projectile--ignored-directories))))
+            helm-rg--extra-args)))
+    (helm-rg input nil)))
+
+;;;###autoload
+(defun helm-projectile-rg ()
+  "Projectile version of `helm-rg'.
+When package `helm-rg' is not installed and `helm-grep-ag-command' is
+pointing to ripgrep (rg) then use `helm-projectile-ag'.  Otherwise if
+`helm-projectile-ask-to-install-helm-rg' is non nil then ask to install
+package `helm-rg'."
+  (interactive)
+  (helm-projectile--with-helm-rg
+      #'helm-projectile-ag
+    (if (projectile-project-p)
+        (helm-projectile--rg-1 (projectile-project-root)
+                               (helm-projectile-rg--region-selection))
+      (error "You're not in a project"))))
+
+(defun helm-projectile--switch-project-and-rg-action (directory)
+  "Switch to a project containing DIRECTORY then run rg in the DIRECTORY.
+When package `helm-rg' is not installed and `helm-grep-ag-command' is
+pointing to ripgrep (rg) then use
+`helm-projectile--switch-project-and-ag-action'.  Otherwise if
+`helm-projectile-ask-to-install-helm-rg' is non nil then ask to install
+package `helm-rg'."
+  (helm-projectile--with-helm-rg
+      (lambda ()
+        (helm-projectile--switch-project-and-ag-action directory))
+    (if (and (file-directory-p directory)
+             (projectile-project-p directory))
+        (let* ((input (helm-projectile-rg--region-selection))
+               (projectile-switch-project-action
+                (lambda ()
+                  (helm-projectile--rg-1 (file-truename directory) input))))
+          (projectile-switch-project-by-name (projectile-project-root directory)))
+      (error (if (file-directory-p directory)
+                 (format "Directory %s is not in any project!" directory)
+               (format "Not a directory %s" directory))))))
+
+(defun helm-projectile-commander-bindings ()
+  "Define Helm versions of Projectile commands in `projectile-commander'."
+  (def-projectile-commander-method ?a
+    "Run ack on project."
+    (call-interactively 'helm-projectile-ack))
+
+  (def-projectile-commander-method ?A
+    "Find ag on project."
+    (call-interactively 'helm-projectile-ag))
+
+  (def-projectile-commander-method ?f
+    "Find file in project."
+    (helm-projectile-find-file))
+
+  (def-projectile-commander-method ?b
+    "Switch to project buffer."
+    (helm-projectile-switch-to-buffer))
+
+  (def-projectile-commander-method ?d
+    "Find directory in project."
+    (helm-projectile-find-dir))
+
+  (def-projectile-commander-method ?g
+    "Run grep on project."
+    (helm-projectile-grep))
+
+  (def-projectile-commander-method ?s
+    "Switch project."
+    (helm-projectile-switch-project))
+
+  (def-projectile-commander-method ?e
+    "Find recently visited file in project."
+    (helm-projectile-recentf))
+
+  (def-projectile-commander-method ?V
+    "Find dirty projects."
+    (helm-projectile-browse-dirty-projects)))
+
+;;;###autoload
+(defun helm-projectile-toggle (toggle)
+  "Toggle Helm version of Projectile commands.
+When TOGGLE is greater than 0 turn Helm version of Projectile commands
+on.  When TOGGLE is is less or equal to 0 turn Helm version of commands
+off."
+  (if (> toggle 0)
+      (progn
+        (when (eq projectile-switch-project-action #'projectile-find-file)
+          (setq projectile-switch-project-action #'helm-projectile-find-file))
+        (define-key projectile-mode-map [remap projectile-find-other-file] #'helm-projectile-find-other-file)
+        (define-key projectile-mode-map [remap projectile-find-other-file-other-window] #'helm-projectile-find-other-file-other-window)
+        (define-key projectile-mode-map [remap projectile-find-other-file-other-frame] #'helm-projectile-find-other-file-other-frame)
+        (define-key projectile-mode-map [remap projectile-find-file] #'helm-projectile-find-file)
+        (define-key projectile-mode-map [remap projectile-find-file-other-window] #'helm-projectile-find-file-other-window)
+        (define-key projectile-mode-map [remap projectile-find-file-other-frame] #'helm-projectile-find-file-other-frame)
+        (define-key projectile-mode-map [remap projectile-find-file-in-known-projects] #'helm-projectile-find-file-in-known-projects)
+        (define-key projectile-mode-map [remap projectile-find-file-dwim] #'helm-projectile-find-file-dwim)
+        (define-key projectile-mode-map [remap projectile-find-file-dwim-other-window] #'helm-projectile-find-file-dwim-other-window)
+        (define-key projectile-mode-map [remap projectile-find-file-dwim-other-frame] #'helm-projectile-find-file-dwim-other-frame)
+        (define-key projectile-mode-map [remap projectile-find-dir] #'helm-projectile-find-dir)
+        (define-key projectile-mode-map [remap projectile-find-dir-other-window] #'helm-projectile-find-dir-other-window)
+        (define-key projectile-mode-map [remap projectile-find-dir-other-frame] #'helm-projectile-find-dir-other-frame)
+        (define-key projectile-mode-map [remap projectile-switch-project] #'helm-projectile-switch-project)
+        ;; At the time of writing projectile didn't have neither
+        ;; `projectile-switch-to-project-other-window' nor
+        ;; `projectile-switch-to-project-other-frame' (hopefully these will be
+        ;; names should they be added).  Adding `helm-projectile' bindings in a
+        ;; - hopefully - backward compatible way, by setting up keys in
+        ;; `projectile-command-map'.
+        (if (where-is-internal 'projectile-switch-project-other-window projectile-mode-map nil t t)
+            (define-key projectile-mode-map [remap projectile-switch-project-other-window] #'helm-projectile-switch-project-other-window)
+          (define-key projectile-command-map (kbd "4 p") #'helm-projectile-switch-project-other-window))
+        (if (where-is-internal 'projectile-switch-project-other-frame projectile-mode-map nil t t)
+            (define-key projectile-mode-map [remap projectile-switch-project-other-frame] #'helm-projectile-switch-project-other-frame)
+          (define-key projectile-command-map (kbd "5 p") #'helm-projectile-switch-project-other-frame))
+        (define-key projectile-mode-map [remap projectile-recentf] #'helm-projectile-recentf)
+        (define-key projectile-mode-map [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer)
+        (define-key projectile-mode-map [remap projectile-switch-to-buffer-other-window] #'helm-projectile-switch-to-buffer-other-window)
+        (define-key projectile-mode-map [remap projectile-switch-to-buffer-other-frame] #'helm-projectile-switch-to-buffer-other-frame)
+        (define-key projectile-mode-map [remap projectile-grep] #'helm-projectile-grep)
+        (define-key projectile-mode-map [remap projectile-ack] #'helm-projectile-ack)
+        (define-key projectile-mode-map [remap projectile-ag] #'helm-projectile-ag)
+        (define-key projectile-mode-map [remap projectile-ripgrep] #'helm-projectile-rg)
+        (define-key projectile-mode-map [remap projectile-browse-dirty-projects] #'helm-projectile-browse-dirty-projects)
+        (helm-projectile-commander-bindings))
+    (progn
+      (when (eq projectile-switch-project-action #'helm-projectile-find-file)
+        (setq projectile-switch-project-action #'projectile-find-file))
+      (define-key projectile-mode-map [remap projectile-find-other-file] nil)
+      (define-key projectile-mode-map [remap projectile-find-other-file-other-window] nil)
+      (define-key projectile-mode-map [remap projectile-find-other-file-other-frame] nil)
+      (define-key projectile-mode-map [remap projectile-find-file] nil)
+      (define-key projectile-mode-map [remap projectile-find-file-other-window] nil)
+      (define-key projectile-mode-map [remap projectile-find-file-other-frame] nil)
+      (define-key projectile-mode-map [remap projectile-find-file-in-known-projects] nil)
+      (define-key projectile-mode-map [remap projectile-find-file-dwim] nil)
+      (define-key projectile-mode-map [remap projectile-find-file-dwim-other-window] nil)
+      (define-key projectile-mode-map [remap projectile-find-file-dwim-other-frame] nil)
+      (define-key projectile-mode-map [remap projectile-find-dir] nil)
+      (define-key projectile-mode-map [remap projectile-find-dir-other-window] nil)
+      (define-key projectile-mode-map [remap projectile-find-dir-other-frame] nil)
+      (define-key projectile-mode-map [remap projectile-switch-project] nil)
+      (if (where-is-internal 'helm-projectile-switch-project-other-window projectile-command-map nil t t)
+          (define-key projectile-mode-map (kbd "4 p") nil)
+        (define-key projectile-mode-map [remap projectile-switch-project-other-window] nil))
+      (if (where-is-internal 'helm-projectile-switch-project-other-frame projectile-command-map nil t t)
+          (define-key projectile-mode-map (kbd "5 p") nil)
+        (define-key projectile-mode-map [remap projectile-switch-project-other-frame] nil))
+      (define-key projectile-mode-map [remap projectile-recentf] nil)
+      (define-key projectile-mode-map [remap projectile-switch-to-buffer] nil)
+      (define-key projectile-mode-map [remap projectile-switch-to-buffer-other-window] nil)
+      (define-key projectile-mode-map [remap projectile-switch-to-buffer-other-frame] nil)
+      (define-key projectile-mode-map [remap projectile-grep] nil)
+      (define-key projectile-mode-map [remap projectile-ag] nil)
+      (define-key projectile-mode-map [remap projectile-ripgrep] nil)
+      (define-key projectile-mode-map [remap projectile-browse-dirty-projects] nil)
+      (projectile-commander-bindings))))
+
+;;;###autoload
+(defun helm-projectile (&optional arg)
+  "Use projectile with Helm instead of ido.
+
+With a prefix ARG invalidates the cache first.
+If invoked outside of a project, displays a list of known projects to jump."
+  (interactive "P")
+  (if (not (projectile-project-p))
+      (helm-projectile-switch-project arg)
+    (projectile-maybe-invalidate-cache arg)
+    (let ((helm-ff-transformer-show-only-basename nil))
+      (helm :sources helm-projectile-sources-list
+            :buffer "*helm projectile*"
+            :truncate-lines helm-projectile-truncate-lines
+            :prompt (projectile-prepend-project-name (if (projectile-project-p)
+                                                         "pattern: "
+                                                       "Switch to project: "))))))
+
+;;;###autoload
+(eval-after-load 'projectile
+  '(progn
+     (define-key projectile-command-map (kbd "h") #'helm-projectile)))
+
+(provide 'helm-projectile)
+
+;;; helm-projectile.el ends here