Compare commits

..

No commits in common. "master" and "v1.0.0" have entirely different histories.

29 changed files with 958 additions and 2493 deletions

View File

@ -10,22 +10,15 @@ jobs:
build:
strategy:
matrix:
os:
- macos-11
- ubuntu-latest
- windows-latest
node_version:
- 16
os: [macos-11, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: Install Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node_version }}
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: 10.x
- run: npm ci
- run: xvfb-run -a npm test
if: runner.os == 'Linux'

1
.gitignore vendored
View File

@ -2,5 +2,4 @@ out
dist
node_modules
.vscode-test/
*.code-workspace
*.vsix

View File

@ -10,5 +10,3 @@ vsc-extension-quickstart.md
**/.eslintrc.json
**/*.map
**/*.ts
setup-development/**

184
README.md
View File

@ -3,13 +3,13 @@
<img alt="Mind Reader Logo" src="media/logo.png"></img>
</p>
<h1>Mind Reader</h1>
<h1>Mind_Reader</h1>
<!-- overview description -->
The current editor options available lack the level of accessibility that is
required to allow people who are visually impaired to adequately write, edit,
and debug code.
and debug code.
This tool extends Visual Studio Codes existing
accessibility options to enable people with a visual impairment to learn
@ -21,7 +21,7 @@ Python programming with LEGO Mindstorms. Our goal is to:
## Major Features
- Compatible with major screen readers:
- Compatibility with major screen readers:
- [NVDA](https://www.nvaccess.org/)
- [JAWS](https://www.freedomscientific.com/products/software/jaws/)
@ -29,119 +29,103 @@ Python programming with LEGO Mindstorms. Our goal is to:
- Present a summary of the scope for an individual line of code.
- Save, Load, Run, and Delete programs directly onto the LEGO SPIKE Prime Hub from within Visual Studio Code
- Save and load programs directly onto the LEGO Hub from within Visual Studio Code
- Line highlighting with customizable colors and formats
## Dependencies
- [Git](https://git-scm.com/)
- [Node.js](https://nodejs.org/en/)
# First Time Setting Up the Line Highlighter Feature
Before running Mind Reader for the first time it is recommended to add the following code block to your `settings.json` file
### Opening Settings.json
1. Launch VS Code
2. Open the `Command Palette` by pressing **Ctrl + Shift + P** (Windows) / **Cmd + Shift + P** (Mac)
3. The Command Palette should appear at the top of your screen ready for you to type
4. Type `settings` and highlight the option that appears saying `Preferences: Open Settings (JSON)` then select it
5. Your `settings.json` window should appear, scroll to the bottom and make sure the last item has a `,` before the closing curly bracket `}`
6. Paste the following code block after the last comma `,`, but before the closing curly bracket `}`:
```
"mind-reader.lineHighlighter.isEnabled" : true,
"mind-reader.lineHighlighter.multiLineIsEnabled" : false,
"mind-reader.lineHighlighter.backgroundColor" : "#232C5C",
"mind-reader.lineHighlighter.outlineColor" : "#4866FE",
"mind-reader.lineHighlighter.outlineWidth" : "1px",
"mind-reader.lineHighlighter.outlineStyle" : "solid",
"mind-reader.lineHighlighter.borderColorTop" : "#FFFFFF",
"mind-reader.lineHighlighter.borderColorRight" : "#FFFFFF",
"mind-reader.lineHighlighter.borderColorBottom" : "#FFFFFF",
"mind-reader.lineHighlighter.borderColorLeft" : "#FFFFFF",
"mind-reader.lineHighlighter.borderWidthTop" : "1px",
"mind-reader.lineHighlighter.borderWidthRight" : "16px",
"mind-reader.lineHighlighter.borderWidthBottom" : "1px",
"mind-reader.lineHighlighter.borderWidthLeft" : "1px",
"mind-reader.lineHighlighter.borderStyleTop" : "solid",
"mind-reader.lineHighlighter.borderStyleRight" : "solid",
"mind-reader.lineHighlighter.borderStyleBottom" : "solid",
"mind-reader.lineHighlighter.borderStyleLeft" : "solid",
"mind-reader.lineHighlighter.fontStyle" : "normal",
"mind-reader.lineHighlighter.fontWeight" : "bolder",
"mind-reader.lineHighlighter.textDecoration" : "none",
"mind-reader.lineHighlighter.textColor" : "#FFFFFF",
```
The values are set to the default values and can be changed here manually, or through the settings window (File -> Preferences -> Settings -> Mind Reader -> Line Highlighter).
Changes made directly in the settings.json will take effect automatically; however, if you change them in the settings window then after you input your new values VS Code must be closed and reopened for the changes to take effect.
After adding the code block, the `settings.json` file should look similar to this:
**NOTE**: While installing Node.js, there will be a section titled "Tools for Native Modules". Make sure that
'Automatically install the necessary tools' is checked:
<p align="center">
<img width="35%" height="35%" alt="line highlighter first time setup" src="media/line_highlighter_setup.PNG"></img>
<img width="50%" height="50%" alt="tools for native modules page with tool installation checked" src="media/nodejs_setup.png"></img>
</p>
7. Save and close `settings.json`
If the compiled serial port version is incompatible, you may see no options presented in the Mind_Reader actions panel:
### Line Highlighter Settings Table
| **Item** | **Description** | **Accepted Value** | **Default Values** |
|------------------------|-------------------------------------------------------|------------------------------------------------------------------------------|--------------------|
| **isEnabled** | Enable/Disables the line highlighter | boolean | true |
| **multiLineIsEnabled** | Highlight when clicking and dragging to select lines | boolean | false |
| **backgroundColor** | Changes the background color of the highlight | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#232C5C" |
| **outlineColor** | Outline Color | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#4866FE" |
| **outlineWidth** | Outline Width | "medium", "thin", "thick", length (integer + string unit), or "none" | "1px" |
| **outlineStyle** | Outline Style | none, hidden, dotted, dashed, solid, double, groove, ridge, inset, or outset | "solid" |
| **borderColorTop** | Top Border Color | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#FFFFFF" |
| **borderColorRight** | Right Border Color | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#FFFFFF" |
| **borderColorBottom** | Bottom Border Color | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#FFFFFF" |
| **borderColorLeft** | Left Border Color | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#FFFFFF" |
| **borderWidthTop** | Top Border Width | "medium", "thin", "thick", length (integer + string unit), or "none" | "1px" |
| **borderWidthRight** | Right Border Width | "medium", "thin", "thick", length (integer + string unit), or "none" | "16px" |
| **borderWidthBottom** | Bottom Border Width | "medium", "thin", "thick", length (integer + string unit), or "none" | "1px" |
| **borderWidthLeft** | Left Border Width | "medium", "thin", "thick", length (integer + string unit), or "none" | "1px" |
| **borderStyleTop** | Top Border Style | none, hidden, dotted, dashed, solid, double, groove, ridge, inset, or outset | "solid" |
| **borderStyleRight** | Right Border Style | none, hidden, dotted, dashed, solid, double, groove, ridge, inset, or outset | "solid" |
| **borderStyleBottom** | Bottom Border Style | none, hidden, dotted, dashed, solid, double, groove, ridge, inset, or outset | "solid" |
| **borderStyleLeft** | Left Border Style | none, hidden, dotted, dashed, solid, double, groove, ridge, inset, or outset | "solid" |
| **fontStyle** | Styling to the font contained within the highlight | "normal", "italic", "oblique", or "none" | "normal" |
| **fontWeight** | Weight of the font contained within the highlight | "normal", "bold", "bolder", "lighter", string based number, "none" | "bolder" |
| **textDecoration** | Decoration of the font contained within the highlight | See: https://www.w3schools.com/cssref/pr_text_text-decoration.asp | "none" |
| **textColor** | Color of the font contained within the highlight | HEX(A), RGB(A), HSL(A), Predefined Color String, or "none" | "#FFFFFF" |
<p align="center">
<img width="50%" height="50%" alt="mind reader actions panel with no items:" src="media/missing_actions.png"></img>
</p>
In this case, you will also need to rebuild the serial port component with `electron-rebuild`. This is a one-time setup
for each version of Visual Studio Code. You may need to repeat this process if you update your version of Visual Studio
Code.
## Installing `electron-rebuild`
**Use Git Bash on Windows, and the terminal on MacOS/Linux. These steps will refer to this as 'the terminal'**
### 1 Install the `electron-rebuild` tool
In the terminal install electron rebuild with `npm` that is included with [Node.js](https://nodejs.org/en/):
```console
$ npm install -g electron-rebuild
```
### 2 Finding your electron version
On MacOS, go to Code > About Visual Studio Code.
On Windows and Linux, go to Help > About.
The electron version should be listed, e.g.: `Electron: 13.5.2`
<p align="center">
<img width="35%" height="35%" alt="vscode information" src="media/vscode_info.png"></img>
</p>
### 3 Finding the Mind_Reader extension directory
On MacOS and Linux this is `~/.vscode/extensions`.
On Windows this is `C:\<YOUR USER>\.vscode\extensions\`. However, in Git Bash, it will appear like on MacOS and Linux
e.g.: `~/.vscode/extensions`.
---
Find the Mind_Reader extension folder, this should look like `xxx.mind-reader-x.x.x`.
Navigate to the found folder in the terminal.
```console
$ cd ~/.vscode/extensions/<mind_reader_folder>
```
### 4 Running `electron-rebuild`
Then, run `electron-rebuild` with `ELECTRON_VERSION` replaced with the electron version found in step 2:
```console
$ electron-rebuild --version=ELECTRON_VERSION
```
# For Developers
## Developer Dependencies
## Development Quick Start
Use the following to set up the extension for development.
### Development environment setup guide
```console
$ git clone https://github.com/SingleSemesterSnobs/Mind_Reader.git
$ cd Mind_Reader
$ npm install
```
### Windows 10 or 11
* Download [install-windows.ps1](setup-development/windows/install-windows.ps1)
* Run `./install-windows.ps1` in PowerShell as a normal user, and accept any UAC prompts that pop up. The installation should take around 8 minutes. If an installer doesn't pop up, don't be alarmed.
While inside the repository do
For other platforms, or to install the extension manually, check out our [Developer Install Guide](../../wiki/Developer-Install-Guide). This is also where you should search if you encounter errors.
```console
$ code .
```
to open the cloned repository in VS Code.
Then, use "Run > Start Debugging" on the menu bar to start the [Extension
Development Host](https://code.visualstudio.com/api/advanced-topics/extension-host)
(<kbd>F5</kbd> by default).
---
If you get an error about a `NODE_MODULE_VERSION` incompatibility or that a file is not a Windows executable,
this is likely the error described above. Run `npm i -g electron-rebuild` if you have not done so and follow the
directions above.
---
See the Visual Studio Code [getting started](https://code.visualstudio.com/api/get-started/your-first-extension)
API page if you need more help.
# Contact Information
### Single Semester Snobs
#### Fall 2021 Semester
- Jake Grossman: [\<JacobGrossman2@my.unt.edu\>](mailto:JacobGrossman2@my.unt.edu)
- Cal Wooten: [\<calwooten@my.unt.edu\>](mailto:calwooten@my.unt.edu)
- Josiah Moses: [\<josiahmoses@my.unt.edu\>](mailto:josiahmoses@my.unt.edu)
- Sophia Drewfs: [\<sophiadrewfs@my.unt.edu\>](mailto:sophiadrewfs@my.unt.edu)
- Mason Bone: [\<masonbone@my.unt.edu\>](mailto:masonbone@my.unt.edu)
### We Don't Byte
#### Spring 2022 Semester
- John Breaux: [\<JohnBreaux@my.unt.edu\>](mailto:JohnBreaux@my.unt.edu)
- Thomas Lane: [\<ThomasLane2@my.unt.edu\>](mailto:ThomasLane2@my.unt.edu)
- Kendrick Johnson: [\<KendrickJohnson@my.unt.edu\>](mailto:KendrickJohnson@my.unt.edu)
- Ryan Tolbert: [\<RyanTolbert@my.unt.edu\>](mailto:RyanTolbert@my.unt.edu)
- Pedro Alvarez: [\<PedroAlvarez3@my.unt.edu\>](mailto:PedroAlvarez3@my.unt.edu)

View File

@ -8,7 +8,7 @@
<body>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6a4XaqHkKcxJ6ZFms1RNrRurcOfl-diW90DAdpAx0Kv-rtrLJXovIhcUpayqFHATkrQ&usqp=CAU" width="600" />
<p></p>
<h1>Welcome to Mind Reader!</h1>
<h1>Welcome to Mind_Reader!</h1>
<p>We are the Single Semester Snobs and this is our tool to Help Blind Students Program Lego Mindstorms Robots in Python.</p>
<ul>
<li>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

359
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "mind-reader",
"version": "2.0.0",
"version": "0.0.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "mind-reader",
"version": "2.0.0",
"version": "0.0.1",
"dependencies": {
"serialport": "^9.2.5"
},
@ -21,12 +21,12 @@
"@vscode/test-electron": "^1.6.2",
"eslint": "^7.27.0",
"glob": "^7.1.7",
"mocha": "^10.0.0",
"mocha": "^8.4.0",
"typescript": "^4.3.2",
"vscode-test": "^1.5.2"
},
"engines": {
"vscode": "^1.66.0"
"vscode": "^1.60.0"
}
},
"node_modules/@babel/code-frame": {
@ -945,30 +945,24 @@
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"anymatch": "~3.1.2",
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
"readdirp": "~3.5.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
"fsevents": "~2.3.1"
}
},
"node_modules/chownr": {
@ -1041,9 +1035,9 @@
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"dependencies": {
"ms": "2.1.2"
},
@ -1751,6 +1745,15 @@
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
"dev": true
},
"node_modules/growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true,
"engines": {
"node": ">=4.x"
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -1934,18 +1937,6 @@
"node": ">=8"
}
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@ -2041,19 +2032,15 @@
"dev": true
},
"node_modules/log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"dev": true,
"dependencies": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
"chalk": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lru-cache": {
@ -2114,9 +2101,9 @@
}
},
"node_modules/minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"node_modules/mkdirp": {
"version": "0.5.5",
@ -2136,40 +2123,43 @@
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
},
"node_modules/mocha": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz",
"integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==",
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz",
"integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==",
"dev": true,
"dependencies": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.3",
"debug": "4.3.4",
"chokidar": "3.5.1",
"debug": "4.3.1",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"glob": "7.2.0",
"glob": "7.1.6",
"growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "4.1.0",
"log-symbols": "4.1.0",
"minimatch": "5.0.1",
"js-yaml": "4.0.0",
"log-symbols": "4.0.0",
"minimatch": "3.0.4",
"ms": "2.1.3",
"nanoid": "3.3.3",
"serialize-javascript": "6.0.0",
"nanoid": "3.1.20",
"serialize-javascript": "5.0.1",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
"workerpool": "6.2.1",
"which": "2.0.2",
"wide-align": "1.1.3",
"workerpool": "6.1.0",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
},
"bin": {
"_mocha": "bin/_mocha",
"mocha": "bin/mocha.js"
"mocha": "bin/mocha"
},
"engines": {
"node": ">= 14.0.0"
"node": ">= 10.12.0"
},
"funding": {
"type": "opencollective",
@ -2182,13 +2172,47 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/mocha/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"node_modules/mocha/node_modules/debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/mocha/node_modules/debug/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/mocha/node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mocha/node_modules/has-flag": {
@ -2201,9 +2225,9 @@
}
},
"node_modules/mocha/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
"integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@ -2212,18 +2236,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/mocha/node_modules/minimatch": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mocha/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -2256,9 +2268,9 @@
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"node_modules/nanoid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
"integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
"version": "3.1.20",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
@ -2583,9 +2595,9 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
@ -2716,9 +2728,9 @@
}
},
"node_modules/serialize-javascript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
"integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
"integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
@ -2805,9 +2817,9 @@
]
},
"node_modules/simple-get": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
"dependencies": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
@ -3193,9 +3205,9 @@
}
},
"node_modules/wide-align/node_modules/ansi-regex": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
"integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"engines": {
"node": ">=4"
}
@ -3241,9 +3253,9 @@
}
},
"node_modules/workerpool": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
"integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
"integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==",
"dev": true
},
"node_modules/wrap-ansi": {
@ -4004,19 +4016,19 @@
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
"readdirp": "~3.5.0"
}
},
"chownr": {
@ -4083,9 +4095,9 @@
}
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"requires": {
"ms": "2.1.2"
}
@ -4620,6 +4632,12 @@
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
"dev": true
},
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -4747,12 +4765,6 @@
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true
},
"is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@ -4836,13 +4848,12 @@
"dev": true
},
"log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"dev": true,
"requires": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
"chalk": "^4.0.0"
}
},
"lru-cache": {
@ -4885,9 +4896,9 @@
}
},
"minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mkdirp": {
"version": "0.5.5",
@ -4904,30 +4915,33 @@
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
},
"mocha": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz",
"integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==",
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz",
"integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==",
"dev": true,
"requires": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.3",
"debug": "4.3.4",
"chokidar": "3.5.1",
"debug": "4.3.1",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"glob": "7.2.0",
"glob": "7.1.6",
"growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "4.1.0",
"log-symbols": "4.1.0",
"minimatch": "5.0.1",
"js-yaml": "4.0.0",
"log-symbols": "4.0.0",
"minimatch": "3.0.4",
"ms": "2.1.3",
"nanoid": "3.3.3",
"serialize-javascript": "6.0.0",
"nanoid": "3.1.20",
"serialize-javascript": "5.0.1",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
"workerpool": "6.2.1",
"which": "2.0.2",
"wide-align": "1.1.3",
"workerpool": "6.1.0",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
@ -4939,13 +4953,35 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0"
"ms": "2.1.2"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"has-flag": {
@ -4955,23 +4991,14 @@
"dev": true
},
"js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
"integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
"dev": true,
"requires": {
"argparse": "^2.0.1"
}
},
"minimatch": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
"integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
"dev": true,
"requires": {
"brace-expansion": "^2.0.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -5000,9 +5027,9 @@
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"nanoid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
"integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
"version": "3.1.20",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==",
"dev": true
},
"napi-build-utils": {
@ -5244,9 +5271,9 @@
}
},
"readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
@ -5315,9 +5342,9 @@
}
},
"serialize-javascript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
"integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
"integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
@ -5378,9 +5405,9 @@
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
},
"simple-get": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
"requires": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
@ -5688,9 +5715,9 @@
},
"dependencies": {
"ansi-regex": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
"integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
@ -5723,9 +5750,9 @@
"dev": true
},
"workerpool": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
"integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
"integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==",
"dev": true
},
"wrap-ansi": {

View File

@ -1,56 +1,10 @@
{
"name": "mind-reader",
"displayName": "Mind Reader",
"homepage": "https://github.com/We-Dont-Byte/Mind_Reader/wiki",
"repository": {
"type": "git",
"url": "https://github.com/We-Dont-Byte/Mind_Reader"
},
"bugs": {
"type": "git",
"url": "https://github.com/We-Dont-Byte/Mind_Reader/issues"
},
"contributors": [
{
"name": "Jake Grossman",
"email": "JacobGrossman2@my.unt.edu"
},
{
"name": "Cal Wooten",
"email": "calwooten@my.unt.edu"
},
{
"name": "Josiah Mosesn",
"email": "josiahmoses@my.unt.edu"
},
{
"name": "Sophia Drewfs",
"email": "sophiadrewfs@my.unt.edu"
},
{
"name": "John Breaux",
"email": "JohnBreaux@my.unt.edu"
},
{
"name": "Thomas Lane",
"email": "ThomasLane2@my.unt.edu"
},
{
"name": "Ryan Tolbert",
"email": "RyanTolbert@my.unt.edu"
},
{
"name": "Kendrick Johnson",
"email": "KendrickJohnson@my.unt.edu"
},
{
"name": "Pedro Alvarez",
"email": "PedroAlvarez3@my.unt.edu"
}
],
"version": "2.0.0",
"displayName": "Mind_Reader",
"repository": "https://github.com/SingleSemesterSnobs/Mind_Reader",
"version": "1.0.0",
"engines": {
"vscode": "^1.66.0"
"vscode": "^1.60.0"
},
"categories": [
"Other"
@ -61,238 +15,187 @@
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "mind-reader.helloWorld",
"title": "Hello World"
},
{
"command": "mind-reader.increaseFontScale",
"title": "Increase Font Scale",
"category": "Mind Reader"
"title": "Increase Font Scale"
},
{
"command": "mind-reader.decreaseFontScale",
"title": "Decrease Font Scale",
"category": "Mind Reader"
"title": "Decrease Font Scale"
},
{
"command": "mind-reader.resetFontScale",
"title": "Reset Font Scale",
"category": "Mind Reader"
"title": "Reset Font Scale"
},
{
"command": "mind-reader.increaseEditorScale",
"title": "Increase Editor Scale",
"category": "Mind Reader"
"title": "Increase Editor Scale"
},
{
"command": "mind-reader.decreaseEditorScale",
"title": "Decrease Editor Scale",
"category": "Mind Reader"
"title": "Decrease Editor Scale"
},
{
"command": "mind-reader.resetEditorScale",
"title": "Reset Editor Scale",
"category": "Mind Reader"
"title": "Reset Editor Scale"
},
{
"command": "mind-reader.selectTheme",
"title": "Select Theme",
"category": "Mind Reader"
"title": "Select Theme"
},
{
"command": "mind-reader.openWebview",
"title": "Mind Reader Webview"
},
{
"command": "mind-reader.openKeybinds",
"title": "Edit Keybinds",
"category": "Mind Reader"
"command": "mind-reader.openKeyBindWin",
"title": "Key Bindings for Windows"
},
{
"command": "mind-reader.getLineScope",
"title": "Get Scope of the Current Line",
"category": "Mind Reader"
"command": "mind-reader.openKeyBindMac",
"title": "Key Bindings for Mac"
},
{
"command": "mind-reader.getWordsUnderCursor",
"title": "Get Words Under the Cursor",
"category": "Mind Reader"
"command": "mind-reader.runLineContext",
"title": "Run Line Context"
},
{
"command": "mind-reader.getLineNumber",
"title": "Get The Current Line Number",
"category": "Mind Reader"
"command": "mind-reader.runCursorContext",
"title": "Run Cursor Context"
},
{
"command": "mind-reader.getIndent",
"title": "Get The Number Of Line Indentations",
"category": "Mind Reader"
},
{
"command": "mind-reader.getLeadingSpaces",
"title": "Get The Number Of Leading Spaces",
"category": "Mind Reader"
},
{
"command": "mind-reader.selectLeadingWhitespace",
"title": "Select The Leading Whitespace",
"category": "Mind Reader"
},
{
"command": "mind-reader.getNumberOfSelectedLines",
"title": "Get The Number Of Selected Lines",
"category": "Mind Reader"
},
{
"command": "mind-reader.getQuickInputBack",
"title": "Go Back in Quick Input",
"category": "Mind Reader"
},
{
"command": "mind-reader.gotoLine",
"title": "Go to Line",
"category": "Mind Reader"
},
{
"command": "mind-reader.gotoSymbol",
"title": "Go to Symbol",
"category": "Mind Reader"
},
{
"command": "mind-reader.navigateBack",
"title": "Navigate Backward",
"category": "Mind Reader"
},
{
"command": "mind-reader.navigateForward",
"title": "Navigate Forward",
"category": "Mind Reader"
},
{
"command": "mind-reader.nextInFiles",
"title": "Go to Next Problem in Files (Error, Warning, Info)",
"category": "Mind Reader"
},
{
"command": "mind-reader.prevInFiles",
"title": "Go to Previous Problem in Files (Error, Warning, Info)",
"category": "Mind Reader"
},
{
"command": "mind-reader.quickOpen",
"title": "Go to File...",
"category": "Mind Reader"
},
{
"command": "mind-reader.quickOpenPreviousRecentlyUsedEditorInGroup",
"title": "View: Quick Open Previous Recently Used Editor in Group"
},
{
"command": "mind-reader.showAllSymbols",
"title": "Go to Symbol in Workspace...",
"category": "Mind Reader"
},
{
"command": "mind-reader.showProblems",
"title": "Show Problems",
"category": "Mind Reader"
},
{
"command": "mind-reader.showCommands",
"title": "Show All Commands",
"category": "Mind Reader"
"title": "Get Line Indentation"
},
{
"command": "mind-reader.connectHub",
"title": "Connect a LEGO SPIKE Prime Hub",
"category": "SPIKE Prime"
"title": "Connect LEGO Hub"
},
{
"command": "mind-reader.disconnectHub",
"title": "Disconnect a LEGO SPIKE Prime Hub",
"category": "SPIKE Prime"
},
{
"command": "mind-reader.runProgram",
"title": "Run a Program on the LEGO SPIKE Prime Hub",
"category": "SPIKE Prime"
},
{
"command": "mind-reader.stopExecution",
"title": "Stop Running Program on the LEGO SPIKE Prime Hub",
"category": "SPIKE Prime"
},
{
"command": "mind-reader.deleteProgram",
"title": "Delete a Program from the LEGO SPIKE Prime Hub",
"category": "SPIKE Prime"
"title": "Disconnect LEGO Hub"
},
{
"command": "mind-reader.uploadCurrentFile",
"title": "Upload Current File to the LEGO SPIKE Prime Hub",
"category": "SPIKE Prime"
"title": "Upload current file to LEGO Hub"
},
{
"command": "mind-reader.runProgram",
"title": "Run a program from the LEGO Hub"
},
{
"command": "mind-reader.stopExecution",
"title": "Stop running program on the LEGO Hub"
},
{
"command": "mind-reader.deleteProgram",
"title": "Delete a program from the LEGO Hub"
}
],
"keybindings": [
{
"command": "accessActions.focus",
"comment": "This opens the Access Actions menu",
"key": "Ctrl+Shift+/ Ctrl+Shift+/",
"mac": "Cmc+Shift+[Slash] Cmc+Shift+[Slash]"
},
{
"command": "mind-reader.decreaseFontScale",
"key": "Shift+Alt+Z -",
"mac": "Cmd+Shift+Z -",
"when": "editorTextFocus"
"key": "numpad_subtract",
"mac": "d"
},
{
"command": "mind-reader.increaseFontScale",
"key": "Shift+Alt+Z =",
"mac": "Cmd+Shift+Z =",
"when": "editorTextFocus"
"key": "numpad_add",
"mac": "[NumpadAdd]"
},
{
"command": "mind-reader.resetFontScale",
"key": "Shift+Alt+Z 0",
"mac": "Cmd+Shift+Z 0",
"when": "editorTextFocus"
"command": "mind-reader.increaseEditorScale",
"key": "shift+numpad_add",
"mac": "Shift+[NumpadAdd]"
},
{
"command": "mind-reader.decreaseEditorScale",
"key": "shift+numpad_subtract",
"mac": "Shift+[NumpadSubtract]"
},
{
"command": "mind-reader.resetEditorScale",
"key": "shift+enter",
"mac": "Shift+[Enter]"
},
{
"command": "mind-reader.showAllSymbols",
"key": "Ctrl+T",
"mac": "Cmd+[KeyT]"
},
{
"command": "mind-reader.gotoLine",
"key": "CTRL+G",
"mac": "Cmd+[KeyG]"
},
{
"command": "mind-reader.quickOpen",
"key": "CTRL+P",
"mac": "Cmd+[KeyP]"
},
{
"command": "mind-reader.gotoSymbol",
"key": "Ctrl+Shift+O",
"mac": "Cmd+Shift+[KeyO]"
},
{
"command": "mind-reader.showProblems",
"key": "Ctrl+Shift+M",
"mac": "Cmd+Shift+[KeyM]"
},
{
"command": "mind-reader.nextInFiles",
"key": "F8",
"mac": "[F8]"
},
{
"command": "mind-reader.prevInFiles",
"key": "Shift+F8",
"mac": "Shift+[F8]"
},
{
"command": "mind-reader.quickOpenPreviousRecentlyUsedEditorInGroup",
"key": "Ctrl+Tab",
"mac": "Cmd+[Tab]"
},
{
"command": "mind-reader.navigateBack",
"key": "Ctrl+Alt+-",
"mac": "Cmd+Alt+[Minus]"
},
{
"command": "mind-reader.getQuickInputBack",
"key": "Ctrl+Alt+-",
"mac": "Cmd+Alt+[Minus]"
},
{
"command": "mind-reader.navigateForward",
"key": "Ctrl+Shift+-",
"mac": "Cmd+Shift+[Minus]"
},
{
"command": "mind-reader.selectTheme",
"key": "Ctrl+Shift+1",
"mac": "Cmd+Shift+[Digit1]"
},
{
"command": "mind-reader.getIndent",
"key": "Ctrl+Shift+/ I",
"mac": "Cmd+Shift+[Slash] I",
"when": "editorTextFocus"
"key": "Shift+Tab",
"mac": "Shift+[Tab]"
},
{
"command": "mind-reader.getLeadingSpaces",
"key": "Ctrl+Shift+/ S",
"mac": "Cmd+Shift+[Slash] S",
"when": "editorTextFocus && editorLangId == python"
"command": "mind-reader.openKeyBindWin",
"key": "Ctrl+Shift+8",
"mac": "Cmd+Shift+8"
},
{
"command": "mind-reader.getLineNumber",
"key": "Ctrl+Shift+/ L",
"mac": "Cmd+Shift+[Slash] L",
"when": "editorTextFocus"
},
{
"command": "mind-reader.getLineScope",
"key": "Ctrl+Shift+/ C",
"mac": "Cmd+Shift+[Slash] C",
"when": "editorTextFocus && editorLangId == python"
},
{
"command": "mind-reader.openKeybinds",
"key": "Ctrl+Shift+/ K",
"mac": "Cmd+Shift+[Slash] K"
},
{
"command": "mind-reader.getNumberOfSelectedLines",
"key": "Ctrl+Shift+/ N",
"mac": "Cmd+Shift+[Slash] N"
},
{
"command": "mind-reader.selectLeadingWhitespace",
"key": "Ctrl+Shift+/ W",
"mac": "Cmd+Shift+[Slash] W"
"command": "mind-reader.openKeyBindMac",
"key": "Ctrl+Shift+9",
"mac": "Cmd+Shift+9"
}
],
"menus": {
@ -304,274 +207,112 @@
],
"mind-reader.editor.context": [
{
"command": "mind-reader.openKeybinds",
"group": "0_configuration@0",
"when": "activeEditor"
},
{
"command": "workbench.action.selectTheme",
"group": "0_configuration@1",
"when": "activeEditor"
},
{
"command": "mind-reader.increaseFontScale",
"group": "1_font-zoom@0",
"command": "mind-reader.increaseEditorScale",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "mind-reader.decreaseFontScale",
"group": "1_font-zoom@1",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "mind-reader.resetFontScale",
"group": "1_font-zoom@2",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "workbench.action.zoomIn",
"group": "2_workbench-zoom@0",
"command": "mind-reader.increaseEditorScale",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "workbench.action.zoomOut",
"group": "2_workbench-zoom@1",
"command": "mind-reader.decreaseEditorScale",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "workbench.action.zoomReset",
"group": "2_workbench-zoom@2",
"command": "mind-reader.resetEditorScale",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "mind-reader.getLineNumber",
"group": "3_getter-functions@0",
"when": "activeEditor"
},
{
"command": "mind-reader.getIndent",
"group": "3_getter-functions@1",
"when": "activeEditor"
},
{
"command": "mind-reader.getLeadingSpaces",
"group": "3_getter-functions@2",
"when": "activeEditor"
},
{
"command": "mind-reader.getNumberOfSelectedLines",
"group": "3_getter-functions@3",
"when": "activeEditor"
},
{
"command": "mind-reader.selectLeadingWhitespace",
"group": "4_selector-functions@0",
"command": "mind-reader.selectTheme",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "mind-reader.openWebview",
"group": "z_disabled@99",
"when": "false"
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "mind-reader.openKeyBindWin",
"group": "mind-reader",
"when": "activeEditor"
},
{
"command": "mind-reader.openKeyBindMac",
"group": "mind-reader",
"when": "activeEditor"
}
]
},
"submenus": [
{
"id": "mind-reader.editor.context",
"label": "Mind Reader"
"label": "Mind_Reader"
}
],
"configuration": [
{
"title": "Mind Reader",
"order": 0,
"properties": {
"mind-reader.productType": {
"order": 1,
"type": "string",
"description": "Specifies the LEGO® product.",
"default": "SPIKE Prime",
"enum": [
"MINDSTORMS EV3",
"SPIKE Prime"
],
"enumDescriptions": [
"LEGO® MINDSTORMS® EV3 (31313)",
"LEGO® Education SPIKE™ Prime Set (45678)"
]
},
"mind-reader.reader.screenReader": {
"order": 0,
"type": "string",
"description": "Specifies which screen reader to optimize for.",
"default": "NVDA",
"enum": [
"JAWS",
"NVDA",
"Orca",
"VoiceOver"
],
"enumDescriptions": [
"Job Access With Speech (Windows)",
"NonVisual Desktop Access (Windows)",
"Orca (Linux)",
"Apple VoiceOver (macOS)"
]
},
"mind-reader.reader.contextWindow": {
"order": 3,
"type": "number",
"description": "The number of words around the cursor to use when reading the cursor context",
"default": 1
},
"mind-reader.connection.portPath": {
"order": 2,
"type": "string",
"markdownDescription": "The default port to try and establish a connection on."
}
}
},
{
"title": "Line Highlighter [Must Close Settings And RESTART VSCode For The Line Highlighter To Function]",
"order": 1,
"properties": {
"mind-reader.lineHighlighter.isEnabled": {
"order": 4,
"type": "boolean",
"markdownDescription": "Enable/Disable the line highlighter.\n\n\n* `Enabled (our default)`: Checked: Line Highlighter is turned `ON`\n* `Disabled`: Unchecked: Line Highlighter is turned `OFF`\n\n### `NOTE`: You Must Close Settings And RESTART Visual Studio Code For The Line Highlighter To Function\n#### Even If No Changes Were Made",
"default": true
},
"mind-reader.lineHighlighter.multiLineIsEnabled": {
"order": 5,
"type": "boolean",
"markdownDescription": "Temporarily Disable highlighting when highlighting multiple lines.\n\n\n* `Enabled`: Checked: Multiline Highlighting is turned `ON`:\n* * When you click and drag line highlights will be applied to all lines\n* `Disabled (our default)`: Unchecked: Multiline Highlighting is turned `OFF`:\n* * When you click and drag the line highlighter will disable itself then re-enable itself when you click onto a single line.",
"default": false
},
"mind-reader.lineHighlighter.backgroundColor": {
"order": 6,
"type": "string",
"markdownDescription": "Set the background color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#232C5C` is our default",
"default": "#232C5C"
},
"mind-reader.lineHighlighter.outlineColor": {
"order": 7,
"type": "string",
"markdownDescription": "Set the outline color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#4866FE` is our default",
"default": "#4866FE"
},
"mind-reader.lineHighlighter.outlineWidth": {
"order": 8,
"type": "string",
"markdownDescription": "Set the outline width to be used by the line highlighter.\n\nSyntax: `medium` or `thin` or `thick` or `length` or `none`\n* `medium`: Specifies a medium outline. (usual default)\n* `thin`: Specifies a thin outline\n* `thick`: Specifies a thick outline\n* `length`: you to define the thickness of the outline in [length](https://www.w3schools.com/cssref/css_units.asp) units.\n* `none`: No outline width will be applied\n* `1px` is our default",
"default": "1px"
},
"mind-reader.lineHighlighter.outlineStyle": {
"order": 9,
"type": "string",
"markdownDescription": "Set the outline style to be used by the line highlighter.\n\nSyntax: `none` or `hidden` or `dotted` or `dashed` or `solid` or `double` or `groove` or `ridge` or `inset` or `outset`\n* `none`: No border will be applied (usual default)\n* `hidden`: The same as `none`\n* `dotted`: Dotted border\n* `dashed`: Dashed border\n* `solid (our default)`: Solid border\n* `double`: Double border\n* `groove`: 3D grooved border, depends on the outline-color value.\n* `ridge`: 3D ridged border, depends on the outline-color value.\n* `inset`: 3D inset border, depends on the outline-color value.\n* `outset`: 3D outset border, depends on the outline-color value.",
"default": "solid"
},
"mind-reader.lineHighlighter.borderColorTop": {
"order": 10,
"type": "string",
"markdownDescription": "Set the top border color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#FFFFFF` is our default",
"default": "#FFFFFF"
},
"mind-reader.lineHighlighter.borderColorRight": {
"order": 11,
"type": "string",
"markdownDescription": "Set the right border color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#FFFFFF` is our default",
"default": "#FFFFFF"
},
"mind-reader.lineHighlighter.borderColorBottom": {
"order": 12,
"type": "string",
"markdownDescription": "Set the bottom border color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#FFFFFF` is our default",
"default": "#FFFFFF"
},
"mind-reader.lineHighlighter.borderColorLeft": {
"order": 13,
"type": "string",
"markdownDescription": "Set the left border color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#FFFFFF` is our default",
"default": "#FFFFFF"
},
"mind-reader.lineHighlighter.borderWidthTop": {
"order": 14,
"type": "string",
"markdownDescription": "Set the top border width to be used by the line highlighter.\n\nSyntax: `medium` or `thin` or `thick` or `length` or `none`\n* `medium`: Specifies a medium border. (usual default)\n* `thin`: Specifies a thin border\n* `thick`: Specifies a thick border\n* `length`: you to define the thickness of the border in [length](https://www.w3schools.com/cssref/css_units.asp) units.\n* `none`: No border width will be applied\n* `1px` is our default",
"default": "1px"
},
"mind-reader.lineHighlighter.borderWidthRight": {
"order": 15,
"type": "string",
"markdownDescription": "Set the right border width to be used by the line highlighter.\n\nSyntax: `medium` or `thin` or `thick` or `length` or `none`\n* `medium`: Specifies a medium border. (usual default)\n* `thin`: Specifies a thin border\n* `thick`: Specifies a thick border\n* `length`: you to define the thickness of the border in [length](https://www.w3schools.com/cssref/css_units.asp) units.\n* `none`: No border width will be applied\n* `16px` is our default\n\n#### \nborderWidthRight exhibits odd behavior, play around with different sizes to find what works best for your environment.",
"default": "16px"
},
"mind-reader.lineHighlighter.borderWidthBottom": {
"order": 16,
"type": "string",
"markdownDescription": "Set the bottom border width to be used by the line highlighter.\n\nSyntax: `medium` or `thin` or `thick` or `length` or `none`\n* `medium`: Specifies a medium border. (usual default)\n* `thin`: Specifies a thin border\n* `thick`: Specifies a thick border\n* `length`: you to define the thickness of the border in [length](https://www.w3schools.com/cssref/css_units.asp) units.\n* `none`: No border width will be applied\n* `1px` is our default",
"default": "1px"
},
"mind-reader.lineHighlighter.borderWidthLeft": {
"order": 17,
"type": "string",
"markdownDescription": "Set the left border width to be used by the line highlighter.\n\nSyntax: `medium` or `thin` or `thick` or `length` or `none`\n* `medium`: Specifies a medium border. (usual default)\n* `thin`: Specifies a thin border\n* `thick`: Specifies a thick border\n* `length`: you to define the thickness of the border in [length](https://www.w3schools.com/cssref/css_units.asp) units.\n* `none`: No border width will be applied\n* `1px` is our default",
"default": "1px"
},
"mind-reader.lineHighlighter.borderStyleTop": {
"order": 18,
"type": "string",
"markdownDescription": "Set the top border style to be used by the line highlighter.\n\nSyntax: `none` or `hidden` or `dotted` or `dashed` or `solid` or `double` or `groove` or `ridge` or `inset` or `outset`\n* `none`: No border will be applied (usual default)\n* `hidden`: The same as `none`\n* `dotted`: Dotted border\n* `dashed`: Dashed border\n* `solid (our default)`: Solid border\n* `double`: Double border\n* `groove`: 3D grooved border, depends on the border-color value.\n* `ridge`: 3D ridged border, depends on the border-color value.\n* `inset`: 3D inset border, depends on the border-color value.\n* `outset`: 3D outset border, depends on the border-color value.",
"default": "solid"
},
"mind-reader.lineHighlighter.borderStyleRight": {
"order": 19,
"type": "string",
"markdownDescription": "Set the right border style to be used by the line highlighter.\n\nSyntax: `none` or `hidden` or `dotted` or `dashed` or `solid` or `double` or `groove` or `ridge` or `inset` or `outset`\n* `none`: No border will be applied (usual default)\n* `hidden`: The same as `none`\n* `dotted`: Dotted border\n* `dashed`: Dashed border\n* `solid (our default)`: Solid border\n* `double`: Double border\n* `groove`: 3D grooved border, depends on the border-color value.\n* `ridge`: 3D ridged border, depends on the border-color value.\n* `inset`: 3D inset border, depends on the border-color value.\n* `outset`: 3D outset border, depends on the border-color value.",
"default": "solid"
},
"mind-reader.lineHighlighter.borderStyleBottom": {
"order": 20,
"type": "string",
"markdownDescription": "Set the bottom border style to be used by the line highlighter.\n\nSyntax: `none` or `hidden` or `dotted` or `dashed` or `solid` or `double` or `groove` or `ridge` or `inset` or `outset`\n* `none`: No border will be applied (usual default)\n* `hidden`: The same as `none`\n* `dotted`: Dotted border\n* `dashed`: Dashed border\n* `solid (our default)`: Solid border\n* `double`: Double border\n* `groove`: 3D grooved border, depends on the border-color value.\n* `ridge`: 3D ridged border, depends on the border-color value.\n* `inset`: 3D inset border, depends on the border-color value.\n* `outset`: 3D outset border, depends on the border-color value.",
"default": "solid"
},
"mind-reader.lineHighlighter.borderStyleLeft": {
"order": 21,
"type": "string",
"markdownDescription": "Set the left border style to be used by the line highlighter.\n\nSyntax: `none` or `hidden` or `dotted` or `dashed` or `solid` or `double` or `groove` or `ridge` or `inset` or `outset`\n* `none`: No border will be applied (usual default)\n* `hidden`: The same as `none`\n* `dotted`: Dotted border\n* `dashed`: Dashed border\n* `solid (our default)`: Solid border\n* `double`: Double border\n* `groove`: 3D grooved border, depends on the border-color value.\n* `ridge`: 3D ridged border, depends on the border-color value.\n* `inset`: 3D inset border, depends on the border-color value.\n* `outset`: 3D outset border, depends on the border-color value.",
"default": "solid"
},
"mind-reader.lineHighlighter.fontStyle": {
"order": 22,
"type": "string",
"markdownDescription": "Set the font style to be used by the line highlighter.\n\nSyntax: `normal` or `italic` or `oblique` or `none`\n* `normal (our default)`: Displays a normal font style. This is default\n* `italic`: Displays an italic font style\n* `oblique`: Displays an oblique font style\n* `none`: No font style will be applied",
"default": "normal"
},
"mind-reader.lineHighlighter.fontWeight": {
"order": 23,
"type": "string",
"markdownDescription": "Set the font weight to be used by the line highlighter.\n\nSyntax: `normal` or `bold` or `bolder` or `lighter` or _number_ or `none`\n* `normal`: Normal Characters. (usual default)\n* `bold`: Thick Characters\n* `bolder (our default)`: Thicker Characters\n* `lighter`: Lighter Characters\n * _number_: From `thin` to `thick` characters: `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, or `900`: `400` is the same as normal, and `700` is the same as bold.\n* `none`: No font weight will be applied",
"default": "bolder"
},
"mind-reader.lineHighlighter.textDecoration": {
"order": 24,
"type": "string",
"markdownDescription": "Set the text decoration to be used by the line highlighter.\n\nSyntax: `(text-decoration-line)` `(text-decoration-color)` `(text-decoration-style)` `(text-decoration-thickness)`\n* `text-decoration-line (required)`: Sets the kind of text decoration to use: `underline`, `overline`, `line-through`\n* `text-decoration-color`: Sets the color of the text decoration\n* `text-decoration-style`: Sets the style of the text decoration: `solid`, `wavy`, `dotted`, `dashed`, `double`\n* `text-decoration-thickness`: Sets the thickness of the decoration line\n* `none (our default)`: No text decorations will be applied\n\n`Examples`:\n1. underline blue wavy 5px\n2. line-through\n3. underline overline dotted red",
"default": "none"
},
"mind-reader.lineHighlighter.textColor": {
"order": 25,
"type": "string",
"markdownDescription": "Set the text color to be used by the line highlighter.\n\nSyntax: _color_ or `transparent`\n\nAvailable color formats include:\n* `HEX(A)`: for Hexadecimal Colors: `#RRGGBB` or `#RRGGBBAA` to add transparency\n* `RGB(A)`: for RGB Colors: `rgb(red, green, blue)` or `rgba(red, green, blue, alpha)`\n* `HSL(A)`: for HSL Colors: `hsl(hue, saturation, lightness)` or `hsla(hue, saturation, lightness, alpha)`\n* `Predefined Color Names`: 140 color names are predefined in the HTML and CSS color specification: `blue`, `red`, `coral`, `brown`, [etc...](https://www.w3schools.com/colors/colors_names.asp)\n* `None`: For no color to be applied: Sometimes VSCode will pull a color from your theme, other times it uses black\n* `#FFFFFF` is our default",
"default": "#FFFFFF"
}
"configuration": {
"title": "Mind_Reader",
"properties": {
"mindReader.productType": {
"type": "string",
"description": "Specifies the LEGO® product.",
"default": "MINDSTORMS EV3",
"enum": [
"MINDSTORMS EV3",
"SPIKE Prime"
],
"enumDescriptions": [
"LEGO® MINDSTORMS® EV3 (31313)",
"LEGO® Education SPIKE™ Prime Set (45678)"
]
},
"mindReader.reader.screenReader": {
"type": "string",
"description": "Specifies which screen reader to optimize for.",
"default": "NVDA",
"enum": [
"NVDA",
"Orca",
"VoiceOver"
],
"enumDescriptions": [
"NonVisual Desktop Access (Windows)",
"Orca (Linux)",
"Apple VoiceOver (macOS)"
]
},
"mindReader.reader.contextWindow": {
"type": "number",
"description": "The number of words around the cursor to use when reading the cursor context",
"default": 1
},
"mindReader.connection.portPath": {
"type": "string",
"markdownDescription": "The default port to try and establish a connection on."
},
"mindReader.connection.clearOutputOnRun": {
"type": "boolean",
"description": "Whether to clear the output each time the program is run",
"default": "true"
}
}
],
},
"views": {
"Mind-Reader": [
"MindReader": [
{
"id": "accessActions",
"name": "Access Actions",
@ -589,8 +330,8 @@
"viewsContainers": {
"activitybar": [
{
"id": "Mind-Reader",
"title": "Mind Reader Actions",
"id": "MindReader",
"title": "MindReader Actions",
"icon": "media/dep.svg"
}
]
@ -615,7 +356,7 @@
"@vscode/test-electron": "^1.6.2",
"eslint": "^7.27.0",
"glob": "^7.1.7",
"mocha": "^10.0.0",
"mocha": "^8.4.0",
"typescript": "^4.3.2",
"vscode-test": "^1.5.2"
},

View File

@ -1,60 +0,0 @@
#!/bin/bash
#* linux-install.sh: First-run setup script
#* Ensures git is installed, clones the repo, and then runs
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
ELEVATE='';if (( $UID !=0 )); then ELEVATE='sudo';fi
help () {
echo "Usage: $0 [-d] [-g path/to/git/directory]"
exit 0
}
gitdir=~/git
# Get option flags:
dry=false
while getopts ghd arg; do
case $arg in
g) gitdir="$OPTARG";;
h) help;;
d) dry=true;;
esac
done
function dryrun {
if $dry; then
echo "> $* [dry]";
else
echo "> $*"
$@
fi
}
setupdir="Mind_Reader/setup-development/linux"
repouri="https://github.com/We-Dont-Byte/Mind_Reader.git"
# Install git
if which git; then
echo "Git already installed."
elif which pacman; then
# using pacman
dryrun $ELEVATE pacman -Sy git
elif which apt; then
# using apt
dryrun $ELEVATE apt-get update && \
dryrun $ELEVATE apt-get install git -y
fi #? TODO: other package managers?
printf "\nCloning repository into $gitdir\n"
dryrun mkdir "$gitdir"
cd $gitdir && dryrun git clone "$repouri"
cd "$gitdir/$setupdir"
bash ./upgrade-linux.sh $@
echo "Opening VS Code..."
cd $gitdir/Mind_Reader
code .

View File

@ -1,4 +0,0 @@
apt-transport-https
build-essential
python3
wget

View File

@ -1,4 +0,0 @@
base-devel
git
wget
python3

View File

@ -1,141 +0,0 @@
#!/bin/bash
#* linux-update.sh: Install and update dependencies of Mind Reader, on linux.
#* Heads-up, this expects to be run from Mind_Reader/setup-development/linux.
# If run with bash -vx, print useful information instead of just a + sign
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
# If run as root, it could be because sudo isn't installed (some people disagree with sudo, especially on Arch)
ELEVATE='';if (( $UID !=0 )); then ELEVATE='sudo';fi
# Get option flags:
dry=false
while getopts d arg; do
case $arg in
d) dry=true;;
esac
done
function dryrun {
if $dry; then
echo "> $* [dry]";
else
echo "> $*"
$@
fi
}
# Get whether the user is running in Windows Subsystem for Linux
function getwsl {
grep "[Mm]icrosoft" /proc/version > /dev/null
return $?
}
# Get the user's default login shell
function getsh {
#* This code was created by user [Todd A. Jacobs](https://stackoverflow.com/users/1301972/todd-a-jacobs) on [StackOverflow](https://stackoverflow.com/a/11059152) and is used in accordance with Creative Commons CC BY-SA 3.0
getent passwd $LOGNAME | cut -d: -f7
}
# Install NVM (this is gross, but the recommended way to install nvm)
function installnvm {
# nvm's install script tries to be smart, so we have to work around its supposed cleverness
usershell=`getsh`
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | dryrun "$usershell"
# Reload profile
case $usershell in
*/bash) dryrun . ~/.bashrc ~/.bashprofile;;
*/zsh) dryrun . ~/.zshrc;;
*) "Your shell, $usershell, is currently unsupported by nvm. It's up to you to set up your development environment."; exit;;
esac
}
# Set these variables if you need to install for a different architecture
# Valid architectures are "x64", "arm64", "armhf"
arch=""
case `uname -i` in
"x86_64") arch="x64";;
"armv[6-8]*") arch="armhf";;
"aarch64") arch="arm64";;
*) echo "Architecture '$(uname -i)' unknown. Assuming x86_64..."
arch="x64";;
esac
if which pacman; then
# Install dependencies with pacman
printf "Installing dependencies with pacman...\n"
cat ./package-managers/pacman.dependencies | dryrun $ELEVATE pacman -S --needed -
# If not in Windows Subsystem for Linux, install vscode
[[ !(getwsl) ]] && dryrun $ELEVATE pacman -S --needed code
# Install Node Version Manager
installnvm
elif which apt-get; then
# Install dependencies using apt-get
printf "Installing dependencies with apt...\n"
dryrun xargs -a ./package-managers/apt.dependencies $ELEVATE apt-get install -y
# Check if vscode exists, if not, install it.
# Microsoft doesn't put it in any Ubuntu repos, you have to get it straight from them.
# This does have the side effect, however, of installing the official repository
# Don't attempt to install vscode if running in WSL; it can cause problems.
if !(which code) && !(getwsl); then
#* Install VSCode
vscodepackagename="code_amd64.deb"
dryrun wget "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-$arch" -O ./code.deb
dryrun $ELEVATE apt install ./code.deb
dryrun rm ./code.deb
fi
# Install Node Version Manager (nvm)
installnvm
fi
cdir=$(pwd)
# Go back to source tree root
cd ../..
# Check the VSCode version
nodeversion="node"
electronversion=""
#* Note:
#* When adding support for new VSCode versions, update this case
#* By the time you're working on this project, things are likely going to differ!
case `code --version` in
#* Each version of VSCode has a corresponding Electron version and Node version
#* These are used when configuring nvm
1.66.*) electronversion="17.2.0"; nodeversion="16.13.0";;
1.67.*) electronversion="17.4.1"; nodeversion="16.13.0";;
*) nodeversion="--lts";;
esac
# Install NodeJS and npm
printf "\nInstalling node $nodeversion\n"
dryrun nvm install "$nodeversion"
dryrun nvm use "$nodeversion"
# Use npm to install electron-rebuild and yo
printf "Installing electron-rebuild and vsce\n"
dryrun npm install -g electron-rebuild vsce
# use npm to acquire dependencies for Mind-Reader
printf "\nAcquiring dependencies...\n"
dryrun npm install
# automatically update vulnerable packages, if possible
printf "\nUpdating vulnerable packages, if possible...\n"
dryrun npm audit fix
# Use electron-rebuild to rebuild electron
if [[ "$electronversion" != "" ]]; then
printf "\nRebuilding electron with version $electronversion...\n"
dryrun electron-rebuild --version $electronversion
else
printf "\n%s\n%s\n%s\n%s\n" \
"Open Visual Studio Code, select the 'Help' tab in the toolbar, and go to 'About'." \
"Find the line that says 'Electron: [electron version]'" \
"Run the command below, filling in the Electron version with the one from that menu:" \
"electron-rebuild --version [electron version]"
fi
cd $cdir
echo "Done!"

