Move coloring for "model commands" to "keyword" and not "function"

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -238,13 +238,6 @@
     'match': '\\b(form(at|a)?)\\s*([A-Za-z_][A-Za-z0-9_]{0,31})*\\s*(%)(\-)?(0)?([0-9]+)(\.)([0-9]+)(e|f|g)(c)?'
     'captures':
       '1': 'keyword.functions.data.stata.test'
-  }
-  {
-    "captures":
-      "1":
-        "name": "support.function.models.stata"
-    "comment": "model commands."
-    "match": "\\b(anova|xtmixed|regress|ivregress|xtreg|xtreg_be|xtreg_fe|xtreg_ml|xtreg_pa_p|xtreg_re|xtregar|xtrere_p|xtset|xtsf_ll|xtsf_llti|xtsum|xttab|xttest0|xttobit|xttobit_p|xttrans)\\b"
   }
   {
     'comment': ' If you put braces following the if or else, (same with foreach, etc)
@@ -593,7 +586,7 @@
     'patterns': [
       {
         'comment': 'generic keywords that alter flow. Without disctintion. We can separate this after, but now they will be colored'
-        'match': '\\b(about|ac|acprplot|ado|adopath|adoupdate|alpha|ameans|an|ano|anov|anova|anova_terms|anovadef|aorder|ap|app|appe|appen|append|arch|arch_dr|arch_estat|arch_p|archlm|areg|areg_p|args|arima|arima_dr|arima_estat|arima_p|asmprobit|asmprobit_estat|asmprobit_lf|asmprobit_mfx__dlg|asmprobit_p|avplot|avplots|bcskew0|bgodfrey|binreg|bip0_lf|biplot|bipp_lf|bipr_lf|bipr_p|biprobit|bitest|bitesti|bitowt|blogit|bmemsize|boot|bootsamp|boxco_l|boxco_p|boxcox|boxcox_p|bprobit|br|break|brier|bro|brow|brows|browse|brr|brrstat|bs|bsampl_w|bsample|bsqreg|bstat|bstrap|ca|ca_estat|ca_p|cabiplot|camat|canon|canon_estat|canon_p|caprojection|cat|cc|cchart|cci|cd|censobs_table|centile|cf|char|chdir|checkdlgfiles|checkestimationsample|checkhlpfiles|checksum|chelp|ci|cii|cl|class|classutil|clear|cli|clis|clist|clog|clog_lf|clog_p|clogi|clogi_sw|clogit|clogit_lf|clogit_p|clogitp|clogl_sw|cloglog|clonevar|clslistarray|cluster|cluster_measures|cluster_stop|cluster_tree|cluster_tree_8|clustermat|cmdlog|cnr|cnre|cnreg|cnreg_p|cnreg_sw|cnsreg|codebook|collaps4|collapse|colormult_nb|colormult_nw|compare|compress|conf|confi|confir|confirm|conren|cons|const|constr|constra|constrai|constrain|constraint|contract|copy|copyright|copysource|cor|corc|corr|corr2data|corr_anti|corr_kmo|corr_smc|corre|correl|correla|correlat|correlate|corrgram|cou|coun|count|cprplot|crc|cret|cretu|cretur|creturn|cross|cs|cscript|cscript_log|csi|ct|ct_is|ctset|ctst_st|cttost|cumsp|cumul|cusum|cutil|d|datasig|datasign|datasigna|datasignat|datasignatu|datasignatur|datasignature|datetof|db|dbeta|de|dec|deco|decod|decode|deff|des|desc|descr|descri|describ|describe|dfbeta|dfgls|dfuller|di|di_g|dir|dirstats|dis|discard|disp|disp_res|disp_s|displ|displa|display|do|doe|doed|doedi|doedit|dotplot|dprobit|drawnorm|ds|ds_util|dstdize|duplicates|durbina|dwstat|dydx|ed|edi|edit|eivreg|emdef|en|enc|enco|encod|encode|eq|erase|ereg|ereg_lf|ereg_p|ereg_sw|ereghet|ereghet_glf|ereghet_glf_sh|ereghet_gp|ereghet_ilf|ereghet_ilf_sh|ereghet_ip|eret|eretu|eretur|ereturn|err|erro|error|est|est_cfexist|est_cfname|est_clickable|est_expand|est_hold|est_table|est_unhold|est_unholdok|estat|estat_default|estat_summ|estat_vce_only|esti|estimates|etodow|etof|etomdy|expand|expandcl|fac|fact|facto|factor|factor_estat|factor_p|factor_pca_rotated|factor_rotate|factormat|fcast|fcast_compute|fcast_graph|fdades|fdadesc|fdadescr|fdadescri|fdadescrib|fdadescribe|fdasav|fdasave|fdause|fh_st|file|filefilter|fillin|find_hlp_file|findfile|findit|fit|fl|fli|flis|flist|fpredict|frac_adj|frac_chk|frac_cox|frac_ddp|frac_dis|frac_dv|frac_in|frac_mun|frac_pp|frac_pq|frac_pv|frac_wgt|frac_xo|fracgen|fracplot|fracpoly|fracpred|fron_ex|fron_hn|fron_p|fron_tn|fron_tn2|frontier|ftodate|ftoe|ftomdy|ftowdate|g|gamhet_glf|gamhet_gp|gamhet_ilf|gamhet_ip|gamma|gamma_d2|gamma_p|gamma_sw|gammahet|gdi_hexagon|gdi_spokes|genrank|genstd|genvmean|gettoken|gladder|glim_l01|glim_l02|glim_l03|glim_l04|glim_l05|glim_l06|glim_l07|glim_l08|glim_l09|glim_l10|glim_l11|glim_l12|glim_lf|glim_mu|glim_nw1|glim_nw2|glim_nw3|glim_p|glim_v1|glim_v2|glim_v3|glim_v4|glim_v5|glim_v6|glim_v7|glm|glm_p|glm_sw|glmpred|glogit|glogit_p|gmeans|gnbre_lf|gnbreg|gnbreg_p|gomp_lf|gompe_sw|gomper_p|gompertz|gompertzhet|gomphet_glf|gomphet_glf_sh|gomphet_gp|gomphet_ilf|gomphet_ilf_sh|gomphet_ip|gphdot|gphpen|gphprint|gprefs|gprobi_p|gprobit|gr|gr7|gr_copy|gr_current|gr_db|gr_describe|gr_dir|gr_draw|gr_draw_replay|gr_drop|gr_edit|gr_editviewopts|gr_example|gr_example2|gr_export|gr_print|gr_qscheme|gr_query|gr_read|gr_rename|gr_replay|gr_save|gr_set|gr_setscheme|gr_table|gr_undo|gr_use|graph|grebar|greigen|grmeanby|gs_fileinfo|gs_filetype|gs_graphinfo|gs_stat|gsort|gwood|h|hareg|hausman|haver|he|heck_d2|heckma_p|heckman|heckp_lf|heckpr_p|heckprob|hel|help|hereg|hetpr_lf|hetpr_p|hetprob|hettest|hexdump|hilite|hist|histogram|hlogit|hlu|hmeans|hotel|hotelling|hprobit|hreg|hsearch|icd9|icd9_ff|icd9p|iis|impute|imtest|inbase|include|inf|infi|infil|infile|infix|inp|inpu|input|ins|insheet|insp|inspe|inspec|inspect|integ|inten|intreg|intreg_p|intrg2_ll|intrg_ll|intrg_ll2|ipolate|iqreg|ir|irf|irf_create|irfm|iri|is_svy|is_svysum|isid|istdize|ivprobit|ivprobit_p|ivreg|ivreg_footnote|ivtob_lf|ivtobit|ivtobit_p|jacknife|jknife|jkstat|joinby|kalarma1|kap|kapmeier|kappa|kapwgt|kdensity|ksm|ksmirnov|ktau|kwallis|labelbook|ladder|levelsof|leverage|lfit|lfit_p|li|lincom|line|linktest|lis|list|lloghet_glf|lloghet_glf_sh|lloghet_gp|lloghet_ilf|lloghet_ilf_sh|lloghet_ip|llogi_sw|llogis_p|llogist|llogistic|llogistichet|lnorm_lf|lnorm_sw|lnorma_p|lnormal|lnormalhet|lnormhet_glf|lnormhet_glf_sh|lnormhet_gp|lnormhet_ilf|lnormhet_ilf_sh|lnormhet_ip|lnskew0|loadingplot|(?<!\\.)log|logi|logis_lf|logistic|logistic_p|logit|logit_estat|logit_p|loglogs|logrank|loneway|lookfor|lookup|lowess|lpredict|lrecomp|lroc|lrtest|ls|lsens|lsens_x|lstat|ltable|ltriang|lv|lvr2plot|m|ma|mac|macr|macro|makecns|man|manova|manovatest|mantel|mark|markin|markout|marksample|mat|mat_capp|mat_order|mat_put_rr|mat_rapp|mata|mata_clear|mata_describe|mata_drop|mata_matdescribe|mata_matsave|mata_matuse|mata_memory|mata_mlib|mata_mosave|mata_rename|mata_which|matalabel|matcproc|matlist|matname|matr|matri|matrix|matrix_input__dlg|matstrik|mcc|mcci|md0_|md1_|md1debug_|md2_|md2debug_|mds|mds_estat|mds_p|mdsconfig|mdslong|mdsmat|mdsshepard|mdytoe|mdytof|me_derd|mean|means|median|memory|memsize|mfp|mfx|mhelp|mhodds|minbound|mixed_ll|mixed_ll_reparm|mkassert|mkdir|mkmat|mkspline|ml|ml_adjs|ml_bhhhs|ml_c_d|ml_check|ml_clear|ml_cnt|ml_debug|ml_defd|ml_e0|ml_e0_bfgs|ml_e0_cycle|ml_e0_dfp|ml_e0i|ml_e1|ml_e1_bfgs|ml_e1_bhhh|ml_e1_cycle|ml_e1_dfp|ml_e2|ml_e2_cycle|ml_ebfg0|ml_ebfr0|ml_ebfr1|ml_ebh0q|ml_ebhh0|ml_ebhr0|ml_ebr0i|ml_ecr0i|ml_edfp0|ml_edfr0|ml_edfr1|ml_edr0i|ml_eds|ml_eer0i|ml_egr0i|ml_elf|ml_elf_bfgs|ml_elf_bhhh|ml_elf_cycle|ml_elf_dfp|ml_elfi|ml_elfs|ml_enr0i|ml_enrr0|ml_erdu0|ml_erdu0_bfgs|ml_erdu0_bhhh|ml_erdu0_bhhhq|ml_erdu0_cycle|ml_erdu0_dfp|ml_erdu0_nrbfgs|ml_exde|ml_footnote|ml_geqnr|ml_grad0|ml_graph|ml_hbhhh|ml_hd0|ml_hold|ml_init|ml_inv|ml_log|ml_max|ml_mlout|ml_mlout_8|ml_model|ml_nb0|ml_opt|ml_p|ml_plot|ml_query|ml_rdgrd|ml_repor|ml_s_e|ml_score|ml_searc|ml_technique|ml_unhold|mleval|mlf_|mlmatbysum|mlmatsum|mlog|mlogi|mlogit|mlogit_footnote|mlogit_p|mlopts|mlsum|mlvecsum|mnl0_|mor|more|mov|move|mprobit|mprobit_lf|mprobit_p|mrdu0_|mrdu1_|mvdecode|mvencode|mvreg|mvreg_estat|nbreg|nbreg_al|nbreg_lf|nbreg_p|nbreg_sw|nestreg|net|newey|newey_p|news|nl|nlcom|nlcom_p|nlexp2|nlexp2a|nlexp3|nlgom3|nlgom4|nlinit|nllog3|nllog4|nlog_rd|nlogit|nlogit_p|nlogitgen|nlogittree|nlpred|nobreak|notes_dlg|nptrend|numlabel|numlist|odbc|old_ver|olo|olog|ologi|ologi_sw|ologit|ologit_p|ologitp|on|one|onew|onewa|oneway|op_colnm|op_comp|op_diff|op_inv|op_str|opr|opro|oprob|oprob_sw|oprobi|oprobi_p|oprobit|oprobitp|opts_exclusive|order|orthog|orthpoly|ou|out|outf|outfi|outfil|outfile|outs|outsh|outshe|outshee|outsheet|ovtest|pac|palette|parse_dissim|pause|pca|pca_display|pca_estat|pca_p|pca_rotate|pcamat|pchart|pchi|pcorr|pctile|pentium|pergram|personal|peto_st|pkcollapse|pkcross|pkequiv|pkexamine|pkshape|pksumm|plugin|pnorm|poisgof|poiss_lf|poiss_sw|poisso_p|poisson|poisson_estat|post|postclose|postfile|postutil|pperron|prais|prais_e|prais_e2|prais_p|predict|predictnl|preserve|print|prob|probi|probit|probit_estat|probit_p|proc_time|procoverlay|procrustes|procrustes_estat|procrustes_p|profiler|prop|proportion|prtest|prtesti|pwcorr|pwd|q\s|qby|qbys|qchi|qladder|qnorm|qqplot|qreg|qreg_c|qreg_p|qreg_sw|qu|quadchk|quantile|que|quer|query|range|ranksum|ratio|rchart|rcof|recast|recode|reg|reg3|reg3_p|regdw|regr|regre|regre_p2|regres|regres_p|regress|regress_estat|regriv_p|remap|ren|rena|renam|rename|renpfix|repeat|reshape|restore|ret|retu|retur|return|rmdir|robvar|roccomp|rocf_lf|rocfit|rocgold|rocplot|roctab|rologit|rologit_p|rot|rota|rotat|rotate|rotatemat|rreg|rreg_p|ru|run|runtest|rvfplot|rvpplot|safesum|sample|sampsi|savedresults|sc|scatter|scm_mine|sco|scob_lf|scob_p|scobi_sw|scobit|scor|score|scoreplot|scoreplot_help|scree|screeplot|screeplot_help|sdtest|sdtesti|se|search|separate|seperate|serrbar|serset|set|set_defaults|sfrancia|sh|she|shel|shell|shewhart|signestimationsample|signrank|signtest|simul|sktest|sleep|slogit|slogit_d2|slogit_p|smooth|snapspan|so|sor|sort|spearman|spikeplot|spikeplt|spline_x|split|sqreg|sqreg_p|sret|sretu|sretur|sreturn|ssc|st|st_ct|st_hc|st_hcd|st_hcd_sh|st_is|st_issys|st_note|st_promo|st_set|st_show|st_smpl|st_subid|stack|stbase|stci|stcox|stcox_estat|stcox_fr|stcox_fr_ll|stcox_p|stcox_sw|stcoxkm|stcstat|stcurv|stcurve|stdes|stem|stepwise|stfill|stgen|stir|stjoin|stmc|stmh|stphplot|stphtest|stptime|strate|streg|streg_sw|streset|sts|stset|stsplit|stsum|sttocc|sttoct|stvary|su|suest|sum|summ|summa|summar|summari|summariz|summarize|sunflower|sureg|survcurv|survsum|svar|svar_p|svmat|svy_disp|svy_dreg|svy_est|svy_est_7|svy_estat|svy_get|svy_gnbreg_p|svy_head|svy_header|svy_heckman_p|svy_heckprob_p|svy_intreg_p|svy_ivreg_p|svy_logistic_p|svy_logit_p|svy_mlogit_p|svy_nbreg_p|svy_ologit_p|svy_oprobit_p|svy_poisson_p|svy_probit_p|svy_regress_p|svy_sub|svy_sub_7|svy_x|svy_x_7|svy_x_p|svydes|svygen|svygnbreg|svyheckman|svyheckprob|svyintreg|svyintrg|svyivreg|svylc|svylog_p|svylogit|svymarkout|svymean|svymlog|svymlogit|svynbreg|svyolog|svyologit|svyoprob|svyoprobit|svyopts|svypois|svypoisson|svyprobit|svyprobt|svyprop|svyratio|svyreg|svyreg_p|svyregress|svyset|svytab|svytest|svytotal|sw|swilk|symmetry|symmi|symplot|sysdescribe|sysdir|sysuse|szroeter|ta|tab|tab1|tab2|tab_or|tabd|tabdi|tabdis|tabdisp|tabi|table|tabodds|tabstat|tabu|tabul|tabula|tabulat|tabulate|te|tes|test|testnl|testparm|teststd|tetrachoric|time_it|timer|tis|tob|tobi|tobit|tobit_p|tobit_sw|token|tokeni|tokeniz|tokenize|total|translate|translator|transmap|treat_ll|treatr_p|treatreg|trim|trnb_cons|trnb_mean|trpoiss_d2|trunc_ll|truncr_p|truncreg|tsappend|tset|tsfill|tsline|tsline_ex|tsreport|tsrevar|tsrline|tsset|tssmooth|tsunab|ttest|ttesti|tut_chk|tut_wait|tutorial|tw|tware_st|two|twoway|twoway__fpfit_serset|twoway__function_gen|twoway__histogram_gen|twoway__ipoint_serset|twoway__ipoints_serset|twoway__kdensity_gen|twoway__lfit_serset|twoway__normgen_gen|twoway__pci_serset|twoway__qfit_serset|twoway__scatteri_serset|twoway__sunflower_gen|twoway_ksm_serset|ty|typ|type|typeof|unab|unabbrev|unabcmd|update|uselabel|var|var_mkcompanion|var_p|varbasic|varfcast|vargranger|varirf|varirf_add|varirf_cgraph|varirf_create|varirf_ctable|varirf_describe|varirf_dir|varirf_drop|varirf_erase|varirf_graph|varirf_ograph|varirf_rename|varirf_set|varirf_table|varlmar|varnorm|varsoc|varstable|varstable_w|varstable_w2|varwle|vec|vec_fevd|vec_mkphi|vec_p|vec_p_w|vecirf_create|veclmar|veclmar_w|vecnorm|vecnorm_w|vecrank|vecstable|verinst|vers|versi|versio|version|view|viewsource|vif|vwls|wdatetof|webdescribe|webseek|webuse|wh|whelp|whi|which|wilc_st|wilcoxon|win|wind|windo|window|winexec|wntestb|wntestq|xchart|xcorr|xi|xmlsav|xmlsave|xmluse|xpose|xsh|xshe|xshel|xshell|xt_iis|xt_tis|xtab_p|xtabond|xtbin_p|xtclog|xtcloglog|xtcloglog_d2|xtcloglog_pa_p|xtcloglog_re_p|xtcnt_p|xtcorr|xtdata|xtdes|xtfront_p|xtfrontier|xtgee|xtgee_elink|xtgee_estat|xtgee_makeivar|xtgee_p|xtgee_plink|xtgls|xtgls_p|xthaus|xthausman|xtht_p|xthtaylor|xtile|xtint_p|xtintreg|xtintreg_d2|xtintreg_p|xtivreg|xtline|xtline_ex|xtlogit|xtlogit_d2|xtlogit_fe_p|xtlogit_pa_p|xtlogit_re_p|xtmixed|xtmixed_estat|xtmixed_p|xtnb_fe|xtnb_lf|xtnbreg|xtnbreg_pa_p|xtnbreg_refe_p|xtpcse|xtpcse_p|xtpois|xtpoisson|xtpoisson_d2|xtpoisson_pa_p|xtpoisson_refe_p|xtpred|xtprobit|xtprobit_d2|xtprobit_re_p|xtps_fe|xtps_lf|xtps_ren|xtps_ren_8|xtrar_p|xtrc|xtrc_p|xtrchh|xtrefe_p|yx|yxview__barlike_draw|yxview_area_draw|yxview_bar_draw|yxview_dot_draw|yxview_dropline_draw|yxview_function_draw|yxview_iarrow_draw|yxview_ilabels_draw|yxview_normal_draw|yxview_pcarrow_draw|yxview_pcbarrow_draw|yxview_pccapsym_draw|yxview_pcscatter_draw|yxview_pcspike_draw|yxview_rarea_draw|yxview_rbar_draw|yxview_rbarm_draw|yxview_rcap_draw|yxview_rcapsym_draw|yxview_rconnected_draw|yxview_rline_draw|yxview_rscatter_draw|yxview_rspike_draw|yxview_spike_draw|yxview_sunflower_draw|zap_s|zinb|zinb_llf|zinb_plf|zip|zip_llf|zip_p|zip_plf|zt_ct_5|zt_hc_5|zt_hcd_5|zt_is_5|zt_iss_5|zt_sho_5|zt_smp_5|ztnb|ztnb_p|ztp|ztp_p|prtab|prchange|eststo|estout|esttab|estadd|estpost)\\b'
+        'match': '\\b(about|ac|acprplot|ado|adopath|adoupdate|alpha|ameans|an|ano|anov|anova|anova_terms|anovadef|aorder|ap|app|appe|appen|append|arch|arch_dr|arch_estat|arch_p|archlm|areg|areg_p|args|arima|arima_dr|arima_estat|arima_p|asmprobit|asmprobit_estat|asmprobit_lf|asmprobit_mfx__dlg|asmprobit_p|avplot|avplots|bcskew0|bgodfrey|binreg|bip0_lf|biplot|bipp_lf|bipr_lf|bipr_p|biprobit|bitest|bitesti|bitowt|blogit|bmemsize|boot|bootsamp|boxco_l|boxco_p|boxcox|boxcox_p|bprobit|br|break|brier|bro|brow|brows|browse|brr|brrstat|bs|bsampl_w|bsample|bsqreg|bstat|bstrap|ca|ca_estat|ca_p|cabiplot|camat|canon|canon_estat|canon_p|caprojection|cat|cc|cchart|cci|cd|censobs_table|centile|cf|char|chdir|checkdlgfiles|checkestimationsample|checkhlpfiles|checksum|chelp|ci|cii|cl|class|classutil|clear|cli|clis|clist|clog|clog_lf|clog_p|clogi|clogi_sw|clogit|clogit_lf|clogit_p|clogitp|clogl_sw|cloglog|clonevar|clslistarray|cluster|cluster_measures|cluster_stop|cluster_tree|cluster_tree_8|clustermat|cmdlog|cnr|cnre|cnreg|cnreg_p|cnreg_sw|cnsreg|codebook|collaps4|collapse|colormult_nb|colormult_nw|compare|compress|conf|confi|confir|confirm|conren|cons|const|constr|constra|constrai|constrain|constraint|contract|copy|copyright|copysource|cor|corc|corr|corr2data|corr_anti|corr_kmo|corr_smc|corre|correl|correla|correlat|correlate|corrgram|cou|coun|count|cprplot|crc|cret|cretu|cretur|creturn|cross|cs|cscript|cscript_log|csi|ct|ct_is|ctset|ctst_st|cttost|cumsp|cumul|cusum|cutil|d|datasig|datasign|datasigna|datasignat|datasignatu|datasignatur|datasignature|datetof|db|dbeta|de|dec|deco|decod|decode|deff|des|desc|descr|descri|describ|describe|dfbeta|dfgls|dfuller|di|di_g|dir|dirstats|dis|discard|disp|disp_res|disp_s|displ|displa|display|do|doe|doed|doedi|doedit|dotplot|dprobit|drawnorm|ds|ds_util|dstdize|duplicates|durbina|dwstat|dydx|ed|edi|edit|eivreg|emdef|en|enc|enco|encod|encode|eq|erase|ereg|ereg_lf|ereg_p|ereg_sw|ereghet|ereghet_glf|ereghet_glf_sh|ereghet_gp|ereghet_ilf|ereghet_ilf_sh|ereghet_ip|eret|eretu|eretur|ereturn|err|erro|error|est|est_cfexist|est_cfname|est_clickable|est_expand|est_hold|est_table|est_unhold|est_unholdok|estat|estat_default|estat_summ|estat_vce_only|esti|estimates|etodow|etof|etomdy|expand|expandcl|fac|fact|facto|factor|factor_estat|factor_p|factor_pca_rotated|factor_rotate|factormat|fcast|fcast_compute|fcast_graph|fdades|fdadesc|fdadescr|fdadescri|fdadescrib|fdadescribe|fdasav|fdasave|fdause|fh_st|file|filefilter|fillin|find_hlp_file|findfile|findit|fit|fl|fli|flis|flist|fpredict|frac_adj|frac_chk|frac_cox|frac_ddp|frac_dis|frac_dv|frac_in|frac_mun|frac_pp|frac_pq|frac_pv|frac_wgt|frac_xo|fracgen|fracplot|fracpoly|fracpred|fron_ex|fron_hn|fron_p|fron_tn|fron_tn2|frontier|ftodate|ftoe|ftomdy|ftowdate|g|gamhet_glf|gamhet_gp|gamhet_ilf|gamhet_ip|gamma|gamma_d2|gamma_p|gamma_sw|gammahet|gdi_hexagon|gdi_spokes|genrank|genstd|genvmean|gettoken|gladder|glim_l01|glim_l02|glim_l03|glim_l04|glim_l05|glim_l06|glim_l07|glim_l08|glim_l09|glim_l10|glim_l11|glim_l12|glim_lf|glim_mu|glim_nw1|glim_nw2|glim_nw3|glim_p|glim_v1|glim_v2|glim_v3|glim_v4|glim_v5|glim_v6|glim_v7|glm|glm_p|glm_sw|glmpred|glogit|glogit_p|gmeans|gnbre_lf|gnbreg|gnbreg_p|gomp_lf|gompe_sw|gomper_p|gompertz|gompertzhet|gomphet_glf|gomphet_glf_sh|gomphet_gp|gomphet_ilf|gomphet_ilf_sh|gomphet_ip|gphdot|gphpen|gphprint|gprefs|gprobi_p|gprobit|gr|gr7|gr_copy|gr_current|gr_db|gr_describe|gr_dir|gr_draw|gr_draw_replay|gr_drop|gr_edit|gr_editviewopts|gr_example|gr_example2|gr_export|gr_print|gr_qscheme|gr_query|gr_read|gr_rename|gr_replay|gr_save|gr_set|gr_setscheme|gr_table|gr_undo|gr_use|graph|grebar|greigen|grmeanby|gs_fileinfo|gs_filetype|gs_graphinfo|gs_stat|gsort|gwood|h|hareg|hausman|haver|he|heck_d2|heckma_p|heckman|heckp_lf|heckpr_p|heckprob|hel|help|hereg|hetpr_lf|hetpr_p|hetprob|hettest|hexdump|hilite|hist|histogram|hlogit|hlu|hmeans|hotel|hotelling|hprobit|hreg|hsearch|icd9|icd9_ff|icd9p|iis|impute|imtest|inbase|include|inf|infi|infil|infile|infix|inp|inpu|input|ins|insheet|insp|inspe|inspec|inspect|integ|inten|intreg|intreg_p|intrg2_ll|intrg_ll|intrg_ll2|ipolate|iqreg|ir|irf|irf_create|irfm|iri|is_svy|is_svysum|isid|istdize|ivprobit|ivprobit_p|ivreg|ivreg_footnote|ivtob_lf|ivtobit|ivtobit_p|jacknife|jknife|jkstat|joinby|kalarma1|kap|kapmeier|kappa|kapwgt|kdensity|ksm|ksmirnov|ktau|kwallis|labelbook|ladder|levelsof|leverage|lfit|lfit_p|li|lincom|line|linktest|lis|list|lloghet_glf|lloghet_glf_sh|lloghet_gp|lloghet_ilf|lloghet_ilf_sh|lloghet_ip|llogi_sw|llogis_p|llogist|llogistic|llogistichet|lnorm_lf|lnorm_sw|lnorma_p|lnormal|lnormalhet|lnormhet_glf|lnormhet_glf_sh|lnormhet_gp|lnormhet_ilf|lnormhet_ilf_sh|lnormhet_ip|lnskew0|loadingplot|(?<!\\.)log|logi|logis_lf|logistic|logistic_p|logit|logit_estat|logit_p|loglogs|logrank|loneway|lookfor|lookup|lowess|lpredict|lrecomp|lroc|lrtest|ls|lsens|lsens_x|lstat|ltable|ltriang|lv|lvr2plot|m|ma|mac|macr|macro|makecns|man|manova|manovatest|mantel|mark|markin|markout|marksample|mat|mat_capp|mat_order|mat_put_rr|mat_rapp|mata|mata_clear|mata_describe|mata_drop|mata_matdescribe|mata_matsave|mata_matuse|mata_memory|mata_mlib|mata_mosave|mata_rename|mata_which|matalabel|matcproc|matlist|matname|matr|matri|matrix|matrix_input__dlg|matstrik|mcc|mcci|md0_|md1_|md1debug_|md2_|md2debug_|mds|mds_estat|mds_p|mdsconfig|mdslong|mdsmat|mdsshepard|mdytoe|mdytof|me_derd|mean|means|median|memory|memsize|mfp|mfx|mhelp|mhodds|minbound|mixed_ll|mixed_ll_reparm|mkassert|mkdir|mkmat|mkspline|ml|ml_adjs|ml_bhhhs|ml_c_d|ml_check|ml_clear|ml_cnt|ml_debug|ml_defd|ml_e0|ml_e0_bfgs|ml_e0_cycle|ml_e0_dfp|ml_e0i|ml_e1|ml_e1_bfgs|ml_e1_bhhh|ml_e1_cycle|ml_e1_dfp|ml_e2|ml_e2_cycle|ml_ebfg0|ml_ebfr0|ml_ebfr1|ml_ebh0q|ml_ebhh0|ml_ebhr0|ml_ebr0i|ml_ecr0i|ml_edfp0|ml_edfr0|ml_edfr1|ml_edr0i|ml_eds|ml_eer0i|ml_egr0i|ml_elf|ml_elf_bfgs|ml_elf_bhhh|ml_elf_cycle|ml_elf_dfp|ml_elfi|ml_elfs|ml_enr0i|ml_enrr0|ml_erdu0|ml_erdu0_bfgs|ml_erdu0_bhhh|ml_erdu0_bhhhq|ml_erdu0_cycle|ml_erdu0_dfp|ml_erdu0_nrbfgs|ml_exde|ml_footnote|ml_geqnr|ml_grad0|ml_graph|ml_hbhhh|ml_hd0|ml_hold|ml_init|ml_inv|ml_log|ml_max|ml_mlout|ml_mlout_8|ml_model|ml_nb0|ml_opt|ml_p|ml_plot|ml_query|ml_rdgrd|ml_repor|ml_s_e|ml_score|ml_searc|ml_technique|ml_unhold|mleval|mlf_|mlmatbysum|mlmatsum|mlog|mlogi|mlogit|mlogit_footnote|mlogit_p|mlopts|mlsum|mlvecsum|mnl0_|mor|more|mov|move|mprobit|mprobit_lf|mprobit_p|mrdu0_|mrdu1_|mvdecode|mvencode|mvreg|mvreg_estat|nbreg|nbreg_al|nbreg_lf|nbreg_p|nbreg_sw|nestreg|net|newey|newey_p|news|nl|nlcom|nlcom_p|nlexp2|nlexp2a|nlexp3|nlgom3|nlgom4|nlinit|nllog3|nllog4|nlog_rd|nlogit|nlogit_p|nlogitgen|nlogittree|nlpred|nobreak|notes_dlg|nptrend|numlabel|numlist|odbc|old_ver|olo|olog|ologi|ologi_sw|ologit|ologit_p|ologitp|on|one|onew|onewa|oneway|op_colnm|op_comp|op_diff|op_inv|op_str|opr|opro|oprob|oprob_sw|oprobi|oprobi_p|oprobit|oprobitp|opts_exclusive|order|orthog|orthpoly|ou|out|outf|outfi|outfil|outfile|outs|outsh|outshe|outshee|outsheet|ovtest|pac|palette|parse_dissim|pause|pca|pca_display|pca_estat|pca_p|pca_rotate|pcamat|pchart|pchi|pcorr|pctile|pentium|pergram|personal|peto_st|pkcollapse|pkcross|pkequiv|pkexamine|pkshape|pksumm|plugin|pnorm|poisgof|poiss_lf|poiss_sw|poisso_p|poisson|poisson_estat|post|postclose|postfile|postutil|pperron|prais|prais_e|prais_e2|prais_p|predict|predictnl|preserve|print|prob|probi|probit|probit_estat|probit_p|proc_time|procoverlay|procrustes|procrustes_estat|procrustes_p|profiler|prop|proportion|prtest|prtesti|pwcorr|pwd|q\s|qby|qbys|qchi|qladder|qnorm|qqplot|qreg|qreg_c|qreg_p|qreg_sw|qu|quadchk|quantile|que|quer|query|range|ranksum|ratio|rchart|rcof|recast|recode|reg|reg3|reg3_p|regdw|regr|regre|regre_p2|regres|regres_p|regress|regress_estat|regriv_p|remap|ren|rena|renam|rename|renpfix|repeat|reshape|restore|ret|retu|retur|return|rmdir|robvar|roccomp|rocf_lf|rocfit|rocgold|rocplot|roctab|rologit|rologit_p|rot|rota|rotat|rotate|rotatemat|rreg|rreg_p|ru|run|runtest|rvfplot|rvpplot|safesum|sample|sampsi|savedresults|sc|scatter|scm_mine|sco|scob_lf|scob_p|scobi_sw|scobit|scor|score|scoreplot|scoreplot_help|scree|screeplot|screeplot_help|sdtest|sdtesti|se|search|separate|seperate|serrbar|serset|set|set_defaults|sfrancia|sh|she|shel|shell|shewhart|signestimationsample|signrank|signtest|simul|sktest|sleep|slogit|slogit_d2|slogit_p|smooth|snapspan|so|sor|sort|spearman|spikeplot|spikeplt|spline_x|split|sqreg|sqreg_p|sret|sretu|sretur|sreturn|ssc|st|st_ct|st_hc|st_hcd|st_hcd_sh|st_is|st_issys|st_note|st_promo|st_set|st_show|st_smpl|st_subid|stack|stbase|stci|stcox|stcox_estat|stcox_fr|stcox_fr_ll|stcox_p|stcox_sw|stcoxkm|stcstat|stcurv|stcurve|stdes|stem|stepwise|stfill|stgen|stir|stjoin|stmc|stmh|stphplot|stphtest|stptime|strate|streg|streg_sw|streset|sts|stset|stsplit|stsum|sttocc|sttoct|stvary|su|suest|sum|summ|summa|summar|summari|summariz|summarize|sunflower|sureg|survcurv|survsum|svar|svar_p|svmat|svy_disp|svy_dreg|svy_est|svy_est_7|svy_estat|svy_get|svy_gnbreg_p|svy_head|svy_header|svy_heckman_p|svy_heckprob_p|svy_intreg_p|svy_ivreg_p|svy_logistic_p|svy_logit_p|svy_mlogit_p|svy_nbreg_p|svy_ologit_p|svy_oprobit_p|svy_poisson_p|svy_probit_p|svy_regress_p|svy_sub|svy_sub_7|svy_x|svy_x_7|svy_x_p|svydes|svygen|svygnbreg|svyheckman|svyheckprob|svyintreg|svyintrg|svyivreg|svylc|svylog_p|svylogit|svymarkout|svymean|svymlog|svymlogit|svynbreg|svyolog|svyologit|svyoprob|svyoprobit|svyopts|svypois|svypoisson|svyprobit|svyprobt|svyprop|svyratio|svyreg|svyreg_p|svyregress|svyset|svytab|svytest|svytotal|sw|swilk|symmetry|symmi|symplot|sysdescribe|sysdir|sysuse|szroeter|ta|tab|tab1|tab2|tab_or|tabd|tabdi|tabdis|tabdisp|tabi|table|tabodds|tabstat|tabu|tabul|tabula|tabulat|tabulate|te|tes|test|testnl|testparm|teststd|tetrachoric|time_it|timer|tis|tob|tobi|tobit|tobit_p|tobit_sw|token|tokeni|tokeniz|tokenize|total|translate|translator|transmap|treat_ll|treatr_p|treatreg|trim|trnb_cons|trnb_mean|trpoiss_d2|trunc_ll|truncr_p|truncreg|tsappend|tset|tsfill|tsline|tsline_ex|tsreport|tsrevar|tsrline|tsset|tssmooth|tsunab|ttest|ttesti|tut_chk|tut_wait|tutorial|tw|tware_st|two|twoway|twoway__fpfit_serset|twoway__function_gen|twoway__histogram_gen|twoway__ipoint_serset|twoway__ipoints_serset|twoway__kdensity_gen|twoway__lfit_serset|twoway__normgen_gen|twoway__pci_serset|twoway__qfit_serset|twoway__scatteri_serset|twoway__sunflower_gen|twoway_ksm_serset|ty|typ|type|typeof|unab|unabbrev|unabcmd|update|uselabel|var|var_mkcompanion|var_p|varbasic|varfcast|vargranger|varirf|varirf_add|varirf_cgraph|varirf_create|varirf_ctable|varirf_describe|varirf_dir|varirf_drop|varirf_erase|varirf_graph|varirf_ograph|varirf_rename|varirf_set|varirf_table|varlmar|varnorm|varsoc|varstable|varstable_w|varstable_w2|varwle|vec|vec_fevd|vec_mkphi|vec_p|vec_p_w|vecirf_create|veclmar|veclmar_w|vecnorm|vecnorm_w|vecrank|vecstable|verinst|vers|versi|versio|version|view|viewsource|vif|vwls|wdatetof|webdescribe|webseek|webuse|wh|whelp|whi|which|wilc_st|wilcoxon|win|wind|windo|window|winexec|wntestb|wntestq|xchart|xcorr|xi|xmlsav|xmlsave|xmluse|xpose|xsh|xshe|xshel|xshell|xt_iis|xt_tis|xtab_p|xtabond|xtbin_p|xtclog|xtcloglog|xtcloglog_d2|xtcloglog_pa_p|xtcloglog_re_p|xtcnt_p|xtcorr|xtdata|xtdes|xtfront_p|xtfrontier|xtgee|xtgee_elink|xtgee_estat|xtgee_makeivar|xtgee_p|xtgee_plink|xtgls|xtgls_p|xthaus|xthausman|xtht_p|xthtaylor|xtile|xtint_p|xtintreg|xtintreg_d2|xtintreg_p|xtivreg|xtline|xtline_ex|xtlogit|xtlogit_d2|xtlogit_fe_p|xtlogit_pa_p|xtlogit_re_p|xtmixed|xtmixed_estat|xtmixed_p|xtnb_fe|xtnb_lf|xtnbreg|xtnbreg_pa_p|xtnbreg_refe_p|xtpcse|xtpcse_p|xtpois|xtpoisson|xtpoisson_d2|xtpoisson_pa_p|xtpoisson_refe_p|xtpred|xtprobit|xtprobit_d2|xtprobit_re_p|xtps_fe|xtps_lf|xtps_ren|xtps_ren_8|xtrar_p|xtrc|xtrc_p|xtrchh|xtrefe_p|yx|yxview__barlike_draw|yxview_area_draw|yxview_bar_draw|yxview_dot_draw|yxview_dropline_draw|yxview_function_draw|yxview_iarrow_draw|yxview_ilabels_draw|yxview_normal_draw|yxview_pcarrow_draw|yxview_pcbarrow_draw|yxview_pccapsym_draw|yxview_pcscatter_draw|yxview_pcspike_draw|yxview_rarea_draw|yxview_rbar_draw|yxview_rbarm_draw|yxview_rcap_draw|yxview_rcapsym_draw|yxview_rconnected_draw|yxview_rline_draw|yxview_rscatter_draw|yxview_rspike_draw|yxview_spike_draw|yxview_sunflower_draw|zap_s|zinb|zinb_llf|zinb_plf|zip|zip_llf|zip_p|zip_plf|zt_ct_5|zt_hc_5|zt_hcd_5|zt_is_5|zt_iss_5|zt_sho_5|zt_smp_5|ztnb|ztnb_p|ztp|ztp_p|prtab|prchange|eststo|estout|esttab|estadd|estpost|ivregress|xtreg|xtreg_be|xtreg_fe|xtreg_ml|xtreg_pa_p|xtreg_re|xtregar|xtrere_p|xtset|xtsf_ll|xtsf_llti|xtsum|xttab|xttest0|xttobit|xttobit_p|xttrans)\\b'
         'name': 'keyword.control.flow.stata'
       }
     ]


Changed all the indexOf comparisons in the event manager of != -1 and == 1 to simpler bitwise shifting (~) to 0 (false) for -1 and -(n+1) (true) for others. The reason was to aid readability, because all we want to know is the array containment status in these cases.

--- js/foundation/eventmanager/eventmanager.coffee
+++ js/foundation/eventmanager/eventmanager.coffee
@@ -122,14 +122,14 @@
     4: []
     keysDown: []
     hasKeyDown: (k)->
-      @keysDown.indexOf(k) != -1
+      if ~@keysDown.indexOf(k) then true else false
     addKeyDown: (k)->
       if !@hasKeyDown(k)
         @keysDown.push( k )
         @[4] = @keysDown
     delKeyDown: (k)->
       i = @keysDown.indexOf(k)
-      if i != -1
+      if ~i
         @keysDown.splice( i, 1 )
         @[4] = @keysDown
     resetKeysDown: ->
@@ -220,7 +220,7 @@
       }
     _cache = @_observerMethods[_eventName]
     _elemIdx = _cache.elems.indexOf( _elem )
