UNPKG

@typecad/typecad

Version:

🤖programmatically 💥create 🛰️hardware

112 lines (111 loc) 5.11 kB
import { exec } from 'node:child_process'; import readline from 'node:readline'; import chalk from 'chalk'; /** * Scans open windows to find KiCad PCB Editor with the specified board name. * @param boardName - The name of the board to look for (without .kicad_pcb extension) * @returns Status object indicating if the window was found and if it has unsaved changes * @private */ export async function scanForKiCadWindow(boardName) { try { // Use PowerShell directly to get window titles instead of the problematic find-window.js const windowTitles = await new Promise((resolve, reject) => { const powershellCommand = `Get-Process | Where-Object {$_.MainWindowTitle -ne '' -and $_.MainWindowTitle -like '*PCB Editor*'} | Select-Object -ExpandProperty MainWindowTitle`; exec(`powershell -Command "${powershellCommand}"`, (error, stdout, stderr) => { if (error) { // Fall back to trying all windows const fallbackCommand = `Get-Process | Where-Object {$_.MainWindowTitle -ne ''} | Select-Object -ExpandProperty MainWindowTitle`; exec(`powershell -Command "${fallbackCommand}"`, (fallbackError, fallbackStdout, fallbackStderr) => { if (fallbackError) { reject(new Error(`Window detection failed: ${fallbackError.message}`)); return; } const allTitles = fallbackStdout.split('\n') .map(line => line.trim()) .filter(line => line.length > 0); // Filter for PCB Editor windows const kicadTitles = allTitles.filter(title => title.toLowerCase().includes('pcb editor')); resolve(kicadTitles); }); return; } const titles = stdout.split('\n') .map(line => line.trim()) .filter(line => line.length > 0); resolve(titles); }); }); // The window titles are already filtered for PCB Editor windows const kicadTitles = windowTitles; // Check each KiCad window title for our specific board for (const title of kicadTitles) { // Check if this window contains our board name // Title format examples: // "board — PCB Editor" (no unsaved changes) // "*board — PCB Editor" (has unsaved changes) const hasUnsavedChanges = title.startsWith('*'); const cleanTitle = hasUnsavedChanges ? title.substring(1) : title; // Extract the board name from the title let titleParts = cleanTitle.split(' — PCB Editor'); if (titleParts.length === 1) { // Try with regular hyphen if em dash didn't work titleParts = cleanTitle.split(' - PCB Editor'); } if (titleParts.length > 0) { const titleBoardName = titleParts[0].trim(); // Check if this matches our board name if (titleBoardName === boardName) { return { found: true, hasUnsavedChanges: hasUnsavedChanges, windowTitle: title, }; } } } return { found: false, hasUnsavedChanges: false }; } catch (error) { return { found: false, hasUnsavedChanges: false }; } } /** * Prompts the user to save changes in KiCad and wait before continuing. * @param boardName - The name of the board * @param windowTitle - The title of the KiCad window * @returns Promise that resolves when user chooses to continue * @private */ export async function promptUserToSave(boardName, windowTitle) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); // Enable raw mode to capture escape key if (process.stdin.isTTY) { process.stdin.setRawMode(true); } return new Promise((resolve) => { // Handle escape key to cancel const onData = (key) => { if (key[0] === 27) { // Escape key rl.close(); if (process.stdin.isTTY) { process.stdin.setRawMode(false); } console.log(chalk.red(`\n❌ ${boardName}.kicad_pcb write cancelled`)); process.exit(0); } }; process.stdin.on('data', onData); rl.question(chalk.bold.bgYellowBright(chalk.bgYellow(`🐉 Warning:`) + chalk.bold.bgBlack(` ${boardName} has unsaved changes in KiCad. Press Enter to continue or Escape to cancel...`)), (answer) => { process.stdin.removeListener('data', onData); if (process.stdin.isTTY) { process.stdin.setRawMode(false); } rl.close(); resolve(); }); }); }