fragments and .js files.",token);}
+if(option.fragment){if(n!=='div'){error("ADsafe violation: Wrap the widget in a div.",token);}}else{error("Use the fragment option.",token);}}
+option.browser=true;assume();}
+function doAttribute(n,a,v){var u,x;if(a==='id'){u=typeof v==='string'?v.toUpperCase():'';if(ids[u]===true){warning("Duplicate id='{a}'.",nexttoken,v);}
+if(option.adsafe){if(adsafe_id){if(v.slice(0,adsafe_id.length)!==adsafe_id){warning("ADsafe violation: An id must have a '{a}' prefix",nexttoken,adsafe_id);}else if(!/^[A-Z]+_[A-Z]+$/.test(v)){warning("ADSAFE violation: bad id.");}}else{adsafe_id=v;if(!/^[A-Z]+_$/.test(v)){warning("ADSAFE violation: bad id.");}}}
+x=v.search(dx);if(x>=0){warning("Unexpected character '{a}' in {b}.",token,v.charAt(x),a);}
+ids[u]=true;}else if(a==='class'||a==='type'||a==='name'){x=v.search(qx);if(x>=0){warning("Unexpected character '{a}' in {b}.",token,v.charAt(x),a);}
+ids[u]=true;}else if(a==='href'||a==='background'||a==='content'||a==='data'||a.indexOf('src')>=0||a.indexOf('url')>=0){if(option.safe&&ux.test(v)){error("ADsafe URL violation.");}
+urls.push(v);}else if(a==='for'){if(option.adsafe){if(adsafe_id){if(v.slice(0,adsafe_id.length)!==adsafe_id){warning("ADsafe violation: An id must have a '{a}' prefix",nexttoken,adsafe_id);}else if(!/^[A-Z]+_[A-Z]+$/.test(v)){warning("ADSAFE violation: bad id.");}}else{warning("ADSAFE violation: bad id.");}}}else if(a==='name'){if(option.adsafe&&v.indexOf('_')>=0){warning("ADsafe name violation.");}}}
+function doTag(n,a){var i,t=htmltag[n],x;src=false;if(!t){error("Unrecognized tag '<{a}>'.",nexttoken,n===n.toLowerCase()?n:n+' (capitalization error)');}
+if(stack.length>0){if(n==='html'){error("Too many tags.",token);}
+x=t.parent;if(x){if(x.indexOf(' '+stack[stack.length-1].name+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}}else if(!option.adsafe&&!option.fragment){i=stack.length;do{if(i<=0){error("A '<{a}>' must be within '<{b}>'.",token,n,'body');}
+i-=1;}while(stack[i].name!=='body');}}
+switch(n){case'div':if(option.adsafe&&stack.length===1&&!adsafe_id){warning("ADSAFE violation: missing ID_.");}
+break;case'script':xmode='script';advance('>');indent=nexttoken.from;if(a.lang){warning("lang is deprecated.",token);}
+if(option.adsafe&&stack.length!==1){warning("ADsafe script placement violation.",token);}
+if(a.src){if(option.adsafe&&(!adsafe_may||!approved[a.src])){warning("ADsafe unapproved script source.",token);}
+if(a.type){warning("type is unnecessary.",token);}}else{if(adsafe_went){error("ADsafe script violation.",token);}
+statements('script');}
+xmode='html';advance('');if(!nexttoken.identifier&&nexttoken.value!=='script'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'script',nexttoken.value);}
+advance();xmode='outer';break;case'style':xmode='style';advance('>');styles();xmode='html';advance('');if(!nexttoken.identifier&&nexttoken.value!=='style'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'style',nexttoken.value);}
+advance();xmode='outer';break;case'input':switch(a.type){case'radio':case'checkbox':case'button':case'reset':case'submit':break;case'text':case'file':case'password':case'file':case'hidden':case'image':if(option.adsafe&&a.autocomplete!=='off'){warning("ADsafe autocomplete violation.");}
+break;default:warning("Bad input type.");}
+break;case'applet':case'body':case'embed':case'frame':case'frameset':case'head':case'iframe':case'noembed':case'noframes':case'object':case'param':if(option.adsafe){warning("ADsafe violation: Disallowed tag: "+n);}
+break;}}
+function closetag(n){return''+n+'>';}
+function html(){var a,attributes,e,n,q,t,v,w=option.white,wmode;xmode='html';xquote='';stack=null;for(;;){switch(nexttoken.value){case'<':xmode='html';advance('<');attributes={};t=nexttoken;if(!t.identifier){warning("Bad identifier {a}.",t,t.value);}
+n=t.value;if(option.cap){n=n.toLowerCase();}
+t.name=n;advance();if(!stack){stack=[];doBegin(n);}
+v=htmltag[n];if(typeof v!=='object'){error("Unrecognized tag '<{a}>'.",t,n);}
+e=v.empty;t.type=n;for(;;){if(nexttoken.id==='/'){advance('/');if(nexttoken.id!=='>'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'>',nexttoken.value);}
+break;}
+if(nexttoken.id&&nexttoken.id.substr(0,1)==='>'){break;}
+if(!nexttoken.identifier){if(nexttoken.id==='(end)'||nexttoken.id==='(error)'){error("Missing '>'.",nexttoken);}
+warning("Bad identifier.");}
+option.white=true;nonadjacent(token,nexttoken);a=nexttoken.value;option.white=w;advance();if(!option.cap&&a!==a.toLowerCase()){warning("Attribute '{a}' not all lower case.",nexttoken,a);}
+a=a.toLowerCase();xquote='';if(is_own(attributes,a)){warning("Attribute '{a}' repeated.",nexttoken,a);}
+if(a.slice(0,2)==='on'){if(!option.on){warning("Avoid HTML event handlers.");}
+xmode='scriptstring';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
+xquote=q;wmode=option.white;option.white=false;advance(q);statements('on');option.white=wmode;if(nexttoken.id!==q){error("Missing close quote on script attribute.");}
+xmode='html';xquote='';advance(q);v=false;}else if(a==='style'){xmode='scriptstring';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
+xmode='styleproperty';xquote=q;advance(q);substyle();xmode='html';xquote='';advance(q);v=false;}else{if(nexttoken.id==='='){advance('=');v=nexttoken.value;if(!nexttoken.identifier&&nexttoken.id!=='"'&&nexttoken.id!=='\''&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'&&nexttoken.type!=='(color)'){warning("Expected an attribute value and instead saw '{a}'.",token,a);}
+advance();}else{v=true;}}
+attributes[a]=v;doAttribute(n,a,v);}
+doTag(n,attributes);if(!e){stack.push(t);}
+xmode='outer';advance('>');break;case'':xmode='html';advance('');if(!nexttoken.identifier){warning("Bad identifier.");}
+n=nexttoken.value;if(option.cap){n=n.toLowerCase();}
+advance();if(!stack){error("Unexpected '{a}'.",nexttoken,closetag(n));}
+t=stack.pop();if(!t){error("Unexpected '{a}'.",nexttoken,closetag(n));}
+if(t.name!==n){error("Expected '{a}' and instead saw '{b}'.",nexttoken,closetag(t.name),closetag(n));}
+if(nexttoken.id!=='>'){error("Missing '{a}'.",nexttoken,'>');}
+xmode='outer';advance('>');break;case''||nexttoken.id==='(end)'){break;}
+if(nexttoken.value.indexOf('--')>=0){warning("Unexpected --.");}
+if(nexttoken.value.indexOf('<')>=0){warning("Unexpected <.");}
+if(nexttoken.value.indexOf('>')>=0){warning("Unexpected >.");}}
+xmode='outer';advance('>');break;case'(end)':return;default:if(nexttoken.id==='(end)'){error("Missing '{a}'.",nexttoken,''+stack[stack.length-1].value+'>');}else{advance();}}
+if(stack&&stack.length===0&&(option.adsafe||!option.fragment||nexttoken.id==='(end)')){break;}}
+if(nexttoken.id!=='(end)'){error("Unexpected material after the end.");}}
+type('(number)',idValue);type('(string)',idValue);syntax['(identifier)']={type:'(identifier)',lbp:0,identifier:true,nud:function(){var v=this.value,s=scope[v],f;if(typeof s==='function'){s=undefined;}else if(typeof s==='boolean'){f=funct;funct=functions[0];addlabel(v,'var');s=funct;funct=f;}
+if(funct===s){switch(funct[v]){case'unused':funct[v]='var';break;case'label':warning("'{a}' is a statement label.",token,v);break;}}else if(funct['(global)']){if(option.undef&&predefined[v]!=='boolean'){warning("'{a}' is not defined.",token,v);}
+note_implied(token);}else{switch(funct[v]){case'closure':case'function':case'var':case'unused':warning("'{a}' used out of scope.",token,v);break;case'label':warning("'{a}' is a statement label.",token,v);break;case'outer':case'global':break;default:if(s===true){funct[v]=true;}else if(s===null){warning("'{a}' is not allowed.",token,v);note_implied(token);}else if(typeof s!=='object'){if(option.undef){warning("'{a}' is not defined.",token,v);}else{funct[v]=true;}
+note_implied(token);}else{switch(s[v]){case'function':case'var':case'unused':s[v]='closure';funct[v]=s['(global)']?'global':'outer';break;case'closure':case'parameter':funct[v]=s['(global)']?'global':'outer';break;case'label':warning("'{a}' is a statement label.",token,v);}}}}
+return this;},led:function(){error("Expected an operator and instead saw '{a}'.",nexttoken,nexttoken.value);}};type('(regexp)',function(){return this;});delim('(endline)');delim('(begin)');delim('(end)').reach=true;delim('').reach=true;delim('');delim('(error)').reach=true;delim('}').reach=true;delim(')');delim(']');delim('"').reach=true;delim("'").reach=true;delim(';');delim(':').reach=true;delim(',');delim('#');delim('@');reserve('else');reserve('case').reach=true;reserve('catch');reserve('default').reach=true;reserve('finally');reservevar('arguments');reservevar('eval');reservevar('false');reservevar('Infinity');reservevar('NaN');reservevar('null');reservevar('this');reservevar('true');reservevar('undefined');assignop('=','assign',20);assignop('+=','assignadd',20);assignop('-=','assignsub',20);assignop('*=','assignmult',20);assignop('/=','assigndiv',20).nud=function(){error("A regular expression literal can be confused with '/='.");};assignop('%=','assignmod',20);bitwiseassignop('&=','assignbitand',20);bitwiseassignop('|=','assignbitor',20);bitwiseassignop('^=','assignbitxor',20);bitwiseassignop('<<=','assignshiftleft',20);bitwiseassignop('>>=','assignshiftright',20);bitwiseassignop('>>>=','assignshiftrightunsigned',20);infix('?',function(left,that){that.left=left;that.right=parse(10);advance(':');that['else']=parse(10);return that;},30);infix('||','or',40);infix('&&','and',50);bitwise('|','bitor',70);bitwise('^','bitxor',80);bitwise('&','bitand',90);relation('==',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'===','==');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'===',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'===',right.value);}
+return this;});relation('===');relation('!=',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'!==','!=');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'!==',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'!==',right.value);}
+return this;});relation('!==');relation('<');relation('>');relation('<=');relation('>=');bitwise('<<','shiftleft',120);bitwise('>>','shiftright',120);bitwise('>>>','shiftrightunsigned',120);infix('in','in',120);infix('instanceof','instanceof',120);infix('+',function(left,that){var right=parse(130);if(left&&right&&left.id==='(string)'&&right.id==='(string)'){left.value+=right.value;left.character=right.character;if(jx.test(left.value)){warning("JavaScript URL.",left);}
+return left;}
+that.left=left;that.right=right;return that;},130);prefix('+','num');infix('-','sub',130);prefix('-','neg');infix('*','mult',140);infix('/','div',140);infix('%','mod',140);suffix('++','postinc');prefix('++','preinc');syntax['++'].exps=true;suffix('--','postdec');prefix('--','predec');syntax['--'].exps=true;prefix('delete',function(){var p=parse(0);if(!p||(p.id!=='.'&&p.id!=='[')){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'.',nexttoken.value);}
+this.first=p;return this;}).exps=true;prefix('~',function(){if(option.bitwise){warning("Unexpected '{a}'.",this,'~');}
+parse(150);return this;});prefix('!',function(){this.right=parse(150);this.arity='unary';if(bang[this.right.id]===true){warning("Confusing use of '{a}'.",this,'!');}
+return this;});prefix('typeof','typeof');prefix('new',function(){var c=parse(155),i;if(c&&c.id!=='function'){if(c.identifier){c['new']=true;switch(c.value){case'Object':warning("Use the object literal notation {}.",token);break;case'Array':if(nexttoken.id!=='('){warning("Use the array literal notation [].",token);}else{advance('(');if(nexttoken.id===')'){warning("Use the array literal notation [].",token);}else{i=parse(0);c.dimension=i;if((i.id==='(number)'&&/[.+\-Ee]/.test(i.value))||(i.id==='-'&&!i.right)||i.id==='(string)'||i.id==='['||i.id==='{'||i.id==='true'||i.id==='false'||i.id==='null'||i.id==='undefined'||i.id==='Infinity'){warning("Use the array literal notation [].",token);}
+if(nexttoken.id!==')'){error("Use the array literal notation [].",token);}}
+advance(')');}
+this.first=c;return this;case'Number':case'String':case'Boolean':case'Math':case'JSON':warning("Do not use {a} as a constructor.",token,c.value);break;case'Function':if(!option.evil){warning("The Function constructor is eval.");}
+break;case'Date':case'RegExp':break;default:if(c.id!=='function'){i=c.value.substr(0,1);if(option.newcap&&(i<'A'||i>'Z')){warning("A constructor name should start with an uppercase letter.",token);}}}}else{if(c.id!=='.'&&c.id!=='['&&c.id!=='('){warning("Bad constructor.",token);}}}else{warning("Weird construction. Delete 'new'.",this);}
+adjacent(token,nexttoken);if(nexttoken.id!=='('){warning("Missing '()' invoking a constructor.");}
+this.first=c;return this;});syntax['new'].exps=true;infix('.',function(left,that){adjacent(prevtoken,token);var m=identifier();if(typeof m==='string'){countMember(m);}
+that.left=left;that.right=m;if(!option.evil&&left&&left.value==='document'&&(m==='write'||m==='writeln')){warning("document.write can be a form of eval.",left);}else if(option.adsafe){if(left&&left.value==='ADSAFE'){if(m==='id'||m==='lib'){warning("ADsafe violation.",that);}else if(m==='go'){if(xmode!=='script'){warning("ADsafe violation.",that);}else if(adsafe_went||nexttoken.id!=='('||peek(0).id!=='(string)'||peek(0).value!==adsafe_id||peek(1).id!==','){error("ADsafe violation: go.",that);}
+adsafe_went=true;adsafe_may=false;}}}
+if(!option.evil&&(m==='eval'||m==='execScript')){warning('eval is evil.');}else if(option.safe){for(;;){if(banned[m]===true){warning("ADsafe restricted word '{a}'.",token,m);}
+if(typeof predefined[left.value]!=='boolean'||nexttoken.id==='('){break;}
+if(standard_member[m]===true){if(nexttoken.id==='.'){warning("ADsafe violation.",that);}
+break;}
+if(nexttoken.id!=='.'){warning("ADsafe violation.",that);break;}
+advance('.');token.left=that;token.right=m;that=token;m=identifier();if(typeof m==='string'){countMember(m);}}}
+return that;},160,true);infix('(',function(left,that){adjacent(prevtoken,token);nospace();var n=0,p=[];if(left){if(left.type==='(identifier)'){if(left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)){if(left.value!=='Number'&&left.value!=='String'&&left.value!=='Boolean'&&left.value!=='Date'){if(left.value==='Math'){warning("Math is not a function.",left);}else if(option.newcap){warning("Missing 'new' prefix when invoking a constructor.",left);}}}}else if(left.id==='.'){if(option.safe&&left.left.value==='Math'&&left.right==='random'){warning("ADsafe violation.",left);}}}
+if(nexttoken.id!==')'){for(;;){p[p.length]=parse(10);n+=1;if(nexttoken.id!==','){break;}
+comma();}}
+advance(')');if(option.immed&&left.id==='function'&&nexttoken.id!==')'){warning("Wrap the entire immediate function invocation in parens.",that);}
+nospace(prevtoken,token);if(typeof left==='object'){if(left.value==='parseInt'&&n===1){warning("Missing radix parameter.",left);}
+if(!option.evil){if(left.value==='eval'||left.value==='Function'||left.value==='execScript'){warning("eval is evil.",left);}else if(p[0]&&p[0].id==='(string)'&&(left.value==='setTimeout'||left.value==='setInterval')){warning("Implied eval is evil. Pass a function instead of a string.",left);}}
+if(!left.identifier&&left.id!=='.'&&left.id!=='['&&left.id!=='('&&left.id!=='&&'&&left.id!=='||'&&left.id!=='?'){warning("Bad invocation.",left);}}
+that.left=left;return that;},155,true).exps=true;prefix('(',function(){nospace();var v=parse(0);advance(')',this);nospace(prevtoken,token);if(option.immed&&v.id==='function'){if(nexttoken.id==='('){warning("Move the invocation into the parens that contain the function.",nexttoken);}else{warning("Do not wrap function literals in parens unless they are to be immediately invoked.",this);}}
+return v;});infix('[',function(left,that){nospace();var e=parse(0),s;if(e&&e.type==='(string)'){if(option.safe&&banned[e.value]===true){warning("ADsafe restricted word '{a}'.",that,e.value);}else if(!option.evil&&(e.value==='eval'||e.value==='execScript')){warning("eval is evil.",that);}else if(option.safe&&(e.value.charAt(0)==='_'||e.value.charAt(0)==='-')){warning("ADsafe restricted subscript '{a}'.",that,e.value);}
+countMember(e.value);if(!option.sub&&ix.test(e.value)){s=syntax[e.value];if(!s||!s.reserved){warning("['{a}'] is better written in dot notation.",e,e.value);}}}else if(!e||e.type!=='(number)'||e.value<0){if(option.safe){warning('ADsafe subscripting.');}}
+advance(']',that);nospace(prevtoken,token);that.left=left;that.right=e;return that;},160,true);prefix('[',function(){var b=token.line!==nexttoken.line;this.first=[];if(b){indent+=option.indent;if(nexttoken.from===indent+option.indent){indent+=option.indent;}}
+while(nexttoken.id!=='(end)'){while(nexttoken.id===','){warning("Extra comma.");advance(',');}
+if(nexttoken.id===']'){break;}
+if(b&&token.line!==nexttoken.line){indentation();}
+this.first.push(parse(10));if(nexttoken.id===','){comma();if(nexttoken.id===']'){warning("Extra comma.",token);break;}}else{break;}}
+if(b){indent-=option.indent;indentation();}
+advance(']',this);return this;},160);(function(x){x.nud=function(){var b,i,s,seen={};b=token.line!==nexttoken.line;if(b){indent+=option.indent;if(nexttoken.from===indent+option.indent){indent+=option.indent;}}
+for(;;){if(nexttoken.id==='}'){break;}
+if(b){indentation();}
+i=optionalidentifier(true);if(!i){if(nexttoken.id==='(string)'){i=nexttoken.value;if(ix.test(i)){s=syntax[i];}
+advance();}else if(nexttoken.id==='(number)'){i=nexttoken.value.toString();advance();}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'}',nexttoken.value);}}
+if(seen[i]===true){warning("Duplicate member '{a}'.",nexttoken,i);}
+seen[i]=true;countMember(i);advance(':');nonadjacent(token,nexttoken);parse(10);if(nexttoken.id===','){comma();if(nexttoken.id===','||nexttoken.id==='}'){warning("Extra comma.",token);}}else{break;}}
+if(b){indent-=option.indent;indentation();}
+advance('}',this);return this;};x.fud=function(){error("Expected to see a statement and instead saw a block.",token);};}(delim('{')));function varstatement(prefix){var id,name,value;if(funct['(onevar)']&&option.onevar){warning("Too many var statements.");}else if(!funct['(global)']){funct['(onevar)']=true;}
+this.first=[];for(;;){nonadjacent(token,nexttoken);id=identifier();if(funct['(global)']&&predefined[id]===false){warning("Redefinition of '{a}'.",token,id);}
+addlabel(id,'unused');if(prefix){break;}
+name=token;this.first.push(token);if(nexttoken.id==='='){nonadjacent(token,nexttoken);advance('=');nonadjacent(token,nexttoken);if(peek(0).id==='='&&nexttoken.identifier){error("Variable {a} was not declared correctly.",nexttoken,nexttoken.value);}
+value=parse(0);name.first=value;}
+if(nexttoken.id!==','){break;}
+comma();}
+return this;}
+stmt('var',varstatement).exps=true;function functionparams(){var i,t=nexttoken,p=[];advance('(');nospace();if(nexttoken.id===')'){advance(')');nospace(prevtoken,token);return;}
+for(;;){i=identifier();p.push(i);addlabel(i,'parameter');if(nexttoken.id===','){comma();}else{advance(')',t);nospace(prevtoken,token);return p;}}}
+function doFunction(i){var s=scope;scope=Object.create(s);funct={'(name)':i||'"'+anonname+'"','(line)':nexttoken.line,'(context)':funct,'(breakage)':0,'(loopage)':0,'(scope)':scope};token.funct=funct;functions.push(funct);if(i){addlabel(i,'function');}
+funct['(params)']=functionparams();block(false);scope=s;funct['(last)']=token.line;funct=funct['(context)'];}
+blockstmt('function',function(){if(inblock){warning("Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.",token);}
+var i=identifier();adjacent(token,nexttoken);addlabel(i,'unused');doFunction(i);if(nexttoken.id==='('&&nexttoken.line===token.line){error("Function statements are not invocable. Wrap the whole function invocation in parens.");}
+return this;});prefix('function',function(){var i=optionalidentifier();if(i){adjacent(token,nexttoken);}else{nonadjacent(token,nexttoken);}
+doFunction(i);if(funct['(loopage)']&&nexttoken.id!=='('){warning("Be careful when making functions within a loop. Consider putting the function in a closure.");}
+return this;});blockstmt('if',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);if(nexttoken.id==='else'){nonadjacent(token,nexttoken);advance('else');if(nexttoken.id==='if'||nexttoken.id==='switch'){statement(true);}else{block(true);}}
+return this;});blockstmt('try',function(){var b,e,s;if(option.adsafe){warning("ADsafe try violation.",this);}
+block(false);if(nexttoken.id==='catch'){advance('catch');nonadjacent(token,nexttoken);advance('(');s=scope;scope=Object.create(s);e=nexttoken.value;if(nexttoken.type!=='(identifier)'){warning("Expected an identifier and instead saw '{a}'.",nexttoken,e);}else{addlabel(e,'exception');}
+advance();advance(')');block(false);b=true;scope=s;}
+if(nexttoken.id==='finally'){advance('finally');block(false);return;}else if(!b){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'catch',nexttoken.value);}
+return this;});blockstmt('while',function(){var t=nexttoken;funct['(breakage)']+=1;funct['(loopage)']+=1;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}).labelled=true;reserve('with');blockstmt('switch',function(){var t=nexttoken,g=false;funct['(breakage)']+=1;advance('(');nonadjacent(this,t);nospace();this.condition=parse(20);advance(')',t);nospace(prevtoken,token);nonadjacent(token,nexttoken);t=nexttoken;advance('{');nonadjacent(token,nexttoken);indent+=option.indent;this.cases=[];for(;;){switch(nexttoken.id){case'case':switch(funct['(verb)']){case'break':case'case':case'continue':case'return':case'switch':case'throw':break;default:warning("Expected a 'break' statement before 'case'.",token);}
+indentation(-option.indent);advance('case');this.cases.push(parse(20));g=true;advance(':');funct['(verb)']='case';break;case'default':switch(funct['(verb)']){case'break':case'continue':case'return':case'throw':break;default:warning("Expected a 'break' statement before 'default'.",token);}
+indentation(-option.indent);advance('default');g=true;advance(':');break;case'}':indent-=option.indent;indentation();advance('}',t);if(this.cases.length===1||this.condition.id==='true'||this.condition.id==='false'){warning("This 'switch' should be an 'if'.",this);}
+funct['(breakage)']-=1;funct['(verb)']=undefined;return;case'(end)':error("Missing '{a}'.",nexttoken,'}');return;default:if(g){switch(token.id){case',':error("Each value should have its own case label.");return;case':':statements();break;default:error("Missing ':' on a case clause.",token);}}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'case',nexttoken.value);}}}}).labelled=true;stmt('debugger',function(){if(!option.debug){warning("All 'debugger' statements should be removed.");}
+return this;}).exps=true;(function(){var x=stmt('do',function(){funct['(breakage)']+=1;funct['(loopage)']+=1;this.first=block(true);advance('while');var t=nexttoken;nonadjacent(token,t);advance('(');nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;});x.labelled=true;x.exps=true;}());blockstmt('for',function(){var f=option.forin,s,t=nexttoken;funct['(breakage)']+=1;funct['(loopage)']+=1;advance('(');nonadjacent(this,t);nospace();if(peek(nexttoken.id==='var'?1:0).id==='in'){if(nexttoken.id==='var'){advance('var');varstatement(true);}else{switch(funct[nexttoken.value]){case'unused':funct[nexttoken.value]='var';break;case'var':break;default:warning("Bad for in variable '{a}'.",nexttoken,nexttoken.value);}
+advance();}
+advance('in');parse(20);advance(')',t);s=block(true);if(!f&&(s.length>1||typeof s[0]!=='object'||s[0].value!=='if')){warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.",this);}
+funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}else{if(nexttoken.id!==';'){if(nexttoken.id==='var'){advance('var');varstatement();}else{for(;;){parse(0,'for');if(nexttoken.id!==','){break;}
+comma();}}}
+nolinebreak(token);advance(';');if(nexttoken.id!==';'){parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}}
+nolinebreak(token);advance(';');if(nexttoken.id===';'){error("Expected '{a}' and instead saw '{b}'.",nexttoken,')',';');}
+if(nexttoken.id!==')'){for(;;){parse(0,'for');if(nexttoken.id!==','){break;}
+comma();}}
+advance(')',t);nospace(prevtoken,token);block(true);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}}).labelled=true;stmt('break',function(){var v=nexttoken.value;if(funct['(breakage)']===0){warning("Unexpected '{a}'.",nexttoken,this.value);}
+nolinebreak(this);if(nexttoken.id!==';'){if(token.line===nexttoken.line){if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+this.first=nexttoken;advance();}}
+reachable('break');return this;}).exps=true;stmt('continue',function(){var v=nexttoken.value;if(funct['(breakage)']===0){warning("Unexpected '{a}'.",nexttoken,this.value);}
+nolinebreak(this);if(nexttoken.id!==';'){if(token.line===nexttoken.line){if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+this.first=nexttoken;advance();}}
+reachable('continue');return this;}).exps=true;stmt('return',function(){nolinebreak(this);if(nexttoken.id==='(regexp)'){warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");}
+if(nexttoken.id!==';'&&!nexttoken.reach){nonadjacent(token,nexttoken);this.first=parse(20);}
+reachable('return');return this;}).exps=true;stmt('throw',function(){nolinebreak(this);nonadjacent(token,nexttoken);this.first=parse(20);reachable('throw');return this;}).exps=true;reserve('void');reserve('class');reserve('const');reserve('enum');reserve('export');reserve('extends');reserve('import');reserve('super');reserve('let');reserve('yield');reserve('implements');reserve('interface');reserve('package');reserve('private');reserve('protected');reserve('public');reserve('static');function jsonValue(){function jsonObject(){var o={},t=nexttoken;advance('{');if(nexttoken.id!=='}'){for(;;){if(nexttoken.id==='(end)'){error("Missing '}' to match '{' from line {a}.",nexttoken,t.line);}else if(nexttoken.id==='}'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}else if(nexttoken.id!=='(string)'){warning("Expected a string and instead saw {a}.",nexttoken,nexttoken.value);}
+if(o[nexttoken.value]===true){warning("Duplicate key '{a}'.",nexttoken,nexttoken.value);}else if(nexttoken.value==='__proto__'){warning("Stupid key '{a}'.",nexttoken,nexttoken.value);}else{o[nexttoken.value]=true;}
+advance();advance(':');jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance('}');}
+function jsonArray(){var t=nexttoken;advance('[');if(nexttoken.id!==']'){for(;;){if(nexttoken.id==='(end)'){error("Missing ']' to match '[' from line {a}.",nexttoken,t.line);}else if(nexttoken.id===']'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}
+jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(']');}
+switch(nexttoken.id){case'{':jsonObject();break;case'[':jsonArray();break;case'true':case'false':case'null':case'(number)':case'(string)':advance();break;case'-':advance('-');if(token.character!==nexttoken.from){warning("Unexpected space after '-'.",token);}
+adjacent(token,nexttoken);advance('(number)');break;default:error("Expected a JSON value.",nexttoken);}}
+var itself=function(s,o){var a,i;JSLINT.errors=[];predefined=Object.create(standard);if(o){a=o.predef;if(a instanceof Array){for(i=0;i
',nexttoken.value);}
+statements('lib');}}
+advance('(end)');}catch(e){if(e){JSLINT.errors.push({reason:e.message,line:e.line||nexttoken.line,character:e.character||nexttoken.from},null);}}
+return JSLINT.errors.length===0;};function is_array(o){return Object.prototype.toString.apply(o)==='[object Array]';}
+function to_array(o){var a=[],k;for(k in o){if(is_own(o,k)){a.push(k);}}
+return a;}
+itself.data=function(){var data={functions:[]},fu,globals,implieds=[],f,i,j,members=[],n,unused=[],v;if(itself.errors.length){data.errors=itself.errors;}
+if(jsonmode){data.json=true;}
+for(n in implied){if(is_own(implied,n)){implieds.push({name:n,line:implied[n]});}}
+if(implieds.length>0){data.implieds=implieds;}
+if(urls.length>0){data.urls=urls;}
+globals=to_array(scope);if(globals.length>0){data.globals=globals;}
+for(i=1;i0){data.unused=unused;}
+members=[];for(n in member){if(typeof member[n]==='number'){data.member=member;break;}}
+return data;};itself.report=function(option){var data=itself.data();var a=[],c,e,err,f,i,k,l,m='',n,o=[],s;function detail(h,s){if(s){o.push(''+h+' '+
+s.sort().join(', ')+'
');}}
+if(data.errors||data.implieds||data.unused){err=true;o.push('Error:');if(data.errors){for(i=0;i
Problem'+(isFinite(c.line)?' at line '+
+c.line+' character '+c.character:'')+': '+c.reason.entityify()+''+
+(e&&(e.length>80?e.slice(0,77)+'...':e).entityify())+'
');}}}
+if(data.implieds){s=[];for(i=0;i'+data.implieds[i].name+' '+
+data.implieds[i].line+'';}
+o.push('Implied global: '+s.join(', ')+'
');}
+if(data.unused){s=[];for(i=0;i'+data.unused[i].name+' '+
+data.unused[i].line+' '+
+data.unused[i]['function']+'
';}
+o.push('Unused variable: '+s.join(', ')+'
');}
+if(data.json){o.push('JSON: bad.
');}
+o.push(' ');}
+if(!option){o.push('
');if(data.urls){detail("URLs
",data.urls,'
');}
+if(data.json&&!err){o.push('
JSON: good.
');}else if(data.globals){o.push('
Global '+
+data.globals.sort().join(', ')+'
');}else{o.push('
No new global variables introduced.
');}
+for(i=0;i
'+f.line+'-'+
+f.last+' '+(f.name||'')+'('+
+(f.param?f.param.join(', '):'')+')
');detail('Unused',f.unused);detail('Closure',f.closure);detail('Variable',f['var']);detail('Exception',f.exception);detail('Outer',f.outer);detail('Global',f.global);detail('Label',f.label);}
+if(data.member){a=to_array(data.member);if(a.length){a=a.sort();m='
/*members ';l=10;for(i=0;i72){o.push(m+'
');m=' ';l=1;}
+l+=n.length+2;if(data.member[k]===1){n=''+n+'';}
+if(i*/
');}
+o.push(' ');}}
+return o.join('');};itself.jslint=itself;itself.edition='2009-10-04';return itself;}());(function(a){var e,i,input;if(!a[0]){print("Usage: jslint.js file.js");quit(1);}
+input=readFile(a[0]);if(!input){print("jslint: Couldn't open file '"+a[0]+"'.");quit(1);}
+if(!JSLINT(input,{bitwise:true,eqeqeq:true,immed:true,newcap:true,nomen:true,onevar:true,plusplus:true,regexp:true,rhino:true,undef:true,white:true})){for(i=0;i
+;; Contributors:
+;; - Lennart Borgman
+
+;;; Commentary:
+;;
+;; This file implements communication with Firefox via MozRepl
+;; (http://hyperstruct.net/projects/mozrepl). It is a slightly
+;; modified version of the file moz.el that comes with MozLab. To use
+;; it you have to install the MozRepl addon in Firefox.
+;;
+;; This file contains
+;;
+;; * a major mode for direct interaction in a buffer (as with
+;; telnet) with MozRepl, `inferior-moz-mode'.
+;; * a minor mode for sending code portions or whole files from
+;; other buffers to MozRepl, `moz-minor-mode'.
+;;
+;; Assuming you want to use javascript-mode to edit Javascript files,
+;; enter the following in your .emacs initialization file (from Emacs
+;; integration in the help text):
+;;
+;; (add-to-list 'auto-mode-alist '("\\.js$" . javascript-mode))
+;; (autoload 'inferior-moz-mode "moz" "MozRepl Inferior Mode" t)
+;; (autoload 'moz-minor-mode "moz" "MozRepl Minor Mode" t)
+;; (add-hook 'javascript-mode-hook 'javascript-moz-setup)
+;; (defun javascript-moz-setup () (moz-minor-mode 1))
+;;
+;; Replace javascript-mode above with the name of your favorite
+;; javascript mode.
+;;
+;; If you got this with nXhtml the setup above is already done for
+;; you.
+;;
+;; *Note 1* You have to start the MozRepl server in Firefox (or
+;; whatever Mozilla browser you use). From the menus do
+;;
+;; Tools - MozRepl - Start
+;;
+;; *Note 2* For clearness and brevity the documentation says Firefox
+;; where the correct term should rather be "your Mozilla web
+;; browser".
+
+;;; Change log:
+;;
+;; 2008-07-20: Lennart Borgman
+;; - Add `moz-minor-mode-map'.
+;; - Add `inferior-moz-insert-moz-repl'.
+;; - Add `inferior-moz-mode-map'.
+;; - Add doc strings to interactive functions.
+;; - Make minor enhancements to documentation etc.
+;; - Change Mozilla to Firefox/MozRepl for clarity and brevity.
+;; - Add error handling when starting MozRepl.
+
+;;; Code:
+
+(require 'comint)
+(require 'cc-cmds)
+
+;; Maybe fix-me: C-c control-char are reserved for major modes. But
+;; this minor mode is used in only one major mode (or one family of
+;; major modes) so it complies I think ...
+(defvar moz-minor-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-c\C-s" 'run-mozilla)
+ (define-key map "\C-\M-x" 'moz-send-defun)
+ (define-key map "\C-c\C-c" 'moz-send-defun-and-go)
+ (define-key map "\C-c\C-r" 'moz-send-region)
+ (define-key map "\C-c\C-l" 'moz-save-buffer-and-send)
+ map))
+
+;;;###autoload
+(define-minor-mode moz-minor-mode
+ "MozRepl minor mode for interaction with Firefox.
+With no argument, this command toggles the mode.
+Non-null prefix argument turns on the mode.
+Null prefix argument turns off the mode.
+
+When this minor mode is enabled, some commands become available
+to send current code area \(as understood by c-mark-function) or
+region or buffer to an inferior MozRepl process (which will be
+started as needed).
+
+The following keys are bound in this minor mode:
+
+\\{moz-minor-mode-map}"
+ nil
+ " Moz"
+ :keymap moz-minor-mode-map
+ :group 'moz)
+
+(defalias 'run-mozilla 'inferior-moz-switch-to-mozilla)
+
+(defvar moz-repl-name "repl"
+ "The current name of the repl.")
+
+(defvar moz-input-separator "\n--end-remote-input\n")
+
+(defvar moz-repl-host "localhost")
+
+(defvar moz-repl-port 4242)
+
+(defvar moz-temporary-file nil)
+
+(defun moz-temporary-file ()
+ (if (and moz-temporary-file
+ (file-readable-p moz-temporary-file))
+ moz-temporary-file
+ (setq moz-temporary-file (make-temp-file "emacs-mozrepl"))))
+
+(defun moz-send-region (start end)
+ "Send the region to Firefox via MozRepl."
+ (interactive "r")
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); "
+ moz-repl-name ".setenv('printPrompt', false); "
+ moz-repl-name ".setenv('inputMode', 'multiline'); "
+ "undefined; \n"))
+ ;; Give the previous line a chance to be evaluated on its own. If
+ ;; it gets concatenated to the following ones, we are doomed.
+ (sleep-for 0 1)
+ (comint-send-region (inferior-moz-process)
+ start end)
+ (comint-send-string (inferior-moz-process)
+ "\n--end-remote-input\n")
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".popenv('inputMode', 'printPrompt'); "
+ "undefined; \n"))
+ (comint-send-string (inferior-moz-process)
+ "\n--end-remote-input\n")
+ (display-buffer (process-buffer (inferior-moz-process))))
+
+(defun moz-send-defun ()
+ "Send the current function to Firefox via MozRepl.
+Curent function is the one recognized by c-mark-function."
+ (interactive)
+ (save-excursion
+ (c-mark-function)
+ (moz-send-region (point) (mark))))
+
+(defun moz-send-defun-and-go ()
+ "Send the current function to Firefox via MozRepl.
+Also switch to the interaction buffer."
+ (interactive)
+ (moz-send-defun)
+ (inferior-moz-switch-to-mozilla nil))
+
+(defun moz-save-buffer-and-send ()
+ "Save the current buffer and load it in Firefox via MozRepl."
+ (interactive)
+ (save-buffer)
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); "
+ moz-repl-name ".setenv('inputMode', 'line'); "
+ moz-repl-name ".setenv('printPrompt', false); undefined; "))
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".load('file://localhost/" (buffer-file-name) "');\n"
+ moz-repl-name ".popenv('inputMode', 'printPrompt'); undefined;\n"))
+ (display-buffer (process-buffer (inferior-moz-process))))
+
+;;; Inferior Mode
+
+(defvar inferior-moz-buffer nil
+ "The buffer in which the inferior process is running.")
+
+(defun inferior-moz-insert-moz-repl ()
+ "Insert value of `moz-repl-name' and a dot (.)."
+ (interactive) (insert moz-repl-name "."))
+
+(defvar inferior-moz-mode-map
+ (let ((map (make-sparse-keymap)))
+ ;; Note: changed from C-c c which is reserved for users.
+ (define-key map "\C-c\C-c" 'inferior-moz-insert-moz-repl)
+ map))
+
+;;;###autoload
+(define-derived-mode inferior-moz-mode comint-mode "Inf-MozRepl"
+ "Major mode for interacting with Firefox via MozRepl."
+ (setq comint-input-sender 'inferior-moz-input-sender)
+ (add-hook 'comint-output-filter-functions 'inferior-moz-track-repl-name nil t))
+
+(defun inferior-moz-track-repl-name (comint-output)
+ (save-match-data
+ (when (string-match "\\(\\w+\\)> $" comint-output)
+ (setq moz-repl-name (match-string 1 comint-output)))))
+
+(defun inferior-moz-self-insert-or-repl-name ()
+ (interactive)
+ (if (looking-back "\\(\\w+\\)> $")
+ (insert moz-repl-name ".")
+ (insert last-command-event)))
+
+(defun inferior-moz-input-sender (proc string)
+ "Custom function to send input with comint-send-input.
+Instead of sending input and newline separately like in
+comint-simple-send, here we *first* concatenate input and
+newline, then send it all together. This prevents newline to be
+interpreted on its own."
+ (comint-send-string proc (concat string "\n")))
+
+(defun inferior-moz-switch-to-mozilla (arg)
+ "Switch to the inferior MozRepl buffer.
+Create the buffer and start the MozRepl process and connect to
+Firefox if needed.
+
+See also `inferior-moz-start-process'."
+ (interactive "P")
+ (when arg
+ (setq moz-repl-host (read-string "Host: " "localhost"))
+ (setq moz-repl-port (read-number "Port: " 4242)))
+ (pop-to-buffer (process-buffer (inferior-moz-process)))
+ (goto-char (process-mark (inferior-moz-process))))
+
+(defun inferior-moz-process ()
+ "Return inferior MozRepl process. Start it if necessary.
+See also `inferior-moz-start-process'."
+ (or (if (buffer-live-p inferior-moz-buffer)
+ (get-buffer-process inferior-moz-buffer))
+ (progn
+ (inferior-moz-start-process)
+ (inferior-moz-process))))
+
+(defvar mozrepl-home-page "http://hyperstruct.net/projects/mozrepl")
+
+(defun inferior-moz-start-process ()
+ "Start an inferior Mozrepl process and connect to Firefox.
+It runs the hook `inferior-moz-hook' after starting the process
+and setting up the inferior Firefox buffer.
+
+Note that you have to start the MozRepl server from Firefox."
+ (interactive)
+ (condition-case err
+ (progn
+ (setq inferior-moz-buffer
+ (apply 'make-comint "MozRepl" (cons moz-repl-host moz-repl-port) nil nil))
+ (sleep-for 0 100)
+ (with-current-buffer inferior-moz-buffer
+ (inferior-moz-mode)
+ (run-hooks 'inferior-moz-hook)))
+ (file-error
+ (with-output-to-temp-buffer (help-buffer)
+ (help-setup-xref (list #'describe-function 'inferior-moz-start-process) (interactive-p))
+ (with-current-buffer (help-buffer)
+ (insert "Can't start MozRepl, the error message was:\n\n "
+ (error-message-string err)
+ "\n"
+ "\nA possible reason is that you have not installed"
+ "\nthe MozRepl add-on to Firefox or that you have not"
+ "\nstarted it. You start it from the menus in Firefox:"
+ "\n\n Tools / MozRepl / Start"
+ "\n"
+ "\nSee ")
+ (insert-text-button
+ "MozRepl home page"
+ 'action (lambda (button)
+ (browse-url mozrepl-home-page))
+ 'help-echo mozrepl-home-page
+ 'face 'button)
+ (insert
+ " for more information."
+ "\n"
+ "\nMozRepl is also available directly from Firefox add-on"
+ "\npages, but is updated less frequently there.")
+ ))
+ (error "Can't start MozRepl"))))
+
+(provide 'moz)
+
+;;; moz.el ends here
diff --git a/emacs.d/nxhtml/related/mozadd.el b/emacs.d/nxhtml/related/mozadd.el
new file mode 100644
index 0000000..a303fe4
--- /dev/null
+++ b/emacs.d/nxhtml/related/mozadd.el
@@ -0,0 +1,369 @@
+;;; mozadd.el --- Additional functionality for MozRepl
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2009-07-22 Wed
+(defconst mozadd:version "0.2") ;; Version:
+;; Last-Updated: 2009-08-04 Tue
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+ ;; `cc-cmds', `cc-defs', `cc-engine', `cc-vars', `comint', `json',
+ ;; `moz', `regexp-opt', `ring'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Live tracking of editing changes, see
+;; `mozadd-mirror-mode'
+;; `mozadd-refresh-edited-on-save-mode'
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(require 'moz)
+(require 'json)
+
+(defun mozadd-warning (format-string &rest args)
+ (let ((str (apply 'format format-string args)))
+ (message "%s" (propertize str 'face 'secondary-selection))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Refresh Firefox after save etc
+
+;; Partly after an idea on EmacsWiki
+
+(defvar mozadd-edited-buffer nil)
+(setq mozadd-edited-buffer nil)
+
+;;;###autoload
+(define-minor-mode mozadd-refresh-edited-on-save-mode
+ "Refresh mozadd edited file in Firefox when saving file.
+The mozadd edited file is the file in the last buffer visited in
+`mozadd-mirror-mode'.
+
+You can use this for example when you edit CSS files.
+
+The mozadd edited file must be shown in Firefox and visible."
+ :lighter "MozRefresh"
+ (if mozadd-refresh-edited-on-save-mode
+ (add-hook 'after-save-hook 'mozadd-queue-reload-mozilla-edited-file nil t)
+ (remove-hook 'after-save-hook 'mozadd-queue-reload-mozilla-edited-file t)))
+(put 'mozadd-refresh-edited-on-save-mode 'permanent-local t)
+
+;;;###autoload
+(define-globalized-minor-mode global-mozadd-refresh-edited-on-save-mode
+ mozadd-refresh-edited-on-save-mode
+ (lambda ()
+ (when (or (derived-mode-p 'css-mode)
+ (mozadd-html-buffer-file-p))
+ (mozadd-refresh-edited-on-save-mode 1))))
+
+(defun mozadd-queue-reload-mozilla-edited-file ()
+ "Reload edited file."
+ (when (buffer-live-p mozadd-edited-buffer)
+ (if (buffer-modified-p mozadd-edited-buffer)
+ (mozadd-warning "Mozadd: Edited buffer %s is not saved, can't reload browser."
+ (buffer-name mozadd-edited-buffer))
+ (mozadd-add-queue-get-mirror-location)
+ (mozadd-add-task-1 'mozadd-send-refresh-edited-to-mozilla))))
+
+(defun mozadd-send-refresh-edited-to-mozilla ()
+ "Update the remote mozrepl instance"
+ (with-current-buffer mozadd-edited-buffer
+ (if (not (mozadd-edited-file-is-shown))
+ (mozadd-warning "Mozadd: Edited buffer %s is not shown, can't reload browser."
+ (buffer-name mozadd-edited-buffer))
+ (comint-send-string (inferior-moz-process)
+ "setTimeout(BrowserReload(), \"1000\");")))
+ (mozadd-exec-next))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mirror html buffer in Firefox
+
+;; Partly after an idea on
+;; http://people.internetconnection.net/2009/02/interactive-html-development-in-emacs/
+
+;; Fun, it kind of works, but is perhaps totally useless .... - slow
+;; and maybe scrolling... - but the file I am testing with have 3000
+;; lines...
+
+;; Fix-me: How do you get the currently shown page in Firefox?
+
+(defun mozadd-perhaps-start ()
+ "Start if MozRepl if not running. Return message if not ok."
+ (unless (buffer-live-p inferior-moz-buffer)
+ (condition-case err
+ (progn
+ (inferior-moz-start-process)
+ nil)
+ (error (error-message-string err)))))
+
+(defvar mozadd-mirror-location nil)
+(make-variable-buffer-local 'mozadd-mirror-location)
+(put 'mozadd-mirror-location 'permanent-local t)
+
+(defvar mozadd-initial-mirror-location nil)
+(make-variable-buffer-local 'mozadd-initial-mirror-location)
+(put 'mozadd-initial-mirror-location 'permanent-local t)
+
+;;(mozadd-get-comint-string-part "\"hi\" there")
+(defun mozadd-get-comint-string-part (comint-output)
+ (save-match-data
+ (if (string-match "^\".*?\"" comint-output)
+ (match-string 0 comint-output)
+ comint-output)))
+
+(defun mozadd-get-initial-mirror-location (comint-output)
+ ;;(message "mozadd-get-initial-mirror-location %S" comint-output)
+ (with-current-buffer mozadd-edited-buffer
+ (setq mozadd-initial-mirror-location (mozadd-get-comint-string-part comint-output)))
+ (mozadd-exec-next)
+ comint-output)
+
+(defun mozadd-get-mirror-location (comint-output)
+ ;;(message "mozadd-get-mirror-location %S" comint-output)
+ (with-current-buffer mozadd-edited-buffer
+ (setq mozadd-mirror-location (mozadd-get-comint-string-part comint-output)))
+ (mozadd-exec-next)
+ comint-output)
+
+(defun mozadd-add-queue-get-mirror-location ()
+ (mozadd-add-task "content.location.href" 'mozadd-get-mirror-location))
+
+(defun mozadd-skip-output-until-prompt (comint-output)
+ ;;(message "mozadd-skip-output-until-prompt %S" comint-output)
+ (if (not (string-match-p "\\(\\w+\\)> $" comint-output))
+ ""
+ ;;(message "done recieve %s" (current-time-string))
+ (mozadd-exec-next)
+ comint-output
+ ""
+ ))
+
+(defun mozadd-queue-send-buffer-content-to-mozilla (buffer)
+ (mozadd-add-queue-get-mirror-location)
+ (setq mozadd-edited-buffer buffer)
+ (mozadd-add-task-1 'mozadd-send-buffer-content-to-mozilla))
+
+(defun mozadd-edited-file-is-shown ()
+ (with-current-buffer mozadd-edited-buffer
+ (string= mozadd-mirror-location mozadd-initial-mirror-location)))
+
+(defvar mozadd-xml-path-outline-style "2px solid red")
+(defun mozadd-send-buffer-content-to-mozilla ()
+ "Update the remote mozrepl instance"
+ (with-current-buffer mozadd-edited-buffer
+ (if (mozadd-edited-file-is-shown)
+ (mozadd-requeue-me-as-task
+ (concat "content.document.body.innerHTML="
+ (json-encode
+ (save-restriction
+ (widen)
+ (let ((where-points nil)
+ (str "")
+ (p1 (point-min))
+ p2)
+ ;; If nxml-where-mode is on add corresponding outline style.
+ (when (and (boundp 'nxml-where-mode) nxml-where-mode)
+ (mapc (lambda (ovl)
+ (when (overlay-get ovl 'nxml-where)
+ (when (/= ?/ (1+ (char-after (overlay-start ovl))))
+ (push (1- (overlay-end ovl)) where-points))))
+ (overlays-in (point-min) (point-max)))
+ (setq where-points (sort where-points '<)))
+ (dolist (p2 where-points)
+ (setq str (concat str
+ (buffer-substring-no-properties p1
+ p2)))
+ (setq str (concat str
+ " style=\"outline: "
+ mozadd-xml-path-outline-style
+ "\""))
+ (setq p1 p2)
+ )
+ (setq str (concat str
+ (buffer-substring-no-properties p1
+ (point-max))))
+ str))
+ )
+ ";")
+ 'mozadd-skip-output-until-prompt)
+ (mozadd-skip-current-task))
+ ;; Timer to avoid looping
+ (run-with-idle-timer 0 nil 'mozadd-maybe-exec-next)
+ ))
+
+(defvar mozadd-current-task nil)
+(setq mozadd-current-task nil)
+
+(defvar mozadd-task-queue nil)
+(setq mozadd-task-queue nil)
+;;(mozadd-add-task "content.location.href" 'mozadd-get-initial-mirror-location)
+;;(mozadd-add-task "hi" 1)
+;;(mozadd-add-task "hm" 2)
+
+(defun mozadd-clear-exec-queue ()
+ (setq mozadd-current-task nil)
+ (setq mozadd-task-queue nil)
+ (when (buffer-live-p inferior-moz-buffer)
+ (with-current-buffer inferior-moz-buffer
+ (dolist (fun (buffer-local-value 'comint-preoutput-filter-functions (current-buffer)))
+ (remove-hook 'comint-preoutput-filter-functions fun t)))))
+
+(defun mozadd-add-task (input task)
+ (mozadd-add-task-1 (list input task)))
+
+(defun mozadd-add-task-1 (task)
+ (setq mozadd-task-queue (cons task mozadd-task-queue))
+ (setq mozadd-task-queue (reverse mozadd-task-queue))
+ ;;(message "add-task: mozadd-task-queue=%S, current=%s" mozadd-task-queue mozadd-current-task)
+ (mozadd-maybe-exec-next))
+
+(defun mozadd-maybe-exec-next ()
+ ;;(message "mozadd-maybe-exec-next, current=%s" mozadd-current-task)
+ (unless mozadd-current-task
+ (mozadd-exec-next)))
+
+(defun mozadd-exec-next ()
+ (when mozadd-current-task
+ (let* ((old-task mozadd-current-task) ;;(pop mozadd-task-queue))
+ (old-filter (when (listp old-task) (nth 1 old-task))))
+ (when (and old-filter (buffer-live-p inferior-moz-buffer))
+ (with-current-buffer inferior-moz-buffer
+ (remove-hook 'comint-preoutput-filter-functions old-filter t)))))
+ (setq mozadd-current-task nil)
+ (when mozadd-task-queue
+ (let* ((this (pop mozadd-task-queue))
+ (input (when (listp this) (nth 0 this)))
+ (task (when (listp this) (nth 1 this)))
+ )
+ (setq mozadd-current-task this)
+ ;;(message "EXEC: %s" this)
+ (if (not (listp this))
+ (funcall this)
+ (when (buffer-live-p inferior-moz-buffer)
+ (with-current-buffer inferior-moz-buffer
+ (add-hook 'comint-preoutput-filter-functions task nil t)))
+ (comint-send-string (inferior-moz-process) input)))))
+
+(defun mozadd-skip-current-task ()
+ ;;(message "mozadd-skip-current-task")
+ ;;(pop mozadd-task-queue)
+ (setq mozadd-current-task nil))
+
+(defun mozadd-requeue-me-as-task (input task)
+ (mozadd-skip-current-task)
+ ;;(message "mozadd-requeue-me-as-task %S %S" input task)
+ (setq mozadd-task-queue (cons (list input task) mozadd-task-queue)))
+
+(defcustom mozadd-browseable-file-extensions
+ '("html" "htm" "xhtml")
+ "File extensions possibly viewable in a web browser."
+ :type '(repeat (string :tag "File extension (without leading dot)"))
+ :group 'mozadd)
+
+(defun mozadd-html-buffer-file-p ()
+ "Return non-nil if buffer file is viewable in a web browser."
+ (when (buffer-file-name)
+ (member (file-name-extension (buffer-file-name))
+ mozadd-browseable-file-extensions)))
+
+;;;###autoload
+(define-minor-mode mozadd-mirror-mode
+ "Mirror content of current file buffer immediately in Firefox.
+When you turn on this mode the file will be opened in Firefox.
+Every change you make in the buffer will trigger a redraw in
+Firefox - regardless of if you save the file or not.
+
+For the mirroring to work the edited file must be shown in
+Firefox and visible.
+
+If `nxml-where-mode' is on the marks will also be shown in
+Firefox as CSS outline style. You can customize the style
+through the option `mozadd-xml-path-outline-style'.
+
+See also `mozadd-refresh-edited-on-save-mode'."
+ nil
+ :lighter " MozMirror"
+ :group 'mozadd
+ (if mozadd-mirror-mode
+ (unless (catch 'ok
+ (unless (mozadd-html-buffer-file-p)
+ (mozadd-warning "You can only mirror html file buffers")
+ (throw 'ok nil))
+ (when (buffer-modified-p)
+ (mozadd-warning "Please save buffer first")
+ (throw 'ok nil))
+ (let ((msg (mozadd-perhaps-start)))
+ (when msg
+ (mozadd-warning msg)
+ (throw 'ok nil)))
+ (mozadd-clear-exec-queue)
+ (setq mozadd-edited-buffer (current-buffer))
+ (mozadd-add-task (concat "content.location.href = "
+ "\"file:///" (buffer-file-name) "\";")
+ 'mozadd-get-initial-mirror-location)
+ (add-hook 'after-change-functions 'mozadd-update-mozilla t t)
+ (add-hook 'nxhtml-where-hook 'mozadd-update-mozilla t t)
+ (add-hook 'post-command-hook 'mozadd-edited-buffer-post-command)
+ t)
+ (setq mozadd-mirror-mode nil))
+ (setq mozadd-edited-buffer nil)
+ (remove-hook 'post-command-hook 'mozadd-edited-buffer-post-command)
+ (remove-hook 'nxhtml-where-hook 'mozadd-update-mozilla t)
+ (remove-hook 'after-change-functions 'mozadd-update-mozilla t)))
+(put 'mozadd-mirror-mode 'permanent-local t)
+
+;;;###autoload
+(define-globalized-minor-mode global-mozadd-mirror-mode mozadd-mirror-mode
+ (lambda ()
+ (when (mozadd-html-buffer-file-p)
+ (mozadd-mirror-mode 1))))
+
+(defun mozadd-edited-buffer-post-command ()
+ "Check if we are in a new edited buffer."
+ (when mozadd-mirror-mode
+ (setq mozadd-edited-buffer (current-buffer))))
+
+
+(defvar mozadd-buffer-content-to-mozilla-timer nil)
+
+(defun mozadd-update-mozilla (&rest ignored)
+ (when (timerp mozadd-buffer-content-to-mozilla-timer)
+ (cancel-timer mozadd-buffer-content-to-mozilla-timer))
+ (setq mozadd-buffer-content-to-mozilla-timer
+ (run-with-idle-timer 1 nil 'mozadd-queue-send-buffer-content-to-mozilla (current-buffer))))
+(put 'mozadd-update-mozilla 'permanent-local-hook t)
+
+
+(provide 'mozadd)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; mozadd.el ends here
diff --git a/emacs.d/nxhtml/related/php-imenu.el b/emacs.d/nxhtml/related/php-imenu.el
new file mode 100644
index 0000000..560bac0
--- /dev/null
+++ b/emacs.d/nxhtml/related/php-imenu.el
@@ -0,0 +1,174 @@
+;;; php-imenu.el --- object-oriented, hierarchical imenu for PHP
+;;;
+;;; Maintainer: Marcel Cary
+;;; Keywords: php languages oop
+;;; Created: 2008-06-23
+;;; Modified: 2008-07-18
+;;; X-URL: http://www.oak.homeunix.org/~marcel/blog/articles/2008/07/14/nested-imenu-for-php
+;;;
+;;; Copyright (C) 2008 Marcel Cary
+;;;
+;;; License
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License
+;;; as published by the Free Software Foundation; either version 2
+;;; of the License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software
+;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+;;;
+;;;
+;;; Usage
+;;;
+;;; Rename this file to php-imenu.el if it isn't already then place it in
+;;; your Emacs lisp path (eg. site-lisp) and add to your .emacs file:
+;;;
+;;;--------------cut here-------------------------------------------
+; ;; Load the php-imenu index function
+; (autoload 'php-imenu-create-index "php-imenu" nil t)
+; ;; Add the index creation function to the php-mode-hook
+; (add-hook 'php-mode-user-hook 'php-imenu-setup)
+; (defun php-imenu-setup ()
+; (setq imenu-create-index-function (function php-imenu-create-index))
+; ;; uncomment if you prefer speedbar:
+; ;(setq php-imenu-alist-postprocessor (function reverse))
+; (imenu-add-menubar-index)
+; )
+;;;----------------end here--------------------------------------------
+;;;
+;;; Commentary
+;;;
+;;; Refines php-mode's imenu support. Imenu provides a menubar entry called
+;;; "Index" that allows you to jump to a structural element of a file. While
+;;; php-mode generates separate lists of functions and classes in imenu,
+;;; php-imenu.el (this code) generates a tree of class and function
+;;; definitions. It lists functions under the classes in which they're
+;;; defined. The hierarchical display of functions within their classes makes
+;;; the "Index" menu far more useful in understanding the high-level structure
+;;; of a file, and it makes it easier to find a method when a file contains
+;;; multiple by the same name.
+;;;
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'imenu)
+(require 'thingatpt)
+
+;;; Alas, speedbar shows menu items in reverse, but only below the top level.
+;;; Provide a way to fix it. See sample configuration in file comment.
+(defvar php-imenu-alist-postprocessor (function identity))
+
+;;; Want to see properties or defines? Add an entry for them here.
+(defvar php-imenu-patterns nil)
+(setq php-imenu-patterns
+ (list
+ ;; types: classes and interfaces
+ (list
+ ;; for some reason [:space:] and \s- aren't matching \n
+ (concat "^\\s-*"
+ "\\(\\(abstract[[:space:]\n]+\\)?class\\|interface\\)"
+ "[[:space:]\n]+"
+ "\\([a-zA-Z0-9_]+\\)[[:space:]\n]*" ; class/iface name
+ "\\([a-zA-Z0-9_[:space:]\n]*\\)" ; extends / implements clauses
+ "[{]")
+ (lambda ()
+ (message "%S %S"
+ (match-string-no-properties 3)
+ (match-string-no-properties 1))
+ (concat (match-string-no-properties 3)
+ " - "
+ (match-string-no-properties 1)))
+ (lambda ()
+ (save-excursion
+ (backward-up-list 1)
+ (forward-sexp)
+ (point))))
+ ;; functions
+ (list
+ (concat "^[[:space:]\n]*"
+ "\\(\\(public\\|protected\\|private\\|"
+ "static\\|abstract\\)[[:space:]\n]+\\)*"
+ "function[[:space:]\n]*&?[[:space:]\n]*"
+ "\\([a-zA-Z0-9_]+\\)[[:space:]\n]*" ; function name
+ "[(]")
+ (lambda ()
+ (concat (match-string-no-properties 3) "()"))
+ (lambda ()
+ (save-excursion
+ (backward-up-list 1)
+ (forward-sexp)
+ (when (not (looking-at "\\s-*;"))
+ (forward-sexp))
+ (point))))
+ ))
+
+;;; Global variable to pass to imenu-progress-message in multiple functions
+(defvar php-imenu-prev-pos nil)
+
+;;; An implementation of imenu-create-index-function
+(defun php-imenu-create-index ()
+ (let (prev-pos)
+ (imenu-progress-message php-imenu-prev-pos 0)
+ (let ((result (php-imenu-create-index-helper (point-min) (point-max) nil)))
+ ;(message "bye %S" result)
+ (imenu-progress-message php-imenu-prev-pos 100)
+ result)))
+
+(defun php-imenu-create-index-helper (min max name)
+ (let ((combined-pattern
+ (concat "\\("
+ (mapconcat
+ (function (lambda (pat) (first pat)))
+ php-imenu-patterns "\\)\\|\\(")
+ "\\)"))
+ (index-alist '()))
+ (goto-char min)
+ (save-match-data
+ (while (re-search-forward combined-pattern max t)
+ (let ((pos (set-marker (make-marker) (match-beginning 0)))
+ (min (match-end 0))
+ (pat (save-excursion
+ (goto-char (match-beginning 0))
+ (find-if (function
+ (lambda (pat) (looking-at (first pat))))
+ php-imenu-patterns))))
+ (when (not pat)
+ (message "php-imenu: How can no pattern get us here! %S" pos))
+ (when (and pat
+ (not (php-imenu-in-string-p))
+ )
+ (let* ((name (funcall (second pat)))
+ (max (funcall (third pat)))
+ (children (php-imenu-create-index-helper min max name)))
+ ;; should validate max: what happens if unmatched curly?
+ ;(message "%S %S %S" nm name (mapcar (function first) children))
+ (if (equal '() children)
+ (push (cons name pos) index-alist)
+ (push (cons name
+ (funcall php-imenu-alist-postprocessor
+ (cons (cons "*go*" pos)
+ children)))
+ index-alist))
+ ))
+ (imenu-progress-message php-imenu-prev-pos nil)
+ )))
+ (reverse index-alist)))
+
+;;; Recognize when in quoted strings or heredoc-style string literals
+(defun php-imenu-in-string-p ()
+ (save-match-data
+ (or (in-string-p)
+ (let ((pt (point)))
+ (save-excursion
+ (and (re-search-backward "<<<\\([A-Za-z0-9_]+\\)$" nil t)
+ (not (re-search-forward (concat "^"
+ (match-string-no-properties 1)
+ ";$")
+ pt t))))))))
diff --git a/emacs.d/nxhtml/related/php-mode.el b/emacs.d/nxhtml/related/php-mode.el
new file mode 100644
index 0000000..a25fb82
--- /dev/null
+++ b/emacs.d/nxhtml/related/php-mode.el
@@ -0,0 +1,1231 @@
+;;; php-mode.el --- major mode for editing PHP code
+
+;; Copyright (C) 1999, 2000, 2001, 2003, 2004 Turadg Aleahmad
+;; 2008 Aaron S. Hawley
+
+;; Maintainer: Aaron S. Hawley
+;; Author: Turadg Aleahmad, 1999-2004
+;; Keywords: php languages oop
+;; Created: 1999-05-17
+;; Modified: 2008-11-28 Fri
+;; X-URL: http://php-mode.sourceforge.net/
+
+(defconst php-mode-version-number "1.5.0-nxhtml-1.94"
+ "PHP Mode version number.")
+
+;;; License
+
+;; This file is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License
+;; as published by the Free Software Foundation; either version 3
+;; of the License, or (at your option) any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this file; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
+
+;;; Usage
+
+;; Put this file in your Emacs lisp path (eg. site-lisp) and add to
+;; your .emacs file:
+;;
+;; (require 'php-mode)
+
+;; To use abbrev-mode, add lines like this:
+;; (add-hook 'php-mode-hook
+;; '(lambda () (define-abbrev php-mode-abbrev-table "ex" "extends")))
+
+;; To make php-mode compatible with html-mode, see http://php-mode.sf.net
+
+;; Many options available under Help:Customize
+;; Options specific to php-mode are in
+;; Programming/Languages/Php
+;; Since it inherits much functionality from c-mode, look there too
+;; Programming/Languages/C
+
+;;; Commentary:
+
+;; PHP mode is a major mode for editing PHP 3 and 4 source code. It's
+;; an extension of C mode; thus it inherits all C mode's navigation
+;; functionality. But it colors according to the PHP grammar and indents
+;; according to the PEAR coding guidelines. It also includes a couple
+;; handy IDE-type features such as documentation search and a source
+;; and class browser.
+
+;;; Contributors: (in chronological order)
+
+;; Juanjo, Torsten Martinsen, Vinai Kopp, Sean Champ, Doug Marcey,
+;; Kevin Blake, Rex McMaster, Mathias Meyer, Boris Folgmann, Roland
+;; Rosenfeld, Fred Yankowski, Craig Andrews, John Keller, Ryan
+;; Sammartino, ppercot, Valentin Funk, Stig Bakken, Gregory Stark,
+;; Chris Morris, Nils Rennebarth, Gerrit Riessen, Eric Mc Sween,
+;; Ville Skytta, Giacomo Tesio, Lennart Borgman, Stefan Monnier,
+;; Aaron S. Hawley, Ian Eure, Bill Lovett, Dias Badekas, David House
+
+;;; Changelog:
+
+;; 1.5.0-nxhtml-1.88 (Lennart Borgman)
+;; Don't indent heredoc end mark
+;; 1.5.0-nxhtml-1.61 (Lennart Borgman)
+;; Added php-mode-to-use.
+;; Made underscore be part of identifiers.
+;; Remove php-mode-to.
+;; Make the indentation check only on current line.
+;; Warn only once per session about indentation.
+;; Tell if can't complete in `php-complete-function'.
+;; Move back point after checking indentation in
+;; `php-check-html-for-indentation'.
+;; Add `c-at-vsemi-p-fn' etc after advice from Alan Mackenzie.
+;;
+;; 1.5
+;; Support function keywords like public, private and the ampersand
+;; character for function-based commands. Support abstract, final,
+;; static, public, private and protected keywords in Imenu. Fix
+;; reversed order of Imenu entries. Use font-lock-preprocessor-face
+;; for PHP and ASP tags. Make php-mode-modified a literal value
+;; rather than a computed string. Add date and time constants of
+;; PHP. (Dias Badekas) Fix false syntax highlighting of keywords
+;; because of underscore character. Change HTML indentation warning
+;; to match only HTML at the beginning of the line. Fix
+;; byte-compiler warnings. Clean-up whitespace and audited style
+;; consistency of code. Remove conditional bindings and XEmacs code
+;; that likely does nothing.
+;;
+;; 1.4
+;; Updated GNU GPL to version 3. Ported to Emacs 22 (CC mode
+;; 5.31). M-x php-mode-version shows version. Provide end-of-defun
+;; beginning-of-defun functionality. Support add-log library.
+;; Fix __CLASS__ constant (Ian Eure). Allow imenu to see visibility
+;; declarations -- "private", "public", "protected". (Bill Lovett)
+;;
+;; 1.3
+;; Changed the definition of # using a tip from Stefan
+;; Monnier to correct highlighting and indentation. (Lennart Borgman)
+;; Changed the highlighting of the HTML part. (Lennart Borgman)
+;;
+;; See the ChangeLog file included with the source package.
+
+
+;;; Code:
+
+(require 'add-log)
+(require 'speedbar)
+(require 'font-lock)
+(require 'cc-mode)
+(require 'cc-langs)
+(require 'custom)
+(require 'etags)
+(eval-when-compile
+ (require 'regexp-opt))
+
+;; Local variables
+;;;###autoload
+(defgroup php nil
+ "Major mode `php-mode' for editing PHP code."
+ :prefix "php-"
+ :group 'languages)
+
+(defcustom php-default-face 'default
+ "Default face in `php-mode' buffers."
+ :type 'face
+ :group 'php)
+
+(defcustom php-speedbar-config t
+ "When set to true automatically configures Speedbar to observe PHP files.
+Ignores php-file patterns option; fixed to expression \"\\.\\(inc\\|php[s34]?\\)\""
+ :type 'boolean
+ :set (lambda (sym val)
+ (set-default sym val)
+ (if (and val (boundp 'speedbar))
+ (speedbar-add-supported-extension
+ "\\.\\(inc\\|php[s34]?\\|phtml\\)")))
+ :group 'php)
+
+(defcustom php-mode-speedbar-open nil
+ "Normally `php-mode' starts with the speedbar closed.
+Turning this on will open it whenever `php-mode' is loaded."
+ :type 'boolean
+ :set (lambda (sym val)
+ (set-default sym val)
+ (when val
+ (speedbar 1)))
+ :group 'php)
+
+(defvar php-imenu-generic-expression
+ '(
+ ("Private Methods"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?private\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ ("Protected Methods"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?protected\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ ("Public Methods"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?public\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ ("Classes"
+ "^\\s-*class\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*" 1)
+ ("All Functions"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ )
+ "Imenu generic expression for PHP Mode. See `imenu-generic-expression'."
+ )
+
+(defcustom php-manual-url "http://www.php.net/manual/en/"
+ "URL at which to find PHP manual.
+You can replace \"en\" with your ISO language code."
+ :type 'string
+ :group 'php)
+
+(defcustom php-search-url "http://www.php.net/"
+ "URL at which to search for documentation on a word."
+ :type 'string
+ :group 'php)
+
+(defcustom php-completion-file ""
+ "Path to the file which contains the function names known to PHP."
+ :type 'string
+ :group 'php)
+
+(defcustom php-manual-path ""
+ "Path to the directory which contains the PHP manual."
+ :type 'string
+ :group 'php)
+
+;;;###autoload
+(defcustom php-file-patterns '("\\.php[s34]?\\'" "\\.phtml\\'" "\\.inc\\'")
+ "List of file patterns for which to automatically invoke `php-mode'."
+ :type '(repeat (regexp :tag "Pattern"))
+ :set (lambda (sym val)
+ (set-default sym val)
+ (let ((php-file-patterns-temp val))
+ (while php-file-patterns-temp
+ (add-to-list 'auto-mode-alist
+ (cons (car php-file-patterns-temp) 'php-mode))
+ (setq php-file-patterns-temp (cdr php-file-patterns-temp)))))
+ :group 'php)
+
+(defcustom php-mode-hook nil
+ "List of functions to be executed on entry to `php-mode'."
+ :type 'hook
+ :group 'php)
+
+(defcustom php-mode-pear-hook nil
+ "Hook called when a PHP PEAR file is opened with `php-mode'."
+ :type 'hook
+ :group 'php)
+
+(defcustom php-mode-force-pear nil
+ "Normally PEAR coding rules are enforced only when the filename contains \"PEAR.\"
+Turning this on will force PEAR rules on all PHP files."
+ :type 'boolean
+ :group 'php)
+
+(defconst php-mode-modified "2009-08-12"
+ "PHP Mode build date.")
+
+(defun php-mode-version ()
+ "Display string describing the version of PHP mode."
+ (interactive)
+ (message "PHP mode %s of %s"
+ php-mode-version-number php-mode-modified))
+
+(defconst php-beginning-of-defun-regexp
+ "^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+&?\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*("
+ "Regular expression for a PHP function.")
+
+(defun php-beginning-of-defun (&optional arg)
+ "Move to the beginning of the ARGth PHP function from point.
+Implements PHP version of `beginning-of-defun-function'."
+ (interactive "p")
+ (let ((arg (or arg 1)))
+ (while (> arg 0)
+ (re-search-backward php-beginning-of-defun-regexp
+ nil 'noerror)
+ (setq arg (1- arg)))
+ (while (< arg 0)
+ (end-of-line 1)
+ (let ((opoint (point)))
+ (beginning-of-defun 1)
+ (forward-list 2)
+ (forward-line 1)
+ (if (eq opoint (point))
+ (re-search-forward php-beginning-of-defun-regexp
+ nil 'noerror))
+ (setq arg (1+ arg))))))
+
+(defun php-end-of-defun (&optional arg)
+ "Move the end of the ARGth PHP function from point.
+Implements PHP befsion of `end-of-defun-function'
+
+See `php-beginning-of-defun'."
+ (interactive "p")
+ (php-beginning-of-defun (- (or arg 1))))
+
+
+(defvar php-warned-bad-indent nil)
+;;(make-variable-buffer-local 'php-warned-bad-indent)
+
+;; Do it but tell it is not good if html tags in buffer.
+(defun php-check-html-for-indentation ()
+ (let ((html-tag-re "^\\s-*?\\sw+.*?>")
+ (here (point)))
+ (goto-char (line-beginning-position))
+ (if (or (when (boundp 'mumamo-multi-major-mode) mumamo-multi-major-mode)
+ ;; Fix-me: no idea how to check for mmm or multi-mode
+ (save-match-data
+ (not (or (re-search-forward html-tag-re (line-end-position) t)
+ (re-search-backward html-tag-re (line-beginning-position) t)))))
+ (progn
+ (goto-char here)
+ t)
+ (goto-char here)
+ (setq php-warned-bad-indent t)
+ ;;(setq php-warned-bad-indent nil)
+ (let* ((known-multi-libs '(("mumamo" mumamo (lambda () (nxhtml-mumamo)))
+ ("mmm-mode" mmm-mode (lambda () (mmm-mode 1)))
+ ("multi-mode" multi-mode (lambda () (multi-mode 1)))))
+ (known-names (mapcar (lambda (lib) (car lib)) known-multi-libs))
+ (available-multi-libs (delq nil
+ (mapcar
+ (lambda (lib)
+ (when (locate-library (car lib)) lib))
+ known-multi-libs)))
+ (available-names (mapcar (lambda (lib) (car lib)) available-multi-libs))
+ (base-msg
+ (concat
+ "Indentation fails badly with mixed HTML/PHP in the HTML part in
+plaín `php-mode'. To get indentation to work you must use an
+Emacs library that supports 'multiple major modes' in a buffer.
+Parts of the buffer will then be in `php-mode' and parts in for
+example `html-mode'. Known such libraries are:\n\t"
+ (mapconcat 'identity known-names ", ")
+ "\n"
+ (if available-multi-libs
+ (concat
+ "You have these available in your `load-path':\n\t"
+ (mapconcat 'identity available-names ", ")
+ "\n\n"
+ "Do you want to turn any of those on? ")
+ "You do not have any of those in your `load-path'.")))
+ (is-using-multi
+ (catch 'is-using
+ (dolist (lib available-multi-libs)
+ (when (and (boundp (cadr lib))
+ (symbol-value (cadr lib)))
+ (throw 'is-using t))))))
+ (unless is-using-multi
+ (if available-multi-libs
+ (if (not (y-or-n-p base-msg))
+ (message "Did not do indentation, but you can try again now if you want")
+ (let* ((name
+ (if (= 1 (length available-multi-libs))
+ (car available-names)
+ ;; Minibuffer window is more than one line, fix that first:
+ (message "")
+ (completing-read "Choose multiple major mode support library: "
+ available-names nil t
+ (car available-names)
+ '(available-names . 1)
+ )))
+ (mode (when name
+ (caddr (assoc name available-multi-libs)))))
+ (when mode
+ ;; Minibuffer window is more than one line, fix that first:
+ (message "")
+ (load name)
+ (funcall mode))))
+ (lwarn 'php-indent :warning base-msg)))
+ nil))))
+
+(defun php-cautious-indent-region (start end &optional quiet)
+ (if (or php-warned-bad-indent
+ (php-check-html-for-indentation))
+ (funcall 'c-indent-region start end quiet)))
+
+(defun php-cautious-indent-line ()
+ (if (or php-warned-bad-indent
+ (php-check-html-for-indentation))
+ (let ((here (point))
+ doit)
+ (move-beginning-of-line nil)
+ ;; Don't indent heredoc end mark
+ (save-match-data
+ (unless (looking-at "[a-zA-Z0-9_]+;\n")
+ (setq doit t)))
+ (goto-char here)
+ (when doit
+ (funcall 'c-indent-line)))))
+
+(defconst php-tags '("" "" "="))
+(defconst php-tags-key (regexp-opt php-tags))
+
+(defconst php-block-stmt-1-kwds '("do" "else" "finally" "try"))
+(defconst php-block-stmt-2-kwds
+ '("for" "if" "while" "switch" "foreach" "elseif" "catch all"))
+
+(defconst php-block-stmt-1-key
+ (regexp-opt php-block-stmt-1-kwds))
+(defconst php-block-stmt-2-key
+ (regexp-opt php-block-stmt-2-kwds))
+
+(defconst php-class-decl-kwds '("class" "interface"))
+
+(defconst php-class-key
+ (concat
+ "\\(" (regexp-opt php-class-decl-kwds) "\\)\\s-+"
+ (c-lang-const c-symbol-key c) ;; Class name.
+ "\\(\\s-+extends\\s-+" (c-lang-const c-symbol-key c) "\\)?" ;; Name of superclass.
+ "\\(\\s-+implements\\s-+[^{]+{\\)?")) ;; List of any adopted protocols.
+
+
+(defun php-c-at-vsemi-p (&optional pos)
+ "Return t on html lines (including php region border), otherwise nil.
+POS is a position on the line in question.
+
+This is was done due to the problem reported here:
+
+ URL `https://answers.launchpad.net/nxhtml/+question/43320'"
+ (setq pos (or pos (point)))
+ (let ((here (point))
+ ret)
+ (save-match-data
+ (goto-char pos)
+ (beginning-of-line)
+ (setq ret (looking-at
+ (rx
+ (or (seq
+ bol
+ (0+ space)
+ "<"
+ (in "a-z\\?"))
+ (seq
+ ;;(0+ anything)
+ (0+ not-newline)
+ (in "a-z\\?")
+ ">"
+ (0+ space)
+ eol))))))
+ (goto-char here)
+ ret))
+
+(defun php-c-vsemi-status-unknown-p ()
+ "See `php-c-at-vsemi-p'."
+ )
+
+;;;###autoload
+(define-derived-mode php-mode c-mode "PHP"
+ "Major mode for editing PHP code.\n\n\\{php-mode-map}"
+ (c-add-language 'php-mode 'c-mode)
+
+;; PHP doesn't have C-style macros.
+;; HACK: Overwrite this syntax with rules to match [^_]?")
+ '(1 font-lock-constant-face))
+
+ ;; Fontify keywords
+ (cons
+ (concat "[^_$]?\\<\\(" php-keywords "\\)\\>[^_]?")
+ '(1 font-lock-keyword-face))
+
+ ;; Fontify keywords and targets, and case default tags.
+ (list "\\<\\(break\\|case\\|continue\\)\\>\\s-+\\(-?\\sw+\\)?"
+ '(1 font-lock-keyword-face) '(2 font-lock-constant-face t t))
+ ;; This must come after the one for keywords and targets.
+ '(":" ("^\\s-+\\(\\sw+\\)\\s-+\\s-+$"
+ (beginning-of-line) (end-of-line)
+ (1 font-lock-constant-face)))
+
+ ;; treat 'print' as keyword only when not used like a function name
+ '("\\" . font-lock-keyword-face)
+
+ ;; Fontify PHP tag
+ (cons php-tags-key font-lock-preprocessor-face)
+
+ ;; Fontify ASP-style tag
+ '("<\\%\\(=\\)?" . font-lock-preprocessor-face)
+ '("\\%>" . font-lock-preprocessor-face)
+
+ )
+ "Subdued level highlighting for PHP mode.")
+
+(defconst php-font-lock-keywords-2
+ (append
+ php-font-lock-keywords-1
+ (list
+
+ ;; class declaration
+ '("\\<\\(class\\|interface\\)\\s-+\\(\\sw+\\)?"
+ (1 font-lock-keyword-face) (2 font-lock-type-face nil t))
+ ;; handle several words specially, to include following word,
+ ;; thereby excluding it from unknown-symbol checks later
+ ;; FIX to handle implementing multiple
+ ;; currently breaks on "class Foo implements Bar, Baz"
+ '("\\<\\(new\\|extends\\|implements\\)\\s-+\\$?\\(\\sw+\\)"
+ (1 font-lock-keyword-face) (2 font-lock-type-face))
+
+ ;; function declaration
+ '("\\<\\(function\\)\\s-+&?\\(\\sw+\\)\\s-*("
+ (1 font-lock-keyword-face)
+ (2 font-lock-function-name-face nil t))
+
+ ;; class hierarchy
+ '("\\<\\(self\\|parent\\)\\>" (1 font-lock-constant-face nil nil))
+
+ ;; method and variable features
+ '("\\<\\(private\\|protected\\|public\\)\\s-+\\$?\\sw+"
+ (1 font-lock-keyword-face))
+
+ ;; method features
+ '("^\\s-*\\(abstract\\|static\\|final\\)\\s-+\\$?\\sw+"
+ (1 font-lock-keyword-face))
+
+ ;; variable features
+ '("^\\s-*\\(static\\|const\\)\\s-+\\$?\\sw+"
+ (1 font-lock-keyword-face))
+ ))
+ "Medium level highlighting for PHP mode.")
+
+(defconst php-font-lock-keywords-3
+ (append
+ php-font-lock-keywords-2
+ (list
+
+ ;; or for HTML
+ ;;'("?\\sw+[^> ]*>" . font-lock-constant-face)
+ ;;'("?\\sw+[^>]*" . font-lock-constant-face)
+ ;;'("
+ '("<[^>]*\\(>\\)" (1 font-lock-constant-face))
+
+ ;; HTML tags
+ '("\\(<[a-z]+\\)[[:space:]]+\\([a-z:]+=\\)[^>]*?" (1 font-lock-constant-face) (2 font-lock-constant-face) )
+ '("\"[[:space:]]+\\([a-z:]+=\\)" (1 font-lock-constant-face))
+
+ ;; HTML entities
+ ;;'("&\\w+;" . font-lock-variable-name-face)
+
+ ;; warn about '$' immediately after ->
+ '("\\$\\sw+->\\s-*\\(\\$\\)\\(\\sw+\\)"
+ (1 font-lock-warning-face) (2 php-default-face))
+
+ ;; warn about $word.word -- it could be a valid concatenation,
+ ;; but without any spaces we'll assume $word->word was meant.
+ '("\\$\\sw+\\(\\.\\)\\sw"
+ 1 font-lock-warning-face)
+
+ ;; Warn about ==> instead of =>
+ '("==+>" . font-lock-warning-face)
+
+ ;; exclude casts from bare-word treatment (may contain spaces)
+ `(,(concat "(\\s-*\\(" php-types "\\)\\s-*)")
+ 1 font-lock-type-face)
+
+ ;; PHP5: function declarations may contain classes as parameters type
+ `(,(concat "[(,]\\s-*\\(\\sw+\\)\\s-+&?\\$\\sw+\\>")
+ 1 font-lock-type-face)
+
+ ;; Fontify variables and function calls
+ '("\\$\\(this\\|that\\)\\W" (1 font-lock-constant-face nil nil))
+ `(,(concat "\\$\\(" php-superglobals "\\)\\W")
+ (1 font-lock-constant-face nil nil)) ;; $_GET & co
+ '("\\$\\(\\sw+\\)" (1 font-lock-variable-name-face)) ;; $variable
+ '("->\\(\\sw+\\)" (1 font-lock-variable-name-face t t)) ;; ->variable
+ '("->\\(\\sw+\\)\\s-*(" . (1 php-default-face t t)) ;; ->function_call
+ '("\\(\\sw+\\)::\\sw+\\s-*(?" . (1 font-lock-type-face)) ;; class::member
+ '("::\\(\\sw+\\>[^(]\\)" . (1 php-default-face)) ;; class::constant
+ '("\\<\\sw+\\s-*[[(]" . php-default-face) ;; word( or word[
+ '("\\<[0-9]+" . php-default-face) ;; number (also matches word)
+
+ ;; Warn on any words not already fontified
+ '("\\<\\sw+\\>" . font-lock-warning-face)
+
+ ))
+ "Gauchy level highlighting for PHP mode.")
+
+(provide 'php-mode)
+
+;;; php-mode.el ends here
diff --git a/emacs.d/nxhtml/related/readme.txt b/emacs.d/nxhtml/related/readme.txt
new file mode 100644
index 0000000..465fbf6
--- /dev/null
+++ b/emacs.d/nxhtml/related/readme.txt
@@ -0,0 +1,7 @@
+This subdir (related/) contains files that are taken from different
+places and are maybe modified to work with nXhtml.
+
+Please notice that major mode that are used with mumamo-mode must be a
+bit more carefully written. One problem I have noticed is that some
+major modes requuires that buffer-file-name is non-nil. That
+assumption does not work when mumamo-mode is used!
diff --git a/emacs.d/nxhtml/related/rhino.js b/emacs.d/nxhtml/related/rhino.js
new file mode 100644
index 0000000..efc50f0
--- /dev/null
+++ b/emacs.d/nxhtml/related/rhino.js
@@ -0,0 +1,14 @@
+// Where you store your files
+var project_folder = 'file:///c:/emacs/p/091105/EmacsW32/nxhtml/related/';
+// Browser environment wrapper over Rhino
+load(project_folder + 'env.js');
+// For DOM constructing
+window.location = project_folder + 'blank.html';
+var my_script = arguments[0];
+// If DOM ready
+window.onload = function(){
+ // Avoid recursive inclusion
+ if ("rhino_flymake.js" != my_script) {
+ load(my_script);
+ }
+}
diff --git a/emacs.d/nxhtml/related/smarty-mode.el b/emacs.d/nxhtml/related/smarty-mode.el
new file mode 100644
index 0000000..ad003b5
--- /dev/null
+++ b/emacs.d/nxhtml/related/smarty-mode.el
@@ -0,0 +1,2753 @@
+;;; smarty-mode.el --- major mode for editing Smarty templates
+
+;; Author: Vincent DEBOUT
+;; Maintainer: Vincent DEBOUT
+;; Keywords: languages smarty templates
+;; WWW: http://deboutv.free.fr/lisp/smarty/
+
+;;; License
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License
+;; as published by the Free Software Foundation; either version 2
+;; of the License, or (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+;; Minor changes by Lennart Borgman
+
+(defconst smarty-version "0.0.5"
+ "Smarty Mode version number.")
+
+(defconst smarty-time-stamp "2007-11-01"
+ "Smarty Mode time stamp for last update.")
+
+(defconst smarty-is-xemacs (string-match "XEmacs" emacs-version)
+ "Non-nil if XEmacs is used.")
+
+(require 'font-lock)
+(when (not smarty-is-xemacs)
+ (require 'cc-mode)
+ (require 'custom)
+ (require 'etags))
+(eval-when-compile
+ (require 'regexp-opt))
+;;(when smarty-is-xemacs
+ (require 'easymenu)
+ (require 'hippie-exp)
+;;)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Customization
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(defgroup smarty nil
+ "Customizations for Smarty mode."
+ :prefix "smarty-"
+ :group 'languages)
+
+(defgroup smarty-mode nil
+ "Customizations for Smarty mode."
+ :group 'smarty)
+
+(defcustom smarty-electric-mode t
+ "*Non-nil enables electrification (automatic template generation).
+If nil, template generators can still be invoked through key bindings and
+menu. Is indicated in the modeline by \"/e\" after the mode name and can be
+toggled by `\\[smarty-electric-mode]'."
+ :type 'boolean
+ :group 'smarty-mode)
+
+(defcustom smarty-stutter-mode t
+ "*Non-nil enables stuttering.
+Is indicated in the modeline by \"/s\" after the mode name and can be toggled
+by `\\[smarty-stutter-mode]'."
+ :type 'boolean
+ :group 'smarty-mode)
+
+(defgroup smarty-menu nil
+ "Customizations for menues."
+ :group 'smarty)
+
+(defcustom smarty-source-file-menu t
+ "*Non-nil means add a menu of all source files in current directory."
+ :type 'boolean
+ :group 'smarty-menu)
+
+(defgroup smarty-highlight nil
+ "Customizations for highlight."
+ :group 'smarty)
+
+(defcustom smarty-highlight-plugin-functions t
+ "*Non-nil means highlight the plugin functions in the buffer."
+ :type 'boolean
+ :group 'smarty-highlight)
+
+(defgroup smarty-template nil
+ "Customizations for templates."
+ :group 'smarty)
+
+(defgroup smarty-header nil
+ "Customizations for header template."
+ :group 'smarty-template)
+
+(defcustom smarty-file-header ""
+ "*String or file to insert as file header.
+If the string specifies an existing file name, the contents of the file is
+inserted, otherwise the string itself is inserted as file header.
+Type `C-j' for newlines.
+If the header contains RCS keywords, they may be written as Keyword
+if the header needs to be version controlled.
+
+The following keywords for template generation are supported:
+ : replaced by the name of the buffer
+ : replaced by the user name and email address
+ \(`user-full-name',`mail-host-address', `user-mail-address')
+ : replaced by user login name (`user-login-name')
+ : replaced by contents of option `smarty-company-name'
+ : replaced by the current date
+ : replaced by the current year
+ : replaced by copyright string (`smarty-copyright-string')
+ : final cursor position."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-file-footer ""
+ "*String or file to insert as file footer.
+If the string specifies an existing file name, the contents of the file is
+inserted, otherwise the string itself is inserted as file footer (i.e. at
+the end of the file).
+Type `C-j' for newlines.
+The same keywords as in option `smarty-file-header' can be used."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-company-name ""
+ "*Name of company to insert in file header.
+See option `smarty-file-header'."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-copyright-string ""
+ "*Copyright string to insert in file header.
+Can be multi-line string (type `C-j' for newline) and contain other file
+header keywords (see option `smarty-file-header')."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-date-format "%Y-%m-%d"
+ "*Specifies the date format to use in the header.
+This string is passed as argument to the command `format-time-string'.
+For more information on format strings, see the documentation for the
+`format-time-string' command (C-h f `format-time-string')."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-modify-date-prefix-string ""
+ "*Prefix string of modification date in Smarty file header.
+If actualization of the modification date is called (menu,
+`\\[smarty-template-modify]'), this string is searched and the rest
+of the line replaced by the current date."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-modify-date-on-saving nil
+ "*Non-nil means update the modification date when the buffer is saved.
+Calls function `\\[smarty-template-modify]').
+
+NOTE: Activate the new setting in a Smarty buffer by using the menu entry
+ \"Activate Options\"."
+ :type 'boolean
+ :group 'smarty-header)
+
+(defgroup smarty-misc nil
+ "Miscellaneous customizations."
+ :group 'smarty)
+
+(defcustom smarty-left-delimiter "{"
+ "Left escaping delimiter."
+ :type 'string
+ :group 'smarty-misc)
+
+(defcustom smarty-right-delimiter "}"
+ "Right escaping delimiter."
+ :type 'string
+ :group 'smarty-misc)
+
+(defcustom smarty-intelligent-tab t
+ "*Non-nil means `TAB' does indentation, word completion and tab insertion.
+That is, if preceding character is part of a word then complete word,
+else if not at beginning of line then insert tab,
+else if last command was a `TAB' or `RET' then dedent one step,
+else indent current line (i.e. `TAB' is bound to `smarty-electric-tab').
+If nil, TAB always indents current line (i.e. `TAB' is bound to
+`indent-according-to-mode').
+
+NOTE: Activate the new setting in a Smarty buffer by using the menu entry
+ \"Activate Options\"."
+ :type 'boolean
+ :group 'smarty-misc)
+
+(defcustom smarty-word-completion-in-minibuffer t
+ "*Non-nil enables word completion in minibuffer (for template prompts).
+
+NOTE: Activate the new setting by restarting Emacs."
+ :type 'boolean
+ :group 'smarty-misc)
+
+(defcustom smarty-word-completion-case-sensitive nil
+ "*Non-nil means word completion using `TAB' is case sensitive.
+That is, `TAB' completes words that start with the same letters and case.
+Otherwise, case is ignored."
+ :type 'boolean
+ :group 'smarty-misc)
+
+;; Functions
+
+(defun smarty-customize ()
+ "Call the customize function with `smarty' as argument."
+ (interactive)
+ (customize-browse 'smarty))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Variables
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-menu-max-size 20
+ "*Specifies the maximum size of a menu before splitting it into submenues.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Menu tools functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-menu-split (list title)
+ "Split menu LIST into several submenues, if number of
+elements > `smarty-menu-max-size'."
+ (if (> (length list) smarty-menu-max-size)
+ (let ((remain list)
+ (result '())
+ (sublist '())
+ (menuno 1)
+ (i 0))
+ (while remain
+ (setq sublist (cons (car remain) sublist))
+ (setq remain (cdr remain))
+ (setq i (+ i 1))
+ (if (= i smarty-menu-max-size)
+ (progn
+ (setq result (cons (cons (format "%s %s" title menuno)
+ (nreverse sublist)) result))
+ (setq i 0)
+ (setq menuno (+ menuno 1))
+ (setq sublist '()))))
+ (and sublist
+ (setq result (cons (cons (format "%s %s" title menuno)
+ (nreverse sublist)) result)))
+ (nreverse result))
+ list))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Source file menu
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-sources-menu nil)
+
+;; Create the source menu
+(defun smarty-add-source-files-menu ()
+ "Scan directory for all Smarty source files and generate menu.
+The directory of the current source file is scanned."
+ (interactive)
+ (message "Scanning directory for source files ...")
+ (let ((newmap (current-local-map))
+ (file-list (smarty-get-source-files))
+ menu-list found)
+ ;; Create list for menu
+ (setq found nil)
+ (while file-list
+ (setq found t)
+ (setq menu-list (cons (vector (car file-list)
+ (list 'find-file (car file-list)) t)
+ menu-list))
+ (setq file-list (cdr file-list)))
+ (setq menu-list (smarty-menu-split menu-list "Sources"))
+ (when found (setq menu-list (cons "--" menu-list)))
+ (setq menu-list (cons ["*Rescan*" smarty-add-source-files-menu t] menu-list))
+ (setq menu-list (cons "Sources" menu-list))
+ ;; Create menu
+ (easy-menu-add menu-list)
+ (easy-menu-define smarty-sources-menu newmap
+ "Smarty source files menu" menu-list))
+ (message ""))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Smarty menu
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-create-mode-menu ()
+ "Create Smarty Mode menu."
+ `("Smarty"
+ ("Templates"
+ ("Built-in Functions"
+ ["capture" smarty-template-capture t]
+ ["config_load" smarty-template-config-load t]
+ ["else" smarty-template-else t]
+ ["elseif" smarty-template-elseif t]
+ ["foreach" smarty-template-foreach t]
+ ["foreachelse" smarty-template-foreachelse t]
+ ["if" smarty-template-if t]
+ ["include" smarty-template-include t]
+ ["include_php" smarty-template-include-php t]
+ ["insert" smarty-template-insert t]
+ ["ldelim" smarty-template-ldelim t]
+ ["literal" smarty-template-literal t]
+ ["php" smarty-template-php t]
+ ["rdelim" smarty-template-rdelim t]
+ ["section" smarty-template-section t]
+ ["sectionelse" smarty-template-sectionelse t]
+ ["strip" smarty-template-strip t])
+ ("Custom Functions"
+ ["assign" smarty-template-assign t]
+ ["counter" smarty-template-counter t]
+ ["cycle" smarty-template-cycle t]
+ ["debug" smarty-template-debug t]
+ ["eval" smarty-template-eval t]
+ ["fetch" smarty-template-fetch t]
+ ["html_checkboxes" smarty-template-html-checkboxes t]
+ ["html_image" smarty-template-html-image t]
+ ["html_options" smarty-template-html-options t]
+ ["html_radios" smarty-template-html-radios t]
+ ["html_select_date" smarty-template-html-select-date t]
+ ["html_select_time" smarty-template-html-select-time t]
+ ["html_table" smarty-template-html-table t]
+ ["mailto" smarty-template-mailto t]
+ ["math" smarty-template-math t]
+ ["popup" smarty-template-popup t]
+ ["popup_init" smarty-template-popup-init t]
+ ["textformat" smarty-template-textformat t])
+ ("Variable Modifiers"
+ ["capitalize" smarty-template-capitalize t]
+ ["cat" smarty-template-cat t]
+ ["count_characters" smarty-template-count-characters t]
+ ["count_paragraphs" smarty-template-count-paragraphs t]
+ ["count_sentences" smarty-template-count-sentences t]
+ ["count_words" smarty-template-count-words t]
+ ["date_format" smarty-template-date-format t]
+ ["default" smarty-template-default t]
+ ["escape" smarty-template-escape t]
+ ["indent" smarty-template-indent t]
+ ["lower" smarty-template-lower t]
+ ["nl2br" smarty-template-nl2br t]
+ ["regex_replace" smarty-template-regex-replace t]
+ ["replace" smarty-template-replace t]
+ ["spacify" smarty-template-spacify t]
+ ["string_format" smarty-template-string-format t]
+ ["strip" smarty-template-vstrip t]
+ ["strip_tags" smarty-template-strip-tags t]
+ ["truncate" smarty-template-truncate t]
+ ["upper" smarty-template-upper t]
+ ["wordwrap" smarty-template-wordwrap t])
+ ("Plugins (Functions)"
+ ("BlockRepeatPlugin"
+ ["repeat" smarty-template-repeat t]
+ ["str_repeat" smarty-template-str-repeat t])
+ ("ClipCache"
+ ["clipcache" smarty-template-clipcache t]
+ ["include_clipcache" smarty-template-include-clipcache t])
+ ("SmartyFormtool"
+ ["formtool_checkall" smarty-template-formtool-checkall t]
+ ["formtool_copy" smarty-template-formtool-copy t]
+ ["formtool_count_chars" smarty-template-formtool-count-chars t]
+ ["formtool_init" smarty-template-formtool-init t]
+ ["formtool_move" smarty-template-formtool-move t]
+ ["formtool_moveall" smarty-template-formtool-moveall t]
+ ["formtool_movedown" smarty-template-formtool-movedown t]
+ ["formtool_moveup" smarty-template-formtool-moveup t]
+ ["formtool_remove" smarty-template-formtool-remove t]
+ ["formtool_rename" smarty-template-formtool-rename t]
+ ["formtool_save" smarty-template-formtool-save t]
+ ["formtool_selectall" smarty-template-formtool-selectall t])
+ ("SmartyPaginate"
+ ["paginate_first" smarty-template-paginate-first t]
+ ["paginate_last" smarty-template-paginate-last t]
+ ["paginate_middle" smarty-template-paginate-middle t]
+ ["paginate_next" smarty-template-paginate-next t]
+ ["paginate_prev" smarty-template-paginate-prev t])
+ ("SmartyValidate"
+ ["validate" smarty-template-validate t]))
+ ("Plugins (Variable Modifiers)"
+ ("AlternativeDateModifierPlugin"
+ ["date_format2" smarty-template-date-formatto t])
+ ("B2Smilies"
+ ["B2Smilies" smarty-template-btosmilies t])
+ ("BBCodePlugin"
+ ["bbcode2html" smarty-template-bbcodetohtml t])
+ )
+ "--"
+ ["Insert Header" smarty-template-header t]
+ ["Insert Footer" smarty-template-footer t]
+ ["Insert Date" smarty-template-insert-date t]
+ ["Modify Date" smarty-template-modify t])
+ "--"
+ ["Show Messages" smarty-show-messages :keys "C-c M-m"]
+ ["Smarty Mode Documentation" smarty-doc-mode :keys "C-c C-h"]
+ ["Version" smarty-version :keys "C-c C-v"]
+ "--"
+ ("Options"
+ ("Mode"
+ ["Electric Mode"
+ (progn (customize-set-variable 'smarty-electric-mode
+ (not smarty-electric-mode))
+ (smarty-mode-line-update))
+ :style toggle :selected smarty-electric-mode :keys "C-c C-m C-e"]
+ ["Stutter Mode"
+ (progn (customize-set-variable 'smarty-stutter-mode
+ (not smarty-stutter-mode))
+ (smarty-mode-line-update))
+ :style toggle :selected smarty-stutter-mode :keys "C-c C-m C-s"]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-mode) t])
+ ("Menu"
+ ["Source Menu"
+ (customize-set-variable 'smarty-source-file-menu
+ (not smarty-source-file-menu))
+ :style toggle :selected smarty-source-file-menu]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-menu) t])
+ ("Highlight"
+ ["Highlight plugin functions"
+ (progn (customize-set-variable 'smarty-highlight-plugin-functions
+ (not smarty-highlight-plugin-functions)))
+ :style toggle :selected smarty-highlight-plugin-functions]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-highlight) t])
+ ("Template"
+ ("Header"
+ ["Header template..."
+ (customize-option 'smarty-file-header) t]
+ ["Footer template..."
+ (customize-option 'smarty-file-footer) t]
+ ["Company..."
+ (customize-option 'smarty-company-name) t]
+ ["Copyright..."
+ (customize-option 'smarty-copyright-string) t]
+ ["Date format..."
+ (customize-option 'smarty-date-format) t]
+ ["Modify date prefix..."
+ (customize-option 'smarty-modify-date-prefix-string) t]
+ ["Modify date on saving"
+ (customize-set-variable 'smarty-modify-date-on-saving
+ (not smarty-modify-date-on-saving))
+ :style toggle :selected smarty-modify-date-on-saving]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-header) t])
+ "--"
+ ["Customize Group..." (customize-group 'smarty-template) t])
+ ("Miscellaneous"
+ ["Left delimiter..."
+ (customize-option 'smarty-left-delimiter) t]
+ ["Right delimiter..."
+ (customize-option 'smarty-right-delimiter) t]
+ ["Use Intelligent Tab"
+ (progn (customize-set-variable 'smarty-intelligent-tab
+ (not smarty-intelligent-tab))
+ (smarty-activate-customizations))
+ :style toggle :selected smarty-intelligent-tab]
+ ["Word Completion in Minibuffer"
+ (progn (customize-set-variable 'smarty-word-completion-in-minibuffer
+ (not smarty-word-completion-in-minibuffer))
+ (message "Activate new setting by saving options and restarting Emacs"))
+ :style toggle :selected smarty-word-completion-in-minibuffer]
+ ["Completion is case sensitive"
+ (customize-set-variable 'smarty-word-completion-case-sensitive
+ (not smarty-word-completion-case-sensitive))
+ :style toggle :selected smarty-word-completion-case-sensitive]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-misc) t])
+ "--"
+ ["Save Options" customize-save-customized t]
+ ["Activate Options" smarty-activate-customizations t]
+ ["Browse Options..." smarty-customize t])))
+
+(defvar smarty-mode-menu-list (smarty-create-mode-menu)
+ "Smarty Mode menu.")
+
+(defvar smarty-mode-map nil
+ "Keymap for Smarty Mode.")
+
+(defun smarty-update-mode-menu ()
+ "Update Smarty Mode menu."
+ (interactive)
+ (easy-menu-remove smarty-mode-menu-list)
+ (setq smarty-mode-menu-list (smarty-create-mode-menu))
+ (easy-menu-add smarty-mode-menu-list)
+ (easy-menu-define smarty-mode-menu smarty-mode-map
+ "Menu keymap for Smarty Mode." smarty-mode-menu-list))
+
+
+
+
+(defvar smarty-mode-hook nil)
+
+(defvar smarty-functions nil
+ "List of Smarty functions.")
+
+(defvar smarty-functions-regexp nil
+ "Regexp for Smarty functions.")
+
+(defconst smarty-01-functions
+ '("capture" "config_load" "foreach" "foreachelse" "include"
+ "include_php" "insert" "if" "elseif" "else" "ldelim" "rdelim"
+ "literal" "php" "section" "sectionelse" "strip" "assign" "counter"
+ "cycle" "debug" "eval" "fetch" "html_checkboxes" "html_image"
+ "html_options" "html_radios" "html_select_date" "html_select_time"
+ "html_table" "math" "mailto" "popup_init" "popup" "textformat")
+ "Smarty built-in & custom functions.")
+
+(defvar smarty-modifiers nil
+ "List of Smarty variable modifiers.")
+
+(defvar smarty-modifiers-regexp nil
+ "Regexp for Smarty variable modifiers.")
+
+(defconst smarty-01-modifiers
+ '("capitalize" "cat" "count_characters" "count_paragraphs"
+ "count_sentences" "count_words" "date_format" "default"
+ "escape" "indent" "lower" "nl2br" "regex_replace" "replace"
+ "spacify" "string_format" "strip" "strip_tags" "truncate"
+ "upper" "wordwrap")
+ "Smarty variable modifiers.")
+
+(defvar smarty-plugins-functions nil
+ "List of Smarty functions.")
+
+(defvar smarty-plugins-functions-regexp nil
+ "Regexp for Smarty functions.")
+
+(defconst smarty-01-plugins-functions
+ '("validate" "formtool_checkall" "formtool_copy" "formtool_count_chars"
+ "formtool_init" "formtool_move" "formtool_moveall"
+ "formtool_movedown" "formtool_moveup" "formtool_remove"
+ "formtool_rename" "formtool_save" "formtool_selectall"
+ "paginate_first" "paginate_last" "paginate_middle"
+ "paginate_next" "paginate_prev" "clipcache" "include_clipcache"
+ "repeat" "str_repeat")
+ "Smarty plugins functions.")
+
+(defvar smarty-plugins-modifiers nil
+ "List of Smarty variable modifiers.")
+
+(defvar smarty-plugins-modifiers-regexp nil
+ "Regexp for Smarty functions.")
+
+(defconst smarty-01-plugins-modifiers
+ '("B2Smilies" "bbcode2html" "date_format2")
+ "Smarty plugins modifiers.")
+
+(defconst smarty-constants
+ (eval-when-compile
+ (regexp-opt
+ '("TRUE" "FALSE" "NULL") t))
+ "Smarty constants.")
+
+
+;; Syntax table creation
+(defvar smarty-mode-syntax-table nil
+ "Syntax table for smarty-mode.")
+
+(defvar smarty-mode-ext-syntax-table nil
+ "Syntax table extended by `_' used in `smarty-mode' buffers.")
+
+(defun smarty-create-syntax-table ()
+ (if smarty-mode-syntax-table
+ ()
+ (setq smarty-mode-syntax-table (make-syntax-table))
+
+ ;; Make | a punctuation character
+ (modify-syntax-entry ?| "." smarty-mode-syntax-table)
+ ;; Make " a punctuation character so highlighing works withing html strings
+ (modify-syntax-entry ?\" "." smarty-mode-syntax-table)
+ ;; define parentheses to match
+ (modify-syntax-entry ?\( "()" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\) ")(" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\{ "(}" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\} "){" smarty-mode-syntax-table)
+ )
+ (set-syntax-table smarty-mode-syntax-table)
+ ;; extended syntax table including '_' (for simpler search regexps)
+ (setq smarty-mode-ext-syntax-table (copy-syntax-table smarty-mode-syntax-table))
+ (modify-syntax-entry ?_ "w" smarty-mode-ext-syntax-table))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; File/directory manipulation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-directory-files (directory &optional full match)
+ "Call `directory-files' if DIRECTORY exists, otherwise generate error
+message."
+ (if (not (file-directory-p directory))
+ (smarty-warning-when-idle "No such directory: \"%s\"" directory)
+ (let ((dir (directory-files directory full match)))
+ (setq dir (delete "." dir))
+ (setq dir (delete ".." dir))
+ dir)))
+
+(defun smarty-get-source-files (&optional full directory)
+ "Get list of SMARTY source files in DIRECTORY or current directory."
+ (let ((mode-alist auto-mode-alist)
+ filename-regexp)
+ ;; create regular expressions for matching file names
+ (setq filename-regexp "\\`[^.].*\\(")
+ (while mode-alist
+ (when (eq (cdar mode-alist) 'smarty-mode)
+ (setq filename-regexp
+ (concat filename-regexp (caar mode-alist) "\\|")))
+ (setq mode-alist (cdr mode-alist)))
+ (setq filename-regexp
+ (concat (substring filename-regexp 0
+ (string-match "\\\\|$" filename-regexp)) "\\)"))
+ ;; find files
+ (smarty-directory-files
+ (or directory default-directory) full filename-regexp)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Messages reporting
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-warnings nil
+ "Warnings to tell the user during start up.")
+
+(defun smarty-run-when-idle (secs repeat function)
+ "Wait until idle, then run FUNCTION."
+ (if (fboundp 'start-itimer)
+ (start-itimer "smarty-mode" function secs repeat t)
+; (run-with-idle-timer secs repeat function)))
+ ;; explicitely activate timer (necessary when Emacs is already idle)
+ (aset (run-with-idle-timer secs repeat function) 0 nil)))
+
+(defun smarty-warning-when-idle (&rest args)
+ "Wait until idle, then print out warning STRING and beep."
+ (save-match-data ;; runs in timer
+ (if noninteractive
+ (smarty-warning (apply 'format args) t)
+ (unless smarty-warnings
+ (smarty-run-when-idle .1 nil 'smarty-print-warnings))
+ (setq smarty-warnings (cons (apply 'format args) smarty-warnings)))))
+
+(defun smarty-warning (string &optional nobeep)
+ "Print out warning STRING and beep."
+ (message (concat "WARNING: " string))
+ (unless (or nobeep noninteractive) (beep)))
+
+(defun smarty-print-warnings ()
+ "Print out messages in variable `smarty-warnings'."
+ (let ((no-warnings (length smarty-warnings)))
+ (setq smarty-warnings (nreverse smarty-warnings))
+ (while smarty-warnings
+ (message (concat "WARNING: " (car smarty-warnings)))
+ (setq smarty-warnings (cdr smarty-warnings)))
+ (beep)
+ (when (> no-warnings 1)
+ (message "WARNING: See warnings in message buffer (type `C-c M-m')."))))
+
+(defun smarty-show-messages ()
+ "Get *Messages* buffer to show recent messages."
+ (interactive)
+ (display-buffer " *Message-Log*"))
+
+(defun smarty-version ()
+ "Echo the current version of Smarty Mode in the minibuffer."
+ (interactive)
+ (message "Smarty Mode %s (%s)" smarty-version smarty-time-stamp)
+ (smarty-keep-region-active))
+
+;; active regions
+(defun smarty-keep-region-active ()
+ "Do whatever is necessary to keep the region active in XEmacs.
+Ignore byte-compiler warnings you might see."
+ (and (boundp 'zmacs-region-stays)
+ (setq zmacs-region-stays t)))
+
+(defmacro smarty-prepare-search-1 (&rest body)
+ "Enable case insensitive search and switch to syntax table that includes '_',
+then execute BODY, and finally restore the old environment. Used for
+consistent searching."
+ `(let ((case-fold-search t) ; case insensitive search
+ (current-syntax-table (syntax-table))
+ result
+ (restore-prog ; program to restore enviroment
+ '(progn
+ ;; restore syntax table
+ (set-syntax-table current-syntax-table))))
+ ;; use extended syntax table
+ (set-syntax-table smarty-mode-ext-syntax-table)
+ ;; execute BODY safely
+ (setq result
+ (condition-case info
+ (progn ,@body)
+ (error (eval restore-prog) ; restore environment on error
+ (error (cadr info))))) ; pass error up
+ ;; restore environment
+ (eval restore-prog)
+ result))
+
+(defmacro smarty-prepare-search-2 (&rest body)
+ "Enable case insensitive search, switch to syntax table that includes '_',
+and remove `intangible' overlays, then execute BODY, and finally restore the
+old environment. Used for consistent searching."
+ `(let ((case-fold-search t) ; case insensitive search
+ (current-syntax-table (syntax-table))
+ result overlay-all-list overlay-intangible-list overlay
+ (restore-prog ; program to restore enviroment
+ '(progn
+ ;; restore syntax table
+ (set-syntax-table current-syntax-table)
+ ;; restore `intangible' overlays
+ (when (fboundp 'overlay-lists)
+ (while overlay-intangible-list
+ (overlay-put (car overlay-intangible-list) 'intangible t)
+ (setq overlay-intangible-list
+ (cdr overlay-intangible-list)))))))
+ ;; use extended syntax table
+ (set-syntax-table smarty-mode-ext-syntax-table)
+ ;; remove `intangible' overlays
+ (when (fboundp 'overlay-lists)
+ (setq overlay-all-list (overlay-lists))
+ (setq overlay-all-list
+ (append (car overlay-all-list) (cdr overlay-all-list)))
+ (while overlay-all-list
+ (setq overlay (car overlay-all-list))
+ (when (memq 'intangible (overlay-properties overlay))
+ (setq overlay-intangible-list
+ (cons overlay overlay-intangible-list))
+ (overlay-put overlay 'intangible nil))
+ (setq overlay-all-list (cdr overlay-all-list))))
+ ;; execute BODY safely
+ (setq result
+ (condition-case info
+ (progn ,@body)
+ (error (eval restore-prog) ; restore environment on error
+ (error (cadr info))))) ; pass error up
+ ;; restore environment
+ (eval restore-prog)
+ result))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Enabling/disabling
+
+(defun smarty-mode-line-update ()
+ "Update the modeline string for Smarty major mode."
+ (setq mode-name (concat "Smarty"
+ (and (or smarty-electric-mode smarty-stutter-mode) "/")
+ (and smarty-electric-mode "e")
+ (and smarty-stutter-mode "s")))
+ (force-mode-line-update t))
+
+(defun smarty-electric-mode (arg)
+ "Toggle Smarty electric mode.
+Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
+ (interactive "P")
+ (setq smarty-electric-mode
+ (cond ((or (not arg) (zerop arg)) (not smarty-electric-mode))
+ ((> arg 0) t) (t nil)))
+ (smarty-mode-line-update))
+
+(defun smarty-stutter-mode (arg)
+ "Toggle Smarty stuttering mode.
+Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
+ (interactive "P")
+ (setq smarty-stutter-mode
+ (cond ((or (not arg) (zerop arg)) (not smarty-stutter-mode))
+ ((> arg 0) t) (t nil)))
+ (smarty-mode-line-update))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Smarty code delimitation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-in-literal ()
+ "Determine if point is in a Smarty literal."
+ (save-excursion
+ (let ((here (point))
+ start state)
+ (beginning-of-line)
+ (setq start (point))
+ (goto-char here)
+ (setq state (parse-partial-sexp start (point)))
+ (cond
+ ((nth 3 state) 'string)
+ ((nth 4 state) 'comment)
+ (t nil)))))
+
+(defun smarty-in-comment-p ()
+ "Check if point is in a comment."
+ (let ((result nil) (here (point-marker)) found)
+ (save-excursion
+ (setq found (re-search-backward (regexp-quote (concat smarty-left-delimiter "*")) nil t))
+ (when found
+ (setq result (re-search-forward (regexp-quote (concat "*" smarty-right-delimiter)) here t))
+ (setq result (not result))))
+ result))
+
+(defun smarty-after-ldelim ()
+ "Check that the previous character is the left delimiter."
+ (let ((here (point-marker)) ldelim-found ldelim-point)
+ (save-excursion
+ (setq ldelim-found (re-search-backward (regexp-quote smarty-left-delimiter) nil t))
+ (re-search-forward (regexp-quote smarty-left-delimiter) here t)
+ (setq ldelim-point (point-marker))
+ (goto-char here)
+ (if (and (= here ldelim-point) ldelim-found)
+ t
+ nil))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Words to expand
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-words-init ()
+ "Initialize reserved words."
+ (setq smarty-functions smarty-01-functions)
+ (setq smarty-modifiers smarty-01-modifiers)
+ (setq smarty-plugins-functions smarty-01-plugins-functions)
+ (setq smarty-plugins-modifiers smarty-01-plugins-modifiers)
+ (setq smarty-functions-regexp (concat "\\<\\(" (regexp-opt smarty-functions) "\\)\\>"))
+ (setq smarty-modifiers-regexp (concat "\\<\\(" (regexp-opt smarty-modifiers) "\\)\\>"))
+ (setq smarty-plugins-functions-regexp (concat "\\<\\(" (regexp-opt smarty-plugins-functions) "\\)\\>"))
+ (setq smarty-plugins-modifiers-regexp (concat "\\<\\(" (regexp-opt smarty-plugins-modifiers) "\\)\\>"))
+ (smarty-abbrev-list-init))
+
+(defvar smarty-abbrev-list nil
+ "Predefined abbreviations for Smarty.")
+
+(defun smarty-abbrev-list-init ()
+ (setq smarty-abbrev-list
+ (append
+ (list nil) smarty-functions
+ (list nil) smarty-modifiers
+ (list nil) smarty-plugins-functions
+ (list nil) smarty-plugins-modifiers)))
+
+(defvar smarty-expand-upper-case nil)
+
+(defun smarty-try-expand-abbrev (old)
+ "Try expanding abbreviations from `smarty-abbrev-list'."
+ (unless old
+ (he-init-string (he-dabbrev-beg) (point))
+ (setq he-expand-list
+ (let ((abbrev-list smarty-abbrev-list)
+ (sel-abbrev-list '()))
+ (while abbrev-list
+ ; (if (stringp (car abbrev-list))
+ ; (insert (concat " " (car abbrev-list))))
+ (when (or (not (stringp (car abbrev-list)))
+ (string-match
+ (concat "^" he-search-string) (car abbrev-list)))
+ (setq sel-abbrev-list
+ (cons (car abbrev-list) sel-abbrev-list)))
+ (setq abbrev-list (cdr abbrev-list)))
+ (nreverse sel-abbrev-list))))
+ (while (and he-expand-list
+ (or (not (stringp (car he-expand-list)))
+ (he-string-member (car he-expand-list) he-tried-table t)))
+ (unless (stringp (car he-expand-list))
+ (setq smarty-expand-upper-case (car he-expand-list)))
+ (setq he-expand-list (cdr he-expand-list)))
+ (if (null he-expand-list)
+ (progn (when old (he-reset-string))
+ nil)
+ (he-substitute-string
+ (if smarty-expand-upper-case
+ (upcase (car he-expand-list))
+ (car he-expand-list))
+ t)
+ (setq he-expand-list (cdr he-expand-list))
+ t))
+
+;; initialize reserved words for Smarty Mode
+(smarty-words-init)
+
+;; function for expanding abbrevs and dabbrevs
+(defun smarty-expand-abbrev (arg))
+(fset 'smarty-expand-abbrev (make-hippie-expand-function
+ '(try-expand-dabbrev
+ try-expand-dabbrev-all-buffers
+ smarty-try-expand-abbrev)))
+
+;; function for expanding parenthesis
+(defun smarty-expand-paren (arg))
+(fset 'smarty-expand-paren (make-hippie-expand-function
+ '(try-expand-list
+ try-expand-list-all-buffers)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Stuttering
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-end-comment-column 80)
+
+(defvar found) ;; silence compiler, dyn var
+
+(defun smarty-electric-tab (&optional prefix-arg)
+ "If preceding character is part of a word or a paren then hippie-expand,
+else if right of non whitespace on line then insert tab,
+else if last command was a tab or return then dedent one step or if a comment
+toggle between normal indent and inline comment indent,
+else indent `correctly'."
+ (interactive "*P")
+ (smarty-prepare-search-2
+ (cond
+ ;; expand word
+ ((= (char-syntax (preceding-char)) ?w)
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil)
+ (hippie-expand-only-buffers
+ (or (and (boundp 'hippie-expand-only-buffers)
+ hippie-expand-only-buffers)
+ '(smarty-mode))))
+ (smarty-expand-abbrev prefix-arg)))
+ ;; expand parenthesis
+ ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil))
+ (smarty-expand-paren prefix-arg))))
+ (setq this-command 'smarty-electric-tab)))
+
+(defun smarty-electric-space (count)
+ "Expand abbreviations and self-insert space(s)."
+ (interactive "p")
+ (let ((here (point-marker)) ldelim-found ldelim-point rdelim-found rdelim-point
+ delete-a)
+ (setq ldelim-found (re-search-backward (regexp-quote smarty-left-delimiter) nil t))
+ (re-search-forward (regexp-quote smarty-left-delimiter) here t)
+ (setq ldelim-point (point-marker))
+ (goto-char here)
+ (setq rdelim-found (re-search-backward (regexp-quote (concat " " smarty-right-delimiter)) nil t))
+ (re-search-forward (regexp-quote (concat " " smarty-right-delimiter)) here t)
+ (setq rdelim-point (point-marker))
+ (goto-char here)
+ (cond ((and (= here ldelim-point) ldelim-found) (insert (concat "ldelim" smarty-right-delimiter)))
+ ((and (= here rdelim-point) rdelim-found)
+ (re-search-backward (regexp-quote (concat " " smarty-right-delimiter)) nil t)
+ (delete-char 1)
+ (insert (concat " " smarty-left-delimiter "rdelim"))
+ (goto-char here))
+ ((smarty-in-comment-p)
+ (self-insert-command count)
+ (cond ((>= (current-column) (+ 2 smarty-end-comment-column))
+ (backward-char 1)
+ (skip-chars-backward "^ \t\n")
+ (indent-new-comment-line)
+ (skip-chars-forward "^ \t\n")
+ (forward-char 1))
+ ((>= (current-column) smarty-end-comment-column)
+ (indent-new-comment-line))
+ (t nil)))
+ ((or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
+ (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z))
+ (and (>= (preceding-char) ?0) (<= (preceding-char) ?9)))
+ (progn
+ (setq here (point-marker))
+ (insert " ")
+ (setq delete-a t)
+ (if (re-search-backward "|" nil t)
+ (progn
+ (setq found (re-search-forward (regexp-quote "B2Smilies") here t))
+ (if (and found (= here (point-marker)))
+ (replace-match "btosmilies")
+ (setq found (re-search-forward (regexp-quote "bbcode2html") here t))
+ (if (and found (= here (point-marker)))
+ (replace-match "bbcodetohtml")
+ (setq found (re-search-forward (regexp-quote "date_format2") here t))
+ (if (and found (= here (point-marker)))
+ (replace-match "date_formatto")
+ (goto-char here)
+ (setq delete-a nil)
+ (delete-char 1)))))
+ (goto-char here)
+ (setq delete-a nil)
+ (delete-char 1)))
+ (smarty-prepare-search-1 (expand-abbrev))
+ (self-insert-command count)
+ (if (and delete-a (looking-at " "))
+ (delete-char 1)))
+ (t (self-insert-command count)))))
+
+(defun smarty-electric-open-bracket (count)
+ "'(' --> '(', '((' --> '[', '[(' --> '{'"
+ (interactive "p")
+ (if (and smarty-stutter-mode (= count 1) (not (smarty-in-literal)))
+ (if (= (preceding-char) ?\()
+ (progn (delete-char -1) (insert-char ?\[ 1))
+ (if (= (preceding-char) ?\[)
+ (progn (delete-char -1) (insert-char ?\{ 1))
+ (insert-char ?\( 1)))
+ (self-insert-command count)))
+
+(defun smarty-electric-close-bracket (count)
+ "')' --> ')', '))' --> ']', '])' --> '}'"
+ (interactive "p")
+ (if (and smarty-stutter-mode (= count 1) (not (smarty-in-literal)))
+ (progn
+ (if (= (preceding-char) ?\))
+ (progn (delete-char -1) (insert-char ?\] 1))
+ (if (= (preceding-char) ?\])
+ (progn (delete-char -1) (insert-char ?} 1))
+ (insert-char ?\) 1)))
+ (blink-matching-open))
+ (self-insert-command count)))
+
+(defun smarty-electric-star (count)
+ "After a left delimiter add a right delemiter to close the comment"
+ (interactive "p")
+ (let ((here (point-marker)) found)
+ (if (and smarty-stutter-mode (= count 1) (not (smarty-in-literal)))
+ (progn
+ (setq found (re-search-backward (regexp-quote smarty-left-delimiter) nil t))
+ (re-search-forward (regexp-quote smarty-left-delimiter) here t)
+ (if (not (and (= here (point-marker)) found))
+ (progn (goto-char here)
+ (self-insert-command count))
+ (self-insert-command count)
+ (insert " ")
+ (setq here (point-marker))
+ (insert " *")
+ (insert smarty-right-delimiter)
+ (goto-char here)))
+ (self-insert-command count))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Electrification
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst smarty-template-prompt-syntax "[^ =<>][^<>@.\n]*[^ =<>]"
+ "Syntax of prompt inserted by template generators.")
+
+(defvar smarty-template-invoked-by-hook nil
+ "Indicates whether a template has been invoked by a hook or by key or menu.
+Used for undoing after template abortion.")
+
+(defun smarty-minibuffer-tab (&optional prefix-arg)
+ "If preceding character is part of a word or a paren then hippie-expand,
+else insert tab (used for word completion in Smarty minibuffer)."
+ (interactive "P")
+ (cond
+ ;; expand word
+ ((= (char-syntax (preceding-char)) ?w)
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil)
+ (hippie-expand-only-buffers
+ (or (and (boundp 'hippie-expand-only-buffers)
+ hippie-expand-only-buffers)
+ '(smarty-mode))))
+ (smarty-expand-abbrev prefix-arg)))
+ ;; expand parenthesis
+ ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil))
+ (smarty-expand-paren prefix-arg)))
+ ;; insert tab
+ (t (insert-tab))))
+
+;; correct different behavior of function `unread-command-events' in XEmacs
+(defun smarty-character-to-event (arg))
+(defalias 'smarty-character-to-event
+ (if (fboundp 'character-to-event) 'character-to-event 'identity))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Abbrev ook bindings
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-mode-abbrev-table nil
+ "Abbrev table to use in `smarty-mode' buffers.")
+
+(defun smarty-mode-abbrev-table-init ()
+ "Initialize `smarty-mode-abbrev-table'."
+ (when smarty-mode-abbrev-table (clear-abbrev-table smarty-mode-abbrev-table))
+ (define-abbrev-table 'smarty-mode-abbrev-table
+ (append
+ '(
+ ("capture" "" smarty-template-capture-hook 0)
+ ("config_load" "" smarty-template-config-load-hook 0)
+ ("else" "" smarty-template-else-hook 0)
+ ("elseif" "" smarty-template-elseif-hook 0)
+ ("foreach" "" smarty-template-foreach-hook 0)
+ ("foreachelse" "" smarty-template-foreachelse-hook 0)
+ ("if" "" smarty-template-if-hook 0)
+ ("include" "" smarty-template-include-hook 0)
+ ("include_php" "" smarty-template-include-php-hook 0)
+ ("insert" "" smarty-template-insert-hook 0)
+ ("ldelim" "" smarty-template-ldelim-hook 0)
+ ("literal" "" smarty-template-literal-hook 0)
+ ("php" "" smarty-template-php-hook 0)
+ ("rdelim" "" smarty-template-rdelim-hook 0)
+ ("section" "" smarty-template-section-hook 0)
+ ("sectionelse" "" smarty-template-sectionelse-hook 0)
+ ("strip" "" smarty-template-strip-hook 0)
+ ("assign" "" smarty-template-assign-hook 0)
+ ("counter" "" smarty-template-counter-hook 0)
+ ("cycle" "" smarty-template-cycle-hook 0)
+ ("debug" "" smarty-template-debug-hook 0)
+ ("eval" "" smarty-template-eval-hook 0)
+ ("fetch" "" smarty-template-fetch-hook 0)
+ ("html_checkboxes" "" smarty-template-html-checkboxes-hook 0)
+ ("html_image" "" smarty-template-html-image-hook 0)
+ ("html_options" "" smarty-template-html-options-hook 0)
+ ("html_radios" "" smarty-template-html-radios-hook 0)
+ ("html_select_date" "" smarty-template-html-select-date-hook 0)
+ ("html_select_time" "" smarty-template-html-select-time-hook 0)
+ ("html_table" "" smarty-template-html-table-hook 0)
+ ("mailto" "" smarty-template-mailto-hook 0)
+ ("math" "" smarty-template-math-hook 0)
+ ("popup" "" smarty-template-popup-hook 0)
+ ("popup_init" "" smarty-template-popup-init-hook 0)
+ ("textformat" "" smarty-template-textformat-hook 0)
+ ("capitalize" "" smarty-template-capitalize-hook 0)
+ ("cat" "" smarty-template-cat-hook 0)
+ ("count_characters" "" smarty-template-count-characters-hook 0)
+ ("count_paragraphs" "" smarty-template-count-paragraphs-hook 0)
+ ("count_sentences" "" smarty-template-count-sentences-hook 0)
+ ("count_words" "" smarty-template-count-words-hook 0)
+ ("date_format" "" smarty-template-date-format-hook 0)
+ ("default" "" smarty-template-default-hook 0)
+ ("escape" "" smarty-template-escape-hook 0)
+ ("indent" "" smarty-template-indent-hook 0)
+ ("lower" "" smarty-template-lower-hook 0)
+ ("nl2br" "" smarty-template-nl2br-hook 0)
+ ("regex_replace" "" smarty-template-regex-replace-hook 0)
+ ("replace" "" smarty-template-replace-hook 0)
+ ("spacify" "" smarty-template-spacify-hook 0)
+ ("string_format" "" smarty-template-string-format-hook 0)
+ ("strip" "" smarty-template-vstrip-hook 0)
+ ("strip_tags" "" smarty-template-strip-tags-hook 0)
+ ("truncate" "" smarty-template-truncate-hook 0)
+ ("upper" "" smarty-template-upper-hook 0)
+ ("wordwrap" "" smarty-template-wordwrap-hook 0)
+ ("validate" "" smarty-template-validate-hook 0)
+ ("clipcache" "" smarty-template-clipcache-hook 0)
+ ("repeat" "" smarty-template-repeat-hook 0)
+ ("str_repeat" "" smarty-template-str-repeat-hook 0)
+ ("include_clipcache" "" smarty-template-include-clipcache-hook 0)
+ ("formtool_checkall" "" smarty-template-formtool-checkall-hook 0)
+ ("formtool_copy" "" smarty-template-formtool-copy-hook 0)
+ ("formtool_count_chars" "" smarty-template-formtool-count-chars-hook 0)
+ ("formtool_init" "" smarty-template-formtool-init-hook 0)
+ ("formtool_move" "" smarty-template-formtool-move-hook 0)
+ ("formtool_moveall" "" smarty-template-formtool-moveall-hook 0)
+ ("formtool_movedown" "" smarty-template-formtool-movedown-hook 0)
+ ("formtool_moveup" "" smarty-template-formtool-moveup-hook 0)
+ ("formtool_remove" "" smarty-template-formtool-remove-hook 0)
+ ("formtool_rename" "" smarty-template-formtool-rename-hook 0)
+ ("formtool_save" "" smarty-template-formtool-save-hook 0)
+ ("formtool_selectall" "" smarty-template-formtool-selectall-hook 0)
+ ("paginate_first" "" smarty-template-paginate-first-hook 0)
+ ("paginate_last" "" smarty-template-paginate-last-hook 0)
+ ("paginate_middle" "" smarty-template-paginate-middle-hook 0)
+ ("paginate_next" "" smarty-template-paginate-next-hook 0)
+ ("paginate_prev" "" smarty-template-paginate-prev-hook 0)
+ ("btosmilies" "" smarty-template-btosmilies-hook 0)
+ ("bbcodetohtml" "" smarty-template-bbcodetohtml-hook 0)
+ ("date_formatto" "" smarty-template-date-formatto-hook 0)))))
+
+;; initialize abbrev table for Smarty Mode
+(smarty-mode-abbrev-table-init)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Abbrev hooks
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-hooked-abbrev (func)
+ "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
+but not if inside a comment or quote)."
+ (if (or (smarty-in-literal)
+ (smarty-in-comment-p))
+ (progn
+ (insert " ")
+ (unexpand-abbrev)
+ (delete-char -1))
+ (if (not smarty-electric-mode)
+ (progn
+ (insert " ")
+ (unexpand-abbrev)
+ (backward-word 1)
+ (delete-char 1))
+ (let ((invoke-char last-command-event)
+ (abbrev-mode -1)
+ (smarty-template-invoked-by-hook t))
+ (let ((caught (catch 'abort
+ (funcall func))))
+ (when (stringp caught) (message caught)))
+ (when (= invoke-char ?-) (setq abbrev-start-location (point)))
+ ;; delete CR which is still in event queue
+ (if (fboundp 'enqueue-eval-event)
+ (enqueue-eval-event 'delete-char -1)
+ (setq unread-command-events ; push back a delete char
+ (list (smarty-character-to-event ?\177))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Fontification
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-font-lock-keywords-1
+ (list
+
+ ;; Fontify built-in functions
+ (cons
+ (concat (regexp-quote smarty-left-delimiter) "[/]*" smarty-functions-regexp)
+ '(1 font-lock-keyword-face))
+
+ (cons
+ (concat "\\<\\(" smarty-constants "\\)\\>")
+ 'font-lock-constant-face)
+
+ (cons (concat "\\(" (regexp-quote (concat smarty-left-delimiter "*")) "\\(\\s-\\|\\w\\|\\s.\\|\\s_\\|\\s(\\|\\s)\\|\\s\\\\)*" (regexp-quote (concat "*" smarty-right-delimiter)) "\\)")
+ 'font-lock-comment-face)
+
+ )
+ "Subdued level highlighting for Smarty mode.")
+
+(defconst smarty-font-lock-keywords-2
+ (append
+ smarty-font-lock-keywords-1
+ (list
+
+ ;; Fontify variable names (\\sw\\|\\s_\\) matches any word character +
+ ;; underscore
+ '("\\$\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face)) ; $variable
+ '("->\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face t t)) ; ->variable
+ '("\\.\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face t t)) ; .variable
+ '("->\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" (1 font-lock-function-name-face t t)) ; ->function_call
+ '("\\<\\(\\(?:\\sw\\|\\s_\\)+\\s-*\\)(" (1 font-lock-function-name-face)) ; word(
+ '("\\<\\(\\(?:\\sw\\|\\s_\\)+\\s-*\\)[[]" (1 font-lock-variable-name-face)) ; word[
+ '("\\<[0-9]+" . 'default) ; number (also matches word)
+
+ ;; Fontify strings
+ ;;'("\"\\([^\"]*\\)\"[^\"]+" (1 font-lock-string-face t t))
+ ))
+
+ "Medium level highlighting for Smarty mode.")
+
+(defconst smarty-font-lock-keywords-3
+ (append
+ smarty-font-lock-keywords-2
+ (list
+ ;; Fontify modifiers
+ (cons (concat "|\\(" smarty-modifiers-regexp "\\)[:|]+") '(1 font-lock-function-name-face))
+ (cons (concat "|\\(" smarty-modifiers-regexp "\\)" (regexp-quote smarty-right-delimiter)) '(1 font-lock-function-name-face))
+
+ ;; Fontify config vars
+ (cons (concat (regexp-quote smarty-left-delimiter) "\\(#\\(?:\\sw\\|\\s_\\)+#\\)") '(1 font-lock-constant-face))))
+ "Balls-out highlighting for Smarty mode.")
+
+(defconst smarty-font-lock-keywords-4
+ (append
+ smarty-font-lock-keywords-3
+ (list
+ ;; Fontify plugin functions
+ (cons
+ (concat (regexp-quote smarty-left-delimiter) "[/]*" smarty-plugins-functions-regexp)
+ '(1 font-lock-keyword-face))
+
+ (cons (concat "|\\(" smarty-plugins-modifiers-regexp "\\)[:|]+") '(1 font-lock-function-name-face))
+ (cons (concat "|\\(" smarty-plugins-modifiers-regexp "\\)" (regexp-quote smarty-right-delimiter)) '(1 font-lock-function-name-face)))))
+
+(defvar smarty-font-lock-keywords smarty-font-lock-keywords-3
+ "Default highlighting level for Smarty mode")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mode map
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-template-map nil
+ "Keymap for Smarty templates.")
+
+(defun smarty-template-map-init ()
+ "Initialize `smarty-template-map'."
+ (setq smarty-template-map (make-sparse-keymap))
+ ;; key bindings for Smarty templates
+ (define-key smarty-template-map "\C-ba" 'smarty-template-capture)
+ (define-key smarty-template-map "\C-bc" 'smarty-template-config-load)
+ (define-key smarty-template-map "\C-b\M-e" 'smarty-template-else)
+ (define-key smarty-template-map "\C-b\C-e" 'smarty-template-elseif)
+ (define-key smarty-template-map "\C-b\C-f" 'smarty-template-foreach)
+ (define-key smarty-template-map "\C-b\M-f" 'smarty-template-foreachelse)
+ (define-key smarty-template-map "\C-bf" 'smarty-template-if)
+ (define-key smarty-template-map "\C-b\C-i" 'smarty-template-include)
+ (define-key smarty-template-map "\C-b\M-i" 'smarty-template-include-php)
+ (define-key smarty-template-map "\C-bi" 'smarty-template-insert)
+ (define-key smarty-template-map "\C-bl" 'smarty-template-ldelim)
+ (define-key smarty-template-map "\C-b\C-l" 'smarty-template-literal)
+ (define-key smarty-template-map "\C-bp" 'smarty-template-php)
+ (define-key smarty-template-map "\C-br" 'smarty-template-rdelim)
+ (define-key smarty-template-map "\C-b\C-s" 'smarty-template-section)
+ (define-key smarty-template-map "\C-b\M-s" 'smarty-template-sectionelse)
+ (define-key smarty-template-map "\C-bs" 'smarty-template-strip)
+ (define-key smarty-template-map "\C-ca" 'smarty-template-assign)
+ (define-key smarty-template-map "\C-co" 'smarty-template-counter)
+ (define-key smarty-template-map "\C-cc" 'smarty-template-cycle)
+ (define-key smarty-template-map "\C-cd" 'smarty-template-debug)
+ (define-key smarty-template-map "\C-ce" 'smarty-template-eval)
+ (define-key smarty-template-map "\C-cf" 'smarty-template-fetch)
+ (define-key smarty-template-map "\C-c\C-hc" 'smarty-template-html-checkboxes)
+ (define-key smarty-template-map "\C-c\C-hi" 'smarty-template-html-image)
+ (define-key smarty-template-map "\C-c\C-ho" 'smarty-template-html-options)
+ (define-key smarty-template-map "\C-c\C-hr" 'smarty-template-html-radios)
+ (define-key smarty-template-map "\C-c\C-hd" 'smarty-template-html-select-date)
+ (define-key smarty-template-map "\C-c\C-hm" 'smarty-template-html-select-time)
+ (define-key smarty-template-map "\C-c\C-ht" 'smarty-template-html-table)
+ (define-key smarty-template-map "\C-ci" 'smarty-template-mailto)
+ (define-key smarty-template-map "\C-ch" 'smarty-template-math)
+ (define-key smarty-template-map "\C-c\C-p" 'smarty-template-popup)
+ (define-key smarty-template-map "\C-c\M-p" 'smarty-template-popup-init)
+ (define-key smarty-template-map "\C-ct" 'smarty-template-textformat)
+ (define-key smarty-template-map "\C-vp" 'smarty-template-capitalize)
+ (define-key smarty-template-map "\C-vc" 'smarty-template-cat)
+ (define-key smarty-template-map "\C-v\C-cc" 'smarty-template-count-characters)
+ (define-key smarty-template-map "\C-v\C-cp" 'smarty-template-count-paragraphs)
+ (define-key smarty-template-map "\C-v\C-cs" 'smarty-template-count-sentences)
+ (define-key smarty-template-map "\C-v\C-cw" 'smarty-template-count-words)
+ (define-key smarty-template-map "\C-vf" 'smarty-template-date-format)
+ (define-key smarty-template-map "\C-vd" 'smarty-template-default)
+ (define-key smarty-template-map "\C-ve" 'smarty-template-escape)
+ (define-key smarty-template-map "\C-vi" 'smarty-template-indent)
+ (define-key smarty-template-map "\C-vl" 'smarty-template-lower)
+ (define-key smarty-template-map "\C-vn" 'smarty-template-nl2br)
+ (define-key smarty-template-map "\C-vx" 'smarty-template-regex-replace)
+ (define-key smarty-template-map "\C-v\C-p" 'smarty-template-replace)
+ (define-key smarty-template-map "\C-vy" 'smarty-template-spacify)
+ (define-key smarty-template-map "\C-vs" 'smarty-template-string-format)
+ (define-key smarty-template-map "\C-v\C-s" 'smarty-template-vstrip)
+ (define-key smarty-template-map "\C-v\M-s" 'smarty-template-strip-tags)
+ (define-key smarty-template-map "\C-vt" 'smarty-template-truncate)
+ (define-key smarty-template-map "\C-vu" 'smarty-template-upper)
+ (define-key smarty-template-map "\C-vw" 'smarty-template-wordwrap)
+ (define-key smarty-template-map "\C-h" 'smarty-template-header)
+ (define-key smarty-template-map "\C-f" 'smarty-template-footer)
+ (define-key smarty-template-map "\C-di" 'smarty-template-insert-date)
+ (define-key smarty-template-map "\C-dm" 'smarty-template-modify))
+
+;; initialize template map for Smarty Mode
+(smarty-template-map-init)
+
+(defun smarty-mode-map-init ()
+ "Initialize `smarty-mode-map'."
+ (setq smarty-mode-map (make-sparse-keymap))
+ ;; template key bindings
+ (define-key smarty-mode-map "\C-c\C-t" smarty-template-map)
+ ;; mode specific key bindings
+ (define-key smarty-mode-map "\C-c\C-m\C-e" 'smarty-electric-mode)
+ (define-key smarty-mode-map "\C-c\C-m\C-s" 'smarty-stutter-mode)
+ (define-key smarty-mode-map "\C-c\C-s\C-u" 'smarty-add-source-files-menu)
+ (define-key smarty-mode-map "\C-c\M-m" 'smarty-show-messages)
+ (define-key smarty-mode-map "\C-c\C-h" 'smarty-doc-mode)
+ (define-key smarty-mode-map "\C-c\C-v" 'smarty-version)
+ ;; electric key bindings
+ (when smarty-intelligent-tab
+ (define-key smarty-mode-map "\t" 'smarty-electric-tab))
+ (define-key smarty-mode-map " " 'smarty-electric-space)
+ (define-key smarty-mode-map "(" 'smarty-electric-open-bracket)
+ (define-key smarty-mode-map ")" 'smarty-electric-close-bracket)
+ (define-key smarty-mode-map "*" 'smarty-electric-star))
+
+;; initialize mode map for Smarty Mode
+(smarty-mode-map-init)
+
+(defvar smarty-minibuffer-local-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map minibuffer-local-map)
+ (when smarty-word-completion-in-minibuffer
+ (define-key map "\t" 'smarty-minibuffer-tab))
+ map)
+ "Keymap for minibuffer used in Smarty Mode.")
+
+(mapcar
+ (function
+ (lambda (sym)
+ (put sym 'delete-selection t) ; for `delete-selection-mode' (Emacs)
+ (put sym 'pending-delete t))) ; for `pending-delete-mode' (XEmacs)
+ '(smarty-electric-space
+ smarty-electric-tab
+ smarty-electric-open-bracket
+ smarty-electric-close-bracket
+ smarty-electric-star))
+
+;;;###autoload
+(defun smarty-mode ()
+ "Smarty Mode
+***********
+
+Smarty Mode is a GNU XEmacs major mode for editing Smarty templates.
+
+1 Introduction
+**************
+
+Smarty-Mode is a mode allowing easy edit of Smarty templates:
+highlight, templates, navigation into source files...
+
+
+
+Features (new features in bold) :
+
+ * Completion
+
+ * Customizable
+
+ * Highlight
+
+ * Menu
+
+ * Stuttering
+
+ * Templates
+ - Built-in Functions
+
+ - User Functions
+
+ - Variable Modifiers
+
+ - Plugin (Functions)
+ * BlockRepeatPlugin
+
+ * ClipCache
+
+ * Smarty Formtool
+
+ * Smarty Paginate
+
+ * Smarty Validate
+
+ - Plugin (Variable Modifiers)
+ * AlternativeDateModifierPlugin
+
+ * B2Smilies
+
+ * BBCodePlugin
+
+ - Fonctions Non-Smarty
+
+
+
+This manual describes Smarty Mode version 0.0.5.
+
+2 Installation
+**************
+
+2.1 Requirements
+================
+
+Smarty Mode is a XEmacs major mode that needs the following
+software/packages:
+
+ * XEmacs (http://www.xemacs.org/).
+
+ * `font-lock' mode generaly installed with XEmacs.
+
+ * `assoc' mode generaly installed with XEmacs.
+
+ * `easymenu' mode generaly installed with XEmacs.
+
+ * `hippie-exp' mode generaly installed with XEmacs.
+
+Before continuing, you must be sure to have all this packages
+installed.
+
+2.2 Download
+============
+
+Two internet address to download Smarty Mode :
+
+ * Principal: Smarty-Mode 0.0.5
+ (http://deboutv.free.fr/lisp/smarty/download/smarty-0.0.5.tar.gz)
+ (http://deboutv.free.fr/lisp/smarty/)
+
+ * Secondary: Smarty-Mode 0.0.5
+ (http://www.morinie.fr/lisp/smarty/download/smarty-0.0.5.tar.gz)
+ (http://www.morinie.fr/lisp/smarty/)
+
+ * Old releases: Smarty-Mode
+ (http://deboutv.free.fr/lisp/smarty/download.php)
+ (http://deboutv.free.fr/lisp/smarty/)
+
+2.3 Installation
+================
+
+2.3.1 Installation
+------------------
+
+To install Smarty Mode you need to choose an installation directory
+\(for example `/usr/local/share/lisp' or `c:\lisp'). The administrator
+must have the write rights on this directory.
+
+With your favorite unzip software, unzip the archive in the
+installation directory.
+
+Example:
+ cd /usr/local/share/lisp
+ tar zxvf smarty-0.0.5.tar.gz
+Now you have a `smarty' directory in the installation directory. This
+directory contains 2 files `smarty-mode.el' and `smarty-mode.elc' and
+another directory `docs' containing the documentation.
+
+You need to configure XEmacs. open you initialization file `init.el'
+\(open the file or start XEmacs then choose the Options menu and Edit
+Init File). Add the following lines (the installation directory in
+this example is `/usr/local/share/lisp') :
+
+ (setq load-path
+ (append (list \"/usr/local/share/lisp/\") load-path))
+ (autoload 'smarty-mode \"smarty-mode\" \"Smarty Mode\" t)
+
+2.3.2 Update
+------------
+
+The update is easy. You need to unzip the archive in the installation
+directory to remove the old release.
+
+Example:
+ cd /usr/local/share/lisp
+ rm -rf smarty
+ tar zxvf smarty-0.0.5.tar.gz
+
+2.4 Invoke Smarty-Mode
+======================
+
+You have two possibilities to invoke the Smarty Mode.
+
+ - Manually: At each file opening you need to launch Smarty Mode
+ with the following command:
+
+ `M-x smarty-mode'
+
+ - Automatically: Add the following linesin your initialization
+ file `init.el' :
+
+ (setq auto-mode-alist
+ (append
+ '((\"\\.tpl$\" . smarty-mode))
+ auto-mode-alist))
+
+
+3 Customization
+***************
+
+This chapter describes the differents parameters and functions that
+you can change to customize Smarty Mode. To do that, open a Smarty
+file, click on the Smarty menu and choose Options then Browse
+Options....
+
+3.1 Parameters
+==============
+
+3.1.1 Mode
+----------
+
+Smarty Mode has 2 modes allowing to simplify the writing of Smarty
+templates. You can enable/disable each mode individually.
+
+`smarty-electric-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable automatic generation of template.
+ If `nil'; template generators can still be invoked through key
+ bindings and menu. Is indicated in the modeline by \"/e\" after
+ the mode name and can be toggled by `smarty-electric-mode'.
+
+`smarty-stutter-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable the stuttering. Is indicated in the
+ modeline by \"/s\" after the mode name and can be toggled by
+ `smarty-stutter-mode'.
+
+3.1.2 Menu
+----------
+
+Smarty Mode has also 1 menu that you can enable/disable. The menu
+Sources is specific to each Smarty files opened.
+
+`smarty-source-file-menu'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; the Sources menu is enabled. This menu
+ contains the list of Smarty file located in the current
+ directory. The Sources menu scans the directory when a file is
+ opened.
+
+3.1.3 Menu
+----------
+
+`smarty-highlight-plugin-functions'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; the functions described in the smarty
+ plugins are highlighted.
+
+3.1.4 Templates
+---------------
+
+3.1.4.1 Header
+..............
+
+`smarty-file-header'
+ Type: string
+ Default value: `\"\"'
+ Description: String or file to insert as file header. If the
+ string specifies an existing file name the contents of the file
+ is inserted; otherwise the string itself is inserted as file
+ header.
+ Type `C-j' for newlines.
+ The follonwing keywords are supported:
+ : replaced by the file name.
+ : replaced by the user name and email address.
+ : replaced by `user-login-name'.
+ : replaced by `smarty-company-name' content.
+ : replaced by the current date.
+ : replaced by the current year.
+ : replaced by `smarty-copyright-string' content.
+ : final cursor position.
+
+`smarty-file-footer'
+ Type: string
+ Default value: `\"\"'
+ Description: String or file to insert as file footer. See
+ `smarty-file-header'
+
+`smarty-company-name'
+ Type: string
+ Default value: `\"\"'
+ Description: Name of the company to insert in file header.
+
+`smarty-copyright-string'
+ Type: string
+ Default value: `\"\"'
+ Description: Coryright string to insert in file header.
+
+`smarty-date-format'
+ Type: string
+ Default value: `\"%Y-%m-%d\"'
+ Description: Date format.
+
+`smarty-modify-date-prefix-string'
+ Type: string
+ Default value: `\"\"'
+ Description: Prefix string of modification date in Smarty file
+ header.
+
+`smarty-modify-date-on-saving'
+ Type: bool
+ Default value: `nil'
+ Description: If `t'; update the modification date when the
+ buffer is saved.
+
+3.1.5 Miscellaneous
+-------------------
+
+`smarty-left-delimiter'
+ Type: string
+ Default value: `\"\"'
+ Description: Left escaping delimiter for Smarty templates.
+
+`smarty-right-delimiter'
+ Type: string
+ Default value: `\"\"'
+ Description: Right escaping delimiter for Smarty templates.
+
+`smarty-intelligent-tab'
+ Type: bool
+ Default value: `t'
+ Description: If `t'; TAB does indentation; completion and insert
+ tabulations. If `nil'; TAB does only indentation.
+
+`smarty-word-completion-in-minibuffer'
+ Type: bool
+ Default value: `t'
+ Description: If `t'; enable completion in the minibuffer.
+
+`smarty-word-completion-case-sensitive'
+ Type: bool
+ Default value: `nil'
+ Description: If `t'; completion is case sensitive.
+
+3.2 Functions
+=============
+
+3.2.1 Mode
+----------
+
+`smarty-electric-mode'
+ Menu: Smarty -> Options -> Mode -> Electric Mode
+ Keybinding: `C-c C-m C-e'
+ Description: This functions is used to enable/disable the
+ electric mode.
+
+`smarty-stutter-mode'
+ Menu: Smarty -> Options -> Mode -> Stutter Mode
+ Keybinding: `C-c C-m C-s'
+ Description: This function is used to enable/disable the stutter
+ mode.
+
+4 Menus
+*******
+
+There are 2 menus: Smarty and Sources. All theses menus can be
+accessed from the menubar or from the right click. This chapter
+describes each menus.
+
+4.1 Smarty
+==========
+
+This is the main menu of Smarty Mode. It allows an easy access to the
+main features of the Smarty Mode: Templates (see *Note Templates::)
+and Options (see *Note Customization::).
+
+This menu contains also 3 functions that are discussed in the next
+part.
+
+4.1.1 Functions
+---------------
+
+`smarty-show-messages'
+ Menu: Smarty -> Show Messages
+ Keybinding: `C-c M-m'
+ Description: This function opens the *Messages* buffer to
+ display previous error messages.
+
+`smarty-doc-mode'
+ Menu: Smarty -> Smarty Mode Documentation
+ Keybinding: `C-c C-h'
+ Description: This function opens the *Help* buffer and prints in
+ it the Smarty Mode documentation.
+
+`smarty-version'
+ Menu: Smarty -> Version
+ Keybinding: `C-c C-v'
+ Description: This function displays in the minibuffer the
+ current Smarty Mode version with the timestamp.
+
+4.2 Sources
+===========
+
+The Sources menu shows the Smarty files in the current directory. If
+you add or delete a file in the current directory, you need to
+refresh the menu.
+
+4.2.1 Customization
+-------------------
+
+`smarty-source-file-menu'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; the Sources menu is enabled. This menu
+ contains the list of Smarty file located in the current
+ directory. The Sources menu scans the directory when a file is
+ opened.
+
+4.2.2 Functions
+---------------
+
+`smarty-add-source-files-menu'
+ Menu: Sources -> *Rescan*
+ Keybinding: `C-c C-s C-u'
+ Description: This function is used to refresh the Sources menu.
+
+5 Stuttering
+************
+
+The stutter mode is a mode that affects a function to a key. For
+example, when you use the `ENTER' key, the associated function will
+create a new line and indent it.
+
+5.1 Customization
+=================
+
+`smarty-stutter-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable the stuttering. Is indicated in the
+ modeline by \"/s\" after the mode name and can be toggled by
+ `smarty-stutter-mode'.
+
+5.2 Functions
+=============
+
+`SPACE'
+ If in comment, indent the comment and add new line if necessary.
+ In other case, add a space.
+
+`('
+ If the previous character is a `(', the `((' will be replaced by
+ `['.
+ If the previous character is a `[', the `[(' will be replaced by
+ `{'.
+ In other case, insert a `('.
+
+`)'
+ If the previous character is a `)', the `))' will be replaced by
+ `]'.
+ If the previous character is a `]', the `])' will be replaced by
+ `}'.
+ In other case, insert a `)'.
+
+6 Templates
+***********
+
+In the Smarty Mode, the Smarty functions (like if, while, for, fopen,
+fclose) are predefined in functions called \"Templates\".
+
+Each template can be invoked by the function name or by using the
+ key after the Smarty function name in the buffer (Note, using
+`M-' disable the template).
+
+A template can be aborted by using the `C-g' or by lefting empty the
+tempate prompt (in the minibuffer).
+
+6.1 Customization
+=================
+
+`smarty-electric-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable automatic generation of template.
+ If `nil'; template generators can still be invoked through key
+ bindings and menu. Is indicated in the modeline by \"/e\" after
+ the mode name and can be toggled by `smarty-electric-mode'.
+
+For a complete description of the template customizable variables,
+see *Note Cu01-Pa01-Template::
+
+6.2 Functions
+=============
+
+6.2.1 Smarty Functions
+----------------------
+
+For Smarty functions, see PDF or HTML documentation.
+
+6.2.2 Non-Smarty Functions
+--------------------------
+
+`smarty-template-header'
+ Menu: Smarty -> Templates -> Insert Header
+ Keybinding: `C-c C-t C-h'
+ Description: This function is used to insert a header in the
+ current buffer.
+
+`smarty-template-footer'
+ Menu: Smarty -> Templates -> Insert Footer
+ Keybinding: `C-c C-t C-f'
+ Description: This function is used to insert a footer in the
+ current buffer.
+
+`smarty-template-insert-date'
+ Menu: Smarty -> Templates -> Insert Date
+ Keybinding: `C-c C-t C-d i'
+ Description: This function is used to insert the date in the
+ current buffer.
+
+`smarty-template-modify'
+ Menu: Smarty -> Templates -> Modify Date
+ Keybinding: `C-c C-t C-d m'
+ Description: This function is used to modify the last
+ modification date in the current buffer.
+
+7 Bugs, Help
+************
+
+ * To report bugs: Bugtracker
+ (http://bugtracker.morinie.fr/lisp/set_project.php?project_id=2)
+
+ * To obtain help you can post on the dedicated forum: Forum
+ (http://forum.morinie.fr/lisp/)
+
+8 Key bindings
+**************
+
+\\{smarty-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'smarty-mode)
+ (setq mode-name "Smarty")
+
+ (smarty-create-syntax-table)
+
+ ;; set maps and tables
+ (use-local-map smarty-mode-map)
+ (set-syntax-table smarty-mode-syntax-table)
+ (setq local-abbrev-table smarty-mode-abbrev-table)
+
+ (set (make-local-variable 'comment-start) (concat smarty-left-delimiter "*"))
+ (set (make-local-variable 'comment-end) (concat "*" smarty-right-delimiter))
+ (set (make-local-variable 'comment-multi-line) t)
+ (set (make-local-variable 'smarty-end-comment-column) 80)
+
+ (make-local-variable 'font-lock-defaults)
+ (if smarty-highlight-plugin-functions
+ (setq smarty-font-lock-keywords smarty-font-lock-keywords-4)
+ (setq smarty-font-lock-keywords smarty-font-lock-keywords-3))
+ (setq font-lock-defaults
+ '((smarty-font-lock-keywords)
+ nil ; Keywords only (i.e. no comment or string highlighting
+ t ; case fold
+ nil ; syntax-alist
+ nil ; syntax-begin
+ ))
+
+ (setq font-lock-maximum-decoration t
+ case-fold-search t)
+
+ ;; add source file menu
+ (if smarty-source-file-menu (smarty-add-source-files-menu))
+ ;; add Smarty menu
+ (easy-menu-add smarty-mode-menu-list)
+ (easy-menu-define smarty-mode-menu smarty-mode-map
+ "Menu keymap for Smarty Mode." smarty-mode-menu-list)
+
+ ;; (message "Smarty Mode %s.%s" smarty-version
+ ;; (if noninteractive "" " See menu for documentation and release notes."))
+ (smarty-mode-line-update)
+ (run-hooks 'smarty-mode-hook))
+
+(defun smarty-doc-mode ()
+ "Display Smarty Mode documentation in *Help* buffer."
+ (interactive)
+ (with-output-to-temp-buffer
+ (if (fboundp 'help-buffer) (help-buffer) "*Help*")
+ (princ mode-name)
+ (princ " mode:\n")
+ (princ (documentation 'smarty-mode))
+ (with-current-buffer standard-output
+ (help-mode))
+ (print-help-return-message)))
+
+(defun smarty-activate-customizations ()
+ "Activate all customizations on local variables."
+ (interactive)
+ (smarty-mode-map-init)
+ (use-local-map smarty-mode-map)
+ (set-syntax-table smarty-mode-syntax-table)
+ (smarty-update-mode-menu)
+ (run-hooks 'menu-bar-update-hook)
+ (smarty-mode-line-update))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Templates
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-template-field (prompt &optional follow-string optional
+ begin end is-string string-char default)
+ "Prompt for string and insert it in buffer with optional FOLLOW-STRING.
+If OPTIONAL is nil, the prompt is left if an empty string is inserted. If
+an empty string is inserted, return nil and call `smarty-template-undo' for
+the region between BEGIN and END. IS-STRING indicates whether a string
+with double-quotes is to be inserted. DEFAULT specifies a default string."
+ (let ((position (point))
+ string)
+ (insert "<" prompt ">")
+ (if (not (> (length string-char) 0))
+ (setq string-char "\""))
+ (setq string
+ (condition-case ()
+ (read-from-minibuffer (concat prompt ": ")
+ (or (and is-string (cons (concat string-char string-char) 1)) default)
+ smarty-minibuffer-local-map)
+ (quit (if (and optional begin end)
+ (progn (beep) "")
+ (keyboard-quit)))))
+ (when (or (not (equal string "")) optional)
+ (delete-region position (point)))
+ (when (and (equal string "") optional begin end)
+ (smarty-template-undo begin end)
+ (message "Template aborted"))
+ (unless (equal string "")
+ (insert string))
+ (when (or (not (equal string "")) (not optional))
+ (insert (or follow-string "")))
+ (if (equal string "") nil string)))
+
+(defun smarty-template-undo (begin end)
+ "Undo aborted template by deleting region and unexpanding the keyword."
+ (cond (smarty-template-invoked-by-hook
+ (goto-char end)
+ (insert " ")
+ (delete-region begin end)
+ (unexpand-abbrev))
+ (t (delete-region begin end))))
+
+(defun smarty-template-generic-function (label close-label field mandatory-count &optional infinite special-field force-var)
+ "Generic function template 'label field1= field2=..."
+ (interactive)
+ (let ((start (point)) found here result-value elt continue field-count stop prompt)
+ (if smarty-template-invoked-by-hook
+ (setq found (smarty-after-ldelim))
+ (insert smarty-left-delimiter)
+ (setq found t))
+ (insert label)
+ (setq here (point-marker))
+ (insert " ")
+ (when found
+ (setq elt field)
+ (setq continue t)
+ (setq field-count 0)
+ (setq stop nil)
+ (while (and elt continue)
+ (setq prompt (car elt))
+ (when (not special-field)
+ (insert prompt "="))
+ (setq result-value (smarty-template-field prompt nil t))
+ (if (and (not result-value)
+ (< field-count mandatory-count))
+ (progn (setq continue nil)
+ (delete-region start (point))
+ (insert (concat label " "))
+ (setq stop t))
+ (if (not result-value)
+ (setq continue nil)
+ (setq here (point-marker))
+ (insert " ")))
+ (setq field-count (+ 1 field-count))
+ (setq elt (cdr elt)))
+ (when (and infinite (or continue force-var))
+ (when (not continue)
+ (delete-region here (point))
+ (insert " "))
+ (setq continue t)
+ (while continue
+ (setq result-value (smarty-template-field "var_name" "=" t here))
+ (if (not result-value)
+ (setq continue nil)
+ (setq continue (smarty-template-field "var_value" nil t here))
+ (setq here (point-marker))
+ (insert " "))))
+ (when (not stop)
+ (delete-region here (point))
+ (if (> 0 mandatory-count)
+ (delete-char -1))
+ (insert smarty-right-delimiter)
+ (setq here (point-marker))
+ (if close-label
+ (insert smarty-left-delimiter "/" label smarty-right-delimiter))
+ (goto-char here)))))
+
+(defun smarty-template-generic-modifier (label field mandatory-count)
+ "Generic modifier template '|label:field1:field2..."
+ (interactive)
+ (let ((start (point)) found here result-value elt continue field-count stop prompt)
+ (setq found (re-search-backward (concat (regexp-quote smarty-left-delimiter) "\\$\\(\\sw\\|\\s.\\)+" (regexp-quote "|")) nil t))
+ (if found
+ (progn
+ (setq found (re-search-forward (regexp-quote smarty-right-delimiter) start t))
+ (if (not found)
+ (progn
+ (goto-char start)
+ (insert label)
+ (setq here (point-marker))
+ (setq elt field)
+ (setq continue t)
+ (setq field-count 0)
+ (setq stop nil)
+ (while (and elt continue)
+ (setq prompt (car elt))
+ (insert ":")
+ (setq result-value (smarty-template-field prompt nil t))
+ (if (and (not result-value)
+ (< field-count mandatory-count))
+ (progn (setq continue nil)
+ (delete-region start (point))
+ (insert (concat label " "))
+ (setq stop t))
+ (if (not result-value)
+ (setq continue nil)
+ (setq here (point-marker))
+ (insert ":")))
+ (setq field-count (+ 1 field-count))
+ (setq elt (cdr elt)))
+ (when (not stop)
+ (delete-region here (point))
+ (if (not (or (looking-at smarty-right-delimiter)
+ (looking-at "|")))
+ (insert smarty-right-delimiter))))
+ (goto-char start)
+ (insert label " ")))
+ (goto-char start)
+ (insert label " "))))
+
+(defun smarty-template-capture-hook ()
+ (smarty-hooked-abbrev 'smarty-template-capture))
+(defun smarty-template-config-load-hook ()
+ (smarty-hooked-abbrev 'smarty-template-config-load))
+(defun smarty-template-else-hook ()
+ (smarty-hooked-abbrev 'smarty-template-else))
+(defun smarty-template-elseif-hook ()
+ (smarty-hooked-abbrev 'smarty-template-elseif))
+(defun smarty-template-foreach-hook ()
+ (smarty-hooked-abbrev 'smarty-template-foreach))
+(defun smarty-template-foreachelse-hook ()
+ (smarty-hooked-abbrev 'smarty-template-foreachelse))
+(defun smarty-template-if-hook ()
+ (smarty-hooked-abbrev 'smarty-template-if))
+(defun smarty-template-include-hook ()
+ (smarty-hooked-abbrev 'smarty-template-include))
+(defun smarty-template-include-php-hook ()
+ (smarty-hooked-abbrev 'smarty-template-include-php))
+(defun smarty-template-insert-hook ()
+ (smarty-hooked-abbrev 'smarty-template-insert))
+(defun smarty-template-ldelim-hook ()
+ (smarty-hooked-abbrev 'smarty-template-ldelim))
+(defun smarty-template-literal-hook ()
+ (smarty-hooked-abbrev 'smarty-template-literal))
+(defun smarty-template-php-hook ()
+ (smarty-hooked-abbrev 'smarty-template-php))
+(defun smarty-template-rdelim-hook ()
+ (smarty-hooked-abbrev 'smarty-template-rdelim))
+(defun smarty-template-section-hook ()
+ (smarty-hooked-abbrev 'smarty-template-section))
+(defun smarty-template-sectionelse-hook ()
+ (smarty-hooked-abbrev 'smarty-template-sectionelse))
+(defun smarty-template-strip-hook ()
+ (smarty-hooked-abbrev 'smarty-template-strip))
+
+(defun smarty-template-assign-hook ()
+ (smarty-hooked-abbrev 'smarty-template-assign))
+(defun smarty-template-counter-hook ()
+ (smarty-hooked-abbrev 'smarty-template-counter))
+(defun smarty-template-cycle-hook ()
+ (smarty-hooked-abbrev 'smarty-template-cycle))
+(defun smarty-template-debug-hook ()
+ (smarty-hooked-abbrev 'smarty-template-debug))
+(defun smarty-template-eval-hook ()
+ (smarty-hooked-abbrev 'smarty-template-eval))
+(defun smarty-template-fetch-hook ()
+ (smarty-hooked-abbrev 'smarty-template-fetch))
+(defun smarty-template-html-checkboxes-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-checkboxes))
+(defun smarty-template-html-image-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-image))
+(defun smarty-template-html-options-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-options))
+(defun smarty-template-html-radios-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-radios))
+(defun smarty-template-html-select-date-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-select-date))
+(defun smarty-template-html-select-time-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-select-time))
+(defun smarty-template-html-table-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-table))
+(defun smarty-template-mailto-hook ()
+ (smarty-hooked-abbrev 'smarty-template-mailto))
+(defun smarty-template-math-hook ()
+ (smarty-hooked-abbrev 'smarty-template-math))
+(defun smarty-template-popup-hook ()
+ (smarty-hooked-abbrev 'smarty-template-popup))
+(defun smarty-template-popup-init-hook ()
+ (smarty-hooked-abbrev 'smarty-template-popup-init))
+(defun smarty-template-textformat-hook ()
+ (smarty-hooked-abbrev 'smarty-template-textformat))
+
+(defun smarty-template-capitalize-hook ()
+ (smarty-hooked-abbrev 'smarty-template-capitalize))
+(defun smarty-template-cat-hook ()
+ (smarty-hooked-abbrev 'smarty-template-cat))
+(defun smarty-template-count-characters-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-characters))
+(defun smarty-template-count-paragraphs-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-paragraphs))
+(defun smarty-template-count-sentences-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-sentences))
+(defun smarty-template-count-words-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-words))
+(defun smarty-template-date-format-hook ()
+ (smarty-hooked-abbrev 'smarty-template-date-format))
+(defun smarty-template-default-hook ()
+ (smarty-hooked-abbrev 'smarty-template-default))
+(defun smarty-template-escape-hook ()
+ (smarty-hooked-abbrev 'smarty-template-escape))
+(defun smarty-template-indent-hook ()
+ (smarty-hooked-abbrev 'smarty-template-indent))
+(defun smarty-template-lower-hook ()
+ (smarty-hooked-abbrev 'smarty-template-lower))
+(defun smarty-template-nl2br-hook ()
+ (smarty-hooked-abbrev 'smarty-template-nl2br))
+(defun smarty-template-regex-replace-hook ()
+ (smarty-hooked-abbrev 'smarty-template-regex-replace))
+(defun smarty-template-replace-hook ()
+ (smarty-hooked-abbrev 'smarty-template-replace))
+(defun smarty-template-spacify-hook ()
+ (smarty-hooked-abbrev 'smarty-template-spacify))
+(defun smarty-template-string-format-hook ()
+ (smarty-hooked-abbrev 'smarty-template-string-format))
+(defun smarty-template-vstrip-hook ()
+ (smarty-hooked-abbrev 'smarty-template-vstrip))
+(defun smarty-template-strip-tags-hook ()
+ (smarty-hooked-abbrev 'smarty-template-strip-tags))
+(defun smarty-template-truncate-hook ()
+ (smarty-hooked-abbrev 'smarty-template-truncate))
+(defun smarty-template-upper-hook ()
+ (smarty-hooked-abbrev 'smarty-template-upper))
+(defun smarty-template-wordwrap-hook ()
+ (smarty-hooked-abbrev 'smarty-template-wordwrap))
+
+(defun smarty-template-validate-hook ()
+ (smarty-hooked-abbrev 'smarty-template-validate))
+(defun smarty-template-clipcache-hook ()
+ (smarty-hooked-abbrev 'smarty-template-clipcache))
+(defun smarty-template-include-clipcache-hook ()
+ (smarty-hooked-abbrev 'smarty-template-include-clipcache))
+(defun smarty-template-formtool-checkall-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-checkall))
+(defun smarty-template-formtool-copy-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-copy))
+(defun smarty-template-formtool-count-chars-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-count-chars))
+(defun smarty-template-formtool-init-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-init))
+(defun smarty-template-formtool-move-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-move))
+(defun smarty-template-formtool-moveall-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-moveall))
+(defun smarty-template-formtool-movedown-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-movedown))
+(defun smarty-template-formtool-moveup-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-moveup))
+(defun smarty-template-formtool-remove-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-remove))
+(defun smarty-template-formtool-rename-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-rename))
+(defun smarty-template-formtool-save-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-save))
+(defun smarty-template-formtool-selectall-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-selectall))
+(defun smarty-template-paginate-first-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-first))
+(defun smarty-template-paginate-last-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-last))
+(defun smarty-template-paginate-middle-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-middle))
+(defun smarty-template-paginate-next-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-next))
+(defun smarty-template-paginate-prev-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-prev))
+
+(defun smarty-template-btosmilies-hook ()
+ (smarty-hooked-abbrev 'smarty-template-btosmilies))
+(defun smarty-template-bbcodetohtml-hook ()
+ (smarty-hooked-abbrev 'smarty-template-bbcodetohtml))
+(defun smarty-template-date-formatto-hook ()
+ (smarty-hooked-abbrev 'smarty-template-date-formatto))
+
+(defun smarty-template-capture ()
+ "Insert a capture statement."
+ (interactive)
+ (smarty-template-generic-function "capture" t '("name" "assign") 0))
+
+(defun smarty-template-config-load ()
+ "Insert a config_load statement."
+ (interactive)
+ (smarty-template-generic-function "config_load" nil '("file" "section" "scope" "global") 1))
+
+(defun smarty-template-else ()
+ "Insert a else statement."
+ (interactive)
+ (smarty-template-generic-function "else" nil '() 0))
+
+(defun smarty-template-elseif ()
+ "Insert a elseif statement."
+ (interactive)
+ (smarty-template-generic-function "elseif" nil '("condition") 1 nil t))
+
+(defun smarty-template-foreach ()
+ "Insert a foreach statement."
+ (interactive)
+ (smarty-template-generic-function "foreach" t '("from" "item" "key" "name") 2))
+
+(defun smarty-template-foreachelse ()
+ "Insert a foreachelse statement."
+ (interactive)
+ (smarty-template-generic-function "foreachelse" nil '() 0))
+
+(defun smarty-template-if ()
+ "Insert a if statement."
+ (interactive)
+ (smarty-template-generic-function "if" t '("condition") 1 nil t))
+
+(defun smarty-template-include ()
+ "Insert a include statement."
+ (interactive)
+ (smarty-template-generic-function "include" nil '("file" "assign") 1 t))
+
+(defun smarty-template-include-php ()
+ "Insert a include_php statement."
+ (interactive)
+ (smarty-template-generic-function "include_php" nil '("file" "once" "assign") 1))
+
+(defun smarty-template-insert ()
+ "Insert a insert statement."
+ (interactive)
+ (smarty-template-generic-function "insert" nil '("name" "assign" "script") 1 t))
+
+(defun smarty-template-ldelim ()
+ "Insert a ldelim statement."
+ (interactive)
+ (smarty-template-generic-function "ldelim" nil '() 0))
+
+(defun smarty-template-literal ()
+ "Insert a literal statement."
+ (interactive)
+ (smarty-template-generic-function "literal" t '() 0))
+
+(defun smarty-template-php ()
+ "Insert a php statement."
+ (interactive)
+ (smarty-template-generic-function "php" t '() 0))
+
+(defun smarty-template-rdelim ()
+ "Insert a rdelim statement."
+ (interactive)
+ (smarty-template-generic-function "rdelim" nil '() 0))
+
+(defun smarty-template-section ()
+ "Insert a section statement."
+ (interactive)
+ (smarty-template-generic-function "section" t '("name" "loop" "start" "step" "max" "show") 2))
+
+(defun smarty-template-sectionelse ()
+ "Insert a sectionelse statement."
+ (interactive)
+ (smarty-template-generic-function "sectionelse" nil '() 0))
+
+(defun smarty-template-strip ()
+ "Insert a strip statement."
+ (interactive)
+ (smarty-template-generic-function "strip" t '() 0))
+
+
+(defun smarty-template-assign ()
+ "Insert a assign statement."
+ (interactive)
+ (smarty-template-generic-function "assign" nil '("var" "value") 2))
+
+(defun smarty-template-counter ()
+ "Insert a counter statement."
+ (interactive)
+ (smarty-template-generic-function "counter" nil '("name" "start" "skip" "direction" "print" "assign") 0))
+
+(defun smarty-template-cycle ()
+ "Insert a cycle statement."
+ (interactive)
+ (smarty-template-generic-function "cycle" nil '("values" "name" "print" "advance" "delimiter" "assign" "reset") 1))
+
+(defun smarty-template-debug ()
+ "Insert a debug statement."
+ (interactive)
+ (smarty-template-generic-function "debug" nil '("output") 0))
+
+(defun smarty-template-eval ()
+ "Insert a eval statement."
+ (interactive)
+ (smarty-template-generic-function "eval" nil '("var" "assign") 1))
+
+(defun smarty-template-fetch ()
+ "Insert a fetch statement."
+ (interactive)
+ (smarty-template-generic-function "fetch" nil '("file" "assign") 1))
+
+(defun smarty-template-html-checkboxes ()
+ "Insert a html_checkboxes statement."
+ (interactive)
+ (smarty-template-generic-function "html_checkboxes" nil '("name" "values" "output" "selected" "options" "separator" "assign" "labels") 0))
+
+(defun smarty-template-html-image ()
+ "Insert a html_image statement."
+ (interactive)
+ (smarty-template-generic-function "html_image" nil '("file" "height" "width" "basedir" "alt" "href" "path_prefix") 1))
+
+(defun smarty-template-html-options ()
+ "Insert a html_options statement."
+ (interactive)
+ (smarty-template-generic-function "html_options" nil '("name" "values" "output" "selected" "options") 0))
+
+(defun smarty-template-html-radios ()
+ "Insert a html_radios statement."
+ (interactive)
+ (smarty-template-generic-function "html_radios" nil '("name" "values" "output" "selected" "options" "separator" "assign") 0))
+
+(defun smarty-template-html-select-date ()
+ "Insert a html_select_date statement."
+ (interactive)
+ (smarty-template-generic-function "html_select_date" nil '("prefix" "time" "start_year" "end_year" "display_days" "display_months" "display_years" "month_format" "day_format" "day_value_format" "year_as_text" "reverse_years" "field_array" "day_size" "month_size" "year_size" "all_extra" "day_extra" "month_extra" "year_extra" "field_order" "field_separator" "month_value_format" "year_empty" "month_empty" "day_empty") 0))
+
+(defun smarty-template-html-select-time ()
+ "Insert a html_select_time statement."
+ (interactive)
+ (smarty-template-generic-function "html_select_time" nil '("prefix" "time" "display_hours" "display_minutes" "display_seconds" "display_meridian" "use_24_hours" "minute_interval" "second_interval" "field_array" "all_extra" "hour_extra" "minute_extra" "second_extra" "meridian_extra") 0))
+
+(defun smarty-template-html-table ()
+ "Insert a html_table statement."
+ (interactive)
+ (smarty-template-generic-function "html_table" nil '("loop" "cols" "rows" "inner" "caption" "table_attr" "th_attr" "tr_attr" "td_attr" "trailpad" "hdir" "vdir") 1))
+
+(defun smarty-template-mailto ()
+ "Insert a mailto statement."
+ (interactive)
+ (smarty-template-generic-function "mailto" nil '("address" "text" "encode" "cc" "bcc" "subject" "newsgroups" "followupto" "extra") 1))
+
+(defun smarty-template-math ()
+ "Insert a math statement."
+ (interactive)
+ (smarty-template-generic-function "math" nil '("equation" "format" "assign") 1 t nil t))
+
+(defun smarty-template-popup ()
+ "Insert a popup statement."
+ (interactive)
+ (smarty-template-generic-function "popup" nil '("text" "trigger" "sticky" "caption" "fgcolor" "bgcolor" "textcolor" "capcolor" "closecolor" "textfont" "captionfont" "closefont" "textsize" "captionsize" "closesize" "width" "height" "left" "right" "center" "above" "below" "border" "offsetx" "offsety" "fgbackground" "bgbackground" "closetext" "noclose" "status" "autostatus" "autostatuscap" "inarray" "caparray" "capicon" "snapx" "snapy" "fixx" "fixy" "background" "padx" "pady" "fullhtml" "frame" "function" "delay" "hauto" "vauto") 1))
+
+(defun smarty-template-popup-init ()
+ "Insert a popup_init statement."
+ (interactive)
+ (smarty-template-generic-function "popup_init" nil '("src") 1))
+
+(defun smarty-template-textformat ()
+ "Insert a textformat statement."
+ (interactive)
+ (smarty-template-generic-function "textformat" t '("style" "indent" "indent_first" "indent_char" "wrap" "wrap_char" "wrap_cut" "assign") 0))
+
+(defun smarty-template-capitalize ()
+ "Insert a capitalize statement."
+ (interactive)
+ (smarty-template-generic-modifier "capitalize" '("upcase_numeric") 0))
+
+(defun smarty-template-cat ()
+ "Insert a cat statement."
+ (interactive)
+ (smarty-template-generic-modifier "cat" '("value") 0))
+
+(defun smarty-template-count-characters ()
+ "Insert a count_characters statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_characters" '("include_whitespace") 0))
+
+(defun smarty-template-count-paragraphs ()
+ "Insert a count_paragraphs statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_paragraphs" '() 0))
+
+(defun smarty-template-count-sentences ()
+ "Insert a count_sentences statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_sentences" '() 0))
+
+(defun smarty-template-count-words ()
+ "Insert a count_words statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_words" '() 0))
+
+(defun smarty-template-date-format ()
+ "Insert a date_format statement."
+ (interactive)
+ (smarty-template-generic-modifier "date_format" '("format" "default") 0))
+
+(defun smarty-template-default ()
+ "Insert a default statement."
+ (interactive)
+ (smarty-template-generic-modifier "default" '("value") 0))
+
+(defun smarty-template-escape ()
+ "Insert a escape statement."
+ (interactive)
+ (smarty-template-generic-modifier "escape" '("html|htmlall|url|urlpathinfo|quotes|hex|hexentity|javascript|mail" "charset") 0))
+
+(defun smarty-template-indent ()
+ "Insert a indent statement."
+ (interactive)
+ (smarty-template-generic-modifier "indent" '("value" "character") 0))
+
+(defun smarty-template-lower ()
+ "Insert a lower statement."
+ (interactive)
+ (smarty-template-generic-modifier "lower" '() 0))
+
+(defun smarty-template-nl2br ()
+ "Insert a nl2br statement."
+ (interactive)
+ (smarty-template-generic-modifier "nl2br" '() 0))
+
+(defun smarty-template-regex-replace ()
+ "Insert a regex_replace statement."
+ (interactive)
+ (smarty-template-generic-modifier "regex_replace" '("regexp" "string_to_replace") 2))
+
+(defun smarty-template-replace ()
+ "Insert a replace statement."
+ (interactive)
+ (smarty-template-generic-modifier "replace" '("string" "string_to_replace_with") 2))
+
+(defun smarty-template-spacify ()
+ "Insert a spacify statement."
+ (interactive)
+ (smarty-template-generic-modifier "spacify" '("character") 0))
+
+(defun smarty-template-string-format ()
+ "Insert a string_format statement."
+ (interactive)
+ (smarty-template-generic-modifier "string_format" '("format") 1))
+
+(defun smarty-template-vstrip ()
+ "Insert a strip statement."
+ (interactive)
+ (smarty-template-generic-modifier "strip" '() 0))
+
+(defun smarty-template-strip-tags ()
+ "Insert a strip_tags statement."
+ (interactive)
+ (smarty-template-generic-modifier "strip_tags" '("replace_by_space") 0))
+
+(defun smarty-template-truncate ()
+ "Insert a truncate statement."
+ (interactive)
+ (smarty-template-generic-modifier "truncate" '("count" "text_to_replace" "character_boundary" "middle_string") 0))
+
+(defun smarty-template-upper ()
+ "Insert a upper statement."
+ (interactive)
+ (smarty-template-generic-modifier "upper" '() 0))
+
+(defun smarty-template-wordwrap ()
+ "Insert a wordwrap statement."
+ (interactive)
+ (smarty-template-generic-modifier "wordwrap" '("count" "string" "character_boundary") 0))
+
+
+(defun smarty-template-validate ()
+ "Insert a validate statement."
+ (interactive)
+ (smarty-template-generic-function "validate" nil '("field" "criteria" "message" "form" "transform" "trim" "empty" "halt" "assign" "append" "page") 3))
+
+(defun smarty-template-repeat ()
+ "Insert a repeat statement."
+ (interactive)
+ (smarty-template-generic-function "repeat" nil '("count" "assign") 1))
+
+(defun smarty-template-str_repeat ()
+ "Insert a str_repeat statement."
+ (interactive)
+ (smarty-template-generic-function "str_repeat" nil '("string" "count" "assign") 2))
+
+(defun smarty-template-clipcache ()
+ "Insert a clipcache statement."
+ (interactive)
+ (smarty-template-generic-function "clipcache" nil '("id" "group" "ttl" "ldelim" "rdelim") 3))
+
+(defun smarty-template-include-clipcache ()
+ "Insert a include_clipcache statement."
+ (interactive)
+ (smarty-template-generic-function "include_clipcache" nil '("file" "cache_id" "cache_lifetime" "ldelim" "rdelim") 3))
+
+(defun smarty-template-formtool-checkall ()
+ "Insert a formtool_checkall statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_checkall" nil '("name" "class" "style") 1))
+
+(defun smarty-template-formtool-copy ()
+ "Insert a formtool_copy statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_copy" nil '("from" "to" "save" "button_text" "all" "counter" "class" "style") 3))
+
+(defun smarty-template-formtool-count-chars ()
+ "Insert a formtool_count_chars statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_count_chars" nil '("name" "limit" "alert") 3))
+
+(defun smarty-template-formtool-init ()
+ "Insert a formtool_init statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_init" nil '("src") 1))
+
+(defun smarty-template-formtool-move ()
+ "Insert a formtool_move statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_move" nil '("from" "to" "save_from" "save_to" "all" "count_to" "count_from" "class" "style") 4))
+
+(defun smarty-template-formtool-moveall ()
+ "Insert a formtool_moveall statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_moveall" nil '("from" "to" "save_from" "save_to" "all" "count_to" "count_from" "class" "style") 4))
+
+(defun smarty-template-formtool-movedown ()
+ "Insert a formtool_movedown statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_movedown" nil '("save" "name" "class" "style") 2))
+
+(defun smarty-template-formtool-moveup ()
+ "Insert a formtool_moveup statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_moveup" nil '("save" "name" "class" "style") 2))
+
+(defun smarty-template-formtool-remove ()
+ "Insert a formtool_remove statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_remove" nil '("from" "save" "all" "counter" "class" "style") 2))
+
+(defun smarty-template-formtool-rename ()
+ "Insert a formtool_rename statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_rename" nil '("name" "from" "save" "class" "style") 3))
+
+(defun smarty-template-formtool-save ()
+ "Insert a formtool_save statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_save" nil '("from" "name" "save") 3))
+
+(defun smarty-template-formtool-selectall ()
+ "Insert a formtool_selectall statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_selectall" nil '("name" "class" "style") 1))
+
+(defun smarty-template-paginate-first ()
+ "Insert a paginate_first statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_first" nil '("id" "text") 0))
+
+(defun smarty-template-paginate-last ()
+ "Insert a paginate_last statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_last" nil '("id" "text") 0))
+
+(defun smarty-template-paginate-middle ()
+ "Insert a paginate_middle statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_middle" nil '("id" "format" "prefix" "page_limit" "link_prefix" "link_suffix") 0))
+
+(defun smarty-template-paginate-next ()
+ "Insert a paginate_next statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_next" nil '("id" "text") 0))
+
+(defun smarty-template-paginate-prev ()
+ "Insert a paginate_prev statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_prev" nil '("id" "text") 0))
+
+
+(defun smarty-template-btosmilies ()
+ "Insert a B2Smilies statement."
+ (interactive)
+ (smarty-template-generic-modifier "B2Smilies" '() 0))
+
+(defun smarty-template-bbcodetohtml ()
+ "Insert a bbcode2html statement."
+ (interactive)
+ (smarty-template-generic-modifier "bbcode2html" '() 0))
+
+(defun smarty-template-date-formatto ()
+ "Insert a date_format2 statement."
+ (interactive)
+ (smarty-template-generic-modifier "date_format2" '("format" "default") 0))
+
+;;
+
+(defun smarty-resolve-env-variable (string)
+ "Resolve environment variables in STRING."
+ (while (string-match "\\(.*\\)${?\\(\\(\\w\\|_\\)+\\)}?\\(.*\\)" string)
+ (setq string (concat (match-string 1 string)
+ (getenv (match-string 2 string))
+ (match-string 4 string))))
+ string)
+
+(defun smarty-insert-string-or-file (string)
+ "Insert STRING or file contents if STRING is an existing file name."
+ (unless (equal string "")
+ (let ((file-name
+ (progn (string-match "^\\([^\n]+\\)" string)
+ (smarty-resolve-env-variable (match-string 1 string)))))
+ (if (file-exists-p file-name)
+ (forward-char (cadr (insert-file-contents file-name)))
+ (insert string)))))
+
+(defun smarty-template-insert-date ()
+ "Insert date in appropriate format."
+ (interactive)
+ (insert
+ (cond
+ ;; 'american, 'european, 'scientific kept for backward compatibility
+ ((eq smarty-date-format 'american) (format-time-string "%m/%d/%Y" nil))
+ ((eq smarty-date-format 'european) (format-time-string "%d.%m.%Y" nil))
+ ((eq smarty-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
+ (t (format-time-string smarty-date-format nil)))))
+
+(defun smarty-template-header (&optional file-title)
+ "Insert a Smarty file header."
+ (interactive)
+ (unless (equal smarty-file-header "")
+ (let (pos)
+ (save-excursion
+ (smarty-insert-string-or-file smarty-file-header)
+ (setq pos (point-marker)))
+ (smarty-template-replace-header-keywords
+ (point-min-marker) pos file-title))))
+
+(defun smarty-template-footer ()
+ "Insert a Smarty file footer."
+ (interactive)
+ (unless (equal smarty-file-footer "")
+ (let (pos)
+ (save-excursion
+ (setq pos (point-marker))
+ (smarty-insert-string-or-file smarty-file-footer)
+ (unless (= (preceding-char) ?\n)
+ (insert "\n")))
+ (smarty-template-replace-header-keywords pos (point-max-marker)))))
+
+(defun smarty-template-replace-header-keywords (beg end &optional file-title is-model)
+ "Replace keywords in header and footer."
+ (let ()
+ (smarty-prepare-search-2
+ (save-excursion
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match (buffer-name) t t))
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match smarty-copyright-string t t))
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match "" t t)
+ (insert (user-full-name))
+ (when user-mail-address (insert " <" user-mail-address ">")))
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match (user-login-name) t t))
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match smarty-company-name t t))
+ (goto-char beg)
+ ;; Replace with $, so that RCS for the source is
+ ;; not over-enthusiastic with replacements
+ (while (search-forward "" end t)
+ (replace-match "$" nil t))
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match "" t t)
+ (smarty-template-insert-date))
+ (goto-char beg)
+ (while (search-forward "" end t)
+ (replace-match (format-time-string "%Y" nil) t t))
+ (goto-char beg)
+ (let (string)
+ (while
+ (re-search-forward "<\\(\\(\\w\\|\\s_\\)*\\) string>" end t)
+ (setq string (read-string (concat (match-string 1) ": ")))
+ (replace-match string t t)))
+ (goto-char beg)
+ (when (and (not is-model) (search-forward "" end t))
+ (replace-match "" t t))))))
+
+(provide 'smarty-mode)
+;;; smarty-mode.el ends here
diff --git a/emacs.d/nxhtml/related/tt-mode.el b/emacs.d/nxhtml/related/tt-mode.el
new file mode 100644
index 0000000..cf01a47
--- /dev/null
+++ b/emacs.d/nxhtml/related/tt-mode.el
@@ -0,0 +1,124 @@
+;; tt-mode.el --- Emacs major mode for editing Template Toolkit files
+;;
+;; Copyright (c) 2002 Dave Cross, all rights reserved.
+;;
+;; This file may be distributed under the same terms as GNU Emacs.
+;;
+;; $Id: tt-mode.el 13 2008-01-27 09:35:16Z dave $
+;;
+;; This file adds simple font highlighting of TT directives when you are
+;; editing Template Toolkit files.
+;;
+;; I usually give these files an extension of .tt and in order to automatically
+;; invoke this mode for these files, I have the following in my .emacs file.
+;;
+;; (setq load-path
+;; (cons "/home/dave/xemacs" load-path))
+;; (autoload 'tt-mode "tt-mode")
+;; (setq auto-mode-alist
+;; (append '(("\\.tt$" . tt-mode)) auto-mode-alist ))
+;;
+;; Something similar may well work for you.
+;;
+;; Author: Dave Cross
+;;
+;; Modified by Lennart Borgman 2008-08-06
+
+(require 'font-lock)
+
+(defvar tt-mode-hook nil
+ "List of functions to call when entering TT mode")
+
+(defvar tt-keywords
+ (concat "\\b\\(?:"
+ (regexp-opt (list "GET" "CALL" "SET" "DEFAULT" "INSERT" "INCLUDE"
+ "BLOCK" "END" "PROCESS" "WRAPPER" "IF" "UNLESS"
+ "ELSIF" "ELSE" "SWITCH" "CASE" "FOR" "FOREACH"
+ "WHILE" "FILTER" "USE" "MACRO" "PERL" "RAWPERL"
+ "TRY" "THROW" "CATCH" "FINAL" "LAST" "RETURN"
+ "STOP" "CLEAR" "META" "TAGS"))
+ "\\)\\b"))
+
+(defvar tt-font-lock-keywords
+ (list
+ ;; Fontify [& ... &] expressions
+ '("\\(\\[%[-+]?\\)\\(\\(.\\|\n\\)+?\\)\\([-+]?%\\]\\)"
+ (1 font-lock-string-face t)
+ (2 font-lock-variable-name-face t)
+ (4 font-lock-string-face t))
+ ;; Look for keywords within those expressions
+ ;;
+ ;; Comment out whole directive tag
+ '("\\[%\\(#.*?\\)%\\]"
+ (1 font-lock-comment-face t))
+ ;; Comments to end of line
+;;; '("\\[%\\(?:.\\|\n\\)*\\(#.*\\)"
+;;; (1 font-lock-comment-face t))
+ '("\\[% *\\([a-z_0-9]*\\) *%\\]"
+ (1 font-lock-constant-face t))
+ (list (concat
+ "\\(\\[%[-+]?\\|;\\)[ \n\t]*\\("
+ tt-keywords
+ "\\)")
+ 2 font-lock-keyword-face t)
+ )
+ "Expressions to font-lock in tt-mode.")
+
+;; (defvar tt-font-lock-keywords
+;; ;; Since this is used in a multi major mode we
+;; (list
+;; ;; Fontify [& ... &] expressions
+;; ;;; '("^\\([-+]?\\)\\(\\(.\\|\n\\)+?\\)\\([-+]?\\)$"
+;; ;;; (1 font-lock-string-face t)
+;; ;;; (2 font-lock-variable-name-face t)
+;; ;;; (4 font-lock-string-face t))
+;; '("\\(#.*\\)$"
+;; (1 font-lock-comment-face t))
+;; '("^ *\\([a-z_0-9]*\\) *$"
+;; (1 font-lock-constant-face t))
+;; (list (concat
+;; "^\\(?:[-+]?\\|;\\)[ \n\t]*\\("
+;; tt-keywords
+;; "\\)")
+;; )
+;; 1 font-lock-keyword-face t)
+;; )
+;; "Expressions to font-lock in tt-mode.")
+
+(defvar tt-font-lock-defaults
+ '(tt-font-lock-keywords nil t))
+
+(defun tt-mode-after-change (beg end pre-len)
+ ;; add/remove font-lock-multiline
+ ;; Fix-me: add variable for search lengths
+ (let* ((here (point))
+ (beg-is-ml (get-text-property beg 'font-lock-multiline))
+ tt-beg
+ tt-end
+ )
+ (when beg-is-ml
+ (let ((beg-ok (not (previous-single-property-change
+ here 'font-lock-multiline
+ nil (- here 1))))
+ )
+ (when beg-ok
+ (goto-char beg)
+ (search-forward "%]" end t)
+ )
+ (search-forward "[%" end t)
+ ))
+ (when tt-end
+ (remove-list-of-text-properties here tt-beg '(font-lock-multiline))
+ (set-text-properties tt-beg tt-end '(font-lock-multiline t))))
+ )
+
+
+;;;###autoload
+(define-derived-mode tt-mode fundamental-mode "TT"
+ "Major mode for editing Template Toolkit files."
+ (set (make-local-variable 'font-lock-defaults) tt-font-lock-defaults)
+ (add-hook 'after-change-functions 'tt-mode-after-change nil t)
+ )
+
+(provide 'tt-mode)
+;; tt-mode.el ends here
diff --git a/emacs.d/nxhtml/related/visual-basic-mode.el b/emacs.d/nxhtml/related/visual-basic-mode.el
new file mode 100644
index 0000000..ca448a6
--- /dev/null
+++ b/emacs.d/nxhtml/related/visual-basic-mode.el
@@ -0,0 +1,1263 @@
+;;; visual-basic-mode.el
+;; This is free software.
+
+;; A mode for editing Visual Basic programs.
+;; Modified version of Fred White's visual-basic-mode.el
+
+;; Copyright (C) 1996 Fred White
+;; Copyright (C) 1998 Free Software Foundation, Inc.
+;; (additions by Dave Love)
+;; Copyright (C) 2008-2009 Free Software Foundation, Inc.
+;; (additions by Randolph Fritz and Vincent Belaiche (VB1) )
+
+;; Author: Fred White
+;; Adapted-by: Dave Love
+;; : Kevin Whitefoot
+;; : Randolph Fritz
+;; : Vincent Belaiche (VB1)
+;; Version: 1.4.8 (2009-09-29)
+;; Serial Version: %Id: 17%
+;; Keywords: languages, basic, Evil
+
+
+;; (Old) LCD Archive Entry:
+;; basic-mode|Fred White|fwhite@alum.mit.edu|
+;; A mode for editing Visual Basic programs.|
+;; 18-Apr-96|1.0|~/modes/basic-mode.el.Z|
+
+;; This file is NOT part of GNU Emacs but the same permissions apply.
+;;
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+
+;;; Commentary:
+
+;; Purpose of this package:
+;; This is a mode for editing programs written in The World's Most
+;; Successful Programming Language. It features automatic
+;; indentation, font locking, keyword capitalization, and some minor
+;; convenience functions.
+
+;; Installation instructions
+;; Put visual-basic-mode.el somewhere in your path, compile it, and add
+;; the following to your init file:
+
+;; (autoload 'visual-basic-mode "visual-basic-mode" "Visual Basic mode." t)
+;; (setq auto-mode-alist (append '(("\\.\\(frm\\|bas\\|cls\\)$" .
+;; visual-basic-mode)) auto-mode-alist))
+;;
+;; If you are doing Rhino scripts, add:
+;; (setq auto-mode-alist (append '(("\\.\\(frm\\|bas\\|cls\\|rvb\\)$" .
+;; visual-basic-mode)) auto-mode-alist))
+
+;; If you had visual-basic-mode already installed, you may need to call
+;; visual-basic-upgrade-keyword-abbrev-table the first time that
+;; visual-basic-mode is loaded.
+
+;; Of course, under Windows 3.1, you'll have to name this file
+;; something shorter than visual-basic-mode.el
+
+;; Revisions:
+;; 1.0 18-Apr-96 Initial version
+;; 1.1 Accomodate emacs 19.29+ font-lock-defaults
+;; Simon Marshall
+; 1.2 Rename to visual-basic-mode
+;; 1.3 Fix some indentation bugs.
+;; 1.3+ Changes by Dave Love: [No attempt at compatibility with
+;; anything other than Emacs 20, sorry, but little attempt to
+;; sanitize for Emacs 20 specifically.]
+;; Change `_' syntax only for font-lock and imenu, not generally;
+;; provide levels of font-locking in the current fashion;
+;; font-lock case-insensitively; use regexp-opt with the font-lok
+;; keywords; imenu support; `visual-basic-split-line', bound to
+;; C-M-j; account for single-statement `if' in indentation; add
+;; keyword "Global"; use local-write-file-hooks, not
+;; write-file-hooks.
+;; 1.4 September 1998
+;; 1.4 KJW Add begin..end, add extra keywords
+;; Add customisation for single line if. Disallow by default.
+;; Fix if regexp to require whitespace after if and require then.
+;; Add more VB keywords. Make begin..end work as if..endif so
+;; that forms are formatted correctly.
+;; 1.4.1 KJW Merged Dave Love and KJW versions.
+;; Added keywords suggested by Mickey Ferguson
+;;
+;; Fixed imenu variable to find private variables and enums
+
+;; Changed syntax class of =, <, > to punctuation to allow dynamic
+;; abbreviations to pick up only the word at point rather than the
+;; whole expression.
+
+;; Fixed bug introduced by KJW adding suport for begin...end in
+;; forms whereby a single end outdented.
+
+;; Partially fixed failure to recognise if statements with
+;; continuations (still fails on 'single line' if with
+;; continuation, ugh).
+;; 1.4.2 RF added "class" and "null" keywords, "Rhino" script note.
+;; 1.4.3 VB1 added
+;; 1) function visual-basic-if-not-on-single-line to recognize single line
+;; if statements, even when line is broken. variable
+;; visual-basic-allow-single-line-if default set to t again.
+;; 2) use of 'words in calling regexp-opt rather than concat \\< ...\\>
+;; 3) new keywords Preserve and Explicit
+;; 1.4.4 VB1 added function visual-basic-close-block
+;; 1.4.5 VB1, (expand-abbrev) within (save-excusion...)
+;; 1.4.6 VB1 correct visual-basic-close-block (single line If case)
+;; 1.4.7 VB1 correct visual-basic-close-block (For/Next)
+;; 1.4.8 VB1 correct visual-basic-close-block (Property, + add With /End With)
+;; add command visual-basic-insert-item
+
+;; Lennart Borgman:
+;; 2009-11-20
+;; - Added eval-and-compile to visual-basic-label-regexp.
+;;
+;; Notes:
+;; Dave Love
+;; BTW, here's a script for making tags tables that I (Dave Love) have
+;; used with reasonable success. It assumes a hacked version of etags
+;; with support for case-folded regexps. I think this is now in the
+;; development version at and should
+;; make it into Emacs after 20.4.
+
+;; #! /bin/sh
+
+;; # etags-vb: (so-called) Visual (so-called) Basic TAGS generation.
+;; # Dave Love . Public domain.
+;; # 1997-11-21
+
+;; if [ $# -lt 1 ]; then
+;; echo "Usage: `basename $0` [etags options] VBfile ... [etags options] " 1>&2
+;; exit 1
+;; fi
+
+;; if [ $1 = "--help" ] || [ $1 = "-h" ]; then
+;; echo "Usage: `basename $0` [etags options] VBfile ... [etags options]
+
+;; "
+;; etags --help
+;; fi
+
+;; exec etags --lang=none -c '/\(global\|public\)[ \t]+\(\(const\|type\)[ \t]+\)*\([a-z_0-9]+\)/\4/' \
+;; -c '/public[ \t]+\(sub\|function\|class\)[ \t]+\([a-z_0-9]+\)/\2/' \
+;; "$@"
+
+;; End Notes Dave Love
+
+
+;; Known bugs:
+;; Doesn't know about ":" separated stmts
+
+
+
+;; todo:
+;; fwd/back-compound-statement
+;; completion over OCX methods and properties.
+;; IDE integration
+;; Change behaviour of ESC-q to recognise words used as paragraph
+;; titles and prevent them being dragged into the previous
+;; paragraph.
+;; etc.
+
+
+;;; Code:
+
+(provide 'visual-basic-mode)
+
+(defvar visual-basic-xemacs-p (string-match "XEmacs\\|Lucid" (emacs-version)))
+(defvar visual-basic-winemacs-p (string-match "Win-Emacs" (emacs-version)))
+(defvar visual-basic-win32-p (eq window-system 'w32))
+
+;; Variables you may want to customize.
+(defvar visual-basic-mode-indent 8 "*Default indentation per nesting level.")
+(defvar visual-basic-fontify-p t "*Whether to fontify Basic buffers.")
+(defvar visual-basic-capitalize-keywords-p t
+ "*Whether to capitalize BASIC keywords.")
+(defvar visual-basic-wild-files "*.frm *.bas *.cls"
+ "*Wildcard pattern for BASIC source files.")
+(defvar visual-basic-ide-pathname nil
+ "*The full pathname of your Visual Basic exe file, if any.")
+;; VB
+(defvar visual-basic-allow-single-line-if t
+ "*Whether to allow single line if")
+
+
+(defvar visual-basic-defn-templates
+ (list "Public Sub ()\nEnd Sub\n\n"
+ "Public Function () As Variant\nEnd Function\n\n"
+ "Public Property Get ()\nEnd Property\n\n")
+ "*List of function templates though which visual-basic-new-sub cycles.")
+
+(defvar visual-basic-imenu-generic-expression
+ '((nil "^\\s-*\\(public\\|private\\)*\\s-+\\(declare\\s-+\\)*\\(sub\\|function\\)\\s-+\\(\\sw+\\>\\)"
+ 4)
+ ("Constants"
+ "^\\s-*\\(private\\|public\\|global\\)*\\s-*\\(const\\s-+\\)\\(\\sw+\\>\\s-*=\\s-*.+\\)$\\|'"
+ 3)
+ ("Variables"
+ "^\\(private\\|public\\|global\\|dim\\)+\\s-+\\(\\sw+\\>\\s-+as\\s-+\\sw+\\>\\)"
+ 2)
+ ("Types" "^\\(public\\s-+\\)*type\\s-+\\(\\sw+\\)" 2)))
+
+
+
+(defvar visual-basic-mode-syntax-table nil)
+(if visual-basic-mode-syntax-table
+ ()
+ (setq visual-basic-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\' "\<" visual-basic-mode-syntax-table) ; Comment starter
+ (modify-syntax-entry ?\n ">" visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\\ "w" visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\= "." visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\< "." visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\> "." visual-basic-mode-syntax-table)) ; Make =, etc., punctuation so that dynamic abbreviations work properly
+
+
+(defvar visual-basic-mode-map nil)
+(if visual-basic-mode-map
+ ()
+ (setq visual-basic-mode-map (make-sparse-keymap))
+ (define-key visual-basic-mode-map "\t" 'visual-basic-indent-line)
+ (define-key visual-basic-mode-map "\r" 'visual-basic-newline-and-indent)
+ (define-key visual-basic-mode-map "\M-\r" 'visual-basic-insert-item)
+ (define-key visual-basic-mode-map "\C-c\C-j" 'visual-basic-insert-item)
+ (define-key visual-basic-mode-map "\M-\C-a" 'visual-basic-beginning-of-defun)
+ (define-key visual-basic-mode-map "\M-\C-e" 'visual-basic-end-of-defun)
+ (define-key visual-basic-mode-map "\M-\C-h" 'visual-basic-mark-defun)
+ (define-key visual-basic-mode-map "\M-\C-\\" 'visual-basic-indent-region)
+ (define-key visual-basic-mode-map "\M-q" 'visual-basic-fill-or-indent)
+ (define-key visual-basic-mode-map "\M-\C-j" 'visual-basic-split-line)
+ (define-key visual-basic-mode-map "\C-c]" 'visual-basic-close-block)
+ (cond (visual-basic-winemacs-p
+ (define-key visual-basic-mode-map '(control C) 'visual-basic-start-ide))
+ (visual-basic-win32-p
+ (define-key visual-basic-mode-map (read "[?\\S-\\C-c]") 'visual-basic-start-ide)))
+ (if visual-basic-xemacs-p
+ (progn
+ (define-key visual-basic-mode-map "\M-G" 'visual-basic-grep)
+ (define-key visual-basic-mode-map '(meta backspace) 'backward-kill-word)
+ (define-key visual-basic-mode-map '(control meta /) 'visual-basic-new-sub))))
+
+
+;; These abbrevs are valid only in a code context.
+(defvar visual-basic-mode-abbrev-table nil)
+
+(defvar visual-basic-mode-hook ())
+
+
+;; Is there a way to case-fold all regexp matches?
+;; Change KJW Add enum, , change matching from 0 or more to zero or one for public etc.
+(eval-and-compile
+ (defconst visual-basic-defun-start-regexp
+ (concat
+ "^[ \t]*\\([Pp]ublic \\|[Pp]rivate \\|[Ss]tatic\\|[Ff]riend \\)?"
+ "\\([Ss]ub\\|[Ff]unction\\|[Pp]roperty +[GgSsLl]et\\|[Tt]ype\\|[Ee]num\\|[Cc]lass\\)"
+ "[ \t]+\\(\\w+\\)[ \t]*(?")))
+
+
+(defconst visual-basic-defun-end-regexp
+ "^[ \t]*[Ee]nd \\([Ss]ub\\|[Ff]unction\\|[Pp]roperty\\|[Tt]ype\\|[Ee]num\\|[Cc]lass\\)")
+
+(defconst visual-basic-dim-regexp
+ "^[ \t]*\\([Cc]onst\\|[Dd]im\\|[Pp]rivate\\|[Pp]ublic\\)\\_>" )
+
+
+;; Includes the compile-time #if variation.
+;; KJW fixed if to require a whitespace so as to avoid matching, for
+;; instance, iFileName and to require then.
+
+;; Two versions; one recognizes single line if just as though it were
+;; a multi-line and the other does not. Modified again to remove the
+;; requirement for then so as to allow it to match if statements that
+;; have continuations -- VB1 further elaborated on this for single line
+;; if statement to be recognized on broken lines.
+;;(defconst visual-basic-if-regexp
+;; "^[ \t]*#?[Ii]f[ \t]+.*[ \t]+[Tt]hen[ \t]*.*\\('\\|$\\)")
+(defconst visual-basic-if-regexp
+ "^[ \t]*#?[Ii]f[ \t]+.*[ \t_]+")
+
+(defconst visual-basic-ifthen-regexp "^[ \t]*#?[Ii]f.+\\<[Tt]hen\\>\\s-\\S-+")
+
+(defconst visual-basic-else-regexp "^[ \t]*#?[Ee]lse\\([Ii]f\\)?")
+(defconst visual-basic-endif-regexp "[ \t]*#?[Ee]nd[ \t]*[Ii]f")
+
+(defconst visual-basic-looked-at-continuation-regexp "_[ \t]*$")
+
+(defconst visual-basic-continuation-regexp
+ (concat "^.*" visual-basic-looked-at-continuation-regexp))
+
+(eval-and-compile
+ (defconst visual-basic-label-regexp "^[ \t]*[a-zA-Z0-9_]+:$"))
+
+(defconst visual-basic-select-regexp "^[ \t]*[Ss]elect[ \t]+[Cc]ase")
+(defconst visual-basic-case-regexp "^[ \t]*[Cc]ase")
+(defconst visual-basic-select-end-regexp "^[ \t]*[Ee]nd[ \t]+[Ss]elect")
+
+
+(defconst visual-basic-for-regexp "^[ \t]*[Ff]or\\b")
+(defconst visual-basic-next-regexp "^[ \t]*[Nn]ext\\b")
+
+(defconst visual-basic-do-regexp "^[ \t]*[Dd]o\\b")
+(defconst visual-basic-loop-regexp "^[ \t]*[Ll]oop\\b")
+
+(defconst visual-basic-while-regexp "^[ \t]*[Ww]hile\\b")
+(defconst visual-basic-wend-regexp "^[ \t]*[Ww]end\\b")
+
+;; Added KJW Begin..end for forms
+(defconst visual-basic-begin-regexp "^[ \t]*[Bb]egin)?")
+;; This has created a bug. End on its own in code should not outdent.
+;; How can we fix this? They are used in separate Lisp expressions so
+;; add another one.
+(defconst visual-basic-end-begin-regexp "^[ \t]*[Ee]nd")
+
+(defconst visual-basic-with-regexp "^[ \t]*[Ww]ith\\b")
+(defconst visual-basic-end-with-regexp "^[ \t]*[Ee]nd[ \t]+[Ww]ith\\b")
+
+(defconst visual-basic-blank-regexp "^[ \t]*$")
+(defconst visual-basic-comment-regexp "^[ \t]*\\s<.*$")
+
+
+;; This is some approximation of the set of reserved words in Visual Basic.
+(eval-and-compile
+ (defvar visual-basic-all-keywords
+ '("Add" "Aggregate" "And" "App" "AppActivate" "Application" "Array" "As"
+ "Asc" "AscB" "Atn" "Attribute"
+ "Beep" "Begin" "BeginTrans" "Boolean" "ByVal" "ByRef"
+ "CBool" "CByte" "CCur"
+ "CDate" "CDbl" "CInt" "CLng" "CSng" "CStr" "CVErr" "CVar" "Call"
+ "Case" "ChDir" "ChDrive" "Character" "Choose" "Chr" "ChrB" "Class"
+ "ClassModule" "Clipboard" "Close" "Collection" "Column" "Columns"
+ "Command" "CommitTrans" "CompactDatabase" "Component" "Components"
+ "Const" "Container" "Containers" "Cos" "CreateDatabase" "CreateObject"
+ "CurDir" "Currency"
+ "DBEngine" "DDB" "Data" "Database" "Databases"
+ "Date" "DateAdd" "DateDiff" "DatePart" "DateSerial" "DateValue" "Day"
+ "Debug" "Declare" "Deftype" "DeleteSetting" "Dim" "Dir" "Do"
+ "DoEvents" "Domain"
+ "Double" "Dynaset" "EOF" "Each" "Else" "Empty" "End" "EndProperty"
+ "Enum" "Environ" "Erase" "Err" "Error" "Exit" "Exp" "Explicit" "FV" "False" "Field"
+ "Fields" "FileAttr" "FileCopy" "FileDateTime" "FileLen" "Fix" "Font" "For"
+ "Form" "FormTemplate" "Format" "Forms" "FreeFile" "FreeLocks" "Friend"
+ "Function"
+ "Get" "GetAllSettings" "GetAttr" "GetObject" "GetSetting" "Global" "GoSub"
+ "GoTo" "Group" "Groups" "Hex" "Hour" "IIf" "IMEStatus" "IPmt" "IRR"
+ "If" "Implements" "InStr" "Input" "Int" "Integer" "Is" "IsArray" "IsDate"
+ "IsEmpty" "IsError" "IsMissing" "IsNull" "IsNumeric" "IsObject" "Kill"
+ "LBound" "LCase" "LOF" "LSet" "LTrim" "Left" "Len" "Let" "Like" "Line"
+ "Load" "LoadPicture" "LoadResData" "LoadResPicture" "LoadResString" "Loc"
+ "Lock" "Log" "Long" "Loop" "MDIForm" "MIRR" "Me" "MenuItems"
+ "MenuLine" "Mid" "Minute" "MkDir" "Month" "MsgBox" "NPV" "NPer" "Name"
+ "New" "Next" "Not" "Now" "Nothing" "Null" "Object" "Oct" "On" "Open"
+ "OpenDatabase"
+ "Operator" "Option" "Optional"
+ "Or" "PPmt" "PV" "Parameter" "Parameters" "Partition"
+ "Picture" "Pmt" "Preserve" "Print" "Printer" "Printers" "Private"
+ "ProjectTemplate" "Property"
+ "Properties" "Public" "Put" "QBColor" "QueryDef" "QueryDefs"
+ "RSet" "RTrim" "Randomize" "Rate" "ReDim" "Recordset" "Recordsets"
+ "RegisterDatabase" "Relation" "Relations" "Rem" "RepairDatabase"
+ "Reset" "Resume" "Return" "Right" "RmDir" "Rnd" "Rollback" "RowBuffer"
+ "SLN" "SYD" "SavePicture" "SaveSetting" "Screen" "Second" "Seek"
+ "SelBookmarks" "Select" "SelectedComponents" "SendKeys" "Set"
+ "SetAttr" "SetDataAccessOption" "SetDefaultWorkspace" "Sgn" "Shell"
+ "Sin" "Single" "Snapshot" "Space" "Spc" "Sqr" "Static" "Step" "Stop" "Str"
+ "StrComp" "StrConv" "String" "Sub" "SubMenu" "Switch" "Tab" "Table"
+ "TableDef" "TableDefs" "Tan" "Then" "Time" "TimeSerial" "TimeValue"
+ "Timer" "To" "Trim" "True" "Type" "TypeName" "UBound" "UCase" "Unload"
+ "Unlock" "Val" "Variant" "VarType" "Verb" "Weekday" "Wend"
+ "While" "Width" "With" "Workspace" "Workspaces" "Write" "Year")))
+
+(defvar visual-basic-font-lock-keywords-1
+ (eval-when-compile
+ (list
+ ;; Names of functions.
+ (list visual-basic-defun-start-regexp
+ '(1 font-lock-keyword-face nil t)
+ '(2 font-lock-keyword-face nil t)
+ '(3 font-lock-function-name-face))
+
+ ;; Statement labels
+ (cons visual-basic-label-regexp 'font-lock-keyword-face)
+
+ ;; Case values
+ ;; String-valued cases get font-lock-string-face regardless.
+ (list "^[ \t]*case[ \t]+\\([^'\n]+\\)" 1 'font-lock-keyword-face t)
+
+ ;; Any keywords you like.
+ (list (regexp-opt
+ '("Dim" "If" "Then" "Else" "ElseIf" "End If") 'words)
+ 1 'font-lock-keyword-face))))
+
+(defvar visual-basic-font-lock-keywords-2
+ (append visual-basic-font-lock-keywords-1
+ (eval-when-compile
+ `((, (regexp-opt visual-basic-all-keywords 'words)
+ 1 font-lock-keyword-face)))))
+
+(defvar visual-basic-font-lock-keywords visual-basic-font-lock-keywords-1)
+
+
+(put 'visual-basic-mode 'font-lock-keywords 'visual-basic-font-lock-keywords)
+
+;;;###autoload
+(defun visual-basic-mode ()
+ "A mode for editing Microsoft Visual Basic programs.
+Features automatic indentation, font locking, keyword capitalization,
+and some minor convenience functions.
+Commands:
+\\{visual-basic-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map visual-basic-mode-map)
+ (setq major-mode 'visual-basic-mode)
+ (setq mode-name "Visual Basic")
+ (set-syntax-table visual-basic-mode-syntax-table)
+
+ ;;; This does not work in multi major modes.
+ ;;(add-hook 'local-write-file-hooks 'visual-basic-untabify)
+
+ (setq local-abbrev-table visual-basic-mode-abbrev-table)
+ (if visual-basic-capitalize-keywords-p
+ (progn
+ (make-local-variable 'pre-abbrev-expand-hook)
+ (add-hook 'pre-abbrev-expand-hook 'visual-basic-pre-abbrev-expand-hook)
+ (abbrev-mode 1)))
+
+ (make-local-variable 'comment-start)
+ (setq comment-start "' ")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "'+ *")
+ (make-local-variable 'comment-column)
+ (setq comment-column 40)
+ (make-local-variable 'comment-end)
+ (setq comment-end "")
+
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'visual-basic-indent-line)
+
+ (if visual-basic-fontify-p
+ (visual-basic-enable-font-lock))
+
+ (make-local-variable 'imenu-generic-expression)
+ (setq imenu-generic-expression visual-basic-imenu-generic-expression)
+
+ (set (make-local-variable 'imenu-syntax-alist) `((,(string-to-char "_") . "w")))
+ (set (make-local-variable 'imenu-case-fold-search) t)
+
+ ;;(make-local-variable 'visual-basic-associated-files)
+ ;; doing this here means we need not check to see if it is bound later.
+ (add-hook 'find-file-hooks 'visual-basic-load-associated-files)
+
+ (run-hooks 'visual-basic-mode-hook))
+
+
+(defun visual-basic-enable-font-lock ()
+ ;; Emacs 19.29 requires a window-system else font-lock-mode errs out.
+ (cond ((or visual-basic-xemacs-p window-system)
+
+ ;; In win-emacs this sets font-lock-keywords back to nil!
+ (if visual-basic-winemacs-p
+ (font-lock-mode 1))
+
+ ;; Accomodate emacs 19.29+
+ ;; From: Simon Marshall
+ (cond ((boundp 'font-lock-defaults)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ `((visual-basic-font-lock-keywords
+ visual-basic-font-lock-keywords-1
+ visual-basic-font-lock-keywords-2)
+ nil t ((,(string-to-char "_") . "w")))))
+ (t
+ (make-local-variable 'font-lock-keywords)
+ (setq font-lock-keywords visual-basic-font-lock-keywords)))
+
+ (if visual-basic-winemacs-p
+ (font-lock-fontify-buffer)
+ (font-lock-mode 1)))))
+
+;; KJW should add some odds and bobs here to cover "end if" one way
+;; could be to create the abbreviations by removing whitespace then we
+;; could put "end if", "end with" and so on in the keyword table
+;; Another idea would be to make it intelligent enough to substitute
+;; the correct end for the construct (with, select, if)
+;; Is this what the abbrev table hook entry is for?
+(defun visual-basic-construct-keyword-abbrev-table ()
+ (if visual-basic-mode-abbrev-table
+ nil
+ (let ((words visual-basic-all-keywords)
+ (word nil)
+ (list nil))
+ (while words
+ (setq word (car words)
+ words (cdr words))
+ (setq list (cons (list (downcase word) word) list)))
+
+ (define-abbrev-table 'visual-basic-mode-abbrev-table list))))
+
+;; Would like to do this at compile-time.
+(visual-basic-construct-keyword-abbrev-table)
+
+
+(defun visual-basic-upgrade-keyword-abbrev-table ()
+ "Use this in case of upgrading visual-basic-mode.el"
+ (interactive)
+
+ (let ((words visual-basic-all-keywords)
+ (word nil)
+ (list nil))
+ (while words
+ (setq word (car words)
+ words (cdr words))
+ (setq list (cons (list (downcase word) word) list)))
+ (define-abbrev-table 'visual-basic-mode-abbrev-table list)))
+
+
+(defun visual-basic-in-code-context-p ()
+ (if (fboundp 'buffer-syntactic-context) ; XEmacs function.
+ (null (buffer-syntactic-context))
+ ;; Attempt to simulate buffer-syntactic-context
+ ;; I don't know how reliable this is.
+ (let* ((beg (save-excursion
+ (beginning-of-line)
+ (point)))
+ (list
+ (parse-partial-sexp beg (point))))
+ (and (null (nth 3 list)) ; inside string.
+ (null (nth 4 list)))))) ; inside comment
+
+
+(defun visual-basic-pre-abbrev-expand-hook ()
+ ;; Allow our abbrevs only in a code context.
+ (setq local-abbrev-table
+ (if (visual-basic-in-code-context-p)
+ visual-basic-mode-abbrev-table)))
+
+
+(defun visual-basic-newline-and-indent (&optional count)
+ "Insert a newline, updating indentation."
+ (interactive)
+ (save-excursion
+ (expand-abbrev)
+ (visual-basic-indent-line))
+ (call-interactively 'newline-and-indent))
+
+(defun visual-basic-beginning-of-defun ()
+ (interactive)
+ (re-search-backward visual-basic-defun-start-regexp))
+
+(defun visual-basic-end-of-defun ()
+ (interactive)
+ (re-search-forward visual-basic-defun-end-regexp))
+
+(defun visual-basic-mark-defun ()
+ (interactive)
+ (beginning-of-line)
+ (visual-basic-end-of-defun)
+ (set-mark (point))
+ (visual-basic-beginning-of-defun)
+ (if visual-basic-xemacs-p
+ (zmacs-activate-region)))
+
+(defun visual-basic-indent-defun ()
+ (interactive)
+ (save-excursion
+ (visual-basic-mark-defun)
+ (call-interactively 'visual-basic-indent-region)))
+
+
+(defun visual-basic-fill-long-comment ()
+ "Fills block of comment lines around point."
+ ;; Derived from code in ilisp-ext.el.
+ (interactive)
+ (save-excursion
+ (beginning-of-line)
+ (let ((comment-re "^[ \t]*\\s<+[ \t]*"))
+ (if (looking-at comment-re)
+ (let ((fill-prefix
+ (buffer-substring
+ (progn (beginning-of-line) (point))
+ (match-end 0))))
+
+ (while (and (not (bobp))
+ (looking-at visual-basic-comment-regexp))
+ (forward-line -1))
+ (if (not (bobp)) (forward-line 1))
+
+ (let ((start (point)))
+
+ ;; Make all the line prefixes the same.
+ (while (and (not (eobp))
+ (looking-at comment-re))
+ (replace-match fill-prefix)
+ (forward-line 1))
+
+ (if (not (eobp))
+ (beginning-of-line))
+
+ ;; Fill using fill-prefix
+ (fill-region-as-paragraph start (point))))))))
+
+
+(defun visual-basic-fill-or-indent ()
+ "Fill long comment around point, if any, else indent current definition."
+ (interactive)
+ (cond ((save-excursion
+ (beginning-of-line)
+ (looking-at visual-basic-comment-regexp))
+ (visual-basic-fill-long-comment))
+ (t
+ (visual-basic-indent-defun))))
+
+
+(defun visual-basic-new-sub ()
+ "Insert template for a new subroutine. Repeat to cycle through alternatives."
+ (interactive)
+ (beginning-of-line)
+ (let ((templates (cons visual-basic-blank-regexp
+ visual-basic-defn-templates))
+ (tem nil)
+ (bound (point)))
+ (while templates
+ (setq tem (car templates)
+ templates (cdr templates))
+ (cond ((looking-at tem)
+ (replace-match (or (car templates)
+ ""))
+ (setq templates nil))))
+
+ (search-backward "()" bound t)))
+
+
+;; (defun visual-basic-untabify ()
+;; "Do not allow any tabs into the file."
+;; (if (eq major-mode 'visual-basic-mode)
+;; (untabify (point-min) (point-max)))
+;; nil)
+
+(defun visual-basic-default-tag ()
+ (if (and (not (bobp))
+ (save-excursion
+ (backward-sexp)
+ (looking-at "\\w")))
+ (backward-word 1))
+ (let ((s (point))
+ (e (save-excursion
+ (forward-sexp)
+ (point))))
+ (buffer-substring s e)))
+
+(defun visual-basic-grep (tag)
+ "Search BASIC source files in current directory for TAG."
+ (interactive
+ (list (let* ((def (visual-basic-default-tag))
+ (tag (read-string
+ (format "Grep for [%s]: " def))))
+ (if (string= tag "") def tag))))
+ (grep (format "grep -n %s %s" tag visual-basic-wild-files)))
+
+
+;;; IDE Connection.
+
+(defun visual-basic-buffer-project-file ()
+ "Return a guess as to the project file associated with the current buffer."
+ (car (directory-files (file-name-directory (buffer-file-name)) t "\\.vbp")))
+
+(defun visual-basic-start-ide ()
+ "Start Visual Basic (or your favorite IDE, (after Emacs, of course))
+on the first project file in the current directory.
+Note: it's not a good idea to leave Visual Basic running while you
+are editing in Emacs, since Visual Basic has no provision for reloading
+changed files."
+ (interactive)
+ (let (file)
+ (cond ((null visual-basic-ide-pathname)
+ (error "No pathname set for Visual Basic. See visual-basic-ide-pathname"))
+ ((null (setq file (visual-basic-buffer-project-file)))
+ (error "No project file found"))
+ ((fboundp 'win-exec)
+ (iconify-emacs)
+ (win-exec visual-basic-ide-pathname 'win-show-normal file))
+ ((fboundp 'start-process)
+ (iconify-frame (selected-frame))
+ (start-process "*VisualBasic*" nil visual-basic-ide-pathname file))
+ (t
+ (error "No way to spawn process!")))))
+
+
+
+;;; Indentation-related stuff.
+
+(defun visual-basic-indent-region (start end)
+ "Perform visual-basic-indent-line on each line in region."
+ (interactive "r")
+ (save-excursion
+ (goto-char start)
+ (beginning-of-line)
+ (while (and (not (eobp))
+ (< (point) end))
+ (if (not (looking-at visual-basic-blank-regexp))
+ (visual-basic-indent-line))
+ (forward-line 1)))
+
+ (cond ((fboundp 'zmacs-deactivate-region)
+ (zmacs-deactivate-region))
+ ((fboundp 'deactivate-mark)
+ (deactivate-mark))))
+
+
+
+(defun visual-basic-previous-line-of-code ()
+ (if (not (bobp))
+ (forward-line -1)) ; previous-line depends on goal column
+ (while (and (not (bobp))
+ (or (looking-at visual-basic-blank-regexp)
+ (looking-at visual-basic-comment-regexp)))
+ (forward-line -1)))
+
+
+(defun visual-basic-find-original-statement ()
+ "If the current line is a continuation, move back to the original stmt."
+ (let ((here (point)))
+ (visual-basic-previous-line-of-code)
+ (while (and (not (bobp))
+ (looking-at visual-basic-continuation-regexp))
+ (setq here (point))
+ (visual-basic-previous-line-of-code))
+ (goto-char here)))
+
+(defun visual-find-matching-stmt (open-p close-p)
+ ;; Searching backwards
+ (let ((level 0))
+ (while (and (>= level 0) (not (bobp)))
+ (visual-basic-previous-line-of-code)
+ (visual-basic-find-original-statement)
+ (cond ((funcall close-p)
+ (setq level (+ level 1)))
+ ((funcall open-p)
+ (setq level (- level 1)))))))
+
+(defun visual-basic-find-matching-stmt (open-regexp close-regexp)
+ (visual-find-matching-stmt
+ (lambda () (looking-at open-regexp))
+ (lambda () (looking-at close-regexp))))
+
+(defun visual-basic-get-complete-tail-of-line ()
+ "Return the tail of the current statement line, starting at
+ point and going up to end of statement line. If you want the
+ complete statement line, you have to call functions
+ `visual-basic-find-original-statement' and then
+ `beginning-of-line' before"
+ (let* ((start-point (point))
+ complete-line
+ (line-beg start-point)
+ line-end)
+ (while (null line-end)
+ (end-of-line)
+ (setq line-end (point))
+ (if (search-backward "_" line-beg t)
+ (if (looking-at visual-basic-looked-at-continuation-regexp)
+ ;; folded line
+ (progn
+ (setq line-end (1- (point))
+ complete-line (cons
+ (buffer-substring-no-properties
+ line-beg line-end)
+ complete-line)
+ line-end nil)
+ (beginning-of-line 2)
+ (setq line-beg (point)))
+ ;; _ found, but not a folded line (this is a syntax error)
+ (setq complete-line
+ (cons (buffer-substring-no-properties line-beg line-end) complete-line)))
+ ;; not a folded line
+ (setq complete-line
+ (cons (buffer-substring-no-properties line-beg line-end)
+ complete-line))))
+ (mapconcat 'identity (nreverse complete-line) " ")))
+
+(defun visual-basic-if-not-on-single-line ()
+ "Return non-`nil' when the If statement is not on a single statement
+line, i.e. requires a matching End if. Note that a statement line may
+be folded over several code lines."
+ (if (looking-at visual-basic-if-regexp)
+ (save-excursion
+ (beginning-of-line)
+ (let (p1
+ p2
+ ;; 1st reconstruct complete line
+ (complete-line (visual-basic-get-complete-tail-of-line)) )
+
+ ;; now complete line has been reconstructed, drop confusing elements
+
+ ;; remove any VB string from complete line, as strings may disrupt : and ' detection
+ (while (and (setq p1 (string-match "\"" complete-line))
+ (setq p2 (string-match "\"" complete-line (1+ p1))))
+ (setq complete-line (concat (substring complete-line 0 p1)
+ (substring complete-line (1+ p2)))))
+ ;; now drop tailing comment if any
+ (when (setq p1 (string-match "'" complete-line))
+ (setq complete-line (substring complete-line p1)))
+ ;; now drop 1st concatenated instruction is any
+ (when (setq p1 (string-match ":" complete-line))
+ (setq complete-line (substring complete-line p1)))
+ ;;
+ (string-match "Then\\s-*$" complete-line))); end (save-excursion ...)
+ ;; else, not a basic if
+ nil))
+
+(defun visual-basic-find-matching-if ()
+ (visual-find-matching-stmt 'visual-basic-if-not-on-single-line
+ (lambda () (looking-at visual-basic-endif-regexp))))
+
+(defun visual-basic-find-matching-select ()
+ (visual-basic-find-matching-stmt visual-basic-select-regexp
+ visual-basic-select-end-regexp))
+
+(defun visual-basic-find-matching-for ()
+ (visual-basic-find-matching-stmt visual-basic-for-regexp
+ visual-basic-next-regexp))
+
+(defun visual-basic-find-matching-do ()
+ (visual-basic-find-matching-stmt visual-basic-do-regexp
+ visual-basic-loop-regexp))
+
+(defun visual-basic-find-matching-while ()
+ (visual-basic-find-matching-stmt visual-basic-while-regexp
+ visual-basic-wend-regexp))
+
+(defun visual-basic-find-matching-with ()
+ (visual-basic-find-matching-stmt visual-basic-with-regexp
+ visual-basic-end-with-regexp))
+
+;;; If this fails it must return the indent of the line preceding the
+;;; end not the first line because end without matching begin is a
+;;; normal simple statement
+(defun visual-basic-find-matching-begin ()
+ (let ((original-point (point)))
+ (visual-basic-find-matching-stmt visual-basic-begin-regexp
+ visual-basic-end-begin-regexp)
+ (if (bobp) ;failed to find a matching begin so assume that it is
+ ;an end statement instead and use the indent of the
+ ;preceding line.
+ (progn (goto-char original-point)
+ (visual-basic-previous-line-of-code)))))
+
+
+(defun visual-basic-calculate-indent ()
+ (let ((original-point (point)))
+ (save-excursion
+ (beginning-of-line)
+ ;; Some cases depend only on where we are now.
+ (cond ((or (looking-at visual-basic-defun-start-regexp)
+ (looking-at visual-basic-label-regexp)
+ (looking-at visual-basic-defun-end-regexp))
+ 0)
+
+ ;; The outdenting stmts, which simply match their original.
+ ((or (looking-at visual-basic-else-regexp)
+ (looking-at visual-basic-endif-regexp))
+ (visual-basic-find-matching-if)
+ (current-indentation))
+
+ ;; All the other matching pairs act alike.
+ ((looking-at visual-basic-next-regexp) ; for/next
+ (visual-basic-find-matching-for)
+ (current-indentation))
+
+ ((looking-at visual-basic-loop-regexp) ; do/loop
+ (visual-basic-find-matching-do)
+ (current-indentation))
+
+ ((looking-at visual-basic-wend-regexp) ; while/wend
+ (visual-basic-find-matching-while)
+ (current-indentation))
+
+ ((looking-at visual-basic-end-with-regexp) ; with/end with
+ (visual-basic-find-matching-with)
+ (current-indentation))
+
+ ((looking-at visual-basic-select-end-regexp) ; select case/end select
+ (visual-basic-find-matching-select)
+ (current-indentation))
+
+ ;; A case of a select is somewhat special.
+ ((looking-at visual-basic-case-regexp)
+ (visual-basic-find-matching-select)
+ (+ (current-indentation) visual-basic-mode-indent))
+
+ ;; Added KJW: Make sure that this comes after the cases
+ ;; for if..endif, end select because end-regexp will also
+ ;; match "end select" etc.
+ ((looking-at visual-basic-end-begin-regexp) ; begin/end
+ (visual-basic-find-matching-begin)
+ (current-indentation))
+
+ (t
+ ;; Other cases which depend on the previous line.
+ (visual-basic-previous-line-of-code)
+
+ ;; Skip over label lines, which always have 0 indent.
+ (while (looking-at visual-basic-label-regexp)
+ (visual-basic-previous-line-of-code))
+
+ (cond
+ ((looking-at visual-basic-continuation-regexp)
+ (visual-basic-find-original-statement)
+ ;; Indent continuation line under matching open paren,
+ ;; or else one word in.
+ (let* ((orig-stmt (point))
+ (matching-open-paren
+ (condition-case ()
+ (save-excursion
+ (goto-char original-point)
+ (beginning-of-line)
+ (backward-up-list 1)
+ ;; Only if point is now w/in cont. block.
+ (if (<= orig-stmt (point))
+ (current-column)))
+ (error nil))))
+ (cond (matching-open-paren
+ (1+ matching-open-paren))
+ (t
+ ;; Else, after first word on original line.
+ (back-to-indentation)
+ (forward-word 1)
+ (while (looking-at "[ \t]")
+ (forward-char 1))
+ (current-column)))))
+ (t
+ (visual-basic-find-original-statement)
+
+ (let ((indent (current-indentation)))
+ ;; All the various +indent regexps.
+ (cond ((looking-at visual-basic-defun-start-regexp)
+ (+ indent visual-basic-mode-indent))
+
+ ((or (visual-basic-if-not-on-single-line)
+ (and (looking-at visual-basic-else-regexp)
+ (not (and visual-basic-allow-single-line-if
+ (looking-at visual-basic-ifthen-regexp)))))
+ (+ indent visual-basic-mode-indent))
+
+ ((or (looking-at visual-basic-select-regexp)
+ (looking-at visual-basic-case-regexp))
+ (+ indent visual-basic-mode-indent))
+
+ ((or (looking-at visual-basic-do-regexp)
+ (looking-at visual-basic-for-regexp)
+ (looking-at visual-basic-while-regexp)
+ (looking-at visual-basic-with-regexp)
+ (looking-at visual-basic-begin-regexp))
+ (+ indent visual-basic-mode-indent))
+
+ (t
+ ;; By default, just copy indent from prev line.
+ indent))))))))))
+
+(defun visual-basic-indent-to-column (col)
+ (let* ((bol (save-excursion
+ (beginning-of-line)
+ (point)))
+ (point-in-whitespace
+ (<= (point) (+ bol (current-indentation))))
+ (blank-line-p
+ (save-excursion
+ (beginning-of-line)
+ (looking-at visual-basic-blank-regexp))))
+
+ (cond ((/= col (current-indentation))
+ (save-excursion
+ (beginning-of-line)
+ (back-to-indentation)
+ (delete-region bol (point))
+ (indent-to col))))
+
+ ;; If point was in the whitespace, move back-to-indentation.
+ (cond (blank-line-p
+ (end-of-line))
+ (point-in-whitespace
+ (back-to-indentation)))))
+
+
+(defun visual-basic-indent-line ()
+ "Indent current line for BASIC."
+ (interactive)
+ (visual-basic-indent-to-column (visual-basic-calculate-indent)))
+
+
+(defun visual-basic-split-line ()
+ "Split line at point, adding continuation character or continuing a comment.
+In Abbrev mode, any abbrev before point will be expanded."
+ (interactive)
+ (let ((pps-list (parse-partial-sexp (save-excursion
+ (beginning-of-line)
+ (point))
+ (point))))
+ ;; Dispatch on syntax at this position.
+ (cond ((equal t (nth 4 pps-list)) ; in comment
+ (indent-new-comment-line))
+ ((equal t (nth 4 pps-list)) ; in string
+ (error "Can't break line inside a string"))
+ (t (just-one-space) ; leading space on next line
+ ; doesn't count, sigh
+ (insert "_")
+ (visual-basic-newline-and-indent)))))
+
+(defun visual-basic-detect-idom ()
+ "Detects whether this is a VBA or VBS script. Returns symbol
+ `vba' if it is VBA, `nil' otherwise"
+ (let (ret)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (cond
+ ((looking-at "^[ \t]*Attribute\\s-+VB_Name\\s-+= ") (setq ret 'vba)))
+ ))
+ ret))
+
+(defun visual-basic-close-block ()
+ "Insert `End If' is current block is a `If Then ...', `End
+With' if the block is a `With ...', etc..."
+ (interactive)
+ (let (end-statement end-indent)
+ (save-excursion
+ (save-match-data
+ (while
+ (unless (bobp)
+ (visual-basic-previous-line-of-code)
+ (visual-basic-find-original-statement)
+ (cond
+ ;; Cases where the current statement is a start-of-smthing statement
+ ((looking-at visual-basic-defun-start-regexp)
+ (let ((smt (match-string 2)))
+ (when (string-match "\\`Prop" smt)
+ (setq smt "Property"))
+ (setq end-statement (concat "End " smt)
+ end-indent 0))
+ nil)
+ ((looking-at visual-basic-select-regexp)
+ (setq end-statement "End Select"
+ end-indent (current-indentation))
+ nil)
+ ((looking-at visual-basic-with-regexp)
+ (setq end-statement "End With"
+ end-indent (current-indentation))
+ nil)
+ ((looking-at visual-basic-case-regexp)
+ (setq end-statement "End Select"
+ end-indent (max 0 (- (current-indentation) visual-basic-mode-indent)))
+ nil)
+ ((looking-at visual-basic-begin-regexp)
+ (setq end-statement "End"
+ end-indent (current-indentation))
+ nil)
+ ((or (visual-basic-if-not-on-single-line)
+ (looking-at visual-basic-else-regexp))
+ (setq end-statement "End If"
+ end-indent (current-indentation))
+ nil)
+
+ ((looking-at visual-basic-do-regexp)
+ (setq end-statement "Loop"
+ end-indent (current-indentation))
+ nil)
+
+ ((looking-at visual-basic-for-regexp)
+ (goto-char (match-end 0))
+ (setq end-statement "Next"
+ end-indent (current-indentation))
+ (let ((vb-idom (visual-basic-detect-idom)))
+ (cond
+ ;; for VBA add the variable name after Next.
+ ((eq vb-idom 'vba)
+ (when (looking-at "\\s-+\\(Each\\s-+\\|\\)\\([^ \t\n\r]+\\)")
+ (setq end-statement (concat end-statement " " (match-string 2)))))))
+ nil)
+ ;; Cases where the current statement is an end-of-smthing statement
+ ((or (looking-at visual-basic-else-regexp)
+ (looking-at visual-basic-endif-regexp))
+ (visual-basic-find-matching-if)
+ t)
+ ((looking-at visual-basic-next-regexp) ; for/next
+ (visual-basic-find-matching-for)
+ t)
+ ((looking-at visual-basic-loop-regexp) ; do/loop
+ (visual-basic-find-matching-do)
+ t)
+ ((looking-at visual-basic-wend-regexp) ; while/wend
+ (visual-basic-find-matching-while)
+ t)
+ ((looking-at visual-basic-end-with-regexp) ; with/end with
+ (visual-basic-find-matching-with)
+ t)
+ ((looking-at visual-basic-select-end-regexp) ; select case/end select
+ (visual-basic-find-matching-select)
+ t)
+
+
+ ;; default is to loop again back to previous line of code.
+ (t t))))))
+ (when end-statement
+ (insert end-statement)
+ (visual-basic-indent-to-column end-indent))))
+
+(defvar delta-split-to-cur-point) ;; Don't know what it is, just silence compiler
+
+(defun visual-basic-insert-item ()
+ "Insert a new item in a block.
+
+This function is under developement, and for the time being only Dim items are handled.
+
+Interting an item means:
+
+* Add a `Case' or `Case Else' into a `Select ... End Select'
+ block. Pressing again toggles between `Case' and `Case
+ Else'. `Case Else' is possible only if there is not already a `Case Else'.
+
+* split a Dim declaration over several lines.
+
+* Add an `Else' or `ElseIf ... Then' into an `If ... Then ... End
+ If' block. Pressing again toggles between `Else' and `ElseIf
+ ... Then'. `Else' is possible only if therei s not already an
+ `Else'.
+"
+ (interactive)
+ ;; possible cases are
+ ;; dim-split-before => split before variable name
+ ;; dim-split-after => split after type name if any
+ ;; if-with-else
+ ;; if-without-else
+ ;; select-with-else
+ ;; select-without-else
+ ;; not-itemizable
+ (let (item-case
+ item-ident
+ split-point
+ cur-point-mark
+ prefix
+ tentative-split-point
+ block-stack (cur-point (point)) previous-line-of-code)
+ (save-excursion
+ (save-match-data
+ (beginning-of-line)
+ (while
+ (progn
+ (visual-basic-find-original-statement)
+ (cond
+ ;; dim case
+ ;;--------------------------------------------------------------
+ ((and (null previous-line-of-code)
+ (looking-at visual-basic-dim-regexp)
+ (null (save-match-data (looking-at visual-basic-defun-start-regexp))))
+ (setq prefix (buffer-substring-no-properties
+ (point)
+ (goto-char (setq split-point (match-end 0)))))
+ (while
+ (progn
+ (if
+ (looking-at "\\s-*\\sw+\\s-*")
+ (progn
+ (goto-char (setq tentative-split-point (match-end 0)))
+ (if (>= tentative-split-point cur-point)
+ nil
+ (while (or
+ (looking-at "([^)\n]+)\\s-*")
+ (looking-at visual-basic-looked-at-continuation-regexp))
+ (goto-char (setq tentative-split-point (match-end 0))))
+ (when (looking-at "As\\s-+\\sw+\\s-*")
+ (goto-char (setq tentative-split-point (match-end 0))))
+ (when (looking-at visual-basic-looked-at-continuation-regexp)
+ (beginning-of-line 2))
+ (if (looking-at ",")
+ (goto-char (setq split-point (match-end 0)))
+ (setq split-point (point))
+ nil)))
+ nil)))
+ (goto-char split-point)
+ (setq item-case (if (<= split-point cur-point) 'dim-split-before 'dim-split-after))
+ (setq delta-split-to-cur-point (- split-point cur-point))
+ (setq cur-point-mark (make-marker))
+ (set-marker cur-point-mark cur-point)
+ (looking-at "\\s-*")
+ (setq delta-split-to-cur-point (- delta-split-to-cur-point
+ (- (match-end 0) (match-beginning 0))))
+ (delete-region (point) (match-end 0))
+ (when (looking-back ",")
+ (delete-region split-point (1- split-point)))
+ (insert "\n" prefix " ")
+ (setq cur-point (marker-position cur-point-mark))
+ (set-marker cur-point-mark nil)
+ nil)
+ ;; next
+ ((looking-at visual-basic-next-regexp)
+ (push (list 'next) block-stack))
+ ;; default
+ ;;--------------------------------------------------------------
+ (t (if (bobp)
+ (setq item-case 'not-itemizable)))
+ )
+ (when (null item-case)
+ (visual-basic-previous-line-of-code)
+ (setq previous-line-of-code t))
+ (null item-case)))))
+ (cond
+ ((eq item-case 'dim-split-after)
+ (goto-char cur-point))
+ )
+ ))
+
+;;; Some experimental functions
+
+;;; Load associated files listed in the file local variables block
+(defun visual-basic-load-associated-files ()
+ "Load files that are useful to have around when editing the source of the file that has just been loaded.
+The file must have a local variable that lists the files to be loaded.
+If the file name is relative it is relative to the directory
+containing the current buffer. If the file is already loaded nothing
+happens, this prevents circular references causing trouble. After an
+associated file is loaded its associated files list will be
+processed."
+ (if (boundp 'visual-basic-associated-files)
+ (let ((files visual-basic-associated-files)
+ (file nil))
+ (while files
+ (setq file (car files)
+ files (cdr files))
+ (message "Load associated file: %s" file)
+ (visual-basic-load-file-ifnotloaded file default-directory)))))
+
+
+
+(defun visual-basic-load-file-ifnotloaded (file default-directory)
+ "Load file if not already loaded.
+If file is relative then default-directory provides the path"
+ (let((file-absolute (expand-file-name file default-directory)))
+ (if (get-file-buffer file-absolute); don't do anything if the buffer is already loaded
+ ()
+ (find-file-noselect file-absolute ))))
+
+
+
+;;; visual-basic-mode.el ends here
+
+
+;External Links
+;* [http://visualbasic.freetutes.com/ Visual Basic tutorials]
+
diff --git a/emacs.d/nxhtml/related/wikipedia-mode.el b/emacs.d/nxhtml/related/wikipedia-mode.el
new file mode 100644
index 0000000..c219e19
--- /dev/null
+++ b/emacs.d/nxhtml/related/wikipedia-mode.el
@@ -0,0 +1,2296 @@
+;;; wikipedia-mode.el --- Mode for editing Wikipedia articles off-line
+;; Copyright (C) 2003, 2004, 2006 Chong Yidong, Uwe Brauer
+
+;; Author: Chong Yidong
+;; Maintainer: Uwe Brauer
+;; Version: 0.51
+;; Keywords: wiki
+;; $Id: wikipedia-mode.el,v 1.5 2006/05/30 15:16:45 oub Exp oub $
+
+
+;; This file is not part of GNU Emacs.
+
+;;{{{ GPL2
+
+;; This file is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of
+;; the License, or (at your option) any later version.
+
+;; This file is distributed in the hope that it will be
+;; useful, but WITHOUT ANY WARRANTY; without even the implied
+;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+;; PURPOSE. See the GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public
+;; License along with GNU Emacs; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+;; MA 02111-1307 USA
+
+;;}}}
+
+;;; Commentary:
+
+;; This is `wikipedia-mode', a major mode for editing articles written
+;; in the markup language used by Wikipedia, the free on-line
+;; encyclopedia (http://www.wikipedia.org). It is intended to work
+;; with GNU Emacs 21.x, and Xemacs 21.4.x. See below for details.
+
+;; wikipedia mode can be found also at:
+;; http://en.wikipedia.org/wiki/Wikipedia:Wikipedia-mode.el
+
+;;{{{ INSTALLING WIKIPEDIA-MODE
+
+;; Installing wikipedia-mode
+;; =========================
+;;
+;; Save wikipedia-mode.el in a convenient directory, preferably in
+;; your `load-path'. Add the following to your `user-init-file':
+;;
+;; (autoload 'wikipedia-mode
+;; "wikipedia-mode.el"
+;; "Major mode for editing documents in Wikipedia markup." t)
+;;
+;; If you did not save wikipedia-mode.el in your `load-path', you must
+;; use the full pathname. On MS Windows, use forward slashes (/)
+;; rather than back slashes (\) to indicate the directory, e.g.:
+;;
+;; (autoload 'wikipedia-mode
+;; "C:/Documents and Settings/USERNAME/.emacs.d/Wikipedia-mode.el"
+;; "Major mode for editing documents in Wikipedia markup." t)
+;;
+;; If you want to associate filenames ending in ".wiki" with
+;; wikipedia-mode, add the following to your init file:
+;;
+;; (setq auto-mode-alist
+;; (cons '("\\.wiki\\'" . wikipedia-mode) auto-mode-alist))
+
+;;}}}
+
+;;{{{ REQUIREMENTS
+
+;; This is not a real requirements but I highly recommend to use
+;; outline-magic written by Carsten Dominik. If you don't want to use it
+;; you have to comment out the relevant reference to outline magic.
+;; It can be found at
+;; http://www.astro.uva.nl/~dominik/Tools/outline-magic.el
+
+
+
+
+;;}}}
+
+;;{{{ RECOMMENDATIONS INSTALLING LONGLINES-MODE
+
+;; Installing longlines-mode
+;; =========================
+;;
+;; If you are using Emacs 22 or later longlines-mode is included so
+;; please skip this section!
+;;
+;; Wikipedia articles don't use newline characters to break paragraphs
+;; into lines, so each paragraph looks like a super-long line to
+;; Emacs. To let Emacs handle "soft word wrapping", you need to
+;; download a third-party package, longlines-mode.
+;;
+;; Download longlines.el, saving into your `load-path':
+;;
+;; http://www.emacswiki.org/elisp/longlines.el
+;;
+;; Add the following to your `user-init-file':
+;;
+;; (autoload 'longlines-mode "longlines.el"
+;; "Minor mode for editing long lines." t)
+;;
+;;
+;; WARNING: if you insert text from one file in wikipedia-mode to
+;; another file in wikipedia-mode I strongly recommend, to turn
+;; longlines-mode off, before the copying!
+
+;;}}}
+
+;;{{{ RECOMMENDATIONS INSTALLING PABBREV-MODE
+
+;; Installing pabbrev-mode
+;; =========================
+;;
+;; You may find pabbrev.el useful, which can be found at
+;; http://www.russet.org.uk/download/emacs/pabbrev.el
+
+
+;;}}}
+
+;;{{{ Xemacs or (GNU) Emacs
+
+;; Xemacs or (GNU) Emacs
+;; =====================
+;; Usually that is a question of taste. However almost all wikipedia
+;; articles nowadays use UTF8 coding, so the question which of the
+;; Macsen to use, boils down to which degree UTF8 support is
+;; implemented (no mule Xemacs is ruled out). While Xemacs has the
+;; better font support, the UTF8 support still is not complete and
+;; hence at the time being it is sad for the maintainer (a long time
+;; Xemacs user) to recommend NOT to use Xemacs, even not 21.5.x, which
+;; has a much better implemented UTF8 coding engine. That might
+;; however change in the foreseeable future....
+;; WARNING: at least for me in Debian testing/unstable Emacs does not
+;; ship all fonts necessary for a flawless editing of UTF8 files. For
+;; example you can chose Greek input, write Greek text, but then when
+;; you close and open the file again, the Greek symbol are not
+;; displayed but you see empty blocks. The reason seems that emacs
+;; chooses for the input fonts other fonts as for the display (don't
+;; ask me). However for installing the (ugly) UTF8 compatible fonts
+;; from ..... solved that problem.
+
+
+;;}}}
+
+;;{{{ INSTALLING EE-HELPER or MOZEX
+
+;; Installing the helper programs.
+;; =========================
+;; Helper Programs: MozEx and EE-HELPER. There are three possibilities
+;; in order to use Emacs as an external editor
+;;
+;; (1) Firefox add-on It's All Text: Recommended. The elisp
+;; library its-all-text.el makes it easier to use this.
+;;
+;; PROS: Easy to intall, supported. (You need to add Emacs
+;; client as the editor.) Can be used for editing other
+;; text fields with Emacs too.
+;;
+;; (2) EE-HELPER: This is perl script which will communicate with
+;; the wikipedia server. However that sometimes be slow.
+
+;; PROS: if the editor supports UTF8, then ee-helper will
+;; pass the coding flawlessly.
+;;
+;; CONTRA: the problem with this script is that it directly
+;; communicates with the wikipedia site and does not
+;; warn you about simultaneous editing. Use it with
+;; care!!! Moreover section editing is not implemented.
+
+;; (3) MozEx: this is a Java-script which allows to communicate
+;; Mozilla (or Firefox) directly with Emacs.
+
+;; PROS: After finishing editing you use the wikipedia
+;; software to submit your changes and not the script,
+;; so you are warned about possible conflicting editing.
+;;
+;; CONTRA: the official version does not support UTF8,
+;; however there is now a new semi official version which
+;; does support UTF8.
+
+;; Installing It's All Text
+;; ========================
+;;
+;; Go to the home page and follow the instructions there:
+;;
+;; https://addons.mozilla.org/en-US/firefox/addon/4125
+;;
+;; Then open It's All Text preferences from the Firefox Add-ons page
+;; and choose emacsclient as your editor (emacsclientw.exe on
+;; Windows).
+
+;; Installing ee-helper
+;; ====================
+;;
+;; Download the perl script from
+;;
+;; http://meta.wikimedia.org/wiki/Help:External_editors
+;;
+;; and follow the instructions. configure the .ee-ini file. chance in
+;; your personal wikipedia-mode-map account setting the editing
+;; functions: activate the `external editor' option.
+
+;; Installing MozEx
+;; ================
+;;
+;; If your web browser is Mozilla or Firefox, take a look at the MozEx
+;; extension, which allows you to call Emacs for editing text boxes:
+;;
+;; http://mozex.mozdev.org/development.html
+;;
+;; See also
+;;
+;; http://www.emacswiki.org/cgi-bin/wiki/FireFox
+;;
+;; If you mostly use MozEx to edit Wikipedia articles, it might be
+;; worthwhile to tell Emacs to enter wikipedia-mode whenever it is
+;; called by MozEx. Just add this to your `user-init-file':
+;;
+;; (add-to-list 'auto-mode-alist '("mozex.\\.*" . wikipedia-mode))
+
+;; Recall: you have to click on edit (either edit article or edit
+;; section), then use mouse3 (or shift f10), then select
+;; mozex, then edit textarea: Edit-->mouse3-->mozex-->Edit
+;; Textarea. After editing, you have to _click_ on the
+;; text in the browser otherwise Mozilla will ignore your
+;; typing.
+
+;;}}}
+
+;;{{{ NEWS
+
+
+;; NEWS
+;; ==================================
+;; (1) Font setting has changed.
+;; (2) Some makeup formats have been added: italics, bold, strong
+;; emphasise, links.
+;; (3) outline-cycle from Carsten Dominiks outline-magic has been
+;; added.
+;; (4) "Draft", "send" and "reply" (for discussion pages)
+;; abilities 'based' on ideas of John Wigleys remember.el: see
+;; the functions wikipedia-draft-*
+;; RATIONALE: This comes handy in 2 situations
+;; 1. You are editing articles which various authors (this I
+;; think is the usual case), you then want not to submit
+;; your edit immediately but want to copy it somewhere and
+;; to continue later. You can use the following functions
+;; for doing that:
+;; wikipedia-draft-buffer \C-c\C-b
+;; wikipedia-draft-region \C-c\C-r
+;; then the buffer/region will be appended to the
+;; wikipedia-draft-data-file (default is
+;; "~/Wiki/discussions/draft.wiki", which you can visit via
+;; wikipedia-draft-view-draft) and it will be
+;; surrounded by the ^L marks in order to set a page.
+;; moreover on top on that a section header == will be
+;; inserted, which consists of the Word Draft, a subject
+;; you are asked for and a date stamp.
+;;
+;; Another possibility consists in using the function
+;; wikipedia-draft, bound to \C-c \C-m then a new buffer
+;; will opened already in wikipedia mode. You edit and then
+;; either can send the content of the buffer to the
+;; wikipedia-draft-data-file in the same manner as
+;; described above using the function
+;; wikipedia-draft-buffer (bound to \C-c\C-k)
+;;
+;; BACK: In order to copy/send the content of temporary
+;; buffer or of a page in the wikipedia-draft-data-file
+;; back in to your wikipedia file, use the function
+;; `wikipedia-send-to-mozex'. You
+;; will be asked to which buffer to copy your text!
+;;
+;;
+;; 2. You want to reply in a discussion page to a specific
+;; contribution, you can use either the function
+;;
+;; \\[wikipedia-reply-at-point-simple] bound to [(meta shift r)]
+;; which inserts a newline, a hline, and the signature of
+;; the author. Or can use
+;; \\[wikipedia-draft-reply] bound [(meta r)]
+;; which does the same as wikipedia-reply-at-point-simple
+;; but in a temporary draft buffer.
+;;
+;; BACK: In order to copy/send the content of that buffer
+;; back in to your wikipedia file, use the function
+;; \\[wikipedia-send-to-mozex] bound to "\C-c\C-c". You
+;; will be asked to which buffer to copy your text! If
+;; you want a copy to be send to your draft file, use
+;; the variable wikipedia-draft-send-archive
+;;
+
+;;}}}
+
+;;{{{ NEW FUNCTIONS AND VARIABLES
+
+
+;; VERSION 0.4
+;;==================
+;; NEW FUNCTIONS
+;; ------------------
+;; wikipedia-insert-enumerate
+;; wikipedia-insert-itemize
+;; wikipedia-insert-strong-emphasis (renamed to wikipedia-insert-bold-italic)
+;; wikipedia-insert-bold
+;; wikipedia-insert-italics
+;; wikipedia-insert-header
+;; wikipedia-insert-link-wiki
+;; wikipedia-turn-on-outline-minor-mode
+;; wikipedia-insert-signature
+;; wikipedia-insert-hline
+;; wikipedia-unfill-paragraph-or-region
+;; wikipedia-start-paragraph
+;; wikipedia-hardlines
+;; wikipedia-outline-magic-keys
+;; wikipedia-enhance-indent
+;; wikipedia-yank-prefix
+;; wikipedia-simple-outline-promote
+;; wikipedia-simple-outline-demote
+;; wikipedia-next-long-line
+;; wikipedia-unfill-paragraph
+;; wikipedia-rename-buffer
+;; wikipedia-draft
+;; wikipedia-draft-buffer-desc
+;; wikipedia-draft-append-to-file
+;; wikipedia-draft-page
+;; wikipedia-draft-region (&optional beg end)
+;; wikipedia-draft-buffer
+;; wikipedia-draft-clipboard
+;; wikipedia-draft-mode
+;; wikipedia-draft-view-draft
+;; wikipedia-mark-section
+;; wikipedia-activate-region
+;; wikipedia-copy-page-to-register
+;; wikipedia-insert-page-to-register
+;; wikipedia-send-to-mozex (target-buffer)
+;; wikipedia-reply-at-point-simple
+;; wikipedia-draft-reply
+;; wikipedia-insert-quotation-with-signature
+;; wikipedia-insert-quotation
+
+;; NEW VARIABLES
+;;---------------------
+;; wikipedia-enumerate-with-terminate-paragraph
+;; wikipedia-draft-buffer "*Wikipedia-Draft*"
+;; wikipedia-draft-mode-map
+;; wikipedia-draft-mode-hook
+;; wikipedia-draft-register ?R
+;; wikipedia-draft-filter-functions
+;; wikipedia-draft-handler-functions '(wikipedia-draft-append-to-file)
+;; wikipedia-draft-data-file "~/Wiki/discussions/draft.wiki"
+;; wikipedia-draft-leader-text "== "
+;; wikipedia-draft-page ?S
+;; wikipedia-draft-send-archive
+;; wikipedia-reply-with-quote
+
+
+;; VERSION 0.5
+;;====================================
+;; NEW FUNCTIONS
+;; ------------------------------------
+;; wikipedia-insert-audio
+;; wikipedia-insert-image
+;; wikipedia-insert-link-www (renamed to wikipedia-insert-link-external)
+;; wikipedia-insert-user
+;; wikipedia-mark-signature
+;; wikipedia-outline-cycle
+;; wikipedia-reply-at-signature
+;; wikipedia-terminate-paragraph-and-indent
+;; wikipedia-yank-prefix
+
+;; NEW VARIABLES (defvar, defcustom, defconst)
+;; ----------------------
+;; wikipedia-reply-with-hline
+;; wikipedia-user-simplify-signature
+;; wikipedia-english-or-german
+;; wikipedia-draft-reply-register ?M
+;; wikipedia-mode-version
+
+;; VERSION 0.51
+;;====================================
+;;
+;; - Now requires Emacs 22 or higher.
+;; - Cleaned the code in various ways.
+;; - Removed wikipedia-english-or-german
+;; - Removed some private stuff
+;; - Simplified some key bindings.
+;; - Changed some key bindings to those used in org-mode.
+;; - Added wikipedia-lang etc
+;; - Added support for templates
+;; - Adjusted header end after inserting heading/promoting/demoting
+;; - Removed some functions that are already supported by outline.el
+;; - Changed wikipedia-mode menus
+;; - Added support for bullets and numbering
+
+;;}}}
+
+;;{{{ TODO
+
+;; Todo
+;; ----
+
+
+;; * Implement TeX highlighting in