extension.ts (5681B)
1 import * as vscode from 'vscode'; 2 import * as cp from 'child_process'; 3 4 // 1. Activation Event 5 export function activate(context: vscode.ExtensionContext) { 6 console.log('Githrun extension is now active!'); 7 8 // Check if githrun CLI is installed 9 checkGithrunInstallation(); 10 11 // Register the CodeLens Provider 12 const docSelector = [ 13 { language: 'markdown', scheme: 'file' }, 14 { language: 'python', scheme: 'file' }, 15 { language: 'plaintext', scheme: 'file' } 16 ]; 17 18 const codeLensProvider = new GithrunCodeLensProvider(); 19 context.subscriptions.push( 20 vscode.languages.registerCodeLensProvider(docSelector, codeLensProvider) 21 ); 22 23 // --- REGISTER COMMANDS --- 24 25 // Command 1: Run from CodeLens (Clicking the button) 26 context.subscriptions.push( 27 vscode.commands.registerCommand('githrun.runUrl', (url: string) => { 28 runGithrun(url); 29 }) 30 ); 31 32 // Command 2: Install CLI 33 context.subscriptions.push( 34 vscode.commands.registerCommand('githrun.installCli', () => { 35 installGithrun(); 36 }) 37 ); 38 39 // Command 3: Run from Input Box (Ctrl+Shift+P) 40 context.subscriptions.push( 41 vscode.commands.registerCommand('githrun.runInput', () => { 42 runFromInput(); 43 }) 44 ); 45 46 // Command 4: Run Current Selection 47 context.subscriptions.push( 48 vscode.commands.registerCommand('githrun.runSelection', () => { 49 runSelection(); 50 }) 51 ); 52 } 53 54 // 2. The CodeLens Provider (The "Scanner") 55 class GithrunCodeLensProvider implements vscode.CodeLensProvider { 56 57 // Regex to find GitHub/Gist URLs ending in .py 58 private regex = /https:\/\/(gist\.)?github\.com\/[\w\-\.\/]+\.py/g; 59 60 provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] { 61 const text = document.getText(); 62 const lenses: vscode.CodeLens[] = []; 63 let match; 64 65 // Loop through all matches in the file 66 while ((match = this.regex.exec(text)) !== null) { 67 const url = match[0]; 68 const startPos = document.positionAt(match.index); 69 const endPos = document.positionAt(match.index + url.length); 70 const range = new vscode.Range(startPos, endPos); 71 72 // Create the "Run" button 73 const cmd: vscode.Command = { 74 title: "$(play) Run with Githrun", // The text user sees 75 tooltip: "Execute this script remotely", 76 command: "githrun.runUrl", 77 arguments: [url] 78 }; 79 80 lenses.push(new vscode.CodeLens(range, cmd)); 81 } 82 return lenses; 83 } 84 } 85 86 // 3. The Runner Logic 87 function runGithrun(url: string) { 88 if (!url) { return; } 89 90 // Get config for auto-install flag 91 const config = vscode.workspace.getConfiguration('githrun'); 92 const autoInstall = config.get('autoInstallDeps') ? ' --auto-install' : ''; 93 94 // Create or show terminal 95 const terminalName = 'Githrun'; 96 // Explicitly type 't' as a vscode.Terminal 97 let terminal = vscode.window.terminals.find((t: vscode.Terminal) => t.name === terminalName); 98 99 if (!terminal) { 100 terminal = vscode.window.createTerminal(terminalName); 101 } 102 103 terminal.show(); 104 // Use the CLI command you built in python! 105 terminal.sendText(`githrun run ${url}${autoInstall}`); 106 } 107 108 // Helper: Run from Input Box 109 async function runFromInput() { 110 const url = await vscode.window.showInputBox({ 111 placeHolder: "https://github.com/username/repo/blob/main/script.py", 112 prompt: "Enter a GitHub URL or Gist to run with Githrun" 113 }); 114 115 if (url) { 116 runGithrun(url.trim()); 117 } 118 } 119 120 // Helper: Run from Selection 121 function runSelection() { 122 const editor = vscode.window.activeTextEditor; 123 if (!editor) { 124 vscode.window.showErrorMessage("No active text editor found."); 125 return; 126 } 127 128 const selection = editor.document.getText(editor.selection); 129 if (!selection) { 130 vscode.window.showInformationMessage("Please highlight a GitHub URL first."); 131 return; 132 } 133 134 // Basic validation 135 const trimmed = selection.trim(); 136 if (trimmed.startsWith("http")) { 137 runGithrun(trimmed); 138 } else { 139 vscode.window.showWarningMessage("The selected text does not look like a URL."); 140 } 141 } 142 143 // 4. Installation Helper 144 function checkGithrunInstallation() { 145 // Check version to verify installation 146 cp.exec('githrun --version', (err: cp.ExecException | null, stdout: string) => { 147 // Regex looks for standard version patterns like 1.0.0, 0.2, v1.0 etc. 148 // It allows for "githrun version 1.0.0" or just "1.0.0" 149 const versionMatch = stdout && stdout.match(/(\d+\.\d+(\.\d+)?)/); 150 151 if (err || !versionMatch) { 152 console.log('Githrun CLI check failed:', err ? err.message : 'No version number in stdout'); 153 154 vscode.window.showWarningMessage( 155 "Githrun CLI is not detected. Install it to run remote scripts?", 156 "Install Now" 157 ).then((selection: string | undefined) => { 158 if (selection === "Install Now") { 159 installGithrun(); 160 } 161 }); 162 } else { 163 console.log(`Githrun CLI detected: ${versionMatch[0]}`); 164 } 165 }); 166 } 167 168 function installGithrun() { 169 const terminal = vscode.window.createTerminal("Install Githrun"); 170 terminal.show(); 171 terminal.sendText("pip install githrun"); 172 vscode.window.showInformationMessage("Installing Githrun... Try running the script once finished."); 173 } 174 175 export function deactivate() {}