-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchuck-core.el
124 lines (102 loc) · 3.89 KB
/
chuck-core.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
;;; chuck-core.el --- ChucK mode core
;;; Commentary:
;;; Code:
(require 'dash)
(defgroup chuck nil
"Support for the ChucK programming language, <http://chuck.cs.princeton.edu/>"
:group 'languages
:prefix "chuck-")
(defcustom chuck-exec "chuck"
"*Command used to start the ChucK VM.
The default will work if `chuck' is on your path. If you don't
want or can't change you `PATH' env variable change this to point
to the full path of `chuck' (i.e `c:\\chuck\\bin\\chuck.exe')"
:type 'string
:group 'chuck)
(defcustom chuck-port 8888
"ChucK server port."
:type 'integer
:group 'chuck)
(defcustom chuck-process-name "ChucK"
"ChucK process name."
:type 'string
:group 'chuck)
(defcustom chuck-buffer-name "*ChucK*"
"ChucK inferior process buffer name."
:type 'string
:group 'chuck)
(defun build-chuck-cmd (cmd &optional arg)
"Build a CMD with optional ARG."
(concat chuck-exec " --port:" (number-to-string chuck-port) " " cmd " " (or arg "")))
(defun send-chuck-cmd (cmd &optional arg)
"Sends a CMD with optional ARG to chuck."
(shell-command (build-chuck-cmd cmd arg)))
(defvar chuck-status-regex
"^[[:space:]]+\\[shred id\\]:[[:space:]]+\\([[:digit:]]+\\)[[:space:]]+\\[source\\]:[[:space:]]+\\(.*?\\)[[:space:]]\\{2\\}\\[spork time\\]:[[:space:]]\\(.*\\)$")
;; ChucK mode internals
(defun ensure-chuck-is-running ()
"Ensure ChucK process is running."
(when (not (chuck-is-running?))
(chuck-run)))
(defun chuck-is-running? ()
"Is ChucK running?."
(get-process chuck-process-name))
(defun chuck-run ()
"Start the ChucK VM as an inferior process."
(start-process-shell-command chuck-process-name chuck-buffer-name (build-chuck-cmd "--loop")))
(defun chuck-kill ()
"Kill the ChucK VM."
(when (chuck-is-running?)
(send-chuck-cmd "--kill")
(with-current-buffer chuck-buffer-name
(kill-buffer-and-window))))
(defun chuck-status ()
"Tell ChucK to report status."
(let* ((chuck-process (get-process chuck-process-name))
(output-start (process-mark chuck-process))
(output-start-position (marker-position output-start)))
(send-chuck-cmd "--status")
(sleep-for 0 100)
(with-current-buffer (marker-buffer output-start)
(let* ((output-end (process-mark chuck-process))
(output-end-position (marker-position output-end))
(chuck-status-string (buffer-substring output-start-position output-end-position))
(status (chuck-parse-status chuck-status-string)))
status))))
(defun chuck-add (filename)
"Add a FILENAME as a shred to the ChucK VM."
(ensure-chuck-is-running)
(send-chuck-cmd "+" filename))
(defun chuck-remove-shred (shred)
"Remove a SHRED associated with current buffer."
(ensure-chuck-is-running)
(send-chuck-cmd "-" shred))
(defun chuck-remove-all ()
"Remove all currently running shreds."
(ensure-chuck-is-running)
(send-chuck-cmd "--remove.all"))
(defun chuck-replace-shred (shred filename)
"Replace a SHRED with contents of FILENAME."
(ensure-chuck-is-running)
(send-chuck-cmd "=" (concat shred " " filename)))
(defun chuck-parse-status (status)
"Parse ChucK STATUS."
(let ((status-lines (--filter (string-match-p chuck-status-regex it)
(split-string status "\n"))))
(-map
(lambda (line)
(string-match chuck-status-regex line)
(list :shred (match-string 1 line)
:source (match-string 2 line)
:time (match-string 3 line)))
status-lines)))
(defun chuck-get-shred-by-source (source)
"Get shred id by it's SOURCE."
(-when-let (entry (-first (lambda (e) (string= (plist-get e :source) source)) (chuck-status)))
(plist-get entry :shred)))
(defun chuck-get-source-by-shred (shred)
"Get source by SHRED id."
(-when-let (entry (-first (lambda (e) (string= (plist-get e :shred) shred)) (chuck-status)))
(plist-get entry :source)))
(provide 'chuck-core)
;;; chuck-core.el ends here