;;; -*- lexical-binding: t; -*- (require 'syd/base) (require 'syd/keymaps) (require 'syd/completion) ; For `consult'. (require 'consult) (defun syd-project-root-find-file (file-name) "Just like `project-root-find-file', but allowing you to select the root directory itself." (declare (interactive-only find-file)) (interactive (list (let ((root (project-root (project-current t)))) (read-file-name "Find file in root: " root root (confirm-nonexistent-file-or-buffer))))) (find-file file-name t)) (defun syd-search-directory (dir) (interactive (list (read-directory-name "Search directory: " default-directory nil t))) (cond ((executable-find "rg") (consult-ripgrep dir)) ((executable-find "grep") (message "Couldn't find ripgrep; using grep") (consult-grep dir)))) (cl-defun syd-project-root (&key (dir default-directory)) "Return the project root of DIR, or nil if DIR belongs to no project." (when-let* ((project (project-current nil dir))) (project-root project))) (defun syd-project-cd () "Change the working directory to the root of the current project." (cd (syd-project-root))) (with-eval-after-load 'project ; Built-in ;; Stay out of my config directory! (setq project-list-file (file-name-concat syd-cache-dir "known-projects")) ;; For each command in `project-switch-commands' will assign it the key found ;; in `project-prefix-map'. We emulate that behaviour but for our own ;; `syd-leader-project-map'. (let* ((project-key (lambda (f) (key-description (where-is-internal f ;; If the keymap is not wrapped in a list, ;; `where-is-internal' will also search the ;; global ;; keymaps (list syd-leader-project-map) ;; First result only. t)))) (switch-cmd (lambda (command name &optional key) (append (list command name) (list (or key (funcall project-key command))))))) (add-to-list 'project-switch-commands (funcall switch-cmd #'syd-project-root-find-file "Browse")))) (defun syd-project-search () (interactive) ;; TODO: Prompt for path project root is not found. ;; TODO: Respect gitignore. (syd-search-directory (syd-project-root))) (general-def :prefix-map 'syd-leader-map "/" `("Search project" . ,#'syd-project-search)) ;; Projection provides a Projectile-like project management library atop ;; Emacs built-in project.el. It's more lightweight, while still featureful. (use-package projection :straight (:type git :host github :repo "msyds/projection" :files (:defaults "src/*.el")) ;; Enable the `projection-hook' feature. :hook (after-init . global-projection-hook-mode) :general (:keymaps 'syd-leader-project-map "R" #'projection-commands-run-project "M" #'projection-multi-compile "T" #'projection-commands-test-project)) ;; Allow interactively selecting available compilation targets from the ;; current project type. (use-package projection-multi :straight (:type git :host github :repo "msyds/projection" :files ("src/projection-multi/*.el")) :general (:keymaps 'syd-leader-project-map "M" #'projection-multi-compile) :after projection) (provide 'syd/project)