diff --git a/package-lock.json b/package-lock.json index 18c5b1e..55ca196 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "Lama2", - "version": "2.3.0", + "version": "2.6.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "Lama2", - "version": "2.3.0", + "version": "2.6.0", "license": "SEE LICENSE IN LICENSE", "dependencies": { "ansi-to-html": "^0.7.2", diff --git a/package.json b/package.json index 2bba428..068011e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "Lama2", "displayName": "Lama2", "description": "Nifty VSCode UI for Lama2, the plain-text powered API client", - "version": "2.3.0", + "version": "2.6.0", "publisher": "Hexmos", "license": "SEE LICENSE IN LICENSE", "icon": "lama2.png", diff --git a/src/executeCurrentFile.ts b/src/executeCurrentFile.ts index 8962b5f..8a4b045 100644 --- a/src/executeCurrentFile.ts +++ b/src/executeCurrentFile.ts @@ -64,7 +64,7 @@ class ExecuteCurrentFile { let windowsBasePath = "C:\\ProgramData\\.lama2" let randomNameBase = this.generateRandomName(8) let currentFilePath = vscode.window.activeTextEditor?.document.fileName - + if (process.platform === "win32") { if (!fs.existsSync(windowsBasePath)) { fs.mkdirSync(windowsBasePath) @@ -72,9 +72,9 @@ class ExecuteCurrentFile { randomNameFlag = `${windowsBasePath}\\${randomNameBase}.flag` randomNameFile = `${windowsBasePath}\\${randomNameBase}.json` cmd = `powershell l2 -o ${randomNameFile} ${currentFilePath}; New-Item -Path ${randomNameFlag}` - }else { - randomNameFlag = `/tmp/${randomNameBase}.flag` - randomNameFile = `/tmp/${randomNameBase}.json` + } else { + randomNameFlag = `/tmp/${randomNameBase}.flag` + randomNameFile = `/tmp/${randomNameBase}.json` cmd = `l2 -o ${randomNameFile} ${currentFilePath}; touch ${randomNameFlag}` } return { @@ -257,4 +257,10 @@ class ExecuteCurrentFile { } -export default ExecuteCurrentFile +export function execCurL2File(context: vscode.ExtensionContext) { + let executeCurrentFile = new ExecuteCurrentFile(context); + return vscode.commands.registerCommand("lama2.ExecuteCurrentFile", () => + executeCurrentFile.execFile() + ); +} + diff --git a/src/extension.ts b/src/extension.ts index e50aff7..bec8921 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,279 +1,48 @@ import * as vscode from "vscode"; -import * as fs from "fs"; -import * as path from "path"; -import ExecuteCurrentFile from "./executeCurrentFile"; -import GenerateCodeSnippet from "./generateCodeSnippet"; -import GetRemoteURL from "./getRemoteUrl"; -import LanguagesData from "./languages"; -import { exec } from 'child_process'; -import triggers from "./triggers"; -let examplesJSONStr = - '{"0006_cookies.l2":"POST \\nhttps://httpbin.org/post\\n\\n# HEADERS\\nCookie:\\"sessionid=foo;another-cookie=bar\\"\\n\\nHeader1:value1\\nHeader2: Value2\\n\\n# DATA\\nhello=world","0002_sample_post.l2":"POST\\nhttps://httpbin.org/post\\n\\n{\\n \\"a\\": \\"b\\",\\n \\"c\\": \\"d\\"\\n}","0005_headers_simple.l2":"POST \\nhttps://httpbin.org/post\\n\\n# HEADERS\\nX-Parse-Application-Id:\'helloworld\'\\nX-Parse-REST-API-Key:\\"byeworld\\"\\n\\n# DATA\\na=\\"b\\" # double-quoted string\\n\'c\'=d # single-quoted & unquoted strings","0008_base64_image":{"0008_base64_image.l2":"POST\\nhttp://httpbin.org/post\\n\\n{\\n\\t\\"imageb64_field\\": \\"\'${PHOTO}\'\\",\\n}","l2.env":"\\nexport PHOTO=`base64 image.jpeg`"},"0001_sample_post_varjson.l2":"POST\\nhttps://httpbin.org/post\\n\\na=b\\nc=d","0007_multipart_file":{"0007_multipart_file.l2":"POST\\nMULTIPART\\nhttp://httpbin.org/post\\n\\n\'X-Parse-Application-Id\':helloworld \\nX-Parse-REST-API-Key:\\"helloworld\\"\\n\\n# DATA\\nfirst=second\\n\\n# FILES\\nmyfile@./image.jpeg"},"0004_env_switch_root":{"0004_env_switch_root.l2":"POST\\n${REMOTE}/post\\n\\n{\\n \\"lorem\\": \\"ipsum\\"\\n}","l2.env":"export LOCAL=\\"http://localhost:8000\\"\\nexport REMOTE=\\"http://httpbin.org\\""},"0003_comment.l2":"# Pound symbol signifies a comment\\nPOST\\nhttps://httpbin.org/post\\n\\na=b # Comments may start at the end of lines as well\\nc=d\\n\\n# Comments work even after the payload","0000_sample_get.l2":"GET\\nhttps://httpbin.org/get","0009_processor_basic":{"0009_processor_basic.l2":"url = \\"http://google.com\\"\\n---\\n# stage 1\\n\\nPOST\\n${REMOTE_COORD}/anything\\n\\n{\\n \\"username\\": \\"admin\\",\\n \\"password\\": \\"Password@123\\",\\n \\"from\\": \\"${LOCAL_COORD}/anything\\",\\n \\"url\\": \\"${url}\\",\\n \\"Token\\": \\"MySuperSecretToken\\"\\n}\\n\\n---\\n\\n// filtering, store in var\\nconsole.log(\\"@@Result\\", result)\\nlet TOKEN = result[\\"json\\"][\\"Token\\"]\\nconsole.log(TOKEN)\\n\\n---\\n\\n# stage 2\\nGET\\n${REMOTE_COORD}/bearer\\n\\nAuthorization: \'Bearer ${TOKEN}\'\\n\\n{}","l2.env":"\\nexport LOCAL_COORD=\\"http://localhost:8080\\"\\nexport REMOTE_COORD=\\"http://httpbin.org\\""}}'; -let examplesJSON = JSON.parse(examplesJSONStr); -let specificExGlobal = ""; -let subSpecificExGlobal = ""; - -interface LanguageData { - info: { - key: string; - title: string; - extname: string; - default: string; - }; - clientsById: Record; -} - -interface LanguagesData { - [key: string]: LanguageData; -} +import { genCodeSnip } from "./generateCodeSnippet"; +import { getRemoteUrl } from "./getRemoteUrl"; +import { replaceTextAfterEnvSelected, suggestENVs } from "./suggestEnvironmentVars"; +import { genLama2Examples } from "./genLama2Examples"; +import { execCurL2File } from "./executeCurrentFile"; +import { prettifyL2File } from "./prettifyL2File"; export function activate(context: vscode.ExtensionContext) { console.log('>>> Congratulations, your extension "Lama2" is now active!'); - // Level1 command pallette - let getremoteUrl = new GetRemoteURL(context); - let getremoteUrlFileDisposable = vscode.commands.registerCommand( - "lama2.GetRemoteURL", - () => getremoteUrl.findURL() - ); - context.subscriptions.push(getremoteUrlFileDisposable); - // Level1 command pallette - let executeCurrentFile = new ExecuteCurrentFile(context); - - let executeCurrentFileDisposable = vscode.commands.registerCommand( - "lama2.ExecuteCurrentFile", - () => executeCurrentFile.execFile() - ); - + let executeCurrentFileDisposable = execCurL2File(context); context.subscriptions.push(executeCurrentFileDisposable); + console.log(">>> executeCurrentFileDisposable is now active!"); // Level1 command pallette + let getremoteUrlFileDisposable = getRemoteUrl(context); + context.subscriptions.push(getremoteUrlFileDisposable); + console.log(">>> getremoteUrlFileDisposable is now active!"); - let prettifyCurrentFileDisposable = vscode.commands.registerCommand( - "lama2.PrettifyCurrentFile", - () => { - console.log("Executing prettify command"); - exec(`l2 -b ${vscode.window.activeTextEditor?.document.fileName}`); - } - ); + // Level1 command pallette + let prettifyCurrentFileDisposable = prettifyL2File(); context.subscriptions.push(prettifyCurrentFileDisposable); - - let generateCodeSnippet = new GenerateCodeSnippet(); - let lama2Examples = vscode.commands.registerCommand( - "lama2.Lama2Examples", - async () => { - let specificEx: string | undefined = await vscode.window.showQuickPick( - Object.keys(examplesJSON) - ); - - if (specificEx) { - specificExGlobal = specificEx; - if (specificEx.endsWith(".env") || specificEx.endsWith(".l2")) { - vscode.window.activeTextEditor?.edit((builder) => { - const doc = vscode.window.activeTextEditor?.document; - builder.replace( - new vscode.Range( - doc!.lineAt(0).range.start, - doc!.lineAt(doc!.lineCount - 1).range.end - ), - examplesJSON[specificExGlobal] - ); - }); - return; - } - - let subSpecificEx: string | undefined = - await vscode.window.showQuickPick( - Object.keys(examplesJSON[specificEx]) - ); - - if (subSpecificEx) { - subSpecificExGlobal = subSpecificEx; - vscode.window.activeTextEditor?.edit((builder) => { - const doc = vscode.window.activeTextEditor?.document; - builder.replace( - new vscode.Range( - doc!.lineAt(0).range.start, - doc!.lineAt(doc!.lineCount - 1).range.end - ), - examplesJSON[specificExGlobal][subSpecificExGlobal] - ); - }); - return; - } - } - } - ); + console.log(">>> prettifyCurrentFileDisposable is now active!"); // Level1 command pallette - let generateCodeSnippetDisposable = vscode.commands.registerCommand( - "lama2.GenerateCodeSnippet", - async () => { - const langkwys = Object.keys(LanguagesData); - let languageOptions: { [key: string]: string } = {}; - for (let i = 0; i < langkwys.length; i++) { - const key = langkwys[i] as keyof typeof LanguagesData; - const languageData = LanguagesData[key]; - languageOptions[languageData.info.title] = languageData.info.key; - } + let lama2Examples = genLama2Examples(); + console.log(">>> lama2Examples is now active!"); - const languageKeys = Object.keys(LanguagesData); - - // Level2 command pallette - let language: string | undefined = await vscode.window.showQuickPick( - Object.keys(languageOptions) - ); - - if (language) { - language = languageOptions[language]; - const languageKey = languageKeys.find( - (key) => - LanguagesData[key as keyof typeof LanguagesData].info.key === - language - )!; - - const clientsById = - LanguagesData[languageKey as keyof typeof LanguagesData].clientsById; - const defaultClient = - LanguagesData[languageKey as keyof typeof LanguagesData].info.default; - - const clientKeys = Object.keys(clientsById); - - if (clientKeys.length === 1) { - const client = clientKeys[0]; - generateCodeSnippet.execFile(language, client); - } else { - // Level3 command pallette - const selection: - | { - label: string; - language: string; - client: string; - } - | undefined = await vscode.window.showQuickPick( - clientKeys - .sort((a, b) => - a === defaultClient ? -1 : b === defaultClient ? 1 : 0 - ) - .map((client) => ({ - label: `${language ?? ""}: ${client} ${isDefault( - defaultClient, - client - )}`, - language: language ?? "", - client: client, - })), - { placeHolder: "Select a client" } - ); - - if (selection) { - generateCodeSnippet.execFile(selection.language, selection.client); - } - } - } - } - ); + // Level1 command pallette + let generateCodeSnippetDisposable = genCodeSnip(); context.subscriptions.push(generateCodeSnippetDisposable); + console.log(">>> generateCodeSnippetDisposable is now active!"); - let envVariables = [] as string[]; - const activeTextEditor = vscode.window.activeTextEditor; - if (activeTextEditor) { - const activeFilePath = activeTextEditor.document.uri.fsPath; - const envFilePath = path.join(path.dirname(activeFilePath), "l2.env"); - fs.readFile(envFilePath, "utf8", (err, data) => { - if (err) { - console.error(err); - return; - } - - envVariables = data - .split("\n") - .filter((line) => line.startsWith("export")) - .map((line) => line.split("=")[0].replace("export ", "")); - console.log("envVariables -> ", envVariables); - }); - } - let cursorPosition: any; - let linePosition: any; - - - - let suggestEnvVariables = vscode.languages.registerCompletionItemProvider( - { language: "lama2", scheme: "file" }, - { - // eslint-disable-next-line no-unused-vars - provideCompletionItems(document, position, token, context) { - // get all text until the `position` and check if it reads `${` - - const linePrefix = document - .lineAt(position) - .text.substring(0, position.character); - if (!linePrefix.endsWith("${")) { - return undefined; - } - let createSuggestion = (text: string) => { - let item = new vscode.CompletionItem( - text, - vscode.CompletionItemKind.Text - ); - item.range = new vscode.Range(position, position); - item.command = { - title: "", - command: "options", - }; - return item; - }; - const suggestionsArray = envVariables.map((item, index) => { - return createSuggestion(item); - }); - - return suggestionsArray; - }, - ...triggers, // trigger - resolveCompletionItem( - item: vscode.CompletionItem, - token: vscode.CancellationToken - ) { - const editor = vscode.window.activeTextEditor; - if (editor) { - const position = editor.selection.active; - cursorPosition = position.character; - linePosition = position.line; - } - return item; - }, - } - ); + let suggestEnvVariables = suggestENVs(); context.subscriptions.push( suggestEnvVariables, - vscode.commands.registerCommand("options", () => { - const editor = vscode.window.activeTextEditor; - if (editor) { - const position = editor.selection.active; - const bracketPosition = editor.document - .lineAt(position.line) - .text.indexOf("{"); - const start = new vscode.Position(linePosition, bracketPosition + 1); // start position - const end = new vscode.Position(linePosition, cursorPosition); // end position - const range = new vscode.Range(start, end); // create range object - const replaceText = ""; - const edit = new vscode.WorkspaceEdit(); - edit.replace(editor.document.uri, range, replaceText); - vscode.workspace.applyEdit(edit); - } + vscode.commands.registerCommand("envoptions", () => { + // This method is activated when the user selects a suggested env variable. + replaceTextAfterEnvSelected(); }) ); } // this method is called when your extension is deactivated -export function deactivate() {} - -function isDefault(defaultClient: string, client: string) { - if (defaultClient == client) { - return "(Default)"; - } else { - return ""; - } -} +export function deactivate() { } diff --git a/src/genLama2Examples.ts b/src/genLama2Examples.ts new file mode 100644 index 0000000..c9aa914 --- /dev/null +++ b/src/genLama2Examples.ts @@ -0,0 +1,50 @@ +import * as vscode from "vscode"; +let examplesJSONStr = + '{"0006_cookies.l2":"POST \\nhttps://httpbin.org/post\\n\\n# HEADERS\\nCookie:\\"sessionid=foo;another-cookie=bar\\"\\n\\nHeader1:value1\\nHeader2: Value2\\n\\n# DATA\\nhello=world","0002_sample_post.l2":"POST\\nhttps://httpbin.org/post\\n\\n{\\n \\"a\\": \\"b\\",\\n \\"c\\": \\"d\\"\\n}","0005_headers_simple.l2":"POST \\nhttps://httpbin.org/post\\n\\n# HEADERS\\nX-Parse-Application-Id:\'helloworld\'\\nX-Parse-REST-API-Key:\\"byeworld\\"\\n\\n# DATA\\na=\\"b\\" # double-quoted string\\n\'c\'=d # single-quoted & unquoted strings","0008_base64_image":{"0008_base64_image.l2":"POST\\nhttp://httpbin.org/post\\n\\n{\\n\\t\\"imageb64_field\\": \\"\'${PHOTO}\'\\",\\n}","l2.env":"\\nexport PHOTO=`base64 image.jpeg`"},"0001_sample_post_varjson.l2":"POST\\nhttps://httpbin.org/post\\n\\na=b\\nc=d","0007_multipart_file":{"0007_multipart_file.l2":"POST\\nMULTIPART\\nhttp://httpbin.org/post\\n\\n\'X-Parse-Application-Id\':helloworld \\nX-Parse-REST-API-Key:\\"helloworld\\"\\n\\n# DATA\\nfirst=second\\n\\n# FILES\\nmyfile@./image.jpeg"},"0004_env_switch_root":{"0004_env_switch_root.l2":"POST\\n${REMOTE}/post\\n\\n{\\n \\"lorem\\": \\"ipsum\\"\\n}","l2.env":"export LOCAL=\\"http://localhost:8000\\"\\nexport REMOTE=\\"http://httpbin.org\\""},"0003_comment.l2":"# Pound symbol signifies a comment\\nPOST\\nhttps://httpbin.org/post\\n\\na=b # Comments may start at the end of lines as well\\nc=d\\n\\n# Comments work even after the payload","0000_sample_get.l2":"GET\\nhttps://httpbin.org/get","0009_processor_basic":{"0009_processor_basic.l2":"url = \\"http://google.com\\"\\n---\\n# stage 1\\n\\nPOST\\n${REMOTE_COORD}/anything\\n\\n{\\n \\"username\\": \\"admin\\",\\n \\"password\\": \\"Password@123\\",\\n \\"from\\": \\"${LOCAL_COORD}/anything\\",\\n \\"url\\": \\"${url}\\",\\n \\"Token\\": \\"MySuperSecretToken\\"\\n}\\n\\n---\\n\\n// filtering, store in var\\nconsole.log(\\"@@Result\\", result)\\nlet TOKEN = result[\\"json\\"][\\"Token\\"]\\nconsole.log(TOKEN)\\n\\n---\\n\\n# stage 2\\nGET\\n${REMOTE_COORD}/bearer\\n\\nAuthorization: \'Bearer ${TOKEN}\'\\n\\n{}","l2.env":"\\nexport LOCAL_COORD=\\"http://localhost:8080\\"\\nexport REMOTE_COORD=\\"http://httpbin.org\\""}}'; +let examplesJSON = JSON.parse(examplesJSONStr); +let specificExGlobal = ""; +let subSpecificExGlobal = ""; + +export function genLama2Examples() { + return vscode.commands.registerCommand("lama2.Lama2Examples", async () => { + let specificEx: string | undefined = await vscode.window.showQuickPick( + Object.keys(examplesJSON) + ); + + if (specificEx) { + specificExGlobal = specificEx; + if (specificEx.endsWith(".env") || specificEx.endsWith(".l2")) { + vscode.window.activeTextEditor?.edit((builder) => { + const doc = vscode.window.activeTextEditor?.document; + builder.replace( + new vscode.Range( + doc!.lineAt(0).range.start, + doc!.lineAt(doc!.lineCount - 1).range.end + ), + examplesJSON[specificExGlobal] + ); + }); + return; + } + + let subSpecificEx: string | undefined = await vscode.window.showQuickPick( + Object.keys(examplesJSON[specificEx]) + ); + + if (subSpecificEx) { + subSpecificExGlobal = subSpecificEx; + vscode.window.activeTextEditor?.edit((builder) => { + const doc = vscode.window.activeTextEditor?.document; + builder.replace( + new vscode.Range( + doc!.lineAt(0).range.start, + doc!.lineAt(doc!.lineCount - 1).range.end + ), + examplesJSON[specificExGlobal][subSpecificExGlobal] + ); + }); + return; + } + } + }); +} diff --git a/src/generateCodeSnippet.ts b/src/generateCodeSnippet.ts index ea10c5e..da1e0cb 100644 --- a/src/generateCodeSnippet.ts +++ b/src/generateCodeSnippet.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import ChokiExtension from "./watchFile"; let fs = require("fs"); import { window } from "vscode"; +import LanguagesData from "./languages"; class GenerateCodeSnippet { LAMA2_TERM_NAME = "AutoLama2"; @@ -110,4 +111,98 @@ class GenerateCodeSnippet { } } -export default GenerateCodeSnippet; + +function isDefault(defaultClient: string, client: string) { + if (defaultClient == client) { + return "(Default)"; + } else { + return ""; + } +} + +interface LanguageData { + info: { + key: string; + title: string; + extname: string; + default: string; + }; + clientsById: Record; +} + +interface LanguagesData { + [key: string]: LanguageData; +} + +export function genCodeSnip() { + let generateCodeSnippet = new GenerateCodeSnippet(); + let generateCodeSnippetDisposable = vscode.commands.registerCommand( + "lama2.GenerateCodeSnippet", + async () => { + const langkwys = Object.keys(LanguagesData); + let languageOptions: { [key: string]: string } = {}; + for (let i = 0; i < langkwys.length; i++) { + const key = langkwys[i] as keyof typeof LanguagesData; + const languageData = LanguagesData[key]; + languageOptions[languageData.info.title] = languageData.info.key; + } + + const languageKeys = Object.keys(LanguagesData); + + // Level2 command pallette + let language: string | undefined = await vscode.window.showQuickPick( + Object.keys(languageOptions) + ); + + if (language) { + language = languageOptions[language]; + const languageKey = languageKeys.find( + (key) => + LanguagesData[key as keyof typeof LanguagesData].info.key === + language + )!; + + const clientsById = + LanguagesData[languageKey as keyof typeof LanguagesData].clientsById; + const defaultClient = + LanguagesData[languageKey as keyof typeof LanguagesData].info.default; + + const clientKeys = Object.keys(clientsById); + + if (clientKeys.length === 1) { + const client = clientKeys[0]; + generateCodeSnippet.execFile(language, client); + } else { + // Level3 command pallette + const selection: + | { + label: string; + language: string; + client: string; + } + | undefined = await vscode.window.showQuickPick( + clientKeys + .sort((a, b) => + a === defaultClient ? -1 : b === defaultClient ? 1 : 0 + ) + .map((client) => ({ + label: `${language ?? ""}: ${client} ${isDefault( + defaultClient, + client + )}`, + language: language ?? "", + client: client, + })), + { placeHolder: "Select a client" } + ); + + if (selection) { + generateCodeSnippet.execFile(selection.language, selection.client); + } + } + } + } + ); + return generateCodeSnippetDisposable; +} + diff --git a/src/getRemoteUrl.ts b/src/getRemoteUrl.ts index dcf7034..3c4161b 100644 --- a/src/getRemoteUrl.ts +++ b/src/getRemoteUrl.ts @@ -1,21 +1,8 @@ import { simpleGit, SimpleGit, CleanOptions } from 'simple-git'; import * as vscode from 'vscode'; import * as path from 'path'; -import { statSync } from 'fs'; -function isGitDirectory() { - try { - statSync('.git'); - return true; - } - catch (err: any) { - if (err.code === 'ENOENT') { - return false; - } - } -} - class GetRemoteURL { context: vscode.ExtensionContext; @@ -24,52 +11,58 @@ class GetRemoteURL { } async findURL() { - if (!isGitDirectory()) { - vscode.window.showErrorMessage("Remote URL not found because it is not a Git repository"); - } - else { - try { - let currentFilePath: string = vscode.window.activeTextEditor!.document.fileName; - let parentDir: string = path.dirname(currentFilePath); - let localgit: SimpleGit = simpleGit(parentDir).clean(CleanOptions.FORCE); + try { + let currentFilePath: string = vscode.window.activeTextEditor!.document.fileName; + let parentDir: string = path.dirname(currentFilePath); + let localgit: SimpleGit = simpleGit(parentDir).clean(CleanOptions.FORCE); - const gitRemotes = await localgit.getRemotes(true); - const branchSummary = await localgit.branch(); - const currentBranch = branchSummary.current; - const remoteURL = gitRemotes[0]['refs']['push']; + const gitRemotes = await localgit.getRemotes(true); + const branchSummary = await localgit.branch(); + const currentBranch = branchSummary.current; + const remoteURL = gitRemotes[0]['refs']['push']; - const rootDir = await localgit.revparse(['--show-toplevel']); - const relativePath = path.relative(rootDir, currentFilePath); // find relative path b/w root and current working directory + const rootDir = await localgit.revparse(['--show-toplevel']); + const relativePath = path.relative(rootDir, currentFilePath); // find relative path b/w root and current working directory - let gitRepoURL = remoteURL; - let gitURLPrefix; - if (!remoteURL.startsWith('git@') && (!remoteURL.startsWith('https'))) { - vscode.window.showErrorMessage("URL not found. Currently supports Github only (both HTTPS and SSH)"); + let gitRepoURL = remoteURL; + let gitURLPrefix; + if (!remoteURL.startsWith('git@') && (!remoteURL.startsWith('https'))) { + vscode.window.showErrorMessage("URL not found. Currently supports Github only (both HTTPS and SSH)"); + } + else { + if (remoteURL.startsWith('git@')) { + gitRepoURL = remoteURL.split('@')[1]; // split with @ and get the repo url + gitURLPrefix = "https://"; } - else { - if (remoteURL.startsWith('git@')) { - gitRepoURL = remoteURL.split('@')[1]; // split with @ and get the repo url - gitURLPrefix = "https://"; - } - else if (remoteURL.startsWith('https')) { - const stripdotgit = remoteURL.substring(0, remoteURL.length - 4) + '/blob/'; // remove .git - gitURLPrefix = ""; - } - const stripdotgit = gitRepoURL.substring(0, gitRepoURL.length - 4) + '/blob/'; // remove .git - const replacecolon = stripdotgit.replace(':', '/'); // replace colon with forward slash - const result = gitURLPrefix + replacecolon + currentBranch + '/' + relativePath; - vscode.window.showInformationMessage("Remote URL successfully found and copied to clipboard"); - vscode.env.clipboard.writeText(result.toString()); + else if (remoteURL.startsWith('https')) { + const stripdotgit = remoteURL.substring(0, remoteURL.length - 4) + '/blob/'; // remove .git + gitURLPrefix = ""; } - return 'SUCCESS'; - } - catch (e) { - /* handle all errors here */ - console.log('ERROR:', e); - return 'FAILED'; + const stripdotgit = gitRepoURL.substring(0, gitRepoURL.length - 4) + '/blob/'; // remove .git + const replacecolon = stripdotgit.replace(':', '/'); // replace colon with forward slash + const result = gitURLPrefix + replacecolon + currentBranch + '/' + relativePath; + vscode.window.showInformationMessage("Remote URL successfully found and copied to clipboard"); + vscode.env.clipboard.writeText(result.toString()); } + return 'SUCCESS'; + } + catch (error: any) { + /* handle all errors here */ + const errorMessage = error.message; + // console.log('ERROR:', errMessage); + vscode.window.showErrorMessage("URL not found because " + errorMessage); + + return 'FAILED'; } } } -export default GetRemoteURL; \ No newline at end of file +export function getRemoteUrl(context: vscode.ExtensionContext) { + let getremoteUrl = new GetRemoteURL(context); + console.log(getremoteUrl); + let getremoteUrlFileDisposable = vscode.commands.registerCommand( + "lama2.GetRemoteURL", + () => getremoteUrl.findURL() + ); + return getremoteUrlFileDisposable; +} \ No newline at end of file diff --git a/src/prettifyL2File.ts b/src/prettifyL2File.ts new file mode 100644 index 0000000..6178a78 --- /dev/null +++ b/src/prettifyL2File.ts @@ -0,0 +1,9 @@ +import * as vscode from "vscode"; +import { exec } from "child_process"; + +export function prettifyL2File() { + return vscode.commands.registerCommand("lama2.PrettifyCurrentFile", () => { + console.log("Executing prettify command"); + exec(`l2 -b ${vscode.window.activeTextEditor?.document.fileName}`); + }); +} \ No newline at end of file diff --git a/src/suggestEnvironmentVars.ts b/src/suggestEnvironmentVars.ts new file mode 100644 index 0000000..03c9a52 --- /dev/null +++ b/src/suggestEnvironmentVars.ts @@ -0,0 +1,118 @@ +import * as vscode from "vscode"; +import { execSync } from "child_process"; + +import triggers from "./triggers"; +let cursorPosition = 0; + +export function getEnvsFromEnvCommand(): {} { + const editor = vscode.window.activeTextEditor; + if (!editor) { + return {}; + } + + const l2FilePath = editor.document.fileName; + if (!l2FilePath.endsWith(".l2")) { + return {}; + } + + try { + // Execute the command and read the stdout for JSON of all the env's + + // const commandOutput = execSync(`./build/l2 --env ${l2FilePath}`, { cwd: "/home/lovestaco/repos/Lama2", }).toString(); // For local debugging + const commandOutput = execSync(`l2 --env ${l2FilePath}`).toString(); + const envMap = JSON.parse(commandOutput); + return envMap; + } catch (error) { + console.error("Error executing the command:", error); + return {}; + } +} + +function createSuggestion(env: string, envVal: string, envSrc: string, position: any) { + let item = new vscode.CompletionItem( + env, + vscode.CompletionItemKind.Text + ); + item.detail = envVal; + item.documentation = `src: ${envSrc}`; + item.range = new vscode.Range(position, position); + item.command = { + title: "", + command: "envoptions", + arguments: [env], + }; + return item; + +} + +export function suggestENVs() { + return vscode.languages.registerCompletionItemProvider( + { language: "lama2", scheme: "file" }, + { + // eslint-disable-next-line no-unused-vars + provideCompletionItems(document, position, token, context) { + const currentLine = document.lineAt(position.line).text; + const triggerPrefix = currentLine + .substring(0, position.character) + .includes("${"); + const triggerPostfix = currentLine + .substring(position.character) + .includes("}"); + + const envVarsObj = getEnvsFromEnvCommand() as Record< + string, + { src: string; val: string } + >; // Explicitly cast to the correct type + const envVars = new Map(Object.entries(envVarsObj)); + + const suggestionsArray = Array.from(envVars.entries()).map( + ([env, meta]) => createSuggestion(env, meta.val, meta.src, position) + ); + + if (triggerPrefix && !triggerPostfix) { + return suggestionsArray; + } else if (triggerPrefix) { + return suggestionsArray; + } else { + return []; + } + }, + ...triggers, // triggers for activating the suggestions + resolveCompletionItem( + item: vscode.CompletionItem, + token: vscode.CancellationToken + ) { + const editor = vscode.window.activeTextEditor; + if (editor) { + const position = editor.selection.active; + cursorPosition = position.character; + } + return item; + }, + } + ); +} + +export function replaceTextAfterEnvSelected() { + const editor = vscode.window.activeTextEditor; + if (editor) { + let position = editor.selection.active; + let lineText = editor.document.lineAt(position.line).text; + let linePosition = editor.document.lineAt(position.line).range.start + .character; + let openingBraceIndex = lineText.indexOf("{", linePosition); + if (openingBraceIndex >= 0 && cursorPosition > openingBraceIndex) { + let newText = lineText.substring(0, openingBraceIndex + 1); + newText += lineText.substring(cursorPosition); + let edit = new vscode.WorkspaceEdit(); + let range = new vscode.Range( + position.line, + 0, + position.line, + lineText.length + ); + edit.replace(editor.document.uri, range, newText); + vscode.workspace.applyEdit(edit); + } + } +} \ No newline at end of file