[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/nix-mode 0f12887ea7 082/500: Add basic company completions
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/nix-mode 0f12887ea7 082/500: Add basic company completions via nix-repl |
Date: |
Sat, 29 Jan 2022 08:26:38 -0500 (EST) |
branch: elpa/nix-mode
commit 0f12887ea7797037301c501e2d5e7013ca5a42f7
Author: Leon Isenberg <ljli@users.noreply.github.com>
Commit: Matthew Bauer <mjbauer95@gmail.com>
Add basic company completions via nix-repl
---
nix-mode.el | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 118 insertions(+), 2 deletions(-)
diff --git a/nix-mode.el b/nix-mode.el
index f934dcc9c1..5affe9a1d0 100644
--- a/nix-mode.el
+++ b/nix-mode.el
@@ -15,6 +15,7 @@
;;; Code:
+(require 'company)
(require 'flycheck)
;; Emacs 24.2 compatability
@@ -218,7 +219,9 @@ If a close brace `}' ends an antiquote, the next character
begins a string."
(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))
+ (setq-local comint-prompt-read-only t)
+ (add-to-list 'company-backends 'company-nix)
+ (company-mode))
(defun nix-repl-show ()
"Load the Nix-REPL."
@@ -232,6 +235,115 @@ If a close brace `}' ends an antiquote, the next
character begins a string."
(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 ()
@@ -473,7 +585,11 @@ The hook `nix-mode-hook' is run when Nix mode is started.
;; Flycheck
(flycheck-select-checker 'nix)
- (flycheck-mode))
+ (flycheck-mode)
+
+ ;; Company
+ (add-to-list 'company-backends 'company-nix)
+ (company-mode))
;;;###autoload
(progn
- [nongnu] elpa/nix-mode 376cbff828 054/500: More let fixes., (continued)
- [nongnu] elpa/nix-mode 376cbff828 054/500: More let fixes., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 1a1ce340af 070/500: Fix indentation case when '{' at beginning., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode dc705bb4df 057/500: Disable generic hanging indent., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 2be81fe55b 074/500: Get rid of match-end., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 4ce19a966b 095/500: Merge branch 'ljli-fontication', ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 1e58da56ac 083/500: Fix var name nix-err-msg-re, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode b1078c6add 092/500: Add case sensitive searching, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 6eb927f3c1 080/500: Add basic flychecking via nix-instantiate, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode afb1629922 085/500: Fix nix--antiquote-open, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 1ebbd318d2 089/500: Add some comments to nix-flycheck.el., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 0f12887ea7 082/500: Add basic company completions via nix-repl,
ELPA Syncer <=
- [nongnu] elpa/nix-mode 5b63478bcb 109/500: Make nix-flycheck optional., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 4076a86333 114/500: Merge pull request #17 from matthewbauer/separate-files, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 2f3dfd90df 115/500: Make nix-format.el optional in nix-mode., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode da7e6de79a 139/500: Move some unpolished elisp to "misc" folder., ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 55b0ea2d96 132/500: Merge pull request #18 from matthewbauer/more-modes, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode d9c1d4d4a4 152/500: Remove maintained modes, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode 594b979c91 140/500: Missed one, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode d1650d795c 151/500: Cleanup documentation, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode be839f971b 157/500: Use nix-mode-mmm when mmm-mode is available, ELPA Syncer, 2022/01/29
- [nongnu] elpa/nix-mode a1860c6bde 144/500: Handle projectile projects, ELPA Syncer, 2022/01/29