/
skewer-repl.el
98 lines (81 loc) · 3.25 KB
/
skewer-repl.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
;;; skewer-repl.el --- create a REPL in a visiting browser
;; This is free and unencumbered software released into the public domain.
;;; Commentary:
;; This is largely based on of IELM's code. Run `skewer-repl' to
;; switch to the REPL buffer and evaluate code. Use
;; `skewer-repl-toggle-strict-mode' to turn strict mode on and off.
;;; Code:
(require 'comint)
(require 'skewer-mode)
(defcustom skewer-repl-strict-p nil
"When non-NIL, all REPL evaluations are done in strict mode."
:type 'boolean
:group 'skewer)
(defcustom skewer-repl-prompt "js> "
"Prompt string for JavaScript REPL."
:type 'string
:group 'skewer)
(defun skewer-repl-process ()
"Return the process for the skewer REPL."
(get-buffer-process (current-buffer)))
(defface skewer-repl-log-face
'((((class color) (background light))
:foreground "#77F")
(((class color) (background dark))
:foreground "#77F"))
"Face for skewer.log() messages."
:group 'skewer)
(define-derived-mode skewer-repl-mode comint-mode "js-REPL"
"Provide a REPL into the visiting browser."
:group 'skewer
:syntax-table emacs-lisp-mode-syntax-table
(setq comint-prompt-regexp (concat "^" (regexp-quote skewer-repl-prompt)))
(setq comint-input-sender 'skewer-input-sender)
(add-to-list 'skewer-callbacks 'skewer-post-repl)
(add-to-list 'skewer-callbacks 'skewer-post-log)
(unless (comint-check-proc (current-buffer))
(start-process "ielm" (current-buffer) "hexl")
(set-process-query-on-exit-flag (skewer-repl-process) nil)
(goto-char (point-max))
(set (make-local-variable 'comint-inhibit-carriage-motion) t)
(comint-output-filter (skewer-repl-process) skewer-repl-prompt)
(set-process-filter (skewer-repl-process) 'comint-output-filter)))
(defun skewer-repl-toggle-strict-mode ()
"Toggle strict mode for expressions evaluated by the REPL."
(interactive)
(setq skewer-repl-strict-p (not skewer-repl-strict-p))
(message "REPL strict mode %s"
(if skewer-repl-strict-p "enabled" "disabled")))
(defun skewer-input-sender (proc input)
"REPL comint handler."
(skewer-eval input 'skewer-post-repl
:verbose t :strict skewer-repl-strict-p))
(defun skewer-post-repl (result)
"Callback for reporting results in the REPL."
(let ((buffer (get-buffer "*skewer-repl*"))
(output (cdr (assoc 'value result))))
(when buffer
(with-current-buffer buffer
(comint-output-filter (skewer-repl-process)
(concat output "\n" skewer-repl-prompt))))))
(defun skewer-post-log (log)
"Callback for logging messages to the REPL."
(let ((buffer (get-buffer "*skewer-repl*"))
(output (propertize (cdr (assoc 'value log))
'font-lock-face 'skewer-repl-log-face)))
(when buffer
(with-current-buffer buffer
(save-excursion
(forward-line 0)
(backward-char)
(insert (concat "\n" output "")))))))
;;;###autoload
(defun skewer-repl ()
"Start a JavaScript REPL to be evaluated in the visiting browser."
(interactive)
(when (not (get-buffer "*skewer-repl*"))
(with-current-buffer (get-buffer-create "*skewer-repl*")
(skewer-repl-mode)))
(switch-to-buffer (get-buffer "*skewer-repl*")))
(provide 'skewer-repl)
;;; skewer-repl.el ends here