|
|
- ;;; nix-repl.el --- Nix repl -*- lexical-binding: t -*-
-
- ;; This file is NOT part of GNU Emacs.
-
- ;; Version: 1.4.0
-
- ;;; Commentary:
-
- ;;; Code:
-
- (defvar nix-prompt-regexp "nix-repl> ")
-
- (require 'comint)
- (require 'nix)
-
- (defgroup nix-repl nil
- "nix-repl customizations"
- :group 'nix)
-
- (defcustom nix-repl-executable-args '("repl")
- "Arguments to provide to nix-repl."
- :type 'list)
-
- (define-derived-mode nix-repl-mode comint-mode "Nix-REPL"
- "Interactive prompt for Nix."
- (setq-local comint-prompt-regexp nix-prompt-regexp)
- (setq-local comint-prompt-read-only t))
-
- (defmacro nix--with-temp-process-filter (proc &rest body)
- "Use temp process PROC filter on BODY."
- (declare (indent defun))
- `(let* ((buf (generate-new-buffer " *temp-process-output*"))
- (proc-filter-saved (process-filter ,proc))
- (proc-marker (with-current-buffer buf (point-marker))))
- (set-process-filter ,proc (nix--process-filter buf proc-marker))
- (unwind-protect
- (with-current-buffer buf
- ,@body)
- (set-process-filter ,proc proc-filter-saved)
- (kill-buffer buf))))
-
- ;;;###autoload
- (defun nix-repl ()
- "Load the Nix-REPL."
- (interactive)
- (pop-to-buffer-same-window
- (get-buffer-create "*Nix-REPL*"))
- (unless (comint-check-proc (current-buffer))
- (nix--make-repl-in-buffer (current-buffer))
- (nix-repl-mode)))
-
- (defalias 'nix-repl-show 'nix-repl)
-
- (defun nix--make-repl-in-buffer (buffer)
- "Make Nix Repl in BUFFER."
- (apply
- 'make-comint-in-buffer
- (append `("Nix-REPL" ,buffer ,nix-executable nil)
- nix-repl-executable-args)))
-
- (defun nix-get-completions (proc prefix)
- "Get Nix completions from Nix-repl process PROC and based off of PREFIX."
- (save-match-data
- (nix--with-temp-process-filter proc
- (goto-char (point-min))
- (process-send-string proc (concat prefix "\t\"" (nix--char-with-ctrl ?a) "\"\n"))
- (let ((i 0))
- (while (and (< (setq i (1+ i)) 100)
- (not (search-forward-regexp "\"\\([^\"]*\\)\"[\n]*nix-repl>" nil t)))
- (sleep-for 0.01))
- (let ((new-prefix (match-string 1))
- (start-compl (point)))
- (if (string-suffix-p " " new-prefix)
- (list (substring new-prefix 0 -1))
- (process-send-string proc (concat new-prefix "\t\t" (nix--char-with-ctrl ?u) "\n"))
- (goto-char start-compl)
- (setq i 0)
- (while (and (< (setq i (1+ i)) 100)
- (not (search-forward-regexp
- "[\n]+nix-repl>\\|Display all \\([0-9]+\\)" nil t)))
- (sleep-for 0.01))
- (if (match-string 1)
- (progn
- (process-send-string proc "n")
- '())
- (search-backward "\n" nil t)
- (split-string (buffer-substring start-compl (1- (point)))))))))))
-
- (defun nix--send-repl (input &optional process mute)
- "Send INPUT to PROCESS.
-
- MUTE if true then don’t alert user."
- (let ((proc (or process (get-buffer-process (current-buffer)))))
- (if mute
- (nix--with-temp-process-filter proc
- (process-send-string proc input))
- (process-send-string proc input))))
-
- (defun nix--char-with-ctrl (char)
- "Generate control character CHAR."
- (char-to-string (logand #b10011111 char)))
-
- (defun nix--process-filter (buf marker)
- "Process filter for Nix-rel buffer BUF at MARKER."
- (lambda (_proc string)
- (when (buffer-live-p buf)
- (with-current-buffer buf
- (save-excursion
- (goto-char marker)
- (insert string)
- (set-marker marker (point)))))))
-
- (provide 'nix-repl)
- ;;; nix-repl.el ends here
|