aboutsummaryrefslogtreecommitdiff
path: root/emacs/.emacs.d/lisp/my/my-project.el
blob: 21a05f18de0029287b2ba902a8fcc4c87e342620 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
;;; my-project.el -- Project related extensions for emacs core -*- lexical-binding: t -*-

;; Copyright (C) 2023 Free Software Foundation.

;; Author: Yuchen Pei <id@ypei.org>
;; Package-Requires: ((emacs "28.2"))

;; This file is part of dotfiles.

;; dotfiles is free software: you can redistribute it and/or modify it under
;; the terms of the GNU Affero General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; dotfiles 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 Affero General
;; Public License for more details.

;; You should have received a copy of the GNU Affero General Public
;; License along with dotfiles.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Project related extensions for emacs core.

;;; Code:



(defvar my-projects-root-dirs nil
  "List of directories to look for projects. Each element in the form
  of (tag . path). One of the tags should be \"3p\" which is a default
  target for cloning a project")
(defun my-get-list-of-projects ()
  (flatten-list
   (mapcar (lambda (pair)
             (mapcar
              (lambda (dir-name) (format "%s(%s)" dir-name (car pair)))
              (directory-files
               (cdr pair) nil directory-files-no-dot-files-regexp)))
           my-projects-root-dirs)))

(defun my-project-guess-project-name ()
  (file-name-nondirectory (directory-file-name
                           (project-root (project-current)))))

(defvar my-licenses nil
  "List of licenses in the form of (licence-id . license-text-file)")

(defun my-project-copy-license-file-to-project (license)
  (interactive (list (completing-read "License to copy to project root: "
                                      (mapcar 'car my-licenses))))
  (let ((from (alist-get (intern license) my-licenses))
        (to (concat (project-root (project-current))
                    "COPYING." license)))
    (copy-file from to)
    (message "Copied license of %s to %s" license to)))

(defun my-project-remember-all-projects ()
  "Remember all projects under `my-projects-root-dirs'."
  (pcase-dolist (`(_ . ,dir) my-projects-root-dirs)
    (project-remember-projects-under dir)))
;; FIXME: do we really need this or does the project package already
;; do so?
(defun my-project-read-project ()
  (let ((key-val
         (completing-read "Choose projects: "
                          (my-get-list-of-projects) nil t)))
    (string-match "^\\(.*\\)(\\(.*\\))$" key-val)
    (cons (match-string 2 key-val) (match-string 1 key-val))))
(defun my-project-get-project-directory (pair)
  (concat 
   (alist-get (car pair) my-projects-root-dirs nil nil 'string=)
   "/" (cdr pair)))
(defun my-project-read-project-root ()
  (my-project-get-project-directory (my-project-read-project)))
(defun my-project-shell-at (arg)
  (interactive "P")
  (if arg (project-shell)
    (my-shell-with-directory (my-project-read-project-root))))
(defun my-project-dired-at (arg)
  (interactive "P")
  (if arg (project-dired)
    (dired (my-project-read-project-root))))
(defun my-project-rgrep-at (arg)
  (interactive "P")
  (if arg (project-query-replace-regexp)
    (my-rgrep-at-directory (my-project-read-project-root))))
(defun my-project-org-set-local-source ()
  (interactive)
  (org-set-property "Local-source" (my-project-read-project-root)))
(defun my-project-code-stats ()
  (interactive)
  (switch-to-buffer-other-window (get-buffer-create "*cloc*"))
  (erase-buffer)
  (my-with-default-directory (my-project-read-project-root)
    (message default-directory)
    (insert default-directory "\n")
    (call-process "cloc" nil "*cloc*" nil "HEAD" "--quiet")))


(provide 'my-project)
;;; my-project.el ends here