Revert "Combine sclang-mode into the main sclang file"
This reverts commit c414b9c7ab
.
This commit is contained in:
parent
daeb0106c5
commit
19dfecc8ca
6 changed files with 723 additions and 687 deletions
|
@ -23,6 +23,7 @@
|
||||||
(require 'sclang-util)
|
(require 'sclang-util)
|
||||||
(require 'sclang-interp)
|
(require 'sclang-interp)
|
||||||
(require 'sclang-language)
|
(require 'sclang-language)
|
||||||
|
(require 'sclang-mode)
|
||||||
(require 'sclang-vars nil 'ignore-missing-file)
|
(require 'sclang-vars nil 'ignore-missing-file)
|
||||||
(require 'sclang-minor-mode)
|
(require 'sclang-minor-mode)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
(require 'sclang-util)
|
(require 'sclang-util)
|
||||||
|
(require 'sclang-mode)
|
||||||
|
|
||||||
(easy-mmode-define-minor-mode sclang-minor-mode
|
(easy-mmode-define-minor-mode sclang-minor-mode
|
||||||
"Toggle sclang-minor-mode.
|
"Toggle sclang-minor-mode.
|
||||||
|
|
703
el/sclang-mode.el
Normal file
703
el/sclang-mode.el
Normal file
|
@ -0,0 +1,703 @@
|
||||||
|
;; copyright 2003-2005 stefan kersten <steve@k-hornz.de>
|
||||||
|
;;
|
||||||
|
;; 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 2 of the
|
||||||
|
;; License, or (at your option) 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; if not, write to the Free Software
|
||||||
|
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
;; USA
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
;; Make byte-compiler happy by declaring external functions and
|
||||||
|
;; variables.
|
||||||
|
(declare-function company-mode "ext:company")
|
||||||
|
(defvar company-backends)
|
||||||
|
|
||||||
|
(require 'font-lock)
|
||||||
|
(require 'sclang-util)
|
||||||
|
(require 'sclang-interp)
|
||||||
|
(require 'sclang-language)
|
||||||
|
(require 'sclang-dev)
|
||||||
|
|
||||||
|
(defun sclang-fill-syntax-table (table)
|
||||||
|
;; string
|
||||||
|
(modify-syntax-entry ?\" "\"" table)
|
||||||
|
(modify-syntax-entry ?\' "\"" table) ; no string syntax class for single quotes
|
||||||
|
;; expression prefix
|
||||||
|
(modify-syntax-entry ?~ "'" table)
|
||||||
|
;; escape
|
||||||
|
(modify-syntax-entry ?\\ "\\" table)
|
||||||
|
;; character quote
|
||||||
|
(modify-syntax-entry ?$ "/" table)
|
||||||
|
;; symbol
|
||||||
|
(modify-syntax-entry ?_ "_" table)
|
||||||
|
;; symbol/punctuation
|
||||||
|
(modify-syntax-entry ?! "." table)
|
||||||
|
(modify-syntax-entry ?% "." table)
|
||||||
|
(modify-syntax-entry ?& "." table)
|
||||||
|
(modify-syntax-entry ?* ". 23n" table)
|
||||||
|
(modify-syntax-entry ?+ "." table)
|
||||||
|
(modify-syntax-entry ?- "." table)
|
||||||
|
(modify-syntax-entry ?/ ". 124b" 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)
|
||||||
|
;; punctuation
|
||||||
|
(modify-syntax-entry ?: "." table)
|
||||||
|
(modify-syntax-entry ?\; "." table)
|
||||||
|
(modify-syntax-entry ?^ "." table)
|
||||||
|
;; parenthesis
|
||||||
|
(modify-syntax-entry ?\( "()" table)
|
||||||
|
(modify-syntax-entry ?\) ")(" table)
|
||||||
|
(modify-syntax-entry ?\[ "(]" table)
|
||||||
|
(modify-syntax-entry ?\] ")[" table)
|
||||||
|
(modify-syntax-entry ?\{ "(}" table)
|
||||||
|
(modify-syntax-entry ?\} "){" table)
|
||||||
|
;; comment end
|
||||||
|
(modify-syntax-entry ?\n "> b" table)
|
||||||
|
;; Give CR the same syntax as newline, for selective-display
|
||||||
|
(modify-syntax-entry ?\^m "> b" table)
|
||||||
|
;; return table
|
||||||
|
table)
|
||||||
|
|
||||||
|
(defun sclang-mode-make-menu (title)
|
||||||
|
(easy-menu-create-menu
|
||||||
|
title
|
||||||
|
'(
|
||||||
|
["Start Interpreter" sclang-start :included (not (sclang-library-initialized-p))]
|
||||||
|
["Restart Interpreter" sclang-start :included (sclang-library-initialized-p)]
|
||||||
|
["Recompile Class Library" sclang-recompile :included (sclang-library-initialized-p)]
|
||||||
|
["Stop Interpreter" sclang-stop :included (sclang-get-process)]
|
||||||
|
["Kill Interpreter" sclang-kill :included (sclang-get-process)]
|
||||||
|
"-"
|
||||||
|
["Show Post Buffer" sclang-show-post-buffer]
|
||||||
|
["Clear Post Buffer" sclang-clear-post-buffer]
|
||||||
|
"-"
|
||||||
|
["Switch To Workspace" sclang-switch-to-workspace]
|
||||||
|
"-"
|
||||||
|
["Evaluate Region" sclang-eval-region]
|
||||||
|
["Evaluate Line" sclang-eval-region-or-line]
|
||||||
|
["Evaluate Defun" sclang-eval-defun]
|
||||||
|
["Evaluate Expression ..." sclang-eval-expression]
|
||||||
|
["Evaluate Document" sclang-eval-document]
|
||||||
|
"-"
|
||||||
|
["Find Definitions ..." sclang-find-definitions]
|
||||||
|
["Find References ..." sclang-find-references]
|
||||||
|
["Pop Mark" sclang-pop-definition-mark]
|
||||||
|
["Show Method Arguments" sclang-show-method-args]
|
||||||
|
["Complete keyword" sclang-complete-symbol]
|
||||||
|
["Dump Interface" sclang-dump-interface]
|
||||||
|
["Dump Full Interface" sclang-dump-full-interface]
|
||||||
|
"-"
|
||||||
|
["Index Help Topics" sclang-index-help-topics]
|
||||||
|
["Find Help ..." sclang-find-help]
|
||||||
|
["Switch to Help Browser" sclang-goto-help-browser]
|
||||||
|
["Open Help GUI" sclang-open-help-gui]
|
||||||
|
"-"
|
||||||
|
["Run Main" sclang-main-run]
|
||||||
|
["Stop Main" sclang-main-stop]
|
||||||
|
["Show Server Panels" sclang-show-server-panel]
|
||||||
|
)))
|
||||||
|
|
||||||
|
(defun sclang-fill-mode-map (map)
|
||||||
|
;; process control
|
||||||
|
(define-key map "\C-c\C-l" 'sclang-recompile)
|
||||||
|
(define-key map "\C-c\C-o" 'sclang-start)
|
||||||
|
;; post buffer control
|
||||||
|
(define-key map "\C-c<" 'sclang-clear-post-buffer)
|
||||||
|
(define-key map "\C-c>" 'sclang-show-post-buffer)
|
||||||
|
;; workspace access
|
||||||
|
(define-key map "\C-c\C-w" 'sclang-switch-to-workspace)
|
||||||
|
;; code evaluation
|
||||||
|
(define-key map "\C-c\C-c" 'sclang-eval-region-or-line)
|
||||||
|
(define-key map "\C-c\C-d" 'sclang-eval-region)
|
||||||
|
(define-key map "\C-\M-x" 'sclang-eval-defun)
|
||||||
|
(define-key map "\C-c\C-e" 'sclang-eval-expression)
|
||||||
|
(define-key map "\C-c\C-f" 'sclang-eval-document)
|
||||||
|
;; language information
|
||||||
|
(define-key map "\C-c\C-n" 'sclang-complete-symbol)
|
||||||
|
(define-key map "\C-c:" 'sclang-find-definitions)
|
||||||
|
(define-key map "\C-c;" 'sclang-find-references)
|
||||||
|
(define-key map "\C-c}" 'sclang-pop-definition-mark)
|
||||||
|
(define-key map "\C-c\C-m" 'sclang-show-method-args)
|
||||||
|
(define-key map "\C-c{" 'sclang-dump-full-interface)
|
||||||
|
(define-key map "\C-c[" 'sclang-dump-interface)
|
||||||
|
;; documentation access
|
||||||
|
(define-key map "\C-c\C-h" 'sclang-find-help)
|
||||||
|
(define-key map "\C-\M-h" 'sclang-goto-help-browser)
|
||||||
|
(define-key map "\C-c\C-y" 'sclang-open-help-gui)
|
||||||
|
(define-key map "\C-ch" 'sclang-find-help-in-gui)
|
||||||
|
;; language control
|
||||||
|
(define-key map "\C-c\C-r" 'sclang-main-run)
|
||||||
|
(define-key map "\C-c\C-s" 'sclang-main-stop)
|
||||||
|
(define-key map "\C-c\C-p" 'sclang-show-server-panel)
|
||||||
|
(define-key map "\C-c\C-k" 'sclang-edit-dev-source)
|
||||||
|
;; electric characters
|
||||||
|
(define-key map "}" 'sclang-electric-brace)
|
||||||
|
(define-key map ")" 'sclang-electric-brace)
|
||||||
|
(define-key map "]" 'sclang-electric-brace)
|
||||||
|
(define-key map "/" 'sclang-electric-slash)
|
||||||
|
(define-key map "*" 'sclang-electric-star)
|
||||||
|
;; menu
|
||||||
|
(let ((title "SCLang"))
|
||||||
|
(define-key map [menu-bar sclang] (cons title (sclang-mode-make-menu title))))
|
||||||
|
;; return map
|
||||||
|
map)
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; font-lock support
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
(defconst sclang-font-lock-keyword-list
|
||||||
|
'(
|
||||||
|
"arg"
|
||||||
|
"classvar"
|
||||||
|
"const"
|
||||||
|
"super"
|
||||||
|
"this"
|
||||||
|
"thisFunction"
|
||||||
|
"thisFunctionDef"
|
||||||
|
"thisMethod"
|
||||||
|
"thisProcess"
|
||||||
|
"thisThread"
|
||||||
|
"var"
|
||||||
|
)
|
||||||
|
"*List of keywords to highlight in SCLang mode.")
|
||||||
|
|
||||||
|
(defconst sclang-font-lock-builtin-list
|
||||||
|
'(
|
||||||
|
"false"
|
||||||
|
"inf"
|
||||||
|
"nil"
|
||||||
|
"true"
|
||||||
|
)
|
||||||
|
"*List of builtins to highlight in SCLang mode.")
|
||||||
|
|
||||||
|
(defconst sclang-font-lock-method-list
|
||||||
|
'(
|
||||||
|
"ar"
|
||||||
|
"for"
|
||||||
|
"forBy"
|
||||||
|
"if"
|
||||||
|
"ir"
|
||||||
|
"kr"
|
||||||
|
"tr"
|
||||||
|
"loop"
|
||||||
|
"while"
|
||||||
|
)
|
||||||
|
"*List of methods to highlight in SCLang mode.")
|
||||||
|
|
||||||
|
(defconst sclang-font-lock-error-list
|
||||||
|
'(
|
||||||
|
"die"
|
||||||
|
"error"
|
||||||
|
"exit"
|
||||||
|
"halt"
|
||||||
|
"verboseHalt"
|
||||||
|
"warn"
|
||||||
|
)
|
||||||
|
"*List of methods signalling errors or warnings.")
|
||||||
|
|
||||||
|
(defvar sclang-font-lock-class-keywords nil)
|
||||||
|
|
||||||
|
(defvar sclang-font-lock-keywords-1 nil
|
||||||
|
"Subdued level highlighting for SCLang mode.")
|
||||||
|
|
||||||
|
(defvar sclang-font-lock-keywords-2 nil
|
||||||
|
"Medium level highlighting for SCLang mode.")
|
||||||
|
|
||||||
|
(defvar sclang-font-lock-keywords-3 nil
|
||||||
|
"Gaudy level highlighting for SCLang mode.")
|
||||||
|
|
||||||
|
(defvar sclang-font-lock-keywords nil
|
||||||
|
"Default expressions to highlight in SCLang mode.")
|
||||||
|
|
||||||
|
(defconst sclang-font-lock-defaults '((sclang-font-lock-keywords
|
||||||
|
sclang-font-lock-keywords-1
|
||||||
|
sclang-font-lock-keywords-2
|
||||||
|
sclang-font-lock-keywords-3
|
||||||
|
)
|
||||||
|
nil nil
|
||||||
|
nil
|
||||||
|
beginning-of-defun
|
||||||
|
))
|
||||||
|
|
||||||
|
(defun sclang-font-lock-syntactic-face (state)
|
||||||
|
(cond ((eq (nth 3 state) ?')
|
||||||
|
;; symbol
|
||||||
|
'font-lock-constant-face)
|
||||||
|
((nth 3 state)
|
||||||
|
;; string
|
||||||
|
'font-lock-string-face)
|
||||||
|
((nth 4 state)
|
||||||
|
;; comment
|
||||||
|
'font-lock-comment-face)))
|
||||||
|
|
||||||
|
(defun sclang-font-lock-class-keyword-matcher (limit)
|
||||||
|
(let ((regexp (concat "\\<" sclang-class-name-regexp "\\>"))
|
||||||
|
(case-fold-search nil)
|
||||||
|
(continue t)
|
||||||
|
(res nil))
|
||||||
|
(while continue
|
||||||
|
(setq res (re-search-forward regexp limit t))
|
||||||
|
(if (or (null res) (null sclang-class-list))
|
||||||
|
(setq continue nil)
|
||||||
|
(let ((thing (thing-at-point 'word)))
|
||||||
|
(if (null thing)
|
||||||
|
(setq res nil continue nil)
|
||||||
|
(when (cl-position (substring-no-properties thing) sclang-class-list :test 'equal)
|
||||||
|
(setq continue nil))))))
|
||||||
|
res))
|
||||||
|
|
||||||
|
(defun sclang-set-font-lock-keywords ()
|
||||||
|
(setq
|
||||||
|
;; level 1
|
||||||
|
sclang-font-lock-keywords-1
|
||||||
|
(list
|
||||||
|
;; keywords
|
||||||
|
(cons (regexp-opt sclang-font-lock-keyword-list 'words)
|
||||||
|
'font-lock-keyword-face)
|
||||||
|
;; builtins
|
||||||
|
(cons (regexp-opt sclang-font-lock-builtin-list 'words)
|
||||||
|
'font-lock-builtin-face)
|
||||||
|
;; pi is a special case
|
||||||
|
(cons "\\<\\([0-9]+\\(\\.\\)\\)pi\\>" 'font-lock-builtin-face)
|
||||||
|
;; constants
|
||||||
|
(cons "\\s/\\s\\?." 'font-lock-constant-face) ; characters
|
||||||
|
(cons (concat "\\\\\\(" sclang-symbol-regexp "\\)")
|
||||||
|
'font-lock-constant-face) ; symbols
|
||||||
|
)
|
||||||
|
;; level 2
|
||||||
|
sclang-font-lock-keywords-2
|
||||||
|
(append
|
||||||
|
sclang-font-lock-keywords-1
|
||||||
|
(list
|
||||||
|
;; variables
|
||||||
|
(cons (concat "\\s'\\(" sclang-identifier-regexp "\\)")
|
||||||
|
'font-lock-variable-name-face) ; environment variables
|
||||||
|
(cons (concat "\\<\\(" sclang-identifier-regexp "\\)\\>:") ; keyword arguments
|
||||||
|
'font-lock-variable-name-face)
|
||||||
|
;; method definitions
|
||||||
|
(cons sclang-method-definition-regexp
|
||||||
|
(list 1 'font-lock-function-name-face))
|
||||||
|
;; methods
|
||||||
|
(cons (regexp-opt sclang-font-lock-method-list 'words)
|
||||||
|
'font-lock-function-name-face)
|
||||||
|
;; errors
|
||||||
|
(cons (regexp-opt sclang-font-lock-error-list 'words)
|
||||||
|
'font-lock-warning-face)
|
||||||
|
))
|
||||||
|
;; level 3
|
||||||
|
sclang-font-lock-keywords-3
|
||||||
|
(append
|
||||||
|
sclang-font-lock-keywords-2
|
||||||
|
(list
|
||||||
|
;; classes
|
||||||
|
(cons 'sclang-font-lock-class-keyword-matcher 'font-lock-type-face)
|
||||||
|
;; (cons (concat "\\<" sclang-class-name-regexp "\\>") 'font-lock-type-face)
|
||||||
|
))
|
||||||
|
;; default level
|
||||||
|
sclang-font-lock-keywords sclang-font-lock-keywords-1
|
||||||
|
))
|
||||||
|
|
||||||
|
(defun sclang-update-font-lock ()
|
||||||
|
"Update font-lock information in all sclang-mode buffers."
|
||||||
|
;; too expensive
|
||||||
|
;; (dolist (buffer (buffer-list))
|
||||||
|
;; (with-current-buffer buffer
|
||||||
|
;; (and (eq major-mode 'sclang-mode)
|
||||||
|
;; (eq t (car font-lock-keywords))
|
||||||
|
;; (setq font-lock-keywords (cdr font-lock-keywords)))))
|
||||||
|
(if (eq major-mode 'sclang-mode)
|
||||||
|
(font-lock-fontify-buffer)))
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; indentation
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
(defcustom sclang-indent-level 4
|
||||||
|
"*Indentation offset for SCLang statements."
|
||||||
|
:group 'sclang-mode
|
||||||
|
:type 'integer)
|
||||||
|
|
||||||
|
(defun sclang-indent-line ()
|
||||||
|
"Indent current line as sclang code.
|
||||||
|
Return the amount the indentation changed by."
|
||||||
|
(let ((indent (calculate-sclang-indent))
|
||||||
|
beg shift-amt
|
||||||
|
(case-fold-search nil)
|
||||||
|
(pos (- (point-max) (point))))
|
||||||
|
(beginning-of-line)
|
||||||
|
(setq beg (point))
|
||||||
|
(skip-chars-forward " \t")
|
||||||
|
(setq shift-amt (- indent (current-column)))
|
||||||
|
(if (zerop shift-amt)
|
||||||
|
(if (> (- (point-max) pos) (point))
|
||||||
|
(goto-char (- (point-max) pos)))
|
||||||
|
(delete-region beg (point))
|
||||||
|
(indent-to indent)
|
||||||
|
;; if initial point was within line's indentation, position
|
||||||
|
;; after the indentation, else stay at same point in text.
|
||||||
|
(if (> (- (point-max) pos) (point))
|
||||||
|
(goto-char (- (point-max) pos))))
|
||||||
|
shift-amt))
|
||||||
|
|
||||||
|
(defun calculate-sclang-indent (&optional parse-start)
|
||||||
|
"Return appropriate indentation for current line as sclang code.
|
||||||
|
Returns the column to indent to."
|
||||||
|
(save-excursion
|
||||||
|
(beginning-of-line)
|
||||||
|
(let ((indent-point (point))
|
||||||
|
(case-fold-search nil)
|
||||||
|
state)
|
||||||
|
(if parse-start
|
||||||
|
(goto-char parse-start)
|
||||||
|
(beginning-of-defun))
|
||||||
|
(while (< (point) indent-point)
|
||||||
|
(setq state (parse-partial-sexp (point) indent-point 0)))
|
||||||
|
(let* ((containing-sexp (nth 1 state))
|
||||||
|
(inside-string-p (nth 3 state))
|
||||||
|
(inside-comment-p (nth 4 state)))
|
||||||
|
(cond (inside-string-p
|
||||||
|
;; inside string: no change
|
||||||
|
(current-indentation))
|
||||||
|
((integerp inside-comment-p)
|
||||||
|
;; inside comment
|
||||||
|
(let ((base (if containing-sexp
|
||||||
|
(save-excursion
|
||||||
|
(goto-char containing-sexp)
|
||||||
|
(+ (current-indentation) sclang-indent-level))
|
||||||
|
0))
|
||||||
|
(offset (* sclang-indent-level
|
||||||
|
(- inside-comment-p
|
||||||
|
(if (save-excursion
|
||||||
|
(back-to-indentation)
|
||||||
|
(looking-at "\\*/"))
|
||||||
|
1 0)))))
|
||||||
|
(+ base offset)))
|
||||||
|
((null containing-sexp)
|
||||||
|
;; top-level: no indentation
|
||||||
|
0)
|
||||||
|
(t
|
||||||
|
(back-to-indentation)
|
||||||
|
(let ((open-paren (and (looking-at "\\s)")
|
||||||
|
(matching-paren (char-after))))
|
||||||
|
(indent (current-indentation)))
|
||||||
|
(goto-char containing-sexp)
|
||||||
|
(if (or (not open-paren) (eq open-paren (char-after)))
|
||||||
|
(cond ((progn (beginning-of-line) (looking-at sclang-block-regexp)) 0)
|
||||||
|
(open-paren (current-indentation))
|
||||||
|
(t (+ (current-indentation) sclang-indent-level)))
|
||||||
|
;; paren mismatch: do nothing
|
||||||
|
indent))))))))
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; electric character commands
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
(defun sclang-electric-brace (arg)
|
||||||
|
(interactive "*P")
|
||||||
|
(self-insert-command (prefix-numeric-value arg))
|
||||||
|
(and (save-excursion
|
||||||
|
(beginning-of-line)
|
||||||
|
(looking-at "\\s *\\s)"))
|
||||||
|
(indent-according-to-mode)))
|
||||||
|
|
||||||
|
(defun sclang-electric-slash (arg)
|
||||||
|
(interactive "*P")
|
||||||
|
(let* ((char (char-before))
|
||||||
|
(indent-p (or (eq char ?/)
|
||||||
|
(eq char ?*))))
|
||||||
|
(self-insert-command (prefix-numeric-value arg))
|
||||||
|
(if indent-p (indent-according-to-mode))))
|
||||||
|
|
||||||
|
(defun sclang-electric-star (arg)
|
||||||
|
(interactive "*P")
|
||||||
|
(let ((indent-p (eq (char-before) ?/)))
|
||||||
|
(self-insert-command (prefix-numeric-value arg))
|
||||||
|
(if indent-p (indent-according-to-mode))))
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; document interface
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
(defvar sclang-document-id nil)
|
||||||
|
(defvar sclang-document-state nil)
|
||||||
|
(defvar sclang-document-envir nil)
|
||||||
|
|
||||||
|
(defvar sclang-document-counter 0)
|
||||||
|
(defvar sclang-document-list nil)
|
||||||
|
(defvar sclang-current-document nil
|
||||||
|
"Currently active document.")
|
||||||
|
|
||||||
|
(defvar sclang-document-idle-timer nil)
|
||||||
|
|
||||||
|
(defconst sclang-document-property-map
|
||||||
|
'((sclang-document-name . (prSetTitle (buffer-name)))
|
||||||
|
(sclang-document-path . (prSetFileName (buffer-file-name)))
|
||||||
|
(sclang-document-listener-p . (prSetIsListener (eq (current-buffer) (sclang-get-post-buffer))))
|
||||||
|
(sclang-document-editable-p . (prSetEditable (not buffer-read-only)))
|
||||||
|
(sclang-document-edited-p . (prSetEdited (buffer-modified-p)))))
|
||||||
|
|
||||||
|
(defmacro sclang-next-document-id ()
|
||||||
|
`(cl-incf sclang-document-counter))
|
||||||
|
|
||||||
|
(defun sclang-document-id (buffer)
|
||||||
|
(cdr (assq 'sclang-document-id (buffer-local-variables buffer))))
|
||||||
|
|
||||||
|
(defun sclang-document-p (buffer)
|
||||||
|
(integerp (sclang-document-id buffer)))
|
||||||
|
|
||||||
|
(defmacro with-sclang-document (buffer &rest body)
|
||||||
|
`(when (sclang-document-p buffer)
|
||||||
|
(with-current-buffer buffer
|
||||||
|
,@body)))
|
||||||
|
|
||||||
|
(defun sclang-get-document (id)
|
||||||
|
(cl-find-if (lambda (buffer) (eq id (sclang-document-id buffer)))
|
||||||
|
sclang-document-list))
|
||||||
|
|
||||||
|
(defun sclang-init-document ()
|
||||||
|
(set (make-local-variable 'sclang-document-id) (sclang-next-document-id))
|
||||||
|
(set (make-local-variable 'sclang-document-envir) nil)
|
||||||
|
(dolist (assoc sclang-document-property-map)
|
||||||
|
(set (make-local-variable (car assoc)) nil))
|
||||||
|
(cl-pushnew (current-buffer) sclang-document-list))
|
||||||
|
|
||||||
|
(defun sclang-document-update-property-1 (assoc &optional force)
|
||||||
|
(when (consp assoc)
|
||||||
|
(let* ((key (car assoc))
|
||||||
|
(prop (cdr assoc))
|
||||||
|
(prev-value (eval key))
|
||||||
|
(cur-value (eval (cadr prop))))
|
||||||
|
(when (or force (not (equal prev-value cur-value)))
|
||||||
|
(set key cur-value)
|
||||||
|
(sclang-perform-command-no-result
|
||||||
|
'documentSetProperty sclang-document-id
|
||||||
|
(car prop) cur-value)))))
|
||||||
|
|
||||||
|
(defun sclang-document-update-property (key &optional force)
|
||||||
|
(sclang-document-update-property-1 (assq key sclang-document-property-map) force))
|
||||||
|
|
||||||
|
(defun sclang-document-update-properties (&optional force)
|
||||||
|
(dolist (assoc sclang-document-property-map)
|
||||||
|
(sclang-document-update-property-1 assoc force)))
|
||||||
|
|
||||||
|
(defun sclang-make-document ()
|
||||||
|
(sclang-perform-command-no-result 'documentNew sclang-document-id)
|
||||||
|
(sclang-document-update-properties t))
|
||||||
|
|
||||||
|
(defun sclang-close-document (buffer)
|
||||||
|
(with-sclang-document
|
||||||
|
buffer
|
||||||
|
(setq sclang-document-list (delq buffer sclang-document-list))
|
||||||
|
(sclang-perform-command-no-result
|
||||||
|
'documentClosed sclang-document-id)))
|
||||||
|
|
||||||
|
(defun sclang-set-current-document (buffer &optional force)
|
||||||
|
(when (or force (not (eq buffer sclang-current-document)))
|
||||||
|
(setq sclang-current-document buffer)
|
||||||
|
(sclang-perform-command-no-result 'documentSetCurrent (sclang-document-id buffer))
|
||||||
|
t))
|
||||||
|
|
||||||
|
(defun sclang-document-library-startup-hook-function ()
|
||||||
|
(dolist (buffer sclang-document-list)
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(sclang-make-document)))
|
||||||
|
(sclang-set-current-document (current-buffer) t))
|
||||||
|
|
||||||
|
(defun sclang-document-kill-buffer-hook-function ()
|
||||||
|
(sclang-close-document (current-buffer)))
|
||||||
|
|
||||||
|
(defun sclang-document-post-command-hook-function ()
|
||||||
|
(when (and (sclang-library-initialized-p)
|
||||||
|
(sclang-document-p (current-buffer)))
|
||||||
|
(sclang-document-update-properties))
|
||||||
|
(sclang-set-current-document (current-buffer)))
|
||||||
|
|
||||||
|
(defun sclang-document-change-major-mode-hook-function ()
|
||||||
|
(sclang-close-document (current-buffer)))
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; command handlers
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentOpen
|
||||||
|
(lambda (arg)
|
||||||
|
(cl-multiple-value-bind (file-name region-start region-length) arg
|
||||||
|
(let ((buffer (get-file-buffer file-name)))
|
||||||
|
(unless buffer
|
||||||
|
(setf buffer (find-file-noselect file-name)))
|
||||||
|
(when buffer
|
||||||
|
(unless (sclang-document-p buffer)
|
||||||
|
(with-current-buffer buffer (sclang-mode)))
|
||||||
|
(goto-char (max (point-min) (min (point-max) region-start)))
|
||||||
|
;; TODO: how to activate region in transient-mark-mode?
|
||||||
|
(sclang-document-id buffer))))))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentNew
|
||||||
|
(lambda (arg)
|
||||||
|
(cl-multiple-value-bind (name str make-listener) arg
|
||||||
|
(let ((buffer (generate-new-buffer name)))
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(insert str)
|
||||||
|
(set-buffer-modified-p nil)
|
||||||
|
(sclang-mode))
|
||||||
|
(sclang-document-id buffer)))))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentClose
|
||||||
|
(lambda (arg)
|
||||||
|
(let ((doc (and (integerp arg) (sclang-get-document arg))))
|
||||||
|
(and doc (kill-buffer doc)))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentRename
|
||||||
|
(lambda (arg)
|
||||||
|
(cl-multiple-value-bind (id name) arg
|
||||||
|
(when (stringp name)
|
||||||
|
(let ((doc (and (integerp id) (sclang-get-document id))))
|
||||||
|
(when doc
|
||||||
|
(with-current-buffer doc
|
||||||
|
(rename-buffer name t)
|
||||||
|
(sclang-document-update-property 'sclang-document-name))))))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentSetEditable
|
||||||
|
(lambda (arg)
|
||||||
|
(cl-multiple-value-bind (id flag) arg
|
||||||
|
(let ((doc (and (integerp id) (sclang-get-document id))))
|
||||||
|
(when doc
|
||||||
|
(with-current-buffer doc
|
||||||
|
(setq buffer-read-only (not flag))
|
||||||
|
(sclang-document-update-property 'sclang-editable-p)))))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentSwitchTo
|
||||||
|
(lambda (arg)
|
||||||
|
(let ((doc (and (integerp arg) (sclang-get-document arg))))
|
||||||
|
(and doc (switch-to-buffer doc)))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentPutString
|
||||||
|
(lambda (arg)
|
||||||
|
(cl-multiple-value-bind (id str) arg
|
||||||
|
(let ((doc (and (integerp id) (sclang-get-document id))))
|
||||||
|
(when doc
|
||||||
|
(with-current-buffer doc
|
||||||
|
(insert str)
|
||||||
|
)
|
||||||
|
nil)))))
|
||||||
|
|
||||||
|
(sclang-set-command-handler
|
||||||
|
'_documentPopTo
|
||||||
|
(lambda (arg)
|
||||||
|
(let ((doc (and (integerp arg) (sclang-get-document arg))))
|
||||||
|
(and doc (display-buffer doc)))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; sclang-mode
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
(defun sclang-mode-set-local-variables ()
|
||||||
|
(set (make-local-variable 'require-final-newline) nil)
|
||||||
|
;; indentation
|
||||||
|
(set (make-local-variable 'indent-line-function)
|
||||||
|
'sclang-indent-line)
|
||||||
|
(set (make-local-variable 'tab-width) 4)
|
||||||
|
(set (make-local-variable 'indent-tabs-mode) t)
|
||||||
|
;; comment formatting
|
||||||
|
(set (make-local-variable 'comment-start) "// ")
|
||||||
|
(set (make-local-variable 'comment-end) "")
|
||||||
|
(set (make-local-variable 'comment-column) 40)
|
||||||
|
(set (make-local-variable 'comment-start-skip) "/\\*+ *\\|//+ *")
|
||||||
|
;; "\\(^\\|\\s-\\);?// *")
|
||||||
|
(set (make-local-variable 'comment-multi-line) t)
|
||||||
|
;; parsing and movement
|
||||||
|
(set (make-local-variable 'parse-sexp-ignore-comments) t)
|
||||||
|
(set (make-local-variable 'beginning-of-defun-function)
|
||||||
|
'sclang-beginning-of-defun)
|
||||||
|
(set (make-local-variable 'end-of-defun-function)
|
||||||
|
'sclang-end-of-defun)
|
||||||
|
;; paragraph formatting
|
||||||
|
;; (set (make-local-variable 'paragraph-start) (concat "$\\|" page-delimiter))
|
||||||
|
;; mostly copied from c++-mode, seems to work
|
||||||
|
(set (make-local-variable 'paragraph-start)
|
||||||
|
"[ \t]*\\(//+\\|\\**\\)[ \t]*$\\|^")
|
||||||
|
(set (make-local-variable 'paragraph-separate) paragraph-start)
|
||||||
|
(set (make-local-variable 'paragraph-ignore-fill-prefix) t)
|
||||||
|
(set (make-local-variable 'adaptive-fill-mode) t)
|
||||||
|
(set (make-local-variable 'adaptive-fill-regexp)
|
||||||
|
"[ \t]*\\(//+\\|\\**\\)[ \t]*\\([ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*\\)")
|
||||||
|
;; font lock
|
||||||
|
(set (make-local-variable 'font-lock-syntactic-face-function)
|
||||||
|
'sclang-font-lock-syntactic-face)
|
||||||
|
(set (make-local-variable 'font-lock-defaults)
|
||||||
|
sclang-font-lock-defaults)
|
||||||
|
;; ---
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(defvar sclang-mode-map (sclang-fill-mode-map (make-sparse-keymap))
|
||||||
|
"Keymap used in SuperCollider mode.")
|
||||||
|
|
||||||
|
(defvar sclang-mode-syntax-table (sclang-fill-syntax-table (make-syntax-table))
|
||||||
|
"Syntax table used in SuperCollider mode.")
|
||||||
|
|
||||||
|
(defcustom sclang-mode-hook nil
|
||||||
|
"*Hook run when entering SCLang mode."
|
||||||
|
:group 'sclang-mode
|
||||||
|
:type 'hook)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-derived-mode sclang-mode prog-mode "SCLang"
|
||||||
|
"Major mode for editing SuperCollider language code.
|
||||||
|
\\{sclang-mode-map}"
|
||||||
|
:group 'sclang
|
||||||
|
:syntax-table sclang-mode-syntax-table
|
||||||
|
(sclang-mode-set-local-variables)
|
||||||
|
(sclang-set-font-lock-keywords)
|
||||||
|
(sclang-init-document)
|
||||||
|
(sclang-make-document)
|
||||||
|
|
||||||
|
;; Setup completion
|
||||||
|
(add-hook 'completion-at-point-functions
|
||||||
|
#'sclang-completion-at-point nil 'local)
|
||||||
|
(when (fboundp 'company-mode)
|
||||||
|
(add-to-list 'company-backends 'company-capf)))
|
||||||
|
|
||||||
|
;; =====================================================================
|
||||||
|
;; module initialization
|
||||||
|
;; =====================================================================
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(add-to-list 'auto-mode-alist '("\\.scd?\\'" . sclang-mode))
|
||||||
|
(add-to-list 'interpreter-mode-alist '("sclang" . sclang-mode))
|
||||||
|
|
||||||
|
(add-hook 'sclang-library-startup-hook 'sclang-document-library-startup-hook-function)
|
||||||
|
(add-hook 'kill-buffer-hook 'sclang-document-kill-buffer-hook-function)
|
||||||
|
(add-hook 'post-command-hook 'sclang-document-post-command-hook-function)
|
||||||
|
(add-hook 'change-major-mode-hook 'sclang-document-change-major-mode-hook-function)
|
||||||
|
|
||||||
|
(provide 'sclang-mode)
|
||||||
|
;;; sclang-mode ends here
|
|
@ -19,6 +19,7 @@
|
||||||
(require 'sclang-util)
|
(require 'sclang-util)
|
||||||
(require 'sclang-interp)
|
(require 'sclang-interp)
|
||||||
(require 'sclang-language)
|
(require 'sclang-language)
|
||||||
|
(require 'sclang-mode)
|
||||||
|
|
||||||
(defcustom sclang-server-panel "Server.default.makeWindow"
|
(defcustom sclang-server-panel "Server.default.makeWindow"
|
||||||
"Expression to execute when `sclang-show-server-panel' is invoked."
|
"Expression to execute when `sclang-show-server-panel' is invoked."
|
||||||
|
|
702
el/sclang.el
702
el/sclang.el
|
@ -26,24 +26,6 @@
|
||||||
;; for more information.
|
;; for more information.
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(require 'cl-lib)
|
|
||||||
(require 'font-lock)
|
|
||||||
(require 'sclang-util)
|
|
||||||
(require 'sclang-browser)
|
|
||||||
(require 'sclang-interp)
|
|
||||||
(require 'sclang-language)
|
|
||||||
(require 'sclang-document)
|
|
||||||
(require 'sclang-minor-mode)
|
|
||||||
(require 'sclang-help)
|
|
||||||
(require 'sclang-server)
|
|
||||||
(require 'sclang-widgets)
|
|
||||||
|
|
||||||
;; Make byte-compiler happy by declaring external functions and
|
|
||||||
;; variables.
|
|
||||||
(declare-function company-mode "ext:company")
|
|
||||||
(defvar company-backends)
|
|
||||||
|
|
||||||
(defgroup sclang nil
|
(defgroup sclang nil
|
||||||
"IDE for working with the SuperCollider language."
|
"IDE for working with the SuperCollider language."
|
||||||
:group 'languages)
|
:group 'languages)
|
||||||
|
@ -73,674 +55,22 @@
|
||||||
(interactive)
|
(interactive)
|
||||||
(customize-group 'sclang))
|
(customize-group 'sclang))
|
||||||
|
|
||||||
(defun sclang-fill-syntax-table (table)
|
(eval-and-compile
|
||||||
;; string
|
(let ((load-path
|
||||||
(modify-syntax-entry ?\" "\"" table)
|
(if (and (boundp 'byte-compile-dest-file)
|
||||||
(modify-syntax-entry ?\' "\"" table) ; no string syntax class for single quotes
|
(stringp byte-compile-dest-file))
|
||||||
;; expression prefix
|
(cons (file-name-directory byte-compile-dest-file) load-path)
|
||||||
(modify-syntax-entry ?~ "'" table)
|
load-path)))
|
||||||
;; escape
|
(require 'sclang-util)
|
||||||
(modify-syntax-entry ?\\ "\\" table)
|
(require 'sclang-browser)
|
||||||
;; character quote
|
(require 'sclang-interp)
|
||||||
(modify-syntax-entry ?$ "/" table)
|
(require 'sclang-language)
|
||||||
;; symbol
|
(require 'sclang-document)
|
||||||
(modify-syntax-entry ?_ "_" table)
|
(require 'sclang-mode)
|
||||||
;; symbol/punctuation
|
(require 'sclang-minor-mode)
|
||||||
(modify-syntax-entry ?! "." table)
|
(require 'sclang-help)
|
||||||
(modify-syntax-entry ?% "." table)
|
(require 'sclang-server)
|
||||||
(modify-syntax-entry ?& "." table)
|
(require 'sclang-widgets)))
|
||||||
(modify-syntax-entry ?* ". 23n" table)
|
|
||||||
(modify-syntax-entry ?+ "." table)
|
|
||||||
(modify-syntax-entry ?- "." table)
|
|
||||||
(modify-syntax-entry ?/ ". 124b" 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)
|
|
||||||
;; punctuation
|
|
||||||
(modify-syntax-entry ?: "." table)
|
|
||||||
(modify-syntax-entry ?\; "." table)
|
|
||||||
(modify-syntax-entry ?^ "." table)
|
|
||||||
;; parenthesis
|
|
||||||
(modify-syntax-entry ?\( "()" table)
|
|
||||||
(modify-syntax-entry ?\) ")(" table)
|
|
||||||
(modify-syntax-entry ?\[ "(]" table)
|
|
||||||
(modify-syntax-entry ?\] ")[" table)
|
|
||||||
(modify-syntax-entry ?\{ "(}" table)
|
|
||||||
(modify-syntax-entry ?\} "){" table)
|
|
||||||
;; comment end
|
|
||||||
(modify-syntax-entry ?\n "> b" table)
|
|
||||||
;; Give CR the same syntax as newline, for selective-display
|
|
||||||
(modify-syntax-entry ?\^m "> b" table)
|
|
||||||
;; return table
|
|
||||||
table)
|
|
||||||
|
|
||||||
(defun sclang-mode-make-menu (title)
|
|
||||||
(easy-menu-create-menu
|
|
||||||
title
|
|
||||||
'(
|
|
||||||
["Start Interpreter" sclang-start :included (not (sclang-library-initialized-p))]
|
|
||||||
["Restart Interpreter" sclang-start :included (sclang-library-initialized-p)]
|
|
||||||
["Recompile Class Library" sclang-recompile :included (sclang-library-initialized-p)]
|
|
||||||
["Stop Interpreter" sclang-stop :included (sclang-get-process)]
|
|
||||||
["Kill Interpreter" sclang-kill :included (sclang-get-process)]
|
|
||||||
"-"
|
|
||||||
["Show Post Buffer" sclang-show-post-buffer]
|
|
||||||
["Clear Post Buffer" sclang-clear-post-buffer]
|
|
||||||
"-"
|
|
||||||
["Switch To Workspace" sclang-switch-to-workspace]
|
|
||||||
"-"
|
|
||||||
["Evaluate Region" sclang-eval-region]
|
|
||||||
["Evaluate Line" sclang-eval-region-or-line]
|
|
||||||
["Evaluate Defun" sclang-eval-defun]
|
|
||||||
["Evaluate Expression ..." sclang-eval-expression]
|
|
||||||
["Evaluate Document" sclang-eval-document]
|
|
||||||
"-"
|
|
||||||
["Find Definitions ..." sclang-find-definitions]
|
|
||||||
["Find References ..." sclang-find-references]
|
|
||||||
["Pop Mark" sclang-pop-definition-mark]
|
|
||||||
["Show Method Arguments" sclang-show-method-args]
|
|
||||||
["Complete keyword" sclang-complete-symbol]
|
|
||||||
["Dump Interface" sclang-dump-interface]
|
|
||||||
["Dump Full Interface" sclang-dump-full-interface]
|
|
||||||
"-"
|
|
||||||
["Index Help Topics" sclang-index-help-topics]
|
|
||||||
["Find Help ..." sclang-find-help]
|
|
||||||
["Switch to Help Browser" sclang-goto-help-browser]
|
|
||||||
["Open Help GUI" sclang-open-help-gui]
|
|
||||||
"-"
|
|
||||||
["Run Main" sclang-main-run]
|
|
||||||
["Stop Main" sclang-main-stop]
|
|
||||||
["Show Server Panels" sclang-show-server-panel]
|
|
||||||
)))
|
|
||||||
|
|
||||||
(defun sclang-fill-mode-map (map)
|
|
||||||
;; process control
|
|
||||||
(define-key map "\C-c\C-l" 'sclang-recompile)
|
|
||||||
(define-key map "\C-c\C-o" 'sclang-start)
|
|
||||||
;; post buffer control
|
|
||||||
(define-key map "\C-c<" 'sclang-clear-post-buffer)
|
|
||||||
(define-key map "\C-c>" 'sclang-show-post-buffer)
|
|
||||||
;; workspace access
|
|
||||||
(define-key map "\C-c\C-w" 'sclang-switch-to-workspace)
|
|
||||||
;; code evaluation
|
|
||||||
(define-key map "\C-c\C-c" 'sclang-eval-region-or-line)
|
|
||||||
(define-key map "\C-c\C-d" 'sclang-eval-region)
|
|
||||||
(define-key map "\C-\M-x" 'sclang-eval-defun)
|
|
||||||
(define-key map "\C-c\C-e" 'sclang-eval-expression)
|
|
||||||
(define-key map "\C-c\C-f" 'sclang-eval-document)
|
|
||||||
;; language information
|
|
||||||
(define-key map "\C-c\C-n" 'sclang-complete-symbol)
|
|
||||||
(define-key map "\C-c:" 'sclang-find-definitions)
|
|
||||||
(define-key map "\C-c;" 'sclang-find-references)
|
|
||||||
(define-key map "\C-c}" 'sclang-pop-definition-mark)
|
|
||||||
(define-key map "\C-c\C-m" 'sclang-show-method-args)
|
|
||||||
(define-key map "\C-c{" 'sclang-dump-full-interface)
|
|
||||||
(define-key map "\C-c[" 'sclang-dump-interface)
|
|
||||||
;; documentation access
|
|
||||||
(define-key map "\C-c\C-h" 'sclang-find-help)
|
|
||||||
(define-key map "\C-\M-h" 'sclang-goto-help-browser)
|
|
||||||
(define-key map "\C-c\C-y" 'sclang-open-help-gui)
|
|
||||||
(define-key map "\C-ch" 'sclang-find-help-in-gui)
|
|
||||||
;; language control
|
|
||||||
(define-key map "\C-c\C-r" 'sclang-main-run)
|
|
||||||
(define-key map "\C-c\C-s" 'sclang-main-stop)
|
|
||||||
(define-key map "\C-c\C-p" 'sclang-show-server-panel)
|
|
||||||
(define-key map "\C-c\C-k" 'sclang-edit-dev-source)
|
|
||||||
;; electric characters
|
|
||||||
(define-key map "}" 'sclang-electric-brace)
|
|
||||||
(define-key map ")" 'sclang-electric-brace)
|
|
||||||
(define-key map "]" 'sclang-electric-brace)
|
|
||||||
(define-key map "/" 'sclang-electric-slash)
|
|
||||||
(define-key map "*" 'sclang-electric-star)
|
|
||||||
;; menu
|
|
||||||
(let ((title "SCLang"))
|
|
||||||
(define-key map [menu-bar sclang] (cons title (sclang-mode-make-menu title))))
|
|
||||||
;; return map
|
|
||||||
map)
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; font-lock support
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
(defconst sclang-font-lock-keyword-list
|
|
||||||
'(
|
|
||||||
"arg"
|
|
||||||
"classvar"
|
|
||||||
"const"
|
|
||||||
"super"
|
|
||||||
"this"
|
|
||||||
"thisFunction"
|
|
||||||
"thisFunctionDef"
|
|
||||||
"thisMethod"
|
|
||||||
"thisProcess"
|
|
||||||
"thisThread"
|
|
||||||
"var"
|
|
||||||
)
|
|
||||||
"*List of keywords to highlight in SCLang mode.")
|
|
||||||
|
|
||||||
(defconst sclang-font-lock-builtin-list
|
|
||||||
'(
|
|
||||||
"false"
|
|
||||||
"inf"
|
|
||||||
"nil"
|
|
||||||
"true"
|
|
||||||
)
|
|
||||||
"*List of builtins to highlight in SCLang mode.")
|
|
||||||
|
|
||||||
(defconst sclang-font-lock-method-list
|
|
||||||
'(
|
|
||||||
"ar"
|
|
||||||
"for"
|
|
||||||
"forBy"
|
|
||||||
"if"
|
|
||||||
"ir"
|
|
||||||
"kr"
|
|
||||||
"tr"
|
|
||||||
"loop"
|
|
||||||
"while"
|
|
||||||
)
|
|
||||||
"*List of methods to highlight in SCLang mode.")
|
|
||||||
|
|
||||||
(defconst sclang-font-lock-error-list
|
|
||||||
'(
|
|
||||||
"die"
|
|
||||||
"error"
|
|
||||||
"exit"
|
|
||||||
"halt"
|
|
||||||
"verboseHalt"
|
|
||||||
"warn"
|
|
||||||
)
|
|
||||||
"*List of methods signalling errors or warnings.")
|
|
||||||
|
|
||||||
(defvar sclang-font-lock-class-keywords nil)
|
|
||||||
|
|
||||||
(defvar sclang-font-lock-keywords-1 nil
|
|
||||||
"Subdued level highlighting for SCLang mode.")
|
|
||||||
|
|
||||||
(defvar sclang-font-lock-keywords-2 nil
|
|
||||||
"Medium level highlighting for SCLang mode.")
|
|
||||||
|
|
||||||
(defvar sclang-font-lock-keywords-3 nil
|
|
||||||
"Gaudy level highlighting for SCLang mode.")
|
|
||||||
|
|
||||||
(defvar sclang-font-lock-keywords nil
|
|
||||||
"Default expressions to highlight in SCLang mode.")
|
|
||||||
|
|
||||||
(defconst sclang-font-lock-defaults '((sclang-font-lock-keywords
|
|
||||||
sclang-font-lock-keywords-1
|
|
||||||
sclang-font-lock-keywords-2
|
|
||||||
sclang-font-lock-keywords-3
|
|
||||||
)
|
|
||||||
nil nil
|
|
||||||
nil
|
|
||||||
beginning-of-defun
|
|
||||||
))
|
|
||||||
|
|
||||||
(defun sclang-font-lock-syntactic-face (state)
|
|
||||||
(cond ((eq (nth 3 state) ?')
|
|
||||||
;; symbol
|
|
||||||
'font-lock-constant-face)
|
|
||||||
((nth 3 state)
|
|
||||||
;; string
|
|
||||||
'font-lock-string-face)
|
|
||||||
((nth 4 state)
|
|
||||||
;; comment
|
|
||||||
'font-lock-comment-face)))
|
|
||||||
|
|
||||||
(defun sclang-font-lock-class-keyword-matcher (limit)
|
|
||||||
(let ((regexp (concat "\\<" sclang-class-name-regexp "\\>"))
|
|
||||||
(case-fold-search nil)
|
|
||||||
(continue t)
|
|
||||||
(res nil))
|
|
||||||
(while continue
|
|
||||||
(setq res (re-search-forward regexp limit t))
|
|
||||||
(if (or (null res) (null sclang-class-list))
|
|
||||||
(setq continue nil)
|
|
||||||
(let ((thing (thing-at-point 'word)))
|
|
||||||
(if (null thing)
|
|
||||||
(setq res nil continue nil)
|
|
||||||
(when (cl-position (substring-no-properties thing) sclang-class-list :test 'equal)
|
|
||||||
(setq continue nil))))))
|
|
||||||
res))
|
|
||||||
|
|
||||||
(defun sclang-set-font-lock-keywords ()
|
|
||||||
(setq
|
|
||||||
;; level 1
|
|
||||||
sclang-font-lock-keywords-1
|
|
||||||
(list
|
|
||||||
;; keywords
|
|
||||||
(cons (regexp-opt sclang-font-lock-keyword-list 'words)
|
|
||||||
'font-lock-keyword-face)
|
|
||||||
;; builtins
|
|
||||||
(cons (regexp-opt sclang-font-lock-builtin-list 'words)
|
|
||||||
'font-lock-builtin-face)
|
|
||||||
;; pi is a special case
|
|
||||||
(cons "\\<\\([0-9]+\\(\\.\\)\\)pi\\>" 'font-lock-builtin-face)
|
|
||||||
;; constants
|
|
||||||
(cons "\\s/\\s\\?." 'font-lock-constant-face) ; characters
|
|
||||||
(cons (concat "\\\\\\(" sclang-symbol-regexp "\\)")
|
|
||||||
'font-lock-constant-face) ; symbols
|
|
||||||
)
|
|
||||||
;; level 2
|
|
||||||
sclang-font-lock-keywords-2
|
|
||||||
(append
|
|
||||||
sclang-font-lock-keywords-1
|
|
||||||
(list
|
|
||||||
;; variables
|
|
||||||
(cons (concat "\\s'\\(" sclang-identifier-regexp "\\)")
|
|
||||||
'font-lock-variable-name-face) ; environment variables
|
|
||||||
(cons (concat "\\<\\(" sclang-identifier-regexp "\\)\\>:") ; keyword arguments
|
|
||||||
'font-lock-variable-name-face)
|
|
||||||
;; method definitions
|
|
||||||
(cons sclang-method-definition-regexp
|
|
||||||
(list 1 'font-lock-function-name-face))
|
|
||||||
;; methods
|
|
||||||
(cons (regexp-opt sclang-font-lock-method-list 'words)
|
|
||||||
'font-lock-function-name-face)
|
|
||||||
;; errors
|
|
||||||
(cons (regexp-opt sclang-font-lock-error-list 'words)
|
|
||||||
'font-lock-warning-face)
|
|
||||||
))
|
|
||||||
;; level 3
|
|
||||||
sclang-font-lock-keywords-3
|
|
||||||
(append
|
|
||||||
sclang-font-lock-keywords-2
|
|
||||||
(list
|
|
||||||
;; classes
|
|
||||||
(cons 'sclang-font-lock-class-keyword-matcher 'font-lock-type-face)
|
|
||||||
;; (cons (concat "\\<" sclang-class-name-regexp "\\>") 'font-lock-type-face)
|
|
||||||
))
|
|
||||||
;; default level
|
|
||||||
sclang-font-lock-keywords sclang-font-lock-keywords-1
|
|
||||||
))
|
|
||||||
|
|
||||||
(defun sclang-update-font-lock ()
|
|
||||||
"Update font-lock information in all sclang-mode buffers."
|
|
||||||
;; too expensive
|
|
||||||
;; (dolist (buffer (buffer-list))
|
|
||||||
;; (with-current-buffer buffer
|
|
||||||
;; (and (eq major-mode 'sclang-mode)
|
|
||||||
;; (eq t (car font-lock-keywords))
|
|
||||||
;; (setq font-lock-keywords (cdr font-lock-keywords)))))
|
|
||||||
(if (eq major-mode 'sclang-mode)
|
|
||||||
(font-lock-fontify-buffer)))
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; indentation
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
(defcustom sclang-indent-level 4
|
|
||||||
"*Indentation offset for SCLang statements."
|
|
||||||
:group 'sclang-mode
|
|
||||||
:type 'integer)
|
|
||||||
|
|
||||||
(defun sclang-indent-line ()
|
|
||||||
"Indent current line as sclang code.
|
|
||||||
Return the amount the indentation changed by."
|
|
||||||
(let ((indent (calculate-sclang-indent))
|
|
||||||
beg shift-amt
|
|
||||||
(case-fold-search nil)
|
|
||||||
(pos (- (point-max) (point))))
|
|
||||||
(beginning-of-line)
|
|
||||||
(setq beg (point))
|
|
||||||
(skip-chars-forward " \t")
|
|
||||||
(setq shift-amt (- indent (current-column)))
|
|
||||||
(if (zerop shift-amt)
|
|
||||||
(if (> (- (point-max) pos) (point))
|
|
||||||
(goto-char (- (point-max) pos)))
|
|
||||||
(delete-region beg (point))
|
|
||||||
(indent-to indent)
|
|
||||||
;; if initial point was within line's indentation, position
|
|
||||||
;; after the indentation, else stay at same point in text.
|
|
||||||
(if (> (- (point-max) pos) (point))
|
|
||||||
(goto-char (- (point-max) pos))))
|
|
||||||
shift-amt))
|
|
||||||
|
|
||||||
(defun calculate-sclang-indent (&optional parse-start)
|
|
||||||
"Return appropriate indentation for current line as sclang code.
|
|
||||||
Returns the column to indent to."
|
|
||||||
(save-excursion
|
|
||||||
(beginning-of-line)
|
|
||||||
(let ((indent-point (point))
|
|
||||||
(case-fold-search nil)
|
|
||||||
state)
|
|
||||||
(if parse-start
|
|
||||||
(goto-char parse-start)
|
|
||||||
(beginning-of-defun))
|
|
||||||
(while (< (point) indent-point)
|
|
||||||
(setq state (parse-partial-sexp (point) indent-point 0)))
|
|
||||||
(let* ((containing-sexp (nth 1 state))
|
|
||||||
(inside-string-p (nth 3 state))
|
|
||||||
(inside-comment-p (nth 4 state)))
|
|
||||||
(cond (inside-string-p
|
|
||||||
;; inside string: no change
|
|
||||||
(current-indentation))
|
|
||||||
((integerp inside-comment-p)
|
|
||||||
;; inside comment
|
|
||||||
(let ((base (if containing-sexp
|
|
||||||
(save-excursion
|
|
||||||
(goto-char containing-sexp)
|
|
||||||
(+ (current-indentation) sclang-indent-level))
|
|
||||||
0))
|
|
||||||
(offset (* sclang-indent-level
|
|
||||||
(- inside-comment-p
|
|
||||||
(if (save-excursion
|
|
||||||
(back-to-indentation)
|
|
||||||
(looking-at "\\*/"))
|
|
||||||
1 0)))))
|
|
||||||
(+ base offset)))
|
|
||||||
((null containing-sexp)
|
|
||||||
;; top-level: no indentation
|
|
||||||
0)
|
|
||||||
(t
|
|
||||||
(back-to-indentation)
|
|
||||||
(let ((open-paren (and (looking-at "\\s)")
|
|
||||||
(matching-paren (char-after))))
|
|
||||||
(indent (current-indentation)))
|
|
||||||
(goto-char containing-sexp)
|
|
||||||
(if (or (not open-paren) (eq open-paren (char-after)))
|
|
||||||
(cond ((progn (beginning-of-line) (looking-at sclang-block-regexp)) 0)
|
|
||||||
(open-paren (current-indentation))
|
|
||||||
(t (+ (current-indentation) sclang-indent-level)))
|
|
||||||
;; paren mismatch: do nothing
|
|
||||||
indent))))))))
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; electric character commands
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
(defun sclang-electric-brace (arg)
|
|
||||||
(interactive "*P")
|
|
||||||
(self-insert-command (prefix-numeric-value arg))
|
|
||||||
(and (save-excursion
|
|
||||||
(beginning-of-line)
|
|
||||||
(looking-at "\\s *\\s)"))
|
|
||||||
(indent-according-to-mode)))
|
|
||||||
|
|
||||||
(defun sclang-electric-slash (arg)
|
|
||||||
(interactive "*P")
|
|
||||||
(let* ((char (char-before))
|
|
||||||
(indent-p (or (eq char ?/)
|
|
||||||
(eq char ?*))))
|
|
||||||
(self-insert-command (prefix-numeric-value arg))
|
|
||||||
(if indent-p (indent-according-to-mode))))
|
|
||||||
|
|
||||||
(defun sclang-electric-star (arg)
|
|
||||||
(interactive "*P")
|
|
||||||
(let ((indent-p (eq (char-before) ?/)))
|
|
||||||
(self-insert-command (prefix-numeric-value arg))
|
|
||||||
(if indent-p (indent-according-to-mode))))
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; document interface
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
(defvar sclang-document-id nil)
|
|
||||||
(defvar sclang-document-state nil)
|
|
||||||
(defvar sclang-document-envir nil)
|
|
||||||
|
|
||||||
(defvar sclang-document-counter 0)
|
|
||||||
(defvar sclang-document-list nil)
|
|
||||||
(defvar sclang-current-document nil
|
|
||||||
"Currently active document.")
|
|
||||||
|
|
||||||
(defvar sclang-document-idle-timer nil)
|
|
||||||
|
|
||||||
(defconst sclang-document-property-map
|
|
||||||
'((sclang-document-name . (prSetTitle (buffer-name)))
|
|
||||||
(sclang-document-path . (prSetFileName (buffer-file-name)))
|
|
||||||
(sclang-document-listener-p . (prSetIsListener (eq (current-buffer) (sclang-get-post-buffer))))
|
|
||||||
(sclang-document-editable-p . (prSetEditable (not buffer-read-only)))
|
|
||||||
(sclang-document-edited-p . (prSetEdited (buffer-modified-p)))))
|
|
||||||
|
|
||||||
(defmacro sclang-next-document-id ()
|
|
||||||
`(cl-incf sclang-document-counter))
|
|
||||||
|
|
||||||
(defun sclang-document-id (buffer)
|
|
||||||
(cdr (assq 'sclang-document-id (buffer-local-variables buffer))))
|
|
||||||
|
|
||||||
(defun sclang-document-p (buffer)
|
|
||||||
(integerp (sclang-document-id buffer)))
|
|
||||||
|
|
||||||
(defmacro with-sclang-document (buffer &rest body)
|
|
||||||
`(when (sclang-document-p buffer)
|
|
||||||
(with-current-buffer buffer
|
|
||||||
,@body)))
|
|
||||||
|
|
||||||
(defun sclang-get-document (id)
|
|
||||||
(cl-find-if (lambda (buffer) (eq id (sclang-document-id buffer)))
|
|
||||||
sclang-document-list))
|
|
||||||
|
|
||||||
(defun sclang-init-document ()
|
|
||||||
(set (make-local-variable 'sclang-document-id) (sclang-next-document-id))
|
|
||||||
(set (make-local-variable 'sclang-document-envir) nil)
|
|
||||||
(dolist (assoc sclang-document-property-map)
|
|
||||||
(set (make-local-variable (car assoc)) nil))
|
|
||||||
(cl-pushnew (current-buffer) sclang-document-list))
|
|
||||||
|
|
||||||
(defun sclang-document-update-property-1 (assoc &optional force)
|
|
||||||
(when (consp assoc)
|
|
||||||
(let* ((key (car assoc))
|
|
||||||
(prop (cdr assoc))
|
|
||||||
(prev-value (eval key))
|
|
||||||
(cur-value (eval (cadr prop))))
|
|
||||||
(when (or force (not (equal prev-value cur-value)))
|
|
||||||
(set key cur-value)
|
|
||||||
(sclang-perform-command-no-result
|
|
||||||
'documentSetProperty sclang-document-id
|
|
||||||
(car prop) cur-value)))))
|
|
||||||
|
|
||||||
(defun sclang-document-update-property (key &optional force)
|
|
||||||
(sclang-document-update-property-1 (assq key sclang-document-property-map) force))
|
|
||||||
|
|
||||||
(defun sclang-document-update-properties (&optional force)
|
|
||||||
(dolist (assoc sclang-document-property-map)
|
|
||||||
(sclang-document-update-property-1 assoc force)))
|
|
||||||
|
|
||||||
(defun sclang-make-document ()
|
|
||||||
(sclang-perform-command-no-result 'documentNew sclang-document-id)
|
|
||||||
(sclang-document-update-properties t))
|
|
||||||
|
|
||||||
(defun sclang-close-document (buffer)
|
|
||||||
(with-sclang-document
|
|
||||||
buffer
|
|
||||||
(setq sclang-document-list (delq buffer sclang-document-list))
|
|
||||||
(sclang-perform-command-no-result
|
|
||||||
'documentClosed sclang-document-id)))
|
|
||||||
|
|
||||||
(defun sclang-set-current-document (buffer &optional force)
|
|
||||||
(when (or force (not (eq buffer sclang-current-document)))
|
|
||||||
(setq sclang-current-document buffer)
|
|
||||||
(sclang-perform-command-no-result 'documentSetCurrent (sclang-document-id buffer))
|
|
||||||
t))
|
|
||||||
|
|
||||||
(defun sclang-document-library-startup-hook-function ()
|
|
||||||
(dolist (buffer sclang-document-list)
|
|
||||||
(with-current-buffer buffer
|
|
||||||
(sclang-make-document)))
|
|
||||||
(sclang-set-current-document (current-buffer) t))
|
|
||||||
|
|
||||||
(defun sclang-document-kill-buffer-hook-function ()
|
|
||||||
(sclang-close-document (current-buffer)))
|
|
||||||
|
|
||||||
(defun sclang-document-post-command-hook-function ()
|
|
||||||
(when (and (sclang-library-initialized-p)
|
|
||||||
(sclang-document-p (current-buffer)))
|
|
||||||
(sclang-document-update-properties))
|
|
||||||
(sclang-set-current-document (current-buffer)))
|
|
||||||
|
|
||||||
(defun sclang-document-change-major-mode-hook-function ()
|
|
||||||
(sclang-close-document (current-buffer)))
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; command handlers
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentOpen
|
|
||||||
(lambda (arg)
|
|
||||||
(cl-multiple-value-bind (file-name region-start region-length) arg
|
|
||||||
(let ((buffer (get-file-buffer file-name)))
|
|
||||||
(unless buffer
|
|
||||||
(setf buffer (find-file-noselect file-name)))
|
|
||||||
(when buffer
|
|
||||||
(unless (sclang-document-p buffer)
|
|
||||||
(with-current-buffer buffer (sclang-mode)))
|
|
||||||
(goto-char (max (point-min) (min (point-max) region-start)))
|
|
||||||
;; TODO: how to activate region in transient-mark-mode?
|
|
||||||
(sclang-document-id buffer))))))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentNew
|
|
||||||
(lambda (arg)
|
|
||||||
(cl-multiple-value-bind (name str make-listener) arg
|
|
||||||
(let ((buffer (generate-new-buffer name)))
|
|
||||||
(with-current-buffer buffer
|
|
||||||
(insert str)
|
|
||||||
(set-buffer-modified-p nil)
|
|
||||||
(sclang-mode))
|
|
||||||
(sclang-document-id buffer)))))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentClose
|
|
||||||
(lambda (arg)
|
|
||||||
(let ((doc (and (integerp arg) (sclang-get-document arg))))
|
|
||||||
(and doc (kill-buffer doc)))
|
|
||||||
nil))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentRename
|
|
||||||
(lambda (arg)
|
|
||||||
(cl-multiple-value-bind (id name) arg
|
|
||||||
(when (stringp name)
|
|
||||||
(let ((doc (and (integerp id) (sclang-get-document id))))
|
|
||||||
(when doc
|
|
||||||
(with-current-buffer doc
|
|
||||||
(rename-buffer name t)
|
|
||||||
(sclang-document-update-property 'sclang-document-name))))))
|
|
||||||
nil))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentSetEditable
|
|
||||||
(lambda (arg)
|
|
||||||
(cl-multiple-value-bind (id flag) arg
|
|
||||||
(let ((doc (and (integerp id) (sclang-get-document id))))
|
|
||||||
(when doc
|
|
||||||
(with-current-buffer doc
|
|
||||||
(setq buffer-read-only (not flag))
|
|
||||||
(sclang-document-update-property 'sclang-editable-p)))))
|
|
||||||
nil))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentSwitchTo
|
|
||||||
(lambda (arg)
|
|
||||||
(let ((doc (and (integerp arg) (sclang-get-document arg))))
|
|
||||||
(and doc (switch-to-buffer doc)))
|
|
||||||
nil))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentPutString
|
|
||||||
(lambda (arg)
|
|
||||||
(cl-multiple-value-bind (id str) arg
|
|
||||||
(let ((doc (and (integerp id) (sclang-get-document id))))
|
|
||||||
(when doc
|
|
||||||
(with-current-buffer doc
|
|
||||||
(insert str)
|
|
||||||
)
|
|
||||||
nil)))))
|
|
||||||
|
|
||||||
(sclang-set-command-handler
|
|
||||||
'_documentPopTo
|
|
||||||
(lambda (arg)
|
|
||||||
(let ((doc (and (integerp arg) (sclang-get-document arg))))
|
|
||||||
(and doc (display-buffer doc)))
|
|
||||||
nil))
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; sclang-mode
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
(defun sclang-mode-set-local-variables ()
|
|
||||||
(set (make-local-variable 'require-final-newline) nil)
|
|
||||||
;; indentation
|
|
||||||
(set (make-local-variable 'indent-line-function)
|
|
||||||
'sclang-indent-line)
|
|
||||||
(set (make-local-variable 'tab-width) 4)
|
|
||||||
(set (make-local-variable 'indent-tabs-mode) t)
|
|
||||||
;; comment formatting
|
|
||||||
(set (make-local-variable 'comment-start) "// ")
|
|
||||||
(set (make-local-variable 'comment-end) "")
|
|
||||||
(set (make-local-variable 'comment-column) 40)
|
|
||||||
(set (make-local-variable 'comment-start-skip) "/\\*+ *\\|//+ *")
|
|
||||||
;; "\\(^\\|\\s-\\);?// *")
|
|
||||||
(set (make-local-variable 'comment-multi-line) t)
|
|
||||||
;; parsing and movement
|
|
||||||
(set (make-local-variable 'parse-sexp-ignore-comments) t)
|
|
||||||
(set (make-local-variable 'beginning-of-defun-function)
|
|
||||||
'sclang-beginning-of-defun)
|
|
||||||
(set (make-local-variable 'end-of-defun-function)
|
|
||||||
'sclang-end-of-defun)
|
|
||||||
;; paragraph formatting
|
|
||||||
;; (set (make-local-variable 'paragraph-start) (concat "$\\|" page-delimiter))
|
|
||||||
;; mostly copied from c++-mode, seems to work
|
|
||||||
(set (make-local-variable 'paragraph-start)
|
|
||||||
"[ \t]*\\(//+\\|\\**\\)[ \t]*$\\|^")
|
|
||||||
(set (make-local-variable 'paragraph-separate) paragraph-start)
|
|
||||||
(set (make-local-variable 'paragraph-ignore-fill-prefix) t)
|
|
||||||
(set (make-local-variable 'adaptive-fill-mode) t)
|
|
||||||
(set (make-local-variable 'adaptive-fill-regexp)
|
|
||||||
"[ \t]*\\(//+\\|\\**\\)[ \t]*\\([ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*\\)")
|
|
||||||
;; font lock
|
|
||||||
(set (make-local-variable 'font-lock-syntactic-face-function)
|
|
||||||
'sclang-font-lock-syntactic-face)
|
|
||||||
(set (make-local-variable 'font-lock-defaults)
|
|
||||||
sclang-font-lock-defaults)
|
|
||||||
;; ---
|
|
||||||
nil)
|
|
||||||
|
|
||||||
(defvar sclang-mode-map (sclang-fill-mode-map (make-sparse-keymap))
|
|
||||||
"Keymap used in SuperCollider mode.")
|
|
||||||
|
|
||||||
(defvar sclang-mode-syntax-table (sclang-fill-syntax-table (make-syntax-table))
|
|
||||||
"Syntax table used in SuperCollider mode.")
|
|
||||||
|
|
||||||
(defcustom sclang-mode-hook nil
|
|
||||||
"*Hook run when entering SCLang mode."
|
|
||||||
:group 'sclang-mode
|
|
||||||
:type 'hook)
|
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
(define-derived-mode sclang-mode prog-mode "SCLang"
|
|
||||||
"Major mode for editing SuperCollider language code.
|
|
||||||
\\{sclang-mode-map}"
|
|
||||||
:group 'sclang
|
|
||||||
:syntax-table sclang-mode-syntax-table
|
|
||||||
(sclang-mode-set-local-variables)
|
|
||||||
(sclang-set-font-lock-keywords)
|
|
||||||
(sclang-init-document)
|
|
||||||
(sclang-make-document)
|
|
||||||
|
|
||||||
;; Setup completion
|
|
||||||
(add-hook 'completion-at-point-functions
|
|
||||||
#'sclang-completion-at-point nil 'local)
|
|
||||||
(when (fboundp 'company-mode)
|
|
||||||
(add-to-list 'company-backends 'company-capf)))
|
|
||||||
|
|
||||||
;; =====================================================================
|
|
||||||
;; module initialization
|
|
||||||
;; =====================================================================
|
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
(add-to-list 'auto-mode-alist '("\\.scd?\\'" . sclang-mode))
|
|
||||||
(add-to-list 'interpreter-mode-alist '("sclang" . sclang-mode))
|
|
||||||
|
|
||||||
(add-hook 'sclang-library-startup-hook 'sclang-document-library-startup-hook-function)
|
|
||||||
(add-hook 'kill-buffer-hook 'sclang-document-kill-buffer-hook-function)
|
|
||||||
(add-hook 'post-command-hook 'sclang-document-post-command-hook-function)
|
|
||||||
(add-hook 'change-major-mode-hook 'sclang-document-change-major-mode-hook-function)
|
|
||||||
|
|
||||||
(provide 'sclang)
|
(provide 'sclang)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue