"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/js/TopasImportCIFFabio.js var require_TopasImportCIFFabio = __commonJS({ "src/js/TopasImportCIFFabio.js"(exports2, module2) { "use strict"; var vscode36 = require("vscode"); var fs19 = require("fs"); var path20 = require("path"); function TopasImportCIFFabio2() { return vscode36.commands.registerCommand("topas-editor.TopasImportCIFFabio", async (caseFlag) => { if (typeof caseFlag === "object" && caseFlag !== null && "text" in caseFlag) { caseFlag = caseFlag.text; } if (!caseFlag) { caseFlag = "none"; } const fileUri = await vscode36.window.showOpenDialog({ canSelectMany: false, filters: { "CIF Files": ["cif", "CIF"], "All Files": ["*"] } }); if (!fileUri || fileUri.length === 0) { return; } const selectedFile = fileUri[0].fsPath; const editor = vscode36.window.activeTextEditor; if (!editor) { vscode36.window.showErrorMessage("No active editor."); return; } try { const cifContent = fs19.readFileSync(selectedFile, "utf8"); const documentText = editor.document.getText(); const existingPhases = (documentText.match(/STR\(/ig) || []).length; const newPhaseNumber = existingPhases + 1; let phaseNameFromCif = path20.basename(selectedFile, path20.extname(selectedFile)); const B_CONV = 8 * Math.PI * Math.PI; const lines = cifContent.split(/\r?\n/); let cell = {}; let atoms = []; let bonds = []; let anisoData = {}; let inLoop = false; let loopHeaders = []; for (const line of lines) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith("#")) continue; if (trimmed.startsWith("loop_")) { inLoop = true; loopHeaders = []; continue; } if (inLoop) { if (trimmed.startsWith("_")) { loopHeaders.push(trimmed); } else { const values = trimmed.match(/(?:[^\s"']+|"([^"]*)"|'([^']*)')+/g)?.map((v) => v.replace(/["']/g, "")) || []; if (values.length === 0) continue; const headerMap = {}; loopHeaders.forEach((h, i) => { headerMap[h] = i; }); if (loopHeaders.includes("_atom_site_label")) { const label = values[headerMap["_atom_site_label"]]; const typeSymbolFromCif = values[headerMap["_atom_site_type_symbol"]]; let finalTypeSymbol = typeSymbolFromCif; if (!finalTypeSymbol || finalTypeSymbol === "." || finalTypeSymbol === "?") { finalTypeSymbol = label; } const chargeRegex = /([A-Za-z]+)(\d+)([\+\-]$)/; const match = finalTypeSymbol.match(chargeRegex); if (match) { const [, element, number, sign] = match; finalTypeSymbol = `${element}${sign}${number}`; } const pureElement = finalTypeSymbol.replace(/[\d\+\-].*/, ""); let atom = { label, typeSymbol: finalTypeSymbol, element: pureElement, x: values[headerMap["_atom_site_fract_x"]], y: values[headerMap["_atom_site_fract_y"]], z: values[headerMap["_atom_site_fract_z"]], occ: values[headerMap["_atom_site_occupancy"]], uiso: values[headerMap["_atom_site_U_iso_or_equiv"]], biso: values[headerMap["_atom_site_B_iso_or_equiv"]] }; if (atom.label && atom.x && atom.y && atom.z) { atoms.push(atom); } } else if (loopHeaders.includes("_atom_site_aniso_label")) { const label = values[headerMap["_atom_site_aniso_label"]]; if (label) { anisoData[label] = { u11: values[headerMap["_atom_site_aniso_U_11"]], b11: values[headerMap["_atom_site_aniso_B_11"]], u22: values[headerMap["_atom_site_aniso_U_22"]], b22: values[headerMap["_atom_site_aniso_B_22"]], u33: values[headerMap["_atom_site_aniso_U_33"]], b33: values[headerMap["_atom_site_aniso_B_33"]], u12: values[headerMap["_atom_site_aniso_U_12"]], b12: values[headerMap["_atom_site_aniso_B_12"]], u13: values[headerMap["_atom_site_aniso_U_13"]], b13: values[headerMap["_atom_site_aniso_B_13"]], u23: values[headerMap["_atom_site_aniso_U_23"]], b23: values[headerMap["_atom_site_aniso_B_23"]] }; } } else if (loopHeaders.includes("_geom_bond_atom_site_label_1")) { const a1 = values[headerMap["_geom_bond_atom_site_label_1"]]; const a2 = values[headerMap["_geom_bond_atom_site_label_2"]]; if (a1 && a2) bonds.push({ a1, a2 }); } else { inLoop = false; } } } else { const parts = trimmed.split(/\s+/); const key = parts[0]; if (parts.length > 1) { if (key.startsWith("_cell_")) { cell[key] = parts[1].split("(")[0]; } else if (key === "_symmetry_space_group_name_H-M" || key === "_space_group_name_H-M_alt") { if (!cell._symmetry_space_group_name_H_M) { cell._symmetry_space_group_name_H_M = trimmed.split(/\s+/).slice(1).join(" ").replace(/'/g, ""); } } else if (key === "_space_group_IT_number" || key === "_symmetry_Int_Tables_number") { if (!cell._space_group_IT_number) cell._space_group_IT_number = parts[1]; } else if (key === "_chemical_name_common" || key === "_chemical_name_systematic") { phaseNameFromCif = trimmed.split(/\s+/).slice(1).join(" ").replace(/['"`]/g, ""); } } } } if (atoms.length === 0) { vscode36.window.showErrorMessage("Failed to parse atoms from CIF file."); return; } const outputLines = []; const sgName = (cell._symmetry_space_group_name_H_M || "P1").replace(/\s/g, ""); const itNumberString = cell._space_group_IT_number || cell._symmetry_Int_Tables_number; const sgNum = itNumberString ? parseInt(itNumberString, 10) : 0; let system = "Triclinic"; if (sgNum > 0) { if (sgNum >= 3 && sgNum <= 15) system = "Monoclinic"; else if (sgNum >= 16 && sgNum <= 74) system = "Orthorhombic"; else if (sgNum >= 75 && sgNum <= 142) system = "Tetragonal"; else if (sgNum >= 143 && sgNum <= 167) system = "Trigonal"; else if (sgNum >= 168 && sgNum <= 194) system = "Hexagonal"; else if (sgNum >= 195 && sgNum <= 230) system = "Cubic"; } else { vscode36.window.showWarningMessage(`Could not find IT number in CIF. Guessing system from lattice parameters.`); const a = parseFloat(cell._cell_length_a || "0"), b = parseFloat(cell._cell_length_b || "0"), c = parseFloat(cell._cell_length_c || "0"), al = parseFloat(cell._cell_angle_alpha || "0"), be = parseFloat(cell._cell_angle_beta || "0"), ga = parseFloat(cell._cell_angle_gamma || "0"), tol = 0.01; if (Math.abs(a - b) < tol && Math.abs(b - c) < tol && Math.abs(al - 90) < tol && Math.abs(be - 90) < tol && Math.abs(ga - 90) < tol) system = "Cubic"; else if (Math.abs(a - b) < tol && Math.abs(al - 90) < tol && Math.abs(be - 90) < tol && Math.abs(ga - 120) < tol) system = "Hexagonal"; else if (Math.abs(a - b) < tol && Math.abs(al - 90) < tol && Math.abs(be - 90) < tol && Math.abs(ga - 90) < tol) system = "Tetragonal"; else if (Math.abs(al - 90) < tol && Math.abs(ga - 90) < tol && Math.abs(be - 90) > tol) system = "Monoclinic"; else if (Math.abs(al - 90) < tol && Math.abs(be - 90) < tol && Math.abs(ga - 90) < tol) system = "Orthorhombic"; else system = "Triclinic"; } let params = ""; const aVal = parseFloat(cell._cell_length_a || "10"), bVal = parseFloat(cell._cell_length_b || "10"), cVal = parseFloat(cell._cell_length_c || "10"), alVal = parseFloat(cell._cell_angle_alpha || "90"), beVal = parseFloat(cell._cell_angle_beta || "90"), gaVal = parseFloat(cell._cell_angle_gamma || "90"); switch (system) { case "Cubic": params = `Cubic(lpa${newPhaseNumber} ${aVal})`; break; case "Tetragonal": params = `Tetragonal(lpa${newPhaseNumber} ${aVal}, lpc${newPhaseNumber} ${cVal})`; break; case "Orthorhombic": params = `Orthorhombic(lpa${newPhaseNumber} ${aVal}, lpb${newPhaseNumber} ${bVal}, lpc${newPhaseNumber} ${cVal})`; break; case "Hexagonal": case "Trigonal": params = `Hexagonal(lpa${newPhaseNumber} ${aVal}, lpc${newPhaseNumber} ${cVal})`; break; case "Monoclinic": params = `Monoclinic(lpa${newPhaseNumber} ${aVal}, lpb${newPhaseNumber} ${bVal}, lpc${newPhaseNumber} ${cVal}, lpbe${newPhaseNumber} ${beVal})`; break; default: params = `Triclinic(lpa${newPhaseNumber} ${aVal}, lpb${newPhaseNumber} ${bVal}, lpc${newPhaseNumber} ${cVal}, lpal${newPhaseNumber} ${alVal}, lpbe${newPhaseNumber} ${beVal}, lpga${newPhaseNumber} ${gaVal})`; break; } outputLines.push(` STR(${sgName}, "${phaseNameFromCif}")`); outputLines.push(` ${params}`); outputLines.push(` MVW(0, 0, 0)`); outputLines.push(``); outputLines.push(` macro ref${newPhaseNumber} { }`); const formatCoordinate = (coordStr) => { const specialFractions = { "0.0833": "=1/12;", "0.1250": "=1/8;", "0.1667": "=1/6;", "0.2500": "=1/4;", "0.3333": "=1/3;", "0.3750": "=3/8;", "0.5000": "=1/2;", "0.6250": "=5/8;", "0.6667": "=2/3;", "0.7500": "=3/4;", "0.8333": "=5/6;", "0.8750": "=7/8;" }; const tolerance = 1e-4; const originalValue = coordStr?.split("(")[0] || "0"; const numValue = parseFloat(originalValue); if (isNaN(numValue)) return `ref${newPhaseNumber} 0.00000`; if (Math.abs(numValue) < tolerance) { return "=0;"; } for (const dec in specialFractions) { if (Math.abs(Math.abs(numValue) - parseFloat(dec)) < tolerance) { const sign = numValue < 0 ? "-" : ""; return `${sign}${specialFractions[dec]}`; } } return `ref${newPhaseNumber} ${numValue.toFixed(5)}`; }; const heavyAtoms = atoms.filter((a) => a.element !== "H" && a.element !== "D"); const hydrogenAtoms = atoms.filter((a) => a.element === "H" || a.element === "D"); let heavyBeqSum = 0; const formattedAtomData = heavyAtoms.map((atom) => { const xStr = `x ${formatCoordinate(atom.x)}`; const yStr = `y ${formatCoordinate(atom.y)}`; const zStr = `z ${formatCoordinate(atom.z)}`; let parsedOcc = parseFloat(atom.occ?.split("(")[0]); const occVal = (isNaN(parsedOcc) ? 1 : parsedOcc).toFixed(2); const occStr = `occ ${atom.typeSymbol} ${occVal}`; let beqStr = "", adpStr = ""; const aniso = anisoData[atom.label]; if (aniso) { const b11 = aniso.b11 || (parseFloat(aniso.u11 || 0) * B_CONV).toFixed(4); const b22 = aniso.b22 || (parseFloat(aniso.u22 || 0) * B_CONV).toFixed(4); const b33 = aniso.b33 || (parseFloat(aniso.u33 || 0) * B_CONV).toFixed(4); const b12 = aniso.b12 || (parseFloat(aniso.u12 || 0) * B_CONV).toFixed(4); const b13 = aniso.b13 || (parseFloat(aniso.u13 || 0) * B_CONV).toFixed(4); const b23 = aniso.b23 || (parseFloat(aniso.u23 || 0) * B_CONV).toFixed(4); adpStr = `ADPs { ${b11} ${b22} ${b33} ${b12} ${b13} ${b23} }`; } let biso = atom.biso?.split("(")[0] || (atom.uiso ? (parseFloat(atom.uiso.split("(")[0]) * B_CONV).toFixed(5) : null); let parsedBiso = parseFloat(biso); if (!isNaN(parsedBiso)) { beqStr = `beq ${parsedBiso.toFixed(5)}`; heavyBeqSum += parsedBiso; } else if (!aniso) { beqStr = `beq @ 0.5`; heavyBeqSum += 0.5; } return { label: atom.label, xStr, yStr, zStr, occStr, beqStr, adpStr }; }); const maxWidths = { label: 0, x: 0, y: 0, z: 0, occ: 0 }; formattedAtomData.forEach((data) => { if (data.label.length > maxWidths.label) maxWidths.label = data.label.length; if (data.xStr.length > maxWidths.x) maxWidths.x = data.xStr.length; if (data.yStr.length > maxWidths.y) maxWidths.y = data.yStr.length; if (data.zStr.length > maxWidths.z) maxWidths.z = data.zStr.length; if (data.occStr.length > maxWidths.occ) maxWidths.occ = data.occStr.length; }); formattedAtomData.forEach((data) => { const parts = [`site ${data.label.padEnd(maxWidths.label)}`, data.xStr.padEnd(maxWidths.x), data.yStr.padEnd(maxWidths.y), data.zStr.padEnd(maxWidths.z), data.occStr.padEnd(maxWidths.occ), data.beqStr]; if (data.adpStr) { parts.push(data.adpStr); } outputLines.push(` ${parts.join(" ")}`); }); if (bonds.length > 0 && hydrogenAtoms.length > 0) { outputLines.push("\n 'Riding Hydrogens (from _geom_bond_ list)"); const heavyAtomBeqs = new Map(heavyAtoms.map((a) => { const bisoVal = a.biso?.split("(")[0] || (a.uiso ? String(parseFloat(a.uiso.split("(")[0]) * B_CONV) : null); return [a.label, parseFloat(bisoVal) || 3]; })); for (const hAtom of hydrogenAtoms) { const parentBond = bonds.find((b) => b.a1 === hAtom.label || b.a2 === hAtom.label); if (parentBond) { const parentLabel = parentBond.a1 === hAtom.label ? parentBond.a2 : parentBond.a1; const parentBeq = heavyAtomBeqs.get(parentLabel) || 3; const hBeq = (parentBeq * 1.2).toFixed(5); const x = parseFloat(hAtom.x?.split("(")[0] || "0").toFixed(5); const y = parseFloat(hAtom.y?.split("(")[0] || "0").toFixed(5); const z = parseFloat(hAtom.z?.split("(")[0] || "0").toFixed(5); outputLines.push(` H_ride(${hAtom.label}, ${parentLabel}, ${x}, ${y}, ${z}, ${hBeq})`); } } } else if (hydrogenAtoms.length > 0) { outputLines.push("\n 'Riding Hydrogens (inferred from distance)"); const calculateDistance = (a1, a2, cellParams2) => { const degToRad = (deg) => deg * Math.PI / 180; const { a, b, c, al, be, ga } = cellParams2; let dx = parseFloat(a1.x.split("(")[0]) - parseFloat(a2.x.split("(")[0]); let dy = parseFloat(a1.y.split("(")[0]) - parseFloat(a2.y.split("(")[0]); let dz = parseFloat(a1.z.split("(")[0]) - parseFloat(a2.z.split("(")[0]); dx -= Math.round(dx); dy -= Math.round(dy); dz -= Math.round(dz); const cos_al = Math.cos(degToRad(al)); const cos_be = Math.cos(degToRad(be)); const cos_ga = Math.cos(degToRad(ga)); const dx_a = dx * a; const dy_b = dy * b; const dz_c = dz * c; return Math.sqrt(dx_a * dx_a + dy_b * dy_b + dz_c * dz_c + 2 * dy_b * dz_c * cos_al + 2 * dz_c * dx_a * cos_be + 2 * dx_a * dy_b * cos_ga); }; const cellParams = { a: aVal, b: bVal, c: cVal, al: alVal, be: beVal, ga: gaVal }; for (const hAtom of hydrogenAtoms) { let minDistance = Infinity; let parentAtom = null; for (const heavyAtom of heavyAtoms) { const distance = calculateDistance(hAtom, heavyAtom, cellParams); if (distance < minDistance) { minDistance = distance; parentAtom = heavyAtom; } } if (parentAtom && minDistance < 1.2) { const parentBeq = parseFloat(parentAtom.biso?.split("(")[0] || (parentAtom.uiso ? String(parseFloat(parentAtom.uiso.split("(")[0]) * B_CONV) : "3.0")) || 3; const hBeq = (parentBeq * 1.2).toFixed(5); const x = parseFloat(hAtom.x?.split("(")[0] || "0").toFixed(5); const y = parseFloat(hAtom.y?.split("(")[0] || "0").toFixed(5); const z = parseFloat(hAtom.z?.split("(")[0] || "0").toFixed(5); outputLines.push(` H_ride(${hAtom.label}, ${parentAtom.label}, ${x}, ${y}, ${z}, ${hBeq})`); } else { const xStr = formatCoordinate(hAtom.x); const yStr = formatCoordinate(hAtom.y); const zStr = formatCoordinate(hAtom.z); const occVal = (parseFloat(hAtom.occ) || 1).toFixed(2); const hBeq = ((heavyBeqSum / heavyAtoms.length || 3) * 1.2).toFixed(5); outputLines.push(` 'site ${hAtom.label.padEnd(8)} x ${xStr} y ${yStr} z ${zStr} occ ${hAtom.typeSymbol} ${occVal} beq ${hBeq} ' H atom with no parent found`); } } } const topasStructureBlock = outputLines.join("\n"); const xddMatch = documentText.match(/\s*xdd\s+([^\s]+)/i); const dataFileName = xddMatch ? xddMatch[1] : ""; const TCHZ_DEFAULT = "TCHZ_Peak_Type(pku, 0.00039,pkv, -0.00221,pkw, -0.00146,!pkz, 0.0000,pkx, 0.00957, pky, 0.0001)"; let selectedTchzLine = TCHZ_DEFAULT; if (dataFileName) { const TCHZ_FE_FE = "TCHZ_Peak_Type(!pku, 0.00130319752 min 0,!pkv, 0.000516355932,!pkw, 0.00081649608 min 0,!pkz, 0.0000,!pkx, 0.0238884451,!pky, 0.0001)"; const TCHZ_FE_FL = "TCHZ_Peak_Type(!pku, 0.00590711399 min 0,!pkv, -0.0133592662,!pkw, 0.00379480658 min 0,!pkz, 0.0000,!pkx, 0.0182574707,!pky, 0.00287813284)"; const TCHZ_FL_FE = "TCHZ_Peak_Type(!pku, 0.00111794292 min 0,!pkv, 0.00332999143,!pkw, 0.000200615316 min 0,!pkz, 0.0000,!pkx, 0.0258996526,!pky, 0.0001)"; const TCHZ_FL_FL = "TCHZ_Peak_Type(!pku, 0.00166955289 min 0,!pkv, 0.00313105249,!pkw, 0.000127263586 min 0,!pkz, 0.0000,!pkx, 0.0257846332,!pky, 0.0001)"; const lowerCaseDataFileName = dataFileName.toLowerCase(); if (lowerCaseDataFileName.includes("_fe_fe.")) selectedTchzLine = TCHZ_FE_FE; else if (lowerCaseDataFileName.includes("_fe_fl.")) selectedTchzLine = TCHZ_FE_FL; else if (lowerCaseDataFileName.includes("_fl_fe.")) selectedTchzLine = TCHZ_FL_FE; else if (lowerCaseDataFileName.includes("_fl_fl.")) selectedTchzLine = TCHZ_FL_FL; } const forStrsRegex = /\n*\s*for strs\s*\{[\s\S]*?\}/m; const existingForStrsMatch = documentText.match(forStrsRegex); const forStrsBlock = existingForStrsMatch ? existingForStrsMatch[0] : ` for strs { ${selectedTchzLine} }`; const finalOutLine = ` 'Out_pdCIF(ciffile, "proc") `; const outPdCIFRegex = /^.*'Out_pdCIF\(([^)]*)\).*$/gm; let textToInsert1 = ` 'Structural information from ${selectedFile}`; let textToInsert2 = ""; if (caseFlag === "rietveld") { textToInsert2 = ` scale @ 0.0001 r_bragg 0 local CIF_PHASE_ID ${newPhaseNumber} 'Refine sample size/strain contributions here IF TCHZ fixed to Instrumental Resolution Function LVol_FWHM_CS_G_L(1, 100, 0.89, 100, csgc${newPhaseNumber}, 100, cslc${newPhaseNumber}, 100) e0_from_Strain( 0.001, sgc${newPhaseNumber}, 0.001, slc${newPhaseNumber}, 0.001) `; } else if (caseFlag === "pdf") { textToInsert2 = ` scale @ 1 'fix if data normalised in Gudrun pdf_zero !zero -0.00 `; } const fullInsertBlock = textToInsert1 + topasStructureBlock + textToInsert2 + (caseFlag === "rietveld" ? forStrsBlock + finalOutLine : ""); await editor.edit((editBuilder) => { if (existingForStrsMatch?.index !== void 0) { const start = editor.document.positionAt(existingForStrsMatch.index); const end = editor.document.positionAt(existingForStrsMatch.index + existingForStrsMatch[0].length); editBuilder.delete(new vscode36.Range(start, end)); } let match; while ((match = outPdCIFRegex.exec(documentText)) !== null) { const start = editor.document.positionAt(match.index); const end = editor.document.positionAt(match.index + match[0].length); editBuilder.delete(new vscode36.Range(start, end)); } }); const selection = editor.selection.active; const insertPos = new vscode36.Position(selection.line + 1, 0); const success = await editor.edit((editBuilder) => { editBuilder.insert(insertPos, fullInsertBlock); }); if (success) { vscode36.window.showInformationMessage(`CIF inserted for phase ${newPhaseNumber} (${phaseNameFromCif})`); } else { vscode36.window.showErrorMessage("Failed to insert CIF."); } } catch (e) { const err = e; vscode36.window.showErrorMessage(`An error occurred during CIF import: ${err.message}`); } }); } module2.exports = TopasImportCIFFabio2; } }); // src/js/TopasCreatePeakFitFile.js var require_TopasCreatePeakFitFile = __commonJS({ "src/js/TopasCreatePeakFitFile.js"(exports2, module2) { "use strict"; var vscode36 = require("vscode"); var fs19 = require("fs"); var path20 = require("path"); function TopasCreatePeakFitFile2() { return vscode36.commands.registerCommand("topas-editor.TopasCreatePeakFitFile", async () => { const fileUris = await vscode36.window.showOpenDialog({ canSelectMany: true, // Allows selecting multiple files openLabel: "Select Data File(s) for Peak Fitting", title: "Select Data File(s)", filters: { "Data Files": ["xy", "xye", "raw", "dat", "rd"], "All Files": ["*"] } }); if (!fileUris || fileUris.length === 0) { vscode36.window.showInformationMessage("Operation cancelled."); return; } const firstFilePath = fileUris[0].fsPath; const dir = path20.dirname(firstFilePath); const baseName = path20.basename(firstFilePath, path20.extname(firstFilePath)); const newInpPath = path20.join(dir, `${baseName}_pkfit_01.inp`); if (fs19.existsSync(newInpPath)) { const choice = await vscode36.window.showWarningMessage( `The file "${path20.basename(newInpPath)}" already exists. Do you want to overwrite it?`, { modal: true }, // Pauses execution until the user chooses "Overwrite" // Confirmation button ); if (choice !== "Overwrite") { vscode36.window.showInformationMessage("Operation cancelled."); return; } } const header = `'-------------------------------------------------------------- 'Input File for Peak Fitting with overall TCHz peak shape 'To find peaks load experimental data into topas 'Use View/search peaks then insert peaks 'Click on plus sign by file name 'Click on peaks phase 'Highlight Position and Area columns, right click to copy then paste below 'Use save/set current button then run with F6 in topas '-------------------------------------------------------------- r_wp 0 r_exp 0 r_p 0 r_wp_dash 0 r_p_dash 0 r_exp_dash 0 weighted_Durbin_Watson 0 gof 0 '-------------------------------------------------------------- 'General information about refinement here 'Remove comments as required '-------------------------------------------------------------- iters 100000 chi2_convergence_criteria 0.0001 'do_errors '-------------------------------------------------------------- 'Information on datafile etc here '--------------------------------------------------------------`; const xddLines = fileUris.map((uri) => { let fileName = path20.basename(uri.fsPath); if (fileName.includes(" ")) { fileName = `"${fileName}"`; } return `xdd ${fileName}`; }).join("\n"); const footer = ` x_calculation_step = Yobs_dx_at(Xo); convolution_step 1`; const fullContent = `${header} ${xddLines} ${footer} `; try { fs19.writeFileSync(newInpPath, fullContent, "utf-8"); const document = await vscode36.workspace.openTextDocument(newInpPath); const editor = await vscode36.window.showTextDocument(document); const lastLine = document.lineCount - 1; const newPosition = new vscode36.Position(lastLine, 0); editor.selection = new vscode36.Selection(newPosition, newPosition); vscode36.window.showInformationMessage(`Peak fitting file created: ${newInpPath}`); } catch (error) { const errMessage = error && error.message ? error.message : String(error); vscode36.window.showErrorMessage(`Failed to create file: ${errMessage}`); } }); } module2.exports = TopasCreatePeakFitFile2; } }); // src/js/TopasInsertPeakFittingBlock.js var require_TopasInsertPeakFittingBlock = __commonJS({ "src/js/TopasInsertPeakFittingBlock.js"(exports2, module2) { "use strict"; var vscode36 = require("vscode"); var fs19 = require("fs"); var path20 = require("path"); function TopasInsertPeakFittingBlock2() { return vscode36.commands.registerCommand("topas-editor.TopasInsertPeakFittingBlock", async () => { const editor = vscode36.window.activeTextEditor; if (!editor) { vscode36.window.showErrorMessage("No active editor found."); return; } const documentText = editor.document.getText(); const xddMatch = documentText.match(/\s*xdd\s+([^\s]+)/i); const dataFileName = xddMatch ? xddMatch[1] : ""; const TCHZ_FE_FE = "TCHZ_Peak_Type(!pku, 0.00130319752 min 0,!pkv, 0.000516355932,!pkw, 0.00081649608 min 0,!pkz, 0.0000,!pkx, 0.0238884451,!pky, 0.0001)"; const TCHZ_FE_FL = "TCHZ_Peak_Type(!pku, 0.00590711399 min 0,!pkv, -0.0133592662,!pkw, 0.00379480658 min 0,!pkz, 0.0000,!pkx, 0.0182574707,!pky, 0.00287813284)"; const TCHZ_FL_FE = "TCHZ_Peak_Type(!pku, 0.00111794292 min 0,!pkv, 0.00332999143,!pkw, 0.000200615316 min 0,!pkz, 0.0000,!pkx, 0.0258996526,!pky, 0.0001)"; const TCHZ_FL_FL = "TCHZ_Peak_Type(!pku, 0.00166955289 min 0,!pkv, 0.00313105249,!pkw, 0.000127263586 min 0,!pkz, 0.0000,!pkx, 0.0257846332,!pky, 0.0001)"; const TCHZ_DEFAULT = "TCHZ_Peak_Type(pku, 0.00039,pkv, -0.00221,pkw, -0.00146,!pkz, 0.0000,pkx, 0.00957, pky, 0.0001)"; let selectedTchzLine = TCHZ_DEFAULT; let message = "Inserted default TCHZ Peak Type."; if (dataFileName) { const lowerCaseDataFileName = dataFileName.toLowerCase(); if (lowerCaseDataFileName.includes("_fe_fe.")) { selectedTchzLine = TCHZ_FE_FE; message = "Inserted TCHZ for FE_FE data."; } else if (lowerCaseDataFileName.includes("_fe_fl.")) { selectedTchzLine = TCHZ_FE_FL; message = "Inserted TCHZ for FE_FL data."; } else if (lowerCaseDataFileName.includes("_fl_fe.")) { selectedTchzLine = TCHZ_FL_FE; message = "Inserted TCHZ for FL_FE data."; } else if (lowerCaseDataFileName.includes("_fl_fl.")) { selectedTchzLine = TCHZ_FL_FL; message = "Inserted TCHZ for FL_FL data."; } } else { vscode36.window.showWarningMessage("No 'xdd' file found in the document. Inserting default TCHZ function."); } const snippetText = ` bkg @ 0 0 0 0 0 0 xo_Is ${selectedTchzLine} LVol_FWHM_CS_G_L(1, 100, 0.89, 100, csgc, 100, cslc, 100) e0_from_Strain( 0.001, sgc, 0.001, slc, 0.001) load xo I { 'copy peak position and intensity here 'insert @'s before 2th and area to refine $0 } `; const snippet = new vscode36.SnippetString(snippetText); editor.insertSnippet(snippet); vscode36.window.showInformationMessage(message); }); } module2.exports = TopasInsertPeakFittingBlock2; } }); // src/extension.ts var extension_exports = {}; __export(extension_exports, { activate: () => activate, deactivate: () => deactivate }); module.exports = __toCommonJS(extension_exports); var vscode35 = __toESM(require("vscode")); var path19 = __toESM(require("path")); var fs18 = __toESM(require("fs")); // src/commands/TopasArchive.ts var vscode = __toESM(require("vscode")); var fs = __toESM(require("fs")); var path = __toESM(require("path")); function TopasArchive() { return vscode.commands.registerCommand("topas-editor.TopasArchive", async () => { const editor = vscode.window.activeTextEditor; if (editor) { const document = editor.document; const filePath = document.fileName; await document.save(); const dirName = path.dirname(filePath); const baseName = path.basename(filePath, path.extname(filePath)); const extension = path.extname(filePath); const now = /* @__PURE__ */ new Date(); const timestamp = now.toISOString().slice(0, 16).replace("T", "-").replace(":", ""); const archiveFilePath = path.join( dirName, `${baseName}_${timestamp}${extension}` ); fs.copyFile(filePath, archiveFilePath, (err) => { if (err) { vscode.window.showErrorMessage("Failed to create archive file."); } else { vscode.window.showInformationMessage(`Archive file created: ${archiveFilePath}`); } }); } else { vscode.window.showErrorMessage("No active editor found."); } }); } // src/commands/TopasBeqByType.ts var vscode2 = __toESM(require("vscode")); function TopasBeqByType() { return vscode2.commands.registerCommand("topas-editor.TopasBeqByType", async () => { const editor = vscode2.window.activeTextEditor; if (!editor) { vscode2.window.showErrorMessage("No active editor found."); return; } const document = editor.document; const selections = editor.selections; await editor.edit((editBuilder) => { selections.forEach((selection) => { for (let lineNumber = selection.start.line; lineNumber <= selection.end.line; lineNumber++) { const line = document.lineAt(lineNumber); const lineText = line.text; if (lineText.toLowerCase().includes("site")) { const occMatch = lineText.match(/occ\s+(\w+)/); if (occMatch) { const type = occMatch[1]; const element = type.replace(/[\d\+\-]/g, ""); const newLine = lineText.replace(/beq.*$/, `beq b${element} 0.5`); editBuilder.replace(line.range, newLine); } } } }); }); }); } // src/commands/TopasInsertFileTextArg.ts var vscode3 = __toESM(require("vscode")); var fs2 = __toESM(require("fs")); var path2 = __toESM(require("path")); function TopasInsertFileTextArg() { return vscode3.commands.registerCommand("topas-editor.TopasInsertFileTextArg", async (caseFlag) => { if (typeof caseFlag === "object" && caseFlag !== null && "text" in caseFlag) { caseFlag = caseFlag.text; } if (!caseFlag) { caseFlag = "none"; } let dirPath = ""; let fileExtension = ""; const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode3.window.showErrorMessage("External program directory not set in environment variables."); return; } switch (caseFlag.toLowerCase()) { case "lam": dirPath = path2.join(topasDir, "lam"); fileExtension = "lam"; break; case "none": const editor2 = vscode3.window.activeTextEditor; if (editor2) { const fileUri2 = editor2.document.uri.fsPath; dirPath = path2.dirname(fileUri2); } else { vscode3.window.showErrorMessage("No active text editor found."); return; } fileExtension = "*"; break; case "str": const editor22 = vscode3.window.activeTextEditor; if (editor22) { const fileUri2 = editor22.document.uri.fsPath; dirPath = path2.dirname(fileUri2); } else { vscode3.window.showErrorMessage("No active text editor found."); return; } fileExtension = "str"; break; default: vscode3.window.showErrorMessage("Unknown case flag. Please use template, lam, tof, or xtl."); return; } if (!fs2.existsSync(dirPath) || !fs2.lstatSync(dirPath).isDirectory()) { vscode3.window.showErrorMessage("Invalid directory path for the selected case."); return; } const fileUri = await vscode3.window.showOpenDialog({ canSelectMany: false, defaultUri: vscode3.Uri.file(dirPath), filters: { "Selected Files": [fileExtension], "All Files": ["*"] } }); if (!fileUri || fileUri.length === 0) { return; } const selectedFile = fileUri[0].fsPath; const selectedFileContent = fs2.readFileSync(selectedFile, "utf8"); let textToInsert1 = ""; let textToInsert2 = ""; switch (caseFlag) { case "str": textToInsert1 = ` 'Structural information read from ${selectedFile} `; textToInsert2 = ` r_bragg 0 scale @ 0.0001 TCHZ_Peak_Type(pku, 0.00039,pkv, -0.00221,pkw, -0.00146,!pkz, 0.0000,pkx, 0.00957,!pky, 0.0000) Phase_Density_g_on_cm3(0) `; break; case "pdf": textToInsert1 = ``; textToInsert2 = ``; break; default: textToInsert1 = ``; textToInsert2 = ``; break; } const editor = vscode3.window.activeTextEditor; if (editor) { await editor.edit((editBuilder) => { editBuilder.insert(editor.selection.active, textToInsert1); editBuilder.insert(editor.selection.active, selectedFileContent); editBuilder.insert(editor.selection.active, textToInsert2); }); } }); } // src/commands/TopasInsertStructure.ts var vscode4 = __toESM(require("vscode")); function TopasInsertStructure() { vscode4.commands.registerCommand("topas-editor.TopasInsertStructure", async () => { const input = await vscode4.window.showInputBox({ prompt: `Enter space group and cell parameters separated by spaces. e.g. Pnma 10.2 8.6 5.4 90 90 90. Don't click on any other window until you have done this. ` }); if (!input) { vscode4.window.showErrorMessage("Input is required."); return; } const values = input.split(" ").filter(Boolean); if (values.length !== 7) { vscode4.window.showErrorMessage("Please enter exactly 7 values separated by spaces."); return; } const sentence = ` a ${values[1]} b ${values[2]} c ${values[3]} al ${values[4]} be ${values[5]} ga ${values[6]} space_group ${values[0]}`; const editor = vscode4.window.activeTextEditor; if (editor) { const position = editor.selection.active; editor.edit((editBuilder) => { editBuilder.insert(position, sentence); }); vscode4.window.showInformationMessage(`Cell parameters inserted. Set refinement flags appropriately for the crystal system. Edit the site line as required.`); } }); } // src/commands/TopasSaveSet.ts var vscode5 = __toESM(require("vscode")); var fs3 = __toESM(require("fs")); var path3 = __toESM(require("path")); function TopasSaveSet() { return vscode5.commands.registerCommand("topas-editor.TopasSaveSet", async () => { const editor = vscode5.window.activeTextEditor; if (editor) { const document = editor.document; const filePath = document.fileName; if (!filePath.toLowerCase().endsWith(".inp")) { vscode5.window.showErrorMessage("This is not an INP file - can't send to TOPAS."); return; } const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode5.window.showErrorMessage("External program directory not set in environment variables."); return; } const outputFilePath = path3.join(topasDir, "launch_file.txt"); if (!fs3.existsSync(topasDir)) { fs3.mkdirSync(topasDir, { recursive: true }); } fs3.writeFile(outputFilePath, `"${filePath}"`, (err) => { if (err) { vscode5.window.showErrorMessage("Failed to save file path for TOPAS."); } else { vscode5.window.showInformationMessage("INP File successfully sent to TOPAS"); } }); await document.save(); const backupFilePath = filePath.replace(".inp", ".backup"); fs3.copyFile(filePath, backupFilePath, (err) => { if (err) { vscode5.window.showErrorMessage("Failed to create backup file."); } else { vscode5.window.showInformationMessage(`Backup file created: ${backupFilePath}`); } }); } else { vscode5.window.showErrorMessage("No active editor found."); } }); } // src/commands/TopasPlotAllPy.ts var vscode6 = __toESM(require("vscode")); var fs4 = __toESM(require("fs")); var path4 = __toESM(require("path")); function TopasPlotAllPy() { return vscode6.commands.registerCommand("topas-editor.TopasPlotAllPy", async () => { const editor = vscode6.window.activeTextEditor; if (!editor) { vscode6.window.showErrorMessage("No active editor open."); return; } const currentFilePath = editor.document.uri.fsPath; const directoryName = path4.dirname(currentFilePath); const topasExtension = vscode6.extensions.getExtension("johnsoevans.topas-editor"); if (!topasExtension) { vscode6.window.showErrorMessage('Extension "johnsoevans.topas-editor" not found.'); return; } const scriptsPath = path4.join(topasExtension.extensionPath, "scripts", "plot_all.py"); let plotContent; try { plotContent = fs4.readFileSync(scriptsPath, "utf8"); } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; vscode6.window.showErrorMessage(`Could not read plot_all.py: ${msg}`); return; } const targetPath = path4.join(directoryName, "plot_all.py"); if (fs4.existsSync(targetPath)) { const choice = await vscode6.window.showWarningMessage( "plot_all.py already exists in this folder. Overwrite?", { modal: true }, "Yes", "No" ); if (choice !== "Yes") { vscode6.window.showInformationMessage("Operation cancelled."); return; } } try { fs4.writeFileSync(targetPath, plotContent); } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; vscode6.window.showErrorMessage(`Could not write file: ${msg}`); return; } try { const doc = await vscode6.workspace.openTextDocument(targetPath); await vscode6.window.showTextDocument(doc); vscode6.window.showInformationMessage("Please wait for plots...if errors: change filename to plot, change xcol then re-run python script in the terminal."); } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; vscode6.window.showErrorMessage(`Could not open file: ${msg}`); return; } const terminal = vscode6.window.createTerminal({ name: "Python Script Directory", cwd: directoryName // Set the working directory to the current folder }); terminal.show(); terminal.sendText(`python ${path4.join(directoryName, "plot_all.py")}`); }); } // src/commands/TopasLivePlotPy.ts var vscode7 = __toESM(require("vscode")); var fs5 = __toESM(require("fs")); var path5 = __toESM(require("path")); function TopasLivePlotPy() { return vscode7.commands.registerCommand("topas-editor.TopasLivePlotPy", async () => { const editor = vscode7.window.activeTextEditor; if (!editor) { vscode7.window.showErrorMessage("No active editor open."); return; } const currentFilePath = editor.document.uri.fsPath; const directoryName = path5.dirname(currentFilePath); const topasExtension = vscode7.extensions.getExtension("johnsoevans.topas-editor"); if (!topasExtension) { vscode7.window.showErrorMessage('Extension "johnsoevans.topas-editor" not found.'); return; } const scriptsPath = path5.join(topasExtension.extensionPath, "scripts", "live_plot.py"); let plotContent; try { plotContent = fs5.readFileSync(scriptsPath, "utf8"); } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; vscode7.window.showErrorMessage(`Could not read live_plot.py: ${msg}`); return; } const targetPath = path5.join(directoryName, "live_plot.py"); if (fs5.existsSync(targetPath)) { const choice = await vscode7.window.showWarningMessage( "live_plot.py already exists in this folder. Overwrite?", { modal: true }, "Yes", "No" ); if (choice !== "Yes") { vscode7.window.showInformationMessage("Operation cancelled."); return; } } try { fs5.writeFileSync(targetPath, plotContent); } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; vscode7.window.showErrorMessage(`Could not write file: ${msg}`); return; } try { const doc = await vscode7.workspace.openTextDocument(targetPath); await vscode7.window.showTextDocument(doc); vscode7.window.showInformationMessage("Edit then run python script for live plots"); } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; vscode7.window.showErrorMessage(`Could not open file: ${msg}`); return; } const terminal = vscode7.window.createTerminal({ name: "Python Script Directory", cwd: directoryName // Set the working directory to the current folder }); terminal.show(); }); } // src/commands/TopasSearchINP.ts var vscode8 = __toESM(require("vscode")); var fs6 = __toESM(require("fs")); var path6 = __toESM(require("path")); function fileContainsString(filePath, searchString) { const fileContent = fs6.readFileSync(filePath, "utf8"); return fileContent.toLowerCase().includes(searchString.toLowerCase()); } function TopasSearchINP() { return vscode8.commands.registerCommand("topas-editor.TopasSearchINP", async () => { const searchString = await vscode8.window.showInputBox({ prompt: "Enter a string to search for in .inp files (filename or content) - warning this may be slow!\n" }); if (!searchString) { vscode8.window.showErrorMessage("Search string is required."); return; } const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode8.window.showErrorMessage("The TOPAS_DIR environment variable is not set."); return; } if (!fs6.existsSync(topasDir)) { vscode8.window.showErrorMessage(`Directory ${topasDir} does not exist.`); return; } vscode8.window.showInformationMessage(`Searching ${topasDir} for files containing ${searchString}.`); const matchingFiles = []; const searchDirectory = (dir) => { const files = fs6.readdirSync(dir); files.forEach((file) => { const fullPath = path6.join(dir, file); if (fs6.statSync(fullPath).isDirectory()) { searchDirectory(fullPath); } else if (file.toLowerCase().endsWith(".inp")) { if (file.toLowerCase().includes(searchString.toLowerCase()) || fileContainsString(fullPath, searchString)) { matchingFiles.push(fullPath); } } }); }; searchDirectory(topasDir); if (matchingFiles.length === 0) { vscode8.window.showInformationMessage(`No matching .inp files found for "${searchString}".`); return; } const selectedFile = await vscode8.window.showQuickPick( matchingFiles.map((file) => path6.basename(file)), { placeHolder: "Select a file to open" } ); if (!selectedFile) { return; } const selectedFilePath = matchingFiles.find((file) => path6.basename(file) === selectedFile); if (selectedFilePath) { const document = await vscode8.workspace.openTextDocument(selectedFilePath); vscode8.window.showTextDocument(document); } }); } // src/commands/TopasInpFromTemplate.ts var vscode9 = __toESM(require("vscode")); var fs7 = __toESM(require("fs")); var os = __toESM(require("os")); function TopasInpFromTemplate() { return vscode9.commands.registerCommand("topas-editor.TopasInpFromTemplate", async (caseFlag) => { if (typeof caseFlag === "object" && caseFlag !== null && "text" in caseFlag) { caseFlag = caseFlag.text; } if (!caseFlag) { caseFlag = "none"; } const extension = vscode9.extensions.getExtension("johnsoevans.topas-editor"); if (!extension) { vscode9.window.showErrorMessage("topas-editor extension not found, cannot identify templates directory."); return; } const templateDir = vscode9.Uri.joinPath(vscode9.Uri.file(extension.extensionPath), "assets", "templates").fsPath; if (!templateDir || !fs7.existsSync(templateDir)) { vscode9.window.showErrorMessage(`Directory ${templateDir} does not exist or is not defined.`); return; } let fileExtension = ""; switch (caseFlag.toLowerCase()) { case "inp": fileExtension = "inp"; break; case "tof": fileExtension = "tof"; break; case "pdf": fileExtension = "gor"; break; case "xtl": fileExtension = "xtl"; break; case "index": fileExtension = "index"; break; case "pkfit": fileExtension = "pkfit"; break; case "none": const editor = vscode9.window.activeTextEditor; if (editor) { const fileUri2 = editor.document.uri.fsPath; } else { vscode9.window.showErrorMessage("No active text editor found."); return; } fileExtension = "*"; break; default: vscode9.window.showErrorMessage("Unknown case flag. Please use template, tof, pdf, index or xtl."); return; } const fileUri = await vscode9.window.showOpenDialog({ canSelectMany: false, openLabel: "Select template", title: "Select a prewritten template then save as a new .inp file in another directory", filters: { "Selected Files": [fileExtension], "All Files": ["*"] }, defaultUri: vscode9.Uri.file(templateDir) // Updated default template folder }); if (!fileUri || fileUri.length === 0) { return; } let content; try { content = fs7.readFileSync(fileUri[0].fsPath, "utf-8"); } catch (error) { const errMessage = error instanceof Error ? error.message : "Unknown error"; vscode9.window.showErrorMessage(`Failed to read the file: ${errMessage}`); return; } const saveUri = await vscode9.window.showSaveDialog({ title: "Save as an INP file in another directory", defaultUri: vscode9.Uri.file(os.homedir()), // Updated default save location filters: { "INP Files": ["inp"] }, saveLabel: "Save as .inp" }); if (!saveUri) { return; } try { fs7.writeFileSync(saveUri.fsPath, content, "utf-8"); vscode9.window.showInformationMessage(`File saved as ${saveUri.fsPath}`); vscode9.window.showInformationMessage(`Change all purple text with -> markers`); const document = await vscode9.workspace.openTextDocument(saveUri); await vscode9.window.showTextDocument(document); } catch (error) { const errMessage = error instanceof Error ? error.message : "Unknown error"; vscode9.window.showErrorMessage(`Failed to save the file: ${errMessage}`); } }); } // src/commands/TopasMolToInp.ts var vscode10 = __toESM(require("vscode")); var fs8 = __toESM(require("fs")); var path7 = __toESM(require("path")); var import_child_process = require("child_process"); function TopasMolToInp() { return vscode10.commands.registerCommand("topas-editor.TopasMolToInp", async () => { const uri = await vscode10.window.showOpenDialog({ canSelectMany: false, openLabel: "Select .mol file", filters: { "MOL files": ["mol"] } }); if (!uri || uri.length === 0) { vscode10.window.showInformationMessage("No .mol file selected."); return; } const molPath = uri[0].fsPath; const folder = path7.dirname(molPath); const baseName = path7.basename(molPath, ".mol"); const inpPath = path7.join(folder, `${baseName}.inp`); const extensionPath = vscode10.extensions.getExtension("johnsoevans.topas-editor")?.extensionPath; if (!extensionPath) { vscode10.window.showErrorMessage("Cannot locate extension path."); return; } const scriptPath = path7.join(extensionPath, "scripts", "mol_to_topas.py"); (0, import_child_process.exec)(`python "${scriptPath}" "${molPath}"`, (error, stdout, stderr) => { if (error) { vscode10.window.showErrorMessage(`Error running Python script: ${error.message}`); return; } fs8.access(inpPath, fs8.constants.F_OK, async (err) => { if (err) { vscode10.window.showWarningMessage("INP file was not created."); return; } const inpDoc = await vscode10.workspace.openTextDocument(inpPath); await vscode10.window.showTextDocument(inpDoc, { preview: false }); vscode10.window.showInformationMessage("INP file created, now edit any purple text following an arrow ->"); }); }); }); } // src/commands/TopasOpenExamples.ts var vscode11 = __toESM(require("vscode")); var fs9 = __toESM(require("fs")); var path8 = __toESM(require("path")); function TopasOpenExamples() { return vscode11.commands.registerCommand("topas-editor.TopasOpenExamples", async (examplesDir) => { if (typeof examplesDir === "object" && examplesDir !== null && "text" in examplesDir) { examplesDir = examplesDir.text; } if (!examplesDir) { examplesDir = ""; } const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode11.window.showErrorMessage("TOPAS_DIR environment variable is not set."); return; } const dirPath = path8.join(topasDir, examplesDir); vscode11.window.showInformationMessage(`Select one of the .inp files in ${dirPath}`); if (!fs9.existsSync(dirPath)) { vscode11.window.showErrorMessage(`Directory ${dirPath} does not exist.`); return; } function findInpFiles(dir, recursive) { let inpFiles2 = []; const files = fs9.readdirSync(dir); for (const file of files) { const filePath = path8.join(dir, file); const stats = fs9.statSync(filePath); if (stats.isDirectory() && recursive) { inpFiles2 = inpFiles2.concat(findInpFiles(filePath, true)); } else if (file.endsWith(".inp") && stats.isFile()) { inpFiles2.push(filePath); } } return inpFiles2; } const isRecursive = !(examplesDir === "test_examples" || examplesDir === "pdf_generate2"); const inpFiles = findInpFiles(dirPath, isRecursive); if (inpFiles.length === 0) { vscode11.window.showInformationMessage("No .inp files found in the specified directory."); return; } const selectedFile = await vscode11.window.showQuickPick( inpFiles.map((file) => ({ label: path8.basename(file), description: file })), { placeHolder: "Select an .inp file to open", matchOnDescription: true } ); if (!selectedFile) { return; } const document = await vscode11.workspace.openTextDocument(selectedFile.description); await vscode11.window.showTextDocument(document); vscode11.window.showInformationMessage("Now send the INP file to TOPAS to refine. Remember that this may overwrite the original INP file"); }); } // src/commands/TopasCreateInpFile.ts var vscode12 = __toESM(require("vscode")); var fs10 = __toESM(require("fs")); var path9 = __toESM(require("path")); function TopasCreateInpFile() { return vscode12.commands.registerCommand("topas-editor.TopasCreateInpFile", async () => { vscode12.window.showInformationMessage(`Navigate to find a data file (e.g. raw, .xy, .xye, etc)`); let selectedFileUri = await vscode12.window.showOpenDialog({ canSelectMany: false, openLabel: "Select a TOPAS-compatible datafile", filters: { "Data Files": ["raw", "xy", "xye", "xdd", "rd", "ye", "brml", "dat"], "All Files": ["*"] } }); if (!selectedFileUri || selectedFileUri.length === 0) { vscode12.window.showErrorMessage("No file was selected!"); return; } const filePath = selectedFileUri[0].fsPath; const fileDir = path9.dirname(filePath); const baseFileName = path9.basename(filePath, path9.extname(filePath)); const dataFileName = path9.basename(filePath); const preText = `'Input file for Simple Rietveld or Pawley refinement r_wp 0 r_exp 0 r_p 0 weighted_Durbin_Watson 0 gof 0 iters 1000 chi2_convergence_criteria 0.001 `; const postText = ` x_calculation_step = Yobs_dx_at(Xo); convolution_step 4 bkg @ 0 0 0 0 0 0 Simple_Axial_Model(axial, 9)`; let fullNewFilePath = path9.join(fileDir, `${baseFileName}_fit_01.inp`); if (fs10.existsSync(fullNewFilePath)) { let overwrite = await vscode12.window.showWarningMessage( `File ${fullNewFilePath} already exists! Do you want to overwrite?`, { modal: true }, "Yes", "No" ); if (overwrite !== "Yes") { const saveUri = await vscode12.window.showSaveDialog({ defaultUri: vscode12.Uri.file(fullNewFilePath), saveLabel: "Save As", title: "INP file already exists, please choose another name", filters: { "Topas Input Files": ["inp"], "All Files": ["*"] } }); if (!saveUri) { vscode12.window.showInformationMessage("No new file created."); return; } fullNewFilePath = saveUri.fsPath; } } const fileContent = `${preText} xdd ${dataFileName} ${postText}`; fs10.writeFileSync(fullNewFilePath, fileContent, { flag: "w" }); const document = await vscode12.workspace.openTextDocument(fullNewFilePath); const editor = await vscode12.window.showTextDocument(document); const endPosition = document.lineAt(document.lineCount - 1).range.end; editor.selection = new vscode12.Selection(endPosition, endPosition); editor.revealRange(new vscode12.Range(endPosition, endPosition)); vscode12.window.showInformationMessage(`File ${fullNewFilePath} created successfully`); vscode12.window.showInformationMessage(`Next select one instrument from the Instrument folder and apply optional corrections from Corrections folder`); vscode12.window.showInformationMessage(`Then choose one option from the Rietveld or Pawley folder and finally add any structure-related commands from the Miscellaneous folder`); }); } // src/commands/TopasOxfordCreateInpFile.ts var vscode12 = __toESM(require("vscode")); var fs10 = __toESM(require("fs")); var path9 = __toESM(require("path")); function TopasOxfordCreateInpFile() { return vscode12.commands.registerCommand("topas-editor.TopasOxfordCreateInpFile", async () => { vscode12.window.showInformationMessage(`Navigate to find a data file (e.g. raw, .xy, .xye, etc)`); let selectedFileUri = await vscode12.window.showOpenDialog({ canSelectMany: false, openLabel: "Select a TOPAS-compatible datafile", filters: { "Data Files": ["raw", "xy", "xye", "xdd", "rd", "ye", "brml", "dat"], "All Files": ["*"] } }); if (!selectedFileUri || selectedFileUri.length === 0) { vscode12.window.showErrorMessage("No file was selected!"); return; } const filePath = selectedFileUri[0].fsPath; const fileDir = path9.dirname(filePath); const baseFileName = path9.basename(filePath, path9.extname(filePath)); const dataFileName = path9.basename(filePath); const preText = `'Input file for Simple Rietveld or Pawley refinement r_wp 0 gof 0 r_exp 0 r_p 0 weighted_Durbin_Watson 0 iters 1000 chi2_convergence_criteria 0.001 'do_errors `; const postText = ` x_calculation_step = Yobs_dx_at(Xo); convolution_step 4 bkg @ 0 0 0 0 0 0 `; let fullNewFilePath = path9.join(fileDir, `${baseFileName}_fit_01.inp`); if (fs10.existsSync(fullNewFilePath)) { let overwrite = await vscode12.window.showWarningMessage( `File ${fullNewFilePath} already exists! Do you want to overwrite?`, { modal: true }, "Yes", "No" ); if (overwrite !== "Yes") { const saveUri = await vscode12.window.showSaveDialog({ defaultUri: vscode12.Uri.file(fullNewFilePath), saveLabel: "Save As", title: "INP file already exists, please choose another name", filters: { "Topas Input Files": ["inp"], "All Files": ["*"] } }); if (!saveUri) { vscode12.window.showInformationMessage("No new file created."); return; } fullNewFilePath = saveUri.fsPath; } } const fileContent = `${preText} xdd ${dataFileName} ${postText}`; fs10.writeFileSync(fullNewFilePath, fileContent, { flag: "w" }); const document = await vscode12.workspace.openTextDocument(fullNewFilePath); const editor = await vscode12.window.showTextDocument(document); const endPosition = document.lineAt(document.lineCount - 1).range.end; editor.selection = new vscode12.Selection(endPosition, endPosition); editor.revealRange(new vscode12.Range(endPosition, endPosition)); vscode12.window.showInformationMessage(`File ${fullNewFilePath} created successfully`); vscode12.window.showInformationMessage(`Next select one instrument from the Instrument folder and apply optional corrections from Corrections folder`); vscode12.window.showInformationMessage(`Then choose one option from the Rietveld or Pawley folder and finally add any structure-related commands from the Miscellaneous folder`); }); } // src/commands/TopasImportCIF.ts var vscode13 = __toESM(require("vscode")); var childProcess = __toESM(require("child_process")); var fs11 = __toESM(require("fs")); var path10 = __toESM(require("path")); function TopasImportCIF() { return vscode13.commands.registerCommand("topas-editor.TopasImportCIF", async (caseFlag) => { if (typeof caseFlag === "object" && caseFlag !== null && "text" in caseFlag) { caseFlag = caseFlag.text; } if (!caseFlag) { caseFlag = "none"; } vscode13.window.showInformationMessage(`Importing CIF - select the file`); const fileUri = await vscode13.window.showOpenDialog({ canSelectMany: false, filters: { "CIF Files": ["cif", "CIF"], "All Files": ["*"] } }); if (!fileUri || fileUri.length === 0) { return; } const selectedFile = fileUri[0].fsPath; const shortName = path10.basename(selectedFile, path10.extname(selectedFile)); const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode13.window.showErrorMessage("TOPAS_DIR environment variable not set."); return; } const programPath = path10.join(topasDir, "cif1.exe"); const outputFilePath = path10.join(path10.dirname(selectedFile), "temp2.str"); const command = `"${programPath}" "${selectedFile}" "${outputFilePath}"`; const editor = vscode13.window.activeTextEditor; if (!editor) { vscode13.window.showErrorMessage("No active editor."); return; } childProcess.exec(command, (error, stdout, stderr) => { if (error) { vscode13.window.showErrorMessage(`Error running ${programPath}: ${stderr}`); return; } fs11.readFile(outputFilePath, "utf8", (err, data) => { if (err) { vscode13.window.showErrorMessage(`Error reading temp.str: ${err}`); return; } const documentText = editor.document.getText(); const existingPhases = (documentText.match(/'Structural information from/g) || []).length; const newPhaseNumber = existingPhases + 1; const forStrsRegex = /\n*\s*for strs\s*\{[\s\S]*?\}/m; const existingForStrsMatch = documentText.match(forStrsRegex); const forStrsBlock = existingForStrsMatch ? existingForStrsMatch[0] : ` for strs { TCHZ_Peak_Type(pku, 0.00039,pkv, -0.00221,pkw, -0.00146,!pkz, 0.0000,pkx, 0.00957, pky, 0.0001) }`; const finalOutLine = ` 'Out_pdCIF(pdCIFplotter.cif, "proc") `; const outPdCIFRegex = /^.*'Out_pdCIF\(([^)]*)\).*$/gm; let textToInsert1 = ` 'Structural information from ${selectedFile} `; let textToInsert2 = ""; if (caseFlag === "rietveld") { textToInsert2 = ` scale @ 0.0001 r_bragg 0 Phase_Density_g_on_cm3(0) phase_name ${shortName} local CIF_PHASE_ID ${newPhaseNumber} 'Refine sample size/strain contributions here IF TCHZ fixed to Instrumental Resolution Function 'LVol_FWHM_CS_G_L(1, 100, 0.89, 100, csgc${newPhaseNumber}, 100, cslc${newPhaseNumber}, 100) 'e0_from_Strain( 0.001, sgc${newPhaseNumber}, 0.001, slc${newPhaseNumber}, 0.001) `; } else if (caseFlag === "pdf") { textToInsert2 = ` scale @ 1 'fix if data normalised in Gudrun pdf_zero !zero -0.00 `; } const fullInsertBlock = textToInsert1 + data + textToInsert2 + (caseFlag === "rietveld" ? forStrsBlock + finalOutLine : ""); editor.edit((editBuilder) => { if (existingForStrsMatch?.index !== void 0) { const start = editor.document.positionAt(existingForStrsMatch.index); const end = editor.document.positionAt(existingForStrsMatch.index + existingForStrsMatch[0].length); editBuilder.delete(new vscode13.Range(start, end)); } let match; while ((match = outPdCIFRegex.exec(documentText)) !== null) { const start = editor.document.positionAt(match.index); const end = editor.document.positionAt(match.index + match[0].length); editBuilder.delete(new vscode13.Range(start, end)); } }).then((cleanSuccess) => { if (!cleanSuccess) { vscode13.window.showErrorMessage("Failed to clean old blocks."); return; } const selection = editor.selection.active; const insertLine = selection.character === 0 ? selection.line : selection.line + 1; const insertPos = new vscode13.Position(insertLine, 0); editor.edit((editBuilder) => { editBuilder.insert(insertPos, fullInsertBlock); }).then((success) => { if (success) { const newOffset = editor.document.offsetAt(insertPos) + fullInsertBlock.length; const endPosition = editor.document.positionAt(newOffset); const lineAfterInsert = endPosition.line; const newPosition = new vscode13.Position(lineAfterInsert, 0); editor.selection = new vscode13.Selection(newPosition, newPosition); editor.revealRange(new vscode13.Range(newPosition, newPosition)); vscode13.commands.executeCommand("workbench.action.focusActiveEditorGroup"); vscode13.window.showInformationMessage(`CIF inserted for phase ${newPhaseNumber} (${shortName})`); } else { vscode13.window.showErrorMessage("Failed to insert CIF."); } }); }); }); }); }); } // src/commands/TopasOxfordImportCIF.ts var vscode13 = __toESM(require("vscode")); var childProcess = __toESM(require("child_process")); var fs11 = __toESM(require("fs")); var path10 = __toESM(require("path")); function TopasOxfordImportCIF() { return vscode13.commands.registerCommand("topas-editor.TopasOxfordImportCIF", async (caseFlag) => { if (typeof caseFlag === "object" && caseFlag !== null && "text" in caseFlag) { caseFlag = caseFlag.text; } if (!caseFlag) { caseFlag = "none"; } vscode13.window.showInformationMessage(`Importing CIF - select the file`); const fileUri = await vscode13.window.showOpenDialog({ canSelectMany: false, filters: { "CIF Files": ["cif", "CIF"], "All Files": ["*"] } }); if (!fileUri || fileUri.length === 0) { return; } const selectedFile = fileUri[0].fsPath; const shortName = path10.basename(selectedFile, path10.extname(selectedFile)); const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode13.window.showErrorMessage("TOPAS_DIR environment variable not set."); return; } const programPath = path10.join(topasDir, "cif1.exe"); const outputFilePath = path10.join(path10.dirname(selectedFile), "temp2.str"); const command = `"${programPath}" "${selectedFile}" "${outputFilePath}"`; const editor = vscode13.window.activeTextEditor; if (!editor) { vscode13.window.showErrorMessage("No active editor."); return; } childProcess.exec(command, (error, stdout, stderr) => { if (error) { vscode13.window.showErrorMessage(`Error running ${programPath}: ${stderr}`); return; } fs11.readFile(outputFilePath, "utf8", (err, data) => { if (err) { vscode13.window.showErrorMessage(`Error reading temp.str: ${err}`); return; } const documentText = editor.document.getText(); const existingPhases = (documentText.match(/'Structural information from/g) || []).length; const newPhaseNumber = existingPhases + 1; const forStrsRegex = /\n*\s*for strs\s*\{[\s\S]*?\}/m; const existingForStrsMatch = documentText.match(forStrsRegex); const forStrsBlock = existingForStrsMatch ? existingForStrsMatch[0] : ` TCHZ_Peak_Type(pku, 0.00039,pkv, -0.00221,pkw, -0.00146,!pkz, 0.0000,pkx, 0.00957, pky, 0.0001) `; const finalOutLine = ` 'Out_pdCIF(pdCIFplotter.cif, "proc") `; const outPdCIFRegex = /^.*'Out_pdCIF\(([^)]*)\).*$/gm; let textToInsert1 = ` 'Structural information from ${selectedFile} `; let textToInsert2 = ""; if (caseFlag === "rietveld") { textToInsert2 = ` scale @ 0.0001 r_bragg 0 Phase_Density_g_on_cm3(0) phase_name ${shortName} `; } else if (caseFlag === "pdf") { textToInsert2 = ` scale @ 1 'fix if data normalised in Gudrun pdf_zero !zero -0.00 `; } const fullInsertBlock = textToInsert1 + data + textToInsert2 + (caseFlag === "rietveld" ? forStrsBlock + finalOutLine : ""); editor.edit((editBuilder) => { if (existingForStrsMatch?.index !== void 0) { const start = editor.document.positionAt(existingForStrsMatch.index); const end = editor.document.positionAt(existingForStrsMatch.index + existingForStrsMatch[0].length); editBuilder.delete(new vscode13.Range(start, end)); } let match; while ((match = outPdCIFRegex.exec(documentText)) !== null) { const start = editor.document.positionAt(match.index); const end = editor.document.positionAt(match.index + match[0].length); editBuilder.delete(new vscode13.Range(start, end)); } }).then((cleanSuccess) => { if (!cleanSuccess) { vscode13.window.showErrorMessage("Failed to clean old blocks."); return; } const selection = editor.selection.active; const insertLine = selection.character === 0 ? selection.line : selection.line + 1; const insertPos = new vscode13.Position(insertLine, 0); editor.edit((editBuilder) => { editBuilder.insert(insertPos, fullInsertBlock); }).then((success) => { if (success) { const newOffset = editor.document.offsetAt(insertPos) + fullInsertBlock.length; const endPosition = editor.document.positionAt(newOffset); const lineAfterInsert = endPosition.line; const newPosition = new vscode13.Position(lineAfterInsert, 0); editor.selection = new vscode13.Selection(newPosition, newPosition); editor.revealRange(new vscode13.Range(newPosition, newPosition)); vscode13.commands.executeCommand("workbench.action.focusActiveEditorGroup"); vscode13.window.showInformationMessage(`CIF inserted for phase ${newPhaseNumber} (${shortName})`); } else { vscode13.window.showErrorMessage("Failed to insert CIF."); } }); }); }); }); }); } // src/commands/TopasOxfordAddExpBackground.ts var vscode = __toESM(require("vscode")); var path = __toESM(require("path")); function TopasOxfordAddExpBackground() { return vscode.commands.registerCommand("topas-editor.TopasOxfordAddExpBackground", async () => { const fileUri = await vscode.window.showOpenDialog({ canSelectMany: false, filters: { "Data & text files": ["xye","xy","dat","txt"], "All Files": ["*"] } }); if (!fileUri || fileUri.length === 0) { return; } const selectedFile = fileUri[0].fsPath; const chosenName = path.basename(selectedFile); const editor = vscode.window.activeTextEditor; if (!editor) { vscode.window.showErrorMessage("No active editor."); return; } const insertBlock = "\r\n\tuser_y measured_exp_bkg \"" + chosenName + "\"\r\n" + "\tprm exp_bkg_scale 1 min 0 'scales the background file\r\n" + "\tfit_obj = exp_bkg_scale * measured_exp_bkg;\r\n" + "\tPlot_Fit_Obj(measured_exp_bkg) ' show on screen\r\n\r\n"; const selection = editor.selection.active; const insertLine = selection.character === 0 ? selection.line : selection.line + 1; const insertPos = new vscode.Position(insertLine, 0); editor.edit((editBuilder) => { editBuilder.insert(insertPos, insertBlock); }).then((success) => { if (success) { const newOffset = editor.document.offsetAt(insertPos) + insertBlock.length; const endPosition = editor.document.positionAt(newOffset); const newPosition = new vscode.Position(endPosition.line, 0); editor.selection = new vscode.Selection(newPosition, newPosition); editor.revealRange(new vscode.Range(newPosition, newPosition)); vscode.commands.executeCommand("workbench.action.focusActiveEditorGroup"); vscode.window.showInformationMessage(`Inserted back_expt for ${chosenName}`); } else { vscode.window.showErrorMessage("Failed to insert back_expt block."); } }); }); } // src/commands/TopasSetDirectory.ts var vscode14 = __toESM(require("vscode")); function TopasSetDirectory() { return vscode14.commands.registerCommand("topas-editor.TopasSetDirectory", async () => { const selectedUri = await vscode14.window.showOpenDialog({ canSelectFolders: true, canSelectFiles: false, canSelectMany: false, openLabel: "Select as TOPAS directory", title: "Navigate then select TOPAS directory" }); if (selectedUri && selectedUri[0]) { const selectedDir = selectedUri[0].fsPath; process.env.TOPAS_DIR = selectedDir; const config = vscode14.workspace.getConfiguration(); await config.update("topas.directory", selectedDir, vscode14.ConfigurationTarget.Global); vscode14.window.showInformationMessage(`TOPAS_DIR has been set to ${selectedDir} and saved to settings.json.`); } else { vscode14.window.showWarningMessage("No directory selected. TOPAS_DIR was not set."); } }); } // src/commands/TopasSimulateFromCIF.ts var vscode15 = __toESM(require("vscode")); var childProcess2 = __toESM(require("child_process")); var fs12 = __toESM(require("fs")); var path11 = __toESM(require("path")); function TopasSimulateFromCIF() { return vscode15.commands.registerCommand("topas-editor.TopasSimulateFromCIF", async () => { const fileUri = await vscode15.window.showOpenDialog({ canSelectMany: false, filters: { "CIF Files": ["cif", "CIF"], "All Files": ["*"] } }); if (!fileUri || fileUri.length === 0) { return; } const selectedFile = fileUri[0].fsPath; const defaultFileName = path11.basename(selectedFile, path11.extname(selectedFile)) + "_sim_01.inp"; const defaultFilePath = path11.join(path11.dirname(selectedFile), defaultFileName); const saveUri = await vscode15.window.showSaveDialog({ title: "Save INP File", defaultUri: vscode15.Uri.file(defaultFilePath), saveLabel: "Save INP File" }); if (!saveUri) { return; } const newFileName = saveUri.fsPath; const topasDir = process.env.TOPAS_DIR; if (!topasDir) { vscode15.window.showErrorMessage("TOPAS_DIR environment variable not set correctly."); return; } const programPath = path11.join(topasDir, "cif1.exe"); const outputFilePath = path11.join(path11.dirname(selectedFile), "temp.str"); const command = `"${programPath}" "${selectedFile}" "${outputFilePath}"`; childProcess2.exec(command, (error, stdout, stderr) => { if (error) { vscode15.window.showErrorMessage(`Error: ${stderr}`); return; } fs12.readFile(outputFilePath, "utf8", (err, data) => { if (err) { vscode15.window.showErrorMessage(`Error reading output file: ${err}`); return; } const preText = `'Calculated pattern assuming Cu Ka2; change as needed iters 0 yobs_eqn !dummy.xy=1; min 0 max 150 del 0.01 xdd_out ${selectedFile}_sim_01.xy load out_record out_fmt out_eqn { " %11.5f " = X; " %11.5f\\n" = Ycalc; } LP_Factor(!th2_monochromator,0) CuKa2(0.0001) bkg 100 'Structural information from ${selectedFile} `; const postText = ` scale @ 0.0001 r_bragg 0 Phase_Density_g_on_cm3(0) for strs { TCHZ_Peak_Type(pku, 0.00039,pkv, -0.00221,pkw, -0.00146,!pkz, 0.0000,pkx, 0.00957, pky, 0.0001) }`; const finalContent = preText + data + postText; fs12.writeFile(newFileName, finalContent, "utf8", (writeErr) => { if (writeErr) { vscode15.window.showErrorMessage(`Error writing to file: ${writeErr}`); return; } vscode15.window.showTextDocument(vscode15.Uri.file(newFileName)); vscode15.window.showInformationMessage("INP file for simulating Cu Ka2 pattern created."); }); }); }); }); } // src/commands/TopasMenuSetup.ts var vscode16 = __toESM(require("vscode")); var fs13 = __toESM(require("fs")); var path12 = __toESM(require("path")); function TopasMenuSetup() { return vscode16.commands.registerCommand("topas-editor.TopasMenuSetup", async () => { try { const userSettingsDirectory = path12.join(process.env.APPDATA || "", "Code", "User"); const userSettingsPath = path12.join(userSettingsDirectory, "settings.json"); const backupSettingsPath = path12.join(userSettingsDirectory, "settings_old.json"); const topasEditorExtension = vscode16.extensions.getExtension("johnsoevans.topas-editor"); if (!topasEditorExtension) { vscode16.window.showWarningMessage("johnsoevans.topas-editor extension not found. Please ensure it is installed and enabled."); return; } const topasEditorPath = topasEditorExtension.extensionPath; const commandsSettingsSource = path12.join(topasEditorPath, "assets", "topas-editor_settings.json"); if (!fs13.existsSync(userSettingsDirectory)) { vscode16.window.showWarningMessage("User settings directory not found. Please check your setup. You will have to set up the TOPAS menus by hand."); return; } const userResponse = await vscode16.window.showWarningMessage( `This will merge the settings from topas-extension\\assets\\topas-editor_settings.json with ${userSettingsDirectory}\\settings.json. You should not lose settings of other extensions. A backup settings_old.json will be made. Do you want to proceed?`, { modal: true }, "Yes" ); if (userResponse !== "Yes") { return; } if (fs13.existsSync(userSettingsPath)) { fs13.copyFileSync(userSettingsPath, backupSettingsPath); } let existingSettings = {}; if (fs13.existsSync(userSettingsPath)) { const userSettingsContent = fs13.readFileSync(userSettingsPath, "utf-8"); existingSettings = userSettingsContent ? JSON.parse(userSettingsContent) : {}; } let newSettings = {}; if (fs13.existsSync(commandsSettingsSource)) { const commandsSettingsContent = fs13.readFileSync(commandsSettingsSource, "utf-8"); newSettings = commandsSettingsContent ? JSON.parse(commandsSettingsContent) : {}; } else { vscode16.window.showWarningMessage("topas-editor_settings.json not found in the topas-editor assets folder. You will have to set up TOPAS menus by hand."); return; } const mergedSettings = { ...existingSettings, ...newSettings }; fs13.writeFileSync(userSettingsPath, JSON.stringify(mergedSettings, null, 4), "utf-8"); vscode16.window.showInformationMessage(`TOPAS menus updated successfully. Backup created at: ${backupSettingsPath}`); const topasDir = process.env.TOPAS_DIR; if (topasDir && fs13.existsSync(topasDir)) { vscode16.window.showInformationMessage(`TOPAS directory is ${topasDir}, change this from the setup menu`); return; } else { const confirmResponse = await vscode16.window.showInformationMessage( "No valid TOPAS directory found\nNavigate to select it\nCancel to set it manually in settings", { modal: true }, "OK" ); if (confirmResponse === "OK") { await vscode16.commands.executeCommand("topas-editor.TopasSetDirectory"); } } } catch (error) { const errorMessage = error.message; vscode16.window.showErrorMessage("An error occurred; you will have to set up TOPAS menus by hand. Error: " + errorMessage); } }); } // src/commands/TopasFold.ts var vscode17 = __toESM(require("vscode")); function TopasFold() { const foldingProvider = { provideFoldingRanges(document, context, token) { const ranges = []; const curlyStack = []; const commentStack = []; const directiveStack = []; let pendingMacroStart = null; const braceStack = []; for (let i = 0; i < document.lineCount; i++) { const line = document.lineAt(i).text.trim(); if (line.includes(`'{{{`)) { curlyStack.push(i); } else if (line.includes(`'}}}`)) { if (curlyStack.length > 0) { const start = curlyStack.pop(); ranges.push(new vscode17.FoldingRange(start, i)); } } if (line.includes("/*")) { commentStack.push(i); } else if (line.includes("*/")) { if (commentStack.length > 0) { const start = commentStack.pop(); ranges.push(new vscode17.FoldingRange(start, i)); } } if (/macro\b/i.test(line)) { pendingMacroStart = i; } if (line.includes("{")) { const isMacro = pendingMacroStart !== null; braceStack.push({ line: isMacro ? pendingMacroStart : i, isMacro }); pendingMacroStart = null; } if (line.includes("}")) { if (braceStack.length > 0) { const { line: start, isMacro } = braceStack.pop(); if (isMacro) { ranges.push(new vscode17.FoldingRange(start, i)); } } } if (line.startsWith("#ifdef") || line.startsWith("#ifndef") || line.startsWith("#if")) { directiveStack.push(i); } else if (line.startsWith("#endif") || line.startsWith("#endif")) { if (directiveStack.length > 0) { const start = directiveStack.pop(); ranges.push(new vscode17.FoldingRange(start, i)); } } } return ranges; } }; vscode17.languages.registerFoldingRangeProvider( { scheme: "file", language: "*" }, // Applies to all file types foldingProvider ); } // src/commands/TopasResetVersion.ts var vscode18 = __toESM(require("vscode")); function TopasResetVersion(context) { return vscode18.commands.registerCommand("topas-editor.TopasResetVersion", async () => { context.globalState.update("storedTopasEditorVersion", "0.0.0"); console.log("Topas version reset in globalState to 0.0.0"); }); } // src/commands/TopasMessage.ts var vscode19 = __toESM(require("vscode")); function TopasMessage() { return vscode19.commands.registerCommand("topas-editor.TopasMessage", async () => { vscode19.window.showErrorMessage("Hello I am topas-editor."); }); } // src/commands/TopasReadHoverHelp.ts var vscode20 = __toESM(require("vscode")); var path13 = __toESM(require("path")); function TopasReadHoverHelp() { return vscode20.commands.registerCommand("topas-editor.TopasReadHoverHelp", async () => { const extension = vscode20.extensions.getExtension("johnsoevans.topas-editor"); if (!extension) { vscode20.window.showErrorMessage("Extension johnsoevans.topase-ditor not found."); return; } const helpFilePath = path13.join(extension.extensionPath, "assets", "hovertext_help.md"); const helpFileUri = vscode20.Uri.file(helpFilePath); await vscode20.commands.executeCommand("markdown.showPreview", helpFileUri); }); } // src/commands/TopasRefineAtoms.ts var vscode21 = __toESM(require("vscode")); function TopasRefineAtoms() { return vscode21.commands.registerCommand("topas-editor.TopasRefineAtoms", async () => { const editor = vscode21.window.activeTextEditor; if (!editor) { vscode21.window.showErrorMessage("No active editor."); return; } const selection = editor.selection; const selectedText = editor.document.getText(selection); const lines = selectedText.split("\n"); const siteLine = lines.find((line) => /^\s*site\b/i.test(line)); const indentMatch = siteLine?.match(/^(\s*)/) || [""]; const indent = indentMatch[1] ?? ""; const macroHeader = [ `${indent}'macros (name, value, reference) to refine xyz coords with +/- max_shift A min/max`, `${indent}prm !max_shift 0.6 'Angstroms along each axis`, `${indent}macro Nvrx(name, value, ref) {x name value min = ref-max_shift/Get(a); max = ref+max_shift/Get(a);}`, `${indent}macro Nvry(name, value, ref) {y name value min = ref-max_shift/Get(b); max = ref+max_shift/Get(b);}`, `${indent}macro Nvrz(name, value, ref) {z name value min = ref-max_shift/Get(c); max = ref+max_shift/Get(c);}` ]; const coordRegex = (label) => new RegExp(`\\b${label}\\s+(?:\\S+\\s+)*?((=.+?;)(?=\\s*:?|$)|(-?\\d*\\.?\\d+))`, "i"); const processedLines = lines.map((line) => { const lineIndent = line.match(/^(\s*)/)?.[1] ?? indent; if (/^\s*site\b/i.test(line)) { const nameMatch = line.match(/site\s+(\S+)/i); const xMatch = line.match(coordRegex("x")); const yMatch = line.match(coordRegex("y")); const zMatch = line.match(coordRegex("z")); const occMatch = line.match(/\bocc\s+(\S+)\s+(.*?)\s+beq/i); if (nameMatch && xMatch && yMatch && zMatch && occMatch) { const name = nameMatch[1]; let xval = xMatch[1]; let yval = yMatch[1]; let zval = zMatch[1]; const occType = occMatch[1]; const occupancy = occMatch[2]; const element = occType.replace(/[\d\+\-]/g, ""); const fixSymbolic = (label, val) => { if (val.startsWith("=")) { const needsZero = /;\s*:/i.test(line); return `${label} ${val}${needsZero && !val.includes(":") ? ":0" : ""}`; } return `Nvr${label}( ${label}${name}, ${val}, ${val})`; }; const xStr = fixSymbolic("x", xval); const yStr = fixSymbolic("y", yval); const zStr = fixSymbolic("z", zval); return `${lineIndent}site ${name} num_posns 0 ${xStr} ${yStr} ${zStr} occ ${occType} ${occupancy} beq beq${element} 0.5`; } } return line; }); const newText = [...macroHeader, ...processedLines].join("\n"); editor.edit((editBuilder) => { editBuilder.replace(selection, newText); }); vscode21.window.showInformationMessage("Atoms set to refine via Nvr macro. Fix parameters for atoms on special positions."); }); } // src/commands/TopasToAdp_5.ts var vscode22 = __toESM(require("vscode")); function TopasToAdp_5() { return vscode22.commands.registerCommand("topas-editor.TopasToAdp_5", async () => { const editor = vscode22.window.activeTextEditor; if (!editor) { vscode22.window.showErrorMessage("No active editor."); return; } const selection = editor.selection; const selectedText = editor.document.getText(selection); const lines = selectedText.split("\n"); const siteLine = lines.find((line) => /^\s*site\b/i.test(line)); const indentMatch = siteLine?.match(/^(\s*)/) || [""]; const indent = indentMatch[1] ?? ""; const macroHeader = [ `${indent}'macros to restrict and randomize ADP_5 coordinates`, `${indent}'*Warning: you will need to fix coordinate parameter names to obey site symmetry`, `${indent}'*Warning: any Get(x) equations will be interpreted incorrectly`, `${indent}#include ROOT##PDF-adps.inc 'delete this line if PDF-adps.incalready included`, `${indent}macro R_ { min -0.05 max 0.05 val_on_continue = Rand(-1, 1) 0.01; }` ]; const coordRegex = (label) => new RegExp(`\\b${label}\\s+(?:\\S+\\s+)*?((=.+?;)(?=\\s*:?|$)|(-?\\d*\\.?\\d+))`, "i"); const processedLines = lines.map((line) => { const lineIndent = line.match(/^(\s*)/)?.[1] ?? indent; if (/^\s*site\b/i.test(line)) { const nameMatch = line.match(/site\s+(\S+)/i); const xMatch = line.match(coordRegex("x")); const yMatch = line.match(coordRegex("y")); const zMatch = line.match(coordRegex("z")); const occMatch = line.match(/\bocc\s+(\S+)\s+(.*?)\s+beq/i); if (nameMatch && xMatch && yMatch && zMatch && occMatch) { const name = nameMatch[1]; let xval = xMatch[1]; let yval = yMatch[1]; let zval = zMatch[1]; const occType = occMatch[1]; const occupancy = occMatch[2]; const element = occType.replace(/[\d\+\-]/g, ""); const fixSymbolic = (label, val) => { if (val.startsWith("=")) { const needsZero = /;\s*:/i.test(line); return `${label} ${val}${needsZero && !val.includes(":") ? ":0" : ""}`; } return `Nvr${label}( ${label}${name}, ${val}, ${val})`; }; const xStr = fixSymbolic("x", xval); const yStr = fixSymbolic("y", yval); const zStr = fixSymbolic("z", zval); return `${lineIndent}ADP_5( ${name}, x${name}, ${xval}, y${name}, ${yval}, z${name}, ${zval}, ${occType}, !occ${occType}, ${occupancy}, x1${name}, 0.0 R_, y1${name}, 0.0 R_, z1${name}, 0.0 R_, x2${name}, 0.0 R_, y2${name}, 0.0 R_, z2${name}, 0.0 R_, bo${name}, 0.1)`; } } return line; }); const newText = [...macroHeader, ...processedLines].join("\n"); editor.edit((editBuilder) => { editBuilder.replace(selection, newText); }); vscode22.window.showInformationMessage("Atoms set to refine via Nvr macro. Fix parameters for atoms on special positions."); }); } // src/commands/TopasRemoveEsds.ts var vscode23 = __toESM(require("vscode")); function TopasRemoveEsds() { return vscode23.commands.registerCommand("topas-editor.TopasRemoveEsds", async () => { const editor = vscode23.window.activeTextEditor; if (!editor) { vscode23.window.showErrorMessage("No active text editor found."); return; } const document = editor.document; const text = document.getText(); const regex = /`_.*?(?=[\s,\)])/g; const newText = text.replace(regex, ""); const edit = new vscode23.WorkspaceEdit(); const fullRange = new vscode23.Range( document.positionAt(0), document.positionAt(text.length) ); edit.replace(document.uri, fullRange, newText); await vscode23.workspace.applyEdit(edit); vscode23.window.showInformationMessage("TOPAS esd's removed from file"); }); } // src/commands/TopasToggleComment.ts var vscode24 = __toESM(require("vscode")); function TopasToggleComment() { return vscode24.commands.registerCommand("topas-editor.TopasToggleComment", async () => { const editor = vscode24.window.activeTextEditor; if (!editor) { vscode24.window.showInformationMessage("No active editor."); return; } const document = editor.document; const selection = editor.selection; let text = document.getText(selection); if (selection.isEmpty) { editor.edit((editBuilder) => { const position = selection.start; editBuilder.insert(position, "\n/* Add a block comment */\n"); }); return; } let lines = text.split("\n"); while (lines.length > 0 && lines[0].trim() === "") lines.shift(); while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop(); const firstLineTrimmed = lines[0].trimStart(); const lastLineTrimmed = lines[lines.length - 1].trimEnd(); const isCommented = firstLineTrimmed.startsWith("/*") && lastLineTrimmed.endsWith("*/"); editor.edit((editBuilder) => { if (isCommented) { lines[0] = lines[0].replace(/\s*\/\*\s*/, ""); lines[lines.length - 1] = lines[lines.length - 1].replace(/\s*\*\/\s*/, ""); editBuilder.replace(selection, lines.join("\n")); } else { const firstNonEmptyLine = lines.find((line) => line.trim() !== ""); const indentation = firstNonEmptyLine ? firstNonEmptyLine.match(/^\s*/)?.[0] || "" : ""; editBuilder.replace(selection, `${indentation}/* ${text} ${indentation}*/`); } }); }); } // src/commands/TopasOpenOut.ts var vscode25 = __toESM(require("vscode")); var path14 = __toESM(require("path")); var fs14 = __toESM(require("fs")); function TopasOpenOut() { return vscode25.commands.registerCommand("topas-editor.TopasOpenOut", async () => { const editor = vscode25.window.activeTextEditor; if (!editor) { vscode25.window.showErrorMessage("No active editor found."); return; } const currentFilePath = editor.document.fileName; const currentDir = path14.dirname(currentFilePath); const currentFileName = path14.basename(currentFilePath); const fileStem = path14.parse(currentFileName).name; const outFilePath = path14.join(currentDir, `${fileStem}.out`); if (fs14.existsSync(outFilePath)) { vscode25.window.showInformationMessage(`Opening ${fileStem}.out`); const doc = await vscode25.workspace.openTextDocument(outFilePath); await vscode25.window.showTextDocument(doc); } else { vscode25.window.showErrorMessage(`Sorry, ${fileStem}.out wasn't found in this directory.`); } }); } // src/commands/TopasOutputLines.ts var vscode26 = __toESM(require("vscode")); function TopasOutputLines() { return vscode26.commands.registerCommand("topas-editor.TopasOutputLines", async () => { const editor = vscode26.window.activeTextEditor; if (!editor) { vscode26.window.showErrorMessage("No active editor."); return; } const document = editor.document; const text = document.getText(); const matrixMatch = text.match(/C_matrix_normalized\s*\{([\s\S]*?)\}/); if (!matrixMatch) { vscode26.window.showErrorMessage("No correlation matrix found, run file again with do_errors included"); return; } const matrixBody = matrixMatch[1].trim(); const rawLines = matrixBody.split("\n").map((line) => line.trimStart()); const contentLines = rawLines.filter((line) => line.trim() !== ""); const matrixDataLines = contentLines.slice(1); const hexRegex = /[0-9A-Fa-f]{8}/; const firstWords = matrixDataLines.map((line) => line.split(/\s+/)[0]).filter((name) => !hexRegex.test(name)); if (firstWords.length === 0) { vscode26.window.showWarningMessage("No valid names found after filtering."); return; } const outStringBlock = ` #if (Run_Number == 0) system_before_save_OUT { del results.txt } out "results.txt" append 'results file for plotting. outstring is file column headers Out_String("Run_Number filename r_wp gof ${firstWords.map((name) => `${name} esd_${name}`).join(" ")} \\n") #endif 'this is a guess of parameters to output based on Correlation Matrix names #define write_out #ifdef write_out out "results.txt" append Out(Run_Number, " %11.5f ") Out_String(filename) Out(Get(r_wp), " %11.5f") Out(Get(gof), " %11.5f") ${firstWords.map((name) => ` Out(${name}, " %18.9f", " %18.9f")`).join("\n")} Out_String("\\n") #endif `; editor.edit((editBuilder) => { const position = editor.selection.active; editBuilder.insert(position, outStringBlock + "\n"); }); vscode26.window.showInformationMessage("Topas output lines inserted."); }); } // src/commands/TopasOutputHeader.ts var vscode27 = __toESM(require("vscode")); function TopasOutputHeader() { return vscode27.commands.registerCommand("topas-editor.TopasOutputHeader", async () => { const editor = vscode27.window.activeTextEditor; if (!editor) { vscode27.window.showErrorMessage("No active editor found."); return; } const selection = editor.selection; const lines = []; for (let i = selection.start.line; i < editor.document.lineCount; i++) { const line = editor.document.lineAt(i); lines.push(line.text); } const items = []; for (const line of lines) { const trimmed = line.trim(); if (trimmed.startsWith("Out_String(")) { const content = trimmed.match(/Out_String\((.*)\)/); if (!content) { continue; } const parts = splitTopLevel(content[1]); if (parts.length === 0) { continue; } const first = parts[0].trim(); if (!/^".*"$/.test(first)) { const item = first.includes("(") ? first.split("(")[0] : first; items.push(item); } } if (trimmed.startsWith("Out(")) { const content = trimmed.match(/Out\((.*)\)/); if (!content) { continue; } const parts = splitTopLevel(content[1]); if (parts.length === 0) { continue; } let rawName = parts[0].trim(); const getMatch = rawName.match(/^Get\s*\(\s*(.*?)\s*\)$/); if (getMatch) { rawName = getMatch[1]; } const runNumberMatch = rawName.match(/^(\w+)\s*\(\s*Run_Number\s*\)$/); if (runNumberMatch) { rawName = runNumberMatch[1]; } const itemName = rawName.replace(/\s+/g, ""); if (parts.length === 2) { items.push(itemName); } else if (parts.length === 3) { items.push(itemName, `esd_${itemName}`); } } } if (items.length === 0) { vscode27.window.showInformationMessage("No valid Out or Out_String items found."); return; } const headerLine = `Out_String("${items.join(" ")} \\n")`; await editor.edit((editBuilder) => { const insertPosition = new vscode27.Position(selection.start.line, 0); editBuilder.insert(insertPosition, " /* Replace existing header line with this one; check carefully! */\n " + headerLine + "\n"); }); }); } function splitTopLevel(input) { const result = []; let current = ""; let level = 0; let inQuotes = false; for (let i = 0; i < input.length; i++) { const char = input[i]; if (char === '"' && input[i - 1] !== "\\") { inQuotes = !inQuotes; } if (!inQuotes) { if (char === "(") { level++; } if (char === ")") { level--; } } if (char === "," && level === 0 && !inQuotes) { result.push(current.trim()); current = ""; } else { current += char; } } if (current) { result.push(current.trim()); } return result; } // src/commands/TopasRemoveRefinedMarker.ts var vscode28 = __toESM(require("vscode")); function TopasRemoveRefinedMarker() { return vscode28.commands.registerCommand("topas-editor.TopasRemoveRefinedMarker", async () => { const editor = vscode28.window.activeTextEditor; if (!editor) { vscode28.window.showErrorMessage("No active text editor found."); return; } const document = editor.document; const text = document.getText(); const updatedText = text.replace(/`/g, ""); const edit = new vscode28.WorkspaceEdit(); const fullRange = new vscode28.Range( document.positionAt(0), document.positionAt(text.length) ); edit.replace(document.uri, fullRange, updatedText); await vscode28.workspace.applyEdit(edit); vscode28.window.showInformationMessage("Backticks removed from the file."); }); } // src/commands/TopasAddMyMenus.ts var vscode29 = __toESM(require("vscode")); var fs15 = __toESM(require("fs")); var path15 = __toESM(require("path")); function TopasAddMyMenus() { return vscode29.commands.registerCommand("topas-editor.TopasAddMyMenus", async () => { try { const userSettingsDirectory = path15.join(process.env.APPDATA || "", "Code", "User"); const userSettingsPath = path15.join(userSettingsDirectory, "settings.json"); const backupSettingsPath = path15.join(userSettingsDirectory, "settings_old.json"); const userResponse = await vscode29.window.showWarningMessage( `This will add menus from your .json file to ${userSettingsPath}. You should not lose settings of other extensions. A backup settings_old.json will be made. You are responsible for the format of your .json file! Do you want to proceed?`, { modal: true }, "Yes" ); if (userResponse !== "Yes") { return; } const fileUri = await vscode29.window.showOpenDialog({ canSelectFiles: true, canSelectFolders: false, canSelectMany: false, openLabel: "Select your menus.json", filters: { "JSON Files": ["json"] } }); if (!fileUri || fileUri.length === 0) { vscode29.window.showWarningMessage("No file selected. Operation cancelled."); return; } const userMenusSource = fileUri[0].fsPath; if (!fs15.existsSync(userSettingsDirectory)) { vscode29.window.showWarningMessage("User settings directory not found. Please check your setup."); return; } if (fs15.existsSync(userSettingsPath)) { fs15.copyFileSync(userSettingsPath, backupSettingsPath); } let existingSettings = {}; if (fs15.existsSync(userSettingsPath)) { const userSettingsContent = fs15.readFileSync(userSettingsPath, "utf-8"); existingSettings = userSettingsContent ? JSON.parse(userSettingsContent) : {}; } let userMenusSettings = {}; if (fs15.existsSync(userMenusSource)) { const commandsSettingsContent = fs15.readFileSync(userMenusSource, "utf-8"); userMenusSettings = commandsSettingsContent ? JSON.parse(commandsSettingsContent) : {}; } else { vscode29.window.showWarningMessage("Selected user menu file not found. Try again."); return; } if (!existingSettings["commands.commands"]) { existingSettings["commands.commands"] = {}; } if (userMenusSettings["commands.commands"]) { for (const key in userMenusSettings["commands.commands"]) { if (!(key in existingSettings["commands.commands"])) { existingSettings["commands.commands"][key] = userMenusSettings["commands.commands"][key]; } } } fs15.writeFileSync(userSettingsPath, JSON.stringify(existingSettings, null, 4), "utf-8"); vscode29.window.showInformationMessage(`TOPAS user menus added successfully. Backup created at: ${backupSettingsPath}`); } catch (error) { const errorMessage = error.message; vscode29.window.showErrorMessage("An error occurred; you will have to set up TOPAS menus by hand. Error: " + errorMessage); } }); } // src/commands/TopasShowSetup.ts var vscode30 = __toESM(require("vscode")); var fs16 = __toESM(require("fs")); var path16 = __toESM(require("path")); var os2 = __toESM(require("os")); function TopasShowSetup() { return vscode30.commands.registerCommand("topas-editor.TopasShowSetup", async () => { const topasDir = process.env.TOPAS_DIR || "TOPAS_DIR is not set"; const extension = vscode30.extensions.getExtension("johnsoevans.topas-editor"); const extensionPath = extension ? extension.extensionPath : "Extension not found"; const settingsPath = path16.join(os2.homedir(), ".config", "Code", "User", "settings.json"); const altSettingsPath = path16.join(os2.homedir(), "AppData", "Roaming", "Code", "User", "settings.json"); const settingsJsonPath = fs16.existsSync(settingsPath) ? settingsPath : fs16.existsSync(altSettingsPath) ? altSettingsPath : "settings.json not found"; vscode30.window.showInformationMessage( `These are the current topas-editor settings:`, `Topas directory: ${topasDir}`, `Extension Path: ${extensionPath}`, `User settings.json Path: ${settingsJsonPath}` ); }); } // src/commands/TopasHelp.ts var vscode31 = __toESM(require("vscode")); var path17 = __toESM(require("path")); function TopasHelp() { return vscode31.commands.registerCommand("topas-editor.TopasHelp", async () => { const extension = vscode31.extensions.getExtension("johnsoevans.topas-editor"); if (!extension) { vscode31.window.showErrorMessage("Extension johnsoevans.topase-editor not found."); return; } const helpFilePath = path17.join(extension.extensionPath, "assets", "topas-editor_help.md"); const helpFileUri = vscode31.Uri.file(helpFilePath); await vscode31.commands.executeCommand("markdown.showPreview", helpFileUri); }); } // src/commands/TopasHoverHelp.ts var vscode32 = __toESM(require("vscode")); var fs17 = __toESM(require("fs")); var path18 = __toESM(require("path")); var hoverEnabled = vscode32.workspace.getConfiguration("topas-editor").get("hoverHelp.enabled", true); var hoverMap = /* @__PURE__ */ new Map(); function loadHoverHelp(context) { hoverMap.clear(); const filePath = context.asAbsolutePath(path18.join("assets", "hovertext_help.md")); let text = fs17.readFileSync(filePath, "utf8").replace(/\r\n/g, "\n"); const sections = text.split(/^##\s+/m).slice(1); for (const section of sections) { const [headerLine, ...bodyLines] = section.split(/\n/); const rawKey = headerLine.trim(); const content = bodyLines.join("\n").trim(); const keys = rawKey.split("|").map((k) => k.trim()).filter((k) => k.length); for (const key of keys) { hoverMap.set(key, content); } } } function registerHoverProvider(context) { loadHoverHelp(context); const provider = vscode32.languages.registerHoverProvider( { scheme: "file", language: "topas" }, { provideHover(document, position) { if (!hoverEnabled) { return; } const range = document.getWordRangeAtPosition(position, /[#\w]+/); if (!range) { return; } const word = document.getText(range); const mdText = hoverMap.get(word); if (mdText) { const markdownContent = `### ${word} ${mdText}`; const md = new vscode32.MarkdownString(markdownContent); md.isTrusted = true; return new vscode32.Hover(md, range); } } } ); context.subscriptions.push(provider); return provider; } function registerHoverCommands(context) { const toggleCmd = vscode32.commands.registerCommand( "topas-editor.TopasToggleHoverHelp", () => { hoverEnabled = !hoverEnabled; vscode32.workspace.getConfiguration("topas-editor").update( "hoverHelp.enabled", hoverEnabled, vscode32.ConfigurationTarget.Global ); vscode32.window.showInformationMessage( `TOPAS hover help ${hoverEnabled ? "enabled" : "disabled"}` ); } ); const refreshCmd = vscode32.commands.registerCommand( "topas-editor.TopasRefreshHoverHelp", () => { loadHoverHelp(context); vscode32.window.showInformationMessage("Hover help data refreshed"); } ); context.subscriptions.push(toggleCmd, refreshCmd); } // src/commands/TopasDecoration.ts var vscode33 = __toESM(require("vscode")); var activeEditor; var decorationEnabled = vscode33.workspace.getConfiguration("topas-editor").get("decorations.enabled", true); var createDecoration = (borderColor, borderWidth, borderStyle = "solid") => { return vscode33.window.createTextEditorDecorationType({ isWholeLine: true, borderWidth: `0 0 ${borderWidth} 0`, borderStyle, light: { borderColor }, dark: { borderColor } }); }; var strLineDecoration = createDecoration("#009900", "1px", "dashed"); var xddLineDecoration = createDecoration("#009900", "1px", "solid"); var badFractionDecoration = vscode33.window.createTextEditorDecorationType({ textDecoration: "underline wavy red; background-color: rgba(255,0,0,0.05)" }); var allowedSpaceGroups = /* @__PURE__ */ new Set([ "1", "10", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", "11", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "12", "120", "121", "122", "123", "124", "125", "125:2", "126", "126:2", "127", "128", "129", "129:2", "13", "130", "130:2", "131", "132", "133", "133:2", "134", "134:2", "135", "136", "137", "137:2", "138", "138:2", "139", "14", "140", "141", "141:2", "142", "142:2", "143", "144", "145", "146", "146r", "147", "148", "148r", "149", "15", "150", "151", "152", "153", "154", "155", "155r", "156", "157", "158", "159", "16", "160", "160r", "161", "161r", "162", "163", "164", "165", "166", "166r", "167", "167r", "168", "169", "17", "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", "18", "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", "19", "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", "2", "20", "200", "201", "201:2", "202", "203", "203:2", "204", "205", "206", "207", "208", "209", "21", "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", "22", "220", "221", "222", "222:2", "223", "224", "224:2", "225", "226", "227", "227:2", "228", "228:2", "229", "23", "230", "24", "25", "26", "27", "28", "29", "3", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "4", "40", "41", "42", "43", "44", "45", "46", "47", "48", "48:2", "49", "5", "50", "50:2", "51", "52", "53", "54", "55", "56", "57", "58", "59", "59:2", "6", "60", "61", "62", "63", "64", "65", "66", "67", "68", "68:2", "69", "7", "70", "70:2", "71", "72", "73", "74", "75", "76", "77", "78", "79", "8", "80", "81", "82", "83", "84", "85", "85:2", "86", "86:2", "87", "88", "88:2", "89", "9", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "a-1", "a1", "a112", "a112/a", "a112/m", "a112/n", "a1121", "a1121/a", "a1121/b", "a1121/n", "a11a", "a11b", "a11m", "a11n", "a12/a1", "a12/a1s", "a12/m1", "a12/n1", "a121", "a121/a1", "a121/c1", "a121/n1", "a1211", "a1a1", "a1c1", "a1m1", "a1n1", "a2", "a2/a", "a2/m", "a2/n", "a21/a", "a21/n", "a212121", "a2122", "a21am", "a21cn", "a21ma", "a21nb", "a22121", "a222", "a2aa", "a2cb", "a2mm", "a2nn", "aa", "ab21b", "ab21n", "aba2", "abaa", "abaa:2", "abcb", "abm2", "abma", "abmm", "abnb", "abnn", "abnn:2", "ac", "ac2a", "ac2m", "acaa", "acaa:2", "acam", "acc21", "accb", "accn", "acmm", "acn21", "acnn", "acnn:2", "am", "am2a", "am2m", "ama2", "amaa", "amam", "amm2", "amma", "ammm", "an", "an21b", "an21n", "anc21", "ancb", "ann21", "annn", "b-1", "b1", "b112", "b112/b", "b112/bs", "b112/m", "b112/n", "b1121", "b1121/a", "b1121/b", "b1121/n", "b11a", "b11b", "b11m", "b11n", "b2/b11", "b2/m11", "b2/n11", "b21/b11", "b21/c11", "b21/n11", "b211", "b2111", "b212121", "b21221", "b21aa", "b21an", "b21na", "b21nn", "b2212", "b222", "b2cb", "b2cm", "b2mb", "b2mm", "bb11", "bb21m", "bb2b", "bba2", "bbab", "bbab:2", "bbcb", "bbcb:2", "bbcm", "bbm2", "bbmb", "bbmm", "bbmms", "bc11", "bc21n", "bc2a", "bcaa", "bcc21", "bcca", "bccn", "bcn21", "bcna", "bm11", "bm21b", "bm2m", "bma2", "bmab", "bmabs", "bmam", "bmcm", "bmm2", "bmmb", "bmmbs", "bmmm", "bn11", "bn21a", "bn2n", "bnaa", "bnan", "bnan:2", "bnc21", "bncn", "bncn:2", "bnn21", "bnnn", "c-1", "c-4", "c1", "c12/c1", "c12/c1s", "c12/m1", "c12/n1", "c121", "c121/a1", "c121/c1", "c121/n1", "c1211", "c1a1", "c1c1", "c1m1", "c1n1", "c2", "c2/c", "c2/c11", "c2/m", "c2/m11", "c2/n", "c2/n11", "c21/b11", "c21/c", "c21/c11", "c21/n", "c21/n11", "c211", "c2111", "c21212", "c212121", "c21aa", "c21an", "c21na", "c21nn", "c222", "c2221", "c2221s", "c2cb", "c2cm", "c2mb", "c2mm", "c4", "c4/a", "c4/a:2", "c4/b", "c4/b:2", "c4/m", "c4/n", "c41", "c42", "c42/a", "c42/a:2", "c42/b", "c42/b:2", "c42/m", "c4212", "c42121", "c422", "c4221", "c43", "ca", "cb11", "cb21b", "cb21n", "cba2", "cbaa", "cbab", "cban", "cbn21", "cbnb", "cc", "cc11", "cc2a", "cc2m", "ccc2", "ccca", "ccca:2", "cccaz", "cccb", "cccb:2", "cccm", "ccm21", "ccmb", "ccmbs", "ccmm", "cm", "cm11", "cm2a", "cm2m", "cmc21", "cmca", "cmcm", "cmm2", "cmma", "cmmb", "cmmm", "cn", "cn11", "cn21b", "cn21n", "cna21", "cnaa", "cnn2", "cnna", "cnna:2", "cnnb", "cnnb:2", "cnnn", "f-1", "f-2", "f-4", "f-42m", "f-43c", "f-43m", "f1", "f12/d1", "f21212", "f21221", "f21an", "f21dd", "f21na", "f22121", "f222", "f23", "f2cb", "f2dd", "f2mm", "f4", "f4/m", "f41", "f41/d", "f41/d:2", "f4132", "f42", "f42/a", "f43", "f43/d", "f43/d:2", "f432", "fb21n", "fba2", "fban", "fc2a", "fcn21", "fcna", "fd", "fd-3", "fd-3:2", "fd-3c", "fd-3c:2", "fd-3cs", "fd-3cz", "fd-3m", "fd-3m:2", "fd-3ms", "fd-3ms1", "fd-3mz", "fd-3s", "fd-3z", "fd21d", "fd2d", "fd3", "fd3:2", "fd3c", "fd3c:2", "fd3cs", "fd3cz", "fd3m", "fd3m:2", "fd3ms", "fd3mz", "fd3s", "fd3z", "fdd2", "fdd21", "fdd2s", "fddd", "fddd:2", "fddds", "fdddz", "fm-3", "fm-3c", "fm-3m", "fm2m", "fm3", "fm3c", "fm3m", "fmm2", "fmmm", "fn21b", "fnc21", "fncb", "i-1", "i-4", "i-42d", "i-42ds", "i-42m", "i-43d", "i-43m", "i-4c2", "i-4m2", "i1", "i112", "i112/a", "i112/as", "i112/b", "i112/m", "i1121", "i1121/a", "i1121/b", "i1121/n", "i11a", "i11b", "i11m", "i11n", "i12/a1", "i12/a1s", "i12/c1", "i12/m1", "i12/m1s", "i121", "i121/a1", "i121/c1", "i121/n1", "i1211", "i121s", "i1a1", "i1c1", "i1m1", "i1n1", "i2", "i2/a", "i2/b11", "i2/c", "i2/c11", "i2/m", "i2/m11", "i21/a", "i21/b11", "i21/c", "i21/c11", "i21/n11", "i211", "i2111", "i212121", "i213", "i21aa", "i21an", "i21na", "i21nn", "i222", "i23", "i2cb", "i2cm", "i2mb", "i2mm", "i4", "i4/m", "i4/mcm", "i4/mcms", "i4/mmm", "i41", "i41/a", "i41/a:2", "i41/acd", "i41/acd:2", "i41/acds", "i41/acdz", "i41/amd", "i41/amd:2", "i41/amds", "i41/amdz", "i41/as", "i41/az", "i41/az1", "i4122", "i4132", "i41cd", "i41md", "i42", "i42/n", "i422", "i43", "i43/b", "i43/b:2", "i432", "i4cm", "i4mm", "ia", "ia-3", "ia-3d", "ia3", "ib11", "ib21b", "ib21n", "iba2", "ibam", "ibams", "ibca", "ibm2", "ibmm", "ibnb", "ibnn", "ic", "ic11", "ic2a", "ic2m", "icab", "icc21", "iccn", "icma", "icmas", "icmm", "icn21", "icnn", "im", "im-3", "im-3m", "im11", "im2a", "im2m", "im3", "im3m", "ima2", "imam", "imams1", "imcb", "imcm", "imm2", "imma", "immb", "immm", "in", "in11", "in21b", "in21n", "inaa", "inan", "inc21", "incn", "inn21", "inna", "innb", "innn", "p-1", "p-3", "p-31c", "p-31cs", "p-31m", "p-3c1", "p-3m1", "p-4", "p-421c", "p-421m", "p-42c", "p-42m", "p-43m", "p-43n", "p-4b2", "p-4b2s", "p-4c2", "p-4m2", "p-4n2", "p-6", "p-62c", "p-62m", "p-6c2", "p-6m2", "p1", "p112", "p112/a", "p112/b", "p112/m", "p112/ms", "p112/n", "p1121", "p1121/a", "p1121/b", "p1121/m", "p1121/n", "p11a", "p11b", "p11m", "p11n", "p12/a1", "p12/c1", "p12/c1s", "p12/m1", "p12/n1", "p121", "p121/a1", "p121/a1s", "p121/c1", "p121/c1s", "p121/m1", "p121/m1s", "p121/n1", "p1211", "p1a1", "p1c1", "p1m1", "p1n1", "p2", "p2/b11", "p2/c", "p2/c11", "p2/m", "p2/m11", "p2/n", "p2/n11", "p21", "p21/a", "p21/b11", "p21/c", "p21/c11", "p21/m", "p21/m11", "p21/n", "p21/n11", "p211", "p2111", "p21212", "p212121", "p212121s", "p2122", "p21221", "p213", "p21ab", "p21am", "p21ca", "p21cn", "p21cns", "p21ma", "p21mn", "p21mns", "p21nb", "p21nm", "p2212", "p22121", "p222", "p2221", "p23", "p2aa", "p2an", "p2cb", "p2cm", "p2mb", "p2mm", "p2mms", "p2na", "p2nn", "p3", "p31", "p3112", "p3112s", "p312", "p3121", "p3121s", "p31c", "p31m", "p32", "p321", "p3212", "p3221", "p3221s", "p3c1", "p3m1", "p4", "p4/m", "p4/mbm", "p4/mcc", "p4/mmm", "p4/mnc", "p4/n", "p4/n:2", "p4/nbm", "p4/nbm:2", "p4/nbms", "p4/nbmz", "p4/ncc", "p4/ncc:2", "p4/nccs", "p4/nccz", "p4/nmm", "p4/nmm:2", "p4/nmms", "p4/nmms1", "p4/nmmz", "p4/nnc", "p4/nnc:2", "p4/nncs", "p4/nncz", "p4/nncz1", "p4/ns", "p4/ns1", "p4/nz", "p41", "p41212", "p4122", "p4132", "p42", "p42/m", "p42/mbc", "p42/mcm", "p42/mmc", "p42/mmcs", "p42/mnm", "p42/n", "p42/n:2", "p42/nbc", "p42/nbc:2", "p42/nbcs", "p42/nbcz", "p42/ncm", "p42/ncm:2", "p42/ncms", "p42/ncmz", "p42/nmc", "p42/nmc:2", "p42/nmcs", "p42/nmcz", "p42/nnm", "p42/nnm:2", "p42/nnms", "p42/nnmz", "p42/ns", "p42/ns1", "p42/nz", "p4212", "p42121", "p422", "p4221", "p42212", "p4222", "p4232", "p42bc", "p42cm", "p42mc", "p42nm", "p43", "p432", "p43212", "p4322", "p4332", "p4bm", "p4cc", "p4mm", "p4nc", "p6", "p6/m", "p6/mcc", "p6/mccs", "p6/mmm", "p61", "p6122", "p62", "p622", "p6222", "p63", "p63/m", "p63/mcm", "p63/mcms", "p63/mmc", "p6322", "p63cm", "p63mc", "p63mcs", "p64", "p6422", "p65", "p6522", "p6cc", "p6mm", "pa-3", "pa3", "pb11", "pb21a", "pb21m", "pb2b", "pb2n", "pba2", "pbaa", "pbab", "pbam", "pban", "pban:2", "pbans", "pbanz", "pbc21", "pbc21s", "pbca", "pbcb", "pbcm", "pbcn", "pbm2", "pbma", "pbmb", "pbmm", "pbmn", "pbn21", "pbna", "pbnb", "pbnm", "pbnms", "pbnn", "pc", "pc11", "pc21b", "pc21n", "pc2a", "pc2m", "pca21", "pca21s", "pcaa", "pcab", "pcam", "pcan", "pcc2", "pcca", "pccb", "pccm", "pccn", "pcm21", "pcma", "pcmb", "pcmm", "pcmn", "pcn2", "pcna", "pcna:2", "pcnb", "pcnbs", "pcnm", "pcnn", "pm", "pm-3", "pm-3m", "pm-3n", "pm11", "pm21b", "pm21n", "pm21ns", "pm21ns1", "pm2a", "pm2m", "pm3", "pm3m", "pm3n", "pma2", "pmaa", "pmab", "pmam", "pman", "pmc21", "pmca", "pmcb", "pmcm", "pmcn", "pmcns", "pmcns1", "pmcns2", "pmm2", "pmma", "pmmb", "pmmm", "pmmn", "pmmn:2", "pmmns", "pmmnz", "pmn21", "pmn21s", "pmna", "pmnb", "pmnbs", "pmnbs1", "pmnm", "pmnm:2", "pmnms", "pmnmz", "pmnn", "pn", "pn-3", "pn-3:2", "pn-3m", "pn-3m:2", "pn-3ms", "pn-3mz", "pn-3n", "pn-3n:2", "pn-3ns", "pn-3nz", "pn-3s", "pn-3z", "pn11", "pn21a", "pn21m", "pn21ms", "pn2b", "pn2n", "pn3", "pn3:2", "pn3m", "pn3m:2", "pn3ms", "pn3mz", "pn3n", "pn3n:2", "pn3ns", "pn3nz", "pn3s", "pn3z", "pna21", "pnaa", "pnab", "pnam", "pnams", "pnan", "pnans", "pnc2", "pnca", "pncb", "pncb:2", "pncbs", "pncbz", "pncm", "pncn", "pnm21", "pnma", "pnmb", "pnmm", "pnmm:2", "pnmms", "pnmmz", "pnmn", "pnn2", "pnna", "pnnb", "pnnm", "pnnn", "pnnn:2", "pnnns", "pnnnz", "r-3", "r-3c", "r-3cr", "r-3crs", "r-3m", "r-3mr", "r-3mrs", "r-3r", "r3", "r32", "r32r", "r3c", "r3cr", "r3m", "r3mr", "r3r", "r-3ch", "r-3mh", "r-3h", "r32h", "r3ch", "r3mh", "r3h" ]); var allowedOccupancies = /* @__PURE__ */ new Set([ "D", "H", "H-1", "D-1", "He", "Li", "Li+1", "Be", "Be+2", "B", "C", "Cval", "N", "O", "O-1", "O-2", "F", "F-1", "Ne", "Na", "Na+1", "Mg", "Mg+2", "Al", "Al+3", "Si", "Siva", "Si+4", "P", "S", "Cl", "Cl-1", "Ar", "K", "K+1", "Ca", "Ca+2", "Sc", "Sc+3", "Ti", "Ti+2", "Ti+3", "Ti+4", "V", "V+2", "V+3", "V+5", "Cr", "Cr+2", "Cr+3", "Mn", "Mn+2", "Mn+3", "Mn+4", "Fe", "Fe+2", "Fe+3", "Co", "Co+2", "Co+3", "Ni", "Ni+2", "Ni+3", "Cu", "Cu+1", "Cu+2", "Zn", "Zn+2", "Ga", "Ga+3", "Ge", "Ge+4", "As", "Se", "Br", "Br-1", "Kr", "Rb", "Rb+1", "Sr", "Sr+2", "Y", "Y+3", "Zr", "Zr+4", "Nb", "Nb+3", "Nb+5", "Mo", "Mo+3", "Mo+5", "Mo+6", "Tc", "Ru", "Ru+3", "Ru+4", "Rh", "Rh+3", "Rh+4", "Pd", "Pd+2", "Pd+4", "Ag", "Ag+1", "Ag+2", "Cd", "Cd+2", "In", "In+3", "Sn", "Sn+2", "Sn+4", "Sb", "Sb+3", "Sb+5", "Te", "I", "I-1", "Xe", "Cs", "Cs+1", "Ba", "Ba+2", "La", "La+3", "Ce", "Ce+3", "Ce+4", "Pr", "Pr+3", "Pr+4", "Nd", "Nd+3", "Pm", "Pm+3", "Sm", "Sm+3", "Eu", "Eu+2", "Eu+3", "Gd", "Gd+3", "Tb", "Tb+3", "Dy", "Dy+3", "Ho", "Ho+3", "Er", "Er+3", "Tm", "Tm+3", "Yb", "Yb+2", "Yb+3", "Lu", "Lu+3", "Hf", "Hf+4", "Ta", "Ta+5", "W", "W+6", "Re", "Os", "Os+4", "Ir", "Ir+3", "Ir+4", "Pt", "Pt+2", "Pt+4", "Au", "Au+1", "Au+3", "Hg", "Hg+1", "Hg+2", "Tl", "Tl+1", "Tl+3", "Pb", "Pb+2", "Pb+4", "Bi", "Bi+3", "Bi+5", "Po", "At", "Rn", "Fr", "Ra", "Ra+2", "Ac", "Ac+3", "Th", "Th+4", "Pa", "U", "U+3", "U+4", "U+6", "Np", "Np+3", "Np+4", "Np+6", "Pu", "Pu+3", "Pu+4", "Pu+6", "Am", "Cm", "Bk", "Cf", "Q", "1H", "2H", "3H", "3He", "4He", "6Li", "7Li", "10B", "11B", "12C", "13C", "14N", "15N", "16O", "17O", "18O", "20Ne", "21Ne", "22Ne", "24Mg", "25Mg", "26Mg", "28Si", "29Si", "30Si", "32S", "33S", "34S", "36S", "35Cl", "37Cl", "36Ar", "38Ar", "40Ar", "39K", "40K", "41K", "40Ca", "42Ca", "43Ca", "44Ca", "46Ca", "48Ca", "46Ti", "47Ti", "48Ti", "49Ti", "50Ti", "50V", "51V", "50Cr", "52Cr", "53Cr", "54Cr", "54Fe", "56Fe", "57Fe", "58Fe", "58Ni", "60Ni", "61Ni", "62Ni", "64Ni", "63Cu", "65Cu", "64Zn", "66Zn", "67Zn", "68Zn", "70Zn", "69Ga", "71Ga", "70Ge", "72Ge", "73Ge", "74Ge", "76Ge", "74Se", "76Se", "77Se", "78Se", "80Se", "82Se", "79Br", "81Br", "86Kr", "85Rb", "87Rb", "84Sr", "86Sr", "87Sr", "88Sr", "90Zr", "91Zr", "92Zr", "94Zr", "96Zr", "92Mo", "94Mo", "95Mo", "96Mo", "97Mo", "98Mo", "100Mo", "102Pd", "104Pd", "105Pd", "106Pd", "108Pd", "110Pd", "107Ag", "109Ag", "106Cd", "108Cd", "110Cd", "111Cd", "112Cd", "113Cd", "114Cd", "116Cd", "113In", "115In", "112Sn", "114Sn", "115Sn", "116Sn", "117Sn", "118Sn", "119Sn", "120Sn", "122Sn", "124Sn", "121Sb", "123Sb", "120Te", "122Te", "123Te", "124Te", "125Te", "126Te", "128Te", "130Te", "130Ba", "132Ba", "134Ba", "135Ba", "136Ba", "137Ba", "138Ba", "138La", "139La", "136Ce", "138Ce", "140Ce", "142Ce", "142Nd", "143Nd", "144Nd", "145Nd", "146Nd", "148Nd", "150Nd", "144Sm", "147Sm", "148Sm", "149Sm", "150Sm", "152Sm", "154Sm", "151Eu", "153Eu", "152Gd", "154Gd", "155Gd", "156Gd", "157Gd", "158Gd", "160Gd", "156Dy", "158Dy", "160Dy", "161Dy", "162Dy", "163Dy", "164Dy", "162Er", "164Er", "166Er", "167Er", "168Er", "170Er", "168Yb", "170Yb", "171Yb", "172Yb", "173Yb", "174Yb", "176Yb", "175Lu", "176Lu", "174Hf", "176Hf", "177Hf", "178Hf", "179Hf", "180Hf", "180Ta", "181Ta", "180W", "182W", "183W", "184W", "186W", "185Re", "187Re", "186Os", "187Os", "188Os", "189Os", "190Os", "192Os", "190Pt", "192Pt", "194Pt", "195Pt", "196Pt", "198Pt", "196Hg", "199Hg", "203Tl", "205Tl", "204Pb", "206Pb", "207Pb", "208Pb", "233U", "234U", "235U", "238U", "238Pu", "239Pu", "240Pu", "242Pu", "244Cm", "246Cm", "248Cm" ]); function getDecorations(editor) { const strLines = []; const xddLines = []; const badFractions = []; const warnings = []; const patternStr = /^\s*(str|STR|hkl_Is|xo_Is|d_Is|for\s+strs|for\s+hklIs)/; const patternXdd = /^\s*(xdd|XDD|TOF_XYE|RAW|DAT|C_matrix_normalized|for\s+xdds)/; const isLineComment = (line) => /^\s*'/.test(line); const isIfdefLine = (line) => /^\s*#ifdef/.test(line); const isBlockCommentStart = (line) => line.includes("/*"); const isBlockCommentEnd = (line) => line.includes("*/"); for (let i = 0; i < editor.document.lineCount; i++) { const lineText = editor.document.lineAt(i).text; let targetArray = null; if (patternStr.test(lineText)) { targetArray = strLines; } else if (patternXdd.test(lineText)) { targetArray = xddLines; } if (targetArray) { let decorationLine = i - 1; while (decorationLine >= 0) { const prevLine = editor.document.lineAt(decorationLine).text; if (isLineComment(prevLine) || isIfdefLine(prevLine)) { decorationLine--; continue; } if (isBlockCommentEnd(prevLine)) { while (decorationLine >= 0 && !isBlockCommentStart(editor.document.lineAt(decorationLine).text)) { decorationLine--; } decorationLine--; continue; } break; } if (decorationLine >= 0) { targetArray.push({ range: new vscode33.Range(decorationLine, 0, decorationLine, 0) }); } } const spaceGroupRegex = /^\s*space_group\s+(['"])?([A-Za-z0-9\-/:]+)\1?/; const spaceGroupMatch = lineText.match(spaceGroupRegex); if (spaceGroupMatch) { const [, quote, groupNameRaw] = spaceGroupMatch; const groupName = groupNameRaw.toLowerCase(); const fullGroup = quote ? `${quote}${groupNameRaw}${quote}` : groupNameRaw; if (!allowedSpaceGroups.has(groupName)) { const start = lineText.indexOf(fullGroup); const end = start + fullGroup.length; warnings.push({ range: new vscode33.Range(i, start, i, end), hoverMessage: `Space group: ${groupNameRaw} may not be recognised by TOPAS` }); } } const siteLineRegex = /^\s*site\b/; if (siteLineRegex.test(lineText)) { const occMatch = /occ\s+([^\s]+)/.exec(lineText); if (occMatch) { const occWord = occMatch[1]; if (!allowedOccupancies.has(occWord)) { const occIndex = lineText.indexOf("occ"); const wordStart = lineText.indexOf(occWord, occIndex); const wordEnd = wordStart + occWord.length; warnings.push({ range: new vscode33.Range(i, wordStart, i, wordEnd), hoverMessage: `Unrecognized atom type ${occWord} try removing charge?` }); } } } if (/^\s*site\b/.test(lineText)) { const badFractionPattern = /(? { activeEditor = editor; if (editor) { updateDecorations(editor); } }, null, context.subscriptions); vscode33.workspace.onDidChangeTextDocument((event) => { if (activeEditor && event.document === activeEditor.document) { updateDecorations(activeEditor); } }, null, context.subscriptions); } // src/commands/TopasToggleDecoration.ts var vscode34 = __toESM(require("vscode")); function TopasToggleDecoration() { return vscode34.commands.registerCommand("topas-editor.TopasToggleDecoration", () => { const config = vscode34.workspace.getConfiguration("topas-editor"); const current = config.get("decorations.enabled", true); const updated = !current; config.update("decorations.enabled", updated, vscode34.ConfigurationTarget.Global).then(() => { toggleDecoration(updated); vscode34.window.showInformationMessage(`TOPAS decoration ${updated ? "enabled" : "disabled"}.`); }, (err) => { vscode34.window.showErrorMessage("Failed to update decoration setting: " + err); }); }); } // src/extension.ts var TopasImportCIFFabio = require_TopasImportCIFFabio(); var TopasCreatePeakFitFile = require_TopasCreatePeakFitFile(); var TopasInsertPeakFittingBlock = require_TopasInsertPeakFittingBlock(); function activate(context) { console.log("Topas-Editor activated"); registerHoverProvider(context); registerHoverCommands(context); TopasArchive(); TopasBeqByType(); TopasCreateInpFile(); TopasFold(); TopasImportCIF(); TopasInpFromTemplate(); TopasInsertFileTextArg(); TopasInsertStructure(); TopasLivePlotPy(); TopasMenuSetup(); TopasMolToInp(); TopasOpenExamples(); TopasPlotAllPy(); TopasReadHoverHelp(); TopasSaveSet(); TopasSearchINP(); TopasSetDirectory(); TopasSimulateFromCIF(); TopasResetVersion(context); TopasMessage(); TopasRemoveEsds(); TopasRefineAtoms(); TopasToAdp_5(); TopasToggleComment(); TopasOpenOut(); TopasOutputLines(); TopasOutputHeader(); TopasOxfordCreateInpFile(); TopasOxfordImportCIF(); TopasOxfordAddExpBackground(); TopasRemoveRefinedMarker(); TopasAddMyMenus(); TopasShowSetup(); TopasHelp(); context.subscriptions.push(TopasImportCIFFabio()); context.subscriptions.push(TopasCreatePeakFitFile()); context.subscriptions.push(TopasOxfordCreateInpFile()); context.subscriptions.push(TopasOxfordImportCIF()); context.subscriptions.push(TopasOxfordAddExpBackground()); context.subscriptions.push(TopasInsertPeakFittingBlock()); context.subscriptions.push(TopasToggleDecoration()); TopasSetupDecorations(context); const config = vscode35.workspace.getConfiguration(); const topasDir = config.get("topas.directory"); if (topasDir) { process.env.TOPAS_DIR = topasDir; vscode35.window.showInformationMessage(`TOPAS directory: ${topasDir}`); } else { vscode35.window.showInformationMessage("TOPAS_DIR is not set. Use the update command [ctrl-tu] to set it."); } const currentVersion = getCurrentExtensionVersion(); const previousVersion = context.globalState.get("storedTopasEditorVersion"); vscode35.window.showInformationMessage(`TOPAS Editor ${currentVersion} activated`); if (previousVersion !== currentVersion) { console.log(`Previous topas-editor version is: ${previousVersion} current version is ${currentVersion} you need to update menus`); vscode35.window.showWarningMessage( `Last recorded menu update at Topas Editor ${previousVersion} and you are running ${currentVersion}. A menu upddate is recommended`, { modal: true }, "Update", // Add an "Update" button "Later", // Add a "Later" button (optional) "Never" // If users want to keep menus as they have custom versions ).then((selection) => { if (selection === "Update") { context.globalState.update("storedTopasEditorVersion", currentVersion); vscode35.commands.executeCommand("topas-editor.TopasMenuSetup").then(() => { console.log("topas-editor.TopasMenuSetup command executed."); }, (err) => { console.error("Error executing topas-editor.TopasMenuSetup command:", err); vscode35.window.showErrorMessage("Failed to execute Topas Menu Setup command. Do this manually"); }); } else if (selection === "Later") { console.log("User chose to update menus later."); } else if (selection === "Never") { context.globalState.update("storedTopasEditorVersion", currentVersion); console.log("User chose to never update menus so stored value updated to current version."); } }); } else { console.log(`Previous topas-editor version is: ${previousVersion} current version is ${currentVersion} no update needed`); } } function getCurrentExtensionVersion() { const extensionPath = vscode35.extensions.getExtension("johnsoevans.topas-editor")?.extensionPath; if (!extensionPath) { return "unknown"; } const packageJsonPath = path19.join(extensionPath, "package.json"); const packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8")); return packageJson.version || "unknown"; } function deactivate() { } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { activate, deactivate });