Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// A launch configuration that launches the extension inside a new window
{
"version": "0.1.0",
"configurations": [
Expand All @@ -8,7 +7,6 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [ "${workspaceRoot}/out/**/*.js" ],
"preLaunchTask": "npm: watch"
Expand Down
2,639 changes: 187 additions & 2,452 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 9 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@
"license": "MIT",
"publisher": "bruno-dias",
"engines": {
"vscode": "^1.16.0"
"vscode": "^1.120.0"
},
"categories": [
"Languages"
],
"activationEvents": [
"onLanguage:ink"
"Programming Languages"
],
"main": "./out/src/extension",
"keywords": [
Expand Down Expand Up @@ -59,12 +56,13 @@
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"postinstall": "node ./node_modules/vscode/bin/install"
"watch": "tsc -watch -p ./"
},
"devDependencies": {
"@types/node": "^8.0.34",
"typescript": "^2.5.3",
"vscode": "^1.1.6"
"@types/node": "^25.9.1",
"@types/vscode": "^1.120.0",
"js-yaml": "^4.1.1",
"typescript": "^6.0.3",
"vscode-test": "^1.4.1"
}
}
}
4 changes: 2 additions & 2 deletions src/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export class DivertCompletionProvider implements CompletionItemProvider {
// Make sure we are at the end of a valid divert arrow.
// Ignore a > at the start of a line.
const before = document.getText(new Range(position.with(position.line, 0), position));
if (!/(->|<-) ?$/.test(before)) return;
if (/-> ?-> ?$/.test(before)) return;
if (!/(->|<-) ?$/.test(before)) return [];
if (/-> ?-> ?$/.test(before)) return [];
return NodeMap.getDivertCompletionTargets(document.uri.fsPath, position.line);
}

Expand Down
10 changes: 5 additions & 5 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { getDefinitionByNameAndScope } from "./nodemap";

