Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
4.3 KiB

преди 4 години
  1. ;;; nix-repl.el --- Nix repl -*- lexical-binding: t -*-
  2. ;; This file is NOT part of GNU Emacs.
  3. ;; Version: 1.4.0
  4. ;;; Commentary:
  5. ;;; Code:
  6. (defvar nix-prompt-regexp "nix-repl> ")
  7. (require 'comint)
  8. (require 'nix)
  9. (defgroup nix-repl nil
  10. "nix-repl customizations"
  11. :group 'nix)
  12. (defcustom nix-repl-executable-args '("repl")
  13. "Arguments to provide to nix-repl."
  14. :type 'list)
  15. (define-derived-mode nix-repl-mode comint-mode "Nix-REPL"
  16. "Interactive prompt for Nix."
  17. (setq-local comint-prompt-regexp nix-prompt-regexp)
  18. (setq-local comint-prompt-read-only t))
  19. (defmacro nix--with-temp-process-filter (proc &rest body)
  20. "Use temp process PROC filter on BODY."
  21. (declare (indent defun))
  22. `(let* ((buf (generate-new-buffer " *temp-process-output*"))
  23. (proc-filter-saved (process-filter ,proc))
  24. (proc-marker (with-current-buffer buf (point-marker))))
  25. (set-process-filter ,proc (nix--process-filter buf proc-marker))
  26. (unwind-protect
  27. (with-current-buffer buf
  28. ,@body)
  29. (set-process-filter ,proc proc-filter-saved)
  30. (kill-buffer buf))))
  31. ;;;###autoload
  32. (defun nix-repl ()
  33. "Load the Nix-REPL."
  34. (interactive)
  35. (pop-to-buffer-same-window
  36. (get-buffer-create "*Nix-REPL*"))
  37. (unless (comint-check-proc (current-buffer))
  38. (nix--make-repl-in-buffer (current-buffer))
  39. (nix-repl-mode)))
  40. (defalias 'nix-repl-show 'nix-repl)
  41. (defun nix--make-repl-in-buffer (buffer)
  42. "Make Nix Repl in BUFFER."
  43. (apply
  44. 'make-comint-in-buffer
  45. (append `("Nix-REPL" ,buffer ,nix-executable nil)
  46. nix-repl-executable-args)))
  47. (defun nix-get-completions (proc prefix)
  48. "Get Nix completions from Nix-repl process PROC and based off of PREFIX."
  49. (save-match-data
  50. (nix--with-temp-process-filter proc
  51. (goto-char (point-min))
  52. (process-send-string proc (concat prefix "\t\"" (nix--char-with-ctrl ?a) "\"\n"))
  53. (let ((i 0))
  54. (while (and (< (setq i (1+ i)) 100)
  55. (not (search-forward-regexp "\"\\([^\"]*\\)\"[\n]*nix-repl>" nil t)))
  56. (sleep-for 0.01))
  57. (let ((new-prefix (match-string 1))
  58. (start-compl (point)))
  59. (if (string-suffix-p " " new-prefix)
  60. (list (substring new-prefix 0 -1))
  61. (process-send-string proc (concat new-prefix "\t\t" (nix--char-with-ctrl ?u) "\n"))
  62. (goto-char start-compl)
  63. (setq i 0)
  64. (while (and (< (setq i (1+ i)) 100)
  65. (not (search-forward-regexp
  66. "[\n]+nix-repl>\\|Display all \\([0-9]+\\)" nil t)))
  67. (sleep-for 0.01))
  68. (if (match-string 1)
  69. (progn
  70. (process-send-string proc "n")
  71. '())
  72. (search-backward "\n" nil t)
  73. (split-string (buffer-substring start-compl (1- (point)))))))))))
  74. (defun nix--send-repl (input &optional process mute)
  75. "Send INPUT to PROCESS.
  76. MUTE if true then dont alert user."
  77. (let ((proc (or process (get-buffer-process (current-buffer)))))
  78. (if mute
  79. (nix--with-temp-process-filter proc
  80. (process-send-string proc input))
  81. (process-send-string proc input))))
  82. (defun nix--char-with-ctrl (char)
  83. "Generate control character CHAR."
  84. (char-to-string (logand #b10011111 char)))
  85. (defun nix--process-filter (buf marker)
  86. "Process filter for Nix-rel buffer BUF at MARKER."
  87. (lambda (_proc string)
  88. (when (buffer-live-p buf)
  89. (with-current-buffer buf
  90. (save-excursion
  91. (goto-char marker)
  92. (insert string)
  93. (set-marker marker (point)))))))
  94. (provide 'nix-repl)
  95. ;;; nix-repl.el ends here