Skip to content

Commit

Permalink
Merge pull request #10 from HexmosTech/copygit
Browse files Browse the repository at this point in the history
Auto suggest environment variables using `l2 --env <path>` command
  • Loading branch information
shrsv committed Jul 18, 2023
2 parents b0a0f5e + cdc416c commit 975913b
Show file tree
Hide file tree
Showing 9 changed files with 356 additions and 316 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
16 changes: 11 additions & 5 deletions src/executeCurrentFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,17 @@ 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)
}
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 {
Expand Down Expand Up @@ -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()
);
}

279 changes: 24 additions & 255 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -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<string, null>;
}

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() { }
Loading

0 comments on commit 975913b

Please sign in to comment.