[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/nix-mode 0ada62bbee 091/500: Merge pull request #11 from m
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/nix-mode 0ada62bbee 091/500: Merge pull request #11 from matthewbauer/completion |
Date: |
Sat, 29 Jan 2022 08:26:39 -0500 (EST) |
branch: elpa/nix-mode
commit 0ada62bbee13d9272c7defec982590b819d06a14
Merge: f309e106ef 1ebbd318d2
Author: Matthew Justin Bauer <mjbauer95@gmail.com>
Commit: GitHub <noreply@github.com>
Merge pull request #11 from matthewbauer/completion
Implement completion
---
nix-flycheck.el | 46 ++++++++++++++++++
nix-mode.el | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 186 insertions(+), 1 deletion(-)
diff --git a/nix-flycheck.el b/nix-flycheck.el
new file mode 100644
index 0000000000..37aa4d4321
--- /dev/null
+++ b/nix-flycheck.el
@@ -0,0 +1,46 @@
+;;; nix-flycheck.el --- Flycheck support for Nix.
+
+;; This file is NOT part of GNU Emacs.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'flycheck)
+
+(defconst nix-err-msg-re
+ "error: \\(.*\\) at \\(.*\\):\\([0-9]+\\):\\([0-9]+\\)")
+
+(defun nix--parse-errors (output checker buffer)
+ (with-temp-buffer
+ (insert output)
+ (goto-char (point-min))
+ (let ((errs '()))
+ (while (search-forward-regexp nix-err-msg-re nil t 1)
+ (let* ((file (match-string 2))
+ (line (string-to-number (match-string 3)))
+ (col (string-to-number (match-string 4)))
+ (msg (match-string 1)))
+ (setq errs
+ (cons (flycheck-error-new-at
+ line col 'error msg
+ :filename (and (not (string= file "(string)")) file)
+ :checker checker
+ :buffer buffer)
+ errs))))
+ errs)))
+
+(flycheck-def-args-var flycheck-nix-args (nix))
+
+(flycheck-define-checker nix
+ "A syntax and evaluation checker for Nix using
nix-instantiate."
+ :command ("nix-instantiate" "--eval" "--strict"
"--show-trace" (eval flycheck-nix-args) "-")
+ :standard-input t
+ :error-parser nix--parse-errors
+ :modes (nix-mode)
+ )
+
+(add-to-list 'flycheck-checkers 'nix)
+
+(provide 'nix-flycheck)
+;;; nix-flycheck.el ends here
diff --git a/nix-mode.el b/nix-mode.el
index 5f9e63f18c..7551a62e7e 100644
--- a/nix-mode.el
+++ b/nix-mode.el
@@ -173,7 +173,140 @@ If a close brace `}' ends an antiquote, the next
character begins a string."
(0 (ignore (nix-syntax-propertize-close-brace)))))
start end))
-;; Indentation
+
+;;; REPL
+
+(defvar nix-prompt-regexp "nix-repl> ")
+
+(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)
+ (add-to-list 'company-backends 'company-nix)
+ (company-mode))
+
+(defun nix-repl-show ()
+ "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)))
+
+(defun nix--make-repl-in-buffer (buffer)
+ (make-comint-in-buffer "Nix-REPL" buffer "nix-repl"))
+
+;;; Company
+
+(defun company-nix (command &optional arg &rest ignored)
+ (interactive '(interactive))
+ (case command
+ (interactive (company-begin-backend 'company-nix))
+ (prefix (and (member major-mode '(nix-mode nix-repl-mode))
+ (nix-grab-attr-path)))
+ (candidates
+ (nix-get-completions (get-buffer-process (nix--get-company-buffer)) arg))
+ (sorted t)))
+
+(defun nix-grab-attr-path ()
+ (if (looking-at "[^a-zA-Z0-9'\\-_\\.]")
+ (buffer-substring (point) (save-excursion (skip-chars-backward
"a-zA-Z0-9'\\-_\\.")
+ (point)))
+ (unless (and (char-after)
+ (string-match "[a-zA-Z0-9'\\-_]" (char-to-string
(char-after)))
+ ""))))
+
+(defun nix--get-company-buffer (&optional buffer)
+ (let* ((buf (or buffer (current-buffer)))
+ (repl-buf (get-buffer "*Nix-REPL*")))
+ (if (or (equal buf "*Nix-REPL*") (equal buf repl-buf))
+ repl-buf
+ (nix--get-company-backend-buffer buf))))
+
+(defvar nix-company-backend-buffer-name " *nix-company-backend*")
+(defvar nix--company-last-buffer nil)
+
+(defun nix--get-company-backend-buffer (buffer)
+ (let* ((buf-file (buffer-file-name buffer))
+ (backend-buf (get-buffer-create nix-company-backend-buffer-name))
+ (last-buf nix--company-last-buffer)
+ (proc (get-buffer-process backend-buf)))
+ (with-current-buffer buffer
+ (if (and proc
+ (process-live-p proc))
+ (if (not (string= last-buf (buffer-name)))
+ (progn (quit-process proc)
+ (nix--make-repl-in-buffer backend-buf)
+ (nix--send-repl (concat ":l " buf-file "\n")
+ (get-buffer-process backend-buf) t)
+ (setq nix--company-last-buffer (buffer-name)))
+ (nix--send-repl ":r\n" proc t))
+ (progn (nix--make-repl-in-buffer backend-buf)
+ (nix--send-repl (concat ":l " buf-file "\n")
+ (get-buffer-process backend-buf) t)
+ (setq nix--company-last-buffer (buffer-name))))
+ backend-buf)))
+
+(defun nix-get-completions (proc 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"))
+ (setq 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)
+ (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)
+ (char-to-string (logand #b10011111 char)))
+
+(defmacro nix--with-temp-process-filter (proc &rest 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))))
+
+(defun nix--process-filter (buf marker)
+ (lambda (proc string)
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (save-excursion
+ (goto-char marker)
+ (insert string)
+ (set-marker marker (point)))))))
+
+;;; Indentation
(defun nix-indent-level-parens ()
"Find indent level based on parens."
@@ -358,6 +491,12 @@ If a close brace `}' ends an antiquote, the next character
begins a string."
(nix-create-keymap)
(nix-create-menu)
+(when (featurep 'flycheck) (require 'nix-flycheck))
+
+(when (require 'company nil 'noerror) (add-to-list
+ 'company-backends
+ 'company-nix))
+
;;;###autoload
(define-derived-mode nix-mode prog-mode "Nix"
"Major mode for editing Nix expressions.
- [nongnu] elpa/nix-mode b4b7edb246 012/500: Move some builtins to warnings., (continued)
- [nongnu] elpa/nix-mode b4b7edb246 012/500: Move some builtins to warnings., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 22500b7f72 038/500: fix tabbing, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode d8b088a4e2 034/500: Disable string indenting again, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 3ad8e224d7 043/500: Use looking-back for hanging indent., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode ec9cf2f4e5 061/500: Remove nix-syntax-propertize-escaped-antiquote., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode c339fc9062 072/500: More small nitpicks., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 1cc3cffa29 060/500: Pick up extra "let" found in acme.nix., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 1772d1f0db 077/500: Fixup syntax entry., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode fa7a4a0d4d 078/500: Update README.md, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 9015ef6603 029/500: check beginning for comment indent, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 0ada62bbee 091/500: Merge pull request #11 from matthewbauer/completion,
ELPA Syncer <=
- [nongnu] elpa/nix-mode 2de7d1d585 088/500: Don't require company to be installed., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 8d2a304865 098/500: Fontification: smoked out corner cases, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 702f62abff 103/500: lexical bindings, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 03e39da643 099/500: Fix flycheck lexical-binding complaints., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 1c54c72161 121/500: Remove visit-file., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 5e943a77e8 133/500: Fix syntax error, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 804ec4e7de 122/500: Remove visit file /2, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 3957a90b1a 125/500: Add `null` to list of Nix builtins, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 046afc4b4d 127/500: Rework indentation, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 18abc92bd8 141/500: fix mmm, ELPA Syncer, 2022/01/29