File:
[LON-CAPA] /
loncom /
html /
adm /
jsMath /
extensions /
newcommand.js
Revision
1.2:
download - view:
text,
annotated -
select for diffs
Tue Oct 9 21:29:22 2007 UTC (17 years, 1 month ago) by
albertel
Branches:
MAIN
CVS tags:
version_2_9_X,
version_2_9_99_0,
version_2_9_1,
version_2_9_0,
version_2_8_X,
version_2_8_99_1,
version_2_8_99_0,
version_2_8_2,
version_2_8_1,
version_2_8_0,
version_2_7_X,
version_2_7_99_1,
version_2_7_99_0,
version_2_7_1,
version_2_7_0,
version_2_6_X,
version_2_6_99_1,
version_2_6_99_0,
version_2_6_3,
version_2_6_2,
version_2_6_1,
version_2_6_0,
version_2_5_99_1,
version_2_5_99_0,
version_2_12_X,
version_2_11_X,
version_2_11_5_msu,
version_2_11_5,
version_2_11_4_uiuc,
version_2_11_4_msu,
version_2_11_4,
version_2_11_3_uiuc,
version_2_11_3_msu,
version_2_11_3,
version_2_11_2_uiuc,
version_2_11_2_msu,
version_2_11_2_educog,
version_2_11_2,
version_2_11_1,
version_2_11_0_RC3,
version_2_11_0_RC2,
version_2_11_0_RC1,
version_2_11_0,
version_2_10_X,
version_2_10_1,
version_2_10_0_RC2,
version_2_10_0_RC1,
version_2_10_0,
loncapaMITrelate_1,
language_hyphenation_merge,
language_hyphenation,
bz6209-base,
bz6209,
bz5969,
bz2851,
PRINT_INCOMPLETE_base,
PRINT_INCOMPLETE,
HEAD,
GCI_3,
GCI_2,
GCI_1,
BZ5971-printing-apage,
BZ5434-fox,
BZ4492-merge,
BZ4492-feature_horizontal_radioresponse
- jsMath 3.4e
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: newenvironment: 'NewEnvironment',
35: def: 'MacroDef'
36: },
37:
38: /*
39: * Implement \newcommand{\name}[n]{...}
40: */
41: NewCommand: function (name) {
42: var cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
43: var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
44: var def = this.GetArgument(this.cmd+name); if (this.error) return;
45: if (n == '') {n = null}
46: if (cs.charAt(0) == this.cmd) {cs = cs.substr(1)}
47: if (!cs.match(/^(.|[a-z]+)$/)) {this.Error("Illegal control sequence name for "+this.cmd+name); return}
48: if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
49: jsMath.Parser.prototype.macros[cs] = ['Macro',def,n];
50: },
51:
52: /*
53: * Implement \newenvironment{name}[n]{begincmd}{endcmd}
54: */
55: NewEnvironment: function (name) {
56: var env = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
57: var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
58: var bdef = this.GetArgument(this.cmd+name); if (this.error) return;
59: var edef = this.GetArgument(this.cmd+name); if (this.error) return;
60: if (n == '') {n = null}
61: if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
62: jsMath.Parser.prototype.environments[env] = ['Environment',bdef,edef,n];
63: },
64:
65: /*
66: * Implement \def command
67: */
68: MacroDef: function (name) {
69: var cs = this.GetCSname(this.cmd+name); if (this.error) return;
70: var params = this.GetTemplate(this.cmd+name); if (this.error) return;
71: var def = this.GetArgument(this.cmd+name); if (this.error) return;
72: if (typeof(params) == 'number') {
73: jsMath.Parser.prototype.macros[cs] = ['Macro',def,params];
74: } else {
75: jsMath.Parser.prototype.macros[cs] = ['MacroWithTemplate',def,params[0],params[1]];
76: }
77: },
78:
79: /*
80: * Get a CS name or give an error
81: */
82: GetCSname: function (cmd) {
83: var c = this.GetNext();
84: if (c != this.cmd) {this.Error(cmd+" must be followed by a control sequence"); return null}
85: var cs = this.trimSpaces(this.GetArgument(cmd)); if (this.error) {return null};
86: return cs.substr(1);
87: },
88:
89: /*
90: * Get a \def parameter template
91: */
92: GetTemplate: function (cmd) {
93: var c; var params = []; var n = 0;
94: c = this.GetNext(); var i = this.i;
95: while (this.i < this.string.length) {
96: c = this.GetNext();
97: if (c == '#') {
98: if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
99: c = this.string.charAt(++this.i);
100: if (!c.match(/[1-9]/)) {this.Error("Illegal use of # in "+cmd); return null}
101: if (1*c != ++n) {this.Error("Parameters must be numbered sequentially"); return null}
102: i = this.i+1;
103: } else if (c == '{') {
104: if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
105: if (params.length > 0) {return [n,params]} else {return n}
106: }
107: this.i++;
108: }
109: this.Error("Missing replacement string for definition of "+cmd);
110: return null;
111: },
112:
113: /*
114: * Process a macro with a parameter template
115: */
116: MacroWithTemplate: function (name,data) {
117: var text = data[0];
118: var n = data[1]; var params = data[2];
119: if (n) {
120: var args = []; var c = this.GetNext();
121: if (params[0] && !this.MatchParam(params[0]))
122: {this.Error("Use of "+this.cmd+name+" doesn't match its definition"); return}
123: for (var i = 0; i < n; i++) {
124: args[args.length] = this.GetParameter(this.cmd+name,params[i+1]);
125: if (this.error) return;
126: }
127: text = this.SubstituteArgs(args,text);
128: }
129: this.string = this.AddArgs(text,this.string.slice(this.i));
130: this.i = 0;
131: },
132:
133: /*
134: * Process a user-defined environment
135: */
136: Environment: function (name,data) {
137: var bdef = data[0]; var edef = data[1]; var n = data[2];
138: if (n) {
139: var args = [];
140: for (var i = 0; i < n; i++) {
141: args[args.length] = this.GetArgument(this.cmd+"begin{"+name+"}"); if (this.error) return;
142: }
143: bdef = this.SubstituteArgs(args,bdef);
144: }
145: var text = this.GetEnd(name); if (this.error) return;
146: text = this.AddArgs(this.AddArgs(bdef,text),edef);
147: this.string = this.AddArgs(text,this.string.slice(this.i));
148: this.i = 0;
149: },
150:
151: /*
152: * Find a single parameter delimited by a trailing template
153: */
154: GetParameter: function (name,param) {
155: if (param == null) {return this.GetArgument(name)}
156: var i = this.i; var j = 0; var hasBraces = 0;
157: while (this.i < this.string.length) {
158: if (this.string.charAt(this.i) == '{') {
159: if (this.i == i) {hasBraces = 1}
160: this.GetArgument(name); j = this.i - i;
161: } else if (this.MatchParam(param)) {
162: if (hasBraces) {i++; j -= 2}
163: return this.string.substr(i,j);
164: } else {
165: this.i++; j++; hasBraces = 0;
166: }
167: }
168: this.Error("Runaway argument for "+name+"?");
169: return null;
170: },
171:
172: /*
173: * Check if a template is at the current location.
174: * (The match must be exact, with no spacing differences. TeX is
175: * a little more forgiving about spaces after macro names)
176: */
177: MatchParam: function (param) {
178: if (this.string.substr(this.i,param.length) != param) {return 0}
179: this.i += param.length;
180: return 1;
181: }
182:
183: });
184:
185: /*
186: * Define a jsMath.Environment() command similar to the
187: * jsMath.Macro() command.
188: *
189: * Usage: jsMath.Environment(name,begin,end[,n])
190: *
191: * where "name" is the name of the environment, "begin" is the
192: * text that replaces the \begin{name} and "end" is the text that
193: * replaces the \end{name}. If "n" is provided, it is the number
194: * of parameters that the \begin{name} accepts, and these are
195: * used to replace #1, #2, etc within the "begin" text.
196: */
197:
198: jsMath.Add(jsMath,{
199: Environment: function (name) {
200: var environments = jsMath.Parser.prototype.environments;
201: environments[name] = ['Environment'];
202: for (var i = 1; i < arguments.length; i++)
203: {environments[name][environments[name].length] = arguments[i]}
204: }
205: });
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>