├── .eslintrc.json
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── language-configuration.json
├── package-lock.json
├── package.json
├── snippets
└── csd-snippets.json
├── src
├── .DS_Store
├── commands
│ ├── csoundCommands.ts
│ └── showOpcodeReference.ts
├── completionProvider.ts
├── extension.ts
├── opcodes.json
├── test
│ ├── runTest.ts
│ └── suite
│ │ ├── extension.test.ts
│ │ └── index.ts
├── utils.ts
└── web
│ ├── extension.ts
│ └── test
│ └── suite
│ ├── extension.test.ts
│ └── index.ts
├── syntaxes
├── csound-csd.tmLanguage.json
├── csound-orc.tmLanguage.json
└── csound-sco.tmLanguage.json
├── tsconfig.json
├── tslint.json
└── webpack.config.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 6,
6 | "sourceType": "module"
7 | },
8 | "plugins": [
9 | "@typescript-eslint"
10 | ],
11 | "rules": {
12 | "@typescript-eslint/naming-convention": "warn",
13 | "@typescript-eslint/semi": "warn",
14 | "curly": "warn",
15 | "eqeqeq": "warn",
16 | "no-throw-literal": "warn",
17 | "semi": "off"
18 | },
19 | "ignorePatterns": [
20 | "out",
21 | "dist",
22 | "**/*.d.ts"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 | node_modules
4 | .vscode-test/
5 | *.vsix
6 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "dbaeumer.vscode-eslint",
6 | "eamodio.tsl-problem-matcher"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": [
13 | "--extensionDevelopmentPath=${workspaceFolder}"
14 | ],
15 | "outFiles": [
16 | "${workspaceFolder}/dist/**/*.js"
17 | ],
18 | "preLaunchTask": "${defaultBuildTask}"
19 | },
20 | {
21 | "name": "Extension Tests",
22 | "type": "extensionHost",
23 | "request": "launch",
24 | "args": [
25 | "--extensionDevelopmentPath=${workspaceFolder}",
26 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
27 | ],
28 | "outFiles": [
29 | "${workspaceFolder}/out/**/*.js",
30 | "${workspaceFolder}/dist/**/*.js"
31 | ],
32 | "preLaunchTask": "tasks: watch-tests"
33 | },
34 | {
35 | "name": "Run Web Extension in VS Code",
36 | "type": "pwa-extensionHost",
37 | "debugWebWorkerHost": true,
38 | "request": "launch",
39 | "args": [
40 | "--extensionDevelopmentPath=${workspaceFolder}",
41 | "--extensionDevelopmentKind=web"
42 | ],
43 | "outFiles": ["${workspaceFolder}/dist/web/**/*.js"],
44 | "preLaunchTask": "${defaultBuildTask}"
45 | }
46 | ]
47 | }
48 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false, // set this to true to hide the "out" folder with the compiled JS files
5 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files
6 | },
7 | "search.exclude": {
8 | "out": true, // set this to false to include "out" folder in search results
9 | "dist": true // set this to false to include "dist" folder in search results
10 | },
11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12 | "typescript.tsc.autoDetect": "off"
13 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": [
10 | "$ts-webpack-watch",
11 | "$tslint-webpack-watch"
12 | ],
13 | "isBackground": true,
14 | "presentation": {
15 | "reveal": "never",
16 | "group": "watchers"
17 | },
18 | "group": {
19 | "kind": "build",
20 | "isDefault": true
21 | }
22 | },
23 | {
24 | "type": "npm",
25 | "script": "watch-tests",
26 | "problemMatcher": "$tsc-watch",
27 | "isBackground": true,
28 | "presentation": {
29 | "reveal": "never",
30 | "group": "watchers"
31 | },
32 | "group": "build"
33 | },
34 | {
35 | "label": "tasks: watch-tests",
36 | "dependsOn": [
37 | "npm: watch",
38 | "npm: watch-tests"
39 | ],
40 | "problemMatcher": []
41 | }
42 | ]
43 | }
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/**
4 | node_modules/**
5 | src/**
6 | .gitignore
7 | .yarnrc
8 | webpack.config.js
9 | vsc-extension-quickstart.md
10 | **/tsconfig.json
11 | **/.eslintrc.json
12 | **/*.map
13 | **/*.ts
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "csound-vscode-plugin" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ## Next
8 |
9 | ## 0.6.6
10 |
11 | * Fixes release issue with 0.6.5
12 |
13 | ## 0.6.5
14 |
15 | * Adds Cabbage opcodes
16 | * Adds "Csound: Browse for Csound Executable Command" to set the path to the
17 | Csound executable using file selector dialog.
18 | * Removes type prefix colouring as it makes things look odd in Csound 7
19 |
20 | ## 0.6.4
21 |
22 | * Adds support for autocomplete for variables by document
23 |
24 | ## 0.6.3
25 |
26 | * Adds support for embedded JSON support for Cabbage section of CSDs
27 |
28 | ## 0.6.2
29 |
30 | * Enable opcode completion and hints for web extension
31 |
32 | ## 0.6.1
33 |
34 | * Fix import of opcodes.json
35 |
36 | ## 0.6.0
37 |
38 | * Adds support for autocomplete, popup hints for opcode arguments, and showing opcode documentation in the editor.
39 |
40 | ## 0.5.2
41 |
42 | * Adds .instr as file extension for ORC syntax highlighting
43 |
44 | ## 0.5.1
45 |
46 | * Adds support for folding for #region / #endregion comments
47 |
48 | * Updated README for information on using --port=10000 flag for live coding
49 |
50 | ## 0.5.0
51 | * Can now play from ORC/SCO pair, associating to the file from the currently-active editor window a file contained in the same folder with the same name but opposite extension.
52 |
53 | * Added CSD barebone as snippet, use the keyword `barebone` to insert the template code in your CSD file.
54 |
55 | ## 0.4.0
56 |
57 | * Updated to vscode 1.60 extension format to work as a Desktop and Web extension. (Play commands currently disabled until WebAudio Csound can be integrated.)
58 |
59 | ## 0.3.1
60 |
61 | * Updated opcode entries to 6.15.0 (synced to Nate Whetsell's Atom language-csound plugin)
62 | ## 0.3.0
63 |
64 | * Added live-coding commands to evaluate ORC and SCO code by sending to Csound over UDP.
65 |
66 | ## 0.2.3
67 |
68 | * Playing the contents of the CSD text editor doesn't shift focus to the output window.
69 | * `alt+escape` to kill CSound processes only works when focus is in a CSD text editor window (to increase
70 | compatibility with other modules).
71 |
72 | ## 0.2.2
73 |
74 | * Fixed to prevent error when running kill command with no Csound subprocesses.
75 |
76 | ## 0.2.1
77 |
78 | * Add command to kill any running Csound subprocess. Kill any Csound process on exiting from VSCode.
79 |
80 | ## 0.2.0
81 |
82 | * Implemented the ability to play the CSD file in the currently-active editor window from within VSCode.
83 |
84 | ## 0.0.3
85 |
86 | * Updated to use converted version of Nate Whetsell's language-csound Atom plugin.
87 |
88 | ## 0.0.2, 0.0.1
89 |
90 | * Initial release
91 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Nathan Whetsell and other contributors
4 |
5 | Copyright (c) 2018 Csound
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # csound-vscode-plugin
3 |
4 | A Csound language plugin for Visual Studio Code.
5 |
6 | ## Features
7 |
8 | csound-vscode-plugin currently provides:
9 |
10 | * Syntax Highlighting for Csound .orc and .udo files
11 |
12 | * Opcode completion with popup hints for opcode arguments
13 |
14 | * Show opcode documentation in the editor
15 |
16 | * Play the file in the currently-active editor window by choosing `Csound: Play Active Document`
17 | from the command palette or using the `alt+.` shortcut. To kill a playing Csound subprocess, choose
18 | `Csound: Terminate any running csound subprocess` from the command palette or use the `alt+escape` shortcut
19 | while the focus is still in a Csound text editor window.
20 |
21 | * Evaluate code at runtime (live coding) using `Csound: Evaluate Orchestra Code` or `ctrl+enter` (`cmd+enter` on macOS) for ORC code and `Csound: Evaluate Score Code` for SCO code.
22 |
23 | ## Requirements
24 |
25 | You must have Csound properly configured on your system so you can use it on the command line.
26 |
27 | ## Live Coding
28 |
29 | Live coding with csound-vscode-plugin requires Csound to use UDP server mode listening to the port given in settings (by default, port 10000). Csound itself must be configured to listen to the matching port that the plugin will use. This can be done per-project by adding `--port=10000` to the CsOptions of the project's CSD, or done for every project by adding the above flag to the `csound.playArgs` settings. (Caution: Unless all of your Csound work is live coding, adding the --port flag may cause your project to run indefinitely if the project was not designed for live coding.)
30 |
31 | ## Extension Settings
32 |
33 | | setting | default | description |
34 | | --------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
35 | | `csound.executable` | `"csound"` | The Csound executable. The default value of `csound` will run the system wide Csound. If you wish to use another Csound executable you can do so by passing an updated path, or browsing for a Csound executable from the Command palette. |
36 | | `csound.playArgs` | `[ "-odac" ]` | Arguments to give to Csound when used for playing the current file.
An array of strings, each element an argument including the leading dash. |
37 | | `csound.saveSilentlyOnPlay` | `false` | Save without prompting before playing the current file. |
38 | | `csound.UDPAddress` | `127.0.0.1` | Address to send live coding evaluations over UDP. |
39 | | `csound.UDPPort` | `10000` | Port to send live coding evaluations over UDP. |
40 | | `csound.htmlFilePath` | `""` | Csound manual root directory on local file system for loading opcode documentation. If empty, defaults to C:\\Program Files\\Csound6_x64\\doc\\manual on Windows, and /Library/Frameworks/CsoundLib64.framework/Versions/6.0/Resources/Manual on macOS. |
41 |
42 | ## Known Issues
43 |
44 | None.
45 |
46 | ## Release Notes
47 |
48 | ## 0.6.6
49 |
50 | * Fixes release issue with 0.6.5
51 |
52 | ## 0.6.5
53 |
54 | * Adds Cabbage opcodes
55 | * Adds "Csound: Browse for Csound Executable Command" to set the path to the
56 | Csound executable using file selector dialog.
57 | * Removes type prefix colouring as it makes things look odd in Csound 7
58 |
59 | ## 0.6.4
60 |
61 | * Adds support for autocomplete for variables by document
62 |
63 | ## 0.6.3
64 |
65 | * Adds support for embedded JSON support for Cabbage section of CSDs
66 |
67 | ## 0.6.2
68 |
69 | * Enable opcode completion and hints for web extension
70 |
71 | ## 0.6.1
72 |
73 | * Fix import of opcodes.json
74 |
75 | ## 0.6.0
76 |
77 | * Adds support for autocomplete, popup hints for opcode arguments, and showing opcode documentation in the editor.
78 |
79 | ## 0.5.2
80 |
81 | * Adds .instr as file extension for ORC syntax highlighting
82 |
83 | ## 0.5.1
84 |
85 | * Adds support for folding for #region / #endregion comments
86 |
87 | * Updated README for information on using --port=10000 flag for live coding
88 |
89 | ## 0.5.0
90 | * Can now play from ORC/SCO pair, associating to the file from the currently-active editor window a file contained in the same folder with the same name but opposite extension.
91 |
92 | * Added CSD barebone as snippet, use the keyword `barebone` to insert the template code in your CSD file.
93 |
94 | ## 0.4.0
95 |
96 | * Updated to vscode 1.60 extension format to work as a Desktop and Web extension. (Play commands currently disabled until WebAudio Csound can be integrated.)
97 |
98 | ## 0.3.1
99 |
100 | * Updated opcode entries to 6.15.0 (synced to Nate Whetsell's Atom language-csound plugin)
101 |
102 | ### 0.3.0
103 |
104 | * Added live-coding commands to evaluate ORC and SCO code by sending to Csound over UDP.
105 |
106 | ### 0.2.3
107 |
108 | * Don't switch focus to output window when playing a CSD file. `alt+escape` only kills Csound subprocesses when focus is in a CSD text editor window (for better compatibility with other modules).
109 |
110 | ### 0.2.2
111 |
112 | * Fix issue when attempting to kill when there are no Csound subprocesses running.
113 |
114 | ### 0.2.1
115 |
116 | * Add command to kill any running Csound subprocess. Kill any Csound process on exiting from VSCode.
117 |
118 | ### 0.2.0
119 |
120 | * Added the ability to play CSD files from within VSCode.
121 |
122 | ### 0.0.1
123 |
124 | * Alpha: initial release
125 |
--------------------------------------------------------------------------------
/language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | // symbol used for single line comment. Remove this entry if your language does not support line comments
4 | //"lineComment": "//",
5 | "lineComment": ";",
6 | // symbols used for start and end a block comment. Remove this entry if your language does not support block comments
7 | "blockComment": [ "/*", "*/" ]
8 | },
9 | // symbols used as brackets
10 | "brackets": [
11 | ["{", "}"],
12 | ["[", "]"],
13 | ["(", ")"]
14 | ],
15 | // symbols that are auto closed when typing
16 | "autoClosingPairs": [
17 | ["{", "}"],
18 | ["[", "]"],
19 | ["(", ")"],
20 | ["\"", "\""],
21 | ["'", "'"],
22 | { "open": "/**", "close": " */", "notIn": ["string"] }
23 |
24 | ],
25 | // symbols that that can be used to surround a selection
26 | "surroundingPairs": [
27 | ["{", "}"],
28 | ["[", "]"],
29 | ["(", ")"],
30 | ["\"", "\""],
31 | ["'", "'"]
32 | ],
33 | "folding": {
34 | "markers": {
35 | "start": "^\\s*(;|//.)\\s*#?region\\b",
36 | "end": "^\\s*(;|//.)\\s*#?endregion\\b"
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "csound-vscode-plugin",
3 | "displayName": "Csound",
4 | "description": "Csound language plugin for Visual Studio Code",
5 | "version": "0.6.6",
6 | "publisher": "kunstmusik",
7 | "engines": {
8 | "vscode": "^1.75.0"
9 | },
10 | "categories": [
11 | "Programming Languages"
12 | ],
13 | "main": "./dist/extension.js",
14 | "browser": "./dist/web/extension.js",
15 | "contributes": {
16 | "commands": [
17 | {
18 | "command": "extension.csoundPlayActiveDocument",
19 | "title": "Csound: Play Active Document"
20 | },
21 | {
22 | "command": "extension.csoundKillCsoundProcess",
23 | "title": "Csound: Terminate any running csound subprocess"
24 | },
25 | {
26 | "command": "extension.csoundSelectExecutable",
27 | "title": "Csound: Browse for Csound executable"
28 | },
29 | {
30 | "command": "extension.csoundEvalOrc",
31 | "title": "Csound: Evaluate Orchestra Code"
32 | },
33 | {
34 | "command": "extension.csoundEvalSco",
35 | "title": "Csound: Evaluate Score Code"
36 | },
37 | {
38 | "command": "extension.showOpcodeReference",
39 | "title": "Csound: Show Csound help"
40 | }
41 | ],
42 | "configuration": {
43 | "title": "Csound",
44 | "properties": {
45 | "csound.executable": {
46 | "type": "string",
47 | "default": "csound",
48 | "description": "The csound executable"
49 | },
50 | "csound.playArgs": {
51 | "type": "array",
52 | "default": [
53 | "-odac"
54 | ],
55 | "description": "Arguments to csound when used for playing the current file. An array of strings, each element an argument including the leading dash."
56 | },
57 | "csound.saveSilentlyOnPlay": {
58 | "type": "boolean",
59 | "default": false,
60 | "description": "Save without prompting before playing the current file."
61 | },
62 | "csound.UDPAddress": {
63 | "type": "string",
64 | "default": "127.0.0.1",
65 | "description": "Server address to send live coding evaluations over UDP. "
66 | },
67 | "csound.UDPPort": {
68 | "type": "number",
69 | "default": 10000,
70 | "description": "Port to send live coding evaluations over UDP."
71 | },
72 | "csound.showHints": {
73 | "type": "boolean",
74 | "default": true,
75 | "description": "Displays syntax hints."
76 | },
77 | "csound.htmlFilePath": {
78 | "type": "string",
79 | "default": "",
80 | "description": "The path to the directory containing HTML opcode files."
81 | }
82 | }
83 | },
84 | "languages": [
85 | {
86 | "id": "csound-orc",
87 | "aliases": [
88 | "Csound ORC",
89 | "csound-orc"
90 | ],
91 | "extensions": [
92 | ".orc",
93 | ".udo",
94 | ".instr"
95 | ],
96 | "configuration": "./language-configuration.json"
97 | },
98 | {
99 | "id": "csound-sco",
100 | "aliases": [
101 | "Csound SCO",
102 | "csound-sco"
103 | ],
104 | "extensions": [
105 | ".sco"
106 | ],
107 | "configuration": "./language-configuration.json"
108 | },
109 | {
110 | "id": "csound-csd",
111 | "aliases": [
112 | "Csound CSD",
113 | "csound-csd"
114 | ],
115 | "extensions": [
116 | ".csd"
117 | ],
118 | "configuration": "./language-configuration.json"
119 | }
120 | ],
121 | "grammars": [
122 | {
123 | "language": "csound-orc",
124 | "scopeName": "source.csound.orc",
125 | "path": "./syntaxes/csound-orc.tmLanguage.json"
126 | },
127 | {
128 | "language": "csound-sco",
129 | "scopeName": "source.csound.sco",
130 | "path": "./syntaxes/csound-sco.tmLanguage.json"
131 | },
132 | {
133 | "language": "csound-csd",
134 | "scopeName": "source.csound.csd",
135 | "path": "./syntaxes/csound-csd.tmLanguage.json",
136 | "embeddedLanguages": {
137 | "meta.embedded.json": "json"
138 | }
139 | }
140 | ],
141 | "configurationDefaults": {
142 | "[csound-csd]": {
143 | "editor.suggestOnTriggerCharacters": true
144 | }
145 | },
146 | "keybindings": [
147 | {
148 | "command": "extension.csoundPlayActiveDocument",
149 | "key": "alt+.",
150 | "when": "editorFocus"
151 | },
152 | {
153 | "command": "extension.csoundKillCsoundProcess",
154 | "key": "alt+escape",
155 | "when": "editorFocus"
156 | },
157 | {
158 | "command": "extension.csoundEvalOrc",
159 | "key": "ctrl+enter",
160 | "mac": "cmd+enter",
161 | "when": "editorTextFocus"
162 | }
163 | ],
164 | "snippets": [
165 | {
166 | "language": "csound-csd",
167 | "path": "./snippets/csd-snippets.json"
168 | }
169 | ]
170 | },
171 | "scripts": {
172 | "vscode:prepublish": "npm run package",
173 | "compile": "webpack",
174 | "watch": "webpack --watch",
175 | "package": "webpack --mode production --devtool hidden-source-map",
176 | "compile-tests": "tsc -p . --outDir out",
177 | "watch-tests": "tsc -p -w . --outDir out",
178 | "pretest": "npm run compile-tests && npm run compile && npm run lint",
179 | "lint": "eslint src --ext ts",
180 | "test": "node ./out/test/runTest.js"
181 | },
182 | "devDependencies": {
183 | "@types/glob": "^7.2.0",
184 | "@types/mocha": "^9.1.1",
185 | "@types/node": "^14.18.63",
186 | "@types/vscode": "^1.75.0",
187 | "@types/webpack-env": "^1.18.5",
188 | "@typescript-eslint/eslint-plugin": "^4.33.0",
189 | "@typescript-eslint/parser": "^4.33.0",
190 | "@vscode/test-electron": "^1.6.2",
191 | "@vscode/test-web": "^0.0.8",
192 | "assert": "^2.1.0",
193 | "eslint": "^7.32.0",
194 | "glob": "^7.2.3",
195 | "mocha": "^9.2.2",
196 | "process": "^0.11.10",
197 | "ts-loader": "^9.5.1",
198 | "typescript": "^4.9.5",
199 | "webpack": "^5.95.0",
200 | "webpack-cli": "^4.10.0"
201 | },
202 | "repository": {
203 | "type": "git",
204 | "url": "https://github.com/csound/csound-vscode-plugin.git"
205 | }
206 | }
--------------------------------------------------------------------------------
/snippets/csd-snippets.json:
--------------------------------------------------------------------------------
1 | {
2 | "barebone": {
3 | "prefix": "barebone",
4 | "body": [
5 | "",
6 | ";all code relating to Csound should be encapsulated between",
7 | "; and ",
8 | " ",
9 | " ;this section tells Csound how to interact",
10 | " ;with various devices and hardware",
11 | " ",
12 | " ",
13 | "",
14 | " ",
15 | " ;this section contains instrument definitions",
16 | " ",
17 | " ",
18 | "",
19 | " ",
20 | " ;this section tells Csound when and how to perform instruments",
21 | " ;defined in the CsInstruments section above.",
22 | " ",
23 | " ",
24 | ""
25 | ],
26 | "description": "Csound .csd file barebone"
27 | }
28 | }
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/csound/csound-vscode-plugin/cf78a8c48e10277aee16bb22846d1129533b0f08/src/.DS_Store
--------------------------------------------------------------------------------
/src/commands/csoundCommands.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import * as path from "path";
4 | import * as cp from "child_process";
5 | import * as vscode from "vscode";
6 | import * as dgram from "dgram";
7 | import { flash, getEvalText, getScoEvalText } from "../utils";
8 |
9 | const socket = dgram.createSocket("udp4");
10 |
11 | let output: vscode.OutputChannel;
12 | const processMap: { [pid: number]: cp.ChildProcess | undefined } = {};
13 |
14 | export async function playActiveDocument(textEditor: vscode.TextEditor) {
15 | const config = vscode.workspace.getConfiguration("csound");
16 | const document = textEditor.document;
17 | // Currently plays csd files
18 | // or orc/sco file pair in the same folder with the same basename
19 |
20 | if (document.isDirty) {
21 | if (!config.get("saveSilentlyOnPlay")) {
22 | const selection = await saveToPlayDialog();
23 | if (selection === "Cancel") {
24 | return;
25 | }
26 | }
27 | await document.save();
28 | }
29 | if (output === undefined) {
30 | output = vscode.window.createOutputChannel("Csound output");
31 | }
32 |
33 | const command = config.get("executable", "csound");
34 | // We need to clone the args array because if we don't, when we push the filename on, it
35 | // will actually go into the config in memory, and be in the args of our next syntax check.
36 | const args: string[] = [...config.get("playArgs", [])];
37 |
38 | if (document.languageId === "csound-orc" || document.languageId === "csound-sco") {
39 | const baseName = document.fileName.substring(0, document.fileName.length - 4);
40 | args.push(baseName + ".orc");
41 | args.push(baseName + ".sco");
42 | }
43 | else if (document.languageId === "csound-csd") {
44 | args.push(document.fileName);
45 | }
46 | else {
47 | return;
48 | }
49 |
50 | const options = { cwd: path.dirname(document.fileName) };
51 |
52 | output.clear();
53 | output.show(true); // true means keep focus in the editor window
54 |
55 | const process = cp.spawn(command, args, options);
56 |
57 | processMap[process.pid] = process;
58 |
59 | process.stdout.on("data", (data) => {
60 | // I've seen spurious 'ANSI reset color' sequences in some csound output
61 | // which doesn't render correctly in this context. Stripping that out here.
62 | output.append(data.toString().replace(/\x1b\[m/g, ""));
63 | });
64 | process.stderr.on("data", (data) => {
65 | // It looks like all csound output is written to stderr, actually.
66 | // If you want your changes to show up, change this one.
67 | output.append(data.toString().replace(/\x1b\[m/g, ""));
68 | });
69 | if (process.pid) {
70 | console.log("Csound is playing (pid " + process.pid + ")");
71 | }
72 | }
73 |
74 | async function saveToPlayDialog(): Promise {
75 | const selected = await vscode.window
76 | .showInformationMessage(
77 | "Save file for Csound to play?",
78 | { modal: true },
79 | { title: "Cancel", isCloseAffordance: true },
80 | { title: "Save", isCloseAffordance: false },
81 | {
82 | title: "Always silently save before playing",
83 | isCloseAffordance: false,
84 | }
85 | )
86 |
87 | .then((selected) => {
88 | if (selected) {
89 | if (selected.title === "Always silently save before playing") {
90 | setSaveSilentlyOnPlay();
91 | return "Save";
92 | } else {
93 | return selected.title;
94 | }
95 | } else {
96 | return "Cancel";
97 | }
98 | });
99 | return selected || "Cancel";
100 | }
101 |
102 | export async function selectCsoundExecutable() {
103 | const config = vscode.workspace.getConfiguration('csound');
104 |
105 | const csoundExecPath = await vscode.window.showOpenDialog({
106 | canSelectFiles: true,
107 | canSelectFolders: false,
108 | canSelectMany: false,
109 | openLabel: 'Select Csound Executable'
110 | });
111 |
112 | if (csoundExecPath && csoundExecPath.length > 0) {
113 | // Use the correct key name that matches your package.json configuration
114 | await config.update('executable', csoundExecPath[0].fsPath, vscode.ConfigurationTarget.Global);
115 | }
116 | }
117 |
118 | async function setSaveSilentlyOnPlay() {
119 | const config = vscode.workspace.getConfiguration("csound");
120 | config.update("saveSilentlyOnPlay", "true", true);
121 | }
122 |
123 | export function killCsoundProcess() {
124 | for (let pid in processMap) {
125 | let p = processMap[pid];
126 | if (p === undefined) {
127 | delete processMap[pid];
128 | } else {
129 | console.log("Killing Csound process (pid " + p.pid + ")");
130 | p.kill("SIGTERM");
131 | console.log("Csound subprocess terminated");
132 | }
133 | }
134 | }
135 |
136 | export async function evalOrc(textEditor: vscode.TextEditor) {
137 | const config = vscode.workspace.getConfiguration("csound");
138 | const port = config.get("UDPPort") as number;
139 | const address = config.get("UDPAddress") as string;
140 |
141 | const document = textEditor.document;
142 | const selection = textEditor.selection;
143 |
144 | const { text, from , to} = getEvalText(document, selection);
145 | socket.send(text, port, address);
146 | flash(textEditor, new vscode.Range(from, to));
147 | }
148 |
149 | export async function evalSco(textEditor: vscode.TextEditor) {
150 | const config = vscode.workspace.getConfiguration("csound");
151 | const port = config.get("UDPPort") as number;
152 | const address = config.get("UDPAddress") as string;
153 |
154 | const document = textEditor.document;
155 | const selection = textEditor.selection;
156 |
157 | const { text, from , to} = getScoEvalText(document, selection);
158 | socket.send("$" + text, port, address);
159 | flash(textEditor, new vscode.Range(from, to));
160 | }
--------------------------------------------------------------------------------
/src/commands/showOpcodeReference.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import * as vscode from "vscode";
4 |
5 | export const showOpcodeReference = async () => {
6 | const editor = vscode.window.activeTextEditor;
7 | if (!editor) {
8 | vscode.window.showInformationMessage("No active editor found.");
9 | return;
10 | }
11 |
12 | const position = editor.selection.active;
13 | const wordRange = editor.document.getWordRangeAtPosition(position);
14 | const opcode = editor.document.getText(wordRange).trim(); // Get the opcode
15 |
16 | console.log(`Opcode: ${opcode}`); // Log the opcode for debugging
17 |
18 | const config = vscode.workspace.getConfiguration("csound");
19 | let htmlFilePath = config.get("htmlFilePath");
20 | const osPlatform = process.platform;
21 |
22 | if (!htmlFilePath) {
23 | if (osPlatform === "win32") {
24 | htmlFilePath = "C:\\Program Files\\Csound6_x64\\doc\\manual"; // Default path for Windows
25 | } else if (osPlatform === "darwin") {
26 | htmlFilePath = "/Library/Frameworks/CsoundLib64.framework/Versions/6.0/Resources/Manual"; // Default path for macOS
27 | }
28 | // } else {
29 | // defaultPath = "html"; // Default for other OS (like Linux)
30 | // }
31 | }
32 | // Construct the URI for the HTML file
33 | const htmlFileUri = vscode.Uri.file(`${htmlFilePath}/${opcode}.html`);
34 |
35 | try {
36 | // Check if the file exists before reading
37 | await vscode.workspace.fs.stat(htmlFileUri);
38 |
39 | // Read the HTML file content
40 | const htmlContent = await vscode.workspace.fs.readFile(htmlFileUri);
41 | const htmlString = htmlContent.toString(); // Convert buffer to string
42 |
43 | const panel = vscode.window.createWebviewPanel(
44 | "htmlPreview", // Identifies the type of the webview. Used internally
45 | `Preview for ${opcode}`, // Title of the panel displayed to the user
46 | vscode.ViewColumn.Beside, // Editor column to show the new webview panel in
47 | {} // Webview options
48 | );
49 |
50 | panel.webview.html = getWebviewContent(htmlString);
51 | } catch (error) {
52 | console.error(error); // Log the error to console for debugging
53 | const errorMessage = (error as Error).message;
54 | vscode.window.showErrorMessage(
55 | `Failed to load HTML file for opcode '${opcode}': ${errorMessage}`
56 | );
57 | }
58 | };
59 |
60 | const getWebviewContent = (htmlContent: string) => {
61 | return `
62 |
63 |
64 |
65 |
66 |
67 | HTML Preview
68 |
69 |
70 | ${htmlContent}
71 |
72 |
73 | `;
74 | }
75 |
--------------------------------------------------------------------------------
/src/completionProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from "vscode";
2 | import opcodesJson from "./opcodes.json";
3 |
4 | export let documentTokens: Map> = new Map(); // Use a Set to avoid duplicates
5 |
6 | // Utility function to convert synopsis with proper markdown and newlines
7 | const formatSynopsisForMarkdown = (synopsis: string): string => {
8 | // Add two spaces before each newline for single line breaks in Markdown
9 | return synopsis.replace(/\n/g, " \n");
10 | };
11 |
12 | // Utility function to remove single-line and multi-line comments from a line
13 | function removeComments(lineText: string): string {
14 | // Remove single-line comments (//)
15 | lineText = lineText.replace(/\/\/.*$/, '');
16 | // Remove multi-line comments (/* ... */)
17 | lineText = lineText.replace(/\/\*[\s\S]*?\*\//g, '');
18 | return lineText;
19 | }
20 |
21 | // Function to add tokens (words) to the Set for the given document
22 | export const addTokensToDocumentSet = function (document: vscode.TextDocument, content: string) {
23 | const uri = document.uri.toString();
24 |
25 | // Get or create the token set for this document
26 | let tokensSet = documentTokens.get(uri);
27 | if (!tokensSet) {
28 | tokensSet = new Set();
29 | documentTokens.set(uri, tokensSet);
30 | }
31 |
32 | // Process the content (can be the entire document or a single line)
33 | const lines = content.split('\n'); // Split content into lines
34 |
35 | lines.forEach(lineText => {
36 | // Remove comments from the line
37 | lineText = removeComments(lineText);
38 |
39 | // Split the line into words
40 | const newWords = lineText.split(/\W+/).filter(Boolean); // Split by non-alphanumeric characters, remove empty strings
41 |
42 | // Add only words that start with a, k, i, S, f (case-sensitive) or words that follow 'instr'
43 | newWords.forEach(word => {
44 | if (/^[akiSf]/.test(word)) { // Matches words starting with the specified characters
45 | tokensSet?.add(word);
46 | }
47 |
48 | // Add words following 'instr'
49 | const instrRegex = /\binstr\s+(\w+)/g;
50 | let match;
51 | while ((match = instrRegex.exec(lineText)) !== null) {
52 | tokensSet?.add(match[1]); // Add the word following 'instr'
53 | }
54 | });
55 | });
56 | }
57 |
58 | //delete token from document when document is closed
59 | export const clearTokensForDocumentSet = function (uri: string) {
60 | documentTokens.delete(uri);
61 | }
62 |
63 | const fullOpcodeCompletions: Array = [];
64 | opcodesJson.opcodes.forEach((categoryObj: any) => {
65 | categoryObj.opcodes.forEach((opcodeObj: any) => {
66 | // Create a new CompletionItem
67 | let completionItem = new vscode.CompletionItem(
68 | opcodeObj.opcodeName,
69 | vscode.CompletionItemKind.Function
70 | );
71 |
72 | // Set the label to be the opcode name
73 | completionItem.label = opcodeObj.opcodeName;
74 |
75 | // Forego detail here, as it is not necessary for the opcode list
76 | completionItem.detail = "";
77 |
78 | const formattedSynopsis = formatSynopsisForMarkdown(
79 | `**${opcodeObj.opcodeName}**: *${opcodeObj.description}* \n\n` +
80 | opcodeObj.synopsis +
81 | "\n\n" +
82 | opcodeObj.functionalSynopsis
83 | );
84 | completionItem.documentation = new vscode.MarkdownString(
85 | formattedSynopsis
86 | );
87 |
88 | // Add the item to the completion list
89 | fullOpcodeCompletions.push(completionItem);
90 | });
91 | });
92 |
93 | export const completionItemProvider = {
94 | async provideCompletionItems(
95 | document: vscode.TextDocument,
96 | position: vscode.Position,
97 | token: vscode.CancellationToken,
98 | context: vscode.CompletionContext
99 | ) {
100 | const config = vscode.workspace.getConfiguration("csound");
101 | const showHints = config.get("showHints") as boolean;
102 | if (!showHints) {
103 | return [];
104 | }
105 |
106 | //get unique set for document
107 | const uri = document.uri.toString();
108 | const wordsSet = documentTokens.get(uri) || new Set();
109 |
110 | const completionItems = Array.from(wordsSet).map(token => {
111 | const item = new vscode.CompletionItem(token, vscode.CompletionItemKind.Variable);
112 | return item;
113 | });
114 |
115 | // fullOpcodeCompletions.push(...completionItems);
116 |
117 | return [...fullOpcodeCompletions, ...completionItems];
118 | },
119 | };
120 |
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import * as vscode from "vscode";
4 | import * as commands from "./commands/csoundCommands";
5 | import { showOpcodeReference } from "./commands/showOpcodeReference";
6 | import { completionItemProvider, addTokensToDocumentSet, clearTokensForDocumentSet } from "./completionProvider";
7 |
8 | export function activate(context: vscode.ExtensionContext) {
9 | console.log("Csound's vscode plugin is now active!");
10 |
11 | // Add autocomplete for opcodes
12 | context.subscriptions.push(
13 | vscode.languages.registerCompletionItemProvider(
14 | ["csound-csd", "csound-orc"],
15 | completionItemProvider,
16 | ""
17 | )
18 | );
19 |
20 | // Listen for changes in text documents
21 | context.subscriptions.push(
22 | vscode.workspace.onDidChangeTextDocument(event => {
23 | const document = event.document;
24 |
25 | event.contentChanges.forEach(change => {
26 | const lineNumber = change.range.start.line;
27 | const lineText = document.lineAt(lineNumber).text;
28 | const changeText = change.text;
29 |
30 | if (/\W/.test(changeText)) {
31 | // Add tokens from the current line
32 | addTokensToDocumentSet(document, lineText);
33 | }
34 | });
35 | })
36 | );
37 |
38 | // Listen for when an editor becomes active (e.g., switching between files)
39 | context.subscriptions.push(
40 | vscode.window.onDidChangeActiveTextEditor(editor => {
41 | if (editor) {
42 | const document = editor.document;
43 | addTokensToDocumentSet(document, document.getText()); // Parse the active document and add tokens
44 | }
45 | })
46 | );
47 |
48 | // Handle already open files when the extension is activated
49 | if (vscode.window.activeTextEditor) {
50 | const document = vscode.window.activeTextEditor.document;
51 | addTokensToDocumentSet(document, document.getText()); // Parse the currently active file
52 | }
53 |
54 | // Clean up token sets when a document is closed
55 | context.subscriptions.push(
56 | vscode.workspace.onDidCloseTextDocument(document => {
57 | const uri = document.uri.toString();
58 | clearTokensForDocumentSet(uri); // Remove the token set for this document
59 | })
60 | );
61 |
62 |
63 | const showOpcodeReferenceCommand = vscode.commands.registerCommand(
64 | "extension.showOpcodeReference",
65 | showOpcodeReference
66 | );
67 | context.subscriptions.push(showOpcodeReferenceCommand);
68 |
69 | const playCommand = vscode.commands.registerTextEditorCommand(
70 | "extension.csoundPlayActiveDocument",
71 | commands.playActiveDocument
72 | );
73 | context.subscriptions.push(playCommand);
74 |
75 | const browseForExecutableCommand = vscode.commands.registerTextEditorCommand(
76 | "extension.csoundSelectExecutable",
77 | commands.selectCsoundExecutable
78 | );
79 | context.subscriptions.push(browseForExecutableCommand);
80 |
81 | const killCommand = vscode.commands.registerTextEditorCommand(
82 | "extension.csoundKillCsoundProcess",
83 | commands.killCsoundProcess
84 | );
85 | context.subscriptions.push(killCommand);
86 |
87 | const evalOrcCommand = vscode.commands.registerTextEditorCommand(
88 | "extension.csoundEvalOrc",
89 | commands.evalOrc
90 | );
91 | context.subscriptions.push(evalOrcCommand);
92 |
93 | const evalScoCommand = vscode.commands.registerTextEditorCommand(
94 | "extension.csoundEvalSco",
95 | commands.evalSco
96 | );
97 | context.subscriptions.push(evalScoCommand);
98 |
99 | }
100 |
101 | // This method is called when your extension is deactivated
102 | export function deactivate() {
103 | commands.killCsoundProcess();
104 | }
105 |
--------------------------------------------------------------------------------
/src/test/runTest.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 |
3 | import { runTests } from '@vscode/test-electron';
4 |
5 | async function main() {
6 | try {
7 | // The folder containing the Extension Manifest package.json
8 | // Passed to `--extensionDevelopmentPath`
9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../');
10 |
11 | // The path to test runner
12 | // Passed to --extensionTestsPath
13 | const extensionTestsPath = path.resolve(__dirname, './suite/index');
14 |
15 | // Download VS Code, unzip it and run the integration test
16 | await runTests({ extensionDevelopmentPath, extensionTestsPath });
17 | } catch (err) {
18 | console.error('Failed to run tests');
19 | process.exit(1);
20 | }
21 | }
22 |
23 | main();
24 |
--------------------------------------------------------------------------------
/src/test/suite/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from 'assert';
2 |
3 | // You can import and use all API from the 'vscode' module
4 | // as well as import your extension to test it
5 | import * as vscode from 'vscode';
6 | // import * as myExtension from '../../extension';
7 |
8 | suite('Extension Test Suite', () => {
9 | vscode.window.showInformationMessage('Start all tests.');
10 |
11 | test('Sample test', () => {
12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5));
13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0));
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/test/suite/index.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import Mocha from 'mocha';
3 | import glob from 'glob';
4 |
5 | export function run(): Promise {
6 | // Create the mocha test
7 | const mocha = new Mocha({
8 | ui: 'tdd',
9 | color: true
10 | });
11 |
12 | const testsRoot = path.resolve(__dirname, '..');
13 |
14 | return new Promise((c, e) => {
15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
16 | if (err) {
17 | return e(err);
18 | }
19 |
20 | // Add files to the test suite
21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
22 |
23 | try {
24 | // Run the mocha test
25 | mocha.run(failures => {
26 | if (failures > 0) {
27 | e(new Error(`${failures} tests failed.`));
28 | } else {
29 | c();
30 | }
31 | });
32 | } catch (err) {
33 | console.error(err);
34 | e(err);
35 | }
36 | });
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import * as vscode from "vscode";
4 |
5 | const starts = [
6 | [/^\s*instr/, "instr"],
7 | [/^\s*endin/, "endin"],
8 | [/^\s*opcode/, "opcode"],
9 | [/^\s*endop/, "endop"],
10 | ];
11 | const startsWithOneOfThese = function (txt:vscode.TextLine) {
12 | for (let i = 0; i < starts.length; i++) {
13 | if (txt.text.match(starts[i][0]) !== null) {
14 | return starts[i][1] as string;
15 | }
16 | }
17 | return null;
18 | };
19 |
20 | const findLineWithBlock = function (document:vscode.TextDocument, start:number, direction:number, limit:number):[number, string] {
21 | for (let i = start; i !== limit; i += direction) {
22 | let find = startsWithOneOfThese(document.lineAt(i));
23 | if (find !== null) {
24 | return [i, find];
25 | }
26 | }
27 | return [-1,""];
28 | };
29 |
30 | export const getEvalText = function (document:vscode.TextDocument, selection:vscode.Selection) {
31 | let text = document.getText(selection);
32 | let from = selection.start;
33 | let to = selection.end;
34 |
35 | if (selection.isEmpty) {
36 | let prevBlockMark = findLineWithBlock(document, selection.start.line, -1, -1);
37 | let nextBlockMark = findLineWithBlock(document, selection.start.line, 1, document.lineCount);
38 |
39 | if (
40 | prevBlockMark !== null &&
41 | nextBlockMark !== null &&
42 | ((prevBlockMark[1] === "instr" && nextBlockMark[1] === "endin") ||
43 | (prevBlockMark[1] === "opcode" && nextBlockMark[1] === "endop"))
44 | ) {
45 | from = document.lineAt(prevBlockMark[0]).range.start;
46 | to = document.lineAt(nextBlockMark[0]).range.end;
47 | text = document.getText(new vscode.Range(from, to));
48 | } else {
49 | const line = document.lineAt(selection.active);
50 | from = line.range.start;
51 | to = line.range.end;
52 | text = document.getText(line.range);
53 | }
54 | }
55 | return { text, from, to };
56 | };
57 |
58 |
59 | export const getScoEvalText = function (document:vscode.TextDocument, selection:vscode.Selection) {
60 | let text = document.getText(selection);
61 | let from = selection.start;
62 | let to = selection.end;
63 |
64 | if (selection.isEmpty) {
65 | const line = document.lineAt(selection.active);
66 | from = line.range.start;
67 | to = line.range.end;
68 | text = document.getText(line.range);
69 | }
70 | return { text, from, to };
71 | };
72 |
73 | export const flash = function (textEditor:vscode.TextEditor, range:vscode.Range) {
74 | const flashDecorationType = vscode.window.createTextEditorDecorationType({
75 | light: {
76 | backgroundColor: 'darkGray'
77 | },
78 | dark: {
79 | backgroundColor: 'rgba(255, 255, 255, 0.5)'
80 | }
81 | });
82 | textEditor.setDecorations(flashDecorationType, [range]);
83 | setTimeout(function () {
84 | flashDecorationType.dispose();
85 | }, 250);
86 | };
--------------------------------------------------------------------------------
/src/web/extension.ts:
--------------------------------------------------------------------------------
1 | // The module 'vscode' contains the VS Code extensibility API
2 | // Import the module and reference it with the alias vscode in your code below
3 | import * as vscode from "vscode";
4 | import { addTokensToDocumentSet, clearTokensForDocumentSet, completionItemProvider } from "../completionProvider";
5 |
6 | // this method is called when your extension is activated
7 | // your extension is activated the very first time the command is executed
8 | export function activate(context: vscode.ExtensionContext) {
9 | const notYetImplementedForWeb = () => {
10 | vscode.window.showInformationMessage(
11 | "This command has not yet been reimplemented for the web."
12 | );
13 | };
14 |
15 | // Add autocomplete for opcodes
16 | context.subscriptions.push(
17 | vscode.languages.registerCompletionItemProvider(
18 | ["csound-csd", "csound-orc"],
19 | completionItemProvider,
20 | ""
21 | )
22 | );
23 |
24 | // Listen for changes in text documents
25 | context.subscriptions.push(
26 | vscode.workspace.onDidChangeTextDocument(event => {
27 | const document = event.document;
28 |
29 | event.contentChanges.forEach(change => {
30 | const lineNumber = change.range.start.line;
31 | const lineText = document.lineAt(lineNumber).text;
32 | const changeText = change.text;
33 |
34 | if (/\W/.test(changeText)) {
35 | // Add tokens from the current line
36 | addTokensToDocumentSet(document, lineText);
37 | }
38 | });
39 | })
40 | );
41 |
42 | // Listen for when an editor becomes active (e.g., switching between files)
43 | context.subscriptions.push(
44 | vscode.window.onDidChangeActiveTextEditor(editor => {
45 | if (editor) {
46 | const document = editor.document;
47 | addTokensToDocumentSet(document, document.getText()); // Parse the active document and add tokens
48 | }
49 | })
50 | );
51 |
52 | // Handle already open files when the extension is activated
53 | if (vscode.window.activeTextEditor) {
54 | const document = vscode.window.activeTextEditor.document;
55 | addTokensToDocumentSet(document, document.getText()); // Parse the currently active file
56 | }
57 |
58 | // Clean up token sets when a document is closed
59 | context.subscriptions.push(
60 | vscode.workspace.onDidCloseTextDocument(document => {
61 | const uri = document.uri.toString();
62 | clearTokensForDocumentSet(uri); // Remove the token set for this document
63 | })
64 | );
65 |
66 | const showOpcodeReferenceCommand = vscode.commands.registerCommand(
67 | "extension.showOpcodeReference",
68 | notYetImplementedForWeb
69 | );
70 | context.subscriptions.push(showOpcodeReferenceCommand);
71 |
72 | // play command
73 | const playCommand = vscode.commands.registerTextEditorCommand(
74 | "extension.csoundPlayActiveDocument",
75 | notYetImplementedForWeb
76 | );
77 | context.subscriptions.push(playCommand);
78 |
79 | const killCommand = vscode.commands.registerTextEditorCommand(
80 | "extension.csoundKillCsoundProcess",
81 | notYetImplementedForWeb
82 | );
83 | context.subscriptions.push(killCommand);
84 |
85 | const evalOrcCommand = vscode.commands.registerTextEditorCommand(
86 | "extension.csoundEvalOrc",
87 | notYetImplementedForWeb
88 | );
89 | context.subscriptions.push(evalOrcCommand);
90 |
91 | const evalScoCommand = vscode.commands.registerTextEditorCommand(
92 | "extension.csoundEvalSco",
93 | notYetImplementedForWeb
94 | );
95 | context.subscriptions.push(evalScoCommand);
96 | }
97 |
98 | // this method is called when your extension is deactivated
99 | export function deactivate() {}
100 |
--------------------------------------------------------------------------------
/src/web/test/suite/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from 'assert';
2 |
3 | // You can import and use all API from the 'vscode' module
4 | // as well as import your extension to test it
5 | import * as vscode from 'vscode';
6 | // import * as myExtension from '../../extension';
7 |
8 | suite('Web Extension Test Suite', () => {
9 | vscode.window.showInformationMessage('Start all tests.');
10 |
11 | test('Sample test', () => {
12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5));
13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0));
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/web/test/suite/index.ts:
--------------------------------------------------------------------------------
1 | // imports mocha for the browser, defining the `mocha` global.
2 | require('mocha/mocha');
3 |
4 | export function run(): Promise {
5 |
6 | return new Promise((c, e) => {
7 | mocha.setup({
8 | ui: 'tdd',
9 | reporter: undefined
10 | });
11 |
12 | // bundles all files in the current directory matching `*.test`
13 | const importAll = (r: __WebpackModuleApi.RequireContext) => r.keys().forEach(r);
14 | importAll(require.context('.', true, /\.test$/));
15 |
16 | try {
17 | // Run the mocha test
18 | mocha.run(failures => {
19 | if (failures > 0) {
20 | e(new Error(`${failures} tests failed.`));
21 | } else {
22 | c();
23 | }
24 | });
25 | } catch (err) {
26 | console.error(err);
27 | e(err);
28 | }
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/syntaxes/csound-csd.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Csound CSD",
3 | "scopeName": "source.csound.csd",
4 | "comment": "Csound CSD Syntax v.6.10",
5 | "firstLineMatch": "",
6 | "patterns": [
7 | {
8 | "begin": "(<)(CsoundSynthesi[sz]er)(>)",
9 | "end": "()(CsoundSynthesi[sz]er)(>)",
10 | "beginCaptures": {
11 | "1": {
12 | "name": "punctuation.definition.tag.begin.csound-document"
13 | },
14 | "2": {
15 | "name": "entity.name.tag.begin.csound-document"
16 | },
17 | "3": {
18 | "name": "punctuation.definition.tag.begin.csound-document"
19 | }
20 | },
21 | "endCaptures": {
22 | "1": {
23 | "name": "punctuation.definition.tag.end.csound-document"
24 | },
25 | "2": {
26 | "name": "entity.name.tag.end.csound-document"
27 | },
28 | "3": {
29 | "name": "punctuation.definition.tag.end.csound-document"
30 | }
31 | },
32 | "patterns": [
33 | {
34 | "name": "meta.orchestra.csound-document",
35 | "begin": "(<)(CsOptions)(>)",
36 | "end": "()(CsOptions)(>)",
37 | "beginCaptures": {
38 | "1": {
39 | "name": "punctuation.definition.tag.begin.csound-document"
40 | },
41 | "2": {
42 | "name": "entity.name.tag.begin.csound-document"
43 | },
44 | "3": {
45 | "name": "punctuation.definition.tag.begin.csound-document"
46 | }
47 | },
48 | "endCaptures": {
49 | "1": {
50 | "name": "punctuation.definition.tag.end.csound-document"
51 | },
52 | "2": {
53 | "name": "entity.name.tag.end.csound-document"
54 | },
55 | "3": {
56 | "name": "punctuation.definition.tag.end.csound-document"
57 | }
58 | },
59 | "patterns": [
60 | {
61 | "include": "source.csound.orc#comments"
62 | }
63 | ]
64 | },
65 | {
66 | "name": "meta.orchestra.csound-document",
67 | "begin": "(<)(CsInstruments)(>)",
68 | "end": "()(CsInstruments)(>)",
69 | "beginCaptures": {
70 | "1": {
71 | "name": "punctuation.definition.tag.begin.csound-document"
72 | },
73 | "2": {
74 | "name": "entity.name.tag.begin.csound-document"
75 | },
76 | "3": {
77 | "name": "punctuation.definition.tag.begin.csound-document"
78 | }
79 | },
80 | "endCaptures": {
81 | "1": {
82 | "name": "punctuation.definition.tag.end.csound-document"
83 | },
84 | "2": {
85 | "name": "entity.name.tag.end.csound-document"
86 | },
87 | "3": {
88 | "name": "punctuation.definition.tag.end.csound-document"
89 | }
90 | },
91 | "contentName": "source.csound.orc.embedded.csound-document",
92 | "patterns": [
93 | {
94 | "include": "source.csound.orc"
95 | }
96 | ]
97 | },
98 | {
99 | "name": "meta.score.csound-document",
100 | "begin": "(<)(CsScore)(>)",
101 | "end": "()(CsScore)(>)",
102 | "beginCaptures": {
103 | "1": {
104 | "name": "punctuation.definition.tag.begin.csound-document"
105 | },
106 | "2": {
107 | "name": "entity.name.tag.begin.csound-document"
108 | },
109 | "3": {
110 | "name": "punctuation.definition.tag.begin.csound-document"
111 | }
112 | },
113 | "endCaptures": {
114 | "1": {
115 | "name": "punctuation.definition.tag.end.csound-document"
116 | },
117 | "2": {
118 | "name": "entity.name.tag.end.csound-document"
119 | },
120 | "3": {
121 | "name": "punctuation.definition.tag.end.csound-document"
122 | }
123 | },
124 | "contentName": "source.csound.sco.embedded.csound-document",
125 | "patterns": [
126 | {
127 | "include": "source.csound.sco"
128 | }
129 | ]
130 | },
131 | {
132 | "name": "meta.html.csound-document",
133 | "begin": "(?=<[hH][tT][mM][lL])",
134 | "end": "(?<=[hH][tT][mM][lL]>)",
135 | "patterns": [
136 | {
137 | "include": "text.html.basic"
138 | }
139 | ]
140 | },
141 | {
142 | "include": "#tags"
143 | }
144 | ]
145 | },
146 | {
147 | "name": "meta.cabbage-gui.csound-document",
148 | "begin": "(<)(Cabbage)(>)",
149 | "end": "()(Cabbage)(>)",
150 | "beginCaptures": {
151 | "1": {
152 | "name": "punctuation.definition.tag.begin.csound-document"
153 | },
154 | "2": {
155 | "name": "entity.name.tag.begin.csound-document"
156 | },
157 | "3": {
158 | "name": "punctuation.definition.tag.begin.csound-document"
159 | }
160 | },
161 | "endCaptures": {
162 | "1": {
163 | "name": "punctuation.definition.tag.end.csound-document"
164 | },
165 | "2": {
166 | "name": "entity.name.tag.end.csound-document"
167 | },
168 | "3": {
169 | "name": "punctuation.definition.tag.end.csound-document"
170 | }
171 | },
172 | "patterns": [
173 | {
174 | "include": "source.json",
175 | "name": "comment.line.cabbage-gui.csound-document",
176 | "begin": ";",
177 | "end": "$",
178 | "beginCaptures": {
179 | "0": {
180 | "name": "punctuation.definition.comment.line.cabbage-gui.csound-document"
181 | }
182 | }
183 | },
184 | {
185 | "include": "source.csound.orc#macroUses"
186 | },
187 | {
188 | "include": "source.csound.orc#preprocessorDirectives"
189 | },
190 | {
191 | "include": "source.csound.orc#floatingPointNumbers"
192 | },
193 | {
194 | "include": "source.csound.orc#decimalNumbers"
195 | },
196 | {
197 | "name": "string.quoted.cabbage-gui.csound-document",
198 | "begin": "\"",
199 | "end": "\"",
200 | "beginCaptures": {
201 | "0": {
202 | "name": "punctuation.definition.string.begin.cabbage-gui.csound-document"
203 | }
204 | },
205 | "endCaptures": {
206 | "0": {
207 | "name": "punctuation.definition.string.end.cabbage-gui.csound-document"
208 | }
209 | },
210 | "patterns": [
211 | {
212 | "include": "source.csound.orc#macroUses"
213 | }
214 | ]
215 | },
216 | {
217 | "match": "^[ \t]*(?i:(button|checkbox|combobox|encoder|hrange|hslider|numberbox|rslider|vrange|vslider|xypad|csoundoutput|filebutton|form|gentable|groupbox|hostbpm|hostplaying|hostppqpos|hosttime|image|infobutton|keyboard|label|line|loadbutton|signaldisplay|socketreceive|socketsend|soundfiler|source|stepper|textbox|texteditor)|(hslider2|hslider3|vslider2|vslider3|directorylist|fftdisplay|hostrecording|listbox|multitab|patmatrix|popupmenu|pvsview|recordbutton|snapshot|sourcebutton|table|transport))\\b",
218 | "captures": {
219 | "1": {
220 | "name": "keyword.widget-type.cabbage-gui.csound-document"
221 | },
222 | "2": {
223 | "name": "invalid.deprecated.cabbage-gui.csound-document"
224 | }
225 | }
226 | },
227 | {
228 | "match": "\\b(?i:(active|address|align|alpha|amprange|arrowbackgroundcolour|arrowcolour|backgroundcolor|backgroundcolour|ballcolour|blacknotecolour|bounds|caption|channel|channelarray|channels|channeltype|color:0|color:1|color|colour:0|colour:1|colour|corners|displaytype|file|fill|fontcolor:0|fontcolor:1|fontcolor|fontcolour:0|fontcolour:1|fontcolour|fontstyle|guirefresh|highlightcolour|identchannel|imgdebug|imgfile|imgpath|items|keywidth|kind|latched|linethickness|max|menucolor|middlec|min|mode|noteseparatorcolour|numberofsteps|outlinecolor|outlinecolour|outlinethickness|plant|pluginid|populate|popup|popuptext|pos|radiogroup|range|rangex|rangey|refreshfiles|rescale|rotate|samplerange|scrubberposition|shape|show|signalvariable|size|sliderincr|tablebackgroundcolour|tablecolor|tablecolour|tablegridcolor|tablegridcolour|tablenumber|tablenumbers|text|textbox|textcolor|textcolour|titlebarcolour|trackercolor|trackercolour|trackerthickness|updaterate|value|valuetextbox|velocity|visible|whitenotecolour|widgetarray|wrap|zoom)|(bold|ffttablenumber|gradient|logger|scalex|scaley|scroll|scrollbars|tablebackgroundcolor))\\b",
229 | "captures": {
230 | "1": {
231 | "name": "support.function.widget-identifier.cabbage-gui.csound-document"
232 | },
233 | "2": {
234 | "name": "invalid.deprecated.cabbage-gui.csound-document"
235 | }
236 | }
237 | }
238 | ]
239 | },
240 | {
241 | "include": "#tags"
242 | }
243 | ],
244 | "repository": {
245 | "tags": {
246 | "patterns": [
247 | {
248 | "begin": "(<)([0-9A-Za-z:-]+)(>)",
249 | "end": "()([0-9A-Za-z:-]+)(>)",
250 | "beginCaptures": {
251 | "1": {
252 | "name": "punctuation.definition.tag.begin.csound-document"
253 | },
254 | "2": {
255 | "name": "entity.name.tag.begin.csound-document"
256 | },
257 | "3": {
258 | "name": "punctuation.definition.tag.begin.csound-document"
259 | }
260 | },
261 | "endCaptures": {
262 | "1": {
263 | "name": "punctuation.definition.tag.end.csound-document"
264 | },
265 | "2": {
266 | "name": "entity.name.tag.end.csound-document"
267 | },
268 | "3": {
269 | "name": "punctuation.definition.tag.end.csound-document"
270 | }
271 | }
272 | }
273 | ]
274 | }
275 | }
276 | }
--------------------------------------------------------------------------------
/syntaxes/csound-orc.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Csound ORC",
3 | "scopeName": "source.csound.orc",
4 | "comment": "Csound Orchestra Syntax v.6.10",
5 | "patterns": [
6 | {
7 | "include": "#commentsAndMacroUses"
8 | },
9 | {
10 | "name": "meta.instrument-block.csound",
11 | "begin": "\\b(?=instr\\b)",
12 | "end": "\\bendin\\b",
13 | "endCaptures": {
14 | "0": {
15 | "name": "storage.type.function.csound"
16 | }
17 | },
18 | "patterns": [
19 | {
20 | "name": "meta.instrument-declaration.csound",
21 | "begin": "instr",
22 | "end": "$",
23 | "beginCaptures": {
24 | "0": {
25 | "name": "storage.type.function.csound"
26 | }
27 | },
28 | "patterns": [
29 | {
30 | "name": "entity.name.function.csound",
31 | "match": "\\d+|[A-Z_a-z]\\w*"
32 | },
33 | {
34 | "include": "#commentsAndMacroUses"
35 | }
36 | ]
37 | },
38 | {
39 | "include": "#commentsAndMacroUses"
40 | },
41 | {
42 | "include": "#labels"
43 | },
44 | {
45 | "include": "#partialExpressions"
46 | }
47 | ]
48 | },
49 | {
50 | "name": "meta.opcode-definition.csound",
51 | "begin": "\\b(?=opcode\\b)",
52 | "end": "\\bendop\\b",
53 | "endCaptures": {
54 | "0": {
55 | "name": "keyword.other.csound"
56 | }
57 | },
58 | "patterns": [
59 | {
60 | "name": "meta.opcode-declaration.csound",
61 | "begin": "opcode",
62 | "end": "$",
63 | "beginCaptures": {
64 | "0": {
65 | "name": "keyword.function.csound"
66 | }
67 | },
68 | "patterns": [
69 | {
70 | "name": "meta.opcode-details.csound",
71 | "begin": "[A-Z_a-z]\\w*\\b",
72 | "end": "$",
73 | "beginCaptures": {
74 | "0": {
75 | "name": "entity.name.function.opcode.csound"
76 | }
77 | },
78 | "patterns": [
79 | {
80 | "name": "meta.opcode-type-signature.csound",
81 | "begin": "\\b(?:0|[afijkKoOpPStV\\[\\]]+)",
82 | "end": ",|$",
83 | "beginCaptures": {
84 | "0": {
85 | "name": "storage.type.csound"
86 | }
87 | },
88 | "patterns": [
89 | {
90 | "include": "#commentsAndMacroUses"
91 | }
92 | ]
93 | },
94 | {
95 | "include": "#commentsAndMacroUses"
96 | }
97 | ]
98 | },
99 | {
100 | "include": "#commentsAndMacroUses"
101 | }
102 | ]
103 | },
104 | {
105 | "include": "#commentsAndMacroUses"
106 | },
107 | {
108 | "include": "#labels"
109 | },
110 | {
111 | "include": "#partialExpressions"
112 | }
113 | ]
114 | },
115 | {
116 | "include": "#labels"
117 | },
118 | {
119 | "include": "#partialExpressions"
120 | }
121 | ],
122 | "repository": {
123 | "bracedStringContents": {
124 | "patterns": [
125 | {
126 | "include": "#escapeSequences"
127 | },
128 | {
129 | "include": "#formatSpecifiers"
130 | }
131 | ]
132 | },
133 | "comments": {
134 | "patterns": [
135 | {
136 | "name": "comment.block.csound",
137 | "begin": "/\\*",
138 | "end": "\\*/",
139 | "beginCaptures": {
140 | "0": {
141 | "name": "punctuation.definition.comment.begin.csound"
142 | }
143 | },
144 | "endCaptures": {
145 | "0": {
146 | "name": "punctuation.definition.comment.end.csound"
147 | }
148 | }
149 | },
150 | {
151 | "name": "comment.line.double-slash.csound",
152 | "begin": "//",
153 | "end": "$",
154 | "beginCaptures": {
155 | "0": {
156 | "name": "punctuation.definition.comment.csound"
157 | }
158 | }
159 | },
160 | {
161 | "include": "#semicolonComments"
162 | },
163 | {
164 | "include": "#lineContinuations"
165 | }
166 | ]
167 | },
168 | "semicolonComments": {
169 | "patterns": [
170 | {
171 | "name": "comment.line.semicolon.csound",
172 | "begin": ";",
173 | "end": "$",
174 | "beginCaptures": {
175 | "0": {
176 | "name": "punctuation.definition.comment.csound"
177 | }
178 | }
179 | }
180 | ]
181 | },
182 | "commentsAndMacroUses": {
183 | "patterns": [
184 | {
185 | "include": "#comments"
186 | },
187 | {
188 | "include": "#macroUses"
189 | }
190 | ]
191 | },
192 | "decimalNumbers": {
193 | "patterns": [
194 | {
195 | "name": "constant.numeric.integer.decimal.csound",
196 | "match": "\\d+"
197 | }
198 | ]
199 | },
200 | "escapeSequences": {
201 | "patterns": [
202 | {
203 | "name": "constant.character.escape.csound",
204 | "match": "\\\\(?:[abfnrtv\"\\\\]|[0-7]{1,3})"
205 | }
206 | ]
207 | },
208 | "floatingPointNumbers": {
209 | "patterns": [
210 | {
211 | "name": "constant.numeric.float.csound",
212 | "match": "(?:\\d+[Ee][+-]?\\d+)|(?:\\d+\\.\\d*|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?"
213 | }
214 | ]
215 | },
216 | "formatSpecifiers": {
217 | "patterns": [
218 | {
219 | "name": "constant.character.placeholder.csound",
220 | "match": "%[#0\\- +]*\\d*(?:\\.\\d+)?[diuoxXfFeEgGaAcs]"
221 | },
222 | {
223 | "name": "constant.character.escape.csound",
224 | "match": "%%"
225 | }
226 | ]
227 | },
228 | "labels": {
229 | "patterns": [
230 | {
231 | "match": "^[ \\t]*(\\w+)(:)(?:[ \\t]+|$)",
232 | "captures": {
233 | "1": {
234 | "name": "entity.name.label.csound"
235 | },
236 | "2": {
237 | "name": "entity.punctuation.label.csound"
238 | }
239 | }
240 | }
241 | ]
242 | },
243 | "lineContinuations": {
244 | "patterns": [
245 | {
246 | "match": "(\\\\)[ \\t]*((;).*)?$",
247 | "captures": {
248 | "1": {
249 | "name": "constant.character.escape.line-continuation.csound"
250 | },
251 | "2": {
252 | "name": "comment.line.semicolon.csound"
253 | },
254 | "3": {
255 | "name": "punctuation.definition.comment.csound"
256 | }
257 | }
258 | }
259 | ]
260 | },
261 | "macroNames": {
262 | "patterns": [
263 | {
264 | "match": "([A-Z_a-z]\\w*)|(\\d+\\w*)",
265 | "captures": {
266 | "1": {
267 | "name": "entity.name.function.preprocessor.csound"
268 | },
269 | "2": {
270 | "name": "invalid.illegal.csound"
271 | }
272 | }
273 | }
274 | ]
275 | },
276 | "macroParameterValueParenthetical": {
277 | "patterns": [
278 | {
279 | "name": "meta.macro-parameter-value-parenthetical.csound",
280 | "begin": "\\(",
281 | "end": "\\)",
282 | "patterns": [
283 | {
284 | "include": "#macroParameterValueParenthetical"
285 | },
286 | {
287 | "name": "constant.character.escape.csound",
288 | "match": "\\\\\\)"
289 | },
290 | {
291 | "include": "$self"
292 | }
293 | ]
294 | }
295 | ]
296 | },
297 | "macroUses": {
298 | "patterns": [
299 | {
300 | "name": "meta.function-like-macro-use.csound",
301 | "begin": "(\\$[A-Z_a-z]\\w*\\.?)\\(",
302 | "end": "\\)",
303 | "beginCaptures": {
304 | "1": {
305 | "name": "entity.name.function.preprocessor.csound"
306 | }
307 | },
308 | "patterns": [
309 | {
310 | "name": "string.quoted.csound",
311 | "begin": "\"",
312 | "end": "\"",
313 | "beginCaptures": {
314 | "0": {
315 | "name": "punctuation.definition.string.begin.csound"
316 | }
317 | },
318 | "endCaptures": {
319 | "0": {
320 | "name": "punctuation.definition.string.end.csound"
321 | }
322 | },
323 | "patterns": [
324 | {
325 | "match": "([#'()])|(\\\\[#'()])",
326 | "captures": {
327 | "1": {
328 | "name": "invalid.illegal.csound"
329 | },
330 | "2": {
331 | "name": "constant.character.escape.csound"
332 | }
333 | }
334 | },
335 | {
336 | "include": "#quotedStringContents"
337 | }
338 | ]
339 | },
340 | {
341 | "name": "string.braced.csound",
342 | "begin": "\\{\\{",
343 | "end": "\\}\\}",
344 | "patterns": [
345 | {
346 | "match": "([#'()])|(\\\\[#'()])",
347 | "captures": {
348 | "1": {
349 | "name": "invalid.illegal.csound"
350 | },
351 | "2": {
352 | "name": "constant.character.escape.csound"
353 | }
354 | }
355 | },
356 | {
357 | "include": "#bracedStringContents"
358 | }
359 | ]
360 | },
361 | {
362 | "include": "#macroParameterValueParenthetical"
363 | },
364 | {
365 | "name": "punctuation.macro-parameter-separator.csound",
366 | "match": "[#']"
367 | },
368 | {
369 | "include": "$self"
370 | }
371 | ]
372 | },
373 | {
374 | "name": "entity.name.function.preprocessor.csound",
375 | "match": "\\$[A-Z_a-z]\\w*(?:\\.|\\b)"
376 | }
377 | ]
378 | },
379 | "numbers": {
380 | "patterns": [
381 | {
382 | "include": "#floatingPointNumbers"
383 | },
384 | {
385 | "match": "(0[Xx])([0-9A-Fa-f]+)",
386 | "captures": {
387 | "1": {
388 | "name": "storage.type.number.csound"
389 | },
390 | "2": {
391 | "name": "constant.numeric.integer.hexadecimal.csound"
392 | }
393 | }
394 | },
395 | {
396 | "include": "#decimalNumbers"
397 | }
398 | ]
399 | },
400 | "partialExpressions": {
401 | "patterns": [
402 | {
403 | "include": "#preprocessorDirectives"
404 | },
405 | {
406 | "name": "variable.language.csound",
407 | "match": "\\b(?:0dbfs|A4|k(?:r|smps)|nchnls(?:_i)?|sr)\\b"
408 | },
409 | {
410 | "include": "#numbers"
411 | },
412 | {
413 | "name": "keyword.control.csound",
414 | "match": "\\b(?:do|else(?:if)?|end(?:if|until)|fi|i(?:f|then)|kthen|od|r(?:ir)?eturn|then|until|while)\\b"
415 | },
416 | {
417 | "name": "keyword.operator.csound",
418 | "match": "\\+=|-=|\\*=|/=|<<|>>|<=|>=|==|!=|&&|\\|\\||[~¬]|[=!+\\-*/^%&|<>#?:]"
419 | },
420 | {
421 | "include": "#quotedStrings"
422 | },
423 | {
424 | "name": "variable.parameter.csound",
425 | "match": "\\bp\\d+\\b"
426 | },
427 | {
428 | "match": "(?:\\b(ATS(?:add(?:(?:nz)?)|cabbageSet|cabbageGet|cabbageGetValue|cabbageSetValue|cabbageDump|bufread|cross|in(?:fo|terpread)|partialtap|read(?:(?:nz)?)|sinnoi)|FL(?:b(?:ox|ut(?:Bank|ton))|c(?:loseButton|o(?:lor(?:(?:2)?)|unt))|execButton|g(?:etsnap|roup(?:(?:(?:E|_e)nd)?))|h(?:ide|vsBox(?:(?:SetValue)?))|joy|k(?:eyIn|nob)|l(?:abel|oadsnap)|mouse|p(?:a(?:ck(?:(?:(?:E|_e)nd)?)|nel(?:(?:(?:E|_e)nd)?))|rintk(?:(?:2)?))|r(?:oller|un)|s(?:avesnap|croll(?:(?:(?:E|_e)nd)?)|et(?:Align|Box|Color(?:(?:2)?)|Font|Position|S(?:ize|napGroup)|Text(?:(?:Color|(?:Siz|Typ)e)?)|Val(?:(?:(?:(?:_)?)i)?)|snap)|how|lid(?:Bnk(?:(?:2(?:(?:Set(?:(?:k)?))?)|GetHandle|Set(?:(?:k)?))?)|er))|t(?:abs(?:(?:(?:E|_e)nd)?)|ext)|update|v(?:alue|keybd|slidBnk(?:(?:2)?))|xyin)|Jacko(?:Audio(?:In(?:(?:Connect)?)|Out(?:(?:Connect)?))|Freewheel|In(?:fo|it)|Midi(?:(?:InConnec|Ou(?:(?:tConnec)?))t)|NoteOut|On|Transport)|K35_(?:(?:[hl])pf)|Mixer(?:Clear|GetLevel|Receive|Se(?:nd|tLevel(?:(?:_i)?)))|OSC(?:bundle|count|init(?:(?:M)?)|listen|raw|send(?:(?:_lo)?))|STK(?:B(?:andedWG|eeThree|low(?:Botl|Hole)|owed|rass)|Clarinet|Drummer|F(?:MVoices|lute)|HevyMetl|M(?:andolin|o(?:dalBar|og))|P(?:ercFlut|lucked)|R(?:esonate|hodey)|S(?:axofony|hakers|i(?:mple|tar)|tifKarp)|TubeBell|VoicForm|W(?:histle|urley))|a(?:bs|ctive|ds(?:r|yn(?:(?:t(?:(?:2)?))?))|ftouch|l(?:lpole|pass|wayson)|mp(?:db(?:(?:fs)?)|midi(?:(?:curve|d)?))|poleparams|r(?:duino(?:Read|St(?:art|op))|eson(?:(?:k)?))|tone(?:(?:[kx])?))|b(?:a(?:bo|lance(?:(?:2)?)|mboo|rmodel)|bcut(?:[ms])|e(?:adsynt|osc|(?:tara|xpr)nd)|form(?:(?:de|en)c1)|i(?:nit|quad(?:(?:a)?)|rnd)|ob|pf(?:(?:cos)?)|qrez|u(?:t(?:b(?:[pr])|hp|lp|t(?:er(?:b(?:[pr])|(?:[hl])p)|on))|zz))|c(?:2r|a(?:basa|uchy(?:(?:i)?))|brt|e(?:il|ll|nt(?:(?:roid)?)|ps(?:(?:inv)?))|h(?:an(?:ctrl|ged2|[io])|e(?:byshevpoly|ckbox)|n(?:_(?:[Sak])|clear|export|get(?:(?:ks|[aiks])?)|mix|params|set(?:(?:ks|[aiks])?))|uap)|l(?:ear|filt|ip|ocko(?:ff|n))|mp(?:(?:lxprod)?)|nt(?:C(?:reate|ycles)|Re(?:ad|set)|State)|o(?:m(?:b(?:(?:inv)?)|p(?:ile(?:csd|orc|str)|ress(?:(?:2)?)))|n(?:nect|trol|v(?:(?:l|olv)e))|py(?:a2ftab|f2array)|s(?:(?:h|inv|seg(?:(?:[br])?))?)|unt(?:(?:_i)?))|p(?:s(?:2pch|midi(?:(?:b|nn)?)|oct|pch|t(?:mid|un(?:(?:i)?))|xpch)|u(?:meter|prc))|r(?:oss(?:2|fm(?:(?:i|pm(?:(?:i)?))?)|pm(?:(?:i)?))|unch)|t(?:lchn|rl(?:14|21|7|init))|userrnd)|d(?:a(?:m|te(?:(?:s)?))|b(?:(?:(?:(?:fs)?)amp)?)|c(?:block(?:(?:2)?)|onv|t(?:(?:inv)?))|e(?:interleave|l(?:ay(?:(?:[1krw])?)|tap(?:(?:xw|[3inx])?))|norm)|i(?:ff|ode_ladder|rectory|s(?:k(?:grain|in(?:(?:2)?))|p(?:fft|lay)|tort(?:(?:1)?))|vz)|o(?:ppler|t|wnsamp)|ripwater|ssi(?:a(?:ctivate|udio)|ctls|(?:ini|lis)t)|u(?:mpk(?:(?:[234])?)|s(?:errnd|t(?:(?:2)?))))|e(?:nvlpx(?:(?:r)?)|phasor|qfil|v(?:alstr|ent(?:(?:_i)?))|x(?:citer|itnow|p(?:(?:curve|on|rand(?:(?:i)?)|seg(?:(?:ba|[abr])?))?)))|f(?:a(?:reylen(?:(?:i)?)|ust(?:audio|c(?:ompile|tl)|dsp|gen|play))|ft(?:(?:inv)?)|i(?:close|l(?:e(?:bit|len|nchnls|peak|s(?:cal|r)|valid)|larray|ter2)|n(?:(?:[ik])?)|open)|l(?:a(?:nger|shtxt)|oo(?:per(?:(?:2)?)|r)|uid(?:AllOut|C(?:C(?:[ik])|ontrol)|Engine|Info|Load|Note|Out|ProgramSelect|SetInterpMethod))|m(?:a(?:nal|x)|b(?:3|ell)|in|metal|od|percfl|(?:rhod|voic|wurli)e)|o(?:f(?:2|ilter)|l(?:d|low(?:(?:2)?))|scil(?:(?:i)?)|ut(?:(?:ir|[ik])?)|[fg])|print(?:(?:(?:k)?)s)|r(?:a(?:c(?:(?:talnoise)?)|mebuffer)|eeverb)|t(?:audio|c(?:hnls|onv|ps)|exists|free|gen(?:(?:once|tmp)?)|l(?:en|oad(?:(?:k)?)|ptim)|morf|om|print|resize(?:(?:i)?)|s(?:a(?:mplebank|ve(?:(?:k)?))|et|lice(?:(?:i)?)|r)))|g(?:a(?:in(?:(?:slider)?)|uss(?:(?:i|trig)?))|buzz|e(?:n(?:array(?:(?:_i)?)|dy(?:(?:[cx])?))|t(?:c(?:fg|ol)|ftargs|row(?:(?:lin)?)|seed))|ogobel|ra(?:in(?:(?:[23])?)|nule)|tf|uiro)|h(?:armon(?:(?:[234])?)|df5(?:read|write)|ilbert(?:(?:2)?)|rtf(?:early|move(?:(?:2)?)|reverb|stat)|sboscil|vs(?:[123])|ypot)|i(?:hold|mage(?:create|free|getpixel|load|s(?:ave|etpixel|ize))|n(?:(?:32|ch|it(?:(?:c(?:14|21|7))?)|let(?:kid|[afkv])|rg|s(?:global|remot)|te(?:g|r(?:leave|p))|value|[hoqstxz])?))|j(?:acktransport|itter(?:(?:2)?)|oystick|spline)|l(?:a(?:_(?:i_(?:a(?:dd_(?:m(?:[cr])|v(?:[cr]))|ssign_(?:m(?:[cr])|t|v(?:[cr])))|conjugate_(?:m(?:[cr])|v(?:[cr]))|d(?:i(?:stance_v(?:[cr])|vide_(?:m(?:[cr])|v(?:[cr])))|ot_(?:m(?:c_vc|r_vr|[cr])|v(?:[cr])))|f_assign|get_(?:m(?:[cr])|v(?:[cr]))|invert_m(?:[cr])|l(?:ower_solve_m(?:[cr])|u_(?:det_m(?:[cr])|factor_m(?:[cr])|solve_m(?:[cr])))|m(?:c_(?:create|set)|r_(?:create|set)|ultiply_(?:m(?:[cr])|v(?:[cr])))|norm(?:1_(?:m(?:[cr])|v(?:[cr]))|_(?:euclid_(?:m(?:[cr])|v(?:[cr]))|inf_(?:m(?:[cr])|v(?:[cr]))|max_m(?:[cr])))|print_(?:m(?:[cr])|v(?:[cr]))|qr_(?:eigen_m(?:[cr])|factor_m(?:[cr])|sym_eigen_m(?:[cr]))|random_(?:m(?:[cr])|v(?:[cr]))|s(?:ize_(?:m(?:[cr])|v(?:[cr]))|ubtract_(?:m(?:[cr])|v(?:[cr])))|t(?:_assign|ra(?:ce_m(?:[cr])|nspose_m(?:[cr])))|upper_solve_m(?:[cr])|v(?:c_(?:create|set)|r_(?:create|set)))|k_(?:a(?:_assign|dd_(?:m(?:[cr])|v(?:[cr]))|ssign_(?:m(?:[cr])|v(?:[cr])|[aft]))|c(?:onjugate_(?:m(?:[cr])|v(?:[cr]))|urrent_(?:f|vr))|d(?:i(?:stance_v(?:[cr])|vide_(?:m(?:[cr])|v(?:[cr])))|ot_(?:m(?:c_vc|r_vr|[cr])|v(?:[cr])))|f_assign|get_(?:m(?:[cr])|v(?:[cr]))|invert_m(?:[cr])|l(?:ower_solve_m(?:[cr])|u_(?:det_m(?:[cr])|factor_m(?:[cr])|solve_m(?:[cr])))|m(?:c_set|r_set|ultiply_(?:m(?:[cr])|v(?:[cr])))|norm(?:1_(?:m(?:[cr])|v(?:[cr]))|_(?:euclid_(?:m(?:[cr])|v(?:[cr]))|inf_(?:m(?:[cr])|v(?:[cr]))|max_m(?:[cr])))|qr_(?:eigen_m(?:[cr])|factor_m(?:[cr])|sym_eigen_m(?:[cr]))|random_(?:m(?:[cr])|v(?:[cr]))|subtract_(?:m(?:[cr])|v(?:[cr]))|t(?:_assign|race_m(?:[cr]))|upper_solve_m(?:[cr])|v(?:(?:[cr])_set)))|g(?:(?:ud)?)|stcycle)|enarray|fo|i(?:mit(?:(?:1)?)|n(?:cos|e(?:(?:n(?:(?:r)?)|to)?)|k_(?:beat_(?:force|(?:ge|reques)t)|create|enable|is_enabled|metro|peers|tempo_(?:(?:[gs])et))|lin|rand|seg(?:(?:[br])?))|veconv)|o(?:cs(?:end|ig)|g(?:(?:10|2|btwo|curve)?)|op(?:seg(?:(?:p)?)|(?:[tx])seg)|renz|scil(?:(?:(?:(?:3)?)phs|[3x])?)|w(?:pass2|res(?:(?:x)?)))|p(?:c(?:anal|filter)|f(?:18|orm|reson)|hasor|interp|oscil(?:(?:sa(?:(?:2)?)|[3a])?)|re(?:ad|son)|s(?:hold(?:(?:p)?)|lot))|u(?:a_(?:exec|i(?:aopcall(?:(?:_off)?)|kopcall(?:(?:_off)?)|opcall(?:(?:_off)?))|opdef)|fs))|m(?:a(?:ca|dsr|gs|nd(?:(?:[eo])l)|parray(?:(?:_i)?)|rimba|ssign|x(?:_k|a(?:bs(?:(?:accum)?)|ccum|lloc|rray))|[cx])|clock|delay|e(?:dian(?:(?:k)?)|tro(?:(?:2)?))|fb|i(?:d(?:global|i(?:arp|c(?:14|21|7|h(?:annelaftertouch|n)|ontrolchange|trl)|default|filestatus|in|noteo(?:ff|n(?:cps|key|oct|pch))|o(?:n(?:(?:2)?)|ut(?:(?:_i)?))|p(?:gm|itchbend|olyaftertouch|rogramchange)|tempo)|remot)|n(?:(?:a(?:bs(?:(?:accum)?)|ccum|rray)|cer)?)|rror)|o(?:d(?:e|matrix)|nitor|og(?:(?:ladder(?:(?:2)?)|vcf(?:(?:2)?))?)|scil)|p(?:3(?:bitrate|in|len|nchnls|s(?:cal|r))|ulse)|rtmsg|to(?:[fn])|u(?:ltitap|te)|vc(?:hpf|lpf(?:[1234]))|xadsr)|n(?:chnls_hw|estedap|l(?:alp|filt(?:(?:2)?))|o(?:ise|t(?:eo(?:ff|n(?:(?:dur(?:(?:2)?))?))|num))|r(?:everb|pn)|s(?:amp|t(?:ance|r(?:num|str)))|t(?:o(?:[fm])|rpol)|xtpow2)|o(?:ct(?:ave|cps|midi(?:(?:b|nn)?)|pch)|labuffer|sc(?:bnk|il(?:(?:1i|ikt(?:(?:[ps])?)|[13insx])?))|ut(?:(?:32|ch|i(?:at|c(?:(?:14)?)|p(?:at|[bc]))|k(?:at|c(?:(?:14)?)|p(?:at|[bc]))|let(?:kid|[afkv])|q(?:[1234])|rg|s(?:[12])|value|[choqsxz])?))|p(?:5g(?:connect|data)|a(?:n(?:(?:2)?)|r(?:eq|t(?:2txt|i(?:als|kkel(?:(?:get|s(?:et|ync))?))))|ssign|ulstretch)|c(?:auchy|h(?:bend|midi(?:(?:b|nn)?)|oct|tom)|o(?:nvolve|unt))|d(?:clip|half(?:(?:y)?))|eak|gm(?:(?:assig|ch)n)|h(?:as(?:er(?:[12])|or(?:(?:bnk)?))|s)|i(?:n(?:dex|k(?:er|ish))|tch(?:(?:a(?:c|mdf))?))|l(?:a(?:net|terev)|(?:ltra|u)ck)|o(?:isson|l(?:2rect|y(?:aft|nomial))|rt(?:(?:k)?)|scil(?:(?:3)?)|w(?:(?:ershape|oftwo|s)?))|r(?:e(?:alloc|piano)|int(?:(?:_type|array|f_i|k(?:s2|[2s])|ln|sk|[fks])?)|oduct)|set|t(?:ablew|rack)|uts|v(?:add|bufread|cross|interp|oc|read|s(?:2(?:array|tab)|a(?:dsyn|nal|rp)|b(?:and(?:width|[pr])|in|lur|uf(?:fer|read(?:(?:2)?)))|c(?:ale|e(?:nt|ps)|(?:f|ros)s)|d(?:emix|is(?:kin|p))|envftw|f(?:ilter|r(?:e(?:ad|eze)|omarray)|t(?:[rw])|write)|gain|hift|i(?:fd|n(?:(?:fo|it)?))|l(?:ock|pc)|m(?:aska|ix|o(?:(?:ot|rp)h))|o(?:sc|ut)|pitch|t(?:anal|encil|race)|voc|warp|ynth))|wd|y(?:assign(?:(?:[it])?)|call(?:(?:1(?:[it])|2(?:[it])|3(?:[it])|4(?:[it])|5(?:[it])|6(?:[it])|7(?:[it])|8(?:[it])|ni|[12345678int])?)|e(?:val(?:(?:[it])?)|xec(?:(?:[it])?))|init|l(?:assign(?:(?:[it])?)|call(?:(?:1(?:[it])|2(?:[it])|3(?:[it])|4(?:[it])|5(?:[it])|6(?:[it])|7(?:[it])|8(?:[it])|ni|[12345678int])?)|e(?:val(?:(?:[it])?)|xec(?:(?:[it])?))|run(?:(?:[it])?))|run(?:(?:[it])?)))|q(?:inf|nan)|r(?:2c|and(?:(?:om(?:(?:[hi])?)|[chi])?)|bjeq|e(?:ad(?:clock|fi|k(?:[234s])|sc(?:ore|ratch)|[fk])|ct2pol|lease|mo(?:teport|ve)|pluck|s(?:hapearray|on(?:(?:bnk|xk|[krxyz])?)|yn)|verb(?:(?:2|sc)?)|windscore|zzy)|fft|ifft|ms|nd(?:(?:31|seed)?)|ound|spline|tclock)|s(?:16b14|32b14|a(?:mphold|ndpaper)|c(?:_(?:lag(?:(?:ud)?)|phasor|trig)|a(?:le(?:(?:array)?)|n(?:hammer|table|[su]))|hed(?:kwhen(?:(?:named)?)|ule(?:(?:k)?)|when)|oreline(?:(?:_i)?))|e(?:ed|kere|lect|mitone|nse(?:(?:key)?)|qtime(?:(?:2)?)|rial(?:Begin|End|Flush|Print|Read|Write(?:(?:_i)?))|t(?:c(?:(?:o|tr)l)|ksmps|row|scorepos))|f(?:i(?:list|nstr(?:(?:3m|[3m])?))|lo(?:ad|oper)|p(?:assign|l(?:ay(?:(?:3m|[3m])?)|ist)|reset))|h(?:aker|ift(?:in|out))|i(?:gnum|n(?:(?:h|inv|syn)?))|l(?:eighbells|i(?:cearray(?:(?:_i)?)|der(?:16(?:(?:f|table(?:(?:f)?))?)|32(?:(?:f|table(?:(?:f)?))?)|64(?:(?:f|table(?:(?:f)?))?)|8(?:(?:f|table(?:(?:f)?))?)|Kawai)))|nd(?:loop|warp(?:(?:st)?))|o(?:ck(?:recv(?:(?:s)?)|send(?:(?:s)?))|rt(?:[ad])|undin)|p(?:a(?:ce|t3d(?:(?:[it])?))|dist|litrig|rintf(?:(?:k)?)|send)|q(?:rt|uinewave)|t(?:atevar|errain|ix|r(?:c(?:at(?:(?:k)?)|har(?:(?:k)?)|mp(?:(?:k)?)|py(?:(?:k)?))|e(?:cv|son)|fromurl|get|in(?:dex(?:(?:k)?)|g2array)|l(?:en(?:(?:k)?)|ower(?:(?:k)?))|rindex(?:(?:k)?)|s(?:et|trip|ub(?:(?:k)?))|to(?:(?:[dl])k|[dl])|upper(?:(?:k)?))|send)|u(?:binstr(?:(?:init)?)|m(?:(?:array)?))|vfilter|y(?:nc(?:grain|loop|phasor)|stem(?:(?:_i)?)))|t(?:a(?:b(?:2(?:array|pvs)|_i|ifd|le(?:(?:3kt|copy|filter(?:(?:i)?)|gpw|i(?:copy|gpw|kt|mix)|kt|mix|ng|ra|s(?:eg|huffle(?:(?:i)?))|w(?:a|kt)|x(?:kt|seg)|[3iw])?)|morph(?:(?:ak|[ai])?)|play|r(?:ec|owlin)|sum|w(?:(?:_i)?))|mbourine|n(?:h|inv(?:(?:2)?))|[bn])|bvcf|emp(?:est|o(?:(?:(?:sc|v)al)?))|i(?:me(?:dseq|inst(?:[ks])|[ks])|val)|lineto|one(?:(?:[kx])?)|r(?:a(?:dsyn|n(?:dom|seg(?:(?:[br])?)))|cross|filter|highest|i(?:g(?:ger|hold|phasor|seq)|m(?:(?:_i)?)|rand)|lowest|mix|s(?:cale|(?:hif|pli)t))|urno(?:ff(?:(?:2)?)|n)|vconv)|u(?:n(?:irand|wrap)|psamp|r(?:andom|d))|v(?:a(?:ctrol|dd(?:(?:_i|v(?:(?:_i)?))?)|get|lpass|set)|bap(?:(?:gmove|lsinit|(?:(?:z)?)move|[gz])?)|c(?:ella|o(?:(?:2(?:(?:(?:f|i(?:f|ni))t)?)|mb|py(?:(?:_i)?))?))|d(?:el(?:_k|ay(?:(?:x(?:w(?:[qs])|[qsw])|[3kx])?))|ivv(?:(?:_i)?))|e(?:cdelay|loc|xp(?:(?:_i|seg|v(?:(?:_i)?))?))|i(?:b(?:es|r(?:(?:ato)?))|ncr)|l(?:i(?:mit|nseg)|owres)|m(?:ap|irror|ult(?:(?:_i|v(?:(?:_i)?))?))|o(?:ice|sim)|p(?:haseseg|o(?:rt|w(?:(?:_i|v(?:(?:_i)?))?))|s|voc)|rand(?:[hi])|subv(?:(?:_i)?)|tab(?:le(?:1k|w(?:[aik])|[aik])|w(?:[aik])|[aik])|wrap)|w(?:aveset|e(?:bsocket|ibull)|g(?:b(?:ow(?:(?:edbar)?)|rass)|clar|flute|pluck(?:(?:2)?)|uide(?:[12]))|i(?:i(?:connect|data|range|send)|ndow)|r(?:ap|itescratch)|terrain)|x(?:adsr|in|out|scan(?:map|smap|[su])|tratim|yscale)|z(?:a(?:cl|kinit|mod|rg|wm|[rw])|df_(?:1pole(?:(?:_mode)?)|2pole(?:(?:_mode)?)|ladder)|filter2|i(?:wm|[rw])|k(?:cl|mod|wm|[rw]))|[Saikp])\\b|\\b(array|bform(?:(?:de|en)c)|c(?:hanged|opy2(?:(?:[ft])tab))|hrtfer|ktableseg|lentab|m(?:(?:ax|in)tab)|p(?:op(?:(?:_f)?)|table(?:(?:iw|[3i])?)|ush(?:(?:_f)?))|s(?:calet|ndload|oundout(?:(?:s)?)|pec(?:addm|di(?:ff|sp)|filt|hist|ptrk|s(?:cal|um)|trum)|tack|umtab)|t(?:ab(?:gen|leiw|map(?:(?:_i)?)|slice)|b(?:0_init|1(?:(?:(?:[012345])?)_init|[012345])|(?:[23456789])_init|[0123456789]))|vbap(?:16|(?:[48])move|[48])|xyin)\\b)(?:(\\:)([A-Za-z]))?",
429 | "captures": {
430 | "1": {
431 | "name": "support.function.csound"
432 | },
433 | "2": {
434 | "name": "invalid.deprecated.csound"
435 | },
436 | "3": {
437 | "name": "punctuation.type-annotation.csound"
438 | },
439 | "4": {
440 | "name": "type-annotation.storage.type.csound"
441 | }
442 | }
443 | },
444 | {
445 | "name": "variable.other.csound",
446 | "match": "\\b[A-Z_a-z]\\w*\\b"
447 | }
448 | ]
449 | },
450 | "preprocessorDirectives": {
451 | "patterns": [
452 | {
453 | "name": "keyword.preprocessor.csound",
454 | "match": "\\#(?:e(?:lse|nd(?:if)?)\\b|\\#\\#)|@+[ \\t]*\\d*"
455 | },
456 | {
457 | "begin": "\\#include",
458 | "end": "$",
459 | "beginCaptures": {
460 | "0": {
461 | "name": "keyword.include.preprocessor.csound"
462 | }
463 | },
464 | "patterns": [
465 | {
466 | "include": "#commentsAndMacroUses"
467 | },
468 | {
469 | "name": "string.include.csound",
470 | "begin": "([^ \\t])",
471 | "end": "\\1",
472 | "beginCaptures": {
473 | "0": {
474 | "name": "punctuation.definition.string.begin.csound"
475 | }
476 | },
477 | "endCaptures": {
478 | "0": {
479 | "name": "punctuation.definition.string.end.csound"
480 | }
481 | }
482 | }
483 | ]
484 | },
485 | {
486 | "begin": "\\#[ \\t]*define",
487 | "end": "(?<=^\\#)|(?<=[^\\\\]\\#)",
488 | "beginCaptures": {
489 | "0": {
490 | "name": "keyword.define.preprocessor.csound"
491 | }
492 | },
493 | "patterns": [
494 | {
495 | "include": "#commentsAndMacroUses"
496 | },
497 | {
498 | "include": "#macroNames"
499 | },
500 | {
501 | "begin": "\\(",
502 | "end": "\\)",
503 | "patterns": [
504 | {
505 | "name": "variable.parameter.preprocessor.csound",
506 | "match": "[A-Z_a-z]\\w*\\b"
507 | }
508 | ]
509 | },
510 | {
511 | "begin": "\\#",
512 | "end": "(?#~.]"
94 | },
95 | {
96 | "name": "string.quoted.csound-score",
97 | "begin": "\"",
98 | "end": "\"",
99 | "beginCaptures": {
100 | "0": {
101 | "name": "punctuation.definition.string.begin.csound-score"
102 | }
103 | },
104 | "endCaptures": {
105 | "0": {
106 | "name": "punctuation.definition.string.end.csound-score"
107 | }
108 | },
109 | "patterns": [
110 | {
111 | "include": "source.csound.orc#macroUses"
112 | }
113 | ]
114 | },
115 | {
116 | "name": "meta.braced-loop.csound-score",
117 | "begin": "\\{",
118 | "end": "\\}",
119 | "beginCaptures": {
120 | "0": {
121 | "name": "punctuation.braced-loop.begin.csound-score"
122 | }
123 | },
124 | "endCaptures": {
125 | "0": {
126 | "name": "punctuation.braced-loop.end.csound-score"
127 | }
128 | },
129 | "patterns": [
130 | {
131 | "name": "meta.braced-loop-details.csound-score",
132 | "begin": "\\G",
133 | "end": "$",
134 | "patterns": [
135 | {
136 | "begin": "\\d+",
137 | "end": "$",
138 | "beginCaptures": {
139 | "0": {
140 | "name": "constant.numeric.integer.decimal.csound-score"
141 | }
142 | },
143 | "patterns": [
144 | {
145 | "begin": "[A-Z_a-z]\\w*\\b",
146 | "end": "$",
147 | "beginCaptures": {
148 | "0": {
149 | "name": "entity.name.function.preprocessor.csound-score"
150 | }
151 | },
152 | "patterns": [
153 | {
154 | "include": "#comments"
155 | },
156 | {
157 | "name": "invalid.illegal.csound-score",
158 | "match": "\\S+"
159 | }
160 | ]
161 | },
162 | {
163 | "include": "#comments"
164 | },
165 | {
166 | "name": "invalid.illegal.csound-score",
167 | "match": "\\S+"
168 | }
169 | ]
170 | },
171 | {
172 | "include": "#comments"
173 | },
174 | {
175 | "name": "invalid.illegal.csound-score",
176 | "match": "\\S+"
177 | }
178 | ]
179 | },
180 | {
181 | "begin": "^",
182 | "end": "(?=\\})",
183 | "patterns": [
184 | {
185 | "include": "$self"
186 | }
187 | ]
188 | }
189 | ]
190 | }
191 | ]
192 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "ES2020",
5 | "lib": [
6 | "ES2020"
7 | ],
8 | "sourceMap": true,
9 | "rootDir": "src",
10 | "strict": true, /* enable all strict type-checking options */
11 | "resolveJsonModule": true,
12 | "esModuleInterop": true,
13 | /* Additional Checks */
14 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
15 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
16 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
17 | },
18 | "exclude": [
19 | "node_modules",
20 | ".vscode-test"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-string-throw": true,
4 | "no-unused-expression": true,
5 | "no-duplicate-variable": true,
6 | "curly": true,
7 | "class-name": true,
8 | "semicolon": [
9 | true,
10 | "always"
11 | ],
12 | "triple-equals": true
13 | },
14 | "defaultSeverity": "warning"
15 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | //@ts-check
2 |
3 | 'use strict';
4 |
5 | const path = require('path');
6 | const webpack = require('webpack');
7 |
8 | //@ts-check
9 | /** @typedef {import('webpack').Configuration} WebpackConfig **/
10 |
11 | /** @type WebpackConfig */
12 | const webExtensionConfig = {
13 | mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
14 | target: 'webworker', // extensions run in a webworker context
15 | entry: {
16 | 'extension': './src/web/extension.ts',
17 | 'test/suite/index': './src/web/test/suite/index.ts'
18 | },
19 | output: {
20 | filename: '[name].js',
21 | path: path.join(__dirname, './dist/web'),
22 | libraryTarget: 'commonjs',
23 | devtoolModuleFilenameTemplate: '../../[resource-path]'
24 | },
25 | resolve: {
26 | mainFields: ['browser', 'module', 'main'], // look for `browser` entry point in imported node modules
27 | extensions: ['.ts', '.js'], // support ts-files and js-files
28 | alias: {
29 | // provides alternate implementation for node module and source files
30 | },
31 | fallback: {
32 | // Webpack 5 no longer polyfills Node.js core modules automatically.
33 | // see https://webpack.js.org/configuration/resolve/#resolvefallback
34 | // for the list of Node.js core module polyfills.
35 | 'assert': require.resolve('assert')
36 | }
37 | },
38 | module: {
39 | rules: [{
40 | test: /\.ts$/,
41 | exclude: /node_modules/,
42 | use: [{
43 | loader: 'ts-loader'
44 | }]
45 | }]
46 | },
47 | plugins: [
48 | new webpack.ProvidePlugin({
49 | process: 'process/browser', // provide a shim for the global `process` variable
50 | }),
51 | ],
52 | externals: {
53 | 'vscode': 'commonjs vscode', // ignored because it doesn't exist
54 | },
55 | performance: {
56 | hints: false
57 | },
58 | devtool: 'nosources-source-map' // create a source map that points to the original source file
59 | };
60 |
61 |
62 | /** @type WebpackConfig */
63 | const extensionConfig = {
64 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
65 | mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
66 |
67 | entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
68 | output: {
69 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
70 | path: path.resolve(__dirname, 'dist'),
71 | filename: 'extension.js',
72 | libraryTarget: 'commonjs2'
73 | },
74 | externals: {
75 | vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
76 | // modules added here also need to be added in the .vsceignore file
77 | },
78 | resolve: {
79 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
80 | extensions: ['.ts', '.js']
81 | },
82 | module: {
83 | rules: [
84 | {
85 | test: /\.ts$/,
86 | exclude: /node_modules/,
87 | use: [
88 | {
89 | loader: 'ts-loader'
90 | }
91 | ]
92 | }
93 | ]
94 | },
95 | devtool: 'nosources-source-map'
96 | };
97 | module.exports = [ webExtensionConfig, extensionConfig ];
98 |
--------------------------------------------------------------------------------