[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/nix-mode f968cb98ef 097/500: Add nix-buffer.
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/nix-mode f968cb98ef 097/500: Add nix-buffer. |
Date: |
Sat, 29 Jan 2022 08:26:40 -0500 (EST) |
branch: elpa/nix-mode
commit f968cb98ef7efa4b844a85ccea273ab14cbf1b71
Author: Matthew Bauer <mjbauer95@gmail.com>
Commit: Matthew Bauer <mjbauer95@gmail.com>
Add nix-buffer.
---
nix-buffer.el | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 227 insertions(+)
diff --git a/nix-buffer.el b/nix-buffer.el
new file mode 100644
index 0000000000..539009427c
--- /dev/null
+++ b/nix-buffer.el
@@ -0,0 +1,227 @@
+;;; nix-buffer.el --- Set up buffer environments with nix
+
+;; Copyright (C) 2016, 2017 Shea Levy
+
+;; Author: Shea Levy
+;; URL: https://github.com/shlevy/nix-buffer/tree/master/
+;; Version: 3.0.0
+;; Package-Requires: ((f "0.17.3") (emacs "24.4"))
+
+;;; Commentary:
+
+;; This package provides 'nix-buffer', to modify your buffer
+;; according to a directory-local nix expression. Think of it as
+;; nix-shell for Emacs. See the documentation for 'nix-buffer' for
+;; more details.
+
+;; It may be desirable to run 'nix-buffer' before 'normal-mode' is
+;; called so it affects all modes.
+
+;;; Code:
+
+(require 'f)
+(require 'subr-x)
+
+(defgroup nix-buffer nil "Customization for nix-buffer."
+ :prefix "nix-buffer-"
+ :group 'environment
+ :package-version '('nix-buffer . "2.3.0"))
+
+(defun nix-buffer--directory-name-setter (opt val)
+ "Defcustom setter for nix-buffer-directory-name.
+OPT The option we're setting.
+
+VAL The value it's being set to."
+ (nix-buffer-update-directory-name val))
+
+(defcustom nix-buffer-directory-name
+ (locate-user-emacs-file "nix-buffer")
+ "Path where nix-buffer keeps its data.
+To update this variable outside of Customize, please use
+'nix-buffer-update-directory-name'."
+ :group 'nix-buffer
+ :type '(directory)
+ :set 'nix-buffer--directory-name-setter
+ :initialize 'custom-initialize-default
+ :risky t)
+
+(defvar nix-buffer--trust-exprs-file
+ (f-join nix-buffer-directory-name "trusted-exprs"))
+
+(defun nix-buffer--load-trusted-exprs ()
+ "Load the trusted nix-buffer exprs."
+ (let ((tbl (ignore-errors
+ (with-temp-buffer
+ (insert-file-contents-literally
+ nix-buffer--trust-exprs-file)
+ (read (current-buffer))))))
+ (if (hash-table-p tbl)
+ tbl
+ (make-hash-table :test 'equal))))
+
+(defvar nix-buffer--trusted-exprs (nix-buffer--load-trusted-exprs))
+
+(defun nix-buffer-update-directory-name (path)
+ "Update the nix-buffer state directory.
+PATH The path to store the nix-buffer state."
+ (setq nix-buffer-directory-name path)
+ (setq nix-buffer--trust-exprs-file
+ (f-join nix-buffer-directory-name "trusted-exprs"))
+ (setq nix-buffer--trusted-exprs (nix-buffer--load-trusted-exprs)))
+
+(defun nix-buffer-unload-function ()
+ "Save state on unload."
+ (ignore-errors (make-directory nix-buffer-directory-name t))
+ (with-temp-buffer
+ (prin1 nix-buffer--trusted-exprs (current-buffer))
+ (write-region nil nil nix-buffer--trust-exprs-file))
+ nil)
+
+(defun nix-buffer--unique-filename (path)
+ "Create a unix-safe filename from an entire path.
+PATH the path to generate the name from."
+ (replace-regexp-in-string "[|\\/]"
+ (lambda (str)
+ (if (equal str "/")
+ "|"
+ (concat "\\\\" str)))
+ path))
+
+(defun nix-buffer--query-safety (expr-file lisp-file)
+ "Ask the user whether to trust a Lisp file.
+EXPR-FILE The nix expression leading to this file.
+
+LISP-FILE The file in question."
+ (let ((res (yes-or-no-p (concat expr-file
+ " resulted in unknown Lisp file "
+ lisp-file
+ "; trust it? "))))
+ (puthash lisp-file res nix-buffer--trusted-exprs)
+ res))
+
+(defvar nix-buffer-after-load-hook nil
+ "Hook run after nix-buffer loads an expression.")
+
+(defun nix-buffer--load-result (expr-file out)
+ "Load the result of a nix-buffer build, checking for safety.
+EXPR-FILE The nix expression being built.
+
+OUT The build result."
+ (when (or (gethash out nix-buffer--trusted-exprs)
+ (nix-buffer--query-safety expr-file out))
+ (load-file out)
+ (run-hooks 'nix-buffer-after-load-hook)))
+
+(defun nix-buffer--sentinel
+ (out-link last-out expr-file user-buf err-buf process event)
+ "Handle the results of the nix build.
+OUT-LINK The path to the output symlink.
+
+LAST-OUT The previous build result, if any.
+
+EXPR-FILE The nix expression being built.
+
+USER-BUF The buffer to apply the results to.
+
+ERR-BUF The standard error buffer of the nix-build
+
+PROCESS The process whose status changed.
+
+EVENT The process status change event string."
+ (unless (process-live-p process)
+ (let ((out-buf (process-buffer process)))
+ (progn
+ (if (= (process-exit-status process) 0)
+ (let ((cur-out (with-current-buffer out-buf
+ (string-trim-right (buffer-string)))))
+ (if (string= "" cur-out)
+ (ignore-errors (delete-file out-link))
+ (unless (string= last-out cur-out)
+ (with-current-buffer user-buf
+ (nix-buffer--load-result expr-file cur-out)))))
+ (with-current-buffer
+ (get-buffer-create "*nix-buffer errors*")
+ (insert "nix-build for nix-buffer for "
+ (buffer-name user-buf)
+ " "
+ (string-trim-right event)
+ " with error output: \n")
+ (insert-buffer-substring err-buf)
+ (pop-to-buffer (current-buffer))))
+ (kill-buffer out-buf)
+ (kill-buffer err-buf)))))
+
+(defun nix-buffer--nix-build (root expr-file)
+ "Start the nix build.
+ROOT The path we started from.
+
+EXPR-FILE The file containing the nix expression to build."
+ (let* ((state-dir (f-join nix-buffer-directory-name
+ (nix-buffer--unique-filename root)))
+ (out-link (f-join state-dir "result"))
+ (current-out (file-symlink-p out-link))
+ (err (generate-new-buffer " nix-buffer-nix-build-stderr")))
+ (progn
+ (ignore-errors (make-directory state-dir t))
+ (make-process
+ :name "nix-buffer-nix-build"
+ :buffer (generate-new-buffer " nix-buffer-nix-build-stdout")
+ :command (list
+ "nix-build"
+ "--arg" "root" root
+ "--out-link" out-link
+ expr-file
+ )
+ :noquery t
+ :sentinel (apply-partially 'nix-buffer--sentinel
+ out-link
+ current-out
+ expr-file
+ (current-buffer)
+ err)
+ :stderr err)
+ (when current-out
+ (nix-buffer--load-result expr-file current-out)))))
+
+;;;###autoload
+(defun nix-buffer ()
+ "Set up the buffer according to the directory-local nix expression.
+Looks for dir-locals.nix upward from the current directory. If found,
+asynchronously builds the derivation defined there with the 'root' arg
+set to the current buffer file name or directory and evaluates the
+resulting elisp if safe to do so. 'nix-buffer-after-load-hook' can be
+used to detect when the elisp load occurs.
+
+If we have previously built dir-locals.nix for the current file or
+directory, the elisp corresponding to the last build is evaluated
+synchronously and the new elisp is evaluated when the build completes,
+unless the newly-built file is identical. As such, the elisp
+generated by dir-locals.nix should be written with multiple
+evaluations in mind.
+
+Because in practice dir-locals.nix will always want to do things that
+are unsafe in dir-locals.el (e.g. append to 'exec-path'), we don't
+reuse that mechanism and instead just load the file as elisp. Because
+this allows arbitrary code execution, the first time we're asked to
+load a particular store path we query the user to verify if it's safe
+to load beforehand.
+
+The Lisp code generated by dir-locals.nix should limit itself to
+modifying buffer-local variables, but there is no actual enforcement
+of this. 'setq-local' is your friend.
+
+If dir-locals.nix does not evaluate to any derivations (e.g. it
+evaluates to {}), then nothing is loaded and the cached result, if any,
+is removed."
+ (interactive)
+ (let* ((root (or (buffer-file-name) default-directory))
+ (expr-dir (locate-dominating-file root "dir-locals.nix")))
+ (when expr-dir
+ (let ((expr-file (f-expand "dir-locals.nix" expr-dir)))
+ (nix-buffer--nix-build root expr-file)))))
+
+(add-hook 'kill-emacs-hook 'nix-buffer-unload-function)
+
+(provide 'nix-buffer)
+
+;;; nix-buffer.el ends here
- [nongnu] elpa/nix-mode ad09b3be7f 066/500: Fix flycheck errors., (continued)
- [nongnu] elpa/nix-mode ad09b3be7f 066/500: Fix flycheck errors., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 6534f146eb 065/500: Formatting, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 5a29112764 073/500: Add function for escaped antiquote., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 460cc23161 075/500: Make " be treated as generic | syntax class., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode ff8409c617 079/500: Declare lexical-binding, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 6a9cb7e682 081/500: Add basic REPL via nix-repl, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 836e14fdd4 093/500: Merge pull request #12 from matthewbauer/case-sensitive-searching, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode ea23a301d7 086/500: Fontification.., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode f309e106ef 090/500: Revert "Make " be treated as generic | syntax class.", ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 64d615d628 096/500: Add nix-mode-mmm, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode f968cb98ef 097/500: Add nix-buffer.,
ELPA Syncer <=
- [nongnu] elpa/nix-mode c0502994b5 100/500: Remove nix-mode-reload., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 956280c161 116/500: Refactor nix--antiquote-close, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode de02e17924 135/500: Fix fontification of "}${" in some contexts, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 0b19f975cd 143/500: Merge pull request #28 from pvmart/fix-nix-mmm, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 719482b701 148/500: Update customizations for Nix related modes., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode b3c6560f6d 166/500: Fix typo: rustfmt -> nixfmt, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 038dcf7b1b 147/500: Cleanup, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 3edda90cfd 146/500: Remove nix-flycheck, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode a967408f64 188/500: Don’t error when nix-shebang fails., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 05d7c828b3 187/500: Fix nix-company and mmm-mode loading., ELPA Syncer, 2022/01/29