Skip to content

Commit 5b590df

Browse files
committed
Merge branch 'dev'
2 parents 88fbe50 + a7b8d3a commit 5b590df

11 files changed

Lines changed: 618 additions & 85 deletions

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
# javascript-regex
22
[![](https://img.shields.io/apm/v/javascript-regex)](https://atom.io/packages/javascript-regex) [![](https://img.shields.io/apm/dm/javascript-regex)](https://atom.io/packages/javascript-regex)
33

4-
Improved syntax for JavaScript regular expressions.
4+
Improved syntax for JavaScript regular expressions, with syntax highlighting.
55

6-
Check out the [One Dark for Regex](https://atom.io/packages/one-dark-regex-syntax) theme for a practical use.
6+
![regex2](https://user-images.githubusercontent.com/695638/192731283-82db8798-d9b9-4f3f-8f13-7a90fb581810.gif)
77

88
This package implements two tree-sitter parsers:
99
- [tree-sitter-regex-unicode-js](https://github.com/wizard04wsu/tree-sitter-regex-unicode-js) for regular expressions that have the Unicode flag set
1010
- [tree-sitter-regex-js](https://github.com/wizard04wsu/tree-sitter-regex-js) for the rest
1111

12-
# Troubleshooting
13-
### Unable to install on Windows
12+
## Troubleshooting
13+
#### If you're unable to install the package on Windows:
1414
Instead of installing it from within Atom, close Atom and try from the command line.
1515

16-
cd %USERPROFILE%\.atom\packages
17-
rmdir /S /Q javascript-regex
16+
cd /d %USERPROFILE%\.atom\packages
17+
rmdir /s /q javascript-regex
1818
apm install javascript-regex
1919

20-
### Failure to load package grammars when I open Atom
20+
#### If there's a failure loading the grammars when you open Atom:
2121
Whenever Atom is updated, this package needs to be rebuilt. Either click the red bug icon in the bottom-right corner of the window, or execute `Incompatible Packages: View` via the command palette. Then, click "Rebuild Packages". You'll have to restart Atom.
2222

2323
If anyone has a better solution, please [let me know](https://github.com/wizard04wsu/javascript-regex/issues/9).

index.js

Lines changed: 0 additions & 76 deletions
This file was deleted.

lib/javascript-regex.js

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
const { CompositeDisposable } = require("atom");
2+
3+
4+
let package,
5+
disposableStyleSheets = {};
6+
7+
const thisPackage = {
8+
9+
name: "javascript-regex",
10+
11+
// Scope names of languages for which relevant injection points will be overridden.
12+
languageScopeNames: [
13+
"source.js",
14+
"source.jsx",
15+
"source.ts",
16+
"source.flow",
17+
],
18+
19+
// Rule names in the language grammar for which injection points will be overridden.
20+
languageGrammarRuleNames: [
21+
"regex",
22+
"regex_pattern",
23+
],
24+
25+
26+
injectionPoints: [
27+
{
28+
// Injection type: the name of the rule in the language grammar that this injection point is to be added to.
29+
type: "regex",
30+
31+
// Get the name of the grammar that should be injected into a matching node. This should match the grammar's "injectionRegex" property.
32+
language(regexNode){
33+
const {lastChild} = regexNode;
34+
if(lastChild.type === "regex_flags"){ // Flags are specified.
35+
const flags = lastChild.text;
36+
let validFlags = "gimsy".split(""),
37+
f = -1;
38+
while(validFlags.length && ++f < flags.length){
39+
const v = validFlags.indexOf(flags[f]);
40+
if(flags[f] === "u"){
41+
return "regex_u"; // Unicode flag is set.
42+
}
43+
else if(v < 0){
44+
break; // Invalid or duplicate flag.
45+
}
46+
validFlags.splice(v, 1);
47+
}
48+
}
49+
return "regex"; // Unicode flag is not set.
50+
},
51+
52+
// Get the node with the text content that should be parsed using the injected grammar.
53+
content(regexNode){
54+
// Return the node containing the regex pattern between the slashes.
55+
return regexNode.children[1];
56+
}
57+
},
58+
],
59+
};
60+
61+
function toggleConfig(configName){
62+
atom.config.set(configName, !atom.config.get(`${thisPackage.name}.${configName}`));
63+
};
64+
65+
function updateStyleSheet(configName, filename){
66+
console.log(disposableStyleSheets);
67+
disposableStyleSheets[configName]?.dispose();
68+
if(atom.config.get(`${thisPackage.name}.${configName}`)){
69+
let path = `${package.path}/styles/${filename}.less`,
70+
css = package.themeManager.loadStylesheet(path);
71+
disposableStyleSheets[configName] = package.styleManager.addStyleSheet(css, { sourcePath: path, priority: 1 });
72+
}
73+
else{
74+
disposableStyleSheets[configName] = void 0;
75+
atom.config.set(`${thisPackage.name}.${configName}`, false);
76+
}
77+
console.log(">>",disposableStyleSheets);
78+
}
79+
80+
module.exports = {
81+
82+
activate(state){
83+
84+
package = atom.packages.loadedPackages[thisPackage.name];
85+
86+
// Add or replace grammars that are associated with this package.
87+
// (i.e., grammars with scope names "source.js.regexp" and "source.js.regexp.unicode")
88+
const packageGrammars = package.grammars;
89+
for(const newGrammar of packageGrammars){
90+
91+
const existingGrammar = atom.grammars.treeSitterGrammarsById[newGrammar.scopeName];
92+
if(existingGrammar){
93+
// A grammar is currently assigned to the new grammar's scope name.
94+
95+
if(existingGrammar.packageName !== thisPackage.name){
96+
// The existing grammar is not the one associated with this package.
97+
98+
// Replace the existing grammar with the new one.
99+
atom.grammars.removeGrammar(existingGrammar);
100+
atom.grammars.addGrammar(newGrammar);
101+
}
102+
}
103+
else{
104+
// Add the new grammar.
105+
atom.grammars.addGrammar(newGrammar);
106+
}
107+
}
108+
109+
// For each associated language scope...
110+
// (i.e., scope names "source.js", "source.jsx", "source.ts", and "source.flow")
111+
for(const languageScopeName of thisPackage.languageScopeNames){
112+
113+
const languageGrammar = atom.grammars.treeSitterGrammarsById[languageScopeName];
114+
if(!languageGrammar) continue; // A grammar does not exist for this language scope.
115+
116+
// Add injection points for associated rules in this language's grammar.
117+
for(const grammarRuleName of thisPackage.languageGrammarRuleNames){
118+
119+
/*
120+
// Remove any existing injection points of this type.
121+
// (i.e., types matching grammar rule names "regex" and "regex_pattern")
122+
const existingInjectionPoints = languageGrammar.injectionPointsByType[grammarRuleName];
123+
for(const injectionPoint of existingInjectionPoints){
124+
languageGrammar.removeInjectionPoint(injectionPoint);
125+
}
126+
*/
127+
128+
// Add new injection points of this type.
129+
// (i.e., types matching grammar rule names "regex" and "regex_pattern")
130+
for(newInjectionPoint of thisPackage.injectionPoints){
131+
if(newInjectionPoint.type === grammarRuleName){
132+
languageGrammar.addInjectionPoint(newInjectionPoint);
133+
}
134+
}
135+
}
136+
}
137+
138+
139+
// Create an instance of the CompositeDisposable class so it can register all the commands that can be called from the plugin,
140+
// allowing other plugins to subscribe to those events.
141+
this.subscriptions = new CompositeDisposable();
142+
143+
// Register the commands.
144+
this.subscriptions.add(atom.commands.add('atom-workspace', {
145+
"javascript-regex:toggle-character-set-backgrounds": ()=>toggleConfig("showCharacterSetBackgrounds"),
146+
"javascript-regex:toggle-group-outlines": ()=>toggleConfig("showGroupOutlines"),
147+
}));
148+
149+
// Load the main syntax highlighting stylesheet.
150+
let path = `${package.path}/styles/javascript-regex.less`,
151+
css = package.themeManager.loadStylesheet(path);
152+
disposableStyleSheets["main"] = package.styleManager.addStyleSheet(css, { sourcePath: path, priority: 1 });
153+
154+
// Load stylesheets per the package settings.
155+
updateStyleSheet("showCharacterSetBackgrounds", "charset-backgrounds");
156+
updateStyleSheet("showGroupOutlines", "group-outlines");
157+
158+
// Observe changes to the package settings.
159+
atom.config.onDidChange(`${thisPackage.name}.showCharacterSetBackgrounds`, {}, ()=>updateStyleSheet("showCharacterSetBackgrounds", "charset-backgrounds"));
160+
atom.config.onDidChange(`${thisPackage.name}.showGroupOutlines`, {}, ()=>updateStyleSheet("showGroupOutlines", "group-outlines"));
161+
},
162+
163+
serialize(){},
164+
165+
deactivate(){
166+
disposableStyleSheets["showCharacterSetBackgrounds"]?.dispose();
167+
disposableStyleSheets["showGroupOutlines"]?.dispose();
168+
disposableStyleSheets["main"].dispose();
169+
this.subscriptions.dispose();
170+
},
171+
172+
config: {
173+
showCharacterSetBackgrounds: {
174+
title: "Display character set backgrounds",
175+
description: "Styles character sets (the contents of a pair of square brackets) with a background to make them easier to interpret as a single character.",
176+
type: "boolean",
177+
default: true,
178+
},
179+
showGroupOutlines: {
180+
title: "Display group outlines",
181+
description: "Styles groups (the contents of a pair of parentheses) with outlines to make them easier to distinguish.",
182+
type: "boolean",
183+
default: false,
184+
},
185+
},
186+
187+
};

menus/javascript-regex.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"menu": [
3+
{
4+
"label": "Packages",
5+
"submenu": [
6+
{
7+
"label": "JavaScript RegExp",
8+
"submenu": [
9+
{
10+
"label": "Toggle Group Outlines",
11+
"command": "javascript-regex:toggle-group-outlines"
12+
},
13+
{
14+
"label": "Toggle Character Set Backgrounds",
15+
"command": "javascript-regex:toggle-character-set-backgrounds"
16+
}
17+
]
18+
}
19+
]
20+
}
21+
]
22+
}

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "javascript-regex",
3-
"version": "2.0.13",
3+
"version": "2.1.0",
44
"description": "Syntax highlighting for JavaScript regular expressions",
55
"keywords": [
66
"javascript",
@@ -10,9 +10,12 @@
1010
],
1111
"repository": "https://github.com/wizard04wsu/javascript-regex",
1212
"license": "MIT",
13-
"main": "index.js",
13+
"main": "lib/javascript-regex.js",
14+
"styleSheets": [
15+
],
1416
"activationHooks": [
1517
"source.js:root-scope-used",
18+
"source.jsx:root-scope-used",
1619
"source.ts:root-scope-used",
1720
"source.flow:root-scope-used"
1821
],

styles/charset-backgrounds.less

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
@import "colors.less";
2+
3+
.syntax--source.syntax--js .syntax--string.syntax--regexp {
4+
5+
//the pattern
6+
.syntax--meta.syntax--pattern {
7+
8+
//character sets
9+
.syntax--constant.syntax--other.syntax--character-class.syntax--set {
10+
background-color: @charset-bg;
11+
12+
//inside the set -> character ranges
13+
.syntax--constant.syntax--other.syntax--character-class.syntax--range {
14+
background-color: @charset-range-bg;
15+
}
16+
}
17+
}
18+
}

styles/colors.less

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Colors used outside of a character set
2+
@content: #7da672;
3+
@delimiter: #00ff00;
4+
@flag: #7afd7a;
5+
@anchor: #ffffff;
6+
@group-delimiter: saturate(#e8e888, 30%, relative);
7+
@group-delimiter-capturing: @backreference;
8+
@group-identifier: desaturate(darken(@group-delimiter, 35%, relative), 70%, relative);
9+
@group-identifier-capturing: desaturate(darken(@group-delimiter-capturing, 35%, relative), 70%, relative);
10+
@group-tag: saturate(lighten(@group-identifier, 25%, relative), 50%, relative);
11+
@group-tag-capturing: saturate(lighten(@group-identifier-capturing, 25%, relative), 50%, relative);
12+
//@group-bg: fade(#e8e888, 1.5%);
13+
@group-bg: transparent;
14+
@backreference: #ffa15d;
15+
@backreference-tag: desaturate(darken(@backreference, 25%, relative), 55%, relative);
16+
@quantifier: #e2608b;
17+
@quantifier-tag: desaturate(darken(@quantifier, 25%, relative), 40%, relative);
18+
@character-special: @character-numeric;
19+
@character-class: #bb8ad2;
20+
@character-class-property: desaturate(darken(@character-class, 30%, relative), 40%, relative);
21+
@character-numeric: #4696e2;
22+
@character-numeric-charcode: desaturate(darken(@character-numeric, 25%, relative), 25%, relative);
23+
@invalid: #ff0000;
24+
25+
// Colors used inside of a character set
26+
@charset: #56b6c2;
27+
@charset-bg: fade(#56b6c2, 6%);
28+
@charset-delimiter: #88eeee;
29+
@charset-character-special: mix(@character-numeric, @charset, 60%);
30+
@charset-character-class: mix(@character-class, @charset, 60%);
31+
@charset-character-class-property: mix(@character-class-property, @charset, 75%);
32+
@charset-character-numeric: @character-numeric;
33+
@charset-character-numeric-charcode: @character-numeric-charcode;
34+
@charset-range-dash: @charset-delimiter;
35+
@charset-range-bg: fade(#88eeee, 6%);

0 commit comments

Comments
 (0)