From 24a89f33162a18132b15db69582a1f0c487d3cdb Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 5 Mar 2024 23:26:50 -0500 Subject: [PATCH 1/5] Add installer to client Signed-off-by: worksofliam --- client/package-lock.json | 40 +++++----- client/package.json | 6 +- client/src/clRunner.ts | 77 +++++++++++++++++++ client/src/extension.ts | 7 +- .../external/handlers/vscodeIbmi/gencmdxml.ts | 26 +++++++ .../{vscodeIbmi.ts => vscodeIbmi/index.ts} | 56 +++++++++++--- 6 files changed, 175 insertions(+), 37 deletions(-) create mode 100644 client/src/clRunner.ts create mode 100644 client/src/external/handlers/vscodeIbmi/gencmdxml.ts rename client/src/external/handlers/{vscodeIbmi.ts => vscodeIbmi/index.ts} (70%) diff --git a/client/package-lock.json b/client/package-lock.json index 37bd743..e1cd602 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,10 +10,10 @@ "license": "MIT", "dependencies": { "vscode-languageclient": "5.1.1", - "xml2js": "^0.4.23" + "xml2js": "^0.6.2" }, "devDependencies": { - "@halcyontech/vscode-ibmi-types": "^2.6.1", + "@halcyontech/vscode-ibmi-types": "^2.8.0", "@types/node": "^18.11.5", "@types/vscode": "^1.50.0", "@types/xml2js": "^0.4.11", @@ -24,9 +24,9 @@ } }, "node_modules/@halcyontech/vscode-ibmi-types": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@halcyontech/vscode-ibmi-types/-/vscode-ibmi-types-2.6.1.tgz", - "integrity": "sha512-oEIPj1eyuyGVXqEiUBc0LIyg5Zv0hgEv90YAbmipsJ19YoCpm1MNsMl2cPmxVPPlyi8V13xptdZ8gABuTvlVRw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@halcyontech/vscode-ibmi-types/-/vscode-ibmi-types-2.8.0.tgz", + "integrity": "sha512-IpSiItq/SsScztZbSn+KuTAqGSZ9azVL6ZlMzrzQsj33dmbjX+gqnNIymVknGIZGXqJqQ8XwMXLuxCYONImltQ==", "dev": true }, "node_modules/@tootallnate/once": { @@ -414,9 +414,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -510,9 +510,9 @@ "dev": true }, "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -532,9 +532,9 @@ }, "dependencies": { "@halcyontech/vscode-ibmi-types": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@halcyontech/vscode-ibmi-types/-/vscode-ibmi-types-2.6.1.tgz", - "integrity": "sha512-oEIPj1eyuyGVXqEiUBc0LIyg5Zv0hgEv90YAbmipsJ19YoCpm1MNsMl2cPmxVPPlyi8V13xptdZ8gABuTvlVRw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@halcyontech/vscode-ibmi-types/-/vscode-ibmi-types-2.8.0.tgz", + "integrity": "sha512-IpSiItq/SsScztZbSn+KuTAqGSZ9azVL6ZlMzrzQsj33dmbjX+gqnNIymVknGIZGXqJqQ8XwMXLuxCYONImltQ==", "dev": true }, "@tootallnate/once": { @@ -859,9 +859,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "setimmediate": { "version": "1.0.5", @@ -943,9 +943,9 @@ "dev": true }, "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", "requires": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" diff --git a/client/package.json b/client/package.json index 8692388..336db82 100644 --- a/client/package.json +++ b/client/package.json @@ -10,13 +10,13 @@ }, "dependencies": { "vscode-languageclient": "5.1.1", - "xml2js": "^0.4.23" + "xml2js": "^0.6.2" }, "devDependencies": { + "@halcyontech/vscode-ibmi-types": "^2.8.0", "@types/node": "^18.11.5", "@types/vscode": "^1.50.0", "@types/xml2js": "^0.4.11", - "@vscode/test-electron": "^2.1.2", - "@halcyontech/vscode-ibmi-types": "^2.6.1" + "@vscode/test-electron": "^2.1.2" } } diff --git a/client/src/clRunner.ts b/client/src/clRunner.ts new file mode 100644 index 0000000..6ca5f47 --- /dev/null +++ b/client/src/clRunner.ts @@ -0,0 +1,77 @@ +import { EndOfLine, ExtensionContext, Position, Range, Selection, TextDocument, commands, window } from "vscode"; +import { getInstance } from './external/api/ibmi'; + +export function initialiseRunner(context: ExtensionContext) { + context.subscriptions.push( + commands.registerCommand(`code-for-ibmi.cl.runSelected`, async () => { + const instance = getInstance(); + const editor = window.activeTextEditor; + + if (editor) { + const document = editor.document; + + if (document && document.languageId === `cl`) { + const connection = instance.getConnection(); + + if (connection) { + const selectedCommand = getCommandString(editor.selection, document); + + if (selectedCommand.range) { + editor.selection = new Selection( + new Position(selectedCommand.range.start, 0), + new Position(selectedCommand.range.end, document.lineAt(selectedCommand.range.end).range.end.character) + ); + } + + await commands.executeCommand(`code-for-ibmi.runAction`, editor.document.uri, undefined, { + command: selectedCommand.content, + environment: `ile`, + name: `CL command`, + }); + } + } + } + }) + ) +} + +function getCommandString(selection: Selection, document: TextDocument): {content: string, range?: {start: number, end: number}} { + if (selection.isEmpty) { + let line = selection.start.line; + + // First let's find out if this command belong to another command + while((line-1) >= 0 && document.lineAt(line-1).text.trim().endsWith(`+`) && line-- > 0); + + // Then fetch all the lines + const startLine = line; + let content = [document.lineAt(line).text.trim()]; + + // Then we fetch the next continuation lines + while (content[content.length - 1].endsWith(`+`)) { + line += 1; + content.push(document.lineAt(line).text.trim()); + } + + return { + content: removePlusJoins(content).join(` `), + range: { + start: startLine, + end: line + } + }; + } else { + const lines = document.getText(new Range(selection.start, selection.end)).split(document.eol === EndOfLine.CRLF ? `\r\n` : `\n`); + return { + content: removePlusJoins(lines).join(` `) + }; + } +} + +function removePlusJoins(lines: string[]) { + for (let i = 0; i < lines.length; i++) { + lines[i] = lines[i].trim(); + if (lines[i].endsWith(`+`)) lines[i] = lines[i].substring(0, lines[i].length - 1); + } + + return lines; +} \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index b3ef08e..3adf1e3 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -11,6 +11,7 @@ import { import {getHandler} from "./external"; import { loadBase } from './external/api/ibmi'; +import { initialiseRunner } from './clRunner'; let client: LanguageClient; @@ -53,7 +54,7 @@ export function activate(context: ExtensionContext) { serverOptions, clientOptions ); -5 + // Start the client. This will also launch the server client.start(); @@ -77,7 +78,9 @@ export function activate(context: ExtensionContext) { return definition; } }); - }) + }); + + initialiseRunner(context); } export function deactivate(): Thenable | undefined { diff --git a/client/src/external/handlers/vscodeIbmi/gencmdxml.ts b/client/src/external/handlers/vscodeIbmi/gencmdxml.ts new file mode 100644 index 0000000..b91da30 --- /dev/null +++ b/client/src/external/handlers/vscodeIbmi/gencmdxml.ts @@ -0,0 +1,26 @@ +export const content = [ + `pgm parm(&name &cmd)`, + ` dcl &name *char 10`, + ` dcl &cmd *char 20`, + ` dcl &destinfo *char 64`, + ` dcl &destfmt *char 8 value('DEST0200')`, + ` dcl &rcvvar *char 1`, + ` dcl &rcvfmt *char 8 value('CMDD0100')`, + ` dcl &error *char 16 value(x'00000010')`, + ` dcl &null2 *char 2 value(x'0000')`, + ` dcl &null3 *char 3 value(x'000000')`, + ` dcl &null10 *char 10 value(x'00000000000000000000')`, + ` /*chgvar &cmd value('GENDDL *LIBL') */`, + ` chgvar %bin(&destinfo 1 4) value(0) /* CCSID */`, + ` chgvar %sst(&destinfo 5 2) value(&null2) /* country */`, + ` chgvar %sst(&destinfo 7 3) value(&null3) /* language */`, + ` chgvar %sst(&destinfo 10 3) value(&null3) /* reserved */`, + ` chgvar %bin(&destinfo 13 4) value(0) /* path type */`, + ` chgvar %bin(&destinfo 17 4) value(15) /* path name len */`, + ` chgvar %sst(&destinfo 21 2) value('/') /* delimiter */`, + ` chgvar %sst(&destinfo 23 10) value(&null10) /* reserved */`, + ` chgvar %sst(&destinfo 33 32) value('/tmp/' *tcat &name)`, + ` call qcdrcmdd (&cmd &destinfo &destfmt +`, + ` &rcvvar &rcvfmt &error)`, + `endpgm` +]; \ No newline at end of file diff --git a/client/src/external/handlers/vscodeIbmi.ts b/client/src/external/handlers/vscodeIbmi/index.ts similarity index 70% rename from client/src/external/handlers/vscodeIbmi.ts rename to client/src/external/handlers/vscodeIbmi/index.ts index 6a2a797..7208db7 100644 --- a/client/src/external/handlers/vscodeIbmi.ts +++ b/client/src/external/handlers/vscodeIbmi/index.ts @@ -1,8 +1,10 @@ -import Handler from './handler'; +import Handler from '../handler'; import * as xml2js from "xml2js"; -import { getInstance } from '../api/ibmi'; +import { getInstance } from '../../api/ibmi'; import Instance from '@halcyontech/vscode-ibmi-types/api/Instance'; +import { content as gencmdxml } from './gencmdxml'; + enum Status { NotChecked, Installed, @@ -31,6 +33,26 @@ export default class vscodeIbmi extends Handler { return false; } + async install(): Promise { + const instance = this.instance; + const connection = instance.getConnection()!; + const content = instance.getContent()!; + const config = instance.getConfig()!; + + const tempLib = config.tempLibrary; + + //It may exist already so we just ignore the error + await connection.runCommand({ command: `CRTSRCPF ${tempLib}/QTOOLS`, noLibList: true }) + + await content.uploadMemberContent(undefined, tempLib, `QTOOLS`, `GENCMDXML`, gencmdxml.join(`\n`)); + const createResult = await connection.runCommand({ + command: `CRTBNDCL PGM(${tempLib}/GENCMDXML) SRCFILE(${tempLib}/QTOOLS) DBGVIEW(*SOURCE) TEXT('vscode-ibmi xml generator for commands')`, + noLibList: true + }); + + return createResult.code === 0; + } + /** * Returns DSPFFD outfile rows */ @@ -102,15 +124,13 @@ export default class vscodeIbmi extends Handler { if (this.installed === Status.Installed) return true; if (this.instance) { const connection = this.instance.getConnection(); + const content = this.instance.getContent(); const config = this.instance.getConfig(); const tempLib = config.tempLibrary; - const checkResult = await connection.runCommand({ - command: `CHKOBJ OBJ(${tempLib}/GENCMDXML) OBJTYPE(*PGM)`, - noLibList: true - }); + const exists = await content.checkObject({ type: `*PGM`, library: tempLib, name: `GENCMDXML`}); - if (checkResult.code === 0) { + if (exists) { this.installed = Status.Installed; return true; } @@ -118,6 +138,14 @@ export default class vscodeIbmi extends Handler { this.installed = Status.NotInstalled; } + if (this.installed === Status.NotInstalled) { + const installed = await this.install(); + if (installed) { + this.installed = Status.Installed; + return true; + } + } + return false; } @@ -145,11 +173,15 @@ export default class vscodeIbmi extends Handler { if (callResult.code === 0) { console.log(callResult); - const xml = await content.downloadStreamfile(`/tmp/${targetName}`); - - const commandData = await xml2js.parseStringPromise(xml); - - return commandData; + try { + const xml = (await content.downloadStreamfileRaw(`/tmp/${targetName}`)).toString(); + + const commandData = await xml2js.parseStringPromise(xml); + + return commandData; + } catch (e) { + console.log(`Command likely doesn't exist: ${targetCommand}: ${e.message}`); + } } return undefined; From 837cdba7392bd32823b523c708131f880c13e4d1 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 5 Mar 2024 23:26:59 -0500 Subject: [PATCH 2/5] Remove unused files Signed-off-by: worksofliam --- client/src/test/completion.test.ts | 39 -------------------------- client/src/test/diagnostics.test.ts | 37 ------------------------- client/src/test/helper.ts | 43 ----------------------------- client/src/test/index.ts | 40 --------------------------- client/src/test/runTest.ts | 24 ---------------- 5 files changed, 183 deletions(-) delete mode 100644 client/src/test/completion.test.ts delete mode 100644 client/src/test/diagnostics.test.ts delete mode 100644 client/src/test/helper.ts delete mode 100644 client/src/test/index.ts delete mode 100644 client/src/test/runTest.ts diff --git a/client/src/test/completion.test.ts b/client/src/test/completion.test.ts deleted file mode 100644 index b09dbc3..0000000 --- a/client/src/test/completion.test.ts +++ /dev/null @@ -1,39 +0,0 @@ - -import * as vscode from 'vscode'; -import * as assert from 'assert'; -import { getDocUri, activate } from './helper'; - -suite('Should do completion', () => { - const docUri = getDocUri('completion.txt'); - - test('Completes JS/TS in txt file', async () => { - await testCompletion(docUri, new vscode.Position(0, 0), { - items: [ - { label: 'JavaScript', kind: vscode.CompletionItemKind.Text }, - { label: 'TypeScript', kind: vscode.CompletionItemKind.Text } - ] - }); - }); -}); - -async function testCompletion( - docUri: vscode.Uri, - position: vscode.Position, - expectedCompletionList: vscode.CompletionList -) { - await activate(docUri); - - // Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion - const actualCompletionList = (await vscode.commands.executeCommand( - 'vscode.executeCompletionItemProvider', - docUri, - position - )) as vscode.CompletionList; - - assert.ok(actualCompletionList.items.length >= 2); - expectedCompletionList.items.forEach((expectedItem, i) => { - const actualItem = actualCompletionList.items[i]; - assert.equal(actualItem.label, expectedItem.label); - assert.equal(actualItem.kind, expectedItem.kind); - }); -} diff --git a/client/src/test/diagnostics.test.ts b/client/src/test/diagnostics.test.ts deleted file mode 100644 index 7e3e1b3..0000000 --- a/client/src/test/diagnostics.test.ts +++ /dev/null @@ -1,37 +0,0 @@ - -import * as vscode from 'vscode'; -import * as assert from 'assert'; -import { getDocUri, activate } from './helper'; - -suite('Should get diagnostics', () => { - const docUri = getDocUri('diagnostics.txt'); - - test('Diagnoses uppercase texts', async () => { - await testDiagnostics(docUri, [ - { message: 'ANY is all uppercase.', range: toRange(0, 0, 0, 3), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }, - { message: 'ANY is all uppercase.', range: toRange(0, 14, 0, 17), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }, - { message: 'OS is all uppercase.', range: toRange(0, 18, 0, 20), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' } - ]); - }); -}); - -function toRange(sLine: number, sChar: number, eLine: number, eChar: number) { - const start = new vscode.Position(sLine, sChar); - const end = new vscode.Position(eLine, eChar); - return new vscode.Range(start, end); -} - -async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: vscode.Diagnostic[]) { - await activate(docUri); - - const actualDiagnostics = vscode.languages.getDiagnostics(docUri); - - assert.equal(actualDiagnostics.length, expectedDiagnostics.length); - - expectedDiagnostics.forEach((expectedDiagnostic, i) => { - const actualDiagnostic = actualDiagnostics[i]; - assert.equal(actualDiagnostic.message, expectedDiagnostic.message); - assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range); - assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity); - }); -} \ No newline at end of file diff --git a/client/src/test/helper.ts b/client/src/test/helper.ts deleted file mode 100644 index 2d3d148..0000000 --- a/client/src/test/helper.ts +++ /dev/null @@ -1,43 +0,0 @@ - -import * as vscode from 'vscode'; -import * as path from 'path'; - -export let doc: vscode.TextDocument; -export let editor: vscode.TextEditor; -export let documentEol: string; -export let platformEol: string; - -/** - * Activates the vscode.lsp-sample extension - */ -export async function activate(docUri: vscode.Uri) { - // The extensionId is `publisher.name` from package.json - const ext = vscode.extensions.getExtension('vscode-samples.lsp-sample')!; - await ext.activate(); - try { - doc = await vscode.workspace.openTextDocument(docUri); - editor = await vscode.window.showTextDocument(doc); - await sleep(2000); // Wait for server activation - } catch (e) { - console.error(e); - } -} - -async function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -export const getDocPath = (p: string) => { - return path.resolve(__dirname, '../../testFixture', p); -}; -export const getDocUri = (p: string) => { - return vscode.Uri.file(getDocPath(p)); -}; - -export async function setTestContent(content: string): Promise { - const all = new vscode.Range( - doc.positionAt(0), - doc.positionAt(doc.getText().length) - ); - return editor.edit(eb => eb.replace(all, content)); -} diff --git a/client/src/test/index.ts b/client/src/test/index.ts deleted file mode 100644 index 107783a..0000000 --- a/client/src/test/index.ts +++ /dev/null @@ -1,40 +0,0 @@ - -import * as path from 'path'; -import * as Mocha from 'mocha'; -import * as glob from 'glob'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd', - color: true - }); - mocha.timeout(100000); - - const testsRoot = __dirname; - - return new Promise((resolve, reject) => { - glob('**.test.js', { cwd: testsRoot }, (err, files) => { - if (err) { - return reject(err); - } - - // Add files to the test suite - files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - reject(new Error(`${failures} tests failed.`)); - } else { - resolve(); - } - }); - } catch (err) { - console.error(err); - reject(err); - } - }); - }); -} \ No newline at end of file diff --git a/client/src/test/runTest.ts b/client/src/test/runTest.ts deleted file mode 100644 index 129337f..0000000 --- a/client/src/test/runTest.ts +++ /dev/null @@ -1,24 +0,0 @@ - -import * as path from 'path'; - -import { runTests } from '@vscode/test-electron'; - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../../'); - - // The path to test runner - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './index'); - - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -main(); From 3341d64ae1da24dba655b5de395b0e127061f350 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 5 Mar 2024 23:27:06 -0500 Subject: [PATCH 3/5] Change trigger character on server Signed-off-by: worksofliam --- server/src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/server.ts b/server/src/server.ts index 14bfaf2..d27f944 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -56,7 +56,7 @@ connection.onInitialize((params: InitializeParams) => { textDocumentSync: TextDocumentSyncKind.Incremental, // Tell the client that this server supports code completion. completionProvider: { - triggerCharacters: [` `, `&`, `(`] + triggerCharacters: [`&`, `(`] }, definitionProvider: true, documentSymbolProvider: true, From 9da98bef4f180fb941e2afbff78439e3010e7699 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 5 Mar 2024 23:30:58 -0500 Subject: [PATCH 4/5] Add snippets Signed-off-by: worksofliam --- package.json | 9 +++- schemas/cl.code-snippets | 108 +++++++++++++++++++++++++++++++++++++++ scripts/e2e.sh | 6 --- 3 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 schemas/cl.code-snippets delete mode 100755 scripts/e2e.sh diff --git a/package.json b/package.json index 7753ee3..a1f7d24 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,14 @@ "onLanguage:cl" ], "main": "./out/extension", - "contributes": {}, + "contributes": { + "snippets": [ + { + "path": "./schemas/cl.code-snippets", + "language": "cl" + } + ] + }, "scripts": { "package": "vsce package", "vscode:prepublish": "npm run webpack", diff --git a/schemas/cl.code-snippets b/schemas/cl.code-snippets new file mode 100644 index 0000000..e36e27e --- /dev/null +++ b/schemas/cl.code-snippets @@ -0,0 +1,108 @@ +{ + "PGM": { + "scope": "clle,cl,clp", + "prefix": "PGM", + "body": ["PGM", "", "ENDPGM"], + "description": "Setup CL Program Start and End" + }, + "SBMJOB": { + "scope": "clle,cl,clp", + "prefix": "SBMJOB", + "body": ["SBMJOB CMD(CALL PGM(${1:*LIBL}/${2:Program}) PARM(${3:Parameters})) +", + "JOB(${4:*JOBD}) JOBD(${5:*USRPRF}) JOBQ(${6:*JOBD}) JOBPTY(${7:*JOBD}) +", + "OUTPTY(${8:*JOBD}) PRTDEV(${9:*CURRENT}) OUTQ(${10:*CURRENT}) USER(${11:*CURRENT})" + ], + "description": "Submit a Job to a Job Queue" + }, + "CALL PGM": { + "scope": "clle,cl,clp", + "prefix": "CALL PGM", + "body": "CALL PGM(${1:*LIBL}/${2:Program}) PARM(${3:Parameters})", + "description": "Call a Program" + }, + "CHGVAR": { + "scope": "clle,cl,clp", + "prefix": "CHGVAR", + "body": "CHGVAR VAR(${1:Variable}) VALUE(${2:Value})", + "description": "Change Variable" + }, + "CVTDAT": { + "scope": "clle,cl,clp", + "prefix": "CVTDAT", + "body": "CVTDAT DATE(${1:Date to Convert}) TOVAR(${2: Var for Converted Date}) FROMFMT(${3:From Format}) TOFMT(${4:To Format}) TOSEP(${5:Separator})", + "description": "Convert Date" + }, + "DCL": { + "scope": "clle,cl,clp", + "prefix": "DCL", + "body": "DCL VAR(${1:Variable}) TYPE(${2:Type}) STG(${3:Storage}) LEN(${4:Length}) VALUE(${5:Initial Value})", + "description": "Declare CL Variable" + }, + "DCLF": { + "scope": "clle,cl,clp", + "prefix": "DCLF", + "body": ["DCLF FILE(${1:*LIBL}/${2:File}) RCDFMT(${2:*ALL}) OPNID(${3:*NONE}) +", + "ALWVARLEN(${4:*NO}) ALWNULL(${5:*NO}) ALWGRAPHIC(${6:*NO}) DCLBINFLD(${7:*DEC})" + ], + "description": "Declare File" + }, + "DLTF": { + "scope": "clle,cl,clp", + "prefix": "DLTF", + "body": "DLTF FILE(${1:*LIBL}/${2:File})", + "description": "Delete File" + }, + "MONMSG": { + "scope": "clle,cl,clp", + "prefix": "MONMSG", + "body": "MONMSG MSGID(${1:Message ID}) CMPDTA(${2:Comparison Data}) EXEC(${3:Command to Execute})", + "description": "Monitor Message" + }, + "RCVF": { + "scope": "clle,cl,clp", + "prefix": "RCVF", + "body": "RCVF DEV(${1:Display Device}) RCDFMT(${2:Record Format}) OPNID(${3:Open File Identifier}) WAIT(${4:Wait})", + "description": "Receive File" + }, + "RTVSYSVAL": { + "scope": "clle,cl,clp", + "prefix": "RTVSYSVAL", + "body": "RTVSYSVAL SYSVAL(${1:System Value}) RTNVAR(${2:Returned Value})", + "description": "Retrieve System Value" + }, + "OTHERWISE": { + "scope": "clle,cl,clp", + "prefix": "OTHERWISE", + "body": "OTHERWISE CMD(${1:Command})", + "description": "Otherwise Condition" + }, + "SELECT": { + "scope": "clle,cl,clp", + "prefix": "SELECT", + "body": ["SELECT", "WHEN COND(${1:Condition}) THEN(${2:Command})", "$0", "ENDDO", "ENDSELECT"], + "description": "Select Statement" + }, + "SNDSMTPEMM": { + "scope": "clle,cl,clp", + "prefix": "SNDSMTPEMM", + "body": ["SNDSMTPEMM RCP((${1:Recipient} ${2:*PRI}) +", + "(${3:Recipient 2} ${4:*CC}) +", + "(${5:Recipient 3} ${6:*BCC})) +", + "SUBJECT('${7:Subject}') +", + "NOTE('${8:Note}') ATTACH(${9:Attachment})" + ], + "description": "Send SMTP Email" + }, + "SUBR": { + "scope": "clle,cl,clp", + "prefix": "SUBR", + "body": ["SUBR SUBR(${1:Subroutine Name})", "$0", "ENDSUBR"], + "description": "Create Subroutine" + }, + "WHEN": { + "scope": "clle,cl,clp", + "prefix": "WHEN", + "body": ["WHEN COND(${1:Condition}) THEN(${2:Command})", "$0", "ENDDO"], + "description": "When Condition" + } +} \ No newline at end of file diff --git a/scripts/e2e.sh b/scripts/e2e.sh deleted file mode 100755 index 860c62e..0000000 --- a/scripts/e2e.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -export CODE_TESTS_PATH="$(pwd)/client/out/test" -export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture" - -node "$(pwd)/client/out/test/runTest" \ No newline at end of file From 2c2cde434ce47ed72cd0cc57c86c27f18fa815cb Mon Sep 17 00:00:00 2001 From: worksofliam Date: Tue, 5 Mar 2024 23:37:59 -0500 Subject: [PATCH 5/5] Register command correctly Signed-off-by: worksofliam --- client/src/clRunner.ts | 2 +- package.json | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/client/src/clRunner.ts b/client/src/clRunner.ts index 6ca5f47..34bede2 100644 --- a/client/src/clRunner.ts +++ b/client/src/clRunner.ts @@ -3,7 +3,7 @@ import { getInstance } from './external/api/ibmi'; export function initialiseRunner(context: ExtensionContext) { context.subscriptions.push( - commands.registerCommand(`code-for-ibmi.cl.runSelected`, async () => { + commands.registerCommand(`vscode-clle.runSelected`, async () => { const instance = getInstance(); const editor = window.activeTextEditor; diff --git a/package.json b/package.json index a1f7d24..d1df7f0 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,30 @@ "path": "./schemas/cl.code-snippets", "language": "cl" } - ] + ], + "commands": [ + { + "command": "vscode-clle.runSelected", + "title": "Run selected CL command", + "category": "IBM i" + } + ], + "keybindings": [ + { + "command": "vscode-clle.runSelected", + "key": "ctrl+r", + "mac": "cmd+r", + "when": "editorLangId == cl" + } + ], + "menus": { + "commandPalette": [ + { + "command": "vscode-clle.runSelected", + "when": "code-for-ibmi:connected && editorLangId === cl" + } + ] + } }, "scripts": { "package": "vsce package",