forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMacroRunner.js
More file actions
1 lines (1 loc) · 14.2 KB
/
Copy pathMacroRunner.js
File metadata and controls
1 lines (1 loc) · 14.2 KB
1
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;i<currentSelections.length;i++)if(!currentSelections.includes(`${expectedSelections[i]}`)||!expectedSelections.includes(currentSelections[i]))throw new Error(`expectCursorsToBe: [${expectedSelections.join(", ")}] `+`but got [${currentSelections.join(", ")}]`)}function raiseKeyEvent(key,event,element,options){const doc=element.ownerDocument;void 0===options?options={view:doc.defaultView,bubbles:!0,cancelable:!0,keyIdentifer:key}:(options.view=doc.defaultView,options.bubbles=!0,options.cancelable=!0,options.keyIdentifier=key);const oEvent=new KeyboardEvent(event,options);"keydown"===event||"keyup"===event||"keypress"===event?(Object.defineProperty(oEvent,"keyCode",{get:function(){return this.keyCodeVal}}),Object.defineProperty(oEvent,"which",{get:function(){return this.keyCodeVal}}),Object.defineProperty(oEvent,"charCode",{get:function(){return this.keyCodeVal}}),oEvent.keyCodeVal=key,oEvent.keyCode!==key&&console.log("SpecRunnerUtils.simulateKeyEvent() - keyCode mismatch: "+oEvent.keyCode),element.dispatchEvent(oEvent)):console.log("SpecRunnerUtils.simulateKeyEvent() - unsupported keyevent: "+event)}function keydown(keysArray,modifiers){for(let key of keysArray){if("string"==typeof key&&(key.startsWith("DOM_VK_")||(key="DOM_VK_"+key),!(key=KeyEvent[key])))throw new Error(`Invalid key "${key}"`);raiseKeyEvent(key,"keydown",document.activeElement,modifiers)}}function typeAtCursor(text,origin){const activeEditor=EditorManager.getActiveEditor();if(!activeEditor)throw new Error(`No active editor found to typeAtCursor: ${text}`);const selections=activeEditor.getSelections();for(let selection of selections)activeEditor.replaceRange(text,selection.start,selection.end,origin)}function _toPos(posString){const pos=posString.split(":");return{line:Number(pos[0])-1,ch:Number(pos[1])-1}}function validateText(text,selection){const activeEditor=EditorManager.getActiveEditor();if(!activeEditor)throw new Error(`No active editor found to validateText: ${text} at selection ${selection}`);const from=selection.split("-")[0],to=selection.split("-")[1],selectedText=activeEditor.getTextBetween(_toPos(from),_toPos(to));if(selectedText!==text)throw new Error(`validateText: expected text at [${selection}] to be "${text}" but got "${selectedText}"`)}function _getMarkLocations(markType,whichAPI,selections){const activeEditor=EditorManager.getActiveEditor();if(!activeEditor)throw new Error(`No active editor found to ${whichAPI}: "${markType}" for selection "${selections}"`);const marks=activeEditor.getAllMarks(markType),marksLocations=[];for(let mark of marks){const loc=mark.find();marksLocations.push(`${loc.from.line+1}:${loc.from.ch+1}-${loc.to.line+1}:${loc.to.ch+1}`)}return marksLocations}function validateAllMarks(markType,selections){const marksLocations=_getMarkLocations(markType,"validateAllMarks",selections);if(!selections||marksLocations.length!==selections.length)throw new Error(`validateAllMarks expected marks "${markType}" at: [${selections&&selections.join(", ")}] `+`but got marked locations [${marksLocations.join(", ")}]`);for(let i=0;i<selections.length;i++)if(!selections.includes(`${marksLocations[i]}`)||!marksLocations.includes(selections[i]))throw new Error(`validateAllMarks expected marks "${markType}" at: [${selections.join(", ")}] `+`but got marked locations [${marksLocations.join(", ")}]`)}function validateEqual(obj1,obj2,message=""){if(!_.isEqual(obj1,obj2))throw new Error(`validateEqual: ${message?message+"\n":""} expected ${JSON.stringify(obj1)} to equal ${JSON.stringify(obj2)}`)}function validateNotEqual(obj1,obj2){if(_.isEqual(obj1,obj2))throw new Error(`validateEqual: expected ${JSON.stringify(obj1)} to NOT equal ${JSON.stringify(obj2)}`)}function validateMarks(markType,selections,totalMarkCount){const marksLocations=_getMarkLocations(markType,"validateMarks",selections);if(selections){if(void 0!==totalMarkCount&&marksLocations.length!==totalMarkCount)throw new Error(`validateMarks expected mark count for "${markType}" to be: ${totalMarkCount} `+`but got ${marksLocations.length}`);for(let selection of selections)if(!marksLocations.includes(selection))throw new Error(`validateMarks expected marks "${markType}" to be at: [${selections.join(", ")}] `+`but got marked locations [${marksLocations.join(", ")}]`)}}function closeFile(){return jsPromise(CommandManager.execute(Commands.FILE_CLOSE,{_forceClose:!0}))}function closeAll(){return jsPromise(CommandManager.execute(Commands.FILE_CLOSE_ALL,{_forceClose:!0}))}function execCommand(commandID,arg){return jsPromise(CommandManager.execute(commandID,arg))}function undo(){return execCommand(Commands.EDIT_UNDO)}function redo(){return execCommand(Commands.EDIT_REDO)}function setPreference(key,value){PreferencesManager.set(key,value)}function getPreference(key){return PreferencesManager.get(key)}function _getFullPath(filePath){return filePath.startsWith("/")?filePath:path.join(ProjectManager.getProjectRoot().fullPath,filePath)}const EDITING={setEditorSpacing:function(useTabs,spaceOrTabCount,isAutoMode){const activeEditor=EditorManager.getActiveEditor();if(!activeEditor)throw new Error("No active editor found to setEditorSpacing");const fullPath=activeEditor.document.file.fullPath;Editor.Editor.getAutoTabSpaces(fullPath)!==isAutoMode&&(Editor.Editor.setAutoTabSpaces(isAutoMode,fullPath),isAutoMode&&Editor.Editor._autoDetectTabSpaces(activeEditor,!0,!0)),Editor.Editor.setUseTabChar(useTabs,fullPath),useTabs?Editor.Editor.setTabSize(spaceOrTabCount,fullPath):Editor.Editor.setSpaceUnits(spaceOrTabCount,fullPath)},splitVertical:function(){CommandManager.execute(Commands.CMD_SPLITVIEW_VERTICAL)},splitHorizontal:function(){CommandManager.execute(Commands.CMD_SPLITVIEW_HORIZONTAL)},splitNone:function(){CommandManager.execute(Commands.CMD_SPLITVIEW_NONE)},getFirstPaneEditor:function(){return MainViewManager.getCurrentlyViewedEditor("first-pane")},getSecondPaneEditor:function(){return MainViewManager.getCurrentlyViewedEditor("second-pane")},isSplit:function(){return MainViewManager.getPaneCount()>1},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});