mirror of
				https://github.com/Jermolene/TiddlyWiki5
				synced 2025-10-30 23:23:02 +00:00 
			
		
		
		
	Switch to using \procedure to define new-style macros, and \function for custom filter operator functions
I now need to update the OP!
This commit is contained in:
		| @@ -20,7 +20,7 @@ Export our filter function | |||||||
| exports.unknown = function(source,operator,options) { | exports.unknown = function(source,operator,options) { | ||||||
| 	var customDefinitionTitle = "[" + operator.operator + "[]]", | 	var customDefinitionTitle = "[" + operator.operator + "[]]", | ||||||
| 		customDefinition = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(customDefinitionTitle); | 		customDefinition = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(customDefinitionTitle); | ||||||
| 	if(customDefinition && customDefinition.srcVariable) { | 	if(customDefinition && customDefinition.srcVariable && customDefinition.srcVariable.isFunctionDefinition) { | ||||||
| 		var variables = Object.create(null); | 		var variables = Object.create(null); | ||||||
| 		$tw.utils.each(customDefinition.srcVariable.params,function(param,index) { | 		$tw.utils.each(customDefinition.srcVariable.params,function(param,index) { | ||||||
| 			var value = operator.operands[index]; | 			var value = operator.operands[index]; | ||||||
| @@ -37,7 +37,13 @@ exports.unknown = function(source,operator,options) { | |||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 		var getVariableInfo = function(name,opts) { | 		var getVariableInfo = function(name,opts) { | ||||||
|  | 			if(name in variables) { | ||||||
|  | 				return { | ||||||
|  | 					text: variables[name] | ||||||
|  | 				}; | ||||||
|  | 			} else { | ||||||
| 				return options.widget.getVariableInfo(name,opts); | 				return options.widget.getVariableInfo(name,opts); | ||||||
|  | 			}; | ||||||
| 		} | 		} | ||||||
| 		var list = options.wiki.filterTiddlers(customDefinition.srcVariable.value,{getVariable: getVariable,getVariableInfo: getVariableInfo},source); | 		var list = options.wiki.filterTiddlers(customDefinition.srcVariable.value,{getVariable: getVariable,getVariableInfo: getVariableInfo},source); | ||||||
| 		if(operator.prefix === "!") { | 		if(operator.prefix === "!") { | ||||||
|   | |||||||
| @@ -1,14 +1,18 @@ | |||||||
| /*\ | /*\ | ||||||
| title: $:/core/modules/parsers/wikiparser/rules/functiondef.js | title: $:/core/modules/parsers/wikiparser/rules/fnprocdef.js | ||||||
| type: application/javascript | type: application/javascript | ||||||
| module-type: wikirule | module-type: wikirule | ||||||
| 
 | 
 | ||||||
| Wiki pragma rule for function definitions | Wiki pragma rule for function and procedure definitions | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| \function name(param:defaultvalue,param2:defaultvalue) | \function name(param:defaultvalue,param2:defaultvalue) | ||||||
| definition text | definition text | ||||||
| \end | \end | ||||||
|  | 
 | ||||||
|  | \procedure name(param:defaultvalue,param2:defaultvalue) | ||||||
|  | definition text | ||||||
|  | \end | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| \*/ | \*/ | ||||||
| @@ -18,7 +22,7 @@ definition text | |||||||
| /*global $tw: false */ | /*global $tw: false */ | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| exports.name = "functiondef"; | exports.name = "fnprocdef"; | ||||||
| exports.types = {pragma: true}; | exports.types = {pragma: true}; | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
| @@ -27,7 +31,7 @@ Instantiate parse rule | |||||||
| exports.init = function(parser) { | exports.init = function(parser) { | ||||||
| 	this.parser = parser; | 	this.parser = parser; | ||||||
| 	// Regexp to match
 | 	// Regexp to match
 | ||||||
| 	this.matchRegExp = /^\\function\s+([^(\s]+)(\(\s*([^)]*)\))?(\s*\r?\n)?/mg; | 	this.matchRegExp = /^\\(function|procedure)\s+([^(\s]+)(\(\s*([^)]*)\))?(\s*\r?\n)?/mg; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
| @@ -37,9 +41,9 @@ exports.parse = function() { | |||||||
| 	// Move past the macro name and parameters
 | 	// Move past the macro name and parameters
 | ||||||
| 	this.parser.pos = this.matchRegExp.lastIndex; | 	this.parser.pos = this.matchRegExp.lastIndex; | ||||||
| 	// Parse the parameters
 | 	// Parse the parameters
 | ||||||
| 	var paramString = this.match[3], | 	var paramString = this.match[4], | ||||||
| 		params = []; | 		params = []; | ||||||
| 	if(this.match[2]) { | 	if(this.match[3]) { | ||||||
| 		var reParam = /\s*([^:),\s]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|([^,"'\s]+)))?/mg, | 		var reParam = /\s*([^:),\s]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|([^,"'\s]+)))?/mg, | ||||||
| 			paramMatch = reParam.exec(paramString); | 			paramMatch = reParam.exec(paramString); | ||||||
| 		while(paramMatch) { | 		while(paramMatch) { | ||||||
| @@ -56,7 +60,7 @@ exports.parse = function() { | |||||||
| 	} | 	} | ||||||
| 	// Is this a multiline definition?
 | 	// Is this a multiline definition?
 | ||||||
| 	var reEnd; | 	var reEnd; | ||||||
| 	if(this.match[4]) { | 	if(this.match[5]) { | ||||||
| 		// If so, the end of the body is marked with \end
 | 		// If so, the end of the body is marked with \end
 | ||||||
| 		reEnd = /(\r?\n\\end[^\S\n\r]*(?:$|\r?\n))/mg; | 		reEnd = /(\r?\n\\end[^\S\n\r]*(?:$|\r?\n))/mg; | ||||||
| 	} else { | 	} else { | ||||||
| @@ -77,16 +81,21 @@ exports.parse = function() { | |||||||
| 		text = ""; | 		text = ""; | ||||||
| 	} | 	} | ||||||
| 	// Save the macro definition
 | 	// Save the macro definition
 | ||||||
| 	return [{ | 	var parseTreeNodes = [{ | ||||||
| 		type: "set", | 		type: "set", | ||||||
| 		attributes: { | 		attributes: { | ||||||
| 			name: {type: "string", value: this.match[1]}, | 			name: {type: "string", value: this.match[2]}, | ||||||
| 			value: {type: "string", value: text} | 			value: {type: "string", value: text} | ||||||
| 		}, | 		}, | ||||||
| 		children: [], | 		children: [], | ||||||
| 		params: params, | 		params: params | ||||||
| 		isFunctionDefinition: true |  | ||||||
| 	}]; | 	}]; | ||||||
|  | 	if(this.match[1] === "function") { | ||||||
|  | 		parseTreeNodes[0].isFunctionDefinition = true; | ||||||
|  | 	} else if(this.match[1] === "procedure") { | ||||||
|  | 		parseTreeNodes[0].isProcedureDefinition = true; | ||||||
|  | 	} | ||||||
|  | 	return parseTreeNodes; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| })(); | })(); | ||||||
| @@ -56,9 +56,10 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { | |||||||
| 						attributes: parseTreeNode.attributes, | 						attributes: parseTreeNode.attributes, | ||||||
| 						params: parseTreeNode.params, | 						params: parseTreeNode.params, | ||||||
| 						isMacroDefinition: parseTreeNode.isMacroDefinition, | 						isMacroDefinition: parseTreeNode.isMacroDefinition, | ||||||
| 						isFunctionDefinition: parseTreeNode.isFunctionDefinition | 						isFunctionDefinition: parseTreeNode.isFunctionDefinition, | ||||||
|  | 						isProcedureDefinition: parseTreeNode.isProcedureDefinition | ||||||
| 					}; | 					}; | ||||||
| 					if (parseTreeNode.isMacroDefinition || parseTreeNode.isFunctionDefinition) { | 					if (parseTreeNode.isMacroDefinition || parseTreeNode.isProcedureDefinition) { | ||||||
| 						// Macro definitions can be folded into | 						// Macro definitions can be folded into | ||||||
| 						// current widget instead of adding | 						// current widget instead of adding | ||||||
| 						// another link to the chain. | 						// another link to the chain. | ||||||
|   | |||||||
| @@ -49,9 +49,11 @@ SetWidget.prototype.execute = function() { | |||||||
| 	this.setEmptyValue = this.getAttribute("emptyValue"); | 	this.setEmptyValue = this.getAttribute("emptyValue"); | ||||||
| 	// Set context variable | 	// Set context variable | ||||||
| 	if(this.parseTreeNode.isMacroDefinition) { | 	if(this.parseTreeNode.isMacroDefinition) { | ||||||
| 		this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition); | 		this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,true); | ||||||
| 	} else if(this.parseTreeNode.isFunctionDefinition) { | 	} else if(this.parseTreeNode.isFunctionDefinition) { | ||||||
| 		this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isFunctionDefinition: this.parseTreeNode.isFunctionDefinition}); | 		this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isFunctionDefinition: true}); | ||||||
|  | 	} else if(this.parseTreeNode.isProcedureDefinition) { | ||||||
|  | 		this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isProcedureDefinition: true}); | ||||||
| 	} else { | 	} else { | ||||||
| 		this.setVariable(this.setName,this.getValue()); | 		this.setVariable(this.setName,this.getValue()); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -197,8 +197,8 @@ TranscludeWidget.prototype.getTransclusionTarget = function() { | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if(parser) { | 			if(parser) { | ||||||
| 				// Add parameters widget for functions | 				// Add parameters widget for procedures | ||||||
| 				if(srcVariable.isFunctionDefinition) { | 				if(srcVariable.isProcedureDefinition) { | ||||||
| 					parser = { | 					parser = { | ||||||
| 						tree: [ | 						tree: [ | ||||||
| 							{ | 							{ | ||||||
|   | |||||||
| @@ -89,6 +89,7 @@ value: value of the variable | |||||||
| params: array of {name:, default:} for each parameter | params: array of {name:, default:} for each parameter | ||||||
| isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) | isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) | ||||||
| options includes: | options includes: | ||||||
|  | 	isProcedureDefinition: true if the variable is set via a \procedure pragma (and hence should not have variable substitution performed) | ||||||
| 	isFunctionDefinition: true if the variable is set via a \function pragma (and hence should not have variable substitution performed) | 	isFunctionDefinition: true if the variable is set via a \function pragma (and hence should not have variable substitution performed) | ||||||
| */ | */ | ||||||
| Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) { | Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) { | ||||||
| @@ -97,7 +98,8 @@ Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,opti | |||||||
| 		value: value, | 		value: value, | ||||||
| 		params: params, | 		params: params, | ||||||
| 		isMacroDefinition: !!isMacroDefinition, | 		isMacroDefinition: !!isMacroDefinition, | ||||||
| 		isFunctionDefinition: !!options.isFunctionDefinition | 		isFunctionDefinition: !!options.isFunctionDefinition, | ||||||
|  | 		isProcedureDefinition: !!options.isProcedureDefinition | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]] | |||||||
| title: Output | title: Output | ||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| \function <$let> | \procedure <$let> | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <$setmultiplevariables $names="[enlist:raw<paramNames>]" $values="[enlist:raw<paramValues>addprefix[--]addsuffix[--]]"> | <$setmultiplevariables $names="[enlist:raw<paramNames>]" $values="[enlist:raw<paramValues>addprefix[--]addsuffix[--]]"> | ||||||
| <$slot $name="ts-body"/> | <$slot $name="ts-body"/> | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ title: Actions | |||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <!-- Define the <$action-mywidget> widget by defining a transcludable variable with that name --> | <!-- Define the <$action-mywidget> widget by defining a transcludable variable with that name --> | ||||||
| \function <$action-mywidget>(one:'Jaguar') | \procedure <$action-mywidget>(one:'Jaguar') | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <$action-setfield $tiddler="Result" $field="text" $value=<<one>>/> | <$action-setfield $tiddler="Result" $field="text" $value=<<one>>/> | ||||||
| \end | \end | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ title: Output | |||||||
| title: Definition | title: Definition | ||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| \function <$codeblock>(code) | \procedure <$codeblock>(code) | ||||||
| <$genesis $type="codeblock" $remappable="no" code={{{ [<code>addprefix[£]addsuffix[@]] }}}/> | <$genesis $type="codeblock" $remappable="no" code={{{ [<code>addprefix[£]addsuffix[@]] }}}/> | ||||||
| \end | \end | ||||||
| + | + | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ title: TiddlerOne | |||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <!-- Redefine the <$transclude> widget by defining a transcludable variable with that name --> | <!-- Redefine the <$transclude> widget by defining a transcludable variable with that name --> | ||||||
| \function <$transclude>(one:'Jaguar') | \procedure <$transclude>(one:'Jaguar') | ||||||
| \whitespace trim | \whitespace trim | ||||||
| 	<$text text=<<one>>/> | 	<$text text=<<one>>/> | ||||||
| 	<$slot $name="body"> | 	<$slot $name="body"> | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ title: TiddlerOne | |||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <!-- Define the <$mywidget> widget by defining a transcludable variable with that name --> | <!-- Define the <$mywidget> widget by defining a transcludable variable with that name --> | ||||||
| \function <$mywidget>(one:'Jaguar') | \procedure <$mywidget>(one:'Jaguar') | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <$text text=<<one>>/> | <$text text=<<one>>/> | ||||||
| <$slot $name="ts-body"> | <$slot $name="ts-body"> | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ title: TiddlerOne | |||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <!-- Redefine the <$text> widget by defining a transcludable variable with that name --> | <!-- Redefine the <$text> widget by defining a transcludable variable with that name --> | ||||||
| \function <$text>(text:'Jaguar') | \procedure <$text>(text:'Jaguar') | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <$genesis $type="text" $remappable="no" text=<<text>>/> | <$genesis $type="text" $remappable="no" text=<<text>>/> | ||||||
| <$set name="<$text>" value=""> | <$set name="<$text>" value=""> | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ title: TiddlerOne | |||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <!-- Redefine the <$mywidget> widget by defining a transcludable variable with that name --> | <!-- Redefine the <$mywidget> widget by defining a transcludable variable with that name --> | ||||||
| \function <$mywidget>($variable:'Jaguar') | \procedure <$mywidget>($variable:'Jaguar') | ||||||
| \whitespace trim | \whitespace trim | ||||||
| <$text text=<<$variable>>/> | <$text text=<<$variable>>/> | ||||||
| <$slot $name="ts-body"> | <$slot $name="ts-body"> | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ tags: [[$:/tags/wiki-test-spec]] | |||||||
| title: Output | title: Output | ||||||
|  |  | ||||||
| \whitespace trim | \whitespace trim | ||||||
| \function test(one:'Jaguar') | \procedure test(one:'Jaguar') | ||||||
| {<$text text=<<one>>/>} | {<$text text=<<one>>/>} | ||||||
| \end | \end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -119,7 +119,38 @@ describe("WikiText parser tests", function() { | |||||||
| 		); | 		); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	it("should parse function definitions with no parameters", function() { | 	it("should parse procedure definitions with no parameters", function() { | ||||||
|  | 		expect(parse("\\procedure myMacro\nnothing\n\\end\n")).toEqual( | ||||||
|  |  | ||||||
|  | 			[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [  ], params : [  ], isProcedureDefinition : true } ] | ||||||
|  |  | ||||||
|  | 		); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	it("should parse single line procedure definitions with no parameters", function() { | ||||||
|  | 		expect(parse("\\procedure myMacro nothing\n")).toEqual( | ||||||
|  |  | ||||||
|  | 			[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [  ], params : [  ], isProcedureDefinition : true } ] | ||||||
|  |  | ||||||
|  | 		); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	it("should parse procedure definitions with parameters", function() { | ||||||
|  | 		expect(parse("\\procedure myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual( | ||||||
|  |  | ||||||
|  | 			[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [  ], params : [ { name: 'one' }, { name: 'two' }, { name: 'three' }, { name: 'four', default: 'elephant' } ], isProcedureDefinition : true } ] | ||||||
|  |  | ||||||
|  | 		); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	it("should parse procedure definitions", function() { | ||||||
|  | 		expect(parse("\\procedure myMacro(one:'Jaguar')\n<$text text=<<one>>/>\n\\end\n\n")).toEqual( | ||||||
|  |  | ||||||
|  | 			[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : '<$text text=<<one>>/>' } }, children : [  ], params : [ { name: 'one', "default": 'Jaguar' } ], isProcedureDefinition : true } ] | ||||||
|  |  | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  | 	});	it("should parse function definitions with no parameters", function() { | ||||||
| 		expect(parse("\\function myMacro\nnothing\n\\end\n")).toEqual( | 		expect(parse("\\function myMacro\nnothing\n\\end\n")).toEqual( | ||||||
|  |  | ||||||
| 			[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [  ], params : [  ], isFunctionDefinition : true } ] | 			[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [  ], params : [  ], isFunctionDefinition : true } ] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jeremy@jermolene.com
					jeremy@jermolene.com