View File

@ -1,173 +0,0 @@
<#
.synopsis
Dependency installer for Mind Reader on Windows.
This sets up a development environment from a BARE windows install.
.description
Install Git for Windows, clone the Mind Reader repository, and install all dependencies.
The script uses winget (A.K.A. "App Installer") to download and install the latest versions of each dependency, defined in winget/dependencies.json
Winget comes preinstalled on Windows 11 (21H2)/10 (21H1) or newer, and can be installed on Windows 10 1704+ through the Windows Store.
If you download Microsoft's developer VM, you have it!
As WinGet is built into Windows, it sidesteps any annoying third-party package managers, and is the lowest common denominator for package installation.
.link
https://github.com/We-Dont-Byte/Mind_Reader/
.parameter GitDir
Path to clone the git repo into (Default: $HOME/git/)
.parameter AllowAdministrator
Force-allow running this script as Administrator (not recommended, despite the frequent UAC prompts!)
.parameter NoPrompt
Disable all prompts for user input, and all waiting. (not recommended when combined with AllowAdministrator!)
.parameter ForceInstall
Force installation/upgrade of all modules, even if already present on the system.
.parameter DryRun
Perform a "dry run" of the script, changing directories and running commands, but without modifying anything.
.example
./install-windows.ps1
Perform a default upgrade of all Mind Reader dependencies
.example
./install-windows.ps1 -DryRun
Perform a dry run of the upgrade process, so you can evaluate what commands will be run
.example
./install-windows.ps1 -NoPrompt
Don't prompt for user input when upgrading
.example
./install-windows.ps1 AllowAdministrator
Allow script to run as Administrator
#>
param (
[string]$GitDir = "$HOME/git/", # Path to clone the git repo into
[switch]$h, [switch]$Help, # Get help
[switch]$AllowAdministrator, # Force allow installation as administrator
[switch]$NoPrompt, # Disable the 3-second wait and press-any-key prompt
[switch]$ForceInstall, # Always try to install
[switch]$DryRun # Run script without installing
)
$RepoURI = "https://github.com/We-Dont-Byte/Mind_Reader.git"
$RepoPath = "$GitDir\Mind_Reader"
$SetupPath = "$RepoPath\setup-development\windows"
if ($h -or $Help) {
Get-Help ./install-windows.ps1
exit
}
# .description
# Get-CommandAvailable: Checks whether a given command is available.
# If command is available, returns $false
function Get-CommandAvailable {
param ($command)
# Use a wildcard here so the command doesn't throw an exception we'd have to trycatch
# It's not a filthy hack if it's elegant!
RETURN (Get-Command -Name $command*)
}
#.description
# Invoke-DryRun a powershell statement
function Invoke-DryRun {
param ([string] $command)
$prompt = "> "
if ($DryRun) {
Write-Host "$prompt$command [dry]" -ForegroundColor darkgray
}
else {
Write-Host "$prompt$command" -ForegroundColor white
Invoke-Expression $command
}
}
#.description
# Reset-Path: Reload the Path environment variable
function Reset-Path {
Write-Output "Reloading Path..."
#* This code was created by user [mpen](https://stackoverflow.com/users/65387/mpen) on [StackOverflow](https://stackoverflow.com/a/31845512) and is used in accordance with Creative Commons CC BY-SA 3.0
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
# Check if Winget is available
if ( -not (Get-CommandAvailable winget) ) {
Write-Warning "It looks like winget isn't available.`n"
Write-Host "Update 'App Installer' through the Microsoft Store, or grab the '.msixbundle' from the winget-cli repository:"
Write-Host "( https://github.com/microsoft/winget-cli/releases/latest )`n" -ForegroundColor White
exit
}
# Check if the user ran the script with administrator privileges.
# Warn them.
if ( ([Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544') ) {
# If an administrator requests installation as administator,
# for example, to keep UAC prompts to a minimum, allow it.
if ($AllowAdministrator) {
Write-Warning "Script was run as Administrator. Exit now if you didn't mean to do this!"
# If you pass NoPrompt as an arg, you're very aware of the damage this script could do to your build env, and you just don't care
# The true chad of sysadmins.
if (!$NoPrompt) {
for ( $i = 3; $i -gt 0; $i--) {
Write-Host "Press Ctrl+C to exit. Continuing in $i...`r" -NoNewLine
Start-Sleep 1
}
Write-Host "Press any key to continue... "
[void][Console]::ReadKey(1) # Equivalent to Command Prompt's `pause` command
}
} else {
# Throw a fatal error if the user tries to run as administrator.
Throw "Script must be run as a normal user."
}
}
# Install Git
if ( -not (Get-CommandAvailable git) ) {
Write-Host "`nInstalling Git with winget..."
Invoke-DryRun 'winget install --id Git.Git'
Reset-Path
if ( -not (Get-CommandAvailable git)) {
Throw "Git failed to install. Aborting."
}
} else {
Write-Host "Git already installed." -ForegroundColor green
}
# Create git directory in GitDir
if ( -not (Test-Path "$GitDir") ) {
Invoke-DryRun "mkdir '$GitDir'"
}
# Clone the repository in GitDir
$dir = $pwd
Set-Location $GitDir
Invoke-DryRun "git clone '$RepoURI'"
# Run the install script
if ( -not (Test-Path "$SetupPath")) {
Throw "Repository contains no subdirectory '$SetupPath'."
}
Set-Location $SetupPath
# Run upgrade-windows to install the rest of the dependency chain.
$upgradeArgs = if ($AllowAdministrator) {" -AllowAdministrator"} else {""}
$upgradeArgs += if ($DryRun) {" -DryRun"} else {""}
PowerShell ("./upgrade-windows.ps1 -Install -NoPrompt" + $upgradeArgs)
Reset-Path
# Open VSCode in the repository location
Write-Host "`nOpening Visual Studio Code"
Set-Location $RepoPath
Invoke-DryRun "code ."
Set-Location $dir
if ( -not $NoPrompt ) {
Write-Host "`nPress any key to exit."; [void][Console]::ReadKey(1)
}

View File

@ -1,214 +0,0 @@
<#
.synopsis
Dependency updater for Mind Reader on Windows.
This script expects to be run from Mind_Reader/setup-development
.description
Updates dependencies (NodeJS, Python, etc.), VSCode, NVDA
The script uses winget (A.K.A. "App Installer") to download and install the latest versions of each dependency, defined in winget/dependencies.json
Winget comes preinstalled on Windows 11 (21H2)/10 (21H1) or newer, and can be installed on Windows 10 1704+ through the Windows Store.
If you download Microsoft's developer VM, you have it!
As WinGet is built into Windows, it sidesteps any annoying third-party package managers, and is the lowest common denominator for package installation.
.link
https://github.com/We-Dont-Byte/Mind_Reader/
.parameter GitDir
Path to clone the git repo into (Default: $HOME/git/)
.parameter AllowAdministrator
Force-allow running this script as Administrator (not recommended, despite the frequent UAC prompts!)
.parameter NoPrompt
Disable all prompts for user input, and all waiting. (not recommended when combined with AllowAdministrator!)
.parameter Install
Force installation/upgrade of all modules, even if already present on the system.
.parameter DryRun
Perform a "dry run" of the script, changing directories and running commands, but without modifying anything.
.example
./upgrade-windows.ps1
Perform a default upgrade of all Mind Reader dependencies
.example
./upgrade-windows.ps1 -DryRun
Perform a dry run of the upgrade process, so you can evaluate what commands will be run
.example
./upgrade-windows.ps1 -NoPrompt
Don't prompt for user input when upgrading
.example
./upgrade-windows.ps1 -AllowAdministrator
Allow script to be run as Administrator
#>
param (
[switch]$AllowAdministrator, # Force allow installation as administrator
[switch]$NoPrompt, # Disable the 3-second wait and press-any-key prompt
[switch]$Install, # Perform all installations, even when commands are present
[switch]$DryRun, # Run script without installing
[switch]$NoWinget # Don't update dependdencies with winget
)
# .description
# Get-CommandAvailable: Checks whether a given command is available.
# If command is available, returns $false
function Get-CommandAvailable {
param ($command)
# Use a wildcard here so the command doesn't throw an exception we'd have to trycatch
# It's not a filthy hack if it's elegant!
RETURN (Get-Command -Name $command*)
}
#.description
# Invoke-Dryrun a powershell statement
function Invoke-Dryrun {
param ([string] $command)
$prompt = "> "
if ($DryRun) {
Write-Host "$prompt$command [dry]" -ForegroundColor darkgray
}
else {
Write-Host "$prompt$command" -ForegroundColor white
Invoke-Expression $command
}
}
#.description
# Reset-Path: Reload the Path environment variable
function Reset-Path {
Write-Output "Reloading Path..."
#* This code was created by user [mpen](https://stackoverflow.com/users/65387/mpen) on [StackOverflow](https://stackoverflow.com/a/31845512) and is used in accordance with Creative Commons CC BY-SA 3.0
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
}
# Check if Winget is available
if ( -not (Get-CommandAvailable winget) ) {
Write-Warning "It looks like winget isn't available.`n"
Write-Host "Update 'App Installer' through the Microsoft Store, or grab the '.msixbundle' from the winget-cli repository:"
Write-Host "( https://github.com/microsoft/winget-cli/releases/latest )`n" -ForegroundColor White
exit
}
# Check if the user ran the script with administrator privileges.
# Warn them.
if ( ([Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544') ) {
# If an administrator requests installation as administator,
# for example, to keep UAC prompts to a minimum, allow it.
if ($AllowAdministrator) {
# If you pass -AllowAdministrator -NoPrompt as an arg, you're very aware of the damage this script could do to your build env, and you just don't care
# The true chad of sysadmins.
if (!$NoPrompt) {
Write-Warning "Script was run as Administrator. Exit now if you didn't mean to do this!"
for ( $i = 3; $i -gt 0; $i--) {
Write-Host "Press Ctrl+C to exit. Continuing in $i...`r" -NoNewLine
Start-Sleep 1
}
Write-Host "Press any key to continue... "
[void][Console]::ReadKey(1) # Equivalent to Command Prompt's `pause` command
}
}
else {
# Throw a fatal errorOccurred if the user tries to run as administrator.
Throw "Script must be run as a normal user."
}
}
# Import the packages from dependencies.json (autogenerated file, do not edit!)
if ( -not $NoWinget) {
Write-Host "`nInstalling packages with winget..."
Invoke-Dryrun 'winget install Microsoft.VisualStudio.2022.BuildTools --override "--wait --quiet --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"'
Invoke-Dryrun "winget import winget/dependencies.json"
# Reload the PATH, so we can use some of those sweet new commands we just installed
Reset-Path
}
# Check whether everything is available now:
$errorOccurred = 0
if ( -not (Get-CommandAvailable code) ) {
$errorOccurred += 1; Write-Host -ForegroundColor red "Visual Studio Code not available"
}
if ( -not (Get-CommandAvailable node) ) {
$errorOccurred += 2; Write-Host -ForegroundColor red "NodeJS not available"
}
if ( -not (Get-CommandAvailable npm ) ) {
$errorOccurred += 4; Write-Host -ForegroundColor red "Node Package Manager not available";
}
if ( $errorOccurred ) { exit }
# .description
# EnsureNodePackageInstalled:
# Checks for the presence of a cmdlet with a given name
# If it's not found, attempt to install it using npm
# If it's still not found, abort (this may not be good behavior?)
function EnsureNodePackageInstalled {
param (
[string[]]$command
)
if ( ($Install) -or -not (Get-CommandAvailable $command[0]) ) {
Write-Host "`nInstalling $($command[0])..."
Invoke-Dryrun "npm install -g $([string]$command)"
Reset-Path
if ( -not (Get-CommandAvailable $command[0])) {
Throw "$command failed to install. Aborting."
}
}
else {
Write-Host "`n$($command[0]) already installed." -ForegroundColor green
}
}
# electron-rebuild is used to rebuild the extension for a given version of Electron
EnsureNodePackageInstalled electron-rebuild
# vsce is used to package the extension
EnsureNodePackageInstalled vsce
# We're about to do some path traversal, so save the current directory
$prev_directory = $pwd
# install NodeJS dependencies for this extension
Write-Host "`nInstalling NodeJS Dependencies..."
Set-Location ..\..
Invoke-Dryrun "npm install"
# Run npm audit fix to upgrade vulnerable dependencies, except breaking changes.
Invoke-Dryrun "npm audit fix"
# if we're on a known VSCode version, go ahead and run electron-rebuild
switch -Regex (code --version) {
#?: Do we update this in the future, or stop maintaining it and remove this entire switch block?
"1\.67\.\d+" { $electronversion = "17.4.1"; break } # April 2022 update
"1\.66\.\d+" { $electronversion = "17.2.0"; break } # March 2022 update
default { $electronversion = $false } # Unknown update
}
if ( $electronversion ) {
Write-Host "`nRebuilding Electron for your version of VSCode..."
Invoke-Dryrun "electron-rebuild --version='$electronversion'"
Write-Host "Done!" -ForegroundColor green
}
else {
Write-Host "`nOpen Visual Studio Code, select the `"Help`" tab in the Toolbar, and go to `"About`".`nYou should see a page that looks like the following:" -ForegroundColor darkcyan
Write-Host " `(i`) Visual Studio Code`n`n Version: 1.66.2 `(user setup`)`n Commit: [Commit ID]`n Date: 2022-04-11T07:46:01.075Z`n Electron: 17.2.0`n [ ... ]" -ForegroundColor White
Write-Host "Note the Electron version `(17.2.0 in the above example`)." -ForegroundColor darkcyan
Write-Host "Run the command " -NoNewLine
Write-Host "electron-rebuild --version ELECTRON_VERSION" -NoNewLine -ForegroundColor green
Write-Host " in Mind Reader`'s root folder.`n"
}
# Return from whence we came
Set-Location $prev_directory
if ( -not $NoPrompt ) {
Write-Host "`nPress any key to exit."; [void][Console]::ReadKey(1)
}

View File

@ -1,29 +0,0 @@
{
"$schema": "https://aka.ms/winget-packages.schema.2.0.json",
"CreationDate": "2022-04-23T21:13:03.702-00:00",
"Sources": [
{
"Packages": [
{
"PackageIdentifier": "Python.Python.3"
},
{
"PackageIdentifier": "Git.Git"
},
{
"PackageIdentifier": "OpenJS.NodeJS.LTS"
},
{
"PackageIdentifier": "Microsoft.VisualStudioCode"
}
],
"SourceDetails": {
"Argument": "https://winget.azureedge.net/cache",
"Identifier": "Microsoft.Winget.Source_8wekyb3d8bbwe",
"Name": "winget",
"Type": "Microsoft.PreIndexed.Package"
}
}
],
"WinGetVersion": "1.2.10271"
}

View File

@ -1,7 +1,6 @@
import * as vscode from 'vscode';
import * as path from 'path';
import HubManager from '../hubManager';
//import EV3Manager from '../ev3Manager';
import { CommandEntry } from './commandEntry';
@ -34,23 +33,12 @@ export const hubCommands: CommandEntry[] = [
{
name: 'mind-reader.deleteProgram',
callback: deleteProgram
}/*,
{
name: 'mind-reader.ev3.test',
callback: ev3test
}*/
},
];
// Current connected hub
let hub: HubManager | null = null;
/*
let ev3: EV3Manager | null = null;
async function ev3test(): Promise<void> {
ev3 = await EV3Manager.activate();
ev3.test();
}
*/
async function connectHub(): Promise<void> {
if (hub && hub.isOpen()) {
vscode.window.showWarningMessage('LEGO Hub is already connected, reconnecting...');
@ -65,7 +53,7 @@ async function connectHub(): Promise<void> {
return;
}
let portPath: string | undefined = vscode.workspace.getConfiguration('mind-reader.connection').get('portPath');
let portPath: string | undefined = vscode.workspace.getConfiguration('mindReader.connection').get('portPath');
if (!portPath) {
let slots: vscode.QuickPickItem[] = [];

View File

@ -1,19 +1,24 @@
import * as vscode from "vscode";
import * as vscode from 'vscode';
import * as fs from 'fs';
import { CommandEntry } from "./commandEntry";
import { CommandEntry } from './commandEntry';
export const navCommands: CommandEntry[] = [
{
name: 'mind-reader.openWebview',
callback: openWebview,
},
{
name: "mind-reader.openKeybinds",
callback: () => vscode.commands.executeCommand("workbench.action.openGlobalKeybindings", "mind-reader"),
name: 'mind-reader.openKeyBindWin',
callback: () => openKeyBindWin('Windows')
},
{
name: 'mind-reader.openKeyBindMac',
callback: () => openKeyBindWin('Mac'),
},
//Navigation Keys......
// TODO: Why is this here? Extensions can rebind existing keybinds.
{
name: 'mind-reader.showAllSymbols',
callback: () => vscode.commands.executeCommand('workbench.action.showAllSymbols'),
@ -77,58 +82,35 @@ export const navCommands: CommandEntry[] = [
// COMMAND CALLBACK IMPLEMENTATIONS
function openWebview(): void {
//vscode.commands.executeCommand('workbench.action.zoomOut');
const panel = vscode.window.createWebviewPanel(
"mind-reader", // Identifies the type of the webview. Used internally
"Mind Reader", // Title of the panel displayed to the user
'mindReader', // Identifies the type of the webview. Used internally
'Mind Reader', // Title of the panel displayed to the user
vscode.ViewColumn.One, // Editor column to show the new webview panel in.
{}
); // Webview options. More on these later.
panel.webview.html = getWebviewContent();
panel.webview.html = getWebviewContent('media/html/main.html');
}
function getWebviewContent() {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mind Reader</title>
</head>
<body>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6a4XaqHkKcxJ6ZFms1RNrRurcOfl-diW90DAdpAx0Kv-rtrLJXovIhcUpayqFHATkrQ&usqp=CAU" width="600" />
<p></p>
<h1>Welcome to Mind Reader!</h1>
<p>We are the Single Semester Snobs and this is our tool to Help Blind Students Program Lego Mindstorms Robots in Python.</p>
<ul>
<li>
This tool includes features such as a hotkey that says how many spaces in the text starts, an Accessibility Pane,
Audio Alerts, and an advanced settings window.
<br>
The tool has hotkeys for both PC and Mac commands.
</li>
<li>This system is intended for everyone, but primarily for students K-12 who are visually impaired. </li>
<li>
Our goal is to provide an enhanced experience for students who are visually impaired that is transparent to
sighted students.
<br>
This allows for everyone to use the same software solution, whether or not they are
vision impaired.
</li>
</ul>
<p>Use the following key binding to bring up a page for all key bindings for windows
<br>
Control and Shift and 8
</p>
<p>Use this key binding to do the same for mac computers:
<br>
Command and Shift and 9
</p>
<h2>This is the Lego Spike Prime!</h2z>
<p></p>
<img src="https://cdn.vox-cdn.com/thumbor/qoaa6N2ppl7oj97MR-aj43qPy0w=/0x0:1024x576/920x613/filters:focal(431x207:593x369):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/63339099/lego_spike.0.png" width="300" />
<p></p>
<a href="https://www.lego.com/en-us/product/lego-education-spike-prime-set-45678">Get the robot!</a>
</body>
</html>`;
function getWebviewContent(filepath: string) {
return fs.readFileSync(filepath, {encoding: 'utf-8'});
}
function openKeyBindWin(os: 'Mac' | 'Windows'): void {
//vscode.commands.executeCommand('workbench.action.zoomOut');
const panel = vscode.window.createWebviewPanel(
'mindReader', // Identifies the type of the webview. Used internally
'MR Key Bindings', // Title of the panel displayed to the user
vscode.ViewColumn.One, // Editor column to show the new webview panel in.
{}
); // Webview options. More on these later.
if (os === 'Windows') {
panel.webview.html = getWebviewContent('media/html/winkeys.html');
} else if (os === 'Mac') {
panel.webview.html = getWebviewContent('media/html/mackeys.html');
}
}

View File

@ -1,388 +1,168 @@
"use strict";
import pl = require("../pylex");
import { CommandEntry } from './commandEntry';
import { Position, Selection, TextEditor, TextLine, window, workspace } from "vscode";
import * as vscode from 'vscode';
import * as pl from '../pylex';
import { CommandEntry } from './commandEntry';
export const textCommands: CommandEntry[] = [
{
name: 'mind-reader.getLineNumber',
callback: getLineNumber,
},
{
name: 'mind-reader.getIndent',
callback: getIndent,
},
{
name: 'mind-reader.getLeadingSpaces',
callback: getLeadingSpaces,
},
{
name: 'mind-reader.selectLeadingWhitespace',
callback: selectLeadingWhitespace
},
{
name: 'mind-reader.getNumberOfSelectedLines',
callback: getNumberOfSelectedLines,
},
{
name: 'mind-reader.getLineScope',
callback: runLineContext,
},
{
name: 'mind-reader.getWordsUnderCursor',
callback: runCursorContext
}
];
{
name: 'mind-reader.getIndent',
callback: getIndent,
},
/** Helper Function
*
* @param editor
* @returns numSpaces
** There are two methods that can be used to find the leading spaces:
** method 1:
** calculates the number of leading spaces by finding the length of the current line
** then subtracting from that the length of the text after trimming the whitespace at the start
** which will equal the number of whitespace characters
**
** TO-USE: set calculateLeadingSpaces to true
**
** method 2 (default):
** finds the index position of the first non-whitespace character in a 0-index
** this number will equal the number of spaces preceding the non-whitespace character
** due to the nature of 0-indexes.
**
** TO-USE: set calculateLeadingSpaces to false
*/
function fetchNumberOfLeadingSpaces(editor: TextEditor | undefined): number {
let numSpaces: number = 0;
{
name: 'mind-reader.runLineContext',
callback: runLineContext,
},
{
name: 'mind-reader.runCursorContext',
callback: runCursorContext
}
]
if (editor) {
/*
* set true to use method 1: find the number of leading spaces through arithmetic
* set false to use method 2: find the index position of the first non-whitespace character in a 0-index
* default: false
*/
const calculateLeadingSpaces: boolean = false; // change boolean value to change method
const line : TextLine = fetchLine(editor);
/* If true, calculate by arithmetic otherwise get index */
numSpaces = (calculateLeadingSpaces)
? pl.Lexer.getLeadingSpacesByArithmetic(line)
: pl.Lexer.getLeadingSpacesByIndex(line);
}
return numSpaces;
}
/** Helper Function
* * This function returns the number of selected lines in the active text editor window
@param editor
@returns numberOfSelectedLines
*/
function fetchNumberOfSelectedLines(editor: TextEditor | undefined): number {
let numberOfSelectedLines: number = 0;
if (editor) {
numberOfSelectedLines = editor.selections.reduce((prev, curr) => prev + (curr.end.line - curr.start.line), 1);
}
return numberOfSelectedLines;
}
/** Helper Function
** This function returns the line number of the active text editor window
* @param editor
* @returns editor!.selection.active.line + 1
*/
function fetchLineNumber(editor: TextEditor | undefined): number {
return editor!.selection.active.line + 1; // line numbers start at 1, not 0, so we add 1 to the result
}
/** Helper Function
** This function returns the text from the current line of the active text editor window
* @param editor
* @returns editor.document.lineAt(fetchLineNumber(editor) - 1)
*/
function fetchLine(editor: TextEditor | undefined): TextLine {
return editor!.document.lineAt(fetchLineNumber(editor) - 1); // We want the line index, so we remove the 1 we added to the result in fetchLineNumber
}
/* Function
* Function to return the number of selected (highlighted) lines
* Changes output to 'Line' for 1 line and 'Lines' for all other instances
*/
function getNumberOfSelectedLines(): void {
const editor: TextEditor | undefined = window.activeTextEditor;
if (editor) {
const numberOfSelectedLines: number = fetchNumberOfSelectedLines(editor);
(numberOfSelectedLines !== 1)
? window.showInformationMessage(`${numberOfSelectedLines.toString()} Lines Selected`)
: window.showInformationMessage(`${numberOfSelectedLines.toString()} Line Selected`);
}
else {
window.showErrorMessage('No document currently active');
}
}
/* Function
* Outputs the current line number the cursor is on
*/
function getLineNumber(): void {
const editor: TextEditor | undefined = window.activeTextEditor;
if (editor) {
const lineNum: number = fetchLineNumber(editor);
window.showInformationMessage(`Line ${lineNum.toString()}`);
}
else {
window.showErrorMessage('No document currently active');
}
}
/* Function
* Used to get the number of indents on a line
*/
function getIndent(): void {
const editor: TextEditor | undefined = window.activeTextEditor;
if (editor) {
const lineNum: number = (fetchLineNumber(editor));
const line : TextLine = fetchLine(editor);
if (line.isEmptyOrWhitespace) {
window.showInformationMessage(`Line ${lineNum.toString()} is Empty`);
}
else {
// Grab tab format from open document
const tabFmt: pl.TabInfo = {
size: typeof editor.options.tabSize === 'number'? editor.options.tabSize: 4,
hard: !editor.options.insertSpaces
};
const i: number = pl.Lexer.getIndent(line.text, tabFmt);
(i !== 1)
? window.showInformationMessage(`Line ${lineNum.toString()}: ${i.toString()} indents`)
: window.showInformationMessage(`Line ${lineNum.toString()}: ${i.toString()} indent`);
}
let editor = vscode.window.activeTextEditor;
if(editor)
{
let lineNum = editor.selection.active.line + 1;
let textLine = editor.document.lineAt(lineNum - 1);
if(textLine.isEmptyOrWhitespace)
{
vscode.window.showInformationMessage("Line number " + lineNum.toString() + " Is Empty");
}
else {
window.showErrorMessage('No document currently active');
}
}
/* Function
* Returns the number of leading spaces on the line the cursor is on
*/
function getLeadingSpaces(): void {
const editor: TextEditor | undefined = window.activeTextEditor;
if (editor) {
const lineNum : number = fetchLineNumber(editor);
const line : TextLine | undefined = fetchLine(editor);
if (line.isEmptyOrWhitespace) {
window.showInformationMessage(`Line ${lineNum.toString()} is empty`);
}
else {
const numSpaces = fetchNumberOfLeadingSpaces(editor);
/* Ternary operator to change the tense of 'space' to 'spaces' for the output if numSpaces is 0 or greater than 1 */
(numSpaces !== 1)
? window.showInformationMessage(`Line ${lineNum.toString()}: ${numSpaces.toString()} spaces`)
: window.showInformationMessage(`Line ${lineNum.toString()}: ${numSpaces.toString()} space`);
}
}
else {
window.showErrorMessage('No document currently active');
}
}
/* Function
* Selects the leading whitespace at the beginning of a line
* This feature was a request from Senior Design Day Spring 2022
*/
function selectLeadingWhitespace(): void {
const editor : TextEditor | undefined = window.activeTextEditor;
if (editor) {
const numSpaces = fetchNumberOfLeadingSpaces(editor); // This will be used for the output message
const lineNum : number = (fetchLineNumber(editor)); // Get the displayed line number
/* If numSpaces isn't greater than 1, then there is no leading whitespace to select */
if (numSpaces >= 1) {
const line : TextLine = fetchLine(editor);
const startPos: number = line.range.start.character; // Start at the starting character position
const endPos : number = line.firstNonWhitespaceCharacterIndex; // End at the first non whitespace character index
/* Apply our selection */
/* We need to subtract 1 from lineNum because we added 1 during the fetchLineNumber above and we want the 0-index for position, so remove it */
editor.selection = new Selection(new Position((lineNum - 1), startPos), new Position((lineNum - 1), endPos));
/* Ternary operator to change the tense of 'space' to 'spaces' for the output if numSpaces is 0 or greater than 1 */
(numSpaces !== 1)
? window.showInformationMessage(`Line ${lineNum.toString()}: ${numSpaces.toString()} spaces selected`)
: window.showInformationMessage(`Line ${lineNum.toString()}: ${numSpaces.toString()} space selected`);
// Move the cursor to the new selection
window.showTextDocument(editor.document);
}
else {
window.showErrorMessage(`Line ${lineNum.toString()}: No leading spaces to select!`); // No whitespace to select
}
}
else {
window.showErrorMessage('No document currently active'); // No active document
else
{
// Grab tab format from open document
let tabFmt = {
size: editor.options.tabSize as number,
hard: !editor.options.insertSpaces
};
let i = pl.Lexer.getIndent(textLine.text, tabFmt);
vscode.window.showInformationMessage("Line Number " + lineNum.toString() + " Indentation " + i.toString());
}
}
else{
vscode.window.showErrorMessage('No document currently active');
}
}
function runLineContext(): void {
const editor: TextEditor | undefined = window.activeTextEditor;
let editor = vscode.window.activeTextEditor;
if (editor){
// current text and line number
let editorText = editor.document.getText();
let line = editor.selection.active.line;
if (editor) {
// current text and line number
const editorText: string = editor.document.getText();
const line : number = editor.selection.active.line;
// get tab info settings
const size : number = typeof editor.options.tabSize === 'number'? editor.options.tabSize: 4;
const hard : boolean = !editor.options.insertSpaces;
// initialize parser
const parser : pl.Parser = new pl.Parser(editorText, {
size,
hard
});
// get tab info settings
let size = parseInt(editor.options.tabSize as string);
let hard = !editor.options.insertSpaces;
parser.parse();
const context: pl.LexNode[] = parser.context(line);
// build text
const contentString: string = createContextString(context, line);
// initialize parser
let parser = new pl.Parser(editorText, {size, hard});
parser.parse();
window.showInformationMessage(contentString);
}
else {
window.showErrorMessage('No document currently active');
}
let context = parser.context(line);
// build text
let contentString = createContextString(context, line);
vscode.window.showInformationMessage(contentString);
} else {
vscode.window.showErrorMessage('No document currently active');
}
}
function createContextString(context: pl.LexNode[], line: number): string {
if (context.length < 1) {
throw new Error('Cannot create context string for empty context');
throw new Error('Cannot create context string for empty context');
}
let contextString: string = `Line ${line + 1}`; // 1 based
// Print the current line
let contextString = 'Line ' + (line+1); // 1 based
if (context[0].token && context[0].token.attr) {
let tokenTypeString: string = `${context[0].token.type.toString()}`;
contextString += `: ${tokenTypeString !== pl.PylexSymbol.STATEMENT?tokenTypeString:""
} ${context[0].token.attr.toString()}`;
contextString += ': ' + context[0].token.type.toString() + ' ' + context[0].token.attr.toString();
}
for (let i = 1; i < context.length; i++) {
let node = context[i];
if (node.label === 'root') {
// root
contextString += ' in the Document Root';
continue;
}
for (let i: number = 1; i < context.length; i++) {
const node: pl.LexNode = context[i];
const inside: string = "inside";
// Node contains information relevant to the current line
if (node.token && node.token.type !== pl.PylexSymbol.EMPTY &&
node.token.type !== pl.PylexSymbol.STATEMENT) {
contextString += ` ${inside} ${node.token.type.toString()}`;
if (node.token.attr) {
contextString += ` ${node.token.attr.toString()}`;
}
}
// Node is the document root
if (node.label === 'root') {
// Append the name (relative path) of the document in the workspace
if (window.activeTextEditor?.document.uri) {
contextString += ` ${inside} ${workspace.asRelativePath(window.activeTextEditor?.document.uri)}`;
} else {
contextString += ` ${inside} the Document`;
}
continue;
if (node.token!.type !== pl.PylexSymbol.EMPTY &&
node.token!.type !== pl.PylexSymbol.INDENT) {
contextString += ' inside ' + node.token!.type.toString();
if (node.token!.attr) {
contextString += ' ' + node.token!.attr.toString();
}
}
}
return contextString;
}
/*
* find up to `n` words around the cursor, where `n` is
* the value of `#mind-reader.reader.contextWindow`
*/
// find up to `n` words around the cursor, where `n` is
// the value of `#mindReader.reader.contextWindow`
function runCursorContext(): void {
const editor: TextEditor | undefined = window.activeTextEditor;
let editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showErrorMessage('RunCursorContext: No Active Editor');
return;
}
if (!editor) {
window.showErrorMessage('RunCursorContext: No Active Editor');
return;
}
const cursorPos : Position = editor.selection.active;
const text : string = editor.document.lineAt(cursorPos).text;
const windowSize : any = workspace.getConfiguration('mind-reader').get('reader.contextWindow');
let trimmedText: string = text.trimStart(); // trim leading whitespace
const leadingWS : number = text.length - trimmedText.length; // # of characters of leading whitespace
let pos : number = leadingWS;
const maxPos : number = text.length;
// clamp cursor start/end to new range
let col : number = cursorPos.character; // effective column of the cursor position
trimmedText = trimmedText.trimEnd(); // trim trailing whitespace
if (col < leadingWS) {
// move effective start to first non-whitespace character in the line
col = leadingWS;
}
else if (col > leadingWS + trimmedText.length - 1) {
// move effective end to last non-whitespace character in the line
col = leadingWS + trimmedText.length - 1;
}
// generate list of space separate words with range data (start, end)
// TODO: can find user position to be done in one pass
const spaceWords: any[] = [];
while (pos < maxPos && trimmedText.length > 0) {
const word: string = trimmedText.replace(/ .*/, '');
spaceWords.push({
word,
start: pos,
end: pos + word.length
});
// remove processed word from trimmed text
const oldText: string = trimmedText;
trimmedText = trimmedText.replace(/[^ ]+/, '').trimStart();
// update pos to start of next word
pos += oldText.length - trimmedText.length;
}
// find word the user is in
let contextStart: number = -1;
let contextEnd : number = -1;
for (let i: number = 0; i < spaceWords.length; i++) {
if (col >= spaceWords[i].start && col <= spaceWords[i].end) {
// found the word
contextStart = Math.max(0, i - windowSize); // clamp start index
contextEnd = Math.min(spaceWords.length, i + windowSize + 1); // clamp end index
// construct cursor context string
let contextString: string = '';
for (let i: number = contextStart; i < contextEnd; i++) {
contextString += spaceWords[i].word + ' ';
}
// output cursor context string
window.showInformationMessage(contextString);
return;
}
const cursorPos: vscode.Position = editor.selection.active;
const text: string = editor.document.lineAt(cursorPos).text;
const windowSize: number = vscode.workspace.getConfiguration('mindReader').get('reader.contextWindow')!;
let trimmedText = text.trimStart(); // trim leading whitespace
let leadingWS = text.length - trimmedText.length; // # of characters of leading whitespace
trimmedText = trimmedText.trimEnd(); // trim trailing whitespace
let pos = leadingWS;
let maxPos = text.length;
// clamp cursor start/end to new range
let col = cursorPos.character; // effective column of the cursor position
if (col < leadingWS) {
// move effective start to first non-whitespace character in the line
col = leadingWS;
} else if (col > leadingWS + trimmedText.length - 1) {
// move effective end to last non-whitespace character in the line
col = leadingWS + trimmedText.length - 1;
}
// generate list of space separate words with range data (start, end)
// TODO: can find user position to be done in one pass
let spaceWords: {word: string, start: number, end: number}[] = [];
while (pos < maxPos && trimmedText.length > 0) {
let word = trimmedText.replace(/ .*/, '');
spaceWords.push({word, start: pos, end: pos+word.length});
// remove processed word from trimmed text
const oldText = trimmedText;
trimmedText = trimmedText.replace(/[^ ]+/, '').trimStart();
// update pos to start of next word
pos += oldText.length - trimmedText.length;
}
// find word the user is in
let contextStart: number = -1, contextEnd: number = -1;
for (let i = 0; i < spaceWords.length; i++) {
if (col >= spaceWords[i].start && col <= spaceWords[i].end) {
// found the word
contextStart = Math.max(0, i - windowSize); // clamp start index
contextEnd = Math.min(spaceWords.length, i + windowSize + 1); // clamp end index
// construct cursor context string
let contextString = '';
for (let i = contextStart; i < contextEnd; i++) {
contextString += spaceWords[i].word + ' ';
}
// output cursor context string
vscode.window.showInformationMessage(contextString);
return;
}
}
}

View File

@ -1,31 +0,0 @@
import * as vscode from 'vscode';
//import * as fs from 'fs';
//import { logger } from './extension';
export default class EV3Manager {
private ev3devBrowser: vscode.Extension<any> | undefined = vscode.extensions.getExtension("ev3dev.ev3dev-browser");
private constructor() {}
public test() {
//console.log(this.ev3devBrowser);
// This seems to be the only thing we, as an extension,
// are allowed to do with this other extension.
vscode.commands.executeCommand("ev3devBrowser.action.pickDevice", null);
}
public static activate(): Promise<EV3Manager> {
return new Promise (async (resolve) => {
try {
let mgr = new EV3Manager();
// Wait for ev3devBrowser to start
await mgr.ev3devBrowser?.activate();
// Return ev3Manager
return resolve(mgr);
}
catch (err) {
throw err;
}
});
}
}

View File

@ -1,47 +1,49 @@
import * as vscode from "vscode";
import * as pl from "./pylex";
import CommandNodeProvider from "./commandNodeProvider";
import Logger from "./log";
import { lineHighlighter } from "./lineHighlighter";
import * as vscode from 'vscode';
import * as pl from './pylex';
import { accessCommands, hubCommands, navCommands, textCommands } from "./commands";
import {
accessCommands,
hubCommands,
navCommands,
textCommands
} from './commands';
import CommandNodeProvider from './commandNodeProvider';
import Logger from './log';
// Output Logger
const product: string = vscode.workspace.getConfiguration("mind-reader").get("productType")!;
const outputChannel = vscode.window.createOutputChannel(product + " Output");
export const logger = new Logger(outputChannel);
const product: string = vscode.workspace.getConfiguration('mindReader').get('productType')!;
const outputChannel = vscode.window.createOutputChannel(product + " Output");
export const logger = new Logger(outputChannel);
let parser: pl.Parser = new pl.Parser();
export function activate(context: vscode.ExtensionContext) {
// Engage LineHighlighter
lineHighlighter();
vscode.window.showInformationMessage('Mind_Reader is loaded!');
parser.parse("Beep Boop");
parser.parse('Beep Boop');
const allCommands = [
accessCommands,
hubCommands,
navCommands,
textCommands,
textCommands
].flat(1);
// Register Commands
allCommands.forEach((command) => {
context.subscriptions.push(
vscode.commands.registerCommand(command.name, command.callback)
allCommands.forEach(command => {
let disposable = vscode.commands.registerCommand(
command.name,
command.callback
);
context.subscriptions.push(disposable);
});
let accessProvider = new CommandNodeProvider(
[accessCommands, textCommands].flat(1)
);
vscode.window.registerTreeDataProvider("accessActions", accessProvider);
let accessProvider = new CommandNodeProvider([accessCommands, textCommands].flat(1));
vscode.window.registerTreeDataProvider('accessActions', accessProvider);
let hubProvider = new CommandNodeProvider(hubCommands);
vscode.window.registerTreeDataProvider("hubActions", hubProvider);
vscode.window.showInformationMessage("Mind Reader finished loading!");
vscode.window.registerTreeDataProvider('hubActions', hubProvider);
}
export function deactivate() {}

View File

@ -76,14 +76,12 @@ export default class HubManager {
// get full lines in buffer
let msgs = this.receiveBuffer.split(/[\r>]/); // split by newline
let msgs = this.receiveBuffer.split(/\r/); // split by newline
this.receiveBuffer = msgs.pop()!; // store unhandled data
msgs = msgs.filter(x => !x.match(/{"m":\d+,"p":/)); // drop sensor broadcast response spam
msgs = msgs.filter(x => !x.startsWith('{"m":0,"p":')); // drop sensor broadcast response spam
for (const msg of msgs) {
// check if message is actually json
if (!msg.includes("{")) { continue; }
// check if this msg is a response to a pending request
try {
let json: { [key: string]: any };
@ -114,15 +112,11 @@ export default class HubManager {
case 'runtime_error':
logger.error(Buffer.from(params[3], 'base64').toString());
break;
case 2:
logger.info(`Battery at ${params[0]}V`);
break;
}
vscode.window.showErrorMessage("Program Error.");
console.log(`Program error: ${msg}`);
}
} catch (err) {
console.log('Could not parse JSON:', msg, err);
console.log('Could not parse JSON:', msg);
}
}
}

View File

@ -1,312 +0,0 @@
/**
* ?
* ?
* ?
* ?
* ?
* ?
* ! Initial Setup:
* ! Open settings.json (ctrl+shift+p type 'settings' choose: 'Preferences: Open Settings (JSON))
* ! Add the following to the bottom (may have to add a comma to the line above if it's not there, also remove the *s):
* "mind-reader.lineHighlighter.isEnabled" : true,
* "mind-reader.lineHighlighter.multiLineIsEnabled" : false,
*
* "mind-reader.lineHighlighter.backgroundColor" : "#232C5C",
* "mind-reader.lineHighlighter.outlineColor" : "#4866FE",
* "mind-reader.lineHighlighter.outlineWidth" : "1px",
* "mind-reader.lineHighlighter.outlineStyle" : "solid",
*
* "mind-reader.lineHighlighter.borderColorTop" : "#FFFFFF",
* "mind-reader.lineHighlighter.borderColorRight" : "#FFFFFF",
* "mind-reader.lineHighlighter.borderColorBottom" : "#FFFFFF",
* "mind-reader.lineHighlighter.borderColorLeft" : "#FFFFFF",
*
* "mind-reader.lineHighlighter.borderWidthTop" : "1px",
* "mind-reader.lineHighlighter.borderWidthRight" : "16px",
* "mind-reader.lineHighlighter.borderWidthBottom" : "1px",
* "mind-reader.lineHighlighter.borderWidthLeft" : "1px",
*
* "mind-reader.lineHighlighter.borderStyleTop" : "solid",
* "mind-reader.lineHighlighter.borderStyleRight" : "solid",
* "mind-reader.lineHighlighter.borderStyleBottom" : "solid",
* "mind-reader.lineHighlighter.borderStyleLeft" : "solid",
*
* "mind-reader.lineHighlighter.fontStyle" : "normal",
* "mind-reader.lineHighlighter.fontWeight" : "bolder",
* "mind-reader.lineHighlighter.textDecoration" : "none",
* "mind-reader.lineHighlighter.textColor" : "#FFFFFF",
*
* ! Restart VSCode for changes to take effect (if they didn't automatically)
* ! Afterwards you can now edit using the settings window, or manually edit them
* ! directly in settings.json by editing the values.
*
* TODO: FEATURE: Add ability for user to change options through a command pallette configurator
* TODO: FEATURE: Add hotkey to toggle linehighlighter on/off
* TODO: BUG: Adding the settings configurator made default settings break (if no values are found in settings.json)
**/
'use strict';
import { Position, window, workspace, TextEditorDecorationType, TextEditor, WorkspaceConfiguration, Range } from 'vscode';
export { lineHighlighter };
let highlightStyle: TextEditorDecorationType;
function lineHighlighter(): void {
let highlightStyle : TextEditorDecorationType = getHighlighterStyle();
let activeTextEditor : TextEditor | undefined = window.activeTextEditor;
let isEnabled : boolean | undefined = getHighlighterStatus();
let multiLineIsEnabled: boolean | undefined = getMultiLineHighlighterStatus();
/**
* Trigger the line highlight when the extension loads so current line gets highlighted
*/
triggerHighlight();
/**
* Trigger for when the active text editor changes
*/
window.onDidChangeActiveTextEditor((editor) => {
if (!editor) {
return;
}
triggerHighlight();
});
/**
* Trigger for when text selection changes
*/
window.onDidChangeTextEditorSelection((editor) => {
if (!editor.textEditor) {
return;
}
triggerHighlight();
});
/**
* Trigger for when the text document changes
*/
workspace.onDidChangeTextDocument(() => {
if (!activeTextEditor) {
return;
}
triggerHighlight();
});
/**
* Trigger for when the window state changes
*/
window.onDidChangeWindowState((editor) => {
if (!editor) {
return;
}
triggerHighlight();
});
/**
* Trigger for when configuration changes
*/
workspace.onDidChangeConfiguration((editor) => {
if (!editor) {
return;
}
highlightStyle.dispose(); // Dump existing styling
isEnabled = getHighlighterStatus(); // check if line highlighter is enable/disabled
multiLineIsEnabled = getMultiLineHighlighterStatus(); // Check if multiline highlighting is enabled/disabled
highlightStyle = getHighlighterStyle(); // get new line highlighter styling
triggerHighlight(); // trigger highlight with new styling
});
/**
* main function that triggers the highlights
*/
function triggerHighlight(): void {
if (!activeTextEditor) {
return;
}
/**
* Sets the activeTextEditor to the current active window
*/
activeTextEditor = window.activeTextEditor;
if (activeTextEditor !== undefined) {
/**
* If the line highlighter function is enabled
* set the decorations with our chosen highlighting style on the selection
* otherwise (highlighter is disabled) dump our highlighting style
*/
switch (isEnabled) {
case true: /* isEnabled is true */
switch (multiLineIsEnabled) {
case true: /* isEnabled is true and multiLineIsEnabled is true */
activeTextEditor.setDecorations(highlightStyle, activeTextEditor.selections);
break;
case false: /* isEnabled is true and multiLineIsEnabled is false */
switch (activeTextEditor.selection.isSingleLine) {
case true: /* isEnabled is true and multiLineIsEnabled is false and VSCode is reporting a single line */
let currentPosition = [];
for (let i = 0; i < activeTextEditor.selections.length; i++) {
currentPosition[i] = { range: new Range(activeTextEditor.selections[i].anchor, activeTextEditor.selections[i].anchor) };
}
activeTextEditor.setDecorations(highlightStyle, currentPosition);
break;
case false: /* isEnabled is true and multiLineIsEnabled is false and VSCode is reporting multiple lines */
// Dispose of our highlighting style so multiple lines aren't all highlighted when clicking and dragging to highlight
activeTextEditor.setDecorations(highlightStyle, []); // This will dispose of a single editor instead of all editors
break;
default: /* isEnabled is true and multiLineIsEnabled is false and VSCode is reporting something else - break out of 3rd switch */
break;
}
break;
default: /* isEnabled is true and multiLineIsEnabled is undetected - break out of 2nd switch statement */
break;
}
break;
case false: /* isEnabled is false */
highlightStyle.dispose();
break;
default: /* break out of initial switch if 'true or false' is not found */
break;
}
// Keep track of position
new Position(activeTextEditor.selection.start.line, activeTextEditor.selection.start.character);
}
}
/**
* * Function to get the user configured highlighting styles, or use defaults
*
* * Designed with user configuration in mind, able to control different sides
* * independently from each other (in most cases). This allows for many different
* * configurations.
*
* ? Colors Can be input with the following values:
* * https://www.w3schools.com/cssref/css_colors.asp for string based color values
* * Hex -> #<value> | rgb(###, ###, ###) | rgba(###, ###, ###, ###) | hsla(##, ##%, ##%, .#)
*
* ? Width Input Values
* ! Some work better than others, if one isn't working try a different method:
* * thin | medium | thick | px | rem | em | cm
*
* ? Other values
* * font-style : none|normal|italic|oblique;
* * font-weight : none|normal|bold|bolder|lighter|number;
* * border-style : none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset;
* * outline-style : none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset;
* * outline-width : none|medium|thin|thick|length;
* * border-width : none|medium|thin|thick|length;
* ? https://www.w3schools.com/cssref/pr_text_text-decoration.asp for text-decoration
*
* ! borderWidthRight acts weirdly, on my system 16px works best with the other directions set to 1px
*
* @returns highlighterStyle
*/
function getHighlighterStyle(): TextEditorDecorationType {
// Used so we don't have to type out workspace.getConfiguration('mind-reader.lineHighlighter') on every line, ie: shorthand
const userConfig: WorkspaceConfiguration = workspace.getConfiguration('mind-reader.lineHighlighter');
const borderWidthTop : string = userConfig.get('borderWidthTop') || "1px";
const borderWidthRight : string = userConfig.get('borderWidthRight') || "16px";
const borderWidthBottom : string = userConfig.get('borderWidthBottom') || "1px";
const borderWidthLeft : string = userConfig.get('borderWidthLeft') || "1px";
const borderStyleTop : string = userConfig.get('borderStyleTop') || "solid";
const borderStyleRight : string = userConfig.get('borderStyleRight') || "solid";
const borderStyleBottom : string = userConfig.get('borderStyleBottom') || "solid";
const borderStyleLeft : string = userConfig.get('borderStyleLeft') || "solid";
const borderColorTop : string = userConfig.get('borderColorTop') || "#FFFFFF";
const borderColorRight : string = userConfig.get('borderColorRight') || "#FFFFFF";
const borderColorBottom : string = userConfig.get('borderColorBottom') || "#FFFFFF";
const borderColorLeft : string = userConfig.get('borderColorLeft') || "#FFFFFF";
const backgroundColor : string = userConfig.get('backgroundColor') || "#232C5C";
const fontStyle : string = userConfig.get('fontStyle') || "normal";
const fontWeight : string = userConfig.get('fontWeight') || "bolder";
const outlineColor : string = userConfig.get('outlineColor') || "#4866FE";
const outlineStyle : string = userConfig.get('outlineStyle') || "solid";
const outlineWidth : string = userConfig.get('outlineWidth') || "1px";
const textDecoration : string = userConfig.get('textDecoration') || "none";
const textColor : string = userConfig.get('textColor') || "#FFFFFF";
// Combine all our styling into a single variable to return
const highlighterStyle : TextEditorDecorationType = window.createTextEditorDecorationType({
isWholeLine : true,
backgroundColor : `${backgroundColor}`,
fontStyle : `${fontStyle}`,
fontWeight : `${fontWeight}`,
textDecoration : `${textDecoration}`,
color : `${textColor}`,
borderColor : `${borderColorTop} ${borderColorRight} ${borderColorBottom} ${borderColorLeft}`,
borderWidth : `${borderWidthTop} ${borderWidthRight} ${borderWidthBottom} ${borderWidthLeft}`,
borderStyle : `${borderStyleTop} ${borderStyleRight} ${borderStyleBottom} ${borderStyleLeft}`,
outlineColor : `${outlineColor}`,
outlineWidth : `${outlineWidth}`,
outlineStyle : `${outlineStyle}`,
});
// Return our variable
return highlighterStyle;
}
/**
* Function to retrieve the 'isEnabled' status
*
* This will determine if the line highlighter will display or not
* - enabled -> will show
* - disabled -> will not show
*
* @returns enabledStatus
*/
function getHighlighterStatus(): boolean | undefined {
// set a boolean variable
let enabledStatus: boolean | undefined;
/***
* if 'isEnabled' is missing from the settings (aka undefined)
* - set our variable to true (default)
* otherwise, 'isEnabled' is listed in the settings
* - so we just pull its value
*/
(workspace.getConfiguration('mind-reader.lineHighlighter').get('isEnabled') === undefined)
? (enabledStatus = true)
: (enabledStatus = workspace.getConfiguration('mind-reader.lineHighlighter').get('isEnabled'));
// return the enabledStatus
return enabledStatus;
}
function getMultiLineHighlighterStatus(): boolean | undefined {
// set a boolean variable
let multiLineIsEnabled: boolean | undefined;
/***
* if 'isEnabled' is missing from the settings (aka undefined)
* - set our variable to true (default)
* otherwise, 'isEnabled' is listed in the settings
* - so we just pull its value
*/
(workspace.getConfiguration('mind-reader.lineHighlighter').get('multiLineIsEnabled') === undefined)
? (multiLineIsEnabled = true)
: (multiLineIsEnabled = workspace.getConfiguration('mind-reader.lineHighlighter').get('multiLineIsEnabled'));
// return the enabledStatus
return multiLineIsEnabled;
}
}
// Clean-up after ourself
export function deactivate() {
// when the plugin is terminated remove all highlighting
if (highlightStyle !== undefined) {
highlightStyle.dispose();
}
}

View File

@ -1,9 +1,9 @@
import { LineToken } from '.';
import { LineToken } from '.';
import { Symbol, EOFTOKEN, TabInfo } from './token';
type Rule = {
pattern: RegExp,
type : Symbol,
pattern: RegExp,
type: Symbol,
};
/**
@ -11,248 +11,205 @@ type Rule = {
* The first item is a recognition pattern, used to recognize the token
* the second item is the token type
*/
const rules: Rule[] = [{
pattern: /^\s*def\s+(?<attr>[a-zA-Z_][a-zA-Z0-9_]*)\(/,
type: Symbol.FUNCTION
},
{
pattern: /^\s*class\s+(?<attr>[a-zA-Z_][a-zA-Z0-9_]*)/,
type: Symbol.CLASS
},
{
pattern: /^\s*if\s+(?<attr>[^:]+):\s*/,
type: Symbol.IF
},
{
pattern: /^\s*elif\s+(?<attr>[^:]+):\s*$/,
type: Symbol.ELIF
},
{
pattern: /^\s*else\s*:/,
type: Symbol.ELSE
},
{
pattern: /^\s*for\s+(?<attr>[^:]+):\s*$/,
type: Symbol.FOR
},
{
pattern: /^\s*while\s+(?<attr>[^:]+):\s*$/,
type: Symbol.WHILE
},
{
pattern: /^\s*try\s*:/,
type: Symbol.TRY
},
{
pattern: /^\s*except(\s*(?<attr>[^:]+))?:\s*$/,
type: Symbol.EXCEPT
},
{
pattern: /^\s*finally\s*:\s*$/,
type: Symbol.FINALLY
},
{
pattern: /^\s*with\s+(?<attr>[^:]+):\s*$/,
type: Symbol.WITH
},
{
pattern: /^\s*#+\s*(?<attr>.*)\s*$/,
type: Symbol.COMMENT
},
{
pattern: /^\s*$/,
type: Symbol.EMPTY
},
{
pattern: /^\s*(?<attr>[^#]+)+\s*$/,
type: Symbol.STATEMENT
}
const rules: Rule[] = [
{
pattern: /^\s*def\s+(?<attr>[a-zA-Z_][a-zA-Z0-9_]*)\(/,
type: Symbol.FUNCTION
},
{
pattern: /^\s*class\s+(?<attr>[a-zA-Z_][a-zA-Z0-9_]*)/,
type: Symbol.CLASS
},
{
pattern: /^\s*if\s+(?<attr>[^:]+):\s*/,
type: Symbol.IF
},
{
pattern: /^\s*elif\s+(?<attr>[^:]+):\s*$/,
type: Symbol.ELIF
},
{
pattern: /^\s*else\s*:/,
type: Symbol.ELSE
},
{
pattern: /^\s*for\s+(?<attr>[^:]+):\s*$/,
type: Symbol.FOR
},
{
pattern: /^\s*while\s+(?<attr>[^:]+):\s*$/,
type: Symbol.WHILE
},
{
pattern: /^\s*try\s*:/,
type: Symbol.TRY
},
{
pattern: /^\s*except(\s*(?<attr>[^:]+))?:\s*$/,
type: Symbol.EXCEPT
},
{
pattern: /^\s*finally\s*:\s*$/,
type: Symbol.FINALLY
},
{
pattern: /^\s*with\s+(?<attr>[^:]+):\s*$/,
type: Symbol.WITH
},
];
/**
* Line-By-Line Lexer
*/
export default class Lexer {
private textLines : string[] = []; // array of text lines
private pos : number = 0;
private _currToken: LineToken = EOFTOKEN;
private textLines: string[] = []; // array of text lines
private pos: number = 0;
private _currToken: LineToken = EOFTOKEN;
/**
* @param `text` The text to lex.
* @param `tabFmt` A tab information descriptor
*/
constructor(text ? : string, private tabFmt ? : TabInfo) {
// default is 4 wide expanded tabs
this.tabFmt = {
...{
size: 4,
hard: false
},
...tabFmt
};
if (text) {
// normalize line feeds
text = text.replace('\r\n', '\n');
}
this.restart(text);
/**
* Calculates indentation level for a line. If using soft tabs,
* indent level rounds up (so, tabSize+1 spaces is 2 levels,
* 2*tabSize+1 is 3, etc.)
*
* @param `text` The line of text.
* @param `tabFmt` A tab information descriptor.
* @return The indent of `text` with consideration for `tabFmt`.
*/
static getIndent(text: string, tabFmt: TabInfo): number {
let leadingSpace: number = text.length - text.trimLeft().length;
let indent: number;
if (tabFmt.hard) {
// used tabs
indent = leadingSpace;
} else {
// use spaces
indent = Math.ceil(leadingSpace/tabFmt.size!);
}
/**
* Restart lexer with new text.
*
* @param `text` The new text to lex.
*/
restart(text ? : string): void {
this.pos = 0;
this._currToken = EOFTOKEN; // if no input, already on EOFTOKEN
if (text) {
this.textLines = text.split('\n');
this.next(); // advance to the first token
}
return indent;
}
/**
* @param `text` The text to lex.
* @param `tabFmt` A tab information descriptor
*/
constructor(text?: string, private tabFmt?: TabInfo) {
// default is 4 wide expanded tabs
this.tabFmt = {
...{size: 4, hard: false},
...tabFmt
};
if (text) {
// normalize linefeeds
text = text.replace('\r\n', '\n');
}
this.restart(text);
}
/**
* Restart lexer with new text.
*
* @param `text` The new text to lex.
*/
restart(text?: string): void {
this.pos = 0;
this._currToken = EOFTOKEN; // if no input, already on EOFTOKEN
if (text) {
this.textLines = text.split('\n');
this.next(); // advance to the first token
}
}
/**
* @return the current {@link LineToken}.
*/
currToken(): LineToken { return this._currToken; }
/**
* Advance the position in the token stream.
*
* @return The new current token, after advancing
*/
next(): LineToken {
if (this._currToken === EOFTOKEN && this.pos > this.textLines.length) {
throw new Error('Cannot advance past end');
}
/**
* @return the current {@link LineToken}.
*/
currToken(): LineToken {
return this._currToken;
// Until a LineToken is found, or EOF
while (this.pos < this.textLines.length) {
let line: string = this.textLines[this.pos];
let indent: number = Lexer.getIndent(line, this.tabFmt!);
let token: LineToken;
for (var r of rules) {
// Does line match pattern?
let match: RegExpMatchArray | null = line.match(r.pattern);
if (match) {
// Yes...
if (match.groups) {
token = new LineToken(r.type, this.pos, indent, match.groups["attr"]);
} else {
token = new LineToken(r.type, this.pos, indent);
}
this._currToken = token;
this.pos++;
return this.currToken();
}
}
// No rules matched
// TODO: move to rules
if (/^\s*(#.*)?$/.test(line)) {
// "empty" line
token = new LineToken(Symbol.EMPTY, this.pos, 999999);
} else {
// This is an INDENT token
token = new LineToken(Symbol.INDENT, this.pos, indent);
}
this._currToken = token;
this.pos++;
return this.currToken();
}
/**
* Advance the position in the token stream.
*
* @return The new current token, after advancing
*/
next(): LineToken {
if (this._currToken === EOFTOKEN && this.pos > this.textLines.length) {
throw new Error('Cannot advance past end');
}
// Didn't return, must be EOF
this._currToken = EOFTOKEN;
this.pos++;
return this.currToken();
}
// Until a LineToken is found, or EOF
while (this.pos < this.textLines.length) {
const line : string = this.textLines[this.pos];
const indent: number = Lexer.getIndent(line, this.tabFmt!);
let token : LineToken;
for (var r of rules) {
// Does line match pattern?
const match: RegExpMatchArray | null = line.match(r.pattern);
if (match) {
// Yes...
if (match.groups) {
token = new LineToken(r.type, this.pos, indent, match.groups["attr"]);
} else {
token = new LineToken(r.type, this.pos, indent);
}
this._currToken = token;
this.pos++;
return this.currToken();
}
}
// No rules matched
token = new LineToken(Symbol.INVALID, this.pos, 999999);
this._currToken = token;
this.pos++;
return this.currToken();
}
// Didn't return, must be EOF
this._currToken = EOFTOKEN;
this.pos++;
return this.currToken();
/**
* Move backwards in the token stream
*
* @param `n` The number of positions to retract.
* @return The new current token after retracting.
*/
retract(n: number = 1): LineToken {
if (this.pos - 1 - n < 0) {
// -1 because this.pos is currently on the next token
throw new RangeError('Cannot retract past start');
}
/**
* Move backwards in the token stream
*
* @param `n` The number of positions to retract.
* @return The new current token after retracting.
*/
retract(n: number = 1): LineToken {
if (this.pos - 1 - n < 0) {
// -1 because this.pos is currently on the next token
throw new RangeError('Cannot retract past start');
}
if (n <= 0) {
throw new RangeError('Retract distance must be positive');
}
if (this.pos - n === 0) {
// just restart
this.pos = 0;
return this.next();
}
let c = n + 1;
while (c > 0) {
this.pos--;
while (/^\s*(#.*)?$/.test(this.textLines[this.pos])) {
// Skip empty lines
this.pos--;
}
c--;
}
return this.next();
if (n <= 0) {
throw new RangeError('Retract distance must be positive');
}
/**
* Calculates indentation level for a line. If using soft tabs,
* indent level rounds up (so, tabSize+1 spaces is 2 levels,
* 2*tabSize+1 is 3, etc.)
*
* @param `text` The line of text.
* @param `tabFmt` A tab information descriptor.
* @return The indent of `text` with consideration for `tabFmt`.
*/
static getIndent(text: string, tabFmt: TabInfo): number {
const leadingSpace: number = text.length - text.trimStart().length;
let indent: number;
if (tabFmt.hard) {
// used tabs
indent = leadingSpace;
}
else {
// used spaces
//? indent = Math.round(leadingSpace / tabFmt.size! * 10) / 10; // fractional indentation support?
indent = Math.ceil(leadingSpace / tabFmt.size!);
}
return indent;
if (this.pos - n === 0) {
// just restart
this.pos = 0;
return this.next();
}
/**
* Calculates leading spaces for a line.
* This method uses arithmetic to calculate the number of leading spaces
*
* @param `line` The line of text.
* @return The number of leading spaces of `text`.
*/
static getLeadingSpacesByArithmetic(line: any): number {
const leadingSpaces: number = line.text.length - line.text.trimStart().length;
return leadingSpaces;
}
/**
* Calculates leading spaces for a line.
* This method finds the index position of the first non-whitespace character
* Since the index is built using a 0-index, the position of this character
* will equal the number of spaces preceding the character.
*
* @param `text` The line of text.
* @return The number of leading spaces of `text` with respect to the index position of the first non-whitespace character.
*/
static getLeadingSpacesByIndex(text: any): number {
const indexNum: number = text.firstNonWhitespaceCharacterIndex;
return indexNum;
let c = n + 1;
while (c > 0) {
this.pos--;
while (/^\s*(#.*)?$/.test(this.textLines[this.pos])) {
// Skip empty lines
this.pos--;
}
c--;
}
return this.next();
}
}

View File

@ -74,9 +74,8 @@ export default class Parser {
return children;
}
if (this.lexer.currToken().type === Symbol.STATEMENT ||
this.lexer.currToken().type === Symbol.EMPTY ||
this.lexer.currToken().type === Symbol.INVALID) {
if (this.lexer.currToken().type === Symbol.INDENT ||
this.lexer.currToken().type === Symbol.EMPTY) {
const label = this.lexer.currToken().type;
// regular code, advance and stay in same block
children.push(new LexNode(

View File

@ -16,10 +16,8 @@ export enum Symbol {
EXCEPT = "except",
FINALLY = "finally",
WITH = "with",
STATEMENT = "statement", // Indent token, contains non-empty code lines
COMMENT = "Comment",
INDENT = "INDENT", // Indent token, default if not EOF, only contains indent information
EMPTY = "EMPTY", // empty line, used only to associate with the previous line
INVALID = "INVALID",
EOF = "EOF"
}
@ -55,7 +53,7 @@ export default class LineToken {
* @return A string representation of the token
*/
toString(): string {
return `${this.type}, linenr: ${this.linenr+1}, indentLevel: ${this.indentLevel}, attr: ${this.attr}`;
return this.type + ", linenr:" + (this.linenr+1) + ", indentLevel: " + this.indentLevel + ", attr: " + this.attr;
}
}

View File

@ -12,7 +12,7 @@ suite('Lexer Test Suite', () => {
});
test('Empty String', () => {
let l: Lexer = new Lexer("");
let l: Lexer = new Lexer(undefined);
assert.deepStrictEqual(l.currToken(), EOFTOKEN);
});
@ -22,19 +22,18 @@ suite('Lexer Test Suite', () => {
});
test('Whitespace', () => {
let s: string = ' '.repeat(4).repeat(4);
let l: Lexer = new Lexer(s);
assert.deepStrictEqual(l.currToken(), new LineToken(Symbol.EMPTY, 0, s.length/4));
let l: Lexer = new Lexer(' \t\t'.repeat(4).repeat(4));
assert.deepStrictEqual(l.currToken(), new LineToken(Symbol.EMPTY, 0, 999999));
});
test('Comment', () => {
let l: Lexer = new Lexer('# this is a comment');
assert.deepStrictEqual(l.currToken(), new LineToken(Symbol.COMMENT, 0, 0, 'this is a comment'));
let l: Lexer = new Lexer('# ur mom eats toes');
assert.deepStrictEqual(l.currToken(), new LineToken(Symbol.EMPTY, 0, 999999));
});
test('Non-Whitespace with no construct', () => {
let l: Lexer = new Lexer('foobar');
assert.deepStrictEqual(l.currToken(), new LineToken(Symbol.STATEMENT, 0, 0, 'foobar'));
assert.deepStrictEqual(l.currToken(), new LineToken(Symbol.INDENT, 0, 0));
});
test('getIndent() accuracy, spaces', () => {
@ -51,14 +50,11 @@ suite('Lexer Test Suite', () => {
}
});
test('getIndent() accuracy, spaces with incomplete indentation', () => {
let size: number = 4;
test('getIndent() accuracy, spaces with incomplete tab', () => {
for (var i = 0; i < 100; i++) {
for (var j = 1; j <= 3; j++) {
let l: Lexer = new Lexer(' '.repeat(i) + ' '.repeat(j) + 'foobar', {size: size, hard: false});
// TODO: Swap these out when fractional indentation is used
//assert.strictEqual(l.currToken().indentLevel, i + (Math.round(j / size * 100) / 100));
assert.strictEqual(l.currToken().indentLevel, i + 1);
let l: Lexer = new Lexer(' '.repeat(i) + ' '.repeat(j) + 'foobar', {size: 4, hard: false});
assert.strictEqual(l.currToken().indentLevel, i+1);
}
}
});
@ -154,7 +150,7 @@ suite('Lexer Test Suite', () => {
test('retract() 1-100', () => {
let lines: string[] = Array.from(Array(100), (_, i) => 'line' + i);
let reference: LineToken[] = lines.map((_, i) => {
return new LineToken(Symbol.STATEMENT, i, 0, `line${i}`);
return new LineToken(Symbol.INDENT, i, 0);
});
for (var i = 0; i < 100; i++) {
@ -173,7 +169,7 @@ suite('Lexer Test Suite', () => {
test('2 full lex and retract passes', () => {
let lines: string[] = Array.from(Array(100), (_, i)=> 'line' + i);
let reference: LineToken[] = lines.map((_, i) => {
return new LineToken(Symbol.STATEMENT, i, 0, `line${i}`);
return new LineToken(Symbol.INDENT, i, 0);
});
let l: Lexer = new Lexer(lines.join('\n'));

View File

@ -13,7 +13,7 @@ suite('LexNode Test Suite', () => {
});
test('children() of leaf', () => {
let n: LexNode = new LexNode('leafLexNode', vscode.TreeItemCollapsibleState.None, new LineToken(Symbol.STATEMENT, 0, 0));
let n: LexNode = new LexNode('leafLexNode', vscode.TreeItemCollapsibleState.None, new LineToken(Symbol.INDENT, 0, 0));
assert.strictEqual(n.children(), null);
});

View File

@ -7,7 +7,7 @@ import LexNode from '../../../pylex/node';
import LineToken from '../../../pylex/token';
import { Symbol } from '../../../pylex/token';
import { root, statement } from '../../util';
import { root,indent,empty } from '../../util';
/**
* Test Descriptor
@ -23,24 +23,23 @@ const tests: ParserTest[] = [
{ name: 'Single Empty Line', input: [''], output: root(null) },
{
name: 'Single Whitespace Only Line',
input: [' '], // length 20
input: [' '],
output: root([
new LexNode(Symbol.EMPTY, 0, new LineToken(Symbol.EMPTY, 0, 20 / 4)) // 4 spaces per indent
empty(0)
])
},
{
name: 'Single Comment Only Line',
input: ['# this is a comment'],
input: ['# ur mom likes peas'],
output: root([
new LexNode(Symbol.EMPTY, 0, new LineToken(Symbol.COMMENT, 0, 0, "this is a comment"))
empty(0)
])
},
{
name: 'Single Non-Control Line',
input: ['my_age = 42'],
output: root([
//statement(0, 0)
new LexNode("name", 0, new LineToken(Symbol.STATEMENT, 0, 0, 'my_age = 42'))
indent(0, 0)
])
},
{
@ -56,10 +55,7 @@ const tests: ParserTest[] = [
'bar = "Blue M&Ms make me happy <:)"',
'reba = "A hard working gal"'
],
output: root([
new LexNode("name", 0, new LineToken(Symbol.STATEMENT, 0, 0, 'bar = "Blue M&Ms make me happy <:)"')),
new LexNode("name", 0, new LineToken(Symbol.STATEMENT, 1, 0, 'reba = "A hard working gal"'))
]),
output: root([indent(0,0), indent(1,0)]),
},
{
@ -70,13 +66,11 @@ const tests: ParserTest[] = [
'billy = "Scrubbly Bubbles!"'
],
output: root([
new LexNode('if radioshack', 0,
new LexNode('if radioshack',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 0, 0, 'radioshack'),
[
new LexNode('print radioshack.hours', 0, new LineToken(Symbol.STATEMENT, 1, 1, 'print radioshack.hours'))
]
),
new LexNode('billy = "Scrubbly Bubbles!"', 0, new LineToken(Symbol.STATEMENT, 2, 0, 'billy = "Scrubbly Bubbles!"'))
[indent(1, 1)]),
indent(2, 0)
])
},
@ -88,12 +82,11 @@ const tests: ParserTest[] = [
' print radioshack.hours'
],
output: root([
new LexNode('billy = "Scrubbly Bubbles!"', 0, new LineToken(Symbol.STATEMENT, 0, 0, 'billy = "Scrubbly Bubbles!"')),
new LexNode('if radioshack', 0, new LineToken(Symbol.IF, 1, 0, 'radioshack'),
[
new LexNode('print radioshack.hours', 0, new LineToken(Symbol.STATEMENT, 2, 1, 'print radioshack.hours'))
]
)
indent(0, 0),
new LexNode('if radioshack',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 1, 0, 'radioshack'),
[indent(2, 1)])
])
},
@ -108,18 +101,15 @@ const tests: ParserTest[] = [
' print("You really eat this?")',
],
output: root([
new LexNode('if yummy', 0, new LineToken(Symbol.IF, 0, 0, 'yummy'),
[
statement(1, 1, 'print("HOoray!")')
]),
new LexNode('elif just_ok', 0, new LineToken(Symbol.ELIF, 2, 0, 'just_ok'),
[
statement(3, 1, 'print("Do you have anything else?")')
]),
new LexNode('else', 0, new LineToken(Symbol.ELSE, 4, 0),
[
statement(5, 1, 'print("You really eat this?")')
]),
new LexNode('if yummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 0, 0, 'yummy'), [indent(1, 1)]),
new LexNode('elif just_ok',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELIF, 2, 0, 'just_ok'), [indent(3, 1)]),
new LexNode('else',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELSE, 4, 0), [indent(5,1)]),
])
},
@ -132,14 +122,13 @@ const tests: ParserTest[] = [
],
output: root([
new LexNode('if yummy',
0,
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 0, 0, 'yummy'),
[
new LexNode('if in_my_tummy', 0, new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
[
statement(2, 2, 'exclaim("Scrumdiddlyumptious!")')
]
)
new LexNode('if in_my_tummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
[indent(2, 2)])
],
)
])
@ -152,20 +141,23 @@ const tests: ParserTest[] = [
' if in_my_tummy:',
' exclaim("Scrumdiddlyumptious!")',
'else:',
' exclaim("DISGUSTING!")'
' exclaim("DAESGUSTEN~)"'
],
output: root([
new LexNode('if yummy', 0, new LineToken(Symbol.IF, 0, 0, 'yummy'),
new LexNode('if yummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 0, 0, 'yummy'),
[
new LexNode('if in_my_tummy', 0, new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
[
statement(2, 2, 'exclaim("Scrumdiddlyumptious!")')
]
)
new LexNode('if in_my_tummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
[indent(2, 2)])
]
),
new LexNode('else', 0, new LineToken(Symbol.ELSE, 3, 0),
[statement(4, 1, 'exclaim("DISGUSTING!")')]
new LexNode('else',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELSE, 3, 0),
[indent(4, 1)]
)
])
},
@ -176,27 +168,31 @@ const tests: ParserTest[] = [
'if yummy:',
' if in_my_tummy:',
' if looks_like_a_mummy:',
' print("you have a spot on your tummy")',
' print("you have a spot on your tummy"',
'else:',
' print("Food is food...")'
],
output: root([
new LexNode('if yummy',
0,
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 0, 0, 'yummy'),
[
new LexNode('if in_my_tummy', 0, new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
new LexNode('if in_my_tummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
[
new LexNode('if looks_like_a_mummy', 0, new LineToken(Symbol.IF, 2, 2, 'looks_like_a_mummy'),
[statement(3, 3, 'print("you have a spot on your tummy")')])
new LexNode('if looks_like_a_mummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 2, 2, 'looks_like_a_mummy'),
[indent(3, 3)])
]
)
]
),
new LexNode('else',
0,
new LexNode('else',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELSE, 4, 0),
[statement(5, 1, 'print("Food is food...")')]
[indent(5, 1)]
)
])
},
@ -207,42 +203,44 @@ const tests: ParserTest[] = [
'if yummy:',
' if in_my_tummy:',
' if looks_like_a_mummy:',
' print("you have a spot on your tummy")',
' print("you have a spot on your tummy"',
' else:',
' print("eek! a zombie!")',
' print("eek! a zombie!)',
' elif in_my_mouth:',
' print("itll be in my tummy soon!")',
' print("itll be in my tummy soon!"',
'else:',
' print("Food is food...")'
],
output: root([
new LexNode('if yummy', 0,
new LexNode('if yummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 0, 0, 'yummy'),
[
new LexNode('if in_my_tummy', 0,
new LexNode('if in_my_tummy',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 1, 1, 'in_my_tummy'),
[
new LexNode('if looks_like_a_mummy',
0,
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.IF, 2, 2, 'looks_like_a_mummy'),
[statement(3, 3, 'print("you have a spot on your tummy")')]),
[indent(3, 3)]),
new LexNode('else',
0,
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELSE, 4, 2),
[statement(5, 3, 'print("eek! a zombie!")')])
[indent(5, 3)])
]
),
new LexNode('elif in_my_mouth',
0,
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELIF, 6, 1, 'in_my_mouth'),
[statement(7, 2, 'print("itll be in my tummy soon!")')]
[indent(7, 2)]
)
]
),
new LexNode('else',
0,
new LexNode('else',
vscode.TreeItemCollapsibleState.None,
new LineToken(Symbol.ELSE, 8, 0),
[statement(9, 1, 'print("Food is food...")')]
[indent(9, 1)]
)
])
},
@ -250,24 +248,21 @@ const tests: ParserTest[] = [
name: 'Multiline Block',
input: [
'if yummy:',
' print("you have a spot on your tummy")',
' print("you have a spot on your tummy"',
' print("eek! a zombie!)',
' print("itll be in my tummy soon!")',
' print("itll be in my tummy soon!"',
'else:',
' print("Food is food...")'
],
output: root([
new LexNode('if yummy', 0, new LineToken(Symbol.IF, 0, 0, 'yummy'),
[
statement(1, 1, 'print("you have a spot on your tummy")'),
statement(2, 1, 'print("eek! a zombie!)'),
statement(3, 1, 'print("itll be in my tummy soon!")'),
indent(1, 1),
indent(2, 1),
indent(3, 1),
]
),
new LexNode('else', 0, new LineToken(Symbol.ELSE, 4, 0),
[
statement(5, 1, 'print("Food is food...")')
])
new LexNode('else', 0, new LineToken(Symbol.ELSE, 4, 0), [indent(5, 1)])
])
}
];

View File

@ -50,19 +50,19 @@ function root(nodes: LexNode[] | null): LexNode {
}
/* short hand for returning an indentation token for a certain line and indentation */
function statement(linenr: number, indentLevel: number, text: string = ""): LexNode {
return new LexNode(PylexSymbol.STATEMENT, 0, new LineToken(PylexSymbol.STATEMENT, linenr, indentLevel, text));
function indent(linenr: number, indentLevel: number): LexNode {
return new LexNode('INDENT', 0, new LineToken(PylexSymbol.INDENT, linenr, indentLevel));
}
/* short hand for returning an empty token for a certain line*/
function empty(linenr: number): LexNode {
return new LexNode(PylexSymbol.EMPTY, 0, new LineToken(PylexSymbol.EMPTY, linenr, 999999));
return new LexNode('EMPTY', 0, new LineToken(PylexSymbol.EMPTY, linenr, 999999));
}
export {
deparent,
root,
statement as statement,
indent,
empty
};