forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTabstopManager.js
More file actions
1 lines (1 loc) · 5.39 KB
/
Copy pathTabstopManager.js
File metadata and controls
1 lines (1 loc) · 5.39 KB
1
define(function(require,exports,module){const Editor=require("editor/Editor").Editor;function parseSnippet(snippet){var out="",i=0,len=snippet.length,stops={};function record(num,start,end){num in stops||(stops[num]={start:start,end:end})}function readBraceBody(braceIdx){for(var j=braceIdx+1,depth=1,inner="";j<len&&depth>0;){var c=snippet.charAt(j);if("\\"===c&&j+1<len)inner+=snippet.charAt(j+1),j+=2;else if("{"!==c)if("}"!==c)inner+=c,j++;else{if(0===--depth){j++;break}inner+=c,j++}else depth++,inner+=c,j++}return{inner:inner,next:j}}for(;i<len;){var ch=snippet.charAt(i);if("\\"===ch&&i+1<len){var esc=snippet.charAt(i+1);if("$"===esc||"}"===esc||"\\"===esc){out+=esc,i+=2;continue}out+=ch,i++}else if("$"!==ch)out+=ch,i++;else{var simple=/^\$(\d+)/.exec(snippet.slice(i));if(simple){record(parseInt(simple[1],10),out.length,out.length),i+=simple[0].length;continue}if("{"===snippet.charAt(i+1)){var body=readBraceBody(i+1);i=body.next;var placeholder=/^(\d+):([\s\S]*)$/.exec(body.inner),choice=/^(\d+)\|([\s\S]*)\|$/.exec(body.inner),plain=/^(\d+)$/.exec(body.inner),varDefault=/^[A-Za-z_][A-Za-z0-9_]*:([\s\S]*)$/.exec(body.inner);if(placeholder){var sub=parseSnippet(placeholder[2]),phStart=out.length;out+=sub.text,record(parseInt(placeholder[1],10),phStart,out.length);for(var si=0;si<sub.stops.length;si++)record(sub.stops[si].number,phStart+sub.stops[si].start,phStart+sub.stops[si].end)}else if(choice){var first=choice[2].split(",")[0]||"",chStart=out.length;out+=first,record(parseInt(choice[1],10),chStart,out.length)}else plain?record(parseInt(plain[1],10),out.length,out.length):varDefault&&(out+=parseSnippet(varDefault[1]).text);continue}var varName=/^\$[A-Za-z_][A-Za-z0-9_]*/.exec(snippet.slice(i));if(varName){i+=varName[0].length;continue}out+=ch,i++}}var ordered=Object.keys(stops).map(Number).filter(function(x){return x>0}).sort(function(a,b){return a-b});return 0 in stops&&ordered.push(0),{text:out,stops:ordered.map(function(num){return{number:num,start:stops[num].start,end:stops[num].end}})}}var _session=null;function _clearSession(){if(_session){var session=_session;_session=null,session.markers.forEach(function(m){m.clear()}),session.activeOutlineMarker&&session.activeOutlineMarker.clear(),session.editor._codeMirror.removeKeyMap(session.keymap),session.editor.off(".tabstop")}}function _isWithinSessionBounds(pos){var minLine=1/0,maxLine=-1/0;return _session.markers.forEach(function(m){var r=_markerRange(m);r&&(minLine=Math.min(minLine,r.from.line),maxLine=Math.max(maxLine,r.to.line))}),minLine!==1/0&&(pos.line>=minLine&&pos.line<=maxLine)}function _handleCursorActivity(event,editor){_session&&_session.editor===editor&&(editor.getSelections().length>1||!_isWithinSessionBounds(editor.getCursorPos()))&&_clearSession()}function _markerRange(marker){var found=marker.find();return found?found.from&&found.to?{from:found.from,to:found.to}:{from:found,to:found}:null}function _selectStop(index){if(!_session||index<0||index>=_session.markers.length)return!1;var range=_markerRange(_session.markers[index]);return!!range&&(_session.index=index,_session.editor.setSelection(range.from,range.to),_session.activeOutlineMarker&&(_session.activeOutlineMarker.clear(),_session.activeOutlineMarker=null),range.from.line===range.to.line&&range.from.ch===range.to.ch||(_session.activeOutlineMarker=_session.editor.markText("tabstop-active",range.from,range.to,Editor.getMarkOptionTabstopOutlineActive())),!0)}function _gotoNext(){if(_session){for(var i=_session.index+1;i<_session.markers.length;i++)if(_selectStop(i))return void(i===_session.markers.length-1&&_clearSession());_clearSession()}}function _gotoPrev(){if(_session)for(var i=_session.index-1;i>=0;i--)if(_selectStop(i))return}function insertSnippet(editor,snippet,from,to){_clearSession();var parsed=parseSnippet(snippet);function posFromOffset(off){var seg=parsed.text.slice(0,off).split("\n");return 1===seg.length?{line:from.line,ch:from.ch+off}:{line:from.line+seg.length-1,ch:seg[seg.length-1].length}}if(editor.document.replaceRange(parsed.text,from,to),!parsed.stops.length)return editor.setCursorPos(posFromOffset(parsed.text.length).line,posFromOffset(parsed.text.length).ch),parsed;if(1===parsed.stops.length){var only=parsed.stops[0],s=posFromOffset(only.start),e=posFromOffset(only.end);return s.line===e.line&&s.ch===e.ch?editor.setCursorPos(s.line,s.ch):editor.setSelection(s,e),parsed}var outlineOption=Editor.getMarkOptionTabstopOutline(),markers=parsed.stops.map(function(stop){var ms=posFromOffset(stop.start),me=posFromOffset(stop.end);return ms.line===me.line&&ms.ch===me.ch?editor.setBookmark("tabstop",ms,{insertLeft:!0}):editor.markText("tabstop",ms,me,{clearWhenEmpty:!1,inclusiveLeft:!1,inclusiveRight:!0,className:outlineOption.className,startStyle:outlineOption.startStyle,endStyle:outlineOption.endStyle})}),keymap={name:"tabstop-session",Tab:function(){_gotoNext()},"Shift-Tab":function(){_gotoPrev()},Esc:function(){_clearSession()}};return _session={editor:editor,markers:markers,index:-1,keymap:keymap,activeOutlineMarker:null},editor._codeMirror.addKeyMap(keymap),editor.on("beforeDestroy.tabstop",_clearSession),editor.on("cursorActivity.tabstop",_handleCursorActivity),_selectStop(0),parsed}function hasActiveSession(){return!!_session}function endSession(){_clearSession()}exports.parseSnippet=parseSnippet,exports.insertSnippet=insertSnippet,exports.hasActiveSession=hasActiveSession,exports.endSession=endSession,exports.goToNextStop=_gotoNext,exports.goToPreviousStop=_gotoPrev});