diff --git a/package.json b/package.json index 5498cfd6..e239756e 100644 --- a/package.json +++ b/package.json @@ -1458,6 +1458,11 @@ "type": "boolean", "default": false }, + "objectscript.autoAdjustName": { + "markdownDescription": "Automatically modify the class name or ROUTINE header to match the file's path when copying or creating a new file. Does not affect `isfs` files.", + "type": "boolean", + "default": true + }, "objectscript.compileOnSave": { "description": "Automatically compile an InterSystems file when saved in the editor.", "type": "boolean", diff --git a/src/commands/webSocketTerminal.ts b/src/commands/webSocketTerminal.ts index 856c81bf..b66b13c8 100644 --- a/src/commands/webSocketTerminal.ts +++ b/src/commands/webSocketTerminal.ts @@ -18,6 +18,8 @@ const keys = { ctrlE: "\x05", ctrlH: "\x08", del: "\x1b[3~", + home: "\x1b\x5b\x48", + end: "\x1b\x5b\x46", }; const actions = { @@ -168,6 +170,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal { outputChannel.appendLine( typeof error == "string" ? error : error instanceof Error ? error.message : JSON.stringify(error) ); + outputChannel.appendLine("Check that the InterSystems server's web server supports WebSockets."); outputChannel.show(true); vscode.window.showErrorMessage( "Failed to initialize WebSocket Terminal. Check 'ObjectScript' Output channel for details.", @@ -372,7 +375,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal { inputArr[inputArr.length - 1].slice(0, this._cursorCol - this._margin) + inputArr[inputArr.length - 1].slice(this._cursorCol - this._margin + 1); this._input = inputArr.join("\r\n"); - this._hideCursorWrite(actions.cursorForward + actions.deleteChar + actions.cursorBack); + this._hideCursorWrite(actions.deleteChar); if (this._input != "" && this._state == "prompt" && this._syntaxColoringEnabled()) { // Syntax color input this._socket.send(JSON.stringify({ type: "color", input: this._input })); @@ -484,6 +487,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal { this._state = "eval"; return; } + case keys.home: case keys.ctrlA: { if (this._state == "prompt" && this._cursorCol - this._margin > 0) { // Move the cursor to the beginning of the line @@ -492,6 +496,7 @@ class WebSocketTerminal implements vscode.Pseudoterminal { } return; } + case keys.end: case keys.ctrlE: { if (this._state == "prompt") { // Move the cursor to the end of the line diff --git a/src/extension.ts b/src/extension.ts index c8a86289..b078b4d5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1045,8 +1045,9 @@ export async function activate(context: vscode.ExtensionContext): Promise { RESTDebugPanel.create(context.extensionUri) ), vscode.commands.registerCommand("vscode-objectscript.exportCurrentFile", exportCurrentFile), - vscode.workspace.onDidCreateFiles((e: vscode.FileCreateEvent) => - Promise.all( + vscode.workspace.onDidCreateFiles((e: vscode.FileCreateEvent) => { + if (!config("autoAdjustName")) return; + return Promise.all( e.files .filter((uri) => !filesystemSchemas.includes(uri.scheme)) .filter((uri) => ["cls", "inc", "int", "mac"].includes(uri.path.split(".").pop().toLowerCase())) @@ -1078,8 +1079,8 @@ export async function activate(context: vscode.ExtensionContext): Promise { // Write the new content to the file return vscode.workspace.fs.writeFile(uri, new TextEncoder().encode(newContent.content.join("\n"))); }) - ) - ), + ); + }), vscode.window.onDidChangeActiveTextEditor((editor: vscode.TextEditor) => { if (config("openClassContracted") && editor && editor.document.languageId === "objectscript-class") { const uri: string = editor.document.uri.toString(); diff --git a/src/providers/FileSystemProvider/TextSearchProvider.ts b/src/providers/FileSystemProvider/TextSearchProvider.ts index 777906f4..916b6732 100644 --- a/src/providers/FileSystemProvider/TextSearchProvider.ts +++ b/src/providers/FileSystemProvider/TextSearchProvider.ts @@ -149,8 +149,8 @@ function searchMatchToLine( // This is in the class description line = descLineToDocLine(content, match.attrline, i); break; - } else if (match.attr == "Super") { - // This is a superclass + } else if (match.attr == "Super" || match.attr == "Name") { + // This is in the class definition line if (content[i].includes(match.text)) { line = i; } @@ -306,7 +306,18 @@ export class TextSearchProvider implements vscode.TextSearchProvider { /** Report matches in `file` to the user */ const reportMatchesForFile = async (file: SearchResult): Promise => { - if (token.isCancellationRequested) { + // The last three checks are needed to protect against + // bad output from the server due to a bug. + if ( + // The user cancelled the search + token.isCancellationRequested || + // The server reported no matches in this file + !file.matches.length || + // The file name is malformed + (file.doc.includes("/") && !/^\/(?:[^/]+\/)+[^/.]*(?:\.[^/.]+)+$/.test(file.doc)) || + (!file.doc.includes("/") && + !/^(%?[\p{L}\d\u{100}-\u{ffff}]+(?:\.[\p{L}\d\u{100}-\u{ffff}]+)+)$/u.test(file.doc)) + ) { return; }