Álvaro Ramírez
Projectile shell dir company completion
Projectile and company are just amazing Emacs packages. Projectile gives random access to files, while company completes well… anything. For shells, Emacs has a handful of options.
Standing on the shoulders of package giants (dash and f included) and some elisp, we can bring random access to project directories from the shell.
(require 'cl-lib) (require 'company) (require 'dash) (require 'f) (require 'projectile) (defvar-local company-projectile-cd-prefix "cd ") (defun company-projectile-cd (command &optional arg &rest ignored) "Company shell completion for any projectile path." (interactive (list 'interactive)) (case command (interactive (company-begin-backend 'company-projectile-cd)) (prefix (company-grab-symbol-cons company-projectile-cd-prefix (length company-projectile-cd-prefix))) (candidates (company-projectile-cd--candidates (company-grab-symbol-cons company-projectile-cd-prefix (length company-projectile-cd-prefix)))) (post-completion (company-projectile-cd--expand-inserted-path arg)))) (defun company-projectile-cd--candidates (input) "Return candidates for given INPUT." (company-projectile-cd--reset-root) (when (consp input) (let ((search-term (substring-no-properties (car input) 0 (length (car input)))) (prefix-found (cdr input))) (when prefix-found (if (projectile-project-p) (company-projectile-cd--projectile search-term) (company-projectile-cd--find-fallback search-term)))))) (defun company-projectile-cd--projectile (search-term) (-filter (lambda (path) (string-match-p (regexp-quote search-term) path)) (-snoc (projectile-current-project-dirs) ;; Throw project root in there also. (projectile-project-root)))) (defun company-projectile-cd--find-fallback (search-term) (ignore-errors (-map (lambda (path) (string-remove-prefix "./" path)) (apply #'process-lines (list "find" "." "-type" "d" "-maxdepth" "2" "-iname" (format "\*%s\*" search-term)))))) (defun company-projectile-cd--expand-inserted-path (path) "Replace relative PATH insertion with its absolute equivalent if needed." (unless (f-exists-p path) (delete-region (point) (- (point) (length path))) (insert (concat (projectile-project-root) path)))) (defun company-projectile-cd--reset-root () "Reset project root. Useful when cd'ing in and out of projects." (projectile-reset-cached-project-root) (when (projectile-project-p) (projectile-project-root)))