;; -*- lexical-binding: t -*- ;; Copyright © 2018-2024 Uko Koknevics ;; TODO: See about porting this to project.el: ;; (define-key map (kbd "a") #'projectile-find-other-file) ;; (define-key map (kbd "E") #'projectile-edit-dir-locals) ;; (define-key map (kbd "g") #'projectile-find-file-dwim) ;; (define-key map (kbd "i") #'projectile-invalidate-cache) ;; (define-key map (kbd "I") #'projectile-ibuffer) ;; (define-key map (kbd "j") #'projectile-find-tag) ;; (define-key map (kbd "l") #'projectile-find-file-in-directory) ;; (define-key map (kbd "m") #'projectile-commander) ;; (define-key map (kbd "o") #'projectile-multi-occur) ;; (define-key map (kbd "q") #'projectile-switch-open-project) ;; (define-key map (kbd "R") #'projectile-regenerate-tags) ;; (define-key map (kbd "s r") #'projectile-ripgrep) ;; (define-key map (kbd "s s") #'projectile-ag) ;; (define-key map (kbd "S") #'projectile-save-project-buffers) ;; (define-key map (kbd "t") #'projectile-toggle-between-implementation-and-test) ;; (define-key map (kbd "T") #'projectile-find-test-file) ;; ;; project lifecycle external commands ;; ;; TODO: Bundle those under some prefix key ;; (define-key map (kbd "C") #'projectile-configure-project) ;; (define-key map (kbd "K") #'projectile-package-project) ;; (define-key map (kbd "L") #'projectile-install-project) ;; (define-key map (kbd "P") #'projectile-test-project) ;; (define-key map (kbd "u") #'projectile-run-project) ;; ;; integration with utilities ;; (define-key map (kbd "x i") #'projectile-run-ielm) ;; (define-key map (kbd "x t") #'projectile-run-term) ;; (define-key map (kbd "x g") #'projectile-run-gdb) ;; (define-key map (kbd "x v") #'projectile-run-vterm) ;; (define-key map (kbd "x 4 v") #'projectile-run-vterm-other-window) ;; ;; misc ;; (define-key map (kbd "z") #'projectile-cache-current-file) ;; (define-key map (kbd "") #'projectile-previous-project-buffer) ;; (define-key map (kbd "") #'projectile-next-project-buffer) ;; (define-key map (kbd "ESC") #'projectile-project-buffers-other-buffer) (cl-defun arkta/project-completing-read (prompt choices &key initial-input action (project (project-current t))) "Present a project tailored PROMPT with CHOICES." (require 'ivy) (let ((prompt (arkta/project-prepend-project-name prompt project))) (ivy-read prompt choices :initial-input initial-input :action action :caller 'arkta/project-completing-read))) (defun arkta/project-expand-root (name &optional project) "Expand NAME to project root." (let (project (or project (project-current t))) (expand-file-name name (project-root project)))) (defun arkta/project-find-references (&optional symbol) "Find all references to SYMBOL in the current project. A thin wrapper around `xref-references-in-directory'." (interactive) (require 'xref) (let ((project-root (project-root (project-current t))) (symbol (or symbol (read-from-minibuffer "Lookup in project: " (arkta/symbol-at-point))))) (xref-show-xrefs (xref-references-in-directory symbol project-root) nil))) (defun arkta/project-magit-status () (interactive) (magit-status (project-root (project-current t)))) (defun arkta/project-prepend-project-name (string &optional project) "Prepend the current project's name to STRING." (let ((project (or project (project-current t)))) (format "[%s] %s" (project-name project) string))) (defun arkta/project-recentf () "Show a list of recently visited files in a project." (interactive) (let ((project (project-current t))) (find-file (arkta/project-expand-root (arkta/project-completing-read "Recently visited files: " (arkta/project-recentf-files project) :project project) project)))) (defun arkta/project-recentf-files (&optional project) "Return a list of recently visited files in a project." (require 'recentf) (let* ((project (or project (project-current t))) (project-root (expand-file-name (project-root project)))) (mapcar (lambda (f) (file-relative-name f project-root)) (cl-remove-if-not (lambda (f) (string-prefix-p project-root (expand-file-name f))) recentf-list)))) (defun arkta/symbol-at-point () "Get the symbol at point and strip its properties." (substring-no-properties (or (thing-at-point 'symbol) ""))) (use-package project :straight '(project :type built-in) :config (defvar-keymap arkta/project-prefix-map :parent project-prefix-map "C-b" 'project-list-buffers "!" 'project-shell-command "&" 'project-async-shell-command "4" 'project-other-window-command "5" 'project-other-frame-command "D" 'project-dired "F" 'project-or-external-find-file "V" 'project-vc-dir "b" 'project-switch-to-buffer "c" 'project-compile "d" 'project-find-dir "e" 'arkta/project-recentf "f" 'project-find-file "k" 'project-kill-buffers "p" 'project-switch-project "r" 'project-query-replace-regexp "v" 'arkta/project-magit-status "M-x" 'project-execute-extended-command "s g" 'project-find-regexp "s r" 'project-find-regexp "s x" 'arkta/project-find-references "x e" 'project-eshell "x s" 'project-shell) (fset 'arkta/project-prefix-map arkta/project-prefix-map) :bind (("C-c p" . arkta/project-prefix-map))) (provide 'arkta-project)