-    if _elemIdx != -1
+    if ~_elemIdx
       _prevFn = _cache.fns[_elemIdx]
       _prevCapture = _cache.capture[_elemIdx]
       Event.stopObserving( _elem, _eventName, _prevFn, _prevCapture )
@@ -241,7 +241,7 @@
       return false
     _cache = @_observerMethods[_eventName]
     _elemIdx = _cache.elems.indexOf(_elem)
-    return false if _elemIdx == -1
+    return false unless ~_elemIdx
     _prevFn = _cache.fns[_elemIdx]
     _prevCapture = _cache.capture[_elemIdx]
     Event.stopObserving( _elem, _eventName, _prevFn, _prevCapture )
@@ -402,19 +402,18 @@
         _value = _eventOptions[_key]
         if _value
           _eventsOn.push( _key )
-          @_listeners.byEvent[_key].unshift( _viewId ) if @_listeners.byEvent[_key].indexOf(_viewId) == -1
-          if _key == 'rectHover' and _value == 'intersects' and @_listeners._rectHoverIntersectMode.indexOf( _viewId ) == -1
+          @_listeners.byEvent[_key].unshift( _viewId ) unless ~@_listeners.byEvent[_key].indexOf(_viewId)
+          if _key == 'rectHover' and _value == 'intersects' and not ~@_listeners._rectHoverIntersectMode.indexOf( _viewId )
             @_listeners._rectHoverIntersectMode.unshift( _viewId )
         else
           _idx = @_listeners.byEvent[_key].indexOf(_viewId)
