Skip to content

Commit c4717a4

Browse files
committed
Release v0.2.0
2 parents d527c50 + d76e956 commit c4717a4

File tree

5 files changed

+163
-69
lines changed

5 files changed

+163
-69
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ All notable changes will be documented in this file.
44

55
Contributors: This document uses style guidelines from [Keep A Changelog](http://keepachangelog.com/).
66

7+
## [v0.2.0] - 2021-05-09
8+
9+
### Added
10+
11+
- The `G-Code: Show the dictionary` command has been added. This command opens a webview that shows all the 'words' in the dictionary and their definitions. The webview is a static html page, the same kind of window used to preview a markdown file. In the future we may consider denoting the source of the definition as well (config file vs inline).
12+
13+
### Changed
14+
15+
- The active document is now being scanned for inline comments on file save event in addition to the activation event that was used initially. In the future listener for the document activation event may be removed, it remains in the codebase for now.
16+
717
## [v0.1.3] - 2021-02-06
818

919
### Changed

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ CAD/CAM packages typically show the X-axis in red, the Y-axis in green, and the
2424
- Should you miss the prompt, you can use the `G-Code: Adapt to current theme` command to force the extension to adapt to the theme you're using (as long as it's supported).
2525

2626

27-
### On-Hover Definitions
27+
### Build your own dictionary
2828

2929
<p align="center"><img src="https://user-images.githubusercontent.com/29161635/98761008-7cc6a780-23a2-11eb-819c-2f8287e03320.gif" alt="icon" height="400px" width="500px"></p>
3030

@@ -64,6 +64,14 @@ Examples of inline definitions:
6464

6565
When providing definitions, regardless of which method you use, don't use leading zeros. Provide a definition for `G1` not `G01`. When you hover over a code like `G01` the extension ignores the leading zero and returns a definition for `G1`.
6666

67+
##### Using the dictionary
68+
69+
**<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> `>G-Code: Show the dictionary`**
70+
71+
<p align="center"><img src="https://user-images.githubusercontent.com/29161635/117580501-35f20a00-b0c6-11eb-818e-7715809e2326.gif" alt="icon" height="400px" width="800px"></p>
72+
73+
You can use the command, `G-Code: Show the dictionary`, to get the definitions on screen, so you can see them alongside your code as you work. You can also see the definition for a particular code just by hovering over it.
74+
6775
### Line Numbering
6876

