branch: elpa/nix-mode
commit 53d1fb96875a25fd43e1543000da991c08f4d290
Author: Akira Komamura <[email protected]>
Commit: Akira Komamura <[email protected]>
nix-flake: Add nix-flake-init
---
nix-flake.el | 81 +++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 64 insertions(+), 17 deletions(-)
diff --git a/nix-flake.el b/nix-flake.el
index ca16c75709..475d53a4df 100644
--- a/nix-flake.el
+++ b/nix-flake.el
@@ -11,6 +11,32 @@
(require 'nix)
(require 'transient)
+;;;; Transient classes
+
+;;;;; flake-ref
+
+(defclass nix-flake-ref-variable (transient-variable)
+ ((variable :initarg :variable)
+ (constant-value :initarg :constant-value :initform nil)))
+
+(cl-defmethod transient-init-value ((obj nix-flake-ref-variable))
+ (unless (oref obj value)
+ (oset obj value (eval (oref obj variable)))))
+
+(cl-defmethod transient-infix-read ((obj nix-flake-ref-variable))
+ (if-let (value (oref obj constant-value))
+ (if (symbolp value)
+ (symbol-value value)
+ value)
+ (nix-flake--select-flake nil (oref obj value))))
+
+(cl-defmethod transient-infix-set ((obj nix-flake-ref-variable) value)
+ (oset obj value value)
+ (set (oref obj variable) value))
+
+(cl-defmethod transient-format-value ((obj nix-flake-ref-variable))
+ "")
+
;;;; Utility functions
(defun nix-flake--to-list (x)
@@ -31,14 +57,17 @@
(thread-last (nix--process-lines "registry" "list")
(mapcar #'split-entry))))
-(defun nix-flake--select-flake ()
+;; This argument complies the standard reader interface of transient
+;; just in case, but it may not be necessary.
+(defun nix-flake--select-flake (&optional prompt initial-input history)
"Select a flake from the registry."
- (completing-read "Flake URL: "
- (thread-last (nix-flake--registry-list)
- (cl-remove-if-not (pcase-lambda (`(,type . ,_))
+ (completing-read (or prompt "Flake URL: ")
+ (thread-last (nix-flake--registry-list)
+ (cl-remove-if-not (pcase-lambda (`(,type . ,_))
(member type '("user" "global"))))
- (mapcar (pcase-lambda (`(,_ ,_ ,ref))
- ref)))))
+ (mapcar (pcase-lambda (`(,_ ,_ ,ref))
+ ref)))
+ nil nil nil history initial-input))
;;;; nix-flake command
@@ -306,8 +335,7 @@ whatever supported by Nix."
(nix-flake--command '("flake" "lock") nil
(nix-flake--directory-ref dir))))
(t
- ;; TODO: Let the user run 'nix flake init' to create flake.nix
- (user-error "The directory does not contain flake.nix"))))
+ (nix-flake-init-dispatch))))
(defun nix-flake--directory-ref (dir)
"Return the flake ref for a local DIR."
@@ -315,18 +343,26 @@ whatever supported by Nix."
;;;; nix flake init
+;;;;; Setting the template repository
+
(defvar nix-flake-template-repository nil)
(defun nix-flake--init-source ()
"Describe the current template repository for init command."
(format "Template repository: %s" nix-flake-template-repository))
-(defun nix-flake--templates (flake-ref)
- "Return a list of templates in FLAKE-REF."
- (thread-last (nix--process-json "flake" "show" "--json" flake-ref)
- (alist-get 'templates)
- (mapcar #'car)
- (mapcar #'symbol-name)))
+(transient-define-infix nix-flake-init:from-registry ()
+ :class 'nix-flake-ref-variable
+ :variable 'nix-flake-template-repository
+ :description "Select from the registry")
+
+(transient-define-infix nix-flake-init:default-templates ()
+ :class 'nix-flake-ref-variable
+ :variable 'nix-flake-template-repository
+ :constant-value "flake:templates"
+ :description "Use the default template set")
+
+;;;;; Running the command
(defun nix-flake--init (flake-ref template-name)
"Initialize a flake from a template.
@@ -341,6 +377,15 @@ template, TEMPLATE-NAME is the name of the template."
,(concat flake-ref "#" template-name))
" ")))
+;;;;; Selecting a template
+
+(defun nix-flake--templates (flake-ref)
+ "Return a list of templates in FLAKE-REF."
+ (thread-last (nix--process-json "flake" "show" "--json" flake-ref)
+ (alist-get 'templates)
+ (mapcar #'car)
+ (mapcar #'symbol-name)))
+
;; It might be better to use `transient-define-suffix', but I don't know for
;; sure.
(defun nix-flake-init-select-template ()
@@ -353,13 +398,16 @@ template, TEMPLATE-NAME is the name of the template."
(nix-flake--templates flake-ref))))
(nix-flake--init flake-ref template-name)))
+;;;;; The transient interface
+
;;;###autoload (autoload 'nix-flake-init "nix-flake" nil t)
(transient-define-prefix nix-flake-init-dispatch (&optional flake-ref)
"Scaffold a project from a template."
[:description "Initialize a flake"]
[:description
nix-flake--init-source
- ("r" nix-flake-init--from-registry)]
+ ("r" nix-flake-init:from-registry)
+ ("d" nix-flake-init:default-templates)]
["Initialize a flake"
("t" "Select template" nix-flake-init-select-template)]
(interactive (list nil))
@@ -371,8 +419,7 @@ template, TEMPLATE-NAME is the name of the template."
(defun nix-flake-init ()
"Run \"nix flake init\" command via a transient interface."
(interactive)
- (let* ((root (ignore-errors
- (vc-root-dir)))
+ (let* ((root (locate-dominating-file default-directory ".git"))
(default-directory
(if (and root
(not (file-equal-p root default-directory))