-          if _idx != -1
-            @_listeners.byEvent[_key].splice( _idx, 1 )
+          @_listeners.byEvent[_key].splice( _idx, 1 ) if ~_idx
       else
         @warn( "EventManager##{_warnMethodName} => Invalid event type: #{_key}" )
     _this = @
     @_listeners.byId[_viewId] = _eventsOn
     if _ctrl.enabled
-      @_listeners.enabled.unshift( _viewId ) if @_listeners.enabled.indexOf(_viewId) == -1
+      @_listeners.enabled.unshift( _viewId ) unless ~@_listeners.enabled.indexOf(_viewId)
       _elem = ELEM.get( _ctrl.elemId )
       @observe( _elem, 'mouseover', '_mouseOver' )
   #
@@ -429,17 +428,16 @@
       console.log(@_listeners.byId[_viewId],_viewId,_ctrl)
     for _key, _value of @_listeners.byEvent
       _viewIdx = _value.indexOf(_viewId)
-      if _viewIdx != -1
-        _value.splice(_viewIdx,1)
+      _value.splice(_viewIdx,1) if ~_viewIdx
       if _key == 'rectHover'
         _intersectHoverIdx = @_listeners._rectHoverIntersectMode.indexOf( _viewId )
-        if _intersectHoverIdx != -1
+        if ~_intersectHoverIdx
           @_listeners._rectHoverIntersectMode.splice( _intersectHoverIdx, 1 )
     _wasFocused = false
     _elem = ELEM.get( _ctrl.elemId )
     for _statusItem in [ 'dragged', 'selected', 'hovered', 'active', 'focused', 'enabled' ]
       _viewIdx = @_listeners[_statusItem].indexOf(_viewId)
