define(function(require,exports,module){const FileViewController=brackets.getModule("project/FileViewController"),CommandManager=brackets.getModule("command/CommandManager"),EditorManager=brackets.getModule("editor/EditorManager"),KeyEvent=brackets.getModule("utils/KeyEvent"),Commands=brackets.getModule("command/Commands"),FileSystem=brackets.getModule("filesystem/FileSystem"),MainViewManager=brackets.getModule("view/MainViewManager"),FileUtils=brackets.getModule("file/FileUtils"),PreferencesManager=brackets.getModule("preferences/PreferencesManager"),Editor=brackets.getModule("editor/Editor"),Dialogs=brackets.getModule("widgets/Dialogs"),_=brackets.getModule("thirdparty/lodash"),ProjectManager=brackets.getModule("project/ProjectManager");function openFile(filePath){if(filePath.startsWith("/"))return jsPromise(FileViewController.openFileAndAddToWorkingSet(filePath));const projectFilePath=path.join(ProjectManager.getProjectRoot().fullPath,filePath);return jsPromise(FileViewController.openFileAndAddToWorkingSet(projectFilePath))}function readTextFile(filePath,bypassCache){filePath.startsWith("/")||(filePath=path.join(ProjectManager.getProjectRoot().fullPath,filePath));const file=FileSystem.getFileForPath(filePath);return jsPromise(FileUtils.readAsText(file,bypassCache))}function writeTextFile(filePath,text,allowBlindWrite){filePath.startsWith("/")||(filePath=path.join(ProjectManager.getProjectRoot().fullPath,filePath));const file=FileSystem.getFileForPath(filePath);return jsPromise(FileUtils.writeText(file,text,allowBlindWrite))}function deletePath(filePath){return filePath.startsWith("/")||(filePath=path.join(ProjectManager.getProjectRoot().fullPath,filePath)),new Promise((resolve,reject)=>{window.fs.unlink(filePath,err=>{err?reject(err):resolve()})})}function setCursors(selections){const activeEditor=EditorManager.getActiveEditor();if(!activeEditor)throw new Error(`No active editor found to set cursor at: ${selections}`);const parsedSelections=selections.map(selection=>{const parts=selection.split("-");if(1===parts.length){const[line,ch]=parts[0].split(":").map(Number);if(isNaN(line)||isNaN(ch))throw new Error(`Invalid cursor format: ${parts[0]} for ${selections}`);return{start:{line:line-1,ch:ch-1},end:{line:line-1,ch:ch-1}}}if(2===parts.length){const[fromLine,fromCh]=parts[0].split(":").map(Number),[toLine,toCh]=parts[1].split(":").map(Number);if(isNaN(fromLine)||isNaN(fromCh)||isNaN(toLine)||isNaN(toCh))throw new Error(`Invalid selection range format: ${selection}`);return{start:{line:fromLine-1,ch:fromCh-1},end:{line:toLine-1,ch:toCh-1}}}throw new Error(`Invalid format: ${selection}`)});activeEditor.setSelections(parsedSelections)}function computeCursors(editor,addQuotes){const selections=editor.getSelections();return selections.map(selection=>{const start=selection.start,end=selection.end;let cursor;return cursor=start.line===end.line&&start.ch===end.ch?`${start.line+1}:${start.ch+1}`:`${start.line+1}:${start.ch+1}-${end.line+1}:${end.ch+1}`,addQuotes?`"${cursor}"`:cursor})}function expectCursorsToBe(expectedSelections){const activeEditor=EditorManager.getActiveEditor();if(!activeEditor)throw new Error(`No active editor found for expectCursorsToBe: ${expectedSelections}`);const currentSelections=computeCursors(activeEditor);if(currentSelections.length!==expectedSelections.length)throw new Error(`expectCursorsToBe: [${expectedSelections.join(", ")}] `+`but got [${currentSelections.join(", ")}]`);for(let i=0;i1},openFileInFirstPane:function(filePath,addToWorkingSet){const command=addToWorkingSet?Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN:Commands.FILE_OPEN;return jsPromise(CommandManager.execute(command,{fullPath:_getFullPath(filePath),paneId:"first-pane"}))},openFileInSecondPane:function(filePath,addToWorkingSet){const command=addToWorkingSet?Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN:Commands.FILE_OPEN;return jsPromise(CommandManager.execute(command,{fullPath:_getFullPath(filePath),paneId:"second-pane"}))},focusFirstPane:function(){MainViewManager.setActivePaneId("first-pane")},focusSecondPane:function(){MainViewManager.setActivePaneId("second-pane")}};function awaitsFor(pollFn,_timeoutMessageOrMessageFn,timeoutms=2e3,pollInterval=10){if("number"==typeof _timeoutMessageOrMessageFn&&(pollInterval=timeoutms=_timeoutMessageOrMessageFn),"number"!=typeof timeoutms||"number"!=typeof pollInterval)throw new Error("awaitsFor: invalid parameters when awaiting for "+_timeoutMessageOrMessageFn);async function _getExpectMessage(_timeoutMessageOrMessageFn){try{"function"==typeof _timeoutMessageOrMessageFn&&(_timeoutMessageOrMessageFn=_timeoutMessageOrMessageFn())instanceof Promise&&(_timeoutMessageOrMessageFn=await _timeoutMessageOrMessageFn)}catch(e){_timeoutMessageOrMessageFn="Error executing expected message function:"+e.stack}return _timeoutMessageOrMessageFn}function _timeoutPromise(promise,ms){const timeout=new Promise((_,reject)=>{setTimeout(async()=>{_timeoutMessageOrMessageFn=await _getExpectMessage(_timeoutMessageOrMessageFn),reject(new Error(_timeoutMessageOrMessageFn||`Promise timed out after ${ms}ms`))},ms)});return Promise.race([promise,timeout])}return new Promise((resolve,reject)=>{let startTime=Date.now(),lapsedTime;async function pollingFn(){try{let result=pollFn();if("[object Promise]"===Object.prototype.toString.call(result)&&(result=await _timeoutPromise(result,timeoutms)),result)return void resolve();if((lapsedTime=Date.now()-startTime)>timeoutms)return _timeoutMessageOrMessageFn=await _getExpectMessage(_timeoutMessageOrMessageFn),void reject("awaitsFor timed out waiting for - "+_timeoutMessageOrMessageFn);setTimeout(pollingFn,pollInterval)}catch(e){reject(e)}}pollingFn()})}async function waitForModalDialog(dialogClass,friendlyName,timeout=2e3){dialogClass=dialogClass||"",friendlyName=friendlyName||dialogClass||"Modal Dialog",await awaitsFor(()=>{let $dlg;return $(`.modal.instance${dialogClass}`).length>=1},`Waiting for Modal Dialog to show ${friendlyName}`,timeout)}async function waitForModalDialogClosed(dialogClass,friendlyName,timeout=2e3){dialogClass=dialogClass||"",friendlyName=friendlyName||dialogClass||"Modal Dialog",await awaitsFor(()=>{let $dlg;return 0===$(`.modal.instance${dialogClass}`).length},`Waiting for Modal Dialog to not there ${friendlyName}`,timeout)}function _clickDialogButtonWithSelector(selectorOrButtonID,dialogClass,isButtonID){dialogClass=dialogClass||"";const $dlg=$(`.modal.instance${dialogClass}`);if(!$dlg.length)throw new Error(`No such dialog present: "${dialogClass}"`);const $button=isButtonID?$dlg.find(".dialog-button[data-button-id='"+selectorOrButtonID+"']"):$dlg.find(selectorOrButtonID);if($button.length>1)throw new Error(`Multiple button in dialog "${selectorOrButtonID}"`);if(!$button.length)throw new Error(`No such button in dialog "${selectorOrButtonID}"`);if($button.prop("disabled"))throw new Error(`Cannot click, button is disabled. "${selectorOrButtonID}"`);$button.click()}function clickDialogButtonID(buttonID,dialogClass){_clickDialogButtonWithSelector(buttonID,dialogClass,!0)}function clickDialogButton(buttonSelector,dialogClass){_clickDialogButtonWithSelector(buttonSelector,dialogClass,!1)}function saveActiveFile(){return jsPromise(CommandManager.execute(Commands.FILE_SAVE))}const __PR={readTextFile:readTextFile,writeTextFile:writeTextFile,deletePath:deletePath,openFile:openFile,setCursors:setCursors,expectCursorsToBe:expectCursorsToBe,keydown:keydown,typeAtCursor:typeAtCursor,validateText:validateText,validateAllMarks:validateAllMarks,validateMarks:validateMarks,closeFile:closeFile,closeAll:closeAll,undo:undo,redo:redo,setPreference:setPreference,getPreference:getPreference,validateEqual:validateEqual,validateNotEqual:validateNotEqual,execCommand:execCommand,saveActiveFile:saveActiveFile,awaitsFor:awaitsFor,waitForModalDialog:waitForModalDialog,waitForModalDialogClosed:waitForModalDialogClosed,clickDialogButtonID:clickDialogButtonID,clickDialogButton:clickDialogButton,EDITING:EDITING,$:$,Commands:Commands,Dialogs:Dialogs};async function runMacro(macroText){let errors=[];try{const AsyncFunction=async function(){}.constructor,macroAsync=new AsyncFunction("__PR","KeyEvent",macroText);await macroAsync(__PR,KeyEvent)}catch(e){console.error("Error executing macro: ",macroText,e),errors.push({lineNo:0,line:"",errorCode:"ERROR_EXEC",errorText:`${e}`})}return errors}Phoenix.isTestWindow&&(window.__PR=__PR),exports.computeCursors=computeCursors,exports.runMacro=runMacro});