6977
**<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> `>G-Code: Line Numbers (Add/Update)`**

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "gcode",
44
"displayName": "G-Code",
55
"description": "The premier Visual Studio Code extension for G-Code",
6-
"version": "0.1.3",
6+
"version": "0.2.0",
77
"preview": true,
88
"author": {
99
"name": "Scott M. Wyant",
@@ -118,6 +118,11 @@
118118
"command": "gcode.tailorTextMateGrammar",
119119
"title": "Adapt to Current Theme",
120120
"category": "G-Code"
121+
},
122+
{
123+
"command": "gcode.showDictionary",
124+
"title": "Show the dictionary",
125+
"category": "G-Code"
121126
}
122127
],
123128
"configuration": {

src/hoverProvider/dictionary.ts

Lines changed: 137 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,168 @@
1-
import { ExtensionContext, window, workspace } from 'vscode'
1+
import { commands, ExtensionContext, ViewColumn, WebviewPanel, window, workspace } from 'vscode'
22

33
interface Definitions {
44
[key: string]: string
55
}
66

77
export class Dictionary {
8-
8+
99
private definitionsFromSettings: Definitions = {};
1010
private definitionsFromComments: Definitions = {};
1111
private definitions: Definitions = {};
12+
private panel: WebviewPanel | undefined
13+
14+
constructor(context: ExtensionContext) {
15+
16+
const fileText = window.activeTextEditor?.document.getText();
17+
18+
const removeLeadingZerosFromKeys = (obj: Definitions): Definitions => {
19+
Object.keys(obj).forEach(key => {
20+
let cleanKey = key;
21+
const prefix = key.replace(/\d+/g, '');
22+
if ((key.length > prefix.length) && key.startsWith(prefix)) {
23+
const suffix = key.substr(prefix.length);
24+
cleanKey = prefix + parseInt(suffix);
25+
if (cleanKey.length < key.length && obj[cleanKey] == undefined) {
26+
obj[cleanKey] = obj[key];
27+
delete obj[key];
28+
}
29+
}
30+
})
31+
return obj
32+
};
33+
34+
const refreshDefinitionsFromComments = (fileText: string) => {
35+
36+
function parse(comments: string[]): Definitions {
37+
// Change first and last characters from parens to double-quotes
38+
comments = comments.map(comment => '"' + comment.substr(1, comment.length - 2) + '"');
39+
// Ensure key value seperator is a colon, add inner quotes
40+
comments = comments.map(comment => comment.replace(/\s*[:=]\s*/, '": "'));
41+
// Finish converting comment to a JSON string
42+
const jsonString: string = "{\n" + comments.join(",\n") + "\n}";
43+
// Parse the JSON to an object !!! This may result in an error, we have not checked for duplicate keys
44+
return JSON.parse(jsonString);
45+
}
1246

13-
constructor(fileText?: string) {
47+
const regex = /\(\s*[A-Z0-9]{2,5}\s*[:=]\s*[a-zA-Z0-9\,\s]+\s*\)/g;
48+
const matches = fileText.match(regex);
49+
const obj = (matches == null) ? {} : parse(matches);
50+
return removeLeadingZerosFromKeys(obj);
1451

15-
// Initialize definitions
16-
this.definitionsFromComments = (fileText == undefined) ? {} : this.refreshDefinitionsFromComments(fileText);
17-
this.definitionsFromSettings = this.refreshDefinitionsFromSettings();
18-
this.definitions = this.mergeDefinitions();
19-
}
52+
}
53+
54+
const refreshDefinitionsFromSettings = () => {
55+
56+
// Get through the proxy object...
57+
const obj = JSON.parse(JSON.stringify(workspace.getConfiguration('gcode.definitions')));
58+
59+
return removeLeadingZerosFromKeys(obj);
60+
}
61+
62+
const mergeDefinitions = () => Object.assign({}, this.definitionsFromSettings, this.definitionsFromComments)
2063

64+
const publish = () => {
65+
this.definitions = mergeDefinitions()
66+
if (this.panel != undefined) { this.panel.webview.html = getWebviewHtml() }
67+
}
68+
69+
// Initialize definitions
70+
this.definitionsFromComments = (fileText == undefined) ? {} : refreshDefinitionsFromComments(fileText);
71+
this.definitionsFromSettings = refreshDefinitionsFromSettings();
72+
publish()
2173

22-
public register(context: ExtensionContext): void {
23-
24-
// Register a function to parse comments when the active editor changes
74+
// Register event handlers
2575
context.subscriptions.push(
26-
workspace.onWillSaveTextDocument(event => {
27-
if (event.document.languageId == 'gcode') {
28-
this.definitionsFromComments = this.refreshDefinitionsFromComments(event.document.getText());
29-
this.definitions = this.mergeDefinitions();
76+
77+
// Parse comments when the active editor changes
78+
window.onDidChangeActiveTextEditor(event => {
79+
if (event?.document.languageId == 'gcode') {
80+
this.definitionsFromComments = refreshDefinitionsFromComments(event.document.getText());
81+
publish()
3082
}
31-
})
32-
);
83+
}),
3384

34-
// Register a function to read definitions from settings when any config file is changed
35-
context.subscriptions.push(
85+
// Parse comments when the document is saved
86+
workspace.onDidSaveTextDocument(document => {
87+
if (document.languageId == 'gcode') {
88+
this.definitionsFromComments = refreshDefinitionsFromComments(document.getText());
89+
publish()
90+
}
91+
}),
92+
93+
// Read definitions from settings when any config file is changed
3694
workspace.onDidChangeConfiguration(event => {
3795
if (event.affectsConfiguration('gcode.definitions')) {
38-
this.definitionsFromSettings = this.refreshDefinitionsFromSettings();
39-
this.definitions = this.mergeDefinitions();
96+
this.definitionsFromSettings = refreshDefinitionsFromSettings();
97+
publish()
4098
}
41-
})
42-
);
43-
}
99+
}),
44100

45-
public lookup(code: string){
46-
const removeLeadingZeros = (code: string) => code.substring(0,1) + parseInt(code.substring(1)).toString();
47-
return this.definitions[removeLeadingZeros(code)];
48-
}
101+
// Register a command to display the dictionary in a webview
102+
commands.registerCommand('gcode.showDictionary', () => {
49103

50-
private mergeDefinitions() {
51-
return Object.assign({}, this.definitionsFromSettings, this.definitionsFromComments)
52-
}
104+
// Create and show panel
105+
if (this.panel != undefined) {
106+
this.panel.reveal(ViewColumn.Beside)
107+
}
108+
else {
109+
this.panel = window.createWebviewPanel(
110+
'gcodeDictionary',
111+
'G-Code Dictionary',
112+
ViewColumn.Beside,
113+
{}
114+
);
115+
this.panel.onDidDispose(
116+
() => { this.panel = undefined; },
117+
undefined,
118+
context.subscriptions
119+
);
120+
}
53121

54-
private refreshDefinitionsFromComments(fileText: string) {
55-
56-
function parse(comments: string[]): Definitions {
57-
// Change first and last characters from parens to double-quotes
58-
comments = comments.map(comment => '"' + comment.substr(1, comment.length - 2) + '"');
59-
// Ensure key value seperator is a colon, add inner quotes
60-
comments = comments.map(comment => comment.replace(/\s*[:=]\s*/, '": "'));
61-
// Finish converting comment to a JSON string
62-
const jsonString: string = "{\n" + comments.join(",\n") + "\n}";
63-
// Parse the JSON to an object !!! This may result in an error, we have not checked for duplicate keys
64-
return JSON.parse(jsonString);
65-
}
122+
// And set its HTML content
123+
this.panel.webview.html = getWebviewHtml();
124+
})
125+
126+
)
127+
128+
const getWebviewHtml = () => {
129+
const template = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>G-Code Dictionary</title></head><body></body></html>';
130+
131+
const keys = Object.keys(this.definitions).sort(function(a, b){
132+
133+
function getWord(str: string){
134+
const prefix = ((str.match(/^[A-Z]/g)) as RegExpMatchArray)[0]
135+
return {
136+
address: prefix,
137+
value: parseInt(str.replace(prefix, ''))
138+
}
139+
}
66140

67-
const regex = /\(\s*[A-Z0-9]{2,5}\s*[:=]\s*[a-zA-Z0-9\,\s]+\s*\)/g;
68-
const matches = fileText.match(regex);
69-
const obj = (matches == null) ? {} : parse(matches);
70-
return this.removeLeadingZerosFromKeys(obj);
141+
const A = getWord(a)
142+
const B = getWord(b)
143+
if(A.address > B.address) {
144+
return 1
145+
}
146+
else if (A.address < B.address) {
147+
return -1
148+
}
149+
else {
150+
return A.value - B.value
151+
}
152+
})
153+
154+
const data = keys.map(key => ({ word: key, meaning: this.definitions[key] }))
155+
const html = (data.map(item => `<p><strong>${item.word}</strong> - ${item.meaning}</p>`)).join('\n')
156+
return template.replace('<body></body>', `<body>${html}</body>`)
157+
}
71158

72159
}
73160

74-
private refreshDefinitionsFromSettings() {
75-
let obj = JSON.parse(JSON.stringify(workspace.getConfiguration('gcode.definitions')));
76-
return this.removeLeadingZerosFromKeys(obj);
161+
public lookup(code: string) {
162+
const removeLeadingZeros = (code: string) => code.substring(0, 1) + parseInt(code.substring(1)).toString();
163+
return this.definitions[removeLeadingZeros(code)];
77164
}
78165

79-
private removeLeadingZerosFromKeys(obj: Definitions): Definitions {
80-
Object.keys(obj).forEach(key => {
81-
let cleanKey = key;
82-
const prefix = key.replace(/\d+/g, '');
83-
if ((key.length > prefix.length) && key.startsWith(prefix)) {
84-
const suffix = key.substr(prefix.length);
85-
cleanKey = prefix + parseInt(suffix);
86-
if (cleanKey.length < key.length && obj[cleanKey] == undefined) {
87-
obj[cleanKey] = obj[key];
88-
delete obj[key];
89-
}
90-
}
91-
})
92-
return obj
93-
}
94166
}
95167

96168

src/hoverProvider/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { Dictionary } from './dictionary'
44

55
export function register(context: ExtensionContext) {
66

7-
const dictionary = new Dictionary();
8-
dictionary.register(context);
7+
const dictionary = new Dictionary(context);
98

109
context.subscriptions.push(
1110
languages.registerHoverProvider('gcode', new gcodeHoverProvider(dictionary))

0 commit comments

Comments
 (0)