-      if _viewIdx != -1
+      if ~_viewIdx
         if _statusItem == 'dragged'
           _ctrl.endDrag( @status.crsrX, @status.crsrY )
         else if _statusItem == 'selected'
@@ -552,7 +550,7 @@
   # mouseover event.
   focus: (_ctrl)->
     _viewId = _ctrl.viewId
-    if @_listeners.focused.indexOf(_viewId) == -1
+    unless ~@_listeners.focused.indexOf(_viewId)
       _elem = ELEM.get( _ctrl.elemId )
       @observe( _elem, 'mouseout', '_mouseOut' )
       @stopObserving( _elem, 'mouseover', '_mouseOver' )
@@ -567,7 +565,7 @@
   blur: (_ctrl)->
     _viewId = _ctrl.viewId
     _viewIdx = @_listeners.focused.indexOf(_viewId)
-    if _viewIdx != -1
+    if ~_viewIdx
       _elem = ELEM.get( _ctrl.elemId )
       @observe( _elem, 'mouseover', '_mouseOver' )
       @stopObserving( _elem, 'mouseout', '_mouseOut' )
@@ -621,8 +619,8 @@
   # #hover( _dragObj ) and #endHover( _dragObj ) calls
   _delegateHover: (_ctrl, x, y)->
     _byEvent = @_listeners.byEvent
-    _findPoint     = _byEvent.rectHover.indexOf( _ctrl.viewId ) == -1
-    _findTopmost   = _byEvent.multiDrop.indexOf( _ctrl.viewId ) == -1
+    _findPoint     = not ~_byEvent.rectHover.indexOf( _ctrl.viewId )
+    _findTopmost   = not ~_byEvent.multiDrop.indexOf( _ctrl.viewId )
     _findIntersect = true
     if _findPoint
       _area = HPoint.new( x, y )
@@ -630,7 +628,7 @@
     else
       _rect = _ctrl.rect
       _area = HRect.new( x, y, _rect.width, _rect.height )
-      if @_listeners._rectHoverIntersectMode.indexOf( _viewId ) == -1
+      if not ~@_listeners._rectHoverIntersectMode.indexOf( _viewId )
         _matchMethod = 'intersects'
       else
         _matchMethod = 'contains'
@@ -640,11 +638,11 @@
       _hoverItems = @_findAllDroppable(_area,_matchMethod,_ctrl.viewid)
     _endHover = []
     for _hoverId in @_listeners.hovered
-      if _hoverItems.indexOf( _hoverId ) == -1
+      unless ~_hoverItems.indexOf( _hoverId )
         _endHover.push( _hoverId )
     _startHover = []
     for _hoverId in _hoverItems
-      if @_listeners.hovered.indexOf( _hoverId ) == -1
+      unless ~@_listeners.hovered.indexOf( _hoverId )
         _startHover.push( _hoverId )
     for _viewId in _startHover
       @_views[_viewId].startHover(_ctrl)
@@ -663,7 +661,7 @@
         continue if _viewId == _selfId
         _view = _views[_viewId]
         if _view.hasAncestor? and _view.hasAncestor( HView ) and _view.rect[_matchMethod](_area)
-          if _droppable.indexOf( _viewId ) != -1
+          if ~_droppable.indexOf( _viewId )
             _dropId = _search( _view.viewsZOrder.slice().reverse() )
             return _dropId if _dropId
             return _viewId
@@ -684,7 +682,7 @@
         continue if _viewId == _selfId
         _view = _views[_viewId]
         if _view.hasAncestor? and _view.hasAncestor( HView ) and _view.rect[_matchMethod](_area)
-          _found.push( _viewId ) if _droppable.indexOf( _viewId ) != -1
+          _found.push( _viewId ) if ~_droppable.indexOf( _viewId )
           _search( _view.viewsZOrder.slice().reverse() )
     _search( HSystem.viewsZOrder.slice().reverse() )
     return _found
@@ -704,7 +702,7 @@
       _ctrl.active = false
       _idx = _active.indexOf( _viewId )
       _active.splice( _idx, 1 )
-      @blur(_ctrl) if _focused.indexOf(_viewId) != -1
+      @blur(_ctrl) if ~_focused.indexOf(_viewId)
       _ctrl.lostActiveStatus(_newActive)
     _prevActive
   #
@@ -713,9 +711,9 @@
     _active = @_listeners.active
     _focused = @_listeners.focused
     _idx = _active.indexOf( _ctrl.viewId )
-    if _idx == -1
+    unless ~_idx
       _active.unshift(_ctrl.viewId)
-      @focus(_ctrl) if _focused.indexOf(_ctrl.viewId) == -1
+      @focus(_ctrl) unless ~_focused.indexOf(_ctrl.viewId)
       _ctrl.active = true
       _ctrl.gainedActiveStatus(_prevActive)
   #
@@ -730,7 +728,7 @@
     _viewId = _ctrl.viewId
     @focus( _viewId )
     @changeActiveControl(_ctrl)
-    @_listeners.dragged.unshift( _viewId ) if @_listeners.dragged.indexOf( _viewId ) == -1
+    @_listeners.dragged.unshift( _viewId ) unless ~@_listeners.dragged.indexOf( _viewId )
     _ctrl.startDrag( @status.crsrX, @status.crsrY, @status.button2 )
   #
   # Cancels text selections, which happen by
@@ -759,11 +757,11 @@
     _startDragIds = []
     _stop = false
     for _viewId in _focused
-      _newActive.push( _viewId ) if _active.indexOf(_viewId) == -1
+      _newActive.push( _viewId ) unless ~_active.indexOf(_viewId)
       _eventOptions = @_listeners.byId[_viewId]
-      if _mouseDownable.indexOf( _viewId ) != -1
+      if ~_mouseDownable.indexOf( _viewId )
         _mouseDownIds.push( _viewId )
-      if _draggable.indexOf( _viewId ) != -1 and _dragged.indexOf( _viewId ) == -1
+      if ~_draggable.indexOf( _viewId ) and not ~_dragged.indexOf( _viewId )
         _startDragIds.push( _viewId )
     for _viewId in _newActive
       _ctrl = @_views[_viewId]
@@ -773,7 +771,7 @@
       _ctrl = @_views[_viewId]
       _stop = true if _ctrl.mouseDown( x, y, _leftClick )
     for _viewId in _startDragIds
-      if _dragged.indexOf( _viewId ) == -1
+      unless ~_dragged.indexOf( _viewId )
         _ctrl = @_views[_viewId]
         _dragged.unshift( _viewId )
         _stop = true if _ctrl.startDrag( x, y, _leftClick )
@@ -804,11 +802,11 @@
     _endDragIds = []
     _stop = false
     for _viewId in _focused
-      _newActive.push( _viewId ) if _active.indexOf(_viewId) == -1
+      _newActive.push( _viewId ) unless ~_active.indexOf(_viewId)
       _eventOptions = @_listeners.byId[_viewId]
-      if _mouseUppable.indexOf( _viewId ) != -1
+      if ~_mouseUppable.indexOf( _viewId )
         _mouseUpIds.push( _viewId )
-      if _draggable.indexOf( _viewId ) != -1 and _dragged.indexOf( _viewId ) != -1
+      if ~_draggable.indexOf( _viewId ) and ~_dragged.indexOf( _viewId )
         _endDragIds.push( _viewId )
     for _viewId in _newActive
       _ctrl = @_views[_viewId]
@@ -819,7 +817,7 @@
       _stop = true if _ctrl.mouseUp( x, y, _leftClick )
     for _viewId in _endDragIds
       _dragIdx = _dragged.indexOf( _viewId )
-      unless _dragIdx == -1
+      if ~_dragIdx
         _ctrl = @_views[_viewId]
         _dragged.splice( _dragIdx, 1 )
         for _dropViewId in _hovered
@@ -853,8 +851,8 @@
     _clickIds = []
     _stop = false
     for _viewId in _focused
-      _newActive.push( _viewId ) if _active.indexOf(_viewId) == -1
-      if _clickable.indexOf(_viewId) != -1
+      _newActive.push( _viewId ) unless ~_active.indexOf(_viewId)
+      if ~_clickable.indexOf(_viewId)
         _clickIds.push( _viewId )
     for _viewId in _newActive
       _ctrl = @_views[_viewId]
@@ -882,7 +880,7 @@
     _doubleClickable = @_listeners.byEvent.doubleClick
     _stop = false
     for _viewId in _focused
-      if _doubleClickable.indexOf(_viewId) != -1
+      if ~_doubleClickable.indexOf(_viewId)
         _doubleClicks.push( _viewId )
     for _viewId in _doubleClickable
       _ctrl = @_views[_viewId]
@@ -905,7 +903,7 @@
     _mouseWheelable = @_listeners.byEvent.mouseWheel
     _stop = false
     for _viewId in _focused
-      if _mouseWheelable.indexOf(_viewId) != -1
+      if ~_mouseWheelable.indexOf(_viewId)
         _mouseWheels.push( _viewId )
     for _viewId in _mouseWheels
       _ctrl = @_views[_viewId]
@@ -922,7 +920,7 @@
     _focused = @_listeners.focused
     _contextMenuable = @_listeners.byEvent.contextMenu
     for _viewId in _focused
-      if _contextMenuable.indexOf(_viewId) != -1
+      if ~_contextMenuable.indexOf(_viewId)
         _ctrl = @_views[_viewId]
         _stop = false if _ctrl.contextMenu? and _ctrl.contextMenu()
     Event.stop(e) if _stop
@@ -990,7 +988,7 @@
   _detectCmdKey: ( _keyCode )->
     # On Opera, return true on any of the keycodes
     if BROWSER_TYPE.opera
-      return @_cmdKeys.indexOf(_keyCode) != -1
+      if ~@_cmdKeys.indexOf(_keyCode) then return true else return false
     # Any mac browser (except opera, above) uses left or right windows key
     # equivalent as the Command key.
     else if BROWSER_TYPE.mac
@@ -1011,7 +1009,7 @@
     _keyDowns = []
     unless @status.hasKeyDown( _keyCode ) and @_lastKeyDown != _keyCode
       for _viewId in _active
-        _keyDowns.push( _viewId ) if _keyDowners.indexOf( _viewId ) != -1
+        _keyDowns.push( _viewId ) if ~_keyDowners.indexOf( _viewId )
       @status.addKeyDown( _keyCode )
     # repeat not implemented yet
     for _viewId in _keyDowns
@@ -1035,14 +1033,14 @@
     _textEnters = []
     if @status.hasKeyDown( _keyCode )
       for _viewId in _active
-        _keyUps.push( _viewId ) if _keyUppers.indexOf( _viewId ) != -1
+        _keyUps.push( _viewId ) if ~_keyUppers.indexOf( _viewId )
       @status.delKeyDown( _keyCode )
     for _viewId in _keyUppers
       _ctrl = @_views[_viewId]
       if _ctrl.keyUp?
         _stop = true if _ctrl.keyUp( _keyCode )
     for _viewId in _textEnterers
-      _textEnters.push( _viewId ) if _enabled.indexOf( _viewId ) != -1
+      _textEnters.push( _viewId ) if ~_enabled.indexOf( _viewId )
     for _viewId in _textEnters
       _ctrl = @_views[_viewId]
       if _ctrl.textEnter?


Cofix outfit

Cofix outfit

--- public/coffee/main.coffee
+++ public/coffee/main.coffee
@@ -96,7 +96,7 @@

")

   addClearFix: =>
