From a64f9c3ef609629e3f7e44a1051ec08fa09af4fd Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Tue, 3 Dec 2024 17:03:56 +0000 Subject: [PATCH 01/27] Feat: Remove language configuration files ready for using vscode's internal configs. Also, change package.json: - Version bump. - Fix user settings descriptions. - Remove language contribution declaration. - Added 3 new user settings: `multiLineStyleBlocks` to add unsupported languages to use the `/** */` comments; `overrideDefaultLanguageMultiLineComments` to override the style of multi-line comments for a language for the native vscode `blockComment` command. `bladeOverrideComments` to switch between HTML style `` comments, and Blade style `{{-- --}}` comments, when the file is using the Blade language. Also added a new keybinding for this. - Updated various dependencies and added new ones. --- .../language-configuration.blade.json | 24 -- .../language-configuration.cpp.json | 35 --- .../language-configuration.css.json | 32 --- .../language-configuration.go.json | 39 --- .../language-configuration.groovy.json | 26 -- .../language-configuration.less.json | 37 --- .../language-configuration.objective-c.json | 27 -- .../language-configuration.php.json | 24 -- .../language-configuration.rust.json | 36 --- .../language-configuration.scss.json | 33 --- .../language-configuration.swift.json | 29 -- package.json | 251 ++++++++---------- 12 files changed, 110 insertions(+), 483 deletions(-) delete mode 100644 language-configuration/language-configuration.blade.json delete mode 100644 language-configuration/language-configuration.cpp.json delete mode 100644 language-configuration/language-configuration.css.json delete mode 100644 language-configuration/language-configuration.go.json delete mode 100644 language-configuration/language-configuration.groovy.json delete mode 100644 language-configuration/language-configuration.less.json delete mode 100644 language-configuration/language-configuration.objective-c.json delete mode 100644 language-configuration/language-configuration.php.json delete mode 100644 language-configuration/language-configuration.rust.json delete mode 100644 language-configuration/language-configuration.scss.json delete mode 100644 language-configuration/language-configuration.swift.json diff --git a/language-configuration/language-configuration.blade.json b/language-configuration/language-configuration.blade.json deleted file mode 100644 index 53fa1af..0000000 --- a/language-configuration/language-configuration.blade.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "{{--", "--}}", "/*", "*/"] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - { "open": "{", "close": "}", "notIn": ["string"] }, - { "open": "[", "close": "]", "notIn": ["string"] }, - { "open": "(", "close": ")", "notIn": ["string"] }, - { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "--", "close": " --}}", "notIn": ["string"]} - ], - "indentationRules": { - "increaseIndentPattern": "({(?!.+}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch).*:)\\s*(/[/*].*)?$", - "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.cpp.json b/language-configuration/language-configuration.cpp.json deleted file mode 100644 index 5fec2dd..0000000 --- a/language-configuration/language-configuration.cpp.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": ["/*", "*/", "/*!"] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - { "open": "[", "close": "]" }, - { "open": "{", "close": "}" }, - { "open": "(", "close": ")" }, - { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"], - ["<", ">"] - ], - "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", - "folding": { - "markers": { - "start": "^\\s*#pragma\\s+region\\b", - "end": "^\\s*#pragma\\s+endregion\\b" - } - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.css.json b/language-configuration/language-configuration.css.json deleted file mode 100644 index 7c76b73..0000000 --- a/language-configuration/language-configuration.css.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "comments": { - "blockComment": ["/*", "*/", "/*!"] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - { "open": "{", "close": "}", "notIn": ["string", "comment"] }, - { "open": "[", "close": "]", "notIn": ["string", "comment"] }, - { "open": "(", "close": ")", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, - { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "folding": { - "markers": { - "start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/", - "end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/" - } - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.go.json b/language-configuration/language-configuration.go.json deleted file mode 100644 index c0ea703..0000000 --- a/language-configuration/language-configuration.go.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/", "/*!" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - { "open": "`", "close": "`", "notIn": ["string"]}, - { "open": "\"", "close": "\"", "notIn": ["string"]}, - { "open": "'", "close": "'", "notIn": ["string", "comment"]}, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"], - ["`", "`"] - ], - "indentationRules": { - "increaseIndentPattern": "^.*(\\bcase\\b.*:|\\bdefault\\b:|(\\b(func|if|else|switch|select|for|struct)\\b.*)?{[^}\"'`]*|\\([^)\"'`]*)$", - "decreaseIndentPattern": "^\\s*(\\bcase\\b.*:|\\bdefault\\b:|}[)}]*[),]?|\\)[,]?)$" - }, - "folding": { - "markers": { - "start": "^\\s*//\\s*#?region\\b", - "end": "^\\s*//\\s*#?endregion\\b" - } - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.groovy.json b/language-configuration/language-configuration.groovy.json deleted file mode 100644 index 183b70b..0000000 --- a/language-configuration/language-configuration.groovy.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "'", "close": "'", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ] -} \ No newline at end of file diff --git a/language-configuration/language-configuration.less.json b/language-configuration/language-configuration.less.json deleted file mode 100644 index d945091..0000000 --- a/language-configuration/language-configuration.less.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comments": { - "blockComment": ["/*", "*/", "/*!"], - "lineComment": "//" - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - { "open": "{", "close": "}", "notIn": ["string", "comment"] }, - { "open": "[", "close": "]", "notIn": ["string", "comment"] }, - { "open": "(", "close": ")", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, - { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "indentationRules": { - "increaseIndentPattern": "(^.*\\{[^}]*$)", - "decreaseIndentPattern": "^\\s*\\}" - }, - "folding": { - "markers": { - "start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/", - "end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/" - } - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.objective-c.json b/language-configuration/language-configuration.objective-c.json deleted file mode 100644 index 05ff8fd..0000000 --- a/language-configuration/language-configuration.objective-c.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/", "/*!" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "'", "close": "'", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ] -} \ No newline at end of file diff --git a/language-configuration/language-configuration.php.json b/language-configuration/language-configuration.php.json deleted file mode 100644 index ce3dfdd..0000000 --- a/language-configuration/language-configuration.php.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/", "/*!" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - { "open": "{", "close": "}", "notIn": ["string"] }, - { "open": "[", "close": "]", "notIn": ["string"] }, - { "open": "(", "close": ")", "notIn": ["string"] }, - { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "indentationRules": { - "increaseIndentPattern": "({(?!.+}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch).*:)\\s*(/[/*].*)?$", - "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.rust.json b/language-configuration/language-configuration.rust.json deleted file mode 100644 index 6873196..0000000 --- a/language-configuration/language-configuration.rust.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/", "/*!" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["<", ">"] - ], - "indentationRules": { - "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", - "decreaseIndentPattern": "^\\s*(\\s*\\/[*].*[*]\\/\\s*)*[})]" - }, - "folding": { - "markers": { - "start": "^\\s*//\\s*#?region\\b", - "end": "^\\s*//\\s*#?endregion\\b" - } - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.scss.json b/language-configuration/language-configuration.scss.json deleted file mode 100644 index fdb5c8b..0000000 --- a/language-configuration/language-configuration.scss.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "comments": { - "blockComment": ["/*", "*/", "/*!"], - "lineComment": "//" - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - { "open": "{", "close": "}", "notIn": ["string", "comment"] }, - { "open": "[", "close": "]", "notIn": ["string", "comment"] }, - { "open": "(", "close": ")", "notIn": ["string", "comment"] }, - { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, - { "open": "'", "close": "'", "notIn": ["string", "comment"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "folding": { - "markers": { - "start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/", - "end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/" - } - } -} \ No newline at end of file diff --git a/language-configuration/language-configuration.swift.json b/language-configuration/language-configuration.swift.json deleted file mode 100644 index e1741f6..0000000 --- a/language-configuration/language-configuration.swift.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/", "/*!" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "'", "close": "'", "notIn": ["string"] }, - { "open": "`", "close": "`", "notIn": ["string"] }, - { "open": "/**", "close": " */", "notIn": ["string"] }, - { "open": "/*!", "close": " */", "notIn": ["string"] } - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"], - ["`", "`"] - ] -} \ No newline at end of file diff --git a/package.json b/package.json index 0a77185f..204dcb8 100644 --- a/package.json +++ b/package.json @@ -1,145 +1,114 @@ { - "name": "automatic-comment-blocks", - "displayName": "Automatic Comment Blocks", - "description": "Provides block comment completion for Javadoc-style multi-line comments and single-line comment blocks for most officially supported languages.", - "version": "1.0.3", - "publisher": "ycodetech", - "homepage": "https://github.com/ycodetech/auto-comment-blocks", - "repository": { - "type": "git", - "url": "https://github.com/ycodetech/auto-comment-blocks.git" - }, - "license": "SEE LICENSE IN LICENSE", - "icon": "img/icon.png", - "galleryBanner": { - "color": "#171A29", - "theme": "dark" - }, - "engines": { - "vscode": "^1.12.0" - }, - "keywords": [ - "auto", - "comment", - "block", - "asterisk" - ], - "categories": [ - "Other" - ], - "activationEvents": [ - "*", - "onCommand:auto-comment-blocks.singleLineBlock" - ], - "main": "./out/src/extension", - "contributes": { - "configuration": { - "title": "Auto Comment Blocks", - "properties": { - "auto-comment-blocks.singleLineBlockOnEnter": { - "type": "boolean", - "default": false, - "description": "If enabled, a new commented line is inserted when Enter is pressed, and comment blocks are broken by pressing Shift+Enter. If disabled (the default), a commented line is inserted when Shift+Enter is pressed, and comment blocks are broken by pressing Enter." - }, - "auto-comment-blocks.disabledLanguages": { - "type": "array", - "default": [], - "description": "Add languageIds here to disable any comment completion for that language." - }, - "auto-comment-blocks.slashStyleBlocks": { - "type": "array", - "default": [], - "description": "Add languageIds here to enable '//' and '///'-style single line comment blocks for that language. This allows unsupported languages to have comment completion." - }, - "auto-comment-blocks.hashStyleBlocks": { - "type": "array", - "default": [], - "description": "Add languageIds here to enable '#'-style single line comment blocks for that language. This allows unsupported languages to have comment completion." - }, - "auto-comment-blocks.semicolonStyleBlocks": { - "type": "array", - "default": [], - "description": "Add languageIds here to enable ';'-style single line comment blocks for that language. This allows unsupported languages to have comment completion." - } - } - }, - "languages": [ - { - "id": "c", - "configuration": "./language-configuration/language-configuration.cpp.json" - }, - { - "id": "cpp", - "configuration": "./language-configuration/language-configuration.cpp.json" - }, + "name": "automatic-comment-blocks", + "displayName": "Automatic Comment Blocks", + "description": "Provides block comment completion for Javadoc-style multi-line comments and single-line comment blocks for most officially supported languages.", + "version": "1.1.0", + "publisher": "ycodetech", + "homepage": "https://github.com/ycodetech/auto-comment-blocks", + "repository": { + "type": "git", + "url": "https://github.com/ycodetech/auto-comment-blocks.git" + }, + "license": "SEE LICENSE IN LICENSE", + "icon": "img/icon.png", + "galleryBanner": { + "color": "#171A29", + "theme": "dark" + }, + "engines": { + "vscode": "^1.74.0" + }, + "keywords": [ + "auto", + "comment", + "block", + "asterisk" + ], + "categories": [ + "Other" + ], + "activationEvents": [ + "*", + "onCommand:auto-comment-blocks.singleLineBlock" + ], + "main": "./out/src/extension.js", + "contributes": { + "configuration": { + "title": "Auto Comment Blocks", + "properties": { + "auto-comment-blocks.singleLineBlockOnEnter": { + "type": "boolean", + "default": false, + "markdownDescription": "If enabled, a new commented line is inserted when Enter is pressed, and single line comments are broken by pressing `Shift + Enter`. If disabled (the default), a commented line is inserted when `Shift + Enter` is pressed, and single line comments are broken by pressing `Enter`." + }, + "auto-comment-blocks.disabledLanguages": { + "type": "array", + "default": [], + "markdownDescription": "Add language IDs here to disable any comment completion for that language." + }, + "auto-comment-blocks.slashStyleBlocks": { + "type": "array", + "default": [], + "markdownDescription": "Add language IDs here to enable `//` and `///`-style single line comment blocks for that language. This allows unsupported languages to have comment completion." + }, + "auto-comment-blocks.hashStyleBlocks": { + "type": "array", + "default": [], + "markdownDescription": "Add language IDs here to enable `#`-style single line comment blocks for that language. This allows unsupported languages to have comment completion." + }, + "auto-comment-blocks.semicolonStyleBlocks": { + "type": "array", + "default": [], + "markdownDescription": "Add language IDs here to enable `;`-style single line comment blocks for that language. This allows unsupported languages to have comment completion." + }, + "auto-comment-blocks.multiLineStyleBlocks": { + "type": "array", + "default": [ + "blade", + "html" + ], + "markdownDescription": "Add language IDs here to enable multi line comment blocks support for that language. This allows unsupported languages to have comment completion. The default is `['blade', 'html']`" + }, + "auto-comment-blocks.overrideDefaultLanguageMultiLineComments": { + "type": "object", + "default": {}, + "markdownDescription": "A key : value pairing of language IDs and the beginning portion of a multi line comment style, to override the default comment style for the vscode `command editor.action.blockComment` (native Keybinding `shift + alt + a`). eg. `{'php': '/*!'}`" + }, + "auto-comment-blocks.bladeOverrideComments": { + "scope": "resource", + "type": "boolean", + "default": false, + "markdownDescription": "When enabled, Blade style block comments will be used in Blade contexts. Ie. `{{-- --}}` comments will be used instead of the HTML `` comments. Keybinding to enable/disable, default `ctrl + shift + m`. If `blade` language ID is set in the disabledLanguages, then the HTML `` comments will be used." + } + } + }, + "keybindings": [ { - "id": "csharp", - "configuration": "./language-configuration/language-configuration.cpp.json" + "command": "auto-comment-blocks.singleLineBlock", + "key": "shift+enter", + "when": "editorTextFocus" }, - { - "id": "css", - "configuration": "./language-configuration/language-configuration.css.json" - }, - { - "id": "scss", - "configuration": "./language-configuration/language-configuration.scss.json" - }, - { - "id": "groovy", - "configuration": "./language-configuration/language-configuration.groovy.json" - }, - { - "id": "php", - "configuration": "./language-configuration/language-configuration.php.json" - }, - { - "id": "objective-c", - "configuration": "./language-configuration/language-configuration.objective-c.json" - }, - { - "id": "objective-cpp", - "configuration": "./language-configuration/language-configuration.objective-c.json" - }, - { - "id": "less", - "configuration": "./language-configuration/language-configuration.less.json" - }, - { - "id": "swift", - "configuration": "./language-configuration/language-configuration.swift.json" - }, - { - "id": "rust", - "configuration": "./language-configuration/language-configuration.rust.json" - }, - { - "id": "go", - "configuration": "./language-configuration/language-configuration.go.json" - }, - { - "id": "blade", - "configuration": "./language-configuration/language-configuration.blade.json" - } - ], - "keybindings": [ - { - "command": "auto-comment-blocks.singleLineBlock", - "key": "shift+enter", - "when": "editorTextFocus" - } - ] - }, - "scripts": { - "vscode:prepublish": "tsc -p ./", - "compile": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "node ./node_modules/vscode/bin/test" - }, - "devDependencies": { - "typescript": "^2.0.3", - "vscode": "^1.0.0", - "mocha": "^2.3.3", - "@types/node": "^6.0.40", - "@types/mocha": "^2.2.32" - } + { + "command": "auto-comment-blocks.changeBladeMultiLineBlock", + "key": "ctrl+shift+m", + "when": "editorTextFocus" + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "test": "node ./out/test/extension.test.js" + }, + "devDependencies": { + "@types/mocha": "^10.0.9", + "@types/node": "^22.9.0", + "@types/vscode": "^1.95.0", + "mocha": "^10.8.2", + "typescript": "^5.6.3" + }, + "dependencies": { + "jsonc-parser": "^3.3.1" + } } From 6df1b4753fff769baab54ca7720cbb4c457f4a41 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Tue, 3 Dec 2024 17:09:34 +0000 Subject: [PATCH 02/27] chore: Update various build and testing configs --- .prettierrc.json | 8 +++++++ .vscode/launch.json | 52 +++++++++++++++++++++++---------------------- .vscode/tasks.json | 41 ++++++++--------------------------- tsconfig.json | 26 ++++++++++------------- 4 files changed, 55 insertions(+), 72 deletions(-) create mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..5a3cb37 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "useTabs": true, + "tabWidth": 4, + "semi": true, + "printWidth": 150, + "bracketSameLine": true, + "bracketSpacing": false +} diff --git a/.vscode/launch.json b/.vscode/launch.json index cd6b87b..89a3f30 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,28 +1,30 @@ // A launch configuration that compiles the extension and then opens it inside a new window { - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], - "preLaunchTask": "npm" - }, - { - "name": "Launch Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ], - "preLaunchTask": "npm" - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/out/**/*.js"], + "preLaunchTask": "npm: watch" + }, + { + "name": "Run Extension Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test" + ], + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/out/**/*.js"], + "preLaunchTask": "npm: watch" + } + ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index cc50ec7..3d2b99e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,42 +1,19 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - // A task runner that calls a custom npm script that compiles the extension. { - "version": "2.0.0", - - // we want to run npm - "command": "npm", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // The tsc compiler is started in watching mode - "isBackground": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch", + "version": "2.0.0", "tasks": [ { - "label": "npm", - "type": "shell", - "args": [ - "run", - "compile", - "--loglevel", - "silent" - ], - "isBackground": true, + "type": "npm", + "script": "watch", "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, "group": { - "_id": "build", + "kind": "build", "isDefault": false } } ] -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 11282c9..345fb18 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,12 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6" - ], - "sourceMap": true, - "rootDir": "." - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] -} \ No newline at end of file + "compilerOptions": { + "module": "commonjs", + "target": "es2022", + "outDir": "out", + "lib": ["es2022"], + "sourceMap": true, + "rootDir": ".", + "typeRoots": ["./node_modules/@types"] + }, + "exclude": ["node_modules", ".vscode-test"] +} From bec4d907918dfe54e403e88249c29a4eb91a6710 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Tue, 3 Dec 2024 22:05:39 +0000 Subject: [PATCH 03/27] feat: Add on change events to determine when a certain user setting has been changed, and show an information message to the user. Also re-configures the comment blocks when the active editor language has been changed. --- src/extension.ts | 83 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 3b4bca8..c7e3877 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,17 +1,82 @@ -'use strict'; +"use strict"; -import { languages, commands, workspace, ExtensionContext, IndentAction, LanguageConfiguration, OnEnterRule, Disposable } from 'vscode'; -import { Configuration } from './configuration'; +import * as vscode from "vscode"; + +import {Configuration} from "./configuration"; -let fs = require('fs'); let configuration = new Configuration(); -export function activate(context: ExtensionContext) { - +export function activate(context: vscode.ExtensionContext) { configuration.configureCommentBlocks(context); configuration.registerCommands(); -} -export function deactivate() { - + const extensionNames = configuration.getExtensionNames(); + + const extensionName = extensionNames.name; + const extensionDisplayName = extensionNames.displayName; + + let disabledLangConfig: string[] = configuration.getConfiguration().get("disabledLanguages"); + + if (disabledLangConfig.length > 0) { + vscode.window.showInformationMessage(`${disabledLangConfig.join(", ")} languages are disabled for ${extensionDisplayName}.`); + } + + /** + * When the configuration/user settings are changed, set the extension + * to reflect the settings and output a message to the user. + */ + vscode.workspace.onDidChangeConfiguration((event: any) => { + /** + * Blade Override Comments + */ + // If the affected setting is bladeOverrideComments... + if (event.affectsConfiguration(`${extensionName}.bladeOverrideComments`)) { + // Get the setting. + let bladeOverrideComments: boolean = configuration.getConfiguration().get("bladeOverrideComments"); + + configuration.setBladeComments(bladeOverrideComments); + + if (!configuration.isLangIdDisabled("blade")) { + vscode.window.showInformationMessage(`${bladeOverrideComments === false ? "Disabled" : "Enabled"} Blade Override Comments setting.`); + } + } + + /** + * Disabled Languages + */ + if (event.affectsConfiguration(`${extensionName}.disabledLanguages`)) { + vscode.window + .showInformationMessage( + `The ${extensionName}.disabledLanguages setting has been changed. Please reload the Extension Host to take effect.`, + "Reload" + ) + .then((selection) => { + if (selection === "Reload") { + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + } + }); + } + + /** + * Override Default Language Block Comments + */ + if (event.affectsConfiguration(`${extensionName}.overrideDefaultLanguageMultiLineComments`)) { + vscode.window + .showInformationMessage( + `The ${extensionName}.overrideDefaultLanguageMultiLineComments setting has been changed. Please reload the Extension Host to take effect.`, + "Reload" + ) + .then((selection) => { + if (selection === "Reload") { + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + } + }); + } + }); + + // Called when active editor language is changed, so re-configure the comment blocks. + vscode.workspace.onDidOpenTextDocument(() => { + configuration.configureCommentBlocks(context); + }); } +export function deactivate() {} From b33e66dbdfe686d83c4ab6798ea0e68a66cf6b9a Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Wed, 4 Dec 2024 15:32:43 +0000 Subject: [PATCH 04/27] feat: Add the some config files: - The default multi-line language config that define the block comment and auto closing pairs, ready to merge with the internal language configs. - An array of languages to skip while finding the internal language configs, because these languages don't have any useful configs that we need. --- config/default-multi-line-config.json | 9 +++++++++ config/skip-languages.jsonc | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 config/default-multi-line-config.json create mode 100644 config/skip-languages.jsonc diff --git a/config/default-multi-line-config.json b/config/default-multi-line-config.json new file mode 100644 index 0000000..2712f88 --- /dev/null +++ b/config/default-multi-line-config.json @@ -0,0 +1,9 @@ +{ + "comments": { + "blockComment": ["/*", "*/"] + }, + "autoClosingPairs": [ + {"open": "/**", "close": " */", "notIn": ["string"]}, + {"open": "/*!", "close": " */", "notIn": ["string"]} + ] +} diff --git a/config/skip-languages.jsonc b/config/skip-languages.jsonc new file mode 100644 index 0000000..0f00aa7 --- /dev/null +++ b/config/skip-languages.jsonc @@ -0,0 +1,17 @@ +// Languages to skip, like plaintext, etc. because they don't have any configuration +// properties that we are interested in. +// The idea taken from the _getLanguagesToSkip() function from this StackOverflow answer +// https://stackoverflow.com/a/72988011/2358222 +{ + "languages": [ + "log", + "Log", + "search-result", + "plaintext", + "scminput", + "properties", + "csv", + "tsv", + "excel" + ] +} From 8c797af5541383aa438b0c8c70840e5a0c1dd257 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Wed, 4 Dec 2024 15:33:33 +0000 Subject: [PATCH 05/27] Feat: Change some onEnter rules regexes, move some rules so they are grouped together properly, and add a rule for the normal `/* */` comment. --- src/rules.ts | 90 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/src/rules.ts b/src/rules.ts index 2b87ffa..4093474 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -1,86 +1,112 @@ -'use strict'; +"use strict"; -import { IndentAction, OnEnterRule } from 'vscode'; +import { IndentAction, OnEnterRule } from "vscode"; export class Rules { - static readonly multilineEnterRules: OnEnterRule[] = [ + { + // e.g. /* | */ + beforeText: /^\s*\/\*(?!\/)([^\*!]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { indentAction: IndentAction.IndentOutdent, appendText: " * " }, + }, { // e.g. /** | */ - beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + beforeText: /^\s*\/\*\*(?!\/)([^\*!]|\*(?!\/))*$/, afterText: /^\s*\*\/$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: ' * ' } + action: { indentAction: IndentAction.IndentOutdent, appendText: " * " }, }, { // e.g. /** ...| beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: ' * ' } + action: { indentAction: IndentAction.None, appendText: " * " }, + }, + { + // e.g. * ...| + beforeText: /^(\t|(\ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { indentAction: IndentAction.None, appendText: "* " }, + }, + { + // e.g. */| + beforeText: /^(\t|(\ ))*\ \*\/\s*$/, + action: { indentAction: IndentAction.None, removeText: 1 }, + }, + { + // e.g. *-----*/| + beforeText: /^(\t|(\ ))*\ \*[^/]*\*\/\s*$/, + action: { indentAction: IndentAction.None, removeText: 1 }, }, { // e.g. /*! | */ beforeText: /^\s*\/\*\!(?!\/)([^\*]|\*(?!\/))*$/, afterText: /^\s*\*\/$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: ' *! ' } + action: { indentAction: IndentAction.IndentOutdent, appendText: " *! " }, }, { // e.g. /*! ...| beforeText: /^\s*\/\*\!(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: ' *! ' } + action: { indentAction: IndentAction.None, appendText: " *! " }, }, { // matches " *!" on a new line // e.g. *! ...| beforeText: /^(\t|(\ ))*\ \*!(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction: IndentAction.None, appendText: '*! ' } + action: { indentAction: IndentAction.None, appendText: "*! " }, }, { - // e.g. * ...| - beforeText: /^(\t|(\ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction: IndentAction.None, appendText: '* ' } + // e.g. /* ...| + beforeText: /^\s*\/\*(?!\/)([^\*]|\*(?!\/))*$/, + action: { indentAction: IndentAction.None, appendText: " * " }, }, { - // e.g. */| - beforeText: /^(\t|(\ ))*\ \*\/\s*$/, - action: { indentAction: IndentAction.None, removeText: 1 } + // e.g. {{-- | --}} + beforeText: /^\s*\{\{\-\-(?!\/)([^\-\-\}\}]|\*(?!\}))*$/, + afterText: /^\s*\-\-\}\}$/, + action: { indentAction: IndentAction.IndentOutdent, appendText: " - " }, }, { - // e.g. *-----*/| - beforeText: /^(\t|(\ ))*\ \*[^/]*\*\/\s*$/, - action: { indentAction: IndentAction.None, removeText: 1 } - } - ] + // e.g. {{-- ...| + beforeText: /^\s*\{\{\-\-(?!\/)([^\-\-\}\}]|\*(?!\/))*$/, + action: { indentAction: IndentAction.None, appendText: " - " }, + }, + { + // e.g. - ...| + beforeText: /^(\t|(\ ))*\ \-(\ ([^\-]|\-(?!\-))*)?$/, + action: { indentAction: IndentAction.None, appendText: "- " }, + }, + ]; static readonly slashEnterRules: OnEnterRule[] = [ { // e.g. // ...| beforeText: /^\s*\/\/(?!\/)/, - action: { indentAction: IndentAction.None, appendText: '// ' } + action: { indentAction: IndentAction.None, appendText: "// " }, }, { // e.g. /// ...| beforeText: /^\s*\/\/\//, - action: { indentAction: IndentAction.None, appendText: '/// ' } + action: { indentAction: IndentAction.None, appendText: "/// " }, }, { // e.g. //! ...| beforeText: /^\s*\/\/!/, - action: { indentAction: IndentAction.None, appendText: '//! ' } - } - ] + action: { indentAction: IndentAction.None, appendText: "//! " }, + }, + ]; static readonly hashEnterRules: OnEnterRule[] = [ { // e.g. # ...| beforeText: /^\s*#/, - action: { indentAction: IndentAction.None, appendText: '# ' } - } - ] + action: { indentAction: IndentAction.None, appendText: "# " }, + }, + ]; static readonly semicolonEnterRules: OnEnterRule[] = [ { // e.g. ; ...| beforeText: /^\s*;/, - action: { indentAction: IndentAction.None, appendText: '; ' } - } - ] -} \ No newline at end of file + action: { indentAction: IndentAction.None, appendText: "; " }, + }, + ]; +} From 51d5b0daa9ae527adab18e90724013592efad57d Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 03:40:55 +0000 Subject: [PATCH 06/27] feat: Add descriptive comments and add support for double semicolon comment `;;`. The descriptive comments are to prevent confusion over what the regexes are matching. --- src/rules.ts | 93 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/src/rules.ts b/src/rules.ts index 4093474..e4d774a 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -1,112 +1,137 @@ "use strict"; -import { IndentAction, OnEnterRule } from "vscode"; +import {IndentAction, OnEnterRule} from "vscode"; export class Rules { static readonly multilineEnterRules: OnEnterRule[] = [ { // e.g. /* | */ + // (matches /* */ with any amount of spaces before it and any character in it.) beforeText: /^\s*\/\*(?!\/)([^\*!]|\*(?!\/))*$/, afterText: /^\s*\*\/$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: " * " }, + action: {indentAction: IndentAction.IndentOutdent, appendText: " * "}, }, { // e.g. /** | */ + // (matches /** */ with any amount of spaces before it and any character in it.) beforeText: /^\s*\/\*\*(?!\/)([^\*!]|\*(?!\/))*$/, afterText: /^\s*\*\/$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: " * " }, + action: {indentAction: IndentAction.IndentOutdent, appendText: " * "}, }, { - // e.g. /** ...| + // e.g. /** | + // (matches /** with any amount of spaces before or after it.) beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: " * " }, + action: {indentAction: IndentAction.None, appendText: " * "}, }, { - // e.g. * ...| + // e.g. * | + // (matches a * with any amount of space before and any character after it.) beforeText: /^(\t|(\ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction: IndentAction.None, appendText: "* " }, + action: {indentAction: IndentAction.None, appendText: "* "}, }, { // e.g. */| + // (matches */ with any amount of space before it.) beforeText: /^(\t|(\ ))*\ \*\/\s*$/, - action: { indentAction: IndentAction.None, removeText: 1 }, + action: {indentAction: IndentAction.None, removeText: 1}, }, { - // e.g. *-----*/| + // e.g. * */| + // (matches * */ and any amount of spaces at the start and any + // amount of spaces between before the */) beforeText: /^(\t|(\ ))*\ \*[^/]*\*\/\s*$/, - action: { indentAction: IndentAction.None, removeText: 1 }, + action: {indentAction: IndentAction.None, removeText: 1}, }, { // e.g. /*! | */ + // (matches /*! */ with any amount of spaces before it and any character in it.) beforeText: /^\s*\/\*\!(?!\/)([^\*]|\*(?!\/))*$/, afterText: /^\s*\*\/$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: " *! " }, + action: {indentAction: IndentAction.IndentOutdent, appendText: " *! "}, }, { - // e.g. /*! ...| + // e.g. /*! | + // (matches /*! with any amount of spaces before it.) beforeText: /^\s*\/\*\!(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: " *! " }, + action: {indentAction: IndentAction.None, appendText: " *! "}, }, { - // matches " *!" on a new line - // e.g. *! ...| + // e.g. *! | + // (matches *! on a new line with any amount of spaces before it.) beforeText: /^(\t|(\ ))*\ \*!(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction: IndentAction.None, appendText: "*! " }, + action: {indentAction: IndentAction.None, appendText: "*! "}, }, { - // e.g. /* ...| + // e.g. /* | + // (matches /* with any amount of spaces before it and any characters after it.) beforeText: /^\s*\/\*(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: " * " }, + action: {indentAction: IndentAction.None, appendText: " * "}, }, { // e.g. {{-- | --}} + // (matches {{-- --}} with any amount of spaces before it and any + // characters inbetween.) beforeText: /^\s*\{\{\-\-(?!\/)([^\-\-\}\}]|\*(?!\}))*$/, afterText: /^\s*\-\-\}\}$/, - action: { indentAction: IndentAction.IndentOutdent, appendText: " - " }, + action: {indentAction: IndentAction.IndentOutdent, appendText: " - "}, }, { - // e.g. {{-- ...| + // e.g. {{-- | + // (matches {{-- with any amount of spaces before it and any characters after it.) beforeText: /^\s*\{\{\-\-(?!\/)([^\-\-\}\}]|\*(?!\/))*$/, - action: { indentAction: IndentAction.None, appendText: " - " }, + action: {indentAction: IndentAction.None, appendText: " - "}, }, { - // e.g. - ...| + // e.g. - | + // (matches a - with any amount of space before and any character after it.) beforeText: /^(\t|(\ ))*\ \-(\ ([^\-]|\-(?!\-))*)?$/, - action: { indentAction: IndentAction.None, appendText: "- " }, + action: {indentAction: IndentAction.None, appendText: "- "}, }, ]; static readonly slashEnterRules: OnEnterRule[] = [ { - // e.g. // ...| + // e.g. // | + // (matched // with any amount of spaces before it.) beforeText: /^\s*\/\/(?!\/)/, - action: { indentAction: IndentAction.None, appendText: "// " }, + action: {indentAction: IndentAction.None, appendText: "// "}, }, { - // e.g. /// ...| + // e.g. /// | + // (matches /// with any amount of spaces before it.) beforeText: /^\s*\/\/\//, - action: { indentAction: IndentAction.None, appendText: "/// " }, + action: {indentAction: IndentAction.None, appendText: "/// "}, }, { - // e.g. //! ...| + // e.g. //! | + // (matches //! with any amount of spaces before it.) beforeText: /^\s*\/\/!/, - action: { indentAction: IndentAction.None, appendText: "//! " }, + action: {indentAction: IndentAction.None, appendText: "//! "}, }, ]; static readonly hashEnterRules: OnEnterRule[] = [ { - // e.g. # ...| + // e.g. # | + // (matches # with any amount of spaces before it.) beforeText: /^\s*#/, - action: { indentAction: IndentAction.None, appendText: "# " }, + action: {indentAction: IndentAction.None, appendText: "# "}, }, ]; static readonly semicolonEnterRules: OnEnterRule[] = [ { - // e.g. ; ...| - beforeText: /^\s*;/, - action: { indentAction: IndentAction.None, appendText: "; " }, + // e.g. ; | + // (matches ; with any amount of spaces before it.) + beforeText: /^\s*;(?!;)/, + action: {indentAction: IndentAction.None, appendText: "; "}, + }, + { + // e.g. ;; | + // (matches ;; with any amount of spaces before it.) + beforeText: /^\s*;;/, + action: {indentAction: IndentAction.None, appendText: ";; "}, }, ]; } From e0df49aaaacd1cd7707332fb240da4c39a2fe28a Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 15:12:22 +0000 Subject: [PATCH 07/27] style: auto formatting. --- src/configuration.ts | 99 ++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 3e44563..f0e454d 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,16 +1,14 @@ -'use strict'; +"use strict"; -import { Disposable, ExtensionContext, LanguageConfiguration, TextEditor, TextEditorEdit, commands, languages, workspace } from 'vscode'; +import {Disposable, ExtensionContext, LanguageConfiguration, TextEditor, TextEditorEdit, commands, languages, workspace} from "vscode"; -import { Rules } from './rules'; -import { config as singleLineConfig } from './single-line-configuration'; -import { config as multiLineConfig } from './multi-line-configuration'; +import {Rules} from "./rules"; +import {config as singleLineConfig} from "./single-line-configuration"; +import {config as multiLineConfig} from "./multi-line-configuration"; export class Configuration { - private readonly extensionName: string = "auto-comment-blocks"; - private readonly singleLineBlockCommand: string = - "auto-comment-blocks.singleLineBlock"; + private readonly singleLineBlockCommand: string = "auto-comment-blocks.singleLineBlock"; private readonly singleLineBlockOnEnter: string = "singleLineBlockOnEnter"; private readonly slashStyleBlocks: string = "slashStyleBlocks"; @@ -18,17 +16,14 @@ export class Configuration { private readonly semicolonStyleBlocks: string = "semicolonStyleBlocks"; private readonly disabledLanguages: string = "disabledLanguages"; - private disabledLanguageList: string[] = - this.getConfiguration().get(this.disabledLanguages); + private disabledLanguageList: string[] = this.getConfiguration().get(this.disabledLanguages); private singleLineBlocksMap: Map = new Map(); private getConfiguration() { - return workspace.getConfiguration(this.extensionName); } private isLangIdDisabled(langId: string) { - return this.disabledLanguageList.indexOf(langId) !== -1; } @@ -36,31 +31,23 @@ export class Configuration { return multiLineConfig["languages"]; } - private setLanguageConfiguration(langId: string, - multiLine?: boolean, - singleLineStyle?: string): Disposable { - + private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): Disposable { var langConfig: LanguageConfiguration = { - onEnterRules: [] + onEnterRules: [], }; if (multiLine) { - langConfig.onEnterRules = - langConfig.onEnterRules.concat(Rules.multilineEnterRules); + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.multilineEnterRules); } - let isOnEnter = this.getConfiguration().get( - this.singleLineBlockOnEnter); + let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); if (isOnEnter && singleLineStyle) { - if (singleLineStyle === '//') { - langConfig.onEnterRules = - langConfig.onEnterRules.concat(Rules.slashEnterRules); - } else if (singleLineStyle === '#') { - langConfig.onEnterRules = - langConfig.onEnterRules.concat(Rules.hashEnterRules); - } else if (singleLineStyle === ';') { - langConfig.onEnterRules = - langConfig.onEnterRules.concat(Rules.semicolonEnterRules); + if (singleLineStyle === "//") { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.slashEnterRules); + } else if (singleLineStyle === "#") { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.hashEnterRules); + } else if (singleLineStyle === ";") { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.semicolonEnterRules); } } @@ -78,33 +65,29 @@ export class Configuration { } // get user-customized langIds for this key and add to the map - let customSlashLangs = - this.getConfiguration().get(this.slashStyleBlocks); + let customSlashLangs = this.getConfiguration().get(this.slashStyleBlocks); for (let langId of customSlashLangs) { if (langId && langId.length > 0) { - this.singleLineBlocksMap.set(langId, '//'); + this.singleLineBlocksMap.set(langId, "//"); } } - let customHashLangs = - this.getConfiguration().get(this.hashStyleBlocks); + let customHashLangs = this.getConfiguration().get(this.hashStyleBlocks); for (let langId of customHashLangs) { if (langId && langId.length > 0) { - this.singleLineBlocksMap.set(langId, '#'); + this.singleLineBlocksMap.set(langId, "#"); } } - let customSemicolonLangs = - this.getConfiguration().get(this.semicolonStyleBlocks); + let customSemicolonLangs = this.getConfiguration().get(this.semicolonStyleBlocks); for (let langId of customSemicolonLangs) { if (langId && langId.length > 0) { - this.singleLineBlocksMap.set(langId, ';'); + this.singleLineBlocksMap.set(langId, ";"); } } } configureCommentBlocks(context: ExtensionContext) { - this.getSingleLineLanguages(); // set language configurations @@ -116,9 +99,7 @@ export class Configuration { } for (let langId of multiLineLangs) { - if (!this.singleLineBlocksMap.has(langId) && - !this.isLangIdDisabled(langId)) { - + if (!this.singleLineBlocksMap.has(langId) && !this.isLangIdDisabled(langId)) { let disposable = this.setLanguageConfiguration(langId, true); context.subscriptions.push(disposable); } @@ -126,28 +107,24 @@ export class Configuration { } private handleSingleLineBlock(textEditor: TextEditor, edit: TextEditorEdit) { - let langId = textEditor.document.languageId; var style = this.singleLineBlocksMap.get(langId); if (style && textEditor.selection.isEmpty) { let line = textEditor.document.lineAt(textEditor.selection.active); let isCommentLine = true; var indentRegex: RegExp; - if (style === '//' && line.text.search(/^\s*\/\/\s*/) !== -1) { + if (style === "//" && line.text.search(/^\s*\/\/\s*/) !== -1) { indentRegex = /\//; if (line.text.search(/^\s*\/\/\/\s*/) !== -1) { - style = '///'; + style = "///"; } if (line.text.search(/^\s*\/\/!\s*/) !== -1) { - style = '//!'; + style = "//!"; } - - } else if (style === '#' && line.text.search(/^\s*#\s*/) !== -1) { + } else if (style === "#" && line.text.search(/^\s*#\s*/) !== -1) { indentRegex = /#/; - - } else if (style === ';' && line.text.search(/^\s*;\s*/) !== -1) { + } else if (style === ";" && line.text.search(/^\s*;\s*/) !== -1) { indentRegex = /;/; - } else { isCommentLine = false; } @@ -156,12 +133,10 @@ export class Configuration { return; } - var indentedNewLine = '\n' + - line.text.substring(0, line.text.search(indentRegex)); - let isOnEnter = this.getConfiguration().get( - this.singleLineBlockOnEnter); + var indentedNewLine = "\n" + line.text.substring(0, line.text.search(indentRegex)); + let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); if (!isOnEnter) { - indentedNewLine += style + ' '; + indentedNewLine += style + " "; } edit.insert(textEditor.selection.active, indentedNewLine); @@ -169,10 +144,8 @@ export class Configuration { } registerCommands() { - - commands.registerTextEditorCommand(this.singleLineBlockCommand, - (textEditor, edit, args) => { - this.handleSingleLineBlock(textEditor, edit); - }) + commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { + this.handleSingleLineBlock(textEditor, edit); + }); } -} \ No newline at end of file +} From 0dbb0613efd230123f7afc9fbbbf332a294e4d25 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 15:16:36 +0000 Subject: [PATCH 08/27] feat: add support for double semicolon comment `;;` on enter when the command is shift+enter. --- src/configuration.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index f0e454d..b7b4704 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,6 +1,7 @@ "use strict"; import {Disposable, ExtensionContext, LanguageConfiguration, TextEditor, TextEditorEdit, commands, languages, workspace} from "vscode"; +import * as vscode from "vscode"; import {Rules} from "./rules"; import {config as singleLineConfig} from "./single-line-configuration"; @@ -106,7 +107,7 @@ export class Configuration { } } - private handleSingleLineBlock(textEditor: TextEditor, edit: TextEditorEdit) { + private handleSingleLineBlock(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) { let langId = textEditor.document.languageId; var style = this.singleLineBlocksMap.get(langId); if (style && textEditor.selection.isEmpty) { @@ -125,6 +126,11 @@ export class Configuration { indentRegex = /#/; } else if (style === ";" && line.text.search(/^\s*;\s*/) !== -1) { indentRegex = /;/; + + // If text is ;;, then change the style from single ; to double ;;. + if (line.text.search(/^\s*;;\s*/) !== -1) { + style = ";;"; + } } else { isCommentLine = false; } From 25d6da2c33dcc283d20314516fa4d9970e4fbafe Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 15:58:32 +0000 Subject: [PATCH 09/27] feat: add the functionality for the new bladeOverrideComments setting and command, plus others. - bladeOverrideComments command functionality to enable/disable the usage of Blade's `{{-- --}}` comments instead of HTML `` comments in blade files. - Add various typings. - Refactor some code: - Use `array.includes()` instead of `array.indexOf()`. - Add a new method `getExtensionNames()` to obtain the extension name, id, and display name from the package.json instead of the explicitly coded `extensionName` property. Removed all references to the old property. - Add a cleaner, DRYer way to the disposables. Collect all disposables in an array and then push the array elements into the extension context subscriptions at the very end. --- src/configuration.ts | 127 ++++++++++++++++++++++++++++++++++++++++--- src/extension.ts | 13 ++++- 2 files changed, 130 insertions(+), 10 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index b7b4704..11db01c 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -2,14 +2,15 @@ import {Disposable, ExtensionContext, LanguageConfiguration, TextEditor, TextEditorEdit, commands, languages, workspace} from "vscode"; import * as vscode from "vscode"; +import * as fs from "node:fs"; import {Rules} from "./rules"; import {config as singleLineConfig} from "./single-line-configuration"; import {config as multiLineConfig} from "./multi-line-configuration"; export class Configuration { - private readonly extensionName: string = "auto-comment-blocks"; private readonly singleLineBlockCommand: string = "auto-comment-blocks.singleLineBlock"; + private readonly changeBladeMultiLineBlockCommand: string = "auto-comment-blocks.changeBladeMultiLineBlock"; private readonly singleLineBlockOnEnter: string = "singleLineBlockOnEnter"; private readonly slashStyleBlocks: string = "slashStyleBlocks"; @@ -20,12 +21,33 @@ export class Configuration { private disabledLanguageList: string[] = this.getConfiguration().get(this.disabledLanguages); private singleLineBlocksMap: Map = new Map(); - private getConfiguration() { - return workspace.getConfiguration(this.extensionName); + /** + * Get the names and ids of this extension from package.json. + * + * @returns {object} An object containing the extension id, name, and display name. + */ + public getExtensionNames() { + const packageJSON = JSON.parse(fs.readFileSync(__dirname + "./../../package.json").toString()); + + const displayName: string = packageJSON.displayName; + const fullname: string = packageJSON.name; + const id: string = `${packageJSON.publisher}.${fullname}`; + + let nameParts = fullname.split("-"); + nameParts[0] = "auto"; + const name = nameParts.join("-"); + + return {id: id, name: name, displayName: displayName}; + } + /** + * Get extension configuration. + */ + public getConfiguration(): vscode.WorkspaceConfiguration { + return vscode.workspace.getConfiguration(this.getExtensionNames().name, null); } - private isLangIdDisabled(langId: string) { - return this.disabledLanguageList.indexOf(langId) !== -1; + public isLangIdDisabled(langId: string): boolean { + return this.disabledLanguageList.includes(langId); } private getMultiLineLanguages(): Array { @@ -149,9 +171,100 @@ export class Configuration { } } - registerCommands() { - commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { + /** + * The keyboard binding handler to change between the multi-line block comments for + * blade `{{-- --}}` and normal `` + * @param textEditor The editor + */ + private handleChangeBladeMultiLineBlock(textEditor: vscode.TextEditor) { + let langId = textEditor.document.languageId; + const extensionNames = this.getExtensionNames(); + + // Only carry out function if languageId is blade. + if (langId === "blade" && !this.isLangIdDisabled(langId)) { + let config = this.getConfiguration(); + // Read current value + let isOverridden = config.get("bladeOverrideComments"); + + if (isOverridden === false) { + // Update to true, globally + // [command, new value, global] + config.update("bladeOverrideComments", true, true); + } else { + // Update to false, globally + // [command, new value, global] + config.update("bladeOverrideComments", false, true); + } + // Read new value + let bladeOverrideComments = config.get("bladeOverrideComments"); + + // Set the comments for blade language. + this.setBladeComments(bladeOverrideComments); + } + // If langId is blade AND Blade is set as disabled in the settings, + // then output a message to the user. + else if (langId == "blade" && this.isLangIdDisabled(langId)) { + vscode.window.showInformationMessage( + `Blade is set as disabled in the "${extensionNames.name}.disabledLanguages" setting. The "${extensionNames.name}.bladeOverrideComments" setting will have no affect.`, + "OK" + ); + + // Set the comments for blade language. + this.setBladeComments(false); + } + } + + /** + * Register some VSCode commands. + */ + public registerCommands() { + const singleLineBlockCommand = vscode.commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { this.handleSingleLineBlock(textEditor, edit); }); + const changeBladeMultiLineBlockCommand = vscode.commands.registerTextEditorCommand( + this.changeBladeMultiLineBlockCommand, + (textEditor, edit, args) => { + this.handleChangeBladeMultiLineBlock(textEditor); + } + ); + return [singleLineBlockCommand, changeBladeMultiLineBlockCommand]; + } + + /** + * Sets the block comments for the blade language determined by the user setting. + * + * @param bladeOverrideComments A boolean indicating whether or not the user setting "Blade Override Comments" is enabled. + * + * @param [onStart=false] A boolean indicating whether or not the method was called + * on starting the extension. + * If `true`, it returns the comments, if `false` (default), it sets the comments to + * the language directly. + * + */ + public setBladeComments(bladeOverrideComments: boolean, onStart: boolean = false): any { + // Is enabled AND blade langId is NOT set as disabled... + if (bladeOverrideComments === true && !this.isLangIdDisabled("blade")) { + if (onStart) { + return ["{{--", "--}}"]; + } else { + vscode.languages.setLanguageConfiguration("blade", { + comments: { + blockComment: ["{{--", "--}}"], + }, + }); + } + } + // Is disabled OR blade langId is set as disabled... + else if (!bladeOverrideComments || this.isLangIdDisabled("blade")) { + if (onStart) { + return [""]; + } else { + vscode.languages.setLanguageConfiguration("blade", { + comments: { + blockComment: [""], + }, + }); + } + } } } diff --git a/src/extension.ts b/src/extension.ts index c7e3877..2caee1e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,9 +6,13 @@ import {Configuration} from "./configuration"; let configuration = new Configuration(); +const disposables: vscode.Disposable[] = []; + export function activate(context: vscode.ExtensionContext) { - configuration.configureCommentBlocks(context); - configuration.registerCommands(); + const configureCommentBlocksDisposable = configuration.configureCommentBlocks(context); + const registerCommandsDisposable = configuration.registerCommands(); + + disposables.push(...configureCommentBlocksDisposable, ...registerCommandsDisposable); const extensionNames = configuration.getExtensionNames(); @@ -76,7 +80,10 @@ export function activate(context: vscode.ExtensionContext) { // Called when active editor language is changed, so re-configure the comment blocks. vscode.workspace.onDidOpenTextDocument(() => { - configuration.configureCommentBlocks(context); + const configureCommentBlocksDisposable = configuration.configureCommentBlocks(context); + disposables.push(...configureCommentBlocksDisposable); }); + + context.subscriptions.push(...disposables); } export function deactivate() {} From 86566af46b4a815fd2fa3e1e4a5f301b1e98184f Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 16:33:27 +0000 Subject: [PATCH 10/27] refactor: Move code blocks to try and keep things organised in a structured way. --- src/configuration.ts | 201 ++++++++++++++++++++++++------------------- 1 file changed, 112 insertions(+), 89 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 11db01c..1240023 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -9,6 +9,9 @@ import {config as singleLineConfig} from "./single-line-configuration"; import {config as multiLineConfig} from "./multi-line-configuration"; export class Configuration { + /************** + * Properties * + **************/ private readonly singleLineBlockCommand: string = "auto-comment-blocks.singleLineBlock"; private readonly changeBladeMultiLineBlockCommand: string = "auto-comment-blocks.changeBladeMultiLineBlock"; @@ -19,8 +22,100 @@ export class Configuration { private readonly disabledLanguages: string = "disabledLanguages"; private disabledLanguageList: string[] = this.getConfiguration().get(this.disabledLanguages); + + /** + * A key:value Map object of supported language IDs and their single line style comments. + * + * @property {string} key Language ID. + * @property {string} value Style of line comment. + */ private singleLineBlocksMap: Map = new Map(); + /*********** + * Methods * + ***********/ + + configureCommentBlocks(context: ExtensionContext) { + const disposables: vscode.Disposable[] = []; + + // Set language configurations + this.getSingleLineLanguages(); + let multiLineLangs = this.getMultiLineLanguages(); + + // Setup the single line languages. + for (let [langId, style] of this.singleLineBlocksMap) { + // Set a bool if the single line language also supports multi line comments + // (ie. the single line language is also present in the multi line map); + let multiLine = multiLineLangs.includes(langId); + disposables.push(this.setLanguageConfiguration(langId, multiLine, style)); + } + + // Setup the multi line languages. + for (let langId of multiLineLangs) { + // If singleLineLangs doesn't have the langId, AND + // the langId isn't set as disabled... + if (!this.singleLineBlocksMap.has(langId) && !this.isLangIdDisabled(langId)) { + disposables.push(this.setLanguageConfiguration(langId, true)); + } + } + + return disposables; + } + + /** + * Register some VSCode commands. + */ + public registerCommands() { + const singleLineBlockCommand = vscode.commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { + this.handleSingleLineBlock(textEditor, edit); + }); + const changeBladeMultiLineBlockCommand = vscode.commands.registerTextEditorCommand( + this.changeBladeMultiLineBlockCommand, + (textEditor, edit, args) => { + this.handleChangeBladeMultiLineBlock(textEditor); + } + ); + return [singleLineBlockCommand, changeBladeMultiLineBlockCommand]; + } + + /** + * Sets the block comments for the blade language determined by the user setting. + * + * @param bladeOverrideComments A boolean indicating whether or not the user setting "Blade Override Comments" is enabled. + * + * @param [onStart=false] A boolean indicating whether or not the method was called + * on starting the extension. + * If `true`, it returns the comments, if `false` (default), it sets the comments to + * the language directly. + * + */ + public setBladeComments(bladeOverrideComments: boolean, onStart: boolean = false): any { + // Is enabled AND blade langId is NOT set as disabled... + if (bladeOverrideComments === true && !this.isLangIdDisabled("blade")) { + if (onStart) { + return ["{{--", "--}}"]; + } else { + vscode.languages.setLanguageConfiguration("blade", { + comments: { + blockComment: ["{{--", "--}}"], + }, + }); + } + } + // Is disabled OR blade langId is set as disabled... + else if (!bladeOverrideComments || this.isLangIdDisabled("blade")) { + if (onStart) { + return [""]; + } else { + vscode.languages.setLanguageConfiguration("blade", { + comments: { + blockComment: [""], + }, + }); + } + } + } + /** * Get the names and ids of this extension from package.json. * @@ -39,6 +134,7 @@ export class Configuration { return {id: id, name: name, displayName: displayName}; } + /** * Get extension configuration. */ @@ -54,29 +150,6 @@ export class Configuration { return multiLineConfig["languages"]; } - private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): Disposable { - var langConfig: LanguageConfiguration = { - onEnterRules: [], - }; - - if (multiLine) { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.multilineEnterRules); - } - - let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); - if (isOnEnter && singleLineStyle) { - if (singleLineStyle === "//") { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.slashEnterRules); - } else if (singleLineStyle === "#") { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.hashEnterRules); - } else if (singleLineStyle === ";") { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.semicolonEnterRules); - } - } - - return languages.setLanguageConfiguration(langId, langConfig); - } - private getSingleLineLanguages() { let commentStyles = Object.keys(singleLineConfig); for (let key of commentStyles) { @@ -110,23 +183,27 @@ export class Configuration { } } - configureCommentBlocks(context: ExtensionContext) { - this.getSingleLineLanguages(); + private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): Disposable { + var langConfig: LanguageConfiguration = { + onEnterRules: [], + }; - // set language configurations - let multiLineLangs = this.getMultiLineLanguages(); - for (let [langId, style] of this.singleLineBlocksMap) { - let multiLine = multiLineLangs.indexOf(langId) !== -1; - let disposable = this.setLanguageConfiguration(langId, multiLine, style); - context.subscriptions.push(disposable); + if (multiLine) { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.multilineEnterRules); } - for (let langId of multiLineLangs) { - if (!this.singleLineBlocksMap.has(langId) && !this.isLangIdDisabled(langId)) { - let disposable = this.setLanguageConfiguration(langId, true); - context.subscriptions.push(disposable); + let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); + if (isOnEnter && singleLineStyle) { + if (singleLineStyle === "//") { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.slashEnterRules); + } else if (singleLineStyle === "#") { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.hashEnterRules); + } else if (singleLineStyle === ";") { + langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.semicolonEnterRules); } } + + return languages.setLanguageConfiguration(langId, langConfig); } private handleSingleLineBlock(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) { @@ -213,58 +290,4 @@ export class Configuration { this.setBladeComments(false); } } - - /** - * Register some VSCode commands. - */ - public registerCommands() { - const singleLineBlockCommand = vscode.commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { - this.handleSingleLineBlock(textEditor, edit); - }); - const changeBladeMultiLineBlockCommand = vscode.commands.registerTextEditorCommand( - this.changeBladeMultiLineBlockCommand, - (textEditor, edit, args) => { - this.handleChangeBladeMultiLineBlock(textEditor); - } - ); - return [singleLineBlockCommand, changeBladeMultiLineBlockCommand]; - } - - /** - * Sets the block comments for the blade language determined by the user setting. - * - * @param bladeOverrideComments A boolean indicating whether or not the user setting "Blade Override Comments" is enabled. - * - * @param [onStart=false] A boolean indicating whether or not the method was called - * on starting the extension. - * If `true`, it returns the comments, if `false` (default), it sets the comments to - * the language directly. - * - */ - public setBladeComments(bladeOverrideComments: boolean, onStart: boolean = false): any { - // Is enabled AND blade langId is NOT set as disabled... - if (bladeOverrideComments === true && !this.isLangIdDisabled("blade")) { - if (onStart) { - return ["{{--", "--}}"]; - } else { - vscode.languages.setLanguageConfiguration("blade", { - comments: { - blockComment: ["{{--", "--}}"], - }, - }); - } - } - // Is disabled OR blade langId is set as disabled... - else if (!bladeOverrideComments || this.isLangIdDisabled("blade")) { - if (onStart) { - return [""]; - } else { - vscode.languages.setLanguageConfiguration("blade", { - comments: { - blockComment: [""], - }, - }); - } - } - } } From a12484d04b02d8ff09b30cdfa23775448af12aab Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 19:50:33 +0000 Subject: [PATCH 11/27] feat: Remove all hardcoded language support and add functionality to automatically support any language found internally in vscode. Deleted: - Delete the hardcoded single-line and multi-line configuration files and imports. Added: - Auto-generated language definition files. These files, will be overwritten every time the extension activates or renews it's definitions. - Several new properties to define new Map()s for the language paths, configs, and definitions. - `findAllLanguageConfigFilePaths()` to find all internal language config file paths from vscode installed extensions (built-in and 3rd party). - `readJsonFile()` and npm packages to read and parse JSON files. - `getLanguagesToSkip()` to read and skip the languages defined in the skip-languages config file. - `setLanguageConfigDefinitions()` to read and set the language config definitions into the Map. - `getLanguageConfig()` to get a specified language config from the definition Map. - `writeJsonFile()` to write JSON into a file. - `setMultiLineCommentLanguageDefinitions()` to determine if a language supports block comments, and set the supported languages into the definition Map. - `setSingleLineCommentLanguageDefinitions()` - replaces the old functionality of `getSingleLineLanguages()` - to determine if a language supports a particular line comment, and set the supported languages into the definition Map. - `writeCommentLanguageDefinitionsToJsonFile()` to write the single-line and multi-line comment language definitions into the auto-generated definitions JSON files respectively. - `mergeConfigAutoClosingPairs()` to merge the autoClosingPairs of the internal config with the default, removing any duplicates. - `mergeConfigOnEnterRules()` to merge the onEnterRules of the internal config with the default, removing any duplicates. - Add a constructor() to setup the definitions. Changed: - Simplified `getSingleLineLanguages()` to return just the Map, and moved the functionality into the new method `setSingleLineCommentLanguageDefinitions()`. - `setLanguageConfiguration()` to use the new internal language configs and merge the configs with the default multi-line config if required and then set vscode to use the language configuration for the extension to work its magic. --- .../multi-line-languages.json | 21 +- .../single-line-languages.json | 61 ++++ src/configuration.ts | 338 +++++++++++++++++- src/single-line-configuration.ts | 35 -- 4 files changed, 402 insertions(+), 53 deletions(-) rename src/multi-line-configuration.ts => auto-generated-language-definitions/multi-line-languages.json (50%) create mode 100644 auto-generated-language-definitions/single-line-languages.json delete mode 100644 src/single-line-configuration.ts diff --git a/src/multi-line-configuration.ts b/auto-generated-language-definitions/multi-line-languages.json similarity index 50% rename from src/multi-line-configuration.ts rename to auto-generated-language-definitions/multi-line-languages.json index 24d70d0..56918c5 100644 --- a/src/multi-line-configuration.ts +++ b/auto-generated-language-definitions/multi-line-languages.json @@ -1,23 +1,36 @@ -export const config = { +{ "languages": [ "blade", "c", "cpp", + "cpp_embedded_latex", "csharp", "css", + "cuda-cpp", + "dart", "go", "groovy", + "hlsl", + "html", "java", "javascript", + "javascriptreact", + "json", + "jsonc", + "jsonl", "less", "objective-c", "objective-cpp", "php", - "proto", "proto3", "rust", + "sass", "scss", + "shaderlab", + "snippets", + "sql", "swift", - "typescript" + "typescript", + "typescriptreact" ] -} +} \ No newline at end of file diff --git a/auto-generated-language-definitions/single-line-languages.json b/auto-generated-language-definitions/single-line-languages.json new file mode 100644 index 0000000..684c86d --- /dev/null +++ b/auto-generated-language-definitions/single-line-languages.json @@ -0,0 +1,61 @@ +{ + "#": [ + "apacheconf", + "coffeescript", + "diff", + "dockercompose", + "dockerfile", + "dotenv", + "editorconfig", + "git-commit", + "git-rebase", + "github-actions-workflow", + "http", + "ignore", + "julia", + "makefile", + "nginx", + "perl", + "powershell", + "python", + "r", + "raku", + "ruby", + "shellscript", + "yaml" + ], + "//": [ + "c", + "cpp", + "cpp_embedded_latex", + "csharp", + "cuda-cpp", + "dart", + "fsharp", + "go", + "groovy", + "hlsl", + "java", + "javascript", + "javascriptreact", + "json", + "jsonc", + "jsonl", + "less", + "objective-c", + "objective-cpp", + "php", + "rust", + "sass", + "scss", + "shaderlab", + "snippets", + "swift", + "typescript", + "typescriptreact" + ], + ";": [ + "clojure", + "ini" + ] +} \ No newline at end of file diff --git a/src/configuration.ts b/src/configuration.ts index 1240023..903975d 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -3,10 +3,10 @@ import {Disposable, ExtensionContext, LanguageConfiguration, TextEditor, TextEditorEdit, commands, languages, workspace} from "vscode"; import * as vscode from "vscode"; import * as fs from "node:fs"; +import * as jsonc from "jsonc-parser"; +import * as path from "path"; import {Rules} from "./rules"; -import {config as singleLineConfig} from "./single-line-configuration"; -import {config as multiLineConfig} from "./multi-line-configuration"; export class Configuration { /************** @@ -31,16 +31,50 @@ export class Configuration { */ private singleLineBlocksMap: Map = new Map(); + /** + * A Map object of an array of supported language IDs for multi line block comments. + * + * @property {string} key - "languages" + * @property {string[]} value - Array of language IDs. + */ + private multiLineBlocksMap: Map = new Map(); + + private readonly singleLineLangDefinitionFilePath = `${__dirname}/../../auto-generated-language-definitions/single-line-languages.json`; + + private readonly multiLineLangDefinitionFilePath = `${__dirname}/../../auto-generated-language-definitions/multi-line-languages.json`; + + /** + * A key:value Map object of language IDs and their config file paths. + */ + private languageConfigFilePaths = new Map(); + + /** + * A key:value Map object of language IDs and their configs. + */ + private readonly languageConfigs = new Map(); + /*********** * Methods * ***********/ + public constructor() { + this.findAllLanguageConfigFilePaths(); + console.log(this.languageConfigFilePaths); + this.setLanguageConfigDefinitions(); + console.log("language configs", this.languageConfigs); + + this.setMultiLineCommentLanguageDefinitions(); + console.log(this.multiLineBlocksMap); + this.setSingleLineCommentLanguageDefinitions(); + console.log(this.singleLineBlocksMap); + } + configureCommentBlocks(context: ExtensionContext) { const disposables: vscode.Disposable[] = []; // Set language configurations - this.getSingleLineLanguages(); - let multiLineLangs = this.getMultiLineLanguages(); + const singleLineLangs = this.getSingleLineLanguages(); + const multiLineLangs = this.getMultiLineLanguages(); // Setup the single line languages. for (let [langId, style] of this.singleLineBlocksMap) { @@ -146,21 +180,212 @@ export class Configuration { return this.disabledLanguageList.includes(langId); } + /** + * Get an array of languages to skip, like plaintext, that don't have comment syntax + * + * Idea from this StackOverflow answer https://stackoverflow.com/a/72988011/2358222 + * + * @returns {string[]} + */ + private getLanguagesToSkip(): string[] { + const json = this.readJsonFile(`${__dirname}/../../config/skip-languages.jsonc`); + return json.languages; + } + + /** + * Find all language config files from vscode installed extensions (built-in and 3rd party). + */ + private findAllLanguageConfigFilePaths() { + // Loop through all installed extensions, including built-in extensions + for (let extension of vscode.extensions.all) { + const packageJSON = extension.packageJSON; + + // If an extension package.json has "contributes" key, + // AND the contributes object has "languages" key... + if (Object.hasOwn(packageJSON, "contributes") && Object.hasOwn(packageJSON.contributes, "languages")) { + // Loop through the languages... + for (let language of packageJSON.contributes.languages) { + // Get the languages to skip. + let skipLangs = this.getLanguagesToSkip(); + + // If skipLangs doesn't include the language ID, + // AND the language object has "configuration" key... + if (!skipLangs?.includes(language.id) && Object.hasOwn(language, "configuration")) { + // Join the extension path with the configuration path. + let configPath = path.join(extension.extensionPath, language.configuration); + // Set the language ID and config path into the languageConfigFilePaths Map. + this.languageConfigFilePaths.set(language.id, configPath); + } + } + } + } + + // Set the languageConfigFilePaths to a new map with all the languages sorted in + // ascending order,for sanity reasons. + this.languageConfigFilePaths = new Map([...this.languageConfigFilePaths].sort()); + } + + /** + * Set the language config definitions. + */ + private setLanguageConfigDefinitions() { + this.languageConfigFilePaths.forEach((filepath, langId) => { + const config = this.readJsonFile(filepath); + + // If the config JSON has more than 0 keys (ie. not empty) + if (Object.keys(config).length > 0) { + /** + * Change all autoClosingPairs items that are using the simpler syntax + * (array instead of object) into the object with open and close keys. + * Prevents vscode from failing quietly and not changing the editor language + * properly, which makes the open file become unresponsive when changing tabs. + */ + + // If config has key autoClosingPairs... + if (Object.hasOwn(config, "autoClosingPairs")) { + // Define a new array as the new AutoClosingPair. + const autoClosingPairsArray: vscode.AutoClosingPair[] = []; + // Loop through the config's autoClosingPairs... + config.autoClosingPairs.forEach((item) => { + // If the item is an array... + if (Array.isArray(item)) { + // Create a new object with the 1st array element [0] as the + // value of the open key, and the 2nd element [1] as the value + // of the close key. + const autoClosingPairsObj = {open: item[0], close: item[1]}; + // Push the object into the new array. + autoClosingPairsArray.push(autoClosingPairsObj); + } + // Otherwise, the item is an object, so just push it into the array. + else { + autoClosingPairsArray.push(item); + } + }); + + // Add the new array to the config's autoClosingPairs key. + config.autoClosingPairs = autoClosingPairsArray; + } + + // Set the language configs into the Map. + this.languageConfigs.set(langId, config); + } + }); + } + + /** + * Get the config of the specified language. + * + * @param langId Language ID + * @returns {vscode.LanguageConfiguration | undefined} + */ + private getLanguageConfig(langId: string) { + if (this.languageConfigs.has(langId)) { + return this.languageConfigs.get(langId); + } + // If no config exists for this language, back out and leave the language unsupported + else { + return undefined; + } + } + + /** + * Read the file and parse the JSON. + * + * @param {string} filepath The path of the file. + * @returns The file content. + */ + private readJsonFile(filepath: string): any { + return jsonc.parse(fs.readFileSync(filepath).toString()); + } + + /** + * Read the file and parse the JSON. + * + * @param {string} filepath The path of the file. + * @param {any} data The data to write into the file. + * @returns The file content. + */ + private writeJsonFile(filepath: string, data: any): any { + // Write the updated JSON back into the file and add tab indentation + // to make it easier to read. + fs.writeFileSync(filepath, JSON.stringify(data, null, "\t")); + } + private getMultiLineLanguages(): Array { return multiLineConfig["languages"]; } private getSingleLineLanguages() { - let commentStyles = Object.keys(singleLineConfig); - for (let key of commentStyles) { - for (let langId of singleLineConfig[key]) { - if (!this.isLangIdDisabled(langId)) { - this.singleLineBlocksMap.set(langId, key); + return this.singleLineBlocksMap; + } + + private setMultiLineCommentLanguageDefinitions() { + let langArray = []; + + this.languageConfigs.forEach((config: any, langId: string) => { + // If the config object has own property of comments AND the comments key has + // own property of blockComment... + if (Object.hasOwn(config, "comments") && Object.hasOwn(config.comments, "blockComment")) { + // If the blockComment array includes the multi line start of "/*"... + if (config.comments.blockComment.includes("/*")) { + // console.log(langId, config.comments); + + // If Language ID isn't already in the langArray... + if (!langArray.includes(langId)) { + langArray.push(langId); + } } } + }); + + const multiLineStyleBlocksLangs = this.getConfiguration().get(this.multiLineStyleBlocks); + + for (let langId of multiLineStyleBlocksLangs) { + if (langId && langId.length > 0 && !langArray.includes(langId)) { + langArray.push(langId); + } } - // get user-customized langIds for this key and add to the map + // Set the language array into the multiLineBlockMap, sorted in ascending order, + // for sanity reasons. + this.multiLineBlocksMap.set("languages", langArray.sort()); + + this.writeCommentLanguageDefinitionsToJsonFile(); + } + + private setSingleLineCommentLanguageDefinitions() { + let style: string; + + this.languageConfigs.forEach((config: any, langId: string) => { + // console.log(langId, config.comments.lineComment); + let style: string = ""; + + // If the config object has own property of comments AND the comments key has + // own property of lineComment... + if (Object.hasOwn(config, "comments") && Object.hasOwn(config.comments, "lineComment")) { + // If the lineComment is "//"... + if (config.comments.lineComment === "//") { + style = "//"; + } + // If the lineComment is "#"... + else if (config.comments.lineComment === "#") { + style = "#"; + } + // If the lineComment includes a ";" (; or ;;)... + else if (config.comments.lineComment.includes(";")) { + style = ";"; + } + + // If style any empty string, (i.e. not an unsupported single line + // comment like bat's @rem)... + if (style != "") { + // Set the langId and it's style into the Map. + this.singleLineBlocksMap.set(langId, style); + } + } + }); + + // Get user-customized langIds for the //-style and add to the map. let customSlashLangs = this.getConfiguration().get(this.slashStyleBlocks); for (let langId of customSlashLangs) { if (langId && langId.length > 0) { @@ -168,6 +393,7 @@ export class Configuration { } } + // Get user-customized langIds for the #-style and add to the map. let customHashLangs = this.getConfiguration().get(this.hashStyleBlocks); for (let langId of customHashLangs) { if (langId && langId.length > 0) { @@ -175,24 +401,68 @@ export class Configuration { } } + // Get user-customized langIds for the ;-style and add to the map. let customSemicolonLangs = this.getConfiguration().get(this.semicolonStyleBlocks); for (let langId of customSemicolonLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, ";"); } } + + // Set the singleLineBlockMap to a new map with all the languages sorted in ascending order, + // for sanity reasons. + this.singleLineBlocksMap = new Map([...this.singleLineBlocksMap].sort()); + + this.writeCommentLanguageDefinitionsToJsonFile(); } - private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): Disposable { - var langConfig: LanguageConfiguration = { - onEnterRules: [], + /** + * Write Comment Language Definitions to the respective JSON file: + * either multi-line-languages.json, or single-line-languages.json. + */ + private writeCommentLanguageDefinitionsToJsonFile() { + // Convert a key:value Map into an key:array object, while reversing/switching the + // keys and values. The Map's values are now the keys of the object and the Map's keys + // are now added as the values of the array. + // e.g. From `Map {apacheconf => #, c => //, clojure => ;, coffeescript => #, cpp => //, …}` + // to `{"#": ["apacheconf", "coffeescript", ...], "//": ["c", "cpp", ...], + // ";": ["clojure", ...]}` + // + // Code from this StackOverflow answer https://stackoverflow.com/a/45728850/2358222 + const reverseMapping = (m: Map): object => { + const o = Object.fromEntries(m); + + return Object.keys(o).reduce((r, k) => Object.assign(r, {[o[k]]: (r[o[k]] || []).concat(k)}), {}); }; + // Write the into the single-line-languages.json file. + this.writeJsonFile(this.singleLineLangDefinitionFilePath, reverseMapping(this.singleLineBlocksMap)); + // Write the into the multi-line-languages.json file. + this.writeJsonFile(this.multiLineLangDefinitionFilePath, Object.fromEntries(this.multiLineBlocksMap)); + } + + private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): Disposable { + const internalLangConfig = this.getLanguageConfig(langId); + const defaultMultiLineConfig = this.readJsonFile(`${__dirname}/../../config/default-multi-line-config.json`); + + let langConfig = {...internalLangConfig}; + if (multiLine) { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.multilineEnterRules); + langConfig.autoClosingPairs = this.mergeConfigAutoClosingPairs(defaultMultiLineConfig, internalLangConfig); + + // Add the multi-line onEnter rules to the langConfig. + langConfig.onEnterRules = this.mergeConfigOnEnterRules(Rules.multilineEnterRules, internalLangConfig); + + /** + * Get the user settings/configuration and set the blade or html comments accordingly. + */ + if (langId === "blade") { + langConfig.comments.blockComment = this.setBladeComments(this.getConfiguration().get("bladeOverrideComments"), true); + } } let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); + if (isOnEnter && singleLineStyle) { if (singleLineStyle === "//") { langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.slashEnterRules); @@ -203,9 +473,49 @@ export class Configuration { } } + console.log(langId, langConfig); + return languages.setLanguageConfiguration(langId, langConfig); } + private mergeConfigAutoClosingPairs(defaultLangConfig, internalLangConfig) { + const defaultAutoClosing = defaultLangConfig.autoClosingPairs; + const internalAutoClosing = internalLangConfig?.autoClosingPairs ?? []; + + // Code based on "2023 update" portion of this StackOverflow answer: + // https://stackoverflow.com/a/1584377/2358222 + + // Copy to avoid side effects. + const merged = [...internalAutoClosing]; + // Loop over the defaultLangConfig autoClosingPairs array... + defaultAutoClosing.forEach((item) => { + // Test all items in the merged array, and if the defaultAutoClosing item's + // opening comment string (item.open) is not already present in one of the + // merged array's objects then add the item to the merged array. + merged.some((mergedItem) => item.open === mergedItem.open) ? null : merged.push(item); + }); + + return merged; + } + private mergeConfigOnEnterRules(defaultOnEnterRules, internalLangConfig) { + const internalOnEnterRules = internalLangConfig?.onEnterRules ?? []; + + // Code based on "2023 update" portion of this StackOverflow answer: + // https://stackoverflow.com/a/1584377/2358222 + + // Copy to avoid side effects. + const merged = [...defaultOnEnterRules]; + // Loop over the defaultLangConfig autoClosingPairs array... + internalOnEnterRules.forEach((item) => { + // Test all items in the merged array, and if the defaultAutoClosing item's + // opening comment string (item.open) is not already present in one of the + // merged array's objects then add the item to the merged array. + merged.some((mergedItem) => item.beforeText === mergedItem.beforeText) ? null : merged.push(item); + }); + + return merged; + } + private handleSingleLineBlock(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) { let langId = textEditor.document.languageId; var style = this.singleLineBlocksMap.get(langId); diff --git a/src/single-line-configuration.ts b/src/single-line-configuration.ts deleted file mode 100644 index 0fbdec6..0000000 --- a/src/single-line-configuration.ts +++ /dev/null @@ -1,35 +0,0 @@ -export const config = { - "//": [ - "blade", - "c", - "cpp", - "csharp", - "fsharp", - "go", - "groovy", - "java", - "javascript", - "less", - "objective-c", - "objective-cpp", - "php", - "rust", - "scss", - "swift", - "typescript" - ], - "#": [ - "coffeescript", - "dockerfile", - "makefile", - "perl", - "powershell", - "python", - "r", - "ruby", - "yaml" - ], - ";": [ - "clojure" - ] -} \ No newline at end of file From 1dd90d55a4f97e5fc6345f5e3c72e8b2cb9ba282 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 5 Dec 2024 22:39:56 +0000 Subject: [PATCH 12/27] refactor: Add typings, and doc comments, and ... ...change the `getMultiLineLanguages()` to use the Map. Also change vscode typings to use vscode global variable. --- src/configuration.ts | 96 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 14 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 903975d..48d1384 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1,6 +1,6 @@ "use strict"; +/* https://code.visualstudio.com/api/language-extensions/language-configuration-guide */ -import {Disposable, ExtensionContext, LanguageConfiguration, TextEditor, TextEditorEdit, commands, languages, workspace} from "vscode"; import * as vscode from "vscode"; import * as fs from "node:fs"; import * as jsonc from "jsonc-parser"; @@ -19,10 +19,14 @@ export class Configuration { private readonly slashStyleBlocks: string = "slashStyleBlocks"; private readonly hashStyleBlocks: string = "hashStyleBlocks"; private readonly semicolonStyleBlocks: string = "semicolonStyleBlocks"; + private readonly multiLineStyleBlocks: string = "multiLineStyleBlocks"; private readonly disabledLanguages: string = "disabledLanguages"; + private readonly overrideDefaultLanguageMultiLineComments: string = "overrideDefaultLanguageMultiLineComments"; private disabledLanguageList: string[] = this.getConfiguration().get(this.disabledLanguages); + private overriddenLangMultiLineCommentList: string[] = this.getConfiguration().get(this.overrideDefaultLanguageMultiLineComments); + /** * A key:value Map object of supported language IDs and their single line style comments. * @@ -69,7 +73,13 @@ export class Configuration { console.log(this.singleLineBlocksMap); } - configureCommentBlocks(context: ExtensionContext) { + /** + * Configure the comment blocks. + * + * @param {vscode.ExtensionContext} context The context of the extension. + * @returns {vscode.Disposable[]} + */ + configureCommentBlocks(context: vscode.ExtensionContext) { const disposables: vscode.Disposable[] = []; // Set language configurations @@ -98,6 +108,8 @@ export class Configuration { /** * Register some VSCode commands. + * + * @returns {vscode.Disposable[]} */ public registerCommands() { const singleLineBlockCommand = vscode.commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { @@ -170,12 +182,19 @@ export class Configuration { } /** - * Get extension configuration. + * Get extension user configuration settings. + * + * @returns {vscode.WorkspaceConfiguration} */ public getConfiguration(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration(this.getExtensionNames().name, null); } + /** + * Is the language ID disabled? + * @param {string} langId Language ID + * @returns {boolean} + */ public isLangIdDisabled(langId: string): boolean { return this.disabledLanguageList.includes(langId); } @@ -193,7 +212,8 @@ export class Configuration { } /** - * Find all language config files from vscode installed extensions (built-in and 3rd party). + * Find all language config file paths from vscode installed extensions + * (built-in and 3rd party). */ private findAllLanguageConfigFilePaths() { // Loop through all installed extensions, including built-in extensions @@ -311,14 +331,27 @@ export class Configuration { fs.writeFileSync(filepath, JSON.stringify(data, null, "\t")); } - private getMultiLineLanguages(): Array { - return multiLineConfig["languages"]; + /** + * Get the multi-line languages from the Map. + * + * @returns {string[]} An array of language ID strings. + */ + private getMultiLineLanguages(): string[] { + return this.multiLineBlocksMap.get("languages"); } - private getSingleLineLanguages() { + /** + * Get the single-line languages and styles. + * + * @returns {Map} The Map of the languages and styles. + */ + private getSingleLineLanguages(): Map { return this.singleLineBlocksMap; } + /** + * Set the multi-line comments language definitions. + */ private setMultiLineCommentLanguageDefinitions() { let langArray = []; @@ -353,6 +386,9 @@ export class Configuration { this.writeCommentLanguageDefinitionsToJsonFile(); } + /** + * Set the single-line comments language definitions. + */ private setSingleLineCommentLanguageDefinitions() { let style: string; @@ -441,9 +477,19 @@ export class Configuration { this.writeJsonFile(this.multiLineLangDefinitionFilePath, Object.fromEntries(this.multiLineBlocksMap)); } - private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): Disposable { - const internalLangConfig = this.getLanguageConfig(langId); - const defaultMultiLineConfig = this.readJsonFile(`${__dirname}/../../config/default-multi-line-config.json`); + /** + * Merge the internal configs with the default multi-line config if required, and + * set vscode to use the language configuration. + * + * @param {string} langId Language ID + * @param {boolean} multiLine Determine's whether to set the language for multi-line comments. + * @param {string} singleLineStyle The style of the single-line comment. + * @returns {vscode.Disposable} + */ + private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): vscode.Disposable { + const internalLangConfig: vscode.LanguageConfiguration = this.getLanguageConfig(langId); + const defaultMultiLineConfig: any = this.readJsonFile(`${__dirname}/../../config/default-multi-line-config.json`); + console.log(typeof defaultMultiLineConfig); let langConfig = {...internalLangConfig}; @@ -475,10 +521,17 @@ export class Configuration { console.log(langId, langConfig); - return languages.setLanguageConfiguration(langId, langConfig); + return vscode.languages.setLanguageConfiguration(langId, langConfig); } - private mergeConfigAutoClosingPairs(defaultLangConfig, internalLangConfig) { + /** + * Merge the internal config AutoClosingPairs with the default config, removing any duplicates. + * + * @param {any} defaultLangConfig Default multi-line comments config. + * @param {vscode.LanguageConfiguration} internalLangConfig Internal language config from vscode extensions. + * @returns {vscode.AutoClosingPair[]} + */ + private mergeConfigAutoClosingPairs(defaultLangConfig, internalLangConfig: vscode.LanguageConfiguration) { const defaultAutoClosing = defaultLangConfig.autoClosingPairs; const internalAutoClosing = internalLangConfig?.autoClosingPairs ?? []; @@ -497,6 +550,14 @@ export class Configuration { return merged; } + + /** + * Merge the internal config onEnterRules with the default config, removing any duplicates. + * + * @param {any} defaultOnEnterRules Default onEnterRules. + * @param {vscode.LanguageConfiguration} internalLangConfig Internal language config from vscode extensions. + * @returns {vscode.OnEnterRule[]} + */ private mergeConfigOnEnterRules(defaultOnEnterRules, internalLangConfig) { const internalOnEnterRules = internalLangConfig?.onEnterRules ?? []; @@ -516,6 +577,12 @@ export class Configuration { return merged; } + /** + * The keyboard binding event handler for the single line blocks on shift+enter. + * + * @param {vscode.TextEditor} textEditor The text editor. + * @param {vscode.TextEditorEdit} edit The text editor edits. + */ private handleSingleLineBlock(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) { let langId = textEditor.document.languageId; var style = this.singleLineBlocksMap.get(langId); @@ -559,9 +626,10 @@ export class Configuration { } /** - * The keyboard binding handler to change between the multi-line block comments for + * The keyboard binding event handler to change between the multi-line block comments for * blade `{{-- --}}` and normal `` - * @param textEditor The editor + * + * @param {vscode.TextEditor} textEditor The text editor. */ private handleChangeBladeMultiLineBlock(textEditor: vscode.TextEditor) { let langId = textEditor.document.languageId; From a63bfe11d735110c9f2f75172ab489e10e20ed7c Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Mon, 9 Dec 2024 22:50:04 +0000 Subject: [PATCH 13/27] refactor: Refactoring code and added 2 new methods for the `overrideDefaultLanguageMultiLineComments` config setting. - Remove unnecessary properties that only define strings, and move the strings directly into the methods that need them. These properties are only declaring the configuration setting names, which are mostly only used once, but contributes to code bloat. - Added the functionality of `disabledLanguageList` and `overriddenLangMultiLineCommentList` properties directly into the `isLangIdDisabled` and `isLangIdMultiLineCommentOverridden` methods respectively, and removed the unnecessary properties. - Added `isLangIdMultiLineCommentOverridden` method to determine if the specified language ID is in the `overrideDefaultLanguageMultiLineComments` config setting. - Added `getOverriddenMultiLineComment` method to get the overridden multi-line comment for that language ID within the `overrideDefaultLanguageMultiLineComments` config setting. - Move the `languageConfigFilePaths` and `languageConfigs` properties to the top to keep things in order of usage. --- src/configuration.ts | 72 +++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 48d1384..6b80bf7 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -12,20 +12,16 @@ export class Configuration { /************** * Properties * **************/ - private readonly singleLineBlockCommand: string = "auto-comment-blocks.singleLineBlock"; - private readonly changeBladeMultiLineBlockCommand: string = "auto-comment-blocks.changeBladeMultiLineBlock"; - private readonly singleLineBlockOnEnter: string = "singleLineBlockOnEnter"; - private readonly slashStyleBlocks: string = "slashStyleBlocks"; - private readonly hashStyleBlocks: string = "hashStyleBlocks"; - private readonly semicolonStyleBlocks: string = "semicolonStyleBlocks"; - private readonly multiLineStyleBlocks: string = "multiLineStyleBlocks"; - private readonly disabledLanguages: string = "disabledLanguages"; - private readonly overrideDefaultLanguageMultiLineComments: string = "overrideDefaultLanguageMultiLineComments"; - - private disabledLanguageList: string[] = this.getConfiguration().get(this.disabledLanguages); + /** + * A key:value Map object of language IDs and their config file paths. + */ + private languageConfigFilePaths = new Map(); - private overriddenLangMultiLineCommentList: string[] = this.getConfiguration().get(this.overrideDefaultLanguageMultiLineComments); + /** + * A key:value Map object of language IDs and their configs. + */ + private readonly languageConfigs = new Map(); /** * A key:value Map object of supported language IDs and their single line style comments. @@ -47,16 +43,6 @@ export class Configuration { private readonly multiLineLangDefinitionFilePath = `${__dirname}/../../auto-generated-language-definitions/multi-line-languages.json`; - /** - * A key:value Map object of language IDs and their config file paths. - */ - private languageConfigFilePaths = new Map(); - - /** - * A key:value Map object of language IDs and their configs. - */ - private readonly languageConfigs = new Map(); - /*********** * Methods * ***********/ @@ -112,11 +98,11 @@ export class Configuration { * @returns {vscode.Disposable[]} */ public registerCommands() { - const singleLineBlockCommand = vscode.commands.registerTextEditorCommand(this.singleLineBlockCommand, (textEditor, edit, args) => { + const singleLineBlockCommand = vscode.commands.registerTextEditorCommand("auto-comment-blocks.singleLineBlock", (textEditor, edit, args) => { this.handleSingleLineBlock(textEditor, edit); }); const changeBladeMultiLineBlockCommand = vscode.commands.registerTextEditorCommand( - this.changeBladeMultiLineBlockCommand, + "auto-comment-blocks.changeBladeMultiLineBlock", (textEditor, edit, args) => { this.handleChangeBladeMultiLineBlock(textEditor); } @@ -196,7 +182,31 @@ export class Configuration { * @returns {boolean} */ public isLangIdDisabled(langId: string): boolean { - return this.disabledLanguageList.includes(langId); + return this.getConfiguration().get("disabledLanguages").includes(langId); + } + + /** + * Is the multi-line comment overridden for the specified language ID? + * + * @param {string} langId Language ID + * @returns {boolean} + */ + private isLangIdMultiLineCommentOverridden(langId: string): boolean { + const overriddenList = this.getConfiguration().get("overrideDefaultLanguageMultiLineComments"); + + return overriddenList.hasOwnProperty(langId); + } + + /** + * Get the overridden multi-line comment for the specified language ID. + * + * @param {string} langId Language ID + * @returns {string} + */ + private getOverriddenMultiLineComment(langId: string) { + const overriddenList = this.getConfiguration().get("overrideDefaultLanguageMultiLineComments"); + + return overriddenList[langId]; } /** @@ -371,7 +381,7 @@ export class Configuration { } }); - const multiLineStyleBlocksLangs = this.getConfiguration().get(this.multiLineStyleBlocks); + const multiLineStyleBlocksLangs = this.getConfiguration().get("multiLineStyleBlocks"); for (let langId of multiLineStyleBlocksLangs) { if (langId && langId.length > 0 && !langArray.includes(langId)) { @@ -422,7 +432,7 @@ export class Configuration { }); // Get user-customized langIds for the //-style and add to the map. - let customSlashLangs = this.getConfiguration().get(this.slashStyleBlocks); + let customSlashLangs = this.getConfiguration().get("slashStyleBlocks"); for (let langId of customSlashLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, "//"); @@ -430,7 +440,7 @@ export class Configuration { } // Get user-customized langIds for the #-style and add to the map. - let customHashLangs = this.getConfiguration().get(this.hashStyleBlocks); + let customHashLangs = this.getConfiguration().get("hashStyleBlocks"); for (let langId of customHashLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, "#"); @@ -438,7 +448,7 @@ export class Configuration { } // Get user-customized langIds for the ;-style and add to the map. - let customSemicolonLangs = this.getConfiguration().get(this.semicolonStyleBlocks); + let customSemicolonLangs = this.getConfiguration().get("semicolonStyleBlocks"); for (let langId of customSemicolonLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, ";"); @@ -507,7 +517,7 @@ export class Configuration { } } - let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); + let isOnEnter = this.getConfiguration().get("singleLineBlockOnEnter"); if (isOnEnter && singleLineStyle) { if (singleLineStyle === "//") { @@ -616,7 +626,7 @@ export class Configuration { } var indentedNewLine = "\n" + line.text.substring(0, line.text.search(indentRegex)); - let isOnEnter = this.getConfiguration().get(this.singleLineBlockOnEnter); + let isOnEnter = this.getConfiguration().get("singleLineBlockOnEnter"); if (!isOnEnter) { indentedNewLine += style + " "; } From 3ae8652320afbfdebaf104a87bb227f5674aef3c Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Mon, 9 Dec 2024 23:18:55 +0000 Subject: [PATCH 14/27] refactor: Add 2 new methods to get and update the config settings and simplify code. - Added `getConfigurationValue` method to get the value of the specified key from the extension's config settings. - Added `updateConfigurationValue` method to update value of the specified key from the extension's config settings. - Changed all code to use these methods. This is so we only chain `vscode.WorkspaceConfiguration`'s `get` and `update` methods directly in the corresponding new methods, which simplifies code. --- src/configuration.ts | 70 +++++++++++++++++++++++++++++++------------- src/extension.ts | 4 +-- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 6b80bf7..8b10e81 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -168,7 +168,7 @@ export class Configuration { } /** - * Get extension user configuration settings. + * Get all the extension's configuration settings. * * @returns {vscode.WorkspaceConfiguration} */ @@ -176,13 +176,46 @@ export class Configuration { return vscode.workspace.getConfiguration(this.getExtensionNames().name, null); } + /** + * Get value of the specified key from the extension's user configuration settings. + * + * @param {string} key The key of the specific setting. + * + * @returns {T} Returns the value of the `key`. + * + * NOTE: Return is typed as `T`, which is a generic type that represents the type that is declared when called (as explained in this StackOverflow answer: https://stackoverflow.com/a/49622066/2358222) + * + * @example ```ts + * this.getConfigurationValue("disabledLanguages"); + * ``` + */ + public getConfigurationValue(key: string): T { + return this.getConfiguration().get(key); + } + + /** + * Update value of the specified key from the extension's user configuration settings. + * + * @param {string} key The key of the specific setting. + + * @param {any} value The value to update the setting with. + * + * @example ```ts + * this.updateConfigurationValue("bladeOverrideComments", true); + * ``` + */ + public updateConfigurationValue(key: string, value: any) { + // .update(config key, new value, global) + this.getConfiguration().update(key, value, true); + } + /** * Is the language ID disabled? * @param {string} langId Language ID * @returns {boolean} */ public isLangIdDisabled(langId: string): boolean { - return this.getConfiguration().get("disabledLanguages").includes(langId); + return this.getConfigurationValue("disabledLanguages").includes(langId); } /** @@ -192,7 +225,7 @@ export class Configuration { * @returns {boolean} */ private isLangIdMultiLineCommentOverridden(langId: string): boolean { - const overriddenList = this.getConfiguration().get("overrideDefaultLanguageMultiLineComments"); + const overriddenList = this.getConfigurationValue("overrideDefaultLanguageMultiLineComments"); return overriddenList.hasOwnProperty(langId); } @@ -204,7 +237,7 @@ export class Configuration { * @returns {string} */ private getOverriddenMultiLineComment(langId: string) { - const overriddenList = this.getConfiguration().get("overrideDefaultLanguageMultiLineComments"); + const overriddenList = this.getConfigurationValue("overrideDefaultLanguageMultiLineComments"); return overriddenList[langId]; } @@ -381,7 +414,7 @@ export class Configuration { } }); - const multiLineStyleBlocksLangs = this.getConfiguration().get("multiLineStyleBlocks"); + const multiLineStyleBlocksLangs = this.getConfigurationValue("multiLineStyleBlocks"); for (let langId of multiLineStyleBlocksLangs) { if (langId && langId.length > 0 && !langArray.includes(langId)) { @@ -432,7 +465,7 @@ export class Configuration { }); // Get user-customized langIds for the //-style and add to the map. - let customSlashLangs = this.getConfiguration().get("slashStyleBlocks"); + let customSlashLangs = this.getConfigurationValue("slashStyleBlocks"); for (let langId of customSlashLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, "//"); @@ -440,7 +473,7 @@ export class Configuration { } // Get user-customized langIds for the #-style and add to the map. - let customHashLangs = this.getConfiguration().get("hashStyleBlocks"); + let customHashLangs = this.getConfigurationValue("hashStyleBlocks"); for (let langId of customHashLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, "#"); @@ -448,7 +481,7 @@ export class Configuration { } // Get user-customized langIds for the ;-style and add to the map. - let customSemicolonLangs = this.getConfiguration().get("semicolonStyleBlocks"); + let customSemicolonLangs = this.getConfigurationValue("semicolonStyleBlocks"); for (let langId of customSemicolonLangs) { if (langId && langId.length > 0) { this.singleLineBlocksMap.set(langId, ";"); @@ -513,11 +546,11 @@ export class Configuration { * Get the user settings/configuration and set the blade or html comments accordingly. */ if (langId === "blade") { - langConfig.comments.blockComment = this.setBladeComments(this.getConfiguration().get("bladeOverrideComments"), true); + langConfig.comments.blockComment = this.setBladeComments(this.getConfigurationValue("bladeOverrideComments"), true); } } - let isOnEnter = this.getConfiguration().get("singleLineBlockOnEnter"); + let isOnEnter = this.getConfigurationValue("singleLineBlockOnEnter"); if (isOnEnter && singleLineStyle) { if (singleLineStyle === "//") { @@ -626,7 +659,7 @@ export class Configuration { } var indentedNewLine = "\n" + line.text.substring(0, line.text.search(indentRegex)); - let isOnEnter = this.getConfiguration().get("singleLineBlockOnEnter"); + let isOnEnter = this.getConfigurationValue("singleLineBlockOnEnter"); if (!isOnEnter) { indentedNewLine += style + " "; } @@ -647,21 +680,18 @@ export class Configuration { // Only carry out function if languageId is blade. if (langId === "blade" && !this.isLangIdDisabled(langId)) { - let config = this.getConfiguration(); // Read current value - let isOverridden = config.get("bladeOverrideComments"); + let isOverridden = this.getConfigurationValue("bladeOverrideComments"); if (isOverridden === false) { - // Update to true, globally - // [command, new value, global] - config.update("bladeOverrideComments", true, true); + // Update to true + this.updateConfigurationValue("bladeOverrideComments", true); } else { - // Update to false, globally - // [command, new value, global] - config.update("bladeOverrideComments", false, true); + // Update to false + this.updateConfigurationValue("bladeOverrideComments", false); } // Read new value - let bladeOverrideComments = config.get("bladeOverrideComments"); + let bladeOverrideComments = this.getConfigurationValue("bladeOverrideComments"); // Set the comments for blade language. this.setBladeComments(bladeOverrideComments); diff --git a/src/extension.ts b/src/extension.ts index 2caee1e..4ec4e68 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,7 +19,7 @@ export function activate(context: vscode.ExtensionContext) { const extensionName = extensionNames.name; const extensionDisplayName = extensionNames.displayName; - let disabledLangConfig: string[] = configuration.getConfiguration().get("disabledLanguages"); + let disabledLangConfig: string[] = configuration.getConfigurationValue("disabledLanguages"); if (disabledLangConfig.length > 0) { vscode.window.showInformationMessage(`${disabledLangConfig.join(", ")} languages are disabled for ${extensionDisplayName}.`); @@ -36,7 +36,7 @@ export function activate(context: vscode.ExtensionContext) { // If the affected setting is bladeOverrideComments... if (event.affectsConfiguration(`${extensionName}.bladeOverrideComments`)) { // Get the setting. - let bladeOverrideComments: boolean = configuration.getConfiguration().get("bladeOverrideComments"); + let bladeOverrideComments: boolean = configuration.getConfigurationValue("bladeOverrideComments"); configuration.setBladeComments(bladeOverrideComments); From 30de00ad87fda5864ffb2339aa7e1a213d5e40b0 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Tue, 10 Dec 2024 20:58:24 +0000 Subject: [PATCH 15/27] fix: certain langConfig property values from preventing activating the extension, and more. Fix: - The `for...of` loops in `configureCommentBlocks` method to use the `singleLineLangs` variable which uses the `getSingleLineLanguages` method instead of directly using the property `singleLineBlocksMap`. - The single line languages `for...of` loop to only setup the config for the langId if it's not currently set as disabled in the user config settings, using the `isLangIdDisabled` method to check. - The merging of onEnterRules for single-line comments. When a language config doesn't have the `onEnterRules` key and the user config setting `singleLineBlockOnEnter` is true, previously the extension couldn't be activated due to the error: > Cannot read properties of undefined (reading 'concat') because the key is undefined. Fixed by using the chaining operator (?.) before trying to access the array method `concat`. If the key exists then concat still works and combines the new rules with the internal config rules. If key is undefined then by using the nullish coalescing operator (??) we just assign the new rules since there's no rules to combine with. - When a config has the `wordPattern` key with a regex pattern as a string, the extension can't activate due to the error: > TypeError: e.exec is not a function It's unknown why the allowed regex as string causes this, there seems to be a similar, related issue in https://github.com/microsoft/vscode/issues/171194 but was closed as (wrongly?) an invalid issue. Fixed by changing the string to an actual regex pattern. But because `wordPattern` can also be an object with a key of `pattern` then we also need to change this and add the regex pattern directly as the value of `wordPattern` instead of an object. - The extension only ran on opening a document, but we need it to run everytime the current editor changes or the current language changes. Fixed to use the on change event `onDidChangeTextDocument` instead. Removed: - Remove the unnecessary check for the length of landId is more than 0 in `setMultiLineCommentLanguageDefinitions` method, because just the first part of that conditional also checks for not NULL or empty strings, so the extra check is redundant. Added: - The return type of `getExtensionNames` method, now as an object with `id`, `name`, and `displayName` keys, so TS isn't guessing at compile time. - Code comments - The execution of changing the blockComment style when it's been overridden for that langId in the user config settings. --- src/configuration.ts | 84 ++++++++++++++++++++++++++++++++++++-------- src/extension.ts | 2 +- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 8b10e81..637ace1 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -65,7 +65,7 @@ export class Configuration { * @param {vscode.ExtensionContext} context The context of the extension. * @returns {vscode.Disposable[]} */ - configureCommentBlocks(context: vscode.ExtensionContext) { + public configureCommentBlocks(context: vscode.ExtensionContext) { const disposables: vscode.Disposable[] = []; // Set language configurations @@ -73,18 +73,20 @@ export class Configuration { const multiLineLangs = this.getMultiLineLanguages(); // Setup the single line languages. - for (let [langId, style] of this.singleLineBlocksMap) { - // Set a bool if the single line language also supports multi line comments - // (ie. the single line language is also present in the multi line map); - let multiLine = multiLineLangs.includes(langId); - disposables.push(this.setLanguageConfiguration(langId, multiLine, style)); + for (let [langId, style] of singleLineLangs) { + if (!this.isLangIdDisabled(langId)) { + // Set a bool if the single line language also supports multi line comments + // (ie. the single line language is also present in the multi line map); + let multiLine = multiLineLangs.includes(langId); + disposables.push(this.setLanguageConfiguration(langId, multiLine, style)); + } } // Setup the multi line languages. for (let langId of multiLineLangs) { // If singleLineLangs doesn't have the langId, AND // the langId isn't set as disabled... - if (!this.singleLineBlocksMap.has(langId) && !this.isLangIdDisabled(langId)) { + if (!singleLineLangs.has(langId) && !this.isLangIdDisabled(langId)) { disposables.push(this.setLanguageConfiguration(langId, true)); } } @@ -153,7 +155,7 @@ export class Configuration { * * @returns {object} An object containing the extension id, name, and display name. */ - public getExtensionNames() { + public getExtensionNames(): {id: string; name: string; displayName: string} { const packageJSON = JSON.parse(fs.readFileSync(__dirname + "./../../package.json").toString()); const displayName: string = packageJSON.displayName; @@ -417,7 +419,10 @@ export class Configuration { const multiLineStyleBlocksLangs = this.getConfigurationValue("multiLineStyleBlocks"); for (let langId of multiLineStyleBlocksLangs) { - if (langId && langId.length > 0 && !langArray.includes(langId)) { + // If langId is exists (ie. not NULL or empty string) AND + // the array doesn't already include langId, + // then add it to the array. + if (langId && !langArray.includes(langId)) { langArray.push(langId); } } @@ -532,7 +537,6 @@ export class Configuration { private setLanguageConfiguration(langId: string, multiLine?: boolean, singleLineStyle?: string): vscode.Disposable { const internalLangConfig: vscode.LanguageConfiguration = this.getLanguageConfig(langId); const defaultMultiLineConfig: any = this.readJsonFile(`${__dirname}/../../config/default-multi-line-config.json`); - console.log(typeof defaultMultiLineConfig); let langConfig = {...internalLangConfig}; @@ -542,6 +546,12 @@ export class Configuration { // Add the multi-line onEnter rules to the langConfig. langConfig.onEnterRules = this.mergeConfigOnEnterRules(Rules.multilineEnterRules, internalLangConfig); + // If the default multi-line comments has been overridden for the langId, + // add the overridden multi-line comments to the langConfig. + if (this.isLangIdMultiLineCommentOverridden(langId)) { + langConfig.comments.blockComment[0] = this.getOverriddenMultiLineComment(langId); + } + /** * Get the user settings/configuration and set the blade or html comments accordingly. */ @@ -552,13 +562,57 @@ export class Configuration { let isOnEnter = this.getConfigurationValue("singleLineBlockOnEnter"); + // Add the single line onEnter rules to the langConfig. if (isOnEnter && singleLineStyle) { + // //-style comments if (singleLineStyle === "//") { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.slashEnterRules); - } else if (singleLineStyle === "#") { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.hashEnterRules); - } else if (singleLineStyle === ";") { - langConfig.onEnterRules = langConfig.onEnterRules.concat(Rules.semicolonEnterRules); + // Make sure that langConfig has the key onEnterRules with the optional + // chaining operator (?.) before trying to access the array method concat(). + // If it does exist, concat (combine) the new rules with the langConfig rules. + // If it's undefined (doesn't exist), then using the nullish coalescing + // operator (??) just assign the new rules. + const rules = langConfig.onEnterRules?.concat(Rules.slashEnterRules) ?? Rules.slashEnterRules; + + // Set the rules. + langConfig.onEnterRules = rules; + } + // #-style comments + else if (singleLineStyle === "#") { + const rules = langConfig.onEnterRules?.concat(Rules.hashEnterRules) ?? Rules.hashEnterRules; + + // Set the rules. + langConfig.onEnterRules = rules; + } + // ;-style comments + else if (singleLineStyle === ";") { + const rules = langConfig.onEnterRules?.concat(Rules.semicolonEnterRules) ?? Rules.semicolonEnterRules; + + // Set the rules. + langConfig.onEnterRules = rules; + } + } + + // Make sure wordPattern is in RegExp form instead of a string, otherwise vscode errors out: + // > TypeError: e.exec is not a function + // + // The extension won't activate when there's a wordPattern key with a string regex in the config when using `setLanguageConfiguration()`. + // + // It's unknown why the allowed regex as string causes this, there seems to be a similar, related issue in https://github.com/microsoft/vscode/issues/171194 but was closed as (wrongly?) an invalid issue. + // + // So we're just changing the string to an actual regex pattern. + + // If langConfig has wordPattern key... + if (Object.hasOwn(langConfig, "wordPattern")) { + // If wordPattern has pattern key, then it's an object... + if (Object.hasOwn(langConfig.wordPattern, "pattern")) { + // @ts-ignore: error TS2339: Property 'pattern' does not exist on type 'RegExp'. + // Ignoring the next line of code because wordPattern can also be an object with + // pattern as a key, eg. wordPattern: {pattern: ""} + langConfig.wordPattern = new RegExp(langConfig.wordPattern.pattern); + } + // Otherwise it's a string. + else { + langConfig.wordPattern = new RegExp(langConfig.wordPattern); } } diff --git a/src/extension.ts b/src/extension.ts index 4ec4e68..55707cc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -79,7 +79,7 @@ export function activate(context: vscode.ExtensionContext) { }); // Called when active editor language is changed, so re-configure the comment blocks. - vscode.workspace.onDidOpenTextDocument(() => { + vscode.workspace.onDidChangeTextDocument(() => { const configureCommentBlocksDisposable = configuration.configureCommentBlocks(context); disposables.push(...configureCommentBlocksDisposable); }); From c07c00613e1af2c05420d8264fc3b77a5bcb25c7 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Tue, 17 Dec 2024 19:56:34 +0000 Subject: [PATCH 16/27] build: update dependencies and change activation event to `onLanguage`. --- package.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 204dcb8..81290e3 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,7 @@ "Other" ], "activationEvents": [ - "*", - "onCommand:auto-comment-blocks.singleLineBlock" + "onLanguage" ], "main": "./out/src/extension.js", "contributes": { @@ -104,9 +103,9 @@ "devDependencies": { "@types/mocha": "^10.0.9", "@types/node": "^22.9.0", - "@types/vscode": "^1.95.0", + "@types/vscode": "^1.96", "mocha": "^10.8.2", - "typescript": "^5.6.3" + "typescript": "^5.7" }, "dependencies": { "jsonc-parser": "^3.3.1" From 08a07e1e95567d6df032ece56fc677ff29ef7de8 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 19 Dec 2024 20:19:00 +0000 Subject: [PATCH 17/27] refactor: change language configuration definition format Change: - The format of the language definitions to separate user-defined languages from the auto-supported languages. (added keys `supportedLanguages` and `customSupportedLanguages` to both multi-line and single-line definitions.) - `singleLineBlocksMap` property type to accept a nested Map. - `getMultiLineLanguages` and `getSingleLineLanguages` methods to accept a stringed key parameter and return the value of that key from the Map. Also changed all references to utilise the new key parameter. - `setMultiLineCommentLanguageDefinitions` and `setSingleLineCommentLanguageDefinitions` methods to set both auto-supported and custom-supported languages into the correct key. - `writeCommentLanguageDefinitionsToJsonFile` method to only be called once per activation, in the class constructor. (Removed the calls in `setMultiLineCommentLanguageDefinitions` and `setSingleLineCommentLanguageDefinitions` methods.) - `handleSingleLineBlock` to use the `getSingleLineLanguages` method instead of the actual property. Also added the customSupportedLangs to it. Removed: - `reverseMapping` function in `writeCommentLanguageDefinitionsToJsonFile` in favour of the new `convertMapToReversedObject` method. Added: - New `convertMapToReversedObject` method to convert the `singleLineBlocksMap` to an object while also reversing the keys and values of the nested map into an key : array pair, where the key is the original value, and an array of the original keys. - The `defaultMultiLineConfig` comments to the `langConfig` only if the comments key doesn't exist. Necessary for custom-supported languages to properly have block comment support. - The `lineComment` to the `langConfig` comments only if it doesn't exist. - Implementation to setup the custom supported languages to `configureCommentBlocks` method. - Various code comments and TODOs and FIXMEs. - User information messages if the `multiLineStyleBlocks`, `slashStyleBlocks`, `hashStyleBlocks` or `semicolonStyleBlocks` settings change, and prompt the user to reload the extension. --- .../multi-line-languages.json | 9 +- .../single-line-languages.json | 122 ++++++----- src/configuration.ts | 205 ++++++++++++++---- src/extension.ts | 66 ++++++ 4 files changed, 297 insertions(+), 105 deletions(-) diff --git a/auto-generated-language-definitions/multi-line-languages.json b/auto-generated-language-definitions/multi-line-languages.json index 56918c5..1e690d9 100644 --- a/auto-generated-language-definitions/multi-line-languages.json +++ b/auto-generated-language-definitions/multi-line-languages.json @@ -1,6 +1,5 @@ { - "languages": [ - "blade", + "supportedLanguages": [ "c", "cpp", "cpp_embedded_latex", @@ -11,7 +10,6 @@ "go", "groovy", "hlsl", - "html", "java", "javascript", "javascriptreact", @@ -22,7 +20,6 @@ "objective-c", "objective-cpp", "php", - "proto3", "rust", "sass", "scss", @@ -32,5 +29,9 @@ "swift", "typescript", "typescriptreact" + ], + "customSupportedLanguages": [ + "blade", + "html" ] } \ No newline at end of file diff --git a/auto-generated-language-definitions/single-line-languages.json b/auto-generated-language-definitions/single-line-languages.json index 684c86d..9f6a72c 100644 --- a/auto-generated-language-definitions/single-line-languages.json +++ b/auto-generated-language-definitions/single-line-languages.json @@ -1,61 +1,65 @@ { - "#": [ - "apacheconf", - "coffeescript", - "diff", - "dockercompose", - "dockerfile", - "dotenv", - "editorconfig", - "git-commit", - "git-rebase", - "github-actions-workflow", - "http", - "ignore", - "julia", - "makefile", - "nginx", - "perl", - "powershell", - "python", - "r", - "raku", - "ruby", - "shellscript", - "yaml" - ], - "//": [ - "c", - "cpp", - "cpp_embedded_latex", - "csharp", - "cuda-cpp", - "dart", - "fsharp", - "go", - "groovy", - "hlsl", - "java", - "javascript", - "javascriptreact", - "json", - "jsonc", - "jsonl", - "less", - "objective-c", - "objective-cpp", - "php", - "rust", - "sass", - "scss", - "shaderlab", - "snippets", - "swift", - "typescript", - "typescriptreact" - ], - ";": [ - "clojure", - "ini" - ] + "supportedLanguages": { + "#": [ + "apacheconf", + "coffeescript", + "diff", + "dockercompose", + "dockerfile", + "dotenv", + "editorconfig", + "git-commit", + "git-rebase", + "github-actions-workflow", + "http", + "ignore", + "julia", + "makefile", + "nginx", + "perl", + "powershell", + "python", + "r", + "raku", + "ruby", + "shellscript", + "toml", + "yaml" + ], + "//": [ + "c", + "cpp", + "cpp_embedded_latex", + "csharp", + "cuda-cpp", + "dart", + "fsharp", + "go", + "groovy", + "hlsl", + "java", + "javascript", + "javascriptreact", + "json", + "jsonc", + "jsonl", + "less", + "objective-c", + "objective-cpp", + "php", + "rust", + "sass", + "scss", + "shaderlab", + "snippets", + "swift", + "typescript", + "typescriptreact" + ], + ";": [ + "clojure", + "ini" + ] + }, + "customSupportedLanguages": {} } \ No newline at end of file diff --git a/src/configuration.ts b/src/configuration.ts index 637ace1..c507aa4 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -29,7 +29,7 @@ export class Configuration { * @property {string} key Language ID. * @property {string} value Style of line comment. */ - private singleLineBlocksMap: Map = new Map(); + private singleLineBlocksMap: Map> = new Map(); /** * A Map object of an array of supported language IDs for multi line block comments. @@ -57,6 +57,7 @@ export class Configuration { console.log(this.multiLineBlocksMap); this.setSingleLineCommentLanguageDefinitions(); console.log(this.singleLineBlocksMap); + this.writeCommentLanguageDefinitionsToJsonFile(); } /** @@ -68,11 +69,14 @@ export class Configuration { public configureCommentBlocks(context: vscode.ExtensionContext) { const disposables: vscode.Disposable[] = []; - // Set language configurations - const singleLineLangs = this.getSingleLineLanguages(); - const multiLineLangs = this.getMultiLineLanguages(); + /** + * Auto-supported languages. + */ + + const singleLineLangs = this.getSingleLineLanguages("supportedLanguages"); + const multiLineLangs = this.getMultiLineLanguages("supportedLanguages"); - // Setup the single line languages. + // Setup the auto-supported single line languages. for (let [langId, style] of singleLineLangs) { if (!this.isLangIdDisabled(langId)) { // Set a bool if the single line language also supports multi line comments @@ -82,7 +86,7 @@ export class Configuration { } } - // Setup the multi line languages. + // Setup the auto-supported multi-line languages. for (let langId of multiLineLangs) { // If singleLineLangs doesn't have the langId, AND // the langId isn't set as disabled... @@ -91,6 +95,29 @@ export class Configuration { } } + /** + * Custom-supported (unsupported) languages + */ + + const customMultiLineLangs = this.getMultiLineLanguages("customSupportedLanguages"); + const customSingleLineLangs = this.getSingleLineLanguages("customSupportedLanguages"); + + // Setup the custom-supported single-line languages, that are otherwise unsupported. + for (let [langId, style] of customSingleLineLangs) { + // Set a bool if the single line language also supports multi line comments + // (ie. the single line language is also present in the multi line map); + let multiLine = customMultiLineLangs.includes(langId); + disposables.push(this.setLanguageConfiguration(langId, multiLine, style)); + } + + // Setup the custom-supported multi-line languages, that are otherwise unsupported. + for (let langId of customMultiLineLangs) { + // If customSingleLineLangs doesn't have the langId + if (!customSingleLineLangs.has(langId)) { + disposables.push(this.setLanguageConfiguration(langId, true)); + } + } + return disposables; } @@ -379,19 +406,21 @@ export class Configuration { /** * Get the multi-line languages from the Map. * + * @param {"supportedLanguages" | "customSupportedLanguages"} key A stringed key, either `"supportedLanguages"` or `"customSupportedLanguages"` * @returns {string[]} An array of language ID strings. */ - private getMultiLineLanguages(): string[] { - return this.multiLineBlocksMap.get("languages"); + private getMultiLineLanguages(key: "supportedLanguages" | "customSupportedLanguages"): string[] { + return this.multiLineBlocksMap.get(key); } /** * Get the single-line languages and styles. * + * @param {"supportedLanguages" | "customSupportedLanguages"} key A stringed key, either `"supportedLanguages"` or `"customSupportedLanguages"` * @returns {Map} The Map of the languages and styles. */ - private getSingleLineLanguages(): Map { - return this.singleLineBlocksMap; + private getSingleLineLanguages(key: "supportedLanguages" | "customSupportedLanguages"): Map { + return this.singleLineBlocksMap.get(key); } /** @@ -416,8 +445,14 @@ export class Configuration { } }); + // Set the supportedLanguages array into the multiLineBlockMap, sorted in ascending order, + // for sanity reasons. + this.multiLineBlocksMap.set("supportedLanguages", langArray.sort()); + const multiLineStyleBlocksLangs = this.getConfigurationValue("multiLineStyleBlocks"); + // Empty the langArray to reuse it. + langArray = []; for (let langId of multiLineStyleBlocksLangs) { // If langId is exists (ie. not NULL or empty string) AND // the array doesn't already include langId, @@ -426,12 +461,9 @@ export class Configuration { langArray.push(langId); } } - - // Set the language array into the multiLineBlockMap, sorted in ascending order, - // for sanity reasons. - this.multiLineBlocksMap.set("languages", langArray.sort()); - - this.writeCommentLanguageDefinitionsToJsonFile(); + // Set the customSupportedLanguages array into the multiLineBlockMap, + // sorted in ascending order, for sanity reasons. + this.multiLineBlocksMap.set("customSupportedLanguages", langArray.sort()); } /** @@ -439,7 +471,7 @@ export class Configuration { */ private setSingleLineCommentLanguageDefinitions() { let style: string; - + const tempMap: Map = new Map(); this.languageConfigs.forEach((config: any, langId: string) => { // console.log(langId, config.comments.lineComment); let style: string = ""; @@ -464,16 +496,23 @@ export class Configuration { // comment like bat's @rem)... if (style != "") { // Set the langId and it's style into the Map. - this.singleLineBlocksMap.set(langId, style); + tempMap.set(langId, style); } } }); + // Set the supportedLanguages tempMap into the singleLineBlocksMap, + // sorted in ascending order, for sanity reasons. + this.singleLineBlocksMap.set("supportedLanguages", new Map([...tempMap].sort())); + + // Empty the tempMap to reuse it. + tempMap.clear(); + // Get user-customized langIds for the //-style and add to the map. let customSlashLangs = this.getConfigurationValue("slashStyleBlocks"); for (let langId of customSlashLangs) { if (langId && langId.length > 0) { - this.singleLineBlocksMap.set(langId, "//"); + tempMap.set(langId, "//"); } } @@ -481,7 +520,7 @@ export class Configuration { let customHashLangs = this.getConfigurationValue("hashStyleBlocks"); for (let langId of customHashLangs) { if (langId && langId.length > 0) { - this.singleLineBlocksMap.set(langId, "#"); + tempMap.set(langId, "#"); } } @@ -489,15 +528,13 @@ export class Configuration { let customSemicolonLangs = this.getConfigurationValue("semicolonStyleBlocks"); for (let langId of customSemicolonLangs) { if (langId && langId.length > 0) { - this.singleLineBlocksMap.set(langId, ";"); + tempMap.set(langId, ";"); } } - // Set the singleLineBlockMap to a new map with all the languages sorted in ascending order, - // for sanity reasons. - this.singleLineBlocksMap = new Map([...this.singleLineBlocksMap].sort()); - - this.writeCommentLanguageDefinitionsToJsonFile(); + // Set the customSupportedLanguages tempMap into the singleLineBlocksMap, + // sorted in ascending order, for sanity reasons. + this.singleLineBlocksMap.set("customSupportedLanguages", new Map([...tempMap].sort())); } /** @@ -505,22 +542,8 @@ export class Configuration { * either multi-line-languages.json, or single-line-languages.json. */ private writeCommentLanguageDefinitionsToJsonFile() { - // Convert a key:value Map into an key:array object, while reversing/switching the - // keys and values. The Map's values are now the keys of the object and the Map's keys - // are now added as the values of the array. - // e.g. From `Map {apacheconf => #, c => //, clojure => ;, coffeescript => #, cpp => //, …}` - // to `{"#": ["apacheconf", "coffeescript", ...], "//": ["c", "cpp", ...], - // ";": ["clojure", ...]}` - // - // Code from this StackOverflow answer https://stackoverflow.com/a/45728850/2358222 - const reverseMapping = (m: Map): object => { - const o = Object.fromEntries(m); - - return Object.keys(o).reduce((r, k) => Object.assign(r, {[o[k]]: (r[o[k]] || []).concat(k)}), {}); - }; - // Write the into the single-line-languages.json file. - this.writeJsonFile(this.singleLineLangDefinitionFilePath, reverseMapping(this.singleLineBlocksMap)); + this.writeJsonFile(this.singleLineLangDefinitionFilePath, this.convertMapToReversedObject(this.singleLineBlocksMap)); // Write the into the multi-line-languages.json file. this.writeJsonFile(this.multiLineLangDefinitionFilePath, Object.fromEntries(this.multiLineBlocksMap)); } @@ -546,6 +569,10 @@ export class Configuration { // Add the multi-line onEnter rules to the langConfig. langConfig.onEnterRules = this.mergeConfigOnEnterRules(Rules.multilineEnterRules, internalLangConfig); + // Only assign the default config comments if it doesn't already exist. + // (nullish assignment operator ??=) + langConfig.comments ??= defaultMultiLineConfig.comments; + // If the default multi-line comments has been overridden for the langId, // add the overridden multi-line comments to the langConfig. if (this.isLangIdMultiLineCommentOverridden(langId)) { @@ -560,9 +587,12 @@ export class Configuration { } } + // FIXME: onEnterRules do not work in any language. let isOnEnter = this.getConfigurationValue("singleLineBlockOnEnter"); // Add the single line onEnter rules to the langConfig. + // + // If isOnEnter is true AND singleLineStyle isn't false, i.e. a string. if (isOnEnter && singleLineStyle) { // //-style comments if (singleLineStyle === "//") { @@ -591,6 +621,16 @@ export class Configuration { langConfig.onEnterRules = rules; } } + // If isOnEnter is false AND singleLineStyle isn't false, i.e. a string. + else if (!isOnEnter && singleLineStyle) { + // If langConfig does NOT have a comments key OR + // the comments key exists but does NOT have the lineComment key... + if (!Object.hasOwn(langConfig, "comments") || !Object.hasOwn(langConfig.comments, "lineComment")) { + // Add the singleLineStyle to the lineComments key and make sure any + // blockComments aren't overwritten. + langConfig.comments = {...langConfig.comments, lineComment: singleLineStyle}; + } + } // Make sure wordPattern is in RegExp form instead of a string, otherwise vscode errors out: // > TypeError: e.exec is not a function @@ -627,6 +667,8 @@ export class Configuration { * @param {any} defaultLangConfig Default multi-line comments config. * @param {vscode.LanguageConfiguration} internalLangConfig Internal language config from vscode extensions. * @returns {vscode.AutoClosingPair[]} + * + * TODO: combine this method and mergeConfigOnEnterRules into one method. */ private mergeConfigAutoClosingPairs(defaultLangConfig, internalLangConfig: vscode.LanguageConfiguration) { const defaultAutoClosing = defaultLangConfig.autoClosingPairs; @@ -654,6 +696,8 @@ export class Configuration { * @param {any} defaultOnEnterRules Default onEnterRules. * @param {vscode.LanguageConfiguration} internalLangConfig Internal language config from vscode extensions. * @returns {vscode.OnEnterRule[]} + * + * TODO: combine this method and mergeConfigAutoClosingPairs into one method. */ private mergeConfigOnEnterRules(defaultOnEnterRules, internalLangConfig) { const internalOnEnterRules = internalLangConfig?.onEnterRules ?? []; @@ -674,6 +718,77 @@ export class Configuration { return merged; } + /** + * Convert a Map to an object with it's inner Map's keys and values reversed/switched. + * + * Code based on this StackOverflow answer https://stackoverflow.com/a/45728850/2358222 + * + * @param {Map>} m The Map to convert to an object. + * @returns {object} The converted object. + * + * @example + * reverseMapping( + * Map { + * "supportedLanguages" => Map { + * "apacheconf" => "#", + * "c" => "//", + * "clojure" => ";", + * "coffeescript" => "#", + * "cpp" => "//", + * … + * } + * } + * ); + * + * // Converts to: + * + * { + * "supportedLanguages" => { + * "#": [ + * "apacheconf", + * "coffeescript", + * ... + * ], + * "//": [ + * "c", + * "cpp", + * ... + * ], + * ";": [ + * "clojure", + * ... + * ] + * } + * } + */ + private convertMapToReversedObject(m: Map>): object { + const result: any = {}; + + // Convert a nested key:value Map from inside another Map into an key:array object, + // while reversing/switching the keys and values. The Map's values are now the keys of + // the object and the Map's keys are now added as the values of the array. The reversed + // object is added to the key of the outerMap. + + // Loop through the outer Map... + for (const [key, innerMap] of m.entries()) { + // Convert the inner Map to an object + const o = Object.fromEntries(innerMap); + + // Reverse the inner object mapping. + // + // Loop through the object (o) keys, assigns a new object (r) with the value of the + // object key (k) as the new key (eg. "//") and the new value is an array of all + // the original object keys (o[k]) (eg. "php"). + // If the key (o[k]) already exists in the new object (r), then just add the + // original key to the array, otherwise start a new array ([]) with the original + // key as value ( (r[o[k]] || []).concat(k) ). + // Add this new reversed object to the result object with the outer map key + // as the key. + result[key] = Object.keys(o).reduce((r, k) => Object.assign(r, {[o[k]]: (r[o[k]] || []).concat(k)}), {}); + } + return result; + } + /** * The keyboard binding event handler for the single line blocks on shift+enter. * @@ -682,7 +797,13 @@ export class Configuration { */ private handleSingleLineBlock(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) { let langId = textEditor.document.languageId; - var style = this.singleLineBlocksMap.get(langId); + const singleLineLangs = this.getSingleLineLanguages("supportedLanguages"); + const customSingleLineLangs = this.getSingleLineLanguages("customSupportedLanguages"); + + // Get the langId from the auto-supported langs. If it doesn't exist, try getting it from + // the custom-supported langs instead. + var style = singleLineLangs.get(langId) ?? customSingleLineLangs.get(langId); + if (style && textEditor.selection.isEmpty) { let line = textEditor.document.lineAt(textEditor.selection.active); let isCommentLine = true; diff --git a/src/extension.ts b/src/extension.ts index 55707cc..162a80e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -30,6 +30,8 @@ export function activate(context: vscode.ExtensionContext) { * to reflect the settings and output a message to the user. */ vscode.workspace.onDidChangeConfiguration((event: any) => { + // TODO: Work on automatically updating the languages instead of making the user reload the extension. + /** * Blade Override Comments */ @@ -76,6 +78,70 @@ export function activate(context: vscode.ExtensionContext) { } }); } + + /** + * Multi-line style Block Comments + */ + if (event.affectsConfiguration(`${extensionName}.multiLineStyleBlocks`)) { + vscode.window + .showInformationMessage( + `The ${extensionName}.multiLineStyleBlocks setting has been changed. Please reload the Extension Host to take effect.`, + "Reload" + ) + .then((selection) => { + if (selection === "Reload") { + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + } + }); + } + + /** + * //-style single-line comments + */ + if (event.affectsConfiguration(`${extensionName}.slashStyleBlocks`)) { + vscode.window + .showInformationMessage( + `The ${extensionName}.slashStyleBlocks setting has been changed. Please reload the Extension Host to take effect.`, + "Reload" + ) + .then((selection) => { + if (selection === "Reload") { + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + } + }); + } + + /** + * #-style single-line comments + */ + if (event.affectsConfiguration(`${extensionName}.hashStyleBlocks`)) { + vscode.window + .showInformationMessage( + `The ${extensionName}.hashStyleBlocks setting has been changed. Please reload the Extension Host to take effect.`, + "Reload" + ) + .then((selection) => { + if (selection === "Reload") { + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + } + }); + } + + /** + * ;-style single-line comments + */ + if (event.affectsConfiguration(`${extensionName}.semicolonStyleBlocks`)) { + vscode.window + .showInformationMessage( + `The ${extensionName}.semicolonStyleBlocks setting has been changed. Please reload the Extension Host to take effect.`, + "Reload" + ) + .then((selection) => { + if (selection === "Reload") { + vscode.commands.executeCommand("workbench.action.restartExtensionHost"); + } + }); + } }); // Called when active editor language is changed, so re-configure the comment blocks. From 4dd59000fa46889e4a65740f8a80227b0207d8cd Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 19 Dec 2024 20:28:43 +0000 Subject: [PATCH 18/27] fix: revert the `onDidChangeTextDocument` back to `onDidOpenTextDocument` In commit 30de00a, the `onDidOpenTextDocument` workspace event in `extension.ts` was changed to `onDidChangeTextDocument`, with the assumption that the former only ran the function when opening a document. However, this is not the case. It runs when a document is opened OR when the language ID has been changed. It's fully described in https://github.com/microsoft/vscode/blob/4e8fbaef741afebd24684b88cac47c2f44dfb8eb/src/vscode-dts/vscode.d.ts#L13716-L13728 This also fixes the issue of running the extension on every document change, even if it's not a comment, which would eventually cause performance issues. --- src/extension.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index 162a80e..27d8208 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -144,8 +144,12 @@ export function activate(context: vscode.ExtensionContext) { } }); + // An event that is emitted when a text document is opened or when the + // language id of a text document has been changed. As described in + // https://github.com/microsoft/vscode/blob/4e8fbaef741afebd24684b88cac47c2f44dfb8eb/src/vscode-dts/vscode.d.ts#L13716-L13728 + // Called when active editor language is changed, so re-configure the comment blocks. - vscode.workspace.onDidChangeTextDocument(() => { + vscode.workspace.onDidOpenTextDocument(() => { const configureCommentBlocksDisposable = configuration.configureCommentBlocks(context); disposables.push(...configureCommentBlocksDisposable); }); From 9d15fd636ea36584d258948e57ba9d3adeb2b5c8 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 19 Dec 2024 21:16:40 +0000 Subject: [PATCH 19/27] refactor: combined `mergeConfigAutoClosingPairs` and `mergeConfigOnEnterRules` methods... ...into one to make the new `mergeConfig` method, and updated the references to use it. --- src/configuration.ts | 81 ++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index c507aa4..aeb07a0 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -564,10 +564,13 @@ export class Configuration { let langConfig = {...internalLangConfig}; if (multiLine) { - langConfig.autoClosingPairs = this.mergeConfigAutoClosingPairs(defaultMultiLineConfig, internalLangConfig); + const mergedConfig = this.mergeConfig(defaultMultiLineConfig.autoClosingPairs, Rules.multilineEnterRules, internalLangConfig); + + langConfig.autoClosingPairs = mergedConfig.mergedAutoClosingPairs; // Add the multi-line onEnter rules to the langConfig. - langConfig.onEnterRules = this.mergeConfigOnEnterRules(Rules.multilineEnterRules, internalLangConfig); + langConfig.onEnterRules = mergedConfig.mergedOnEnterRules; + console.log(mergedConfig); // Only assign the default config comments if it doesn't already exist. // (nullish assignment operator ??=) @@ -663,59 +666,57 @@ export class Configuration { /** * Merge the internal config AutoClosingPairs with the default config, removing any duplicates. + * And Merge the internal config onEnterRules with the default rules, removing any duplicates. * * @param {any} defaultLangConfig Default multi-line comments config. * @param {vscode.LanguageConfiguration} internalLangConfig Internal language config from vscode extensions. - * @returns {vscode.AutoClosingPair[]} - * - * TODO: combine this method and mergeConfigOnEnterRules into one method. + * @returns {{mergedOnEnterRules: any[]; mergedAutoClosingPairs: vscode.AutoClosingPair[]}} An object with the merged onEnterRules and autoClosingPairs arrays. */ - private mergeConfigAutoClosingPairs(defaultLangConfig, internalLangConfig: vscode.LanguageConfiguration) { - const defaultAutoClosing = defaultLangConfig.autoClosingPairs; + private mergeConfig( + defaultAutoClosingPairs, + defaultOnEnterRules, + internalLangConfig: vscode.LanguageConfiguration + ): {mergedOnEnterRules: any[]; mergedAutoClosingPairs: vscode.AutoClosingPair[]} { + // Get the internal config properties or define an empty array. const internalAutoClosing = internalLangConfig?.autoClosingPairs ?? []; + const internalOnEnterRules = internalLangConfig?.onEnterRules ?? []; - // Code based on "2023 update" portion of this StackOverflow answer: - // https://stackoverflow.com/a/1584377/2358222 - - // Copy to avoid side effects. - const merged = [...internalAutoClosing]; - // Loop over the defaultLangConfig autoClosingPairs array... - defaultAutoClosing.forEach((item) => { + /** + * Merge the arrays and remove any duplicates. + * + * Code based on "2023 update" portion of this StackOverflow answer: + * https://stackoverflow.com/a/1584377/2358222 + * + * @param {string} key The key to check against for preventing duplicates. + * @param item The current item in the loop. + * @param merged The array to merge into. + */ + const merge = (key: string, item: any, merged: any) => { // Test all items in the merged array, and if the defaultAutoClosing item's // opening comment string (item.open) is not already present in one of the // merged array's objects then add the item to the merged array. - merged.some((mergedItem) => item.open === mergedItem.open) ? null : merged.push(item); - }); + merged.some((mergedItem) => item[key] === mergedItem[key]) ? null : merged.push(item); + }; - return merged; - } + /** + * Merge autoClosingPairs. + */ - /** - * Merge the internal config onEnterRules with the default config, removing any duplicates. - * - * @param {any} defaultOnEnterRules Default onEnterRules. - * @param {vscode.LanguageConfiguration} internalLangConfig Internal language config from vscode extensions. - * @returns {vscode.OnEnterRule[]} - * - * TODO: combine this method and mergeConfigAutoClosingPairs into one method. - */ - private mergeConfigOnEnterRules(defaultOnEnterRules, internalLangConfig) { - const internalOnEnterRules = internalLangConfig?.onEnterRules ?? []; + // Copy to avoid side effects. + const mergedAutoClosingPairs = [...internalAutoClosing]; + // Loop over the defaultLangConfig autoClosingPairs array... + defaultAutoClosingPairs.forEach((item) => merge("open", item, mergedAutoClosingPairs)); - // Code based on "2023 update" portion of this StackOverflow answer: - // https://stackoverflow.com/a/1584377/2358222 + /** + * Merge onEnterRules + */ // Copy to avoid side effects. - const merged = [...defaultOnEnterRules]; - // Loop over the defaultLangConfig autoClosingPairs array... - internalOnEnterRules.forEach((item) => { - // Test all items in the merged array, and if the defaultAutoClosing item's - // opening comment string (item.open) is not already present in one of the - // merged array's objects then add the item to the merged array. - merged.some((mergedItem) => item.beforeText === mergedItem.beforeText) ? null : merged.push(item); - }); + const mergedOnEnterRules = [...defaultOnEnterRules]; + + internalOnEnterRules.forEach((item) => merge("beforeText", item, mergedOnEnterRules)); - return merged; + return {mergedOnEnterRules, mergedAutoClosingPairs}; } /** From e6d1b5342582f04e7af82155c8aee3d611ed12ea Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 13:00:13 +0000 Subject: [PATCH 20/27] feat: added support for double hash (`##`) style single-line comments. --- src/configuration.ts | 3 +++ src/rules.ts | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index aeb07a0..be99f7e 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -819,6 +819,9 @@ export class Configuration { } } else if (style === "#" && line.text.search(/^\s*#\s*/) !== -1) { indentRegex = /#/; + if (line.text.search(/^\s*##/) !== -1) { + style = "##"; + } } else if (style === ";" && line.text.search(/^\s*;\s*/) !== -1) { indentRegex = /;/; diff --git a/src/rules.ts b/src/rules.ts index e4d774a..f1af123 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -115,9 +115,15 @@ export class Rules { { // e.g. # | // (matches # with any amount of spaces before it.) - beforeText: /^\s*#/, + beforeText: /^\s*#(?!#)/, action: {indentAction: IndentAction.None, appendText: "# "}, }, + { + // e.g. ## | + // (matches ## with any amount of spaces before it.) + beforeText: /^\s*##/, + action: {indentAction: IndentAction.None, appendText: "## "}, + }, ]; static readonly semicolonEnterRules: OnEnterRule[] = [ From 55d5a1bc44b0a8b3908edc942afcb1e3b0585594 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 13:01:59 +0000 Subject: [PATCH 21/27] chore: update prettier config --- .prettierrc.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.prettierrc.json b/.prettierrc.json index 5a3cb37..a2cc252 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -4,5 +4,16 @@ "semi": true, "printWidth": 150, "bracketSameLine": true, - "bracketSpacing": false + "bracketSpacing": false, + "overrides": [ + { + "files": [ + "*.json", + "*.jsonc" + ], + "options": { + "printWidth": 5 + } + } + ] } From e9b574c92c1b9ecf6a2b7b7ff5ef502a565abe05 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 13:56:18 +0000 Subject: [PATCH 22/27] fix: `//` onEnterRule regex to stop it preventing the `//!` from matching it's regex. When using `//!`-style and the `singleLineBlockOnEnter` setting is turned on, the `//` regex matches because the negative lookahead `(?!...)` expression doesn't include the `!` therefore it would still match the `//` part of the `//!`. Therefore, it would enter `//` on the next line instead of the anticipated `//!`-style. Fixed by updating the regex to include the `!` in the negative lookahead expression which basically means "don't match if it has these characters in". --- src/rules.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules.ts b/src/rules.ts index f1af123..6951f88 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -94,7 +94,7 @@ export class Rules { { // e.g. // | // (matched // with any amount of spaces before it.) - beforeText: /^\s*\/\/(?!\/)/, + beforeText: /^\s*\/\/(?!\/|!)/, action: {indentAction: IndentAction.None, appendText: "// "}, }, { From 8ff8cb9107978d410329c89539e9232144409ec4 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 14:05:59 +0000 Subject: [PATCH 23/27] docs: update the "FIXME" code comment for the onEnterRules to note all languages that don't work. --- src/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index be99f7e..c9f4338 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -590,7 +590,7 @@ export class Configuration { } } - // FIXME: onEnterRules do not work in any language. + // FIXME: onEnterRules do not work in these languages: python, c, cpp, cuda-cpp, java, javascript, javascriptreact, php (and blade by extension), sass, scss, typescript, typescriptreact. let isOnEnter = this.getConfigurationValue("singleLineBlockOnEnter"); // Add the single line onEnter rules to the langConfig. From 43fbb47b4dead150c0ba54d65bae8135f258be40 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 15:14:32 +0000 Subject: [PATCH 24/27] style: correct hyphenation in code comments for consistency --- src/configuration.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index c9f4338..ad00154 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -24,7 +24,7 @@ export class Configuration { private readonly languageConfigs = new Map(); /** - * A key:value Map object of supported language IDs and their single line style comments. + * A key:value Map object of supported language IDs and their single-line style comments. * * @property {string} key Language ID. * @property {string} value Style of line comment. @@ -32,7 +32,7 @@ export class Configuration { private singleLineBlocksMap: Map> = new Map(); /** - * A Map object of an array of supported language IDs for multi line block comments. + * A Map object of an array of supported language IDs for multi-line block comments. * * @property {string} key - "languages" * @property {string[]} value - Array of language IDs. @@ -76,11 +76,11 @@ export class Configuration { const singleLineLangs = this.getSingleLineLanguages("supportedLanguages"); const multiLineLangs = this.getMultiLineLanguages("supportedLanguages"); - // Setup the auto-supported single line languages. + // Setup the auto-supported single-line languages. for (let [langId, style] of singleLineLangs) { if (!this.isLangIdDisabled(langId)) { - // Set a bool if the single line language also supports multi line comments - // (ie. the single line language is also present in the multi line map); + // Set a bool if the single-line language also supports multi-line comments + // (ie. the single-line language is also present in the multi-line map); let multiLine = multiLineLangs.includes(langId); disposables.push(this.setLanguageConfiguration(langId, multiLine, style)); } @@ -104,8 +104,8 @@ export class Configuration { // Setup the custom-supported single-line languages, that are otherwise unsupported. for (let [langId, style] of customSingleLineLangs) { - // Set a bool if the single line language also supports multi line comments - // (ie. the single line language is also present in the multi line map); + // Set a bool if the single-line language also supports multi-line comments + // (ie. the single-line language is also present in the multi-line map); let multiLine = customMultiLineLangs.includes(langId); disposables.push(this.setLanguageConfiguration(langId, multiLine, style)); } @@ -433,7 +433,7 @@ export class Configuration { // If the config object has own property of comments AND the comments key has // own property of blockComment... if (Object.hasOwn(config, "comments") && Object.hasOwn(config.comments, "blockComment")) { - // If the blockComment array includes the multi line start of "/*"... + // If the blockComment array includes the multi-line start of "/*"... if (config.comments.blockComment.includes("/*")) { // console.log(langId, config.comments); @@ -492,7 +492,7 @@ export class Configuration { style = ";"; } - // If style any empty string, (i.e. not an unsupported single line + // If style any empty string, (i.e. not an unsupported single-line // comment like bat's @rem)... if (style != "") { // Set the langId and it's style into the Map. @@ -593,7 +593,7 @@ export class Configuration { // FIXME: onEnterRules do not work in these languages: python, c, cpp, cuda-cpp, java, javascript, javascriptreact, php (and blade by extension), sass, scss, typescript, typescriptreact. let isOnEnter = this.getConfigurationValue("singleLineBlockOnEnter"); - // Add the single line onEnter rules to the langConfig. + // Add the single-line onEnter rules to the langConfig. // // If isOnEnter is true AND singleLineStyle isn't false, i.e. a string. if (isOnEnter && singleLineStyle) { @@ -791,7 +791,7 @@ export class Configuration { } /** - * The keyboard binding event handler for the single line blocks on shift+enter. + * The keyboard binding event handler for the single-line blocks on shift+enter. * * @param {vscode.TextEditor} textEditor The text editor. * @param {vscode.TextEditorEdit} edit The text editor edits. From e6378e226c4dadb03cac5cd6e4fb0d66a5012881 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 15:15:51 +0000 Subject: [PATCH 25/27] style: correct hyphenation in code comments for consistency (pt.2) --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 81290e3..f5ec1f2 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "auto-comment-blocks.singleLineBlockOnEnter": { "type": "boolean", "default": false, - "markdownDescription": "If enabled, a new commented line is inserted when Enter is pressed, and single line comments are broken by pressing `Shift + Enter`. If disabled (the default), a commented line is inserted when `Shift + Enter` is pressed, and single line comments are broken by pressing `Enter`." + "markdownDescription": "If enabled, a new commented line is inserted when Enter is pressed, and single-line comments are broken by pressing `Shift + Enter`. If disabled (the default), a commented line is inserted when `Shift + Enter` is pressed, and single-line comments are broken by pressing `Enter`." }, "auto-comment-blocks.disabledLanguages": { "type": "array", @@ -48,17 +48,17 @@ "auto-comment-blocks.slashStyleBlocks": { "type": "array", "default": [], - "markdownDescription": "Add language IDs here to enable `//` and `///`-style single line comment blocks for that language. This allows unsupported languages to have comment completion." + "markdownDescription": "Add language IDs here to enable `//` and `///`-style single-line comment blocks for that language. This allows unsupported languages to have comment completion." }, "auto-comment-blocks.hashStyleBlocks": { "type": "array", "default": [], - "markdownDescription": "Add language IDs here to enable `#`-style single line comment blocks for that language. This allows unsupported languages to have comment completion." + "markdownDescription": "Add language IDs here to enable `#`-style single-line comment blocks for that language. This allows unsupported languages to have comment completion." }, "auto-comment-blocks.semicolonStyleBlocks": { "type": "array", "default": [], - "markdownDescription": "Add language IDs here to enable `;`-style single line comment blocks for that language. This allows unsupported languages to have comment completion." + "markdownDescription": "Add language IDs here to enable `;`-style single-line comment blocks for that language. This allows unsupported languages to have comment completion." }, "auto-comment-blocks.multiLineStyleBlocks": { "type": "array", @@ -66,12 +66,12 @@ "blade", "html" ], - "markdownDescription": "Add language IDs here to enable multi line comment blocks support for that language. This allows unsupported languages to have comment completion. The default is `['blade', 'html']`" + "markdownDescription": "Add language IDs here to enable multi-line comment blocks support for that language. This allows unsupported languages to have comment completion. The default is `['blade', 'html']`" }, "auto-comment-blocks.overrideDefaultLanguageMultiLineComments": { "type": "object", "default": {}, - "markdownDescription": "A key : value pairing of language IDs and the beginning portion of a multi line comment style, to override the default comment style for the vscode `command editor.action.blockComment` (native Keybinding `shift + alt + a`). eg. `{'php': '/*!'}`" + "markdownDescription": "A key : value pairing of language IDs and the beginning portion of a multi-line comment style, to override the default comment style for the vscode `command editor.action.blockComment` (native Keybinding `shift + alt + a`). eg. `{'php': '/*!'}`" }, "auto-comment-blocks.bladeOverrideComments": { "scope": "resource", From a3590585b05c1f386db7b22aae742c5b040beaa0 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 15:27:21 +0000 Subject: [PATCH 26/27] docs: update changlog and readme --- CHANGELOG.md | 113 +++++++++++++++++++++++++++++++++------------- README.md | 125 +++++++++++++++++++++++++++++---------------------- 2 files changed, 155 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8f2c28..93e5098 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,62 +1,115 @@ -# Change Log +# ChangeLog + All notable changes to this extension will be documented in this file. - -## [1.0.3] -- Added support for JavaScript and TypeScript multiline block comments - a [pull request by a-stewart](https://github.com/kevb34ns/auto-comment-blocks/pull/35) for the original plugin. Fixes issue kevb34ns/auto-comment-blocks#27. -- Created a new language config file for Blade to use blade's comments as well as the multiline block comments -- Updated various language config files to reflect a [pull request by a-stewart](https://github.com/kevb34ns/auto-comment-blocks/pull/37) for the original plugin. -- Added support for protocol buffers - a [pull request by jun-sheaf](https://github.com/kevb34ns/auto-comment-blocks/pull/30) for the original plugin. -- Added support for `//!` comments - a [pull request by Lucretiel](https://github.com/kevb34ns/auto-comment-blocks/pull/29) for the original plugin and fixes the issue kevb34ns/auto-comment-blocks#25 -- Added support for csharp(c#) (using the cpp(c++) config file) - Fixes the issue kevb34ns/auto-comment-blocks#41. -- Updated the support for `/*! */` comments and including the `!` on every line. +This Changelog uses the [Keep a Changelog](http://keepachangelog.com/) structure. + +## [1.1.0](https://github.com/yCodeTech/auto-comment-blocks/releases/tag/v1.1.0) - 2024-22-12 + +A complete overhaul to enable automatic support for all languages that vscode finds internally (via built-in or 3rd party extensions) that has both a language configuration file, and a comments key in the file. + +For a full changelog, view the [release PR](https://github.com/yCodeTech/auto-comment-blocks/pull/1). + +#### Removed: + +- All language configuration files and package.json contribution declaration, in favour of auto-supported languages. So this extension no longer needs to keep adding language support, as the extension does it automatically. + +#### Added: + +- Added 3 new settings: + + - `multiLineStyleBlocks` to add support of multi-line block comment to the specified unsupported languages. + - `overrideDefaultLanguageMultiLineComments` to override the style of multi-line comments for a language for the native vscode `blockComment` command. + + - `bladeOverrideComments`, to switch between HTML style `` comments, and Blade style `{{-- --}}` comments, when the file is using the Blade language. + +- Added a keyboard binding to enable/disable the `bladeOverrideComments` setting, and a user information message appears to state whether enabled or disabled. + +- Added support for `/* */`. + +- Added an event to reconfigure the comment blocks evertime a document is opened OR the document language has been changed. + +- Added a config file to define the default multi-line config comments and autoClosingPairs; and a config file to define language IDs the need to be skipped when auto finding the languages to support (because these languages are known not to have any config properties we're interested in.) + +- Added support for double semicolon `;;` and double hash `##` comments. + +## [v1.0.3](https://github.com/yCodeTech/auto-comment-blocks/releases/tag/v1.0.3) - 2022-09-17 + +- Added support for JavaScript and TypeScript multi-line block comments - a [pull request by a-stewart](https://github.com/kevb34ns/auto-comment-blocks/pull/35) for the original plugin. Fixes issue kevb34ns/auto-comment-blocks#27. +- Created a new language config file for Blade to use blade's comments as well as the multi-line block comments +- Updated various language config files to reflect a [pull request by a-stewart](https://github.com/kevb34ns/auto-comment-blocks/pull/37) for the original plugin. +- Added support for protocol buffers - a [pull request by jun-sheaf](https://github.com/kevb34ns/auto-comment-blocks/pull/30) for the original plugin. +- Added support for `//!` comments - a [pull request by Lucretiel](https://github.com/kevb34ns/auto-comment-blocks/pull/29) for the original plugin and fixes the issue kevb34ns/auto-comment-blocks#25 +- Added support for csharp(c#) (using the cpp(c++) config file) - Fixes the issue kevb34ns/auto-comment-blocks#41. +- Updated the support for `/*! */` comments and including the `!` on every line. ## [1.0.2] -- Added support for PHP Blade. + +- Added support for PHP Blade. + +--- + +Forked by @yCodeTech from here upwards. + +--- ## [1.0.1] -- Add multi-line support for Rust, Go -- Add single-line support for YAML + +- Add multi-line support for Rust, Go +- Add single-line support for YAML ## [1.0.0] -- Add multi-line comment support for Less, Objective-C/C++, and Swift. -- Add single-line comment blocks for most officially supported languages. See README for more information. + +- Add multi-line comment support for Less, Objective-C/C++, and Swift. +- Add single-line comment blocks for most officially supported languages. See README for more information. ## [0.3.2] -- Fix a bug that broke the extension, caused by the previous bugfix. + +- Fix a bug that broke the extension, caused by the previous bugfix. ## [0.3.1] -- Fix bug that that caused every language to have single-line block comments. + +- Fix bug that that caused every language to have single-line block comments. ## [0.3.0] -- Add single-line blocks for C/C++ (disabled by default). -- Add comment completion for PHP files. + +- Add single-line blocks for C/C++ (disabled by default). +- Add comment completion for PHP files. ## [0.2.2] -- Add Javadoc-style comments for Groovy files. + +- Add Javadoc-style comments for Groovy files. ## [0.2.1] -- Fixed misspelled filename leading to C functionality breaking. -- Change extension description to include support for new languages. + +- Fixed misspelled filename leading to C functionality breaking. +- Change extension description to include support for new languages. ## [0.2.0] -- Added block comment completion for CSS/Sass files. + +- Added block comment completion for CSS/Sass files. ## [0.1.0] -- Add QDoc (Qt-style) comment block completion for C and C++. + +- Add QDoc (Qt-style) comment block completion for C and C++. ## [0.0.5] -- Fix major typo that caused an asterisk to be inserted following any indented line. -- Changelog now starts with the latest update rather than the oldest. + +- Fix major typo that caused an asterisk to be inserted following any indented line. +- Changelog now starts with the latest update rather than the oldest. ## [0.0.4] -- Fixed an issue that caused asterisk insertion and indentation bugs when indenting using an odd number of spaces. + +- Fixed an issue that caused asterisk insertion and indentation bugs when indenting using an odd number of spaces. ## [0.0.3] -- Changed `galleryBanner.theme`, again. + +- Changed `galleryBanner.theme`, again. ## [0.0.2] -- Changed `galleryBanner.theme`. + +- Changed `galleryBanner.theme`. ## [0.0.1] -- Initial release + +- Initial release diff --git a/README.md b/README.md index 1f43207..71410ee 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,110 @@ # Automatic Comment Blocks -A VScode extension that provides block comment completion for Javadoc-style multi-line comments and single-line comment blocks for most officially supported languages. +Visual Studio Marketplace Version   +Visual Studio Marketplace Installs + -This is a fork of the original by [kevb34ns](https://github.com/kevb34ns/auto-comment-blocks) with some additional language support. +A VScode extension that provides block comment completion for Javadoc-style multi-line comments and single-line comment blocks for most officially supported languages -View the [Changelog](/CHANGELOG.md) for more detailed changes/additions/removals. +This is a fork of the original by [kevb34ns](https://github.com/kevb34ns/auto-comment-blocks) with lots of additional support. View the extension on [VScode Marketplace](https://marketplace.visualstudio.com/items?itemName=yCodeTech.automatic-comment-blocks). -## MAJOR CHANGES IN 1.0.3 UPDATE (Please Read) +--- + +### As of [v1.1.0](https://github.com/yCodeTech/auto-comment-blocks/releases/tag/v1.1.0), this extension now automatically adds language support, and no-longer keeps hardcoded language support... + +Instead, the extension will automatically find all officially supported languages recognised by VScode internally which are either built-in or added via 3rd party extensions. + +There are 3 conditions in which a language is officially supported: + +1. The defined language also has a language config file; and +2. The language is not defined in the `skip-languages` config file; and +3. The language config has either `lineComment` or `blockComment` keys defined. + +Most of the officially VScode-supported languages (as defined in the [docs](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers)) pass these conditions. + +--- -- Added support for JavaScript and TypeScript multiline block comments. -- Added support for Blade to use blade's handlebar comments as well as the multiline block comments. -- Added support for protocol buffers. -- Added support for `//!` comments. -- Added support for csharp. -- Updated the support for `/*! */` comments and including the `!` on every line. +## Major changes in [v1.1.0](https://github.com/yCodeTech/auto-comment-blocks/releases/tag/v1.1.0) -## MAJOR CHANGES IN 1.0 UPDATE (Please Read) +- Removed hardcoded language config files and support. +- Added automatic language support. +- 3 new user settings. +- Support for `/* */`, `##`, `;;`, and `{{-- --}}` (blade comments). -A lot has changed in this update. Please open issues for any bugs you encounter. +View the [Changelog](/CHANGELOG.md) for more detailed changes/additions/removals. ### Single-line Comment Blocks -You can now use single line comment blocks for languages with `//`, `#`, or `;` style single line comments. Press `Shift+Enter` while on a commented line to insert a new commented line with the same level of indentation. See the Settings section for how to change the behavior so that `Enter` inserts a commented line while `Shift+Enter` breaks out of the comment block (this only works correctly for a subset of languages right now). -The Language Support section shows which languages are supported. See the Settings section for how to add single line comment support to languages that are not officially supported. +You can insert single-line comment blocks for languages that use `//`, `#`, or `;`-styles. + +Press `shift + enter` while on a commented line to insert a new commented line with the same level of indentation. See the Settings section for how to change the behaviour so that `enter` inserts a commented line while `shift + enter` breaks out of the comment block (this only works correctly for a subset of languages right now). + +The Language Support section shows which languages are supported. See the Settings section for how to add single-line comment support to languages that are not officially supported. ### Multi-line Comment Blocks -This feature has not changed, but support has now been added for Less, Objective-C/C++, and Swift. -## Usage ![Demo](https://raw.githubusercontent.com/kevinkyang/auto-comment-blocks/master/img/demo.gif) +While inside any style of the multi-line comment blocks, when pressing `enter`, the extension will insert an asterisk (`*`) at the start of every new line, and align the comment, respecting indentation. + ### Javadoc-style comment blocks -Type `/**` to start a block comment, then hit the Enter key, and the extension will close the block. While inside the comment block, the extension will insert an asterisk at the start of every new line, and align the comment, respecting indentation. + +Type `/**` to start the Javadoc-style block comment, after typing the 2nd `*`, the extension will auto-close the block. ### QDoc-style (Qt) comment blocks -Use `/*!` in all file types that support the normal `/*` comments to start a QDoc comment block. -### New: "single-line" block comments -You can insert single line comment blocks for languages with `//`, `#`, or `;` style single line comments. Press `Shift+Enter` while on a commented line to insert a new commented line with the same level of indentation. See the Settings section for issues and more options. +Use `/*!` in all file types that support the normal `/*` comments to start a QDoc comment block; and like the Javadoc-style, the extension will auto-close the block after the `!` is typed. + +### New: Normal comment blocks + +Using the normal comment block `/* */` either typing manually or the native VScode command "Toggle Block Comment" (`editor.action.blockComment`, native keybinding `shift + alt + a`), the block will have the same on enter functionality as described above. ### Language Support -| Comment Style | Language Support | -| ------- | ------- | -| `/** */`, `/*! */` | Blade, C, C++, C#, CSS, Go, Groovy, Java, JavaScript, Less, Objective C/C++, PHP, Proto, Proto3, Rust, SCSS/Sass Swift, Typescript | -| `//`, `///` | Blade, C, C++, C#, F#, Go, Groovy, Java, JavaScript, Less, Objective C/C++, PHP, Rust, SCSS/Sass, Swift, TypeScript | -| `#` | CoffeeScript, Dockerfile, Makefile, Perl, PowerShell, Python, R, Ruby, YAML | -| `;` | Clojure | +All auto-supported languages are defined in the auto-generated files found in [auto-generated-language-definitions directory](auto-generated-language-definitions) of the repo. Custom supported languages specified by user settings can also appear in these files. + +These files are only for documentation purposes and are not used in the extension. + +Some languages that appear in the files will have been added from 3rd party language extensions. The supported languages will be different from person to person, dependant on extensions installed/enabled. ## Settings Reload the extension after changing any settings. -* `auto-comment-blocks.singleLineBlockOnEnter`: If enabled, pressing `Enter` inserts a new commented line at the same indentation, and pressing `Shift+Enter` breaks the comment block. - + **Caution**: This feature is buggy in many languages (see Issues section), but it seems to work fine for C, C++, Go, Less, PHP, Ruby, and Sass. -* `auto-comment-blocks.disabledLanguages`: Add languageIds here to disable any comment completion for that language. -* `auto-comment-blocks.slashStyleBlocks`: Add languageIds here to enable '//' and '///'-style single line comment blocks for that language. -* `auto-comment-blocks.hashStyleBlocks`: Add languageIds here to enable '#'-style single line comment blocks for that language. -* `auto-comment-blocks.semicolonStyleBlocks`: Add languageIds here to enable ';'-style single line comment blocks for that language. +- `auto-comment-blocks.singleLineBlockOnEnter`: If enabled, pressing `enter` inserts a new commented line at the same indentation, and pressing `shift + enter` breaks the comment block. + + If disabled (the default), a commented line is inserted when `shift + enter` is pressed, and single-line comments are broken by pressing `enter`." + + **Caution**: This feature is buggy in many languages, see [Issues section](#issues). + +- `auto-comment-blocks.disabledLanguages`: Add language IDs here to disable any comment completion for that language. + +- `auto-comment-blocks.slashStyleBlocks`: Add language IDs here to enable '//' and '///'-style single-line comment blocks for that language, allowing unsupported languages to have comment completion. + +- `auto-comment-blocks.hashStyleBlocks`: Add language IDs here to enable `#` and `##`-style single-line comment blocks for that language, allowing unsupported languages to have comment completion. + +- `auto-comment-blocks.semicolonStyleBlocks`: Add language IDs here to enable `;` and `;;`-style single-line comment blocks for that language, allowing unsupported languages to have comment completion. + +- `auto-comment-blocks.multiLineStyleBlocks`: Add language IDs here to enable multi-line comment blocks support for that language, allowing unsupported languages to have comment completion. The default is `['blade', 'html']`" + +- `auto-comment-blocks.overrideDefaultLanguageMultiLineComments`: A key : value pairing of language IDs and the beginning portion of a multi-line comment style, to override the default comment style for the vscode "Toggle Block Comment" `editor.action.blockComment` command (native Keybinding `shift + alt + a`). eg. `{'php': '/*!'}` + +- `auto-comment-blocks.bladeOverrideComments`: When enabled, Blade-style block comments will be used in Blade contexts. Ie. `{{-- --}}` comments will be used instead of the HTML `` comments. Keybinding to enable/disable, default `ctrl + shift + m`. If `blade` language ID is set in the disabledLanguages, then the HTML `` comments will be used. ## Issues -* Single-line blocks using `Enter`: if you enable the `singleLineBlockOnEnter` setting, there are a few things to keep in mind: - + It seems to work find for C, C++, Go, Less, PHP, Ruby, and Sass. - + It doesn't work at all for Python, JavaScript, and TypeScript. - + For every other language, if you press `Tab` immediately after breaking out of a comment block, it will insert a commented line, for some unknown reason. -* Sometimes multi-line completion/aseterisk insertion doesn't work. The reason is still unknown. It may go away if you reload your workspace. -* Currently, VS Code only allows extensions to overwrite, instead of modify, existing language configurations. This means that this extension may clash with another extension that overwrites the same language configurations, causing one or both not to work. In that case, uninstalling this extension is the only option for now. +- Single-line comments using `enter`: if you enable the `singleLineBlockOnEnter` setting, there are a few things to keep in mind: -Please create an issue in the [repository](https://github.com/kevinkyang/auto-comment-blocks/issues) if you find any bugs, or have questions or feature requests. + - It seems to work fine for Go, Less, Ruby. + + - It doesn't work at all for: python, c, cpp, cuda-cpp, java, javascript, javascriptreact, php (and blade), sass, scss, typescript, typescriptreact. -## Release Notes + - For some languages, including C, C++, Sass - if you press `Tab` immediately after breaking out of a comment block, it will insert a commented line, for some unknown reason. -### 1.0.3 -- Added support for JavaScript and TypeScript multiline block comments - a pull request by a-stewart for the original plugin. Fixes issue #27. -- Created a new language config file for Blade to use blade's comments as well as the multiline block comments -- Updated various language config files to reflect a pull request by a-stewart for the original plugin. -- Added support for protocol buffers - a pull request by jun-sheaf for the original plugin. -- Added support for `//!` comments - a pull request by Lucretiel for the original plugin and fixes the issue #25 -- Added support for csharp (using the cpp config file) - Fixes the issue #41. -- Updated the support for `/*! */` comments and including the `!` on every line. +- Sometimes multi-line completion/asterisk insertion doesn't work. The reason is still unknown. It may go away if you reload your workspace. -### 1.0.2 -- Added support for PHP Blade. +- Currently, VS Code only allows extensions to overwrite, instead of modify, existing language configurations. This means that this extension may clash with another extension that overwrites the same language configurations, causing one or both not to work. In that case, uninstalling this extension is the only option for now. -### 1.0.0 -- Add multi-line comment support for Less, Objective-C/C++, and Swift. -- Add single-line comment blocks for most officially supported languages. See README for more information. +Please create an issue in the [repository](https://github.com/kevinkyang/auto-comment-blocks/issues) if you find any bugs, or have questions or feature requests. From e2fac8067ed70f44955863e395fb1a11b7cb570c Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sun, 22 Dec 2024 15:31:13 +0000 Subject: [PATCH 27/27] build: update vscode engine version to be able to package the extension. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5ec1f2..09b245e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "theme": "dark" }, "engines": { - "vscode": "^1.74.0" + "vscode": "^1.96.0" }, "keywords": [ "auto",