First commit.
This commit is contained in:
133
lisp/utilities/project.el
Normal file
133
lisp/utilities/project.el
Normal file
@@ -0,0 +1,133 @@
|
||||
;;; project.el --- helpers for working with projects -*- lexical-binding: t; -*-
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
|
||||
(with-eval-after-load 'eieio
|
||||
(defclass user/proj ()
|
||||
()
|
||||
"Project class.")
|
||||
|
||||
(cl-defgeneric user/proj-name ((project user/proj))
|
||||
"Get the PROJECT name.")
|
||||
|
||||
(cl-defgeneric user/proj-root ((project user/proj))
|
||||
"Get the PROJECT root path.")
|
||||
|
||||
(cl-defgeneric user/proj-include-paths ((project user/proj))
|
||||
"Get the include paths for PROJECT.")
|
||||
|
||||
(cl-defgeneric user/proj-build ((project user/proj))
|
||||
"Build PROJECT.")
|
||||
|
||||
(cl-defmethod user/proj-name ((project user/proj))
|
||||
(file-name-nondirectory
|
||||
(directory-file-name (user/proj-root project))))
|
||||
|
||||
(cl-defmethod user/proj-include-paths ((project user/proj)))
|
||||
|
||||
(with-eval-after-load 'ede
|
||||
(defclass user/ede-proj (user/proj)
|
||||
((ede :initarg :ede :initform nil
|
||||
:documentation "EDE project instance."))
|
||||
"EDE project class.")
|
||||
|
||||
(cl-defmethod user/proj-from-path :static ((project user/ede-proj) &rest args)
|
||||
"Constructor for EDE project at path in ARGS."
|
||||
(when (featurep 'ede)
|
||||
(let ((ede-proj (ede-current-project (expand-file-name (first args)))))
|
||||
(when (cl-some (lambda (args)
|
||||
(and (featurep (first args))
|
||||
(funcall (second args) ede-proj)))
|
||||
'((ede/cpp-root ede-cpp-root-project-p)
|
||||
(ede/generic ede-generic-makefile-project-p)
|
||||
(ede/generic ede-generic-cmake-project-p)
|
||||
(ede/linux ede-linux-project-p)
|
||||
(ede/compdb ede-compdb-project-p)))
|
||||
(make-instance 'user/ede-proj :ede ede-proj)))))
|
||||
|
||||
(cl-defmethod user/proj-name ((project user/ede-proj))
|
||||
(ede-name (oref project :ede)))
|
||||
|
||||
(cl-defmethod user/proj-root ((project user/ede-proj))
|
||||
(ede-project-root-directory (oref project :ede)))
|
||||
|
||||
(cl-defmethod user/proj-include-paths ((project user/ede-proj))
|
||||
(let ((root-path (user/proj-root project))
|
||||
(include-paths (oref (oref project :ede) include-path)))
|
||||
(mapcar #'(lambda (path) (expand-file-name path root-path))
|
||||
include-paths)))
|
||||
|
||||
(cl-defmethod user/proj-build ((project user/ede-proj))
|
||||
(let ((ede-proj (oref project :ede)))
|
||||
(project-compile-project
|
||||
ede-proj
|
||||
(read-string "Build command: " (oref ede-proj compile-command))))))
|
||||
|
||||
(with-eval-after-load 'projectile
|
||||
(defclass user/projectile-proj (user/proj)
|
||||
((root-path :initarg :root-path
|
||||
:type string
|
||||
:documentation "Project root path."))
|
||||
"Projectile project class.")
|
||||
|
||||
(cl-defmethod user/proj-from-path :static ((project user/projectile-proj) &rest args)
|
||||
"Constructor for projectile project at path in ARGS."
|
||||
(let ((default-directory (file-name-as-directory (first args)))
|
||||
(projectile-require-project-root nil))
|
||||
(when (and (feature-p 'projectile) (projectile-project-p))
|
||||
(make-instance 'user/projectile-proj :root-path (projectile-project-root)))))
|
||||
|
||||
(cl-defmethod user/proj-root ((project user/projectile-proj))
|
||||
(oref project :root-path)))
|
||||
|
||||
(with-eval-after-load 'vc
|
||||
(defclass user/vc-proj (user/proj)
|
||||
((root-path :initarg :root-path
|
||||
:type string
|
||||
:documentation "Project root path."))
|
||||
"VC project class.")
|
||||
|
||||
(cl-defmethod user/proj-from-path :static ((project user/vc-proj) &rest args)
|
||||
"Constructor for VC project at path in ARGS."
|
||||
(let* ((vc-backend (and (fboundp 'vc-responsible-backend)
|
||||
(ignore-errors
|
||||
(vc-responsible-backend
|
||||
(file-truename (first args))))))
|
||||
(root-path (and vc-backend
|
||||
(vc-call-backend
|
||||
vc-backend 'root (file-truename (first args))))))
|
||||
(when root-path
|
||||
(make-instance 'user/vc-proj :root-path root-path))))
|
||||
|
||||
(cl-defmethod user/proj-root ((project user/vc-proj))
|
||||
(oref project :root-path)))
|
||||
|
||||
(cl-defmethod user/proj-from-path :static ((project user/proj) &rest args)
|
||||
"Constructor for project at path in ARGS."
|
||||
(let ((f (lambda (proj-type)
|
||||
(when (fboundp proj-type)
|
||||
(funcall #'user/proj-from-path proj-type (first args)))))
|
||||
(proj-types '(user/ede-proj user/projectile-proj user/vc-proj)))
|
||||
(cl-some f proj-types))))
|
||||
|
||||
|
||||
(defmacro with-project (project &optional path &rest body)
|
||||
"Bind PROJECT for PATH and evaluate BODY if project exists."
|
||||
(declare (indent defun)
|
||||
(debug let))
|
||||
`(let ((,project (user/proj-from-path user/proj (or ,path (path-abs-buffer)))))
|
||||
(when ,project
|
||||
,@body)))
|
||||
|
||||
|
||||
(defmacro with-project-root (project-root &optional path &rest body)
|
||||
"Bind PROJECT-ROOT for PATH and evaluate BODY if project exists."
|
||||
(declare (indent defun)
|
||||
(debug let))
|
||||
`(with-project project (or ,path (path-abs-buffer))
|
||||
(let ((,project-root (user/proj-root project)))
|
||||
,@body)))
|
||||
|
||||
|
||||
(provide 'utilities/project)
|
||||
;;; project.el ends here
|
Reference in New Issue
Block a user