mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-30 05:19:57 +00:00
Add support for prompts within build scripts
This commit is contained in:
parent
50118dbe13
commit
4a6501778a
@ -16,7 +16,7 @@ The $tw.Commander class is a command interpreter
|
||||
Parse a sequence of commands
|
||||
commandTokens: an array of command string tokens
|
||||
wiki: reference to the wiki store object
|
||||
streams: {output:, error:}, each of which has a write(string) method
|
||||
streams: {output:, input:, error:}
|
||||
callback: a callback invoked as callback(err) where err is null if there was no error
|
||||
*/
|
||||
var Commander = function(commandTokens,callback,wiki,streams) {
|
||||
@ -65,52 +65,95 @@ Commander.prototype.execute = function() {
|
||||
};
|
||||
|
||||
/*
|
||||
Returns the next string token without consuming it, or null if there are none left
|
||||
Returns the next string token without consuming it, or null if there are none left. Callback invoked(err,data)
|
||||
*/
|
||||
Commander.prototype.peekNextToken = function() {
|
||||
Commander.prototype.peekNextToken = function(callback) {
|
||||
var self = this;
|
||||
if(this.nextToken >= this.commandTokens.length) {
|
||||
return null;
|
||||
return callback(null,null);
|
||||
} else {
|
||||
return this.stringifyToken(this.nextToken);
|
||||
return this.stringifyToken(this.nextToken,function(err,data) {
|
||||
if(!err) {
|
||||
// Save the stringified token for next time so that we don't run prompts twice
|
||||
self.commandTokens[self.nextToken] = data;
|
||||
}
|
||||
callback(err,data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Returns and consumes the next string token, or null if there are none left
|
||||
Returns and consumes the next string token, or null if there are none left. Callback invoked(err,data)
|
||||
*/
|
||||
Commander.prototype.getNextToken = function() {
|
||||
Commander.prototype.getNextToken = function(callback) {
|
||||
if(this.nextToken >= this.commandTokens.length) {
|
||||
return null;
|
||||
return callback(null,null);
|
||||
} else {
|
||||
return this.stringifyToken(this.nextToken++);
|
||||
return this.stringifyToken(this.nextToken++,callback);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Returns and consumes the string tokens until the end of the token stream or the first token that starts with "--".
|
||||
Callback invoked(err,tokenArray)
|
||||
*/
|
||||
Commander.prototype.getTokensUntilCommand = function(callback) {
|
||||
var self = this,
|
||||
tokens = [];
|
||||
function processNextToken() {
|
||||
self.peekNextToken(function(err,data) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
if(!data || data.substr(0,2) === "--") {
|
||||
return callback(null,tokens);
|
||||
} else {
|
||||
self.getNextToken(function(err,data) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
tokens.push(data);
|
||||
processNextToken();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
processNextToken();
|
||||
};
|
||||
|
||||
/*
|
||||
Returns a specified stringified token, or null if the index does not exist
|
||||
Returns a specified stringified token, or null if the index does not exist. Callback invoked(err,data)
|
||||
*/
|
||||
Commander.prototype.stringifyToken = function(index) {
|
||||
Commander.prototype.stringifyToken = function(index,callback) {
|
||||
var self = this;
|
||||
if(index >= this.commandTokens.length) {
|
||||
return null;
|
||||
return callback(null,null);
|
||||
} else {
|
||||
var token = this.commandTokens[index];
|
||||
if(typeof token === "string") {
|
||||
return token;
|
||||
return callback(null,token);
|
||||
} else if(typeof token === "object") {
|
||||
switch(token.type) {
|
||||
case "filter":
|
||||
return this.wiki.filterTiddlers(token.text)[0] || "";
|
||||
break;
|
||||
return callback(null,this.wiki.filterTiddlers(token.text)[0] || "");
|
||||
case "wikified":
|
||||
return this.wiki.renderText("text/plain","text/vnd.tiddlywiki",token.text,{
|
||||
return callback(null,this.wiki.renderText("text/plain","text/vnd.tiddlywiki",token.text,{
|
||||
parseAsInline: false,
|
||||
parentWidget: $tw.rootWidget
|
||||
}));
|
||||
case "prompt":
|
||||
$tw.utils.terminalQuestion({
|
||||
promptText: token.prompt || "Please enter a value",
|
||||
defaultResult: token["default"] || "",
|
||||
callback: function(err,userText) {
|
||||
callback(err,userText);
|
||||
},
|
||||
input: self.streams.input,
|
||||
output: self.streams.output,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw "Unknown dynamic command token type: " + token.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,62 +165,64 @@ Execute the next command in the sequence
|
||||
Commander.prototype.executeNextCommand = function() {
|
||||
var self = this;
|
||||
// Get and check the command token
|
||||
var commandName = this.getNextToken();
|
||||
if(!commandName) {
|
||||
return this.callback(null);
|
||||
}
|
||||
if(commandName.substr(0,2) !== "--") {
|
||||
this.callback("Missing command: " + commandName);
|
||||
} else {
|
||||
commandName = commandName.substr(2); // Trim off the --
|
||||
// Accumulate the parameters to the command
|
||||
var params = [],
|
||||
nextToken = this.peekNextToken();
|
||||
while(typeof nextToken === "string" && nextToken.substr(0,2) !== "--") {
|
||||
params.push(this.getNextToken());
|
||||
nextToken = this.peekNextToken();
|
||||
var commandName = this.getNextToken(function(err,commandName) {
|
||||
if(err) {
|
||||
return self.callback(err);
|
||||
}
|
||||
// Get the command info
|
||||
var command = $tw.commands[commandName],
|
||||
c,err;
|
||||
if(!command) {
|
||||
this.callback("Unknown command: " + commandName);
|
||||
if(!commandName) {
|
||||
return self.callback(null);
|
||||
}
|
||||
if(commandName.substr(0,2) !== "--") {
|
||||
return self.callback("Missing command: " + commandName);
|
||||
} else {
|
||||
if(this.verbose) {
|
||||
this.streams.output.write("Executing command: " + commandName + " " + params.join(" ") + "\n");
|
||||
}
|
||||
// Parse named parameters if required
|
||||
if(command.info.namedParameterMode) {
|
||||
params = this.extractNamedParameters(params,command.info.mandatoryParameters);
|
||||
if(typeof params === "string") {
|
||||
return this.callback(params);
|
||||
}
|
||||
}
|
||||
if(command.info.synchronous) {
|
||||
// Synchronous command
|
||||
c = new command.Command(params,this);
|
||||
err = c.execute();
|
||||
commandName = commandName.substr(2); // Trim off the --
|
||||
// Get the parameters to the command
|
||||
self.getTokensUntilCommand(function(err,params) {
|
||||
if(err) {
|
||||
this.callback(err);
|
||||
return self.callback(err);
|
||||
}
|
||||
var command = $tw.commands[commandName],
|
||||
c,err;
|
||||
if(!command) {
|
||||
self.callback("Unknown command: " + commandName);
|
||||
} else {
|
||||
this.executeNextCommand();
|
||||
}
|
||||
} else {
|
||||
// Asynchronous command
|
||||
c = new command.Command(params,this,function(err) {
|
||||
if(err) {
|
||||
self.callback(err);
|
||||
} else {
|
||||
self.executeNextCommand();
|
||||
if(self.verbose) {
|
||||
self.streams.output.write("Executing command: " + commandName + " " + params.join(" ") + "\n");
|
||||
}
|
||||
// Parse named parameters if required
|
||||
if(command.info.namedParameterMode) {
|
||||
params = self.extractNamedParameters(params,command.info.mandatoryParameters);
|
||||
if(typeof params === "string") {
|
||||
return self.callback(params);
|
||||
}
|
||||
}
|
||||
if(command.info.synchronous) {
|
||||
// Synchronous command
|
||||
c = new command.Command(params,self);
|
||||
err = c.execute();
|
||||
if(err) {
|
||||
self.callback(err);
|
||||
} else {
|
||||
self.executeNextCommand();
|
||||
}
|
||||
} else {
|
||||
// Asynchronous command
|
||||
c = new command.Command(params,self,function(err) {
|
||||
if(err) {
|
||||
self.callback(err);
|
||||
} else {
|
||||
self.executeNextCommand();
|
||||
}
|
||||
});
|
||||
err = c.execute();
|
||||
if(err) {
|
||||
self.callback(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
err = c.execute();
|
||||
if(err) {
|
||||
this.callback(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -29,7 +29,11 @@ exports.startup = function(callback) {
|
||||
callback();
|
||||
},
|
||||
$tw.wiki,
|
||||
{output: process.stdout, error: process.stderr}
|
||||
{
|
||||
output: process.stdout,
|
||||
input: process.stdin,
|
||||
error: process.stderr
|
||||
}
|
||||
);
|
||||
commander.execute();
|
||||
};
|
||||
|
@ -21,6 +21,50 @@ exports.log = function(text,colour) {
|
||||
console.log($tw.node ? exports.terminalColour(colour) + text + exports.terminalColour() : text);
|
||||
};
|
||||
|
||||
/*
|
||||
Prompts the user for input and handles the input using a callback function. Options:
|
||||
promptText: Prompt text
|
||||
defaultResult: Default result returned if the user types enter
|
||||
callback: callback invoked (err,usertext)
|
||||
input: optional input stream
|
||||
output: optional output stream
|
||||
*/
|
||||
exports.terminalQuestion = function(options) {
|
||||
var readline = require("readline"),
|
||||
promptText = options.promptText,
|
||||
defaultResult = options.defaultResult,
|
||||
callback = options.callback,
|
||||
inputStream = options.input || process.stdin,
|
||||
outputStream = options.output || process.stdout;
|
||||
var rl = readline.createInterface({
|
||||
input: inputStream,
|
||||
output: outputStream
|
||||
});
|
||||
// Handle errors on the input stream
|
||||
rl.on("error",function(err) {
|
||||
rl.close();
|
||||
callback(err); // Pass the error to the callback
|
||||
});
|
||||
// Prompt user for input
|
||||
var prompt = exports.terminalColourText(promptText,"yellow");
|
||||
if(defaultResult) {
|
||||
prompt += exports.terminalColourText(" (" + defaultResult + ")","blue");
|
||||
}
|
||||
prompt += exports.terminalColourText(": ");
|
||||
rl.question(prompt,function(input) {
|
||||
// Use default value for the empty string
|
||||
if(input === "" && defaultResult) {
|
||||
input = defaultResult;
|
||||
}
|
||||
callback(null,input); // Pass the input to the callback
|
||||
rl.close();
|
||||
});
|
||||
};
|
||||
|
||||
exports.terminalColourText = function(text,colour) {
|
||||
return exports.terminalColour(colour) + text + exports.terminalColour("reset");
|
||||
};
|
||||
|
||||
exports.terminalColour = function(colour) {
|
||||
if(!$tw.browser && $tw.node && process.stdout.isTTY) {
|
||||
if(colour) {
|
||||
@ -36,14 +80,24 @@ exports.terminalColour = function(colour) {
|
||||
};
|
||||
|
||||
exports.terminalColourLookup = {
|
||||
"reset": "0;0",
|
||||
"black": "0;30",
|
||||
"red": "0;31",
|
||||
"green": "0;32",
|
||||
"brown/orange": "0;33",
|
||||
"yellow": "0;33",
|
||||
"brown/orange": "0;33", // Backwards compatbility
|
||||
"blue": "0;34",
|
||||
"purple": "0;35",
|
||||
"cyan": "0;36",
|
||||
"light gray": "0;37"
|
||||
"white": "0;37",
|
||||
"gray": "0;90",
|
||||
"light red": "0;91",
|
||||
"light green": "0;92",
|
||||
"light yellow": "0;93",
|
||||
"light blue": "0;94",
|
||||
"light purple": "0;95",
|
||||
"light cyan": "0;96",
|
||||
"light gray": "0;97"
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -33,6 +33,12 @@
|
||||
{
|
||||
"type": "filter",
|
||||
"text": "[<version>!match[5.3.6-prerelease]then[text/html]else[text/plain]]"
|
||||
},
|
||||
"dinghy",
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Please enter the name of your new wiki",
|
||||
"default": "untitled"
|
||||
}
|
||||
],
|
||||
"index": [
|
||||
|
Loading…
Reference in New Issue
Block a user