diff --git a/dist/local-echo.js b/dist/local-echo.js index d2f30eb..61d7b43 100644 --- a/dist/local-echo.js +++ b/dist/local-echo.js @@ -1,2 +1,2 @@ -var LocalEchoController=function(t){var r={};function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:n})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,r){if(1&r&&(t=e(t)),8&r)return t;if(4&r&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(e.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&r&&"string"!=typeof t)for(var i in t)e.d(n,i,function(r){return t[r]}.bind(null,i));return n},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e.p="",e(e.s=7)}([function(t,r,e){var n=void 0!==typeof JSON?JSON:e(1),i=e(4),s=e(5),o=e(6);r.quote=function(t){return i(t,function(t){return t&&"object"==typeof t?t.op.replace(/(.)/g,"\\$1"):/["\s]/.test(t)&&!/'/.test(t)?"'"+t.replace(/(['\\])/g,"\\$1")+"'":/["'\s]/.test(t)?'"'+t.replace(/(["\\$`!])/g,"\\$1")+'"':String(t).replace(/([#!"$&'()*,:;<=>?@\[\\\]^`{|}])/g,"\\$1")}).join(" ")};for(var u="(?:"+["\\|\\|","\\&\\&",";;","\\|\\&","[&;()|<>]"].join("|")+")",a="(\\\\['\"|&;()<> \\t]|[^\\s'\"|&;()<> \\t])+",c='"((\\\\"|[^"])*?)"',h="'((\\\\'|[^'])*?)'",l="",f=0;f<4;f++)l+=(Math.pow(16,8)*Math.random()).toString(16);r.parse=function(t,r,e){var f=function(t,r,e){var o=new RegExp(["("+u+")","("+a+"|"+c+"|"+h+")*"].join("|"),"g"),f=s(t.match(o),Boolean),p=!1;if(!f)return[];r||(r={});e||(e={});return i(f,function(t,i){if(!p){if(RegExp("^"+u+"$").test(t))return{op:t};for(var s=e.escape||"\\",o=!1,a=!1,c="",h=!1,v=0,m=t.length;v="0"&&n<="9";)r+=n,a();if("."===n)for(r+=".";a()&&n>="0"&&n<="9";)r+=n;if("e"===n||"E"===n)for(r+=n,a(),"-"!==n&&"+"!==n||(r+=n,a());n>="0"&&n<="9";)r+=n,a();if(t=+r,isFinite(t))return t;u("Bad number")},h=function(){var t,r,e,i="";if('"'===n)for(;a();){if('"'===n)return a(),i;if("\\"===n)if(a(),"u"===n){for(e=0,r=0;r<4&&(t=parseInt(a(),16),isFinite(t));r+=1)e=16*e+t;i+=String.fromCharCode(e)}else{if("string"!=typeof o[n])break;i+=o[n]}else i+=n}u("Bad string")},l=function(){for(;n&&n<=" ";)a()};s=function(){switch(l(),n){case"{":return function(){var t,r={};if("{"===n){if(a("{"),l(),"}"===n)return a("}"),r;for(;n;){if(t=h(),l(),a(":"),Object.hasOwnProperty.call(r,t)&&u('Duplicate key "'+t+'"'),r[t]=s(),l(),"}"===n)return a("}"),r;a(","),l()}}u("Bad object")}();case"[":return function(){var t=[];if("["===n){if(a("["),l(),"]"===n)return a("]"),t;for(;n;){if(t.push(s()),l(),"]"===n)return a("]"),t;a(","),l()}}u("Bad array")}();case'"':return h();case"-":return c();default:return n>="0"&&n<="9"?c():function(){switch(n){case"t":return a("t"),a("r"),a("u"),a("e"),!0;case"f":return a("f"),a("a"),a("l"),a("s"),a("e"),!1;case"n":return a("n"),a("u"),a("l"),a("l"),null}u("Unexpected '"+n+"'")}()}},t.exports=function(t,r){var o;return i=t,e=0,n=" ",o=s(),l(),n&&u("Syntax error"),"function"==typeof r?function t(e,n){var i,s,o=e[n];if(o&&"object"==typeof o)for(i in o)Object.prototype.hasOwnProperty.call(o,i)&&(void 0!==(s=t(o,i))?o[i]=s:delete o[i]);return r.call(e,n,o)}({"":o},""):o}},function(t,r){var e,n,i,s=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};function u(t){return s.lastIndex=0,s.test(t)?'"'+t.replace(s,function(t){var r=o[t];return"string"==typeof r?r:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}t.exports=function(t,r,s){var o;if(e="",n="","number"==typeof s)for(o=0;o=3;if(i&&t.reduce)return t.reduce(r,n);if(t.reduce)return t.reduce(r);for(var s=0;sthis.size&&this.entries.pop(0),this.cursor=this.entries.length))}},{key:"rewind",value:function(){this.cursor=this.entries.length}},{key:"getPrevious",value:function(){var t=Math.max(0,this.cursor-1);return this.cursor=t,this.entries[t]}},{key:"getNext",value:function(){var t=Math.min(this.entries.length,this.cursor+1);return this.cursor=t,this.entries[t]}}]),t}(),s=e(0);function o(t){return function(t){if(Array.isArray(t)){for(var r=0,e=new Array(t.length);r1&&void 0!==arguments[1])||arguments[1],n=[],i=/\w+/g;r=i.exec(t);)e?n.push(r.index):n.push(r.index+r[0].length);return n}function a(t,r){var e=u(t,!0).reverse().find(function(t){return te&&(i=0,n+=1)}return{row:n,col:i}}function h(t,r){return c(t,t.length,r).row+1}function l(t){return null!=t.match(/[^\\][ \t]$/m)}function f(t,r){for(var e=0;e1&&void 0!==arguments[1]?arguments[1]:{};!function(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")}(this,t),this.term=r,this.term.on("data",this.handleTermData.bind(this)),this.term.on("resize",this.handleTermResize.bind(this)),this.history=new i(e.historySize||10),this.maxAutocompleteEntries=e.maxAutocompleteEntries||100,this._autocompleteHandlers=[],this._active=!1,this._input="",this._cursor=0,this._activePrompt=null,this._activeCharPrompt=null,this._termSize={cols:this.term.cols,rows:this.term.rows}}return function(t,r,e){r&&f(t.prototype,r),e&&f(t,e)}(t,[{key:"addAutocompleteHandler",value:function(t){for(var r=arguments.length,e=new Array(r>1?r-1:0),n=1;n1&&void 0!==arguments[1]?arguments[1]:"> ";return new Promise(function(n,i){r.term.write(t),r._activePrompt={prompt:t,continuationPrompt:e,resolve:n,reject:i},r._input="",r._cursor=0,r._active=!0})}},{key:"readChar",value:function(t){var r=this;return new Promise(function(e,n){r.term.write(t),r._activeCharPrompt={prompt:t,resolve:e,reject:n}})}},{key:"abortRead",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"aborted";null==this._activePrompt&&null==this._activeCharPrompt||this.term.write("\r\n"),null!=this._activePrompt&&(this._activePrompt.reject(t),this._activePrompt=null),null!=this._activeCharPrompt&&(this._activeCharPrompt.reject(t),this._activeCharPrompt=null),this._active=!1}},{key:"println",value:function(t){this.print(t+"\n")}},{key:"print",value:function(t){var r=t.replace(/[\r\n]+/g,"\n");this.term.write(r.replace(/\n/g,"\r\n"))}},{key:"printWide",value:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;if(0==t.length)return println("");for(var e=t.reduce(function(t,r){return Math.max(t,r.length)},0)+r,n=Math.floor(this._termSize.cols/e),i=Math.ceil(t.length/n),s=0,o=0;o1&&void 0!==arguments[1])||arguments[1])&&this.clearInput();var r=this.applyPrompts(t);this.print(r),this._cursor>t.length&&(this._cursor=t.length);var e=this.applyPromptOffset(t,this._cursor),n=h(r,this._termSize.cols),i=c(r,e,this._termSize.cols),s=i.col,o=n-i.row-1;term.write("\r");for(var u=0;uthis._input.length&&(t=this._input.length);var r=this.applyPrompts(this._input),e=(h(r,this._termSize.cols),c(r,this.applyPromptOffset(this._input,this._cursor),this._termSize.cols)),n=e.col,i=e.row,s=c(r,this.applyPromptOffset(this._input,t),this._termSize.cols),o=s.col,u=s.row;if(u>i)for(var a=i;an)for(var f=n;f0){var r=Math.min(t,this._input.length-this._cursor);this.setCursor(this._cursor+r)}else if(t<0){var e=Math.max(t,-this._cursor);this.setCursor(this._cursor+e)}}},{key:"handleCursorErase",value:function(t){var r=this._cursor,e=this._input;if(t){if(r<=0)return;var n=e.substr(0,r-1)+e.substr(r);this.clearInput(),this._cursor-=1,this.setInput(n,!1)}else{var i=e.substr(0,r)+e.substr(r+1);this.setInput(i)}}},{key:"handleCursorInsert",value:function(t){var r=this._cursor,e=this._input,n=e.substr(0,r)+t+e.substr(r);this._cursor+=t.length,this.setInput(n)}},{key:"handleReadComplete",value:function(){this.history&&this.history.push(this._input),this._activePrompt&&(this._activePrompt.resolve(this._input),this._activePrompt=null),this.term.write("\r\n"),this._active=!1}},{key:"handleTermResize",value:function(t){var r=t.rows,e=t.cols;this.clearInput(),this._termSize={cols:e,rows:r},this.setInput(this._input,!1)}},{key:"handleTermData",value:function(t){var r=this;if(this._active){if(null!=this._activeCharPrompt)return this._activeCharPrompt.resolve(t),this._activeCharPrompt=null,void this.term.write("\r\n");if(t.length>3&&27!==t.charCodeAt(0)){var e=t.replace(/[\r\n]+/g,"\r");Array.from(e).forEach(function(t){return r.handleData(t)})}else this.handleData(t)}}},{key:"handleData",value:function(t){var r=this;if(this._active){var e,n=t.charCodeAt(0);if(27==n)switch(t.substr(1)){case"[A":if(this.history){var i=this.history.getPrevious();i&&(this.setInput(i),this.setCursor(i.length))}break;case"[B":if(this.history){var c=this.history.getNext();c||(c=""),this.setInput(c),this.setCursor(c.length)}break;case"[D":this.handleCursorMove(-1);break;case"[C":this.handleCursorMove(1);break;case"[3~":this.handleCursorErase(!1);break;case"[F":this.setCursor(this._input.length);break;case"[H":this.setCursor(0);break;case"b":null!=(e=a(this._input,this._cursor))&&this.setCursor(e);break;case"f":null!=(e=function(t,r){var e=u(t,!1).find(function(t){return t>r});return null==e?t.length:e}(this._input,this._cursor))&&this.setCursor(e);break;case"":null!=(e=a(this._input,this._cursor))&&(this.setInput(this._input.substr(0,e)+this._input.substr(this._cursor)),this.setCursor(e))}else if(n<32||127===n)switch(t){case"\r":!function(t){return""!=t.trim()&&((t.match(/'/g)||[]).length%2!=0||(t.match(/"/g)||[]).length%2!=0||""==t.split(/(\|\||\||&&)/g).pop().trim()||!(!t.endsWith("\\")||t.endsWith("\\\\")))}(this._input)?this.handleReadComplete():this.handleCursorInsert("\n");break;case"":this.handleCursorErase(!0);break;case"\t":if(this._autocompleteHandlers.length>0){var h=this._input.substr(0,this._cursor),f=l(h),p=function(t,r){var e=Object(s.parse)(r),n=e.length-1,i=e[n]||"";return""===r.trim()?(n=0,i=""):l(r)&&(n+=1,i=""),t.reduce(function(t,r){var i=r.fn,s=r.args;try{return t.concat(i.apply(void 0,[n,e].concat(o(s))))}catch(r){return console.error("Auto-complete error:",r),t}},[]).filter(function(t){return t.startsWith(i)})}(this._autocompleteHandlers,h);if(p.sort(),0===p.length)f||this.handleCursorInsert(" ");else if(1===p.length){var v=function(t){return""===t.trim()?"":l(t)?"":Object(s.parse)(t).pop()||""}(h);this.handleCursorInsert(p[0].substr(v.length)+" ")}else p.length<=this.maxAutocompleteEntries?this.printAndRestartPrompt(function(){r.printWide(p)}):this.printAndRestartPrompt(function(){return r.readChar("Display all ".concat(p.length," possibilities? (y or n)")).then(function(t){"y"!=t&&"Y"!=t||r.printWide(p)})})}else this.handleCursorInsert(" ");break;case"":this.setCursor(this._input.length),this.term.write("^C\r\n"+((this._activePrompt||{}).prompt||"")),this._input="",this._cursor=0,this.history&&this.history.rewind()}else this.handleCursorInsert(t)}}}]),t}();e.d(r,"HistoryController",function(){return i});r.default=p}]).default; +var LocalEchoController=function(t){var e={};function r(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=t,r.c=e,r.d=function(t,e,i){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)r.d(i,n,function(e){return t[e]}.bind(null,n));return i},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=1)}([function(t,e){e.quote=function(t){return t.map((function(t){return t&&"object"==typeof t?t.op.replace(/(.)/g,"\\$1"):/["\s]/.test(t)&&!/'/.test(t)?"'"+t.replace(/(['\\])/g,"\\$1")+"'":/["'\s]/.test(t)?'"'+t.replace(/(["\\$`!])/g,"\\$1")+'"':String(t).replace(/([A-z]:)?([#!"$&'()*,:;<=>?@\[\\\]^`{|}])/g,"$1\\$2")})).join(" ")};for(var r="(?:"+["\\|\\|","\\&\\&",";;","\\|\\&","\\<\\(",">>",">\\&","[&;()|<>]"].join("|")+")",i="",n=0;n<4;n++)i+=(Math.pow(16,8)*Math.random()).toString(16);e.parse=function(t,e,n){var s=function(t,e,n){var s=new RegExp(["("+r+")","((\\\\['\"|&;()<> \\t]|[^\\s'\"|&;()<> \\t])+|\"((\\\\\"|[^\"])*?)\"|'((\\\\'|[^'])*?)')*"].join("|"),"g"),o=t.match(s).filter(Boolean),a=!1;if(!o)return[];e||(e={});n||(n={});return o.map((function(t,s){if(!a){if(RegExp("^"+r+"$").test(t))return{op:t};for(var u=n.escape||"\\",h=!1,l=!1,c="",p=!1,f=0,v=t.length;fthis.size&&this.entries.shift(),this.cursor=this.entries.length)}},{key:"rewind",value:function(){this.cursor=this.entries.length}},{key:"getPrevious",value:function(){var t=Math.max(0,this.cursor-1);return this.cursor=t,this.entries[t]}},{key:"getNext",value:function(){var t=Math.min(this.entries.length,this.cursor+1);return this.cursor=t,this.entries[t]}}])&&i(e.prototype,r),n&&i(e,n),t}(),s=r(0);function o(t){return function(t){if(Array.isArray(t))return a(t)}(t)||function(t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(t))return Array.from(t)}(t)||function(t,e){if(!t)return;if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return a(t,e)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,i=new Array(e);r1&&void 0!==arguments[1])||arguments[1],i=[],n=/\w+/g;e=n.exec(t);)r?i.push(e.index):i.push(e.index+e[0].length);return i}function h(t,e){var r=u(t,!0).reverse().find((function(t){return tr)&&(n=0,i+=1)}return{row:i,col:n}}function c(t,e){return l(t,t.length,e).row+1}function p(t){return null!=t.match(/[^\\][ \t]$/m)}function f(t){return""===t.trim()||p(t)?"":Object(s.parse)(t).pop()||""}function v(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function m(t,e){for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:null,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};v(this,t),this.term=e,this._handleTermData=this.handleTermData.bind(this),this._handleTermResize=this.handleTermResize.bind(this),this.history=new n(r.historySize||10),this.maxAutocompleteEntries=r.maxAutocompleteEntries||100,this._autocompleteHandlers=[],this._active=!1,this._input="",this._cursor=0,this._activePrompt=null,this._activeCharPrompt=null,this._termSize={cols:0,rows:0},this._disposables=[],e&&(e.loadAddon?e.loadAddon(this):this.attach())}var e,r,i;return e=t,(r=[{key:"activate",value:function(t){this.term=t,this.attach()}},{key:"dispose",value:function(){this.detach()}},{key:"detach",value:function(){this.term.off?(this.term.off("data",this._handleTermData),this.term.off("resize",this._handleTermResize)):(this._disposables.forEach((function(t){return t.dispose()})),this._disposables=[])}},{key:"attach",value:function(){this.term.on?(this.term.on("data",this._handleTermData),this.term.on("resize",this._handleTermResize)):(this._disposables.push(this.term.onData(this._handleTermData)),this._disposables.push(this.term.onResize(this._handleTermResize))),this._termSize={cols:this.term.cols,rows:this.term.rows}}},{key:"addAutocompleteHandler",value:function(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),i=1;i1&&void 0!==arguments[1]?arguments[1]:"> ";return new Promise((function(i,n){e.term.write(t),e._activePrompt={prompt:t,continuationPrompt:r,resolve:i,reject:n},e._input="",e._cursor=0,e._active=!0}))}},{key:"readChar",value:function(t){var e=this;return new Promise((function(r,i){e.term.write(t),e._activeCharPrompt={prompt:t,resolve:r,reject:i}}))}},{key:"abortRead",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"aborted";null==this._activePrompt&&null==this._activeCharPrompt||this.term.write("\r\n"),null!=this._activePrompt&&(this._activePrompt.reject(t),this._activePrompt=null),null!=this._activeCharPrompt&&(this._activeCharPrompt.reject(t),this._activeCharPrompt=null),this._active=!1}},{key:"println",value:function(t){this.print(t+"\n")}},{key:"print",value:function(t){var e=t.replace(/[\r\n]+/g,"\n");this.term.write(e.replace(/\n/g,"\r\n"))}},{key:"printWide",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;if(0==t.length)return println("");for(var r=t.reduce((function(t,e){return Math.max(t,e.length)}),0)+e,i=Math.floor(this._termSize.cols/r),n=Math.ceil(t.length/i),s=0,o=0;o1&&void 0!==arguments[1])||arguments[1];e&&this.clearInput();var r=this.applyPrompts(t);this.print(r),this._cursor>t.length&&(this._cursor=t.length);var i=this.applyPromptOffset(t,this._cursor),n=c(r,this._termSize.cols),s=l(r,i,this._termSize.cols),o=s.col,a=s.row,u=n-a-1;this.term.write("\r");for(var h=0;hthis._input.length&&(t=this._input.length);var e=this.applyPrompts(this._input),r=(c(e,this._termSize.cols),l(e,this.applyPromptOffset(this._input,this._cursor),this._termSize.cols)),i=r.col,n=r.row,s=l(e,this.applyPromptOffset(this._input,t),this._termSize.cols),o=s.col,a=s.row;if(a>n)for(var u=n;ui)for(var p=i;p0){var e=Math.min(t,this._input.length-this._cursor);this.setCursor(this._cursor+e)}else if(t<0){var r=Math.max(t,-this._cursor);this.setCursor(this._cursor+r)}}},{key:"handleCursorErase",value:function(t){var e=this._cursor,r=this._input;if(t){if(e<=0)return;var i=r.substr(0,e-1)+r.substr(e);this.clearInput(),this._cursor-=1,this.setInput(i,!1)}else{var n=r.substr(0,e)+r.substr(e+1);this.setInput(n)}}},{key:"handleCursorInsert",value:function(t){var e=this._cursor,r=this._input,i=r.substr(0,e)+t+r.substr(e);this._cursor+=t.length,this.setInput(i)}},{key:"handleReadComplete",value:function(){this.history&&this.history.push(this._input),this._activePrompt&&(this._activePrompt.resolve(this._input),this._activePrompt=null),this.term.write("\r\n"),this._active=!1}},{key:"handleTermResize",value:function(t){var e=t.rows,r=t.cols;this.clearInput(),this._termSize={cols:r,rows:e},this.setInput(this._input,!1)}},{key:"handleTermData",value:function(t){var e=this;if(this._active){if(null!=this._activeCharPrompt)return this._activeCharPrompt.resolve(t),this._activeCharPrompt=null,void this.term.write("\r\n");if(t.length>3&&27!==t.charCodeAt(0)){var r=t.replace(/[\r\n]+/g,"\r");Array.from(r).forEach((function(t){return e.handleData(t)}))}else this.handleData(t)}}},{key:"handleData",value:function(t){var e=this;if(this._active){var r,i,n,a,l=t.charCodeAt(0);if(27==l)switch(t.substr(1)){case"[A":if(this.history){var c=this.history.getPrevious();c&&(this.setInput(c),this.setCursor(c.length))}break;case"[B":if(this.history){var v=this.history.getNext();v||(v=""),this.setInput(v),this.setCursor(v.length)}break;case"[D":this.handleCursorMove(-1);break;case"[C":this.handleCursorMove(1);break;case"[3~":this.handleCursorErase(!1);break;case"[F":this.setCursor(this._input.length);break;case"[H":this.setCursor(0);break;case"b":null!=(r=h(this._input,this._cursor))&&this.setCursor(r);break;case"f":i=this._input,n=this._cursor,null!=(r=null==(a=u(i,!1).find((function(t){return t>n})))?i.length:a)&&this.setCursor(r);break;case"":null!=(r=h(this._input,this._cursor))&&(this.setInput(this._input.substr(0,r)+this._input.substr(this._cursor)),this.setCursor(r))}else if(l<32||127===l)switch(t){case"\r":!function(t){return""!=t.trim()&&((t.match(/'/g)||[]).length%2!=0||(t.match(/"/g)||[]).length%2!=0||""==t.split(/(\|\||\||&&)/g).pop().trim()||!(!t.endsWith("\\")||t.endsWith("\\\\")))}(this._input)?this.handleReadComplete():this.handleCursorInsert("\n");break;case"":this.handleCursorErase(!0);break;case"\t":if(this._autocompleteHandlers.length>0){var m=this._input.substr(0,this._cursor),d=p(m),_=function(t,e){var r=Object(s.parse)(e),i=r.length-1,n=r[i]||"";return""===e.trim()?(i=0,n=""):p(e)&&(i+=1,n=""),t.reduce((function(t,e){var n=e.fn,s=e.args;try{return t.concat(n.apply(void 0,[i,r].concat(o(s))))}catch(e){return console.error("Auto-complete error:",e),t}}),[]).filter((function(t){return t.startsWith(n)}))}(this._autocompleteHandlers,m);if(_.sort(),0===_.length)d||this.handleCursorInsert(" ");else if(1===_.length){var g=f(m);this.handleCursorInsert(_[0].substr(g.length)+" ")}else if(_.length<=this.maxAutocompleteEntries){var y=function t(e,r){if(e.length>=r[0].length)return e;var i=e;e+=r[0].slice(e.length,e.length+1);for(var n=0;n?@\\[\\\\\\]^`{|}])/g, '\\\\$1'); \n }\n }).join(' ');\n};\n\nvar CONTROL = '(?:' + [\n '\\\\|\\\\|', '\\\\&\\\\&', ';;', '\\\\|\\\\&', '[&;()|<>]'\n].join('|') + ')';\nvar META = '|&;()<> \\\\t';\nvar BAREWORD = '(\\\\\\\\[\\'\"' + META + ']|[^\\\\s\\'\"' + META + '])+';\nvar SINGLE_QUOTE = '\"((\\\\\\\\\"|[^\"])*?)\"';\nvar DOUBLE_QUOTE = '\\'((\\\\\\\\\\'|[^\\'])*?)\\'';\n\nvar TOKEN = '';\nfor (var i = 0; i < 4; i++) {\n TOKEN += (Math.pow(16,8)*Math.random()).toString(16);\n}\n\nexports.parse = function (s, env, opts) {\n var mapped = parse(s, env, opts);\n if (typeof env !== 'function') return mapped;\n return reduce(mapped, function (acc, s) {\n if (typeof s === 'object') return acc.concat(s);\n var xs = s.split(RegExp('(' + TOKEN + '.*?' + TOKEN + ')', 'g'));\n if (xs.length === 1) return acc.concat(xs[0]);\n return acc.concat(map(filter(xs, Boolean), function (x) {\n if (RegExp('^' + TOKEN).test(x)) {\n return json.parse(x.split(TOKEN)[1]);\n }\n else return x;\n }));\n }, []);\n};\n\nfunction parse (s, env, opts) {\n var chunker = new RegExp([\n '(' + CONTROL + ')', // control chars\n '(' + BAREWORD + '|' + SINGLE_QUOTE + '|' + DOUBLE_QUOTE + ')*'\n ].join('|'), 'g');\n var match = filter(s.match(chunker), Boolean);\n var commented = false;\n\n if (!match) return [];\n if (!env) env = {};\n if (!opts) opts = {};\n return map(match, function (s, j) {\n if (commented) {\n return;\n }\n if (RegExp('^' + CONTROL + '$').test(s)) {\n return { op: s };\n }\n\n // Hand-written scanner/parser for Bash quoting rules:\n //\n // 1. inside single quotes, all characters are printed literally.\n // 2. inside double quotes, all characters are printed literally\n // except variables prefixed by '$' and backslashes followed by\n // either a double quote or another backslash.\n // 3. outside of any quotes, backslashes are treated as escape\n // characters and not printed (unless they are themselves escaped)\n // 4. quote context can switch mid-token if there is no whitespace\n // between the two quote contexts (e.g. all'one'\"token\" parses as\n // \"allonetoken\")\n var SQ = \"'\";\n var DQ = '\"';\n var DS = '$';\n var BS = opts.escape || '\\\\';\n var quote = false;\n var esc = false;\n var out = '';\n var isGlob = false;\n\n for (var i = 0, len = s.length; i < len; i++) {\n var c = s.charAt(i);\n isGlob = isGlob || (!quote && (c === '*' || c === '?'));\n if (esc) {\n out += c;\n esc = false;\n }\n else if (quote) {\n if (c === quote) {\n quote = false;\n }\n else if (quote == SQ) {\n out += c;\n }\n else { // Double quote\n if (c === BS) {\n i += 1;\n c = s.charAt(i);\n if (c === DQ || c === BS || c === DS) {\n out += c;\n } else {\n out += BS + c;\n }\n }\n else if (c === DS) {\n out += parseEnvVar();\n }\n else {\n out += c;\n }\n }\n }\n else if (c === DQ || c === SQ) {\n quote = c;\n }\n else if (RegExp('^' + CONTROL + '$').test(c)) {\n return { op: s };\n }\n else if (RegExp('^#$').test(c)) {\n commented = true;\n if (out.length){\n return [out, { comment: s.slice(i+1) + match.slice(j+1).join(' ') }];\n }\n return [{ comment: s.slice(i+1) + match.slice(j+1).join(' ') }];\n }\n else if (c === BS) {\n esc = true;\n }\n else if (c === DS) {\n out += parseEnvVar();\n }\n else out += c;\n }\n\n if (isGlob) return {op: 'glob', pattern: out};\n\n return out;\n\n function parseEnvVar() {\n i += 1;\n var varend, varname;\n //debugger\n if (s.charAt(i) === '{') {\n i += 1;\n if (s.charAt(i) === '}') {\n throw new Error(\"Bad substitution: \" + s.substr(i - 2, 3));\n }\n varend = s.indexOf('}', i);\n if (varend < 0) {\n throw new Error(\"Bad substitution: \" + s.substr(i));\n }\n varname = s.substr(i, varend - i);\n i = varend;\n }\n else if (/[*@#?$!_\\-]/.test(s.charAt(i))) {\n varname = s.charAt(i);\n i += 1;\n }\n else {\n varend = s.substr(i).match(/[^\\w\\d_]/);\n if (!varend) {\n varname = s.substr(i);\n i = s.length;\n } else {\n varname = s.substr(i, varend.index);\n i += varend.index - 1;\n }\n }\n return getVar(null, '', varname);\n }\n })\n // finalize parsed aruments\n .reduce(function(prev, arg){\n if (arg === undefined){\n return prev;\n }\n return prev.concat(arg);\n },[]);\n\n function getVar (_, pre, key) {\n var r = typeof env === 'function' ? env(key) : env[key];\n if (r === undefined) r = '';\n\n if (typeof r === 'object') {\n return pre + TOKEN + json.stringify(r) + TOKEN;\n }\n else return pre + r;\n }\n}\n","exports.parse = require('./lib/parse');\nexports.stringify = require('./lib/stringify');\n","var at, // The index of the current character\n ch, // The current character\n escapee = {\n '\"': '\"',\n '\\\\': '\\\\',\n '/': '/',\n b: '\\b',\n f: '\\f',\n n: '\\n',\n r: '\\r',\n t: '\\t'\n },\n text,\n\n error = function (m) {\n // Call error when something is wrong.\n throw {\n name: 'SyntaxError',\n message: m,\n at: at,\n text: text\n };\n },\n \n next = function (c) {\n // If a c parameter is provided, verify that it matches the current character.\n if (c && c !== ch) {\n error(\"Expected '\" + c + \"' instead of '\" + ch + \"'\");\n }\n \n // Get the next character. When there are no more characters,\n // return the empty string.\n \n ch = text.charAt(at);\n at += 1;\n return ch;\n },\n \n number = function () {\n // Parse a number value.\n var number,\n string = '';\n \n if (ch === '-') {\n string = '-';\n next('-');\n }\n while (ch >= '0' && ch <= '9') {\n string += ch;\n next();\n }\n if (ch === '.') {\n string += '.';\n while (next() && ch >= '0' && ch <= '9') {\n string += ch;\n }\n }\n if (ch === 'e' || ch === 'E') {\n string += ch;\n next();\n if (ch === '-' || ch === '+') {\n string += ch;\n next();\n }\n while (ch >= '0' && ch <= '9') {\n string += ch;\n next();\n }\n }\n number = +string;\n if (!isFinite(number)) {\n error(\"Bad number\");\n } else {\n return number;\n }\n },\n \n string = function () {\n // Parse a string value.\n var hex,\n i,\n string = '',\n uffff;\n \n // When parsing for string values, we must look for \" and \\ characters.\n if (ch === '\"') {\n while (next()) {\n if (ch === '\"') {\n next();\n return string;\n } else if (ch === '\\\\') {\n next();\n if (ch === 'u') {\n uffff = 0;\n for (i = 0; i < 4; i += 1) {\n hex = parseInt(next(), 16);\n if (!isFinite(hex)) {\n break;\n }\n uffff = uffff * 16 + hex;\n }\n string += String.fromCharCode(uffff);\n } else if (typeof escapee[ch] === 'string') {\n string += escapee[ch];\n } else {\n break;\n }\n } else {\n string += ch;\n }\n }\n }\n error(\"Bad string\");\n },\n\n white = function () {\n\n// Skip whitespace.\n\n while (ch && ch <= ' ') {\n next();\n }\n },\n\n word = function () {\n\n// true, false, or null.\n\n switch (ch) {\n case 't':\n next('t');\n next('r');\n next('u');\n next('e');\n return true;\n case 'f':\n next('f');\n next('a');\n next('l');\n next('s');\n next('e');\n return false;\n case 'n':\n next('n');\n next('u');\n next('l');\n next('l');\n return null;\n }\n error(\"Unexpected '\" + ch + \"'\");\n },\n\n value, // Place holder for the value function.\n\n array = function () {\n\n// Parse an array value.\n\n var array = [];\n\n if (ch === '[') {\n next('[');\n white();\n if (ch === ']') {\n next(']');\n return array; // empty array\n }\n while (ch) {\n array.push(value());\n white();\n if (ch === ']') {\n next(']');\n return array;\n }\n next(',');\n white();\n }\n }\n error(\"Bad array\");\n },\n\n object = function () {\n\n// Parse an object value.\n\n var key,\n object = {};\n\n if (ch === '{') {\n next('{');\n white();\n if (ch === '}') {\n next('}');\n return object; // empty object\n }\n while (ch) {\n key = string();\n white();\n next(':');\n if (Object.hasOwnProperty.call(object, key)) {\n error('Duplicate key \"' + key + '\"');\n }\n object[key] = value();\n white();\n if (ch === '}') {\n next('}');\n return object;\n }\n next(',');\n white();\n }\n }\n error(\"Bad object\");\n };\n\nvalue = function () {\n\n// Parse a JSON value. It could be an object, an array, a string, a number,\n// or a word.\n\n white();\n switch (ch) {\n case '{':\n return object();\n case '[':\n return array();\n case '\"':\n return string();\n case '-':\n return number();\n default:\n return ch >= '0' && ch <= '9' ? number() : word();\n }\n};\n\n// Return the json_parse function. It will have access to all of the above\n// functions and variables.\n\nmodule.exports = function (source, reviver) {\n var result;\n \n text = source;\n at = 0;\n ch = ' ';\n result = value();\n white();\n if (ch) {\n error(\"Syntax error\");\n }\n\n // If there is a reviver function, we recursively walk the new structure,\n // passing each name/value pair to the reviver function for possible\n // transformation, starting with a temporary root object that holds the result\n // in an empty key. If there is not a reviver function, we simply return the\n // result.\n\n return typeof reviver === 'function' ? (function walk(holder, key) {\n var k, v, value = holder[key];\n if (value && typeof value === 'object') {\n for (k in value) {\n if (Object.prototype.hasOwnProperty.call(value, k)) {\n v = walk(value, k);\n if (v !== undefined) {\n value[k] = v;\n } else {\n delete value[k];\n }\n }\n }\n }\n return reviver.call(holder, key, value);\n }({'': result}, '')) : result;\n};\n","var cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n gap,\n indent,\n meta = { // table of character substitutions\n '\\b': '\\\\b',\n '\\t': '\\\\t',\n '\\n': '\\\\n',\n '\\f': '\\\\f',\n '\\r': '\\\\r',\n '\"' : '\\\\\"',\n '\\\\': '\\\\\\\\'\n },\n rep;\n\nfunction quote(string) {\n // If the string contains no control characters, no quote characters, and no\n // backslash characters, then we can safely slap some quotes around it.\n // Otherwise we must also replace the offending characters with safe escape\n // sequences.\n \n escapable.lastIndex = 0;\n return escapable.test(string) ? '\"' + string.replace(escapable, function (a) {\n var c = meta[a];\n return typeof c === 'string' ? c :\n '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n }) + '\"' : '\"' + string + '\"';\n}\n\nfunction str(key, holder) {\n // Produce a string from holder[key].\n var i, // The loop counter.\n k, // The member key.\n v, // The member value.\n length,\n mind = gap,\n partial,\n value = holder[key];\n \n // If the value has a toJSON method, call it to obtain a replacement value.\n if (value && typeof value === 'object' &&\n typeof value.toJSON === 'function') {\n value = value.toJSON(key);\n }\n \n // If we were called with a replacer function, then call the replacer to\n // obtain a replacement value.\n if (typeof rep === 'function') {\n value = rep.call(holder, key, value);\n }\n \n // What happens next depends on the value's type.\n switch (typeof value) {\n case 'string':\n return quote(value);\n \n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null';\n \n case 'boolean':\n case 'null':\n // If the value is a boolean or null, convert it to a string. Note:\n // typeof null does not produce 'null'. The case is included here in\n // the remote chance that this gets fixed someday.\n return String(value);\n \n case 'object':\n if (!value) return 'null';\n gap += indent;\n partial = [];\n \n // Array.isArray\n if (Object.prototype.toString.apply(value) === '[object Array]') {\n length = value.length;\n for (i = 0; i < length; i += 1) {\n partial[i] = str(i, value) || 'null';\n }\n \n // Join all of the elements together, separated with commas, and\n // wrap them in brackets.\n v = partial.length === 0 ? '[]' : gap ?\n '[\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + ']' :\n '[' + partial.join(',') + ']';\n gap = mind;\n return v;\n }\n \n // If the replacer is an array, use it to select the members to be\n // stringified.\n if (rep && typeof rep === 'object') {\n length = rep.length;\n for (i = 0; i < length; i += 1) {\n k = rep[i];\n if (typeof k === 'string') {\n v = str(k, value);\n if (v) {\n partial.push(quote(k) + (gap ? ': ' : ':') + v);\n }\n }\n }\n }\n else {\n // Otherwise, iterate through all of the keys in the object.\n for (k in value) {\n if (Object.prototype.hasOwnProperty.call(value, k)) {\n v = str(k, value);\n if (v) {\n partial.push(quote(k) + (gap ? ': ' : ':') + v);\n }\n }\n }\n }\n \n // Join all of the member texts together, separated with commas,\n // and wrap them in braces.\n\n v = partial.length === 0 ? '{}' : gap ?\n '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + '}' :\n '{' + partial.join(',') + '}';\n gap = mind;\n return v;\n }\n}\n\nmodule.exports = function (value, replacer, space) {\n var i;\n gap = '';\n indent = '';\n \n // If the space parameter is a number, make an indent string containing that\n // many spaces.\n if (typeof space === 'number') {\n for (i = 0; i < space; i += 1) {\n indent += ' ';\n }\n }\n // If the space parameter is a string, it will be used as the indent string.\n else if (typeof space === 'string') {\n indent = space;\n }\n\n // If there is a replacer, it must be a function or an array.\n // Otherwise, throw an error.\n rep = replacer;\n if (replacer && typeof replacer !== 'function'\n && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {\n throw new Error('JSON.stringify');\n }\n \n // Make a fake root object containing our value under the key of ''.\n // Return the result of stringifying the value.\n return str('', {'': value});\n};\n","module.exports = function (xs, f) {\n if (xs.map) return xs.map(f);\n var res = [];\n for (var i = 0; i < xs.length; i++) {\n var x = xs[i];\n if (hasOwn.call(xs, i)) res.push(f(x, i, xs));\n }\n return res;\n};\n\nvar hasOwn = Object.prototype.hasOwnProperty;\n","/**\n * Array#filter.\n *\n * @param {Array} arr\n * @param {Function} fn\n * @return {Array}\n */\n\nmodule.exports = function (arr, fn) {\n if (arr.filter) return arr.filter(fn);\n var ret = [];\n for (var i = 0; i < arr.length; i++) {\n if (!hasOwn.call(arr, i)) continue;\n if (fn(arr[i], i, arr)) ret.push(arr[i]);\n }\n return ret;\n};\n\nvar hasOwn = Object.prototype.hasOwnProperty;\n","var hasOwn = Object.prototype.hasOwnProperty;\n\nmodule.exports = function (xs, f, acc) {\n var hasAcc = arguments.length >= 3;\n if (hasAcc && xs.reduce) return xs.reduce(f, acc);\n if (xs.reduce) return xs.reduce(f);\n \n for (var i = 0; i < xs.length; i++) {\n if (!hasOwn.call(xs, i)) continue;\n if (!hasAcc) {\n acc = xs[i];\n hasAcc = true;\n continue;\n }\n acc = f(acc, xs[i], i);\n }\n return acc;\n};\n","/**\n * The history controller provides an ring-buffer\n */\nexport class HistoryController {\n constructor(size) {\n this.size = size;\n this.entries = [];\n this.cursor = 0;\n }\n\n /**\n * Push an entry and maintain ring buffer size\n */\n push(entry) {\n // Skip empty entries\n if (entry.trim() === \"\") return;\n // Skip duplicate entries\n const lastEntry = this.entries[this.entries.length - 1];\n if (entry == lastEntry) return;\n // Keep track of entries\n this.entries.push(entry);\n if (this.entries.length > this.size) {\n this.entries.pop(0);\n }\n this.cursor = this.entries.length;\n }\n\n /**\n * Rewind history cursor on the last entry\n */\n rewind() {\n this.cursor = this.entries.length;\n }\n\n /**\n * Returns the previous entry\n */\n getPrevious() {\n const idx = Math.max(0, this.cursor - 1);\n this.cursor = idx;\n return this.entries[idx];\n }\n\n /**\n * Returns the next entry\n */\n getNext() {\n const idx = Math.min(this.entries.length, this.cursor + 1);\n this.cursor = idx;\n return this.entries[idx];\n }\n}\n","import { parse } from \"shell-quote\";\n\n/**\n * Detects all the word boundaries on the given input\n */\nexport function wordBoundaries(input, leftSide = true) {\n let match;\n const words = [];\n const rx = /\\w+/g;\n\n while ((match = rx.exec(input))) {\n if (leftSide) {\n words.push(match.index);\n } else {\n words.push(match.index + match[0].length);\n }\n }\n\n return words;\n}\n\n/**\n * The closest left (or right) word boundary of the given input at the\n * given offset.\n */\nexport function closestLeftBoundary(input, offset) {\n const found = wordBoundaries(input, true)\n .reverse()\n .find(x => x < offset);\n return found == null ? 0 : found;\n}\nexport function closestRightBoundary(input, offset) {\n const found = wordBoundaries(input, false).find(x => x > offset);\n return found == null ? input.length : found;\n}\n\n/**\n * Convert offset at the given input to col/row location\n *\n * This function is not optimized and practically emulates via brute-force\n * the navigation on the terminal, wrapping when they reach the column width.\n */\nexport function offsetToColRow(input, offset, maxCols) {\n let row = 0,\n col = 0;\n\n for (let i = 0; i < offset; ++i) {\n const chr = input.charAt(i);\n if (chr == \"\\n\") {\n col = 0;\n row += 1;\n } else {\n col += 1;\n if (col > maxCols) {\n col = 0;\n row += 1;\n }\n }\n }\n\n return { row, col };\n}\n\n/**\n * Counts the lines in the given input\n */\nexport function countLines(input, maxCols) {\n return offsetToColRow(input, input.length, maxCols).row + 1;\n}\n\n/**\n * Checks if there is an incomplete input\n *\n * An incomplete input is considered:\n * - An input that contains unterminated single quotes\n * - An input that contains unterminated double quotes\n * - An input that ends with \"\\\"\n * - An input that has an incomplete boolean shell expression (&& and ||)\n * - An incomplete pipe expression (|)\n */\nexport function isIncompleteInput(input) {\n // Empty input is not incomplete\n if (input.trim() == \"\") {\n return false;\n }\n\n // Check for dangling single-quote strings\n if ((input.match(/'/g) || []).length % 2 !== 0) {\n return true;\n }\n // Check for dangling double-quote strings\n if ((input.match(/\"/g) || []).length % 2 !== 0) {\n return true;\n }\n // Check for dangling boolean or pipe operations\n if (\n input\n .split(/(\\|\\||\\||&&)/g)\n .pop()\n .trim() == \"\"\n ) {\n return true;\n }\n // Check for tailing slash\n if (input.endsWith(\"\\\\\") && !input.endsWith(\"\\\\\\\\\")) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns true if the expression ends on a tailing whitespace\n */\nexport function hasTailingWhitespace(input) {\n return input.match(/[^\\\\][ \\t]$/m) != null;\n}\n\n/**\n * Returns the last expression in the given input\n */\nexport function getLastToken(input) {\n // Empty expressions\n if (input.trim() === \"\") return \"\";\n if (hasTailingWhitespace(input)) return \"\";\n\n // Last token\n const tokens = parse(input);\n return tokens.pop() || \"\";\n}\n\n/**\n * Returns the auto-complete candidates for the given input\n */\nexport function collectAutocompleteCandidates(callbacks, input) {\n const tokens = parse(input);\n let index = tokens.length - 1;\n let expr = tokens[index] || \"\";\n\n // Empty expressions\n if (input.trim() === \"\") {\n index = 0;\n expr = \"\";\n } else if (hasTailingWhitespace(input)) {\n // Expressions with danging space\n index += 1;\n expr = \"\";\n }\n\n // Collect all auto-complete candidates from the callbacks\n const all = callbacks.reduce((candidates, { fn, args }) => {\n try {\n return candidates.concat(fn(index, tokens, ...args));\n } catch (e) {\n console.error(\"Auto-complete error:\", e);\n return candidates;\n }\n }, []);\n\n // Filter only the ones starting with the expression\n return all.filter(txt => txt.startsWith(expr));\n}\n","import { HistoryController } from \"./HistoryController\";\nimport {\n closestLeftBoundary,\n closestRightBoundary,\n collectAutocompleteCandidates,\n countLines,\n getLastToken,\n hasTailingWhitespace,\n isIncompleteInput,\n offsetToColRow\n} from \"./Utils\";\n\n/**\n * A local terminal controller is responsible for displaying messages\n * and handling local echo for the terminal.\n *\n * Local echo supports most of bash-like input primitives. Namely:\n * - Arrow navigation on the input\n * - Alt-arrow for word-boundary navigation\n * - Alt-backspace for word-boundary deletion\n * - Multi-line input for incomplete commands\n * - Auto-complete hooks\n */\nexport default class LocalEchoController {\n constructor(term, options = {}) {\n this.term = term;\n this.term.on(\"data\", this.handleTermData.bind(this));\n this.term.on(\"resize\", this.handleTermResize.bind(this));\n this.history = new HistoryController(options.historySize || 10);\n this.maxAutocompleteEntries = options.maxAutocompleteEntries || 100;\n\n this._autocompleteHandlers = [];\n this._active = false;\n this._input = \"\";\n this._cursor = 0;\n this._activePrompt = null;\n this._activeCharPrompt = null;\n this._termSize = {\n cols: this.term.cols,\n rows: this.term.rows\n };\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // User-Facing API\n /////////////////////////////////////////////////////////////////////////////\n\n /**\n * Register a handler that will be called to satisfy auto-completion\n */\n addAutocompleteHandler(fn, ...args) {\n this._autocompleteHandlers.push({\n fn,\n args\n });\n }\n\n /**\n * Remove a previously registered auto-complete handler\n */\n removeAutocompleteHandler(fn) {\n const idx = this._autocompleteHandlers.findIndex(e => e.fn === fn);\n if (idx === -1) return;\n\n this._autocompleteHandlers.splice(idx, 1);\n }\n\n /**\n * Return a promise that will resolve when the user has completed\n * typing a single line\n */\n read(prompt, continuationPrompt = \"> \") {\n return new Promise((resolve, reject) => {\n this.term.write(prompt);\n this._activePrompt = {\n prompt,\n continuationPrompt,\n resolve,\n reject\n };\n\n this._input = \"\";\n this._cursor = 0;\n this._active = true;\n });\n }\n\n /**\n * Return a promise that will be resolved when the user types a single\n * character.\n *\n * This can be active in addition to `.read()` and will be resolved in\n * priority before it.\n */\n readChar(prompt) {\n return new Promise((resolve, reject) => {\n this.term.write(prompt);\n this._activeCharPrompt = {\n prompt,\n resolve,\n reject\n };\n });\n }\n\n /**\n * Abort a pending read operation\n */\n abortRead(reason = \"aborted\") {\n if (this._activePrompt != null || this._activeCharPrompt != null) {\n this.term.write(\"\\r\\n\");\n }\n if (this._activePrompt != null) {\n this._activePrompt.reject(reason);\n this._activePrompt = null;\n }\n if (this._activeCharPrompt != null) {\n this._activeCharPrompt.reject(reason);\n this._activeCharPrompt = null;\n }\n this._active = false;\n }\n\n /**\n * Prints a message and changes line\n */\n println(message) {\n this.print(message + \"\\n\");\n }\n\n /**\n * Prints a message and properly handles new-lines\n */\n print(message) {\n const normInput = message.replace(/[\\r\\n]+/g, \"\\n\");\n this.term.write(normInput.replace(/\\n/g, \"\\r\\n\"));\n }\n\n /**\n * Prints a list of items using a wide-format\n */\n printWide(items, padding = 2) {\n if (items.length == 0) return println(\"\");\n\n // Compute item sizes and matrix row/cols\n const itemWidth =\n items.reduce((width, item) => Math.max(width, item.length), 0) + padding;\n const wideCols = Math.floor(this._termSize.cols / itemWidth);\n const wideRows = Math.ceil(items.length / wideCols);\n\n // Print matrix\n let i = 0;\n for (let row = 0; row < wideRows; ++row) {\n let rowStr = \"\";\n\n // Prepare columns\n for (let col = 0; col < wideCols; ++col) {\n if (i < items.length) {\n let item = items[i++];\n item += \" \".repeat(itemWidth - item.length);\n rowStr += item;\n }\n }\n this.println(rowStr);\n }\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Internal API\n /////////////////////////////////////////////////////////////////////////////\n\n /**\n * Apply prompts to the given input\n */\n applyPrompts(input) {\n const prompt = (this._activePrompt || {}).prompt || \"\";\n const continuationPrompt =\n (this._activePrompt || {}).continuationPrompt || \"\";\n\n return prompt + input.replace(/\\n/g, \"\\n\" + continuationPrompt);\n }\n\n /**\n * Advances the `offset` as required in order to accompany the prompt\n * additions to the input.\n */\n applyPromptOffset(input, offset) {\n const newInput = this.applyPrompts(input.substr(0, offset));\n return newInput.length;\n }\n\n /**\n * Clears the current prompt\n *\n * This function will erase all the lines that display the current prompt\n * and move the cursor in the beginning of the first line of the prompt.\n */\n clearInput() {\n const currentPrompt = this.applyPrompts(this._input);\n\n // Get the overall number of lines to clear\n const allRows = countLines(currentPrompt, this._termSize.cols);\n\n // Get the line we are currently in\n const promptCursor = this.applyPromptOffset(this._input, this._cursor);\n const { col, row } = offsetToColRow(\n currentPrompt,\n promptCursor,\n this._termSize.cols\n );\n\n // First move on the last line\n const moveRows = allRows - row - 1;\n for (var i = 0; i < moveRows; ++i) term.write(\"\\x1B[E\");\n\n // Clear current input line(s)\n term.write(\"\\r\\x1B[K\");\n for (var i = 1; i < allRows; ++i) term.write(\"\\x1B[F\\x1B[K\");\n }\n\n /**\n * Replace input with the new input given\n *\n * This function clears all the lines that the current input occupies and\n * then replaces them with the new input.\n */\n setInput(newInput, clearInput = true) {\n // Clear current input\n if (clearInput) this.clearInput();\n\n // Write the new input lines, including the current prompt\n const newPrompt = this.applyPrompts(newInput);\n this.print(newPrompt);\n\n // Trim cursor overflow\n if (this._cursor > newInput.length) {\n this._cursor = newInput.length;\n }\n\n // Move the cursor to the appropriate row/col\n const newCursor = this.applyPromptOffset(newInput, this._cursor);\n const newLines = countLines(newPrompt, this._termSize.cols);\n const { col, row } = offsetToColRow(\n newPrompt,\n newCursor,\n this._termSize.cols\n );\n const moveUpRows = newLines - row - 1;\n\n term.write(\"\\r\");\n for (var i = 0; i < moveUpRows; ++i) term.write(\"\\x1B[F\");\n for (var i = 0; i < col; ++i) this.term.write(\"\\x1B[C\");\n\n // Replace input\n this._input = newInput;\n }\n\n /**\n * This function completes the current input, calls the given callback\n * and then re-displays the prompt.\n */\n printAndRestartPrompt(callback) {\n const cursor = this._cursor;\n\n // Complete input\n this.setCursor(this._input.length);\n this.term.write(\"\\r\\n\");\n\n // Prepare a function that will resume prompt\n const resume = () => {\n this._cursor = cursor;\n this.setInput(this._input);\n };\n\n // Call the given callback to echo something, and if there is a promise\n // returned, wait for the resolution before resuming prompt.\n const ret = callback();\n if (ret == null) {\n resume();\n } else {\n ret.then(resume);\n }\n }\n\n /**\n * Set the new cursor position, as an offset on the input string\n *\n * This function:\n * - Calculates the previous and current\n */\n setCursor(newCursor) {\n if (newCursor < 0) newCursor = 0;\n if (newCursor > this._input.length) newCursor = this._input.length;\n\n // Apply prompt formatting to get the visual status of the display\n const inputWithPrompt = this.applyPrompts(this._input);\n const inputLines = countLines(inputWithPrompt, this._termSize.cols);\n\n // Estimate previous cursor position\n const prevPromptOffset = this.applyPromptOffset(this._input, this._cursor);\n const { col: prevCol, row: prevRow } = offsetToColRow(\n inputWithPrompt,\n prevPromptOffset,\n this._termSize.cols\n );\n\n // Estimate next cursor position\n const newPromptOffset = this.applyPromptOffset(this._input, newCursor);\n const { col: newCol, row: newRow } = offsetToColRow(\n inputWithPrompt,\n newPromptOffset,\n this._termSize.cols\n );\n\n // Adjust vertically\n if (newRow > prevRow) {\n for (let i = prevRow; i < newRow; ++i) term.write(\"\\x1B[B\");\n } else {\n for (let i = newRow; i < prevRow; ++i) term.write(\"\\x1B[A\");\n }\n\n // Adjust horizontally\n if (newCol > prevCol) {\n for (let i = prevCol; i < newCol; ++i) term.write(\"\\x1B[C\");\n } else {\n for (let i = newCol; i < prevCol; ++i) term.write(\"\\x1B[D\");\n }\n\n // Set new offset\n this._cursor = newCursor;\n }\n\n /**\n * Move cursor at given direction\n */\n handleCursorMove(dir) {\n if (dir > 0) {\n const num = Math.min(dir, this._input.length - this._cursor);\n this.setCursor(this._cursor + num);\n } else if (dir < 0) {\n const num = Math.max(dir, -this._cursor);\n this.setCursor(this._cursor + num);\n }\n }\n\n /**\n * Erase a character at cursor location\n */\n handleCursorErase(backspace) {\n const { _cursor, _input } = this;\n if (backspace) {\n if (_cursor <= 0) return;\n const newInput = _input.substr(0, _cursor - 1) + _input.substr(_cursor);\n this.clearInput();\n this._cursor -= 1;\n this.setInput(newInput, false);\n } else {\n const newInput = _input.substr(0, _cursor) + _input.substr(_cursor + 1);\n this.setInput(newInput);\n }\n }\n\n /**\n * Insert character at cursor location\n */\n handleCursorInsert(data) {\n const { _cursor, _input } = this;\n const newInput = _input.substr(0, _cursor) + data + _input.substr(_cursor);\n this._cursor += data.length;\n this.setInput(newInput);\n }\n\n /**\n * Handle input completion\n */\n handleReadComplete() {\n if (this.history) {\n this.history.push(this._input);\n }\n if (this._activePrompt) {\n this._activePrompt.resolve(this._input);\n this._activePrompt = null;\n }\n this.term.write(\"\\r\\n\");\n this._active = false;\n }\n\n /**\n * Handle terminal resize\n *\n * This function clears the prompt using the previous configuration,\n * updates the cached terminal size information and then re-renders the\n * input. This leads (most of the times) into a better formatted input.\n */\n handleTermResize(data) {\n const { rows, cols } = data;\n this.clearInput();\n this._termSize = { cols, rows };\n this.setInput(this._input, false);\n }\n\n /**\n * Handle terminal input\n */\n handleTermData(data) {\n if (!this._active) return;\n\n // If we have an active character prompt, satisfy it in priority\n if (this._activeCharPrompt != null) {\n this._activeCharPrompt.resolve(data);\n this._activeCharPrompt = null;\n this.term.write(\"\\r\\n\");\n return;\n }\n\n // If this looks like a pasted input, expand it\n if (data.length > 3 && data.charCodeAt(0) !== 0x1b) {\n const normData = data.replace(/[\\r\\n]+/g, \"\\r\");\n Array.from(normData).forEach(c => this.handleData(c));\n } else {\n this.handleData(data);\n }\n }\n\n /**\n * Handle a single piece of information from the terminal.\n */\n handleData(data) {\n if (!this._active) return;\n const ord = data.charCodeAt(0);\n let ofs;\n\n // Handle ANSI escape sequences\n if (ord == 0x1b) {\n switch (data.substr(1)) {\n case \"[A\": // Up arrow\n if (this.history) {\n let value = this.history.getPrevious();\n if (value) {\n this.setInput(value);\n this.setCursor(value.length);\n }\n }\n break;\n\n case \"[B\": // Down arrow\n if (this.history) {\n let value = this.history.getNext();\n if (!value) value = \"\";\n this.setInput(value);\n this.setCursor(value.length);\n }\n break;\n\n case \"[D\": // Left Arrow\n this.handleCursorMove(-1);\n break;\n\n case \"[C\": // Right Arrow\n this.handleCursorMove(1);\n break;\n\n case \"[3~\": // Delete\n this.handleCursorErase(false);\n break;\n\n case \"[F\": // End\n this.setCursor(this._input.length);\n break;\n\n case \"[H\": // Home\n this.setCursor(0);\n break;\n\n case \"b\": // ALT + LEFT\n ofs = closestLeftBoundary(this._input, this._cursor);\n if (ofs != null) this.setCursor(ofs);\n break;\n\n case \"f\": // ALT + RIGHT\n ofs = closestRightBoundary(this._input, this._cursor);\n if (ofs != null) this.setCursor(ofs);\n break;\n\n case \"\\x7F\": // CTRL + BACKSPACE\n ofs = closestLeftBoundary(this._input, this._cursor);\n if (ofs != null) {\n this.setInput(\n this._input.substr(0, ofs) + this._input.substr(this._cursor)\n );\n this.setCursor(ofs);\n }\n break;\n }\n\n // Handle special characters\n } else if (ord < 32 || ord === 0x7f) {\n switch (data) {\n case \"\\r\": // ENTER\n if (isIncompleteInput(this._input)) {\n this.handleCursorInsert(\"\\n\");\n } else {\n this.handleReadComplete();\n }\n break;\n\n case \"\\x7F\": // BACKSPACE\n this.handleCursorErase(true);\n break;\n\n case \"\\t\": // TAB\n if (this._autocompleteHandlers.length > 0) {\n const inputFragment = this._input.substr(0, this._cursor);\n const hasTailingSpace = hasTailingWhitespace(inputFragment);\n const candidates = collectAutocompleteCandidates(\n this._autocompleteHandlers,\n inputFragment\n );\n\n // Sort candidates\n candidates.sort();\n\n // Depending on the number of candidates, we are handing them in\n // a different way.\n if (candidates.length === 0) {\n // No candidates? Just add a space if there is none already\n if (!hasTailingSpace) {\n this.handleCursorInsert(\" \");\n }\n } else if (candidates.length === 1) {\n // Just a single candidate? Complete\n const lastToken = getLastToken(inputFragment);\n this.handleCursorInsert(\n candidates[0].substr(lastToken.length) + \" \"\n );\n } else if (candidates.length <= this.maxAutocompleteEntries) {\n // If we are less than maximum auto-complete candidates, print\n // them to the user and re-start prompt\n this.printAndRestartPrompt(() => {\n this.printWide(candidates);\n });\n } else {\n // If we have more than maximum auto-complete candidates, print\n // them only if the user acknowledges a warning\n this.printAndRestartPrompt(() =>\n this.readChar(\n `Display all ${candidates.length} possibilities? (y or n)`\n ).then(yn => {\n if (yn == \"y\" || yn == \"Y\") {\n this.printWide(candidates);\n }\n })\n );\n }\n } else {\n this.handleCursorInsert(\" \");\n }\n break;\n\n case \"\\x03\": // CTRL+C\n this.setCursor(this._input.length);\n this.term.write(\"^C\\r\\n\" + ((this._activePrompt || {}).prompt || \"\"));\n this._input = \"\";\n this._cursor = 0;\n if (this.history) this.history.rewind();\n break;\n }\n\n // Handle visible characters\n } else {\n this.handleCursorInsert(data);\n }\n }\n}\n","import LocalEchoController from \"./lib/LocalEchoController\";\nexport { HistoryController } from './lib/HistoryController';\n\nexport default LocalEchoController;\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://LocalEchoController/webpack/bootstrap","webpack://LocalEchoController/./node_modules/.pnpm/shell-quote@1.7.2/node_modules/shell-quote/index.js","webpack://LocalEchoController/./lib/HistoryController.js","webpack://LocalEchoController/./lib/Utils.js","webpack://LocalEchoController/./lib/LocalEchoController.js","webpack://LocalEchoController/./index.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","quote","xs","map","op","replace","test","String","join","CONTROL","TOKEN","Math","pow","random","toString","parse","env","opts","mapped","chunker","RegExp","match","filter","Boolean","commented","j","BS","escape","esc","out","isGlob","len","length","charAt","parseEnvVar","comment","slice","pattern","varend","varname","Error","substr","indexOf","index","_","pre","undefined","JSON","stringify","getVar","reduce","prev","arg","concat","acc","split","x","HistoryController","size","this","entries","cursor","entry","trim","push","shift","idx","max","min","wordBoundaries","input","leftSide","words","rx","exec","closestLeftBoundary","offset","found","reverse","find","offsetToColRow","maxCols","row","col","countLines","hasTailingWhitespace","getLastToken","pop","LocalEchoController","term","options","_handleTermData","handleTermData","_handleTermResize","handleTermResize","history","historySize","maxAutocompleteEntries","_autocompleteHandlers","_active","_input","_cursor","_activePrompt","_activeCharPrompt","_termSize","cols","rows","_disposables","loadAddon","attach","detach","off","forEach","dispose","on","onData","onResize","fn","args","findIndex","e","splice","prompt","continuationPrompt","Promise","resolve","reject","write","reason","message","print","normInput","items","padding","println","itemWidth","width","item","wideCols","floor","wideRows","ceil","rowStr","repeat","applyPrompts","currentPrompt","allRows","applyPromptOffset","moveRows","newInput","clearInput","newPrompt","newCursor","newLines","moveUpRows","callback","setCursor","resume","setInput","ret","then","inputWithPrompt","prevCol","prevRow","newCol","newRow","dir","num","backspace","data","charCodeAt","normData","Array","from","handleData","ofs","ord","getPrevious","getNext","handleCursorMove","handleCursorErase","endsWith","isIncompleteInput","handleReadComplete","handleCursorInsert","inputFragment","hasTailingSpace","candidates","callbacks","tokens","expr","console","error","txt","startsWith","collectAutocompleteCandidates","sort","lastToken","sameFragment","getSharedFragment","fragment","oldFragment","printAndRestartPrompt","printWide","readChar","yn","rewind"],"mappings":"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","file":"local-echo.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","exports.quote = function (xs) {\n return xs.map(function (s) {\n if (s && typeof s === 'object') {\n return s.op.replace(/(.)/g, '\\\\$1');\n }\n else if (/[\"\\s]/.test(s) && !/'/.test(s)) {\n return \"'\" + s.replace(/(['\\\\])/g, '\\\\$1') + \"'\";\n }\n else if (/[\"'\\s]/.test(s)) {\n return '\"' + s.replace(/([\"\\\\$`!])/g, '\\\\$1') + '\"';\n }\n else {\n return String(s).replace(/([A-z]:)?([#!\"$&'()*,:;<=>?@\\[\\\\\\]^`{|}])/g, '$1\\\\$2');\n }\n }).join(' ');\n};\n\n// '<(' is process substitution operator and\n// can be parsed the same as control operator\nvar CONTROL = '(?:' + [\n '\\\\|\\\\|', '\\\\&\\\\&', ';;', '\\\\|\\\\&', '\\\\<\\\\(', '>>', '>\\\\&', '[&;()|<>]'\n].join('|') + ')';\nvar META = '|&;()<> \\\\t';\nvar BAREWORD = '(\\\\\\\\[\\'\"' + META + ']|[^\\\\s\\'\"' + META + '])+';\nvar SINGLE_QUOTE = '\"((\\\\\\\\\"|[^\"])*?)\"';\nvar DOUBLE_QUOTE = '\\'((\\\\\\\\\\'|[^\\'])*?)\\'';\n\nvar TOKEN = '';\nfor (var i = 0; i < 4; i++) {\n TOKEN += (Math.pow(16,8)*Math.random()).toString(16);\n}\n\nexports.parse = function (s, env, opts) {\n var mapped = parse(s, env, opts);\n if (typeof env !== 'function') return mapped;\n return mapped.reduce(function (acc, s) {\n if (typeof s === 'object') return acc.concat(s);\n var xs = s.split(RegExp('(' + TOKEN + '.*?' + TOKEN + ')', 'g'));\n if (xs.length === 1) return acc.concat(xs[0]);\n return acc.concat(xs.filter(Boolean).map(function (x) {\n if (RegExp('^' + TOKEN).test(x)) {\n return JSON.parse(x.split(TOKEN)[1]);\n }\n else return x;\n }));\n }, []);\n};\n\nfunction parse (s, env, opts) {\n var chunker = new RegExp([\n '(' + CONTROL + ')', // control chars\n '(' + BAREWORD + '|' + SINGLE_QUOTE + '|' + DOUBLE_QUOTE + ')*'\n ].join('|'), 'g');\n var match = s.match(chunker).filter(Boolean);\n var commented = false;\n\n if (!match) return [];\n if (!env) env = {};\n if (!opts) opts = {};\n return match.map(function (s, j) {\n if (commented) {\n return;\n }\n if (RegExp('^' + CONTROL + '$').test(s)) {\n return { op: s };\n }\n\n // Hand-written scanner/parser for Bash quoting rules:\n //\n // 1. inside single quotes, all characters are printed literally.\n // 2. inside double quotes, all characters are printed literally\n // except variables prefixed by '$' and backslashes followed by\n // either a double quote or another backslash.\n // 3. outside of any quotes, backslashes are treated as escape\n // characters and not printed (unless they are themselves escaped)\n // 4. quote context can switch mid-token if there is no whitespace\n // between the two quote contexts (e.g. all'one'\"token\" parses as\n // \"allonetoken\")\n var SQ = \"'\";\n var DQ = '\"';\n var DS = '$';\n var BS = opts.escape || '\\\\';\n var quote = false;\n var esc = false;\n var out = '';\n var isGlob = false;\n\n for (var i = 0, len = s.length; i < len; i++) {\n var c = s.charAt(i);\n isGlob = isGlob || (!quote && (c === '*' || c === '?'));\n if (esc) {\n out += c;\n esc = false;\n }\n else if (quote) {\n if (c === quote) {\n quote = false;\n }\n else if (quote == SQ) {\n out += c;\n }\n else { // Double quote\n if (c === BS) {\n i += 1;\n c = s.charAt(i);\n if (c === DQ || c === BS || c === DS) {\n out += c;\n } else {\n out += BS + c;\n }\n }\n else if (c === DS) {\n out += parseEnvVar();\n }\n else {\n out += c;\n }\n }\n }\n else if (c === DQ || c === SQ) {\n quote = c;\n }\n else if (RegExp('^' + CONTROL + '$').test(c)) {\n return { op: s };\n }\n else if (RegExp('^#$').test(c)) {\n commented = true;\n if (out.length){\n return [out, { comment: s.slice(i+1) + match.slice(j+1).join(' ') }];\n }\n return [{ comment: s.slice(i+1) + match.slice(j+1).join(' ') }];\n }\n else if (c === BS) {\n esc = true;\n }\n else if (c === DS) {\n out += parseEnvVar();\n }\n else out += c;\n }\n\n if (isGlob) return {op: 'glob', pattern: out};\n\n return out;\n\n function parseEnvVar() {\n i += 1;\n var varend, varname;\n //debugger\n if (s.charAt(i) === '{') {\n i += 1;\n if (s.charAt(i) === '}') {\n throw new Error(\"Bad substitution: \" + s.substr(i - 2, 3));\n }\n varend = s.indexOf('}', i);\n if (varend < 0) {\n throw new Error(\"Bad substitution: \" + s.substr(i));\n }\n varname = s.substr(i, varend - i);\n i = varend;\n }\n else if (/[*@#?$!_\\-]/.test(s.charAt(i))) {\n varname = s.charAt(i);\n i += 1;\n }\n else {\n varend = s.substr(i).match(/[^\\w\\d_]/);\n if (!varend) {\n varname = s.substr(i);\n i = s.length;\n } else {\n varname = s.substr(i, varend.index);\n i += varend.index - 1;\n }\n }\n return getVar(null, '', varname);\n }\n })\n // finalize parsed aruments\n .reduce(function(prev, arg){\n if (arg === undefined){\n return prev;\n }\n return prev.concat(arg);\n },[]);\n\n function getVar (_, pre, key) {\n var r = typeof env === 'function' ? env(key) : env[key];\n if (r === undefined && key != '')\n r = '';\n else if (r === undefined)\n r = '$';\n\n if (typeof r === 'object') {\n return pre + TOKEN + JSON.stringify(r) + TOKEN;\n }\n else return pre + r;\n }\n}\n","/**\n * The history controller provides an ring-buffer\n */\nexport class HistoryController {\n constructor(size) {\n this.size = size;\n this.entries = [];\n this.cursor = 0;\n }\n\n /**\n * Push an entry and maintain ring buffer size\n */\n push(entry) {\n // Skip empty entries\n if (entry.trim() === \"\") return;\n // Skip duplicate entries\n const lastEntry = this.entries[this.entries.length - 1];\n if (entry == lastEntry) return;\n // Keep track of entries\n this.entries.push(entry);\n if (this.entries.length > this.size) {\n this.entries.shift();\n }\n this.cursor = this.entries.length;\n }\n\n /**\n * Rewind history cursor on the last entry\n */\n rewind() {\n this.cursor = this.entries.length;\n }\n\n /**\n * Returns the previous entry\n */\n getPrevious() {\n const idx = Math.max(0, this.cursor - 1);\n this.cursor = idx;\n return this.entries[idx];\n }\n\n /**\n * Returns the next entry\n */\n getNext() {\n const idx = Math.min(this.entries.length, this.cursor + 1);\n this.cursor = idx;\n return this.entries[idx];\n }\n}\n","import { parse } from \"shell-quote\";\n\n/**\n * Detects all the word boundaries on the given input\n */\nexport function wordBoundaries(input, leftSide = true) {\n let match;\n const words = [];\n const rx = /\\w+/g;\n\n while ((match = rx.exec(input))) {\n if (leftSide) {\n words.push(match.index);\n } else {\n words.push(match.index + match[0].length);\n }\n }\n\n return words;\n}\n\n/**\n * The closest left (or right) word boundary of the given input at the\n * given offset.\n */\nexport function closestLeftBoundary(input, offset) {\n const found = wordBoundaries(input, true)\n .reverse()\n .find(x => x < offset);\n return found == null ? 0 : found;\n}\nexport function closestRightBoundary(input, offset) {\n const found = wordBoundaries(input, false).find(x => x > offset);\n return found == null ? input.length : found;\n}\n\n/**\n * Convert offset at the given input to col/row location\n *\n * This function is not optimized and practically emulates via brute-force\n * the navigation on the terminal, wrapping when they reach the column width.\n */\nexport function offsetToColRow(input, offset, maxCols) {\n let row = 0,\n col = 0;\n\n for (let i = 0; i < offset; ++i) {\n const chr = input.charAt(i);\n if (chr == \"\\n\") {\n col = 0;\n row += 1;\n } else {\n col += 1;\n if (col > maxCols) {\n col = 0;\n row += 1;\n }\n }\n }\n\n return { row, col };\n}\n\n/**\n * Counts the lines in the given input\n */\nexport function countLines(input, maxCols) {\n return offsetToColRow(input, input.length, maxCols).row + 1;\n}\n\n/**\n * Checks if there is an incomplete input\n *\n * An incomplete input is considered:\n * - An input that contains unterminated single quotes\n * - An input that contains unterminated double quotes\n * - An input that ends with \"\\\"\n * - An input that has an incomplete boolean shell expression (&& and ||)\n * - An incomplete pipe expression (|)\n */\nexport function isIncompleteInput(input) {\n // Empty input is not incomplete\n if (input.trim() == \"\") {\n return false;\n }\n\n // Check for dangling single-quote strings\n if ((input.match(/'/g) || []).length % 2 !== 0) {\n return true;\n }\n // Check for dangling double-quote strings\n if ((input.match(/\"/g) || []).length % 2 !== 0) {\n return true;\n }\n // Check for dangling boolean or pipe operations\n if (\n input\n .split(/(\\|\\||\\||&&)/g)\n .pop()\n .trim() == \"\"\n ) {\n return true;\n }\n // Check for tailing slash\n if (input.endsWith(\"\\\\\") && !input.endsWith(\"\\\\\\\\\")) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns true if the expression ends on a tailing whitespace\n */\nexport function hasTailingWhitespace(input) {\n return input.match(/[^\\\\][ \\t]$/m) != null;\n}\n\n/**\n * Returns the last expression in the given input\n */\nexport function getLastToken(input) {\n // Empty expressions\n if (input.trim() === \"\") return \"\";\n if (hasTailingWhitespace(input)) return \"\";\n\n // Last token\n const tokens = parse(input);\n return tokens.pop() || \"\";\n}\n\n/**\n * Returns the auto-complete candidates for the given input\n */\nexport function collectAutocompleteCandidates(callbacks, input) {\n const tokens = parse(input);\n let index = tokens.length - 1;\n let expr = tokens[index] || \"\";\n\n // Empty expressions\n if (input.trim() === \"\") {\n index = 0;\n expr = \"\";\n } else if (hasTailingWhitespace(input)) {\n // Expressions with danging space\n index += 1;\n expr = \"\";\n }\n\n // Collect all auto-complete candidates from the callbacks\n const all = callbacks.reduce((candidates, { fn, args }) => {\n try {\n return candidates.concat(fn(index, tokens, ...args));\n } catch (e) {\n console.error(\"Auto-complete error:\", e);\n return candidates;\n }\n }, []);\n\n // Filter only the ones starting with the expression\n return all.filter(txt => txt.startsWith(expr));\n}\n\n\nexport function getSharedFragment(fragment, candidates) {\n\n // end loop when fragment length = first candidate length\n if (fragment.length >= candidates[0].length) return fragment;\n \n // save old fragemnt\n const oldFragment = fragment;\n \n // get new fragment\n fragment += candidates[0].slice(fragment.length, fragment.length+1);\n\n for (let i=0; i d.dispose());\n this._disposables = [];\n }\n }\n \n /**\n * Attach controller to the terminal, handling events\n */\n attach() {\n if (this.term.on) {\n this.term.on(\"data\", this._handleTermData);\n this.term.on(\"resize\", this._handleTermResize);\n } else {\n this._disposables.push(this.term.onData(this._handleTermData));\n this._disposables.push(this.term.onResize(this._handleTermResize));\n }\n this._termSize = {\n cols: this.term.cols,\n rows: this.term.rows,\n };\n }\n\n /**\n * Register a handler that will be called to satisfy auto-completion\n */\n addAutocompleteHandler(fn, ...args) {\n this._autocompleteHandlers.push({\n fn,\n args\n });\n }\n\n /**\n * Remove a previously registered auto-complete handler\n */\n removeAutocompleteHandler(fn) {\n const idx = this._autocompleteHandlers.findIndex(e => e.fn === fn);\n if (idx === -1) return;\n\n this._autocompleteHandlers.splice(idx, 1);\n }\n\n /**\n * Return a promise that will resolve when the user has completed\n * typing a single line\n */\n read(prompt, continuationPrompt = \"> \") {\n return new Promise((resolve, reject) => {\n this.term.write(prompt);\n this._activePrompt = {\n prompt,\n continuationPrompt,\n resolve,\n reject\n };\n\n this._input = \"\";\n this._cursor = 0;\n this._active = true;\n });\n }\n\n /**\n * Return a promise that will be resolved when the user types a single\n * character.\n *\n * This can be active in addition to `.read()` and will be resolved in\n * priority before it.\n */\n readChar(prompt) {\n return new Promise((resolve, reject) => {\n this.term.write(prompt);\n this._activeCharPrompt = {\n prompt,\n resolve,\n reject\n };\n });\n }\n\n /**\n * Abort a pending read operation\n */\n abortRead(reason = \"aborted\") {\n if (this._activePrompt != null || this._activeCharPrompt != null) {\n this.term.write(\"\\r\\n\");\n }\n if (this._activePrompt != null) {\n this._activePrompt.reject(reason);\n this._activePrompt = null;\n }\n if (this._activeCharPrompt != null) {\n this._activeCharPrompt.reject(reason);\n this._activeCharPrompt = null;\n }\n this._active = false;\n }\n\n /**\n * Prints a message and changes line\n */\n println(message) {\n this.print(message + \"\\n\");\n }\n\n /**\n * Prints a message and properly handles new-lines\n */\n print(message) {\n const normInput = message.replace(/[\\r\\n]+/g, \"\\n\");\n this.term.write(normInput.replace(/\\n/g, \"\\r\\n\"));\n }\n\n /**\n * Prints a list of items using a wide-format\n */\n printWide(items, padding = 2) {\n if (items.length == 0) return println(\"\");\n\n // Compute item sizes and matrix row/cols\n const itemWidth =\n items.reduce((width, item) => Math.max(width, item.length), 0) + padding;\n const wideCols = Math.floor(this._termSize.cols / itemWidth);\n const wideRows = Math.ceil(items.length / wideCols);\n\n // Print matrix\n let i = 0;\n for (let row = 0; row < wideRows; ++row) {\n let rowStr = \"\";\n\n // Prepare columns\n for (let col = 0; col < wideCols; ++col) {\n if (i < items.length) {\n let item = items[i++];\n item += \" \".repeat(itemWidth - item.length);\n rowStr += item;\n }\n }\n this.println(rowStr);\n }\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Internal API\n /////////////////////////////////////////////////////////////////////////////\n\n /**\n * Apply prompts to the given input\n */\n applyPrompts(input) {\n const prompt = (this._activePrompt || {}).prompt || \"\";\n const continuationPrompt =\n (this._activePrompt || {}).continuationPrompt || \"\";\n\n return prompt + input.replace(/\\n/g, \"\\n\" + continuationPrompt);\n }\n\n /**\n * Advances the `offset` as required in order to accompany the prompt\n * additions to the input.\n */\n applyPromptOffset(input, offset) {\n const newInput = this.applyPrompts(input.substr(0, offset));\n return newInput.length;\n }\n\n /**\n * Clears the current prompt\n *\n * This function will erase all the lines that display the current prompt\n * and move the cursor in the beginning of the first line of the prompt.\n */\n clearInput() {\n const currentPrompt = this.applyPrompts(this._input);\n\n // Get the overall number of lines to clear\n const allRows = countLines(currentPrompt, this._termSize.cols);\n\n // Get the line we are currently in\n const promptCursor = this.applyPromptOffset(this._input, this._cursor);\n const { col, row } = offsetToColRow(\n currentPrompt,\n promptCursor,\n this._termSize.cols\n );\n\n // First move on the last line\n const moveRows = allRows - row - 1;\n for (var i = 0; i < moveRows; ++i) this.term.write(\"\\x1B[E\");\n\n // Clear current input line(s)\n this.term.write(\"\\r\\x1B[K\");\n for (var i = 1; i < allRows; ++i) this.term.write(\"\\x1B[F\\x1B[K\");\n }\n\n /**\n * Replace input with the new input given\n *\n * This function clears all the lines that the current input occupies and\n * then replaces them with the new input.\n */\n setInput(newInput, clearInput = true) {\n // Clear current input\n if (clearInput) this.clearInput();\n\n // Write the new input lines, including the current prompt\n const newPrompt = this.applyPrompts(newInput);\n this.print(newPrompt);\n\n // Trim cursor overflow\n if (this._cursor > newInput.length) {\n this._cursor = newInput.length;\n }\n\n // Move the cursor to the appropriate row/col\n const newCursor = this.applyPromptOffset(newInput, this._cursor);\n const newLines = countLines(newPrompt, this._termSize.cols);\n const { col, row } = offsetToColRow(\n newPrompt,\n newCursor,\n this._termSize.cols\n );\n const moveUpRows = newLines - row - 1;\n\n this.term.write(\"\\r\");\n for (var i = 0; i < moveUpRows; ++i) this.term.write(\"\\x1B[F\");\n for (var i = 0; i < col; ++i) this.term.write(\"\\x1B[C\");\n\n // Replace input\n this._input = newInput;\n }\n\n /**\n * This function completes the current input, calls the given callback\n * and then re-displays the prompt.\n */\n printAndRestartPrompt(callback) {\n const cursor = this._cursor;\n\n // Complete input\n this.setCursor(this._input.length);\n this.term.write(\"\\r\\n\");\n\n // Prepare a function that will resume prompt\n const resume = () => {\n this._cursor = cursor;\n this.setInput(this._input);\n };\n\n // Call the given callback to echo something, and if there is a promise\n // returned, wait for the resolution before resuming prompt.\n const ret = callback();\n if (ret == null) {\n resume();\n } else {\n ret.then(resume);\n }\n }\n\n /**\n * Set the new cursor position, as an offset on the input string\n *\n * This function:\n * - Calculates the previous and current\n */\n setCursor(newCursor) {\n if (newCursor < 0) newCursor = 0;\n if (newCursor > this._input.length) newCursor = this._input.length;\n\n // Apply prompt formatting to get the visual status of the display\n const inputWithPrompt = this.applyPrompts(this._input);\n const inputLines = countLines(inputWithPrompt, this._termSize.cols);\n\n // Estimate previous cursor position\n const prevPromptOffset = this.applyPromptOffset(this._input, this._cursor);\n const { col: prevCol, row: prevRow } = offsetToColRow(\n inputWithPrompt,\n prevPromptOffset,\n this._termSize.cols\n );\n\n // Estimate next cursor position\n const newPromptOffset = this.applyPromptOffset(this._input, newCursor);\n const { col: newCol, row: newRow } = offsetToColRow(\n inputWithPrompt,\n newPromptOffset,\n this._termSize.cols\n );\n\n // Adjust vertically\n if (newRow > prevRow) {\n for (let i = prevRow; i < newRow; ++i) this.term.write(\"\\x1B[B\");\n } else {\n for (let i = newRow; i < prevRow; ++i) this.term.write(\"\\x1B[A\");\n }\n\n // Adjust horizontally\n if (newCol > prevCol) {\n for (let i = prevCol; i < newCol; ++i) this.term.write(\"\\x1B[C\");\n } else {\n for (let i = newCol; i < prevCol; ++i) this.term.write(\"\\x1B[D\");\n }\n\n // Set new offset\n this._cursor = newCursor;\n }\n\n /**\n * Move cursor at given direction\n */\n handleCursorMove(dir) {\n if (dir > 0) {\n const num = Math.min(dir, this._input.length - this._cursor);\n this.setCursor(this._cursor + num);\n } else if (dir < 0) {\n const num = Math.max(dir, -this._cursor);\n this.setCursor(this._cursor + num);\n }\n }\n\n /**\n * Erase a character at cursor location\n */\n handleCursorErase(backspace) {\n const { _cursor, _input } = this;\n if (backspace) {\n if (_cursor <= 0) return;\n const newInput = _input.substr(0, _cursor - 1) + _input.substr(_cursor);\n this.clearInput();\n this._cursor -= 1;\n this.setInput(newInput, false);\n } else {\n const newInput = _input.substr(0, _cursor) + _input.substr(_cursor + 1);\n this.setInput(newInput);\n }\n }\n\n /**\n * Insert character at cursor location\n */\n handleCursorInsert(data) {\n const { _cursor, _input } = this;\n const newInput = _input.substr(0, _cursor) + data + _input.substr(_cursor);\n this._cursor += data.length;\n this.setInput(newInput);\n }\n\n /**\n * Handle input completion\n */\n handleReadComplete() {\n if (this.history) {\n this.history.push(this._input);\n }\n if (this._activePrompt) {\n this._activePrompt.resolve(this._input);\n this._activePrompt = null;\n }\n this.term.write(\"\\r\\n\");\n this._active = false;\n }\n\n /**\n * Handle terminal resize\n *\n * This function clears the prompt using the previous configuration,\n * updates the cached terminal size information and then re-renders the\n * input. This leads (most of the times) into a better formatted input.\n */\n handleTermResize(data) {\n const { rows, cols } = data;\n this.clearInput();\n this._termSize = { cols, rows };\n this.setInput(this._input, false);\n }\n\n /**\n * Handle terminal input\n */\n handleTermData(data) {\n if (!this._active) return;\n\n // If we have an active character prompt, satisfy it in priority\n if (this._activeCharPrompt != null) {\n this._activeCharPrompt.resolve(data);\n this._activeCharPrompt = null;\n this.term.write(\"\\r\\n\");\n return;\n }\n\n // If this looks like a pasted input, expand it\n if (data.length > 3 && data.charCodeAt(0) !== 0x1b) {\n const normData = data.replace(/[\\r\\n]+/g, \"\\r\");\n Array.from(normData).forEach(c => this.handleData(c));\n } else {\n this.handleData(data);\n }\n }\n\n /**\n * Handle a single piece of information from the terminal.\n */\n handleData(data) {\n if (!this._active) return;\n const ord = data.charCodeAt(0);\n let ofs;\n\n // Handle ANSI escape sequences\n if (ord == 0x1b) {\n switch (data.substr(1)) {\n case \"[A\": // Up arrow\n if (this.history) {\n let value = this.history.getPrevious();\n if (value) {\n this.setInput(value);\n this.setCursor(value.length);\n }\n }\n break;\n\n case \"[B\": // Down arrow\n if (this.history) {\n let value = this.history.getNext();\n if (!value) value = \"\";\n this.setInput(value);\n this.setCursor(value.length);\n }\n break;\n\n case \"[D\": // Left Arrow\n this.handleCursorMove(-1);\n break;\n\n case \"[C\": // Right Arrow\n this.handleCursorMove(1);\n break;\n\n case \"[3~\": // Delete\n this.handleCursorErase(false);\n break;\n\n case \"[F\": // End\n this.setCursor(this._input.length);\n break;\n\n case \"[H\": // Home\n this.setCursor(0);\n break;\n\n case \"b\": // ALT + LEFT\n ofs = closestLeftBoundary(this._input, this._cursor);\n if (ofs != null) this.setCursor(ofs);\n break;\n\n case \"f\": // ALT + RIGHT\n ofs = closestRightBoundary(this._input, this._cursor);\n if (ofs != null) this.setCursor(ofs);\n break;\n\n case \"\\x7F\": // CTRL + BACKSPACE\n ofs = closestLeftBoundary(this._input, this._cursor);\n if (ofs != null) {\n this.setInput(\n this._input.substr(0, ofs) + this._input.substr(this._cursor)\n );\n this.setCursor(ofs);\n }\n break;\n }\n\n // Handle special characters\n } else if (ord < 32 || ord === 0x7f) {\n switch (data) {\n case \"\\r\": // ENTER\n if (isIncompleteInput(this._input)) {\n this.handleCursorInsert(\"\\n\");\n } else {\n this.handleReadComplete();\n }\n break;\n\n case \"\\x7F\": // BACKSPACE\n this.handleCursorErase(true);\n break;\n\n case \"\\t\": // TAB\n if (this._autocompleteHandlers.length > 0) {\n const inputFragment = this._input.substr(0, this._cursor);\n const hasTailingSpace = hasTailingWhitespace(inputFragment);\n const candidates = collectAutocompleteCandidates(\n this._autocompleteHandlers,\n inputFragment\n );\n\n // Sort candidates\n candidates.sort();\n\n // Depending on the number of candidates, we are handing them in\n // a different way.\n if (candidates.length === 0) {\n // No candidates? Just add a space if there is none already\n if (!hasTailingSpace) {\n this.handleCursorInsert(\" \");\n }\n } else if (candidates.length === 1) {\n // Just a single candidate? Complete\n const lastToken = getLastToken(inputFragment);\n this.handleCursorInsert(\n candidates[0].substr(lastToken.length) + \" \"\n );\n } else if (candidates.length <= this.maxAutocompleteEntries) {\n\n // search for a shared fragement\n const sameFragment = getSharedFragment(inputFragment, candidates);\n \n // if there's a shared fragement between the candidates\n // print complete the shared fragment\n if (sameFragment) {\n const lastToken = getLastToken(inputFragment);\n this.handleCursorInsert(\n sameFragment.substr(lastToken.length)\n );\n }\n\n // If we are less than maximum auto-complete candidates, print\n // them to the user and re-start prompt\n this.printAndRestartPrompt(() => {\n this.printWide(candidates);\n });\n } else {\n // If we have more than maximum auto-complete candidates, print\n // them only if the user acknowledges a warning\n this.printAndRestartPrompt(() =>\n this.readChar(\n `Display all ${candidates.length} possibilities? (y or n)`\n ).then(yn => {\n if (yn == \"y\" || yn == \"Y\") {\n this.printWide(candidates);\n }\n })\n );\n }\n } else {\n this.handleCursorInsert(\" \");\n }\n break;\n\n case \"\\x03\": // CTRL+C\n this.setCursor(this._input.length);\n this.term.write(\"^C\\r\\n\" + ((this._activePrompt || {}).prompt || \"\"));\n this._input = \"\";\n this._cursor = 0;\n if (this.history) this.history.rewind();\n break;\n }\n\n // Handle visible characters\n } else {\n this.handleCursorInsert(data);\n }\n }\n}\n","import LocalEchoController from \"./lib/LocalEchoController\";\nexport { HistoryController } from './lib/HistoryController';\n\nexport default LocalEchoController;\n"],"sourceRoot":""} \ No newline at end of file diff --git a/lib/HistoryController.js b/lib/HistoryController.js index 0a3c6d7..fdf5d03 100644 --- a/lib/HistoryController.js +++ b/lib/HistoryController.js @@ -20,7 +20,7 @@ export class HistoryController { // Keep track of entries this.entries.push(entry); if (this.entries.length > this.size) { - this.entries.pop(0); + this.entries.shift(); } this.cursor = this.entries.length; }