Skip to content

Commit 0b265db

Browse files
author
IORP
committed
update
1 parent 5b46398 commit 0b265db

File tree

4 files changed

+132
-57
lines changed

4 files changed

+132
-57
lines changed

README.md

+14-6
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@ developed and maintained by Indian Ocean Roleplay™
1919

2020
# Define Custom Snippet Anywhere
2121

22+
you can define two types of snippet
23+
24+
\*note: second type support autocompletion of parameters.
25+
2226
```
23-
/*
24-
#defineSnip init_cmd cmd:function(playerid, const params[]) {\n\treturn 1;\n}
25-
*/
27+
//#snippet init_cmd cmd:myfunction(playerid, const params[]) {\n\treturn 1;\n}
28+
29+
//#function createcar(vehicleid, Float:posX, Float:posY, Float:posZ);
2630
```
2731

2832
# Usage of .pawnignore
33+
2934
in big projects, you might have lot's of file but you don't want definitions from all files.
3035
so just use .pawnignore to ignore a folder or file from workspace. The usage is very simple,
31-
just right click on folder or file and click on ``Add to .pawnignore`` this works exactly like
32-
``.gitignore``
36+
just right click on folder or file and click on `Add to .pawnignore` this works exactly like
37+
`.gitignore`
3338

3439
# Installation
3540

@@ -48,6 +53,7 @@ Alternatively, you can check out the source code or view the marketplace page:
4853
press Ctrl+Shift+P or F1 and then type **>Initialize Pawn Build Task**
4954

5055
## Explanation
56+
5157
`"command": "${workspaceRoot}/pawno/pawncc.exe",` is the important bit here,
5258
this is the path to your Pawn compiler and I've assumed most of you have a
5359
left-over `pawno` folder from that long dead text editor! This folder not only
@@ -83,7 +89,9 @@ command palette with CTRL+Shift+P (Windows) or CMD+Shift+P (Mac) and type
8389
`Run Task`, hit enter and select `build-normal`.
8490

8591
## Important Note
92+
8693
sometime, you will get errors lke arguments are invalid. We have seen that problem with powershell only. so make sure, you have selected cmd (commmand prompt) to build your gamemode file.
8794

8895
# Thank you
89-
we are open for suggestions, please open a issue and share your idea so that we can improve this extension.
96+
97+
we are open for suggestions, please open a issue and share your idea so that we can improve this extension.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
"onCommand:pawn-community-tool.pawnignore",
4040
"onCommand:pawn-community-tool.initTask",
4141
"onCommand:pawn-community-tool.seq-num",
42-
"onLanguage:pawn"
42+
"onLanguage:pawn",
43+
"onLanguage:Pawn"
4344
],
4445
"main": "./out/client/extension.js",
4546
"contributes": {
@@ -209,4 +210,4 @@
209210
"@types/node": "^13.13.41",
210211
"vscode": "^1.1.37"
211212
}
212-
}
213+
}

src/server/parser.ts