export class InkDefinitionProvider implements DefinitionProvider {

public provideDefinition (document: TextDocument, position: Position) : Location {
public provideDefinition (document: TextDocument, position: Position) : Location | undefined {
const lineStart = new Position(position.line, 0);
const lineEnd = new Position(position.line + 1, 0);
const before = new Range(lineStart, position);
const after = new Range(position, lineEnd);
const beforeText = document.getText(before);
const afterText = document.getText(after);
const beforeMatch = beforeText.match(/(->\s*\w*)$/)[1];
const afterMatch = afterText.match(/^([\w\.]*)\s*/)[1];
const beforeMatch = beforeText.match(/(->\s*\w*)$/)?.[1] ;
const afterMatch = afterText.match(/^([\w\.]*)\s*/)?.[1];
if (!(beforeMatch && afterMatch)) return;
const name = (beforeMatch + afterMatch).match(/->\s*([\w.]+)/)[1];
const [target] = name.split(".");
const name = (beforeMatch + afterMatch).match(/->\s*([\w.]+)/)?.[1];
const [target] = name ? name.split(".") : [];
return getDefinitionByNameAndScope(target, document.uri.fsPath, position.line);

}
Expand Down
63 changes: 40 additions & 23 deletions src/nodemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ const PERMANENT_DIVERTS = [
new CompletionItem("->", CompletionItemKind.Keyword)
]

class DivertTarget {
constructor ( public readonly name : string | null) { }
public line : number;
public readonly parentFile : NodeMap;
abstract class DivertTarget {
constructor ( public readonly name : string) { }
abstract get line() : number;
abstract get parentFile() : NodeMap;
public toCompletionItem () : CompletionItem {
return new CompletionItem(this.name, CompletionItemKind.Reference);
return new CompletionItem(this.name as string, CompletionItemKind.Reference);
}
}

Expand Down Expand Up @@ -75,8 +75,8 @@ class StitchNode extends DivertTarget {
this.labels = textContent
.split("\n")
.map((line, index) => ({ found: line.match(/^\s*[-\*\+]\s*\((\w+)\)/), index }))
.filter(({ found }) => found !== null)
.map(({ found, index }) => new LabelNode(found[1], index, this));
.map(({ found, index }) => found ? new LabelNode(found[1], index, this) : null)
.filter((v): v is LabelNode => !!v);
}
}

Expand All @@ -89,7 +89,7 @@ class KnotNode extends DivertTarget {
}

constructor (
public readonly name : string | null,
public readonly name : string,
public readonly startLine : number,
public readonly endLine : number,
public readonly parentFile : NodeMap,
Expand All @@ -106,9 +106,14 @@ class KnotNode extends DivertTarget {
, line : string
, index : number) => {
if (line.match(/^\s*={1}\s*(\w+)/)) {
// Found the start of a new stitch.
const newName = line.match(/^\s*={1}\s*(\w+)/)[1];
const node = new StitchNode(lastName, lastStart, index, this, currentNode.join("\n"));

}

// Found the start of a new stitch.
const newNameRegex = line.match(/^\s*={1}\s*(\w+)/);
if (newNameRegex) {
const newName = newNameRegex[1];
const node = new StitchNode(lastName as string, lastStart, index, this, currentNode.join("\n"));
nodes.push(node);
if (index === lines.length -1) {
// The new stitch is also the last line of the knot.
Expand All @@ -117,9 +122,11 @@ class KnotNode extends DivertTarget {
}
return { nodes, currentNode: [line], lastStart: index, lastName: newName };
}


if (index === lines.length - 1) {
// Found the last line.
const node = new StitchNode(lastName, lastStart, index + 1, this, currentNode.join("\n"), this.lastLine);
const node = new StitchNode(lastName as string, lastStart, index + 1, this, currentNode.join("\n"), this.lastLine);
nodes.push(node);
return { nodes, currentNode: [line], lastStart: index, lastName: null };
}
Expand All @@ -145,21 +152,21 @@ class NodeMap {
this.knots = lines
.reduce((
{nodes, currentNode, lastStart, lastName, isFunction}
: { nodes: KnotNode[], currentNode: string[], lastStart : number, lastName : string | null, isFunction }
: { nodes: KnotNode[], currentNode: string[], lastStart : number, lastName : string | null, isFunction: boolean }
, line : string
, index : number) => {
if (line.match(/^\s*===(\s*function)?\s*(\w+)/)) {
const match = line.match(/^\s*===(\s*function)?\s*(\w+)/);
if (match) {
// Found the start of a new knot.
const match = line.match(/^\s*===(\s*function)?\s*(\w+)/);
const newName = match[2];
const foundFunction = (!!match[1]);
const node = new KnotNode(lastName, lastStart, index, this, currentNode.join("\n"), isFunction);
const node = new KnotNode(lastName as string, lastStart, index, this, currentNode.join("\n"), isFunction);
nodes.push(node);
return { nodes, currentNode: [line], lastStart: index, lastName: newName, isFunction: foundFunction };
}
if (index === lines.length - 1) {
// Found the last line
const node = new KnotNode(lastName, lastStart, index + 1, this, currentNode.concat(line).join("\n"), false, true);
const node = new KnotNode(lastName as string, lastStart, index + 1, this, currentNode.concat(line).join("\n"), false, true);
nodes.push(node);
return { nodes, currentNode: [line], lastStart: index, lastName: null, isFunction };
}
Expand All @@ -170,8 +177,13 @@ class NodeMap {
this.includes = lines
.filter(line => line.match(/^\s*INCLUDE\s+(\w+\.ink)/))
.map(line => {
const filename = line.match(/^\s*INCLUDE\s+(\w+\.ink)/)[1];
const match = line.match(/^\s*INCLUDE\s+(\w+\.ink)/);
const filename = match ? match[1] : null;
const dirname = path.dirname(filePath);
if (!filename) {
console.log("Error parsing include line: ", line);
return "";
}
return path.normalize(dirname + path.sep + filename);
});
}
Expand All @@ -197,13 +209,14 @@ const nodeMaps : { [key: string]: NodeMap; } = {};
let mapsDone : boolean = false;

export function generateMaps () : Thenable<void> {
return workspace.findFiles("**/*.ink")
.then(uris => {
return Promise.all(uris.map(({fsPath}) => NodeMap.from(fsPath))).catch(err => console.log);
})
.then((maps : NodeMap[]) => {
return Promise.resolve(workspace.findFiles("**/*.ink"))
.then(uris => Promise.all(uris.map(({ fsPath }) => NodeMap.from(fsPath))))
.then((maps: NodeMap[]) => {
maps.forEach(map => nodeMaps[map.filePath] = map);
mapsDone = true;
})
.catch((err: unknown) => {
console.error("Error generating maps:", err);
});
}

Expand Down Expand Up @@ -263,6 +276,10 @@ function getDivertsInScope (filePath: string, line : number) : DivertTarget[] {
export function getDefinitionByNameAndScope (name: string, filePath : string, line : number) : Location {
const divert = getDivertsInScope(filePath, line)
.find(target => target.name === name);
if (!divert){
console.log(`Divert not found: ${name}`);
return new Location(Uri.file(filePath), new Position(line, 0));
}
return new Location(Uri.file(divert.parentFile.filePath), new Position(divert.line, 0));
}

Expand Down
10 changes: 5 additions & 5 deletions src/wordcount.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';

import { window, workspace, commands, Disposable, ExtensionContext, StatusBarAlignment, StatusBarItem, TextDocument } from "vscode";
import { window, Disposable, StatusBarAlignment, StatusBarItem } from "vscode";

/* Provides word count functionality. Mostly adapted from the example
word counter extension.
*/
export class WordAndNodeCounter {
private _statusBarItem: StatusBarItem;
private _statusBarItem: StatusBarItem | undefined;

private plural (n: number, word: string) : string {
return `${n} ${n === 1 ? word : `${word}s`}`;
Expand Down Expand Up @@ -49,14 +49,14 @@ export class WordAndNodeCounter {
if (line.match(/\}/) !== null) {
scope = "root";
// Add just the part of the line after the }, if anything.
return WordAndNodeCounter.lineReducer({ scope, lines }, (line.match(/}(.*)/)[1]));
return WordAndNodeCounter.lineReducer({ scope, lines }, (line.match(/}(.*)/)?.[1] || ""));
}
return stack;
}
if (scope === "comment") { // Continuing multiline comment
if (line.match(/\*\//) !== null) {
scope = "root";
return WordAndNodeCounter.lineReducer({ scope, lines }, (line.match(/\*\/(.*)/)[1]));
return WordAndNodeCounter.lineReducer({ scope, lines }, (line.match(/\*\/(.*)/)?.[1] || ""));
}
return stack;
}
Expand Down Expand Up @@ -106,7 +106,7 @@ export class WordAndNodeCounter {
}

public dispose() {
this._statusBarItem.dispose();
this._statusBarItem?.dispose();
}
}

Expand Down
7 changes: 5 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
{
"compilerOptions": {
"module": "commonjs",
"module": "nodenext",
"target": "es6",
"outDir": "out",
"lib": [
"es6"
],
"sourceMap": true,
"rootDir": "."
"rootDir": ".",
"types": [
"node"
]
},
"exclude": [
"node_modules",
Expand Down