-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathchuck-mode.elc
executable file
·328 lines (291 loc) · 13.4 KB
/
chuck-mode.elc
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
;;; ChucK major mode for editing ChucK code and hopefully in the
;;; future also updating a running ChucK engine
;;;
;;; (c) 2004 Mikael Johansson
;;; revised by Graham Coleman 2006
;;; TODO
;;; 2. revisit running the process
;;; 3. maybe display the running stats in a subwindow
;;; 4. remove req for saving the buffer, use temps
;;; 5. get remove to accept several shred numbers
;;; ->
;;; inf. build in audicle style revisions
;; mode hook for user defined actions
(defvar chuck-mode-hook nil)
;;; CHANGE THIS to something that fits your system!!!
(defvar chuck-exec "chuck")
;;; CHANGE THIS to list of commonly required classes
(defvar chuck-lib (list "fade.ck" "scale.ck" "tg.ck"))
;; call chuck with some arguments
(defun run-chuck (ch-action &rest args)
(apply 'call-process chuck-exec
nil ;;no infile
;;0 ;;discard output and return nil immediately
"*ChucK*" ;;don't throw away output just yet
nil ;;do not redisplay
ch-action ;;the action
args)) ;;apply spreads the args
;; make a temp ck dir if you need it
(defun make-ck-dir ()
(if (not (file-exists-p ".ck")) ;;if no dir
(make-directory ".ck" nil))) ;;create it
;; save into a temp file and return filename, under construction
(defun save-temp ()
(make-ck-dir)
(let ((bname (format ".ck/temp.ck")))
(write-region (point-min) (point-max) ;;write the whole buffer
bname ;;temp name
nil nil nil) ;;no append, mustbenew, or visit
bname)) ;;return the filename
;; ChucK as an internal listener does not work well. Run it externally
;; and control it internally.
;(defun run-chuck ()
; "Start a ChucK listener"
; (interactive)
; (start-process "ChucK" "*ChucK*" chuck-exec "--loop"))
;(defun kill-chuck ()
; "Kills a running ChucK listener"
; (interactive)
; (call-process chuck-exec nil 0 "--kill"))
;;try running chuck as an internal listener
(defun start-chuck ()
"Start a ChucK listener"
(interactive)
(let ((cproc
(start-process "ChucK" "*ChucK*" chuck-exec "--loop")))
;;(set-process-coding-system cproc
;; (keyboard-coding-system)
;; (terminal-coding-system))
;;(setq chuck-proc cproc)
;;(process-send-eof cproc)
;;(process-kill-without-query cproc)
;;(set-process-filter cproc 'chuck-insert-filter)
;;(set-process-sentinel cproc nil)) ;;the null sentinel
)
(switch-to-buffer-other-window "*ChucK*") ;;open in bottom
)
;;filter
(defun chuck-insert-filter (proc string)
(with-current-buffer (process-buffer proc)
(let ((moving (= (point) (process-mark proc))))
(save-excursion
;; Insert the text, advancing the process marker.
(goto-char (process-mark proc))
(insert string)
(set-marker (process-mark proc) (point)))
(if moving (goto-char (process-mark proc))))))
(defun chuck-add-code ()
"Add buffer to running ChucK"
(interactive)
(if (buffer-modified-p)
(message "You need to save first")
(run-chuck "--add" buffer-file-name)))
(defun chuck-add-code-nosave ()
"Add buffer to running ChucK w/o requiring save"
(interactive)
(run-chuck "--add" (save-temp)))
(defun chuck-add-library ()
"Add commonly required class files."
(interactive)
(dolist (f chuck-lib)
(run-chuck "--add" f)))
(defun chuck-remove-code ()
"Remove code snippet from running ChucK"
(interactive)
(run-chuck "--remove"
(read-string "Remove which shred? ")))
(defun chuck-replace-code ()
"Replace code snippet in running ChucK with buffer"
(interactive)
(if (buffer-modified-p)
(message "You need to save first")
(run-chuck "--replace"
(read-string "Replace which shred? ")
buffer-file-name)))
(defun chuck-replace-code-nosave ()
"Replace shred in running ChucK without saving"
(interactive)
(run-chuck "--replace"
(read-string "Replace which shred? ")
(save-temp)))
(defun chuck-status ()
"Tell ChucK to report status"
(interactive)
(run-chuck "--status"))
(defun chuck-remove-all ()
"Remove all shreds"
(interactive)
(run-chuck "--removeall"))
;; keymap for ChucK mode
(defvar chuck-mode-map
(let ((chuck-mode-map (make-keymap)))
(define-key chuck-mode-map (kbd "<RET>") 'newline-and-indent)
(define-key chuck-mode-map [menu-bar chuck]
(cons "ChucK" (make-sparse-keymap "ChucK")))
;;TODO find a key binding for this
(define-key chuck-mode-map [menu-bar chuck chuck-remove-all]
'("Remove all shreds from running ChucK" . chuck-remove-all))
(define-key chuck-mode-map [menu-bar chuck chuck-add-library]
'("Add library to running ChucK" . chuck-add-library))
(define-key chuck-mode-map "\M-s" 'chuck-status)
;; M-s is normally undefined
(define-key chuck-mode-map [menu-bar chuck chuck-status]
'("Query ChucK status" . chuck-status))
(define-key chuck-mode-map "\M-r" 'chuck-replace-code)
;; M-r normally move-to-window-line
(define-key chuck-mode-map [menu-bar chuck chuck-replace-code]
'("Replace code in running ChucK with buffer" . chuck-replace-code))
(define-key chuck-mode-map "\M-e" 'chuck-remove-code)
;; M-e is normally sentence-end
(define-key chuck-mode-map [menu-bar chuck chuck-remove-code]
'("Remove code from running ChucK" . chuck-remove-code))
(define-key chuck-mode-map "\M-a" 'chuck-add-code)
;; M-e is normally forward-sentence
(define-key chuck-mode-map [menu-bar chuck chuck-add-code]
'("Add buffer to running ChucK" . chuck-add-code))
chuck-mode-map)
"Keymap for ChucK major mode")
;; Filename binding
(add-to-list 'auto-mode-alist '("\\.ck\\'" . chuck-mode))
;; Syntax highlighting
(defconst chuck-font-lock-keywords-1
(list
(cons (concat "\\<for\\>\\|" "\\<while\\>\\|" "\\<break\\>\\|" "\\<if\\>\\|"
"\\<else\\>\\|" "\\<then\\>\\|" "\\<NULL\\>\\|" "\\<null\\>\\|"
"\\<return\\>") 'font-lock-keyword-face)
(cons (concat "\\<until\\>\\|" "\\<before\\>\\|" "\\<after\\>\\|"
"\\<at\\>\\|" "\\<function\\>\\|" "\\<fun\\>\\|" "\\<new\\>\\|"
"\\<class\\>\\|" "\\<extends\\>\\|" "\\<implements\\>\\|"
"\\<until\\>\\|" "\\<before\\>\\|" "\\<after\\>\\|" "\\<at\\>\\|"
"\\<function\\>\\|" "\\<fun\\>\\|" "\\<new\\>\\|" "\\<class\\>\\|"
"\\<extends\\>\\|" "\\<implements\\>\\|" "\\<public\\>\\|"
"\\<protected\\>\\|" "\\<private\\>\\|" "\\<static\\>\\|"
"\\<const\\>\\|" "\\<spork\\>") 'font-lock-keyword-face)
(cons (concat "\\<=>\\>\\|" "\\<=<\\>\\|" "\\<!=>\\>\\|" "\\<->\\>\\|"
"\\<<-\\>\\|" "\\<+->\\>\\|" "\\<-->\\>\\|" "\\<*->\\>\\|"
"\\</->\\>\\|" "\\<&->\\>\\|" "\\<|->\\>\\|" "\\<^->\\>\\|"
"\\<>>->\\>\\|" "\\<<<->\\>\\|" "\\<%->\\>\\|" "\\<@=>\\>\\|"
"\\<+=>\\>\\|" "\\<-=>\\>\\|" "\\<*=>\\>\\|" "\\</=>\\>\\|"
"\\<&=>\\>\\|" "\\<|=>\\>\\|" "\\<^=>\\>\\|" "\\<>>=>\\>\\|"
"\\<<<=>\\>\\|" "\\<%=>\\>") 'font-lock-builtin-face)
(cons (concat "\\<Std\\>\\|" "\\<abs\\>\\|" "\\<fabs\\>\\|"
"\\<rand\\>\\|" "\\<randf\\>\\|" "\\<rand2f\\>\\|" "\\<randi\\>\\|" "\\<rand2\\>\\|"
"\\<sgn\\>\\|" "\\<system\\>\\|" "\\<aoti\\>\\|" "\\<atof\\>\\|"
"\\<getenv\\>\\|" "\\<setenv\\>\\|" "\\<Math\\>\\|" "\\<sin\\>\\|"
"\\<cos\\>\\|" "\\<tan\\>\\|" "\\<asin\\>\\|" "\\<acos\\>\\|"
"\\<atan\\>\\|" "\\<atan2\\>\\|" "\\<sinh\\>\\|" "\\<cosh\\>\\|"
"\\<tanh\\>\\|" "\\<hypot\\>\\|" "\\<pow\\>\\|"
"\\<sqrt\\>\\|" "\\<exp\\>\\|" "\\<log\\>\\|" "\\<log2\\>\\|"
"\\<log10\\>\\|" "\\<floor\\>\\|" "\\<ceil\\>\\|" "\\<round\\>\\|"
"\\<trunc\\>\\|" "\\<fmod\\>\\|" "\\<remainder\\>\\|" "\\<min\\>\\|"
"\\<max\\>\\|" "\\<nextpow2\\>\\|" "\\<pi\\>\\|" "\\<twopi\\>\\|"
"\\<math.e\\>\\|" "\\<sin\\>\\|" "\\<cos\\>\\|"
"\\<tan\\>\\|" "\\<asin\\>\\|" "\\<acos\\>\\|" "\\<atan\\>\\|"
"\\<atan2\\>\\|" "\\<sinh\\>\\|" "\\<cosh\\>\\|" "\\<tanh\\>\\|"
"\\<hypot\\>\\|" "\\<pow\\>\\|" "\\<sqrt\\>\\|" "\\<exp\\>\\|"
"\\<log\\>\\|" "\\<log2\\>\\|" "\\<log10\\>\\|" "\\<floor\\>\\|"
"\\<ceil\\>\\|" "\\<round\\>\\|"
"\\<trunc\\>\\|" "\\<fmod\\>\\|" "\\<remainder\\>\\|" "\\<min\\>\\|"
"\\<max\\>\\|" "\\<nextpow2\\>\\|" "\\<Machine\\>\\|" "\\<add\\>\\|"
"\\<remove\\>\\|" "\\<replace\\>\\|" "\\<status\\>\\|" "\\<spork\\>\\|"
"\\<net\\>\\|" "\\<init\\>\\|" "\\<data\\>\\|" "\\<data\\>\\|"
"\\<send\\>\\|" "\\<bind\\>\\|" "\\<connect\\>")
'font-lock-function-name-face)
(cons (concat "\\<dac\\>\\|" "\\<adc\\>\\|"
"\\<blackhole\\>\\|" "\\<Gain\\>\\|" "\\<Noise\\>\\|"
"\\<Impulse\\>\\|" "\\<Step\\>\\|" "\\<HalfRect\\>\\|"
"\\<fullrect\\>\\|" "\\<zerox\\>\\|" "\\<delayp\\>\\|"
"\\<SndBuf\\>\\|" "\\<phasor\\>\\|"
"\\<SinOsc\\>\\|" "\\<PulseOsc\\>\\|" "\\<SqrOsc\\>\\|"
"\\<TriOsc\\>\\|" "\\<SawOsc\\>\\|" "\\<netout\\>\\|"
"\\<netin\\>\\|" "\\<BandedWG\\>\\|" "\\<BlowBotl\\>\\|"
"\\<BlowHole\\>\\|" "\\<Bowed\\>\\|" "\\<Brass\\>\\|"
"\\<Clarinet\\>\\|" "\\<Flute\\>\\|"
"\\<Mandolin\\>\\|" "\\<ModalBar\\>\\|" "\\<Moog\\>\\|"
"\\<Saxofony\\>\\|" "\\<Shakers\\>\\|" "\\<Sitar\\>\\|"
"\\<StifKarp\\>\\|" "\\<VoicForm\\>\\|" "\\<FM\\>\\|"
"\\<BeeThree\\>\\|" "\\<FMVoices\\>\\|" "\\<HevyMetl\\>\\|"
"\\<PercFlut\\>\\|" "\\<Rhodey\\>\\|"
"\\<TubeBell\\>\\|" "\\<Wurley\\>\\|" "\\<Delay\\>\\|"
"\\<DelayA\\>\\|" "\\<DelayL\\>\\|" "\\<Echo\\>\\|" "\\<Envelope\\>\\|"
"\\<ADSR\\>\\|" "\\<BiQuad\\>\\|" "\\<Filter\\>\\|" "\\<OnePole\\>\\|"
"\\<TwoPole\\>\\|" "\\<OneZero\\>\\|" "\\<TwoZero\\>\\|"
"\\<PoleZero\\>\\|" "\\<LPF\\>\\|" "\\<HPF\\>\\|" "\\<JCRev\\>\\|"
"\\<NRev\\>\\|" "\\<PRCRev\\>\\|"
"\\<Chorus\\>\\|" "\\<Modulate\\>\\|" "\\<PitShift\\>\\|"
"\\<SubNoise\\>\\|" "\\<WvIn\\>\\|" "\\<WaveLoop\\>\\|" "\\<WvOut\\>")
'font-lock-constant-face)
(cons (concat "\\<NULL\\>\\|" "\\<adc\\>\\|"
"\\<array\\>\\|" "\\<blackhole\\>\\|" "\\<bunghole\\>\\|"
"\\<cherr\\>\\|" "\\<chout\\>\\|" "\\<class\\>\\|" "\\<code\\>\\|"
"\\<compiler\\>\\|" "\\<dac\\>\\|" "\\<day\\>\\|" "\\<double\\>\\|"
"\\<dur\\>\\|" "\\<endl\\>\\|" "\\<false\\>\\|" "\\<float\\>\\|"
"\\<function\\>\\|" "\\<global\\>\\|" "\\<host\\>\\|" "\\<hour\\>\\|"
"\\<int\\>\\|" "\\<language\\>\\|" "\\<machine\\>\\|" "\\<midiin\\>\\|"
"\\<midiout\\>\\|" "\\<minute\\>\\|" "\\<ms\\>\\|" "\\<now\\>\\|"
"\\<null\\>\\|" "\\<object\\>\\|"
"\\<pattern\\>\\|" "\\<math.pi\\>\\|" "\\<samp\\>\\|" "\\<second\\>\\|"
"\\<shred\\>\\|" "\\<single\\>\\|" "\\<start\\>\\|" "\\<stderr\\>\\|"
"\\<stdout\\>\\|" "\\<string\\>\\|" "\\<thread\\>\\|" "\\<time\\>\\|"
"\\<transport\\>\\|" "\\<true\\>\\|" "\\<tuple\\>\\|" "\\<ugen\\>\\|"
"\\<uint\\>\\|" "\\<void\\>\\|" "\\<week\\>") 'font-lock-type-face)
'("\\('\\w*'\\)" . font-lock-variable-name-face))
"Highlighting for ChucK mode")
(defvar chuck-font-lock-keywords chuck-font-lock-keywords-1
"Default highlighting for ChucK mode")
;; Indenting for ChucK mode
(defun chuck-indent-line ()
"Indent current line as ChucK code"
(interactive)
(beginning-of-line)
(if (bobp) ;; Start of buffer starts out unindented
(indent-line-to 0)
(let ((not-indented t) cur-indent)
(if (looking-at ".*}") ; Closing a block
(progn
(save-excursion
(forward-line -1)
(setq cur-indent (- (current-indentation) default-tab-width)))
(if (< cur-indent 0)
(setq cur-indent 0)))
(save-excursion
(while not-indented
(forward-line -1)
(if (looking-at ".*}") ; Earlier block closed
(progn
(setq cur-indent (current-indentation))
(setq not-indented nil))
(if (looking-at ".*{") ; In open block
(progn
(setq cur-indent (+ (current-indentation) default-tab-width))
(setq not-indented nil))
(if (bobp)
(setq not-indented nil)))))))
(if cur-indent
(indent-line-to cur-indent)
(indent-line-to 0)))))
;; Syntax table
(defvar chuck-mode-syntax-table nil "Syntax table for ChucK mode")
(setq chuck-mode-syntax-table
(let ((chuck-mode-syntax-table (make-syntax-table)))
(modify-syntax-entry ?_ "_" chuck-mode-syntax-table)
(modify-syntax-entry ?/ ". 12" chuck-mode-syntax-table)
(modify-syntax-entry ?\n ">" chuck-mode-syntax-table)
chuck-mode-syntax-table))
;; Entry point
(defun chuck-mode ()
"Major mode for editing ChucK music/audio scripts"
(interactive)
(kill-all-local-variables)
(set-syntax-table chuck-mode-syntax-table)
(use-local-map chuck-mode-map)
(set (make-local-variable 'font-lock-defaults)
'(chuck-font-lock-keywords))
(set (make-local-variable 'indent-line-function)
'chuck-indent-line)
(setq major-mode 'chuck-mode)
(setq mode-name "ChucK")
(setq default-tab-width 4)
(run-hooks 'chuck-mode-hook))
(provide 'chuck-mode)
; (setq foo (regexp-opt '("dac" "adc" "blackhole" "gain" "Noise" "Impulse" "step" "halfrect" "fullrect" "zerox" "delayp" "SndBuf" "phasor" "sinosc" "pulseosc" "sqrosc" "triosc" "sawosc" "netout" "netin" "BandedWG" "BlowBotl" "BlowHole" "Bowed" "Brass" "Clarinet" "Flute" "Mandolin" "ModalBar" "Moog" "Saxofony" "Shakers" "Sitar" "StifKarp" "VoicForm" "FM" "BeeThree" "FMVoices" "HevyMetl" "PercFlut" "Rhodey" "TubeBell" "Wurley" "Delay" "DelayA" "DelayL" "Echo" "Envelope" "ADSR" "BiQuad" "Filter" "OnePole" "TwoPole" "OneZero" "TwoZero" "PoleZero" "JCRev" "NRev" "PRCRev" "Chorus" "Modulate" "PitShift" "SubNoise" "WvIn" "WaveLoop" "WvOut")))