diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e7df509 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,42 @@ +name: CI + +on: + push: + paths-ignore: + - '**.md' + pull_request: + paths-ignore: + - '**.md' + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + emacs_version: + - 27.2 + - 26.3 + - 25.3 + + steps: + - name: Set up Emacs + uses: purcell/setup-emacs@master + with: + version: ${{matrix.emacs_version}} + + - name: Install Eldev + run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh + + - name: Check out the elisp source code + uses: actions/checkout@v2 + + - name: Test the uncompiled source + run: | + cd el + eldev -p -dtT test + + - name: Compile and run tests again + run: | + cd el + eldev compile + eldev -p -dtT test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4aee566 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +*.elc +.eldev +/el/sclang-autoloads.el diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c3263..03618c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added + - Ability to distribute via package managers - Support for `completion-at-point-functions` and `company` via `company-capf` ### Changed diff --git a/CMakeLists.txt b/CMakeLists.txt index e21cfa5..9d77014 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ add_subdirectory(el) -add_subdirectory(sc) +add_subdirectory(sc/scide_scel) install(DIRECTORY HelpSource DESTINATION share/SuperCollider/Extensions/scide_scel/) diff --git a/README.md b/README.md index 74a9e36..21a949a 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,139 @@ -Scel -==== +# scel - sclang-mode for emacs SuperCollider/Emacs interface +## Installation -Installation requirements -------------------------- +There are 3 options for installation: -For the HTML help system, you will need emacs-w3m support. +1. Using SuperCollider Quarks (recommended) +2. From debian package `supercollider-emacs` +3. From source +Option #1 is the best cross-platform option, and is recommended. Whatever option +you choose, *make sure not to mix installation methods*. In particular, do not +install the Quark if you already have the supercollider-emacs package or if you +compiled SuperCollider with the `-DSC_EL=ON` option. Otherwise you will get an +error from SuperCollider about duplicated classes. -Installation (default) ----------------------- +### Install Option 1: SuperCollider's own package manager -By default emacs-lisp files are installed in +The repository contains two subprojects. `/el` contains the emacs-lisp +implementation. `/sc` contains the SuperCollider code required to +implement the Emacs interface. SuperCollider has its own package system +called Quarks, which we can use to install both halves. -`$prefix/share/emacs/site-lisp` - -SuperCollider files are put in - -`$prefix/share/SuperCollider/Extensions/scide_scel` - - -The only thing you need to do is loading the sclang interface in your `~/.emacs`: +Evaluate this code in the SuperCollider GUI by pasting it and pressing +shift+enter: +``` supercollider +Quarks.install("https://github.com/supercollider/scel"); ``` + +The scel repository will be downloaded to your local file system and the path +will be added to your currently used `sclang_conf.yaml` file. (You can find its +location by evaluating `Platform.userConfigDir`) + +Next, find out where scel was installed. You will use this install-path in your +emacs config. + +``` supercollider +Quarks.folder.postln; + +// -> /Users//Library/Application Support/SuperCollider/downloaded-quarks +``` + +Now in your emacs config, add the `/el` subdirectory to your load path +``` emacs-lisp +;; in ~/.emacs + +;; Paste path from above, appending "/scel/el" +(add-to-list 'load-path "/Users//Library/Application Support/SuperCollider/downloaded-quarks/scel/el") +(require 'sclang) +``` +#### On macOS + +If `sclang` executable is not on your path, you may need to add it to your +exec-path. + +``` emacs-lisp +;; in ~/.emacs +(setq exec-path (append exec-path '("/Applications/SuperCollider.app/Contents/MacOS/"))) +``` + +#### Installing with an emacs package manager + +It's completely possible to install with +[straight.el](https://github.com/raxod502/straight.el), +[use-package](https://github.com/jwiegley/use-package), +[doom](https://github.com/hlissner/doom-emacs), etc. Instructions for doing so +are beyond the scope of this README, but note that `autoloads` are implemented +for entry-point functions so if you like to have a speedy start-up time you can +use the `:defer t` option. + +### Install Option 2: Debian package + +There is a debian package which provides emacs integration called +`supercollider-emacs`. Option #1 will likely be more recent, but +if you prefer you can install the package with: + +``` shell +sudo apt install supercollider-emacs +``` + +### Install Option 3: Installing from source + +If you are building SuperCollider from source, you can optionally compile and +install this library along with it. The cmake `-DSC_EL` flag controls whether +scel will be compiled. On Linux machines `-DSC_EL=ON` by default. See the +supercollider README files for more info. + +``` emacs-lisp +;; in ~/.emacs +(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/SuperCollider/") ;; path will depend on your compilation settings (require 'sclang) ``` -For the HTML help system to fully function also add -``` +## Optional Installation Requirements + +There are two options for SuperCollider help files. They can be opened in the +help browser that ships with SuperCollider, or if you prefer an emacs-only +workflow they can be opened using the w3m browser. The browse-in-emacs option +requires an additional dependency. + +```emacs-lisp +;; in ~/.emacs (require 'w3m) ``` +## Usage -Installation (detailed) ------------------------ +The main function which starts interacting with the sclang interpreter is +`sclang-start`. You can execute that anywhere with `M-x sclang-start`, or from +within a `.scd` buffer by pressing `C-c C-o`. -Put all `*.el` files in emacs' load-path. e.g. if you put them in -`~/emacs/`, add the following lines to `~/.emacs` (or whatever your init -file is called): +If you know you want to launch sclang when you start emacs you can use the `-f` +option to execute that function right away: -``` -(add-to-list 'load-path "~/emacs") -(require 'sclang) +``` shell +# in your terminal +emacs -f sclang-start ``` -for the HTML help system to fully function also add -``` -(require 'w3m) -``` +## Configuration -now put all `*.sc` files in sclang's library path, e.g. if you put them -in a non-standard location, such as `~/SuperCollider/Emacs`, add the -following to `~/.config/SuperCollider/sclang_conf.yaml` (Linux) or `~/Library/Application Support/SuperCollider/sclang_conf.yaml` (macOS): +To fine-tune the installation from within emacs' graphical customization +interface, type: -``` -includePaths: - [~/SuperCollider/Emacs] -``` +`M-x sclang-customize` -(note normally this is not needed as they are put into sclang's library -path during installation with scons). +NOTE: If you use an sclang configuration file different from the default +`sclang_conf.yaml`, you need to specify it in scel by customizing the +`sclang-library-configuration-file `variable. Otherwise, even after installing +the Quark in SuperCollider, you won't be able to run sclang code in emacs. -Usage ------ - -In order to automatically start sclang when invoking emacs, use the following command line: - -``` -$> emacs -sclang -``` - -you're now ready to edit, inspect and execute sclang code! - - -Getting help ------------- +## Getting help Inside an sclang-mode buffer (e.g. by editing a .sc file), execute @@ -87,11 +143,16 @@ and a window with key bindings in sclang-mode will pop up. `C-x C-h` lets you search for a help file -`C-M-h` opens or switches to the Help browser (if no Help file has been opened, the default Help file will be opened). +`C-M-h` opens or switches to the Help browser (if no Help file has been opened, +the default Help file will be opened). -`E` copies the buffer, puts it in text mode and sclang-minor-mode, to enable you to edit the code parts to try out variations of the provided code in the help file. With `C-M-h` you can then return to the Help browser and browse further from the Help file. +`E` copies the buffer, puts it in text mode and sclang-minor-mode, to enable you +to edit the code parts to try out variations of the provided code in the help +file. With `C-M-h` you can then return to the Help browser and browse further +from the Help file. -`C-c C-e` allows you to edit the source of the HTML file, for example if you want to improve it and commit it to the repository. +`C-c C-e` allows you to edit the source of the HTML file, for example if you +want to improve it and commit it to the repository. To enable moving around in the help file with arrow keys add the following in your `~/.emacs`: @@ -105,25 +166,18 @@ in your `~/.emacs`: (define-key w3m-mode-map [down] 'next-line))) ``` -This ensures that the arrow keys are just for moving through the document, and not from hyperlink to hyperlink, which is the default in w3m-mode. +This ensures that the arrow keys are just for moving through the document, and +not from hyperlink to hyperlink, which is the default in w3m-mode. -Customization -------------- +## Server control -To fine-tune the installation from within emacs' graphical customization interface, type: +In the post buffer window, right-click on the server name; by default the two +servers `internal` and `localhost` are available. You will get a menu with +common server control operations. -`M-x sclang-customize` +To select another server, step through the server list by left-clicking on the +server name. -In particular, you will have to customize `sclang-runtime-directory'. - - -Server control --------------- - -In the post buffer window, right-click on the server name; by default the two servers `internal` and `localhost` are available. You will get a menu with common server control operations. - -To select another server, step through the server list by left-clicking on the server name. - -Servers instantiated from the language will automatically be available -in the mode line. +Servers instantiated from the language will automatically be available in the +mode line. diff --git a/el/Eldev b/el/Eldev new file mode 100644 index 0000000..9ff63c3 --- /dev/null +++ b/el/Eldev @@ -0,0 +1,6 @@ +; -*- mode: emacs-lisp; lexical-binding: t -*- +; +;; You can obtain eldev from https://github.com/doublep/eldev +;; We use it for package development and running tests + +(eldev-use-plugin 'autoloads) diff --git a/el/sclang-dev.el b/el/sclang-dev.el index 440409c..211082d 100644 --- a/el/sclang-dev.el +++ b/el/sclang-dev.el @@ -13,13 +13,8 @@ ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 ;; USA - -(eval-when-compile - (require 'sclang-util) - (require 'sclang-interp) - ) - - +(require 'sclang-util) +(require 'sclang-interp) (sclang-set-command-handler 'openDevSource diff --git a/el/sclang-help.el b/el/sclang-help.el index e70a864..46e1c1a 100644 --- a/el/sclang-help.el +++ b/el/sclang-help.el @@ -24,15 +24,29 @@ (require 'sclang-interp) (require 'sclang-language) (require 'sclang-mode) -(require 'sclang-vars) +(require 'sclang-vars nil 'ignore-missing-file) (require 'sclang-minor-mode) -(defcustom sclang-help-directory "~/SuperCollider/Help" - "*Directory where the SuperCollider help files are kept. OBSOLETE." +(defun sclang-system-root () + "Find the common install location for the platform." + (cond + ((boundp 'sclang-system-data-dir) + sclang-system-data-dir) + + ((eql 'darwin system-type) + (expand-file-name "~/Library/Application Support/SuperCollider")) + + ((and (eql 'gnu/linux system-type) + (file-exists-p "/usr/local/share/SuperCollider")) + "/usr/local/share/SuperCollider") + + ((eql 'gnu/linux system-type) + "/usr/share/SuperCollider"))) + +(defcustom sclang-system-help-dir (expand-file-name "Help" (sclang-system-root)) + "Installation dependent help directory." :group 'sclang-interface - :version "21.3" - :type 'directory - :options '(:must-match)) + :type 'directory) (defcustom sclang-help-path (list sclang-system-help-dir "~/.local/share/SuperCollider/Help") @@ -41,6 +55,11 @@ :version "21.4" :type '(repeat directory)) +(defcustom sclang-system-extension-dir (expand-file-name "Extensions" (sclang-system-root)) + "Installation dependent extension directory." + :group 'sclang-interface + :type 'directory) + (defconst sclang-extension-path (list sclang-system-extension-dir "~/.local/share/SuperCollider/Extensions") "List of SuperCollider extension directories.") diff --git a/el/sclang-interp.el b/el/sclang-interp.el index 1bf7308..b836347 100644 --- a/el/sclang-interp.el +++ b/el/sclang-interp.el @@ -15,9 +15,8 @@ ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 ;; USA -(eval-when-compile - (require 'sclang-util) - (require 'compile)) +(require 'sclang-util) +(require 'compile) ;; ===================================================================== ;; post buffer access @@ -303,6 +302,7 @@ If EOB-P is non-nil, positions cursor at end of buffer." (list "-s")) (list "-iscel")))) +;;;###autoload (autoload 'sclang-start "sclang" "Start SuperCollider process." t) (defun sclang-start () "Start SuperCollider process." (interactive) diff --git a/el/sclang-minor-mode.el b/el/sclang-minor-mode.el index caf5416..c5e2a47 100644 --- a/el/sclang-minor-mode.el +++ b/el/sclang-minor-mode.el @@ -16,11 +16,8 @@ ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -(eval-when-compile - (require 'sclang-util) - (require 'sclang-mode) - ) - +(require 'sclang-util) +(require 'sclang-mode) (easy-mmode-define-minor-mode sclang-minor-mode "Toggle sclang-minor-mode. diff --git a/el/sclang-mode.el b/el/sclang-mode.el index ad7b626..4263a54 100644 --- a/el/sclang-mode.el +++ b/el/sclang-mode.el @@ -24,10 +24,8 @@ (declare-function company-mode "ext:company") (defvar company-backends) -(eval-when-compile - (require 'font-lock) - (require 'sclang-util)) - +(require 'font-lock) +(require 'sclang-util) (require 'sclang-interp) (require 'sclang-language) (require 'sclang-dev) @@ -671,7 +669,7 @@ Returns the column to indent to." :group 'sclang-mode :type 'hook) -;;;###autoload +;;;###autoload (autoload 'sclang-mode "sclang" "Major mode for editing SuperCollider language" t) (define-derived-mode sclang-mode prog-mode "SCLang" "Major mode for editing SuperCollider language code. \\{sclang-mode-map}" diff --git a/el/sclang-server.el b/el/sclang-server.el index 1f948db..375c492 100644 --- a/el/sclang-server.el +++ b/el/sclang-server.el @@ -16,12 +16,10 @@ ;; USA (require 'cl-lib) - -(eval-when-compile - (require 'sclang-util) - (require 'sclang-interp) - (require 'sclang-language) - (require 'sclang-mode)) +(require 'sclang-util) +(require 'sclang-interp) +(require 'sclang-language) +(require 'sclang-mode) (defcustom sclang-server-panel "Server.default.makeWindow" "Expression to execute when `sclang-show-server-panel' is invoked." diff --git a/el/sclang-util.el b/el/sclang-util.el index ea104cb..8a0ea6f 100644 --- a/el/sclang-util.el +++ b/el/sclang-util.el @@ -1,3 +1,5 @@ +;;; package: sclang-util --- Utility helpers for sclang +;; ;; copyright 2003-2005 stefan kersten ;; ;; This program is free software; you can redistribute it and/or @@ -83,4 +85,4 @@ (provide 'sclang-util) -;; EOF \ No newline at end of file +;;; sclang-util.el ends here diff --git a/el/sclang-vars.el.in b/el/sclang-vars.el.in index 57fac1b..96b1f62 100644 --- a/el/sclang-vars.el.in +++ b/el/sclang-vars.el.in @@ -16,19 +16,23 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to -;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. +;;; Commentary: +;; +;; This file is included in the distribution in order to convey system +;; installation variables which are known at compile time, but only when +;; the library is installed with cmake along with SuperCollider source. +;; +;; When using the stand-alone package, this file can be ignored and +;; the constants it defines will have no effect. + ;;; Code: (defconst sclang-system-data-dir "@PKG_DATA_DIR@" - "Installation dependent data directory.") - -(defconst sclang-system-help-dir "@PKG_DATA_DIR@/Help" - "Installation dependent help directory.") - -(defconst sclang-system-extension-dir "@PKG_DATA_DIR@/Extensions" - "Installation dependent extension directory.") + "Installation dependent data directory. +Bound only when library is installed with SuperCollider.") (provide 'sclang-vars) ;;; sclang-vars.el ends here diff --git a/el/sclang-widgets.el b/el/sclang-widgets.el index 45f9475..d5aa3c6 100644 --- a/el/sclang-widgets.el +++ b/el/sclang-widgets.el @@ -27,9 +27,9 @@ ;;; Code: (require 'cl-lib) -(eval-when-compile (require 'sclang-util) - (require 'sclang-language)) -(eval-and-compile (require 'sclang-interp)) +(require 'sclang-util) +(require 'sclang-language) +(require 'sclang-interp) (defvar sclang-widgets nil) (make-variable-buffer-local 'sclang-widgets) diff --git a/el/sclang.el b/el/sclang.el index 3550287..edae1fb 100644 --- a/el/sclang.el +++ b/el/sclang.el @@ -1,5 +1,7 @@ ;;; sclang.el --- IDE for working with the SuperCollider language -;; copyright 2003 stefan kersten +;; Copyright 2003 stefan kersten +;; Version: 1.0.0 +;; URL: https://github.com/supercollider/scel ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as @@ -16,6 +18,13 @@ ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 ;; USA +;;; Commentary: +;; +;; This package provides code for interfacing with sclang and scsynth. +;; In order to be useful you need to install SuperCollider and the +;; sc-el Quark. See the README or https://github.com/supercollider/scel +;; for more information. + ;;; Code: (defgroup sclang nil "IDE for working with the SuperCollider language." @@ -41,27 +50,22 @@ "Options for the SuperCollider process." :group 'sclang-interface) +;;;###autoload (defun sclang-customize () "Customize sclang variables." (interactive) (customize-group 'sclang)) -(eval-and-compile - (let ((load-path - (if (and (boundp 'byte-compile-dest-file) - (stringp byte-compile-dest-file)) - (cons (file-name-directory byte-compile-dest-file) load-path) - load-path))) - (require 'sclang-util) - (require 'sclang-browser) - (require 'sclang-interp) - (require 'sclang-language) - (require 'sclang-document) - (require 'sclang-mode) - (require 'sclang-minor-mode) - (require 'sclang-help) - (require 'sclang-server) - (require 'sclang-widgets))) +(require 'sclang-util) +(require 'sclang-browser) +(require 'sclang-interp) +(require 'sclang-language) +(require 'sclang-document) +(require 'sclang-mode) +(require 'sclang-minor-mode) +(require 'sclang-help) +(require 'sclang-server) +(require 'sclang-widgets) (provide 'sclang) diff --git a/el/test/fixtures/super-boring.scd b/el/test/fixtures/super-boring.scd new file mode 100644 index 0000000..a8b058e --- /dev/null +++ b/el/test/fixtures/super-boring.scd @@ -0,0 +1 @@ +{ WhiteNoise.ar(0.2!2); }.play; \ No newline at end of file diff --git a/el/test/sclang-mode-test.el b/el/test/sclang-mode-test.el new file mode 100644 index 0000000..54d78d4 --- /dev/null +++ b/el/test/sclang-mode-test.el @@ -0,0 +1,12 @@ +;; -*- no-byte-compile: t; lexical-binding: t; -*- +;;; test/sclang-mode-test.el + +(ert-deftest sclang-autoloaded-functions () + "Some functions should be callable interactively without requiring them" + (should (commandp 'sclang-start t)) + (should (commandp 'sclang-mode t))) + +(ert-deftest sclang-major-mode-init-test () + "Loading a file with an scd extension should init sclang-mode" + (find-file "fixtures/super-boring.scd") + (should (eq 'sclang-mode major-mode))) diff --git a/sc/CMakeLists.txt b/sc/scide_scel/CMakeLists.txt similarity index 100% rename from sc/CMakeLists.txt rename to sc/scide_scel/CMakeLists.txt diff --git a/sc/Document.sc b/sc/scide_scel/Document.sc similarity index 100% rename from sc/Document.sc rename to sc/scide_scel/Document.sc diff --git a/sc/Emacs.sc b/sc/scide_scel/Emacs.sc similarity index 100% rename from sc/Emacs.sc rename to sc/scide_scel/Emacs.sc diff --git a/sc/EmacsBuffer.sc b/sc/scide_scel/EmacsBuffer.sc similarity index 100% rename from sc/EmacsBuffer.sc rename to sc/scide_scel/EmacsBuffer.sc diff --git a/sc/EmacsDocument.sc b/sc/scide_scel/EmacsDocument.sc similarity index 100% rename from sc/EmacsDocument.sc rename to sc/scide_scel/EmacsDocument.sc diff --git a/sc/ScelDocument.sc b/sc/scide_scel/ScelDocument.sc similarity index 100% rename from sc/ScelDocument.sc rename to sc/scide_scel/ScelDocument.sc diff --git a/sc/extBuffer.sc b/sc/scide_scel/extBuffer.sc similarity index 100% rename from sc/extBuffer.sc rename to sc/scide_scel/extBuffer.sc diff --git a/sc/extClassBrowser.sc b/sc/scide_scel/extClassBrowser.sc similarity index 100% rename from sc/extClassBrowser.sc rename to sc/scide_scel/extClassBrowser.sc diff --git a/sc/extString.sc b/sc/scide_scel/extString.sc similarity index 100% rename from sc/extString.sc rename to sc/scide_scel/extString.sc diff --git a/sc/homeContext.sc b/sc/scide_scel/homeContext.sc similarity index 100% rename from sc/homeContext.sc rename to sc/scide_scel/homeContext.sc diff --git a/sc/storeLispOn.sc b/sc/scide_scel/storeLispOn.sc similarity index 100% rename from sc/storeLispOn.sc rename to sc/scide_scel/storeLispOn.sc diff --git a/scel.quark b/scel.quark new file mode 100644 index 0000000..7d1b71c --- /dev/null +++ b/scel.quark @@ -0,0 +1,5 @@ +( + name: "scel", + summary: "SuperCollider/Emacs interface", + version: "1.0.0", +)