mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			474 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
			
		
		
	
	
			474 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
	
	
;; ess-julia.el --- ESS julia mode and inferior interaction
 | 
						|
;;
 | 
						|
;; Copyright (C) 2012 Vitalie Spinu.
 | 
						|
;;
 | 
						|
;; Filename: ess-julia.el
 | 
						|
;; Author: Vitalie Spinu (based on julia-mode.el from julia-lang project)
 | 
						|
;; Maintainer: Vitalie Spinu
 | 
						|
;; Created: 02-04-2012 (ESS 12.03)
 | 
						|
;; Keywords: ESS, julia
 | 
						|
;;
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;;
 | 
						|
;; This file is *NOT* part of GNU Emacs.
 | 
						|
;; This file is part of ESS
 | 
						|
;;
 | 
						|
;; This program is free software; you can redistribute it and/or
 | 
						|
;; modify it under the terms of the GNU General Public License as
 | 
						|
;; published by the Free Software Foundation; either version 3, any later version.
 | 
						|
;;
 | 
						|
;; This program is distributed in the hope that it will be useful, but WITHOUT
 | 
						|
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
						|
;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
						|
;; details.
 | 
						|
;;
 | 
						|
;; You should have received a copy of the GNU General Public License along with
 | 
						|
;; this program; see the file COPYING.  If not, write to the Free Software
 | 
						|
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 | 
						|
;; USA.
 | 
						|
;;
 | 
						|
;;
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;;
 | 
						|
;;; Commentary:
 | 
						|
;;  customise inferior-julia-program-name to point to your julia-release-basic
 | 
						|
;;  and start the inferior with M-x julia.
 | 
						|
;;
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;;
 | 
						|
(require 'compile); for compilation-* below
 | 
						|
 | 
						|
;;; Code:
 | 
						|
 | 
						|
(defvar julia-mode-hook nil)
 | 
						|
 | 
						|
(add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode))
 | 
						|
 | 
						|
