2022-07-30 17:15:38 +00:00
|
|
|
;;; sclang-interp.el --- IDE for working with SuperCollider -*- coding: utf-8;
|
2009-01-02 19:06:25 +00:00
|
|
|
;;
|
2022-07-30 17:15:38 +00:00
|
|
|
;; Copyright 2003 stefan kersten <steve@k-hornz.de>
|
|
|
|
|
|
|
|
;;; License:
|
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
;; 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
|
2009-04-20 08:38:27 +00:00
|
|
|
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
2009-01-02 19:06:25 +00:00
|
|
|
;; USA
|
|
|
|
|
2022-07-30 17:15:38 +00:00
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
;; SuperCollider interpreter interface
|
|
|
|
|
2021-08-09 16:05:52 +00:00
|
|
|
(require 'sclang-util)
|
|
|
|
(require 'compile)
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; post buffer access
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
;; FIXME: everything will fail when renaming the post buffer!
|
|
|
|
|
2022-07-30 17:15:38 +00:00
|
|
|
;;; Code:
|
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
(defconst sclang-post-buffer (sclang-make-buffer-name "PostBuffer")
|
|
|
|
"Name of the SuperCollider process output buffer.")
|
|
|
|
|
|
|
|
(defconst sclang-bullet-latin-1 (string-to-char (decode-coding-string "\xa5" 'utf-8))
|
|
|
|
"Character for highlighting errors (latin-1).")
|
|
|
|
|
|
|
|
(defconst sclang-bullet-utf-8 (string-to-char (decode-coding-string "\xe2\x80\xa2" 'utf-8))
|
|
|
|
"Character for highlighting errors (utf-8).")
|
|
|
|
|
|
|
|
(defconst sclang-parse-error-regexp
|
2022-07-30 17:15:38 +00:00
|
|
|
"^\\(WARNING\\|ERROR\\): .*\n[\t ]*in file '\\([^']+\\)'\n[\t ]*line \\([0-9]+\\) char \\([0-9]+\\)"
|
2009-01-02 19:06:25 +00:00
|
|
|
"Regular expression matching parse errors during library compilation.")
|
|
|
|
|
|
|
|
(defcustom sclang-max-post-buffer-size 0
|
|
|
|
"*Maximum number of characters to insert in post buffer.
|
|
|
|
Zero means no limit."
|
|
|
|
:group 'sclang-interface
|
|
|
|
:version "21.3"
|
|
|
|
:type 'integer)
|
|
|
|
|
|
|
|
(defcustom sclang-auto-scroll-post-buffer nil
|
|
|
|
"*Automatically scroll post buffer on output regardless of point position.
|
|
|
|
Default behavior is to only scroll when point is not at end of buffer."
|
|
|
|
:group 'sclang-interface
|
|
|
|
:version "21.3"
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defun sclang-get-post-buffer ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Get or create the sclang post buffer."
|
2009-01-02 19:06:25 +00:00
|
|
|
(get-buffer-create sclang-post-buffer))
|
|
|
|
|
|
|
|
(defmacro with-sclang-post-buffer (&rest body)
|
2022-07-30 17:15:38 +00:00
|
|
|
"BODY in the sclang post buffer."
|
2009-01-02 19:06:25 +00:00
|
|
|
`(with-current-buffer (sclang-get-post-buffer)
|
|
|
|
,@body))
|
|
|
|
|
|
|
|
;; (defun sclang-post-string (string)
|
|
|
|
;; (with-sclang-post-buffer
|
|
|
|
;; (let ((eobp (mapcar (lambda (w)
|
2022-07-30 17:15:38 +00:00
|
|
|
;; (cons w (= (window-point w) (point-max))))
|
|
|
|
;; (get-buffer-window-list (current-buffer) nil t))))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; (save-excursion
|
|
|
|
;; ;; insert STRING into process buffer
|
|
|
|
;; (goto-char (point-max))
|
|
|
|
;; (insert string))
|
|
|
|
;; (dolist (assoc eobp)
|
|
|
|
;; (when (cdr assoc)
|
2022-07-30 17:15:38 +00:00
|
|
|
;; (save-selected-window
|
|
|
|
;; (let ((window (car assoc)))
|
|
|
|
;; (select-window window)
|
|
|
|
;; (set-window-point window (point-max))
|
|
|
|
;; (recenter -1))))))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
;; (defun sclang-post-string (string &optional proc)
|
|
|
|
;; (let* ((buffer (process-buffer proc))
|
2022-07-30 17:15:38 +00:00
|
|
|
;; (window (display-buffer buffer)))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; (with-current-buffer buffer
|
|
|
|
;; (let ((moving (= (point) (process-mark proc))))
|
2022-07-30 17:15:38 +00:00
|
|
|
;; (save-excursion
|
|
|
|
;; ;; Insert the text, advancing the process marker.
|
|
|
|
;; (goto-char (process-mark proc))
|
|
|
|
;; (insert string)
|
|
|
|
;; (set-marker (process-mark proc) (point)))
|
|
|
|
;; (when moving
|
|
|
|
;; (goto-char (process-mark proc))
|
|
|
|
;; (set-window-point window (process-mark proc)))))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-show-post-buffer (&optional eob-p)
|
|
|
|
"Show SuperCollider process buffer.
|
|
|
|
If EOB-P is non-nil, positions cursor at end of buffer."
|
|
|
|
(interactive "P")
|
|
|
|
(with-sclang-post-buffer
|
2010-08-28 13:00:25 +00:00
|
|
|
(let ((window (display-buffer (current-buffer))))
|
2009-01-02 19:06:25 +00:00
|
|
|
(when eob-p
|
|
|
|
(goto-char (point-max))
|
|
|
|
(save-selected-window
|
2022-07-30 17:15:38 +00:00
|
|
|
(set-window-point window (point-max)))))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-clear-post-buffer ()
|
|
|
|
"Clear the output buffer."
|
|
|
|
(interactive)
|
|
|
|
(with-sclang-post-buffer (erase-buffer)))
|
|
|
|
|
|
|
|
(defun sclang-init-post-buffer ()
|
|
|
|
"Initialize post buffer."
|
|
|
|
(get-buffer-create sclang-post-buffer)
|
|
|
|
(with-sclang-post-buffer
|
|
|
|
;; setup sclang mode
|
|
|
|
(sclang-mode)
|
|
|
|
(set (make-local-variable 'font-lock-fontify-region-function)
|
2022-07-30 17:15:38 +00:00
|
|
|
(lambda (&rest args)))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; setup compilation mode
|
|
|
|
(compilation-minor-mode)
|
2022-07-30 17:15:38 +00:00
|
|
|
;; see elisp docs for `make-variable-buffer-local' and `make-local-variable' use cases
|
|
|
|
(set (make-local-variable 'compilation-error-screen-columns) nil)
|
|
|
|
(set (make-local-variable 'compilation-error-regexp-alist)
|
|
|
|
(cons (list sclang-parse-error-regexp 2 3 4) compilation-error-regexp-alist))
|
|
|
|
(set (make-local-variable 'compilation-parse-errors-function)
|
|
|
|
(lambda (limit-search find-at-least)
|
|
|
|
(compilation-parse-errors limit-search find-at-least)))
|
|
|
|
(set (make-local-variable 'compilation-parse-errors-filename-function)
|
|
|
|
(lambda (file-name)
|
|
|
|
file-name)))
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-clear-post-buffer)
|
|
|
|
(sclang-show-post-buffer))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; interpreter interface
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defconst sclang-process "SCLang"
|
|
|
|
"Name of the SuperCollider interpreter subprocess.")
|
|
|
|
|
|
|
|
(defcustom sclang-program "sclang"
|
|
|
|
"*Name of the SuperCollider interpreter program."
|
|
|
|
:group 'sclang-programs
|
|
|
|
:version "21.3"
|
|
|
|
:type 'string)
|
|
|
|
|
2019-12-24 22:18:08 +00:00
|
|
|
(defcustom sclang-runtime-directory nil
|
|
|
|
"Path to the SuperCollider runtime directory."
|
2009-01-02 19:06:25 +00:00
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
2019-12-24 22:18:08 +00:00
|
|
|
:type '(choice (const nil) directory)
|
2009-01-02 19:06:25 +00:00
|
|
|
:options '(:must-match))
|
|
|
|
|
2019-12-24 22:18:08 +00:00
|
|
|
(defcustom sclang-library-configuration-file nil
|
|
|
|
"Path of the library configuration file."
|
2009-01-02 19:06:25 +00:00
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
2019-12-24 22:18:08 +00:00
|
|
|
:type '(choice (const nil) file)
|
2009-01-02 19:06:25 +00:00
|
|
|
:options '(:must-match))
|
|
|
|
|
|
|
|
(defcustom sclang-heap-size ""
|
|
|
|
"*Initial heap size."
|
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
|
|
|
:type 'string)
|
|
|
|
|
|
|
|
(defcustom sclang-heap-growth ""
|
|
|
|
"*Heap growth."
|
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
|
|
|
:type 'string)
|
|
|
|
|
2019-12-24 22:18:08 +00:00
|
|
|
(defcustom sclang-udp-port nil
|
|
|
|
"UDP listening port."
|
2009-01-02 19:06:25 +00:00
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
2019-12-24 22:18:08 +00:00
|
|
|
:type '(choice (const :tag "Default" nil) integer))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defcustom sclang-main-run nil
|
|
|
|
"*Call Main.run on startup."
|
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
|
|
|
:type 'boolean)
|
2009-09-26 06:17:48 +00:00
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
(defcustom sclang-main-stop nil
|
|
|
|
"*Call Main.stop on shutdown."
|
|
|
|
:group 'sclang-options
|
|
|
|
:version "21.3"
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; helper functions
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defun sclang-get-process ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Return the current sclang process."
|
2009-01-02 19:06:25 +00:00
|
|
|
(get-process sclang-process))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; library startup/shutdown
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defvar sclang-library-initialized-p nil)
|
|
|
|
|
|
|
|
(defcustom sclang-library-startup-hook nil
|
|
|
|
"*Hook run after initialization of the SCLang process."
|
|
|
|
:group 'sclang-interface
|
|
|
|
:type 'hook)
|
|
|
|
|
|
|
|
(defcustom sclang-library-shutdown-hook nil
|
|
|
|
"*Hook run before deletion of the SCLang process."
|
|
|
|
:group 'sclang-interface
|
|
|
|
:type 'hook)
|
|
|
|
|
|
|
|
;; library initialization works like this:
|
|
|
|
;;
|
|
|
|
;; * emacs starts sclang with SCLANG_COMMAND_FIFO set in the environment
|
|
|
|
;; * sclang opens fifo for communication with emacs during class tree
|
|
|
|
;; initialization
|
|
|
|
;; * sclang sends '_init' command
|
|
|
|
;; * '_init' command handler calls sclang-on-library-startup to complete
|
|
|
|
;; initialization
|
|
|
|
|
|
|
|
(defun sclang-library-initialized-p ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Is sclang library initialized?"
|
2009-01-02 19:06:25 +00:00
|
|
|
(and (sclang-get-process)
|
|
|
|
sclang-library-initialized-p))
|
|
|
|
|
|
|
|
(defun sclang-on-library-startup ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Initialize sclang library."
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-message "Initializing library...")
|
|
|
|
(setq sclang-library-initialized-p t)
|
|
|
|
(run-hooks 'sclang-library-startup-hook)
|
|
|
|
(sclang-message "Initializing library...done"))
|
|
|
|
|
|
|
|
(defun sclang-on-library-shutdown ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Library shutdown."
|
2011-12-06 23:00:16 +00:00
|
|
|
(when sclang-library-initialized-p
|
|
|
|
(run-hooks 'sclang-library-shutdown-hook)
|
|
|
|
(setq sclang-library-initialized-p nil)
|
|
|
|
(sclang-message "Shutting down library...")))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; process hooks
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defun sclang-process-sentinel (proc msg)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Process sentinel PROC MSG."
|
2009-01-02 19:06:25 +00:00
|
|
|
(with-sclang-post-buffer
|
|
|
|
(goto-char (point-max))
|
|
|
|
(insert
|
|
|
|
(if (and (bolp) (eolp)) "\n" "\n\n")
|
|
|
|
(format "*** %s %s ***" proc (substring msg 0 -1))
|
|
|
|
"\n\n"))
|
|
|
|
(when (memq (process-status proc) '(exit signal))
|
2011-09-25 04:03:20 +00:00
|
|
|
(sclang-on-library-shutdown)
|
|
|
|
(sclang-stop-command-process)))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-process-filter (process string)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Process filter PROCESS STRING."
|
2009-01-02 19:06:25 +00:00
|
|
|
(let ((buffer (process-buffer process)))
|
|
|
|
(with-current-buffer buffer
|
|
|
|
(when (and (> sclang-max-post-buffer-size 0)
|
2022-07-30 17:15:38 +00:00
|
|
|
(> (buffer-size) sclang-max-post-buffer-size))
|
|
|
|
(erase-buffer))
|
2009-01-02 19:06:25 +00:00
|
|
|
(let ((move-point (or sclang-auto-scroll-post-buffer
|
2022-07-30 17:15:38 +00:00
|
|
|
(= (point) (process-mark process)))))
|
|
|
|
(save-excursion
|
|
|
|
;; replace mac-roman bullet with unicode character
|
|
|
|
(subst-char-in-string sclang-bullet-latin-1 sclang-bullet-utf-8 string t)
|
|
|
|
;; insert the text, advancing the process marker.
|
|
|
|
(goto-char (process-mark process))
|
|
|
|
(insert string)
|
|
|
|
(set-marker (process-mark process) (point)))
|
|
|
|
(when move-point
|
|
|
|
(goto-char (process-mark process))
|
|
|
|
(walk-windows
|
|
|
|
(lambda (window)
|
|
|
|
(when (eq buffer (window-buffer window))
|
|
|
|
(set-window-point window (process-mark process))))
|
|
|
|
nil t))))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; process startup/shutdown
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defun sclang-memory-option-p (string)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Is STRING an sclang memory option?"
|
2009-01-02 19:06:25 +00:00
|
|
|
(let ((case-fold-search nil))
|
|
|
|
(string-match "^[1-9][0-9]*[km]?$" string)))
|
|
|
|
|
|
|
|
(defun sclang-port-option-p (number)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Is NUMBER a valid sclang port?"
|
2019-12-24 22:18:08 +00:00
|
|
|
(and (integerp number) (>= number 0) (<= number #XFFFF)))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-make-options ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Make options."
|
2019-12-24 22:18:08 +00:00
|
|
|
(let ((default-directory ""))
|
2019-12-26 10:12:53 +00:00
|
|
|
(nconc
|
2019-12-24 22:18:08 +00:00
|
|
|
(when (and sclang-runtime-directory
|
2022-07-30 17:15:38 +00:00
|
|
|
(file-directory-p sclang-runtime-directory))
|
2019-12-24 22:18:08 +00:00
|
|
|
(list "-d" (expand-file-name sclang-runtime-directory)))
|
|
|
|
(when (and sclang-library-configuration-file
|
2022-07-30 17:15:38 +00:00
|
|
|
(file-exists-p sclang-library-configuration-file))
|
2019-12-24 22:18:08 +00:00
|
|
|
(list "-l" (expand-file-name sclang-library-configuration-file)))
|
|
|
|
(when (sclang-memory-option-p sclang-heap-size)
|
|
|
|
(list "-m" sclang-heap-size))
|
|
|
|
(when (sclang-memory-option-p sclang-heap-growth)
|
|
|
|
(list "-g" sclang-heap-growth))
|
|
|
|
(when (sclang-port-option-p sclang-udp-port)
|
|
|
|
(list "-u" (number-to-string sclang-udp-port)))
|
|
|
|
(when sclang-main-run
|
|
|
|
(list "-r"))
|
|
|
|
(when sclang-main-stop
|
|
|
|
(list "-s"))
|
|
|
|
(list "-iscel"))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
2021-08-17 00:33:05 +00:00
|
|
|
;;;###autoload (autoload 'sclang-start "sclang" "Start SuperCollider process." t)
|
2009-01-02 19:06:25 +00:00
|
|
|
(defun sclang-start ()
|
|
|
|
"Start SuperCollider process."
|
|
|
|
(interactive)
|
|
|
|
(sclang-stop)
|
2011-12-06 23:00:16 +00:00
|
|
|
(sclang-on-library-shutdown)
|
2009-01-02 19:06:25 +00:00
|
|
|
(sit-for 1)
|
|
|
|
(sclang-init-post-buffer)
|
|
|
|
(sclang-start-command-process)
|
|
|
|
(let ((process-connection-type nil))
|
|
|
|
(let ((proc (apply 'start-process
|
2022-07-30 17:15:38 +00:00
|
|
|
sclang-process sclang-post-buffer
|
|
|
|
sclang-program (sclang-make-options))))
|
2009-01-02 19:06:25 +00:00
|
|
|
(set-process-sentinel proc 'sclang-process-sentinel)
|
|
|
|
(set-process-filter proc 'sclang-process-filter)
|
|
|
|
(set-process-coding-system proc 'mule-utf-8 'mule-utf-8)
|
2011-07-18 18:18:29 +00:00
|
|
|
(set-process-query-on-exit-flag proc nil)
|
2009-01-02 19:06:25 +00:00
|
|
|
proc)))
|
|
|
|
|
|
|
|
(defun sclang-kill ()
|
|
|
|
"Kill SuperCollider process."
|
|
|
|
(interactive)
|
|
|
|
(when (sclang-get-process)
|
|
|
|
(kill-process sclang-process)
|
|
|
|
(delete-process sclang-process)))
|
|
|
|
|
|
|
|
(defun sclang-stop ()
|
|
|
|
"Stop SuperCollider process."
|
|
|
|
(interactive)
|
|
|
|
(when (sclang-get-process)
|
|
|
|
(process-send-eof sclang-process)
|
|
|
|
(let ((tries 4)
|
2022-07-30 17:15:38 +00:00
|
|
|
(i 0))
|
2009-01-02 19:06:25 +00:00
|
|
|
(while (and (sclang-get-process)
|
2022-07-30 17:15:38 +00:00
|
|
|
(< i tries))
|
|
|
|
(cl-incf i)
|
|
|
|
(sit-for 0.5))))
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-kill)
|
2011-09-25 04:03:20 +00:00
|
|
|
(sclang-stop-command-process))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
2011-06-27 11:19:19 +00:00
|
|
|
(defun sclang-recompile ()
|
|
|
|
"Recompile class library."
|
|
|
|
(interactive)
|
|
|
|
(when (sclang-get-process)
|
2022-07-30 17:15:38 +00:00
|
|
|
(process-send-string sclang-process "\x18")))
|
2011-06-27 11:19:19 +00:00
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
;; =====================================================================
|
|
|
|
;; command process
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defcustom sclang-mkfifo-program "mkfifo"
|
|
|
|
"*Name of the \"mkfifo\" program.
|
|
|
|
|
|
|
|
Change this if \"mkfifo\" has a non-standard name or location."
|
|
|
|
:group 'sclang-programs
|
|
|
|
:type 'string)
|
|
|
|
|
|
|
|
(defcustom sclang-cat-program "cat"
|
|
|
|
"*Name of the \"cat\" program.
|
|
|
|
|
|
|
|
Change this if \"cat\" has a non-standard name or location."
|
|
|
|
:group 'sclang-programs
|
|
|
|
:type 'string)
|
|
|
|
|
|
|
|
(defconst sclang-command-process "SCLang Command"
|
|
|
|
"Subprocess for receiving command results from sclang.")
|
|
|
|
|
2011-09-25 04:03:20 +00:00
|
|
|
(defconst sclang-cmd-helper-proc "SCLang Command Helper"
|
2022-07-30 17:15:38 +00:00
|
|
|
"Dummy subprocess that will keep the command fifo open for writing.
|
|
|
|
This is needed so reading does not automatically fail when sclang
|
|
|
|
closes its own writing end of the fifo.")
|
2011-09-25 04:03:20 +00:00
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
(defvar sclang-command-fifo nil
|
|
|
|
"FIFO for communicating with the subprocess.")
|
|
|
|
|
|
|
|
(defun sclang-delete-command-fifo ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Delete the command fifo."
|
2009-01-02 19:06:25 +00:00
|
|
|
(and sclang-command-fifo
|
|
|
|
(file-exists-p sclang-command-fifo)
|
|
|
|
(delete-file sclang-command-fifo)))
|
|
|
|
|
|
|
|
(defun sclang-release-command-fifo ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Release the command fifo."
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-delete-command-fifo)
|
|
|
|
(setq sclang-command-fifo nil))
|
|
|
|
|
|
|
|
(defun sclang-create-command-fifo ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Create the command fifo."
|
2009-01-02 19:06:25 +00:00
|
|
|
(setq sclang-command-fifo (make-temp-name
|
2022-07-30 17:15:38 +00:00
|
|
|
(expand-file-name
|
|
|
|
"sclang-command-fifo." temporary-file-directory)))
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-delete-command-fifo)
|
|
|
|
(let ((res (call-process sclang-mkfifo-program
|
2022-07-30 17:15:38 +00:00
|
|
|
nil t t
|
|
|
|
sclang-command-fifo)))
|
2009-01-02 19:06:25 +00:00
|
|
|
(unless (eq 0 res)
|
|
|
|
(message "SCLang: Couldn't create command fifo")
|
|
|
|
(setq sclang-command-fifo nil))))
|
|
|
|
|
|
|
|
(defun sclang-start-command-process ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Start the command process."
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-create-command-fifo)
|
|
|
|
(when sclang-command-fifo
|
2011-09-25 04:03:20 +00:00
|
|
|
;; start the dummy process to keep the fifo open
|
|
|
|
(let ((process-connection-type nil))
|
|
|
|
(let ((proc (start-process-shell-command
|
2022-07-30 17:15:38 +00:00
|
|
|
sclang-cmd-helper-proc nil
|
|
|
|
(concat sclang-cat-program " > " sclang-command-fifo))))
|
|
|
|
(set-process-query-on-exit-flag proc nil)))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; sclang gets the fifo path via the environment
|
|
|
|
(setenv "SCLANG_COMMAND_FIFO" sclang-command-fifo)
|
|
|
|
(let ((process-connection-type nil))
|
|
|
|
(let ((proc (start-process
|
2022-07-30 17:15:38 +00:00
|
|
|
sclang-command-process nil
|
|
|
|
sclang-cat-program sclang-command-fifo)))
|
|
|
|
(set-process-filter proc 'sclang-command-process-filter)
|
|
|
|
;; this is important. use a unibyte stream without eol
|
|
|
|
;; conversion for communication.
|
|
|
|
(set-process-coding-system proc 'no-conversion 'no-conversion)
|
|
|
|
(set-process-query-on-exit-flag proc nil)))
|
2009-01-02 19:06:25 +00:00
|
|
|
(unless (get-process sclang-command-process)
|
|
|
|
(message "SCLang: Couldn't start command process"))))
|
|
|
|
|
2011-09-25 04:03:20 +00:00
|
|
|
(defun sclang-stop-command-process ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Stop the command process."
|
2011-09-25 04:03:20 +00:00
|
|
|
(when (get-process sclang-cmd-helper-proc)
|
|
|
|
(kill-process sclang-cmd-helper-proc)
|
|
|
|
(delete-process sclang-cmd-helper-proc))
|
|
|
|
;; the real command process should now quit automatically,
|
|
|
|
;; since there is no more writers to the command fifo
|
|
|
|
(sclang-release-command-fifo))
|
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
(defvar sclang-command-process-previous nil
|
|
|
|
"Unprocessed command process output.")
|
|
|
|
|
|
|
|
(defun sclang-command-process-filter (proc string)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Command process filter PROC STRING."
|
2009-01-02 19:06:25 +00:00
|
|
|
(when sclang-command-process-previous
|
|
|
|
(setq string (concat sclang-command-process-previous string)))
|
|
|
|
(let (end)
|
|
|
|
(while (and (> (length string) 3)
|
2022-07-30 17:15:38 +00:00
|
|
|
(>= (length string)
|
|
|
|
(setq end (+ 4 (sclang-string-to-int32 string)))))
|
2019-12-17 07:32:05 +00:00
|
|
|
(sclang-handle-command-result
|
2019-12-26 10:12:53 +00:00
|
|
|
(read (decode-coding-string (substring string 4 end) 'utf-8)))
|
2009-01-02 19:06:25 +00:00
|
|
|
(setq string (substring string end))))
|
|
|
|
(setq sclang-command-process-previous string))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; command interface
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
;; symbol property: sclang-command-handler
|
|
|
|
|
|
|
|
(defun sclang-set-command-handler (symbol function)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Set command handler SYMBOL to FUNCTION."
|
2009-01-02 19:06:25 +00:00
|
|
|
(put symbol 'sclang-command-handler function))
|
|
|
|
|
|
|
|
(defun sclang-perform-command (symbol &rest args)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Eval command SYMBOL with ARGS."
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-eval-string (sclang-format
|
2022-07-30 17:15:38 +00:00
|
|
|
"Emacs.lispPerformCommand(%o, %o, true)"
|
|
|
|
symbol args)))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-perform-command-no-result (symbol &rest args)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Eval command SYMBOL with ARGS. No result."
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-eval-string (sclang-format
|
2022-07-30 17:15:38 +00:00
|
|
|
"Emacs.lispPerformCommand(%o, %o, false)"
|
|
|
|
symbol args)))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-default-command-handler (fun arg)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Default command handler for FUN with ARG.
|
2009-01-02 19:06:25 +00:00
|
|
|
Displays short message on error."
|
2022-07-30 17:15:38 +00:00
|
|
|
(condition-case err
|
2009-01-02 19:06:25 +00:00
|
|
|
(funcall fun arg)
|
2022-07-30 17:15:38 +00:00
|
|
|
(error (sclang-message
|
|
|
|
(format "Error in command handler: %s" err)) nil)))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-debug-command-handler (fun arg)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Debugging command handler for FUN with ARG.
|
2009-01-02 19:06:25 +00:00
|
|
|
Enters debugger on error."
|
|
|
|
(let ((debug-on-error t)
|
2022-07-30 17:15:38 +00:00
|
|
|
(debug-on-signal t))
|
2009-01-02 19:06:25 +00:00
|
|
|
(funcall fun arg)))
|
|
|
|
|
|
|
|
(defvar sclang-command-handler 'sclang-default-command-handler
|
|
|
|
"Function called when handling command result.")
|
|
|
|
|
|
|
|
(defun sclang-toggle-debug-command-handler (&optional arg)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Toggle debugging of command handler (or set with ARG).
|
|
|
|
Activate debugging iff ARG is positive."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive "P")
|
|
|
|
(setq sclang-command-handler
|
2022-07-30 17:15:38 +00:00
|
|
|
(if (or (and arg (> arg 0))
|
|
|
|
(eq sclang-command-handler 'sclang-debug-command-handler))
|
|
|
|
'sclang-default-command-handler
|
|
|
|
'sclang-debug-command-handler))
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-message "Command handler debugging %s."
|
2022-07-30 17:15:38 +00:00
|
|
|
(if (eq sclang-command-handler 'sclang-debug-command-handler)
|
|
|
|
"enabled"
|
|
|
|
"disabled")))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(defun sclang-handle-command-result (list)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Handle command result LIST."
|
2009-01-02 19:06:25 +00:00
|
|
|
(condition-case nil
|
|
|
|
(let ((fun (get (nth 0 list) 'sclang-command-handler))
|
2022-07-30 17:15:38 +00:00
|
|
|
(arg (nth 1 list))
|
|
|
|
(id (nth 2 list)))
|
|
|
|
(when (functionp fun)
|
|
|
|
(let ((res (funcall sclang-command-handler fun arg)))
|
|
|
|
(when id
|
|
|
|
(sclang-eval-string
|
|
|
|
(sclang-format "Emacs.lispHandleCommandResult(%o, %o)" id res))))))
|
2009-01-02 19:06:25 +00:00
|
|
|
(error nil)))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; code evaluation
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defconst sclang-token-interpret-cmd-line (char-to-string #X1b))
|
|
|
|
(defconst sclang-token-interpret-print-cmd-line (char-to-string #X0c))
|
|
|
|
|
|
|
|
(defcustom sclang-eval-line-forward t
|
|
|
|
"*If non-nil `sclang-eval-line' advances to the next line."
|
|
|
|
:group 'sclang-interface
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defun sclang-send-string (token string &optional force)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Send TOKEN STRING to sclang (optionally FORCE)."
|
2009-01-02 19:06:25 +00:00
|
|
|
(let ((proc (sclang-get-process)))
|
|
|
|
(when (and proc (or (sclang-library-initialized-p) force))
|
|
|
|
(process-send-string proc (concat string token))
|
|
|
|
string)))
|
|
|
|
|
|
|
|
(defun sclang-eval-string (string &optional print-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate STRING with sclang and print the result if PRINT-P is non-nil.
|
|
|
|
Return STRING if successful, otherwise nil."
|
2009-01-02 19:06:25 +00:00
|
|
|
(sclang-send-string
|
|
|
|
(if print-p sclang-token-interpret-print-cmd-line sclang-token-interpret-cmd-line)
|
|
|
|
string))
|
|
|
|
|
|
|
|
(defun sclang-eval-expression (string &optional silent-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate STRING as SuperCollider code (suppress output if SILENT-P is non-nil)."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive "sEval: \nP")
|
|
|
|
(sclang-eval-string string (not silent-p)))
|
|
|
|
|
|
|
|
(defun sclang-eval-line (&optional silent-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate current line with sclang (suppress output if SILENT-P is non-nil)."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive "P")
|
|
|
|
(let ((string (sclang-line-at-point)))
|
|
|
|
(when string
|
|
|
|
(sclang-eval-string string (not silent-p)))
|
|
|
|
(and sclang-eval-line-forward
|
2022-07-30 17:15:38 +00:00
|
|
|
(/= (line-end-position) (point-max))
|
|
|
|
(forward-line 1))
|
2009-01-02 19:06:25 +00:00
|
|
|
string))
|
|
|
|
|
|
|
|
(defun sclang-eval-region (&optional silent-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate current region with sclang (suppress output if SILENT-P is non-nil)."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive "P")
|
|
|
|
(sclang-eval-string
|
|
|
|
(buffer-substring-no-properties (region-beginning) (region-end))
|
|
|
|
(not silent-p)))
|
|
|
|
|
|
|
|
(defun sclang-eval-region-or-line (&optional silent-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate current line or region (suppress output if SILENT-P is non-nil)."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive "P")
|
|
|
|
(if (and transient-mark-mode mark-active)
|
|
|
|
(sclang-eval-region silent-p)
|
|
|
|
(sclang-eval-line silent-p)))
|
|
|
|
|
|
|
|
(defun sclang-eval-defun (&optional silent-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate current function definition (suppress output if SILENT-P is non-nil)."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive "P")
|
|
|
|
(let ((string (sclang-defun-at-point)))
|
|
|
|
(when (and string (string-match "^(" string))
|
|
|
|
(sclang-eval-string string (not silent-p))
|
|
|
|
string)))
|
|
|
|
|
2022-07-30 17:15:38 +00:00
|
|
|
(defun sclang-eval-dwim ()
|
|
|
|
"Evaluate line, region, function or buffer."
|
|
|
|
(interactive "P")
|
|
|
|
(or (sclang-eval-defun)
|
|
|
|
(sclang-eval-region-or-line)))
|
|
|
|
|
2009-09-12 15:11:18 +00:00
|
|
|
(defun sclang-eval-document (&optional silent-p)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Evaluate current buffer with sclang (suppress output if SILENT-P is non-nil)."
|
2009-09-12 15:11:18 +00:00
|
|
|
(interactive "P")
|
2011-06-09 16:22:06 +00:00
|
|
|
(save-excursion
|
|
|
|
(sclang-eval-string
|
2022-07-30 17:15:38 +00:00
|
|
|
(buffer-substring-no-properties (point-min) (point-max))
|
2011-06-09 16:22:06 +00:00
|
|
|
(not silent-p))))
|
2009-09-12 15:11:18 +00:00
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
(defvar sclang-eval-results nil
|
|
|
|
"Save results of sync SCLang evaluation.")
|
|
|
|
|
|
|
|
(sclang-set-command-handler
|
|
|
|
'evalSCLang
|
|
|
|
(lambda (arg) (push arg sclang-eval-results)))
|
|
|
|
|
|
|
|
(defun sclang-eval-sync (string)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Eval STRING in sclang and return result as a Lisp value."
|
2009-01-02 19:06:25 +00:00
|
|
|
(let ((proc (get-process sclang-command-process)))
|
|
|
|
(if (and (processp proc) (eq (process-status proc) 'run))
|
2022-07-30 17:15:38 +00:00
|
|
|
(let ((time (current-time)) (tick 10000) elt)
|
|
|
|
(sclang-perform-command 'evalSCLang string time)
|
|
|
|
(while (and (> (cl-decf tick) 0)
|
|
|
|
(not (setq elt (assoc time sclang-eval-results))))
|
|
|
|
(accept-process-output proc 0 100))
|
|
|
|
(if elt
|
|
|
|
(prog1 (if (eq (nth 1 elt) 'ok)
|
|
|
|
(nth 2 elt)
|
|
|
|
(setq sclang-eval-results (delq elt sclang-eval-results))
|
|
|
|
(signal 'sclang-error (nth 2 elt)))
|
|
|
|
(setq sclang-eval-results (delq elt sclang-eval-results)))
|
|
|
|
(error "SCLang sync eval timeout")))
|
2009-01-02 19:06:25 +00:00
|
|
|
(error "SCLang Command process not running"))))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; searching
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
;; (defun sclang-help-file-paths ()
|
|
|
|
;; "Return a list of help file paths."
|
|
|
|
|
|
|
|
|
|
|
|
;; (defun sclang-grep-help-files ()
|
|
|
|
;; (interactive)
|
|
|
|
;; (let ((sclang-grep-prompt "Search help files: ")
|
2022-07-30 17:15:38 +00:00
|
|
|
;; (sclang-grep-files (mapcar 'cdr sclang-help-topic-alist)))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; (call-interactively 'sclang-grep-files)))
|
|
|
|
|
|
|
|
;; (defvar sclang-grep-history nil)
|
|
|
|
|
|
|
|
;; (defcustom sclang-grep-case-fold-search t
|
|
|
|
;; "*Non-nil if sclang-grep-files should ignore case."
|
|
|
|
;; :group 'sclang-interface
|
|
|
|
;; :version "21.4"
|
|
|
|
;; :type 'boolean)
|
|
|
|
|
|
|
|
;; (defvar sclang-grep-files nil)
|
|
|
|
;; (defvar sclang-grep-prompt "Grep: ")
|
|
|
|
|
|
|
|
;; (defun sclang-grep-files (regexp)
|
|
|
|
;; (interactive
|
|
|
|
;; (let ((grep-default (or (when current-prefix-arg (sclang-symbol-at-point))
|
2022-07-30 17:15:38 +00:00
|
|
|
;; (car sclang-grep-history))))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; (list (read-from-minibuffer sclang-grep-prompt
|
2022-07-30 17:15:38 +00:00
|
|
|
;; grep-default
|
|
|
|
;; nil nil 'sclang-grep-history))))
|
2009-01-02 19:06:25 +00:00
|
|
|
;; (grep-compute-defaults)
|
|
|
|
;; (grep (concat grep-program
|
2022-07-30 17:15:38 +00:00
|
|
|
;; " -n"
|
|
|
|
;; (and sclang-grep-case-fold-search " -i")
|
|
|
|
;; " -e" regexp
|
|
|
|
;; " " (mapconcat 'shell-quote-argument sclang-grep-files " "))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; workspace
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defcustom sclang-show-workspace-on-startup t
|
|
|
|
"*If non-nil show the workspace buffer on library startup."
|
|
|
|
:group 'sclang-interface
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defconst sclang-workspace-buffer (sclang-make-buffer-name "Workspace"))
|
|
|
|
|
|
|
|
(defun sclang-fill-workspace-mode-map (map)
|
2022-07-30 17:15:38 +00:00
|
|
|
"Fill the workspace keymap MAP."
|
2009-01-02 19:06:25 +00:00
|
|
|
(define-key map "\C-c}" 'bury-buffer))
|
|
|
|
|
|
|
|
(defun sclang-switch-to-workspace ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Switch to SuperCollider workspace buffer."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive)
|
|
|
|
(let ((buffer (get-buffer sclang-workspace-buffer)))
|
|
|
|
(unless buffer
|
|
|
|
(setq buffer (get-buffer-create sclang-workspace-buffer))
|
|
|
|
(with-current-buffer buffer
|
2022-07-30 17:15:38 +00:00
|
|
|
(sclang-mode)
|
|
|
|
;; why a buffer local keymap?
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
(set-keymap-parent map sclang-mode-map)
|
|
|
|
(sclang-fill-workspace-mode-map map)
|
|
|
|
(use-local-map map))
|
|
|
|
(let ((line (concat "// " (make-string 69 ?=) "\n")))
|
|
|
|
(insert line)
|
|
|
|
(insert "// SuperCollider Workspace\n")
|
|
|
|
(insert line)
|
|
|
|
;; (insert "// using HTML Help: C-c C-h as usual, then switch to w3m buffer\n")
|
|
|
|
;; (insert "// and do M-x sclang-minor-mode in order te enable sclang code execution\n")
|
|
|
|
;; (insert line)
|
|
|
|
(insert "\n"))
|
|
|
|
(set-buffer-modified-p nil)
|
|
|
|
;; cwd to sclang-runtime-directory
|
|
|
|
(if (and sclang-runtime-directory
|
|
|
|
(file-directory-p sclang-runtime-directory))
|
|
|
|
(setq default-directory sclang-runtime-directory))))
|
2009-01-02 19:06:25 +00:00
|
|
|
(switch-to-buffer buffer)))
|
|
|
|
|
2009-09-26 06:17:48 +00:00
|
|
|
(add-hook 'sclang-library-startup-hook
|
2022-07-30 17:15:38 +00:00
|
|
|
(lambda () (and sclang-show-workspace-on-startup
|
|
|
|
(sclang-switch-to-workspace))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; language control
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(defun sclang-main-run ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Run sclang process."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive)
|
|
|
|
(sclang-eval-string "thisProcess.run"))
|
|
|
|
|
|
|
|
(defun sclang-main-stop ()
|
2022-07-30 17:15:38 +00:00
|
|
|
"Stop sclang process."
|
2009-01-02 19:06:25 +00:00
|
|
|
(interactive)
|
|
|
|
(sclang-eval-string "thisProcess.stop"))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; default command handlers
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
(sclang-set-command-handler '_init (lambda (arg) (sclang-on-library-startup)))
|
|
|
|
|
|
|
|
(sclang-set-command-handler
|
|
|
|
'_eval
|
|
|
|
(lambda (expr)
|
|
|
|
(when (stringp expr)
|
|
|
|
(eval (read expr)))))
|
|
|
|
|
|
|
|
;; =====================================================================
|
|
|
|
;; module setup
|
|
|
|
;; =====================================================================
|
|
|
|
|
|
|
|
;; shutdown process cleanly
|
|
|
|
(add-hook 'kill-emacs-hook (lambda () (sclang-stop)))
|
|
|
|
|
|
|
|
;; add command line switches
|
|
|
|
(add-to-list 'command-switch-alist
|
2022-07-30 17:15:38 +00:00
|
|
|
(cons "-sclang"
|
|
|
|
(lambda (switch)
|
|
|
|
(sclang-start))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(add-to-list 'command-switch-alist
|
2022-07-30 17:15:38 +00:00
|
|
|
(cons "-sclang-debug"
|
|
|
|
(lambda (switch)
|
|
|
|
(sclang-toggle-debug-command-handler 1))))
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(add-to-list 'command-switch-alist
|
2022-07-30 17:15:38 +00:00
|
|
|
(cons "-scmail"
|
|
|
|
(lambda (switch)
|
|
|
|
(sclang-start)
|
|
|
|
(when command-line-args-left
|
|
|
|
(let ((file (pop command-line-args-left)))
|
|
|
|
(with-current-buffer (get-buffer-create sclang-workspace-buffer)
|
|
|
|
(and (file-exists-p file) (insert-file-contents file))
|
|
|
|
(set-buffer-modified-p nil)
|
|
|
|
(sclang-mode)
|
|
|
|
(switch-to-buffer (current-buffer))))))))
|
|
|
|
|
2009-01-02 19:06:25 +00:00
|
|
|
|
|
|
|
(provide 'sclang-interp)
|
|
|
|
|
2022-07-30 17:15:38 +00:00
|
|
|
;;; sclang-interp.el ends here
|