Annotation of loncom/html/adm/jsMath/extensions/newcommand.js, revision 1.1

1.1     ! albertel    1: /*
        !             2:  *  extensions/newcommand.js
        !             3:  *  
        !             4:  *  Part of the jsMath package for mathematics on the web.
        !             5:  *
        !             6:  *  This file implements the \newcommand and \def macros.  It will be
        !             7:  *  loaded automatically when needed, or can be loaded by
        !             8:  *  
        !             9:  *    jsMath.Extension.Require('newcommand');
        !            10:  *
        !            11:  *  ---------------------------------------------------------------------
        !            12:  *
        !            13:  *  Copyright 2005-2006 by Davide P. Cervone
        !            14:  * 
        !            15:  *  Licensed under the Apache License, Version 2.0 (the "License");
        !            16:  *  you may not use this file except in compliance with the License.
        !            17:  *  You may obtain a copy of the License at
        !            18:  * 
        !            19:  *      http://www.apache.org/licenses/LICENSE-2.0
        !            20:  * 
        !            21:  *  Unless required by applicable law or agreed to in writing, software
        !            22:  *  distributed under the License is distributed on an "AS IS" BASIS,
        !            23:  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        !            24:  *  See the License for the specific language governing permissions and
        !            25:  *  limitations under the License.
        !            26:  */
        !            27: 
        !            28: /********************************************************************/
        !            29: 
        !            30: jsMath.Package(jsMath.Parser,{
        !            31:   
        !            32:   macros: {
        !            33:     newcommand: 'NewCommand',
        !            34:     def: 'MacroDef'
        !            35:   },
        !            36:   
        !            37:   /*
        !            38:    *  Implement \newcommand[n]{\name}{...}
        !            39:    */
        !            40:   NewCommand: function (name) {
        !            41:     var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
        !            42:     var cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
        !            43:     var def = this.GetArgument(this.cmd+name); if (this.error) return;
        !            44:     if (n == '') {n = null}
        !            45:     if (cs.charAt(0) == this.cmd) {cs = cs.substr(1)}
        !            46:     if (!cs.match(/^(.|[a-z]+)$/)) {this.Error("Illegal control sequence name for "+this.cmd+name); return}
        !            47:     if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
        !            48:     jsMath.Parser.prototype.macros[cs] = ['Macro',def,n];
        !            49:   },
        !            50:   
        !            51:   /*
        !            52:    *  Implement \def command
        !            53:    */
        !            54:   MacroDef: function (name) {
        !            55:     var cs = this.GetCSname(this.cmd+name); if (this.error) return;
        !            56:     var params = this.GetTemplate(this.cmd+name); if (this.error) return;
        !            57:     var def = this.GetArgument(this.cmd+name); if (this.error) return;
        !            58:     if (typeof(params) == 'number') {
        !            59:       jsMath.Parser.prototype.macros[cs] = ['Macro',def,params];
        !            60:     } else {
        !            61:       jsMath.Parser.prototype.macros[cs] = ['MacroWithTemplate',def,params[0],params[1]];
        !            62:     }
        !            63:   },
        !            64: 
        !            65:   /*
        !            66:    *  Get a CS name or give an error
        !            67:    */
        !            68:   GetCSname: function (cmd) {
        !            69:     var c = this.GetNext();
        !            70:     if (c != this.cmd) {this.Error(cmd+" must be followed by a control sequence"); return null}
        !            71:     var cs = this.trimSpaces(this.GetArgument(cmd)); if (this.error) {return null};
        !            72:     return cs.substr(1);
        !            73:   },
        !            74:   
        !            75:   /*
        !            76:    *  Get a \def parameter template
        !            77:    */
        !            78:   GetTemplate: function (cmd) {
        !            79:     var c; var params = []; var n = 0;
        !            80:     c = this.GetNext(); var i = this.i;
        !            81:     while (this.i < this.string.length) {
        !            82:       c = this.GetNext();
        !            83:       if (c == '#') {
        !            84:         if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
        !            85:         c = this.string.charAt(++this.i);
        !            86:         if (!c.match(/[1-9]/)) {this.Error("Illegal use of # in "+cmd); return null}
        !            87:         if (1*c != ++n) {this.Error("Parameters must be numbered sequentially"); return null}
        !            88:         i = this.i+1;
        !            89:       } else if (c == '{') {
        !            90:         if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
        !            91:         if (params.length > 0) {return [n,params]} else {return n}
        !            92:       }
        !            93:       this.i++;
        !            94:     }
        !            95:     this.Error("Missing replacement string for definition of "+cmd);
        !            96:     return null;
        !            97:   },
        !            98:   
        !            99:   /*
        !           100:    *  Process a macro with a parameter template
        !           101:    */
        !           102:   MacroWithTemplate: function (name,data) {
        !           103:     var text = data[0];
        !           104:     var n = data[1]; var params = data[2];
        !           105:     if (n) {
        !           106:       var args = []; var c = this.GetNext();
        !           107:       if (params[0] && !this.MatchParam(params[0]))
        !           108:         {this.Error("Use of "+this.cmd+name+" doesn't match its definition"); return}
        !           109:       for (var i = 0; i < n; i++) {
        !           110:         args[args.length] = this.GetParameter(this.cmd+name,params[i+1]);
        !           111:         if (this.error) return;
        !           112:       }
        !           113:       text = this.SubstituteArgs(args,text);
        !           114:     }
        !           115:     this.string = this.AddArgs(text,this.string.slice(this.i));
        !           116:     this.i = 0;
        !           117:   },
        !           118: 
        !           119:   /*
        !           120:    *  Find a single parameter delimited by a trailing template
        !           121:    */
        !           122:   GetParameter: function (name,param) {
        !           123:     if (param == null) {return this.GetArgument(name)}
        !           124:     var i = this.i; var j = 0; var hasBraces = 0;
        !           125:     while (this.i < this.string.length) {
        !           126:       if (this.string.charAt(this.i) == '{') {
        !           127:         if (this.i == i) {hasBraces = 1}
        !           128:         this.GetArgument(name); j = this.i - i;
        !           129:       } else if (this.MatchParam(param)) {
        !           130:         if (hasBraces) {i++; j -= 2}
        !           131:         return this.string.substr(i,j);
        !           132:       } else {
        !           133:         this.i++; j++; hasBraces = 0;
        !           134:       }
        !           135:     }
        !           136:     this.Error("Runaway argument for "+name+"?");
        !           137:     return null;
        !           138:   },
        !           139: 
        !           140:   /*
        !           141:    *  Check if a template is at the current location.
        !           142:    *  (The match must be exact, with no spacing differences.  TeX is
        !           143:    *   a little more forgiving about spaces after macro names)
        !           144:    */
        !           145:   MatchParam: function (param) {
        !           146:     if (this.string.substr(this.i,param.length) != param) {return 0}
        !           147:     this.i += param.length;
        !           148:     return 1;
        !           149:   }
        !           150:   
        !           151: });

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>