+109-47
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ interface PawnFunction {
1616
let pawnFuncCollection: Map<string, PawnFunction> = new Map();
1717
let pawnWords: Map<string, CompletionItem[]> = new Map();
1818

19-
let commentRegex = RegExp(/^\/\*/gm);
20-
let commentEndRegex = RegExp(/^\*\//gm);
19+
let commentRegex = RegExp(/\/\*/gm);
20+
let commentEndRegex = RegExp(/\*\//gm);
2121

2222
export const resetAutocompletes = () => {
2323
pawnFuncCollection.clear();
@@ -27,13 +27,13 @@ export const parseDefine = (textDocument: TextDocument) => {
2727
const regexDefine = /^(\s*)#define\s+([^\s()]{1,})\s+([^\s]{1,})$/gm;
2828
const content = textDocument.getText();
2929
const splitContent = content.split('\n');
30-
let excempt = false;
30+
let excempt = 0;
3131
splitContent.forEach((cont: string, index: number) => {
3232
if (commentRegex.test(cont)) {
33-
excempt = true;
33+
excempt++;
3434
} else if (commentEndRegex.test(cont)) {
35-
excempt = false;
36-
} else if (!excempt) {
35+
excempt--;
36+
} else if (excempt === 0) {
3737
var m;
3838
do {
3939
m = regexDefine.exec(cont);
@@ -69,13 +69,13 @@ export const parsefuncsDefines = (textDocument: TextDocument) => {
6969
const regex = /^(\s*)#define\s+([\S]{1,})\((.*?)\)/gm;
7070
const content = textDocument.getText();
7171
const splitContent = content.split('\n');
72-
let excempt = false;
72+
let excempt = 0;
7373
splitContent.forEach((cont: string, index: number) => {
7474
if (commentRegex.test(cont)) {
75-
excempt = true;
75+
excempt++;
7676
} else if (commentEndRegex.test(cont)) {
77-
excempt = false;
78-
} else if (!excempt) {
77+
excempt--;
78+
} else if (excempt === 0) {
7979
var m;
8080
do {
8181
m = regex.exec(cont);
@@ -149,31 +149,33 @@ export const parsefuncsDefines = (textDocument: TextDocument) => {
149149
};
150150

151151
export const parseCustomSnip = (textDocument: TextDocument) => {
152-
const regexDefine = /^(\s*)\/\/#definesnip\s+([^\s]{1,})\s+(.*?)$/gm;
152+
const regexDefine = /^\/\/#snippet\s([^\s]{1,})\s([^\s].{1,})$/gm;
153+
const regexFunction = /^\/\/#function\s([\S]{1,})\((.*?)\)/gm;
153154
const content = textDocument.getText();
154155
const splitContent = content.split('\n');
155-
let excempt = false;
156+
157+
let excempt = 0;
156158
splitContent.forEach((cont: string, index: number) => {
157159
if (commentRegex.test(cont)) {
158-
excempt = true;
160+
excempt++;
159161
} else if (commentEndRegex.test(cont)) {
160-
excempt = false;
161-
} else if (!excempt) {
162-
var m;
162+
excempt--;
163+
} else if (excempt === 0) {
164+
let fisrtReg;
163165
do {
164-
m = regexDefine.exec(cont);
165-
if (m) {
166-
let func = m[2];
167-
let args = m[3];
166+
fisrtReg = regexDefine.exec(cont);
167+
if (fisrtReg) {
168+
let func = fisrtReg[1];
169+
let args = fisrtReg[2];
168170
const newSnip: CompletionItem = {
169171
label: func,
170-
kind: CompletionItemKind.Text,
172+
kind: CompletionItemKind.Function,
171173
insertText: args,
172174
documentation: `${func} ${args}`
173175
};
174176
const newDef: Definition = Location.create(textDocument.uri, {
175-
start: { line: index, character: m.input.indexOf(func) },
176-
end: { line: index, character: m.input.indexOf(func) + func.length }
177+
start: { line: index, character: fisrtReg.input.indexOf(func) },
178+
end: { line: index, character: fisrtReg.input.indexOf(func) + func.length }
177179

178180
});
179181
const pwnFun: PawnFunction = {
@@ -182,12 +184,70 @@ export const parseCustomSnip = (textDocument: TextDocument) => {
182184
definition: newDef,
183185
type: 'customsnip'
184186
};
185-
const findSnip = pawnFuncCollection.get(func);
186-
if (findSnip === undefined) {
187-
pawnFuncCollection.set(func, pwnFun);
187+
pawnFuncCollection.set(func, pwnFun);
188+
}
189+
} while (fisrtReg);
190+
var m;
191+
do {
192+
m = regexFunction.exec(cont);
193+
if (m) {
194+
let func = m[1];
195+
let args = m[2];
196+
let doc: string = '';
197+
let endDoc = -1;
198+
if (splitContent[index - 1] !== undefined) endDoc = splitContent[index - 1].indexOf('*/');
199+
if (endDoc !== -1) {
200+
let startDoc = -1;
201+
let inNum = index;
202+
while (inNum >= 0) {
203+
inNum--;
204+
if (splitContent[inNum] === undefined) continue;
205+
startDoc = splitContent[inNum].indexOf('/*');
206+
if (startDoc !== -1) {
207+
if (inNum === index) {
208+
doc = splitContent[index];
209+
} else if (inNum < index) {
210+
while (inNum < index) {
211+
doc += splitContent[inNum] + '\n\n';
212+
inNum++;
213+
214+
}
215+
}
216+
break;
217+
}
218+
}
219+
}
220+
doc = doc.replace('/*', '').replace('*/', '').trim();
221+
const newSnip: CompletionItem = {
222+
label: func + '(' + args + ')',
223+
kind: CompletionItemKind.Function,
224+
insertText: func + '(' + args + ')',
225+
documentation: doc,
226+
};
227+
const newDef: Definition = Location.create(textDocument.uri, {
228+
start: { line: index, character: m.input.indexOf(func) },
229+
end: { line: index, character: m.input.indexOf(func) + func.length }
230+
231+
});
232+
let params: ParameterInformation[] = [];
233+
if (args.trim().length > 0) {
234+
params = args.split(',').map((value) => ({ label: value.trim() }));
188235
} else {
189-
if (findSnip.type === 'macrofunction' || findSnip.type === 'macrodefine') pawnFuncCollection.set(func, pwnFun);
236+
params = [];
237+
}
238+
const pwnFun: PawnFunction = {
239+
textDocument: textDocument,
240+
definition: newDef,
241+
completion: newSnip,
242+
params,
243+
type: 'customsnip'
244+
};
245+
const indexPos = func.indexOf(':');
246+
if (indexPos !== -1) {
247+
const resOut = /:(.*)/gm.exec(func);
248+
if (resOut) func = resOut[1];
190249
}
250+
pawnFuncCollection.set(func, pwnFun);
191251
}
192252
} while (m);
193253
}
@@ -198,13 +258,13 @@ export const parsefuncs = (textDocument: TextDocument) => {
198258
const regex = /^(\s*)(public|stock|function|func)\s+([\S]{1,})\((.*?)\)/gm;
199259
const content = textDocument.getText();
200260
const splitContent = content.split('\n');
201-
let excempt = false;
261+
let excempt = 0;
202262
splitContent.forEach((cont: string, index: number) => {
203263
if (commentRegex.test(cont)) {
204-
excempt = true;
264+
excempt++;
205265
} else if (commentEndRegex.test(cont)) {
206-
excempt = false;
207-
} else if (!excempt) {
266+
excempt--;
267+
} else if (excempt === 0) {
208268
var m;
209269
do {
210270
m = regex.exec(cont);
@@ -281,13 +341,13 @@ export const parsefuncsNonPrefix = (textDocument: TextDocument) => {
281341
const regex = /^([\S]{1,})\((.*?)\)/gm;
282342
const content = textDocument.getText();
283343
const splitContent = content.split('\n');
284-
let excempt = false;
344+
let excempt = 0;
285345
splitContent.forEach((cont: string, index: number) => {
286346
if (commentRegex.test(cont)) {
287-
excempt = true;
347+
excempt++;
288348
} else if (commentEndRegex.test(cont)) {
289-
excempt = false;
290-
} else if (!excempt) {
349+
excempt--;
350+
} else if (excempt === 0) {
291351
var m;
292352
do {
293353
m = regex.exec(cont);
@@ -364,13 +424,13 @@ export const parseNatives = (textDocument: TextDocument) => {
364424
const regex = /^(\s*)(native)\s([\S]{1,})\((.*?)\)/gm;
365425
const content = textDocument.getText();
366426
const splitContent = content.split('\n');
367-
let excempt = false;
427+
let excempt = 0;
368428
splitContent.forEach((cont: string, index: number) => {
369429
if (commentRegex.test(cont)) {
370-
excempt = true;
430+
excempt++;
371431
} else if (commentEndRegex.test(cont)) {
372-
excempt = false;
373-
} else if (!excempt) {
432+
excempt--;
433+
} else if (excempt === 0) {
374434
var m;
375435
do {
376436
m = regex.exec(cont);
@@ -435,7 +495,7 @@ export const parseNatives = (textDocument: TextDocument) => {
435495
if (findSnip === undefined) {
436496
pawnFuncCollection.set(func, pwnFun);
437497
} else {
438-
pawnFuncCollection.set(func, pwnFun);
498+
if (findSnip.type !== 'customsnip') pawnFuncCollection.set(func, pwnFun);
439499
}
440500
}
441501
} while (m);
@@ -449,13 +509,13 @@ export const parseWords = (textDocument: TextDocument) => {
449509
const splitContent = content.split('\n');
450510
const words: string[] = [];
451511
const wordCompletion: CompletionItem[] = [];
452-
let excempt = false;
512+
let excempt = 0;
453513
splitContent.forEach((cont: string, index: number) => {
454514
if (commentRegex.test(cont)) {
455-
excempt = true;
515+
excempt++;
456516
} else if (commentEndRegex.test(cont)) {
457-
excempt = false;
458-
} else if (!excempt) {
517+
excempt--;
518+
} else if (excempt === 0 && !RegExp(/^\/\//gm).test(cont.trim())) {
459519
var m;
460520
do {
461521
m = regex.exec(cont);
@@ -511,11 +571,13 @@ const isParseAllowed = async (textDocument: TextDocument) => {
511571
return true;
512572
};
513573

514-
export const parseSnippets = async (textDocument: TextDocument) => {
574+
export const parseSnippets = async (textDocument: TextDocument, reset: boolean = true) => {
515575
const ext = path.extname(textDocument.uri);
516576
if (ext !== ".pwn" && ext !== ".inc") return false;
517-
pawnFuncCollection.forEach((value: PawnFunction, key: string) => { if (value.textDocument.uri === textDocument.uri) pawnFuncCollection.delete(key); });
518-
pawnWords.delete(textDocument.uri);
577+
if (reset) {
578+
pawnFuncCollection.forEach((value: PawnFunction, key: string) => { if (value.textDocument.uri === textDocument.uri) pawnFuncCollection.delete(key); });
579+
pawnWords.delete(textDocument.uri);
580+
}
519581
if (!await isParseAllowed(textDocument)) return;
520582

521583
const allowDefine = (await connection.workspace.getConfiguration({ section: 'pawn.language.allowDefine' })) as true | false | null;

src/server/server.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,20 @@ connection.onInitialized(() => {
3838

3939
connection.onNotification("revalidateAllOpenedDocuments", () => {
4040
resetAutocompletes();
41-
documents.all().forEach(parseSnippets);
41+
documents.all().forEach(doc => parseSnippets(doc));
4242
});
4343

4444
connection.onDidChangeConfiguration(() => {
45-
documents.all().forEach(parseSnippets);
45+
documents.all().forEach(doc => parseSnippets(doc));
4646
});
4747

4848
documents.onDidClose(() => {
4949
});
5050

51+
documents.onDidChangeContent(change => {
52+
parseSnippets(change.document, false);
53+
});
54+
5155
documents.onDidSave(change => {
5256
parseSnippets(change.document);
5357
});

0 commit comments

Comments
 (0)