From 297fb8b2aff546a542cabe284f4923fd54e55191 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 7 Jan 2013 15:40:53 -0800 Subject: [PATCH 01/26] Create gh-pages branch via GitHub --- fonts/OpenSans-Bold-webfont.eot | Bin 0 -> 21190 bytes fonts/OpenSans-Bold-webfont.svg | 146 ++++ fonts/OpenSans-Bold-webfont.ttf | Bin 0 -> 21012 bytes fonts/OpenSans-Bold-webfont.woff | Bin 0 -> 14036 bytes fonts/OpenSans-BoldItalic-webfont.eot | Bin 0 -> 23510 bytes fonts/OpenSans-BoldItalic-webfont.svg | 146 ++++ fonts/OpenSans-BoldItalic-webfont.ttf | Bin 0 -> 23304 bytes fonts/OpenSans-BoldItalic-webfont.woff | Bin 0 -> 15572 bytes fonts/OpenSans-Italic-webfont.eot | Bin 0 -> 23866 bytes fonts/OpenSans-Italic-webfont.svg | 146 ++++ fonts/OpenSans-Italic-webfont.ttf | Bin 0 -> 23680 bytes fonts/OpenSans-Italic-webfont.woff | Bin 0 -> 15836 bytes fonts/OpenSans-Light-webfont.eot | Bin 0 -> 20886 bytes fonts/OpenSans-Light-webfont.svg | 146 ++++ fonts/OpenSans-Light-webfont.ttf | Bin 0 -> 20704 bytes fonts/OpenSans-Light-webfont.woff | Bin 0 -> 13972 bytes fonts/OpenSans-LightItalic-webfont.eot | Bin 0 -> 24074 bytes fonts/OpenSans-LightItalic-webfont.svg | 146 ++++ fonts/OpenSans-LightItalic-webfont.ttf | Bin 0 -> 23864 bytes fonts/OpenSans-LightItalic-webfont.woff | Bin 0 -> 15944 bytes fonts/OpenSans-Regular-webfont.eot | Bin 0 -> 20878 bytes fonts/OpenSans-Regular-webfont.svg | 146 ++++ fonts/OpenSans-Regular-webfont.ttf | Bin 0 -> 20688 bytes fonts/OpenSans-Regular-webfont.woff | Bin 0 -> 13988 bytes fonts/OpenSans-Semibold-webfont.eot | Bin 0 -> 21046 bytes fonts/OpenSans-Semibold-webfont.svg | 146 ++++ fonts/OpenSans-Semibold-webfont.ttf | Bin 0 -> 20852 bytes fonts/OpenSans-Semibold-webfont.woff | Bin 0 -> 14052 bytes fonts/OpenSans-SemiboldItalic-webfont.eot | Bin 0 -> 23882 bytes fonts/OpenSans-SemiboldItalic-webfont.svg | 146 ++++ fonts/OpenSans-SemiboldItalic-webfont.ttf | Bin 0 -> 23660 bytes fonts/OpenSans-SemiboldItalic-webfont.woff | Bin 0 -> 15748 bytes images/bullet.png | Bin 0 -> 1045 bytes images/hr.gif | Bin 0 -> 1121 bytes images/nav-bg.gif | Bin 0 -> 1238 bytes index.html | 128 ++++ javascripts/respond.js | 779 +++++++++++++++++++ params.json | 1 + stylesheets/ie.css | 3 + stylesheets/normalize.css | 459 +++++++++++ stylesheets/pygment_trac.css | 70 ++ stylesheets/styles.css | 851 +++++++++++++++++++++ 42 files changed, 3459 insertions(+) create mode 100644 fonts/OpenSans-Bold-webfont.eot create mode 100644 fonts/OpenSans-Bold-webfont.svg create mode 100644 fonts/OpenSans-Bold-webfont.ttf create mode 100644 fonts/OpenSans-Bold-webfont.woff create mode 100644 fonts/OpenSans-BoldItalic-webfont.eot create mode 100644 fonts/OpenSans-BoldItalic-webfont.svg create mode 100644 fonts/OpenSans-BoldItalic-webfont.ttf create mode 100644 fonts/OpenSans-BoldItalic-webfont.woff create mode 100644 fonts/OpenSans-Italic-webfont.eot create mode 100644 fonts/OpenSans-Italic-webfont.svg create mode 100644 fonts/OpenSans-Italic-webfont.ttf create mode 100644 fonts/OpenSans-Italic-webfont.woff create mode 100644 fonts/OpenSans-Light-webfont.eot create mode 100644 fonts/OpenSans-Light-webfont.svg create mode 100644 fonts/OpenSans-Light-webfont.ttf create mode 100644 fonts/OpenSans-Light-webfont.woff create mode 100644 fonts/OpenSans-LightItalic-webfont.eot create mode 100644 fonts/OpenSans-LightItalic-webfont.svg create mode 100644 fonts/OpenSans-LightItalic-webfont.ttf create mode 100644 fonts/OpenSans-LightItalic-webfont.woff create mode 100644 fonts/OpenSans-Regular-webfont.eot create mode 100644 fonts/OpenSans-Regular-webfont.svg create mode 100644 fonts/OpenSans-Regular-webfont.ttf create mode 100644 fonts/OpenSans-Regular-webfont.woff create mode 100644 fonts/OpenSans-Semibold-webfont.eot create mode 100644 fonts/OpenSans-Semibold-webfont.svg create mode 100644 fonts/OpenSans-Semibold-webfont.ttf create mode 100644 fonts/OpenSans-Semibold-webfont.woff create mode 100644 fonts/OpenSans-SemiboldItalic-webfont.eot create mode 100644 fonts/OpenSans-SemiboldItalic-webfont.svg create mode 100644 fonts/OpenSans-SemiboldItalic-webfont.ttf create mode 100644 fonts/OpenSans-SemiboldItalic-webfont.woff create mode 100644 images/bullet.png create mode 100644 images/hr.gif create mode 100644 images/nav-bg.gif create mode 100644 index.html create mode 100644 javascripts/respond.js create mode 100644 params.json create mode 100644 stylesheets/ie.css create mode 100644 stylesheets/normalize.css create mode 100644 stylesheets/pygment_trac.css create mode 100644 stylesheets/styles.css diff --git a/fonts/OpenSans-Bold-webfont.eot b/fonts/OpenSans-Bold-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..e1c7674430d0dc4eb95a461948412adcd3194385 GIT binary patch literal 21190 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 + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-Bold-webfont.ttf b/fonts/OpenSans-Bold-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2d94f0629db751b8412a814df98fbe82f6fdd1df GIT binary patch literal 21012 zcmbt+3w#vS+4ng!v$NN1_L|M+x|>Z1F$p2Ngft)!5CH>3h!_J#J=fGeE;XnZlwL%?|pyYOPHO@&dhnv zbDr~D{?BukamJVj9|~h5Mobuc^&?OJoiXmh)q;`3FCM{?OvZU{oJTIbtR}v3?rj(1 zd=$>7OrJY-{+TPQ=zJ@-7pLE_IAS+k!x@to6*~~M48v6jwZHx_{GHb@vj?Ni7Z)2=!7QXL43m39emOtZs1I|ll&0TzB zMRUb!oIi{A1+JSned-IJyz>QPWB!WvU2~`2IG=Cizh-Rghqym-{nWWLN^2WIUo(2g z_s*ZUXmP^b=Qv}R?!)=Z^B2yT|7l;})r^h57x&+Vjkv*HxO-kL?O#&2wx;)!#5Zo7 z<+Z(=5!|;?-1l4D$0D9c zZlvH}@9X}c`l=#-=FM<*T~f3)Pi!|zRv5EuT3|2PId zb2BHd(RThnd?_my)oQaloUSZ)w#V!92ZA}F+;CogL19sGBw7+HE$da@yW)b%s_H&9 zeQV>1es%rpf6y>s;Dv(*4{01a>>^0*$WfOxjUF?$`ODQZ|L0?jvKU!#;P31k zX7F14^=E%!U$IVJ#e4BAwnk%B8uO3VE*RIQHQg{#W3eH*np)X5Xrj2bVq)Yk8u$0f zt=4!|gxVEU)II&t&s_4;ZEP7MhyZNt7%*TCg zUHP9+%#TGiOJ$oj;)aRhi-{BQK1)?r`=n}3t

QU1&XWS9^QD#_$?zm0l_?HTGPx zRr$P;hMH>4UKLqEjXaC@M>M(Yl2}AjdNpZmT-(|iYo|u&;0O89=*0ZB;;h9yqXr!& zb)I}r6pc8mB7YX$aaBcXG;3vhTO=|vHe%|WNL!?1n)wR4FN<16(~-52k!wdxjjfHW zjfv)B8f$6O8gVE3N6l)DGw1}*xJ65Y4(CRr`H{nG!3I2Z323`KO&jRLZP`_^$l-M3 zu}ItK%krZdpV+n*9l9j8HWpcX$=cXdqJ+9bpG1#`hQWtn@KOip!1pg50HLuFv8i*W zoZl0A)L(^8tX)HFYwC!twQ7-ZZ5QV6!#9Ddove{J4jaZt@Ak0iOnlPKmxJ=i+LpH1 zG*BNKmX95e4Fl&JTiTK=!Y-OVEXgArJ1sI@3(qJJl;VxSDh*e`7kpHch;qiE4YDy4 z_d_Zj&^I!(vJ0X2Ijc-57UohalU&BJRUC88R->`QDaFQ|N~NZFbPKOc$>L16^GepY zHsOtW%c9=se)*EFVrf~|8q2P;O|z7b(8iMPWBd)Y;Y5p9vZM>|)$BDXSz&&ql4~A% zwdRVaR0k`<+p{u9JKZX?Ri?6SEEkuvYf^4;qE(~gu_cpQFT1k6WkS2cCndgGH=(ty<59kWT!RGX9ZrQ!D#IQ<2UG^d zSu&VIcL)9U%AK}g4j5}S@3PjUY~~$S8{J`5?3G&3qdW1aOMIb6d8O7rZ_nU8Uyf$M zO2?kTN51@u4zxVaPASjouiPn%PnABkuxF<|Y{Nm0XQv~_iG!eLXI9XK+dSgaD?S7C zN%w@rJ$NctJcW1WXWmngc~2qTv$H63XE9xu8$FUtyzqF5X=Ez;{L4SBF^|ThE?OU} zi~19Cg0^7P8VzE2{4s20iTYSI57u<@=-4A;pKE@r`LuDohD*j>3w9 zT6>jyizLhtYcN(v$2{aM@59RiIiWh0_pj^MtGw-lm+n6H@G47-yyCS*hSus>oCsHN-5Z z*O#TGFfPK0zA14;4hv5WV^h7h- zr9P08h}ZRtm8gE6u=9WS#SlL6*H0w3Z%%bq$EQq*SC5k`Pj|k_pZ%B1io{>|{GE?J z{`_yZuIN0w{M<@Xn|u#lJofSD?~04$0k(9XP#O4F2pOwoD_Am@c$ZJSiz>&Hc4Au% zF(^(9(u*9&wIYvJ9y#pQRmhZDqnBe>u$|6*`@==SNGkNoZW& zq$eB`+=%AlhH!&c1EEq~If5&uIQ8Lm8EtFj{p+KuWaZIvXx>r?QzBl^-P|7t4aQx) zz@?UD4~`yw{J@^~);`J$M)u=_OK%y+tBo~_p8m&I#^3qSl{0RcVWb9J)OvMm`>2MC z#`1ga-an!BXIHJ?^VWWnmA@3hVw#G9(7NGsar^u20u-JnLY zXVB&RF`>&#OikXSx0M>LM{kqaO6zB#n@KB^d~()e?3I?``7CJVqzrCy%`HR?O0o

@%hI6 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 GmH!73$*E-k literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Bold-webfont.woff b/fonts/OpenSans-Bold-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..cd86852d0a0c1930dab144b687318df762aa7ad3 GIT binary patch literal 14036 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 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-BoldItalic-webfont.svg b/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100644 index 0000000..8392240 --- /dev/null +++ b/fonts/OpenSans-BoldItalic-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-BoldItalic-webfont.ttf b/fonts/OpenSans-BoldItalic-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f74e0e3ca7fc8276e5ad7adf934032d4f6f8f7b6 GIT binary patch literal 23304 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 Jqg8+5{{i(PmP-Ht literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-BoldItalic-webfont.woff b/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..f3248c1142bc295baf37546c887f63cb021bdf00 GIT binary patch literal 15572 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

3m6 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 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Italic-webfont.svg b/fonts/OpenSans-Italic-webfont.svg new file mode 100644 index 0000000..29c7497 --- /dev/null +++ b/fonts/OpenSans-Italic-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-Italic-webfont.ttf b/fonts/OpenSans-Italic-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..63f187e984b225756e2030556c4465eeaf8724e5 GIT binary patch literal 23680 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


@ftTG)1Ne;2W3;2T_!O!c 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 + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-Light-webfont.ttf b/fonts/OpenSans-Light-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b50ef9dcb5bc8984f50d4c770c6149661edc0f1d GIT binary patch literal 20704 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 NWyB80sJ;Tm{tu1K%R~SG literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-LightItalic-webfont.svg b/fonts/OpenSans-LightItalic-webfont.svg new file mode 100644 index 0000000..60765da --- /dev/null +++ b/fonts/OpenSans-LightItalic-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-LightItalic-webfont.ttf b/fonts/OpenSans-LightItalic-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5898c8c7818efebdfec1733d531b1417764fe59f GIT binary patch literal 23864 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 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-LightItalic-webfont.woff b/fonts/OpenSans-LightItalic-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..9c978dc30cebf694a34c54e2cd2ca53539acff7a GIT binary patch literal 15944 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
8{k>V($m&YfrUylNrC=o<~)tYxTU& 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 w=uX)Q(ZAw?^=XdvhzN+X2?81c zaYKw45vw{4B7+FHfr^MrkWmL`baXO03_6Z$QrzErsuR%9dG7bze{S+rSDo6fchgH~cVMiawRZCONiA1Cdzi67CAi+b7AI04F*Tt*3GEKGH_yGz(^T$6 zdj;O-ziGzA@!NJLer9a&R`l<r&xHR-NWH{Ql;~ByRJGyd4IqlyxKRG|SUnH)$&;s=MlSKP2 z`~q)+@Uo)t`a{6EyR5aGqXF`W9$j`Bzv0e zVu?^n$RElG<%IG>g`u+0^`V{N{7>1rbGSc*`?iVup2dAEG$9+2H(@~#Z^=ba;rqkm?goXd*A2%majQcrF7h}qte;RL+ z6_eRwwWZh{PFJeixq7 zx~S*Hy?Xbl?%VGYaP7cBmkz${@++4lg7`!T3&P<9i$3=?=Bo6nZ8d)R8W zo^52Gum(1c-O3iSWjJ>~dzjVZjLH(A_ZCoe2dh(AiOPJJshx+8R0rQON@bBg>8iPS zWUo=;+@evT_f_sIP4A-elF*-2M{yTbD!FXf$N`a2;V!CNGBrJ9;v6%&i)t>>^7#t%9$GPG zOqR;<8cT`RL7b{?KV>cPdO}rYT~u31Xc2Yt3f>=5<$_BiAyp|Htg@jaS500uK12sS zvclm}S*t{An9-sRQ;gBMv)o~HVlN53E5LD-gvwM)@tBdJ(7;H|_-Ub$p-B^rSI~V< z>KR>!R)q$xsu>?y6gMkQZY*pfn!r3i)3bjdWqvov8I@t<6Opp#oWwQYnjTLG{xPlDsIih zi#6HZtl4-m>slW3ggpgePxz30X=|P|zx5u|o}UNTDqrBeo6dd4SK_@XP;aAH+>Y1b zO$o`x+)6Q5Q|YA%Qx@|m#mQZx)5NUBnhPDd$~33DxzX#gyNWeORbk5_e8buF*#7K^3@{N_l0p)V#!Hr;knpX#b^{k_LyQ>U${=~q3lkLmtjJ|Ste zT&|bYB%Bus-B+wCv4remR;5@qM+Ka6lO~~i$*oz?q1k{_v!FMPE9kguIrYM^E#KF1 zDj&43Q>|%F>siU&dY1Ztc2K@YA6YDqU&Z2Sz-2s;kr|7{;ugRkx7r;zPB5NkaTYg9 zp6r|s!I;Ku&5izGdRB*EG+|Q2CE1;uN0&^vWVWR^afz$o&CDh(!{4lC7~`}0o8uO1 zN^xVgMX>?9ZY>R?4&ZDcjm`#qI2&+lcARzio3$`6R=a2J>wWm&b6B7_Wnb?P|NS`~ zsG06YDbwOBZj{BZnSRkpqbMO#&Ft(U1wm?`8V~hA` ztHh-k&+D&$#fyin9>&Xu-#wgL_0#=$mVRvb%HjHnVJn7i<7NHy6MWYaK727x=$F&B zSl_usAI5jlhVwKxWVYkI;S9B{ZT6XoRQOBNq^Qk3!pXv6% zmWQ_ve(U)qGvA#*dd9>leDJAJcQ$M-DC2wk?p(2Khj&lHG+vVFkLkphx&P2om%C-qD40klR(tMia~IQ_%+3NVgB8Hg+??dz2#JGE*5-JS_*W*G z;IlL*Y^f31S*+Qt&54{cahPL;q=*Vh0ajBTZp{N=%{Vl>wM-lq;;_)ImEbT0UW{Sy zad^CqHaRV$L$FFKDMTZf6G=ydX|_&iWrhk%=#nqT8J<1rim?G-{7uGK!UVg1(4_pfe*+Wd{Xep ztaD$R-ZLFzd8`wwV2fEigJydU;Va^7j;9c+VktmMcY%~pYICC{MDne3uvrbcwXQ&b z6NgT>=Eq?G>`{q*SFp$K6gekS=mzMj)1wwtseW(V6U+qoYQUpr06npY$GeAFoWab( zF1Sr#rLt54{}{Nj@ZP*KCRuo-$i*QW1)?gsOCnC{4L&2h%vznerdNkop4+x>#l!r; z9+w1n^k2z~|MtQy-_@P`=gx%bvvGV z;Ktp5(C7DlYNGzv`}I%a)5g62(!7;h_>TUgrbzD%STypo#aCZ3ejMo;$X(t?$lW|c z>Lx`lSCul=khi2%lA@KwDoIqDhnx-5_e)_s>x6ACn2$pE-%Q_`hh!e*Wg!@A%usJ4Z;16_?o$ zO~-tdCOIY-1Wi7Rofr8=HEg=X?opQ zUISQb*=I^8vlVXz5d1I08Bd1Hz~C6l~iDYoJ`XLQJA56vYLX$gtU?)f2l9hv$~ zFdHxp=clAT(kx&(pWX)@+DsdfUSqsCA!pJ1+sI!L4h-jC@l%^N5$%Qjz`g}ON*M+~ zV}aq2+zIGmKbQ^s!Pq5Xt!$eF;QLLzsxIo=uPS!Qv`YpIxTJ4Q9|KNU>C#7nCs~Zg zxL*p_x1Oe{4jn$_+}BDM%xgOfvi>Y?qY0hrXf|YDz=6T18&VE3A5zW>gqSgRGqCqU zo@q9jM0+3=hh`=OmfIVP5bBQE@Id|cI_VRB2cNCq zp>NQa>#O);93Rp@;YGYB{tNWe7(8e2fu%Pw_7v!*I06x13c)Jl!f?+_Il9TeHm?==Q#{niu~(Sn)2M8z|i=-U~lmDS!^hU{@xsz@X9` zPbD#CvjghPGS%Fqc~hI?UNdo*Hv^1j_R^u57%dBorUe;TgIB3GPovr4^a{}wtKhvM znMmSTiVXP#!4wDwCh;Ze%pPm+xbBHbBi}gl_CK~Z=?A5=>-e(xru(j*xANj4vv#}} zU#*{gM}OVAMT~JQXp@C87O^QTUO<$AN{*+~7(MppM2f8-9a<@ch}2OGHy=cDg_=BC z7RK$$qQSas7;GmRtWqG{^U5mP#=5WhG&j!yklI$&BI53we*9pAHGj*(EqIeXYQe%kCc`3 zPCRAZgLmJ!pj*w%fmglUuqK{sO-pPz@s|kMj>W+LG}8gl)eA3C@LgO2WC>=sNlvm= zHKstD!VvV8skSE75!I||&8i%Y!=(mbRx=1<6Xu|e2tr!LY6FOF@S{CR7|ElilDen> zPs9Qd@CD5GZj}+UrC8ddo;vkt>uD*RV(r?Q4_z;R($eWcUFAa`i0!4l>Q*DJ|uV4%mQX`oZ4gTABqc>`E1eQbrr4;@qBgo-!bbJDhJR@{u73)=~m~ z7Rg^;^Uh@TWqsxKkB+F6PPRT@FlY9c+@_z_f9UyGmstJ7JepG}?cA(i8vNVqpXoYq zKMydKfv?h72L#;We&VbwaF(!ltSQZL6M<)TG$&kPKN&tQ8^9|Nav%s6vq#mSTgwH) zJ(z!m*yjdezgT6LpOm=AqnS+vM>q>-nZsi@bhev?qrm_sh9t+56C;w(D*Z49lg#Gg z^Y{=xXjb1VCVus!!!iBLtDpV!{%8944MR7MUHkBc^`q-XNwfHK{2AZ64E-bhwVh|) z`dt5oU-QBZ@!H0x*VhlGxCLip!CS?knHh38ZfcVm#7|tclxbF)4V*Yc7Q7J-@CY9( zA8T#cD~&bfY+nBJaZ?W2#jq2VP6AK)kjibC$^?R}grE{KcghT`z_JOtRe01M&4go9 znHCYJ$VetEsh#MO9q1xMs1xj&gjMo~T)+&|N-|*tF_YaBDl{z!3)vHJTaree}o&L!`TDCv+-~;tr4?l2s*)5N*yLJ8IMQi!IU)Ef? zd*-7r?%RG-{L*XwxNy&@V|#DAd(DFJ4-Tw;NLoGSu6`G<8Z-IU+kiibO#|E{8-vh` zfLiDT7ofHiqd3}>Lj)oykYywO2oNR;1t!t~Yr0#@!wm35H47#~5dcmHwl%v0(k9Q- zXmiN{0e6J>!@|6tB-9K5djnwcqKY)=5MSiHF-JyRDNH-_G4?e}fGZu7`t8?RrtRX+VWw{F%ydcCFIzb+F(D0cO=e}DJBCkNkIGc`VC zFTp2ttuhHZFTg4<(6*2?30Kl#Pa|j`bdow(b+;X9L9h>b;sy&7VLb544HC60;9C}6 zsD|Y~-gA%8#u6i&V>$Y^Lhf~Es=F*N)Mg7VQ zk=y%iH%L0&ijFVpb%9-?{Ehmqp?OiuzJ<+o3iEcf^Y zHCCpT+L}qNIbvE5E8L@~+N(^mTs{T<>(%0R=c~k2mnPGMC*%v zq`SvkZF4BTjH1%6v7TZ^mBt{|%BxhLN9|gr_38n)$;#YmsgYt_Rx>YzmUdKhe*C61xRLB2F#HV<2awi$*h^*#Mf|kk`H-)8}s=-#H*-`E|4J*Z-xR*7xk<{dn2Ce?9n}{(wG1s(AUh*EQ&xr5mN5 zT;X-6ck7L()_%RT_Nr?q98=$7=Q7gt&S~+JJ9l&U#uxOb|Dqq)_l{UToUh|cbY8_x z{si!dKa<z>3}eySlHN$X_V|8swSLNAl1@mEJI8b?_waQ{*0kps{pE=a-<5>`gE zkgQ`7EetuE6X`+GZ93UtVL`N1D9H4vn(EekAd)?^SUCv$g7$#SU4^rXm-Rx6pvqt6od`sh)|F?DCS4`!%$et`qlgj{f9I9PF}7x zKL1Bp&gqFq)Pp~p_Uzif^y!S0D*dBZK3>0a!-_lan|1fXn=vOBL9QPc`m9${>!-rz zRY;fF2ya0FfFrY6ODFWD`Y}E)S+{X!@zBIkysDWPsGGM#EQ+WN)VIeCscmq`qNjPE z55L$ssJ{Liy_q|I+Wg9<)B210UQG|QHmOVXwo4w98YpS!-1o6S?fY+Z0j~@xoOXXdZ)V9FW~K6 z*sqOM8~vW|(`phtWu-n-ey2~k!^sX2>4Yje-(h=q=&ZH*!Pa#~U!c3GmyofyC2iPL zV7ZO%37!U zKJd2#o*>vpwfqjt7(|Lzdce>K@IJHiidYON|L$3iyj+z#l#yL4kpHS|GffHG6Jf$=XTqH9a z?YK~4ZR~3xK(MN?fi)SThj=LFp_pQXTQFql!K1ASX~L1#uQme%#nK0@%UfQRUR}}p za$7%Q&Y0SyF#K<0&T!Q%7zj9s%VLJeCU6b13xZFHQ}K4pg`Yns7uTSl89*=}Wlhk= z%}(SGXaa(QT=k3h`QZ8a1kD7&Nbmc|q)dfLq*^_VlF3P?v}!S|OvAj7%XYX^hD3z| zFroqxfEY;&c#a|^bll3{(;Hk?-LX=4TV19-zYJCo6_IysJMi{ zkKGXIld&6yNlcaj3mfw@#4e28EaKyMe*|SF=nw0!kVsFoe)I1ifB5#_tW}G<>(lvaK1DyNALCKp8F8F){g@ah=~3c)8*JWw7t9*X3k_;D=BSl4C`_WHgiVQ( z#CL(t6sLp@%rtKbCWT^y5$fNoE#HI>- zW|-~JIE~!p579N8@PQvh)QW7QQeKqwn}uy+4j{A;6fvtvXxixaYa4dkfS= z;PHZoM+5g3hHR?&!k7X=QX-j(aG?oe&m_WyCMfB++0-5`H1fyfF;Ps~s|?c18%%i* zKKS!rOnKt{`!JU?@O}?G(s(Lyry2MXVlV|l#xR5+R#n+e?iW#37??J=hKO-dK7kZO zyQZLtyszQN;TMiH=@e+Vx$=oE+a8y9BCL#e zLL*r&$2&9F%ZAONdSc?Wac*@XD=Z?cnCu+$jTYRm#~OI(N2%h@3IEnsLyD zJ5=f5zQgbQvp1bJsU8H>{0B8#+D|6ciVIKt^8_x~RlmE@>-Qk%>Z9K{eyM^WVuo*6 z1yhzKBpb?bM7otfFHyKKBiU>V!?`%{Ng+fAK16ymAT)?C=1W3NJ0F1OU^X-6dRF4g zu4!2n+??RPu3=xr7YTj-4*gW18&B)1|CP`(|G<{#pOfdeEPm+awQtGGpVPLZ{9i-2U`A6QRA@g33IhoJ66p&iMd%9~>1k5cHg4r#=soxI8~OCz zdQblMLoj(~N-fg9))%EqS}$+WrDd%~y%$p!q7N%oJXqT4D}x9~bs%O*5q(N^m=S|i zB?8_!=vwZfzBpKRA794r-m9nYgh5aseblm~^{7;a@ejlJNjKUMAxrA-HlIS6T`6Uh zk7t?%5Fk{pDa5bjL?BKM3oyXLfnl<>)h)l&@}r!)T-mgF`7cwGwn05|S2OT#3(X0` zBu9z}i4_xtTSc8l!Xk1ilo!I}Yir5K5}{L?6NVjL&yVV-d05|X{`uaY!)r0_Ad~`x z7Z{xpIfG9~k$S^Y<1D7{=PjaN*yh4ameDUFhb-Bzr3sUsB11^$P{NmEUUEd>-E9NF zy~Y57@B(1xhGXdbGzL+*$8`GMpAdi{+Lud3O2l+X#A9ee*?2jRPvoC$(%0y5sYu?^ zGDT``#Yka0w&<_QTh0x_c!NxpF%(-fZ6dd1Seq7rs>qMDOxU}OalTSHC40?b&;_|I zizq~KQf>&;?XxlvrDG;jhh{T0lOh(55q6u-INt|s1XG7A*k>Mq$!s}K2V8VRLgEPMmr$kK(>02a-Q!rYeyP#6!SlY4^ zo=7r`AyU8Hdr?ehtmNA_W5LR2V^EO_FDT{lm7NUMMCIbOyucboe! zSvY)gNp#o2R{z!;F5R(t^w@^Y6D^jTfpdwe@R#Qy&*?+f8*xxjtT^r>n1cwGTM6bI zI>-^}2u?{#)T{tzKcECd`aI1LNTM15R=0+76yY5~LkMR&6K+3@LZ;;)c%Cpr1)HGM z3{%{1p$NH=MJp_dSP<@Qi;K<;WGyC!hb^!+i;U-|wi?Y_U9 z^!>@-N5uw$u`t3gD)RmF*&J^B&yYvD#449Y_4pHyt-NpgQ)l#Fq#W+!CHcX7({l6? zZ+zHuV-+s|UNIJ>5_t6juM=6^L3l;wE-V8|LL~9phD;yk7EFH_t*SLj5p;6iM9oE+ zKxqaX&PJ2$67>TP4`d54ng)zAv&n@@BEc;PZ3SaxoDA%u2*yi=0YGRkF7kA9&NiLC z)oD@c?@6=G`P<2V?cDM}!{&z?HasMSc`7g2HslI^;HR%QKE(^U^WCNw-i|cC{u%KH z!Qll?eTb4GL+2q7V0;-Mq$51;w|Xc%?x(ORvO{1ExOl2RO0`SmA(&y1Ay=dY5U7H; zBG|(0K`4{h!tTM;bdh^QuAtv2oq>f8zR2NWN}5y#D1gU&VFL!`j@KIYt7QT9+t9D8_+}l=Fd|P9T|LoVVHO1^B;c7$b(X%!)4B6e$@TMeMAWt z5x|20C5x&a$Tm}RT*4_x4kP{>C{ukR5$^>poYA<~NBr+~!{G6W{HTx8aVX7VS_|u5VlaxD}4O5^NPpyA3K@{_2zo{^~)~q#qWM0u;vNnJ*ctpv=#ygXdbrhG3e=eqX*HK=x!Cn^YrR07AZ{-Y_QLH2 z@a!(ZnI6S}ORiFL$$VCOdG~lSQ}a8P_93IR+#`fnMJeQ30mVVW9=bIX`SDz|dU`Zl zHuinIDzRn|L1&{7s?Bl@2Q0~iPZ12*w4R&_{wV2cNH$2lVvYhJ;@^sHh{hJ(Ik$6F z^?++`{P49A1Ng!>vr9fcSYAAB@aV(wm-LVIzn^S=tZvPTqtiFNKI@LrOXvRk`+0Zl zo3tU*H?-p7(VZhZZc4oDpPC+-HSqC+)*jb%DXv?$=cUK)A2nvtjiUzKBwsw|mal(6 z2{A_&fGPbkXVciVNjn8Tu#M2|#iX?f!rO!lG$cuykbx+a6HXi|e@L!qX=DYMs#F*7 zESyg-iGP!DJ}CqNxo2dXVQ~nihDTCwO)1|!_vq331xufO6hf}kH9dx0_tHD971FDB z-?hI<#3Urte=|PCbeh>w72SLEsI2_?b!E^mlt((ZUiXVW9jMnq^e}}uQUW&2 z)NdMs(9~}Rg?2DcG%Nb_p--v~vzpMS8>wBGc4S#Q+G9O3$t8*eP#WyQ60aEpF1hm3 zdi{gzdvZ_PsPu&YnroGoU)=is3`_sy_%L0P^vVIf++;hE=0dVT(2J`cA&E#8LrGCV zhr5jkC`1#7kU!`35Nv%TE~IX^T8l^W39st?`A0|fMT^Y-me(ui^qR&aRt0o~s5^$ctOo%XOb04$ zp`0<*x%!j9I1FHzK{W~|2~z#fQL7kiZ11esj$q>Kd<+A;YLplqX3f4PjLOho6EG&? z-?rKx48+i1(8YpzF(N0F7P4)W&md2M7?|Q8$=V+ZkF?kRKs!+o9!XKDU0y**&EbwS zU+`4@+cO(KzkTP9C!Tov=_jA4mkKx_)Zf;B(ZAE*Tg9bk-~ITb_fDK@!q`;E`*{Li zVbV+@UIUeSo*}ec;R|pzzYS|@AlimFVu%zBmGWhTxVYjL$`zboanh{IO^1b`q_{n@ zVIg>81_IknuCzb~zrg6SsP_b|)eY1C^iRX=a%^c>`}pGaw zjT@o&QaoS2{>2-|KHB%DuoD1FC14?Y2X;ccsY86-Ztp<9{>J2iN2X@LlL2ER7H07Y z7lf?H6qr15SUhAaTTpNyAR?Qm(d={?Mx+Qo1!I-Tpyzp$$1t1CFnRtm-YMw$I&vyJ&{JnxN-hjzt@UdJ3Slq0)F;6d` zh=T$^a$_&#*<`H7qptK>d+og8(u;!qyDfiF8T96ja~)e! zKYYA3LH(j8L7sztJ7AqjJV2IK790;@ELw?EMRkfAgoOxQ4hxa0Q@l{uqB;e(^={dk z8pz5g4ej;B&2AK^U_@B~3=O9cLS|+!)#9qKb14QUG{JAeNECgi(q)P@6&96B)Bbco zd%EY7ci(bbmq}}1Uitake_AkP_wc1_W<0)mNguiA-46}Ar~lx-CB1u847~5=&GiGe zbS%C4n(FI%S6y?Hz-8XKucaNP8tBvohV7*}0Fwz^frKF0UvZPDZ!)3WUD#m4Ob;Lj z1(u*3RDdimDuGl}qw#BY)G6=G5q%l*4d#IU{(^aJamLc0N3}68U1f`vj;Lb83;V6`)rBdD=UY-l%aajDt4S*yihP-vP&3p_W<DN*;l-;*F9$@h%;t)qs5Fh1#z4| zALxqX-1!#UZOxQqvqc2GO8N6vtUo*7P8OeeDC*?{%2_rEOW}qC>9I^sVi5r^LQHQ? zh(QJ&<#Tc*xNF)BtJPlaJ(_r>hu^A1UfQXjc=f2So3&%^@q-9(PSl59R<*lAn%BB| z=e!Pe(#OB-m6r89@!a*Ti-E%;(8Vg~a$($yNJCklHq!i;xK|NhuP=KMnZnQ?^<{kh ze*KvKhEy&E^)Y;VYjf*yzF+T;J|LSFGx`WnzRgM28QH4s^oNB;wLHi|0C-FY2F(hY zN^rM>OAeN(M(V?*_}L*otMlqF;(Di=Kd!iZaAp5zF6{;0Sl4uY><8)gUqUZDWJ$}u zB{bKlp8F7DQ`zJ>i!wBntCF!95bBVMsJRN}%V>gxAf`jLUfi1@T(mTZ25U5)A&m75 z^3uSNpgH7&=E=ak;~p{HR2yt^6l(z!6{v{uz$gxw12E15u!>MoAAqj{^Ssy6xgYNN z;`Hfxvkts-2mkh7Y0NkteQ4)u^CA7z$s$M5N&V!MG13~TVGA#-9fg?G8Qm={6m}u1 zCa4}BwuKBOL7QO`l84UE+>30S@CG^}jg;uZz+LP5_!CVsS~ZIjvWbo79x3 zmI-)0(Rijz@MZ$uxSUCcGFGpU4UV!jCY%sW!TJK^J2Wd9hRDmMz&?OGW`J8+Q3wEw zD#!{Xc=HK*vt`hXxzlHz{%r4iw=7+7$FT!@r7=@@r`fmp0V*##WL~{%v;Ow@>!f=} z)#@iUKO>3p*GfZ`PV#U>?OtM3n8Mt#7*!a95RCy_shAg$O|yaR`%; zBKN@hf!~d3q%i~xF|pQy=$j# zT>j=E>2JKH_s;EdIJhSE-l_NB?76YK`N-QL?g1Gwc9a7v{Y^)~hqIFYNfyeJc~q?Q zBlA6BGBZ00mqAV}V-tRg!IqXNErz1#M7m(hbns$hb-G|q0gp^G5uB-|Q*1m7(72)a zDD-0|M}>p}B2_5Kriqx0o&+ecO+`ZCK%Zl;z4qyW0}Z{ltXsH<*XyJE4wkd-E&J~D zVt#S_*zo07+`dLXwfK`sD@wKi4rH4Y%D1PnxtLEvA5yYGjwRe47sL2%G0lzf+oK78 zK%6keG(S#QKpMFAt|rwR6)SllNt`aChm(q6%+a{ZNi7!wK?rdP%Y$n2jC_J&f{X8mQ}OMiL0{tCYs8$-IGlXS90U)-=*|BgGbBYMbe z64r3_2QQ@pqV8;w;qhyJtmG5{`)qS_qFbqh>RP(lniG+Z;xIyzw^GO*H|!%sq7j$Y ziV^BTnH`x*RxE++L6ks%=Xr-;$&M6s?FOrmX{Fr&3M%V5dUjjg>8!9T*@_V_mMZ}$ zQ4d80b&?Xv?*PxotHh!mXf=(fqBC7UH-iyLtrSi=!pFWr+hKj%JID2HFHhaYyX@S> zJ3qHeKdJ80o1WwTPhPt7mWys0y6B$8%SJ5fI=SZXJJLtuF@4(`uj=*h9Ot87dsct% z*;t$jQuViT5 zATM0HeCWbleIDv29^s!{U42 zA103xi=>ciYIB;bpAxrU)SA(gm93_R?yzC6bXg zp~u301$*U_qq$?g{)3D#c%Dgz%LT#voM}1g;2LQlyfyjHp=CT*;tia>(S$DF~-}sVD{fPYcvA z{DSU2ED}5q2A|Ml!NT00&USdxPIBuU{q%T(>%wuk+s9##C9DECxS_(SH{hc+@x+-< zjDtdLNl-~sAFV^}n9w7yv zE|##XnbCyBEKWey@;-nJrkmp;FdrTzhsRW892GmCP~_~y@+@C z=g}tz)-TZy4dHt0cap@9>wOE}Y}mSa!!!TXPnYtamvk-}x`dl}hw-aN=r=E^s_wER z@oK-izEs^K_@O}hn+Y{~m^bP89FLKCw_zziN}a?4tmFz!T7YGB`LO6)1PZDC#rt3C zUsRL9zUfGbVs!|L95t8Mh$N=Mh-*x7c*T+sunuNCt9*&bK}nKuPHD#ZB6bvV z>!{g^ttVTgoJj7!#kEOnnsPJq;<c|Heib#ORT7CxmK?FbH9{U5>2rqf&9c&We zmi9C*8F(S;w(TW5SYib>ld<6|HH=q*kk^8SM3dx(&m;{4w+!QBSO#sP zZK7xBJ<49z$6Ub*z<=~tlKh{`>iH^3lD5iS73%+=WKC}btO`>Q!h_lm6~u5axZZ2a5s6dIM!3+8RMDj+3HR6-tIl@EA*}KeeB=r z|2j|@m>Y-(-b%YT?e4VqgBJxK3x1qllira2V@7_)D;eKscFP=>c_8z{tR7hhvJPZt zXWyCqdCr2IO}YJYZ~8C)t8#bbzLxvv-0$;p^J?-|<-L=qhg{-+L+JakB4*5T)Pb51 z%at*+=yPLfz!}3gL}YQ*iYPgb6dUk18=G;=5kH@uJeIH~|ma3z~}P>tr^Gg|LlBdpwRNLhjAP*NkS1yJ~SZ zgs)JASQHgh^jWel$)j>mHH6&X4E*1K&zVg|>k=H##?$mm?=wDWR{A@iG5hsr&~C-k z6974V0B!E?-2K~+p8dB^rnP-?t?h$r!&xoHFb5-Rdv^$5Wg0Ke+<-o(V>3o-U||B_ z4q*hf0-BoSc<2Lev+#wdsknDGuG}QxzVK;+w-nS$%F1(7(BJRD&t-7=#Y;Dt$m0m2f!IY&@lrQ7FmdS<*;1%dm+Sf^N}g+fZC=)*mfQ9 zO^VJ~QCtGLl(I5GqbR;k(+w-Gx+DMD0~z6qSWk8_YF~Q8ldnbvK|j!`KO4YmK)pfi zQZ^W0u)3UGfz{wc*id#AvUFFo;p`fGnC@CcwMVhhsJI=&{(!Zm*RyeKJo1uvvE{6e ztwvqiDt0dxHJP{>*0~j>7Af40#Fmr0P(9*C03psA*&g;hzI?SCU&4BZdr=kRXKQ%C zGH?3Su3h_fP44^CKH9abXk%ZVY)6y(SaRPjxvxm>yC?UR$$gLHzACxzYwXLD?=3G+ znKJc;d9x=^8b7DjxD>51_7yeCfO)fLP-6hbv6r7)uJU`?WvX@PNR9KgqqG|O#+K^F z2fF;jaB%0S9DERK%t*-V&;V5~?yovS1LDdF2_XeE9B4QnN;d3hI7TKLDQMUSCmS|2 zQhFsDRy1r~lMM?R*8F6{jD}@MvSC8Q97r}?Xed6Tf%RX>p#(z%_OVnDNJ7xH<`#@6 z4fh4FYi|b7Osi~f`q2y&w>N!g`t#bGUNn6t+nXLVy(`^2nu literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Regular-webfont.svg b/fonts/OpenSans-Regular-webfont.svg new file mode 100644 index 0000000..01038bb --- /dev/null +++ b/fonts/OpenSans-Regular-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-Regular-webfont.ttf b/fonts/OpenSans-Regular-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..05951e7b36b2352b1a69e2052d08fbffd77d5151 GIT binary patch literal 20688 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 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Regular-webfont.woff b/fonts/OpenSans-Regular-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..274664b28e8ed522cf1753f933ca085d8c8cc330 GIT binary patch literal 13988 zcmY*=b8sfj8|@q0&c?QF+qUy28*gme*jO8EoQ-YUwrxAP`F{8QbGz!)^f`T=erjr_ zYpS}RaZ{9#0Du6#8%H4k`M;~u^#A4m_5c4SA)zJ@0D#zht3SShXPDATB`GE@@vVh_ zbNp`*0crtYimHq(-&)Bx*Z+o59)~ZssjaaC000X8tz&&-^jVjV&(zhK2mk>420-XP zzycA#lj#STBY+>y59Sec}?fH)XACN6RC9sod_0RV_VYYC@y zS(+Q00RT+R-yYU)aJ(y2_F8_6-`e>%C;SE(QVztTrLD6&0Kg3Yog?Tw2Rh0kGlGr1 z>9>z1{@e5Zt;6S6)W6yqyMO0pjsDh%{sTw}NV}b}t@*cB@y#E;eVyc7Ldp*IPR;-T zTj4jS`o=gbBEyM;qxp9%`}ntS`CIcIHo~NHUo|x{GBN`MCS|{b61}pm&B{>e!vO^H zAQl1tjhPu4ZG)M>Kq4EN0B&^s$>7q4005X1K;!o$|BVBUjkCJDN4vXuq88Eu0+b0v zSPjjjOy7rl`uisa2ggTy`}=SG15P@?f<)NBz=9x=S+RK_d07Dv1WeTKs=D-&^cv}B@+#t~SfkCCA zYJX$qK9$g9_%rNADhKLtDk+*_8Y=1%>SNk|+6rYg&+h9lL8T5*r45qm)&?OLcvw(a zR9Ked(@()qzvHi-FR0I}kFK+?MJR0~6+$w8DR<;MqFdo@u)l9hmy|U1LK~vsMrNk| zv_LaZRJmhVe*-gPbJL^k{oTWzgFP%{bW}_f47Akv--#&+$w`_@YAPDa>Z(iA^RtUH z3v--IY%Cni?5s`I^|g&P4Rvk~&W^6XT%4Y+?{6P(9`2B!;b9SB5a8m%qa$M@VxknK z$a<4UsJofWhNY}0gChz}R5fzJi)d)9t;)-K#wkpC0f3S-nP9-@_ge=p1xNPyQVx2whP0$oEtC(6 zha(dRPz?W_&K{A^#>-phG?~sSJDO1D_Os)t)Cp5+$1Vt%=}TF-D((+8`w$}`vD!mQ z&%x?>(CX6_*8^lbP{0-Pn9>~;m6%ibgL%>7$08WCBk(oG2Nje8%*fHPAm$J5_GY#F zdCgv+?e-yTSi_@-02zutr?&nuq&E7Ma;RsE)5yV^;pRY0BA5ngX;m2`G?&X$=qV6u z0^|5%Q-MHHR3SJb=3vaCzo16X+Ue?$drrr*TqxtT4T4y$o)Z|hR{#@oPanY|D;gZM zOv5bFPZlPk!0lEmNUbE07|d*+I6K*FTp93dpPi{>Vh*o!9H_dc8^+{|B6+>RIGBhi zP@Bgg5xg9$1#1MF5U;G>nK$Uf7zNTY|H+C>ZshTLVMqyD$;*MlXl|Qr8jTT{v&FIX zVm`1@rgtQs*XE|qu6FYKP?XVPYY#;+E@bCV&Gy8Rk6(e%1wzyhgbc8r_|2HjuNfVe ze)UZ_!WDb=x*E*ywEzGCfP8%ckla@Xygb~|)fe41bUY2qJSTG4y0*Q!>HN~Q_Ni|$Dpu>mrK}m@6g$IpqW2hA3;Dg3WgkEp6 zoyvJ4xUTLd?%MslO^VB#yrx{IUb44325!~~V$p0>z$hJn|7fxHpfw94io~L!9gI21 z!>y>5TO{Ovqm@xvqf*a;bLVMGqbxPBl?DHPk4If4)k_^eAXJ=8#brRuAYMJpZ@RCoe6t)PR;@zVZ@zQoa^Y!(Br~9`xH5}f!eD9;!pOJgWZ(ej z!lBXJ=m)f+`3^6R9T;)y3--uLi9K>sla7AHQZ3(Fq>(0#k#joL0G3$}6{o@_3Yb~P zvFeub9q^B&y3gs#j*=_RAA3p$wb33rjdXx-Mq~^T=cK}uBLi_{&%b`c|~Wp+TIaqD<-sMSEiViM*7-t-EF?^ON8BS9|rDAjMlF1OFOcb#43d;7U#ze zPeVVmx`rDImaqhUW3a43^`r=)#Yv9_>Yhui&SMqzb`X?ZD|o+H2J1#m21 zYvVb=<4U>-K9RkGJDyAY>v@IBr>E#h{%;eF`_b>jeH)d}>3zeOXMFVZrkcwh;O_BtKek?Pby90k)Wg@XbVcVb0O@y}R zNC8{;d;=Et zXw%Vge@7FkL!;p$#*TKe!jSWMuc@5i_5Ma#^)f>WG8gYf?V|M^wYJiJgVl-C3wL+6 z!O3g+L_UGnV)HW^^W95TtEAJ|S&~KbQ`E_2GDDb@*D0%CzSVniUYw_YgE4sICSBdXIgE)RuK&#Y+!5^#V+yS?Jo6TC%Jvl*h8b|OJNSl); z%B-#tSlPZYs+-~+!iXG0<=C7(BAc(_ctB~%@N6?1X)e1|>1#Z*Y5}!X`*V&y$O2Y; zEK`t@Qj<>iefAU!v&w+U{rNgiGz^K5?zVU;>+SZezolqZhb0Ss&HE?UA#3f$efrg> zC(p0TD*N`&)lB>LSDL7V($p!Lp}&243`+^LdqAfe=Xy_u* zh55`orY;v)ig`Zmvq&5ShV0tIK6SVqWsoU-V!p=J;B$un__A^Z@rf!mpPV$*alnIm zSAJ2DN51jETz7hQPjn!|H9Igl(xj8l9E9~moF>0LJs3`(%sdu$cb7TQ6J>)z6>HG` zV&(IriR028$gjQfk+FUF2`4qfxkmU>`r0pewy5Frh1%gedOWEfWLMt$mV-iC9G~ul zDA(@vzCU_8QB~P&e@1w`*J02W<@*52kCDmuTK5E`(-P%)BIHgG^u4H9tIG8mi`g4= zRFWsUO5CKoIy}{0l4=pdP<_FSicHX9t~8MtaFJ>@cBUi@+~R3ri-jNz81-LdE2d;? z`XpUZMPctzxdHEkc&~04;}Gb&4+;5^Qne!+k&L%e8z$k)qd2xzNltib`WVcNU&`Dv zpXN&CP-!XwMj(DTvE!(y&DnW0cwoKAuvUE?@>iu#xBj<*zn`Y?AeG02tI9Ecg8U)Y1wBa=>+!nb**wB2l1W!6wHa|X^IziBOKee! zxl?8{Ks0j%FTE@JQx7iQV5we&Rjd{GZ47!qV)RRBopzK-aGxxR(dn<>C5;lvah4id z+9qVch8+tHR__Vmfb0*85ac;_8aQgD@(*J23ON#M%tROGUXjlh3u%1(Pda>ID;Ivx zIl~dKb?!+}Zh)DPqV|lc#vwJ#X*Gg~8Y+>kwiYuT)E<<4dy5;;&?1P})Eno+1vMfX zQQ=P)AN(EyCFRTJyIQp)FCLPWB`D#sXACJaOgfkE=!ZG+m%}YScZ(IqXzw-H6WDS= z8W@NYCIE2|ZI0kNNO}nAH7U@u%;G@Z=S^LrD&2dcVaZ_5O~_tfkr4fiQCrSY z8I@c>KrP9p_b(#5_wGTR36|E9E5q=^k%@-hw4J2Ll#eeIbZ(IaH|Llm!MJ0!>)g%? z*o#~pY})FFT{GJ+I^&TXOYlAF^;ml^{+o5hBj1;$DGR?%y^d1gKxBse!aMaXnMay{ zbn1-9y*A5_e^1k@h4J_PelPVABb{hwg8dHa#8_y|N647{kErT4^T9?UPDEm8D79%W z!=Mf170%@jD0d1hZZi^5U27J*A}Y?ms*lrIHw^WL2D1UnQ zuG2gPV(jcz1a2gU%*M_hv&7SK1nq3bf6N1K8i=6sglW{vRqP$P`03ci$D|kyrnnA8 zHrV6S-ig1!RsIUh``jeCwX^Iz#!ceC47EzMW(sx%kH=Jcex~5S{Ucy;xw}~w@%%(< z-Kq^8;ezx|f?>gQL~GF!5G{KYqeC!PJCA6d$jF8KI~=NT+TCvprQmqLPNPFHd@(9! ztgnIGND51PSa%E8YgLH9uaPM^HWFeX9`W*?Ua?%=n^ioV=b$ai&5ZR(B9ZcNgxsYF z-$0A)bQDozMuC6#UdxF{=jUj10oEt!!+CU9cb2PZePVdhReW`FVgxx zwgJh`$uybJy^&U0c;ObcJ( zK7fv5*TA|J&3k(wek7P~u>``%#q4Cb?kNn5ld1cJ&b2glBay;F-=TEWPQi(4V4!dl z1be#MOAIcJI9T5f^7pK2P9%!gp9R)!RPOmny<>4A=sfaQAHC*{c97il%F6<{OYfgz z5Pl>tuAlW`UE~_8Vtywzd9w9D{s=S8YnSp9mmd4a+#+-vK`>{UfM!^Six#hzG^B>n z`XAPtCbIox?M&RLzch!#EQib?9&WV>phd!0NUf9>9g%0dUupf1vWT{^qPB01Q8dvf z$npsCmic9c86XL*lVzcS_PR`ATjVi>Upd$e; zpPjn7`=iyou^~ExE}N5*(}Z`mTTG9>HnMDAX~7EKr<^ zfyJ)z$*L)%05ENb_DN_r8Rv39EzGDD_EHY`l1c<7(4JUIg0>X@hLkrAE*RQ7QdkrJ<9$BmU?twN z1$~#peeSFN$N6y^p-*&Q12@k7;5v42t9z9)n%Lil~5Z+cm#=l2kr z0=efKunp2FoKgj~XYREeXYW5nDRaJ>Hk4^RC$iNbn?o-x2KTqze5Phw>J8B}>=Ofqht`Ru{iO z^$b+uDrRU*A00O)Q|%R)#icQ10oR2?W6f+}z?lnUDlBJ}~5v+yA=id<65b`l+E=6k0 z&Hj0bmR6{6(!!`lcsL~h&)OzgA&cIyw31Hms1%buY?Iu4tGEuOyt>q7w|r*>JDS8( z;kSzsZkI~BTzwgIQN8qZ=@)j!?aoWu%{8!Hzw7em(#xvQ@!*E!tei zQ;12i99RT@T|-%D)&0XCS;8+{@7zp7HzPLQ;Iphl16rtCSciA;8LY!#ZJZ4`^V;jw ztao!?!y{(zY5Z%+5~(pivLJpzhE}~Q-?ehy(>1Jdq;~|wtr;54sWl&X0$u4tMdGRC zGF_!)2sGaSltTmtZVe^EZwag`?0=-y(Y_Zs5J+x+$OR61v?tJ!ti!PEU#xM;;ogLA z%o-2$pDs;ZUK+aDzP9rc_y&B+TIVC^N(rjmo@loD<SZ-ZRwk8o_0KRe!^U(|m#tC3OLiSzzUn;pK< z?|79XjD$XWIM#BYBRcEL~n^6RC z2&f*vD^VdQ#kmuMY!Vxw480Te`~{zUf+fCBq>Th2tJfO8F6GB9c_vk=@%6~-pEbA3 zSk}fUgP`j=>A}CDA>HNu#VCtK=XF?mR4l-M2NLgtx&Kg5k@LW2mHvaNYM6;}mA-`Z zBRV)G^w8-|NB}8_I7_=Hgw#_FZEQa0aYkwyzNed-#mtsp1lXbA>G!M1PDy^^iA^{Q zOQWl+ETU7^@KDi5Jk@A6VFwVqpFt46W0{s0WB zN1B)hQ>pr(uVj)C7b9#j(Y$Or++S!6iHDu69N;pfmA8;NFxc#^iY(c=WwSZzDRY= zxCrT+?x%4b`h4|%378)ln%Ykp~HtH!1x zZy0Eea!^U+XtYVP_buI5DvBwlgse;zYb&Qu%}c2aB%uQ@wJOB%`SpOwL3D{K8iO?E zwe1>{e0F?Nl0TL}G|0Li%+`NY?mUP)@uy)#mP-!5kXc%jNHAc*>p|0@b`NbG-;KBwJI`NYYG%-C#L2SR7Vk+1H{XTgy++A5zfPAjOq2>J>{eL<^O;m4d|nBq^#iB-ViDK z*zhqr`x+dw9x_$D8K7?>#7i|$J+$wOQB`KR{4OoWL_5Ef(QiRU2V`SF2Sx7q8*)o= zInIm3&grCv@L(#f>?YzeAYk@r_ol?OF?&auP2pc(+e3vkz@sC0 zCE08b+kw?vYWufumqmRkVRK-|qSKNY&9RQqy18w~rTTX!|KyA{&U$QPoWxYxZ#F2p z`0V5@ZFXiQ-A0<-@X(a=64`*eEt^@sAkNl>T&YFVElhnIh89*Q$Mj&*j?GR0d#Uer8(bdOU>vj)_8jGN*a@{o*`jP^B5ZQ(h(0 z7KE9lDtOymBnqVLETqI8k1#f^NExkM7#SP$7t-O|DKyRp9KZgJVEVOgYYAZ`MbOKa znbbzCWKS&OvF;@k$xOav{vnj=YWDbVS2puMAq`FvDlK@-Qqxk~858gz)YN~#i@BM% z(r`95BZbUh*kBqOZd7*3f;wW}Ax7?q8&pYf>eVq00qx;%8f_?QRlFR0r zSVMYA5m+gBnYk@DMnW%YD9!tq)WHBw=Qiluygcl(Wtc>XS7>;C3n^ebJ^dPOi?T>KIqk+?=>CQ2zKc= zKE%9~w@&Fg9Lm2w-PO04sR|#J{p5`Pv3Su6#@OX+bPUHS*L4*7i!&8*O}pa=t|$)5 zMiAC!%2id~mK#ESnp0IiCIkGZqKR`J8Ie9!!*oa`KAPh!!7pU`%4A2)f9=nl)TuFD zV2h4C(N#i{xK0Hfa*(JhwlnC+f%RpuENg`jQ!M^J#a&k?Rz>KL>61YVeo0;gbgUuG z&nli&T~|dkLF;BfwSRmiIUy z*fq`hGgPKp!sMW5F~_tU2xs)F7L$*90$VxE7FiWVSFSyrYQ9gg9l7sySe>+`GBvUf z7mF1EaEVp{NCq!Q%+KBbUiUrY6mKvWyl(8_KM(mcpKO-FJB-PNv>7IK`3(ry%*gHU zq_B#9Fsia;MPZ|pq{dPWT`sxpn4Y-NCwNLk48kLh=Skyz-3i1H?2R_htnzl z>F{68c0h8JWL!GQlRGZ z%46lWVe7z~LJ{ZX%sz=tXZL76JH*7!Lu38rm1fPvs&4rQJ8sP|!)0pVL@F2HjjRAn zWCuM<6oQOb1x-`MlV<97u%m)a;tW8>Kv0=;!jfzC{p+2Fo$|;e0EzWG`FG;7{{B2o zYxv-^h_U>gm_PzN%lWdLAo8Lf0r)K>w>njiD*CgLmn_dJTTog4waMMHtrNEhW;i88 z95uM_$dM2pU-+&V3j{9gY{^YJ%m#gXddpvHYU(JF+WWAmo#L=tg3EWKt+bJyE>~-9 z&!!D6uR%QlT0Bh29#6X|^DdBe)fl^_2hnSsQr2KinVI2Zv zgM^@pR!=^dVN1FV3nMdK+vQIh<~r7J`H-Q4S0d=O9RaSRyI$RMIoL&A$`r$j#utp} zQt1l?s-0dA8)FZ}edodJO?=fHt!v=@A^+Z{pBr$P?XU zzRT+HdL^4w*Ok)e?6Sq~?o`>-N^{GcL$KQ+3YOg_bOfrI5z9j<&0#ADRqMPgb+%??d+$`3=fKII_)z{bW=xkiwFHoH7^g`p8_Vf44 zMZ$T+%l*3eEHaJBy#yO64*0^1ELeN|l-kcn<*=~6y6Vh-YHGOu44fG@?jnTFh{|&^ zJ%IH3a$RRL`FM)QY7?V96tg@}Mu5xlyKZp0N6nRQFLY|#b_%fJ*)3r7q^lx(G180| zuK=`pcK>tx#SFEoE|CE0Dq3ixXW7c!VFy_OQeTz=&2qflUc-t-K3;fYH0vqtP;&={ z2oVe(1=*dSCGE%^lMU5v(qjoD?5~f_u`^kSLNT5{H_6Gtf65lceh0Srb1Umvb0Y(z zp?qnPL3b=HJkxoTYhR-Ftas(0Dgku&z5dr*f`iG|&&laNFpdXDoMzGDKd_I#)#twV ziKg<2_%G{D+C=fJZ`2IIrx=XGjASgl#51;fTQPtZN%`E`TFV#?0dSd6HV{6qGdMtB zMGhF^{nBgGVW-Xbe-H_uj{DxT)V5m{9UgD5)Pl42>YYdV+LH+tcbTHEdyQ&1FIlgO`!Qsb)S8Zo_4dn2)ks7{s=&|3VUp`zb>?x72+4 zJB+1C1D;^#-v{t3@SU^2JvrA8-pA+v0^C}$Y9>h8p?2z4=jQ&HHLtl)UB(b=l~wPn zYruQZ=bDge-%Am4MF7&~_- zpVTB5a&*39tpWIOxfz?KwNnjEn@J>NxBy2)v!?BMITK9nfzOgs%eykWeE~n<5~uHKAxe7ROC0JwvzFr@}g%fjDRm4GoaDx^4b%`t~l;-M=s@vZ+{`M zANwRAopM9S_fec36P>i(5<|2vRtn?rJF}e45jKTfh$~|obZKlbG!_`RdIafljnhWr z774NA>$M7db3b^Q&7r*%;TN*cUvOOEmUvDgS zYlMI{`Gac4EQ=Gr6km%n1LE+$H%kkN4t1OwY8tdXCSjiXpQIGA`#PkxSHJaW!_vC5 zKElWQB!QT;wD?}9u02{Nu+>~|kNC+9^IP_-s1FBBT(=9SyQW+5x1R+&mVKdT3g1KC}5H_IK$uP{>-dXz4Bua=$QV%a{eE5 z@L)GeP`xa!2s#q+AP8|awApdIWbK`DtQhkBc36vl5F%WWfNBb32h~+rm5pjE2qxDD z5Pn#Jl{H*~b1JukW+I_lGH!gWrd|`GaTPv!hk24q^cYa;Ncat={lQNHAXJxujQ)u3^$<_d2{G3=qg>ABTpQL>lntYw zYaw905>4_S*8sY#Rs^E$3DR`uYAaW^KsC<~TqG9b_o8P~ZuLMgSAKV4lH$zlwL4r3 zKPLZ#FQ&;)BK}#&N2oHiTS??9?={wlx$wPpoZTY9EZxrs!ZVJp+tIVCu2&g^Tty*K z&tQXm!I`}&)XxdUuiJwgQ_3GGUc#NZJ?9v`qy5jgRHe3ZDSe(G`Hj{+dY@9G4%o;X z$m}-Q3>2dk%_3xJ*;LL7xJ2MH6tsb{$SROF0eT>QJU9Iotx7`ixB+CmlEPDNzk4lD?%~J@l2W{ZwTSTfIL}&^`IG5 zi9fQB)15n9T+W{B{5aR!I6ci!pKV>j+5eTeyLt*om^4KR?;hh!vRFWAI&?SX?aYHQ zBtm>l;?$ucXAmWcw|w1ThIJp3W8glB?~oCcP`f>j&(jabY}n64cZ#$z-z1kzLiFgldZ7=Ayt}6W`lhx1Uu{ z?hhxD1ZOP9H=PiMgfDk!qK$~Tb(W)J<>j7m{5b}^mcCy-KDYPt{*3Tg!U{&2;o_RtKlD5L#+nhte%k@eJ@=02&*bxc`%OH(iHgQ$ zDO=84_6dI;CHZ28h~i~2{ONsD;Cxs zl1EoXC(P(HC5&GDB#j_&s4s#c&ghJB5KHMMV%{F74_e~MIdLTO{}DB*bZiz)#IG2X zX~zR&?6Q501k*M#ZJnCX@G@_MJexH zuC&SCkg+(&?1e`vEWpd&SRKnnDqOCl%ichBy*eJr-YBWlO&?%jH*Errc61NZ@3iM8 z=!*S2irA)KopJhXxjDyA(zEB#Zb!xwvm|ddxi&bXwJRqN!jd~Q33{kCGXpksa%eGz zFfm}*B!rA4HtY<0nj`BKU_^fg!m&jIMrO<~dwb}UinZt-Ri=8L-!^tv7EjkEi@^>|7`|CUO6FEik=x|rTt;KNgU8V!|Zt;u`%zVhdqS@c(* znz5L=`dw_Lt@SL4as+AWreG*>c(pa8i2r^+LPT;0#?xfi(ig?BE%dh>?g)xw?C85(C|r;p z99b|)01`f`NtnVUzodE8vn*@f9?>+`)EBUzlVN@dCKAZXFsYQe{XrvAU=?MF^QQ_m z!W_E981ncB8p|?+8Ak~sHXqglLiL|fqb4j%%(_lS3st49KmY8+wL$nWQpDkXYWQB{ z4uw^V1i2bc?i=^w#yxgN`q~I^CKb^IXJS7>H#C>-zx276HcQ@I!Yp9rNBAQvFAXfch4U?u(T4dG0Ia+ zz}fSkKvAJ;pL%1jP~ZLmafE)Kk)yB(b>MuFd{sW14f^$MVSCSqesO3HZrir2(6o4t zRJcDx6UhLhD&A9|mYN_yC`9XNN<{)Dq~aF@C0>PK`q4a+DEPMgPKSN>WJhypa+}?! zlY;&cE;QJ12s$5tX+vnI`_PmV!XF&`)dy=_hG2h}bwvb0*2iVOtd4;C&1NPIItkvL zJui?27soQD)m1GE^qz?kN#sm=KO45UpaN$gh#_Ocx4wj?N)h`Eqk-W%j-YE&ogl>jFk zgBKEbkL`3mAHg2`b4vFWU(nHib%OEd*M@e{d@?}0JkyAXOH%%mPWgKuM|M80QsR{a z!5KM=rO6^e6ezwEi#iHD0qawwntjNa(H3pbp{f_T!A;Q=YLqLD^KK{ljfx2OX0SGR z)5FSXkh1Z#W4`#>;i=e_ylzbHJQqntbn2WYd;wCp zzm@OU4kn+{P}Gj=Mc&;__>7d7;wgIeJf`b<)l|Fq9`6?7#F{Er+H1xLeYCf}sxDMrN~JWZfFcOtPbxp?Qvk zk)5Oa*OKdyRzD=$+(6o}BS+dcw$s^4P!7dvo1CL->}#9W0J$3@a^uj|77g6 zSMU+kUlx6>^Jy3P@NI2gY3`Hl8v21FWIZ}AGB#tC#GOTez2yV!dbjP3Q0~9s`Vg-I z>B3R$(*Enh*Qtyab0e06U)+5YowRxacDsCIgH7}n1!&WUH=>Fj8d`C;+cyOFsoO$U zaS?}~MLp=(m*CUgXOWT>HM2SBmsvRI5v8u&JxcW|V6u+FHS>O=1RmZyG#;aI3DeD4 z&T)NsJC@@)M&UhLuIG>Sh-;}kK5T9(VbCT+{6e?OZYsm4?-KdSWqIZP zq4(3YtqIoz^yD$D8~^@@GTI>Vy*~~`p{WCDvTO^=;$y0)wT+s0_oEW#in2?<1}Pd`tq$RMHLgE71-NPh zffYG#4MD%}l1le672i5)FQ(W;`MlYk{b*McosO0U$ir42jwIEMf}=;tnAK9H!Q-IdPgUj?t%cINX&RD*$34v0 zKS*lok0&Y^Uw;f;4EZ+tc8PPpBr=9}iDNQN&f9hI{dKv~+CavdMbYfLYn$6q`YTUf zU%tOi4xi%5_t)~O%NxXY(PnXzWUV0m3u|};uCn2sfj0v5$KWh02_3Lf3)8kVFW#3o z>1HRqSA>yM9NMvpJeJJToN_r?dJ|h2(J@^syfD7R}{FRyB#uGc=25P-?Q>48gy>&zjh$ z1Y0U1C(ur1U%1_mELuB^C}(l@OINWI^~S)T!Gtp*GLYZZa~^stXQRA1EBPd6O~$pK z<&768l(U~xoT93vEQ?gcFjQ(KXXf;@>q^cou3)1QrARqm8xdnvKbvmAT36q~dP7Xk z!dWA)YckT!FpZ1zysNLbvz~vSJYIE8LTatD#X|qY;{Q4IdcRKmWSi}=q21h_16M#_ z9=9ZJoZVdu4k(gA+X$z4`+mfsz43v6OKZ zC{r*7)SGOZ`t5$tyU&f+W7lujZa4NQ*T^NPTEq_W@#0ES)ACFb)nX2@@o7pi)5ON? zJBT~HBu-+R;bjpi;dZF}q(IU|3Rm%U8Sj8+d>GCMbyPvJWU@FZ-z1gbjn)wTGsuneMg6Gh87IRq5aDdpQO|zx1_7YE}}2R03>)yYHw9D5C8_A zWczpBIRFp>5CK2{$N*pf&~FY3_%2BQE=O1X<{<8?w(;@|;L7MBU5oN*;n+Bx*s3#) zLfA6(X_`$c`qITwvn0`#-LP`DeZ#nPJv81Arw!rQ>#0r(*-n12T1OcI9X*iKTKJbW z^k>(wnS7M%SY2d%MyX4|nkzf}JM4|ma?e5BhIp#VI&fzZfwY0iV@@-{89xZJms*R; z0yxj&!9o{(MMNLf6kV2HfsZhF5kKZGGKW4J&{!wuVU>*v1&(5!JVrWN^sa(z&JQZR zZsK^~ZwyCqAO86{q|#kB$}u=$T^bI&*Sa}q5G1qkMAiR%!W!JfH=A>x7*PcFSJu&X z#25l^F1Jn|H_w062#c5f@81;LsUZasW8}~sH^AR0mGcg_Deg#re2DLkG`e{KOepVk znpWdxFz?v`^=Q|ut;zOQ$G`FG|M0t znpnD7B=#>PMP|)4j9G*5s99=$x{1KAH zbYB&pY)b?&MuymaK`>oUkFusV74;)Qvuz~R0wK?!&JiIZM}c++VVogVc>`qH@Bca% zw$}D5R#-TRYQ2!ckA_*Pqf$P_rZkn6^eG!eyFKJ;{FO@A5e+W`MV$T`B_r&v@b&i| zO#F|t3A(>Y|1emHy#(U0ABznUr(${g`$D literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Semibold-webfont.eot b/fonts/OpenSans-Semibold-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..289aade3e229d405a8ba85c31018f08075e115dc GIT binary patch literal 21046 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 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Semibold-webfont.svg b/fonts/OpenSans-Semibold-webfont.svg new file mode 100644 index 0000000..cc2ca42 --- /dev/null +++ b/fonts/OpenSans-Semibold-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 2011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-Semibold-webfont.ttf b/fonts/OpenSans-Semibold-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6f15073125b8703bc52cbc0e06f30d16e7c2b512 GIT binary patch literal 20852 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 G*#8B1{{jR6 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-Semibold-webfont.woff b/fonts/OpenSans-Semibold-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..4e47cb1a69b2a7f0ca3336a5530008e6d5b423a9 GIT binary patch literal 14052 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 To$P%_2Tu721o2B~8}NSsFG&!4 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-SemiboldItalic-webfont.eot b/fonts/OpenSans-SemiboldItalic-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..50a8a6f7558e8dc27d16077ee37dd040bbec00e3 GIT binary patch literal 23882 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 Q9rxKDN}LW;y&?Ah00pQ#mH+?% literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-SemiboldItalic-webfont.svg b/fonts/OpenSans-SemiboldItalic-webfont.svg new file mode 100644 index 0000000..65b50e2 --- /dev/null +++ b/fonts/OpenSans-SemiboldItalic-webfont.svg @@ -0,0 +1,146 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/OpenSans-SemiboldItalic-webfont.ttf b/fonts/OpenSans-SemiboldItalic-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..55ba3120f765578c27764752b8ea0c25bdb24f99 GIT binary patch literal 23660 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 literal 0 HcmV?d00001 diff --git a/fonts/OpenSans-SemiboldItalic-webfont.woff b/fonts/OpenSans-SemiboldItalic-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..0adc6df1621cf92805c944d9c5b4908e29dfe938 GIT binary patch literal 15748 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 literal 0 HcmV?d00001 diff --git a/images/bullet.png b/images/bullet.png new file mode 100644 index 0000000000000000000000000000000000000000..22ea54375ac8492b3c51cf6da0bfba787030e6d9 GIT binary patch literal 1045 zcmaJ=O-K}B7@ibMElse)x>0N3oSw5?98V->HIYF>5iUK zA`Lu5bm#{vC?X;w=x7lgyL9T*sXTTmFGV2OH|y@!L7T&T@AvXP&-=VT-;Kifxt{J| zH$f0R`J7b5r*C(49>o8{Pv7?AV*q8#Xu_I8HN}BMO0y~uVDSuTK#Y?R@n{4n4cmZ4dWW)fkR5n>5}VL{^~aW+Sr5{lATBNx7jWECM>py^tzM%5ye zkkmXh_8)PP86bocU)lJ`1N64~}H(jKdD$GkFi8&};*Mu=C6N$&UXgrpPv22!2 zrMWC0iDfx95#duQsfm>=b0v`+8^ydqi(wJ{`h8Vaq*?K`q0Gt?%>6K|7Cp}KZ=#S zlqz|jE8f;-HrN>f2WBg4$)%0t#jaI36bgN8`@Nj}IiRsO(?g)Qee+lH&GBcsu2Wkl zFCBT&_xy3&YHDb`?e40)*7fb$>q7tSN4El%;X-14`Lx|}Z~o~0K!1sNa^}RTSBEYK xuLp8pMev~G*qx4^U<$GJkL{hEhf4vXZ<2_8$_Xo1dk6i8n$M0)FVmCDe*jLcM%4fS literal 0 HcmV?d00001 diff --git a/images/hr.gif b/images/hr.gif new file mode 100644 index 0000000000000000000000000000000000000000..bdb4168de55a60c4d84ea1f5cb2dcbea7009c746 GIT binary patch literal 1121 zcmZ?wbhEHbWMyDxSj51fqO1Z0sw%3Aii)bLs?N^N3}B%6pF6@gK*1%kBoRp4*jE%J zCTFLXC?ut(XXe=|z2CiGNg*@ERw>-n*TA>HIW;5GqpB!1xXLdixhgx^GDXSWPQj+a zsv@@_H?<^Dp&~aYuh^=>Rw*$hKPlA;$OZ}PD=C1Llw{i~If5hKW)J z8<-g?n3?DqniyD`Sn4Pk85kPq8ye{wnCluESecqz85k-+ffCTRqLehNAQv~NT|l0# zQbtKhft9{~d3m{Bxv^e;QM$gNrKP35fswwEkuFe$ZgFK^Nn(X=Ua>OF1ees}+TSP$$Sz2y8{{ffi_eM3D1ke6TzeSPsO&CP|Y zE-nd5MYtEM!Nnn!1*!T$sm1xFMaii^<;ozd3ap%qQWHz^i$e1Ab6}wukda@KU!0L& zpx_*As%NO+o0y!L2ND76@b$Iw%quQQ%u7!7bg@+enxU7OnPO#O;%w<+?&@e}YU*le z=xXTbWaMgTZ0c%cXl`uj=;#8|>yn>bnwy$e0@Is<(CdU#FDNnO765H_NiE7OOHFYr z%Fk5*d)g`!w_7Z5ng`XJg4->YIQ8lS9itD5TBN9k2?5g&hzU=)Kn^_Vr{)3Edl4{U zGyebg_s{QNKYx7x_Vvr>Pai+LfA{vy>sK#dJb(7|$>T>4AKbrp_s;EGH*Z|OcJ<2T zOBXMkKX>-b=~E|996xsS$l*f=5A5H!chBx!J9li~wsp(qO&d3?U$=J6>QyUOEMK;C z$>K!|7tEhGch2ltGiOYnHg(G6NfRgZ_x1L4cXf8Ox3#u3H#IiY*VWckS5;P&mz9GzJE102GaYNdN!< literal 0 HcmV?d00001 diff --git a/images/nav-bg.gif b/images/nav-bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..474396561daa9bebc874426b013e976333fe0153 GIT binary patch literal 1238 zcmZ?wbhEHbG+{7dXkcK_($X?DHC6o29pM|G;F4I92&8T7D+&^mvr|hHl2X$%^K6yg z@7}MZkeOnu6mIHk;9KCFnvv;IRg@ZBBb2320kUN}5%WiyPD~AkS7Qqokz3N?*Ucyj-u` zSTDaQUEk2s(o)~RNZ-gv7pOwFxH7LKu|hYmSQ%!5OKNd)QD#9&W`3Rm$i&2?{L&Iz zC7??oUdSzg8=F_G2lkF$a(=FUMPh-zp`HQAOE87LzW9~q=E7AMmjtCE+>6!V;*iRM zRQ;gT;{4L0QdGl)fawRsgeP1e2cGm(^ML8S2$--L|Nr~@=l8FlKfZta z`sMSdk00K@d;8|~tCugHKYRM*@uPti4*$!dV9LNIy>6iT3ec%8XM~CYHO;iDl5v%N=u513Jdb{a&xk?GBeWC zQd5$X5)DCA|t}XLPLUs0t5X0e0{vVJU!gqTwR=<93AZKY;CNqEG^8*hTC z__d<1|JvQk-S_wrYXxUpIrT POm + + + + + Josh.js by sdether + + + + + + + + + + +

+ +
+ +
+
+

Josh.js

+

Toolkit for building bash-like shell in the browser, including full readline support

+
+ Project maintained by sdether + Hosted on GitHub Pages — Theme by mattgraham +
+ +

josh.js 0.2

+ +

Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components:

+ +
    +
  • +readline.js - full readline support for ctrl sequences, tab, history, etc.
  • +
  • +shell.js - visual presentation of the shell and command handling
  • +
  • +pathhandler.js - provide cd, ls, pwd and path completion toolikit
  • +
  • +history.js - localStorage backed command history
  • +

License

+ +

josh.js is licensed under the Apache 2.0 License

+ +

Status

+ +
    +
  • code is ready for experimental use + +
      +
    • Tested under Chrome, Firefox, Safari and IE9
    • +
    • API may not yet be stable
    • +
    +
  • +
  • needs minified versions of complete toolkit and just readline.js
  • +
  • needs code documentation and documenation site
  • +
  • would like to add AMD support
  • +

Usage

+ +

Until documentation is written, refer to index.html and example.js for a sample implementation of a shell with path completion.

+ +

Components

+ +

josh is built from 4 components and can be used in part or in full.

+ +

readline.js

+ +

readline.js has no dependencies on any outside libraries, although it requires either history.js or an object implementing the same calls.

+ +

It implements key trapping to bring GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with shell.js to create a full console.

+ +

shell.js

+ +

shell.js has external dependencies of jQuery, Underscore and internal dependencies of readline.js and history.js.

+ +

It provides a simple console UI, using a panel for the console viewport and an auto-scrolling view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string.

+ +

It also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, shell.js provides the following commands:

+ +
    +
  • help - list all known commands (including user added)
  • +
  • clear - clear the "screen" i.e. viewport
  • +
  • history - show the command history captured by readline.js in history.js +
  • +

pathhandler.js

+ +

pathhandler.js is a mix in to easily add the cd, ls and pwd commands as well as path completion. It has the same external dependencies of jQuery, Underscore as shell.js and also uses Underscore templating.

+ +

By implementing the functions getNode and getChildNodes, this library adds path traversal, discovery and completion just like a bash shell.

+ +

history.js

+ +

history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the shell.js history command to list all executed commands, and by readline.js for up/down arrow and reverse search capabilities.

+ +

Changelog

+ +

0.2 -- 2013/01/07

+ +
    +
  • console wrapper to allow debug logging to be turned on and off
  • +
  • refactored how pathhandler attaches to shell because it needs to keep a reference to the shell
  • +
  • refactored how prompts are set. now uses dedicated callback rather than returning the prompt in the onEnter callback
  • +
  • tested and made fixes to ensure compatibility with major modern browsers
  • +

0.1 -- 2013/01/04

+ +
    +
  • Initial code-complete release
  • +
+
+ +
+ + + + \ No newline at end of file diff --git a/javascripts/respond.js b/javascripts/respond.js new file mode 100644 index 0000000..76bc260 --- /dev/null +++ b/javascripts/respond.js @@ -0,0 +1,779 @@ +if(typeof Object.create!=="function"){ +Object.create=function(o){ +function F(){ +}; +F.prototype=o; +return new F(); +}; +} +var ua={toString:function(){ +return navigator.userAgent; +},test:function(s){ +return this.toString().toLowerCase().indexOf(s.toLowerCase())>-1; +}}; +ua.version=(ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1]; +ua.webkit=ua.test("webkit"); +ua.gecko=ua.test("gecko")&&!ua.webkit; +ua.opera=ua.test("opera"); +ua.ie=ua.test("msie")&&!ua.opera; +ua.ie6=ua.ie&&document.compatMode&&typeof document.documentElement.style.maxHeight==="undefined"; +ua.ie7=ua.ie&&document.documentElement&&typeof document.documentElement.style.maxHeight!=="undefined"&&typeof XDomainRequest==="undefined"; +ua.ie8=ua.ie&&typeof XDomainRequest!=="undefined"; +var domReady=function(){ +var _1=[]; +var _2=function(){ +if(!arguments.callee.done){ +arguments.callee.done=true; +for(var i=0;i<_1.length;i++){ +_1[i](); +} +} +}; +if(document.addEventListener){ +document.addEventListener("DOMContentLoaded",_2,false); +} +if(ua.ie){ +(function(){ +try{ +document.documentElement.doScroll("left"); +} +catch(e){ +setTimeout(arguments.callee,50); +return; +} +_2(); +})(); +document.onreadystatechange=function(){ +if(document.readyState==="complete"){ +document.onreadystatechange=null; +_2(); +} +}; +} +if(ua.webkit&&document.readyState){ +(function(){ +if(document.readyState!=="loading"){ +_2(); +}else{ +setTimeout(arguments.callee,10); +} +})(); +} +window.onload=_2; +return function(fn){ +if(typeof fn==="function"){ +_1[_1.length]=fn; +} +return fn; +}; +}(); +var cssHelper=function(){ +var _3={BLOCKS:/[^\s{][^{]*\{(?:[^{}]*\{[^{}]*\}[^{}]*|[^{}]*)*\}/g,BLOCKS_INSIDE:/[^\s{][^{]*\{[^{}]*\}/g,DECLARATIONS:/[a-zA-Z\-]+[^;]*:[^;]+;/g,RELATIVE_URLS:/url\(['"]?([^\/\)'"][^:\)'"]+)['"]?\)/g,REDUNDANT_COMPONENTS:/(?:\/\*([^*\\\\]|\*(?!\/))+\*\/|@import[^;]+;)/g,REDUNDANT_WHITESPACE:/\s*(,|:|;|\{|\})\s*/g,MORE_WHITESPACE:/\s{2,}/g,FINAL_SEMICOLONS:/;\}/g,NOT_WHITESPACE:/\S+/g}; +var _4,_5=false; +var _6=[]; +var _7=function(fn){ +if(typeof fn==="function"){ +_6[_6.length]=fn; +} +}; +var _8=function(){ +for(var i=0;i<_6.length;i++){ +_6[i](_4); +} +}; +var _9={}; +var _a=function(n,v){ +if(_9[n]){ +var _b=_9[n].listeners; +if(_b){ +for(var i=0;i<_b.length;i++){ +_b[i](v); +} +} +} +}; +var _c=function(_d,_e,_f){ +if(ua.ie&&!window.XMLHttpRequest){ +window.XMLHttpRequest=function(){ +return new ActiveXObject("Microsoft.XMLHTTP"); +}; +} +if(!XMLHttpRequest){ +return ""; +} +var r=new XMLHttpRequest(); +try{ +r.open("get",_d,true); +r.setRequestHeader("X_REQUESTED_WITH","XMLHttpRequest"); +} +catch(e){ +_f(); +return; +} +var _10=false; +setTimeout(function(){ +_10=true; +},5000); +document.documentElement.style.cursor="progress"; +r.onreadystatechange=function(){ +if(r.readyState===4&&!_10){ +if(!r.status&&location.protocol==="file:"||(r.status>=200&&r.status<300)||r.status===304||navigator.userAgent.indexOf("Safari")>-1&&typeof r.status==="undefined"){ +_e(r.responseText); +}else{ +_f(); +} +document.documentElement.style.cursor=""; +r=null; +} +}; +r.send(""); +}; +var _11=function(_12){ +_12=_12.replace(_3.REDUNDANT_COMPONENTS,""); +_12=_12.replace(_3.REDUNDANT_WHITESPACE,"$1"); +_12=_12.replace(_3.MORE_WHITESPACE," "); +_12=_12.replace(_3.FINAL_SEMICOLONS,"}"); +return _12; +}; +var _13={mediaQueryList:function(s){ +var o={}; +var idx=s.indexOf("{"); +var lt=s.substring(0,idx); +s=s.substring(idx+1,s.length-1); +var mqs=[],rs=[]; +var qts=lt.toLowerCase().substring(7).split(","); +for(var i=0;i-1&&_23.href&&_23.href.length!==0&&!_23.disabled){ +_1f[_1f.length]=_23; +} +} +if(_1f.length>0){ +var c=0; +var _24=function(){ +c++; +if(c===_1f.length){ +_20(); +} +}; +var _25=function(_26){ +var _27=_26.href; +_c(_27,function(_28){ +_28=_11(_28).replace(_3.RELATIVE_URLS,"url("http://github.com/+_27.substring(0,_27.lastIndexOf(%22/"))+"/$1)"); +_26.cssHelperText=_28; +_24(); +},_24); +}; +for(i=0;i<_1f.length;i++){ +_25(_1f[i]); +} +}else{ +_20(); +} +}; +var _29={mediaQueryLists:"array",rules:"array",selectors:"object",declarations:"array",properties:"object"}; +var _2a={mediaQueryLists:null,rules:null,selectors:null,declarations:null,properties:null}; +var _2b=function(_2c,v){ +if(_2a[_2c]!==null){ +if(_29[_2c]==="array"){ +return (_2a[_2c]=_2a[_2c].concat(v)); +}else{ +var c=_2a[_2c]; +for(var n in v){ +if(v.hasOwnProperty(n)){ +if(!c[n]){ +c[n]=v[n]; +}else{ +c[n]=c[n].concat(v[n]); +} +} +} +return c; +} +} +}; +var _2d=function(_2e){ +_2a[_2e]=(_29[_2e]==="array")?[]:{}; +for(var i=0;i<_4.length;i++){ +_2b(_2e,_4[i].cssHelperParsed[_2e]); +} +return _2a[_2e]; +}; +domReady(function(){ +var els=document.body.getElementsByTagName("*"); +for(var i=0;i=_44)||(max&&_46<_44)||(!min&&!max&&_46===_44)); +}else{ +return false; +} +}else{ +return _46>0; +} +}else{ +if("device-height"===_41.substring(l-13,l)){ +_47=screen.height; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_47>=_44)||(max&&_47<_44)||(!min&&!max&&_47===_44)); +}else{ +return false; +} +}else{ +return _47>0; +} +}else{ +if("width"===_41.substring(l-5,l)){ +_46=document.documentElement.clientWidth||document.body.clientWidth; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_46>=_44)||(max&&_46<_44)||(!min&&!max&&_46===_44)); +}else{ +return false; +} +}else{ +return _46>0; +} +}else{ +if("height"===_41.substring(l-6,l)){ +_47=document.documentElement.clientHeight||document.body.clientHeight; +if(_42!==null){ +if(_43==="length"){ +return ((min&&_47>=_44)||(max&&_47<_44)||(!min&&!max&&_47===_44)); +}else{ +return false; +} +}else{ +return _47>0; +} +}else{ +if("device-aspect-ratio"===_41.substring(l-19,l)){ +return _43==="aspect-ratio"&&screen.width*_44[1]===screen.height*_44[0]; +}else{ +if("color-index"===_41.substring(l-11,l)){ +var _48=Math.pow(2,screen.colorDepth); +if(_42!==null){ +if(_43==="absolute"){ +return ((min&&_48>=_44)||(max&&_48<_44)||(!min&&!max&&_48===_44)); +}else{ +return false; +} +}else{ +return _48>0; +} +}else{ +if("color"===_41.substring(l-5,l)){ +var _49=screen.colorDepth; +if(_42!==null){ +if(_43==="absolute"){ +return ((min&&_49>=_44)||(max&&_49<_44)||(!min&&!max&&_49===_44)); +}else{ +return false; +} +}else{ +return _49>0; +} +}else{ +if("resolution"===_41.substring(l-10,l)){ +var res; +if(_45==="dpcm"){ +res=_3d("1cm"); +}else{ +res=_3d("1in"); +} +if(_42!==null){ +if(_43==="resolution"){ +return ((min&&res>=_44)||(max&&res<_44)||(!min&&!max&&res===_44)); +}else{ +return false; +} +}else{ +return res>0; +} +}else{ +return false; +} +} +} +} +} +} +} +} +}; +var _4a=function(mq){ +var _4b=mq.getValid(); +var _4c=mq.getExpressions(); +var l=_4c.length; +if(l>0){ +for(var i=0;i0){ +s[c++]=","; +} +s[c++]=n; +} +} +if(s.length>0){ +_39[_39.length]=cssHelper.addStyle("@media "+s.join("")+"{"+mql.getCssText()+"}",false); +} +}; +var _4e=function(_4f){ +for(var i=0;i<_4f.length;i++){ +_4d(_4f[i]); +} +if(ua.ie){ +document.documentElement.style.display="block"; +setTimeout(function(){ +document.documentElement.style.display=""; +},0); +setTimeout(function(){ +cssHelper.broadcast("cssMediaQueriesTested"); +},100); +}else{ +cssHelper.broadcast("cssMediaQueriesTested"); +} +}; +var _50=function(){ +for(var i=0;i<_39.length;i++){ +cssHelper.removeStyle(_39[i]); +} +_39=[]; +cssHelper.mediaQueryLists(_4e); +}; +var _51=0; +var _52=function(){ +var _53=cssHelper.getViewportWidth(); +var _54=cssHelper.getViewportHeight(); +if(ua.ie){ +var el=document.createElement("div"); +el.style.position="absolute"; +el.style.top="-9999em"; +el.style.overflow="scroll"; +document.body.appendChild(el); +_51=el.offsetWidth-el.clientWidth; +document.body.removeChild(el); +} +var _55; +var _56=function(){ +var vpw=cssHelper.getViewportWidth(); +var vph=cssHelper.getViewportHeight(); +if(Math.abs(vpw-_53)>_51||Math.abs(vph-_54)>_51){ +_53=vpw; +_54=vph; +clearTimeout(_55); +_55=setTimeout(function(){ +if(!_3a()){ +_50(); +}else{ +cssHelper.broadcast("cssMediaQueriesTested"); +} +},500); +} +}; +window.onresize=function(){ +var x=window.onresize||function(){ +}; +return function(){ +x(); +_56(); +}; +}(); +}; +var _57=document.documentElement; +_57.style.marginLeft="-32767px"; +setTimeout(function(){ +_57.style.marginTop=""; +},20000); +return function(){ +if(!_3a()){ +cssHelper.addListener("newStyleParsed",function(el){ +_4e(el.cssHelperParsed.mediaQueryLists); +}); +cssHelper.addListener("cssMediaQueriesTested",function(){ +if(ua.ie){ +_57.style.width="1px"; +} +setTimeout(function(){ +_57.style.width=""; +_57.style.marginLeft=""; +},0); +cssHelper.removeListener("cssMediaQueriesTested",arguments.callee); +}); +_3c(); +_50(); +}else{ +_57.style.marginLeft=""; +} +_52(); +}; +}()); +try{ +document.execCommand("BackgroundImageCache",false,true); +} +catch(e){ +} + diff --git a/params.json b/params.json new file mode 100644 index 0000000..c07f8ae --- /dev/null +++ b/params.json @@ -0,0 +1 @@ +{"note":"Don't delete this file! It's used internally to help with page regeneration.","body":"josh.js 0.2\r\n===========\r\n\r\n***Javascript Online SHell*** provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components:\r\n\r\n* `readline.js` - full readline support for ctrl sequences, tab, history, etc.\r\n* `shell.js` - visual presentation of the shell and command handling\r\n* `pathhandler.js` - provide cd, ls, pwd and path completion toolikit\r\n* `history.js` - localStorage backed command history\r\n\r\n## License\r\njosh.js is licensed under the Apache 2.0 License\r\n\r\n## Status\r\n\r\n* code is ready for experimental use\r\n * Tested under Chrome, Firefox, Safari and IE9\r\n * API may not yet be stable\r\n* needs minified versions of complete toolkit and just readline.js\r\n* needs code documentation and documenation site\r\n* would like to add AMD support\r\n\r\n## Usage\r\n\r\nUntil documentation is written, refer to `index.html` and `example.js` for a sample implementation of a shell with path completion.\r\n\r\n## Components\r\n***josh*** is built from 4 components and can be used in part or in full.\r\n\r\n### readline.js\r\n\r\n`readline.js` has no dependencies on any outside libraries, although it requires either `history.js` or an object implementing the same calls.\r\n\r\nIt implements key trapping to bring [GNU Readline](http://cnswww.cns.cwru.edu/php/chet/readline/readline.html) like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with `shell.js` to create a full console.\r\n\r\n### shell.js\r\n`shell.js` has external dependencies of [jQuery](http://jquery.com/), [Underscore](http://underscorejs.org/) and internal dependencies of `readline.js` and `history.js`.\r\n\r\nIt provides a simple console UI, using a *panel* for the console viewport and an auto-scrolling *view* inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string.\r\n\r\nIt also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, `shell.js` provides the following commands:\r\n* help - list all known commands (including user added)\r\n* clear - clear the \"screen\" i.e. viewport\r\n* history - show the command history captured by `readline.js` in `history.js`\r\n\r\n### pathhandler.js\r\n`pathhandler.js` is a mix in to easily add the `cd`, `ls` and `pwd` commands as well as path completion. It has the same external dependencies of [jQuery](http://jquery.com/), [Underscore](http://underscorejs.org/) as `shell.js` and also uses Underscore templating.\r\n\r\nBy implementing the functions `getNode` and `getChildNodes`, this library adds path traversal, discovery and completion just like a bash shell.\r\n\r\n### history.js\r\n`history.js` implements a localStorage back command history storage that persists over page changes and reloads. It is used by the `shell.js` history command to list all executed commands, and by `readline.js` for up/down arrow and reverse search capabilities.\r\n\r\n## Changelog\r\n\r\n**0.2** -- 2013/01/07\r\n* console wrapper to allow debug logging to be turned on and off\r\n* refactored how pathhandler attaches to shell because it needs to keep a reference to the shell\r\n* refactored how prompts are set. now uses dedicated callback rather than returning the prompt in the `onEnter` callback\r\n* tested and made fixes to ensure compatibility with major modern browsers\r\n\r\n**0.1** -- 2013/01/04\r\n* Initial code-complete release\r\n","name":"Josh.js","google":"","tagline":"Toolkit for building bash-like shell in the browser, including full readline support"} \ No newline at end of file diff --git a/stylesheets/ie.css b/stylesheets/ie.css new file mode 100644 index 0000000..43882f2 --- /dev/null +++ b/stylesheets/ie.css @@ -0,0 +1,3 @@ +nav { + display: none; +} diff --git a/stylesheets/normalize.css b/stylesheets/normalize.css new file mode 100644 index 0000000..bc2ba93 --- /dev/null +++ b/stylesheets/normalize.css @@ -0,0 +1,459 @@ +/* normalize.css 2012-02-07T12:37 UTC - http://github.com/necolas/normalize.css */ +/* ============================================================================= + HTML5 display definitions + ========================================================================== */ +/* + * Corrects block display not defined in IE6/7/8/9 & FF3 + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects inline-block display not defined in IE6/7/8/9 & FF3 + */ +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/* + * Prevents modern browsers from displaying 'audio' without controls + */ +audio:not([controls]) { + display: none; +} + +/* + * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4 + * Known issue: no IE6 support + */ +[hidden] { + display: none; +} + +/* ============================================================================= + Base + ========================================================================== */ +/* + * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units + * http://clagnut.com/blog/348/#c790 + * 2. Prevents iOS text size adjust after orientation change, without disabling user zoom + * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ + */ +html { + font-size: 100%; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -ms-text-size-adjust: 100%; + /* 2 */ +} + +/* + * Addresses font-family inconsistency between 'textarea' and other form elements. + */ +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/* + * Addresses margins handled incorrectly in IE6/7 + */ +body { + margin: 0; +} + +/* ============================================================================= + Links + ========================================================================== */ +/* + * Addresses outline displayed oddly in Chrome + */ +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers + * people.opera.com/patrickl/experiments/keyboard/test + */ +a:hover, +a:active { + outline: 0; +} + +/* ============================================================================= + Typography + ========================================================================== */ +/* + * Addresses font sizes and margins set differently in IE6/7 + * Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5 + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.75em; + margin: 2.33em 0; +} + +/* + * Addresses styling not present in IE7/8/9, S5, Chrome + */ +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to 'bolder' in FF3+, S4/5, Chrome +*/ +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/* + * Addresses styling not present in S5, Chrome + */ +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE6/7/8/9 + */ +mark { + background: #ff0; + color: #000; +} + +/* + * Addresses margins set differently in IE6/7 + */ +p, +pre { + margin: 1em 0; +} + +/* + * Corrects font family set oddly in IE6, S4/5, Chrome + * en.wikipedia.org/wiki/User:Davidgothberg/Test59 + */ +pre, +code, +kbd, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/* + * 1. Addresses CSS quotes not supported in IE6/7 + * 2. Addresses quote property not supported in S4 + */ +/* 1 */ +q { + quotes: none; +} + +/* 2 */ +q:before, +q:after { + content: ''; + content: none; +} + +small { + font-size: 75%; +} + +/* + * Prevents sub and sup affecting line-height in all browsers + * gist.github.com/413930 + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ============================================================================= + Lists + ========================================================================== */ +/* + * Addresses margins set differently in IE6/7 + */ +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/* + * Addresses paddings set differently in IE6/7 + */ +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/* + * Corrects list images handled incorrectly in IE7 + */ +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ============================================================================= + Embedded content + ========================================================================== */ +/* + * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3 + * 2. Improves image quality when scaled in IE7 + * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ + */ +img { + border: 0; + /* 1 */ + -ms-interpolation-mode: bicubic; + /* 2 */ +} + +/* + * Corrects overflow displayed oddly in IE9 + */ +svg:not(:root) { + overflow: hidden; +} + +/* ============================================================================= + Figures + ========================================================================== */ +/* + * Addresses margin not present in IE6/7/8/9, S5, O11 + */ +figure { + margin: 0; +} + +/* ============================================================================= + Forms + ========================================================================== */ +/* + * Corrects margin displayed oddly in IE6/7 + */ +form { + margin: 0; +} + +/* + * Define consistent border, margin, and padding + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE6/7/8/9 + * 2. Corrects text not wrapping in FF3 + * 3. Corrects alignment displayed oddly in IE6/7 + */ +legend { + border: 0; + /* 1 */ + padding: 0; + white-space: normal; + /* 2 */ + *margin-left: -7px; + /* 3 */ +} + +/* + * 1. Corrects font size not being inherited in all browsers + * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome + * 3. Improves appearance and consistency in all browsers + */ +button, +input, +select, +textarea { + font-size: 100%; + /* 1 */ + margin: 0; + /* 2 */ + vertical-align: baseline; + /* 3 */ + *vertical-align: middle; + /* 3 */ +} + +/* + * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet + */ +button, +input { + line-height: normal; + /* 1 */ +} + +/* + * 1. Improves usability and consistency of cursor style between image-type 'input' and others + * 2. Corrects inability to style clickable 'input' types in iOS + * 3. Removes inner spacing in IE7 without affecting normal text inputs + * Known issue: inner spacing remains in IE6 + */ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + /* 1 */ + -webkit-appearance: button; + /* 2 */ + *overflow: visible; + /* 3 */ +} + +/* + * Re-set default cursor for disabled elements + */ +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to content-box in IE8/9 + * 2. Removes excess padding in IE8/9 + * 3. Removes excess padding in IE7 + Known issue: excess padding remains in IE6 + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ + *height: 13px; + /* 3 */ + *width: 13px; + /* 3 */ +} + +/* + * 1. Addresses appearance set to searchfield in S5, Chrome + * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof) + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in S5, Chrome on OS X + */ +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in FF3+ + * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/ + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE6/7/8/9 + * 2. Improves readability and alignment in all browsers + */ +textarea { + overflow: auto; + /* 1 */ + vertical-align: top; + /* 2 */ +} + +/* ============================================================================= + Tables + ========================================================================== */ +/* + * Remove most spacing between table cells + */ +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css new file mode 100644 index 0000000..c79bef4 --- /dev/null +++ b/stylesheets/pygment_trac.css @@ -0,0 +1,70 @@ +.highlight .hll { background-color: #404040 } +.highlight { color: #d0d0d0 } +.highlight .c { color: #999999; font-style: italic } /* Comment */ +.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight .g { color: #d0d0d0 } /* Generic */ +.highlight .k { color: #6ab825; font-weight: normal } /* Keyword */ +.highlight .l { color: #d0d0d0 } /* Literal */ +.highlight .n { color: #d0d0d0 } /* Name */ +.highlight .o { color: #d0d0d0 } /* Operator */ +.highlight .x { color: #d0d0d0 } /* Other */ +.highlight .p { color: #d0d0d0 } /* Punctuation */ +.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #cd2828; font-weight: normal } /* Comment.Preproc */ +.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #e50808; font-weight: normal; background-color: #520000 } /* Comment.Special */ +.highlight .gd { color: #d22323 } /* Generic.Deleted */ +.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #d22323 } /* Generic.Error */ +.highlight .gh { color: #ffffff; font-weight: normal } /* Generic.Heading */ +.highlight .gi { color: #589819 } /* Generic.Inserted */ +.highlight .go { color: #cccccc } /* Generic.Output */ +.highlight .gp { color: #aaaaaa } /* Generic.Prompt */ +.highlight .gs { color: #d0d0d0; font-weight: normal } /* Generic.Strong */ +.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ +.highlight .gt { color: #d22323 } /* Generic.Traceback */ +.highlight .kc { color: #6ab825; font-weight: normal } /* Keyword.Constant */ +.highlight .kd { color: #6ab825; font-weight: normal } /* Keyword.Declaration */ +.highlight .kn { color: #6ab825; font-weight: normal } /* Keyword.Namespace */ +.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */ +.highlight .kr { color: #6ab825; font-weight: normal } /* Keyword.Reserved */ +.highlight .kt { color: #6ab825; font-weight: normal } /* Keyword.Type */ +.highlight .ld { color: #d0d0d0 } /* Literal.Date */ +.highlight .m { color: #3677a9 } /* Literal.Number */ +.highlight .s { color: #9dd5f1 } /* Literal.String */ +.highlight .na { color: #bbbbbb } /* Name.Attribute */ +.highlight .nb { color: #24909d } /* Name.Builtin */ +.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */ +.highlight .no { color: #40ffff } /* Name.Constant */ +.highlight .nd { color: #ffa500 } /* Name.Decorator */ +.highlight .ni { color: #d0d0d0 } /* Name.Entity */ +.highlight .ne { color: #bbbbbb } /* Name.Exception */ +.highlight .nf { color: #447fcf } /* Name.Function */ +.highlight .nl { color: #d0d0d0 } /* Name.Label */ +.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */ +.highlight .nx { color: #d0d0d0 } /* Name.Other */ +.highlight .py { color: #d0d0d0 } /* Name.Property */ +.highlight .nt { color: #6ab825;} /* Name.Tag */ +.highlight .nv { color: #40ffff } /* Name.Variable */ +.highlight .ow { color: #6ab825; font-weight: normal } /* Operator.Word */ +.highlight .w { color: #666666 } /* Text.Whitespace */ +.highlight .mf { color: #3677a9 } /* Literal.Number.Float */ +.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */ +.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */ +.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */ +.highlight .sb { color: #9dd5f1 } /* Literal.String.Backtick */ +.highlight .sc { color: #9dd5f1 } /* Literal.String.Char */ +.highlight .sd { color: #9dd5f1 } /* Literal.String.Doc */ +.highlight .s2 { color: #9dd5f1 } /* Literal.String.Double */ +.highlight .se { color: #9dd5f1 } /* Literal.String.Escape */ +.highlight .sh { color: #9dd5f1 } /* Literal.String.Heredoc */ +.highlight .si { color: #9dd5f1 } /* Literal.String.Interpol */ +.highlight .sx { color: #ffa500 } /* Literal.String.Other */ +.highlight .sr { color: #9dd5f1 } /* Literal.String.Regex */ +.highlight .s1 { color: #9dd5f1 } /* Literal.String.Single */ +.highlight .ss { color: #9dd5f1 } /* Literal.String.Symbol */ +.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #40ffff } /* Name.Variable.Class */ +.highlight .vg { color: #40ffff } /* Name.Variable.Global */ +.highlight .vi { color: #40ffff } /* Name.Variable.Instance */ +.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/stylesheets/styles.css b/stylesheets/styles.css new file mode 100644 index 0000000..e7b4ffc --- /dev/null +++ b/stylesheets/styles.css @@ -0,0 +1,851 @@ +@font-face { + font-family: 'OpenSansLight'; + src: url("http://github.com/fonts/OpenSans-Light-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-Light-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Light-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Light-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Light-webfont.svg#OpenSansLight") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'OpenSansLightItalic'; + src: url("http://github.com/fonts/OpenSans-LightItalic-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-LightItalic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-LightItalic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-LightItalic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-LightItalic-webfont.svg#OpenSansLightItalic") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'OpenSansRegular'; + src: url("http://github.com/fonts/OpenSans-Regular-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-Regular-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Regular-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Regular-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Regular-webfont.svg#OpenSansRegular") format("svg"); + font-weight: normal; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +@font-face { + font-family: 'OpenSansItalic'; + src: url("http://github.com/fonts/OpenSans-Italic-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-Italic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Italic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Italic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Italic-webfont.svg#OpenSansItalic") format("svg"); + font-weight: normal; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +@font-face { + font-family: 'OpenSansSemibold'; + src: url("http://github.com/fonts/OpenSans-Semibold-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-Semibold-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Semibold-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Semibold-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Semibold-webfont.svg#OpenSansSemibold") format("svg"); + font-weight: normal; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +@font-face { + font-family: 'OpenSansSemiboldItalic'; + src: url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.svg#OpenSansSemiboldItalic") format("svg"); + font-weight: normal; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +@font-face { + font-family: 'OpenSansBold'; + src: url("http://github.com/fonts/OpenSans-Bold-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-Bold-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Bold-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Bold-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Bold-webfont.svg#OpenSansBold") format("svg"); + font-weight: normal; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +@font-face { + font-family: 'OpenSansBoldItalic'; + src: url("http://github.com/fonts/OpenSans-BoldItalic-webfont.eot"); + src: url("http://github.com/fonts/OpenSans-BoldItalic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-BoldItalic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-BoldItalic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-BoldItalic-webfont.svg#OpenSansBoldItalic") format("svg"); + font-weight: normal; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +/* normalize.css 2012-02-07T12:37 UTC - http://github.com/necolas/normalize.css */ +/* ============================================================================= + HTML5 display definitions + ========================================================================== */ +/* + * Corrects block display not defined in IE6/7/8/9 & FF3 + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects inline-block display not defined in IE6/7/8/9 & FF3 + */ +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/* + * Prevents modern browsers from displaying 'audio' without controls + */ +audio:not([controls]) { + display: none; +} + +/* + * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4 + * Known issue: no IE6 support + */ +[hidden] { + display: none; +} + +/* ============================================================================= + Base + ========================================================================== */ +/* + * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units + * http://clagnut.com/blog/348/#c790 + * 2. Prevents iOS text size adjust after orientation change, without disabling user zoom + * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ + */ +html { + font-size: 100%; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -ms-text-size-adjust: 100%; + /* 2 */ +} + +/* + * Addresses font-family inconsistency between 'textarea' and other form elements. + */ +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/* + * Addresses margins handled incorrectly in IE6/7 + */ +body { + margin: 0; +} + +/* ============================================================================= + Links + ========================================================================== */ +/* + * Addresses outline displayed oddly in Chrome + */ +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers + * people.opera.com/patrickl/experiments/keyboard/test + */ +a:hover, +a:active { + outline: 0; +} + +/* ============================================================================= + Typography + ========================================================================== */ +/* + * Addresses font sizes and margins set differently in IE6/7 + * Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5 + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.75em; + margin: 2.33em 0; +} + +/* + * Addresses styling not present in IE7/8/9, S5, Chrome + */ +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to 'bolder' in FF3+, S4/5, Chrome +*/ +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/* + * Addresses styling not present in S5, Chrome + */ +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE6/7/8/9 + */ +mark { + background: #ff0; + color: #000; +} + +/* + * Addresses margins set differently in IE6/7 + */ +p, +pre { + margin: 1em 0; +} + +/* + * Corrects font family set oddly in IE6, S4/5, Chrome + * en.wikipedia.org/wiki/User:Davidgothberg/Test59 + */ +pre, +code, +kbd, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/* + * 1. Addresses CSS quotes not supported in IE6/7 + * 2. Addresses quote property not supported in S4 + */ +/* 1 */ +q { + quotes: none; +} + +/* 2 */ +q:before, +q:after { + content: ''; + content: none; +} + +small { + font-size: 75%; +} + +/* + * Prevents sub and sup affecting line-height in all browsers + * gist.github.com/413930 + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ============================================================================= + Lists + ========================================================================== */ +/* + * Addresses margins set differently in IE6/7 + */ +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/* + * Addresses paddings set differently in IE6/7 + */ +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/* + * Corrects list images handled incorrectly in IE7 + */ +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ============================================================================= + Embedded content + ========================================================================== */ +/* + * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3 + * 2. Improves image quality when scaled in IE7 + * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ + */ +img { + border: 0; + /* 1 */ + -ms-interpolation-mode: bicubic; + /* 2 */ +} + +/* + * Corrects overflow displayed oddly in IE9 + */ +svg:not(:root) { + overflow: hidden; +} + +/* ============================================================================= + Figures + ========================================================================== */ +/* + * Addresses margin not present in IE6/7/8/9, S5, O11 + */ +figure { + margin: 0; +} + +/* ============================================================================= + Forms + ========================================================================== */ +/* + * Corrects margin displayed oddly in IE6/7 + */ +form { + margin: 0; +} + +/* + * Define consistent border, margin, and padding + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE6/7/8/9 + * 2. Corrects text not wrapping in FF3 + * 3. Corrects alignment displayed oddly in IE6/7 + */ +legend { + border: 0; + /* 1 */ + padding: 0; + white-space: normal; + /* 2 */ + *margin-left: -7px; + /* 3 */ +} + +/* + * 1. Corrects font size not being inherited in all browsers + * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome + * 3. Improves appearance and consistency in all browsers + */ +button, +input, +select, +textarea { + font-size: 100%; + /* 1 */ + margin: 0; + /* 2 */ + vertical-align: baseline; + /* 3 */ + *vertical-align: middle; + /* 3 */ +} + +/* + * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet + */ +button, +input { + line-height: normal; + /* 1 */ +} + +/* + * 1. Improves usability and consistency of cursor style between image-type 'input' and others + * 2. Corrects inability to style clickable 'input' types in iOS + * 3. Removes inner spacing in IE7 without affecting normal text inputs + * Known issue: inner spacing remains in IE6 + */ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + /* 1 */ + -webkit-appearance: button; + /* 2 */ + *overflow: visible; + /* 3 */ +} + +/* + * Re-set default cursor for disabled elements + */ +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to content-box in IE8/9 + * 2. Removes excess padding in IE8/9 + * 3. Removes excess padding in IE7 + Known issue: excess padding remains in IE6 + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ + *height: 13px; + /* 3 */ + *width: 13px; + /* 3 */ +} + +/* + * 1. Addresses appearance set to searchfield in S5, Chrome + * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof) + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in S5, Chrome on OS X + */ +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in FF3+ + * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/ + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE6/7/8/9 + * 2. Improves readability and alignment in all browsers + */ +textarea { + overflow: auto; + /* 1 */ + vertical-align: top; + /* 2 */ +} + +/* ============================================================================= + Tables + ========================================================================== */ +/* + * Remove most spacing between table cells + */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +body { + padding: 0px 0 20px 0px; + margin: 0px; + font: 14px/1.5 "OpenSansRegular", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #f0e7d5; + font-weight: normal; + background: #252525; + background-attachment: fixed !important; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2a2a29), color-stop(100%, #1c1c1c)); + background: -webkit-linear-gradient(#2a2a29, #1c1c1c); + background: -moz-linear-gradient(#2a2a29, #1c1c1c); + background: -o-linear-gradient(#2a2a29, #1c1c1c); + background: -ms-linear-gradient(#2a2a29, #1c1c1c); + background: linear-gradient(#2a2a29, #1c1c1c); +} + +h1, h2, h3, h4, h5, h6 { + color: #e8e8e8; + margin: 0 0 10px; + font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; +} + +p, ul, ol, table, pre, dl { + margin: 0 0 20px; +} + +h1, h2, h3 { + line-height: 1.1; +} + +h1 { + font-size: 28px; +} + +h2 { + font-size: 24px; +} + +h4, h5, h6 { + color: #e8e8e8; +} + +h3 { + font-size: 18px; + line-height: 24px; + font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; + color: #b6b6b6; +} + +a { + color: #ffcc00; + font-weight: 400; + text-decoration: none; +} +a:hover { + color: #ffeb9b; +} + +a small { + font-size: 11px; + color: #666; + margin-top: -0.6em; + display: block; +} + +ul { + list-style-image: url("http://github.com/images/bullet.png"); +} + +strong { + font-family: 'OpenSansBold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; +} + +.wrapper { + max-width: 650px; + margin: 0 auto; + position: relative; + padding: 0 20px; +} + +section img { + max-width: 100%; +} + +blockquote { + border-left: 3px solid #ffcc00; + margin: 0; + padding: 0 0 0 20px; + font-style: italic; +} + +code { + font-family: "Lucida Sans", Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal; + color: #efefef; + font-size: 13px; + margin: 0 4px; + padding: 4px 6px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} + +pre { + padding: 8px 15px; + background: #191919; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; + border: 1px solid #121212; + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); + overflow: auto; + overflow-y: hidden; +} +pre code { + color: #efefef; + text-shadow: 0px 1px 0px #000; + margin: 0; + padding: 0; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th { + text-align: left; + padding: 5px 10px; + border-bottom: 1px solid #434343; + color: #b6b6b6; + font-family: 'OpenSansSemibold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; +} + +td { + text-align: left; + padding: 5px 10px; + border-bottom: 1px solid #434343; +} + +hr { + border: 0; + outline: none; + height: 3px; + background: transparent url("http://github.com/images/hr.gif") center center repeat-x; + margin: 0 0 20px; +} + +dt { + color: #F0E7D5; + font-family: 'OpenSansSemibold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; +} + +#header { + z-index: 100; + left: 0; + top: 0px; + height: 60px; + width: 100%; + position: fixed; + background: url(http://github.com/images/nav-bg.gif) #353535; + border-bottom: 4px solid #434343; + -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -o-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); +} +#header nav { + max-width: 650px; + margin: 0 auto; + padding: 0 10px; + background: blue; + margin: 6px auto; +} +#header nav li { + font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + list-style: none; + display: inline; + color: white; + line-height: 50px; + text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.2); + font-size: 14px; +} +#header nav li a { + color: white; + border: 1px solid #5d910b; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #93bd20), color-stop(100%, #659e10)); + background: -webkit-linear-gradient(#93bd20, #659e10); + background: -moz-linear-gradient(#93bd20, #659e10); + background: -o-linear-gradient(#93bd20, #659e10); + background: -ms-linear-gradient(#93bd20, #659e10); + background: linear-gradient(#93bd20, #659e10); + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; + -moz-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + -webkit-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + -o-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + background-color: #93bd20; + padding: 10px 12px; + margin-top: 6px; + line-height: 14px; + font-size: 14px; + display: inline-block; + text-align: center; +} +#header nav li a:hover { + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #749619), color-stop(100%, #527f0e)); + background: -webkit-linear-gradient(#749619, #527f0e); + background: -moz-linear-gradient(#749619, #527f0e); + background: -o-linear-gradient(#749619, #527f0e); + background: -ms-linear-gradient(#749619, #527f0e); + background: linear-gradient(#749619, #527f0e); + background-color: #659e10; + border: 1px solid #527f0e; + -moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + -webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + -o-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); +} +#header nav li.fork { + float: left; + margin-left: 0px; +} +#header nav li.downloads { + float: right; + margin-left: 6px; +} +#header nav li.title { + float: right; + margin-right: 10px; + font-size: 11px; +} + +section { + max-width: 650px; + padding: 30px 0px 50px 0px; + margin: 20px 0; + margin-top: 70px; +} +section #title { + border: 0; + outline: none; + margin: 0 0 50px 0; + padding: 0 0 5px 0; +} +section #title h1 { + font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + font-size: 40px; + text-align: center; + line-height: 36px; +} +section #title p { + color: #d7cfbe; + font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + font-size: 18px; + text-align: center; +} +section #title .credits { + font-size: 11px; + font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + color: #696969; + margin-top: -10px; +} +section #title .credits.left { + float: left; +} +section #title .credits.right { + float: right; +} + +@media print, screen and (max-width: 720px) { + #title .credits { + display: block; + width: 100%; + line-height: 30px; + text-align: center; + } + #title .credits .left { + float: none; + display: block; + } + #title .credits .right { + float: none; + display: block; + } +} +@media print, screen and (max-width: 480px) { + #header { + margin-top: -20px; + } + + section { + margin-top: 40px; + } + + nav { + display: none; + } +} From 1b3368d9a4d481f7c365fe763e8a2fe4bc7f3856 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Tue, 8 Jan 2013 21:52:18 -0800 Subject: [PATCH 02/26] added demo to site --- .gitignore | 3 + .idea/encodings.xml | 5 + .idea/josh.js-pages.iml | 9 + .idea/libraries/sass_stdlib.xml | 8 + .idea/misc.xml | 8 + .idea/modules.xml | 9 + .idea/scopes/scope_settings.xml | 5 + .idea/vcs.xml | 7 + index.html | 213 +++++++---- javascripts/example.js | 155 ++++++++ javascripts/history.js | 145 +++++++ javascripts/pathhandler.js | 157 ++++++++ javascripts/readline.js | 653 ++++++++++++++++++++++++++++++++ javascripts/shell.js | 392 +++++++++++++++++++ stylesheets/styles.css | 6 + 15 files changed, 1693 insertions(+), 82 deletions(-) create mode 100644 .gitignore create mode 100644 .idea/encodings.xml create mode 100644 .idea/josh.js-pages.iml create mode 100644 .idea/libraries/sass_stdlib.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/scopes/scope_settings.xml create mode 100644 .idea/vcs.xml create mode 100644 javascripts/example.js create mode 100644 javascripts/history.js create mode 100644 javascripts/pathhandler.js create mode 100644 javascripts/readline.js create mode 100644 javascripts/shell.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28fdb01 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/workspace.xml +.idea/tasks.xml +.DS_Store \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..7c62b52 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.idea/josh.js-pages.iml b/.idea/josh.js-pages.iml new file mode 100644 index 0000000..3b09ca3 --- /dev/null +++ b/.idea/josh.js-pages.iml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/libraries/sass_stdlib.xml b/.idea/libraries/sass_stdlib.xml new file mode 100644 index 0000000..8962a7d --- /dev/null +++ b/.idea/libraries/sass_stdlib.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..5cf522e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + jar:file:\C:\Program Files (x86)\JetBrains\WebStorm 5.0.2\lib\webide.jar!\resources\html5-schema\html5.rnc + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..798cf33 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..0d5175c --- /dev/null +++ b/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..ab55cf1 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/index.html b/index.html index 57d19be..18ff58d 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ - + Josh.js by sdether @@ -9,120 +9,169 @@ - - - - - -
- -
+ + + + + + + + + + + + +
+
Type help or hit TAB for a list of commands. Hit Esc or + Ctrl-C to hide this shell +
+
+
+ + + +
+ +
-

Josh.js

-

Toolkit for building bash-like shell in the browser, including full readline support

-
- Project maintained by sdether - Hosted on GitHub Pages — Theme by mattgraham +

Josh.js

+ +

Toolkit for building bash-like shell in the browser, including full readline support

+
+ Project maintained by sdether + Hosted on GitHub Pages — Theme by mattgraham

josh.js 0.2

-

Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components:

+

+ Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components: +

-
    -
  • -readline.js - full readline support for ctrl sequences, tab, history, etc.
  • -
  • -shell.js - visual presentation of the shell and command handling
  • -
  • -pathhandler.js - provide cd, ls, pwd and path completion toolikit
  • -
  • -history.js - localStorage backed command history
  • -

License

+
    +
  • + readline.js - full readline support for ctrl sequences, tab, history, etc. +
  • +
  • + shell.js - visual presentation of the shell and command handling +
  • +
  • + pathhandler.js - provide cd, ls, pwd and path completion toolikit +
  • +
  • + history.js - localStorage backed command history +
  • +
-

josh.js is licensed under the Apache 2.0 License

+

Demo

+

Hit the ~ key to show a demo console.

-

Status

+

License

-
    -
  • code is ready for experimental use +

    josh.js is licensed under the Apache 2.0 License

    -
      -
    • Tested under Chrome, Firefox, Safari and IE9
    • -
    • API may not yet be stable
    • -
    -
  • -
  • needs minified versions of complete toolkit and just readline.js
  • -
  • needs code documentation and documenation site
  • -
  • would like to add AMD support
  • -

Usage

+

Status

-

Until documentation is written, refer to index.html and example.js for a sample implementation of a shell with path completion.

+
    +
  • code is ready for experimental use -

    Components

    +
      +
    • Tested under Chrome, Firefox, Safari and IE9
    • +
    • API may not yet be stable
    • +
    +
  • +
  • needs minified versions of complete toolkit and just readline.js
  • +
  • needs code documentation and documenation site
  • +
  • would like to add AMD support
  • +
+

Usage

-

josh is built from 4 components and can be used in part or in full.

+

Until documentation is written, refer to index.html and + example.js for a sample implementation of a shell with path completion.

-

readline.js

+

Components

-

readline.js has no dependencies on any outside libraries, although it requires either history.js or an object implementing the same calls.

+

josh is built from 4 components and can be used in part or in full.

-

It implements key trapping to bring GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with shell.js to create a full console.

+

readline.js

-

shell.js

+

readline.js has no dependencies on any outside libraries, although it requires either + history.js or an object implementing the same calls.

-

shell.js has external dependencies of jQuery, Underscore and internal dependencies of readline.js and history.js.

+

It implements key trapping to bring + GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with + shell.js to create a full console.

-

It provides a simple console UI, using a panel for the console viewport and an auto-scrolling view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string.

+

shell.js

-

It also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, shell.js provides the following commands:

+

shell.js has external dependencies of jQuery, + Underscore and internal dependencies of readline.js and + history.js.

-
    -
  • help - list all known commands (including user added)
  • -
  • clear - clear the "screen" i.e. viewport
  • -
  • history - show the command history captured by readline.js in history.js -
  • -

pathhandler.js

+

It provides a simple console UI, using a panel for the console viewport and an auto-scrolling + view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string. +

-

pathhandler.js is a mix in to easily add the cd, ls and pwd commands as well as path completion. It has the same external dependencies of jQuery, Underscore as shell.js and also uses Underscore templating.

+

It also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, + shell.js provides the following commands:

-

By implementing the functions getNode and getChildNodes, this library adds path traversal, discovery and completion just like a bash shell.

+
    +
  • help - list all known commands (including user added)
  • +
  • clear - clear the "screen" i.e. viewport
  • +
  • history - show the command history captured by readline.js in history.js +
  • +
+

pathhandler.js

-

history.js

+

pathhandler.js is a mix in to easily add the cd, ls and + pwd commands as well as path completion. It has the same external dependencies of + jQuery, Underscore as + shell.js and also uses Underscore templating.

-

history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the shell.js history command to list all executed commands, and by readline.js for up/down arrow and reverse search capabilities.

+

By implementing the functions getNode and + getChildNodes, this library adds path traversal, discovery and completion just like a bash shell. +

-

Changelog

+

history.js

-

0.2 -- 2013/01/07

+

+ history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the + shell.js history command to list all executed commands, and by + readline.js for up/down arrow and reverse search capabilities.

-
    -
  • console wrapper to allow debug logging to be turned on and off
  • -
  • refactored how pathhandler attaches to shell because it needs to keep a reference to the shell
  • -
  • refactored how prompts are set. now uses dedicated callback rather than returning the prompt in the onEnter callback
  • -
  • tested and made fixes to ensure compatibility with major modern browsers
  • -

0.1 -- 2013/01/04

+
-
    -
  • Initial code-complete release
  • -
-
+
+ - - - - + \ No newline at end of file diff --git a/javascripts/example.js b/javascripts/example.js new file mode 100644 index 0000000..fb1ffa3 --- /dev/null +++ b/javascripts/example.js @@ -0,0 +1,155 @@ +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +(function(root, $, _) { + var _console = (Josh.Debug && root.console) ? root.console : { + log: function() { + } + }; + var fs = { + bin: {}, + boot: {}, + dev: {}, + etc: { + default: {}, + 'rc.d': {}, + sysconfig: {}, + x11: {} + }, + home: { + bob: {}, + jane: {} + }, + lib: {}, + 'lost+found': {}, + misc: {}, + mnt: { + cdrom: {}, + sysimage: {} + }, + net: {}, + opt: {}, + proc: {}, + root: {}, + sbin: {}, + usr: { + x11: {}, + bin: {}, + include: {}, + lib: {}, + local: {}, + man: {}, + sbin: {}, + share: { + doc: {} + }, + src: {} + }, + var: { + lib: {}, + lock: {}, + run: {}, + log: { + httpd: { + access_log: {}, + error_log: {} + }, + 'boot.log': {}, + cron: {}, + messages: {} + } + } + }; + + function buildTree(parent, node) { + parent.childnodes = _.map(_.pairs(node), function(pair) { + var child = { + name: pair[0], + path: parent.path + "/" + pair[0], + parent: parent + }; + buildTree(child, pair[1]); + return child; + }); + parent.children = _.keys(node); + return parent; + } + + function findNode(current, parts, callback) { + if(!parts || parts.length == 0) { + return callback(current); + } + if(parts[0] == ".") { + // carry on + } else if(parts[0] == "..") { + current = current.parent; + } else { + current = _.first(_.filter(current.childnodes, function(node) { + return node.name == parts[0]; + })); + } + if(!current) { + return callback(); + } + return findNode(current, _.rest(parts), callback); + } + + var root = buildTree({ + name: "", + path: "" + }, + fs + ); + root.path = '/'; + var history = Josh.History(); + var shell = Josh.Shell({history: history, console: _console}); + var pathhandler = Josh.PathHandler(shell, {console: _console}); + pathhandler.current = root; + pathhandler.getNode = function(path, callback) { + if(!path) { + return callback(pathhandler.current); + } + var parts = _.filter(path.split('/'), function(x) { + return x; + }); + var start = ((path || '')[0] == '/') ? root : pathhandler.current; + _console.log('start: ' + start.path + ', parts: ' + JSON.stringify(parts)); + return findNode(start, parts, callback); + }; + pathhandler.getChildNodes = function(node, callback) { + _console.log("children for " + node.name); + callback(node.childnodes); + }; + + $(document).ready(function() { + var consolePanel = $('#shell-panel'); + function showConsole() { + consolePanel.slideDown(); + consolePanel.focus(); + } + + function hideConsole() { + consolePanel.slideUp(); + consolePanel.blur(); + } + shell.onActivate(function() { + showConsole(); + }); + shell.onDeactivate(function() { + hideConsole(); + }); + }); +})(this, $, _); \ No newline at end of file diff --git a/javascripts/history.js b/javascripts/history.js new file mode 100644 index 0000000..49fb27a --- /dev/null +++ b/javascripts/history.js @@ -0,0 +1,145 @@ +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +var Josh = Josh || {}; +(function (root) { + Josh.History = function (config) { + config = config || {}; + + var _console = Josh.Debug && root.console ? root.console : {log: function() {}}; + var _history = config.history || ['']; + var _cursor = config.cursor || 0; + var _searchCursor = _cursor; + var _lastSearchTerm = ''; + var _storage = config.storage || root.localStorage; + var _key = config.key || 'josh.history'; + + if (_storage) { + var data = _storage.getItem(_key); + if (data) { + _history = JSON.parse(data); + _searchCursor = _cursor = _history.length - 1; + } else { + save(); + } + } + function save() { + if (_storage) { + _storage.setItem(_key, JSON.stringify(_history)); + } + } + + function setHistory() { + _searchCursor = _cursor; + _lastSearchTerm = ''; + return _history[_cursor]; + } + + return { + update:function (text) { + _console.log("updating history to " + text); + _history[_cursor] = text; + save(); + }, + accept:function (text) { + _console.log("accepting history " + text); + var last = _history.length - 1; + if (text) { + if (_cursor == last) { + _console.log("we're at the end already, update last position"); + _history[_cursor] = text; + } else if (!_history[last]) { + _console.log("we're not at the end, but the end was blank, so update last position"); + _history[last] = text; + } else { + _console.log("appending to end"); + _history.push(text); + } + _history.push(''); + } + _searchCursor = _cursor = _history.length - 1; + save(); + }, + items:function () { + return _history.slice(0, _history.length - 1); + }, + clear:function () { + _history = [_history[_history.length - 1]]; + save(); + }, + hasNext:function () { + return _cursor < (_history.length - 1); + }, + hasPrev:function () { + return _cursor > 0; + }, + prev:function () { + --_cursor; + return setHistory(); + }, + next:function () { + ++_cursor; + return setHistory(); + }, + top:function () { + _cursor = 0; + return setHistory(); + }, + end:function () { + _cursor = _history.length - 1; + return setHistory(); + }, + search:function (term) { + if (!term && !_lastSearchTerm) { + return null; + } + var iterations = _history.length; + if (term == _lastSearchTerm) { + _searchCursor--; + iterations--; + } + if (!term) { + term = _lastSearchTerm; + } + _lastSearchTerm = term; + for (var i = 0; i < iterations; i++) { + if (_searchCursor < 0) { + _searchCursor = _history.length - 1; + } + var idx = _history[_searchCursor].indexOf(term); + if (idx != -1) { + return { + text:_history[_searchCursor], + cursoridx:idx, + term:term + }; + } + _searchCursor--; + } + return null; + }, + applySearch:function () { + if (_lastSearchTerm) { + _console.log("setting history to position" + _searchCursor + "(" + _cursor + "): " + _history[_searchCursor]); + _cursor = _searchCursor; + return _history[_cursor]; + } + return null; + } + }; + }; +})(this); + diff --git a/javascripts/pathhandler.js b/javascripts/pathhandler.js new file mode 100644 index 0000000..056b8ad --- /dev/null +++ b/javascripts/pathhandler.js @@ -0,0 +1,157 @@ +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +var Josh = Josh || {}; +(function(root, $, _) { + Josh.PathHandler = function(shell, config) { + var _console = config.console || (Josh.Debug && root.console ? root.console : { + log: function() { + } + }); + var _shell = shell; + var self = { + handlers: { + ls: { + exec: ls, + completion: pathCompletionHandler + }, + exec: { + exec: exec, + completion: commandAndPathCompletionHandler + }, + cd: { + exec: cd, + completion: pathCompletionHandler + }, + pwd: { + exec: pwd, + completion: pathCompletionHandler + } + }, + pathCompletionHandler: pathCompletionHandler, + templates: { + not_found: _.template("
<%=cmd%>: <%=path%>: No such file or directory
"), + ls: _.template("
<% _.each(nodes, function(node) { %><%=node.name%> <% }); %>
"), + pwd: _.template("
<%=node.path %> 
"), + prompt: _.template("<%= node.path %> $") + }, + getNode: function(path, callback) { + callback(); + }, + getChildNodes: function(node, callback) { + callback([]); + }, + getPrompt: function() { + return self.templates.prompt({node: self.current}); + }, + current: null + }; + + self.handlers._original_exec = _shell.getCommandHandler('_exec'); + _shell.setCommandHandler("ls", self.handlers.ls); + _shell.setCommandHandler("pwd", self.handlers.pwd); + _shell.setCommandHandler("cd", self.handlers.cd); + _shell.setCommandHandler("_exec", self.handlers.exec); + _shell.onNewPrompt(function(callback) { + callback(self.getPrompt()); + }); + + function commandAndPathCompletionHandler(cmd, arg, line, callback) { + if(arg[0] == '.' || arg[0] == '/') { + return pathCompletionHandler(cmd, arg, line, callback); + } + return self.handlers._original_exec.completion(cmd, arg, line, callback); + } + + function pathCompletionHandler(cmd, arg, line, callback) { + _console.log("completing '" + arg+ "'"); + var partial = ""; + self.getNode(arg, function(node) { + if(!node) { + _console.log("no node"); + var lastPathSeparator = arg.lastIndexOf("/"); + if(lastPathSeparator == arg.length - 1) { + return callback(); + } + var parent = arg.substr(0, lastPathSeparator + 1); + _console.log("parent: " + parent); + partial = arg.substr(lastPathSeparator + 1); + return self.getNode(parent, function(node) { + if(!node) { + return callback(); + } + return completeChildren(node, partial, callback); + }); + } + if(!arg || arg[arg.length - 1] == '/') { + return completeChildren(node, partial, callback); + } + return callback({ + completion: '/', + suggestions: [] + }); + }); + } + + function completeChildren(node, partial, callback) { + self.getChildNodes(node, function(childNodes) { + callback(_shell.bestMatch(partial, _.map(childNodes, function(x) { + return x.name; + }))); + }); + } + + function exec(cmd, args, callback) { + callback(); + } + + function cd(cmd, args, callback) { + self.getNode(args[0], function(node) { + if(!node) { + return callback(self.templates.not_found({cmd: 'cd', path: args[0]})); + } + self.current = node; + return callback(); + }); + } + + function pwd(cmd, args, callback) { + callback(self.templates.pwd({node: self.current})); + } + + function ls(cmd, args, callback) { + _console.log('ls'); + if(!args || !args[0]) { + return render_ls(self.current, self.current.path, callback); + } + return self.getNode(args[0], function(node) { + render_ls(node, args[0], callback); + }); + } + + function render_ls(node, path, callback) { + if(!node) { + return callback(self.templates.not_found({cmd: 'ls', path: path})); + } + return self.getChildNodes(node, function(children) { + _console.log("finish render: " + node.name); + callback(self.templates.ls({nodes: children})); + }); + } + + return self; + }; +})(this, $, _); \ No newline at end of file diff --git a/javascripts/readline.js b/javascripts/readline.js new file mode 100644 index 0000000..ecd84db --- /dev/null +++ b/javascripts/readline.js @@ -0,0 +1,653 @@ +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +var Josh = Josh || {}; +(function(root) { + var SPECIAL = { + 8: 'BACKSPACE', + 9: 'TAB', + 13: 'ENTER', + 19: 'PAUSE', + 20: 'CAPS_LOCK', + 27: 'ESCAPE', + 32: 'SPACE', + 33: 'PAGE_UP', + 34: 'PAGE_DOWN', + 35: 'END', + 36: 'HOME', + 37: 'LEFT', + 38: 'UP', + 39: 'RIGHT', + 40: 'DOWN', + 45: 'INSERT', + 46: 'DELETE' + }; + + Josh.ReadLine = function(config) { + config = config || {}; + + // instance fields + var _console = config.console || (Josh.Debug && root.console ? root.console : { + log: function() { + } + }); + var _history = config.history || new Josh.History(); + var _activationKey = config.activationKey || { keyCode: 192, shiftKey: true }; // ~ + var _deactivationKey = config.deactivationKey || { keyCode: 27 }; // Esc + var _active = false; + var _onActivate; + var _onDeactivate; + var _onCompletion; + var _onEnter; + var _onKeydown; + var _onChange; + var _onCancel; + var _onEOT; + var _onSearchStart; + var _onSearchEnd; + var _onSearchChange; + var _inSearch = false; + var _searchMatch; + var _lastSearchText = ''; + var _text = ''; + var _cursor = 0; + var _kill_buffer = ''; + var _lastCmd; + var _completionActive; + var _cmdQueue = []; + var _suspended = false; + + // public methods + var self = { + activate: function() { + _active = true; + if(_onActivate) { + _onActivate(); + } + }, + deactivate: function() { + _active = false; + if(_onDeactivate) { + _onDeactivate(); + } + }, + onActivate: function(completionHandler) { + _onActivate = completionHandler; + }, + onDeactivate: function(completionHandler) { + _onDeactivate = completionHandler; + }, + onKeydown: function(keydownHandler) { + _onKeydown = keydownHandler; + }, + onChange: function(changeHandler) { + _onChange = changeHandler; + }, + onEnter: function(enterHandler) { + _onEnter = enterHandler; + }, + onCompletion: function(completionHandler) { + _onCompletion = completionHandler; + }, + onCancel: function(completionHandler) { + _onCancel = completionHandler; + }, + onEOT: function(completionHandler) { + _onEOT = completionHandler; + }, + onSearchStart: function(completionHandler) { + _onSearchStart = completionHandler; + }, + onSearchEnd: function(completionHandler) { + _onSearchEnd = completionHandler; + }, + onSearchChange: function(completionHandler) { + _onSearchChange = completionHandler; + }, + getLine: function() { + return { + text: _text, + cursor: _cursor + }; + } + }; + + // private methods + function getKeyInfo(e) { + var info = { + code: e.keyCode || e.charCode, + shift: e.shiftKey, + control: e.controlKey, + alt: e.altKey, + isChar: true + }; + + var code = info.code; + var c = String.fromCharCode(code); + info.name = SPECIAL[code] || c; + info.char = c; + return info; + } + + function queue(cmd) { + if(_suspended) { + _cmdQueue.push(cmd); + return; + } + call(cmd); + } + + function call(cmd) { + _console.log('calling: ' + cmd.name + ', previous: ' + _lastCmd); + if(_inSearch && cmd.name != "cmdKeyPress" && cmd.name != "cmdReverseSearch") { + _inSearch = false; + if(cmd.name == 'cmdCancelSearch') { + _searchMatch = null; + } + if(_searchMatch) { + if(_searchMatch.text) { + _cursor = _searchMatch.cursoridx; + _text = _searchMatch.text; + _history.applySearch(); + } + _searchMatch = null; + } + if(_onSearchEnd) { + _onSearchEnd(); + } + } + _lastCmd = cmd.name; + cmd(); + } + + function cmdCancelSearch() { + // do nothing.. action for this was already taken in call() + } + + function cmdBackspace() { + if(_cursor == 0) { + return; + } + --_cursor; + _text = remove(_text, _cursor, _cursor + 1); + refresh(); + } + + function cmdComplete() { + if(!_onCompletion) { + return; + } + suspend(function(resumeCallback) { + _onCompletion(self.getLine(), function(completion) { + if(completion) { + _text = insert(_text, _cursor, completion); + updateCursor(_cursor + completion.length); + } + _completionActive = true; + resumeCallback(); + }); + }); + } + + function cmdDone() { + if(!_text) { + return; + } + var text = _text; + _history.accept(text); + _text = ''; + _cursor = 0; + if(!_onEnter) { + return; + } + suspend(function(resumeCallback) { + _onEnter(text, function(text) { + if(text) { + _text = text; + _cursor = _text.length; + } + if(_onChange) { + _onChange(self.getLine()); + } + resumeCallback(); + }); + }); + + } + + function suspend(asyncCall) { + _suspended = true; + asyncCall(resume); + } + + function resume() { + var cmd = _cmdQueue.shift(); + if(!cmd) { + _suspended = false; + return; + } + call(cmd); + resume(); + } + + function cmdEnd() { + updateCursor(_text.length); + } + + function cmdHome() { + updateCursor(0); + } + + function cmdLeft() { + if(_cursor == 0) { + return; + } + updateCursor(_cursor - 1); + } + + function cmdRight() { + if(_cursor == _text.length) { + return; + } + updateCursor(_cursor + 1); + } + + function cmdBackwardWord() { + if(_cursor == 0) { + return; + } + var previousWhitespace = 0; + var findNonWhiteSpace = _text[_cursor] == ' ' || _text[_cursor - 1] == ' '; + for(var i = _cursor - 1; i > 0; i--) { + if(findNonWhiteSpace) { + if(_text[i] != ' ') { + findNonWhiteSpace = false; + } + } else { + if(_text[i] == ' ') { + previousWhitespace = i + 1; + break; + } + } + } + updateCursor(previousWhitespace); + } + + function cmdForwardWord() { + if(_cursor == _text.length) { + return; + } + var nextWhitespace = _text.length; + var findNonWhitespace = _text[_cursor] == ' '; + for(var i = _cursor + 1; i < _text.length; i++) { + if(findNonWhitespace) { + if(_text[i] != ' ') { + findNonWhitespace = false; + } + } else { + if(_text[i] == ' ') { + nextWhitespace = i; + break; + } + } + } + updateCursor(nextWhitespace); + } + + function cmdHistoryPrev() { + if(!_history.hasPrev()) { + return; + } + getHistory(_history.prev); + } + + function cmdHistoryNext() { + if(!_history.hasNext()) { + return; + } + getHistory(_history.next); + } + + function cmdHistoryTop() { + getHistory(_history.top); + } + + function cmdHistoryEnd() { + getHistory(_history.end); + } + + function cmdDeleteChar() { + if(_text.length == 0) { + if(_onEOT) { + _onEOT(); + return; + } + } + if(_cursor == _text.length) { + return; + } + _text = remove(_text, _cursor, _cursor + 1); + refresh(); + } + + function cmdCancel() { + if(_onCancel) { + _onCancel(); + } + } + + function cmdKillToEOF() { + _kill_buffer = _text.substr(_cursor); + _text = _text.substr(0, _cursor); + refresh(); + } + + function cmdYank() { + _text = insert(_text, _cursor, _kill_buffer); + updateCursor(_cursor + _kill_buffer.length); + } + + function cmdRefresh() { + refresh(); + } + + function cmdReverseSearch() { + if(!_inSearch) { + _inSearch = true; + if(_onSearchStart) { + _onSearchStart(); + } + if(_onSearchChange) { + _onSearchChange({}); + } + } else { + if(!_searchMatch) { + _searchMatch = {term: ''}; + } + search(); + } + } + + function updateCursor(position) { + _cursor = position; + refresh(); + } + + function addText(c) { + _text = insert(_text, _cursor, c); + ++_cursor; + refresh(); + } + + function addSearchText(c) { + if(!_searchMatch) { + _searchMatch = {term: ''}; + } + _searchMatch.term += c; + search(); + } + + function search() { + _console.log("searchtext: " + _searchMatch.term); + var match = _history.search(_searchMatch.term); + if(match != null) { + _searchMatch = match; + _console.log("match: " + match); + if(_onSearchChange) { + _onSearchChange(match); + } + } + } + + function refresh() { + if(_onChange) { + _onChange(self.getLine()); + } + } + + function getHistory(historyCall) { + _history.update(_text); + _text = historyCall(); + updateCursor(_text.length); + } + + function checkKeyMatch(a, b) { + return a.keyCode == b.keyCode + && Boolean(a.shiftKey) == Boolean(b.shiftKey) + && Boolean(a.ctrlKey) == Boolean(b.ctrlKey) + && Boolean(a.altKey) == Boolean(b.altKey); + } + + function remove(text, from, to) { + if(text.length <= 1 || text.length <= to - from) { + return ''; + } + if(from == 0) { + + // delete leading characters + return text.substr(to); + } + var left = text.substr(0, from); + var right = text.substr(to); + return left + right; + } + + function insert(text, idx, ins) { + if(idx == 0) { + return ins + text; + } + if(idx >= text.length) { + return text + ins; + } + var left = text.substr(0, idx); + var right = text.substr(idx); + return left + ins + right; + } + + + // set up key capture + root.onkeydown = function(e) { + e = e || window.event; + + // check if the keypress is an the activation key + if(!_active && checkKeyMatch(e, _activationKey)) { + self.activate(); + return false; + } + + // return as unhandled if we're not active or the key is just a modifier key + if(!_active || e.keyCode == 16 || e.keyCode == 17 || e.keyCode == 18) { + return true; + } + + var handled = true; + + // check keys special keys, regardless of modifiers + switch(e.keyCode) { + case 8: // Backspace + queue(cmdBackspace); + break; + case 9: // Tab + queue(cmdComplete); + break; + case 13: // Enter + queue(cmdDone); + break; + case 27: // Esc + if(_inSearch) { + queue(cmdCancelSearch); + } else { + handled = false; + } + break; + case 33: // Page Up + queue(cmdHistoryTop); + break; + case 34: // Page Down + queue(cmdHistoryEnd); + break; + case 35: // End + queue(cmdEnd); + break; + case 36: // Home + queue(cmdHome); + break; + case 37: // Left + queue(cmdLeft); + break; + case 38: // Up + queue(cmdHistoryPrev); + break; + case 39: // Right + queue(cmdRight); + break; + case 40: // Down + queue(cmdHistoryNext); + break; + case 46: // Delete + queue(cmdDeleteChar); + break; + + // these we catch and have no commands for + case 10: // Pause + case 19: // Caps Lock + case 45: // Insert + break; + + // all others we don't handle at this level + default: + handled = false; + break; + } + if(!handled) { + + // intercept ctrl- and alt- sequences + if(e.ctrlKey && !e.shiftKey && !e.altKey) { + switch(e.keyCode) { + case 65: // A + queue(cmdHome); + handled = true; + break; + case 66: // B + queue(cmdLeft); + handled = true; + break; + case 67: // C + queue(cmdCancel); + handled = true; + break; + case 68: // D + queue(cmdDeleteChar); + handled = true; + break; + case 69: // E + queue(cmdEnd); + handled = true; + break; + case 70: // F + queue(cmdRight); + handled = true; + break; + case 80: // P + queue(cmdHistoryPrev); + handled = true; + break; + case 78: // N + queue(cmdHistoryNext); + handled = true; + break; + case 75: // K + queue(cmdKillToEOF); + handled = true; + break; + case 89: // Y + queue(cmdYank); + handled = true; + break; + case 76: // L + queue(cmdRefresh); + handled = true; + break; + case 82: // R + queue(cmdReverseSearch); + handled = true; + break; + } + } else if(e.altKey && !e.ctrlKey && !e.shiftKey) { + switch(e.keyCode) { + case 66: // B + queue(cmdBackwardWord); + handled = true; + break; + case 70: // F + queue(cmdForwardWord); + handled = true; + break; + } + } + } + if(!handled) { + if(!checkKeyMatch(e, _deactivationKey)) { + return true; + } + self.deactivate(); + } else { + var info = getKeyInfo(e); + if(_onKeydown) { + _onKeydown({ + code: e.keyCode, + shift: e.shiftKey, + control: e.controlKey, + alt: e.altKey, + name: SPECIAL[e.keyCode], + isChar: false + }); + } + } + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; + return false; + }; + root.onkeypress = function(e) { + if(!_active) { + return true; + } + var key = getKeyInfo(e); + if(key.code == 0 || e.defaultPrevented) { + return false; + } + queue(function cmdKeyPress() { + if(_inSearch) { + addSearchText(key.char); + } else { + addText(key.char); + } + if(_onKeydown) { + _onKeydown(key); + } + }); + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; + return false; + }; + + return self; + }; +})(this); + + diff --git a/javascripts/shell.js b/javascripts/shell.js new file mode 100644 index 0000000..41a6a2b --- /dev/null +++ b/javascripts/shell.js @@ -0,0 +1,392 @@ +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +var Josh = Josh || {}; +(function(root, $, _) { + Josh.Shell = function(config) { + config = config || {}; + + // instance fields + var _console = config.console || (Josh.Debug && root.console ? root.console : { + log: function() { + } + }); + var _prompt = config.prompt || 'jsh$'; + var _shell_view_id = config.shell_view_id || '#shell-view'; + var _shell_panel_id = config.shell_panel_id || '#shell-panel'; + var _input_id = config.input_id || '#shell-cli'; + var _input_html = config.input_html || '
 
'; + var _search_html = config.search_html || '
(reverse-i-search)`\': 
'; + var _suggest_html = config.suggest_html || '
'; + var _suggest_id = config.suggest_id = "#shell-suggest"; + var _blinktime = config.blinktime || 500; + var _history = config.history || new Josh.History(); + var _readline = config.readline || new Josh.ReadLine({history: _history, console: _console}); + var _active = false; + var _cursor_visible = false; + var _suggestion; + var _itemTemplate = _.template("
<%- i %> <%- cmd %>
"); + var _activationHandler; + var _deactivationHandler; + var _cmdHandlers = { + clear: { + exec: function(cmd, args, callback) { + $(_input_id).parent().empty(); + callback(); + } + }, + help: { + exec: function(cmd, args, callback) { + var content = $('
Commands:
'); + var itemTemplate = _.template('
 <%=command%>
'); + _.each(commands(), function(command) { + content.append(itemTemplate({command: command})) + }); + callback(content); + } + }, + history: { + exec: function(cmd, args, callback) { + if(args[0] == "-c") { + _history.clear(); + callback(); + return; + } + var content = $('
'); + _.each(_history.items(), function(cmd, i) { + content.append(_itemTemplate({cmd: cmd, i: i})); + }); + callback(content); + } + }, + _default: { + exec: function(cmd, args, callback) { + var content = _.template('
Unrecognized command: <%=cmd%>
', {cmd: cmd}); + callback(content); + } + }, + _exec: { + exec: function(cmd, args, callback) { + var content = _.template('
Unrecognized command: <%=cmd%>
', {cmd: cmd}); + callback(content); + }, + completion: function(cmd, arg, line, callback) { + callback(self.bestMatch(arg, self.commands())) + } + } + }; + var _line = { + text: '', + cursor: 0 + }; + var _searchMatch = ''; + var _view, _panel; + var _promptHandler; + + // public methods + var self = { + commands: commands, + activate: function() { + if($(_shell_view_id).length == 0) { + _active = false; + return; + } + _readline.activate(); + }, + deactivate: function() { + _console.log("deactivating"); + _active = false; + _readline.deactivate(); + }, + setCommandHandler: function(cmd, cmdHandler) { + _cmdHandlers[cmd] = cmdHandler; + }, + getCommandHandler: function(cmd) { + return _cmdHandlers[cmd]; + }, + setPrompt: function(prompt) { + _prompt = prompt; + if(!_active) { + return; + } + self.refresh(); + }, + onActivate: function(completionHandler) { + _activationHandler = completionHandler; + }, + onDeactivate: function(completionHandler) { + _deactivationHandler = completionHandler; + }, + onNewPrompt: function(completionHandler) { + _promptHandler = completionHandler; + }, + render: function() { + var text = _line.text || ''; + var cursorIdx = _line.cursor || 0; + if(_searchMatch) { + cursorIdx = _searchMatch.cursoridx || 0; + text = _searchMatch.text || ''; + $(_input_id + ' .searchterm').text(_searchMatch.term); + } + var left = _.escape(text.substr(0, cursorIdx)).replace(/ /g, ' '); + var cursor = text.substr(cursorIdx, 1); + var right = _.escape(text.substr(cursorIdx + 1)).replace(/ /g, ' '); + $(_input_id + ' .prompt').text(_prompt); + $(_input_id + ' .input .left').html(left); + if(!cursor) { + $(_input_id + ' .input .cursor').html(' ').css('textDecoration', 'underline'); + } else { + $(_input_id + ' .input .cursor').text(cursor).css('textDecoration', 'underline'); + } + $(_input_id + ' .input .right').html(right); + _cursor_visible = true; + self.scrollToBottom(); + _console.log('rendered "' + text + '" w/ cursor at ' + cursorIdx); + }, + refresh: function() { + $(_input_id).replaceWith(_input_html); + self.render(); + _console.log('refreshed ' + _input_id); + + }, + scrollToBottom: function() { + _panel.animate({scrollTop: _view.height()}, 0); + }, + bestMatch: function(partial, possible) { + var result = { + completion: null, + suggestions: [] + }; + if(!possible || possible.length == 0) { + return result; + } + var common = ''; + if(!partial) { + if(possible.length == 1) { + result.completion = possible[0]; + result.suggestions = possible; + return result; + } + if(!_.every(possible, function(x) { + return possible[0][0] == x[0] + })) { + result.suggestions = possible; + return result; + } + common = possible[0][0]; + } + for(var i = 0; i < possible.length; i++) { + var option = possible[i]; + if(option.slice(0, partial.length) == partial) { + result.suggestions.push(option); + if(!common) { + common = option; + _console.log("initial common:" + common); + } else if(option.slice(0, common.length) != common) { + _console.log("find common stem for '" + common + "' and '" + option + "'"); + var j = partial.length; + while(j < common.length && j < option.length) { + if(common[j] != option[j]) { + common = common.substr(0, j); + break; + } + j++; + } + } + } + } + result.completion = common.substr(partial.length); + return result; + } + }; + + function commands() { + return _.chain(_cmdHandlers).keys().filter(function(x) { + return x[0] != "_" + }).value(); + } + + function blinkCursor() { + if(!_active) { + return; + } + root.setTimeout(function() { + if(!_active) { + return; + } + _cursor_visible = !_cursor_visible; + if(_cursor_visible) { + $(_input_id + ' .input .cursor').css('textDecoration', 'underline'); + } else { + $(_input_id + ' .input .cursor').css('textDecoration', ''); + } + blinkCursor(); + }, _blinktime); + } + + function split(str) { + return _.filter(str.split(/\s+/), function(x) { + return x; + }); + } + + function getHandler(cmd) { + var handler; + if(!cmd) { + handler = _cmdHandlers._default; + } else { + handler = _cmdHandlers[cmd]; + } + if(!handler) { + handler = _cmdHandlers._default; + } + return handler; + } + + // init + _readline.onActivate(function() { + _console.log("activating shell"); + if(!_view) { + _view = $(_shell_view_id); + } + if(!_panel) { + _panel = $(_shell_panel_id); + } + if($(_input_id).length == 0) { + _view.append(_input_html); + } + self.refresh(); + _active = true; + blinkCursor(); + if(_promptHandler) { + _promptHandler(function(prompt) { + self.setPrompt(prompt); + }) + } + if(_activationHandler) { + _activationHandler(); + } + }); + _readline.onDeactivate(function() { + if(_deactivationHandler) { + _deactivationHandler(); + } + }); + _readline.onChange(function(line) { + if(_suggestion) { + $(_suggest_id).remove(); + _suggestion = null; + self.scrollToBottom(); + } + _line = line; + self.render(); + }); + _readline.onSearchStart(function() { + $(_input_id).replaceWith(_search_html); + _console.log('started search'); + }); + _readline.onSearchEnd(function() { + $(_input_id).replaceWith(_input_html); + _searchMatch = null; + self.render(); + _console.log("ended search"); + }); + _readline.onSearchChange(function(match) { + _searchMatch = match; + self.render(); + }); + _readline.onEnter(function(cmdtext, callback) { + _console.log("got command: " + cmdtext); + var parts = split(cmdtext); + var cmd = parts[0]; + var args = parts.slice(1); + var handler = getHandler(cmd); + return handler.exec(cmd, args, function(output, cmdtext) { + if(output) { + $(_input_id).after(output); + } + $(_input_id + ' .input .cursor').css('textDecoration', ''); + $(_input_id).removeAttr('id'); + $(_shell_view_id).append(_input_html); + if(_promptHandler) { + _promptHandler(function(prompt) { + self.setPrompt(prompt); + return callback(cmdtext); + }); + } + return callback(cmdtext); + }); + }); + _readline.onCompletion(function(line, callback) { + if(_suggestion) { + $(_suggest_id).remove(); + _suggestion = null; + } + if(!line) { + return callback(); + } + var text = line.text.substr(0, line.cursor); + var parts = split(text); + + var cmd = parts.shift() || ''; + var arg = parts.pop() || ''; + _console.log("getting completion handler for " + cmd); + var handler = _cmdHandlers[cmd]; + if(!handler) { + if(arg) { + if(!_cmdHandlers._default.completion) { + + // we have an argument, i.e. this isn't command completion, but we have no handler for command nor a completion handler for default + return callback(); + } + } + + // let's try command completion + handler = _cmdHandlers._exec; + arg = cmd; + cmd = 'exec'; + } else if(cmd == text) { + + // the text to complete is just a valid command, append a space + return callback(' '); + } + if(!handler.completion) { + // handler has no completion function, so we can't complete + return callback(); + } + _console.log("calling completion handler for " + cmd); + return handler.completion(cmd, arg, line, function(match) { + _console.log("completion: " + JSON.stringify(match)); + if(!match) { + return callback(); + } + if(match.suggestions) { + _suggestion = $(_suggest_html); + for(var i = 0; i < match.suggestions.length; i++) { + _console.log("suggestion: " + match.suggestions[i]); + _suggestion.append($("
").text(match.suggestions[i])); + } + $(_input_id).after(_suggestion); + } + self.scrollToBottom(); + return callback(match.completion); + }); + }); + _readline.onEOT(self.deactivate); + _readline.onCancel(self.deactivate); + return self; + } +})(this, $, _); diff --git a/stylesheets/styles.css b/stylesheets/styles.css index e7b4ffc..4275f45 100644 --- a/stylesheets/styles.css +++ b/stylesheets/styles.css @@ -849,3 +849,9 @@ section #title .credits.right { display: none; } } + +#demo { + border: 1px dashed #E6EBE0; + background: #454545; + padding: 2px; +} From a453fd1a12e2431f2ed5aae0b006d2236cbee2a5 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Wed, 9 Jan 2013 23:33:49 -0800 Subject: [PATCH 03/26] updated to latest shell --- javascripts/shell.js | 53 +++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/javascripts/shell.js b/javascripts/shell.js index 41a6a2b..820f262 100644 --- a/javascripts/shell.js +++ b/javascripts/shell.js @@ -37,7 +37,6 @@ var Josh = Josh || {}; var _readline = config.readline || new Josh.ReadLine({history: _history, console: _console}); var _active = false; var _cursor_visible = false; - var _suggestion; var _itemTemplate = _.template("
<%- i %> <%- cmd %>
"); var _activationHandler; var _deactivationHandler; @@ -256,6 +255,22 @@ var Josh = Josh || {}; return handler; } + function renderOutput(output, callback) { + if(output) { + $(_input_id).after(output); + } + $(_input_id + ' .input .cursor').css('textDecoration', ''); + $(_input_id).removeAttr('id'); + $(_shell_view_id).append(_input_html); + if(_promptHandler) { + return _promptHandler(function(prompt) { + self.setPrompt(prompt); + return callback(); + }); + } + return callback(); + } + // init _readline.onActivate(function() { _console.log("activating shell"); @@ -286,11 +301,6 @@ var Josh = Josh || {}; } }); _readline.onChange(function(line) { - if(_suggestion) { - $(_suggest_id).remove(); - _suggestion = null; - self.scrollToBottom(); - } _line = line; self.render(); }); @@ -315,26 +325,12 @@ var Josh = Josh || {}; var args = parts.slice(1); var handler = getHandler(cmd); return handler.exec(cmd, args, function(output, cmdtext) { - if(output) { - $(_input_id).after(output); - } - $(_input_id + ' .input .cursor').css('textDecoration', ''); - $(_input_id).removeAttr('id'); - $(_shell_view_id).append(_input_html); - if(_promptHandler) { - _promptHandler(function(prompt) { - self.setPrompt(prompt); - return callback(cmdtext); - }); - } - return callback(cmdtext); + renderOutput(output, function() { + callback(cmdtext) + }); }); }); _readline.onCompletion(function(line, callback) { - if(_suggestion) { - $(_suggest_id).remove(); - _suggestion = null; - } if(!line) { return callback(); } @@ -373,15 +369,16 @@ var Josh = Josh || {}; if(!match) { return callback(); } - if(match.suggestions) { - _suggestion = $(_suggest_html); + if(match.suggestions && match.suggestions.length > 1) { + var suggestion = $(_suggest_html); for(var i = 0; i < match.suggestions.length; i++) { _console.log("suggestion: " + match.suggestions[i]); - _suggestion.append($("
").text(match.suggestions[i])); + suggestion.append($("
").text(match.suggestions[i])); } - $(_input_id).after(_suggestion); + return renderOutput(suggestion, function() { + callback(match.completion); + }); } - self.scrollToBottom(); return callback(match.completion); }); }); From 887a8264ecf50bfc08f996ec33a2628d18c15073 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Sun, 13 Jan 2013 09:23:17 -0800 Subject: [PATCH 04/26] testing if i can frame github for a demo --- github.html | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 github.html diff --git a/github.html b/github.html new file mode 100644 index 0000000..d7f3a0b --- /dev/null +++ b/github.html @@ -0,0 +1,56 @@ + + + + + + + + +
+
+ +
+
+ +
+
+ + \ No newline at end of file From 907189c8d269a4ff28be5b846d4443f1acba8162 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Sun, 13 Jan 2013 15:17:59 -0800 Subject: [PATCH 05/26] updated code and some docs --- github.html | 56 -------- index.html | 13 +- javascripts/example.js | 259 +++++++++++++++++++------------------ javascripts/pathhandler.js | 55 ++++---- javascripts/readline.js | 14 +- javascripts/shell.js | 61 ++++----- 6 files changed, 203 insertions(+), 255 deletions(-) delete mode 100644 github.html diff --git a/github.html b/github.html deleted file mode 100644 index d7f3a0b..0000000 --- a/github.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - -
-
- -
-
- -
-
- - \ No newline at end of file diff --git a/index.html b/index.html index 18ff58d..a1e2657 100644 --- a/index.html +++ b/index.html @@ -92,6 +92,7 @@

josh.js 0.2

Demo

+

Hit the ~ key to show a demo console.

License

@@ -109,8 +110,18 @@

Status

  • needs minified versions of complete toolkit and just readline.js
  • -
  • needs code documentation and documenation site
  • +
  • needs code documentation and documentation site
  • would like to add AMD support
  • +
  • base shell UI should get some basic behaviors + +
      +
    • + more-like handling for output that exceeds the shell viewport size +
    • +
    • resizing and close chrome
    • +
    • scrollwheel support
    • +
    +
  • Usage

    diff --git a/javascripts/example.js b/javascripts/example.js index fb1ffa3..16bbe84 100644 --- a/javascripts/example.js +++ b/javascripts/example.js @@ -15,141 +15,150 @@ *-------------------------------------------------------------------------*/ (function(root, $, _) { - var _console = (Josh.Debug && root.console) ? root.console : { - log: function() { - } - }; - var fs = { - bin: {}, - boot: {}, - dev: {}, - etc: { - default: {}, - 'rc.d': {}, - sysconfig: {}, - x11: {} - }, - home: { - bob: {}, - jane: {} - }, - lib: {}, - 'lost+found': {}, - misc: {}, - mnt: { - cdrom: {}, - sysimage: {} - }, - net: {}, - opt: {}, - proc: {}, - root: {}, - sbin: {}, - usr: { - x11: {}, + Josh.Example = (function(root, $, _) { + var _console = (Josh.Debug && root.console) ? root.console : { + log: function() { + } + }; + var fs = { bin: {}, - include: {}, - lib: {}, - local: {}, - man: {}, - sbin: {}, - share: { - doc: {} + boot: {}, + dev: {}, + etc: { + default: {}, + 'rc.d': {}, + sysconfig: {}, + x11: {} + }, + home: { + bob: {}, + jane: {} }, - src: {} - }, - var: { lib: {}, - lock: {}, - run: {}, - log: { - httpd: { - access_log: {}, - error_log: {} + 'lost+found': {}, + misc: {}, + mnt: { + cdrom: {}, + sysimage: {} + }, + net: {}, + opt: {}, + proc: {}, + root: {}, + sbin: {}, + usr: { + x11: {}, + bin: {}, + include: {}, + lib: {}, + local: {}, + man: {}, + sbin: {}, + share: { + doc: {} }, - 'boot.log': {}, - cron: {}, - messages: {} + src: {} + }, + var: { + lib: {}, + lock: {}, + run: {}, + log: { + httpd: { + access_log: {}, + error_log: {} + }, + 'boot.log': {}, + cron: {}, + messages: {} + } } - } - }; - - function buildTree(parent, node) { - parent.childnodes = _.map(_.pairs(node), function(pair) { - var child = { - name: pair[0], - path: parent.path + "/" + pair[0], - parent: parent - }; - buildTree(child, pair[1]); - return child; - }); - parent.children = _.keys(node); - return parent; - } + }; - function findNode(current, parts, callback) { - if(!parts || parts.length == 0) { - return callback(current); + function buildTree(parent, node) { + parent.childnodes = _.map(_.pairs(node), function(pair) { + var child = { + name: pair[0], + path: parent.path + "/" + pair[0], + parent: parent + }; + buildTree(child, pair[1]); + return child; + }); + parent.children = _.keys(node); + return parent; } - if(parts[0] == ".") { - // carry on - } else if(parts[0] == "..") { - current = current.parent; - } else { - current = _.first(_.filter(current.childnodes, function(node) { - return node.name == parts[0]; - })); - } - if(!current) { - return callback(); - } - return findNode(current, _.rest(parts), callback); - } - var root = buildTree({ - name: "", - path: "" - }, - fs - ); - root.path = '/'; - var history = Josh.History(); - var shell = Josh.Shell({history: history, console: _console}); - var pathhandler = Josh.PathHandler(shell, {console: _console}); - pathhandler.current = root; - pathhandler.getNode = function(path, callback) { - if(!path) { - return callback(pathhandler.current); + function findNode(current, parts, callback) { + if(!parts || parts.length == 0) { + return callback(current); + } + if(parts[0] == ".") { + // carry on + } else if(parts[0] == "..") { + current = current.parent; + } else { + current = _.first(_.filter(current.childnodes, function(node) { + return node.name == parts[0]; + })); + } + if(!current) { + return callback(); + } + return findNode(current, _.rest(parts), callback); } - var parts = _.filter(path.split('/'), function(x) { - return x; - }); - var start = ((path || '')[0] == '/') ? root : pathhandler.current; - _console.log('start: ' + start.path + ', parts: ' + JSON.stringify(parts)); - return findNode(start, parts, callback); - }; - pathhandler.getChildNodes = function(node, callback) { - _console.log("children for " + node.name); - callback(node.childnodes); - }; - $(document).ready(function() { - var consolePanel = $('#shell-panel'); - function showConsole() { - consolePanel.slideDown(); - consolePanel.focus(); - } + var root = buildTree({ + name: "", + path: "" + }, + fs + ); + root.path = '/'; + var history = Josh.History(); + var shell = Josh.Shell({history: history, console: _console}); + var pathhandler = Josh.PathHandler(shell, {console: _console}); + pathhandler.current = root; + pathhandler.getNode = function(path, callback) { + if(!path) { + return callback(pathhandler.current); + } + var parts = _.filter(path.split('/'), function(x) { + return x; + }); + var start = ((path || '')[0] == '/') ? root : pathhandler.current; + _console.log('start: ' + start.path + ', parts: ' + JSON.stringify(parts)); + return findNode(start, parts, callback); + }; + pathhandler.getChildNodes = function(node, callback) { + _console.log("children for " + node.name); + callback(node.childnodes); + }; - function hideConsole() { - consolePanel.slideUp(); - consolePanel.blur(); - } - shell.onActivate(function() { - showConsole(); - }); - shell.onDeactivate(function() { - hideConsole(); + $(document).ready(function() { + var consolePanel = $('#shell-panel'); + + function showConsole() { + consolePanel.slideDown(); + consolePanel.focus(); + } + + function hideConsole() { + consolePanel.slideUp(); + consolePanel.blur(); + } + + shell.onActivate(function() { + showConsole(); + }); + shell.onDeactivate(function() { + hideConsole(); + }); }); - }); + return { + Tree: root, + Shell: shell, + PathHandler: pathhandler + }; + })(root, $, _); })(this, $, _); \ No newline at end of file diff --git a/javascripts/pathhandler.js b/javascripts/pathhandler.js index 056b8ad..9974219 100644 --- a/javascripts/pathhandler.js +++ b/javascripts/pathhandler.js @@ -22,26 +22,11 @@ var Josh = Josh || {}; } }); var _shell = shell; + var _original_default = _shell.getCommandHandler('_default'); var self = { - handlers: { - ls: { - exec: ls, - completion: pathCompletionHandler - }, - exec: { - exec: exec, - completion: commandAndPathCompletionHandler - }, - cd: { - exec: cd, - completion: pathCompletionHandler - }, - pwd: { - exec: pwd, - completion: pathCompletionHandler - } - }, + current: null, pathCompletionHandler: pathCompletionHandler, + commandAndPathCompletionHandler: commandAndPathCompletionHandler, templates: { not_found: _.template("
    <%=cmd%>: <%=path%>: No such file or directory
    "), ls: _.template("
    <% _.each(nodes, function(node) { %><%=node.name%> <% }); %>
    "), @@ -56,24 +41,38 @@ var Josh = Josh || {}; }, getPrompt: function() { return self.templates.prompt({node: self.current}); - }, - current: null + } }; - self.handlers._original_exec = _shell.getCommandHandler('_exec'); - _shell.setCommandHandler("ls", self.handlers.ls); - _shell.setCommandHandler("pwd", self.handlers.pwd); - _shell.setCommandHandler("cd", self.handlers.cd); - _shell.setCommandHandler("_exec", self.handlers.exec); + _shell.setCommandHandler("ls", { + exec: ls, + completion: pathCompletionHandler + }); + _shell.setCommandHandler("pwd", { + exec: pwd, + completion: pathCompletionHandler + }); + _shell.setCommandHandler("cd", { + exec: cd, + completion: pathCompletionHandler + }); + _shell.setCommandHandler("_default", { + exec: _original_default.exec, + completion: commandAndPathCompletionHandler + }); _shell.onNewPrompt(function(callback) { callback(self.getPrompt()); }); function commandAndPathCompletionHandler(cmd, arg, line, callback) { + _console.log("calling command and path completion handler w/ cmd: '"+cmd+"', arg: '"+arg+"'"); + if(!arg) { + arg = cmd; + } if(arg[0] == '.' || arg[0] == '/') { return pathCompletionHandler(cmd, arg, line, callback); } - return self.handlers._original_exec.completion(cmd, arg, line, callback); + return _original_default.completion(cmd, arg, line, callback); } function pathCompletionHandler(cmd, arg, line, callback) { @@ -114,10 +113,6 @@ var Josh = Josh || {}; }); } - function exec(cmd, args, callback) { - callback(); - } - function cd(cmd, args, callback) { self.getNode(args[0], function(node) { if(!node) { diff --git a/javascripts/readline.js b/javascripts/readline.js index ecd84db..76e775e 100644 --- a/javascripts/readline.js +++ b/javascripts/readline.js @@ -127,18 +127,16 @@ var Josh = Josh || {}; // private methods function getKeyInfo(e) { + var code = e.keyCode || e.charCode; + var c = String.fromCharCode(code); var info = { - code: e.keyCode || e.charCode, + code: code, + character: c, shift: e.shiftKey, control: e.controlKey, alt: e.altKey, isChar: true }; - - var code = info.code; - var c = String.fromCharCode(code); - info.name = SPECIAL[code] || c; - info.char = c; return info; } @@ -632,9 +630,9 @@ var Josh = Josh || {}; } queue(function cmdKeyPress() { if(_inSearch) { - addSearchText(key.char); + addSearchText(key.character); } else { - addText(key.char); + addText(key.character); } if(_onKeydown) { _onKeydown(key); diff --git a/javascripts/shell.js b/javascripts/shell.js index 820f262..b6999de 100644 --- a/javascripts/shell.js +++ b/javascripts/shell.js @@ -72,18 +72,15 @@ var Josh = Josh || {}; } }, _default: { - exec: function(cmd, args, callback) { - var content = _.template('
    Unrecognized command: <%=cmd%>
    ', {cmd: cmd}); - callback(content); - } - }, - _exec: { exec: function(cmd, args, callback) { var content = _.template('
    Unrecognized command: <%=cmd%>
    ', {cmd: cmd}); callback(content); }, completion: function(cmd, arg, line, callback) { - callback(self.bestMatch(arg, self.commands())) + if(!arg) { + arg = cmd; + } + return callback(self.bestMatch(arg, self.commands())) } } }; @@ -94,6 +91,8 @@ var Josh = Josh || {}; var _searchMatch = ''; var _view, _panel; var _promptHandler; + var _initializationHandler; + var _initialized; // public methods var self = { @@ -123,6 +122,9 @@ var Josh = Josh || {}; } self.refresh(); }, + onInitialize: function(completionHandler) { + _initializationHandler = completionHandler; + }, onActivate: function(completionHandler) { _activationHandler = completionHandler; }, @@ -243,16 +245,7 @@ var Josh = Josh || {}; } function getHandler(cmd) { - var handler; - if(!cmd) { - handler = _cmdHandlers._default; - } else { - handler = _cmdHandlers[cmd]; - } - if(!handler) { - handler = _cmdHandlers._default; - } - return handler; + return _cmdHandlers[cmd] || _cmdHandlers._default; } function renderOutput(output, callback) { @@ -271,11 +264,10 @@ var Josh = Josh || {}; return callback(); } - // init - _readline.onActivate(function() { + function activate() { _console.log("activating shell"); if(!_view) { - _view = $(_shell_view_id); + _view = $(_shell_view_id); } if(!_panel) { _panel = $(_shell_panel_id); @@ -294,6 +286,17 @@ var Josh = Josh || {}; if(_activationHandler) { _activationHandler(); } + } + + // init + _readline.onActivate(function() { + if(!_initialized) { + _initialized = true; + if(_initializationHandler) { + return _initializationHandler(activate); + } + } + return activate(); }); _readline.onDeactivate(function() { if(_deactivationHandler) { @@ -340,22 +343,10 @@ var Josh = Josh || {}; var cmd = parts.shift() || ''; var arg = parts.pop() || ''; _console.log("getting completion handler for " + cmd); - var handler = _cmdHandlers[cmd]; - if(!handler) { - if(arg) { - if(!_cmdHandlers._default.completion) { - - // we have an argument, i.e. this isn't command completion, but we have no handler for command nor a completion handler for default - return callback(); - } - } - - // let's try command completion - handler = _cmdHandlers._exec; - arg = cmd; - cmd = 'exec'; - } else if(cmd == text) { + var handler = getHandler(cmd); + if(handler != _cmdHandlers._default && cmd && cmd == text) { + _console.log("valid cmd, no args: append space"); // the text to complete is just a valid command, append a space return callback(' '); } From 2c90cae690511fe76fce3c95963a077d0eefd585 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 14 Jan 2013 10:34:28 -0800 Subject: [PATCH 06/26] doc updates for 0.2.4 fixes --- index.html | 13 +- javascripts/example.js | 340 +++++++++++++++++++------------------ javascripts/pathhandler.js | 52 +++--- javascripts/shell.js | 2 +- 4 files changed, 218 insertions(+), 189 deletions(-) diff --git a/index.html b/index.html index a1e2657..4ac3b31 100644 --- a/index.html +++ b/index.html @@ -116,13 +116,22 @@

    Status

    • - more-like handling for output that exceeds the shell viewport size -
    • + more-like handling for output that exceeds the shell viewport size
    • resizing and close chrome
    • scrollwheel support
    +
  • Readline Issues/Omissions + +
      +
    • Not handling spaces in path completion
    • +
    • Missing support for Alt-Backspace & Alt-D in readline.js
    • +
    • + Word-commands do not have path separator awareness
    • +
    +
  • +

    Usage

    Until documentation is written, refer to index.html and diff --git a/javascripts/example.js b/javascripts/example.js index 16bbe84..0f2ea21 100644 --- a/javascripts/example.js +++ b/javascripts/example.js @@ -1,164 +1,176 @@ -/* ------------------------------------------------------------------------* - * Copyright 2013 Arne F. Claassen - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *-------------------------------------------------------------------------*/ - -(function(root, $, _) { - Josh.Example = (function(root, $, _) { - var _console = (Josh.Debug && root.console) ? root.console : { - log: function() { - } - }; - var fs = { - bin: {}, - boot: {}, - dev: {}, - etc: { - default: {}, - 'rc.d': {}, - sysconfig: {}, - x11: {} - }, - home: { - bob: {}, - jane: {} - }, - lib: {}, - 'lost+found': {}, - misc: {}, - mnt: { - cdrom: {}, - sysimage: {} - }, - net: {}, - opt: {}, - proc: {}, - root: {}, - sbin: {}, - usr: { - x11: {}, - bin: {}, - include: {}, - lib: {}, - local: {}, - man: {}, - sbin: {}, - share: { - doc: {} - }, - src: {} - }, - var: { - lib: {}, - lock: {}, - run: {}, - log: { - httpd: { - access_log: {}, - error_log: {} - }, - 'boot.log': {}, - cron: {}, - messages: {} - } - } - }; - - function buildTree(parent, node) { - parent.childnodes = _.map(_.pairs(node), function(pair) { - var child = { - name: pair[0], - path: parent.path + "/" + pair[0], - parent: parent - }; - buildTree(child, pair[1]); - return child; - }); - parent.children = _.keys(node); - return parent; - } - - function findNode(current, parts, callback) { - if(!parts || parts.length == 0) { - return callback(current); - } - if(parts[0] == ".") { - // carry on - } else if(parts[0] == "..") { - current = current.parent; - } else { - current = _.first(_.filter(current.childnodes, function(node) { - return node.name == parts[0]; - })); - } - if(!current) { - return callback(); - } - return findNode(current, _.rest(parts), callback); - } - - var root = buildTree({ - name: "", - path: "" - }, - fs - ); - root.path = '/'; - var history = Josh.History(); - var shell = Josh.Shell({history: history, console: _console}); - var pathhandler = Josh.PathHandler(shell, {console: _console}); - pathhandler.current = root; - pathhandler.getNode = function(path, callback) { - if(!path) { - return callback(pathhandler.current); - } - var parts = _.filter(path.split('/'), function(x) { - return x; - }); - var start = ((path || '')[0] == '/') ? root : pathhandler.current; - _console.log('start: ' + start.path + ', parts: ' + JSON.stringify(parts)); - return findNode(start, parts, callback); - }; - pathhandler.getChildNodes = function(node, callback) { - _console.log("children for " + node.name); - callback(node.childnodes); - }; - - $(document).ready(function() { - var consolePanel = $('#shell-panel'); - - function showConsole() { - consolePanel.slideDown(); - consolePanel.focus(); - } - - function hideConsole() { - consolePanel.slideUp(); - consolePanel.blur(); - } - - shell.onActivate(function() { - showConsole(); - }); - shell.onDeactivate(function() { - hideConsole(); - }); - }); - return { - Tree: root, - Shell: shell, - PathHandler: pathhandler - }; - })(root, $, _); -})(this, $, _); \ No newline at end of file +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +(function(root, $, _) { + Josh.Example = (function(root, $, _) { + var _console = (Josh.Debug && root.console) ? root.console : { + log: function() { + } + }; + var fs = { + bin: {}, + boot: {}, + dev: {}, + etc: { + default: {}, + 'rc.d': {}, + sysconfig: {}, + x11: {} + }, + home: { + bob: { + video: { + 'firefly.m4v': {} + }, + videos: { + 'Arrested Development': { + 's1e1.m4v': {} + }, + 'Better Off Ted': { + 's1e1.m4v': {} + } + } + }, + jane: {} + }, + lib: {}, + 'lost+found': {}, + misc: {}, + mnt: { + cdrom: {}, + sysimage: {} + }, + net: {}, + opt: {}, + proc: {}, + root: {}, + sbin: {}, + usr: { + x11: {}, + bin: {}, + include: {}, + lib: {}, + local: {}, + man: {}, + sbin: {}, + share: { + doc: {} + }, + src: {} + }, + var: { + lib: {}, + lock: {}, + run: {}, + log: { + httpd: { + access_log: {}, + error_log: {} + }, + 'boot.log': {}, + cron: {}, + messages: {} + } + } + }; + + function buildTree(parent, node) { + parent.childnodes = _.map(_.pairs(node), function(pair) { + var child = { + name: pair[0], + path: parent.path + "/" + pair[0], + parent: parent + }; + buildTree(child, pair[1]); + return child; + }); + parent.children = _.keys(node); + return parent; + } + + function findNode(current, parts, callback) { + if(!parts || parts.length == 0) { + return callback(current); + } + if(parts[0] == ".") { + // carry on + } else if(parts[0] == "..") { + current = current.parent; + } else { + current = _.first(_.filter(current.childnodes, function(node) { + return node.name == parts[0]; + })); + } + if(!current) { + return callback(); + } + return findNode(current, _.rest(parts), callback); + } + + var root = buildTree({ + name: "", + path: "" + }, + fs + ); + root.path = '/'; + var history = Josh.History(); + var shell = Josh.Shell({history: history, console: _console}); + var pathhandler = Josh.PathHandler(shell, {console: _console}); + pathhandler.current = root; + pathhandler.getNode = function(path, callback) { + if(!path) { + return callback(pathhandler.current); + } + var parts = _.filter(path.split('/'), function(x) { + return x; + }); + var start = ((path || '')[0] == '/') ? root : pathhandler.current; + _console.log('start: ' + start.path + ', parts: ' + JSON.stringify(parts)); + return findNode(start, parts, callback); + }; + pathhandler.getChildNodes = function(node, callback) { + _console.log("children for " + node.name); + callback(node.childnodes); + }; + + $(document).ready(function() { + var consolePanel = $('#shell-panel'); + + function showConsole() { + consolePanel.slideDown(); + consolePanel.focus(); + } + + function hideConsole() { + consolePanel.slideUp(); + consolePanel.blur(); + } + + shell.onActivate(function() { + showConsole(); + }); + shell.onDeactivate(function() { + hideConsole(); + }); + }); + return { + Tree: root, + Shell: shell, + PathHandler: pathhandler + }; + })(root, $, _); +})(this, $, _); diff --git a/javascripts/pathhandler.js b/javascripts/pathhandler.js index 9974219..e5c16a0 100644 --- a/javascripts/pathhandler.js +++ b/javascripts/pathhandler.js @@ -76,31 +76,39 @@ var Josh = Josh || {}; } function pathCompletionHandler(cmd, arg, line, callback) { - _console.log("completing '" + arg+ "'"); - var partial = ""; - self.getNode(arg, function(node) { - if(!node) { - _console.log("no node"); - var lastPathSeparator = arg.lastIndexOf("/"); - if(lastPathSeparator == arg.length - 1) { + _console.log("completing '" + arg + "'"); + if(!arg) { + _console.log("completing on current"); + return completeChildren(self.current, '', callback); + } + if(arg[arg.length - 1] == '/') { + _console.log("completing children w/o partial"); + return self.getNode(arg, function(node) { + if(!node) { + _console.log("no node for path"); return callback(); } - var parent = arg.substr(0, lastPathSeparator + 1); - _console.log("parent: " + parent); - partial = arg.substr(lastPathSeparator + 1); - return self.getNode(parent, function(node) { - if(!node) { - return callback(); - } - return completeChildren(node, partial, callback); - }); - } - if(!arg || arg[arg.length - 1] == '/') { - return completeChildren(node, partial, callback); + return completeChildren(node, '', callback); + }); + } + var partial = ""; + var lastPathSeparator = arg.lastIndexOf("/"); + var parent = arg.substr(0, lastPathSeparator + 1); + partial = arg.substr(lastPathSeparator + 1); + _console.log("completing children via parent '" + parent+"' w/ partial '"+partial+"'"); + return self.getNode(parent, function(node) { + if(!node) { + _console.log("no node for parent path"); + return callback(); } - return callback({ - completion: '/', - suggestions: [] + return completeChildren(node, partial, function(completion) { + if(completion && completion.completion == '' && completion.suggestions.length == 1) { + return callback({ + completion: '/', + suggestions: [] + }); + } + return callback(completion); }); }); } diff --git a/javascripts/shell.js b/javascripts/shell.js index b6999de..b312d85 100644 --- a/javascripts/shell.js +++ b/javascripts/shell.js @@ -167,6 +167,7 @@ var Josh = Josh || {}; _panel.animate({scrollTop: _view.height()}, 0); }, bestMatch: function(partial, possible) { + _console.log("bestMatch on partial '"+partial+"'"); var result = { completion: null, suggestions: [] @@ -187,7 +188,6 @@ var Josh = Josh || {}; result.suggestions = possible; return result; } - common = possible[0][0]; } for(var i = 0; i < possible.length; i++) { var option = possible[i]; From 25f466cabb3e2dc351453df43620c8ad9b705df1 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 14 Jan 2013 10:39:09 -0800 Subject: [PATCH 07/26] formatting cleanup --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 4ac3b31..9282e9a 100644 --- a/index.html +++ b/index.html @@ -127,7 +127,7 @@

    Status

  • Not handling spaces in path completion
  • Missing support for Alt-Backspace & Alt-D in readline.js
  • - Word-commands do not have path separator awareness
  • + Word commands do not have path separator awareness From 4e319d160bab3b4b6d5d08ea9881e9a1ebcdbbaf Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Sun, 20 Jan 2013 10:45:13 -0800 Subject: [PATCH 08/26] updated for 0.2.5 release --- index.html | 154 ++++++++++++++++++++++---- javascripts/example.js | 25 ++++- javascripts/killring.js | 104 ++++++++++++++++++ javascripts/pathhandler.js | 1 + javascripts/readline.js | 219 ++++++++++++++++++++++++++----------- javascripts/shell.js | 8 +- 6 files changed, 421 insertions(+), 90 deletions(-) create mode 100644 javascripts/killring.js diff --git a/index.html b/index.html index 9282e9a..1c7972f 100644 --- a/index.html +++ b/index.html @@ -18,8 +18,8 @@ - + @@ -28,17 +28,20 @@ #shell-panel { display: none; height: 400px; - width: 100%; + width: 97.0%; opacity: 0.9; background-color: #002f05; color: #00fe00; position: fixed; padding: 20px 20px 20px 20px; top: 0; + left: 0; z-index: 1000; font-family: 'Source Code Pro', sans-serif; font-size: 0.9em; - overflow: hidden; + overflow: scroll; + overflow-x: hidden; + overflow-y: scroll; } @@ -89,6 +92,9 @@

    josh.js 0.2

  • history.js - localStorage backed command history
  • +
  • + killring.js - killring for kill & yank handling in readline +
  • Demo

    @@ -99,7 +105,8 @@

    License

    josh.js is licensed under the Apache 2.0 License

    -

    Status

    +

    + Status

    • code is ready for experimental use @@ -116,41 +123,128 @@

      Status

      • - more-like handling for output that exceeds the shell viewport size
      • + more-like handling for output that exceeds the shell viewport size +
      • resizing and close chrome
      • -
      • scrollwheel support
      • -
      -
    • -
    • Readline Issues/Omissions - -
        -
      • Not handling spaces in path completion
      • -
      • Missing support for Alt-Backspace & Alt-D in readline.js
      • -
      • - Word commands do not have path separator awareness
    • +
    • Readline has not been tested with non-ascii.
    - -

    Usage

    +

    + Usage

    Until documentation is written, refer to index.html and example.js for a sample implementation of a shell with path completion.

    -

    Components

    +

    + Components +

    -

    josh is built from 4 components and can be used in part or in full.

    +

    josh is built from 5 components and can be used in part or in full.

    -

    readline.js

    +

    + readline.js +

    readline.js has no dependencies on any outside libraries, although it requires either - history.js or an object implementing the same calls.

    + history.js and killring.js or objects implementing the same calls.

    It implements key trapping to bring GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with shell.js to create a full console.

    -

    shell.js

    +

    + Line Editing +

    + +

    In the below C-x refers to the Ctrl-x keystroke, while + M-x refers to the Meta-x which is mapped to Alt, ⌘ and + Left Windows.

    + +
    +
    Movement
    +
    + C-b or Left Arrow +
    +
    Move back one character
    +
    + M-b or Right Arrow +
    +
    Move back one word
    +
    C-f
    +
    Move forward one character
    +
    M-f
    +
    Move forward one word
    +
    + C-a or Home +
    +
    Move to the beginning of the line
    +
    + C-e or End +
    +
    Move to the end of the line
    + +
    +
    Edit/Kill
    +
    Backspace
    +
    Delete one character back
    +
    + C-d or Delete +
    +
    Delete character under cursor
    +
    C-k
    +
    + Kill (i.e. put in kill ring) text to the end of the line +
    +
    M-Backspace
    +
    + Kill one word back +
    +
    M-d
    +
    + Kill word under cursor +
    +
    C-y
    +
    + Yank (i.e. pull from kill ring) the most recently killed text +
    +
    M-y
    +
    Rotate to the next item in killring and yank it. Must be preceded by yank +
    + +
    +
    History
    +
    C-r
    +
    Reverse search through history
    +
    + C-p or Up Arrow +
    +
    Previous entry in history
    +
    + C-n or Down Arrow +
    +
    Next entry in history
    +
    Page Up
    +
    Top of history
    +
    Page Down
    +
    Bottom of history
    + +
    +
    Misc
    +
    C-l
    +
    refresh line (clear screen in shell)
    +
    Tab
    +
    Invoke completion handler for text under cursor
    +
    + C-c or Esc +
    +
    Deactivate Readline (closes the shell)
    +
    ~
    +
    Activate Readline (opens the shell)
    +
    +

    + shell.js +

    shell.js has external dependencies of jQuery, Underscore and internal dependencies of readline.js and @@ -169,7 +263,9 @@

    shell.js

  • history - show the command history captured by readline.js in history.js
  • -

    pathhandler.js

    +

    + pathhandler.js +

    pathhandler.js is a mix in to easily add the cd, ls and pwd commands as well as path completion. It has the same external dependencies of @@ -180,13 +276,23 @@

    pathhandler.js

    getChildNodes, this library adds path traversal, discovery and completion just like a bash shell.

    -

    history.js

    +

    + history.js +

    history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the shell.js history command to list all executed commands, and by readline.js for up/down arrow and reverse search capabilities.

    +

    + killring.js +

    + +

    + killing.js implements the kill and yank behavior as well as state tracking, i.e. multiple consecutive kills are combined as a single kill and killring rotation tracks the previous yank, so that the + readline.js can remove the previous yank and replace it with the rotated text.

    + diff --git a/javascripts/example.js b/javascripts/example.js index 0f2ea21..884b0de 100644 --- a/javascripts/example.js +++ b/javascripts/example.js @@ -128,7 +128,25 @@ ); root.path = '/'; var history = Josh.History(); - var shell = Josh.Shell({history: history, console: _console}); + var killring = new Josh.KillRing(); + var readline = new Josh.ReadLine({history: history, killring: killring, console: _console }); + var shell = Josh.Shell({readline: readline, history: history, console: _console}); + var killringItemTemplate = _.template("
    <%- i %> <%- cmd %>
    "); + + shell.setCommandHandler("killring", { + exec: function(cmd, args, callback) { + if(args[0] == "-c") { + killring.clear(); + callback(); + return; + } + var content = $('
    '); + _.each(killring.items(), function(cmd, i) { + content.append(killringItemTemplate({cmd: cmd, i: i})); + }); + callback(content); + } + }); var pathhandler = Josh.PathHandler(shell, {console: _console}); pathhandler.current = root; pathhandler.getNode = function(path, callback) { @@ -167,10 +185,11 @@ hideConsole(); }); }); - return { + Josh.Instance = { Tree: root, Shell: shell, - PathHandler: pathhandler + PathHandler: pathhandler, + KillRing: killring }; })(root, $, _); })(this, $, _); diff --git a/javascripts/killring.js b/javascripts/killring.js new file mode 100644 index 0000000..dc22874 --- /dev/null +++ b/javascripts/killring.js @@ -0,0 +1,104 @@ +/* ------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ + +var Josh = Josh || {}; +(function(root) { + Josh.KillRing = function(config) { + config = config || {}; + + var _console = Josh.Debug && root.console ? root.console : {log: function() { + }}; + var _ring = config.ring || []; + var _cursor = config.cursor || 0; + var _uncommitted = false; + var _yanking = false; + if(_ring.length == 0) { + _cursor = -1; + } else if(_cursor >= _ring.length) { + _cursor = _ring.length - 1; + } + var self = { + isinkill: function() { + return _uncommitted; + }, + lastyanklength: function() { + if(!_yanking) { + return 0; + } + return _ring[_cursor].length; + }, + append: function(value) { + _yanking = false; + if(!value) { + return; + } + if(_ring.length == 0 || !_uncommitted) { + _ring.push(''); + } + _cursor = _ring.length - 1; + _console.log("appending: " + value); + _uncommitted = true; + _ring[_cursor] += value; + }, + prepend: function(value) { + _yanking = false; + if(!value) { + return; + } + if(_ring.length == 0 || !_uncommitted) { + _ring.push(''); + } + _cursor = _ring.length - 1; + _console.log("prepending: " + value); + _uncommitted = true; + _ring[_cursor] = value + _ring[_cursor]; + }, + commit: function() { + _console.log("committing"); + _yanking = false; + _uncommitted = false; + }, + yank: function() { + self.commit(); + if(_ring.length == 0) { + return null; + } + _yanking = true; + return _ring[_cursor]; + }, + rotate: function() { + if(!_yanking || _ring.length == 0) { + return null; + } + --_cursor; + if(_cursor < 0) { + _cursor = _ring.length - 1; + } + return self.yank(); + }, + items: function() { + return _ring.slice(0); + }, + clear: function() { + _ring = []; + _cursor = -1; + _yanking = false; + _uncommited = false; + } + }; + return self; + } +})(this); \ No newline at end of file diff --git a/javascripts/pathhandler.js b/javascripts/pathhandler.js index e5c16a0..9e3512a 100644 --- a/javascripts/pathhandler.js +++ b/javascripts/pathhandler.js @@ -17,6 +17,7 @@ var Josh = Josh || {}; (function(root, $, _) { Josh.PathHandler = function(shell, config) { + config = config || {}; var _console = config.console || (Josh.Debug && root.console ? root.console : { log: function() { } diff --git a/javascripts/readline.js b/javascripts/readline.js index 76e775e..770f13e 100644 --- a/javascripts/readline.js +++ b/javascripts/readline.js @@ -47,6 +47,7 @@ var Josh = Josh || {}; var _history = config.history || new Josh.History(); var _activationKey = config.activationKey || { keyCode: 192, shiftKey: true }; // ~ var _deactivationKey = config.deactivationKey || { keyCode: 27 }; // Esc + var _killring = config.killring || new Josh.KillRing(); var _active = false; var _onActivate; var _onDeactivate; @@ -56,6 +57,7 @@ var Josh = Josh || {}; var _onChange; var _onCancel; var _onEOT; + var _onClear; var _onSearchStart; var _onSearchEnd; var _onSearchChange; @@ -64,7 +66,6 @@ var Josh = Josh || {}; var _lastSearchText = ''; var _text = ''; var _cursor = 0; - var _kill_buffer = ''; var _lastCmd; var _completionActive; var _cmdQueue = []; @@ -96,6 +97,9 @@ var Josh = Josh || {}; onChange: function(changeHandler) { _onChange = changeHandler; }, + onClear: function(completionHandler) { + _onClear = completionHandler; + }, onEnter: function(enterHandler) { _onEnter = enterHandler; }, @@ -129,7 +133,7 @@ var Josh = Josh || {}; function getKeyInfo(e) { var code = e.keyCode || e.charCode; var c = String.fromCharCode(code); - var info = { + return { code: code, character: c, shift: e.shiftKey, @@ -137,7 +141,6 @@ var Josh = Josh || {}; alt: e.altKey, isChar: true }; - return info; } function queue(cmd) { @@ -167,10 +170,28 @@ var Josh = Josh || {}; _onSearchEnd(); } } + if(!_inSearch && _killring.isinkill() && cmd.name.substr(0, 7) != 'cmdKill') { + _killring.commit(); + } _lastCmd = cmd.name; cmd(); } + function suspend(asyncCall) { + _suspended = true; + asyncCall(resume); + } + + function resume() { + var cmd = _cmdQueue.shift(); + if(!cmd) { + _suspended = false; + return; + } + call(cmd); + resume(); + } + function cmdCancelSearch() { // do nothing.. action for this was already taken in call() } @@ -226,21 +247,6 @@ var Josh = Josh || {}; } - function suspend(asyncCall) { - _suspended = true; - asyncCall(resume); - } - - function resume() { - var cmd = _cmdQueue.shift(); - if(!cmd) { - _suspended = false; - return; - } - call(cmd); - resume(); - } - function cmdEnd() { updateCursor(_text.length); } @@ -267,42 +273,14 @@ var Josh = Josh || {}; if(_cursor == 0) { return; } - var previousWhitespace = 0; - var findNonWhiteSpace = _text[_cursor] == ' ' || _text[_cursor - 1] == ' '; - for(var i = _cursor - 1; i > 0; i--) { - if(findNonWhiteSpace) { - if(_text[i] != ' ') { - findNonWhiteSpace = false; - } - } else { - if(_text[i] == ' ') { - previousWhitespace = i + 1; - break; - } - } - } - updateCursor(previousWhitespace); + updateCursor(findBeginningOfPreviousWord()); } function cmdForwardWord() { if(_cursor == _text.length) { return; } - var nextWhitespace = _text.length; - var findNonWhitespace = _text[_cursor] == ' '; - for(var i = _cursor + 1; i < _text.length; i++) { - if(findNonWhitespace) { - if(_text[i] != ' ') { - findNonWhitespace = false; - } - } else { - if(_text[i] == ' ') { - nextWhitespace = i; - break; - } - } - } - updateCursor(nextWhitespace); + updateCursor(findEndOfCurrentWord()); } function cmdHistoryPrev() { @@ -348,20 +326,71 @@ var Josh = Josh || {}; } function cmdKillToEOF() { - _kill_buffer = _text.substr(_cursor); + _killring.append(_text.substr(_cursor)); _text = _text.substr(0, _cursor); refresh(); } - function cmdYank() { - _text = insert(_text, _cursor, _kill_buffer); - updateCursor(_cursor + _kill_buffer.length); + function cmdKillWordForward() { + if(_text.length == 0) { + if(_onEOT) { + _onEOT(); + return; + } + } + if(_cursor == _text.length) { + return; + } + var end = findEndOfCurrentWord(); + _killring.append(_text.substring(_cursor, end)) + _text = remove(_text, _cursor, end); + refresh(); } - function cmdRefresh() { + function cmdKillWordBackward() { + if(_cursor == 0) { + return; + } + var oldCursor = _cursor; + _cursor = findBeginningOfPreviousWord(); + _killring.prepend(_text.substring(_cursor, oldCursor)); + _text = remove(_text, _cursor, oldCursor); refresh(); } + function cmdYank() { + var yank = _killring.yank(); + if(!yank) { + return; + } + _text = insert(_text, _cursor, yank); + updateCursor(_cursor + yank.length); + } + + function cmdRotate() { + var lastyanklength = _killring.lastyanklength(); + if(!lastyanklength) { + return; + } + var yank = _killring.rotate(); + if(!yank) { + return; + } + var oldCursor = _cursor; + _cursor = _cursor - lastyanklength; + _text = remove(_text, _cursor, oldCursor); + _text = insert(_text, _cursor, yank); + updateCursor(_cursor + yank.length); + } + + function cmdClear() { + if(_onClear) { + _onClear(); + } else { + refresh(); + } + } + function cmdReverseSearch() { if(!_inSearch) { _inSearch = true; @@ -429,6 +458,51 @@ var Josh = Josh || {}; && Boolean(a.altKey) == Boolean(b.altKey); } + function findBeginningOfPreviousWord() { + var position = _cursor - 1; + if(position < 0) { + return 0; + } + var word = false; + for(var i = position; i > 0; i--) { + var word2 = isWordChar(_text[i]); + if(word && !word2) { + return i + 1; + } + word = word2; + } + return 0; + } + + function findEndOfCurrentWord() { + if(_text.length == 0) { + return 0; + } + var position = _cursor + 1; + if(position >= _text.length) { + return _text.length - 1; + } + var word = false; + for(var i = position; i < _text.length; i++) { + var word2 = isWordChar(_text[i]); + if(word && !word2) { + return i; + } + word = word2; + } + return _text.length - 1; + } + + function isWordChar(c) { + if(c == undefined) { + return false; + } + var code = c.charCodeAt(0); + return (code >= 48 && code <= 57) + || (code >= 65 && code <= 90) + || (code >= 97 && code <= 122); + } + function remove(text, from, to) { if(text.length <= 1 || text.length <= to - from) { return ''; @@ -467,17 +541,14 @@ var Josh = Josh || {}; } // return as unhandled if we're not active or the key is just a modifier key - if(!_active || e.keyCode == 16 || e.keyCode == 17 || e.keyCode == 18) { + if(!_active || e.keyCode == 16 || e.keyCode == 17 || e.keyCode == 18 || e.keyCode == 91) { return true; } var handled = true; - // check keys special keys, regardless of modifiers + // check for some special keys, regardless of modifiers switch(e.keyCode) { - case 8: // Backspace - queue(cmdBackspace); - break; case 9: // Tab queue(cmdComplete); break; @@ -532,9 +603,14 @@ var Josh = Josh || {}; } if(!handled) { - // intercept ctrl- and alt- sequences - if(e.ctrlKey && !e.shiftKey && !e.altKey) { + // intercept ctrl- and meta- sequences + if(e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) { switch(e.keyCode) { + case 8: // Backspace + + // Backspace behaves the same with or without Ctrl, but different for meta + queue(cmdBackspace); + break; case 65: // A queue(cmdHome); handled = true; @@ -576,7 +652,7 @@ var Josh = Josh || {}; handled = true; break; case 76: // L - queue(cmdRefresh); + queue(cmdClear); handled = true; break; case 82: // R @@ -584,16 +660,35 @@ var Josh = Josh || {}; handled = true; break; } - } else if(e.altKey && !e.ctrlKey && !e.shiftKey) { + } else if((e.altKey || e.metaKey) && !e.ctrlKey && !e.shiftKey) { switch(e.keyCode) { + case 8: // Backspace + queue(cmdKillWordBackward); + break; case 66: // B queue(cmdBackwardWord); handled = true; break; + case 68: // D + queue(cmdKillWordForward); + handled = true; + break; case 70: // F queue(cmdForwardWord); handled = true; break; + case 89: // Y + queue(cmdRotate); + handled = true; + break; + } + } else { + + // check for some more special keys without Ctrl or Alt + switch(e.keyCode) { + case 8: // Backspace + queue(cmdBackspace); + break; } } } diff --git a/javascripts/shell.js b/javascripts/shell.js index b312d85..233d31f 100644 --- a/javascripts/shell.js +++ b/javascripts/shell.js @@ -167,7 +167,7 @@ var Josh = Josh || {}; _panel.animate({scrollTop: _view.height()}, 0); }, bestMatch: function(partial, possible) { - _console.log("bestMatch on partial '"+partial+"'"); + _console.log("bestMatch on partial '" + partial + "'"); var result = { completion: null, suggestions: [] @@ -307,6 +307,12 @@ var Josh = Josh || {}; _line = line; self.render(); }); + _readline.onClear(function() { + _cmdHandlers.clear.exec(null, null, function() { + renderOutput(null, function() { + }); + }); + }); _readline.onSearchStart(function() { $(_input_id).replaceWith(_search_html); _console.log('started search'); From f3c3e97427b986e311770bb898471dd8b0ec0c67 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 21 Jan 2013 17:38:14 -0800 Subject: [PATCH 09/26] 0.2.6 update --- index.html | 446 ++++++++++++++++++++-------------------- javascripts/example.js | 35 +++- javascripts/readline.js | 246 +++++++++------------- javascripts/shell.js | 11 +- 4 files changed, 353 insertions(+), 385 deletions(-) diff --git a/index.html b/index.html index 1c7972f..35bc881 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,6 @@ Josh.js by sdether - - + + + - + + @@ -46,8 +48,8 @@
    -
    Type help or hit TAB for a list of commands. Hit Esc or - Ctrl-C to hide this shell +
    Type help or hit TAB for a list of commands. Hit + Ctrl-C to hide the shell
    @@ -63,237 +65,241 @@
    -
    -
    -

    Josh.js

    +
    +
    +

    Josh.js

    -

    Toolkit for building bash-like shell in the browser, including full readline support

    -
    - Project maintained by sdether - Hosted on GitHub Pages — Theme by mattgraham -
    +

    Toolkit for building bash-like shell in the browser, including full readline support

    +
    + Project maintained by sdether + Hosted on GitHub Pages — Theme by mattgraham +
    -

    josh.js 0.2

    +

    josh.js 0.2

    -

    - Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components: -

    +

    + Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components: +

    -
      -
    • - readline.js - full readline support for ctrl sequences, tab, history, etc. -
    • -
    • - shell.js - visual presentation of the shell and command handling -
    • -
    • - pathhandler.js - provide cd, ls, pwd and path completion toolikit -
    • -
    • - history.js - localStorage backed command history -
    • -
    • - killring.js - killring for kill & yank handling in readline -
    • -
    +
      +
    • + readline.js - full readline support for ctrl sequences, tab, history, etc. +
    • +
    • + shell.js - visual presentation of the shell and command handling +
    • +
    • + pathhandler.js - provide cd, ls, pwd and path completion toolikit +
    • +
    • + history.js - localStorage backed command history +
    • +
    • + killring.js - killring for kill & yank handling in readline +
    • +
    -

    Demo

    +

    Demo

    -

    Hit the ~ key to show a demo console.

    +

    Hit the ~ key to show a demo console.

    -

    License

    +

    License

    -

    josh.js is licensed under the Apache 2.0 License

    +

    josh.js is licensed under the Apache 2.0 License

    -

    - Status

    +

    + Status

    -
      -
    • code is ready for experimental use +
        +
      • code is ready for experimental use -
          -
        • Tested under Chrome, Firefox, Safari and IE9
        • -
        • API may not yet be stable
        • -
        -
      • -
      • needs minified versions of complete toolkit and just readline.js
      • -
      • needs code documentation and documentation site
      • -
      • would like to add AMD support
      • -
      • base shell UI should get some basic behaviors - -
          -
        • - more-like handling for output that exceeds the shell viewport size -
        • -
        • resizing and close chrome
        • -
        -
      • -
      • Readline has not been tested with non-ascii.
      • +
          +
        • Tested under Chrome, Firefox, Safari and IE9
        • +
        • API may not yet be stable
        -

        - Usage

        - -

        Until documentation is written, refer to index.html and - example.js for a sample implementation of a shell with path completion.

        - -

        - Components -

        - -

        josh is built from 5 components and can be used in part or in full.

        - -

        - readline.js -

        - -

        readline.js has no dependencies on any outside libraries, although it requires either - history.js and killring.js or objects implementing the same calls.

        - -

        It implements key trapping to bring - GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with - shell.js to create a full console.

        - -

        - Line Editing -

        - -

        In the below C-x refers to the Ctrl-x keystroke, while - M-x refers to the Meta-x which is mapped to Alt, ⌘ and - Left Windows.

        - -
        -
        Movement
        -
        - C-b or Left Arrow -
        -
        Move back one character
        -
        - M-b or Right Arrow -
        -
        Move back one word
        -
        C-f
        -
        Move forward one character
        -
        M-f
        -
        Move forward one word
        -
        - C-a or Home -
        -
        Move to the beginning of the line
        -
        - C-e or End -
        -
        Move to the end of the line
        - -
        -
        Edit/Kill
        -
        Backspace
        -
        Delete one character back
        -
        - C-d or Delete -
        -
        Delete character under cursor
        -
        C-k
        -
        - Kill (i.e. put in kill ring) text to the end of the line -
        -
        M-Backspace
        -
        - Kill one word back -
        -
        M-d
        -
        - Kill word under cursor -
        -
        C-y
        -
        - Yank (i.e. pull from kill ring) the most recently killed text -
        -
        M-y
        -
        Rotate to the next item in killring and yank it. Must be preceded by yank -
        - -
        -
        History
        -
        C-r
        -
        Reverse search through history
        -
        - C-p or Up Arrow -
        -
        Previous entry in history
        -
        - C-n or Down Arrow -
        -
        Next entry in history
        -
        Page Up
        -
        Top of history
        -
        Page Down
        -
        Bottom of history
        - -
        -
        Misc
        -
        C-l
        -
        refresh line (clear screen in shell)
        -
        Tab
        -
        Invoke completion handler for text under cursor
        -
        - C-c or Esc -
        -
        Deactivate Readline (closes the shell)
        -
        ~
        -
        Activate Readline (opens the shell)
        -
        -

        - shell.js -

        - -

        shell.js has external dependencies of jQuery, - Underscore and internal dependencies of readline.js and - history.js.

        - -

        It provides a simple console UI, using a panel for the console viewport and an auto-scrolling - view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string. -

        - -

        It also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, - shell.js provides the following commands:

        + +
      • needs minified versions of complete toolkit and just readline.js
      • +
      • needs code documentation and documentation site
      • +
      • would like to add AMD support
      • +
      • base shell UI should get some basic behaviors
          -
        • help - list all known commands (including user added)
        • -
        • clear - clear the "screen" i.e. viewport
        • -
        • history - show the command history captured by readline.js in history.js +
        • + more-like handling for output that exceeds the shell viewport size
        • +
        • resizing and close chrome
        -

        - pathhandler.js -

        - -

        pathhandler.js is a mix in to easily add the cd, ls and - pwd commands as well as path completion. It has the same external dependencies of - jQuery, Underscore as - shell.js and also uses Underscore templating.

        - -

        By implementing the functions getNode and - getChildNodes, this library adds path traversal, discovery and completion just like a bash shell. -

        - -

        - history.js -

        - -

        - history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the - shell.js history command to list all executed commands, and by - readline.js for up/down arrow and reverse search capabilities.

        - -

        - killring.js -

        - -

        - killing.js implements the kill and yank behavior as well as state tracking, i.e. multiple consecutive kills are combined as a single kill and killring rotation tracks the previous yank, so that the - readline.js can remove the previous yank and replace it with the rotated text.

        - -
    + +
  • Readline has not been tested with non-ascii.
  • + +

    + Usage

    + +

    Until documentation is written, refer to index.html and + example.js for a sample implementation of a shell with path completion.

    + +

    + Components +

    + +

    josh is built from 5 components and can be used in part or in full.

    + +

    + readline.js +

    + +

    readline.js has no dependencies on any outside libraries, although it requires either + history.js and killring.js or objects implementing the same calls.

    + +

    It implements key trapping to bring + GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with + shell.js to create a full console.

    + +

    + Line Editing +

    + +

    In the below C-x refers to the Ctrl-x keystroke, while + M-x refers to the Meta-x which is mapped to Alt, ⌘ and + Left Windows.

    + +
    +
    Movement
    +
    + C-b or Left Arrow +
    +
    Move back one character
    +
    + M-b or Right Arrow +
    +
    Move back one word
    +
    C-f
    +
    Move forward one character
    +
    M-f
    +
    Move forward one word
    +
    + C-a or Home +
    +
    Move to the beginning of the line
    +
    + C-e or End +
    +
    Move to the end of the line
    + +
    +
    Edit/Kill
    +
    Backspace
    +
    Delete one character back
    +
    + C-d or Delete +
    +
    Delete character under cursor
    +
    C-k
    +
    + Kill (i.e. put in kill ring) text to the end of the line +
    +
    M-Backspace
    +
    + Kill one word back +
    +
    M-d
    +
    + Kill word under cursor +
    +
    C-y
    +
    + Yank (i.e. pull from kill ring) the most recently killed text +
    +
    M-y
    +
    Rotate to the next item in killring and yank it. Must be preceded by yank +
    + +
    +
    History
    +
    C-r
    +
    Reverse search through history
    +
    + C-p or Up Arrow +
    +
    Previous entry in history
    +
    + C-n or Down Arrow +
    +
    Next entry in history
    +
    Page Up
    +
    Top of history
    +
    Page Down
    +
    Bottom of history
    + +
    +
    Misc
    +
    C-l
    +
    refresh line (clear screen in shell)
    +
    Tab
    +
    Invoke completion handler for text under cursor
    +
    + Esc in reverse search +
    +
    Cancel search
    +
    C-c
    +
    call onCancel handler
    +
    + C-d on empty line +
    +
    call onCancel handler
    +
    +

    + shell.js +

    + +

    shell.js has external dependencies of jQuery, + Underscore and internal dependencies of readline.js and + history.js.

    + +

    It provides a simple console UI, using a panel for the console viewport and an auto-scrolling + view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string. +

    + +

    It also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, + shell.js provides the following commands:

    + +
      +
    • help - list all known commands (including user added)
    • +
    • clear - clear the "screen" i.e. viewport
    • +
    • history - show the command history captured by readline.js in history.js +
    • +
    +

    + pathhandler.js +

    + +

    pathhandler.js is a mix in to easily add the cd, ls and + pwd commands as well as path completion. It has the same external dependencies of + jQuery, Underscore as + shell.js and also uses Underscore templating.

    + +

    By implementing the functions getNode and + getChildNodes, this library adds path traversal, discovery and completion just like a bash shell. +

    + +

    + history.js +

    + +

    + history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the + shell.js history command to list all executed commands, and by + readline.js for up/down arrow and reverse search capabilities.

    + +

    + killring.js +

    + +

    + killing.js implements the kill and yank behavior as well as state tracking, i.e. multiple consecutive kills are combined as a single kill and killring rotation tracks the previous yank, so that the + readline.js can remove the previous yank and replace it with the rotated text.

    + +
    + + + + + + + + + + + + + + + + + + +
    + +
    +

    Hello World Shell

    + +

    This tutorial shows how easy it is to create the below shell window with a custom prompt and a new command + hello.

    + +

    + +

    +
    Type help or hit TAB for a list of commands.
    +
    +
    +

    +

    Creating the Shell

    + +

    The + Josh.Shell uses local storage to store a history of the commands that you have typed. By default this is keyed with + josh.history. That history is available to all instances of the shell on your site. For this tutorial, we want to make sure we have our own copy, so we don't get commands from other tutorials and examples, so we need to create a history object with its own key: +

    +
    var history = new Josh.History({ key: 'helloworld.history'});
    +

    Now we can create a Shell instance with that history:

    +
    var shell = Josh.Shell({history: history});
    +

    Now the shell exists but has not yet been activated.

    + +

    Note on how the shell attaches to its UI elements: By default + Josh.Shell expects to find a div#shell-panel that contains a + div#shell-view. The former is the physical container providing the dimensions of the shell, while the latter is a div the shell will continue to append to and scroll to mimic a screen. If you want to use other div IDs (because you have multiple shells on one page), you can provide + shell-panel-id and shell-view-id in the constructor.

    + +

    Rendering the prompt

    + +

    The default prompt for Josh is + jsh$. Let's create a prompt instead that keeps track of how many times it has been shown: +

    +
    var promptCounter = 0;
    +shell.onNewPrompt(function(callback) {
    +    promptCounter++;
    +    callback("[" + promptCounter + "] $ ");
    +});
    +

    + onNewPrompt is called every time Josh needs to re-render the prompt. This happens usually a command is executed, but can also happen on tab completion, when a list of possible completions is shown. + onNewPrompt expects a function that accepts a callback as its only argument. Josh will not continue until the callback has been called with an html string to display. This allows the prompt to rendered as part of an asynchronous action. For our example, we just increment the promptCounter and send back a simple string with the counter. +

    + +

    Adding a new command

    + +

    Josh implements just three commands out of the box:

    +
      +
    • help - show a list of known commands
    • +
    • history - show the commands previously entered
    • +
    • clear - clear the console (i.e. remove all children from div#shell-view
    • +
    +

    Let's add a new command called hello with tab completion:

    +
    shell.setCommandHandler("hello", {
    +    exec: function(cmd, args, callback) {
    +        var arg = args[0] || '';
    +        var response = "who is this " + arg + " you are talking to?";
    +        if(arg === 'josh') {
    +            response = 'pleased to meet you.';
    +        } else if(arg === 'world') {
    +            response = 'world says hi.'
    +        } else if(!arg) {
    +            response = 'who are you saying hello to?';
    +        }
    +        callback(response);
    +    },
    +    completion: function(cmd, arg, line, callback) {
    +        callback(shell.bestMatch(arg, ['world', 'josh']))
    +    }
    +});
    +

    To add a command, simply call shell.setCommandHandler and provide it at least an + exec handler, and optionally a completion handler.

    + +

    + exec expects a function that takes the name of the called command, an array of whitespace separated arguments to the command and a callback that MUST be called with an html string to output to the console. For our toy command we implement a command named + hello which understands arguments josh and + world and has alternate outputs for no arguments and unknown arguments.

    + +

    + completion expects a function that takes the current command, the current argument being completed, the complete line (since the cursor may not be at the tail) and a callback that MUST be called either with a completion data structure. The format of this data structure is: +

    +
    {
    +  completion: {string to append to current argument},
    +  suggestions: [{array of possible completions},...]
    +}
    +

    Here are some expected completions:

    +
      +
    • hello <TAB> => {completion:null,suggestions:['world', 'josh']}
    • +
    • hello wo<TAB> => {completion:'rld',suggestions:['world']}
    • +
    • hello x<TAB> => {completion:'',suggestions:[]}
    • +
    +

    To simplify this process of finding the partial strings and possible completions, Shell offers a method + bestMatch which expects as input the partial to match (our arg to the completion handler) and a list of all possible completions and it will narrow down what to append to the partial and what suggestions to show. +

    + +

    Turning it on

    + +

    Now that we've added our custom behavior to + Josh.Shell, all we have to do is activate the shell to render the prompt and start capturing all keystrokes via readline (i.e. if you want the shell to only capture keys while the shell has focus, it is up to you to write focus and blur code to activate and deactivate the shell.) +

    +
    shell.activate();
    +

    And that's all there is to getting a custom Bash-like shell in your web page.

    +
    +
    + + + + \ No newline at end of file diff --git a/index.html b/index.html index f41526c..3d820b1 100644 --- a/index.html +++ b/index.html @@ -99,10 +99,14 @@

    josh.js 0.2

    -

    Demo

    +

    Live Demo

    Hit the ~ key to show a demo console ( Annotated source of demo)

    +

    Tutorials

    +
      +
    • Hello world - put a console on a web page and add a new custom command with completion
    • +

    License

    josh.js is licensed under the Apache 2.0 License

    diff --git a/stylesheets/styles.css b/stylesheets/styles.css index 4d18547..2f3075b 100644 --- a/stylesheets/styles.css +++ b/stylesheets/styles.css @@ -712,7 +712,6 @@ dt { max-width: 650px; margin: 0 auto; padding: 0 10px; - background: blue; margin: 6px auto; } #header nav li { From e83070c05cb64919814a2888e75067dc1c685dc2 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 4 Feb 2013 23:11:16 -0800 Subject: [PATCH 17/26] moving the sample shell inside the page --- index.html | 46 +++++++++++++++--------------------------- javascripts/example.js | 38 +++++----------------------------- 2 files changed, 21 insertions(+), 63 deletions(-) diff --git a/index.html b/index.html index 3d820b1..1e8822a 100644 --- a/index.html +++ b/index.html @@ -28,31 +28,19 @@ -
    -
    Type help or hit TAB for a list of commands. Hit - Ctrl-C to hide the shell -
    -
    -

    Setup Document Behavior

    Activation and display behavior happens at document ready time.

        $(document).ready(function() {

    The default name for the div the shell uses as its container is shell-panel, although that can be changed via -the shell config parameter shell-view-id. The Shell display model relies on a div to contain a 'view'. The -acts as the view-port, i.e. the visible portion of the shell content, while the view is appended to and -scrolled up as new content is added.

          var $consolePanel = $('#shell-panel');

    We use jquery-ui's resizable to let us drag the bottom edge of the console up and down.

          $consolePanel.resizable({ handles: "s"});

    Wire up a the keypress handler. This will be used only for shell activation.

          $(document).keypress(function(event) {

    If the shell is already active drop out of the keyhandler, since all keyhandling happens in Readline.

            if(shell.isActive()) {
    -          return;
    -        }

    Mimicking Quake-style dropdown consoles, we activate and show on ~.

            _console.log("activating shell");
    -        if(event.keyCode == 126) {
    -          event.preventDefault();
    -          shell.activate();
    -          $consolePanel.slideDown();
    -          $consolePanel.focus();
    -        }
    -      });

    Whenever we get either a EOT (Ctrl-D on empty line) or a Cancel (Ctrl-C) signal from the shell, -we deactivate the shell and hide the console.

          function hideAndDeactivate() {
    -        _console.log("deactivating shell");
    -        shell.deactivate();
    -        $consolePanel.slideUp();
    -        $consolePanel.blur();
    -      }

    Attach our hide function to the EOT and Cancel events.

          shell.onEOT(hideAndDeactivate);
    -      shell.onCancel(hideAndDeactivate);
    -    });

    We attach the various objects we've created here to Josh.Instance purely so they can be inspected via a +the shell config parameter shell-panel-id. The Shell display model relies on a 'panel' to contain a 'view'. +The 'panel' acts as the view-port, i.e. the visible portion of the shell content, while the 'view' is appended +to and scrolled up as new content is added.

          var $consolePanel = $('#shell-panel');

    We use jquery-ui's resizable to let us drag the bottom edge of the console up and down.

          $consolePanel.resizable({ handles: "s"});

    activate the shell

          shell.activate();
    +    });

    We attach the various objects we've created here to Josh.Instance purely so they can be inspected via a javascript console. This is not required for the functionality of the example.

        Josh.Instance = {
           Tree: treeroot,
           Shell: shell,
           PathHandler: pathhandler,
           KillRing: killring
    -    };

    This code builds our fake directory structure. Since most real applications of Josh would not keep their + };

    This code builds our fake directory structure. Since most real applications of Josh would not keep their entire hierarchy in memory, but instead make callbacks to a server to find nodes and node children, the details of this function are of little interest.

        function buildTree() {
           var fs = {
    
    From ea9a496af1d31dd0e18856e0d46013ffcd3177fa Mon Sep 17 00:00:00 2001
    From: Arne Claassen 
    Date: Wed, 6 Feb 2013 23:18:47 -0800
    Subject: [PATCH 19/26] added quakeconsole tutorial
    
    ---
     .idea/codeStyleSettings.xml |   9 +
     index.html                  | 396 ++++++++++++++++++------------------
     javascripts/quakeconsole.js | 161 +++++++++++++++
     quakeconsole.html           | 211 +++++++++++++++++++
     4 files changed, 581 insertions(+), 196 deletions(-)
     create mode 100644 .idea/codeStyleSettings.xml
     create mode 100644 javascripts/quakeconsole.js
     create mode 100644 quakeconsole.html
    
    diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
    new file mode 100644
    index 0000000..90a9579
    --- /dev/null
    +++ b/.idea/codeStyleSettings.xml
    @@ -0,0 +1,9 @@
    +
    +
    +  
    +    
    +  
    +
    +
    diff --git a/index.html b/index.html
    index 1e8822a..5425912 100644
    --- a/index.html
    +++ b/index.html
    @@ -1,53 +1,53 @@
     
     
     
    -    
    -    
    -    Josh.js by sdether
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    -    
    +  
    +  
    +  Josh.js by sdether
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
     
     
     
     
     
    @@ -55,239 +55,243 @@
     
     
    -

    Josh.js

    +

    Josh.js

    -

    Toolkit for building a bash-like shell in the browser, including full readline support

    -
    - Project maintained by sdether - Hosted on GitHub Pages — Theme by mattgraham +

    Toolkit for building a bash-like shell in the browser, including full readline support

    +
    + Project maintained by sdether + Hosted on GitHub Pages — Theme by mattgraham

    josh.js 0.2

    - Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components: + Javascript Online SHell provides a toolkit for building bash-like command line consoles for web pages. It consists of the following components:

      -
    • - readline.js - full readline support for ctrl sequences, tab, history, etc. -
    • -
    • - shell.js - visual presentation of the shell and command handling -
    • -
    • - pathhandler.js - provide cd, ls, pwd and path completion toolkit -
    • -
    • - history.js - localStorage backed command history -
    • -
    • - killring.js - killring for kill & yank handling in readline -
    • +
    • + readline.js - full readline support for ctrl sequences, tab, history, etc. +
    • +
    • + shell.js - visual presentation of the shell and command handling +
    • +
    • + pathhandler.js - provide cd, ls, pwd and path completion toolkit +
    • +
    • + history.js - localStorage backed command history +
    • +
    • + killring.js - killring for kill & yank handling in readline +

    Live Demo

    Drag bottom of shell to change size.
    -
    Type help or hit TAB for a list of commands. -
    -
    +
    Type help or hit TAB for a list of commands. +
    +

    Annotated source of demo

    Tutorials

      -
    • Hello world - put a console on a web page and add a new custom command with completion
    • +
    • + Hello world - put a console on a web page and add a new custom command with completion +
    • +
    • Quake Console - Create a quake-style console with ls, cd, pwd and bash filename tab-completion

    License

    josh.js is licensed under the Apache 2.0 License

    - Status

    + Status
      -
    • code is ready for experimental use - -
        -
      • Tested under Chrome, Firefox, Safari and IE9
      • -
      • API may not yet be stable
      • -
      -
    • -
    • needs minified versions of complete toolkit and just readline.js
    • -
    • needs code documentation and documentation site
    • -
    • would like to add AMD support
    • -
    • implement NCurses for better UI control
    • -
    • Readline has not been tested with non-ascii.
    • +
    • code is ready for experimental use + +
        +
      • Tested under Chrome, Firefox, Safari and IE9
      • +
      • API may not yet be stable
      • +
      +
    • +
    • needs minified versions of complete toolkit and just readline.js
    • +
    • needs code documentation and documentation site
    • +
    • would like to add AMD support
    • +
    • implement NCurses for better UI control
    • +
    • Readline has not been tested with non-ascii.

    - Usage

    + Usage

    Until documentation is written, refer to index.html and - the annotated version of example.js for a sample implementation of a shell with path completion.

    + the annotated version of + example.js for a sample implementation of a shell with path completion.

    - Components + Components

    josh is built from 5 components and can be used in part or in full.

    - readline.js + readline.js

    readline.js has no dependencies on any outside libraries, although it requires either - history.js and killring.js or objects implementing the same calls.

    + history.js and killring.js or objects implementing the same calls.

    It implements key trapping to bring - GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with - shell.js to create a full console.

    + GNU Readline like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with + shell.js to create a full console.

    - Line Editing + Line Editing

    In the below C-x refers to the Ctrl-x keystroke, while - M-x refers to the Meta-x keystroke which is mapped to Alt, ⌘ and - Left Windows.

    + M-x refers to the Meta-x keystroke which is mapped to Alt, ⌘ and + Left Windows.

    -
    Movement
    -
    - C-b or Left Arrow -
    -
    Move back one character
    -
    - M-b or Right Arrow -
    -
    Move back one word
    -
    C-f
    -
    Move forward one character
    -
    M-f
    -
    Move forward one word
    -
    - C-a or Home -
    -
    Move to the beginning of the line
    -
    - C-e or End -
    -
    Move to the end of the line
    - -
    -
    Edit/Kill
    -
    Backspace
    -
    Delete one character back
    -
    - C-d or Delete -
    -
    Delete character under cursor
    -
    C-k
    -
    - Kill (i.e. put in kill ring) text to the end of the line -
    -
    M-Backspace
    -
    - Kill one word back -
    -
    M-d
    -
    - Kill word under cursor -
    -
    C-y
    -
    - Yank (i.e. pull from kill ring) the most recently killed text -
    -
    M-y
    -
    Rotate to the next item in killring and yank it. Must be preceded by yank -
    - -
    -
    History
    -
    C-r
    -
    Reverse search through history
    -
    - C-p or Up Arrow -
    -
    Previous entry in history
    -
    - C-n or Down Arrow -
    -
    Next entry in history
    -
    Page Up
    -
    Top of history
    -
    Page Down
    -
    Bottom of history
    - -
    -
    Misc
    -
    C-l
    -
    refresh line (clear screen in shell)
    -
    Tab
    -
    Invoke completion handler for text under cursor
    -
    - Esc in reverse search -
    -
    Cancel search
    -
    C-c
    -
    call onCancel handler
    -
    - C-d on empty line -
    -
    call onCancel handler
    +
    Movement
    +
    + C-b or Left Arrow +
    +
    Move back one character
    +
    + M-b or Right Arrow +
    +
    Move back one word
    +
    C-f
    +
    Move forward one character
    +
    M-f
    +
    Move forward one word
    +
    + C-a or Home +
    +
    Move to the beginning of the line
    +
    + C-e or End +
    +
    Move to the end of the line
    + +
    +
    Edit/Kill
    +
    Backspace
    +
    Delete one character back
    +
    + C-d or Delete +
    +
    Delete character under cursor
    +
    C-k
    +
    + Kill (i.e. put in kill ring) text to the end of the line +
    +
    M-Backspace
    +
    + Kill one word back +
    +
    M-d
    +
    + Kill word under cursor +
    +
    C-y
    +
    + Yank (i.e. pull from kill ring) the most recently killed text +
    +
    M-y
    +
    Rotate to the next item in killring and yank it. Must be preceded by yank +
    + +
    +
    History
    +
    C-r
    +
    Reverse search through history
    +
    + C-p or Up Arrow +
    +
    Previous entry in history
    +
    + C-n or Down Arrow +
    +
    Next entry in history
    +
    Page Up
    +
    Top of history
    +
    Page Down
    +
    Bottom of history
    + +
    +
    Misc
    +
    C-l
    +
    refresh line (clear screen in shell)
    +
    Tab
    +
    Invoke completion handler for text under cursor
    +
    + Esc in reverse search +
    +
    Cancel search
    +
    C-c
    +
    call onCancel handler
    +
    + C-d on empty line +
    +
    call onCancel handler

    - shell.js + shell.js

    shell.js has external dependencies of jQuery, - Underscore and internal dependencies of readline.js and - history.js.

    + Underscore and internal dependencies of readline.js and + history.js.

    It provides a simple console UI, using a panel for the console viewport and an auto-scrolling - view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string. + view inside the panel. It uses Underscore templates for generating the view html, although any template generator can be substituted as long as it can be expressed in the form of a function that takes a JSON object of arguments and returns an html string.

    It also implements command handling so that new commands can be added by name with execution and completion handlers. Out of the box, - shell.js provides the following commands:

    + shell.js provides the following commands:

      -
    • help - list all known commands (including user added)
    • -
    • clear - clear the "screen" i.e. viewport
    • -
    • history - show the command history captured by readline.js in history.js -
    • +
    • help - list all known commands (including user added)
    • +
    • clear - clear the "screen" i.e. viewport
    • +
    • history - show the command history captured by readline.js in history.js +

    - pathhandler.js + pathhandler.js

    pathhandler.js is a mix in to easily add the cd, ls and - pwd commands as well as path completion. It has the same external dependencies of - jQuery, Underscore as - shell.js and also uses Underscore templating.

    + pwd commands as well as path completion. It has the same external dependencies of + jQuery, Underscore as + shell.js and also uses Underscore templating.

    By implementing the functions getNode and - getChildNodes, this library adds path traversal, discovery and completion just like a bash shell. + getChildNodes, this library adds path traversal, discovery and completion just like a bash shell.

    - history.js + history.js

    - history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the - shell.js history command to list all executed commands, and by - readline.js for up/down arrow and reverse search capabilities.

    + history.js implements a localStorage back command history storage that persists over page changes and reloads. It is used by the + shell.js history command to list all executed commands, and by + readline.js for up/down arrow and reverse search capabilities.

    - killring.js + killring.js

    - killing.js implements the kill and yank behavior as well as state tracking, i.e. multiple consecutive kills are combined as a single kill and killring rotation tracks the previous yank, so that the - readline.js can remove the previous yank and replace it with the rotated text.

    + killing.js implements the kill and yank behavior as well as state tracking, i.e. multiple consecutive kills are combined as a single kill and killring rotation tracks the previous yank, so that the + readline.js can remove the previous yank and replace it with the rotated text.

    diff --git a/javascripts/quakeconsole.js b/javascripts/quakeconsole.js new file mode 100644 index 0000000..c047bd8 --- /dev/null +++ b/javascripts/quakeconsole.js @@ -0,0 +1,161 @@ +/*------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ +(function(root, $, _) { + Josh.QuakeConsole = (function(root, $, _) { + var treeroot = buildTree(); + var shell = Josh.Shell(); + var pathhandler = new Josh.PathHandler(shell); + pathhandler.current = treeroot; + pathhandler.getNode = function(path, callback) { + if(!path) { + return callback(pathhandler.current); + } + var parts = _.filter(path.split('/'), function(x) { + return x; + }); + var start = ((path || '')[0] == '/') ? treeroot : pathhandler.current; + return findNode(start, parts, callback); + }; + pathhandler.getChildNodes = function(node, callback) { + callback(node.childnodes); + }; + function findNode(current, parts, callback) { + if(!parts || parts.length == 0) { + return callback(current); + } + if(parts[0] == ".") { + + } else if(parts[0] == "..") { + current = current.parent; + } else { + current = _.first(_.filter(current.childnodes, function(node) { + return node.name == parts[0]; + })); + } + if(!current) { + return callback(); + } + return findNode(current, _.rest(parts), callback); + } + $(document).ready(function() { + var $consolePanel = $('#shell-panel'); + $consolePanel.resizable({ handles: "s"}); + $(document).keypress(function(event) { + if(shell.isActive()) { + return; + } + if(event.keyCode == 126) { + event.preventDefault(); + shell.activate(); + $consolePanel.slideDown(); + $consolePanel.focus(); + } + }); + function hideAndDeactivate() { + shell.deactivate(); + $consolePanel.slideUp(); + $consolePanel.blur(); + } + shell.onEOT(hideAndDeactivate); + shell.onCancel(hideAndDeactivate); + }); + function buildTree() { + var fs = { + bin: {}, + boot: {}, + dev: {}, + etc: { + default: {}, + 'rc.d': {}, + sysconfig: {}, + x11: {} + }, + home: { + bob: { + video: { + 'firefly.m4v': {} + }, + videos: { + 'Arrested Development': { + 's1e1.m4v': {} + }, + 'Better Off Ted': { + 's1e1.m4v': {} + } + } + }, + jane: {} + }, + lib: {}, + 'lost+found': {}, + misc: {}, + mnt: { + cdrom: {}, + sysimage: {} + }, + net: {}, + opt: {}, + proc: {}, + root: {}, + sbin: {}, + usr: { + x11: {}, + bin: {}, + include: {}, + lib: {}, + local: {}, + man: {}, + sbin: {}, + share: { + doc: {} + }, + src: {} + }, + var: { + lib: {}, + lock: {}, + run: {}, + log: { + httpd: { + access_log: {}, + error_log: {} + }, + 'boot.log': {}, + cron: {}, + messages: {} + } + } + }; + + function build(parent, node) { + parent.childnodes = _.map(_.pairs(node), function(pair) { + var child = { + name: pair[0], + path: parent.path + "/" + pair[0], + parent: parent + }; + build(child, pair[1]); + return child; + }); + parent.children = _.keys(node); + return parent; + } + var tree = build({name: "", path: ""}, fs); + tree.path = '/'; + return tree; + } + })(root, $, _); +})(this, $, _); \ No newline at end of file diff --git a/quakeconsole.html b/quakeconsole.html new file mode 100644 index 0000000..a592b46 --- /dev/null +++ b/quakeconsole.html @@ -0,0 +1,211 @@ + + + + + + Josh.js by sdether + + + + + + + + + + + + + + + + + + + + + +
    +
    Type help or hit TAB for a list of commands. Press + Ctrl-C to hide the console. +
    +
    +
    + +
    + +
    +

    Quake-style console with unix-style path handling

    + +

    This tutorial shows implements a quake-style shell that drops down over your current page. Inside the shell a fake filesystem illustrates how + Pathhandler.js can be used to provide standard unix commands ls, cd, pwd and filepath tab completion. Type ~ to activate the shell we will be building in this tutorial. +

    + +

    Hooking up PathHandler.js

    + +

    PathHandler is a mix-in for Josh.Shell to provide provide the standard unix + ls, pwd and cd commands, as well + as standard bash-style path tab-completion. It expects a + Josh.Shell instance as its first argument so that it can + attach its command handlers to the shell as well as override the default handler to support completion of paths + starting with . or / without a leading command.

    +
    var shell = Josh.Shell();
    +var pathhandler = new Josh.PathHandler(shell);
    + +

    PathHandler operates on path nodes which are expected to be objects with a minimum structure of:

    + +
    {
    +    name: 'localname',
    +    path: '/full/path/to/localname'
    +}
    +

    where name is the name of the node and + path is the absolute path to the node. It does not modify + these nodes, so any additional state your implementation requires can be attached to the nodes and be relied on + as being part of the node when PathHandler provides one to your handler as an argument.

    + +

    The pathhandler expects to be initialized with the current directory in the form pf a path node. For this + example, we've build up a full tree of nodes providing a skeleton unix file system. Our nodes take the structure of:

    +
    {
    +    name: 'localname',
    +    path: '/full/path/to/localname',
    +    parent: {parent node},
    +    children: [{child nodes}]
    +}
    +

    This allows the example to simply navigate up and down a tree from any node. The tree is built by the helper builtTree() + whose implementation is not of consequence to how PathHandler works and is therefore just assumed to exist, so that we can create + the tree and assign its root as pathhandler.current.

    +
    var treeroot = buildTree();
    +pathhandler.current = treeroot;
    + +

    Implementing PathHandler's required methods

    +

    PathHandler requires two method, getNode and getChildNodes, to be provided in order to operate.

    + +

    getNode gets called with a path string. This string is completely opaque to PathHandler, + i.e. supporting constructs such as . and .. are up to the implementor. PathHandler + calls getNode anytime it has a path and needs to determine what if any node exists at that path. Thish happens + during path completion as well as cd and ls execution. It simply provides the path and + expects its callback to be called with a pathnode for that path or null. The only assumption about paths that it does + have is that the path separator is /.

    + +
    pathhandler.getNode = function(path, callback) {
    +  if(!path) {
    +    return callback(pathhandler.current);
    +  }
    +  var parts = _.filter(path.split('/'), function(x) {
    +    return x;
    +  });
    +  var start = ((path || '')[0] == '/') ? treeroot : pathhandler.current;
    +  return findNode(start, parts, callback);
    +};
    +

    For this example, no path always means the current node, otherwise we split the path into its components and walk the tree + via a helper findNode from either the root or the current node depending on whether the path started with a /. findNode is specific to this implementation, since it can work on an in memory tree. In a service bound implementation the findNode logic would likely reside at the server and the callback called in the completion closure of an ajax call.

    +
    function findNode(current, parts, callback) {
    +  if(!parts || parts.length == 0) {
    +    return callback(current);
    +  }
    +  if(parts[0] == ".") {
    +
    +  } else if(parts[0] == "..") {
    +    current = current.parent;
    +  } else {
    +    current = _.first(_.filter(current.childnodes, function(node) {
    +      return node.name == parts[0];
    +    }));
    +  }
    +  if(!current) {
    +    return callback();
    +  }
    +  return findNode(current, _.rest(parts), callback);
    +}
    + +

    The second required method is getChildNodes and is used by path completion to determine the possible + completion candidates. Path completion first determines the nearest resolvable node for the given path. It does this + by first calling getNode on the current path and failing to get a node, looking for the nearest tail + / to find a parent and use the trailing characters as the partial path to be completed against children + found via getChildNodes. For our example, we've attached the child node objects directly to the pathnode + object, so we can simply return it. Usually this would be used to call the server with the provided node's path or id so that + the appropriate children could be retrieved.

    + +
    pathhandler.getChildNodes = function(node, callback) {
    +  callback(node.childnodes);
    +};
    + +

    Setup Quake-console Behavior

    + +

    The default name for the div the shell uses as its container is shell-panel, although that can be changed via + the shell config parameter shell-panel-id. The Josh.Shell display model is based on a + panel that defines the viewport of the console screen while the content is appended to a + view that is contained inside the panel and continuously scrolled down. For the quake-style console, + we want the panel to take up the width of the browser and overlay the page's top portion. For this we add the panel + right after the body tag:

    +
    <div id="shell-panel">
    +  <div>Type <code>help</code> or hit <code>TAB</code> for a list of commands.
    +    Press <code>Ctrl-C</code> to hide the console.
    +  </div>
    +  <div id="shell-view"></div>
    +</div>
    +

    With css, we make sure this is initially invisible, is fixed in top position and has a high z-index so that it will + always be on top.

    + +

    We use jquery-ui's resizable so that the shell can be resized by dragging its bottom edge.

    +
    var $consolePanel = $('#shell-panel');
    +$consolePanel.resizable({ handles: "s"});
    + +

    Next, we wire up a the keypress handler for shell activation, since Josh.ReadLine does not listen to keys + until the shell is activated. This handler will only execute while the shell is inactive and trigger on ~, + using jquery animaton to slide it down and give it focus.

    +
    $(document).keypress(function(event) {
    +  if(shell.isActive()) {
    +    return;
    +  }
    +  if(event.keyCode == 126) {
    +    event.preventDefault();
    +    shell.activate();
    +    $consolePanel.slideDown();
    +    $consolePanel.focus();
    +  }
    +});
    + +

    Finally, we wire create a function to deactivate the shell, slide it back up and hide it and attach it to the shell's EOT (Ctrl-D on empty line) or a Cancel (Ctrl-C) signals: + we deactivate the shell and hide the console.

    +
    function hideAndDeactivate() {
    +  shell.deactivate();
    +  $consolePanel.slideUp();
    +  $consolePanel.blur();
    +}
    +shell.onEOT(hideAndDeactivate);
    +shell.onCancel(hideAndDeactivate);
    +

    Now the Shell is ready to be activated and it's faked unix file system browsed, all with minimal custom code.

    +
    +
    + + + + \ No newline at end of file From 496ff440f51eaaa1354b1224ba6c9742e452b247 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Wed, 6 Feb 2013 23:19:46 -0800 Subject: [PATCH 20/26] fixing quakeconsole tutorial link --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 5425912..e8fb838 100644 --- a/index.html +++ b/index.html @@ -102,7 +102,7 @@

    Tutorials

  • Hello world - put a console on a web page and add a new custom command with completion
  • -
  • Quake Console - Create a quake-style console with ls, cd, pwd and bash filename tab-completion
  • +
  • Quake Console - Create a quake-style console with ls, cd, pwd and bash filename tab-completion
  • License

    From a7e35abbb86a7ad3c34ac6c35f28adf214dd88f0 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 18 Mar 2013 07:31:11 -0700 Subject: [PATCH 21/26] added github console tutorial --- .gitignore | 4 +- .idea/codeStyleSettings.xml | 6 +- .idea/misc.xml | 3 - docs/githubconsole.html | 337 +++++++++++++++ githubconsole.html | 308 ++++++++++++++ helloworld.html | 308 +++++++------- index.html | 28 +- javascripts/githubconsole.js | 642 +++++++++++++++++++++++++++++ javascripts/highlight.min.js | 1 + javascripts/pathhandler.js | 26 +- javascripts/readline.js | 2 +- javascripts/shell.js | 88 ++-- pathhandler.html | 157 +++++++ quakeconsole.html | 49 ++- readline.html | 74 ++++ shell.html | 112 +++++ stylesheets/githubconsole.css | 41 ++ stylesheets/styles.css | 727 +++++++++++++++------------------ stylesheets/tomorrow-night.css | 52 +++ 19 files changed, 2328 insertions(+), 637 deletions(-) create mode 100644 docs/githubconsole.html create mode 100644 githubconsole.html create mode 100644 javascripts/githubconsole.js create mode 100644 javascripts/highlight.min.js create mode 100644 pathhandler.html create mode 100644 readline.html create mode 100644 shell.html create mode 100644 stylesheets/githubconsole.css create mode 100644 stylesheets/tomorrow-night.css diff --git a/.gitignore b/.gitignore index 28fdb01..ad861ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea/workspace.xml .idea/tasks.xml -.DS_Store \ No newline at end of file +.DS_Store +config/ +log/ \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index 90a9579..d63a15e 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -2,7 +2,11 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 5cf522e..262e5d3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,8 +1,5 @@ - - jar:file:\C:\Program Files (x86)\JetBrains\WebStorm 5.0.2\lib\webide.jar!\resources\html5-schema\html5.rnc - diff --git a/docs/githubconsole.html b/docs/githubconsole.html new file mode 100644 index 0000000..47ae469 --- /dev/null +++ b/docs/githubconsole.html @@ -0,0 +1,337 @@ + githubconsole.js

    githubconsole.js

    /*------------------------------------------------------------------------*
    + * Copyright 2013 Arne F. Claassen
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *   http://www.apache.org/licenses/LICENSE-2.0
    +
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + *-------------------------------------------------------------------------*/
    +(function(root, $, _) {
    +  Josh.GitHubConsole = (function(root, $, _) {

    Enable console debugging, when Josh.Debug is set and there is a console object on the document root.

        var _console = (Josh.Debug && root.console) ? root.console : {
    +      log: function() {
    +      }
    +    };

    Console State

    + +

    _self contains all state variables for the console's operation

        var _self = {
    +      shell: Josh.Shell({console: _console}),
    +      api: "http://josh.claassen.net/github/"
    +    };

    Josh.PathHandler is attached to Josh.Shell to provide basic file system navigation.

        _self.pathhandler = new Josh.PathHandler(_self.shell, {console: _console});

    Custom Templates

    + +

    Josh.Shell uses Underscore templates for rendering output to the shell. This console overrides some and adds a couple of new ones for its own commands.

    templates.prompt

    Override of the default prompt to provide a multi-line prompt of the current user, repo and path and branch.

        _self.shell.templates.prompt = _.template("<em>[<%= self.user.login %>/<%= self.repo.name %>]</em></br>(<%=self.branch%>) <strong><%= node.path %> $</strong>");

    templates.ls

    Override of the pathhandler ls template to create a multi-column listing.

        _self.shell.templates.ls = _.template("<ul class='widelist'><% _.each(nodes, function(node) { %><li><%- node.name %></li><% }); %></ul><div class='clear'/>");

    templates.not_found

    Override of the pathhandler not_found template, since we will throw not_found if you try to access a valid file. This is done for the simplicity of the tutorial.

        _self.shell.templates.not_found = _.template("<div><%=cmd%>: <%=path%>: No such directory</div>");

    templates.rateLimitTemplate

    Since GitHub rate limits un-authenticated use rather drastically, we render the current rate limit status in the shell so that it is clear that extended experimenting requires authentication.

        _self.shell.templates.rateLimitTemplate = _.template("<%=remaining%>/<%=limit%><% if(!authenticated) {%> <a href='http://josh.claassen.net/github/authenticate'>Authenticate with Github to increase your Rate Limit.</a><%}%>");

    templates.user

    Render basic information (including gravatar) whenever we switch users or enter user without an argument

        _self.shell.templates.user = _.template("<div class='userinfo'>" +
    +      "<img src='<%=user.avatar_url%>' style='float:right;'/>" +
    +      "<table>" +
    +      "<tr><td><strong>Id:</strong></td><td><%=user.id %></td></tr>" +
    +      "<tr><td><strong>Name:</strong></td><td><%=user.login %></td></tr>" +
    +      "<tr><td><strong>Location:</strong></td><td><%=user.location %></td></tr>" +
    +      "</table>" +
    +      "</div>"
    +    );

    templates.user_error

    Generic error in case setting the user fails.

        _self.shell.templates.user_error = _.template("Unable to set user '<%=name%>': <%=msg%>");

    templates.repos

    Just like ls, we render a wide list of repositories for repo -l.

        _self.shell.templates.repos = _.template("<ul class='widelist'><% _.each(repos, function(repo) { %><li><%- repo.name %></li><% }); %></ul><div class='clear'/>");

    template.repo

    Whenever we change repositories or repo is called without an argument, we show basic information about the repo.

        _self.shell.templates.repo = _.template("<div><div><strong>Name: </strong><%=repo.full_name%></div><div><strong>Description: </strong><%=repo.description %></div></div>");

    template.reponotfound

    Error message in case someone tries to switch to an invalid repo.

        _self.shell.templates.repo_not_found = _.template("<div>repo: <%=repo%>: No such repo for user '<%= user %>'</div>");

    templates.repo_error

    Generic error message in case setting the repo fails.

        _self.shell.templates.repo_error = _.template("Unable to switch to repository '<%=name%>': <%=msg%>");

    templates.branches

    Again, like ls, we render a wide like of branches for branch -l.

        _self.shell.templates.branches = _.template("webfont.woff<ul class='widelist'><% _.each(branches, function(branch) { %><li><%- branch.name %></li><% }); %></ul><div class='clear'/>");

    templates.branch_error

    Generic error message in case setting the current branch fails.

        _self.shell.templates.branch_error = _.template("Unable to switch to branch '<%=name%>': <%=msg%>");

    templates.branches_error

    Generic error in case fetching the list of branches fails.

        _self.shell.templates.branches_error = _.template("Unable to load branch list: <%=msg%>");

    Adding Commands to the Console

    user [ username ]

    The user command is used to display information about the current user or switch between github users.

        _self.shell.setCommandHandler("user", {

    exec handles the execution of the command.

          exec: function(cmd, args, callback) {

    Given no arguments, it renders information about the current user, using the data fetched at user initialization.

            if(!args || args.length == 0) {
    +          return callback(_self.shell.templates.user({user: _self.user}));
    +        }
    +        var username = args[0];

    Given an argument (assumed to be a username), it calls setUser to fetch the specified user and repository +information.

            return setUser(username, null,
    +          function(msg) {
    +            return callback(_self.shell.templates.user_error({name: username, msg: msg}));
    +          },
    +          function(user) {
    +            return callback(_self.shell.templates.user({user: user}));
    +          }
    +        );
    +      }

    user has no completion handler, since the userbase of github is quite large and creating a search based +completion handler is beyond the scope of this tutorial implementation.

        });

    repo [ -l | reponame ]

    The repo command is used to display information about the current repo or switch to. It

        _self.shell.setCommandHandler("repo", {

    exec handles the execution of the command.

          exec: function(cmd, args, callback) {

    Given no arguments, it renders information about the current repo.

            if(!args || args.length == 0) {
    +          return callback(_self.shell.templates.repo({repo: _self.repo}));
    +        }
    +        var name = args[0];

    Given the argument -l, it lists all repos for the current user. This information was fetched at user +initialization

            if(name === '-l') {
    +          return callback(_self.shell.templates.repos({repos: _self.repos}));
    +        }

    Otherwise, the argument is assumed to a repo name, which getRepo uses to fetch the repository's information +from the data in _self.repos, if possible.

            var repo = getRepo(name, _self.repos);

    If there is no matching repo, it renders an error.

            if(!repo) {
    +          return callback(_self.shell.templates.repo_error({name: name, msg: 'no such repo'}));
    +        }

    Given a valid repo, setRepo initializes the repo (i.e. fetching the root directory) and renders the repo +information.

            return setRepo(repo,
    +          function(msg) {
    +            return callback(_self.shell.templates.repo_error({name: name, msg: msg}));
    +          },
    +          function(repo) {
    +            if(!repo) {
    +              return callback(_self.shell.templates.repo_not_found({repo: name, user: _self.user.login}));
    +            }
    +            return callback(_self.shell.templates.repo({repo: _self.repo}));
    +          }
    +        );
    +      },

    completion uses _self.repo and Josh.Shell.bestMatch to try and match the partial information to the possible +matching repositories.

          completion: function(cmd, arg, line, callback) {
    +        callback(_self.shell.bestMatch(arg, _.map(_self.repos, function(repo) {
    +          return repo.name;
    +        })));
    +      }
    +    });

    branch [ -l | branchname ]

    The branch command is used to switch or list branches for the current repository.

        _self.shell.setCommandHandler("branch", {

    exec handles the execution of the command.

          exec: function(cmd, args, callback) {

    Given no arguments, it simply returns the current branch, which will be rendered by the shell.

            if(!args || args.length == 0) {
    +          return callback(_self.branch);
    +        }
    +        var branch = args[0];

    Given the argument -l, it lists all branches for the current repo. This information is lazily +initialized via ensureBranches.

            if(branch === '-l') {
    +          return ensureBranches(
    +            function(msg) {
    +              callback(_self.shell.templates.branches_error({msg: msg}));
    +            },
    +            function() {
    +              return callback(_self.shell.templates.branches({branches: _self.branches}));
    +            }
    +          );
    +        }

    Owherwise, the current branch is switched by fetching the root directory for the new branch, and on success, +setting _self.branch and setting the current pathandler node to the root directory fetched.

            return getDir(_self.repo.full_name, branch, "/", function(node) {
    +          if(!node) {
    +            callback(_self.shell.templates.branch_error({name: branch, msg: "unable to load root directory for branch"}));
    +          }
    +          _self.branch = branch;
    +          _self.pathhandler.current = node;
    +          _self.root = node;
    +          callback();
    +        });
    +      },

    completion handles TAB completion on a partial branch name. The list of possible branches is once again +lazily initialized via ensureBranches.

          completion: function(cmd, arg, line, callback) {
    +        return ensureBranches(
    +          function() {
    +            callback();
    +          },
    +          function() {
    +            callback(_self.shell.bestMatch(arg, _.map(_self.branches, function(branch) {
    +              return branch.name;
    +            })));
    +          }
    +        );
    +      }
    +    });

    This attaches a custom prompt render to the shell.

        _self.shell.onNewPrompt(function(callback) {
    +      callback(_self.shell.templates.prompt({self: _self, node: _self.pathhandler.current}));
    +    });

    Wiring up PathHandler

    getNode

    getNode is required by Josh.PathHandler to provide filesystem behavior. Given a path, it is expected to return +a pathnode or null;

        _self.pathhandler.getNode = function(path, callback) {
    +      _console.log("looking for node at: " + path);
    +      if(!path) {
    +        return callback(_self.pathhandler.current);
    +      }

    buildAbsolutePath is called recursively to turn path into an absolute path that can be resolved against the +github API with getDir.

          buildAbsolutePath(path, _self.pathhandler.current, function(absPath) {
    +        _console.log("path to fetch: " + absPath);
    +        return getDir(_self.repo.full_name, _self.branch, absPath, callback);
    +      });
    +    };

    getChildNodes

    getChildNodes is the second function implementation required for Josh.PathHandler. Given a pathnode, it returns +a list of child pathnodes. This is used by Tab completion to resolve a partial path, after first resolving the +nearest parent node using `getNode

        _self.pathhandler.getChildNodes = function(node, callback) {

    If the given node is a file node, no further work is required.

          if(node.isfile) {
    +        _console.log("it's a file, no children");
    +        return callback();
    +      }

    Otherwise, if the child nodes have already been initialized, which is done lazily, return them.

          if(node.children) {
    +        _console.log("got children, let's turn them into nodes");
    +        return callback(makeNodes(node.children));
    +      }

    Finally, use getDir to fetch and populate the child nodes.

          _console.log("no children, fetch them");
    +      return getDir(_self.repo.full_name, _self.branch, node.path, function(detailNode) {
    +        node.children = detailNode.children;
    +        callback(makeNodes(node.children));
    +      });
    +    };

    Supporting Functions

    get

    This function is responsible for all API requests, given a partial API path, resource, and an query argument object, +args.

        function get(resource, args, callback) {
    +      var url = _self.api + resource;
    +      if(args) {
    +        url += "?" + _.map(args,function(v, k) {
    +          return k + "=" + v;
    +        }).join("&");
    +      }
    +      _console.log("fetching: " + url);
    +      var request = {
    +        url: url,
    +        dataType: 'json',
    +        xhrFields: {
    +          withCredentials: true
    +        }
    +      };
    +      $.ajax(request).done(function(response,status,xhr) {

    Every response from the API includes rate limiting headers, as well as an indicator injected by the API proxy +whether the request was done with authentication. Both are used to display request rate information and a +link to authenticate, if required.

            var ratelimit = {
    +          remaining: parseInt(xhr.getResponseHeader("X-RateLimit-Remaining")),
    +          limit: parseInt(xhr.getResponseHeader("X-RateLimit-Limit")),
    +          authenticated: xhr.getResponseHeader('Authenticated') === 'true'
    +        };
    +        $('#ratelimit').html(_self.shell.templates.rateLimitTemplate(ratelimit));
    +        if(ratelimit.remaining == 0) {
    +          alert("Whoops, you've hit the github rate limit. You'll need to authenticate to continue");
    +          _self.shell.deactivate();
    +          return null;
    +        }

    For simplicity, this tutorial trivially deals with request failures by just returning null from this function +via the callback.

            if(status !== 'success') {
    +          return callback();
    +        }
    +        return callback(response);
    +      })
    +    }

    ensureBranches

    This function lazily fetches the branches for the current repo from the API.

        function ensureBranches(err, callback) {
    +      get("repos/" + _self.repo.full_name + "/branches", null, function(branches) {
    +        if(!branches) {
    +          return err("api request failed to return branch list");
    +        }
    +        _self.branches = branches;
    +        return callback();
    +      });
    +    }

    setUser

    This function fetches the specified user and initializes a repository to the provided value (which may be null). +one fetched by initialzeRepos.

        function setUser(user_name, repo_name, err, callback) {
    +      if(_self.user && _self.user.login === user_name) {
    +        return callback(_self.user);
    +      }
    +      return get("users/" + user_name, null, function(user) {
    +        if(!user) {
    +          return err("no such user");
    +        }
    +        return initializeRepos(user, repo_name, err, function(repo) {
    +          _self.user = user;
    +          return callback(_self.user);
    +        });
    +      });
    +    }

    initalizeRepos

    This function first fetches all repos for the given user from the API and then sets the current repo to the provided +value (which may be null).

        function initializeRepos(user, repo_name, err, callback) {
    +      return getRepos(user.login, function(repos) {
    +        var repo = getRepo(repo_name, repos);
    +        if(!repo) {
    +          return err("user has no repositories");
    +        }
    +        return setRepo(repo, err, function(repo) {
    +          _self.repos = repos;
    +          return callback(repo);
    +        });
    +      });
    +    }

    getDir

    This function function fetches the directory listing for a path on a given repo and branch.

        function getDir(repo_full_name, branch, path, callback) {

    Although paths in the internal representation may have a trailing /, it has to be removed before using it +as the argument for an API request.

          if(path && path.length > 1 && path[path.length - 1] === '/') {
    +        path = path.substr(0, path.length - 1);
    +      }
    +      get("repos/" + repo_full_name + "/contents" + path, {ref: branch}, function(data) {

    The API call may return either an array, indicating that the path was a directory, or an object. Since only +are stored as pathnodes, retrieving anything but an array returns null via the callback.

            if(Object.prototype.toString.call(data) !== '[object Array]') {
    +          _console.log("path '" + path + "' was a file");
    +          return callback();
    +        }

    Given a directory listing, i.e. array, the current directory node is created and the API return value captured +as children so that they can later be transformed into child pathnodes, if required.

            var node = {
    +          name: _.last(_.filter(path.split("/"), function(x) {
    +            return x;
    +          })) || "",
    +          path: path,
    +          children: data
    +        };
    +        _console.log("got node at: " + node.path);
    +        return callback(node);
    +      });
    +    }

    getRepos

    This function fetches all repositories for a given user.

        function getRepos(userLogin, callback) {
    +      return get("users/" + userLogin + "/repos", null, function(data) {
    +        callback(data);
    +      });
    +    }

    getRepo

    This function tries to match a repository from the given list of known repositories. Should repo_name be null, +the first repository in repos is returned.

        function getRepo(repo_name, repos) {
    +      if(!repos || repos.length == 0) {
    +        return null;
    +      }
    +      var repo;
    +      if(repo_name) {
    +        repo = _.find(repos, function(repo) {
    +          return repo.name === repo_name;
    +        });
    +        if(!repo) {
    +          return callback();
    +        }
    +      } else {
    +        repo = repos[0];
    +      }
    +      return repo;
    +    }

    setRepo

    This function fetches the root directory for the specified repository and initializes the current repository +state.

        function setRepo(repo, err, callback) {
    +      return getDir(repo.full_name, repo.default_branch, "/", function(node) {
    +        if(!node) {
    +          return err("could not initialize root directory of repository '" + repo.full_name + "'");
    +        }
    +        _console.log("setting repo to '" + repo.name + "'");
    +        _self.repo = repo;
    +        _self.branch = repo.default_branch;
    +        _self.pathhandler.current = node;
    +        _self.root = node;
    +        return callback(repo);
    +      });
    +    }

    buildAbsolutePath

    This function resolves a path to an absolute path given a current node.

        function buildAbsolutePath(path, current, callback) {
    +      _console.log("resolving path: "+path);
    +      var parts = path.split("/");

    If the first part of the path is .., current is used to determine the parent path and construct an absolute +path from the combination of the parent path and the remainder of path. Since this compoint path may still +contain . or .., path operators that the github API does not understand, the resulting value is fed back +into buildAbsolutePath.

          if(parts[0] === '..' ) {
    +        var parentParts = _.filter(current.path.split("/"), function(x) {
    +          return x;
    +        });
    +        path = "/" + parentParts.slice(0, parentParts.length - 1).join('/') + "/" + parts.slice(1).join("/");
    +        return buildAbsolutePath(path, _self.root, callback);
    +      }

    If the first parht of the path is either a . or not empty (i.e. the path had started with a /, the path must +be relative and an absolute path can be constructed by combining the path and current. Once again, the value +isfed back into buildAbsolutePath for final resolution.

          if(parts[0] === '.' || parts[0] !== '') {
    +        path = current.path+"/"+path;
    +        return buildAbsolutePath(path, _self.root, callback);
    +      }

    At this point the path looks absolute, but all . and .. mentions need to removed and resolved before a truly +absolute path can be returned.

          var resolved = [];
    +      _.each(parts, function(x) {
    +        if(x === '.') {
    +          return;
    +        }
    +        if(x === '..') {
    +          resolved.pop();
    +        } else {
    +          resolved.push(x);
    +        }
    +      });
    +      return callback(resolved.join('/'));
    +    }

    makeNodes

    This method builds child pathnodes from the directory information returned by getDir.

        function makeNodes(children) {
    +      return _.map(children, function(node) {
    +        return {
    +          name: node.name,
    +          path: "/" + node.path,
    +          isFile: node.type === 'file'
    +        };
    +      });
    +    }

    UI setup and initialization

    initializationError

    This function is a lazy way with giving up if some request failed during intialization, forcing the user +to reload to retry.

        function initializationError(context, msg) {
    +      _console.log("[" + context + "] failed to initialize: " + msg);
    +      alert("unable to initialize shell. Encountered a problem talking to github api. Try reloading the page");
    +    }

    intializeUI

    After a current user and repo have been set, this function initializes the UI state to allow the shell to be +shown and hidden.

        function initializeUI() {
    +      _console.log("activating");
    +      var $consolePanel = $('#shell-container');
    +      $consolePanel.resizable({ handles: "s"});
    +      $(document).keypress(function(event) {
    +        if(_self.shell.isActive()) {
    +          return;
    +        }
    +        if(event.keyCode == 126) {
    +          event.preventDefault();
    +          activateAndShow();
    +        }
    +      });
    +      function activateAndShow() {
    +        _self.shell.activate();
    +        $consolePanel.slideDown();
    +        $consolePanel.focus();
    +      }
    +
    +      function hideAndDeactivate() {
    +        _self.shell.deactivate();
    +        $consolePanel.slideUp();
    +        $consolePanel.blur();
    +      }
    +
    +      _self.shell.onEOT(hideAndDeactivate);
    +      _self.shell.onCancel(hideAndDeactivate);
    +    }

    On document ready, the default user and repo are loaded from the API before the UI can complete initialization.

        $(document).ready(function() {
    +      setUser("sdether", "josh.js",
    +        function(msg) {
    +          initializationError("default", msg);
    +        },
    +        initializeUI
    +      );
    +    });
    +  })(root, $, _);
    +})(this, $, _);
    +
    +
    \ No newline at end of file diff --git a/githubconsole.html b/githubconsole.html new file mode 100644 index 0000000..fe81243 --- /dev/null +++ b/githubconsole.html @@ -0,0 +1,308 @@ + + + + + + Josh.js by sdether + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    Github rate limit:
    +
    +
    Type help or hit TAB for a list of commands. Press + Ctrl-C to hide the console. +
    +
    + +
    +
    + +
    + +
    +

    Github Console

    + +

    This tutorial expands on the + Quake Console tutorial by using the GitHub REST API instead of a faked filesystem. The purpose of the tutorial is to show how to wire up Josh.PathHandler and custom commands to a remote API. +

    + +

    Try out the Console

    + +

    Type ~ to activate the shell we will be discussed belowl.

    + +

    You can explore the current repository's file system via the standard ls and + cd commands as well as take advantage of path TAB completion. Additional commands are: +

    +
      +
    • user - show the current user's info
    • +
    • user username - change the user to explore
    • +
    • repo -l - list the current user's repositories
    • +
    • repo repository_name - change the repository to explore (supports + TAB completion) +
    • +
    • branch -l - list the current repository's branches
    • +
    • branch branch_name - change the branch to explore (supports TAB completion) +
    • +
    + +

    You will be limited to 60 requests/hour by the API (where each console command may use multiple requests). If you + authenticate via GitHub, you will have a more flexible 5000 requests/hour to play with. +

    + +

    Annotated Source

    + +

    The approach of this tutorial is to walk through the pieces required to wire up + Josh.Shell to a remote REST API via asynchronous calls to produce an interactive command line interface by explaining the flow. While some code will be shown inline, the primary code reference is the + annotated source code with links to specific, mentioned functions throughout the tutorial. +

    + +

    Application State

    + +

    The console is designed to always be in the context of a repository, so that there is no state in which commands like + ls are not available. It initializes with the + sdether/josh.js repository and after this the user can switch users, repositories and branches, while always staying in the context of some repository. That means that at any point in time, we will have a current user object, a list of all that user's repositories, and a current directory on the current branch as state. Changing users picks a default repository and branch to keep that state populated. Branches and current directory information are loaded on demand. +

    +

    The available state looks like this:

    +
    {
    +  api: "http://josh.claassen.net/github/", // the proxy we use for the GitHub API
    +  shell: $instance_of_Josh.Shell,
    +  pathhandler: $instance_of_Josh.PathHandler,
    +  user: $current_user_object,
    +  repo: $current_repository,
    +  repos: $list_of_user_repos,
    +  branch: $current_branch,
    +  branches: $lazy_initialized_list_of_branches_for_current_repo
    +}
    + +

    The GitHub API

    + +

    GitHub provides a + REST API, giving access to most of its data and functionality. We're just going to worry about read capability around repositories. Each repo is basically a file system which plays nicely into + Josh.PathHandler's area of applicability.

    + +

    The user object comes from:

    +
    GET /users/:user
    +

    We never fetch an individual repository, instead opting to fetch all at user initialization via:

    +
    GET /users/:user/repos
    +

    We do the same for branches, fetching all, lazily, once we need to auto-complete or list them:

    +
    GET /repos/:owner/:repo/branches
    +

    Finally, we fetch the current directory via

    +
    GET /repos/:owner/:repo/contents/:path
    +

    This is done for the root during repo initialization, and for path completion, cd, ls, etc. on demand.

    + +

    The API returns + json, which is perfect for us as well, but it is rather drastically rate limited without authentication. I.e. without authentication you will be limited to 60 requests per hour, while with authentication the limit is 5000 per hour. For this reason, we proxy all github calls through a simple node.js application that can handle oauth to optionally authenticate the use of this console. This application is outside the scope of the tutorial, but the code can be found on the josh.js + github-authentication-backend branch. +

    + +

    Initializing the Console

    + +

    In order for us to show the console, we have to have initialized a user, a repository and retrieved it's root directory. This is done after + document.ready

    +
    $(document).ready(function() {
    +      setUser("sdether", "josh.js",
    +        function(msg) {
    +          initializationError("default", msg);
    +        },
    +        initializeUI
    +      );
    +    });
    + +

    We call + setUser(user_name, repo_name, err, callback) for + sdether and + josh.js, before setting the authenticated user as the current user and initializing the UI of the shell. +

    +
    function setUser(user_name, repo_name, err, callback) {
    +  if(_self.user && _self.user.login === user_name) {
    +    return callback(_self.user);
    +  }
    +  return get("users/" + user_name, null, function(user) {
    +    if(!user) {
    +      return err("no such user");
    +    }
    +    return initializeRepos(user, repo_name, err, function(repo) {
    +      _self.user = user;
    +      return callback(_self.user);
    +    });
    +  });
    +}
    +

    This function follows the pattern of providing both an + error and + success callback, since once the shell is initialized we need to make sure that any action we take on its behalf does result in its callback being called with some value, lest the shell stop functioning. Unlike previous tutorials, we're now doing network requests and those will fail sooner or later. For this reason we need to make sure we always have a quick + err callback to stop the current operation and call the callback provided by + Josh.Shell on command execution. We also need to make sure that we do not mutate the application state until we are done with all operations that can fail, so that the worst case is us reporting to the shell that the operation failed while our current, known good state is preserved. +

    + +

    All API access goes through a helper function + get(resource, args, callback), which is responsible for constructing the + json call and inspecting the response. For simplicity, all error conditions just result in + callback being called with null instead of a + json payload.

    +
    function get(resource, args, callback) {
    +  var url = _self.api + resource;
    +  if(args) {
    +    url += "?" + _.map(args,function(v, k) { return k + "=" + v; }).join("&");
    +  }
    +  var request = {
    +    url: url,
    +    dataType: 'json',
    +    xhrFields: {
    +      withCredentials: true
    +    }
    +  };
    +  $.ajax(request).done(function(response, status, xhr) {
    +
    +    // Every response from the API includes rate limiting headers, as well as an
    +    // indicator injected by the API proxy whether the request was done with
    +    // authentication. Both are used to display request rate information and a
    +    // link to authenticate, if required.
    +    var ratelimit = {
    +      remaining: parseInt(xhr.getResponseHeader("X-RateLimit-Remaining")),
    +      limit: parseInt(xhr.getResponseHeader("X-RateLimit-Limit")),
    +      authenticated: xhr.getResponseHeader('Authenticated') === 'true'
    +    };
    +    $('#ratelimit').html(_self.shell.templates.rateLimitTemplate(ratelimit));
    +    if(ratelimit.remaining == 0) {
    +      alert("Whoops, you've hit the github rate limit. You'll need to authenticate to continue");
    +      _self.shell.deactivate();
    +      return null;
    +    }
    +
    +    // For simplicity, this tutorial trivially deals with request failures by
    +    //just returning null from this function via the callback.
    +    if(status !== 'success') {
    +      return callback();
    +    }
    +    return callback(response);
    +  })
    +}
    +

    Most of this function is actually devoted to CORS and rate limiting handling, which is unique to us calling the GitHub API via a proxy located on another server. When dealing with your own API, calls will likely just be $.getJSON() +

    +

    + Also for simplicity, any initialization failures, just bail out via + initializationError(). Once we have a user, we can call + initializeRepos(user, repo_name, err, callback). +

    + +

    Adding Commands

    + +

    Commands are added via Josh.Shell.SetCommandHandler(cmd,handler) where + handler is an object with two properties, exec and + completion.

    +
    Josh.Shell.SetCommandHandler($cmd, {
    +  exec: function(cmd, args, callback) {
    +    ...
    +  },
    +  completion: function(cmd, arg, line, callback) {
    +    ...
    +  });
    +  }
    +});
    +

    Unlike the callback pattern we used for + setUser, Josh functions do not have a separate error handler. Since Josh interacts with the UI, it has no concept of failure -- it has to execute the callback to continue executing. It is up to the caller to deal with errors and transform them into the appropriate UI response. But it still gives us the flexibility to undertake asynchronous actions, such as calling a remote API and complete the function execution upon asynchronous callback from the remote call. +

    + +

    user [username]

    + +

    The user command does not have + TAB completion, since doing efficient tab completion against the full set of GitHub users is beyond this tutorial. Instead it expects a valid username for + setUser(user_name, repo_name, err, callback) and renders the user template with the new current user. +

    + +

    If called without a username, we simply render the user template with the current user.

    + +

    repo [-l | reponame]

    + +

    The + repo command can show information about the current repository, change the current repository or list all repositories belonging to the user. It also provides + TAB completion of partial repository names against the repositories of the current user.

    + +

    Given no argument, we simply render the repository template with the current repository.

    + +

    If the argument is + -l, we render the repository list template with the repositories we fetched on user initialization.

    + +

    Finally, the argument is used to try and look up the repository from the known repositories list. If that succeeds, we call + setRepo(repo, err, callback), which fetches the root directory to initialize the current node of + Josh.PathHandler before changing the current repository to the one specified. Upon switching we again render the repository template with the now current repository. +

    + +

    The completion handler for the command simply calls + Josh.Shell.bestMatch with the partial argument and a list of all repository names. + bestMatch takes care of creating the completion object with the appropriate argument completion and list of possible choices. +

    + +

    branch [-l | branchname]

    + +

    The branch command either displays the current branch name, changes the current branch or list all branches for the current repository. It also provides + TAB completion of partial branch names against the lazy initialized list of all branches for the current repository.

    + +

    Given no argument, the command simply prints the current branch name. The + -l argument renders a list of all known branches for the current repository, while an actual branchname as argument will cause the console to change its current branch. +

    + +

    Showing the list of branches uses + ensureBranches(err, callback) to lazily initialize the list of branches from the API. +

    + +

    The completion handler for the command calls Josh.Shell.bestMatch -- just like repo completion -- with the partial argument and the list of all branches. +

    + +

    Wiring up Josh.PathHandler

    +

    PathHandler provides unix filepath handling. This works by abstracting the filesystem into two operations, getNode(path, callback) and getChildNodes(node, callback). The former returns a pathnode given a path string while the latter returns pathnodes for all children of a given node. With these two all tree operations including TAB completion can be accomplished by PathHandler.

    +

    A pathnode is an opaque object in which we can track any node state we want but has to have two properties:

    +
    {
    +  name: 'localname',
    +  path: '/full/path/to/localname'
    +}
    +

    getNode is responsible for fetching the appropriate directory from the API either by relative or absolute path. A path is considered relative if it lacks a leading /. PathHandler tracks the current directory/file node in PathHandler.current which is used to convert a relative path to an absolutish path. Since we also support the standard file system . and .. symbols and the github API does not, we then need to take the absolutish path and resolve these symbols before passing the resulting absolute path to getDir(repo_full_name, branch, path, callback).

    +

    It is the job of getDir to fetch a directory node via GET /repos/:owner/:repo/contents/:path. This API call returns either an array of file objects for a directory or a file object in case the path points directly at a file. We only care about directories for completion and cd, ls, etc. so we ignore file results and build a pathnode for the directory like this:

    +
    var node = {
    +  name: _.last(_.filter(path.split("/"), function(x) { return x; })) || "",
    +  path: path,
    +  children: data
    +};
    +

    where name is set to the last segment in the path and children stores the actual API results (which are lazily converted to childNodes for completion by function makeNodes(children)

    + +

    Easy remote integration

    + +

    The use of the github console is fairly limited, but it illustrates that wiring commands and file system behavior to a remote API is fairly simple. While we chose to create a custom vocabulary, we could have just as easily proxied calls to mimic git itself. Either way, Josh.js is an easy way to add a Command Line interface for your existing API or for an API custom tailored to your CLI, allowing you to create powerful admin tools without providing access to the servers themselves.

    +
    + +
    + + + + \ No newline at end of file diff --git a/helloworld.html b/helloworld.html index da4d845..6ed5197 100644 --- a/helloworld.html +++ b/helloworld.html @@ -1,134 +1,140 @@ - - - Josh.js by sdether - - - - - - - - - - - - - - - - - - - + + + Josh.js by sdether + + + + + + + + + + + + + + + + + + + + + +
    -
    -

    Hello World Shell

    - -

    This tutorial shows how easy it is to create the below shell window with a custom prompt and a new command - hello.

    - -

    - -

    -
    Type help or hit TAB for a list of commands.
    -
    -
    -

    -

    Creating the Shell

    - -

    The - Josh.Shell uses local storage to store a history of the commands that you have typed. By default this is keyed with - josh.history. That history is available to all instances of the shell on your site. For this tutorial, we want to make sure we have our own copy, so we don't get commands from other tutorials and examples, so we need to create a history object with its own key: -

    -
    var history = new Josh.History({ key: 'helloworld.history'});
    -

    Now we can create a Shell instance with that history:

    -
    var shell = Josh.Shell({history: history});
    -

    Now the shell exists but has not yet been activated.

    - -

    Note on how the shell attaches to its UI elements: By default - Josh.Shell expects to find a div#shell-panel that contains a - div#shell-view. The former is the physical container providing the dimensions of the shell, while the latter is a div the shell will continue to append to and scroll to mimic a screen. If you want to use other div IDs (because you have multiple shells on one page), you can provide - shell-panel-id and shell-view-id in the constructor.

    - -

    Rendering the prompt

    - -

    The default prompt for Josh is - jsh$. Let's create a prompt instead that keeps track of how many times it has been shown: -

    -
    var promptCounter = 0;
    +  
    +

    Hello World Shell

    + +

    This tutorial shows how easy it is to create the below shell window with a custom prompt and a new command + hello.

    + +

    + +

    +
    Type help or hit TAB for a list of commands.
    +
    +
    +

    Creating the Shell

    + +

    The + Josh.Shell uses local storage to store a history of the commands that you have typed. By default this is keyed with + josh.history. That history is available to all instances of the shell on your site. For this tutorial, we want to make sure we have our own copy, so we don't get commands from other tutorials and examples, so we need to create a history object with its own key: +

    +
    var history = new Josh.History({ key: 'helloworld.history'});
    +

    Now we can create a Shell instance with that history:

    +
    var shell = Josh.Shell({history: history});
    +

    Now the shell exists but has not yet been activated.

    + +

    Note on how the shell attaches to its UI elements: By default + Josh.Shell expects to find a div#shell-panel that contains a + div#shell-view. The former is the physical container providing the dimensions of the shell, while the latter is a div the shell will continue to append to and scroll to mimic a screen. If you want to use other div IDs (because you have multiple shells on one page), you can provide + shell-panel-id and shell-view-id in the constructor.

    + +

    Rendering the prompt

    + +

    The default prompt for Josh is + jsh$. Let's create a prompt instead that keeps track of how many times it has been shown: +

    +
    var promptCounter = 0;
     shell.onNewPrompt(function(callback) {
         promptCounter++;
         callback("[" + promptCounter + "] $ ");
    -});
    -

    - onNewPrompt is called every time Josh needs to re-render the prompt. This happens usually a command is executed, but can also happen on tab completion, when a list of possible completions is shown. - onNewPrompt expects a function that accepts a callback as its only argument. Josh will not continue until the callback has been called with an html string to display. This allows the prompt to rendered as part of an asynchronous action. For our example, we just increment the promptCounter and send back a simple string with the counter. -

    - -

    Adding a new command

    - -

    Josh implements just three commands out of the box:

    -
      -
    • help - show a list of known commands
    • -
    • history - show the commands previously entered
    • -
    • clear - clear the console (i.e. remove all children from div#shell-view
    • -
    -

    Let's add a new command called hello with tab completion:

    -
    shell.setCommandHandler("hello", {
    +});
    +

    + onNewPrompt is called every time Josh needs to re-render the prompt. This happens usually a command is executed, but can also happen on tab completion, when a list of possible completions is shown. + onNewPrompt expects a function that accepts a callback as its only argument. Josh will not continue until the callback has been called with an html string to display. This allows the prompt to rendered as part of an asynchronous action. For our example, we just increment the promptCounter and send back a simple string with the counter. +

    + +

    Adding a new command

    + +

    Josh implements just three commands out of the box:

    +
      +
    • help - show a list of known commands
    • +
    • history - show the commands previously entered
    • +
    • clear - clear the console (i.e. remove all children from div#shell-view
    • +
    +

    Let's add a new command called hello with tab completion:

    +
    shell.setCommandHandler("hello", {
         exec: function(cmd, args, callback) {
             var arg = args[0] || '';
             var response = "who is this " + arg + " you are talking to?";
    @@ -144,40 +150,40 @@ 

    Adding a new command

    completion: function(cmd, arg, line, callback) { callback(shell.bestMatch(arg, ['world', 'josh'])) } -});
    -

    To add a command, simply call shell.setCommandHandler and provide it at least an - exec handler, and optionally a completion handler.

    - -

    - exec expects a function that takes the name of the called command, an array of whitespace separated arguments to the command and a callback that MUST be called with an html string to output to the console. For our toy command we implement a command named - hello which understands arguments josh and - world and has alternate outputs for no arguments and unknown arguments.

    - -

    - completion expects a function that takes the current command, the current argument being completed, the complete line (since the cursor may not be at the tail) and a callback that MUST be called either with a completion data structure. The format of this data structure is: -

    -
    {
    +});
    +

    To add a command, simply call shell.setCommandHandler and provide it at least an + exec handler, and optionally a completion handler.

    + +

    + exec expects a function that takes the name of the called command, an array of whitespace separated arguments to the command and a callback that MUST be called with an html string to output to the console. For our toy command we implement a command named + hello which understands arguments josh and + world and has alternate outputs for no arguments and unknown arguments.

    + +

    + completion expects a function that takes the current command, the current argument being completed, the complete line (since the cursor may not be at the tail) and a callback that MUST be called either with a completion data structure. The format of this data structure is: +

    +
    {
       completion: {string to append to current argument},
       suggestions: [{array of possible completions},...]
    -}
    -

    Here are some expected completions:

    -
      -
    • hello <TAB> => {completion:null,suggestions:['world', 'josh']}
    • -
    • hello wo<TAB> => {completion:'rld',suggestions:['world']}
    • -
    • hello x<TAB> => {completion:'',suggestions:[]}
    • -
    -

    To simplify this process of finding the partial strings and possible completions, Shell offers a method - bestMatch which expects as input the partial to match (our arg to the completion handler) and a list of all possible completions and it will narrow down what to append to the partial and what suggestions to show. -

    - -

    Turning it on

    - -

    Now that we've added our custom behavior to - Josh.Shell, all we have to do is activate the shell to render the prompt and start capturing all keystrokes via readline (i.e. if you want the shell to only capture keys while the shell has focus, it is up to you to write focus and blur code to activate and deactivate the shell.) -

    -
    shell.activate();
    -

    And that's all there is to getting a custom Bash-like shell in your web page.

    -
    +}
    +

    Here are some expected completions:

    +
      +
    • hello <TAB> => {completion:null,suggestions:['world', 'josh']}
    • +
    • hello wo<TAB> => {completion:'rld',suggestions:['world']}
    • +
    • hello x<TAB> => {completion:'',suggestions:[]}
    • +
    +

    To simplify this process of finding the partial strings and possible completions, Shell offers a method + bestMatch which expects as input the partial to match (our arg to the completion handler) and a list of all possible completions and it will narrow down what to append to the partial and what suggestions to show. +

    + +

    Turning it on

    + +

    Now that we've added our custom behavior to + Josh.Shell, all we have to do is activate the shell to render the prompt and start capturing all keystrokes via readline (i.e. if you want the shell to only capture keys while the shell has focus, it is up to you to write focus and blur code to activate and deactivate the shell.) +

    +
    shell.activate();
    +

    And that's all there is to getting a custom Bash-like shell in your web page.

    +
    diff --git a/index.html b/index.html index e8fb838..bd17aa2 100644 --- a/index.html +++ b/index.html @@ -38,6 +38,10 @@ overflow-x: hidden; overflow-y: scroll; border: 1px dashed #E6EBE0; + } + + #shell-cli .prompt { + font-weight: bold; } @@ -102,7 +106,12 @@

    Tutorials

  • Hello world - put a console on a web page and add a new custom command with completion
  • -
  • Quake Console - Create a quake-style console with ls, cd, pwd and bash filename tab-completion
  • +
  • Quake Console - Create a quake-style console with ls, + cd, pwd and bash filename tab-completion +
  • +
  • + GitHub Console - Extend the Quake Console to talk to GitHub's REST API to navigate repositories, their branches and file system +
  • License

    @@ -139,7 +148,7 @@

    josh is built from 5 components and can be used in part or in full.

    - readline.js + readline.js

    readline.js has no dependencies on any outside libraries, although it requires either @@ -242,8 +251,9 @@

    call onCancel handler
    +

    More readline.js docs

    - shell.js + shell.js

    shell.js has external dependencies of jQuery, @@ -263,19 +273,21 @@

  • history - show the command history captured by readline.js in history.js
  • +

    More shell.js docs

    - pathhandler.js + pathhandler.js

    pathhandler.js is a mix in to easily add the cd, ls and - pwd commands as well as path completion. It has the same external dependencies of - jQuery, Underscore as - shell.js and also uses Underscore templating.

    + pwd commands as well as path completion. It has + Underscore as its dependency for templating, however since all + templates it uses are exposed, they could easily be replaced with a different function that accepts an argument object returns html. +

    By implementing the functions getNode and getChildNodes, this library adds path traversal, discovery and completion just like a bash shell.

    - +

    More pathhandler.js docs

    history.js

    diff --git a/javascripts/githubconsole.js b/javascripts/githubconsole.js new file mode 100644 index 0000000..45ffae9 --- /dev/null +++ b/javascripts/githubconsole.js @@ -0,0 +1,642 @@ +/*------------------------------------------------------------------------* + * Copyright 2013 Arne F. Claassen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *-------------------------------------------------------------------------*/ +(function(root, $, _) { + Josh.GitHubConsole = (function(root, $, _) { + + // Enable console debugging, when Josh.Debug is set and there is a console object on the document root. + var _console = (Josh.Debug && root.console) ? root.console : { + log: function() { + } + }; + + // Console State + // ============= + // + // `_self` contains all state variables for the console's operation + var _self = { + shell: Josh.Shell({console: _console}), + api: "http://josh.claassen.net/github/" + }; + + // `Josh.PathHandler` is attached to `Josh.Shell` to provide basic file system navigation. + _self.pathhandler = new Josh.PathHandler(_self.shell, {console: _console}); + + // Custom Templates + // ================ + // `Josh.Shell` uses *Underscore* templates for rendering output to the shell. This console overrides some and adds a couple of new ones for its own commands. + + // **templates.prompt** + + // Override of the default prompt to provide a multi-line prompt of the current user, repo and path and branch. + _self.shell.templates.prompt = _.template("[<%= self.user.login %>/<%= self.repo.name %>]
    (<%=self.branch%>) <%= node.path %> $"); + + // **templates.ls** + + // Override of the pathhandler ls template to create a multi-column listing. + _self.shell.templates.ls = _.template("
      <% _.each(nodes, function(node) { %>
    • <%- node.name %>
    • <% }); %>
    "); + + // **templates.not_found** + + // Override of the pathhandler *not_found* template, since we will throw *not_found* if you try to access a valid file. This is done for the simplicity of the tutorial. + _self.shell.templates.not_found = _.template("
    <%=cmd%>: <%=path%>: No such directory
    "); + + //**templates.rateLimitTemplate** + + // Since GitHub rate limits un-authenticated use rather drastically, we render the current rate limit status in the shell so that it is clear that extended experimenting requires authentication. + _self.shell.templates.rateLimitTemplate = _.template("<%=remaining%>/<%=limit%><% if(!authenticated) {%> Authenticate with Github to increase your Rate Limit.<%}%>"); + + //**templates.user** + + // Render basic information (including gravatar) whenever we switch users or enter `user` without an argument + _self.shell.templates.user = _.template("
    " + + "" + + "" + + "" + + "" + + "" + + "
    Id:<%=user.id %>
    Name:<%=user.login %>
    Location:<%=user.location %>
    " + + "
    " + ); + + // **templates.user_error** + + // Generic error in case setting the user fails. + _self.shell.templates.user_error = _.template("Unable to set user '<%=name%>': <%=msg%>"); + + // **templates.repos** + + // Just like `ls`, we render a wide list of repositories for `repo -l`. + _self.shell.templates.repos = _.template("
      <% _.each(repos, function(repo) { %>
    • <%- repo.name %>
    • <% }); %>
    "); + + // **template.repo** + + // Whenever we change repositories or `repo` is called without an argument, we show basic information about the repo. + _self.shell.templates.repo = _.template("
    Name: <%=repo.full_name%>
    Description: <%=repo.description %>
    "); + + // **template.repo_not_found** + + // Error message in case someone tries to switch to an invalid repo. + _self.shell.templates.repo_not_found = _.template("
    repo: <%=repo%>: No such repo for user '<%= user %>'
    "); + + // **templates.repo_error** + + // Generic error message in case setting the repo fails. + _self.shell.templates.repo_error = _.template("Unable to switch to repository '<%=name%>': <%=msg%>"); + + // **templates.branches** + + // Again, like `ls`, we render a wide like of branches for `branch -l`. + _self.shell.templates.branches = _.template("webfont.woff
      <% _.each(branches, function(branch) { %>
    • <%- branch.name %>
    • <% }); %>
    "); + + // **templates.branch_error** + + // Generic error message in case setting the current branch fails. + _self.shell.templates.branch_error = _.template("Unable to switch to branch '<%=name%>': <%=msg%>"); + + // **templates.branches_error** + + // Generic error in case fetching the list of branches fails. + _self.shell.templates.branches_error = _.template("Unable to load branch list: <%=msg%>"); + + // Adding Commands to the Console + // ============================== + + //
    + + // user [ username ] + // ----------------- + + // The `user` command is used to display information about the current user or switch between github users. + _self.shell.setCommandHandler("user", { + + // `exec` handles the execution of the command. + exec: function(cmd, args, callback) { + + // Given no arguments, it renders information about the current user, using the data fetched at user initialization. + if(!args || args.length == 0) { + return callback(_self.shell.templates.user({user: _self.user})); + } + var username = args[0]; + + // Given an argument (assumed to be a username), it calls `setUser` to fetch the specified user and repository + // information. + return setUser(username, null, + function(msg) { + return callback(_self.shell.templates.user_error({name: username, msg: msg})); + }, + function(user) { + return callback(_self.shell.templates.user({user: user})); + } + ); + } + + // `user` has no completion handler, since the userbase of github is quite large and creating a search based + // completion handler is beyond the scope of this tutorial implementation. + }); + + //
    + + // repo [ -l | reponame ] + // ---------------------- + + // The `repo` command is used to display information about the current repo or switch to. It + _self.shell.setCommandHandler("repo", { + + // `exec` handles the execution of the command. + exec: function(cmd, args, callback) { + + // Given no arguments, it renders information about the current repo. + if(!args || args.length == 0) { + return callback(_self.shell.templates.repo({repo: _self.repo})); + } + var name = args[0]; + + // Given the argument `-l`, it lists all repos for the current user. This information was fetched at user + // initialization + if(name === '-l') { + return callback(_self.shell.templates.repos({repos: _self.repos})); + } + + // Otherwise, the argument is assumed to a repo name, which `getRepo` uses to fetch the repository's information + // from the data in `_self.repos`, if possible. + var repo = getRepo(name, _self.repos); + + // If there is no matching repo, it renders an error. + if(!repo) { + return callback(_self.shell.templates.repo_error({name: name, msg: 'no such repo'})); + } + + // Given a valid repo, `setRepo` initializes the repo (i.e. fetching the root directory) and renders the repo + // information. + return setRepo(repo, + function(msg) { + return callback(_self.shell.templates.repo_error({name: name, msg: msg})); + }, + function(repo) { + if(!repo) { + return callback(_self.shell.templates.repo_not_found({repo: name, user: _self.user.login})); + } + return callback(_self.shell.templates.repo({repo: _self.repo})); + } + ); + }, + + // `completion` uses `_self.repo` and `Josh.Shell.bestMatch` to try and match the partial information to the possible + // matching repositories. + completion: function(cmd, arg, line, callback) { + callback(_self.shell.bestMatch(arg, _.map(_self.repos, function(repo) { + return repo.name; + }))); + } + }); + + //
    + + // branch [ -l | branchname ] + // -------------------------- + + // The `branch` command is used to switch or list branches for the current repository. + _self.shell.setCommandHandler("branch", { + + // `exec` handles the execution of the command. + exec: function(cmd, args, callback) { + + // Given no arguments, it simply returns the current branch, which will be rendered by the shell. + if(!args || args.length == 0) { + return callback(_self.branch); + } + var branch = args[0]; + + // Given the argument `-l`, it lists all branches for the current repo. This information is lazily + // initialized via `ensureBranches`. + if(branch === '-l') { + return ensureBranches( + function(msg) { + callback(_self.shell.templates.branches_error({msg: msg})); + }, + function() { + return callback(_self.shell.templates.branches({branches: _self.branches})); + } + ); + } + + // Owherwise, the current branch is switched by fetching the root directory for the new branch, and on success, + // setting `_self.branch` and setting the current pathandler node to the root directory fetched. + return getDir(_self.repo.full_name, branch, "/", function(node) { + if(!node) { + callback(_self.shell.templates.branch_error({name: branch, msg: "unable to load root directory for branch"})); + } + _self.branch = branch; + _self.pathhandler.current = node; + _self.root = node; + callback(); + }); + }, + + // `completion` handles `TAB` completion on a partial branch name. The list of possible branches is once again + // lazily initialized via `ensureBranches`. + completion: function(cmd, arg, line, callback) { + return ensureBranches( + function() { + callback(); + }, + function() { + callback(_self.shell.bestMatch(arg, _.map(_self.branches, function(branch) { + return branch.name; + }))); + } + ); + } + }); + + //
    + + // This attaches a custom prompt render to the shell. + _self.shell.onNewPrompt(function(callback) { + callback(_self.shell.templates.prompt({self: _self, node: _self.pathhandler.current})); + }); + + // Wiring up PathHandler + // ===================== + + //
    + + // getNode + // ------- + + // `getNode` is required by `Josh.PathHandler` to provide filesystem behavior. Given a path, it is expected to return + // a pathnode or null; + _self.pathhandler.getNode = function(path, callback) { + _console.log("looking for node at: " + path); + + // If the given path is empty, just return the current pathnode. + if(!path) { + return callback(_self.pathhandler.current); + } + var parts = getPathParts(path); + + // If the first part of path parts isn't empty, the path is a relative path, which can be turned into an + // *absolutish* path by pre-pending the parts of the current pathnode. + if(parts[0] !== '') { + parts = getPathParts(_self.pathhandler.current.path).concat(parts); + } + + // At this point the path is *absolutish*, i.e. looks absolute, but all `.` and `..` mentions need to removed and + // resolved before it is truly absolute. + var resolved = []; + _.each(parts, function(x) { + if(x === '.') { + return; + } + if(x === '..') { + resolved.pop(); + } else { + resolved.push(x); + } + }); + var absolute = resolved.join('/'); + _console.log("path to fetch: " + absolute); + return getDir(_self.repo.full_name, _self.branch, absolute, callback); + }; + + //
    + + // getChildNodes + // ------------- + + // `getChildNodes` is the second function implementation required for `Josh.PathHandler`. Given a pathnode, it returns + // a list of child pathnodes. This is used by `Tab` completion to resolve a partial path, after first resolving the + // nearest parent node using `getNode + _self.pathhandler.getChildNodes = function(node, callback) { + + // If the given node is a file node, no further work is required. + if(node.isfile) { + _console.log("it's a file, no children"); + return callback(); + } + + // Otherwise, if the child nodes have already been initialized, which is done lazily, return them. + if(node.children) { + _console.log("got children, let's turn them into nodes"); + return callback(makeNodes(node.children)); + } + + // Finally, use `getDir` to fetch and populate the child nodes. + _console.log("no children, fetch them"); + return getDir(_self.repo.full_name, _self.branch, node.path, function(detailNode) { + node.children = detailNode.children; + callback(makeNodes(node.children)); + }); + }; + + // Supporting Functions + // ==================== + + //
    + + // get + // --- + + // This function is responsible for all API requests, given a partial API path, `resource`, and an query argument object, + // `args`. + function get(resource, args, callback) { + var url = _self.api + resource; + if(args) { + url += "?" + _.map(args,function(v, k) { + return k + "=" + v; + }).join("&"); + } + _console.log("fetching: " + url); + var request = { + url: url, + dataType: 'json', + xhrFields: { + withCredentials: true + } + }; + $.ajax(request).done(function(response, status, xhr) { + + // Every response from the API includes rate limiting headers, as well as an indicator injected by the API proxy + // whether the request was done with authentication. Both are used to display request rate information and a + // link to authenticate, if required. + var ratelimit = { + remaining: parseInt(xhr.getResponseHeader("X-RateLimit-Remaining")), + limit: parseInt(xhr.getResponseHeader("X-RateLimit-Limit")), + authenticated: xhr.getResponseHeader('Authenticated') === 'true' + }; + $('#ratelimit').html(_self.shell.templates.rateLimitTemplate(ratelimit)); + if(ratelimit.remaining == 0) { + alert("Whoops, you've hit the github rate limit. You'll need to authenticate to continue"); + _self.shell.deactivate(); + return null; + } + + // For simplicity, this tutorial trivially deals with request failures by just returning null from this function + // via the callback. + if(status !== 'success') { + return callback(); + } + return callback(response); + }) + } + + //
    + + // ensureBranches + // -------------- + + // This function lazily fetches the branches for the current repo from the API. + function ensureBranches(err, callback) { + get("repos/" + _self.repo.full_name + "/branches", null, function(branches) { + if(!branches) { + return err("api request failed to return branch list"); + } + _self.branches = branches; + return callback(); + }); + } + + //
    + + // setUser + // ------- + + // This function fetches the specified user and initializes a repository to the provided value (which may be null). + // one fetched by `initialzeRepos`. + function setUser(user_name, repo_name, err, callback) { + if(_self.user && _self.user.login === user_name) { + return callback(_self.user); + } + return get("users/" + user_name, null, function(user) { + if(!user) { + return err("no such user"); + } + return initializeRepos(user, repo_name, err, function(repo) { + _self.user = user; + return callback(_self.user); + }); + }); + } + + //
    + + // initalizeRepos + // -------------- + + // This function first fetches all repos for the given user from the API and then sets the current repo to the provided + // value (which may be null). + function initializeRepos(user, repo_name, err, callback) { + return getRepos(user.login, function(repos) { + var repo = getRepo(repo_name, repos); + if(!repo) { + return err("user has no repositories"); + } + return setRepo(repo, err, function(repo) { + _self.repos = repos; + return callback(repo); + }); + }); + } + + //
    + + // getDir + // ------ + + // This function function fetches the directory listing for a path on a given repo and branch. + function getDir(repo_full_name, branch, path, callback) { + + // Although paths in the internal representation may have a trailing `/`, it has to be removed before using it + // as the argument for an API request. + if(path && path.length > 1 && path[path.length - 1] === '/') { + path = path.substr(0, path.length - 1); + } + get("repos/" + repo_full_name + "/contents" + path, {ref: branch}, function(data) { + + // The API call may return either an array, indicating that the path was a directory, or an object. Since only + // are stored as pathnodes, retrieving anything but an array returns null via the callback. + if(Object.prototype.toString.call(data) !== '[object Array]') { + _console.log("path '" + path + "' was a file"); + return callback(); + } + + // Given a directory listing, i.e. array, the current directory node is created and the API return value captured + // as children so that they can later be transformed into child pathnodes, if required. + var node = { + name: _.last(_.filter(path.split("/"), function(x) { + return x; + })) || "", + path: path, + children: data + }; + _console.log("got node at: " + node.path); + return callback(node); + }); + } + + //
    + + // getRepos + // -------- + + // This function fetches all repositories for a given user. + function getRepos(userLogin, callback) { + return get("users/" + userLogin + "/repos", null, function(data) { + callback(data); + }); + } + + //
    + + // getRepo + // ------- + + // This function tries to match a repository from the given list of known repositories. Should `repo_name` be null, + // the first repository in `repos` is returned. + function getRepo(repo_name, repos) { + if(!repos || repos.length == 0) { + return null; + } + var repo; + if(repo_name) { + repo = _.find(repos, function(repo) { + return repo.name === repo_name; + }); + if(!repo) { + return callback(); + } + } else { + repo = repos[0]; + } + return repo; + } + + //
    + + // setRepo + // ------- + + // This function fetches the root directory for the specified repository and initializes the current repository + // state. + function setRepo(repo, err, callback) { + return getDir(repo.full_name, repo.default_branch, "/", function(node) { + if(!node) { + return err("could not initialize root directory of repository '" + repo.full_name + "'"); + } + _console.log("setting repo to '" + repo.name + "'"); + _self.repo = repo; + _self.branch = repo.default_branch; + _self.pathhandler.current = node; + _self.root = node; + return callback(repo); + }); + } + + //
    + + // getPathParts + // ------------ + + // This function splits a path on `/` and removes any empty trailing element. + function getPathParts(path) { + var parts = path.split("/"); + if(parts[parts.length - 1] === '') { + return parts.slice(0, parts.length - 1); + } + return parts; + } + + //
    + + // makeNodes + // --------- + + // This function builds child pathnodes from the directory information returned by getDir. + function makeNodes(children) { + return _.map(children, function(node) { + return { + name: node.name, + path: "/" + node.path, + isFile: node.type === 'file' + }; + }); + } + + // UI setup and initialization + // =========================== + + //
    + + // initializationError + // ------------------- + + // This function is a lazy way with giving up if some request failed during intialization, forcing the user + // to reload to retry. + function initializationError(context, msg) { + _console.log("[" + context + "] failed to initialize: " + msg); + alert("unable to initialize shell. Encountered a problem talking to github api. Try reloading the page"); + } + + //
    + + // intializeUI + // ----------- + + // After a current user and repo have been set, this function initializes the UI state to allow the shell to be + // shown and hidden. + function initializeUI() { + _console.log("activating"); + var $consolePanel = $('#shell-container'); + $consolePanel.resizable({ handles: "s"}); + $(document).keypress(function(event) { + if(_self.shell.isActive()) { + return; + } + if(event.keyCode == 126) { + event.preventDefault(); + activateAndShow(); + } + }); + function activateAndShow() { + _self.shell.activate(); + $consolePanel.slideDown(); + $consolePanel.focus(); + } + + function hideAndDeactivate() { + _self.shell.deactivate(); + $consolePanel.slideUp(); + $consolePanel.blur(); + } + + _self.shell.onEOT(hideAndDeactivate); + _self.shell.onCancel(hideAndDeactivate); + } + + //
    + + // On document ready, the default user and repo are loaded from the API before the UI can complete initialization. + $(document).ready(function() { + setUser("sdether", "josh.js", + function(msg) { + initializationError("default", msg); + }, + initializeUI + ); + }); + })(root, $, _); +}) + (this, $, _); \ No newline at end of file diff --git a/javascripts/highlight.min.js b/javascripts/highlight.min.js new file mode 100644 index 0000000..545fa1d --- /dev/null +++ b/javascripts/highlight.min.js @@ -0,0 +1 @@ +var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(//gm,">")}function b(p){for(var o=p.firstChild;o;o=o.nextSibling){if(o.nodeName=="CODE"){return o}if(!(o.nodeType==3&&o.nodeValue.match(/\s+/))){break}}}function h(p,o){return Array.prototype.map.call(p.childNodes,function(q){if(q.nodeType==3){return o?q.nodeValue.replace(/\n/g,""):q.nodeValue}if(q.nodeName=="BR"){return"\n"}return h(q,o)}).join("")}function a(q){var p=(q.className+" "+q.parentNode.className).split(/\s+/);p=p.map(function(r){return r.replace(/^language-/,"")});for(var o=0;o"}while(x.length||v.length){var u=t().splice(0,1)[0];y+=l(w.substr(p,u.offset-p));p=u.offset;if(u.event=="start"){y+=s(u.node);r.push(u.node)}else{if(u.event=="stop"){var o,q=r.length;do{q--;o=r[q];y+=("")}while(o!=u.node);r.splice(q,1);while(q'+L[0]+""}else{r+=L[0]}N=A.lR.lastIndex;L=A.lR.exec(K)}return r+K.substr(N)}function z(){if(A.sL&&!e[A.sL]){return l(w)}var r=A.sL?d(A.sL,w):g(w);if(A.r>0){v+=r.keyword_count;B+=r.r}return''+r.value+""}function J(){return A.sL!==undefined?z():G()}function I(L,r){var K=L.cN?'':"";if(L.rB){x+=K;w=""}else{if(L.eB){x+=l(r)+K;w=""}else{x+=K;w=r}}A=Object.create(L,{parent:{value:A}});B+=L.r}function C(K,r){w+=K;if(r===undefined){x+=J();return 0}var L=o(r,A);if(L){x+=J();I(L,r);return L.rB?0:r.length}var M=s(A,r);if(M){if(!(M.rE||M.eE)){w+=r}x+=J();do{if(A.cN){x+=""}A=A.parent}while(A!=M.parent);if(M.eE){x+=l(r)}w="";if(M.starts){I(M.starts,"")}return M.rE?0:r.length}if(t(r,A)){throw"Illegal"}w+=r;return r.length||1}var F=e[D];f(F);var A=F;var w="";var B=0;var v=0;var x="";try{var u,q,p=0;while(true){A.t.lastIndex=p;u=A.t.exec(E);if(!u){break}q=C(E.substr(p,u.index-p),u[0]);p=u.index+q}C(E.substr(p));return{r:B,keyword_count:v,value:x,language:D}}catch(H){if(H=="Illegal"){return{r:0,keyword_count:0,value:l(E)}}else{throw H}}}function g(s){var o={keyword_count:0,r:0,value:l(s)};var q=o;for(var p in e){if(!e.hasOwnProperty(p)){continue}var r=d(p,s);r.language=p;if(r.keyword_count+r.r>q.keyword_count+q.r){q=r}if(r.keyword_count+r.r>o.keyword_count+o.r){q=o;o=r}}if(q.language){o.second_best=q}return o}function i(q,p,o){if(p){q=q.replace(/^((<[^>]+>|\t)+)/gm,function(r,v,u,t){return v.replace(/\t/g,p)})}if(o){q=q.replace(/\n/g,"
    ")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagName("pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.javascript=function(a){return{k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const",literal:"true false null undefined NaN Infinity"},c:[a.ASM,a.QSM,a.CLCM,a.CBLCLM,a.CNM,{b:"("+a.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[a.CLCM,a.CBLCLM,{cN:"regexp",b:"/",e:"/[gim]*",i:"\\n",c:[{b:"\\\\/"}]},{b:"<",e:">;",sL:"xml"}],r:0},{cN:"function",bWK:true,e:"{",k:"function",c:[{cN:"title",b:"[A-Za-z$_][0-9A-Za-z$_]*"},{cN:"params",b:"\\(",e:"\\)",c:[a.CLCM,a.CBLCLM],i:"[\"'\\(]"}],i:"\\[|%"}]}}(hljs);hljs.LANGUAGES.css=function(a){var b={cN:"function",b:a.IR+"\\(",e:"\\)",c:[a.NM,a.ASM,a.QSM]};return{cI:true,i:"[=/|']",c:[a.CBLCLM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",eE:true,k:"import page media charset",c:[b,a.ASM,a.QSM,a.NM]},{cN:"tag",b:a.IR,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[a.CBLCLM,{cN:"rule",b:"[^\\s]",rB:true,e:";",eW:true,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[b,a.NM,a.QSM,a.ASM,a.CBLCLM,{cN:"hexcolor",b:"\\#[0-9A-F]+"},{cN:"important",b:"!important"}]}}]}]}]}}(hljs);hljs.LANGUAGES.xml=function(a){var c="[A-Za-z0-9\\._:-]+";var b={eW:true,c:[{cN:"attribute",b:c,r:0},{b:'="',rB:true,e:'"',c:[{cN:"value",b:'"',eW:true}]},{b:"='",rB:true,e:"'",c:[{cN:"value",b:"'",eW:true}]},{b:"=",c:[{cN:"value",b:"[^\\s/>]+"}]}]};return{cI:true,c:[{cN:"pi",b:"<\\?",e:"\\?>",r:10},{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"|$)",e:">",k:{title:"style"},c:[b],starts:{e:"",rE:true,sL:"css"}},{cN:"tag",b:"|$)",e:">",k:{title:"script"},c:[b],starts:{e:"<\/script>",rE:true,sL:"javascript"}},{b:"<%",e:"%>",sL:"vbscript"},{cN:"tag",b:"",c:[{cN:"title",b:"[^ />]+"},b]}]}}(hljs);hljs.LANGUAGES.json=function(a){var e={literal:"true false null"};var d=[a.QSM,a.CNM];var c={cN:"value",e:",",eW:true,eE:true,c:d,k:e};var b={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:true,eE:true,c:[a.BE],i:"\\n",starts:c}],i:"\\S"};var f={b:"\\[",e:"\\]",c:[a.inherit(c,{cN:null})],i:"\\S"};d.splice(d.length,0,b,f);return{c:d,k:e,i:"\\S"}}(hljs); \ No newline at end of file diff --git a/javascripts/pathhandler.js b/javascripts/pathhandler.js index 9e3512a..d15247a 100644 --- a/javascripts/pathhandler.js +++ b/javascripts/pathhandler.js @@ -23,17 +23,15 @@ var Josh = Josh || {}; } }); var _shell = shell; + _shell.templates.not_found = _.template("
    <%=cmd%>: <%=path%>: No such file or directory
    "); + _shell.templates.ls = _.template("
    <% _.each(nodes, function(node) { %><%=node.name%> <% }); %>
    "); + _shell.templates.pwd = _.template("
    <%=node.path %> 
    "); + _shell.templates.prompt = _.template("<%= node.path %> $"); var _original_default = _shell.getCommandHandler('_default'); var self = { current: null, pathCompletionHandler: pathCompletionHandler, commandAndPathCompletionHandler: commandAndPathCompletionHandler, - templates: { - not_found: _.template("
    <%=cmd%>: <%=path%>: No such file or directory
    "), - ls: _.template("
    <% _.each(nodes, function(node) { %><%=node.name%> <% }); %>
    "), - pwd: _.template("
    <%=node.path %> 
    "), - prompt: _.template("<%= node.path %> $") - }, getNode: function(path, callback) { callback(); }, @@ -41,7 +39,7 @@ var Josh = Josh || {}; callback([]); }, getPrompt: function() { - return self.templates.prompt({node: self.current}); + return _shell.templates.prompt({node: self.current}); } }; @@ -96,6 +94,12 @@ var Josh = Josh || {}; var lastPathSeparator = arg.lastIndexOf("/"); var parent = arg.substr(0, lastPathSeparator + 1); partial = arg.substr(lastPathSeparator + 1); + if(partial === '..' || partial === '.') { + return callback({ + completion: '/', + suggestions: [] + }); + } _console.log("completing children via parent '" + parent+"' w/ partial '"+partial+"'"); return self.getNode(parent, function(node) { if(!node) { @@ -125,7 +129,7 @@ var Josh = Josh || {}; function cd(cmd, args, callback) { self.getNode(args[0], function(node) { if(!node) { - return callback(self.templates.not_found({cmd: 'cd', path: args[0]})); + return callback(_shell.templates.not_found({cmd: 'cd', path: args[0]})); } self.current = node; return callback(); @@ -133,7 +137,7 @@ var Josh = Josh || {}; } function pwd(cmd, args, callback) { - callback(self.templates.pwd({node: self.current})); + callback(_shell.templates.pwd({node: self.current})); } function ls(cmd, args, callback) { @@ -148,11 +152,11 @@ var Josh = Josh || {}; function render_ls(node, path, callback) { if(!node) { - return callback(self.templates.not_found({cmd: 'ls', path: path})); + return callback(_shell.templates.not_found({cmd: 'ls', path: path})); } return self.getChildNodes(node, function(children) { _console.log("finish render: " + node.name); - callback(self.templates.ls({nodes: children})); + callback(_shell.templates.ls({nodes: children})); }); } diff --git a/javascripts/readline.js b/javascripts/readline.js index 2534ce6..739b713 100644 --- a/javascripts/readline.js +++ b/javascripts/readline.js @@ -15,7 +15,7 @@ *-------------------------------------------------------------------------*/ var Josh = Josh || {}; -Josh.Version = "0.2.6"; +Josh.Version = "0.2.7"; (function(root) { var SPECIAL = { 8: 'BACKSPACE', diff --git a/javascripts/shell.js b/javascripts/shell.js index 681e72c..21a54cf 100644 --- a/javascripts/shell.js +++ b/javascripts/shell.js @@ -25,36 +25,26 @@ var Josh = Josh || {}; } }); var _prompt = config.prompt || 'jsh$'; - var _shell_view_id = config.shell_view_id || '#shell-view'; - var _shell_panel_id = config.shell_panel_id || '#shell-panel'; - var _input_id = config.input_id || '#shell-cli'; - var _input_html = config.input_html || '
     
    '; - var _search_html = config.search_html || '
    (reverse-i-search)`\': 
    '; - var _suggest_html = config.suggest_html || '
    '; - var _suggest_id = config.suggest_id = "#shell-suggest"; + var _shell_view_id = config.shell_view_id || 'shell-view'; + var _shell_panel_id = config.shell_panel_id || 'shell-panel'; + var _input_id = config.input_id || 'shell-cli'; var _blinktime = config.blinktime || 500; var _history = config.history || new Josh.History(); var _readline = config.readline || new Josh.ReadLine({history: _history, console: _console}); var _active = false; var _cursor_visible = false; - var _itemTemplate = _.template("
    <%- i %> <%- cmd %>
    "); var _activationHandler; var _deactivationHandler; var _cmdHandlers = { clear: { exec: function(cmd, args, callback) { - $(_input_id).parent().empty(); + $(id(_input_id)).parent().empty(); callback(); } }, help: { exec: function(cmd, args, callback) { - var content = $('
    Commands:
    '); - var itemTemplate = _.template('
     <%=command%>
    '); - _.each(commands(), function(command) { - content.append(itemTemplate({command: command})) - }); - callback(content); + callback(self.templates.help({commands: commands()})); } }, history: { @@ -64,17 +54,12 @@ var Josh = Josh || {}; callback(); return; } - var content = $('
    '); - _.each(_history.items(), function(cmd, i) { - content.append(_itemTemplate({cmd: cmd, i: i})); - }); - callback(content); + callback(self.templates.history({items: _history.items()})); } }, _default: { exec: function(cmd, args, callback) { - var content = _.template('
    Unrecognized command: <%=cmd%>
    ', {cmd: cmd}); - callback(content); + callback(self.templates.bad_command({cmd: cmd})); }, completion: function(cmd, arg, line, callback) { if(!arg) { @@ -97,11 +82,19 @@ var Josh = Josh || {}; // public methods var self = { commands: commands, + templates: { + history: _.template("
    <% _.each(items, function(cmd, i) { %>
    <%- i %> <%- cmd %>
    <% }); %>
    "), + help: _.template("
    Commands:
    <% _.each(commands, function(cmd) { %>
     <%- cmd %>
    <% }); %>
    "), + bad_command: _.template('
    Unrecognized command: <%=cmd%>
    '), + input_cmd: _.template('
     
    '), + input_search: _.template('
    (reverse-i-search)`\': 
    '), + suggest: _.template("
    <% _.each(suggestions, function(suggestion) { %>
    <%- suggestion %>
    <% }); %>
    ") + }, isActive: function() { return _readline.isActive(); }, activate: function() { - if($(_shell_view_id).length == 0) { + if($(id(_shell_view_id)).length == 0) { _active = false; return; } @@ -149,25 +142,25 @@ var Josh = Josh || {}; if(_searchMatch) { cursorIdx = _searchMatch.cursoridx || 0; text = _searchMatch.text || ''; - $(_input_id + ' .searchterm').text(_searchMatch.term); + $(id(_input_id) + ' .searchterm').text(_searchMatch.term); } var left = _.escape(text.substr(0, cursorIdx)).replace(/ /g, ' '); var cursor = text.substr(cursorIdx, 1); var right = _.escape(text.substr(cursorIdx + 1)).replace(/ /g, ' '); - $(_input_id + ' .prompt').text(_prompt); - $(_input_id + ' .input .left').html(left); + $(id(_input_id) + ' .prompt').html(_prompt); + $(id(_input_id) + ' .input .left').html(left); if(!cursor) { - $(_input_id + ' .input .cursor').html(' ').css('textDecoration', 'underline'); + $(id(_input_id) + ' .input .cursor').html(' ').css('textDecoration', 'underline'); } else { - $(_input_id + ' .input .cursor').text(cursor).css('textDecoration', 'underline'); + $(id(_input_id) + ' .input .cursor').text(cursor).css('textDecoration', 'underline'); } - $(_input_id + ' .input .right').html(right); + $(id(_input_id) + ' .input .right').html(right); _cursor_visible = true; self.scrollToBottom(); _console.log('rendered "' + text + '" w/ cursor at ' + cursorIdx); }, refresh: function() { - $(_input_id).replaceWith(_input_html); + $(id(_input_id)).replaceWith(self.templates.input_cmd({id:_input_id})); self.render(); _console.log('refreshed ' + _input_id); @@ -223,6 +216,10 @@ var Josh = Josh || {}; } }; + function id(id) { + return "#"+id; + } + function commands() { return _.chain(_cmdHandlers).keys().filter(function(x) { return x[0] != "_" @@ -239,9 +236,9 @@ var Josh = Josh || {}; } _cursor_visible = !_cursor_visible; if(_cursor_visible) { - $(_input_id + ' .input .cursor').css('textDecoration', 'underline'); + $(id(_input_id) + ' .input .cursor').css('textDecoration', 'underline'); } else { - $(_input_id + ' .input .cursor').css('textDecoration', ''); + $(id(_input_id) + ' .input .cursor').css('textDecoration', ''); } blinkCursor(); }, _blinktime); @@ -259,11 +256,11 @@ var Josh = Josh || {}; function renderOutput(output, callback) { if(output) { - $(_input_id).after(output); + $(id(_input_id)).after(output); } - $(_input_id + ' .input .cursor').css('textDecoration', ''); - $(_input_id).removeAttr('id'); - $(_shell_view_id).append(_input_html); + $(id(_input_id) + ' .input .cursor').css('textDecoration', ''); + $(id(_input_id)).removeAttr('id'); + $(id(_shell_view_id)).append(self.templates.input_cmd({id:_input_id})); if(_promptHandler) { return _promptHandler(function(prompt) { self.setPrompt(prompt); @@ -276,13 +273,13 @@ var Josh = Josh || {}; function activate() { _console.log("activating shell"); if(!_view) { - _view = $(_shell_view_id); + _view = $(id(_shell_view_id)); } if(!_panel) { - _panel = $(_shell_panel_id); + _panel = $(id(_shell_panel_id)); } - if($(_input_id).length == 0) { - _view.append(_input_html); + if($(id(_input_id)).length == 0) { + _view.append(self.templates.input_cmd({id:_input_id})); } self.refresh(); _active = true; @@ -323,11 +320,11 @@ var Josh = Josh || {}; }); }); _readline.onSearchStart(function() { - $(_input_id).replaceWith(_search_html); + $(id(_input_id)).replaceWith(self.templates.input_search({id:_input_id})); _console.log('started search'); }); _readline.onSearchEnd(function() { - $(_input_id).replaceWith(_input_html); + $(id(_input_id)).replaceWith(self.templates.input_cmd({id:_input_id})); _searchMatch = null; self.render(); _console.log("ended search"); @@ -376,12 +373,7 @@ var Josh = Josh || {}; return callback(); } if(match.suggestions && match.suggestions.length > 1) { - var suggestion = $(_suggest_html); - for(var i = 0; i < match.suggestions.length; i++) { - _console.log("suggestion: " + match.suggestions[i]); - suggestion.append($("
    ").text(match.suggestions[i])); - } - return renderOutput(suggestion, function() { + return renderOutput(self.templates.suggest({suggestions: match.suggestions}), function() { callback(match.completion); }); } diff --git a/pathhandler.html b/pathhandler.html new file mode 100644 index 0000000..0bd5020 --- /dev/null +++ b/pathhandler.html @@ -0,0 +1,157 @@ + + + + + + Josh.js by sdether + + + + + + + + + + + + + + +
    + +
    +

    Josh.PathHandler

    + +

    pathhandler.js is a mix in to easily add the cd, ls and + pwd commands as well as path completion. It has + Underscore as its dependency for templating, however since all + templates it uses are exposed, they could easily be replaced with a different function that accepts an argument object returns html. +

    + +

    By implementing the functions getNode and + getChildNodes, this library adds path traversal, discovery and completion just like a bash shell. +

    + +

    The Path Node

    + +

    PathHandler deals with files/directories a path node with at least the following two fields:

    +
    {
    +    name: 'localname',
    +    path: '/full/path/to/localname'
    +}
    +

    where name is the name of the node and + path is the absolute path to the node. PathHandler gets path nodes as the callback argument for + getNode and does not modify it itself, so any additional state required can be attached to the node and be relied on as being part of the node when it is provided to + getChildNodes or a template.

    + +

    The Commands

    + +

    PathHandler is used to add standard unix directory handling commands and path completion to Josh.Shell.

    + +

    pwd

    + +

    Prints the current directory, as defined by pathhandler.current.

    + +

    ls [path]

    + +

    Prints out the listing of all childNodes of the node represented by path. If path is not specified, pathhandler.current is used instead.

    + +

    cd [path]

    + +

    Changes pathhandler.current to the node found at path, if one could be found. If path is not specified, pathhandler.current is used instead, resulting in a no-op.

    + +

    Templates

    + +

    Each template is expected to a function that takes a data object and returns html. The default templates are built with + _.template but any templating system can be used as long as follows the same behavior.

    + +

    not_found

    + +

    Called when getNode returns null as its callback argument.

    + +

    Data:

    +
      +
    • cmd - command that resulted in a miss on path lookup
    • +
    • path - the path that did not match a node
    • +
    +

    ls

    + +

    Called to generate output for a successful ls cmd.

    + +

    Data:

    +
      +
    • nodes - array of path nodes
    • +
    +

    pwd

    + +

    Called to generate output for pwd cmd.

    + +

    Data:

    +
      +
    • node - the current node
    • +
    +

    prompt

    + +

    Called to generate the new prompt after any cmd attempt (including after completions).

    + +

    Data:

    +
      +
    • node - the current node
    • +
    +

    Properties

    + +

    current

    +

    Contains the current directory. It has to be initialized before activating the shell, since on activation, getPrompt will be called by the shell and requires current to be set to display the prompt. Could be changed manually, but generally is changed as a result of calling cd.

    + +

    pathCompletionHandler

    +

    Contains the path completion handler used by PathHandler. Exposed so that other commands added that work on paths, can use it as their completion handler. It is used for the ls and cd commands. The only assumption it makes about paths is that they are separated by /.

    +

    Path completion is done by first finding the nearest node, i.e. if a trailing slash is found, it calls getNode with the path, otherwise it will call getNode and upon receiving null, will take the subpath to the nearest slash and call getNode again. If a node is found in either scenario, it then calls getChildnodes to get all all children, i.e. the possible completions and in turn call shell.bestMatch with any partial path after the slash and the list of possible child node names.

    + +

    commandAndPathCompletionHandler

    + +

    Contains a wrapper around pathCompletionHandler that replaces the default completion handler of the shell, so that a completion event without a known command can determine whether to complete as a command name or a path.

    + +

    templates

    +

    Contains the templates described above.

    + +

    Functions

    + +

    new Josh.PathHandler(shell, config)

    +

    Create a new path handler and attach it to a shell instance.

    + +

    getNode(path, callback)

    +

    This method is called with a path and a callback expecting a path node returned if the path is valid. The default implementation always calls callback with null. This is where custom path resolution logic goes and where path nodes are constructed.

    + +

    getChildNodes(node, callback)

    + +

    This method is called by the pathCompletionHandler after resolving a path to a node via getNode and expects its callback to be called with an array of pathnodes.

    + +

    getPrompt

    + +

    This method is called each time the prompt needs to be re-rendered, which in turn calls templates.prompt with pathhandler,current. Could be replaced for custom prompt behavior beyond altering the template.

    + +

    + +

    Internal Dependencies

    + +

    Josh.Shell

    + +

    External Dependencies

    + +

    Underscore

    +
    +
    + + + + \ No newline at end of file diff --git a/quakeconsole.html b/quakeconsole.html index a592b46..5872154 100644 --- a/quakeconsole.html +++ b/quakeconsole.html @@ -6,6 +6,7 @@ Josh.js by sdether + + + + + + + + + + + +
    + +
    +

    Josh.Readline

    + +

    Josh.Readline is the underlying plumbing responsible for all keystroke handling, bringing + GNU Readline like line editing to the browser. It is used by + Josh.Shell to implement + bash-like command prompt behavior, but could easily be wired up to any text box requiring advanced key handling. It has no dependencies on any outside libraries, although it does require either + Josh.History and Josh.Killring or objects implementing the same calls.

    + +

    Functions

    +

    When using Josh.Shell Readline is proxied for those calls that need to be exposed and otherwise invisible. The full API for readline is really only of interest for usage away from Josh.Shell.

    + +

    new Josh.Readline(config)

    +

    isActive()

    +

    activate()

    +

    deactivate()

    +

    getLine

    +

    onActivate(eventHandler)

    +

    onDeactivate(eventHandler)

    +

    onChange(eventHandler)

    +

    onClear(eventHandler)

    +

    onEnter(eventHandler)

    +

    onCompletion(eventHandler)

    +

    onCancel(eventHandler)

    +

    onEOT(eventHandler)

    +

    onSearchStart(eventHandler)

    +

    onSearchEnd(eventHandler)

    +

    onSearchChange(eventHandler)

    +

    +

    + +

    Internal Dependencies

    +

    Josh.History

    +

    Josh.Killring

    + +

    External Dependencies

    +

    None

    +
    +
    + + + + \ No newline at end of file diff --git a/shell.html b/shell.html new file mode 100644 index 0000000..bfe18ef --- /dev/null +++ b/shell.html @@ -0,0 +1,112 @@ + + + + + + Josh.js by sdether + + + + + + + + + + + + + + +
    + +
    +

    Josh.Shell

    + +

    It provides a simple console UI, using a panel for the console viewport and an auto-scrolling + view inside the panel. It uses Underscore templates for generating the view html, although any + template generator can be substituted as long as it can be expressed in the form of a function that takes a + JSON object of arguments and returns an html string. +

    + +

    It also implements command handling so that new commands can be added by name with execution and completion + handlers. Out of the box, + shell.js provides the following commands:

    + +
      +
    • help - list all known commands (including user added)
    • +
    • clear - clear the "screen" i.e. viewport
    • +
    • history - show the command history captured by readline.js in + history.js +
    • +
    + +

    Functions

    + +

    new Josh.Shell(config)

    + +

    Config keys:

    +
      +
    • +
    + +

    bestMatch(partial, possible)

    + +

    commands()

    + +

    isActive()

    + +

    activate()

    + +

    deactivate()

    + +

    render()

    + +

    refresh()

    + +

    scrollToBottom()

    + +

    getCommandHandler(commandHandler)

    + +

    setCommandHandler(cmdName,cmdHandler)

    + +

    setPrompt(prompt)

    + +

    onEOT(eventHandler)

    + +

    onCancel(eventHandler)

    + +

    onInitialize(eventHandler)

    + +

    onActivate(eventHandler)

    + +

    onDeactivate(eventHandler)

    + +

    onNewPrompt(eventHandler)

    + +

    Internal Dependencies

    + +

    Josh.Readline

    + +

    Josh.History

    + +

    External Dependencies

    + +

    jQuery

    + +

    Underscore

    +
    +
    + + + + \ No newline at end of file diff --git a/stylesheets/githubconsole.css b/stylesheets/githubconsole.css new file mode 100644 index 0000000..e8e2619 --- /dev/null +++ b/stylesheets/githubconsole.css @@ -0,0 +1,41 @@ +#shell-container { + display: none; + height: 400px; + width: 100%; + opacity: 0.9; + background-color: #002f05; + color: #00fe00; + position: fixed; + padding: 0px 20px 20px 20px; + top: 0; + left: 0; + z-index: 1000; + font-family: 'Source Code Pro', sans-serif; + font-size: 0.9em; +} +#shell-panel { + overflow: scroll; + overflow-x: hidden; + overflow-y: scroll; + height: 100%; + width: 98%; +} +#shell-status { + position: absolute; + left: 0; + bottom: 0; +} +ul.widelist li { + float: left; + list-style: none; + width: 33%; +} +.clear { + clear: both; +} +.userinfo img { + float: right; +} +.userinfo table { + width: 75%; +} \ No newline at end of file diff --git a/stylesheets/styles.css b/stylesheets/styles.css index 2f3075b..785bf05 100644 --- a/stylesheets/styles.css +++ b/stylesheets/styles.css @@ -1,73 +1,3 @@ -@font-face { - font-family: 'OpenSansLight'; - src: url("http://github.com/fonts/OpenSans-Light-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-Light-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Light-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Light-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Light-webfont.svg#OpenSansLight") format("svg"); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'OpenSansLightItalic'; - src: url("http://github.com/fonts/OpenSans-LightItalic-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-LightItalic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-LightItalic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-LightItalic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-LightItalic-webfont.svg#OpenSansLightItalic") format("svg"); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'OpenSansRegular'; - src: url("http://github.com/fonts/OpenSans-Regular-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-Regular-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Regular-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Regular-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Regular-webfont.svg#OpenSansRegular") format("svg"); - font-weight: normal; - font-style: normal; - -webkit-font-smoothing: antialiased; -} - -@font-face { - font-family: 'OpenSansItalic'; - src: url("http://github.com/fonts/OpenSans-Italic-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-Italic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Italic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Italic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Italic-webfont.svg#OpenSansItalic") format("svg"); - font-weight: normal; - font-style: normal; - -webkit-font-smoothing: antialiased; -} - -@font-face { - font-family: 'OpenSansSemibold'; - src: url("http://github.com/fonts/OpenSans-Semibold-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-Semibold-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Semibold-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Semibold-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Semibold-webfont.svg#OpenSansSemibold") format("svg"); - font-weight: normal; - font-style: normal; - -webkit-font-smoothing: antialiased; -} - -@font-face { - font-family: 'OpenSansSemiboldItalic'; - src: url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-SemiboldItalic-webfont.svg#OpenSansSemiboldItalic") format("svg"); - font-weight: normal; - font-style: normal; - -webkit-font-smoothing: antialiased; -} - -@font-face { - font-family: 'OpenSansBold'; - src: url("http://github.com/fonts/OpenSans-Bold-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-Bold-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-Bold-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-Bold-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-Bold-webfont.svg#OpenSansBold") format("svg"); - font-weight: normal; - font-style: normal; - -webkit-font-smoothing: antialiased; -} - -@font-face { - font-family: 'OpenSansBoldItalic'; - src: url("http://github.com/fonts/OpenSans-BoldItalic-webfont.eot"); - src: url("http://github.com/fonts/OpenSans-BoldItalic-webfont.eot?#iefix") format("embedded-opentype"), url("http://github.com/fonts/OpenSans-BoldItalic-webfont.woff") format("woff"), url("http://github.com/fonts/OpenSans-BoldItalic-webfont.ttf") format("truetype"), url("http://github.com/fonts/OpenSans-BoldItalic-webfont.svg#OpenSansBoldItalic") format("svg"); - font-weight: normal; - font-style: normal; - -webkit-font-smoothing: antialiased; -} - /* normalize.css 2012-02-07T12:37 UTC - http://github.com/necolas/normalize.css */ /* ============================================================================= HTML5 display definitions @@ -86,7 +16,7 @@ hgroup, nav, section, summary { - display: block; + display: block; } /* @@ -95,16 +25,16 @@ summary { audio, canvas, video { - display: inline-block; - *display: inline; - *zoom: 1; + display: inline-block; + *display: inline; + *zoom: 1; } /* * Prevents modern browsers from displaying 'audio' without controls */ audio:not([controls]) { - display: none; + display: none; } /* @@ -112,7 +42,7 @@ audio:not([controls]) { * Known issue: no IE6 support */ [hidden] { - display: none; + display: none; } /* ============================================================================= @@ -125,12 +55,12 @@ audio:not([controls]) { * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ */ html { - font-size: 100%; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -ms-text-size-adjust: 100%; - /* 2 */ + font-size: 100%; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -ms-text-size-adjust: 100%; + /* 2 */ } /* @@ -141,14 +71,14 @@ button, input, select, textarea { - font-family: sans-serif; + font-family: sans-serif; } /* * Addresses margins handled incorrectly in IE6/7 */ body { - margin: 0; + margin: 0; } /* ============================================================================= @@ -158,7 +88,7 @@ body { * Addresses outline displayed oddly in Chrome */ a:focus { - outline: thin dotted; + outline: thin dotted; } /* @@ -167,7 +97,7 @@ a:focus { */ a:hover, a:active { - outline: 0; + outline: 0; } /* ============================================================================= @@ -178,40 +108,40 @@ a:active { * Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5 */ h1 { - font-size: 2em; - margin: 0.67em 0; + font-size: 2em; + margin: 0.67em 0; } h2 { - font-size: 1.5em; - margin: 0.83em 0; + font-size: 1.5em; + margin: 0.83em 0; } h3 { - font-size: 1.17em; - margin: 1em 0; + font-size: 1.17em; + margin: 1em 0; } h4 { - font-size: 1em; - margin: 1.33em 0; + font-size: 1em; + margin: 1.33em 0; } h5 { - font-size: 0.83em; - margin: 1.67em 0; + font-size: 0.83em; + margin: 1.67em 0; } h6 { - font-size: 0.75em; - margin: 2.33em 0; + font-size: 0.75em; + margin: 2.33em 0; } /* * Addresses styling not present in IE7/8/9, S5, Chrome */ abbr[title] { - border-bottom: 1px dotted; + border-bottom: 1px dotted; } /* @@ -219,26 +149,26 @@ abbr[title] { */ b, strong { - font-weight: bold; + font-weight: bold; } blockquote { - margin: 1em 40px; + margin: 1em 40px; } /* * Addresses styling not present in S5, Chrome */ dfn { - font-style: italic; + font-style: italic; } /* * Addresses styling not present in IE6/7/8/9 */ mark { - background: #ff0; - color: #000; + background: #ff0; + color: #000; } /* @@ -246,7 +176,7 @@ mark { */ p, pre { - margin: 1em 0; + margin: 1em 0; } /* @@ -257,9 +187,9 @@ pre, code, kbd, samp { - font-family: monospace, serif; - _font-family: 'courier new', monospace; - font-size: 1em; + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; } /* @@ -268,18 +198,18 @@ samp { */ /* 1 */ q { - quotes: none; + quotes: none; } /* 2 */ q:before, q:after { - content: ''; - content: none; + content: ''; + content: none; } small { - font-size: 75%; + font-size: 75%; } /* @@ -288,18 +218,18 @@ small { */ sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } sup { - top: -0.5em; + top: -0.5em; } sub { - bottom: -0.25em; + bottom: -0.25em; } /* ============================================================================= @@ -312,11 +242,11 @@ dl, menu, ol, ul { - margin: 1em 0; + margin: 1em 0; } dd { - margin: 0 0 0 40px; + margin: 0 0 0 40px; } /* @@ -325,7 +255,7 @@ dd { menu, ol, ul { - padding: 0 0 0 40px; + padding: 0 0 0 40px; } /* @@ -333,8 +263,8 @@ ul { */ nav ul, nav ol { - list-style: none; - list-style-image: none; + list-style: none; + list-style-image: none; } /* ============================================================================= @@ -346,17 +276,17 @@ nav ol { * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ */ img { - border: 0; - /* 1 */ - -ms-interpolation-mode: bicubic; - /* 2 */ + border: 0; + /* 1 */ + -ms-interpolation-mode: bicubic; + /* 2 */ } /* * Corrects overflow displayed oddly in IE9 */ svg:not(:root) { - overflow: hidden; + overflow: hidden; } /* ============================================================================= @@ -366,7 +296,7 @@ svg:not(:root) { * Addresses margin not present in IE6/7/8/9, S5, O11 */ figure { - margin: 0; + margin: 0; } /* ============================================================================= @@ -376,16 +306,16 @@ figure { * Corrects margin displayed oddly in IE6/7 */ form { - margin: 0; + margin: 0; } /* * Define consistent border, margin, and padding */ fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } /* @@ -394,13 +324,13 @@ fieldset { * 3. Corrects alignment displayed oddly in IE6/7 */ legend { - border: 0; - /* 1 */ - padding: 0; - white-space: normal; - /* 2 */ - *margin-left: -7px; - /* 3 */ + border: 0; + /* 1 */ + padding: 0; + white-space: normal; + /* 2 */ + *margin-left: -7px; + /* 3 */ } /* @@ -412,14 +342,14 @@ button, input, select, textarea { - font-size: 100%; - /* 1 */ - margin: 0; - /* 2 */ - vertical-align: baseline; - /* 3 */ - *vertical-align: middle; - /* 3 */ + font-size: 100%; + /* 1 */ + margin: 0; + /* 2 */ + vertical-align: baseline; + /* 3 */ + *vertical-align: middle; + /* 3 */ } /* @@ -427,8 +357,8 @@ textarea { */ button, input { - line-height: normal; - /* 1 */ + line-height: normal; + /* 1 */ } /* @@ -441,12 +371,12 @@ button, input[type="button"], input[type="reset"], input[type="submit"] { - cursor: pointer; - /* 1 */ - -webkit-appearance: button; - /* 2 */ - *overflow: visible; - /* 3 */ + cursor: pointer; + /* 1 */ + -webkit-appearance: button; + /* 2 */ + *overflow: visible; + /* 3 */ } /* @@ -454,7 +384,7 @@ input[type="submit"] { */ button[disabled], input[disabled] { - cursor: default; + cursor: default; } /* @@ -465,14 +395,14 @@ input[disabled] { */ input[type="checkbox"], input[type="radio"] { - box-sizing: border-box; - /* 1 */ - padding: 0; - /* 2 */ - *height: 13px; - /* 3 */ - *width: 13px; - /* 3 */ + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ + *height: 13px; + /* 3 */ + *width: 13px; + /* 3 */ } /* @@ -480,12 +410,12 @@ input[type="radio"] { * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof) */ input[type="search"] { - -webkit-appearance: textfield; - /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; - /* 2 */ - box-sizing: content-box; + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; } /* @@ -493,7 +423,7 @@ input[type="search"] { */ input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; + -webkit-appearance: none; } /* @@ -502,8 +432,8 @@ input[type="search"]::-webkit-search-cancel-button { */ button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; + border: 0; + padding: 0; } /* @@ -511,10 +441,10 @@ input::-moz-focus-inner { * 2. Improves readability and alignment in all browsers */ textarea { - overflow: auto; - /* 1 */ - vertical-align: top; - /* 2 */ + overflow: auto; + /* 1 */ + vertical-align: top; + /* 2 */ } /* ============================================================================= @@ -524,329 +454,340 @@ textarea { * Remove most spacing between table cells */ table { - border-collapse: collapse; - border-spacing: 0; + border-collapse: collapse; + border-spacing: 0; } body { - padding: 0px 0 20px 0px; - margin: 0px; - font: 14px/1.5 "OpenSansRegular", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: #f0e7d5; - font-weight: normal; - background: #252525; - background-attachment: fixed !important; - background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2a2a29), color-stop(100%, #1c1c1c)); - background: -webkit-linear-gradient(#2a2a29, #1c1c1c); - background: -moz-linear-gradient(#2a2a29, #1c1c1c); - background: -o-linear-gradient(#2a2a29, #1c1c1c); - background: -ms-linear-gradient(#2a2a29, #1c1c1c); - background: linear-gradient(#2a2a29, #1c1c1c); + padding: 0px 0 20px 0px; + margin: 0px; + font: 14px/1.5 "OpenSansRegular", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #f0e7d5; + font-weight: normal; + background: #252525; + background-attachment: fixed !important; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2a2a29), color-stop(100%, #1c1c1c)); + background: -webkit-linear-gradient(#2a2a29, #1c1c1c); + background: -moz-linear-gradient(#2a2a29, #1c1c1c); + background: -o-linear-gradient(#2a2a29, #1c1c1c); + background: -ms-linear-gradient(#2a2a29, #1c1c1c); + background: linear-gradient(#2a2a29, #1c1c1c); } h1, h2, h3, h4, h5, h6 { - color: #e8e8e8; - margin: 0 0 10px; - font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; + color: #e8e8e8; + margin: 0 0 10px; + font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; } p, ul, ol, table, pre, dl { - margin: 0 0 20px; + margin: 0 0 20px; } h1, h2, h3 { - line-height: 1.1; + line-height: 1.1; } h1 { - font-size: 28px; + font-size: 28px; } h2 { - font-size: 24px; + font-size: 24px; } h4, h5, h6 { - color: #e8e8e8; + color: #e8e8e8; } h3 { - font-size: 18px; - line-height: 24px; - font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif !important; - font-weight: normal; - color: #b6b6b6; + font-size: 18px; + line-height: 24px; + font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; + color: #b6b6b6; } a { - color: #ffcc00; - font-weight: 400; - text-decoration: none; + color: #ffcc00; + font-weight: 400; + text-decoration: none; } + a:hover { - color: #ffeb9b; + color: #ffeb9b; } a small { - font-size: 11px; - color: #666; - margin-top: -0.6em; - display: block; + font-size: 11px; + color: #666; + margin-top: -0.6em; + display: block; } ul { - list-style-image: url("http://github.com/images/bullet.png"); + list-style-image: url("http://github.com/images/bullet.png"); } strong { - font-family: 'OpenSansBold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; - font-weight: normal; + font-family: 'OpenSansBold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; } .wrapper { - max-width: 650px; - margin: 0 auto; - position: relative; - padding: 0 20px; + max-width: 650px; + margin: 0 auto; + position: relative; + padding: 0 20px; } section img { - max-width: 100%; + max-width: 100%; } blockquote { - border-left: 3px solid #ffcc00; - margin: 0; - padding: 0 0 0 20px; - font-style: italic; + border-left: 3px solid #ffcc00; + margin: 0; + padding: 0 0 0 20px; + font-style: italic; } code { - font-family: 'Source Code Pro', "Lucida Sans", Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal; - color: #efefef; - border: 1px solid #3a3a39; - background-color: #2a2a29; - border-radius: 5px; -moz-border-radius: 4px; - padding: 0px 2px; - -webkit-border-radius: 2px; - -o-border-radius: 2px; - -ms-border-radius: 2px; - -khtml-border-radius: 2px; - border-radius: 2px; + font-family: 'Source Code Pro', "Lucida Sans", Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal; + color: #efefef; + border: 1px solid #3a3a39; + background-color: #2a2a29; + border-radius: 5px; + -moz-border-radius: 4px; + padding: 0px 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; } -pre { - padding: 8px 15px; - background: #191919; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - -o-border-radius: 2px; - -ms-border-radius: 2px; - -khtml-border-radius: 2px; - border-radius: 2px; - border: 1px solid #121212; - -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); - -o-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); - overflow: auto; - overflow-y: hidden; +a code { + text-decoration: underline; + color: #efefef; +} + +a:hover code { + background-color: #4a4a49; + border: 1px dotted #6a6a69; } + pre code { - color: #efefef; - text-shadow: 0px 1px 0px #000; - margin: 0; - padding: 0; + color: #efefef; + text-shadow: 0px 1px 0px #000; + margin: 0; + padding: 0; } table { - width: 100%; - border-collapse: collapse; + width: 100%; + border-collapse: collapse; } th { - text-align: left; - padding: 5px 10px; - border-bottom: 1px solid #434343; - color: #b6b6b6; - font-family: 'OpenSansSemibold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; - font-weight: normal; + text-align: left; + padding: 5px 10px; + border-bottom: 1px solid #434343; + color: #b6b6b6; + font-family: 'OpenSansSemibold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; } td { - text-align: left; - padding: 5px 10px; - border-bottom: 1px solid #434343; + text-align: left; + padding: 5px 10px; + border-bottom: 1px solid #434343; } hr { - border: 0; - outline: none; - height: 3px; - background: transparent url("http://github.com/images/hr.gif") center center repeat-x; - margin: 0 0 20px; + border: 0; + outline: none; + height: 3px; + background: transparent url("http://github.com/images/hr.gif") center center repeat-x; + margin: 0 0 20px; } dt { - color: #F0E7D5; - font-family: 'OpenSansSemibold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; - font-weight: normal; + color: #F0E7D5; + font-family: 'OpenSansSemibold', "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: normal; } #header { - z-index: 100; - left: 0; - top: 0px; - height: 60px; - width: 100%; - position: fixed; - background: url(http://github.com/images/nav-bg.gif) #353535; - border-bottom: 4px solid #434343; - -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - -o-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + z-index: 100; + left: 0; + top: 0px; + height: 60px; + width: 100%; + position: fixed; + background: url(http://github.com/images/nav-bg.gif) #353535; + border-bottom: 4px solid #434343; + -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + -o-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); } + #header nav { - max-width: 650px; - margin: 0 auto; - padding: 0 10px; - margin: 6px auto; + max-width: 650px; + margin: 0 auto; + padding: 0 10px; + margin: 6px auto; } + #header nav li { - font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; - list-style: none; - display: inline; - color: white; - line-height: 50px; - text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.2); - font-size: 14px; + font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + list-style: none; + display: inline; + color: white; + line-height: 50px; + text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.2); + font-size: 14px; } + #header nav li a { - color: white; - border: 1px solid #5d910b; - background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #93bd20), color-stop(100%, #659e10)); - background: -webkit-linear-gradient(#93bd20, #659e10); - background: -moz-linear-gradient(#93bd20, #659e10); - background: -o-linear-gradient(#93bd20, #659e10); - background: -ms-linear-gradient(#93bd20, #659e10); - background: linear-gradient(#93bd20, #659e10); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - -o-border-radius: 2px; - -ms-border-radius: 2px; - -khtml-border-radius: 2px; - border-radius: 2px; - -moz-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); - -webkit-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); - -o-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); - box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); - background-color: #93bd20; - padding: 10px 12px; - margin-top: 6px; - line-height: 14px; - font-size: 14px; - display: inline-block; - text-align: center; + color: white; + border: 1px solid #5d910b; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #93bd20), color-stop(100%, #659e10)); + background: -webkit-linear-gradient(#93bd20, #659e10); + background: -moz-linear-gradient(#93bd20, #659e10); + background: -o-linear-gradient(#93bd20, #659e10); + background: -ms-linear-gradient(#93bd20, #659e10); + background: linear-gradient(#93bd20, #659e10); + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; + -moz-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + -webkit-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + -o-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0px 3px 7px rgba(0, 0, 0, 0.7); + background-color: #93bd20; + padding: 10px 12px; + margin-top: 6px; + line-height: 14px; + font-size: 14px; + display: inline-block; + text-align: center; } + #header nav li a:hover { - background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #749619), color-stop(100%, #527f0e)); - background: -webkit-linear-gradient(#749619, #527f0e); - background: -moz-linear-gradient(#749619, #527f0e); - background: -o-linear-gradient(#749619, #527f0e); - background: -ms-linear-gradient(#749619, #527f0e); - background: linear-gradient(#749619, #527f0e); - background-color: #659e10; - border: 1px solid #527f0e; - -moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); - -webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); - -o-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); - box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #749619), color-stop(100%, #527f0e)); + background: -webkit-linear-gradient(#749619, #527f0e); + background: -moz-linear-gradient(#749619, #527f0e); + background: -o-linear-gradient(#749619, #527f0e); + background: -ms-linear-gradient(#749619, #527f0e); + background: linear-gradient(#749619, #527f0e); + background-color: #659e10; + border: 1px solid #527f0e; + -moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + -webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + -o-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); + box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 1px 0px rgba(0, 0, 0, 0); } + #header nav li.fork { - float: left; - margin-left: 0px; + float: left; + margin-left: 0px; } + #header nav li.downloads { - float: right; - margin-left: 6px; + float: right; + margin-left: 6px; } + #header nav li.title { - float: right; - margin-right: 10px; - font-size: 11px; + float: right; + margin-right: 10px; + font-size: 11px; } section { - max-width: 650px; - padding: 30px 0px 50px 0px; - margin: 20px 0; - margin-top: 70px; + max-width: 650px; + padding: 30px 0px 50px 0px; + margin: 20px 0; + margin-top: 70px; } + section #title { - border: 0; - outline: none; - margin: 0 0 50px 0; - padding: 0 0 5px 0; + border: 0; + outline: none; + margin: 0 0 50px 0; + padding: 0 0 5px 0; } + section #title h1 { - font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; - font-size: 40px; - text-align: center; - line-height: 36px; + font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + font-size: 40px; + text-align: center; + line-height: 36px; } + section #title p { - color: #d7cfbe; - font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; - font-size: 18px; - text-align: center; + color: #d7cfbe; + font-family: 'OpenSansLight', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + font-size: 18px; + text-align: center; } + section #title .credits { - font-size: 11px; - font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; - color: #696969; - margin-top: -10px; + font-size: 11px; + font-family: 'OpenSansRegular', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + color: #696969; + margin-top: -10px; } + section #title .credits.left { - float: left; + float: left; } + section #title .credits.right { - float: right; + float: right; } @media print, screen and (max-width: 720px) { - #title .credits { - display: block; - width: 100%; - line-height: 30px; - text-align: center; - } - #title .credits .left { - float: none; - display: block; - } - #title .credits .right { - float: none; - display: block; - } + #title .credits { + display: block; + width: 100%; + line-height: 30px; + text-align: center; + } + + #title .credits .left { + float: none; + display: block; + } + + #title .credits .right { + float: none; + display: block; + } } + @media print, screen and (max-width: 480px) { - #header { - margin-top: -20px; - } + #header { + margin-top: -20px; + } - section { - margin-top: 40px; - } + section { + margin-top: 40px; + } - nav { - display: none; - } + nav { + display: none; + } } #demo { diff --git a/stylesheets/tomorrow-night.css b/stylesheets/tomorrow-night.css new file mode 100644 index 0000000..cf2c44d --- /dev/null +++ b/stylesheets/tomorrow-night.css @@ -0,0 +1,52 @@ +/* Tomorrow Night Theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +.tomorrow-comment, pre .comment, pre .title { + color: #969896; +} + +.tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { + color: #cc6666; +} + +.tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant { + color: #de935f; +} + +.tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { + color: #f0c674; +} + +.tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { + color: #b5bd68; +} + +.tomorrow-aqua, pre .css .hexcolor { + color: #8abeb7; +} + +.tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { + color: #81a2be; +} + +.tomorrow-purple, pre .keyword, pre .javascript .function { + color: #b294bb; +} + +pre code { + display: block; + background: #1d1f21; + color: #c5c8c6; + padding: 0.5em; +} + +pre .coffeescript .javascript, +pre .javascript .xml, +pre .tex .formula, +pre .xml .javascript, +pre .xml .vbscript, +pre .xml .css, +pre .xml .cdata { + opacity: 0.5; +} From e1f417afab3a4ab0fc12618668575166b1b889a7 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 18 Mar 2013 09:33:01 -0700 Subject: [PATCH 22/26] adding link to wordpress CLI article --- index.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/index.html b/index.html index bd17aa2..956dc16 100644 --- a/index.html +++ b/index.html @@ -113,6 +113,11 @@

    Tutorials

    GitHub Console - Extend the Quake Console to talk to GitHub's REST API to navigate repositories, their branches and file system + +

    Articles

    +

    License

    josh.js is licensed under the Apache 2.0 License

    From 3a945ca7de49e2faa58ea6cb9ed75161d82bd629 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Tue, 19 Mar 2013 10:59:08 -0700 Subject: [PATCH 23/26] Update index.html --- index.html | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 956dc16..58e048a 100644 --- a/index.html +++ b/index.html @@ -315,6 +315,18 @@

    + - \ No newline at end of file + From eb8a38a6c993867ebb3ae4bed9c3a790f8da5215 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Thu, 21 Mar 2013 08:20:10 -0700 Subject: [PATCH 24/26] adding google analytics --- docs/example.html | 17 ++++++++++++++++- docs/githubconsole.html | 16 +++++++++++++++- githubconsole.html | 13 +++++++++++++ helloworld.html | 13 +++++++++++++ pathhandler.html | 13 +++++++++++++ quakeconsole.html | 13 +++++++++++++ readline.html | 13 +++++++++++++ shell.html | 13 +++++++++++++ 8 files changed, 109 insertions(+), 2 deletions(-) diff --git a/docs/example.html b/docs/example.html index e677fe8..4e435dd 100644 --- a/docs/example.html +++ b/docs/example.html @@ -184,4 +184,19 @@ })(root, $, _); })(this, $, _); -
    \ No newline at end of file + + + + \ No newline at end of file diff --git a/docs/githubconsole.html b/docs/githubconsole.html index 47ae469..2f6f674 100644 --- a/docs/githubconsole.html +++ b/docs/githubconsole.html @@ -334,4 +334,18 @@ })(root, $, _); })(this, $, _); - \ No newline at end of file + + + \ No newline at end of file diff --git a/githubconsole.html b/githubconsole.html index fe81243..1cfab20 100644 --- a/githubconsole.html +++ b/githubconsole.html @@ -303,6 +303,19 @@

    Easy remote integration

    + \ No newline at end of file diff --git a/helloworld.html b/helloworld.html index 6ed5197..69dea88 100644 --- a/helloworld.html +++ b/helloworld.html @@ -187,6 +187,19 @@

    Turning it on

    + \ No newline at end of file diff --git a/pathhandler.html b/pathhandler.html index 0bd5020..0217e90 100644 --- a/pathhandler.html +++ b/pathhandler.html @@ -152,6 +152,19 @@

    Underscore

    + \ No newline at end of file diff --git a/quakeconsole.html b/quakeconsole.html index 5872154..d7f46a4 100644 --- a/quakeconsole.html +++ b/quakeconsole.html @@ -215,6 +215,19 @@

    Setup Quake-console Behavior

    + \ No newline at end of file diff --git a/readline.html b/readline.html index 8f0e115..696f888 100644 --- a/readline.html +++ b/readline.html @@ -69,6 +69,19 @@

    External Dependencies

    + \ No newline at end of file diff --git a/shell.html b/shell.html index bfe18ef..1fa9b37 100644 --- a/shell.html +++ b/shell.html @@ -107,6 +107,19 @@

    Underscore

    + \ No newline at end of file From fe902eca76e84056a1d69e6ece89d58cf55319d1 Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Thu, 15 Aug 2013 23:36:52 -0700 Subject: [PATCH 25/26] adding clickable tab to githubconsole and quakeconsole tutorials to enable activation without ~ --- githubconsole.html | 1 + javascripts/githubconsole.js | 18 ++ javascripts/quakeconsole.js | 305 ++++++++++++++++++---------------- quakeconsole.html | 107 +++++++++--- stylesheets/githubconsole.css | 32 +++- 5 files changed, 298 insertions(+), 165 deletions(-) diff --git a/githubconsole.html b/githubconsole.html index 1cfab20..a280f63 100644 --- a/githubconsole.html +++ b/githubconsole.html @@ -32,6 +32,7 @@ +
    Click or type ~ to show Console
    Github rate limit:
    diff --git a/javascripts/githubconsole.js b/javascripts/githubconsole.js index 45ffae9..f498ba9 100644 --- a/javascripts/githubconsole.js +++ b/javascripts/githubconsole.js @@ -599,6 +599,22 @@ // shown and hidden. function initializeUI() { _console.log("activating"); + + // We grab the `consoletab` and wire up hover behavior for it. + var $consoletab = $('#consoletab'); + $consoletab.hover(function() { + $consoletab.addClass('consoletab-hover'); + $consoletab.removeClass('consoletab'); + }, function() { + $consoletab.removeClass('consoletab-hover'); + $consoletab.addClass('consoletab'); + }); + + // We also wire up a click handler to show the console to the `consoletab`. + $consoletab.click(function() { + activateAndShow(); + }); + var $consolePanel = $('#shell-container'); $consolePanel.resizable({ handles: "s"}); $(document).keypress(function(event) { @@ -611,6 +627,7 @@ } }); function activateAndShow() { + $consoletab.slideUp(); _self.shell.activate(); $consolePanel.slideDown(); $consolePanel.focus(); @@ -620,6 +637,7 @@ _self.shell.deactivate(); $consolePanel.slideUp(); $consolePanel.blur(); + $consoletab.slideDown(); } _self.shell.onEOT(hideAndDeactivate); diff --git a/javascripts/quakeconsole.js b/javascripts/quakeconsole.js index c047bd8..11f4a80 100644 --- a/javascripts/quakeconsole.js +++ b/javascripts/quakeconsole.js @@ -14,148 +14,175 @@ * limitations under the License. *-------------------------------------------------------------------------*/ (function(root, $, _) { - Josh.QuakeConsole = (function(root, $, _) { - var treeroot = buildTree(); - var shell = Josh.Shell(); - var pathhandler = new Josh.PathHandler(shell); - pathhandler.current = treeroot; - pathhandler.getNode = function(path, callback) { - if(!path) { - return callback(pathhandler.current); - } - var parts = _.filter(path.split('/'), function(x) { - return x; - }); - var start = ((path || '')[0] == '/') ? treeroot : pathhandler.current; - return findNode(start, parts, callback); - }; - pathhandler.getChildNodes = function(node, callback) { - callback(node.childnodes); - }; - function findNode(current, parts, callback) { - if(!parts || parts.length == 0) { - return callback(current); - } - if(parts[0] == ".") { + Josh.QuakeConsole = (function(root, $, _) { + var treeroot = buildTree(); + var shell = Josh.Shell(); + var pathhandler = new Josh.PathHandler(shell); + pathhandler.current = treeroot; + pathhandler.getNode = function(path, callback) { + if(!path) { + return callback(pathhandler.current); + } + var parts = _.filter(path.split('/'), function(x) { + return x; + }); + var start = ((path || '')[0] == '/') ? treeroot : pathhandler.current; + return findNode(start, parts, callback); + }; + pathhandler.getChildNodes = function(node, callback) { + callback(node.childnodes); + }; + function findNode(current, parts, callback) { + if(!parts || parts.length == 0) { + return callback(current); + } + if(parts[0] == ".") { - } else if(parts[0] == "..") { - current = current.parent; - } else { - current = _.first(_.filter(current.childnodes, function(node) { - return node.name == parts[0]; - })); - } - if(!current) { - return callback(); - } - return findNode(current, _.rest(parts), callback); + } else if(parts[0] == "..") { + current = current.parent; + } else { + current = _.first(_.filter(current.childnodes, function(node) { + return node.name == parts[0]; + })); + } + if(!current) { + return callback(); + } + return findNode(current, _.rest(parts), callback); + } + + $(document).ready(function() { + + // We grab the `consoletab` and wire up hover behavior for it. + var $consoletab = $('#consoletab'); + $consoletab.hover(function() { + $consoletab.addClass('consoletab-hover'); + $consoletab.removeClass('consoletab'); + }, function() { + $consoletab.removeClass('consoletab-hover'); + $consoletab.addClass('consoletab'); + }); + + // We also wire up a click handler to show the console to the `consoletab`. + $consoletab.click(function() { + activateAndShow(); + }); + + var $consolePanel = $('#shell-panel'); + $consolePanel.resizable({ handles: "s"}); + $(document).keypress(function(event) { + if(shell.isActive()) { + return; } - $(document).ready(function() { - var $consolePanel = $('#shell-panel'); - $consolePanel.resizable({ handles: "s"}); - $(document).keypress(function(event) { - if(shell.isActive()) { - return; - } - if(event.keyCode == 126) { - event.preventDefault(); - shell.activate(); - $consolePanel.slideDown(); - $consolePanel.focus(); - } - }); - function hideAndDeactivate() { - shell.deactivate(); - $consolePanel.slideUp(); - $consolePanel.blur(); - } - shell.onEOT(hideAndDeactivate); - shell.onCancel(hideAndDeactivate); - }); - function buildTree() { - var fs = { - bin: {}, - boot: {}, - dev: {}, - etc: { - default: {}, - 'rc.d': {}, - sysconfig: {}, - x11: {} - }, - home: { - bob: { - video: { - 'firefly.m4v': {} - }, - videos: { - 'Arrested Development': { - 's1e1.m4v': {} - }, - 'Better Off Ted': { - 's1e1.m4v': {} - } - } - }, - jane: {} - }, - lib: {}, - 'lost+found': {}, - misc: {}, - mnt: { - cdrom: {}, - sysimage: {} - }, - net: {}, - opt: {}, - proc: {}, - root: {}, - sbin: {}, - usr: { - x11: {}, - bin: {}, - include: {}, - lib: {}, - local: {}, - man: {}, - sbin: {}, - share: { - doc: {} - }, - src: {} - }, - var: { - lib: {}, - lock: {}, - run: {}, - log: { - httpd: { - access_log: {}, - error_log: {} - }, - 'boot.log': {}, - cron: {}, - messages: {} - } - } - }; + if(event.keyCode == 126) { + event.preventDefault(); + activateAndShow(); + } + }); + + function activateAndShow() { + $consoletab.slideUp(); + shell.activate(); + $consolePanel.slideDown(); + $consolePanel.focus(); + + } - function build(parent, node) { - parent.childnodes = _.map(_.pairs(node), function(pair) { - var child = { - name: pair[0], - path: parent.path + "/" + pair[0], - parent: parent - }; - build(child, pair[1]); - return child; - }); - parent.children = _.keys(node); - return parent; + function hideAndDeactivate() { + shell.deactivate(); + $consolePanel.slideUp(); + $consolePanel.blur(); + $consoletab.slideDown(); + } + + shell.onEOT(hideAndDeactivate); + shell.onCancel(hideAndDeactivate); + }); + function buildTree() { + var fs = { + bin: {}, + boot: {}, + dev: {}, + etc: { + default: {}, + 'rc.d': {}, + sysconfig: {}, + x11: {} + }, + home: { + bob: { + video: { + 'firefly.m4v': {} + }, + videos: { + 'Arrested Development': { + 's1e1.m4v': {} + }, + 'Better Off Ted': { + 's1e1.m4v': {} + } } - var tree = build({name: "", path: ""}, fs); - tree.path = '/'; - return tree; + }, + jane: {} + }, + lib: {}, + 'lost+found': {}, + misc: {}, + mnt: { + cdrom: {}, + sysimage: {} + }, + net: {}, + opt: {}, + proc: {}, + root: {}, + sbin: {}, + usr: { + x11: {}, + bin: {}, + include: {}, + lib: {}, + local: {}, + man: {}, + sbin: {}, + share: { + doc: {} + }, + src: {} + }, + var: { + lib: {}, + lock: {}, + run: {}, + log: { + httpd: { + access_log: {}, + error_log: {} + }, + 'boot.log': {}, + cron: {}, + messages: {} + } } - })(root, $, _); + }; + + function build(parent, node) { + parent.childnodes = _.map(_.pairs(node), function(pair) { + var child = { + name: pair[0], + path: parent.path + "/" + pair[0], + parent: parent + }; + build(child, pair[1]); + return child; + }); + parent.children = _.keys(node); + return parent; + } + + var tree = build({name: "", path: ""}, fs); + tree.path = '/'; + return tree; + } + })(root, $, _); })(this, $, _); \ No newline at end of file diff --git a/quakeconsole.html b/quakeconsole.html index d7f46a4..069f2b8 100644 --- a/quakeconsole.html +++ b/quakeconsole.html @@ -48,11 +48,43 @@ overflow-x: hidden; overflow-y: scroll; } - #shell-cli .prompt { - font-weight: bold; - } + + #shell-cli .prompt { + font-weight: bold; + } + + #consoletab { + position: fixed; + top: -10px; + left: 35%; + font-family: 'Source Code Pro', sans-serif; + font-size: 0.8em; + color: #efefef; + background-color: #2a2a29; + border-radius: 10px; + -moz-border-radius: 4px; + padding: 10px 5px 2px 5px; + -webkit-border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; + -khtml-border-radius: 5px; + border-radius: 5px; + text-shadow: 0px 2px 0px #000; + z-index: 100000; + } + + .consoletab-hover { + border: 3px solid #aaaaaa; + opacity: 1; + } + + .consoletab { + border: 2px solid #3a3a39; + opacity: 0.7; + } +
    Click or type ~ to show Console
    Type help or hit TAB for a list of commands. Press Ctrl-C to hide the console. @@ -74,6 +106,7 @@

    Quake-style console with unix-style path handling

    Try out the Console

    +

    Type ~ to activate the shell we will be building in this tutorial.

    Hooking up PathHandler.js

    @@ -98,26 +131,35 @@

    Hooking up PathHandler.js

    these nodes, so any additional state your implementation requires can be attached to the nodes and be relied on as being part of the node when PathHandler provides one to your handler as an argument.

    -

    The pathhandler expects to be initialized with the current directory in the form pf a path node. For this - example, we've build up a full tree of nodes providing a skeleton unix file system. Our nodes take the structure of:

    +

    The pathhandler expects to be initialized with the current + directory in the form pf a path node. For this + example, we've build up a full tree of nodes providing a skeleton unix file system. Our nodes take the structure of: +

    {
         name: 'localname',
         path: '/full/path/to/localname',
         parent: {parent node},
         children: [{child nodes}]
     }
    -

    This allows the example to simply navigate up and down a tree from any node. The tree is built by the helper builtTree() - whose implementation is not of consequence to how PathHandler works and is therefore just assumed to exist, so that we can create - the tree and assign its root as pathhandler.current.

    +

    This allows the example to simply navigate up and down a tree from any node. The tree is built by the helper + builtTree() + whose implementation is not of consequence to how + PathHandler works and is therefore just assumed to exist, so that we can create + the tree and assign its root as pathhandler.current.

    var treeroot = buildTree();
     pathhandler.current = treeroot;

    Implementing PathHandler's required methods

    -

    PathHandler requires two method, getNode and getChildNodes, to be provided in order to operate.

    -

    getNode gets called with a path string. This string is completely opaque to PathHandler, - i.e. supporting constructs such as . and .. are up to the implementor. PathHandler - calls getNode anytime it has a path and needs to determine what if any node exists at that path. Thish happens +

    PathHandler requires two method, getNode and + getChildNodes, to be provided in order to operate.

    + +

    getNode gets called with a path string. This string is completely opaque to + PathHandler, + i.e. supporting constructs such as . and .. are up to the implementor. + PathHandler + calls + getNode anytime it has a path and needs to determine what if any node exists at that path. Thish happens during path completion as well as cd and ls execution. It simply provides the path and expects its callback to be called with a pathnode for that path or null. The only assumption about paths that it does have is that the path separator is /.

    @@ -133,7 +175,12 @@

    Implementing PathHandler's required methods

    return findNode(start, parts, callback); };

    For this example, no path always means the current node, otherwise we split the path into its components and walk the tree - via a helper findNode from either the root or the current node depending on whether the path started with a /. findNode is specific to this implementation, since it can work on an in memory tree. In a service bound implementation the findNode logic would likely reside at the server and the callback called in the completion closure of an ajax call.

    + via a helper + findNode from either the root or the current node depending on whether the path started with a + /. + findNode is specific to this implementation, since it can work on an in memory tree. In a service bound implementation the + findNode logic would likely reside at the server and the callback called in the completion closure of an ajax call. +

    function findNode(current, parts, callback) {
       if(!parts || parts.length == 0) {
         return callback(current);
    @@ -157,7 +204,8 @@ 

    Implementing PathHandler's required methods

    completion candidates. Path completion first determines the nearest resolvable node for the given path. It does this by first calling getNode on the current path and failing to get a node, looking for the nearest tail / to find a parent and use the trailing characters as the partial path to be completed against children - found via getChildNodes. For our example, we've attached the child node objects directly to the pathnode + found via + getChildNodes. For our example, we've attached the child node objects directly to the pathnode object, so we can simply return it. Usually this would be used to call the server with the provided node's path or id so that the appropriate children could be retrieved.

    @@ -167,10 +215,12 @@

    Implementing PathHandler's required methods

    Setup Quake-console Behavior

    -

    The default name for the div the shell uses as its container is shell-panel, although that can be changed via +

    The default name for the div the shell uses as its container is + shell-panel, although that can be changed via the shell config parameter shell-panel-id. The Josh.Shell display model is based on a panel that defines the viewport of the console screen while the content is appended to a - view that is contained inside the panel and continuously scrolled down. For the quake-style console, + view that is contained inside the panel and continuously scrolled down. For the + quake-style console, we want the panel to take up the width of the browser and overlay the page's top portion. For this we add the panel right after the body tag:

    <div id="shell-panel">
    @@ -180,15 +230,18 @@ 

    Setup Quake-console Behavior

    <div id="shell-view"></div> </div>

    With css, we make sure this is initially invisible, is fixed in top position and has a high z-index so that it will - always be on top.

    + always be on top.

    -

    We use jquery-ui's resizable so that the shell can be resized by dragging its bottom edge.

    +

    We use jquery-ui's + resizable so that the shell can be resized by dragging its bottom edge.

    var $consolePanel = $('#shell-panel');
     $consolePanel.resizable({ handles: "s"});
    -

    Next, we wire up a the keypress handler for shell activation, since Josh.ReadLine does not listen to keys - until the shell is activated. This handler will only execute while the shell is inactive and trigger on ~, - using jquery animaton to slide it down and give it focus.

    +

    Next, we wire up a the keypress handler for shell activation, since + Josh.ReadLine does not listen to keys + until the shell is activated. This handler will only execute while the shell is inactive and trigger on + ~, + using jquery animaton to slide it down and give it focus.

    $(document).keypress(function(event) {
       if(shell.isActive()) {
         return;
    @@ -201,7 +254,8 @@ 

    Setup Quake-console Behavior

    } });
    -

    Finally, we wire create a function to deactivate the shell, slide it back up and hide it and attach it to the shell's EOT (Ctrl-D on empty line) or a Cancel (Ctrl-C) signals: +

    Finally, we wire create a function to deactivate the shell, slide it back up and hide it and attach it to the shell's + EOT (Ctrl-D on empty line) or a Cancel (Ctrl-C) signals: we deactivate the shell and hide the console.

    function hideAndDeactivate() {
       shell.deactivate();
    @@ -210,7 +264,7 @@ 

    Setup Quake-console Behavior

    } shell.onEOT(hideAndDeactivate); shell.onCancel(hideAndDeactivate);
    -

    Now the Shell is ready to be activated and it's faked unix file system browsed, all with minimal custom code.

    +

    Now the Shell is ready to be activated and it's faked unix file system browsed, all with minimal custom code.