├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── CI.yml
│ └── publish.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.yml
├── .vscode
└── settings.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── __tests__
├── index.js
└── package.json
├── data
└── documentation-data.yml
├── images
├── icon.png
├── play-arrow-with-logo.svg
├── play-arrow.svg
└── processing.png
├── jest.config.js
├── legacy
└── pde.tmLanguage.json
├── media
├── error.png
├── hover-1.png
└── hover-2.png
├── package.json
├── pde.configuration.json
├── rollup.config.js
├── rollup
└── plugins
│ ├── package.json
│ ├── src
│ ├── index.ts
│ ├── json-and-yaml.ts
│ └── types.ts
│ └── tsconfig.json
├── scripts
├── checkDocs.mjs
├── helpers
│ └── fetchDocs.mjs
└── writeDocs.mjs
├── snippets
└── snippets.json
├── src
├── commands
│ ├── index.ts
│ ├── run.ts
│ └── search.ts
├── config.ts
├── diagnostics.ts
├── documentation-data.yml
├── documentation.ts
├── env.d.ts
├── index.ts
├── types.d.ts
├── utils
│ ├── escapePath.ts
│ ├── index.ts
│ └── search.ts
└── validateCommand.ts
├── syntaxes
└── pde.tmLanguage.json
├── tsconfig.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 4
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.{json,html,yml,yaml,css,scss}]
13 | indent_style = space
14 | indent_size = 2
15 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | */node_modules/
2 | /src/serviceWorker.ts
3 | lint
4 | start
5 | lib
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | function* range(min, max) {
2 | for (let num = min; num < max; num++) {
3 | yield num
4 | }
5 | }
6 |
7 | module.exports = {
8 | env: {
9 | es2021: true,
10 | node: true,
11 | },
12 | extends: ["eslint:recommended", "plugin:@typescript-eslint/eslint-recommended"],
13 | parser: "@typescript-eslint/parser",
14 | globals: {
15 | Atomics: "readonly",
16 | SharedArrayBuffer: "readonly",
17 | },
18 | parserOptions: {
19 | ecmaVersion: 2021,
20 | sourceType: "module",
21 | project: ["./tsconfig.json"],
22 | },
23 | plugins: ["@typescript-eslint", "prefer-arrow"],
24 | rules: {
25 | // General ESLint rules
26 | "arrow-body-style": ["warn", "as-needed"],
27 | "default-case-last": "warn",
28 | "dot-location": ["warn", "property"],
29 | eqeqeq: "error",
30 | "id-length": ["error", {exceptions: ["_", "$"]}],
31 | "max-len": "off",
32 | "max-lines": ["warn", 500],
33 | "max-statements": ["warn", {max: 25}],
34 | "no-else-return": "warn",
35 | "no-empty": ["warn", {allowEmptyCatch: true}],
36 | "no-extra-semi": "off",
37 | "no-negated-condition": "warn",
38 | "no-nested-ternary": "warn",
39 | "no-unused-vars": "off",
40 | "no-var": "warn",
41 | "object-shorthand": "warn",
42 | "one-var": ["warn", "never"],
43 | "padding-line-between-statements": [
44 | "warn",
45 | {blankLine: "always", prev: "*", next: "return"},
46 | {blankLine: "always", prev: ["const", "let", "var"], next: "*"},
47 | {blankLine: "any", prev: ["const", "let", "var"], next: ["const", "let", "var"]},
48 | {blankLine: "always", prev: "function", next: "*"},
49 | ],
50 | "prefer-const": "warn",
51 | "prefer-destructuring": [
52 | "error",
53 | {
54 | array: false,
55 | object: true,
56 | },
57 | ],
58 | "prefer-exponentiation-operator": "warn",
59 | "prefer-object-spread": "warn",
60 | "prefer-template": "warn",
61 | "require-await": "warn",
62 | "require-unicode-regexp": "warn",
63 | "sort-imports": ["warn"],
64 |
65 | // Typescript Rules
66 | "@typescript-eslint/array-type": "warn",
67 | "@typescript-eslint/consistent-indexed-object-style": ["warn", "index-signature"],
68 | "@typescript-eslint/consistent-type-assertions": ["warn", {assertionStyle: "as"}],
69 | "@typescript-eslint/member-ordering": "warn",
70 | "@typescript-eslint/naming-convention": [
71 | "error",
72 | {
73 | selector: "default",
74 | format: ["camelCase"],
75 | },
76 | {
77 | selector: "variableLike",
78 | format: ["camelCase"],
79 | leadingUnderscore: "allow",
80 | },
81 | {
82 | selector: "memberLike",
83 | modifiers: ["private"],
84 | format: ["camelCase"],
85 | leadingUnderscore: "require",
86 | },
87 | {
88 | selector: "property",
89 | modifiers: ["private"],
90 | format: ["camelCase"],
91 | leadingUnderscore: "require",
92 | },
93 | {
94 | selector: "typeLike",
95 | format: ["PascalCase"],
96 | },
97 | {
98 | selector: "variable",
99 | types: ["boolean"],
100 | format: ["PascalCase"],
101 | prefix: ["is", "should", "has", "can", "did", "will"],
102 | },
103 | {
104 | selector: "parameter",
105 | format: ["camelCase"],
106 | leadingUnderscore: "allow",
107 | },
108 | {
109 | selector: "property",
110 | format: ["camelCase", "PascalCase", "snake_case", "UPPER_CASE"],
111 | },
112 | {
113 | selector: "enumMember",
114 | format: ["camelCase", "PascalCase", "snake_case", "UPPER_CASE"],
115 | },
116 | ],
117 | "@typescript-eslint/no-magic-numbers": [
118 | "warn",
119 | {
120 | ignoreEnums: true,
121 | ignoreNumericLiteralTypes: true,
122 | ignoreReadonlyClassProperties: true,
123 | ignoreArrayIndexes: true,
124 | ignore: [...Array.from(range(-10, 11)), 16, 32, 64, 128, 256, 512],
125 | },
126 | ],
127 | "@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
128 | "@typescript-eslint/prefer-for-of": "warn",
129 | "@typescript-eslint/prefer-function-type": "warn",
130 | "@typescript-eslint/prefer-optional-chain": "warn",
131 |
132 | // Typescript extension rules
133 | "@typescript-eslint/default-param-last": "warn",
134 | "@typescript-eslint/dot-notation": "warn",
135 | "@typescript-eslint/lines-between-class-members": ["warn", "always"],
136 | "@typescript-eslint/no-dupe-class-members": "warn",
137 | "@typescript-eslint/no-duplicate-imports": "warn",
138 | "@typescript-eslint/no-extra-semi": "off",
139 | "@typescript-eslint/no-shadow": "warn",
140 | "@typescript-eslint/no-unused-expressions": "warn",
141 | "@typescript-eslint/no-unused-vars": "off",
142 | "@typescript-eslint/no-unused-vars-experimental": "warn",
143 | "@typescript-eslint/no-use-before-define": "warn",
144 |
145 | // Preter arrow rules
146 | "prefer-arrow-callback": "warn",
147 | "prefer-arrow/prefer-arrow-functions": [
148 | "warn",
149 | {
150 | disallowPrototype: true,
151 | singleReturnOnly: false,
152 | classPropertiesAllowed: true,
153 | allowStandaloneDeclarations: false,
154 | },
155 | ],
156 | },
157 | }
158 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Enforce Unix newlines
2 | * text=auto eol=lf
3 |
4 | # Don't diff or textually merge documentation data
5 | data/documentation-data.yml binary
6 |
7 | .eslintrc.js linguist-detectable=false
8 | rollup.config.js linguist-detectable=false
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG] "
5 | labels: ""
6 | assignees: ""
7 | ---
8 |
9 | **Describe the bug**
10 | A clear and concise description of what the bug is.
11 |
12 | **To Reproduce**
13 | Steps to reproduce the behavior:
14 |
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **VSCode (please complete the following information):**
27 |
28 | - OS: [e.g. iOS8.1]
29 | - Version [e.g. 22]
30 |
31 | **Additional context**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE] "
5 | labels: ""
6 | assignees: ""
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11 |
12 | **Describe the solution you'd like**
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered**
16 | A clear and concise description of any alternative solutions or features you've considered.
17 |
18 | **Additional context**
19 | Add any other context or screenshots about the feature request here.
20 |
--------------------------------------------------------------------------------
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | name: build
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v2
12 | - uses: actions/setup-node@v1
13 | with:
14 | node-version: "14.x"
15 | registry-url: "https://registry.npmjs.org"
16 |
17 | - name: install deps
18 | run: yarn install --frozen-lockfile
19 |
20 | - name: build
21 | run: yarn workspaces run tsc
22 |
23 | - name: lint
24 | run: yarn lint
25 |
26 | - name: check with prettier
27 | run: yarn prettier . --check
28 |
29 | - name: test
30 | run: yarn test
31 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish to release
2 | on:
3 | release:
4 | types: [published]
5 |
6 | jobs:
7 | publish:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | - uses: actions/setup-node@v1
12 | with:
13 | node-version: "14.x"
14 | registry-url: "https://registry.npmjs.org"
15 |
16 | - name: install deps
17 | run: yarn install --frozen-lockfile
18 |
19 | - name: build plugins
20 | run: yarn workspace rollup-plugins run build
21 |
22 | - name: build
23 | run: yarn vsce package
24 |
25 | - name: Release
26 | uses: softprops/action-gh-release@v1
27 | with:
28 | files: ./processing-vscode-*.vsix
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 |
32 | - name: Publish to marketplace
33 | uses: lannonbr/vsce-action@master
34 | with:
35 | args: "publish -p $PUBLISH_TOKEN"
36 | env:
37 | PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | *.log
4 | .idea
5 | *.vsix
6 | lib
7 | processing-vscode.js
8 | .eslintcache
9 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | data/*
2 | src/*.yml
3 | */node_modules/
4 | build
5 | .serverless
6 | .vscode
7 | lib/
8 | tsconfig*.json
9 | legacy
10 | processing-vscode.js
11 | pnpm-lock.yaml
12 |
--------------------------------------------------------------------------------
/.prettierrc.yml:
--------------------------------------------------------------------------------
1 | # Normal Options
2 | arrowParens: "always"
3 | bracketSpacing: false
4 | embeddedLanguageFormatting: "auto"
5 | endOfLine: "lf"
6 | htmlWhitespaceSensitivity: "strict"
7 | jsxBracketSameLine: false
8 | jsxSingleQuote: false
9 | printWidth: 99
10 | quoteProps: "as-needed"
11 | semi: false
12 | singleQuote: false
13 | tabWidth: 4
14 | trailingComma: "all"
15 | useTabs: false
16 |
17 | # JSDoc plugin
18 | jsdocSpaces: 1
19 | jsdocDescriptionWithDot: false
20 | jsdocDescriptionTag: false
21 | jsdocVerticalAlignment: false
22 | jsdocKeepUnParseAbleExampleIndent: false
23 | jsdocSingleLineComment: false
24 | tsdoc: true
25 |
26 | plugins:
27 | - ./node_modules/prettier-plugin-jsdoc
28 | - ./node_modules/prettier-plugin-package
29 |
30 | overrides:
31 | - files:
32 | - "*.html"
33 | - "*.yml"
34 | - "*.yaml"
35 | - "*.json"
36 | - "*.css"
37 | - "*.scss"
38 | options:
39 | tabWidth: 2
40 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.exclude": {
3 | "out": false // set this to true to hide the "out" folder with the compiled JS files
4 | },
5 | "search.exclude": {
6 | "out": true // set this to false to include "out" folder in search results
7 | },
8 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
9 | "[typescript]": {
10 | "editor.defaultFormatter": "esbenp.prettier-vscode",
11 | "editor.formatOnSave": true,
12 | },
13 | "[json]": {
14 | "editor.defaultFormatter": "esbenp.prettier-vscode"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | *.log
2 |
3 | .github
4 | .vscode/
5 | data/
6 | legacy/
7 | media/
8 | node_modules/**
9 | rollup/
10 | scripts/
11 | src/
12 | .editorconfig
13 | .eslintcache
14 | .eslintignore
15 | .eslintrc.js
16 | .gitattributes
17 | .gitignore
18 | .prettierignore
19 | .prettierrc.yml
20 | .vscodeignore
21 | pnpm-lock.yaml
22 | pnpm-workspace.yaml
23 | rollup.config.js
24 | tsconfig.json
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [2.4.1] - 2021-12-17
9 |
10 | ### Added
11 |
12 | - feat: accomidate for legacy `processing.path` conig option
13 |
14 | ### Fixed
15 |
16 | - fix: escape spaces in executable path
17 |
18 | ## [2.4.0] - 2021-07-10
19 |
20 | ### Added
21 |
22 | - feat(snippets): add snippets for circle() and square()
23 |
24 | ## [2.3.0] - 2021-05-27
25 |
26 | ### Added
27 |
28 | - feat(py): add config option processing.py.isEnabled
29 | - feat(search): directly search processing reference if possible
30 | - feat(search): add py.processing.org search
31 |
32 | ### Changed
33 |
34 | - fix: add extra restrictions to commands
35 |
36 | ## [2.2.0] - 2021-05-21
37 |
38 | ### Added
39 |
40 | - feat: add python run button
41 |
42 | ### Changed
43 |
44 | - fix(docs): trim documentation hover data
45 | - fix: don't show hover docs on single line comments
46 |
47 | ## [2.1.0] - 2021-05-02
48 |
49 | ### Added
50 |
51 | - feat: add `runPathQuote` option
52 |
53 | ### Changed
54 |
55 | - ! diagnostics are opt-out by default
56 |
57 | ### Fixed
58 |
59 | - fix: quote windows path names
60 |
61 | ## [2.0.6] - 2021-03-19
62 |
63 | ### Fixed
64 |
65 | - Make valid project names case insensitive
66 |
67 | ## [2.0.5] - 2020-03-19
68 |
69 | ### Fixed
70 |
71 | - Handle paths with spaces better
72 |
73 | ## [2.0.4] - 2020-03-18
74 |
75 | ### Fixed
76 |
77 | - Added quotes around run command to allow for whitespaced paths [#1](https://github.com/Luke-zhang-04/processing-vscode/pull/1)
78 |
79 | ## [2.0.3] - 2021-03-01
80 |
81 | Even more changes to README
82 |
83 | ## [2.0.2] - 2021-03-01
84 |
85 | More changes to README
86 |
87 | ## [2.0.1] - 2021-03-01
88 |
89 | Only some changes to README and CI
90 |
91 | ### Changed
92 |
93 | - made the run button a lighter green
94 |
95 | ## [2.0.0] - 2021-03-01
96 |
97 | ### Added
98 |
99 | - feat: add documentation on hover for Processing Buildtins
100 | - feat: add diagnostics from the `processing-java` CLI
101 | - feat: add a run button to the editor menu
102 | - feat: add quotes to `autoClosingPairs` and `surroundingPairs`
103 |
104 | ### Changed
105 |
106 | - changed configuration `processing.path` to `processing.processingPath`
107 | - changed language configuration
108 | - changed the langauge grammar to Red Hat's [Java Grammar](https://github.com/redhat-developer/vscode-java/blob/master/syntaxes/java.tmLanguage.json)
109 |
110 | ### Removed
111 |
112 | - removed the task file feature in favour of a run button
113 |
114 | ## [1.4.6] - 2020-09-03
115 |
116 | ### Fixed
117 |
118 | - Updated markdown files
119 |
120 | ## [1.4.5] - 2020-09-03
121 |
122 | ### Fixed
123 |
124 | - Updated packages
125 |
126 | ### Changed
127 |
128 | - Using GitHub Actions instead of Travis
129 |
130 | ## [1.4.4] - 2020-08-25
131 |
132 | ### Added
133 |
134 | Can now use DuckDuckGo or Google to search. Thanks to [@atnbueno](https://github.com/atnbueno)
135 |
136 | ## [1.4.3] - 2020-08-25
137 |
138 | ### Fixed
139 |
140 | Merged in bugfix PRs from [@hysysk](https://github.com/hysysk) and [@atnbueno](https://github.com/atnbueno)
141 |
142 | Updated dependencies
143 |
144 | ## [1.4.1] - 2019-12-23
145 |
146 | ### Fixed
147 |
148 | Improved snippets.json thanks to work from [@jerrylususu](https://github.com/jerrylususu)
149 |
150 | Fixed Windows on Bash path issue thanks to [@micuat](https://github.com/micuat)
151 |
152 | ## [1.4.0] - 2019-08-30
153 |
154 | ### Fixed
155 |
156 | Updated tests from latest template to fix automatic builds.
157 |
158 | ### Added
159 |
160 | Users can now choose between processing.org's documentation and p5js
161 |
162 | Thanks to [@brianmcfadden](https://github.com/brianmcfadden)
163 |
164 | ## [1.3.1] - 2019-06-05
165 |
166 | ### Fixed
167 |
168 | - Updated NPM packages
169 |
170 | ## [1.3] - 2019-02-06
171 |
172 | ### Removed
173 |
174 | - Removed the opn requirement, using new internal open external API
175 |
176 | ### Fixed
177 |
178 | - Updated package.json requirements
179 |
180 | ## [1.2.2] - 2018-07-25
181 |
182 | ### Added
183 |
184 | - Added path setting
185 |
186 | ## [1.1.0] - 2018-05-09
187 |
188 | ### Added
189 |
190 | - Added documentation search
191 |
192 | ### Fixed
193 |
194 | - Changed extension namespace to processing (from "extension")
195 |
196 | ## [1.0.0] - 2018-05-09
197 |
198 | ### Added
199 |
200 | - Added Changelog
201 | - Support for multi root workplaces
202 |
203 | ### Fixed
204 |
205 | - Updated dependencies and deploy scripts
206 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 - 2020 Tobiah Zarlez, 2021 Luke Zhang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Processing for Visual Studio Code
4 |
5 | [](https://marketplace.visualstudio.com/items?itemName=Luke-zhang-04.processing-vscode)
6 |
7 | [](https://marketplace.visualstudio.com/items?itemName=Luke-zhang-04.processing-vscode)
8 | [](https://marketplace.visualstudio.com/items?itemName=Luke-zhang-04.processing-vscode)
9 | [](https://github.com/Luke-zhang-04/processing-vscode/actions)
10 | [](./LICENSE)
11 | 
12 | [](https://snyk.io/test/github/Luke-zhang-04/processing-vscode)
13 |
14 | Note on Processing 4: I'm not sure how this extension will handle Processing 4. I will wait for it to be out of beta and fix the extension if needed.
15 |
16 | ## Contents
17 |
18 | - [What this extension is](#what-this-extension-is)
19 | - [What this extension isn't](#what-this-extension-isnt)
20 | - [Why the fork?](#why-the-fork)
21 | - [Screenshots](#screenshots)
22 | - [Feature list](#feature-list)
23 | - [Syntax Highlighting](#syntax-highlighting)
24 | - [Snippets](#snippets)
25 | - [Documentation on Hover](#documentation-on-hover)
26 | - [Commands](#commands)
27 | - [Using task files](#using-task-files)
28 | - [Processing Python](#processing-python)
29 | - [Credits](#credits)
30 |
31 | ## What this extension is
32 |
33 | This is a [fork of a Visual Studio Code extension created by Tobiah Zarlez](https://github.com/TobiahZ/processing-vscode) to add [Processing](https://processing.org/) language support, with added documentation on hover, diagnostics, and more.
34 |
35 | ## What this extension isn't
36 |
37 | - This extension does not allow you to debug Java or Processing projects.
38 | - This is **NOT a language server**, and hence cannot provide the features a language server can. There simply is not enough demand for a Processing language server, and that type of thing is definitely out of the scope of my abilities. Language servers take entire teams from big companies such as Microsoft to make.
39 | - This extension cannot provide IntelliSense, for example
40 |
41 | ## Why the fork?
42 |
43 | The [original extension](https://github.com/TobiahZ/processing-vscode) was missing some features that I wanted and it seemed as if the repo was no longer being maintained. So, forked the extension and changed some things.
44 |
45 | - Better syntax highlighting (from [Red Hat Java](https://github.com/redhat-developer/vscode-java/blob/master/syntaxes/java.tmLanguage.json))
46 | - Documentation on hover (via Regex)
47 | - A run button (both Processing Java and Processing Python)
48 | - Simple diagnostics (via the processing-java CLI, which can be extremely slow, and is disabled by default)
49 | - Strings are auto closing and surrounding (didn't work in the old extension)
50 |
51 | See the [CHANGELOG](https://github.com/Luke-zhang-04/processing-vscode/blob/main/CHANGELOG.md) for all changes
52 |
53 | ## Screenshots
54 |
55 | 
56 |
57 |
58 | More Screenshots
59 |
60 | 
61 | 
62 |
63 |
64 |
65 | ## Feature list
66 |
67 | ### Syntax highlighting
68 |
69 | Open any .pde file, or choose "Processing" from the drop down menu in the bottom right corner. Syntax highlighting is from [Red Hat's Java extension](https://github.com/redhat-developer/vscode-java/blob/master/syntaxes/java.tmLanguage.json).
70 |
71 | ### Snippets
72 |
73 | Once the language has been set, you will see code snippets pop up automatically as you type!
74 |
75 | ### Documentation on hover
76 |
77 | When you hover over a function such as `square`, documentation for this function will appear! Documentation is scraped directly from the [Processing reference page](https://processing.org/reference/), so anything missing from there will be missing here too.
78 |
79 | ### Commands
80 |
81 | Installing this extension will add the following commands to your command pallette (`CTRL+SHIFT+P`, or opened by `View -> Command Pallette`). These commands can be selected and run from there, to complete the corresponding tasks.
82 |
83 | - Open Extension Documentation
84 | - Opens this documentation.
85 | - Open Documentation for Selection
86 | - Use the pallet command "Processing: Open Documentation for Selection" to open the processing documentation for the current selection.
87 | - By default uses processing.org's documentation. Can change to p5js's if preferred using the `processing.docs` setting.
88 | - Run
89 | - Runs the current Processing project (from current working directory). Will automatically detect if the project is Processing Java or Python.
90 | - If the setting `processing.shouldSendSigint` is set to `true`, run will interrupt the current running processing program before running the new one.
91 | - RunJava
92 | - Runs the current Processing Java project (from CWD)
93 | - RunPy
94 | - Runs the current Processing Python project (from CWD)
95 | - Search Processing Website
96 | - Use the pallet command "Processing: Search Processing Website" to quickly search whatever you want on the processing website.
97 | - By default uses Google for search. Can change to DuckDuckGo if preferred using the `processing.search` setting.
98 |
99 | ## Using Task Files
100 |
101 | The [original extension](https://github.com/TobiahZ/processing-vscode) made use of a [tasks.json](https://github.com/TobiahZ/processing-vscode/blob/b98d44b095b303f7f66017c632b17e47fa00dfcd/ProcessingTasks.json) file to run processing projects. This has been replaced with the run command and run button (processing.Run). You can bind this command to a keybinding.
102 |
103 | Alternatively, if you prefer the `tasks.json` file, you can continue to use it, but the `command` field should be changed to `"${config:processing.path}"`.
104 |
105 | ## Processing Python
106 |
107 | This extension attempts to make Processing with Python easier to use. Follow these steps:
108 |
109 | 1. Download the [processing-python library](https://py.processing.org/tutorials/command-line/#requirements) for your operating system
110 | - Take note of the location of this file. For example, I might store mine in `~/processing.py-linux64/processing.py-3056-linux64/processing-py.jar`
111 | 2. Download the proper [Java version](https://py.processing.org/tutorials/command-line/#requirements) for your operating system
112 | - Follow the steps in the [Processing docs](https://py.processing.org/tutorials/command-line/#requirements)
113 | 3. Configure the extension
114 | - Change the following configuration options
115 | - `processing.py.jarPath`: the path to your `processing-py.jar` file. Preferably, this is an absolute path. In this example, it will be `~/processing.py-linux64/processing.py-3056-linux64/processing-py.jar`
116 | - `processing.py.javaPath`: the path to your `java` executable. For example, `/usr/bin/java`
117 | - Make sure `processing.py.isEnabled` is set to `true` (true by default)
118 | 4. Downloads stub definitions (optional)
119 | - Definitions can be found [here](https://github.com/Abdulla060/Processing.py-intellisense/blob/master/lib/Processing3.pyi)
120 | - After than, follow the imports in [this example](https://github.com/Abdulla060/Processing.py-intellisense/blob/master/Example.py)
121 |
122 | ## Credits
123 |
124 | - Snippets are based on the [Processing Sublime Text plugin](https://github.com/b-g/processing-sublime).
125 | - Syntax highlighting is based on the [VSCode Java grammar](https://github.com/microsoft/vscode/blob/main/extensions/java/syntaxes/java.tmLanguage.json)
126 | - Thanks to [Tobiah Zarlez](https://github.com/TobiahZ) for making the [original extension](https://github.com/TobiahZ/processing-vscode)
127 |
128 | ## Development
129 |
130 | - Run `yarn vsce package`
131 | - Run `code --install-extension processing-vscode-.vsix`
132 |
--------------------------------------------------------------------------------
/__tests__/index.js:
--------------------------------------------------------------------------------
1 | import {escapeExecutablePath} from "../src/utils/escapePath"
2 |
3 | describe("test path escape", () => {
4 | it("should escape Windows path with space", () => {
5 | const originalPath = "C:\\Program Files\\processing\\processing-java"
6 |
7 | expect(escapeExecutablePath(originalPath)).toBe(
8 | "C:\\Program` Files\\processing\\processing-java",
9 | )
10 | })
11 |
12 | it("should escape Unix path with space", () => {
13 | const originalPath = "/usr/bin/something else/processing-java"
14 |
15 | expect(escapeExecutablePath(originalPath)).toBe(
16 | "/usr/bin/something\\ else/processing-java",
17 | )
18 | })
19 |
20 | it("should leave Windows path without spaces as is", () => {
21 | const originalPath = ".\\processing\\processing-java"
22 |
23 | expect(escapeExecutablePath(originalPath)).toBe(".\\processing\\processing-java")
24 | })
25 |
26 | it("should leave Unix path without spaces as is", () => {
27 | const originalPath = "/usr/bin/processing-java"
28 |
29 | expect(escapeExecutablePath(originalPath)).toBe("/usr/bin/processing-java")
30 | })
31 |
32 | it("should not escape already escaped spaces on Windows", () => {
33 | const originalPath = "C:\\Program` Files\\processing\\processing java"
34 |
35 | expect(escapeExecutablePath(originalPath)).toBe(
36 | "C:\\Program` Files\\processing\\processing` java",
37 | )
38 | })
39 |
40 | it("should not escape already escaped spaces on Unix", () => {
41 | const originalPath = "/usr/bin/something else/processing\\ java"
42 |
43 | expect(escapeExecutablePath(originalPath)).toBe(
44 | "/usr/bin/something\\ else/processing\\ java",
45 | )
46 | })
47 |
48 | it("should detect platform if no path seperators available", () => {
49 | const originalPath = "processing java"
50 |
51 | if (process.platform === "win32") {
52 | expect(escapeExecutablePath(originalPath)).toBe("processing` java")
53 | } else {
54 | expect(escapeExecutablePath(originalPath)).toBe("processing\\ java")
55 | }
56 | })
57 |
58 | it("should leave single path as is", () => {
59 | const originalPath = "processing-java"
60 |
61 | expect(escapeExecutablePath(originalPath)).toBe("processing-java")
62 | })
63 | })
64 |
--------------------------------------------------------------------------------
/__tests__/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module"
3 | }
4 |
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Luke-zhang-04/processing-vscode/c116f535868f409d0f40fd16440201c597dbbaa0/images/icon.png
--------------------------------------------------------------------------------
/images/play-arrow-with-logo.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/images/play-arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/images/processing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Luke-zhang-04/processing-vscode/c116f535868f409d0f40fd16440201c597dbbaa0/images/processing.png
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {import("ts-jest/dist/types").InitialOptionsTsJest}
3 | */
4 | module.exports = {
5 | preset: "ts-jest",
6 | testEnvironment: "node",
7 | }
8 |
--------------------------------------------------------------------------------
/legacy/pde.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "fileTypes": [
3 | "pde",
4 | "java"
5 | ],
6 | "foldingStartMarker": "(\\{\\s*(//.*)?$|^\\s*// \\{\\{\\{)",
7 | "foldingStopMarker": "^\\s*(\\}|// \\}\\}\\}$)",
8 | "name": "Processing",
9 | "patterns": [
10 | {
11 | "captures": {
12 | "1": {
13 | "name": "keyword.other.package.java"
14 | },
15 | "2": {
16 | "name": "storage.modifier.package.java"
17 | },
18 | "3": {
19 | "name": "punctuation.terminator.java"
20 | }
21 | },
22 | "match": "^\\s*(package)\\b(?:\\s*([^ ;$]+)\\s*(;)?)?",
23 | "name": "meta.package.java"
24 | },
25 | {
26 | "captures": {
27 | "1": {
28 | "name": "keyword.other.import.processing"
29 | },
30 | "2": {
31 | "name": "storage.modifier.import.processing"
32 | },
33 | "3": {
34 | "name": "punctuation.terminator.processing"
35 | }
36 | },
37 | "match": "^\\s*(import)\\b(?:\\s*([^ ;$]+)\\s*(;)?)?",
38 | "name": "meta.import.processing"
39 | },
40 | {
41 | "include": "#class-body"
42 | }
43 | ],
44 | "repository": {
45 | "all-types": {
46 | "patterns": [
47 | {
48 | "include": "#simple-arrays"
49 | },
50 | {
51 | "include": "#simple-types"
52 | },
53 | {
54 | "include": "#object-types"
55 | }
56 | ]
57 | },
58 | "annotations": {
59 | "patterns": [
60 | {
61 | "begin": "(@[^ (]+)(\\()",
62 | "beginCaptures": {
63 | "1": {
64 | "name": "storage.type.annotation.processing"
65 | },
66 | "2": {
67 | "name": "punctuation.definition.annotation-arguments.begin.processing"
68 | }
69 | },
70 | "end": "(\\))",
71 | "endCaptures": {
72 | "1": {
73 | "name": "punctuation.definition.annotation-arguments.end.processing"
74 | }
75 | },
76 | "name": "meta.declaration.annotation.processing",
77 | "patterns": [
78 | {
79 | "captures": {
80 | "1": {
81 | "name": "constant.other.key.processing"
82 | },
83 | "2": {
84 | "name": "keyword.operator.assignment.processing"
85 | }
86 | },
87 | "match": "(\\w*)\\s*(=)"
88 | },
89 | {
90 | "include": "#code"
91 | },
92 | {
93 | "match": ",",
94 | "name": "punctuation.seperator.property.processing"
95 | }
96 | ]
97 | },
98 | {
99 | "match": "@\\w*",
100 | "name": "storage.type.annotation.processing"
101 | }
102 | ]
103 | },
104 | "anonymous-classes-and-new": {
105 | "begin": "\\bnew\\b",
106 | "beginCaptures": {
107 | "0": {
108 | "name": "keyword.control.new.processing"
109 | }
110 | },
111 | "end": "(?<=\\)|\\])(?!\\s*{)|(?<=})|(?=;)",
112 | "patterns": [
113 | {
114 | "begin": "(\\w+)\\s*(?=\\[)",
115 | "beginCaptures": {
116 | "1": {
117 | "name": "storage.type.processing"
118 | }
119 | },
120 | "end": "}|(?=;|\\))",
121 | "patterns": [
122 | {
123 | "begin": "\\[",
124 | "end": "\\]",
125 | "patterns": [
126 | {
127 | "include": "#inner-code"
128 | }
129 | ]
130 | },
131 | {
132 | "begin": "{",
133 | "end": "(?=})",
134 | "patterns": [
135 | {
136 | "include": "#code"
137 | }
138 | ]
139 | }
140 | ]
141 | },
142 | {
143 | "begin": "(?=\\w.*\\()",
144 | "end": "(?<=\\))",
145 | "patterns": [
146 | {
147 | "include": "#object-types"
148 | },
149 | {
150 | "begin": "\\(",
151 | "beginCaptures": {
152 | "1": {
153 | "name": "storage.type.processing"
154 | }
155 | },
156 | "end": "\\)",
157 | "patterns": [
158 | {
159 | "include": "#inner-code"
160 | }
161 | ]
162 | }
163 | ]
164 | },
165 | {
166 | "begin": "{",
167 | "end": "}",
168 | "name": "meta.inner-class.processing",
169 | "patterns": [
170 | {
171 | "include": "#class-body"
172 | }
173 | ]
174 | }
175 | ]
176 | },
177 | "assertions": {
178 | "patterns": [
179 | {
180 | "begin": "\\b(assert)\\s",
181 | "beginCaptures": {
182 | "1": {
183 | "name": "keyword.control.assert.processing"
184 | }
185 | },
186 | "end": "$",
187 | "name": "meta.declaration.assertion.processing",
188 | "patterns": [
189 | {
190 | "match": ":",
191 | "name": "keyword.operator.assert.expression-seperator.processing"
192 | },
193 | {
194 | "include": "#code"
195 | }
196 | ]
197 | }
198 | ]
199 | },
200 | "class": {
201 | "begin": "(?=\\w?[\\w\\s]*(?:class|(?:@)?interface)\\s+\\w+)",
202 | "end": "}",
203 | "endCaptures": {
204 | "0": {
205 | "name": "punctuation.section.class.end.processing"
206 | }
207 | },
208 | "name": "meta.class.processing",
209 | "patterns": [
210 | {
211 | "include": "#storage-modifiers"
212 | },
213 | {
214 | "include": "#comments"
215 | },
216 | {
217 | "captures": {
218 | "1": {
219 | "name": "storage.modifier.processing"
220 | },
221 | "2": {
222 | "name": "entity.name.type.class.processing"
223 | }
224 | },
225 | "match": "(class|(?:@)?interface)\\s+(\\w+)",
226 | "name": "meta.class.identifier.processing"
227 | },
228 | {
229 | "begin": "extends",
230 | "beginCaptures": {
231 | "0": {
232 | "name": "storage.modifier.extends.processing"
233 | }
234 | },
235 | "end": "(?={|implements)",
236 | "name": "meta.definition.class.inherited.classes.processing",
237 | "patterns": [
238 | {
239 | "include": "#object-types-inherited"
240 | },
241 | {
242 | "include": "#comments"
243 | }
244 | ]
245 | },
246 | {
247 | "begin": "(implements)\\s",
248 | "beginCaptures": {
249 | "1": {
250 | "name": "storage.modifier.implements.processing"
251 | }
252 | },
253 | "end": "(?=\\s*extends|\\{)",
254 | "name": "meta.definition.class.implemented.interfaces.processing",
255 | "patterns": [
256 | {
257 | "include": "#object-types-inherited"
258 | },
259 | {
260 | "include": "#comments"
261 | }
262 | ]
263 | },
264 | {
265 | "begin": "{",
266 | "end": "(?=})",
267 | "name": "meta.class.body.processing",
268 | "patterns": [
269 | {
270 | "include": "#class-body"
271 | }
272 | ]
273 | }
274 | ]
275 | },
276 | "enum": {
277 | "begin": "(?=\\w?[\\w\\s]*(?:enum)\\s+\\w+)",
278 | "end": "}",
279 | "endCaptures": {
280 | "0": {
281 | "name": "punctuation.section.class.end.processing"
282 | }
283 | },
284 | "name": "meta.class.processing",
285 | "patterns": [
286 | {
287 | "include": "#storage-modifiers"
288 | },
289 | {
290 | "include": "#comments"
291 | },
292 | {
293 | "captures": {
294 | "1": {
295 | "name": "storage.modifier.processing"
296 | },
297 | "2": {
298 | "name": "entity.name.type.class.processing"
299 | }
300 | },
301 | "match": "(enum)\\s+(\\w+)",
302 | "name": "meta.class.identifier.processing"
303 | },
304 | {
305 | "begin": "extends",
306 | "beginCaptures": {
307 | "0": {
308 | "name": "storage.modifier.extends.processing"
309 | }
310 | },
311 | "end": "(?={|implements)",
312 | "name": "meta.definition.class.inherited.classes.processing",
313 | "patterns": [
314 | {
315 | "include": "#object-types-inherited"
316 | },
317 | {
318 | "include": "#comments"
319 | }
320 | ]
321 | },
322 | {
323 | "begin": "(implements)\\s",
324 | "beginCaptures": {
325 | "1": {
326 | "name": "storage.modifier.implements.processing"
327 | }
328 | },
329 | "end": "(?=\\s*extends|\\{)",
330 | "name": "meta.definition.class.implemented.interfaces.processing",
331 | "patterns": [
332 | {
333 | "include": "#object-types-inherited"
334 | },
335 | {
336 | "include": "#comments"
337 | }
338 | ]
339 | },
340 | {
341 | "begin": "{",
342 | "end": "(?=})",
343 | "name": "meta.class.body.processing",
344 | "patterns": [
345 | {
346 | "include": "#enum-body"
347 | }
348 | ]
349 | }
350 | ]
351 | },
352 | "class-body": {
353 | "patterns": [
354 | {
355 | "include": "#comments"
356 | },
357 | {
358 | "include": "#class"
359 | },
360 | {
361 | "include": "#enum"
362 | },
363 | {
364 | "include": "#methods"
365 | },
366 | {
367 | "include": "#annotations"
368 | },
369 | {
370 | "include": "#storage-modifiers"
371 | },
372 | {
373 | "include": "#code"
374 | }
375 | ]
376 | },
377 | "enum-body": {
378 | "patterns": [
379 | {
380 | "include": "#comments"
381 | },
382 | {
383 | "include": "#class"
384 | },
385 | {
386 | "include": "#enum"
387 | },
388 | {
389 | "include": "#enums"
390 | },
391 | {
392 | "include": "#methods"
393 | },
394 | {
395 | "include": "#annotations"
396 | },
397 | {
398 | "include": "#storage-modifiers"
399 | },
400 | {
401 | "include": "#code"
402 | }
403 | ]
404 | },
405 | "code": {
406 | "patterns": [
407 | {
408 | "include": "#comments"
409 | },
410 | {
411 | "include": "#class"
412 | },
413 | {
414 | "include": "#enum"
415 | },
416 | {
417 | "begin": "{",
418 | "end": "}",
419 | "patterns": [
420 | {
421 | "include": "#code"
422 | }
423 | ]
424 | },
425 | {
426 | "include": "#assertions"
427 | },
428 | {
429 | "include": "#parens"
430 | },
431 | {
432 | "include": "#constants-and-special-vars"
433 | },
434 | {
435 | "include": "#anonymous-classes-and-new"
436 | },
437 | {
438 | "include": "#keywords"
439 | },
440 | {
441 | "include": "#operators"
442 | },
443 | {
444 | "include": "#storage-modifiers"
445 | },
446 | {
447 | "include": "#strings"
448 | },
449 | {
450 | "include": "#all-types"
451 | },
452 | {
453 | "include": "#function-calls"
454 | }
455 | ]
456 | },
457 | "inner-code": {
458 | "patterns": [
459 | {
460 | "include": "#comments"
461 | },
462 | {
463 | "include": "#assertions"
464 | },
465 | {
466 | "include": "#parens"
467 | },
468 | {
469 | "include": "#constants-and-special-vars"
470 | },
471 | {
472 | "include": "#anonymous-classes-and-new"
473 | },
474 | {
475 | "include": "#keywords"
476 | },
477 | {
478 | "include": "#inner-operators"
479 | },
480 | {
481 | "include": "#storage-modifiers"
482 | },
483 | {
484 | "include": "#strings"
485 | },
486 | {
487 | "include": "#all-types"
488 | },
489 | {
490 | "include": "#function-calls"
491 | }
492 | ]
493 | },
494 | "comments": {
495 | "patterns": [
496 | {
497 | "captures": {
498 | "0": {
499 | "name": "punctuation.definition.comment.processing"
500 | }
501 | },
502 | "match": "/\\*\\*/",
503 | "name": "comment.block.empty.processing"
504 | },
505 | {
506 | "include": "text.html.javadoc"
507 | },
508 | {
509 | "include": "#comments-inline"
510 | }
511 | ]
512 | },
513 | "comments-inline": {
514 | "patterns": [
515 | {
516 | "begin": "/\\*",
517 | "captures": {
518 | "0": {
519 | "name": "punctuation.definition.comment.processing"
520 | }
521 | },
522 | "end": "\\*/",
523 | "name": "comment.block.processing"
524 | },
525 | {
526 | "captures": {
527 | "1": {
528 | "name": "comment.line.double-slash.processing"
529 | },
530 | "2": {
531 | "name": "punctuation.definition.comment.processing"
532 | }
533 | },
534 | "match": "\\s*((//).*$\\n?)"
535 | }
536 | ]
537 | },
538 | "constants-and-special-vars": {
539 | "patterns": [
540 | {
541 | "match": "\\b(true|false|null)\\b",
542 | "name": "constant.language.processing"
543 | },
544 | {
545 | "match": "\\b(this|super)\\b",
546 | "name": "variable.language.processing"
547 | },
548 | {
549 | "match": "\\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)([LlFfUuDd]|UL|ul)?\\b",
550 | "name": "constant.numeric.processing"
551 | },
552 | {
553 | "match": "(#[0-9a-fA-F]+)\\b",
554 | "name": "constant.numeric.processing"
555 | },
556 | {
557 | "captures": {
558 | "1": {
559 | "name": "keyword.operator.dereference.processing"
560 | }
561 | },
562 | "match": "(\\.)?\\b([A-Z][A-Z0-9_]+)(?!<|\\.class|\\s*\\w+\\s*=)\\b",
563 | "name": "constant.other.processing"
564 | }
565 | ]
566 | },
567 | "enums": {
568 | "begin": "^(?=\\s*[A-Z0-9_]+\\s*({|\\(|,))",
569 | "end": "(?=;|})",
570 | "patterns": [
571 | {
572 | "begin": "\\w+",
573 | "beginCaptures": {
574 | "0": {
575 | "name": "constant.other.enum.java"
576 | }
577 | },
578 | "end": "(?=,|;|})",
579 | "name": "meta.enum.java",
580 | "patterns": [
581 | {
582 | "include": "#parens"
583 | },
584 | {
585 | "begin": "{",
586 | "end": "}",
587 | "patterns": [
588 | {
589 | "include": "#class-body"
590 | }
591 | ]
592 | }
593 | ]
594 | }
595 | ]
596 | },
597 | "keywords": {
598 | "patterns": [
599 | {
600 | "match": "\\b(try|catch|finally|throw)\\b",
601 | "name": "keyword.control.catch-exception.processing"
602 | },
603 | {
604 | "match": "\\b(return|break|case|continue|default|do|while|for|switch|if|else)\\b",
605 | "name": "keyword.control.processing"
606 | },
607 | {
608 | "match": "\\b(displayHeight|displayWidth|focused|frameCount|frameRate|height|key|keyCode|keyPressed|mouseButton|mousePressed|mouseX|mouseY|online|pixelHeight|pixelWidth|pixels|pmouseX|pmouseY|screen|width)\\b",
609 | "name": "constant.other.processing"
610 | },
611 | {
612 | "match": "\\b(ADD|ALIGN_CENTER|ALIGN_LEFT|ALIGN_RIGHT|ALPHA|ALPHA_MASK|ALT|AMBIENT|ARGB|ARROW|BACKSPACE|BEVEL|BLEND|BLUE_MASK|BLUR|CENTER|CENTER_RADIUS|CHATTER|CODED|COMPLAINT|COMPONENT|COMPOSITE|CONCAVE_POLYGON|CONTROL|CONVEX_POLYGON|CORNER|CORNERS|CROSS|CUSTOM|DARKEST|DEGREES|DEG_TO_RAD|DELETE|DIFFERENCE|DIFFUSE|DISABLED|DISABLE_TEXT_SMOOTH|DOWN|ENTER|EPSILON|ESC|FX2D|GIF|GREEN_MASK|GREY|HALF|HALF_PI|HAND|HARD_LIGHT|HSB|IMAGE|INVERT|JAVA2D|JPEG|LEFT|LIGHTEST|LINES|LINE_LOOP|LINE_STRIP|MAX_FLOAT|MITER|MODEL|MOVE|MULTIPLY|NORMALIZED|NO_DEPTH_TEST|NTSC|ONE|OPAQUE|OPENGL|ORTHOGRAPHIC|OVERLAY|P2D|P3D|PAL|PDF|PERSPECTIVE|PI|PIXEL_CENTER|POINTS|POLYGON|POSTERIZE|PROBLEM|PROJECT|QUADS|QUAD_STRIP|QUARTER_PI|RADIANS|RAD_TO_DEG|RED_MASK|REPLACE|RETURN|RGB|RIGHT|ROUND|SCREEN|SECAM|SHIFT|SOFT_LIGHT|SPAN|SPECULAR|SQUARE|SUBTRACT|SVIDEO|TAB|TARGA|TEXT|TFF|THIRD_PI|THRESHOLD|TIFF|TRIANGLES|TRIANGLE_FAN|TRIANGLE_STRIP|TUNER|TAU|TWO|TWO_PI|UP|WAIT|WHITESPACE)\\b",
613 | "name": "support.constant.processing"
614 | },
615 | {
616 | "match": "\\b(Array|Character|FloatDict|FloatList|IntDict|IntList|Integer|JSONArray|JSONObject|Math|Object|PFont|PGraphics|PImage|PShader|PShape|PSound|PVector|StringBuffer|StringDict|StringList|Table|TableRow|Thread|XML)\\b",
617 | "name": "support.class.processing"
618 | },
619 | {
620 | "match": "\\b(instanceof)\\b",
621 | "name": "keyword.operator.processing"
622 | }
623 | ]
624 | },
625 | "operators": {
626 | "patterns": [
627 | {
628 | "include": "#common-operators"
629 | },
630 | {
631 | "begin": "=",
632 | "beginCaptures": {
633 | "0": {
634 | "name": "keyword.operator.assignment.processing"
635 | }
636 | },
637 | "end": ";",
638 | "patterns": [
639 | {
640 | "include": "#inner-code"
641 | }
642 | ]
643 | },
644 | {
645 | "match": ";",
646 | "name": "punctuation.terminator.processing"
647 | }
648 | ]
649 | },
650 | "inner-operators": {
651 | "patterns": [
652 | {
653 | "include": "#common-operators"
654 | },
655 | {
656 | "match": "(=)",
657 | "name": "keyword.operator.assignment.processing"
658 | }
659 | ]
660 | },
661 | "common-operators": {
662 | "patterns": [
663 | {
664 | "match": "(==|!=|<=|>=|<>|<|>)",
665 | "name": "keyword.operator.comparison.processing"
666 | },
667 | {
668 | "match": "(\\-\\-|\\+\\+)",
669 | "name": "keyword.operator.increment-decrement.processing"
670 | },
671 | {
672 | "match": "(\\+\\=|\\-\\=|\\*\\=|\\/\\=)",
673 | "name": "keyword.operator.arithmetic-assignment.processing"
674 | },
675 | {
676 | "match": "(\\-|\\+|\\*|\\/|%)",
677 | "name": "keyword.operator.arithmetic.processing"
678 | },
679 | {
680 | "match": "(!|&&|\\|\\|)",
681 | "name": "keyword.operator.logical.processing"
682 | },
683 | {
684 | "match": "(?<=\\S)\\.(?=\\S)",
685 | "name": "keyword.operator.dereference.processing"
686 | },
687 | {
688 | "match": "(\\?|\\:)",
689 | "name": "keyword.operator.ternary.processing"
690 | }
691 | ]
692 | },
693 | "function-calls": {
694 | "patterns": [
695 | {
696 | "captures": {
697 | "1": {
698 | "name": "support.function.any-method.processing"
699 | }
700 | },
701 | "match": "(?x)\n \t\t\t\t(\n \t\t\t\t\t(?!while|for|do|if|else|switch|catch|enumerate|return|r?iterate)(?: \\b[A-Za-z_][A-Za-z0-9_]*+\\b | :: )*+ # actual name\n \t\t\t\t)\n \t\t\t\t \\s*(?:\\()",
702 | "name": "meta.function-call.processing"
703 | }
704 | ]
705 | },
706 | "methods": {
707 | "begin": "(?!new)(?=\\w.*\\s+)(?=[^=]+\\()",
708 | "end": "}|(?=;)",
709 | "name": "meta.method.processing",
710 | "patterns": [
711 | {
712 | "include": "#storage-modifiers"
713 | },
714 | {
715 | "begin": "(\\w+)\\s*\\(",
716 | "beginCaptures": {
717 | "1": {
718 | "name": "entity.name.function.processing"
719 | }
720 | },
721 | "end": "\\)",
722 | "name": "meta.method.identifier.processing",
723 | "patterns": [
724 | {
725 | "include": "#parameters"
726 | }
727 | ]
728 | },
729 | {
730 | "begin": "(?=\\w.*\\s+\\w+\\s*\\()",
731 | "end": "(?=\\w+\\s*\\()",
732 | "name": "meta.method.return-type.processing",
733 | "patterns": [
734 | {
735 | "include": "#all-types"
736 | }
737 | ]
738 | },
739 | {
740 | "include": "#throws"
741 | },
742 | {
743 | "begin": "{",
744 | "end": "(?=})",
745 | "name": "meta.method.body.processing",
746 | "patterns": [
747 | {
748 | "include": "#code"
749 | }
750 | ]
751 | }
752 | ]
753 | },
754 | "object-types": {
755 | "patterns": [
756 | {
757 | "begin": "\\b((?:[a-z]\\w*\\.)*[A-Z]+\\w*)<",
758 | "end": ">|[^\\w\\s,\\?<\\[\\]]",
759 | "name": "storage.type.generic.processing",
760 | "patterns": [
761 | {
762 | "include": "#object-types"
763 | },
764 | {
765 | "begin": "<",
766 | "comment": "This is to support <>'s with no actual type prefix",
767 | "end": ">|[^\\w\\s,\\[\\]<]",
768 | "name": "storage.type.generic.processing"
769 | }
770 | ]
771 | },
772 | {
773 | "begin": "\\b((?:[a-z]\\w*\\.)*[A-Z]+\\w*)(?=\\[)",
774 | "end": "(?=[^\\]\\s])",
775 | "name": "storage.type.object.array.processing",
776 | "patterns": [
777 | {
778 | "begin": "\\[",
779 | "end": "\\]",
780 | "patterns": [
781 | {
782 | "include": "#inner-code"
783 | }
784 | ]
785 | }
786 | ]
787 | },
788 | {
789 | "captures": {
790 | "1": {
791 | "name": "keyword.operator.dereference.processing"
792 | }
793 | },
794 | "match": "\\b(?:[a-z]\\w*(\\.))*[A-Z]+\\w*\\b",
795 | "name": "storage.type.processing"
796 | }
797 | ]
798 | },
799 | "object-types-inherited": {
800 | "patterns": [
801 | {
802 | "begin": "\\b((?:[a-z]\\w*\\.)*[A-Z]+\\w*)<",
803 | "end": ">|[^\\w\\s,<]",
804 | "name": "entity.other.inherited-class.processing",
805 | "patterns": [
806 | {
807 | "include": "#object-types"
808 | },
809 | {
810 | "begin": "<",
811 | "comment": "This is to support <>'s with no actual type prefix",
812 | "end": ">|[^\\w\\s,<]",
813 | "name": "storage.type.generic.processing"
814 | }
815 | ]
816 | },
817 | {
818 | "captures": {
819 | "1": {
820 | "name": "keyword.operator.dereference.processing"
821 | }
822 | },
823 | "match": "\\b(?:[a-z]\\w*(\\.))*[A-Z]+\\w*",
824 | "name": "entity.other.inherited-class.processing"
825 | }
826 | ]
827 | },
828 | "parameters": {
829 | "patterns": [
830 | {
831 | "match": "final",
832 | "name": "storage.modifier.processing"
833 | },
834 | {
835 | "include": "#simple-arrays"
836 | },
837 | {
838 | "include": "#simple-types"
839 | },
840 | {
841 | "include": "#object-types"
842 | },
843 | {
844 | "match": "\\w+",
845 | "name": "variable.parameter.processing"
846 | }
847 | ]
848 | },
849 | "parens": {
850 | "begin": "\\(",
851 | "end": "\\)",
852 | "patterns": [
853 | {
854 | "include": "#inner-code"
855 | }
856 | ]
857 | },
858 | "simple-arrays": {
859 | "patterns": [
860 | {
861 | "match": "\\b(?:void|boolean|byte|char|short|int|float|long|double|color)(\\[\\])*\\b",
862 | "name": "storage.type.simple.array.processing"
863 | }
864 | ]
865 | },
866 | "simple-types": {
867 | "patterns": [
868 | {
869 | "match": "\\b(?:void|boolean|byte|char|short|int|float|long|double|color)\\b",
870 | "name": "storage.type.simple.processing"
871 | }
872 | ]
873 | },
874 | "storage-modifiers": {
875 | "captures": {
876 | "1": {
877 | "name": "storage.modifier.processing"
878 | }
879 | },
880 | "match": "\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient)\\b"
881 | },
882 | "strings": {
883 | "patterns": [
884 | {
885 | "begin": "\"",
886 | "beginCaptures": {
887 | "0": {
888 | "name": "punctuation.definition.string.begin.processing"
889 | }
890 | },
891 | "end": "\"",
892 | "endCaptures": {
893 | "0": {
894 | "name": "punctuation.definition.string.end.processing"
895 | }
896 | },
897 | "name": "string.quoted.double.processing",
898 | "patterns": [
899 | {
900 | "match": "\\\\.",
901 | "name": "constant.character.escape.processing"
902 | }
903 | ]
904 | },
905 | {
906 | "begin": "'",
907 | "beginCaptures": {
908 | "0": {
909 | "name": "punctuation.definition.string.begin.processing"
910 | }
911 | },
912 | "end": "'",
913 | "endCaptures": {
914 | "0": {
915 | "name": "punctuation.definition.string.end.processing"
916 | }
917 | },
918 | "name": "string.quoted.single.processing",
919 | "patterns": [
920 | {
921 | "match": "\\\\.",
922 | "name": "constant.character.escape.processing"
923 | }
924 | ]
925 | }
926 | ]
927 | },
928 | "throws": {
929 | "begin": "throws",
930 | "beginCaptures": {
931 | "0": {
932 | "name": "storage.modifier.processing"
933 | }
934 | },
935 | "end": "(?={|;)",
936 | "name": "meta.throwables.processing",
937 | "patterns": [
938 | {
939 | "include": "#object-types"
940 | }
941 | ]
942 | },
943 | "values": {
944 | "patterns": [
945 | {
946 | "include": "#strings"
947 | },
948 | {
949 | "include": "#object-types"
950 | },
951 | {
952 | "include": "#constants-and-special-vars"
953 | }
954 | ]
955 | }
956 | },
957 | "scopeName": "source.pde",
958 | "uuid": "D3D6351E-1416-4AE7-8060-665C6108D2C5"
959 | }
960 |
--------------------------------------------------------------------------------
/media/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Luke-zhang-04/processing-vscode/c116f535868f409d0f40fd16440201c597dbbaa0/media/error.png
--------------------------------------------------------------------------------
/media/hover-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Luke-zhang-04/processing-vscode/c116f535868f409d0f40fd16440201c597dbbaa0/media/hover-1.png
--------------------------------------------------------------------------------
/media/hover-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Luke-zhang-04/processing-vscode/c116f535868f409d0f40fd16440201c597dbbaa0/media/hover-2.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "processing-vscode",
3 | "version": "2.4.1",
4 | "private": true,
5 | "description": "Processing Language Support for VSCode",
6 | "license": "MIT",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/Luke-zhang-04/processing-vscode.git"
10 | },
11 | "homepage": "https://github.com/Luke-zhang-04/processing-vscode",
12 | "bugs": "https://github.com/Luke-zhang-04/processing-vscode/issues",
13 | "main": "./processing-vscode.js",
14 | "engines": {
15 | "vscode": "^1.48.0"
16 | },
17 | "scripts": {
18 | "build": "rollup -c rollup.config.js",
19 | "deploy": "vsce publish",
20 | "format": "prettier . --write && eslint --ext ts --fix --cache",
21 | "lint": "eslint --ext ts src --max-warnings 0 --cache",
22 | "test": "node --experimental-vm-modules --experimental-specifier-resolution=node node_modules/.bin/jest",
23 | "vscode:prepublish": "rollup -c rollup.config.js"
24 | },
25 | "keywords": [
26 | "processing",
27 | "pde",
28 | "processing.py",
29 | "processing-python",
30 | "language",
31 | "snippets",
32 | "diagnostics",
33 | "runner"
34 | ],
35 | "devDependencies": {
36 | "@rollup/plugin-node-resolve": "^13.0.0",
37 | "@rollup/plugin-typescript": "^8.2.1",
38 | "@types/glob": "^7.1.4",
39 | "@types/jest": "^27.0.3",
40 | "@types/jsdom": "^16.2.13",
41 | "@types/node": "^16.3.1",
42 | "@types/node-fetch": "^2.5.11",
43 | "@types/vscode": "^1.48.0",
44 | "@typescript-eslint/eslint-plugin": "^4.28.2",
45 | "@typescript-eslint/parser": "^4.28.2",
46 | "eslint": "^7.30.0",
47 | "eslint-plugin-prefer-arrow": "^1.2.3",
48 | "glob": "^7.1.7",
49 | "jest": "^27.4.5",
50 | "jsdom": "^16.6.0",
51 | "node-fetch": "^2.6.1",
52 | "prettier": "^2.3.2",
53 | "prettier-plugin-jsdoc": "^0.3.23",
54 | "prettier-plugin-package": "^1.3.0",
55 | "rollup": "^2.53.0",
56 | "rollup-plugin-progress": "^1.1.2",
57 | "rollup-plugin-terser": "^7.0.2",
58 | "ts-jest": "^27.1.2",
59 | "tslib": "^2.3.0",
60 | "typescript": "~4.3.5",
61 | "vsce": "^1.95.1",
62 | "yaml": "^1.10.2"
63 | },
64 | "activationEvents": [
65 | "onCommand:processing.OpenExtensionDocumentation",
66 | "onCommand:processing.OpenDocs",
67 | "onCommand:processing.SearchWebsite",
68 | "onCommand:processing.Run",
69 | "onCommand:processing.RunJava",
70 | "onCommand:processing.RunPy",
71 | "onLanguage:pde",
72 | "onLanguage:python"
73 | ],
74 | "categories": [
75 | "Programming Languages",
76 | "Snippets"
77 | ],
78 | "contributes": {
79 | "commands": [
80 | {
81 | "command": "processing.Run",
82 | "title": "Processing: Run Open Processing Project",
83 | "enablement": "resourceLangId == python || resourceLangId == pde"
84 | },
85 | {
86 | "command": "processing.RunPy",
87 | "title": "Processing: Run Open Processing Python Project",
88 | "icon": "./images/play-arrow-with-logo.svg",
89 | "enablement": "resourceLangId == python && config.processing.py.isEnabled"
90 | },
91 | {
92 | "command": "processing.RunJava",
93 | "title": "Processing: Run Open Processing Java Project",
94 | "icon": "./images/play-arrow.svg",
95 | "enablement": "resourceLangId == pde"
96 | },
97 | {
98 | "command": "processing.OpenExtensionDocumentation",
99 | "title": "Processing: Open Extension Documentation",
100 | "enablement": "resourceLangId == pde"
101 | },
102 | {
103 | "command": "processing.OpenDocs",
104 | "title": "Processing: Open Documentation for Selection",
105 | "enablement": "resourceLangId == pde || resourceLangId == python && config.processing.py.isEnabled"
106 | },
107 | {
108 | "command": "processing.SearchWebsite",
109 | "title": "Processing: Search Processing Website",
110 | "enablement": "resourceLangId == pde || resourceLangId == python && config.processing.py.isEnabled"
111 | }
112 | ],
113 | "languages": [
114 | {
115 | "id": "pde",
116 | "aliases": [
117 | "Processing",
118 | "pde"
119 | ],
120 | "extensions": [
121 | ".pde"
122 | ],
123 | "configuration": "./pde.configuration.json"
124 | }
125 | ],
126 | "grammars": [
127 | {
128 | "language": "pde",
129 | "scopeName": "source.pde",
130 | "path": "./syntaxes/pde.tmLanguage.json"
131 | }
132 | ],
133 | "snippets": [
134 | {
135 | "language": "pde",
136 | "path": "./snippets/snippets.json"
137 | }
138 | ],
139 | "menus": {
140 | "editor/context": [
141 | {
142 | "when": "editorHasSelection && editorLangId == 'pde'",
143 | "command": "processing.OpenDocs",
144 | "group": "navigation@1"
145 | },
146 | {
147 | "when": "resourceLangId == pde",
148 | "command": "processing.RunJava",
149 | "group": "navigation"
150 | },
151 | {
152 | "when": "resourceLangId == python && config.processing.py.isEnabled",
153 | "command": "processing.RunPy",
154 | "group": "navigation"
155 | }
156 | ],
157 | "editor/title": [
158 | {
159 | "when": "resourceLangId == pde",
160 | "command": "processing.RunJava",
161 | "group": "navigation"
162 | },
163 | {
164 | "when": "resourceLangId == python && config.processing.py.isEnabled",
165 | "command": "processing.RunPy",
166 | "group": "navigation"
167 | }
168 | ]
169 | },
170 | "configuration": {
171 | "type": "object",
172 | "title": "Processing",
173 | "properties": {
174 | "processing.processingPath": {
175 | "type": "string",
176 | "default": "processing-java",
177 | "description": "Path to Processing. Leave default if you've added processing to your path, otherwise enter the path to `processing-java` here. Example: `/usr/bin/processing-java` for Unix, or `C:\\Program Files\\processing-3.0.1\\processing-java` for Windows."
178 | },
179 | "processing.path": {
180 | "type": "string",
181 | "default": "processing-java",
182 | "description": "Legacy path to Processing. Use processing.processingPath instead. If processing.processingPath is available, it will be used",
183 | "deprecationMessage": "Legacy path to Processing. Use processing.processingPath instead. If processing.processingPath is available, it will be used"
184 | },
185 | "processing.docs": {
186 | "type": "string",
187 | "default": "auto",
188 | "enum": [
189 | "processing.org",
190 | "p5js.org",
191 | "py.processing.org",
192 | "auto"
193 | ],
194 | "enumDescriptions": [
195 | "Use processing.org for documentation",
196 | "Use p5js for documentation",
197 | "Use py.processing.org for documentation",
198 | "Automatically determine either processing.org or py.processing.org (never p5js) depending on the current file"
199 | ],
200 | "description": "Which documentation this extension should use"
201 | },
202 | "processing.search": {
203 | "type": "string",
204 | "default": "Google",
205 | "enum": [
206 | "Google",
207 | "DuckDuckGo"
208 | ],
209 | "enumDescriptions": [
210 | "Use Google to search documentation",
211 | "Use DuckDuckGo to search documentation"
212 | ],
213 | "description": "Which search engine should this extension use?"
214 | },
215 | "processing.shouldGiveDiagnostics": {
216 | "type": "boolean",
217 | "default": false,
218 | "description": "If the extension should provide diagnostics (via processing-java). Note that this feature is quite slow."
219 | },
220 | "processing.shouldSendSigint": {
221 | "type": "boolean",
222 | "default": false,
223 | "description": "If the extension should send sigint to the terminal stop the current running processing program before running the new one by sending \"\\x03\" (^C). If true, it essentially presses ctrl+c for you."
224 | },
225 | "processing.runPathQuotes": {
226 | "type": "string",
227 | "enum": [
228 | "auto",
229 | "always"
230 | ],
231 | "default": "auto",
232 | "description": "When the run path should be quoted. If always, the run path will always be quoted. If auto, the extension will attempt to figure out when to quote the path."
233 | },
234 | "processing.py.jarPath": {
235 | "type": "string",
236 | "default": "processing-py.jar",
237 | "description": "The location of your processing-py.jar file. You can download it from https://py.processing.org/tutorials/command-line/#requirements."
238 | },
239 | "processing.py.javaPath": {
240 | "type": "string",
241 | "default": "java",
242 | "description": "Path to Java. Leave default if you've added java to your path, otherwise enter the path to `java` here. Example: `/usr/bin/java` for Unix, or potentially `C:\\Program Files\\Java\\jdk1.8.0_202\\bin\\javac.exe` for Windows."
243 | },
244 | "processing.py.isEnabled": {
245 | "type": "boolean",
246 | "default": true,
247 | "description": "If processing.py features should be enabled or not."
248 | }
249 | }
250 | }
251 | },
252 | "displayName": "Processing VSCode",
253 | "icon": "images/processing.png",
254 | "publisher": "Luke-zhang-04",
255 | "workspaces": [
256 | ".",
257 | "./rollup/plugins"
258 | ]
259 | }
260 |
--------------------------------------------------------------------------------
/pde.configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "//",
4 | "blockComment": ["/*", "*/"]
5 | },
6 | "brackets": [
7 | ["{", "}"],
8 | ["[", "]"],
9 | ["(", ")"]
10 | ],
11 | "autoClosingPairs": [
12 | {
13 | "open": "{",
14 | "close": "}"
15 | },
16 | {
17 | "open": "[",
18 | "close": "]"
19 | },
20 | {
21 | "open": "(",
22 | "close": ")"
23 | },
24 | {
25 | "open": "'",
26 | "close": "'",
27 | "notIn": ["string", "comment"]
28 | },
29 | {
30 | "open": "\"",
31 | "close": "\"",
32 | "notIn": ["string"]
33 | },
34 | {
35 | "open": "`",
36 | "close": "`",
37 | "notIn": ["string", "comment"]
38 | },
39 | {
40 | "open": "/**",
41 | "close": " */",
42 | "notIn": ["string"]
43 | }
44 | ],
45 | "surroundingPairs": [
46 | ["{", "}"],
47 | ["[", "]"],
48 | ["(", ")"],
49 | ["'", "'"],
50 | ["\"", "\""],
51 | ["<", ">"]
52 | ],
53 | "autoCloseBefore": ";:.,=}])>` \n\t",
54 | "folding": {
55 | "markers": {
56 | "start": "^\\s*//\\s*#?region\\b",
57 | "end": "^\\s*//\\s*#?endregion\\b"
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import {yaml} from "./rollup/plugins/lib/index.js"
2 | import progress from "rollup-plugin-progress"
3 | import resolve from "@rollup/plugin-node-resolve"
4 | import {terser} from "rollup-plugin-terser"
5 | import typescript from "@rollup/plugin-typescript"
6 |
7 | const banner = `/**
8 | * Processing-vscode - Processing Language Support for VSCode
9 | * https://github.com/Luke-zhang-04/processing-vscode
10 | *
11 | * @license MIT
12 | * @version 2.4.1
13 | * @preserve
14 | * @copyright (C) 2016 - 2020 Tobiah Zarlez, 2021 Luke Zhang
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 | `
25 |
26 | /**
27 | * @type {import("rollup").RollupOptions}
28 | */
29 | const config = {
30 | input: "src/index.ts",
31 | output: {
32 | file: "./processing-vscode.js",
33 | format: "cjs",
34 | banner,
35 | inlineDynamicImports: true,
36 | sourcemap: process.env.NODE_ENV === "dev" ? "inline" : false,
37 | },
38 | plugins: [
39 | progress(),
40 | typescript(),
41 | yaml(),
42 | resolve({
43 | resolveOnly: [/^(?!vscode)$/],
44 | }),
45 | process.env.NODE_ENV === "dev"
46 | ? undefined
47 | : terser({
48 | format: {
49 | comments: (_, {value}) =>
50 | (/@preserve/.test(value) || !/processing-vscode/iu.test(value)) &&
51 | /@preserve|li[cs]ense|copyright/iu.test(value),
52 | },
53 | }),
54 | ],
55 | }
56 |
57 | export default config
58 |
--------------------------------------------------------------------------------
/rollup/plugins/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rollup-plugins",
3 | "version": "0.0.0",
4 | "license": "MIT",
5 | "main": "./lib/index.js",
6 | "scripts": {
7 | "build": "tsc"
8 | },
9 | "dependencies": {
10 | "@rollup/pluginutils": "^4.1.0",
11 | "js-yaml": "^4.1.0"
12 | },
13 | "devDependencies": {
14 | "@types/js-yaml": "^4.0.1",
15 | "rollup": "^2.53.0",
16 | "typescript": "^4.3.2"
17 | },
18 | "types": "./lib/index.d.ts"
19 | }
20 |
--------------------------------------------------------------------------------
/rollup/plugins/src/index.ts:
--------------------------------------------------------------------------------
1 | export {default as yaml} from "./json-and-yaml"
2 |
--------------------------------------------------------------------------------
/rollup/plugins/src/json-and-yaml.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @license MIT
3 | * @file improved Version of @rollup/plugin-json and @rollup/plugin-yaml that combines the two and
4 | * provides the option for JSON.stringify()
5 | * @copyright (c) 2019 RollupJS Plugin Contributors
6 | * (https://github.com/rollup/plugins/graphs/contributors), 2021 Luke Zhang
7 | * @see {@link https://github.com/rollup/plugins/tree/master/packages/json}
8 | * @see {@link https://github.com/rollup/plugins/tree/master/packages/yaml}
9 | */
10 |
11 | import {FilterPattern, createFilter, dataToEsm} from "@rollup/pluginutils"
12 | import yaml from "js-yaml"
13 | import type {PluginFunc} from "./types"
14 |
15 | type ValidYamlType =
16 | | number
17 | | string
18 | | boolean
19 | | null
20 | | undefined
21 | | {[key: string]: ValidYamlType}
22 | | ValidYamlType[]
23 |
24 | type RollupJsonOptions = {
25 | /**
26 | * All JSON and YAML files will be parsed by default, but you can also specifically include files
27 | *
28 | * @default ["**/*.json", "**/*.y(a)?ml"]
29 | */
30 | include?: FilterPattern
31 | /**
32 | * All JSON and YAML files will be parsed by default, but you can also specifically exclude files
33 | *
34 | * @default
35 | */
36 | exclude?: FilterPattern
37 | /**
38 | * For tree-shaking, properties will be declared as variables, using either `var` or `const`.
39 | *
40 | * @default true
41 | */
42 | preferConst?: boolean
43 | /**
44 | * Specify indentation for the generated default export
45 | *
46 | * @default
47 | */
48 | indent?: string
49 | /**
50 | * Ignores indent and generates the smallest code
51 | *
52 | * @default false
53 | */
54 | compact?: boolean
55 | /**
56 | * Generate a named export for every property of the JSON object
57 | *
58 | * @default true
59 | */
60 | namedExports?: boolean
61 | /**
62 | * Character for when json should be stringified and then parsed at runtime
63 | *
64 | * @default 14 * 1024 (14kb)
65 | * @see {@link https://v8.dev/blog/cost-of-javascript-2019#json}
66 | */
67 | stringifyLimit?: number
68 | /**
69 | * A function which can optionally mutate parsed YAML. The function should return the mutated
70 | * `object`, or `undefined` which will make no changes to the parsed YAML.
71 | *
72 | * @default undefined
73 | */
74 | transform?: (data: ValidYamlType, filePath: string) => ValidYamlType | undefined
75 | /**
76 | * - If `single`, specifies that the target YAML documents contain only one document in the target file(s).
77 | * - If more than one [document stream](https://yaml.org/spec/1.2/spec.html#id2801681) exists in
78 | * the target YAML file(s), set `documentMode: 'multi'`.
79 | *
80 | * @default 'single'
81 | */
82 | documentMode?: "single" | "multi"
83 | }
84 |
85 | const json: PluginFunc = ({
86 | include = ["**/*.y(a)?ml", "**/*.json"],
87 | exclude,
88 | preferConst = true,
89 | indent = " ",
90 | compact = false,
91 | namedExports = true,
92 | stringifyLimit = 14 * 1024,
93 | transform,
94 | documentMode = "single",
95 | } = {}) => {
96 | const filter = createFilter(include, exclude)
97 |
98 | let loadMethod = (documentMode === "multi" ? yaml.loadAll : yaml.load) as (
99 | str: string,
100 | iterator?: (doc: any) => void,
101 | opts?: yaml.LoadOptions,
102 | ) => ValidYamlType
103 |
104 | const plugin: ReturnType> = {
105 | name: "json/yaml",
106 | transform(code, id) {
107 | if (!filter(id)) {
108 | return null
109 | }
110 |
111 | try {
112 | const parsed = transform?.(loadMethod(code), id) ?? loadMethod(code)
113 | const stringified = JSON.stringify(parsed, null, 0)
114 |
115 | return {
116 | code:
117 | stringified.length > stringifyLimit
118 | ? `export default JSON.parse(${JSON.stringify(stringified)})`
119 | : dataToEsm(parsed, {
120 | preferConst,
121 | compact,
122 | namedExports,
123 | indent,
124 | }),
125 | map: {mappings: ""},
126 | }
127 | } catch (err) {
128 | const message = `Could not parse JSON file: ${
129 | err instanceof Error ? err.toString() : JSON.stringify(err)
130 | }`
131 |
132 | this.error({message, id})
133 | }
134 | },
135 | }
136 |
137 | return plugin
138 | }
139 |
140 | export default json
141 |
--------------------------------------------------------------------------------
/rollup/plugins/src/types.ts:
--------------------------------------------------------------------------------
1 | export type PluginFunc = (options: T) => import("rollup").Plugin | undefined
2 |
--------------------------------------------------------------------------------
/rollup/plugins/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Basic Options */
6 | // "incremental": true, /* Enable incremental compilation */
7 | "target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
8 | "module": "ES2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9 | // "lib": [], /* Specify library files to be included in the compilation. */
10 | // "allowJs": true, /* Allow javascript files to be compiled. */
11 | // "checkJs": true, /* Report errors in .js files. */
12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
13 | "declaration": true, /* Generates corresponding '.d.ts' file. */
14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15 | // "sourceMap": true, /* Generates corresponding '.map' file. */
16 | // "outFile": "./", /* Concatenate and emit output to single file. */
17 | "outDir": "./lib", /* Redirect output structure to the directory. */
18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19 | // "composite": true, /* Enable project compilation */
20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
21 | // "removeComments": true, /* Do not emit comments to output. */
22 | // "noEmit": true, /* Do not emit outputs. */
23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 |
27 | /* Strict Type-Checking Options */
28 | "strict": true, /* Enable all strict type-checking options. */
29 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30 | "strictNullChecks": true, /* Enable strict null checks. */
31 | "strictFunctionTypes": true, /* Enable strict checking of function types. */
32 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36 |
37 | /* Additional Checks */
38 | "noUnusedLocals": true, /* Report errors on unused locals. */
39 | "noUnusedParameters": true, /* Report errors on unused parameters. */
40 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42 | "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
43 | "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
44 | "noPropertyAccessFromIndexSignature": false, /* Require undeclared properties from index signatures to use element accesses. */
45 |
46 | /* Module Resolution Options */
47 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
48 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
49 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
50 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
51 | // "typeRoots": [], /* List of folders to include type definitions from. */
52 | // "types": [], /* Type declaration files to be included in compilation. */
53 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
54 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
55 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
56 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
57 |
58 | /* Source Map Options */
59 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
60 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
61 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
62 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
63 |
64 | /* Experimental Options */
65 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
66 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
67 |
68 | /* Advanced Options */
69 | "skipLibCheck": true, /* Skip type checking of declaration files. */
70 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
71 | },
72 | "include": ["./src"]
73 | }
74 |
--------------------------------------------------------------------------------
/scripts/checkDocs.mjs:
--------------------------------------------------------------------------------
1 | #!/bin/node
2 |
3 | /**
4 | * @file Checks If documentation data is up to date
5 | */
6 |
7 | import crypto from "crypto"
8 | import {dirname} from "path"
9 | import {fileURLToPath} from "url"
10 | import {promises as fs} from "fs"
11 | import yaml from "yaml"
12 | import getDocs from "./helpers/fetchDocs.mjs"
13 |
14 | export const hash = (algo, contents, format = "hex") =>
15 | crypto.createHash(algo).update(contents).digest(format)
16 |
17 | const __dirname = dirname(fileURLToPath(import.meta.url))
18 |
19 | const newDocs = await getDocs()
20 | const newDocsString = `# THIS IS AN AUTOGENERATED FILE; DO NOT EDIT DIRECTLY\n\n${yaml.stringify(
21 | newDocs,
22 | {
23 | sortMapEntries: true,
24 | },
25 | )}`.trim()
26 |
27 | const oldDocsString = (
28 | await fs.readFile(`${__dirname}/../data/documentation-data.yml`, "utf-8")
29 | ).trim()
30 |
31 | if (hash("sha256", newDocsString) === hash("sha256", oldDocsString)) {
32 | console.log("Documentation data is up to date")
33 | } else {
34 | throw new Error("Documentation is out of date")
35 | }
36 |
--------------------------------------------------------------------------------
/scripts/helpers/fetchDocs.mjs:
--------------------------------------------------------------------------------
1 | #!/bin/node
2 |
3 | import {JSDOM} from "jsdom"
4 | import fetch from "node-fetch"
5 |
6 | const docsUrl = "https://processing.org/reference"
7 |
8 | // Processing global variables
9 | const variables = [
10 | "focused",
11 | "frameCount",
12 | "height",
13 | "width",
14 | "pixelHeight",
15 | "pixelWidth",
16 | "mouseButton",
17 | "mouseX",
18 | "mouseY",
19 | "pmouseX",
20 | "pmouseY",
21 | "key",
22 | "keyCode",
23 | "keyPressed",
24 | "HALF_PI",
25 | "PI",
26 | "QUARTER_PI",
27 | "TAU",
28 | "TWO_PI",
29 | ]
30 |
31 | const constants = ["HALF_PI.html", "PI.html", "QUARTER_PI.html", "TAU.html", "TWO_PI.html"]
32 |
33 | // Processing classes
34 | const classes = [
35 | "Array",
36 | "ArrayList",
37 | "FloatDict",
38 | "FloatList",
39 | "HashMap",
40 | "IntDict",
41 | "IntList",
42 | "JSONArray",
43 | "JSONObject",
44 | "Object",
45 | "String",
46 | "StringDict",
47 | "StringList",
48 | "Table",
49 | "TableRow",
50 | "XML",
51 | "PShape",
52 | "PImage",
53 | "PGraphics",
54 | "PShader",
55 | "PFont",
56 | "PVector",
57 | ]
58 |
59 | /**
60 | * Gets all the links to Processing builtins
61 | */
62 | const getDocLinks = async () => {
63 | const response = await fetch(docsUrl)
64 |
65 | if (response.status !== 200) {
66 | console.log(`Response for all links returned status ${response.status}.`)
67 | console.log(response)
68 |
69 | return
70 | }
71 |
72 | const {window} = new JSDOM(await response.text()) // Fetch docs and parse as document
73 | const {document} = window
74 | const references = Array.from(document.querySelectorAll("div.category a")) // All reference items
75 |
76 | return {
77 | functionLinks: references // Function doc links
78 | .filter(({innerHTML}) => /[A-z]\(\)/u.test(innerHTML))
79 | .map((item) => item.getAttribute("href").trim()),
80 | variableLinks: references // Variable doc links
81 | .filter(({innerHTML}) => variables.includes(innerHTML))
82 | .map((item) => item.getAttribute("href").trim()),
83 | classLinks: references // Class doc links
84 | .filter(({innerHTML}) => classes.includes(innerHTML))
85 | .map((item) => item.getAttribute("href").trim()),
86 | }
87 | }
88 |
89 | /**
90 | * Escapes some html
91 | *
92 | * @param {string} html - Html to escape
93 | * @returns {string} Escaped html
94 | */
95 | const escapeHTML = (html) =>
96 | html
97 | .replace(/<(\/)?(b|pre)>/gu, "`")
98 | .replace(/
/gu, "")
99 | .replace(/<[^>]*>/gu, "")
100 | .replace(/</gu, "<")
101 | .replace(/>/gu, ">")
102 | .trim()
103 |
104 | /**
105 | * Gets the documentation for a single link
106 | *
107 | * @param {string} link - Link to get doc from
108 | * @returns {Promise}
109 | */
110 | const documentVariable = async (link) => {
111 | const documentation = {
112 | docUrl: `${docsUrl}/${link}`,
113 | type: constants.includes(link) ? "const" : "var",
114 | }
115 |
116 | const response = await fetch(`${docsUrl}/${link}`)
117 |
118 | if (!response.ok) {
119 | console.log(`Response for ${link} returned status ${response.status}.`)
120 | console.log(response)
121 |
122 | return
123 | }
124 |
125 | const {window} = new JSDOM(await response.text()) // Parse webpage
126 | const {document} = window
127 |
128 | for (const item of Array.from(document.querySelectorAll(".content table tr"))) {
129 | const header = item.querySelector("th")
130 |
131 | if (!header) {
132 | continue
133 | }
134 |
135 | const {innerHTML} = header // Get the header for each table item
136 |
137 | const property = (() => {
138 | if (["Description", "Examples", "Name"].includes(innerHTML)) {
139 | return innerHTML.toLowerCase()
140 | }
141 | })()
142 |
143 | if (property) {
144 | if (property === "description") {
145 | const description = escapeHTML(item.querySelector("td").innerHTML).replace(
146 | /\\n/gu,
147 | "\n\n",
148 | )
149 |
150 | documentation.description =
151 | description.length > 1000 ? description.slice(0, 1000) + ". . ." : description
152 | } else if (property === "examples") {
153 | documentation[property] = escapeHTML(item.querySelector("td").innerHTML).replace(
154 | /`/giu,
155 | "",
156 | )
157 | } else {
158 | documentation[property] = escapeHTML(item.querySelector("td").innerHTML)
159 | }
160 | }
161 | }
162 |
163 | return documentation
164 | }
165 |
166 | /**
167 | * Gets the documentation for a single link
168 | *
169 | * @param {string} link - Link to get doc from
170 | * @returns {Promise}
171 | */
172 | const documentFunction = async (link) => {
173 | const documentation = {
174 | docUrl: `${docsUrl}/${link}`,
175 | parameters: {},
176 | type: "function",
177 | }
178 |
179 | const response = await fetch(`${docsUrl}/${link}`)
180 |
181 | if (!response.ok) {
182 | console.log(`Response for ${link} returned status ${response.status}.`)
183 | console.log(response)
184 |
185 | return
186 | }
187 |
188 | const {window} = new JSDOM(await response.text())
189 | const {document} = window
190 |
191 | for (const item of Array.from(document.querySelectorAll(".content table tr"))) {
192 | const header = item.querySelector("th")
193 |
194 | if (!header) {
195 | continue
196 | }
197 |
198 | const {innerHTML} = header
199 |
200 | const property = (() => {
201 | if (["Description", "Syntax", "Returns", "Parameters", "Name"].includes(innerHTML)) {
202 | return innerHTML.toLowerCase()
203 | }
204 | })()
205 |
206 | if (property) {
207 | if (property === "parameters") {
208 | Array.from(item.querySelectorAll("td table tr")).forEach((item) => {
209 | documentation.parameters[item.querySelector("th").innerHTML] = escapeHTML(
210 | item.querySelector("td").innerHTML,
211 | )
212 | })
213 | } else if (property === "syntax") {
214 | documentation.syntax = escapeHTML(item.querySelector("td").innerHTML).replace(
215 | /`/gu,
216 | "",
217 | )
218 | } else if (property === "description") {
219 | const description = escapeHTML(item.querySelector("td").innerHTML).replace(
220 | /\\n/gu,
221 | "\n\n",
222 | )
223 |
224 | documentation.description =
225 | description.length > 1000 ? description.slice(0, 1000) + ". . ." : description
226 | } else {
227 | documentation[property] = escapeHTML(item.querySelector("td").innerHTML)
228 | }
229 | }
230 | }
231 |
232 | return documentation
233 | }
234 |
235 | /**
236 | * Gets the documentation for a single link
237 | *
238 | * @param {string} link - Link to get doc from
239 | * @returns {Promise}
240 | */
241 | const documentClass = async (link) => {
242 | const documentation = {
243 | docUrl: `${docsUrl}/${link}`,
244 | parameters: {},
245 | methods: {},
246 | fields: {},
247 | type: "class",
248 | }
249 |
250 | const response = await fetch(`${docsUrl}/${link}`)
251 |
252 | if (!response.ok) {
253 | // If response wasn't ok, return
254 | console.log(`Response for ${link} returned status ${response.status}.`)
255 | console.log(response)
256 |
257 | return
258 | }
259 |
260 | const {window} = new JSDOM(await response.text()) // Parse the page
261 | const {document} = window
262 |
263 | for (const item of Array.from(document.querySelectorAll(".content table tr"))) {
264 | const header = item.querySelector("th")
265 |
266 | if (!header) {
267 | continue
268 | }
269 |
270 | const {innerHTML} = header
271 |
272 | const property = (() => {
273 | if (["Description", "Constructor", "Parameters", "Name"].includes(innerHTML)) {
274 | return innerHTML.toLowerCase()
275 | }
276 | })()
277 |
278 | if (property) {
279 | if (property === "parameters") {
280 | Array.from(item.querySelectorAll("td table tr")).forEach((item) => {
281 | documentation.parameters[item.querySelector("th").innerHTML] = escapeHTML(
282 | item.querySelector("td").innerHTML,
283 | )
284 | })
285 | } else if (property === "constructor") {
286 | documentation.syntax = escapeHTML(item.querySelector("td").innerHTML).replace(
287 | /`/gu,
288 | "",
289 | )
290 | } else if (property === "description") {
291 | const description = escapeHTML(item.querySelector("td").innerHTML).replace(
292 | /\\n/gu,
293 | "\n\n",
294 | )
295 |
296 | documentation.description =
297 | description.length > 1000 ? description.slice(0, 1000) + ". . ." : description
298 | } else {
299 | documentation[property] = escapeHTML(item.querySelector("td").innerHTML)
300 | }
301 | }
302 | }
303 |
304 | return documentation
305 | }
306 |
307 | /**
308 | * Gets the documentation for the links in `links`
309 | *
310 | * @param {{
311 | * functionLinks: string[]
312 | * variableLinks: string[]
313 | * classLinks: string[]
314 | * }} links
315 | * - Links go get documenttion from
316 | */
317 | const documentLinks = async ({classLinks, functionLinks, variableLinks}) => {
318 | /**
319 | * All documentation (final object dumped to JSON)
320 | *
321 | * @type {import("../../src/types").Documentation}
322 | */
323 | const documentation = {}
324 |
325 | const fetchPromises = [] // Get documentation asynchronously
326 |
327 | console.log(` Getting documentation for ${functionLinks.length} functions`)
328 | for (const link of functionLinks) {
329 | // Document functions
330 | const job = (async () => {
331 | const doc = await documentFunction(link)
332 |
333 | if (doc) {
334 | documentation[doc.name.replace(/\(\)/gu, "")] = {
335 | ...doc,
336 | name: undefined,
337 | }
338 | }
339 | })()
340 |
341 | fetchPromises.push(job)
342 | }
343 |
344 | console.log(` Getting documentation for ${classLinks.length} classes`)
345 | for (const link of classLinks) {
346 | // Document classes
347 | const job = (async () => {
348 | const doc = await documentClass(link)
349 |
350 | if (doc) {
351 | documentation[doc.name.replace(/\(\)/gu, "")] = {
352 | ...doc,
353 | name: undefined,
354 | }
355 | }
356 | })()
357 |
358 | fetchPromises.push(job)
359 | }
360 |
361 | console.log(` Getting documentation for ${variableLinks.length} variables`)
362 | for (const link of variableLinks) {
363 | // Document variables
364 | const job = (async () => {
365 | const doc = await documentVariable(link)
366 |
367 | if (doc) {
368 | documentation[doc.name.replace(/\(\)/gu, "")] = {
369 | ...doc,
370 | name: undefined,
371 | }
372 | }
373 | })()
374 |
375 | fetchPromises.push(job)
376 | }
377 |
378 | await Promise.all(fetchPromises)
379 |
380 | return documentation
381 | }
382 |
383 | /**
384 | * @returns Documentation from https://processing.org/reference
385 | */
386 | export const getDocs = async () => {
387 | const links = await getDocLinks()
388 |
389 | if (!links) {
390 | return
391 | }
392 |
393 | console.log(
394 | `Got doc links for ${
395 | links.functionLinks.length + links.classLinks.length + links.variableLinks.length
396 | } items`,
397 | )
398 |
399 | const docs = await documentLinks(links)
400 |
401 | return docs
402 | }
403 |
404 | export default getDocs
405 |
--------------------------------------------------------------------------------
/scripts/writeDocs.mjs:
--------------------------------------------------------------------------------
1 | #!/bin/node
2 |
3 | /**
4 | * @file gets Documentation from https://processing.org/reference and dumps it into
5 | * `src/documentation-data.json` with some bootleg webscraping
6 | */
7 |
8 | import {dirname} from "path"
9 | import {fileURLToPath} from "url"
10 | import {promises as fs} from "fs"
11 | import yaml from "yaml"
12 | import getDocs from "./helpers/fetchDocs.mjs"
13 |
14 | const __dirname = dirname(fileURLToPath(import.meta.url))
15 |
16 | const docs = await getDocs()
17 |
18 | await fs.writeFile(
19 | `${__dirname}/../data/documentation-data.yml`,
20 | `# THIS IS AN AUTOGENERATED FILE; DO NOT EDIT DIRECTLY\n\n${yaml.stringify(docs, {
21 | sortMapEntries: true,
22 | })}`,
23 | "utf8",
24 | )
25 |
--------------------------------------------------------------------------------
/src/commands/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 |
7 | import {openDocumentation, openProcessingDocs, searchUnityDocs} from "./search"
8 | import {run as runProject} from "./run"
9 | import {shouldEnablePython} from "../config"
10 | import vscode from "vscode"
11 |
12 | export const subscribeCommands = (context: vscode.ExtensionContext): void => {
13 | context.subscriptions.push(vscode.commands.registerCommand("processing.Run", runProject))
14 |
15 | if (shouldEnablePython) {
16 | context.subscriptions.push(
17 | vscode.commands.registerCommand("processing.RunPy", () => runProject("py")),
18 | )
19 | }
20 |
21 | context.subscriptions.push(
22 | vscode.commands.registerCommand("processing.RunJava", () => runProject("java")),
23 | )
24 |
25 | context.subscriptions.push(
26 | vscode.commands.registerCommand(
27 | "processing.OpenExtensionDocumentation",
28 | openDocumentation,
29 | ),
30 | )
31 |
32 | // Open Processing Documentation, when you already have something you want to search selected
33 | context.subscriptions.push(
34 | vscode.commands.registerTextEditorCommand("processing.OpenDocs", openProcessingDocs),
35 | )
36 |
37 | context.subscriptions.push(
38 | vscode.commands.registerCommand("processing.SearchWebsite", searchUnityDocs),
39 | )
40 | }
41 |
42 | export default subscribeCommands
43 |
--------------------------------------------------------------------------------
/src/commands/run.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 |
7 | import {
8 | jarPath,
9 | javaCommand,
10 | processingCommand,
11 | shouldAlwaysQuotePath,
12 | shouldSendSigint,
13 | } from "../config"
14 | import path, {dirname} from "path"
15 | import {isValidProcessingProject} from "../utils"
16 | import vscode from "vscode"
17 |
18 | const pythonUtils = {
19 | getProjectFilename: ({fileName}: vscode.TextDocument): string =>
20 | shouldAlwaysQuotePath || / |\\/u.test(fileName) ? `"${fileName}"` : fileName,
21 |
22 | getJarFilename: (): string =>
23 | shouldAlwaysQuotePath || / |\\/u.test(jarPath) ? `"${jarPath}"` : jarPath,
24 | }
25 |
26 | class RunManager {
27 | private _terminal?: vscode.Terminal = undefined
28 |
29 | private _pythonTerminal?: vscode.Terminal = undefined
30 |
31 | public run = (mode?: "py" | "java"): void => {
32 | const {activeTextEditor: editor} = vscode.window
33 |
34 | if (!editor) {
35 | vscode.window.showErrorMessage("No active text editor found")
36 |
37 | return
38 | }
39 |
40 | const processingMode = (() => {
41 | if (mode) {
42 | return mode
43 | }
44 |
45 | if (/\.pde$/u.test(editor.document.fileName)) {
46 | return "java"
47 | } else if (editor.document.languageId === "python") {
48 | return "py"
49 | }
50 |
51 | return
52 | })()
53 |
54 | if (processingMode === "java") {
55 | this._runJavaMode(editor)
56 | } else if (processingMode === "py") {
57 | this._runPythonMode(editor)
58 | } else {
59 | vscode.window.showErrorMessage("Could not determine processing mode.")
60 | }
61 | }
62 |
63 | /**
64 | * This monstrosity searches for an existing terminal if it exists or creates a new one and returns it.
65 | *
66 | * @param terminalName - Key of terminal in class
67 | * @param terminalDisplayName - Display name of terminal
68 | * @returns Vscode terminal
69 | */
70 | private _getTerminal = (
71 | terminalName: "_terminal" | "_pythonTerminal",
72 | terminalDisplayName: string,
73 | ): vscode.Terminal =>
74 | (this[terminalName] !== undefined && this[terminalName]?.exitStatus === undefined // Terminal exists
75 | ? vscode.window.terminals.find((terminal) => terminal.name === terminalDisplayName) // Find existing terminal
76 | : (this[terminalName] = vscode.window.createTerminal(terminalDisplayName))) ?? // Terminal doesn't exist; create a new terminal
77 | (this[terminalName] = vscode.window.createTerminal(terminalDisplayName)) // Somehow couldn't find an existing terminal
78 |
79 | /**
80 | * Runs the current project in Java mode
81 | *
82 | * @param editor - Vscode text editor
83 | */
84 | private _runJavaMode = (editor: vscode.TextEditor): void => {
85 | const terminalName = "_terminal"
86 | const hasTerminal =
87 | this[terminalName] !== undefined && this[terminalName]?.exitStatus === undefined
88 | const currentTerminal = this._getTerminal(terminalName, "Processing")
89 |
90 | let sketchName = dirname(editor.document.fileName)
91 | const isValidProjectName = isValidProcessingProject(sketchName.split(path.sep).pop())
92 | const shouldQuotePath = shouldAlwaysQuotePath || / |\\/u.test(sketchName)
93 |
94 | if (shouldQuotePath) {
95 | sketchName = `"${sketchName}"`
96 | }
97 |
98 | currentTerminal.show()
99 |
100 | if (!isValidProjectName) {
101 | vscode.window.showWarningMessage(
102 | "Warning: Processing project names must be valid Java variable names. Your program may fail to run properly.",
103 | )
104 | }
105 |
106 | // If file is a processing project file
107 | const cmd = `${
108 | hasTerminal && shouldSendSigint ? "\x03" : ""
109 | }${processingCommand} --sketch=${sketchName} --run`
110 |
111 | currentTerminal.sendText(cmd)
112 | }
113 |
114 | /**
115 | * Runs the current project in Python mode
116 | *
117 | * @param editor - Vscode text editor
118 | */
119 | private _runPythonMode = (editor: vscode.TextEditor): void => {
120 | const terminalName = "_terminal"
121 | const hasTerminal =
122 | this[terminalName] !== undefined && this[terminalName]?.exitStatus === undefined
123 | const currentTerminal = this._getTerminal(terminalName, "Processing-py")
124 |
125 | currentTerminal.show()
126 |
127 | // If file is a processing project file
128 | const cmd = `${
129 | hasTerminal && shouldSendSigint ? "\x03" : ""
130 | }${javaCommand} -jar ${pythonUtils.getJarFilename()} ${pythonUtils.getProjectFilename(
131 | editor.document,
132 | )}`
133 |
134 | currentTerminal.sendText(cmd)
135 | }
136 | }
137 |
138 | const runManager = new RunManager()
139 |
140 | /**
141 | * Runs the current processing project
142 | *
143 | * @param editor - Vscode text editor
144 | * @param log - Vscode output log
145 | */
146 | export const {run} = runManager
147 |
--------------------------------------------------------------------------------
/src/commands/search.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2016 - 2020 Tobiah Zarlez, 2021 Luke Zhang
5 | */
6 |
7 | import {search} from "../utils"
8 | import vscode from "vscode"
9 |
10 | const openDocErrorMessage = async (str: string) => {
11 | const item = await vscode.window.showErrorMessage(`Error: ${str}`, "Open Docs")
12 |
13 | if (item === "Open Docs") {
14 | search.openURL("docs")
15 | }
16 | }
17 |
18 | export const openDocumentation = () => {
19 | search.openURL(
20 | "https://github.com/Luke-zhang-04/processing-vscode#processing-for-visual-studio-code",
21 | )
22 | }
23 |
24 | export const openProcessingDocs = (textEditor: vscode.TextEditor) => {
25 | // selection[0] is the start, and selection[1] is the end
26 | const {selection} = textEditor
27 |
28 | if (!selection.isSingleLine) {
29 | openDocErrorMessage("Multiple lines selected, please select a class or function.")
30 |
31 | return
32 | }
33 |
34 | let range = undefined
35 |
36 | if (selection.isEmpty) {
37 | // selection is empty, get any word at cursor
38 | range = textEditor.document.getWordRangeAtPosition(selection.active)
39 | } else {
40 | // selection is not empty, get text from it
41 | range = new vscode.Range(selection.start, selection.end)
42 | }
43 |
44 | if (range === undefined) {
45 | openDocErrorMessage(
46 | 'Nothing is selected. Please select a class, or use "Search Documentation" instead!',
47 | )
48 |
49 | return
50 | }
51 |
52 | search.openProcessingDocs(
53 | textEditor.document.lineAt(range.start.line).text,
54 | range.start.character,
55 | range.end.character,
56 | )
57 | }
58 |
59 | export const searchUnityDocs = () => {
60 | vscode.window
61 | .showInputBox({
62 | prompt: "Search Processing Website:",
63 | })
64 | .then((result: string | undefined) => {
65 | if (result !== undefined) {
66 | // Use the node module "open" to open a web browser
67 | search.openURL("docs", result)
68 | }
69 | })
70 | }
71 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 |
7 | import {escapeExecutablePath} from "./utils"
8 | import vscode from "vscode"
9 |
10 | const getProcessingCommand = (): string => {
11 | // Look for processing.processingPath, then processing.path, then default to processing-java
12 | const config = vscode.workspace
13 | .getConfiguration()
14 | .get(
15 | "processing.processingPath",
16 | vscode.workspace.getConfiguration().get("processing.path", "processing-java"),
17 | )
18 |
19 | if (typeof config !== "string") {
20 | const msg = "Config option processing.processingPath must be of type string"
21 |
22 | vscode.window.showErrorMessage(msg)
23 |
24 | return "processing-java"
25 | }
26 |
27 | return escapeExecutablePath(config)
28 | }
29 |
30 | const getJavaCommand = (): string => {
31 | const config = vscode.workspace
32 | .getConfiguration()
33 | .get("processing.py.javaPath", "java")
34 |
35 | if (typeof config !== "string") {
36 | const msg = "Config option processing.py.javaPath must be of type string"
37 |
38 | vscode.window.showErrorMessage(msg)
39 |
40 | return "java"
41 | }
42 |
43 | return config
44 | }
45 |
46 | const getJarPath = (): string => {
47 | const config = vscode.workspace
48 | .getConfiguration()
49 | .get("processing.py.jarPath", "processing-py.jar")
50 |
51 | if (typeof config !== "string") {
52 | const msg = "Config option processing.py.jarPath must be of type string"
53 |
54 | vscode.window.showErrorMessage(msg)
55 |
56 | return "processing-py.jar"
57 | }
58 |
59 | return config
60 | }
61 |
62 | const getShouldEnablePython = (): boolean => {
63 | const isEnabled = vscode.workspace
64 | .getConfiguration()
65 | .get("processing.py.isEnabled", true)
66 |
67 | if (typeof isEnabled !== "boolean") {
68 | const msg = "Config option processing.py.isEnabled should be a boolean"
69 |
70 | vscode.window.showErrorMessage(msg)
71 |
72 | return true
73 | }
74 |
75 | return isEnabled
76 | }
77 |
78 | type SearchEngines = "Google" | "DuckDuckGo"
79 | type DocOptions = "processing.org" | "p5js.org" | "py.processing.org" | "auto"
80 |
81 | const getSearchConfig = (): {searchEngine: SearchEngines; processingDocs: DocOptions} => {
82 | const config = vscode.workspace.getConfiguration("processing")
83 | const processingDocs = config.get("docs", "auto")
84 | const searchEngine = config.get("search", "Google")
85 |
86 | if (!["processing.org", "p5js.org", "py.processing.org", "auto"].includes(processingDocs)) {
87 | const msg =
88 | 'Config option processing.docs must be "processing.org" | "p5js.org" | "py.processing.org" | "auto"'
89 |
90 | vscode.window.showErrorMessage(msg)
91 |
92 | return {searchEngine: "Google", processingDocs: "auto"}
93 | } else if (!["Google", "DuckDuckGo"].includes(searchEngine)) {
94 | const msg = 'Config option processing.search must be "Google" | "DuckDuckGo"'
95 |
96 | vscode.window.showErrorMessage(msg)
97 |
98 | return {searchEngine: "Google", processingDocs: "auto"}
99 | }
100 |
101 | return {
102 | searchEngine,
103 | processingDocs,
104 | }
105 | }
106 |
107 | const getshouldEnableDiagnostics = (): boolean => {
108 | const shouldGiveDiagnostics = vscode.workspace
109 | .getConfiguration()
110 | .get("processing.shouldGiveDiagnostics", true)
111 |
112 | if (typeof shouldGiveDiagnostics !== "boolean") {
113 | const msg = "Config option processing.shouldGiveDiagnostics must be of type boolean"
114 |
115 | vscode.window.showErrorMessage(msg)
116 |
117 | return true
118 | }
119 |
120 | return shouldGiveDiagnostics
121 | }
122 |
123 | const getQuoteEnablement = (): boolean => {
124 | const shouldQuotePath = vscode.workspace
125 | .getConfiguration()
126 | .get<"always" | "auto">("processing.runPathQuotes", "auto")
127 |
128 | if (shouldQuotePath !== "always" && shouldQuotePath !== "auto") {
129 | const msg = 'Config option processing.runPathQuotes should be "auto" or "always"'
130 |
131 | vscode.window.showErrorMessage(msg)
132 |
133 | return false
134 | }
135 |
136 | return shouldQuotePath === "always"
137 | }
138 |
139 | const getShouldSendSigint = (): boolean => {
140 | const isEnabled = vscode.workspace
141 | .getConfiguration()
142 | .get("processing.shouldSendSigint", false)
143 |
144 | if (typeof isEnabled !== "boolean") {
145 | const msg = "Config option processing.shouldSendSigint must be of type boolean"
146 |
147 | vscode.window.showErrorMessage(msg)
148 |
149 | throw new Error(msg)
150 | }
151 |
152 | return isEnabled
153 | }
154 |
155 | export let processingCommand = getProcessingCommand()
156 | export let javaCommand = getJavaCommand()
157 | export let jarPath = getJarPath()
158 | export let shouldEnablePython = getShouldEnablePython()
159 | export let searchConfig = getSearchConfig()
160 | export let shouldEnableDiagnostics = getshouldEnableDiagnostics()
161 | export let shouldAlwaysQuotePath = getQuoteEnablement()
162 | export let shouldSendSigint = getShouldSendSigint()
163 |
164 | vscode.workspace.onDidChangeConfiguration(() => {
165 | processingCommand = getProcessingCommand()
166 | javaCommand = getJavaCommand()
167 | jarPath = getJarPath()
168 | shouldEnablePython = getShouldEnablePython()
169 | searchConfig = getSearchConfig()
170 | shouldEnableDiagnostics = getshouldEnableDiagnostics()
171 | shouldAlwaysQuotePath = getQuoteEnablement()
172 | shouldSendSigint = getShouldSendSigint()
173 | })
174 |
--------------------------------------------------------------------------------
/src/diagnostics.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 |
7 | import path, {dirname} from "path"
8 | import childProcess from "child_process"
9 | import crypto from "crypto"
10 | import {isValidProcessingProject} from "./utils"
11 | import {processingCommand} from "./config"
12 | import vscode from "vscode"
13 |
14 | let oldHash = ""
15 |
16 | const hash = (content: {toString: () => string}) =>
17 | crypto.createHash("sha384").update(content.toString()).digest("hex")
18 |
19 | const createDiagnostic = (
20 | lineOfText: vscode.TextLine,
21 | lineIndex: number,
22 | charIndex: number,
23 | message: string,
24 | ): vscode.Diagnostic => {
25 | const range = new vscode.Range(lineIndex, charIndex, lineIndex, lineOfText.text.length)
26 |
27 | const diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Error)
28 |
29 | diagnostic.code = "processing-java"
30 |
31 | return diagnostic
32 | }
33 |
34 | const refreshDiagnostics = async (
35 | diagnostics: vscode.DiagnosticCollection,
36 | doc: vscode.TextDocument,
37 | log: vscode.OutputChannel,
38 | ): Promise => {
39 | try {
40 | const foundDiagnostics: vscode.Diagnostic[] = []
41 | let sketchName = doc.fileName.includes(".pde") ? dirname(doc.fileName) : undefined
42 |
43 | if (
44 | sketchName &&
45 | doc.getText() &&
46 | isValidProcessingProject(sketchName.split(path.sep).pop())
47 | ) {
48 | const shouldQuotePath = sketchName.includes(" ")
49 |
50 | if (shouldQuotePath) {
51 | sketchName = `"${sketchName}"`
52 | }
53 |
54 | console.log({sketchName})
55 | const diagnostic = await new Promise((resolve) => {
56 | const processingProcess = childProcess.spawn(processingCommand, [
57 | `--sketch=${sketchName}`,
58 | "--build",
59 | ])
60 |
61 | const problems: string[] = []
62 |
63 | const handleOutput = (data: Buffer): void => {
64 | for (const line of data.toString().split("\n")) {
65 | if (/(:[0-9]+){4}:/gu.test(line)) {
66 | problems.push(line)
67 | }
68 | }
69 | }
70 |
71 | processingProcess.stderr.on("data", handleOutput)
72 | processingProcess.stdout.on("data", handleOutput)
73 |
74 | processingProcess.on("exit", () => {
75 | resolve(problems)
76 | })
77 | }).catch(() => undefined)
78 |
79 | if (!diagnostic) {
80 | return
81 | }
82 |
83 | if (diagnostic.length > 0) {
84 | log.appendLine(diagnostic.toString())
85 | }
86 |
87 | for (const result of diagnostic) {
88 | const splitResult = result.split(":")
89 | const lineIndex = Number(splitResult[1]) - 1
90 | const charIndex = Number(splitResult[2]) - 2
91 |
92 | foundDiagnostics.push(
93 | createDiagnostic(
94 | doc.lineAt(lineIndex),
95 | lineIndex > 0 ? lineIndex : 0,
96 | charIndex > 0 ? charIndex : 0,
97 | splitResult.slice(5).join("").trim(),
98 | ),
99 | )
100 | }
101 |
102 | diagnostics.set(doc.uri, foundDiagnostics)
103 | }
104 | } catch (_) {}
105 | }
106 |
107 | export const subscribeDiagnostics = (
108 | diagnostics: vscode.DiagnosticCollection,
109 | context: vscode.ExtensionContext,
110 | log: vscode.OutputChannel,
111 | ): void => {
112 | let isRunning = false
113 | let shouldRunAgain = false
114 |
115 | const runDiagnostics = async (
116 | editor: vscode.TextEditor | vscode.TextDocumentChangeEvent,
117 | ): Promise => {
118 | if (isRunning) {
119 | shouldRunAgain = true
120 | } else {
121 | isRunning = true
122 |
123 | oldHash = `${editor.document.fileName} = ${hash(editor.document.getText())}`
124 |
125 | await refreshDiagnostics(diagnostics, editor.document, log)
126 |
127 | let newHash = `${editor.document.fileName} = ${hash(editor.document.getText())}`
128 |
129 | while (shouldRunAgain || oldHash !== newHash) {
130 | shouldRunAgain = false
131 | oldHash = newHash
132 |
133 | await refreshDiagnostics(diagnostics, editor.document, log)
134 |
135 | newHash = `${editor.document.fileName} = ${hash(editor.document.getText())}`
136 |
137 | if (!shouldRunAgain || oldHash === newHash) {
138 | break
139 | }
140 | }
141 |
142 | await refreshDiagnostics(diagnostics, editor.document, log)
143 |
144 | isRunning = false
145 | }
146 | }
147 |
148 | if (vscode.window.activeTextEditor) {
149 | const editor = vscode.window.activeTextEditor
150 |
151 | runDiagnostics(editor)
152 | }
153 |
154 | context.subscriptions.push(
155 | vscode.window.onDidChangeActiveTextEditor((editor) => {
156 | if (editor && /\.pde/u.test(editor.document.fileName)) {
157 | runDiagnostics(editor)
158 | }
159 | }),
160 | )
161 |
162 | context.subscriptions.push(
163 | vscode.workspace.onDidChangeTextDocument((editor) => {
164 | if (/\.pde/u.test(editor.document.fileName)) {
165 | if (editor.contentChanges.length > 0) {
166 | runDiagnostics(editor)
167 | }
168 | }
169 | }),
170 | )
171 |
172 | context.subscriptions.push(
173 | vscode.workspace.onDidCloseTextDocument((doc) => diagnostics.delete(doc.uri)),
174 | )
175 | }
176 |
177 | export default subscribeDiagnostics
178 |
--------------------------------------------------------------------------------
/src/documentation-data.yml:
--------------------------------------------------------------------------------
1 | ../data/documentation-data.yml
--------------------------------------------------------------------------------
/src/documentation.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 |
7 | import type {
8 | Documentation,
9 | DocumentationClass,
10 | DocumentationFunction,
11 | DocumentationVariable,
12 | } from "./types"
13 | import documentation from "./documentation-data.yml"
14 | import vscode from "vscode"
15 |
16 | /**
17 | * Gets the hovered "thing" and returns it
18 | *
19 | * @param line - Contents of line
20 | * @param position - Position of hover
21 | */
22 | const getHoveredItem = (line: string, position: number): string | undefined => {
23 | if (/\/\//u.test(line.slice(0, position))) {
24 | return
25 | }
26 |
27 | const itemStart = (() => {
28 | let index = position
29 |
30 | for (; index >= 0 && index < line.length; index--) {
31 | if (!/[a-z]|[0-9]|_/iu.test(line[index]!)) {
32 | break
33 | }
34 | }
35 |
36 | return index + 1
37 | })()
38 |
39 | const itemEnd = (() => {
40 | let index = position
41 |
42 | for (; index >= 0 && index < line.length; index++) {
43 | if (!/[a-z]|[0-9]|_/iu.test(line[index]!)) {
44 | break
45 | }
46 | }
47 |
48 | return index
49 | })()
50 |
51 | return line.slice(itemStart, itemEnd)
52 | }
53 |
54 | const documentVariable = (
55 | info: DocumentationVariable,
56 | item: keyof typeof documentation,
57 | ): vscode.Hover =>
58 | new vscode.Hover([
59 | info.examples
60 | ? `\`\`\`js
61 | ${info.type} ${item}
62 | \`\`\`
63 | \`\`\`java
64 | // Examples
65 | ${info.examples}
66 | \`\`\``
67 | : `\`\`\`js
68 | ${info.type} ${item}
69 | \`\`\``,
70 | `${info.examples ? "" : `${item}\n\n`}${info.description}
71 |
72 | *@see* — [${info.docUrl}](${info.docUrl})
73 | `,
74 | ])
75 |
76 | const documentFuntion = (
77 | info: DocumentationFunction,
78 | item: keyof typeof documentation,
79 | ): vscode.Hover => {
80 | const params = Object.entries(info.parameters).map(([name, desc]) => {
81 | const typeDefs = desc.indexOf(":")
82 |
83 | if (typeDefs === -1) {
84 | return `*@param* \`${name}\` — ${desc}`
85 | }
86 |
87 | const formattedDesc = `\`${desc.slice(0, typeDefs)}\`${desc.slice(typeDefs)}`
88 |
89 | return `*@param* \`${name}\` — ${formattedDesc}`
90 | })
91 | const {returns} = info
92 |
93 | // Prepare yourself
94 | return new vscode.Hover([
95 | ...(info.syntax
96 | ? [
97 | `\`\`\`js
98 | ${info.type} ${item}
99 | \`\`\`
100 | \`\`\`java
101 | ${info.syntax}
102 | \`\`\``,
103 | ]
104 | : []),
105 | `${info.syntax ? "" : `${item}\n\n`}${info.description}
106 |
107 | *@see* — [${info.docUrl}](${info.docUrl})
108 |
109 | ${params.join("\n\n")}
110 |
111 | ${returns ? `*@returns* \`${returns}\`` : ""}
112 | `,
113 | ])
114 | }
115 |
116 | const documentClass = (
117 | info: DocumentationClass,
118 | item: keyof typeof documentation,
119 | ): vscode.Hover => {
120 | const params = Object.entries(info.parameters).map(([name, desc]) => {
121 | const typeDefs = desc.indexOf(":")
122 |
123 | if (typeDefs === -1) {
124 | return `*@param* \`${name}\` — ${desc}`
125 | }
126 |
127 | const formattedDesc = `\`${desc.slice(0, typeDefs)}\`${desc.slice(typeDefs)}`
128 |
129 | return `*@param* \`${name}\` — ${formattedDesc}`
130 | })
131 |
132 | // Prepare yourself
133 | return new vscode.Hover([
134 | ...(info.syntax
135 | ? [
136 | `\`\`\`js
137 | ${info.type} ${item}
138 | \`\`\`
139 | \`\`\`java
140 | ${info.syntax}
141 | \`\`\``,
142 | ]
143 | : []),
144 | `${info.syntax ? "" : `${item}\n\n`}${info.description}
145 |
146 | *@see* — [${info.docUrl}](${info.docUrl})
147 |
148 | ${params.join("\n\n")}
149 | `,
150 | ])
151 | }
152 |
153 | vscode.languages.registerHoverProvider(
154 | {scheme: "file", language: "pde"},
155 | {
156 | provideHover: (document, position) => {
157 | const line = document.lineAt(position.line)
158 | const item = getHoveredItem(line.text, position.character) as
159 | | keyof typeof documentation
160 | | undefined
161 |
162 | if (item === undefined) {
163 | return
164 | }
165 |
166 | const info = (documentation as Documentation)[item]
167 |
168 | if (!info) {
169 | return
170 | } else if (info.type === "function") {
171 | return documentFuntion(info, item)
172 | } else if (info.type === "class") {
173 | return documentClass(info, item)
174 | }
175 |
176 | // Not a function or class, therefore a variable
177 | return documentVariable(info, item)
178 | },
179 | },
180 | )
181 |
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.yml" {
2 | const content: {[key: string]: unknown}
3 |
4 | export default content
5 | }
6 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @version 2.4.1
5 | * @copyright (C) 2016 - 2020 Tobiah Zarlez, 2021 Luke Zhang
6 | */
7 |
8 | import {processingCommand, shouldEnableDiagnostics} from "./config"
9 | import isValidProcessingCommand from "./validateCommand"
10 | import subscribeCommands from "./commands"
11 | import subscribeDiagnostics from "./diagnostics"
12 | import vscode from "vscode"
13 |
14 | export const activate = async (context: vscode.ExtensionContext) => {
15 | const log = vscode.window.createOutputChannel("Processing")
16 |
17 | log.appendLine("Activating Processing language extension...")
18 |
19 | subscribeCommands(context)
20 |
21 | if (shouldEnableDiagnostics) {
22 | if (await isValidProcessingCommand(processingCommand)) {
23 | const pdeDiagnostics = vscode.languages.createDiagnosticCollection("processing")
24 |
25 | context.subscriptions.push(pdeDiagnostics)
26 | subscribeDiagnostics(pdeDiagnostics, context, log)
27 | } else {
28 | log.appendLine(
29 | `ERROR! The configured processing command ${processingCommand} could not be executed.`,
30 | )
31 | log.show()
32 | }
33 | }
34 |
35 | await import("./documentation")
36 |
37 | log.appendLine("Processing language extension is now active!")
38 | }
39 |
40 | // this method is called when your extension is deactivated
41 | export const deactivate = () => {}
42 |
--------------------------------------------------------------------------------
/src/types.d.ts:
--------------------------------------------------------------------------------
1 | export interface DocumentationClass {
2 | description: string
3 | syntax: string
4 | parameters: {[key: string]: string}
5 | docUrl: string
6 | type: "class"
7 | }
8 |
9 | export interface DocumentationFunction {
10 | description: string
11 | syntax: string
12 | parameters: {[key: string]: string}
13 | returns: string
14 | docUrl: string
15 | type: "function"
16 | }
17 |
18 | export interface DocumentationVariable {
19 | description: string
20 | examples?: string
21 | docUrl: string
22 | type: "var" | "const"
23 | }
24 |
25 | export type Documentation = {
26 | [key: string]: DocumentationFunction | DocumentationVariable | DocumentationClass
27 | }
28 |
--------------------------------------------------------------------------------
/src/utils/escapePath.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 |
7 | export const escapeExecutablePath = (pathName: string): string => {
8 | if (!/ /gu.test(pathName)) {
9 | return pathName
10 | }
11 |
12 | let isWindowsPath = /[a-zA-Z]:[\\/](?:[a-zA-Z0-9]+[\\/])*([a-zA-Z0-9]+)/gu.test(pathName)
13 |
14 | if (!/[\\/]/gu.test(pathName)) {
15 | isWindowsPath = process.platform === "win32"
16 | }
17 |
18 | if (isWindowsPath) {
19 | // Windows path
20 | return pathName.replace(/(?
11 | path !== undefined && /^[/_$a-z][/\w$]*$/iu.test(path)
12 |
--------------------------------------------------------------------------------
/src/utils/search.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2016 - 2020 Tobiah Zarlez, 2021 Luke Zhang
5 | */
6 |
7 | import type {Documentation} from "../types"
8 | import documentation from "../documentation-data.yml"
9 | import {searchConfig} from "../config"
10 | import vscode from "vscode"
11 |
12 | const enum Urls {
13 | ProcessingorgDocs = "https://processing.org/reference/",
14 | ProcessingorgSearchGoogle = "https://www.google.com/search?as_sitesearch=processing.org&as_q=",
15 | ProcessingorgSearchDuckDuckGo = "https://duckduckgo.com/?q=!processing+%5C",
16 | P5jsDocs = "https://p5js.org/reference/",
17 | P5jsSearchGoogle = "https://www.google.com/search?as_sitesearch=p5js.org&as_q=",
18 | P5jsSearchDuckDuckGo = "https://duckduckgo.com/?q=!p5+",
19 | PyDocs = "https://py.processing.org/reference/",
20 | PySearchGoogle = "https://www.google.com/search?as_sitesearch=py.processing.org&as_q=",
21 | PySearchDuckDuckGo = "https://duckduckgo.com/?q=%5Csite%3Apy.processing.org+",
22 | }
23 |
24 | export const openURL = async (searchBase?: string, url?: string): Promise => {
25 | if (searchBase === "open") {
26 | await vscode.env.openExternal(vscode.Uri.parse(url as string))
27 | } else {
28 | const {processingDocs, searchEngine} = searchConfig
29 | const searchUrl = ((): string => {
30 | let directDocUrl: string | undefined
31 |
32 | if (searchBase === "docs") {
33 | const {
34 | window: {activeTextEditor},
35 | } = vscode
36 | const languageId = activeTextEditor?.document.languageId
37 |
38 | if (!url) {
39 | if (processingDocs === "p5js.org") {
40 | return Urls.P5jsDocs
41 | } else if (
42 | (processingDocs === "auto" && languageId === "pyton") ||
43 | processingDocs === "py.processing.org"
44 | ) {
45 | return Urls.PyDocs
46 | }
47 |
48 | // (processingDocs === "auto" && languageId === "pde")
49 | // || processingDocs === "processing.org"
50 | return Urls.ProcessingorgDocs
51 | } else if (
52 | // Look for entry directly in documentation data
53 | (processingDocs === "auto" || processingDocs === "processing.org") &&
54 | languageId === "pde" &&
55 | (directDocUrl = (documentation as Documentation)[url]?.docUrl) !== undefined
56 | ) {
57 | return directDocUrl
58 | } else if (searchEngine === "DuckDuckGo") {
59 | // Search Engine == "google"
60 | if (processingDocs === "p5js.org") {
61 | return `${Urls.P5jsSearchDuckDuckGo}${url}`
62 | } else if (
63 | (processingDocs === "auto" && languageId === "pyton") ||
64 | processingDocs === "py.processing.org"
65 | ) {
66 | return `${Urls.PySearchDuckDuckGo}${url}`
67 | }
68 |
69 | // (processingDocs === "auto" && languageId === "pde")
70 | // || processingDocs === "processing.org"
71 | return `${Urls.ProcessingorgSearchDuckDuckGo}${url}`
72 | }
73 |
74 | // Search Engine == "google"
75 | if (processingDocs === "p5js.org") {
76 | return `${Urls.P5jsSearchGoogle}${url}`
77 | } else if (
78 | (processingDocs === "auto" && languageId === "pyton") ||
79 | processingDocs === "py.processing.org"
80 | ) {
81 | return `${Urls.PySearchGoogle}${url}`
82 | }
83 |
84 | // (processingDocs === "auto" && languageId === "pde")
85 | // || processingDocs === "processing.org"
86 | return `${Urls.ProcessingorgSearchGoogle}${url}`
87 | }
88 |
89 | return searchBase ?? ""
90 | })()
91 |
92 | await vscode.env.openExternal(vscode.Uri.parse(searchUrl))
93 | }
94 |
95 | return
96 | }
97 |
98 | // Slice and Trim
99 | export const prepareInput = (input: string, start: number, end: number) => {
100 | // input is the whole line, part of which is selected by the user (defined by star/end)
101 |
102 | if (start >= end) {
103 | return ""
104 | }
105 |
106 | // Everything looks good by this point, so time to open a web browser!
107 | return input.slice(start, end).trim()
108 | }
109 |
110 | export const openProcessingDocs = (input: string, start: number, end: number) => {
111 | // Use the node module "opn" to open a web browser
112 | openURL("docs", prepareInput(input, start, end))
113 | }
114 |
--------------------------------------------------------------------------------
/src/validateCommand.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Processing-vscode - Processing Language Support for VSCode
3 | *
4 | * @copyright (C) 2021 Luke Zhang
5 | */
6 | import childProcess from "child_process"
7 |
8 | export const isValidProcessingCommand = async (cmd: string): Promise => {
9 | const result = await new Promise((resolve) => {
10 | const processingProcess = childProcess.spawn(cmd, ["--help"])
11 |
12 | let output = ""
13 |
14 | processingProcess.stderr.on("data", (data) => (output += data.toString()))
15 | processingProcess.stdout.on("data", (data) => (output += data.toString()))
16 |
17 | processingProcess.on("exit", () => {
18 | resolve(output.trim())
19 | })
20 |
21 | processingProcess.on("error", () => resolve(false))
22 | })
23 |
24 | return typeof result === "boolean"
25 | ? result
26 | : /Command line edition for Processing/u.test(result)
27 | }
28 |
29 | export default isValidProcessingCommand
30 |
--------------------------------------------------------------------------------
/syntaxes/pde.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "information_for_contributors": [
3 | "This file has is based off https://github.com/microsoft/vscode/blob/main/extensions/java/syntaxes/java.tmLanguage.json"
4 | ],
5 | "scopeName": "source.pde",
6 | "uuid": "fa3cf963-f9b4-4e28-949d-af2b8d279f97",
7 | "name": "Processing",
8 | "fileTypes": ["pde", "bsh"],
9 | "patterns": [
10 | {
11 | "begin": "\\b(package)\\b\\s*",
12 | "beginCaptures": {
13 | "1": {
14 | "name": "keyword.other.package.processing"
15 | }
16 | },
17 | "end": "\\s*(;)",
18 | "endCaptures": {
19 | "1": {
20 | "name": "punctuation.terminator.processing"
21 | }
22 | },
23 | "name": "meta.package.processing",
24 | "contentName": "storage.modifier.package.processing",
25 | "patterns": [
26 | {
27 | "include": "#comments"
28 | },
29 | {
30 | "match": "(?<=\\.)\\s*\\.|\\.(?=\\s*;)",
31 | "name": "invalid.illegal.character_not_allowed_here.processing"
32 | },
33 | {
34 | "match": "(?",
859 | "endCaptures": {
860 | "0": {
861 | "name": "punctuation.bracket.angle.processing"
862 | }
863 | },
864 | "patterns": [
865 | {
866 | "match": "\\b(extends|super)\\b",
867 | "name": "storage.modifier.$1.processing"
868 | },
869 | {
870 | "match": "(?>>?|~|\\^)",
931 | "name": "keyword.operator.bitwise.processing"
932 | },
933 | {
934 | "match": "((&|\\^|\\||<<|>>>?)=)",
935 | "name": "keyword.operator.assignment.bitwise.processing"
936 | },
937 | {
938 | "match": "(===?|!=|<=|>=|<>|<|>)",
939 | "name": "keyword.operator.comparison.processing"
940 | },
941 | {
942 | "match": "([+*/%-]=)",
943 | "name": "keyword.operator.assignment.arithmetic.processing"
944 | },
945 | {
946 | "match": "(=)",
947 | "name": "keyword.operator.assignment.processing"
948 | },
949 | {
950 | "match": "(\\-\\-|\\+\\+)",
951 | "name": "keyword.operator.increment-decrement.processing"
952 | },
953 | {
954 | "match": "(\\-|\\+|\\*|\\/|%)",
955 | "name": "keyword.operator.arithmetic.processing"
956 | },
957 | {
958 | "match": "(!|&&|\\|\\|)",
959 | "name": "keyword.operator.logical.processing"
960 | },
961 | {
962 | "match": "(\\||&)",
963 | "name": "keyword.operator.bitwise.processing"
964 | },
965 | {
966 | "match": "\\b(const|goto)\\b",
967 | "name": "keyword.reserved.processing"
968 | },
969 | {
970 | "match": "\\b(Array|Character|FloatDict|FloatList|IntDict|IntList|Integer|JSONArray|JSONObject|Math|Object|PFont|PGraphics|PImage|PShader|PShape|PSound|PVector|String|StringBuffer|StringDict|StringList|Table|TableRow|Thread|XML|Byte|Short|Long|Float|Double|Boolean|System)\\b",
971 | "name": "support.class.processing"
972 | },
973 | {
974 | "match": "\\b(ADD|ALIGN_CENTER|ALIGN_LEFT|ALIGN_RIGHT|ALPHA|ALPHA_MASK|ALT|AMBIENT|ARGB|ARROW|BACKSPACE|BEVEL|BLEND|BLUE_MASK|BLUR|CENTER|CENTER_RADIUS|CHATTER|CODED|COMPLAINT|COMPONENT|COMPOSITE|CONCAVE_POLYGON|CONTROL|CONVEX_POLYGON|CORNER|CORNERS|CROSS|CUSTOM|DARKEST|DEGREES|DEG_TO_RAD|DELETE|DIFFERENCE|DIFFUSE|DISABLED|DISABLE_TEXT_SMOOTH|DOWN|ENTER|EPSILON|ESC|FX2D|GIF|GREEN_MASK|GREY|HALF|HALF_PI|HAND|HARD_LIGHT|HSB|IMAGE|INVERT|JAVA2D|JPEG|LEFT|LIGHTEST|LINES|LINE_LOOP|LINE_STRIP|MAX_FLOAT|MITER|MODEL|MOVE|MULTIPLY|NORMALIZED|NO_DEPTH_TEST|NTSC|ONE|OPAQUE|OPENGL|ORTHOGRAPHIC|OVERLAY|P2D|P3D|PAL|PDF|PERSPECTIVE|PI|PIXEL_CENTER|POINTS|POLYGON|POSTERIZE|PROBLEM|PROJECT|QUADS|QUAD_STRIP|QUARTER_PI|RADIANS|RAD_TO_DEG|RED_MASK|REPLACE|RETURN|RGB|RIGHT|ROUND|SCREEN|SECAM|SHIFT|SOFT_LIGHT|SPAN|SPECULAR|SQUARE|SUBTRACT|SVIDEO|TAB|TARGA|TEXT|TFF|THIRD_PI|THRESHOLD|TIFF|TRIANGLES|TRIANGLE_FAN|TRIANGLE_STRIP|TUNER|TAU|TWO|TWO_PI|UP|WAIT|WHITESPACE)\\b",
975 | "name": "constant.language.processing"
976 | }
977 | ]
978 | },
979 | "lambda-expression": {
980 | "patterns": [
981 | {
982 | "match": "->",
983 | "name": "storage.type.function.arrow.processing"
984 | }
985 | ]
986 | },
987 | "member-variables": {
988 | "begin": "(?=private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final)",
989 | "end": "(?=\\=|;)",
990 | "patterns": [
991 | {
992 | "include": "#storage-modifiers"
993 | },
994 | {
995 | "include": "#variables"
996 | },
997 | {
998 | "include": "#primitive-arrays"
999 | },
1000 | {
1001 | "include": "#object-types"
1002 | }
1003 | ]
1004 | },
1005 | "method-call": {
1006 | "begin": "(\\.)\\s*([A-Za-z_$][\\w$]*)\\s*(\\()",
1007 | "beginCaptures": {
1008 | "1": {
1009 | "name": "punctuation.separator.period.processing"
1010 | },
1011 | "2": {
1012 | "name": "entity.name.function.processing"
1013 | },
1014 | "3": {
1015 | "name": "punctuation.definition.parameters.begin.bracket.round.processing"
1016 | }
1017 | },
1018 | "end": "\\)",
1019 | "endCaptures": {
1020 | "0": {
1021 | "name": "punctuation.definition.parameters.end.bracket.round.processing"
1022 | }
1023 | },
1024 | "name": "meta.method-call.processing",
1025 | "patterns": [
1026 | {
1027 | "include": "#code"
1028 | }
1029 | ]
1030 | },
1031 | "methods": {
1032 | "begin": "(?!new)(?=[\\w<].*\\s+)(?=([^=/]|/(?!/))+\\()",
1033 | "end": "(})|(?=;)",
1034 | "endCaptures": {
1035 | "1": {
1036 | "name": "punctuation.section.method.end.bracket.curly.processing"
1037 | }
1038 | },
1039 | "name": "meta.method.processing",
1040 | "patterns": [
1041 | {
1042 | "include": "#storage-modifiers"
1043 | },
1044 | {
1045 | "begin": "(\\w+)\\s*(\\()",
1046 | "beginCaptures": {
1047 | "1": {
1048 | "name": "entity.name.function.processing"
1049 | },
1050 | "2": {
1051 | "name": "punctuation.definition.parameters.begin.bracket.round.processing"
1052 | }
1053 | },
1054 | "end": "\\)",
1055 | "endCaptures": {
1056 | "0": {
1057 | "name": "punctuation.definition.parameters.end.bracket.round.processing"
1058 | }
1059 | },
1060 | "name": "meta.method.identifier.processing",
1061 | "patterns": [
1062 | {
1063 | "include": "#parameters"
1064 | },
1065 | {
1066 | "include": "#parens"
1067 | },
1068 | {
1069 | "include": "#comments"
1070 | }
1071 | ]
1072 | },
1073 | {
1074 | "include": "#generics"
1075 | },
1076 | {
1077 | "begin": "(?=\\w.*\\s+\\w+\\s*\\()",
1078 | "end": "(?=\\s+\\w+\\s*\\()",
1079 | "name": "meta.method.return-type.processing",
1080 | "patterns": [
1081 | {
1082 | "include": "#all-types"
1083 | },
1084 | {
1085 | "include": "#parens"
1086 | },
1087 | {
1088 | "include": "#comments"
1089 | }
1090 | ]
1091 | },
1092 | {
1093 | "include": "#throws"
1094 | },
1095 | {
1096 | "begin": "{",
1097 | "beginCaptures": {
1098 | "0": {
1099 | "name": "punctuation.section.method.begin.bracket.curly.processing"
1100 | }
1101 | },
1102 | "end": "(?=})",
1103 | "contentName": "meta.method.body.processing",
1104 | "patterns": [
1105 | {
1106 | "include": "#code"
1107 | }
1108 | ]
1109 | },
1110 | {
1111 | "include": "#comments"
1112 | }
1113 | ]
1114 | },
1115 | "module": {
1116 | "begin": "((open)\\s)?(module)\\s+(\\w+)",
1117 | "end": "}",
1118 | "beginCaptures": {
1119 | "1": {
1120 | "name": "storage.modifier.processing"
1121 | },
1122 | "3": {
1123 | "name": "storage.modifier.processing"
1124 | },
1125 | "4": {
1126 | "name": "entity.name.type.module.processing"
1127 | }
1128 | },
1129 | "endCaptures": {
1130 | "0": {
1131 | "name": "punctuation.section.module.end.bracket.curly.processing"
1132 | }
1133 | },
1134 | "name": "meta.module.processing",
1135 | "patterns": [
1136 | {
1137 | "begin": "{",
1138 | "beginCaptures": {
1139 | "0": {
1140 | "name": "punctuation.section.module.begin.bracket.curly.processing"
1141 | }
1142 | },
1143 | "end": "(?=})",
1144 | "contentName": "meta.module.body.processing",
1145 | "patterns": [
1146 | {
1147 | "match": "\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b",
1148 | "name": "keyword.module.processing"
1149 | }
1150 | ]
1151 | }
1152 | ]
1153 | },
1154 | "numbers": {
1155 | "patterns": [
1156 | {
1157 | "match": "(?x)\n\\b(?)?(\\()",
1444 | "beginCaptures": {
1445 | "1": {
1446 | "name": "storage.modifier.processing"
1447 | },
1448 | "2": {
1449 | "name": "entity.name.type.record.processing"
1450 | },
1451 | "3": {
1452 | "patterns": [
1453 | {
1454 | "include": "#generics"
1455 | }
1456 | ]
1457 | },
1458 | "4": {
1459 | "name": "punctuation.definition.parameters.begin.bracket.round.processing"
1460 | }
1461 | },
1462 | "end": "\\)",
1463 | "endCaptures": {
1464 | "0": {
1465 | "name": "punctuation.definition.parameters.end.bracket.round.processing"
1466 | }
1467 | },
1468 | "name": "meta.record.identifier.processing",
1469 | "patterns": [
1470 | {
1471 | "include": "#code"
1472 | }
1473 | ]
1474 | },
1475 | {
1476 | "begin": "(implements)\\s",
1477 | "beginCaptures": {
1478 | "1": {
1479 | "name": "storage.modifier.implements.processing"
1480 | }
1481 | },
1482 | "end": "(?=\\s*\\{)",
1483 | "name": "meta.definition.class.implemented.interfaces.processing",
1484 | "patterns": [
1485 | {
1486 | "include": "#object-types-inherited"
1487 | },
1488 | {
1489 | "include": "#comments"
1490 | }
1491 | ]
1492 | },
1493 | {
1494 | "include": "#record-body"
1495 | }
1496 | ]
1497 | },
1498 | "record-body": {
1499 | "begin": "{",
1500 | "beginCaptures": {
1501 | "0": {
1502 | "name": "punctuation.section.class.begin.bracket.curly.processing"
1503 | }
1504 | },
1505 | "end": "(?=})",
1506 | "name": "meta.record.body.processing",
1507 | "patterns": [
1508 | {
1509 | "include": "#record-constructor"
1510 | },
1511 | {
1512 | "include": "#class-body"
1513 | }
1514 | ]
1515 | },
1516 | "record-constructor": {
1517 | "begin": "(?!new)(?=[\\w<].*\\s+)(?=([^\\(=/]|/(?!/))+(?={))",
1518 | "end": "(})|(?=;)",
1519 | "endCaptures": {
1520 | "1": {
1521 | "name": "punctuation.section.method.end.bracket.curly.processing"
1522 | }
1523 | },
1524 | "name": "meta.method.processing",
1525 | "patterns": [
1526 | {
1527 | "include": "#storage-modifiers"
1528 | },
1529 | {
1530 | "begin": "(\\w+)",
1531 | "beginCaptures": {
1532 | "1": {
1533 | "name": "entity.name.function.processing"
1534 | }
1535 | },
1536 | "end": "(?=\\s*{)",
1537 | "name": "meta.method.identifier.processing",
1538 | "patterns": [
1539 | {
1540 | "include": "#comments"
1541 | }
1542 | ]
1543 | },
1544 | {
1545 | "include": "#comments"
1546 | },
1547 | {
1548 | "begin": "{",
1549 | "beginCaptures": {
1550 | "0": {
1551 | "name": "punctuation.section.method.begin.bracket.curly.processing"
1552 | }
1553 | },
1554 | "end": "(?=})",
1555 | "contentName": "meta.method.body.processing",
1556 | "patterns": [
1557 | {
1558 | "include": "#code"
1559 | }
1560 | ]
1561 | }
1562 | ]
1563 | },
1564 | "static-initializer": {
1565 | "patterns": [
1566 | {
1567 | "include": "#anonymous-block-and-instance-initializer"
1568 | },
1569 | {
1570 | "match": "static",
1571 | "name": "storage.modifier.processing"
1572 | }
1573 | ]
1574 | },
1575 | "storage-modifiers": {
1576 | "match": "\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient|volatile|default|strictfp|sealed|non-sealed)\\b",
1577 | "name": "storage.modifier.processing"
1578 | },
1579 | "strings": {
1580 | "patterns": [
1581 | {
1582 | "begin": "\"",
1583 | "beginCaptures": {
1584 | "0": {
1585 | "name": "punctuation.definition.string.begin.processing"
1586 | }
1587 | },
1588 | "end": "\"",
1589 | "endCaptures": {
1590 | "0": {
1591 | "name": "punctuation.definition.string.end.processing"
1592 | }
1593 | },
1594 | "name": "string.quoted.double.processing",
1595 | "patterns": [
1596 | {
1597 | "match": "\\\\.",
1598 | "name": "constant.character.escape.processing"
1599 | }
1600 | ]
1601 | },
1602 | {
1603 | "begin": "'",
1604 | "beginCaptures": {
1605 | "0": {
1606 | "name": "punctuation.definition.string.begin.processing"
1607 | }
1608 | },
1609 | "end": "'",
1610 | "endCaptures": {
1611 | "0": {
1612 | "name": "punctuation.definition.string.end.processing"
1613 | }
1614 | },
1615 | "name": "string.quoted.single.processing",
1616 | "patterns": [
1617 | {
1618 | "match": "\\\\.",
1619 | "name": "constant.character.escape.processing"
1620 | }
1621 | ]
1622 | }
1623 | ]
1624 | },
1625 | "throws": {
1626 | "begin": "throws",
1627 | "beginCaptures": {
1628 | "0": {
1629 | "name": "storage.modifier.processing"
1630 | }
1631 | },
1632 | "end": "(?={|;)",
1633 | "name": "meta.throwables.processing",
1634 | "patterns": [
1635 | {
1636 | "match": ",",
1637 | "name": "punctuation.separator.delimiter.processing"
1638 | },
1639 | {
1640 | "match": "[a-zA-Z$_][\\.a-zA-Z0-9$_]*",
1641 | "name": "storage.type.processing"
1642 | }
1643 | ]
1644 | },
1645 | "try-catch-finally": {
1646 | "patterns": [
1647 | {
1648 | "begin": "\\btry\\b",
1649 | "beginCaptures": {
1650 | "0": {
1651 | "name": "keyword.control.try.processing"
1652 | }
1653 | },
1654 | "end": "}",
1655 | "endCaptures": {
1656 | "0": {
1657 | "name": "punctuation.section.try.end.bracket.curly.processing"
1658 | }
1659 | },
1660 | "name": "meta.try.processing",
1661 | "patterns": [
1662 | {
1663 | "begin": "\\(",
1664 | "beginCaptures": {
1665 | "0": {
1666 | "name": "punctuation.section.try.resources.begin.bracket.round.processing"
1667 | }
1668 | },
1669 | "end": "\\)",
1670 | "endCaptures": {
1671 | "0": {
1672 | "name": "punctuation.section.try.resources.end.bracket.round.processing"
1673 | }
1674 | },
1675 | "name": "meta.try.resources.processing",
1676 | "patterns": [
1677 | {
1678 | "include": "#code"
1679 | }
1680 | ]
1681 | },
1682 | {
1683 | "begin": "{",
1684 | "beginCaptures": {
1685 | "0": {
1686 | "name": "punctuation.section.try.begin.bracket.curly.processing"
1687 | }
1688 | },
1689 | "end": "(?=})",
1690 | "contentName": "meta.try.body.processing",
1691 | "patterns": [
1692 | {
1693 | "include": "#code"
1694 | }
1695 | ]
1696 | }
1697 | ]
1698 | },
1699 | {
1700 | "begin": "\\b(catch)\\b",
1701 | "beginCaptures": {
1702 | "1": {
1703 | "name": "keyword.control.catch.processing"
1704 | }
1705 | },
1706 | "end": "}",
1707 | "endCaptures": {
1708 | "0": {
1709 | "name": "punctuation.section.catch.end.bracket.curly.processing"
1710 | }
1711 | },
1712 | "name": "meta.catch.processing",
1713 | "patterns": [
1714 | {
1715 | "include": "#comments"
1716 | },
1717 | {
1718 | "begin": "\\(",
1719 | "beginCaptures": {
1720 | "0": {
1721 | "name": "punctuation.definition.parameters.begin.bracket.round.processing"
1722 | }
1723 | },
1724 | "end": "\\)",
1725 | "endCaptures": {
1726 | "0": {
1727 | "name": "punctuation.definition.parameters.end.bracket.round.processing"
1728 | }
1729 | },
1730 | "contentName": "meta.catch.parameters.processing",
1731 | "patterns": [
1732 | {
1733 | "include": "#comments"
1734 | },
1735 | {
1736 | "include": "#storage-modifiers"
1737 | },
1738 | {
1739 | "begin": "[a-zA-Z$_][\\.a-zA-Z0-9$_]*",
1740 | "beginCaptures": {
1741 | "0": {
1742 | "name": "storage.type.processing"
1743 | }
1744 | },
1745 | "end": "(\\|)|(?=\\))",
1746 | "endCaptures": {
1747 | "1": {
1748 | "name": "punctuation.catch.separator.processing"
1749 | }
1750 | },
1751 | "patterns": [
1752 | {
1753 | "include": "#comments"
1754 | },
1755 | {
1756 | "match": "\\w+",
1757 | "captures": {
1758 | "0": {
1759 | "name": "variable.parameter.processing"
1760 | }
1761 | }
1762 | }
1763 | ]
1764 | }
1765 | ]
1766 | },
1767 | {
1768 | "begin": "{",
1769 | "beginCaptures": {
1770 | "0": {
1771 | "name": "punctuation.section.catch.begin.bracket.curly.processing"
1772 | }
1773 | },
1774 | "end": "(?=})",
1775 | "contentName": "meta.catch.body.processing",
1776 | "patterns": [
1777 | {
1778 | "include": "#code"
1779 | }
1780 | ]
1781 | }
1782 | ]
1783 | },
1784 | {
1785 | "begin": "\\bfinally\\b",
1786 | "beginCaptures": {
1787 | "0": {
1788 | "name": "keyword.control.finally.processing"
1789 | }
1790 | },
1791 | "end": "}",
1792 | "endCaptures": {
1793 | "0": {
1794 | "name": "punctuation.section.finally.end.bracket.curly.processing"
1795 | }
1796 | },
1797 | "name": "meta.finally.processing",
1798 | "patterns": [
1799 | {
1800 | "begin": "{",
1801 | "beginCaptures": {
1802 | "0": {
1803 | "name": "punctuation.section.finally.begin.bracket.curly.processing"
1804 | }
1805 | },
1806 | "end": "(?=})",
1807 | "contentName": "meta.finally.body.processing",
1808 | "patterns": [
1809 | {
1810 | "include": "#code"
1811 | }
1812 | ]
1813 | }
1814 | ]
1815 | }
1816 | ]
1817 | },
1818 | "simple-types": {
1819 | "patterns": [
1820 | {
1821 | "match": "\\b(?:void|boolean|byte|char|short|int|float|long|double|color|String|PVector)\\b",
1822 | "name": "storage.type.simple.processing"
1823 | }
1824 | ]
1825 | },
1826 | "variables-local": {
1827 | "begin": "(?=\\b(var)\\b\\s+[A-Za-z_$][\\w$]*\\s*(=|:|;))",
1828 | "end": "(?=\\=|:|;)",
1829 | "name": "meta.definition.variable.local.processing",
1830 | "patterns": [
1831 | {
1832 | "match": "\\bvar\\b",
1833 | "name": "storage.type.local.processing"
1834 | },
1835 | {
1836 | "match": "([A-Za-z$_][\\w$]*)(?=\\s*(\\[\\])*\\s*(=|:|;))",
1837 | "captures": {
1838 | "1": {
1839 | "name": "variable.other.definition.processing"
1840 | }
1841 | }
1842 | },
1843 | {
1844 | "include": "#code"
1845 | }
1846 | ]
1847 | }
1848 | }
1849 | }
1850 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Basic Options */
6 | // "incremental": true, /* Enable incremental compilation */
7 | "target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
8 | "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9 | // "lib": [], /* Specify library files to be included in the compilation. */
10 | "allowJs": true, /* Allow javascript files to be compiled. */
11 | "checkJs": false, /* Report errors in .js files. */
12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
13 | "declaration": false, /* Generates corresponding '.d.ts' file. */
14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15 | // "sourceMap": true, /* Generates corresponding '.map' file. */
16 | // "outFile": "./", /* Concatenate and emit output to single file. */
17 | // "outDir": "./lib", /* Redirect output structure to the directory. */
18 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19 | // "composite": true, /* Enable project compilation */
20 | // "tsBuildInfoFile": "./tsbuildinfo", /* Specify file to store incremental compilation information */
21 | "removeComments": false, /* Do not emit comments to output. */
22 | "noEmit": true, /* Do not emit outputs. */
23 | "importHelpers": true, /* Import emit helpers from 'tslib'. */
24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 |
27 | /* Strict Type-Checking Options */
28 | "strict": true, /* Enable all strict type-checking options. */
29 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30 | "strictNullChecks": true, /* Enable strict null checks. */
31 | "strictFunctionTypes": true, /* Enable strict checking of function types. */
32 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36 |
37 | /* Additional Checks */
38 | "noUnusedLocals": true, /* Report errors on unused locals. */
39 | "noUnusedParameters": true, /* Report errors on unused parameters. */
40 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42 |
43 | /* Module Resolution Options */
44 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
45 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
48 | // "typeRoots": [], /* List of folders to include type definitions from. */
49 | // "types": [], /* Type declaration files to be included in compilation. */
50 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
51 | // "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
54 |
55 | /* Source Map Options */
56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
60 |
61 | /* Experimental Options */
62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
64 |
65 | /* Advanced Options */
66 | "skipLibCheck": false, /* Skip type checking of declaration files. */
67 | "skipDefaultLibCheck": true,
68 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
69 | "resolveJsonModule": true,
70 | "noUncheckedIndexedAccess": true,
71 | },
72 | "include": [
73 | "src"
74 | ]
75 | }
76 |
--------------------------------------------------------------------------------