Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2701 views
1
;; ess-julia.el --- ESS julia mode and inferior interaction
2
;;
3
;; Copyright (C) 2012 Vitalie Spinu.
4
;;
5
;; Filename: ess-julia.el
6
;; Author: Vitalie Spinu (based on julia-mode.el from julia-lang project)
7
;; Maintainer: Vitalie Spinu
8
;; Created: 02-04-2012 (ESS 12.03)
9
;; Keywords: ESS, julia
10
;;
11
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
;;
13
;; This file is *NOT* part of GNU Emacs.
14
;; This file is part of ESS
15
;;
16
;; This program is free software; you can redistribute it and/or
17
;; modify it under the terms of the GNU General Public License as
18
;; published by the Free Software Foundation; either version 3, or
19
;; (at your option) any later version.
20
;;
21
;; This file is distributed in the hope that it will be useful,
22
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
;; GNU General Public License for more details.
25
;;
26
;; A copy of the GNU General Public License is available at
27
;; http://www.r-project.org/Licenses/
28
;;
29
;;
30
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31
;;
32
;;; Commentary:
33
;; customise inferior-julia-program-name to point to your julia-basic
34
;; and start the inferior with M-x julia.
35
;;
36
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37
;;
38
;;; Code:
39
40
(require 'compile); for compilation-* below
41
(require 'ess-utils)
42
43
(autoload 'inferior-ess "ess-inf" "Run an ESS process.")
44
(autoload 'ess-mode "ess-mode" "Edit an ESS process.")
45
46
(defvar julia-syntax-table
47
(let ((table (make-syntax-table)))
48
(modify-syntax-entry ?_ "_" table) ; underscores in words
49
(modify-syntax-entry ?@ "_" table)
50
(modify-syntax-entry ?. "_" table)
51
(modify-syntax-entry ?# "<" table) ; # single-line comment start
52
(modify-syntax-entry ?\n ">" table) ; \n single-line comment end
53
(modify-syntax-entry ?\{ "(} " table)
54
(modify-syntax-entry ?\} "){ " table)
55
(modify-syntax-entry ?\[ "(] " table)
56
(modify-syntax-entry ?\] ")[ " table)
57
(modify-syntax-entry ?\( "() " table)
58
(modify-syntax-entry ?\) ")( " table)
59
;(modify-syntax-entry ?\\ "." table) ; \ is an operator outside quotes
60
(modify-syntax-entry ?' "." table) ; character quote or transpose
61
(modify-syntax-entry ?\" "\"" table)
62
(modify-syntax-entry ?` "\"" table)
63
;; (modify-syntax-entry ?\" "." table)
64
(modify-syntax-entry ?? "." table)
65
(modify-syntax-entry ?$ "." table)
66
(modify-syntax-entry ?& "." table)
67
(modify-syntax-entry ?* "." table)
68
(modify-syntax-entry ?+ "." table)
69
(modify-syntax-entry ?- "." table)
70
(modify-syntax-entry ?< "." table)
71
(modify-syntax-entry ?> "." table)
72
(modify-syntax-entry ?= "." table)
73
(modify-syntax-entry ?% "." table)
74
table)
75
"Syntax table for `julia-mode'.")
76
77
;; syntax table that holds within strings
78
(defvar julia-mode-string-syntax-table
79
(let ((table (make-syntax-table)))
80
table)
81
"Syntax table for `julia-mode'.")
82
83
;; disable " inside char quote
84
(defvar julia-mode-char-syntax-table
85
(let ((table (make-syntax-table)))
86
(modify-syntax-entry ?\" "." table)
87
table)
88
"Syntax table for `julia-mode'.")
89
90
(defconst julia-char-regex
91
"\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|$!\\^~\\\\;:]\\|^\\)\\('\\(\\([^']*?[^\\\\]\\)\\|\\(\\\\\\\\\\)\\)'\\)")
92
93
(defconst julia-unquote-regex
94
"\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|!\\^~\\\\;:]\\|^\\)\\($[a-zA-Z0-9_]+\\)")
95
96
(defconst julia-forloop-in-regex
97
"for +[^
98
]+ +.*\\(in\\)\\(\\s-\\|$\\)+")
99
100
(defconst julia-font-lock-keywords
101
(list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Ranges\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" .
102
font-lock-type-face)
103
(cons
104
(concat "\\<\\("
105
(mapconcat
106
'identity
107
'("if" "else" "elseif" "while" "for" "begin" "end" "quote"
108
"try" "catch" "return" "local" "abstract" "function" "macro" "ccall"
109
"finally" "typealias" "break" "continue" "type" "global" "@\\w+"
110
"module" "using" "import" "export" "const" "let" "bitstype" "do"
111
"baremodule" "importall" "immutable")
112
"\\|") "\\)\\>")
113
'font-lock-keyword-face)
114
'("\\<\\(true\\|false\\|C_NULL\\|Inf\\|NaN\\|Inf32\\|NaN32\\|nothing\\)\\>" . font-lock-constant-face)
115
(list julia-unquote-regex 2 'font-lock-constant-face)
116
(list julia-char-regex 2 'font-lock-string-face)
117
(list julia-forloop-in-regex 1 'font-lock-keyword-face)
118
;; (cons ess-subset-regexp 'font-lock-constant-face)
119
(cons "\\(\\sw+!?\\) ?(" '(1 font-lock-function-name-face keep))
120
;(list julia-string-regex 0 'font-lock-string-face)
121
))
122
123
(defconst julia-block-start-keywords
124
(list "if" "while" "for" "begin" "try" "function" "type" "let" "macro"
125
"quote" "do" "immutable"))
126
127
(defconst julia-block-other-keywords
128
(list "else" "elseif"))
129
130
(defconst julia-block-end-keywords
131
(list "end" "else" "elseif" "catch" "finally"))
132
133
(defun julia-at-keyword (kw-list)
134
"Return the word at point if it matches any keyword in KW-LIST.
135
KW-LIST is a list of strings. The word at point is not
136
considered a keyword if used as a field name, X.word, or
137
quoted, :word, or it is part of Julia's comprehension syntax."
138
(and (or (= (point) 1)
139
(and (not (equal (char-before (point)) ?.))
140
(not (equal (char-before (point)) ?:))))
141
(not (ess-inside-string-or-comment-p (point)))
142
(not (ess-inside-brackets-p (point) t))
143
(member (current-word) kw-list)))
144
145
(defun julia-last-open-block-pos (min)
146
"Move back and return the position of the last open block, if one found.
147
Do not move back beyond position MIN."
148
(let ((count 0))
149
(while (not (or (> count 0) (<= (point) min)))
150
(backward-word 1)
151
(setq count
152
(cond ((julia-at-keyword julia-block-start-keywords)
153
(+ count 1))
154
((and (equal (current-word) "end")
155
(not (ess-inside-comment-p))
156
(not (ess-inside-brackets-p)))
157
(- count 1))
158
(t count))))
159
(if (> count 0)
160
(point)
161
nil)))
162
163
(defun julia-last-open-block (min)
164
"Move back and return indentation level for last open block.
165
Do not move back beyond MIN."
166
(let ((pos (julia-last-open-block-pos min)))
167
(and pos
168
(progn
169
(goto-char pos)
170
(+ julia-basic-offset (current-indentation))))))
171
172
(defun julia-form-indent ()
173
"Return indent implied by a special form opening on the previous line."
174
(forward-line -1)
175
(end-of-line)
176
(backward-sexp)
177
(if (julia-at-keyword julia-block-other-keywords)
178
(+ julia-basic-offset (current-indentation))
179
(if (char-equal (char-after (point)) ?\()
180
(progn
181
(backward-word 1)
182
(let ((cur (current-indentation)))
183
(if (julia-at-keyword julia-block-start-keywords)
184
(+ julia-basic-offset cur)
185
nil)))
186
nil)))
187
188
(defun julia-paren-indent ()
189
"Return indent by last opening paren."
190
(let* ((p (parse-partial-sexp
191
(save-excursion
192
;; only indent by paren if the last open
193
;; paren is closer than the last open
194
;; block
195
(or (julia-last-open-block-pos (point-min))
196
(point-min)))
197
(point-at-bol)))
198
(pos (cadr p)))
199
(if (or (= 0 (car p)) (null pos))
200
nil
201
(progn (goto-char pos) (+ 1 (current-column))))))
202
203
(defun julia-indent-line ()
204
"Indent current line of julia code."
205
(interactive)
206
(let* ((indent (save-excursion
207
(end-of-line)
208
(or (and (ess-inside-string-p (point-at-bol)) 0)
209
(save-excursion (ignore-errors (julia-form-indent)))
210
(save-excursion (ignore-errors (julia-paren-indent)))
211
;; previous line ends in =
212
(save-excursion
213
(beginning-of-line)
214
(skip-chars-backward " \t\n")
215
(when (eql (char-before) ?=)
216
(+ julia-basic-offset (current-indentation))))
217
(save-excursion
218
(let ((endtok (progn
219
(beginning-of-line)
220
(forward-to-indentation 0)
221
(julia-at-keyword julia-block-end-keywords))))
222
(ignore-errors (+ (julia-last-open-block (point-min))
223
(if endtok (- julia-basic-offset) 0)))))
224
;; take same indentation as previous line
225
(save-excursion (forward-line -1)
226
(current-indentation))
227
0)))
228
(cur-point (point))
229
(cur-indent (progn (back-to-indentation)
230
(point)))
231
(shift (max 0 (- cur-point cur-indent))))
232
(delete-region (point-at-bol) cur-indent)
233
(indent-to indent)
234
(goto-char (+ (point) shift)))
235
(when (julia-at-keyword julia-block-end-keywords)
236
(forward-word 1)))
237
238
(defvar julia-editing-alist
239
'((paragraph-start . (concat "\\s-*$\\|" page-delimiter))
240
(paragraph-separate . (concat "\\s-*$\\|" page-delimiter))
241
(paragraph-ignore-fill-prefix . t)
242
(require-final-newline . mode-require-final-newline)
243
(comment-start . "# ")
244
(comment-add . 1)
245
(comment-start-skip . "#+\\s-*")
246
(comment-column . 40)
247
(ess-indent-line-function . 'julia-indent-line)
248
(indent-line-function . 'julia-indent-line)
249
(parse-sexp-ignore-comments . t)
250
(ess-style . ess-default-style) ;; ignored
251
(ess-local-process-name . nil)
252
(ess-mode-syntax-table . julia-syntax-table)
253
(add-log-current-defun-header-regexp . "^.*function[ \t]*\\([^ \t(]*\\)[ \t]*(")
254
(font-lock-defaults . '(julia-font-lock-keywords nil nil ((?\_ . "w"))))
255
)
256
"General options for julia source files.")
257
258
(defun julia-send-string-function (process string visibly)
259
"Send the Julia STRING to the PROCESS.
260
VISIBLY is not currently used."
261
(let ((file (concat temporary-file-directory "julia_eval_region.jl")))
262
(with-temp-file file
263
(insert string))
264
(process-send-string process (format ess-load-command file))))
265
266
267
;;; HELP
268
(defun julia-get-help-topics (&optional proc)
269
(append (ess-get-words-from-vector "ESS.all_help_topics()\n")
270
(julia--get-objects)))
271
;; (ess-command com)))
272
273
(defun julia--retrive-topics (url)
274
(with-current-buffer (url-retrieve-synchronously url)
275
(require 'url)
276
(goto-char (point-min))
277
(let (out)
278
(while (re-search-forward "toctree.*href=\"\\(.+\\)\">\\(.+\\)</a" nil t)
279
(push (propertize (match-string 2)
280
:manual (concat url (match-string 1)))
281
out))
282
(kill-buffer)
283
(nreverse out))))
284
285
(defvar julia--manual-topics nil)
286
(defun julia-manual-lookup-function (&rest args) ; args are not used
287
(interactive)
288
"Look up topics at http://docs.julialang.org/en/latest/manual/"
289
;; <li class="toctree-l1"><a class="reference internal" href="introduction/">Introduction</a></li>
290
(let* ((pages (or julia--manual-topics
291
(setq julia--manual-topics
292
(julia--retrive-topics "http://docs.julialang.org/en/latest/manual/"))))
293
(page (ess-completing-read "Lookup:" pages nil t)))
294
(browse-url (get-text-property 1 :manual page))))
295
296
;; julia 0.3.0 doesn't provide categories. Thus we don't support this anymore.
297
;; (defun julia-reference-lookup-function (&rest args) ; args are not used
298
;; (interactive)
299
;; "Look up reference topics"
300
;; ;; <li class="toctree-l1"><a class="reference internal" href="introduction/">Introduction</a></li>
301
;; (let* ((pages (ess-get-words-from-vector "ESS.help_categories()\n")))
302
;; (ess-display-help-on-object
303
;; (ess-completing-read "Category" pages nil t))))
304
305
306
307
;;; COMPLETION
308
(defun julia-object-completion ()
309
"Return completions at point in a format required by `completion-at-point-functions'. "
310
(let ((proc (ess-get-next-available-process ess-dialect t))
311
(beg (ess-symbol-start)))
312
(if proc
313
(when beg
314
(let* ((prefix (buffer-substring-no-properties beg (point)))
315
(obj (and (string-match "\\(.*\\)\\..*$" prefix)
316
(match-string 1 prefix)))
317
(beg (if obj
318
(+ beg 1 (length obj))
319
beg)))
320
(list beg (point)
321
(nreverse (mapcar 'car (julia--get-objects proc obj)))
322
:exclusive 'no)))
323
(when (string-match "complet" (symbol-name last-command))
324
(message "No ESS process of dialect %s started" ess-dialect)
325
nil))))
326
327
(defun julia--get-objects (&optional proc obj)
328
"Return all available objects.
329
Local caching might be used. If MODULE is givven, return only
330
objects from that MODULE."
331
(setq proc (or proc
332
(get-process ess-local-process-name)))
333
(when (process-live-p proc)
334
(let ((objects (process-get proc 'objects)))
335
(if (process-get proc 'busy)
336
(if obj
337
(assoc obj objects)
338
(process-get proc 'objects))
339
(if obj
340
(or (cdr (assoc obj objects))
341
;; don't cache composite objects and datatypes
342
(julia--get-components proc obj))
343
;; this segment is entered when user completon at top level is
344
;; requested, either Tab or AC. Hence Main is always updated.
345
(let ((modules (ess-get-words-from-vector
346
"ESS.main_modules()\n" nil nil proc))
347
(loc (process-get proc 'last-objects-cache))
348
(lev (process-get proc 'last-eval)))
349
(prog1
350
(apply #'nconc
351
(mapcar
352
(lambda (mod)
353
;; we are caching all modules, and reinit Main every
354
;; time user enters commands
355
(copy-sequence
356
(or (and (or (not (equal mod "Main"))
357
(ignore-errors (time-less-p lev loc)))
358
(cdr (assoc mod objects)))
359
(julia--get-components proc mod t))))
360
modules))
361
(process-put proc 'last-objects-cache (current-time)))))))))
362
363
(defun julia--get-components (proc obj &optional cache?)
364
(with-current-buffer (ess-command (format "ESS.components(%s)\n" obj)
365
nil nil nil nil proc)
366
(goto-char (point-min))
367
(let (list)
368
(while (re-search-forward
369
"^\\([^ \t\n]+\\) +\\([^ \t\n]+\\)$" nil t)
370
(push (cons (match-string 1) (match-string 2)) list))
371
(when cache?
372
(let ((objects (process-get proc 'objects)))
373
(push (cons obj list) objects)
374
(process-put proc 'objects objects)))
375
list)))
376
377
378
;;; AC
379
(defvar ac-source-julia-objects
380
'((prefix . ess-symbol-start)
381
(requires . 2)
382
(candidates . ess-ac-julia-objects)
383
(document . ess-ac-help-object)
384
)
385
"Auto-completion source for julia objects")
386
387
(defun ess-ac-julia-objects ()
388
"Get all cached objects"
389
(let ((aprf ac-prefix))
390
(let ((proc (ess-get-next-available-process nil t)))
391
(when aprf
392
(if (string-match "\\(.*\\)\\..*$" aprf)
393
(let ((module (match-string 1 aprf)))
394
(mapcar (lambda (el) (concat module "." (car el)))
395
(julia--get-objects proc module)))
396
(julia--get-objects proc))))))
397
398
399
400
;;; ERRORS
401
(defvar julia-error-regexp-alist '(julia-in julia-at julia-while-load)
402
"List of symbols which are looked up in `compilation-error-regexp-alist-alist'.")
403
404
(add-to-list 'compilation-error-regexp-alist-alist
405
'(julia-in "^\\s-*in [^ \t\n]* \\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1))
406
(add-to-list 'compilation-error-regexp-alist-alist
407
'(julia-at "^\\S-+\\s-+\\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1))
408
(add-to-list 'compilation-error-regexp-alist-alist
409
'(julia-while-load "^\\s-*\\(while loading\\s-\\(.*\\), in .* on line +\\([0-9]+\\)\\)" 2 3 nil 2 1))
410
411
412
;;; ELDOC
413
(defun julia-eldoc-function ()
414
"Return the doc string, or nil.
415
If an ESS process is not associated with the buffer, do not try
416
to look up any doc strings."
417
(interactive)
418
(when (and (ess-process-live-p)
419
(not (ess-process-get 'busy)))
420
(let ((funname (or (and ess-eldoc-show-on-symbol ;; aggressive completion
421
(symbol-at-point))
422
(car (ess--funname.start)))))
423
(when funname
424
(let* ((args (copy-sequence (nth 2 (ess-function-arguments funname))))
425
(W (- (window-width (minibuffer-window)) (+ 4 (length funname))))
426
(doc (concat (propertize funname 'face font-lock-function-name-face) ": ")))
427
(when args
428
(setq args (sort args (lambda (s1 s2)
429
(< (length s1) (length s2)))))
430
(setq doc (concat doc (pop args)))
431
(while (and args (< (+ (length doc) (length (car args))) W))
432
(setq doc (concat doc " "
433
(pop args))))
434
(when (and args (< (length doc) W))
435
(setq doc (concat doc " {--}"))))
436
doc)))))
437
438
439
;;; IMENU
440
(defvar julia-imenu-generic-expression
441
;; don't use syntax classes, screws egrep
442
'(("Function (_)" "[ \t]*function[ \t]+\\(_[^ \t\n]*\\)" 1)
443
("Function" "^[ \t]*function[ \t]+\\([^_][^\t\n]*\\)" 1)
444
("Const" "[ \t]*const \\([^ \t\n]*\\)" 1)
445
("Type" "^[ \t]*[a-zA-Z0-9_]*type[a-zA-Z0-9_]* \\([^ \t\n]*\\)" 1)
446
("Require" " *\\(\\brequire\\)(\\([^ \t\n)]*\\)" 2)
447
("Include" " *\\(\\binclude\\)(\\([^ \t\n)]*\\)" 2)
448
))
449
450
451
;;; CORE
452
(defvar julia-customize-alist
453
'((comint-use-prompt-regexp . t)
454
(ess-eldoc-function . 'julia-eldoc-function)
455
(inferior-ess-primary-prompt . "a> ") ;; from julia>
456
(inferior-ess-secondary-prompt . nil)
457
(inferior-ess-prompt . "\\w*> ")
458
(ess-local-customize-alist . 'julia-customize-alist)
459
(inferior-ess-program . inferior-julia-program-name)
460
(inferior-ess-font-lock-defaults . julia-font-lock-keywords)
461
(ess-get-help-topics-function . 'julia-get-help-topics)
462
(ess-help-web-search-command . "http://docs.julialang.org/en/latest/search/?q=%s")
463
(ess-manual-lookup-command . 'julia-manual-lookup-function)
464
;; (ess-reference-lookup-command . 'julia-reference-lookup-function)
465
(ess-load-command . "include(\"%s\")\n")
466
(ess-funargs-command . "ESS.fun_args(\"%s\")\n")
467
(ess-dump-error-re . "in \\w* at \\(.*\\):[0-9]+")
468
(ess-error-regexp . "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)")
469
(ess-error-regexp-alist . julia-error-regexp-alist)
470
(ess-send-string-function . nil);'julia-send-string-function)
471
(ess-imenu-generic-expression . julia-imenu-generic-expression)
472
;; (inferior-ess-objects-command . inferior-R-objects-command)
473
;; (inferior-ess-search-list-command . "search()\n")
474
(inferior-ess-help-command . "ESS.help(\"%s\")\n")
475
;; (inferior-ess-help-command . "help(\"%s\")\n")
476
(ess-language . "julia")
477
(ess-dialect . "julia")
478
(ess-suffix . "jl")
479
(ess-ac-sources . '(ac-source-julia-objects))
480
(ess-dump-filename-template . (ess-replace-regexp-in-string
481
"S$" ess-suffix ; in the one from custom:
482
ess-dump-filename-template-proto))
483
(ess-mode-syntax-table . julia-syntax-table)
484
(ess-mode-editing-alist . julia-editing-alist)
485
(ess-change-sp-regexp . nil );ess-R-change-sp-regexp)
486
(ess-help-sec-regex . ess-help-R-sec-regex)
487
(ess-help-sec-keys-alist . ess-help-R-sec-keys-alist)
488
(ess-loop-timeout . ess-S-loop-timeout);fixme: dialect spec.
489
(ess-cmd-delay . ess-R-cmd-delay)
490
(ess-function-pattern . ess-R-function-pattern)
491
(ess-object-name-db-file . "ess-jl-namedb.el" )
492
(ess-smart-operators . ess-R-smart-operators)
493
(inferior-ess-help-filetype . nil)
494
(inferior-ess-exit-command . "exit()\n")
495
;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
496
(inferior-ess-start-file . nil) ;; "~/.ess-R"
497
(inferior-ess-start-args . "")
498
(inferior-ess-language-start . nil)
499
(ess-STERM . "iESS")
500
(ess-editor . R-editor)
501
(ess-pager . R-pager)
502
)
503
"Variables to customize for Julia -- set up later than emacs initialization.")
504
505
(defvar julia-versions '("julia")
506
"List of partial strings for versions of Julia to access within ESS.
507
Each string specifies the start of a filename. If a filename
508
beginning with one of these strings is found on `exec-path', a M-x
509
command for that version of Julia is made available.")
510
511
(defcustom inferior-julia-args ""
512
"String of arguments (see 'julia --help') used when starting julia."
513
;; These arguments are currently not passed to other versions of julia that have
514
;; been created using the variable `ess-r-versions'."
515
:group 'ess-julia
516
:type 'string)
517
518
;;;###autoload
519
(defun julia-mode (&optional proc-name)
520
"Major mode for editing julia source. See `ess-mode' for more help."
521
(interactive "P")
522
;; (setq ess-customize-alist julia-customize-alist)
523
(ess-mode julia-customize-alist proc-name)
524
;; for emacs >= 24
525
(remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first
526
(add-hook 'completion-at-point-functions 'julia-object-completion nil 'local)
527
(add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local)
528
(if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
529
(set (make-local-variable 'end-of-defun-function) 'ess-end-of-function)
530
;; (local-set-key "\t" 'julia-indent-line) ;; temp workaround
531
;; (set (make-local-variable 'indent-line-function) 'julia-indent-line)
532
(set (make-local-variable 'julia-basic-offset) 4)
533
(setq imenu-generic-expression julia-imenu-generic-expression)
534
(imenu-add-to-menubar "Imenu-jl")
535
(run-hooks 'julia-mode-hook))
536
537
(defvar julia-mode-hook nil)
538
(defvar julia-post-run-hook nil
539
"Functions run in process buffer after starting julia process.")
540
541
;;;###autoload
542
(defun julia (&optional start-args)
543
"Call 'julia'.
544
Optional prefix (C-u) allows to set command line arguments, such as
545
--load=<file>. This should be OS agnostic.
546
If you have certain command line arguments that should always be passed
547
to julia, put them in the variable `inferior-julia-args'."
548
(interactive "P")
549
;; get settings, notably inferior-julia-program-name :
550
(if (null inferior-julia-program-name)
551
(error "'inferior-julia-program-name' does not point to 'julia' or 'julia-basic' executable")
552
(setq ess-customize-alist julia-customize-alist)
553
(ess-write-to-dribble-buffer ;; for debugging only
554
(format
555
"\n(julia): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n"
556
ess-dialect (current-buffer) start-args current-prefix-arg))
557
(let* ((jl-start-args
558
(concat inferior-julia-args " " ; add space just in case
559
(if start-args
560
(read-string
561
(concat "Starting Args"
562
(if inferior-julia-args
563
(concat " [other than '" inferior-julia-args "']"))
564
" ? "))
565
nil))))
566
(inferior-ess jl-start-args)
567
568
(remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first
569
(add-hook 'completion-at-point-functions 'julia-object-completion nil 'local)
570
(add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local)
571
572
(ess--tb-start)
573
(set (make-local-variable 'julia-basic-offset) 4)
574
;; remove ` from julia's logo
575
(goto-char (point-min))
576
(while (re-search-forward "`" nil t)
577
(replace-match "'"))
578
(goto-char (point-max))
579
;; --> julia helpers from ../etc/ess-julia.jl :
580
(ess--inject-code-from-file (format "%sess-julia.jl" ess-etc-directory))
581
(with-ess-process-buffer nil
582
(run-mode-hooks 'julia-post-run-hook))
583
)))
584
585
(add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode))
586
587
(provide 'ess-julia)
588
589
;;; ess-julia.el ends here
590
591