You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.5 KiB
93 lines
3.5 KiB
(defun rlbr/get-venv-name (&optional library-root)
|
|
"Generate venv name based off of the base-name of the library root"
|
|
(file-name-base
|
|
(directory-file-name
|
|
(if library-root
|
|
library-root
|
|
(elpy-library-root)))))
|
|
|
|
(defun rlbr/handle-name-conflicts (venv-name)
|
|
"Deal with potential name conflicts in venv"
|
|
(let ((venv-conflicts)
|
|
(venv-partition-name))
|
|
(setq venv-partition-name (rlbr/split-venv-with-number venv-name))
|
|
(setq venv-conflicts
|
|
(seq-filter
|
|
(lambda (item) (string-equal (cdr item) venv-name))
|
|
(mapcar #'rlbr/split-venv-with-number (pyvenv-virtualenv-list))))
|
|
(when venv-conflicts
|
|
(setcar venv-partition-name (1+ (apply 'max (mapcar #'car venv-conflicts)))))
|
|
(rlbr/join-venv-with-number venv-partition-name)))
|
|
|
|
;; We'll save using file-precious-flag, so avoid destroying
|
|
;; symlinks. (If we're not already visiting the buffer, this is
|
|
;; handled by find-file-visit-truename, above.)
|
|
(defun rlbr/save-buffer-func-to-file (visit-file func args)
|
|
"Rip off of custom-save-all"
|
|
(let* ((filename visit-file)
|
|
(recentf-exclude (if recentf-mode
|
|
(append
|
|
`(,(concat "\\`" (regexp-quote (recentf-expand-file-name visit-file)) "\\'")
|
|
,(concat "\\`" (regexp-quote (file-truename (recentf-expand-file-name visit-file))) "\\'"))
|
|
recentf-exclude)))
|
|
(old-buffer (find-buffer-visiting filename))
|
|
old-buffer-name)
|
|
(with-current-buffer
|
|
(let ((find-file-visit-truename t))
|
|
(or old-buffer
|
|
(let ((delay-mode-hooks t))
|
|
(find-file-noselect filename))))
|
|
(when old-buffer
|
|
(setq old-buffer-name
|
|
(buffer-file-name))
|
|
(set-visited-file-name
|
|
(file-chase-links filename)))
|
|
(unless (eq major-mode
|
|
'emacs-lisp-mode)
|
|
(delay-mode-hooks
|
|
(emacs-lisp-mode)))
|
|
(let ((inhibit-read-only t)
|
|
(print-length nil)
|
|
(print-level nil))
|
|
(apply func args))
|
|
(let ((file-precious-flag t))
|
|
(save-buffer))
|
|
(if old-buffer
|
|
(progn
|
|
(set-visited-file-name
|
|
old-buffer-name)
|
|
(set-buffer-modified-p nil))
|
|
(kill-buffer (current-buffer))))))
|
|
|
|
(defun rlbr/setup-python-venv-dirlocals (&optional library-root)
|
|
"Setup .dir-locals file in library root and tell vc system to ignore .dir-locals file"
|
|
(let* ((library-root (if library-root
|
|
library-root
|
|
(elpy-library-root)))
|
|
(default-directory library-root)
|
|
(dir-locals-path (expand-file-name
|
|
".dir-locals.el"))
|
|
(venv-name (rlbr/get-venv-name
|
|
library-root)))
|
|
(rlbr/save-buffer-func-to-file dir-locals-path 'add-dir-local-variable
|
|
`(python-mode pyvenv-workon ,venv-name))
|
|
(let* ((vc-root (vc-find-root dir-locals-path ".git"))
|
|
(vc-ignore-file (vc-call-backend 'Git 'find-ignore-file vc-root)))
|
|
(if (apply 'string-equal (mapcar 'directory-file-name (mapcar 'file-truename (list vc-root library-root))))
|
|
(progn
|
|
(unless (file-exists-p vc-ignore-file)
|
|
(with-temp-buffer
|
|
(write-file vc-ignore-file)))
|
|
(vc-ignore ".dir-locals.el"))
|
|
(when (y-or-n-p (format "Ignore .dir-locals.el in repo '%s' ?" vc-root))
|
|
(unless (file-exists-p vc-ignore-file)
|
|
(with-temp-buffer
|
|
(write-file vc-ignore-file)))
|
|
(vc-ignore ".dir-locals.el"))))))
|
|
|
|
(defun rlbr/init-python-venv-in-library-root (&optional library-root)
|
|
"If no venv is specified in the library root .dir-locals file, prompt to either create one or use default"
|
|
(let ((venv-name (rlbr/get-venv-name)))
|
|
(setq venv-name (rlbr/handle-name-conflicts venv-name))
|
|
(if (y-or-n-p (format "Create venv '%'?" venv-name))
|
|
(pyvenv-create venv-name python-command))))
|