(defvar julia-syntax-table
 | 
						|
  (let ((table (make-syntax-table)))
 | 
						|
    (modify-syntax-entry ?_ "_" table)   ; underscores in words
 | 
						|
    (modify-syntax-entry ?@ "_" table)
 | 
						|
    (modify-syntax-entry ?. "_" table)
 | 
						|
    (modify-syntax-entry ?# "<" table)   ; #  single-line comment start
 | 
						|
    (modify-syntax-entry ?\n ">" table)  ; \n single-line comment end
 | 
						|
    (modify-syntax-entry ?\{ "(} " table)
 | 
						|
    (modify-syntax-entry ?\} "){ " table)
 | 
						|
    (modify-syntax-entry ?\[ "(] " table)
 | 
						|
    (modify-syntax-entry ?\] ")[ " table)
 | 
						|
    (modify-syntax-entry ?\( "() " table)
 | 
						|
    (modify-syntax-entry ?\) ")( " table)
 | 
						|
    ;(modify-syntax-entry ?\\ "." table)  ; \ is an operator outside quotes
 | 
						|
    (modify-syntax-entry ?'  "." table)  ; character quote or transpose
 | 
						|
    (modify-syntax-entry ?\" "\"" table)
 | 
						|
    (modify-syntax-entry ?` "\"" table)
 | 
						|
    ;; (modify-syntax-entry ?\" "." table)
 | 
						|
    (modify-syntax-entry ?? "." table)
 | 
						|
    (modify-syntax-entry ?$ "." table)
 | 
						|
    (modify-syntax-entry ?& "." table)
 | 
						|
    (modify-syntax-entry ?* "." table)
 | 
						|
    (modify-syntax-entry ?+ "." table)
 | 
						|
    (modify-syntax-entry ?- "." table)
 | 
						|
    (modify-syntax-entry ?< "." table)
 | 
						|
    (modify-syntax-entry ?> "." table)
 | 
						|
    (modify-syntax-entry ?= "." table)
 | 
						|
    (modify-syntax-entry ?% "." table)
 | 
						|
    table)
 | 
						|
  "Syntax table for julia-mode")
 | 
						|
 | 
						|
;; syntax table that holds within strings
 | 
						|
(defvar julia-mode-string-syntax-table
 | 
						|
  (let ((table (make-syntax-table)))
 | 
						|
    table)
 | 
						|
  "Syntax table for julia-mode")
 | 
						|
 | 
						|
;; disable " inside char quote
 | 
						|
(defvar julia-mode-char-syntax-table
 | 
						|
  (let ((table (make-syntax-table)))
 | 
						|
    (modify-syntax-entry ?\" "." table)
 | 
						|
    table)
 | 
						|
  "Syntax table for julia-mode")
 | 
						|
 | 
						|
;; not used
 | 
						|
;; (defconst julia-string-regex
 | 
						|
;;   "\"[^\"]*?\\(\\(\\\\\\\\\\)*\\\\\"[^\"]*?\\)*\"")
 | 
						|
 | 
						|
(defconst julia-char-regex
 | 
						|
  "\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|$!\\^~\\\\;:]\\|^\\)\\('\\(\\([^']*?[^\\\\]\\)\\|\\(\\\\\\\\\\)\\)'\\)")
 | 
						|
 | 
						|
(defconst julia-unquote-regex
 | 
						|
  "\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|!\\^~\\\\;:]\\|^\\)\\($[a-zA-Z0-9_]+\\)")
 | 
						|
 | 
						|
(defconst julia-forloop-in-regex
 | 
						|
  "for +[^ 	
 | 
						|
]+ +.*\\(in\\)\\(\\s-\\|$\\)+")
 | 
						|
 | 
						|
(defconst ess-subset-regexp
 | 
						|
      "\\[[0-9:, ]*\\]" )
 | 
						|
 | 
						|
(defconst julia-font-lock-defaults
 | 
						|
  (list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\)\\|Int\\(8\\|16\\|32\\|64\\)\\|Integer\\|Float\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexNum\\|Bool\\|Char\\|Number\\|Scalar\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Buffer\\|Size\\|Index\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|PtrInt\\|Long\\|Ulong\\)\\>" .
 | 
						|
      font-lock-type-face)
 | 
						|
    (cons
 | 
						|
     (concat "\\<\\("
 | 
						|
         (mapconcat
 | 
						|
          'identity
 | 
						|
          '("if" "else" "elseif" "while" "for" "begin" "end" "quote"
 | 
						|
            "try" "catch" "return" "local" "abstract" "function" "macro" "ccall"
 | 
						|
	    "typealias" "break" "continue" "type" "global" "@\\w+"
 | 
						|
	    "module" "import" "export" "const" "let" "bitstype" "using")
 | 
						|
          "\\|") "\\)\\>")
 | 
						|
     'font-lock-keyword-face)
 | 
						|
    '("\\<\\(true\\|false\\|C_NULL\\|Inf\\|NaN\\|Inf32\\|NaN32\\)\\>" . font-lock-constant-face)
 | 
						|
    (list julia-unquote-regex 2 'font-lock-constant-face)
 | 
						|
    (list julia-char-regex 2 'font-lock-string-face)
 | 
						|
    (list julia-forloop-in-regex 1 'font-lock-keyword-face)
 | 
						|
    ;; (cons ess-subset-regexp 'font-lock-constant-face)
 | 
						|
    (cons "\\(\\sw+\\) ?(" '(1 font-lock-function-name-face keep))
 | 
						|
    ;(list julia-string-regex 0 'font-lock-string-face)
 | 
						|
))
 | 
						|
 | 
						|
(defconst julia-block-start-keywords
 | 
						|
  (list "if" "while" "for" "begin" "try" "function" "type" "let" "macro"
 | 
						|
	"quote"))
 | 
						|
 | 
						|
(defconst julia-block-other-keywords
 | 
						|
  (list "else" "elseif"))
 | 
						|
 | 
						|
(defconst julia-block-end-keywords
 | 
						|
  (list "end" "else" "elseif" "catch"))
 | 
						|
 | 
						|
(defun ess-inside-brackets-p (&optional pos)
 | 
						|
  (save-excursion
 | 
						|
    (let* ((pos (or pos (point)))
 | 
						|
	   (beg (re-search-backward "\\[" (max (point-min) (- pos 1000)) t))
 | 
						|
	   (end (re-search-forward "\\]" (min (point-max) (+ pos 1000)) t)))
 | 
						|
    (and beg end (> pos beg) (> end pos)))))
 | 
						|
 | 
						|
(defun julia-at-keyword (kw-list)
 | 
						|
  ; not a keyword if used as a field name, X.word, or quoted, :word
 | 
						|
  (and (or (= (point) 1)
 | 
						|
	   (and (not (equal (char-before (point)) ?.))
 | 
						|
		(not (equal (char-before (point)) ?:))))
 | 
						|
       (not (ess-inside-string-or-comment-p (point)))
 | 
						|
       (not (ess-inside-brackets-p (point)))
 | 
						|
       (member (current-word) kw-list)))
 | 
						|
 | 
						|
; get the position of the last open block
 | 
						|
(defun julia-last-open-block-pos (min)
 | 
						|
  (let ((count 0))
 | 
						|
    (while (not (or (> count 0) (<= (point) min)))
 | 
						|
      (backward-word 1)
 | 
						|
      (setq count
 | 
						|
	    (cond ((julia-at-keyword julia-block-start-keywords)
 | 
						|
		   (+ count 1))
 | 
						|
		  ((and (equal (current-word) "end")
 | 
						|
			(not (ess-inside-comment-p)) (not (ess-inside-brackets-p)))
 | 
						|
		   (- count 1))
 | 
						|
		  (t count))))
 | 
						|
    (if (> count 0)
 | 
						|
	(point)
 | 
						|
      nil)))
 | 
						|
 | 
						|
; get indent for last open block
 | 
						|
(defun julia-last-open-block (min)
 | 
						|
  (let ((pos (julia-last-open-block-pos min)))
 | 
						|
    (and pos
 | 
						|
	 (progn
 | 
						|
	   (goto-char pos)
 | 
						|
	   (+ julia-basic-offset (current-indentation))))))
 | 
						|
 | 
						|
; return indent implied by a special form opening on the previous line, if any
 | 
						|
(defun julia-form-indent ()
 | 
						|
  (forward-line -1)
 | 
						|
  (end-of-line)
 | 
						|
  (backward-sexp)
 | 
						|
  (if (julia-at-keyword julia-block-other-keywords)
 | 
						|
      (+ julia-basic-offset (current-indentation))
 | 
						|
    (if (char-equal (char-after (point)) ?\()
 | 
						|
        (progn
 | 
						|
          (backward-word 1)
 | 
						|
          (let ((cur (current-indentation)))
 | 
						|
            (if (julia-at-keyword julia-block-start-keywords)
 | 
						|
                (+ julia-basic-offset cur)
 | 
						|
              nil)))
 | 
						|
      nil)))
 | 
						|
 | 
						|
(defun julia-paren-indent ()
 | 
						|
  (let* ((p (parse-partial-sexp (save-excursion
 | 
						|
				  ;; only indent by paren if the last open
 | 
						|
				  ;; paren is closer than the last open
 | 
						|
				  ;; block
 | 
						|
				  (or (julia-last-open-block-pos (point-min))
 | 
						|
				      (point-min)))
 | 
						|
				(progn (beginning-of-line)
 | 
						|
				       (point))))
 | 
						|
         (pos (cadr p)))
 | 
						|
    (if (or (= 0 (car p)) (null pos))
 | 
						|
        nil
 | 
						|
      (progn (goto-char pos) (+ 1 (current-column))))))
 | 
						|
					;  (forward-line -1)
 | 
						|
					;  (end-of-line)
 | 
						|
					;  (let ((pos (condition-case nil
 | 
						|
					;                (scan-lists (point) -1 1)
 | 
						|
					;              (error nil))))
 | 
						|
					;   (if pos
 | 
						|
					;       (progn (goto-char pos) (+ 1 (current-column)))
 | 
						|
					;     nil)))
 | 
						|
 | 
						|
(defun julia-indent-line ()
 | 
						|
  "Indent current line of julia code"
 | 
						|
  (interactive)
 | 
						|
					;  (save-excursion
 | 
						|
    (end-of-line)
 | 
						|
    (indent-line-to
 | 
						|
     (or (and (ess-inside-string-p (point-at-bol)) 0)
 | 
						|
	 (save-excursion (ignore-errors (julia-form-indent)))
 | 
						|
         (save-excursion (ignore-errors (julia-paren-indent)))
 | 
						|
         ;; previous line ends in =
 | 
						|
	 (save-excursion
 | 
						|
           (beginning-of-line)
 | 
						|
           (skip-chars-backward " \t\n")
 | 
						|
           (when (eql (char-before) ?=)
 | 
						|
             (+ julia-basic-offset (current-indentation))))
 | 
						|
         (save-excursion
 | 
						|
           (let ((endtok (progn
 | 
						|
                           (beginning-of-line)
 | 
						|
                           (forward-to-indentation 0)
 | 
						|
                           (julia-at-keyword julia-block-end-keywords))))
 | 
						|
             (ignore-errors (+ (julia-last-open-block (point-min))
 | 
						|
                               (if endtok (- julia-basic-offset) 0)))))
 | 
						|
	 ;; take same indentation as previous line
 | 
						|
	 (save-excursion (forward-line -1)
 | 
						|
			 (current-indentation))
 | 
						|
         0))
 | 
						|
    (when (julia-at-keyword julia-block-end-keywords)
 | 
						|
      (forward-word 1)))
 | 
						|
 | 
						|
(defvar julia-editing-alist
 | 
						|
  '((paragraph-start		  . (concat "\\s-*$\\|" page-delimiter))
 | 
						|
    (paragraph-separate		  . (concat "\\s-*$\\|" page-delimiter))
 | 
						|
    (paragraph-ignore-fill-prefix . t)
 | 
						|
    (require-final-newline	  . t)
 | 
						|
    (comment-start		  . "# ")
 | 
						|
    (comment-add                  . 1)
 | 
						|
    (comment-start-skip		  . "#+\\s-*")
 | 
						|
    (comment-column		  . 40)
 | 
						|
    ;;(comment-indent-function	. 'S-comment-indent)
 | 
						|
    ;;(ess-comment-indent	    . 'S-comment-indent)
 | 
						|
    ;; (ess-indent-line			    . 'S-indent-line)
 | 
						|
    ;;(ess-calculate-indent	      . 'ess-calculate-indent)
 | 
						|
    (ess-indent-line-function	  . 'julia-indent-line)
 | 
						|
    (indent-line-function	  . 'julia-indent-line)
 | 
						|
    (parse-sexp-ignore-comments	  . t)
 | 
						|
    (ess-style		  	  . ess-default-style) ;; ignored
 | 
						|
    (ess-local-process-name	  . nil)
 | 
						|
    ;;(ess-keep-dump-files	    . 'ask)
 | 
						|
    (ess-mode-syntax-table	  . julia-syntax-table)
 | 
						|
    ;; For Changelog add, require ' ' before <- : "attr<-" is a function name :
 | 
						|
    ;; (add-log-current-defun-header-regexp . "^\\(.+\\)\\s-+=[ \t\n]*function")
 | 
						|
    (add-log-current-defun-header-regexp . "^.*function[ \t]*\\([^ \t(]*\\)[ \t]*(")
 | 
						|
    (font-lock-defaults		  . '(julia-font-lock-defaults
 | 
						|
                                      nil nil ((?\_ . "w"))))
 | 
						|
    )
 | 
						|
  "General options for julia source files.")
 | 
						|
 | 
						|
(autoload 'inferior-ess "ess-inf" "Run an ESS process.")
 | 
						|
(autoload 'ess-mode     "ess-mode" "Edit an ESS process.")
 | 
						|
 | 
						|
(defun julia-send-string-function (process string visibly)
 | 
						|
  (let ((file (concat temporary-file-directory "julia_eval_region.jl")))
 | 
						|
    (with-temp-file file
 | 
						|
      (insert string))
 | 
						|
    (process-send-string process (format ess-load-command file))))
 | 
						|
 | 
						|
(defun julia-get-help-topics (&optional proc)
 | 
						|
  (ess-get-words-from-vector "ESS.all_help_topics()\n"))
 | 
						|
    ;; (ess-command com)))
 | 
						|
 | 
						|
(defvar julia-help-command "help(\"%s\")\n")
 | 
						|
 | 
						|
(defvar ess-julia-error-regexp-alist '(julia-in julia-at)
 | 
						|
  "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.")
 | 
						|
 | 
						|
(add-to-list 'compilation-error-regexp-alist-alist
 | 
						|
             '(julia-in  "^\\s-*in [^ \t\n]* \\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1))
 | 
						|
(add-to-list 'compilation-error-regexp-alist-alist
 | 
						|
             '(julia-at "^\\S-+\\s-+\\(at \\(.*\\):\\([0-9]+\\)\\)"  2 3 nil 2 1))
 | 
						|
 | 
						|
(defvar julia-customize-alist
 | 
						|
  '((comint-use-prompt-regexp		. t)
 | 
						|
    (ess-eldoc-function           . 'ess-julia-eldoc-function)
 | 
						|
    (inferior-ess-primary-prompt	. "a> ") ;; from julia>
 | 
						|
    (inferior-ess-secondary-prompt	. nil)
 | 
						|
    (inferior-ess-prompt		. "\\w*> ")
 | 
						|
    (ess-local-customize-alist		. 'julia-customize-alist)
 | 
						|
    (inferior-ess-program		. inferior-julia-program-name)
 | 
						|
    (inferior-ess-font-lock-defaults	. julia-font-lock-defaults)
 | 
						|
    (ess-get-help-topics-function	. 'julia-get-help-topics)
 | 
						|
    (ess-help-web-search-command        . "http://docs.julialang.org/en/latest/search/?q=%s")
 | 
						|
    (ess-load-command   		. "include(\"%s\")\n")
 | 
						|
    (ess-funargs-command                . "ESS.fun_args(\"%s\")\n")
 | 
						|
    (ess-dump-error-re			. "in \\w* at \\(.*\\):[0-9]+")
 | 
						|
    (ess-error-regexp			. "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)")
 | 
						|
    (ess-error-regexp-alist		. ess-julia-error-regexp-alist)
 | 
						|
    (ess-send-string-function		. nil);'julia-send-string-function)
 | 
						|
    (ess-imenu-generic-expression       . julia-imenu-generic-expression)
 | 
						|
    ;; (inferior-ess-objects-command	. inferior-R-objects-command)
 | 
						|
    ;; (inferior-ess-search-list-command	. "search()\n")
 | 
						|
    (inferior-ess-help-command		. julia-help-command)
 | 
						|
    ;; (inferior-ess-help-command	. "help(\"%s\")\n")
 | 
						|
    (ess-language			. "julia")
 | 
						|
    (ess-dialect			. "julia")
 | 
						|
    (ess-suffix				. "jl")
 | 
						|
    (ess-dump-filename-template		. (ess-replace-regexp-in-string
 | 
						|
					   "S$" ess-suffix ; in the one from custom:
 | 
						|
					   ess-dump-filename-template-proto))
 | 
						|
    (ess-mode-syntax-table		. julia-syntax-table)
 | 
						|
    (ess-mode-editing-alist	        . julia-editing-alist)
 | 
						|
    (ess-change-sp-regexp		. nil );ess-R-change-sp-regexp)
 | 
						|
    (ess-help-sec-regex			. ess-help-R-sec-regex)
 | 
						|
    (ess-help-sec-keys-alist		. ess-help-R-sec-keys-alist)
 | 
						|
    (ess-loop-timeout			. ess-S-loop-timeout);fixme: dialect spec.
 | 
						|
    (ess-cmd-delay			. ess-R-cmd-delay)
 | 
						|
    (ess-function-pattern		. ess-R-function-pattern)
 | 
						|
    (ess-object-name-db-file		. "ess-r-namedb.el" )
 | 
						|
    (ess-smart-operators		. ess-R-smart-operators)
 | 
						|
    (inferior-ess-help-filetype        . nil)
 | 
						|
    (inferior-ess-exit-command		. "exit()\n")
 | 
						|
    ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
 | 
						|
    (inferior-ess-start-file		. nil) ;; "~/.ess-R"
 | 
						|
    (inferior-ess-start-args		. "")
 | 
						|
    (inferior-ess-language-start	. nil)
 | 
						|
    (ess-STERM		. "iESS")
 | 
						|
    (ess-editor	. R-editor)
 | 
						|
    (ess-pager		. R-pager)
 | 
						|
    )
 | 
						|
  "Variables to customize for Julia -- set up later than emacs initialization.")
 | 
						|
 | 
						|
 | 
						|
(defvar ess-julia-versions '("julia")
 | 
						|
  "List of partial strings for versions of Julia to access within ESS.
 | 
						|
Each string specifies the start of a filename.  If a filename
 | 
						|
beginning with one of these strings is found on `exec-path', a M-x
 | 
						|
command for that version of Julia is made available.  ")
 | 
						|
 | 
						|
(defcustom inferior-julia-args ""
 | 
						|
  "String of arguments (see 'julia --help') used when starting julia."
 | 
						|
;; These arguments are currently not passed to other versions of julia that have
 | 
						|
;; been created using the variable `ess-r-versions'."
 | 
						|
  :group 'ess-julia
 | 
						|
  :type 'string)
 | 
						|
 | 
						|
;;;###autoload
 | 
						|
(defun julia-mode  (&optional proc-name)
 | 
						|
  "Major mode for editing julia source.  See `ess-mode' for more help."
 | 
						|
  (interactive "P")
 | 
						|
  ;; (setq ess-customize-alist julia-customize-alist)
 | 
						|
  (ess-mode julia-customize-alist proc-name)
 | 
						|
  ;; for emacs < 24
 | 
						|
  ;; (add-hook 'comint-dynamic-complete-functions 'ess-complete-object-name nil 'local)
 | 
						|
  ;; for emacs >= 24
 | 
						|
  ;; (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first
 | 
						|
  ;; (add-hook 'completion-at-point-functions 'ess-object-completion nil 'local)
 | 
						|
  ;; (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local)
 | 
						|
  (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
 | 
						|
  (set (make-local-variable 'end-of-defun-function) 'ess-end-of-function)
 | 
						|
  ;; (local-set-key  "\t" 'julia-indent-line) ;; temp workaround
 | 
						|
  ;; (set (make-local-variable 'indent-line-function) 'julia-indent-line)
 | 
						|
  (set (make-local-variable 'julia-basic-offset) 4)
 | 
						|
  (setq imenu-generic-expression julia-imenu-generic-expression)
 | 
						|
  (imenu-add-to-menubar "Imenu-jl")
 | 
						|
  (run-hooks 'julia-mode-hook))
 | 
						|
 | 
						|
 | 
						|
(defvar ess-julia-post-run-hook nil
 | 
						|
  "Functions run in process buffer after the initialization of
 | 
						|
  julia process.")
 | 
						|
 | 
						|
;;;###autoload
 | 
						|
(defun julia (&optional start-args)
 | 
						|
  "Call 'julia',
 | 
						|
Optional prefix (C-u) allows to set command line arguments, such as
 | 
						|
--load=<file>.  This should be OS agnostic.
 | 
						|
If you have certain command line arguments that should always be passed
 | 
						|
to julia, put them in the variable `inferior-julia-args'."
 | 
						|
  (interactive "P")
 | 
						|
  ;; get settings, notably inferior-julia-program-name :
 | 
						|
  (if (null inferior-julia-program-name)
 | 
						|
      (error "'inferior-julia-program-name' does not point to 'julia-release-basic' executable")
 | 
						|
    (setq ess-customize-alist julia-customize-alist)
 | 
						|
    (ess-write-to-dribble-buffer   ;; for debugging only
 | 
						|
     (format
 | 
						|
      "\n(julia): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n"
 | 
						|
      ess-dialect (current-buffer) start-args current-prefix-arg))
 | 
						|
    (let* ((jl-start-args
 | 
						|
	    (concat inferior-julia-args " " ; add space just in case
 | 
						|
		    (if start-args
 | 
						|
			(read-string
 | 
						|
                         (concat "Starting Args"
 | 
						|
                                 (if inferior-julia-args
 | 
						|
                                     (concat " [other than '" inferior-julia-args "']"))
 | 
						|
                                 " ? "))
 | 
						|
		      nil))))
 | 
						|
      (inferior-ess jl-start-args) ;; -> .. (ess-multi ...) -> .. (inferior-ess-mode) ..
 | 
						|
      (ess--tb-start)
 | 
						|
      (set (make-local-variable 'julia-basic-offset) 4)
 | 
						|
      ;; remove ` from julia's logo
 | 
						|
      (goto-char (point-min))
 | 
						|
      (while (re-search-forward "`" nil t)
 | 
						|
        (replace-match "'"))
 | 
						|
      (goto-char (point-max))
 | 
						|
      (ess--inject-code-from-file (format "%sess-julia.jl" ess-etc-directory))
 | 
						|
      (with-ess-process-buffer nil
 | 
						|
        (run-mode-hooks 'ess-julia-post-run-hook))
 | 
						|
      )))
 | 
						|
 | 
						|
;;; ELDOC
 | 
						|
 | 
						|
(defun ess-julia-eldoc-function ()
 | 
						|
  "Return the doc string, or nil.
 | 
						|
If an ESS process is not associated with the buffer, do not try
 | 
						|
to look up any doc strings."
 | 
						|
  (interactive)
 | 
						|
  (when (and (ess-process-live-p)
 | 
						|
             (not (ess-process-get 'busy)))
 | 
						|
    (let ((funname (or (and ess-eldoc-show-on-symbol ;; aggressive completion
 | 
						|
                            (symbol-at-point))
 | 
						|
                       (car (ess--funname.start)))))
 | 
						|
      (when funname
 | 
						|
        (let* ((args (copy-sequence (nth 2 (ess-function-arguments funname))))
 | 
						|
               (W (- (window-width (minibuffer-window)) (+ 4 (length funname))))
 | 
						|
               (doc (concat (propertize funname 'face font-lock-function-name-face) ": ")))
 | 
						|
          (when args
 | 
						|
            (setq args (sort args (lambda (s1 s2)
 | 
						|
                                    (< (length s1) (length s2)))))
 | 
						|
            (setq doc (concat doc (pop args)))
 | 
						|
            (while (and args (< (length doc) W))
 | 
						|
              (setq doc (concat doc "  "
 | 
						|
                                (pop args))))
 | 
						|
            (when (and args (< (length doc) W))
 | 
						|
              (setq doc (concat doc " {--}"))))
 | 
						|
          doc)))))
 | 
						|
 | 
						|
 | 
						|
;;; IMENU
 | 
						|
(defvar julia-imenu-generic-expression
 | 
						|
  ;; don't use syntax classes, screws egrep
 | 
						|
  '(("Function (_)" "[ \t]*function[ \t]+\\(_[^ \t\n]*\\)" 1)
 | 
						|
    ("Function" "[ \t]*function[ \t]+\\([^_][^\t\n]*\\)" 1)
 | 
						|
    ("Const" "[ \t]*const \\([^ \t\n]*\\)" 1)
 | 
						|
    ("Type"  "^[ \t]*[a-zA-Z0-9_]*type[a-zA-Z0-9_]* \\([^ \t\n]*\\)" 1)
 | 
						|
    ("Require"      " *\\(\\brequire\\)(\\([^ \t\n)]*\\)" 2)
 | 
						|
    ("Include"      " *\\(\\binclude\\)(\\([^ \t\n)]*\\)" 2)
 | 
						|
    ;; ("Classes" "^.*setClass(\\(.*\\)," 1)
 | 
						|
    ;; ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to
 | 
						|
    ;; ("Generics" "^.*setGeneric(\\([^,]*\\)," 1)
 | 
						|
    ;; ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\"\\(.+\\)\"," 2)
 | 
						|
    ;; ;;[ ]*\\(signature=\\)?(\\(.*,?\\)*\\)," 1)
 | 
						|
    ;; ;;
 | 
						|
    ;; ;;("Other" "^\\(.+\\)\\s-*<-[ \t\n]*[^\\(function\\|read\\|.*data\.frame\\)]" 1)
 | 
						|
    ;; ("Package" "^.*\\(library\\|require\\)(\\(.*\\)," 2)
 | 
						|
    ;; ("Data" "^\\(.+\\)\\s-*<-[ \t\n]*\\(read\\|.*data\.frame\\).*(" 1)))
 | 
						|
    ))
 | 
						|
 | 
						|
(provide 'ess-julia)
 |