-    $("

")
+    $("

")

   addPrezi: (prezi) =>
     @prezi_pair_count++


[#6] brunch had been configured

[#6] brunch had been configured

--- config.coffee
+++ config.coffee
@@ -27,7 +27,7 @@
       joinTo: objectify(
         "javascripts#{DIR_SEP}app.min.js", (path) -> /^app/.test(path) and not /\.prod\./.test(path)
         "javascripts#{DIR_SEP}head.min.js", (path) -> /^vendor(\/|\\)head/.test(path) and not /\.prod\./.test(path)
-        "javascripts#{DIR_SEP}vendor.min.js", (path) -> /^vendor/.test(path) and not /\.prod\./.test(path)
+        "javascripts#{DIR_SEP}vendor.min.js", (path) -> /^vendor/.test(path) and not /\.prod\./.test(path) and not /.*(\/|\\)head(\/|\\).*/.test(path) and not /^vendor(\/|\\)test(\/|\\).*/.test(path) and not /.*[_].*/.test(path)
         # "test#{DIR_SEP}javascripts#{DIR_SEP}test-vendor.js", /^test(\/|\\)(?=vendor)/

         "test#{DIR_SEP}javascripts#{DIR_SEP}test-vendor.js", (path) -> /^vendor(\/|\\)test(\/|\\)scripts(\/|\\)(?!blanket|mocha-blanket)/.test(path) and not /\.prod\./.test(path)
@@ -102,7 +102,7 @@
         javascripts:
           joinTo: objectify(
             "javascripts#{DIR_SEP}app.js", (path) -> /^app/.test(path) and not /\.dev\./.test(path)
-            "javascripts#{DIR_SEP}vendor.min.js", (path) -> /^vendor/.test(path) and not /\.dev\./.test(path)
+            "javascripts#{DIR_SEP}vendor.min.js", (path) -> /^vendor/.test(path) and not /\.dev\./.test(path) and not /\brunch-reload\./.test(path) and not /.*(\/|\\)head(\/|\\).*/.test(path) and not /^vendor(\/|\\)test(\/|\\).*/.test(path) and not /.*[_].*/.test(path)
             "javascripts#{DIR_SEP}head.min.js", (path) -> /^vendor(\/|\\)head/.test(path) and not /\.dev\./.test(path)
           )
           order: jsOrder


Don't match to string literals, because the path seperator is different on windows

--- config.coffee
+++ config.coffee
@@ -197,12 +197,8 @@

   modules:
     definition: (path, data) ->
-      needHeaders = [
-        'public/javascripts/app.js'
-        'public/javascripts/world.js'
-        'public/javascripts/whole-app.js'
-      ]
-      defn = if path in needHeaders then commonjsHeader else ''
+      needHeaderExpr = regJoin('^public/javascripts/?(app.js|world.js|whole-app.js)')
+      defn = if path.match(needHeaderExpr) then commonjsHeader else ''
       return defn

 #- Find all .coffee and .jade files in /app


don't publish postFactlinkObject, that's unnecessary.

--- js-library/Gruntfile.coffee
+++ js-library/Gruntfile.coffee
@@ -139,7 +139,6 @@
           'build/factlink_loader_basic.min.js':       ['build/factlink_loader_basic.js']
           'build/factlink_loader_publishers.min.js':  ['build/factlink_loader_publishers.js']
           'build/factlink_loader_bookmarklet.min.js': ['build/factlink_loader_bookmarklet.js']
-          'build/postFactlinkObject.min.js': ['build/js/jail_iframe/util/postFactlinkObject.js']
     shell:
       gzip_js_files:
         command: ' find build/ -iname \'*.js\'  -exec bash -c \' gzip -9 -f < "{}" > "{}.gz" \' \\; '
@@ -156,10 +155,6 @@
       extension_events:
         files: [
           { src: ['factlink.*.js'], cwd: 'build/js/extension_events', dest: 'build', expand: true }
-        ]
-      postFactlinkObject:
-        files: [
-          { src: ['postFactlinkObject.js'], cwd: 'build/js/jail_iframe/util', dest: 'build', expand: true }
         ]
       dist:
         files: [
@@ -210,7 +205,7 @@

   grunt.registerTask 'jail_iframe', []
   grunt.registerTask 'compile',  [ 'clean',
-    'copy:build',  'copy:extension_events', 'coffee', 'copy:postFactlinkObject', 'copy:config_development',
+    'copy:build',  'copy:extension_events', 'coffee', 'copy:config_development',
     'sass', 'cssUrlEmbed', 'cssmin',
     'concat', 'mocha', 'uglify', 'code_inliner',
     'shell:gzip_js_files', 'copy:dist'


debug off

debug off

--- js/views/destination.coffee
+++ js/views/destination.coffee
@@ -40,7 +40,6 @@

     route: (e) ->
-      console.log "route"
       $.mobile.showPageLoadingMsg();
       @directionService = new google.maps.DirectionsService()
       destination = $("#destination-input").val()


one more example of precedence/associativity being different from C


Optimize preact-render-to-string usage

Optimize preact-render-to-string usage

Only check for library once and create one global instance of `RenderTo*Dom`

--- src/svgtiler.coffee
+++ src/svgtiler.coffee
@@ -646,6 +646,8 @@
   'symbol'
 ]

+preactRenderToDom = null
+
 class SVGContent extends HasSettings
   ###
   Base helper for parsing SVG as specified in SVG Tiler:
@@ -680,17 +682,21 @@
       @svg =
         (window?.preactRenderToString?.default ?
          require('preact-render-to-string')) @value
-      if (preactRenderToDom = window?.preactRenderToDom?.default ?
-                              require 'preact-render-to-dom')?
-        if xmldom?
-          @dom = new preactRenderToDom.RenderToXMLDom {xmldom,
-            svg: true
-            skipNS: true
-          }
-          .render @value
+      if preactRenderToDom == null
+        if window?
+          preactRenderToDom = window?.preactRenderToDom?.RenderToDom
         else
-          @dom = new preactRenderToDom.RenderToDom document, svg: true
-          .render @value
+          preactRenderToDom = require 'preact-render-to-dom'
+        if preactRenderToDom?
+          if xmldom?
+            preactRenderToDom = new preactRenderToDom.RenderToXMLDom {xmldom,
+              svg: true
+              skipNS: true
+            }
+          else
+            preactRenderToDom = new preactRenderToDom.RenderToDom {svg: true}
+      if preactRenderToDom?
+        @dom = preactRenderToDom.render @value
         @postprocessDOM()
     else if typeof @value == 'string'
       if @value.trim() == ''  ## Blank SVG treated as 0x0 symbol


Fix bug after image insertion

Fix bug after image insertion

Some reason @range became null after insertImage

--- src/modules/image-tooltip.coffee
+++ src/modules/image-tooltip.coffee
@@ -77,8 +77,9 @@
     if @range
       @preview.innerHTML = 'Preview'
       @textbox.value = ''
-      @quill.insertEmbed(@range.end, 'image', url, 'user')
-      @quill.setSelection(@range.end + 1, @range.end + 1)
+      index = @range.end
+      @quill.insertEmbed(index, 'image', url, 'user')
+      @quill.setSelection(index + 1, index + 1)
     this.hide()

   _onToolbar: (range, value) ->


corr_w_scatter: remove trailing whitespace

--- corr_w_scatter/corr_w_scatter.coffee
+++ corr_w_scatter/corr_w_scatter.coffee
@@ -98,7 +98,7 @@
     d3.selectAll("line.axes").remove()
     xScale = d3.scale.linear()
                      .domain(d3.extent(data.dat[i]))
-                     .range([innerPad, w-innerPad])
+                     .range([innerPad, w-innerPad])
     yScale = d3.scale.linear()
                      .domain(d3.extent(data.dat[j]))
                      .range([h-innerPad, innerPad])


Least SLOC changes to use the current "user"

--- test/routes/time_entries.coffee
+++ test/routes/time_entries.coffee
@@ -6,7 +6,7 @@

 startApp = require './../start_app'
 base = require './../base'
-options = require './../options'
+optionsBase = require './../options'
 user_test_helper = require './user_test_helper'

 TimeEntry = require "#{__dirname}/../../models/time_entry"
@@ -14,6 +14,9 @@
 testUser = undefined
 testProject = undefined
 timeEntriesCreated = []
+
+options = (u)->
+  optionsBase u or testUser

 makeProject = (user, cb)->
   ops = options user


test javascript build failure

test javascript build failure

--- karma/flows/services.coffee
+++ karma/flows/services.coffee
@@ -68,6 +68,8 @@
       test.http.flush()
       test.http.verifyNoOutstandingRequest()

+    it 'should always fail', ->
+      expect(true).toBe(false)

     it 'should set flow defintion after fetching', ->
       test.window.flowId = test.flows.rules_first.id


Refactor array/object stuff into ObjectTransfoms

--- js2coffee.coffee
+++ js2coffee.coffee
@@ -105,6 +105,7 @@
     LoopTransforms
     SwitchTransforms
     MemberTransforms
+    ObjectTransforms
     OtherTransforms ]
   run [ BlockTransforms ]

@@ -126,8 +127,7 @@
 # }}} -----------------------------------------------------------------------
 # {{{ CommentTransforms

-###**
-# CommentTransforms:
+###
 # Injects comments as nodes in the AST. This takes the comments in the
 # `Program` node, finds list of expressions in bodies (eg, a BlockStatement's
 # `body`), and injects the comment nodes wherever relevant.
@@ -158,8 +158,7 @@
   BlockComment: (node) ->
     @convertCommentPrefixes(node)

-  ###*
-  # updateCommentTypes():
+  ###
   # Updates comment `type` as needed. It changes *Block* to *BlockComment*, and
   # *Line* to *LineComment*. This makes it play nice with the rest of the AST,
   # because "Block" and "Line" are ambiguous.
@@ -171,8 +170,7 @@
         when 'Block' then c.type = 'BlockComment'
         when 'Line'  then c.type = 'LineComment'

-  ###*
-  # injectComments():
+  ###
   # Injects comment nodes into a node list.
   ###

@@ -180,8 +178,7 @@
     node[key] = @addCommentsToList(node.range, node[key])
     node

-  ###*
-  # addCommentsToList():
+  ###
   # Delegate of `injectComments()`.
   #
   # Checks out the `@comments` list for any relevants comments, and injects
@@ -209,8 +206,7 @@
         left = item.range[1]
     list

-  ###*
-  # convertCommentPrefixes():
+  ###
   # Changes JS block comments into CoffeeScript block comments.
   # This involves changing prefixes like `*` into `#`.
   ###
@@ -234,11 +230,15 @@
 # }}} -----------------------------------------------------------------------
 # {{{ SwitchTransforms

-###*
-# SwitchTransforms:
+###
 # Updates `SwitchCase`s to a more coffee-compliant AST. This means having
 # to remove `return`/`break` statements, and taking into account the
 # correct way of consolidating empty ccases.
+#
+#     switch (x) { case a: b(); break; }
+#
+#     switch x
+#       when a then b()
 ###

 class SwitchTransforms extends TransformerBase
@@ -293,8 +293,7 @@
 # }}} -----------------------------------------------------------------------
 # {{{ MemberTransforms

-###*
-# MemberTransforms:
+###
 # Performs transformations on `a.b` scope resolutions.
 #
 #     this.x            =>  @x
@@ -348,10 +347,30 @@
     node

 # }}} -----------------------------------------------------------------------
+# {{{ ObjectTransforms
+
+###
+# Mangles the AST with various CoffeeScript tweaks.
+###
+
+class ObjectTransforms extends TransformerBase
+  ArrayExpression: (node) ->
+    @parenthesizeObjectsInElements(node)
+
+  ###
+  # Ensures that an Array's elements objects are braced.
+  ###
+
+  parenthesizeObjectsInElements: (node) ->
+    for item in node.elements
+      if item.type is 'ObjectExpression'
+        item._braced = true
+    node
+
+# }}} -----------------------------------------------------------------------
 # {{{ OtherTransforms

-###*
-# OtherTransforms:
+###
 # Mangles the AST with various CoffeeScript tweaks.
 ###

@@ -384,9 +403,6 @@
   VariableDeclarator: (node) ->
     @addShadowingIfNeeded(node)
     @addExplicitUndefinedInitializer(node)
-
-  ArrayExpression: (node) ->
-    @parenthesizeObjectsInElements(node)

   ReturnStatement: (node) ->
     @parenthesizeObjectsInArgument(node)
@@ -411,16 +427,6 @@
         ]

   ###
-  # Ensures that an Array's elements objects are braced.
-  ###
-
-  parenthesizeObjectsInElements: (node) ->
-    for item in node.elements
-      if item.type is 'ObjectExpression'
-        item._braced = true
-    node
-
-  ###
   # Ensures that a ReturnStatement with an object ('return {a:1}') has a braced
   # expression.
   ###
@@ -542,8 +548,7 @@
 # }}} -----------------------------------------------------------------------
 # {{{ LoopTransforms

-###**
-# LoopTransforms:
+###
 # Provides transformations for `while`, `for` and `do`.
 ###

@@ -611,8 +616,7 @@
 # }}} -----------------------------------------------------------------------
 # {{{ BlockTransforms

-###**
-# BlockTransforms:
+###
 # Flattens nested `BlockStatements`.
 ###

@@ -625,7 +629,7 @@
 # }}} -----------------------------------------------------------------------
 # {{{ FunctionTransforms

-###**
+###
 # FunctionTransforms:
 # Reorders functions.
 #


use router to read query

use router to read query

--- tutor/src/components/tabs.cjsx
+++ tutor/src/components/tabs.cjsx
@@ -1,6 +1,7 @@
 React = require 'react'
 classnames = require 'classnames'
-qs = require 'qs'
+
+Router = require '../router'

 # Used to cancel router transitions the same way an onClick event is
 class FakeEvent
@@ -21,15 +22,17 @@
     tabs: React.PropTypes.arrayOf(
       React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.element ])
     ).isRequired
+    windowImpl: React.PropTypes.object

   getDefaultProps: ->
+    windowImpl: window
     initialActive: 0

   contextTypes:
     router: React.PropTypes.object

   getInitialState: ->
-    {tab} = qs.parse(location.search.slice(1))
+    {tab} = Router.getQuery(@props.windowImpl)
     activeIndex: if _.isUndefined(tab) then @props.initialActive else parseInt(tab, 10)

   componentWillMount: ->
@@ -58,7 +61,8 @@

   # callable from the parent component via a ref
   selectTabIndex: (activeIndex) ->
-    @context.router.transitionTo(pathname: location.pathname, query: {tab: activeIndex})
+    query = _.extend(Router.getQuery(@props.windowImpl), tab: activeIndex)
+    @context.router.transitionTo(pathname: location.pathname, query: query)
     @setState({activeIndex})

   onTabClick: (activeIndex, ev) ->


SPEC: remove $combinator cruft

SPEC: remove $combinator cruft


:lipstick:

:lipstick:

--- spec/git-spec.coffee
+++ spec/git-spec.coffee
@@ -85,7 +85,7 @@
       expect(repo.getConfigValue("core.ignorecase")).toBe 'true'
       expect(repo.getConfigValue("not.section")).toBe null

-  describe 'isPathModified(path)', ->
+  describe '.isPathModified(path)', ->
     repo = null

     beforeEach ->
@@ -107,7 +107,7 @@
         fs.writeFileSync(path.join(repo.getWorkingDirectory(), 'new.txt'), 'new', 'utf8')
         expect(repo.isPathModified('new.txt')).toBe false

-  describe 'isPathNew(path)', ->
+  describe '.isPathNew(path)', ->
     repo = null

     beforeEach ->


Better test for `git.cmd` returning promises

--- spec/git-spec.coffee
+++ spec/git-spec.coffee
@@ -80,8 +80,9 @@

   describe "git.cmd", ->
     it "returns a promise", ->
-      waitsForPromise ->
-        git.cmd().then -> expect(true).toBeTruthy()
+      promise = git.cmd()
+      expect(promise.catch).toBeDefined()
+      expect(promise.then).toBeDefined()

   describe "git.add", ->
     it "calls git.cmd with ['add', '--all', {fileName}]", ->


spec tweaks

spec tweaks

--- spec/protocol.coffee
+++ spec/protocol.coffee
@@ -3,7 +3,8 @@
 io = require 'socket.io-client'
 BeginOfTest = 0
 InBetween = 0
-MatchId = ""
+GravityMatchId = ''
+MoleculeMatchId = ''
 History = 0

 #   GCP PROTOCOL SPECIFICATION   *StudioLounge Multiplayer Game*
@@ -52,41 +53,67 @@
     (@lukas = server.gcp()).on "connect", () -> @emit 'login', "I am Lukas"

     it "should allow players to chat in the public chatroom", (done) ->
-      @lukas.send "happy again :-)"
-      @anyplayer.on 'message', (msg) ->
-        expect(msg).to.equal "Lukas:   happy again :-)"
+      @lukas.emit 'chat', "happy again :-)"
+      @anyplayer.on 'chat', (msg) ->
+        expect(msg).to.deep.equal {
+          player: "Lukas",
+          text: "happy again :-)"
+        }
         History += 1
       @anotherplayer.on 'message', (msg) ->
-        expect(msg).to.equal "Lukas:   happy again :-)"
+        expect(msg).to.deep.equal {
+          player: "Lukas",
+          text: "happy again :-)"
+        }
         done()

     it "must not let players chat who are not logged in", (done) ->
       server.gcp().on 'connect', () ->
-        @send "I did not log in but I chat anayway"
-      @lukas.on 'message', (msg) -> expect(true).to.be.not.ok
-      setTimeout done, 58
-
-
-
-
-
-  describe "MATCHING (players with games)", () ->
+        @emit 'chat', "I did not log in but I chat anayway"
+      @lukas.on 'chat', (msg) -> expect(true).to.be.not.ok
+      setTimeout done, 100 #ms
+
+
+
+
+
+  describe "GAME APPublishing", () ->
+
+    xit "should let the server publish game apps", (done) ->
+      server.post { game: "new.game", name: "FunnyFoo" }
+      @lukas.on 'publish', (game) ->
+        expect(game).to.deep.equal {
+          game: "new.game",
+          name: "FunnyFoo"
+        }
+        done()
+
+
+
+
+
+  describe "MATCH MAKING (players <-> games)", () ->

     InBetween = Date.now()

     it "should allow any logged in player to host games", (done) ->
-      @anyplayer.emit 'host', { game: "my.game", min: 2, max: 3}
+      @anyplayer.emit 'host', { game: "de.gravity", max: 3 }
       @anyplayer.on 'host', (match) -> # host gets it too
+        GravityMatchId = match.id # server assigned GUID
+        expect(match.game).to.equal "de.gravity"
         expect(match.host).to.equal "Anyname"
-        expect(match.min).to.equal 2
         expect(match.max).to.equal 3
-        MatchId = match.id # server assigned GUID
+        expect(match.id).to.be.ok
         History += 1
       @lukas.on 'host', (match) ->
+        expect(match.game).to.equal "de.gravity"
         expect(match.host).to.equal "Anyname"
-        expect(match.min).to.equal 2
         expect(match.max).to.equal 3
-        done()
+        expect(match.id).to.be.ok
+        done()
+      @lukas.emit 'host', { game: "de.mole", max: 3 }
+      @anotherplayer.on 'host', (match) ->
+        MoleculeMatchId = match.id

     it "should deny anyone else to host a new game", (done) ->
       @troll.emit 'host', { game: "a.random.game", min: 43, max: 55 }
@@ -94,25 +121,52 @@
       setTimeout done, 58

     it "should broadcast that another player joins", (done) ->
-      @anotherplayer.on 'join', (msg) =>
+      @anotherplayer.emit 'join', { match: GravityMatchId }
       @anyplayer.on 'join', (msg) =>
         expect(msg.player).to.equal "Ananda"
-        expect(msg.id).to.equal MatchId
-        History += 1
-        done()
-
-
-
+        expect(msg.match).to.equal GravityMatchId
+        History += 1
+        done()
+      @anyplayer.emit 'join', { match: MoleculeMatchId }
+
+
+

   describe "CUSTOM MESSAGING", () ->

     it "should broadcast game messages among players of a match", (done) ->
-      @anotherplayer.emit 'move', { foo: "my", data: 42 }
-      @anyplayer.on 'move', (msg) =>
-        expect(msg).to.deep.equal( { foo: "my", data: 42 }
-        History += 1
-        done()
+      @anyplayer.emit 'msg', {
+        foo: "my", data: 42,
+        match: GravityMatchId
+        persist: 1
+      }
+      @anotherplayer.on 'msg', (msg) =>
+        expect(msg).to.deep.equal {
+          foo: "my", data: 42,
+          match: GravityMatchId,
+          sender: "Anyname",
+          next: "Ananda",
+          persist: 1
+        }
+        History += 1
+        done()
+
+
+
+
+
+  describe "CHECKING IN AND OUT", () ->
+
+    it "should let player check into the lobby", (done) ->
+      @lukas.emit 'checkin', "lobby-xy"
+      @anyplayer.on 'checkin', (status) ->
+        expect(status.player).to.equal "Lukas"
+        expect(status.match).to.equal "lobby-xy"
+      # status updates only for matched players
+      @anotherplayer.on 'checkin', (status) ->
+        expect("this").to.be.not.ok
+      setTimeout done, 99 # ms


Add handy ActiveRecord properties to retrieve DB and context

--- src/access/active-record.coffee
+++ src/access/active-record.coffee
@@ -113,4 +113,13 @@

     destroy: (cb) -> states[@_n].destroy.call(@, cb)

+Object.defineProperty(ActiveRecord::, "_db", {
+    get: () -> @_gw.db
+})
+
+Object.defineProperty(ActiveRecord::, "_ctx", {
+    get: () -> @_gw.db.context
+})
+
+
 module.exports = ActiveRecord


Gnuplot support

Gnuplot support

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -159,7 +159,7 @@
       { include: '#metaEnvMath' }
       # { include: '#metaEnvTable' }
       { include: '#envList' }
-      # { include: '#envGnuplot' }
+      { include: '#envGnuplot' }
       # { include: '#metaEnvMinted' }
       # { include: '#metaEnvListing' }
       # { include: '#envLuaCode' }
@@ -1069,6 +1069,43 @@
       5:
         name: 'punctuation.definition.arguments.end.latex'
   }
+  envGnuplot: {
+    comment: 'Matches gnuplot env.'
+    name: 'meta.environment.embedded.$5.latex'
+    contentName: 'source.embedded.gnuplot'
+    begin: '((\\\\)begin)(\\{)((gnuplot)\\*?)(\\})(?:(\\[)(.*?)(\\]))?'
+    beginCaptures:
+      1:
+        name: 'support.function.environment.begin.latex'
+      2:
+        name: 'punctuation.definition.function.begin.latex'
+      3:
+        name: 'punctuation.definition.arguments.begin.latex'
+      4:
+        name: 'variable.parameter.environment.$5.latex'
+      # 5: Used for $4 and meta scope name (basically just non starred version)
+      6:
+        name: 'punctuation.definition.arguments.end.latex'
+      7:
+        name: 'punctuation.definition.arguments.optional.begin.latex'
+      8:
+        name: 'variable.parameter.optional.function.environment.latex'
+      9:
+        name: 'punctuation.definition.arguments.optional.end.latex'
+    end: '((\\\\)end)(\\{)(\\4)(\\})'
+    endCaptures:
+      1:
+        name: 'support.function.environment.end.latex'
+      2:
+        name: 'punctuation.definition.function.latex'
+      3:
+        name: 'punctuation.definition.arguments.begin.latex'
+      4:
+        name: 'variable.parameter.environment.latex'
+      5:
+        name: 'punctuation.definition.arguments.end.latex'
+    patterns: [{ include: 'source.gnuplot' }]
+  }

   # Experimental


Slightly better scoping

Slightly better scoping


fix * comment line

fix * comment line

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -705,7 +705,7 @@
         'captures':
           '0':
             'name': 'punctuation.definition.comment.stata'
-        'begin': '^\\s*(\\*).*$\\n?'
+        'begin': '^\\s*(\\*)'
         'name': 'comment.line.star.stata'
         'end': '(?=\\n)'
         'comment': 'TODO! need to except out the occasion that a * comes after a /// on the previous line. May be easiest to join with the comment.line.triple-slash.stata below'


fix userId bug

fix userId bug

--- both/checks.coffee
+++ both/checks.coffee
@@ -151,7 +151,7 @@
 		return true

 	for team in shift.teams when team._id == obj.teamId
-		for user in team.participants when user._id == Meteor.userId() && user.thisTeamleader
+		for user in team.participants when user._id == obj.userId && user.thisTeamleader
 			return true

 	throw new Meteor.Error 550, TAPi18n.__('permissions.notShiftAdmin')


extracted protected info to environment

extracted protected info to environment

--- src/scripts/buzzfeedstats.coffee
+++ src/scripts/buzzfeedstats.coffee
@@ -18,7 +18,7 @@
   robot.respond /realtime$/i, (msg) ->
     gaCallback msg, "buzzfeed"

-  robot.hear /buzzfeed .* users$/i, (msg) ->
+  robot.hear /buzzfeed .* (users|viewers)$/i, (msg) ->
     gaCallback msg, "buzzfeed"


dashboard: removed the groupSettingsUpdated eventlistener

--- client/Dashboard/AppView.coffee
+++ client/Dashboard/AppView.coffee
@@ -65,9 +65,6 @@
     @searchWrapper.addSubView @searchIcon
     @header.addSubView @searchWrapper

-    @on "groupSettingsUpdated", (group)->
-      @setData group
-      @createTabs()

   setListeners:->


router: fix redirect for referrer page when logged in

--- client/Main/kodingrouter.coffee
+++ client/Main/kodingrouter.coffee
@@ -283,7 +283,7 @@
         KD.mixpanel "Visit referrer url, success", {username}

         # give a notification to tell that this is a referral link here - SY
-        @handleRoute "/Activity"
+        @handleRoute if KD.isLoggedIn() then "/Activity" else "/"

       '/:name?/Logout'         : ({params:{name}})-> requireLogin -> mainController.doLogout()


KodingRouter: changed opensection logic

KodingRouter: changed opensection logic

removed:
- setting initial route
- change group on every opensection

--- client/Main/kodingrouter.coffee
+++ client/Main/kodingrouter.coffee
@@ -15,9 +15,8 @@
     @openRoutes     = {}
     @openRoutesById = {}
     KD.singleton('display').on 'DisplayIsDestroyed', @bound 'cleanupRoute'
-    @ready = no
+
     KD.getSingleton('mainController').once 'AccountChanged', =>
-      @ready = yes
       @utils.defer => @emit 'ready'

     super()
@@ -81,22 +80,15 @@
     delete @openRoutes[@openRoutesById[contentDisplay.id]]

   openSection:(app, group, query)->
-    return @once 'ready', @openSection.bind this, arguments...  unless @ready
-
-    KD.getSingleton('groupsController').changeGroup group, (err)=>
-      if err then new KDNotificationView title: err.message
-      else
-        # temp fix for not showing homepage to loggedin users
-        # app = 'Activity' if app is 'Home' and KD.isLoggedIn()
-
+
+    @ready =>
+      {appManager, groupsController} = KD.singletons
+      groupsController.ready =>
         @setPageTitle nicenames[app] ? app
-        appManager  = KD.getSingleton "appManager"
         handleQuery = appManager.tell.bind appManager, app, "handleQuery", query

         appManager.once "AppCreated", handleQuery  unless appWasOpen = appManager.get app
-
-        appManager.open app, (appInstance)=>
-          appInstance.setOption "initialRoute", @getCurrentPath()
+        appManager.open app

         handleQuery()  if appWasOpen

@@ -288,7 +280,6 @@
       '/:name?/Logout'         : ({params:{name}})-> requireLogin -> mainController.doLogout()

       '/:name?/Topics/:slug'   : createContentHandler 'Topics'
-      '/:name?/Activity/:slug' : createContentHandler 'Activity'

       '/:name/Groups'          : createSectionHandler 'Groups'
       '/:name/Followers'       : createContentHandler 'Members', yes


regarding previous: evidently file tab switching must be keyup...

--- salvus/page/editor.coffee
+++ salvus/page/editor.coffee
@@ -322,12 +322,12 @@

     activate_handlers: () =>
         #console.log "activate_handlers - #{@project_id}"
-        $(document).keydown(@keydown_handler)
+        $(document).keyup(@keyup_handler)
         $(window).resize(@_window_resize_while_editing)

     remove_handlers: () =>
         #console.log "remove_handlers - #{@project_id}"
-        $(document).unbind 'keydown', @keydown_handler
+        $(document).unbind 'keyup', @keyup_handler
         $(window).unbind 'resize', @_window_resize_while_editing

     close_all_open_files: () =>
@@ -338,7 +338,7 @@
         @remove_handlers()
         @close_all_open_files()

-    keydown_handler: (ev) =>
+    keyup_handler: (ev) =>
         #console.log("keyup handler for -- #{@project_id}", ev)
         if (ev.metaKey or ev.ctrlKey) and ev.keyCode == 79
             #console.log("editor keyup")


Fix issues when data is function, not an object.

--- tasks/i18n-pug.coffee
+++ tasks/i18n-pug.coffee
@@ -23,14 +23,16 @@
             err.origError = e
             grunt.fail.warn err

-        if not 'i18n' of @options
+        config = {}
+        config.options = @options()
+
+        if not config.options.i18n?
             err = new Error(
                 'You need to configure an `i18n` object in your target'+
                 ' options. See here: https://github.com/SnijderC/'+
                 'grunt-i18n-pug/blob/master/README.md'
             )
             grunt.fail.fatal err
-

         gettextFilter = (context) ->
             (text, options) ->
@@ -63,11 +65,10 @@
                 return context.__mf(text)

         # Get raw config (unparsed configuration)
-        config = grunt.config.getRaw(
+        config.files = grunt.config.getRaw(
             # Most commonly `i18n_pug.[target]` or `i18n_pug`
             if @target.length then "#{@name}.#{@target}" else @name
-        )
-
+        ).files
         # Find the i18n settings object in the options and preserve it
         i18nConfig = config.options.i18n
         # Remove options not supported by grunt-contrib-pug from config
@@ -91,12 +92,29 @@
         for locale in i18nConfig.locales
             # Make a duplicate of config (i.e. not byref)
             _config = _.cloneDeep(config)
+            _config.options._i18n = {}
             # Register __(), __n(), etc. in pugs data namespace
-            i18nConfig.register = _config.options.data
+            i18nConfig.register = _config.options._i18n
             # Configure i18n
             i18n.configure i18nConfig
             # Set the locale
-            _config.options.data.setLocale(locale)
+            _config.options._i18n.setLocale locale
+            if typeof _config.options.data != 'function'
+                _.assign(_config.options.data, _config.options._i18n)
+                delete _config.options._i18n
+            else
+                data_callback = _config.options.data
+
+                _config.options.data = (
+                    (data_obj) ->
+                        (src, dest) ->
+                            data = data_callback(src, dest)
+                            _.assign(data, data_obj._i18n)
+                            delete data_obj._i18n
+                            console.log data_obj
+                            console.log(data)
+                            data
+                )(_config.options)

             # add a gettext filter
             _config.options.filters = {
@@ -120,7 +138,6 @@
                                 dest = "#{locale}/#{dest}"
                             # Run callback if any
                             return callbacks[key] src, dest
-
             target = if @target then "#{@target}_#{locale}" else locale
             grunt.config.set "pug.#{target}", _config
             grunt.task.run ["pug:#{target}"]


initial ship types calculation

initial ship types calculation

--- client/browser/fc/layout.coffee
+++ client/browser/fc/layout.coffee
@@ -58,11 +58,23 @@
   Template.fcMembersList.undockedCharacters().count()

 Template.fcShipsList.shipTypes = ->
-  shipTypes = []
+  shipTypes = {}
   for character in Characters.find({active: true}).fetch()
-    console.log "character "+character
-
-
+    type = shipTypes[character.shiptypeid] #even capsule has a type
+    if !type?
+       #even capsule has a type
+       type =
+         id: character.shiptypeid
+         name: character.shiptype
+         characters: []
+    type.characters.push character
+  result = []
+  for k, v in shipTypes
+    result.push
+      name: k
+      id: v.id
+      characters: v.characters
+  result

 Template.fcMembersList.inactiveCharacters = ->
   Characters.find({active: false})


fixing up pubish, currently no posts are visible form the browser, however one can see them through the browser console.

--- client/coffeescript/main.coffee
+++ client/coffeescript/main.coffee
@@ -3,7 +3,8 @@
 Users = new Meteor.Collection("users_proto")

 # Subscriptions
-Meteor.subscribe( "my_user" )
+#the subscription my_user has been removed.
+#Meteor.subscribe( "my_user" )
 Meteor.subscribe( "my_posts" )
 Meteor.subscribe( "assigned_posts" )


IDE: realtime messaging activity check taken to separate method

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -1084,6 +1084,20 @@

     log 'continuePrivateMessage'
     @statusBar.avatars.show()
+
+
+  isRealtimeSessionActive: (id, callback) ->
+
+    hostName = if @amIHost then KD.nick() else @collaborationHost
+    title    = "#{hostName}.#{id}"
+
+    @rtm.once 'FileQueryFinished', (file) =>
+
+      if file.result.items.length > 0
+      then callback yes
+      else callback no
+
+    @rtm.fetchFileByTitle title
     {message} = KD.singletons.socialapi
     nick      = KD.nick()


ide: don't trigger focus when it's not needed

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -167,6 +167,10 @@

   setActivePaneFocus: (state) ->
     return  unless pane = @getActivePaneView()
+    return  if pane is @activePaneView
+
+    @activePaneView = pane
+
     KD.utils.defer -> pane.setFocus? state

   splitTabView: (type = 'vertical', ideViewOptions) ->


delete url appropriatly

delete url appropriatly

--- src/scripts/keep-alive.coffee
+++ src/scripts/keep-alive.coffee
@@ -68,7 +68,8 @@
     url = msg.match[1]

     robot.brain.data.keepalives ?= []
-    robot.brain.data.keepalives.pop url
+
+    robot.brain.data.keepalives.splice(robot.brain.data.keepalives.indexOf(url), 1);
     msg.send "OK. I've removed that url from my list of urls to keep alive."

   robot.respond /what are you keeping alive/i, (msg) ->


api notification wrappers. Need to be tested.

--- web/coffee/dependencies.coffee
+++ web/coffee/dependencies.coffee
@@ -17,3 +17,10 @@

   $.notify data.message, style

+$.fn.apiNotify = (data, configuration) ->
+  style = "info"
+  if data.status == 0
+    style = "error"
+  configuration["className"] = style
+
+  return $(this).notify(message, configuration)


Fix user form validation.

Fix user form validation.

--- web/coffeescripts/setup.coffee
+++ web/coffeescripts/setup.coffee
@@ -134,6 +134,12 @@
         $('#password-error').text 'Password must be at least 8 characters.'
         valid = false

+      # admin updating a user's password
+      if @session.bareJid() != @selected.jid
+        if password1 != password2
+          $('#password-error').text 'Passwords must match.'
+          valid = false
+
     else # new user
       if node == ''
         $('#user-name-error').text 'User name is required.'
@@ -158,7 +164,7 @@
     valid

   saveUser: ->
-    return unless this.validateUser()
+    return false unless this.validateUser()
     user =
       jid: $('#jid').val()
       username: $('#user-name').val()
@@ -199,7 +205,7 @@
     valid

   saveSystem: ->
-    return unless this.validateSystem()
+    return false unless this.validateSystem()
     user =
       jid: $('#jid').val()
       username: $('#user-name').val()
@@ -400,7 +406,9 @@
       """).prependTo '#jid-fields'

       $('#name').focus()
-
+      if @session.bareJid() != user.jid
+        $('#password1-label').text 'Password'
+        $('#password2-label').text 'Password Again'
       $('#jid').val user.jid
       $('#name').val user.name
       $('#user-name').val user.jid.split('@')[0]


add support for Asana inbox URLs

add support for Asana inbox URLs

--- scripts/asana-info.coffee
+++ scripts/asana-info.coffee
@@ -19,7 +19,7 @@

 # Listen for Asana deeplinks
 module.exports = (robot) ->
-  robot.hear /app\.asana\.com\/\d{1}\/\d+\/(\d+)/i, (msg) ->
+  robot.hear /app\.asana\.com\/\d{1}\/[inbox\/]*\d+\/(\d+)/i, (msg) ->
     id = msg.match[1]

     # Check for a task first


change menu item height on JSMenuView

change menu item height on JSMenuView

--- JSKit/04_JSMenuView.coffee
+++ JSKit/04_JSMenuView.coffee
@@ -26,7 +26,7 @@
         @_div = "

"
         menustr = ""
         for disp in @_menuitem
-            menustr += "
"+disp+"
"
+            menustr += "
"+disp+"
"
         @_div = @_div.replace(//, menustr)

         if ($(@_viewSelector+"_menu").length)
@@ -36,7 +36,7 @@
         $(@_viewSelector+"_menu").css("left", "0px")
         $(@_viewSelector+"_menu").css("top", "0px")
         $(@_viewSelector+"_menu").css("width", @_frame.size.width+"px")
-        $(@_viewSelector+"_menu").css("height", ((@_frame.size.height + 4) * @_menuitem.length)+"px")
+        $(@_viewSelector+"_menu").css("height", (@_frame.size.height * @_menuitem.length)+"px")
         $(@_viewSelector+"_menu").css("position", "absolute")
         $(@_viewSelector+"_menu").css("overflow", "visible")
         $(@_viewSelector+"_menu").css("font-size", @_textSize+"pt")


Add sku_code

Add sku_code

--- client/skr/models/SkuLoc.coffee
+++ client/skr/models/SkuLoc.coffee
@@ -11,6 +11,7 @@
         qty_picking:  {"type":"integer","required":true,"default":"0"}
         qty_reserved: {"type":"integer","required":true,"default":"0"}
         bin:          "string"
+        sku_code:      {"type":"string","required":true}

     associations:
         sku:         { model: "Sku" }


clear contents when re-using table layout

--- src/tex-writer-mkts-table.coffee
+++ src/tex-writer-mkts-table.coffee
@@ -158,6 +158,13 @@
   return R

 #-----------------------------------------------------------------------------------------------------------
+@clear_contents = ( S, L, layout_name ) ->
+  unless ( target = L.selectors_and_content_events[ layout_name ] )?
+    throw new Error "#{badge} µ65671 unknown layout #{rpr layout_name}"
+  target.length = 0
+  return null
+
+#-----------------------------------------------------------------------------------------------------------
 @get_selectors_and_content_events = ( S, L, layout_name ) ->
   unless ( R = L.selectors_and_content_events[ layout_name ] )?
     debug '88733', L.selectors_and_content_events
@@ -217,6 +224,8 @@
       unless Q.layout?
         throw new Error "#{badge} µ29245 missing required attribute `layout` for <mkts-table-content>: #{rpr event}"
       @push_layout_name S, L, Q.layout
+      ### TAINT might want to add option to keep contents ###
+      @clear_contents S, L, Q.layout
       send stamp event
     #.......................................................................................................
     ### When table contents end, we send all the sub-events needed to draw the table, and then the


:racehorse: Bump tileCount to 6

:racehorse: Bump tileCount to 6

--- src/text-editor-presenter.coffee
+++ src/text-editor-presenter.coffee
@@ -20,7 +20,7 @@
     @measuredHorizontalScrollbarHeight = horizontalScrollbarHeight
     @measuredVerticalScrollbarWidth = verticalScrollbarWidth
     @gutterWidth ?= 0
-    @tileCount ?= 3
+    @tileCount ?= 6

     @disposables = new CompositeDisposable
     @emitter = new Emitter


fixed minor textwrap bug

fixed minor textwrap bug

--- src/textwrap/helpers/wrap.coffee
+++ src/textwrap/helpers/wrap.coffee
@@ -40,8 +40,7 @@
   # Start by trying the largest font size
   sizeMax   = Math.floor(vars.size.value[1])
   lineWidth = if vars.shape.value is "circle" then width * 0.75 else width
-  sizes     = fontSizes words,
-    "font-size": sizeMax + "px"
+  sizes     = fontSizes words, {"font-size": sizeMax + "px"},
     parent: vars.container.value
   maxWidth  = d3.max sizes, (d) -> d.width
   areaMod   = 1.165 + (width / height * 0.11)


extend hubot

extend hubot

--- scripts/chart.coffee
+++ scripts/chart.coffee
@@ -17,9 +17,14 @@

 module.exports = (robot) ->

-  hubot_url = () ->
-    server = robot.server.address()
-    process.env.HEROKU_URL ? "http://#{server.address}:#{server.port}"
+  robot.helper =
+    url: () ->
+      server = robot.server.address()
+      process.env.HEROKU_URL ? "http://#{server.address}:#{server.port}"
+
+  #hubot_url = () ->
+  #  server = robot.server.address()
+  #  process.env.HEROKU_URL ? "http://#{server.address}:#{server.port}"

   robot.respond /chart\s+(\w+)\s+(.+)/i, (msg) ->
     type = msg.match[1]
@@ -31,7 +36,7 @@
       if err
         msg.send "#{err.name}: #{err.message}"
       filename = encodeURIComponent(chart.filename)
-      msg.send "#{hubot_url()}/hubot/charts/#{filename}"
+      msg.send "#{robot.helper.url()}/hubot/charts/#{filename}"

   ## Get an image from `/tmp` dir
   robot.router.get "/hubot/charts/:key", (req, res) ->


add timer to detect if the breadcrumbs parents is hidden

--- src/coffee/ezBreadcrumbs.coffee
+++ src/coffee/ezBreadcrumbs.coffee
@@ -336,8 +336,26 @@
             # execute custom code after the plugin has loaded
             o.opts.onAfterLoad(_this) if $.isFunction(o.opts.onAfterLoad)

+            untilBody = o.el.parentsUntil 'body'
+
+            o.smartCompressionTimer = window.setInterval( ->
+                hiddenParent = false
+
+                untilBody.each ->
+                    if ($ this).is ':hidden'
+                        hiddenParent = true
+
+                        return false
+
+                unless hiddenParent
+                    # trigger the resize event after the plugin has loaded
+                    o.browserWindow.trigger o.resizeKey
+
+                    window.clearInterval o.smartCompressionTimer
+            , 200)
+
             # trigger the resize event after the plugin has loaded
-            o.browserWindow.trigger o.resizeKey
+            # o.browserWindow.trigger o.resizeKey

         o.resize = (e) ->
             current = $ this


fix(baseService): clone rest options to prevent overwriting

--- src/coffee/services/base.coffee
+++ src/coffee/services/base.coffee
@@ -547,7 +547,7 @@
             headers: response.headers
       else {}

-    options = _.omit(@_rest._options, ['access_token'])
+    options = _.deepClone(_.omit(@_rest._options, ['access_token']))
     if options.config
       options.config = _.omit(options.config, ['client_id', 'client_secret'])


fix(base-service): handle 405 errors

fix(base-service): handle 405 errors

--- src/coffee/services/base.coffee
+++ src/coffee/services/base.coffee
@@ -631,8 +631,18 @@
         # we return a custom JSON error message
         reject new SphereHttpError.NotFound "Endpoint '#{endpoint}' not found.",
           _.extend responseJson,
-            statusCode: 404
+            statusCode: response.statusCode
             message: "Endpoint '#{endpoint}' not found."
+            originalRequest: originalRequest
+      else if response.statusCode is 405
+        endpoint = response.request.uri.path
+        # since the API doesn't return an error message for a unsupported method
+        # we return a custom JSON error message
+        errMsg = "The chosen HTTP method is not allowed for the endpoint '#{endpoint}'. This might be caused by a malformed request."
+        reject new SphereHttpError.MethodNotAllowed errMsg,
+          _.extend responseJson,
+            statusCode: response.statusCode
+            message: errMsg
             originalRequest: originalRequest
       else
         # a SphereError response e.g.: {statusCode: 400, message: 'Oops, something went wrong'}


enable storage of metadata for each group

--- bin/comCenter.coffee
+++ bin/comCenter.coffee
@@ -13,6 +13,7 @@
     everyone: null
     port: null
     connectedClients: {}
+    groupData: {}

     # Initialise
@@ -34,6 +35,7 @@
     setupComCenter: ->
         comCenter = @
         connectedClients = @connectedClients
+        groupData = @groupData

         #Trigger when each client connects
         @everyone.on 'connect', ->
@@ -68,6 +70,7 @@
         )

         @everyone.now.joinGroup = (groupName) ->
+            console.log('groupname: '+groupName)
             #remove the client from any rooms he's currently in
             nowjs.getGroup(@now.group).removeUser(@user.clientId)

@@ -79,9 +82,30 @@
             console.log '==========================='
             console.log JSON.stringify(@now.group)

+            #Create the groupData storage object if it doesn't already exist
+            if not groupData[@now.group]?
+                groupData[@now.group] = {}
+

             if @now.group?
                 nowjs.getGroup(@now.group).now.receiveMessage({fromUser:"server", message:"#{@now.name} has joined the session.", messageType:'serverMessage'})
+
+
+            #Tell the new connecting user if the host is connected and run the corresponding function if so
+            if groupData[@now.group].hostConnected == true
+
+                #clientId of the requesting client
+                clientId = @user.clientId
+
+                functionInfo = {functionName:'hostIsConnected',args:groupData[@now.group]}
+
+
+                #Send message to the requesting user
+                nowjs.getClient clientId, ->
+                    @now.receiveMessage({message:functionInfo, fromUser:"server", messageType:'groupFunction'})
+
+
+

         @everyone.now.callGroupFunction = (functionInfo) ->
             #Call a specific function for everyone in a group
@@ -106,6 +130,25 @@
             #Send message to the recipient user
             nowjs.getClient clientId, ->
                 @now.receiveMessage({message:message,fromUser:fromUser,messageType:'privateMessage'})
+
+
+
+
+        @everyone.now.updateGroupData = (data) ->
+            #data should be an object.  Update groupData with the data object
+
+            for key,val of data
+                groupData[@now.group][key] = val
+
+        @everyone.now.connectHost = ->
+            groupData[@now.group].hostConnected = true
+
+            functionInfo = {functionName:'hostIsConnected',args:groupData[@now.group]}
+
+            #Tell all members that the host is connected
+            if @now.group?
+                console.log 'tocall hostIsConnected'
+                nowjs.getGroup(@now.group).now.receiveMessage({message:functionInfo, fromUser:@now.name, messageType:'groupFunction'})

         @everyone.now.addActiveDoc = (docInfo) ->


kill proc on end/error

kill proc on end/error

--- lib/connection/local.coffee
+++ lib/connection/local.coffee
@@ -70,8 +70,12 @@
   connect: (proc, sock) ->
     proc.message = (m) -> sock.write JSON.stringify m
     client.readStream sock
-    sock.on 'end', -> client.detach()
-    sock.on 'error', -> client.detach()
+    sock.on 'end', ->
+      proc.kill()
+      client.detach()
+    sock.on 'error', ->
+      proc.kill()
+      client.detach()
     proc.ready = -> true
     client.flush()
     proc


füge ausnahme für MS Office tmp dateien hinzu #5

--- lib/directory-upload.coffee
+++ lib/directory-upload.coffee
@@ -55,8 +55,8 @@
     # console.log filename
     change=false
     change=true if event=='change'
-    if filename? and filename.indexOf '~$$'<0 and filename.indexOf '.tmp'<0
-      and filename == 'Thumbs.db' #filename dosnt contain ~$$
+    if filename? and filename.indexOf '~$$'<0 and filename.indexOf '.tmp'<0 and filename == 'Thumbs.db' #filename dosnt contain ~$$
+      console.log "File: #{filename}"
       @upload filename,change

   #Lade die Datei ueber Daisy hoch


more appropriate error description

more appropriate error description

--- src/service/classifier.coffee
+++ src/service/classifier.coffee
@@ -182,7 +182,7 @@
     error =
       status: status
       message: http.STATUS_CODES[status]
-      description: "you goofed"
+      description: "Problem with request"

   statuses:
     "authorization": 401


One at a time, fuck this

One at a time, fuck this

--- scripts/karma.coffee
+++ scripts/karma.coffee
@@ -84,24 +84,21 @@
   karma = new Karma robot
   allow_self = process.env.KARMA_ALLOW_SELF or "true"

-  robot.hear /(?:[\(]([\w\d\. ]+)[\)]|([\w\d\.]+))\+\+(\s|$)/g, (msg) ->
-    for subject in msg.match[1..]
-      subject = subject.toLowerCase()
-      if allow_self is true or msg.message.user.name.toLowerCase() != subject
-        karma.increment subject
-        msg.send "#{subject} #{karma.incrementResponse()} (Karma: #{karma.get(subject)})"
-      else
-        msg.send msg.random karma.selfDeniedResponses(msg.message.user.name)
+  robot.hear /(?:[\(]([\w\d\. ]+)[\)]|([\w\d\.]+))\+\+(\s|$)/, (msg) ->
+    subject = msg.match[1].toLowerCase()
+    if allow_self is true or msg.message.user.name.toLowerCase() != subject
+      karma.increment subject
+      msg.send "#{subject} #{karma.incrementResponse()} (Karma: #{karma.get(subject)})"
+    else
+      msg.send msg.random karma.selfDeniedResponses(msg.message.user.name)

   robot.hear /(?:[\(]([\w\d\. ]+)[\)]|([\w\d\.]+))--(\s|$)/, (msg) ->
-    console.log "Matches: #{msg.match}"
-    for subject in msg.match[1..]
-      subject = subject.toLowerCase()
-      if allow_self is true or msg.message.user.name.toLowerCase() != subject
-        karma.decrement subject
-        msg.send "#{subject} #{karma.decrementResponse()} (Karma: #{karma.get(subject)})"
-      else
-        msg.send msg.random karma.selfDeniedResponses(msg.message.user.name)
+    subject = msg.match[1].toLowerCase()
+    if allow_self is true or msg.message.user.name.toLowerCase() != subject
+      karma.decrement subject
+      msg.send "#{subject} #{karma.decrementResponse()} (Karma: #{karma.get(subject)})"
+    else
+      msg.send msg.random karma.selfDeniedResponses(msg.message.user.name)

   robot.respond /karma empty ?(\S+[^-\s])$/i, (msg) ->
     subject = msg.match[1].toLowerCase()


Moved existence test on sh config

Moved existence test on sh config

--- lib/build.coffee
+++ lib/build.coffee
@@ -37,7 +37,6 @@
       delete require.cache[realAtomBuild]
       build = require realAtomBuild
       [ exec, env, args, cwd, sh ] = [ build.cmd, build.env, build.args, build.cwd, build.sh ]
-      sh = true if not sh?

     if !exec && fs.existsSync @root + '/package.json'
       realPackage = fs.realpathSync @root + '/package.json'
@@ -64,7 +63,7 @@
       env: env || {},
       args: args || [],
       cwd: cwd || @root,
-      sh: sh
+      sh: if sh? then sh else true
     }

   replace: (value) ->


enhanced remove() and add _buidlContext()

--- lib/chain.coffee
+++ lib/chain.coffee
@@ -56,12 +56,33 @@
     # it's all good
     return success:true

-  # remove function from the array
+  # remove function from the array via: index, id, or itself
+  #  chain.remove 3
+  #  chain.remove 'some-id'
   #  chain.remove fn1
-  remove: (fn) ->
+  remove: (selector) ->

-    # return -1 unless we find it
-    index = @array.indexOf fn
+    switch typeof selector
+
+      # a string must be an id of one of the functions, so find it
+      when 'string'
+
+        # return -1 unless we find it
+        index = -1
+
+        for fn,i in @array
+          if selector is fn?.options?.id
+            index = i
+            break
+
+      # if they provided the index to use...
+      when 'number' then index = selector
+
+      # find the function in the array
+      when 'function' then index = @array.indexOf selector
+
+      # woh! no good
+      else return error:'Remove requires an ID, an index, or a function.', remove:selector

     # by default, return an empty object because we didn't remove anything
     result = {}
@@ -72,7 +93,7 @@
       result.removed = @array.splice index, 1

       # let everyone know we removed it
-      @emit 'remove', fn
+      @emit 'remove', result.removed

     # and return the result whether it's empty or not
     return result
@@ -85,9 +106,9 @@
       @emit 'remove', array   # emit a remove event with the array

   # main function which begins the execution of the chain
-  # options optionally configures the `context` and the `done`
+  # options optionally configures `context`, `done`, and `_buildContext`
   run: (options, done) ->
-    context = options?.context ? {}                # get context or default to {}
+    context = @_buildContext options               # build/use context
     done = options?.done ? done                    # look for `done`
     control = new Control @, @array, context, done # create controller
     @emit 'start', control:control, chain:this     # notify we're starting
@@ -105,3 +126,15 @@
     control._done? result.error, results
     @emit 'done', result.error, results
     return results
+
+  # allows users to override how a context is built by changing this function.
+  # also, this defualt implementation accepts a base object (prototype) to use
+  # when creating a new context object, and a property descriptor
+  _buildContext: (options) ->
+    # if they specified a context to use, then use it
+    if options?.context? then options.context
+
+    # otherwise, build a new context.
+    # use their specified prototype or an empty object,
+    # and a property descriptor (if specified)
+    else Object.create options?.base ? {}, options?.props


mouse.cancel_weel stops event propagation.

--- engine/events.coffee
+++ engine/events.coffee
@@ -97,7 +97,7 @@
                 touch.touch_target = touch.target = t.target
                 @touch.touch_events[touch.id] = touch
             @touch.touches = event.touches.length
-
+
         if enable_touch
             root_element.addEventListener 'touchstart', touch_start, false

@@ -242,6 +242,7 @@
             # until then, we'll have 1 or -1
             mouse.wheel += Math.max(-1, Math.min(1, event.deltaY))
             if mouse.cancel_wheel
+                event.stopPropagation()
                 event.preventDefault()
         root_element.addEventListener 'wheel', wheel, false


adding guiding for searching for more info about each principle

--- scripts/solid.coffee
+++ scripts/solid.coffee
@@ -23,11 +23,11 @@
   robot.respond /define solid/i, (msg)->
     msg.send "In object-oriented computer programming, the term SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible and maintainable. The principles are a subset of many principles promoted by Robert C. Martin. Though they apply to any object-oriented design, the SOLID principles can also form a core philosophy for methodologies such as agile development or adaptive software development. The SOLID acronym was introduced by Michael Feathers.\n
 They are:\n
-1) Single responsibility principle \n
-2) Open/closed principle \n
-3) Liskov substitution principle \n
-4) Interface segregation principle \n
-5) Dependency inversion principle"
+1) (SRP) Single responsibility principle. Run `doc define SRP` for more info. \n
+2) (OCP) Open/closed principle. Run `doc define OCP` for more info. \n
+3) (LSP) Liskov substitution principle. Run `doc define LSP` for more info. \n
+4) (ISP) Interface segregation principle. Run `doc define ISP` for more info. \n
+5) (DIP) Dependency inversion principle. Run `doc define DIP` for more info."

   robot.respond /define SRP/i, (msg)->
     msg.send "Single responsibility principle. A class should have only a single responsibility (i.e. changes to only one part of the software's specification should be able to affect the specification of the class)."


some cleanup for PlotView, reorg as render_init, render_canvas, and render

--- static/coffee/common/plot.coffee
+++ static/coffee/common/plot.coffee
@@ -20,13 +20,6 @@
   view_options: () ->
     _.extend({plot_model: @model, plot_view: @}, @options)

-  build_tools: () ->
-    build_views(@tools, @mget_obj('tools'), @view_options())
-
-  bind_tools: () ->
-    for toolspec in @mget('tools')
-      @tools[toolspec.id].bind_events(this)
-
   events:
     "mousemove .bokeh_canvas_wrapper": "_mousemove"
     "mousedown .bokeh_canvas_wrapper": "_mousedown"
@@ -48,11 +41,17 @@

   request_render : () ->
     if not @is_paused
-      @throttled()
+      @throttled_render()
     return

+  request_render_canvas : () ->
+    if not @is_paused
+      @throttled_render_canvas()
+    return
+
   initialize: (options) ->
-    @throttled = _.throttle(@render_deferred_components, 50)
+    @throttled_render = _.throttle(@render, 50)
+    @throttled_render_canvas = _.throttle(@render_canvas, 30)

     super(_.defaults(options, @default_options))

@@ -96,7 +95,7 @@
     @mousedownCallbacks = []
     @keydownCallbacks = []
     @render_init()
-    @render()
+    @render_canvas()
     @build_views()
     @request_render()
     return this
@@ -125,16 +124,14 @@

     return [x, y]

-  render_init: () ->
-    #FIXME template
-    @$el.append($("""
-

-

-        <canvas class='bokeh_canvas'></canvas>
-

-      """))
-    @canvas_wrapper = @$el.find('.bokeh_canvas_wrapper')
-    @canvas = @$el.find('canvas.bokeh_canvas')
+  build_tools: () ->
+    build_views(@tools, @mget_obj('tools'), @view_options())
+    return this
+
+  bind_tools: () ->
+    for toolspec in @mget('tools')
+      @tools[toolspec.id].bind_events(this)
+    return this

   build_views: ()->
     build_views(@renderers, @mget_obj('renderers'), @view_options())
@@ -158,9 +155,10 @@

     @build_tools()
     @bind_tools()
+    return this

   bind_bokeh_events: () ->
-    safebind(this, @view_state, 'change', @render)
+    safebind(this, @view_state, 'change', @request_render_canvas)
     safebind(this, @x_range, 'change', @request_render)
     safebind(this, @y_range, 'change', @request_render)
     safebind(this, @model, 'change:renderers', @build_views)
@@ -168,19 +166,18 @@
     safebind(this, @model, 'change', @render)
     safebind(this, @model, 'destroy', () => @remove())

-  # FIXME document throughly when render is called vs render_deferred
-  # should we have a "render_init" "render" and a
-  # "render_canvas" function add_dom is called at instatiation.
-  # "render" is called for plot resizing.  render_canvas is called
-  # when changes to the canvas are desired.  A ScatterRendererView
-  # would only have a "render_canvas function
-
-  render: () ->
-    if @is_paused
-      return
-
-    super()
-
+  render_init: () ->
+    # TODO use template
+    @$el.append($("""
+

+

+        <canvas class='bokeh_canvas'></canvas>
+

+      """))
+    @canvas_wrapper = @$el.find('.bokeh_canvas_wrapper')
+    @canvas = @$el.find('canvas.bokeh_canvas')
+
+  render_canvas: () ->
     oh = @view_state.get('outer_height')
     ow = @view_state.get('outer_width')

@@ -190,9 +187,12 @@

     @ctx = @canvas[0].getContext('2d')

+    @render();
+
     @render_end()

-  render_deferred_components: (force) ->
+  render: (force) ->
+    super()
     @ctx.fillStyle = @mget('border_fill')
     @ctx.fillRect(0,0,  @view_state.get('canvas_width'), @view_state.get('canvas_height'))
     @ctx.fillStyle = @mget('background_fill')
@@ -211,20 +211,15 @@
     @ctx.clip()
     @ctx.beginPath()

-    for k, v of @images
-      v.render()
-    for k, v of @underlays
-      v.render()
-    for k, v of @glyphs
-      v.render()
+    for level in [@images, @underlays, @glyphs]
+      for k, v of level
+        v.render()

     @ctx.restore()

-    for k, v of @overlays
-      v.render()
-    for k, v of @annotations
-      v.render()
-
+    for level in [@overlays, @annotations]
+      for k, v of @overlays
+        v.render()

 class Plot extends HasParent
   type: 'Plot'


Options; release focus on clicking advanced.

When the show/hide advanced options link is clicked, it gains the focus,
and the URL is displayed by chrome in the bottom-left corder of the
window.  This partially obscures the footer, so we immediately blur the
link.

Also, same for the "show help" link.

--- pages/options.coffee
+++ pages/options.coffee
@@ -152,9 +152,13 @@
         $("advancedOptionsLink").innerHTML = "Hide advanced options"
       advancedMode = !advancedMode
       event.preventDefault()
+      # Prevent the "advanced options" link from retaining the focus.
+      document.activeElement.blur()

 activateHelpDialog = ->
   showHelpDialog chrome.extension.getBackgroundPage().helpDialogHtml(true, true, "Command Listing"), frameId
+  # Prevent the "show help" link from retaining the focus.
+  document.activeElement.blur()

 #
 # Initialization.


Better event interval execution.

Better event interval execution.

- Use later.js's execution API to fire events.
- Humanize tminus "now".

--- lib/event-watch-view.coffee
+++ lib/event-watch-view.coffee
@@ -35,7 +35,10 @@

   # Private: Returns humanized remaining time string.
   formatTminus: (dt, fromTime) ->
-    moment.duration(dt - fromTime).humanize()
+    dt = moment.duration(dt - fromTime)
+    if dt < moment.duration(1, 'seconds')
+      return 'now'
+    dt.humanize()

   # Private: Returns formatted time string.
   formatTime: (dt, fromTime) ->
@@ -198,16 +201,17 @@
       @watchConfig key

   # Private: Sets up timeout for next update.
-  # Use optional interval (in miliseconds) if given, otherwise use configuration setting.
+  # Use optional interval (in minutes) if given, otherwise use configuration setting.
   startTimer: (interval) ->
-    interval = @refreshIntervalMinutes * 60000 if !interval
-    if @timer
-      clearInterval(@timer)
-    @timer = setInterval((=> @update()), interval)
+    interval = @refreshIntervalMinutes if !interval
+    @stopTimer()
+    sched = later.parse.recur().every(interval).minute()
+    @timer = later.setInterval (=> @update()), sched

   # Private: Stops timeout for next update.
   stopTimer: ->
-    clearInterval(@timer)
+    if @timer
+      @timer.clear()

   # Private: Create DOM element of given type with given classes.
   createElement: (type, classes...) ->
@@ -280,7 +284,7 @@
     @hasWarning = @displayEvents()
     @generateTooltipTitle()
     if !wasWarning && @hasWarning
-      @startTimer 60000  # 1 minute refresh during warnings
+      @startTimer 1  # 1 minute refresh during warnings
     else if wasWarning && !@hasWarning
       @startTimer()