Skip to content

Commit f7699ff

Browse files
authored
feat: enable rule saving (#145)
1 parent 89b490f commit f7699ff

File tree

4 files changed

+105
-34
lines changed

4 files changed

+105
-34
lines changed

media/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
if (message.command === 'toggle') {
3131
basic.classList.toggle("hidden");
3232
advanced.classList.toggle("hidden");
33+
} else if (message.command === "setPattern") {
34+
const input = document.querySelector('textarea.patternInput');
35+
input.value = message.pattern;
3336
}
3437
});
3538

package.json

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@
189189
"title": "Toggle Advanced Mode",
190190
"category": "Sourcery"
191191
},
192+
{
193+
"command": "sourcery.scan.selectLanguage",
194+
"title": "Select Language",
195+
"category": "Sourcery"
196+
},
192197
{
193198
"command": "sourcery.rule.create",
194199
"title": "Create custom rule",
@@ -207,6 +212,11 @@
207212
],
208213
"menus": {
209214
"view/title": [
215+
{
216+
"command": "sourcery.scan.selectLanguage",
217+
"when": "view == sourcery.rules",
218+
"group": "navigation"
219+
},
210220
{
211221
"command": "sourcery.scan.toggleAdvanced",
212222
"when": "view == sourcery.rules",
@@ -223,7 +233,7 @@
223233
"editor/context": [
224234
{
225235
"submenu": "sourcery.editor",
226-
"group": "z_commands@2"
236+
"group": "1_modification@2"
227237
}
228238
],
229239
"explorer/context": [
@@ -234,7 +244,7 @@
234244
],
235245
"sourcery.editor": [
236246
{
237-
"command": "sourcery.rule.create",
247+
"command": "sourcery.scan.open",
238248
"title": "Create Sourcery rule with this pattern",
239249
"when": "editorLangId==python && editorHasSelection"
240250
}
@@ -271,6 +281,14 @@
271281
{
272282
"command": "sourcery.scan.toggleAdvanced",
273283
"when": "false"
284+
},
285+
{
286+
"command": "sourcery.scan.selectLanguage",
287+
"when": "false"
288+
},
289+
{
290+
"command": "sourcery.rule.create",
291+
"when": "false"
274292
}
275293
]
276294
},

src/extension.ts

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function createLangServer(): LanguageClient {
7777
return new LanguageClient(command, serverOptions, clientOptions);
7878
}
7979

80-
function getValidInput(): string | null {
80+
export function getValidInput(): string | null {
8181
const editor = window.activeTextEditor;
8282

8383
if (editor) {
@@ -157,6 +157,19 @@ function registerCommands(context: ExtensionContext, riProvider: RuleInputProvid
157157
riProvider.toggle();
158158
}));
159159

160+
context.subscriptions.push(commands.registerCommand('sourcery.scan.selectLanguage', () => {
161+
const items = ['python', 'javascript'];
162+
163+
window.showQuickPick(items, {
164+
canPickMany: false,
165+
placeHolder: 'Select language'
166+
}).then((selected) => {
167+
riProvider.setLanguage(selected);
168+
}
169+
);
170+
171+
}));
172+
160173
context.subscriptions.push(commands.registerCommand('sourcery.scan.applyRule', (entry) => {
161174
workspace.openTextDocument(entry.resourceUri).then(doc => {
162175
window.showTextDocument(doc).then(e => {
@@ -184,7 +197,12 @@ function registerCommands(context: ExtensionContext, riProvider: RuleInputProvid
184197
vscode.commands.executeCommand('setContext',
185198
'sourceryRulesActive',
186199
true);
187-
vscode.commands.executeCommand("sourcery.rules.focus")
200+
201+
vscode.commands.executeCommand("sourcery.rules.focus").then( () => {
202+
const input = getValidInput();
203+
riProvider.setPattern(input);
204+
}
205+
);
188206
}));
189207

190208
context.subscriptions.push(commands.registerCommand('sourcery.walkthrough.open', () => {
@@ -202,22 +220,33 @@ function registerCommands(context: ExtensionContext, riProvider: RuleInputProvid
202220
});
203221
}));
204222

205-
context.subscriptions.push(commands.registerCommand('sourcery.rule.create', () => {
206-
const input = getValidInput();
207-
208-
let request: ExecuteCommandParams = {
209-
command: 'config/rule/create',
210-
arguments: [{'selected': input}]
211-
};
212-
languageClient.sendRequest(ExecuteCommandRequest.type, request).then((values) => {
213-
const openPath = Uri.file(path.join(workspace.rootPath, '.sourcery.yaml'));
214-
workspace.openTextDocument(openPath).then(doc => {
215-
const opts: TextDocumentShowOptions = {
216-
selection: new Range(doc.lineCount - 1, 0, doc.lineCount - 1, 0)
217-
};
218-
window.showTextDocument(doc, opts);
223+
context.subscriptions.push(commands.registerCommand('sourcery.rule.create', (rule, advanced: boolean, language: string) => {
224+
225+
vscode.window.showInputBox({
226+
title: "What would you like to call your rule?" ,
227+
prompt: "This should be lowercase, with words separated by hyphens (e.g. my-brilliant-rule)"
228+
}).then((name) => {
229+
if (name) {
230+
let request: ExecuteCommandParams = {
231+
command: 'config/rule/create',
232+
arguments: [{
233+
"rule_id": name,
234+
'rule': rule,
235+
"inplace": false,
236+
'advanced': advanced,
237+
"language": language
238+
}
239+
]
240+
};
241+
languageClient.sendRequest(ExecuteCommandRequest.type, request).then((result) => {
242+
const openPath = Uri.file(result);
243+
workspace.openTextDocument(openPath).then(doc => {
244+
window.showTextDocument(doc);
245+
});
219246
});
247+
}
220248
});
249+
221250
}));
222251

223252
context.subscriptions.push(commands.registerCommand('sourcery.refactor.workspace', (resource: Uri, selected?: Uri[]) => {
@@ -231,30 +260,31 @@ function registerCommands(context: ExtensionContext, riProvider: RuleInputProvid
231260
languageClient.sendRequest(ExecuteCommandRequest.type, request);
232261
}));
233262

234-
context.subscriptions.push(commands.registerCommand('sourcery.scan.rule', (rule, advanced: boolean, inplace: boolean, language: string) => {
235-
if (inplace) {
263+
context.subscriptions.push(commands.registerCommand('sourcery.scan.rule', (rule, advanced: boolean, fix: boolean, language: string) => {
264+
if (fix) {
236265
vscode.window
237266
.showInformationMessage("Are you sure?", "Yes", "No")
238267
.then(answer => {
239268
if (answer === "Yes") {
240-
runScan(rule, advanced, inplace, language);
269+
runScan(rule, advanced, fix, language);
241270
}
242271
})
243272
} else {
244-
runScan(rule, advanced, inplace, language);
273+
runScan(rule, advanced, fix, language);
245274
}
246275

247276
}));
248277

249-
function runScan(rule, advanced: boolean, inplace: boolean, language: string) {
278+
function runScan(rule, advanced: boolean, fix: boolean, language: string) {
250279
tree.clear();
251280
treeView.title = "Results";
252281
let request: ExecuteCommandParams = {
253282
command: 'rule/scan',
254283
arguments: [{
255284
'rule': rule,
285+
'rule_id': 'test-rule',
256286
'advanced': advanced,
257-
'inplace': inplace,
287+
'inplace': fix,
258288
"language": language
259289
}]
260290
};

src/rule-search.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as vscode from 'vscode';
2-
import {window} from 'vscode';
32
import {randomBytes} from "crypto";
3+
import {getValidInput} from "./extension";
44

55
export class RuleInputProvider implements vscode.WebviewViewProvider {
66

@@ -18,10 +18,19 @@ export class RuleInputProvider implements vscode.WebviewViewProvider {
1818
this._extensionUri = _context.extensionUri;
1919
}
2020

21-
public async toggle() {
21+
public toggle() {
2222
this._view.webview.postMessage({ command: 'toggle' });
2323
}
2424

25+
public setLanguage(language) {
26+
this._languageId = language;
27+
this._setTitle();
28+
}
29+
30+
public setPattern(pattern) {
31+
this._view.webview.postMessage( {command: "setPattern", pattern: pattern})
32+
}
33+
2534
public async resolveWebviewView(
2635
webviewView: vscode.WebviewView,
2736
context: vscode.WebviewViewResolveContext,
@@ -38,11 +47,19 @@ export class RuleInputProvider implements vscode.WebviewViewProvider {
3847
]
3948
};
4049

41-
this._languageId = this._resolveLanguage();
42-
this._setTitle();
50+
this._setViewState();
51+
52+
webviewView.onDidChangeVisibility(() => {
53+
if (this._view.visible) {
54+
this._setViewState();
55+
}
56+
});
4357

4458
webviewView.webview.html = await this._getHtmlForWebview(webviewView.webview);
4559

60+
const input = getValidInput();
61+
this.setPattern(input);
62+
4663
webviewView.webview.onDidReceiveMessage(async data => {
4764
switch (data.type) {
4865
case "scan": {
@@ -54,12 +71,18 @@ export class RuleInputProvider implements vscode.WebviewViewProvider {
5471
break;
5572
}
5673
case "save": {
57-
window.showInformationMessage("Saving rules directly not yet available.")
74+
vscode.commands.executeCommand("sourcery.rule.create", data.rule, data.advanced, this._languageId);
75+
break;
5876
}
5977
}
6078
});
6179
}
6280

81+
private _setViewState() {
82+
this._languageId = this._resolveLanguage();
83+
this._setTitle();
84+
}
85+
6386
private _setTitle() {
6487
this._view.title = "Rules - " + this._languageId;
6588
}
@@ -88,7 +111,7 @@ export class RuleInputProvider implements vscode.WebviewViewProvider {
88111
return languageId;
89112
}
90113
}
91-
return languageId;
114+
return "python";
92115
}
93116

94117
// Default to python
@@ -138,27 +161,24 @@ export class RuleInputProvider implements vscode.WebviewViewProvider {
138161
<label for="patternInput">Pattern</label>
139162
<textarea
140163
class="patternInput""
141-
placeholder="Enter your pattern here..."
142164
nonce="${nonce}"
143165
></textarea>
144166
<label for="replacementInput">Replacement</label>
145167
<textarea
146168
class="replacementInput""
147-
placeholder="Enter your replacement here..."
148169
nonce="${nonce}"
149170
></textarea>
150171
<label for="conditionInput">Condition</label>
151172
<textarea
152173
class="conditionInput""
153-
placeholder="Enter your condition here..."
154174
nonce="${nonce}"
155175
></textarea>
156176
</div>
157177
<div id="advancedContainer" class="hidden">
158178
<label for="ruleInput">Rule</label>
159179
<textarea
160180
class="ruleInput""
161-
placeholder="Enter your rule here in yaml format.\nHere's an example:\nall:\n- pattern: typing.List\n replacement: list\n- not:\n inside:\n kind: import_from_statement"
181+
placeholder="all:\n- pattern: typing.List\n replacement: list\n- not:\n inside:\n kind: import_from_statement"
162182
nonce="${nonce}"
163183
></textarea>
164184
</div>

0 commit comments

Comments
 (0)