public void NoCommand() { var ctx = new Mod.Context(); var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute(""); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Is.Empty); }
public void CommandSingleNumberedParameter() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("cd luna"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(ctx.CurrentItem.ID, Is.EqualTo(_testContent.Axes.GetChild("Luna").ID)); }
/// <summary> /// Evaluates an expression which may contain joining conditions (and, or) /// </summary> /// <param name="context">The current Revolver context</param> /// <param name="exp">The expression to evaluate</param> /// <returns>The outcome of th expression</returns> public static bool EvaluateExpression(Context context, string exp) { // Break the expression around the joining condition keywords bool res = false; string[] expElms = exp.Trim().Replace(" ", " ").Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); int startInd = 0; string op = string.Empty; for (int i = 0; i < expElms.Length; i++) { if (expElms[i] == "and" || expElms[i] == "or" || i == expElms.Length - 1) { string[] currentPart; if (i == expElms.Length - 1) { currentPart = new string[(i + 1) - startInd]; Array.Copy(expElms, startInd, currentPart, 0, (i + 1) - startInd); } else { currentPart = new string[i - startInd]; Array.Copy(expElms, startInd, currentPart, 0, i - startInd); } bool currentRes = EvaluateSingleExpression(context, string.Join(" ", currentPart)); if (op.Length > 0) { switch (op) { case "and": res &= currentRes; break; case "or": res |= currentRes; break; default: throw new ExpressionException("Invalid operator: " + op); } } else res = currentRes; if (expElms.Length > i + 1) op = expElms[i]; if (expElms.Length > i + 2) startInd = i + 1; } } return res; }
/// <summary> /// Create a new instance of the ContextSwitcher /// </summary> /// <param name="context">The context to switch. ContextSwitcher stores the initial context.</param> /// <param name="path">The path to switc to</param> public ContextSwitcher(Context context, string path) { if (!string.IsNullOrEmpty(path)) { _active = true; StoreContext(context); _result = context.SetContext(path); } else _result = new CommandResult(CommandStatus.Success, "ContextSwitcher not active"); }
public void CommandMultipleNumberedParameters() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("find pwd luna"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Contains.Substring("Carme")); Assert.That(result.Message, Contains.Substring("Ganymede")); Assert.That(result.Message, Contains.Substring("Metis")); }
public void SetContext_Relative() { var context = new Revolver.Core.Context(); context.CurrentItem = _testTreeRoot; var result = context.SetContext("Sycorax"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(context.CurrentDatabase.Name, Is.EqualTo("web")); Assert.That(context.CurrentItem.ID, Is.EqualTo(_testTreeRoot.Axes.GetChild("Sycorax").ID)); Assert.That(context.CurrentLanguage.Name, Is.EqualTo("en")); }
public void CommandSingleNamedParameter() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("ls -r os"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Is.Not.Contains("Luna")); Assert.That(result.Message, Contains.Substring("Deimos")); Assert.That(result.Message, Contains.Substring("phobos")); Assert.That(result.Message, Contains.Substring("Adrastea Phobos")); }
/// <summary> /// Evaluates the tokens in a prompt string /// </summary> /// <param name="context">The context to use during evaluation</param> /// <param name="prompt">The prompt to evaluate</param> /// <returns>The prompt</returns> public static string EvaluatePrompt(Context context, string prompt) { string toRet = prompt; if (context.CurrentItem != null) { // Path / DB tokens toRet = toRet.Replace("%path%", context.CurrentItem.Paths.FullPath); toRet = toRet.Replace("%itemname%", context.CurrentItem.Name); toRet = toRet.Replace("%ver%", context.CurrentItem.Version.Number.ToString()); } else { toRet = toRet.Replace("%path%", "<undefined>"); toRet = toRet.Replace("%itemname%", "<undefined>"); toRet = toRet.Replace("%ver%", "<undefined>"); } if (context.CurrentDatabase != null) toRet = toRet.Replace("%db%", context.CurrentDatabase.Name); else toRet = toRet.Replace("%db%", "<undefined>"); if (context.CurrentLanguage != null) { toRet = toRet.Replace("%lang%", context.CurrentLanguage.Title); toRet = toRet.Replace("%langcode%", context.CurrentLanguage.Name); } else { toRet = toRet.Replace("%lang%", "<undefined>"); toRet = toRet.Replace("%langcode%", "<undefined>"); } // DateTime tokens DateTime dt = DateTime.Now; toRet = toRet.Replace("%date%", dt.ToShortDateString()); toRet = toRet.Replace("%time%", dt.ToShortTimeString()); // Environment variables toRet = Parser.PerformSubstitution(context, toRet); return toRet; }
/// <summary> /// Evaulate the path string in relation to the current item /// </summary> /// <param name="context">The Revolver context to evaluate the path against</param> /// <param name="path">The path to evaulate. Can either be absolute or relative</param> /// <returns>The full sitecore path to the target item</returns> public static string EvaluatePath(Context context, string path) { if (ID.IsID(path)) return path; string workingPath = string.Empty; if (!path.StartsWith("/")) workingPath = context.CurrentItem.Paths.FullPath + "/" + path; else workingPath = path; // Strip any language and version tags if (workingPath.IndexOf(':') >= 0) workingPath = workingPath.Substring(0, workingPath.IndexOf(':')); // Make relative paths absolute string[] parts = workingPath.Split('/'); StringCollection targetParts = new StringCollection(); targetParts.AddRange(parts); while (targetParts.Contains("..")) { int ind = targetParts.IndexOf(".."); targetParts.RemoveAt(ind); if (ind > 0) { targetParts.RemoveAt(ind - 1); } } if (targetParts[targetParts.Count - 1] == ".") targetParts.RemoveAt(targetParts.Count - 1); // Remove empty elements while (targetParts.Contains("")) { targetParts.RemoveAt(targetParts.IndexOf("")); } string[] toRet = new string[targetParts.Count]; targetParts.CopyTo(toRet, 0); return "/" + string.Join("/", toRet); }
public void MultipleSubCommands() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("replace < (ga -a name) B < (echo c) -c"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Is.EqualTo("cebhionn")); }
public void CommandChaining() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("ga -a name > replace $~$ B c -c"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success), result.Message); Assert.That(result.Message, Is.EqualTo("cebhionn")); }
/// <summary> /// Evaluate a single expression /// </summary> /// <param name="item">The current item</param> /// <param name="exp">The expression to evaluate</param> /// <returns>The outcome of the expression</returns> public static bool EvaluateSingleExpression(Context context, string exp) { // Clean the expression exp = exp.Trim(); // substitute tokens exp = Parser.PerformSubstitution(context, exp); // Parse elements string[] elms = Parser.ParseFirstLevelGroups(exp, Constants.SubcommandEnter, Constants.SubcommandExit); // Validate the expression if (elms.Length != 1 && elms.Length != 2 && elms.Length != 3 && elms.Length != 5 && elms.Length != 7) throw new ExpressionException("Malformed expression"); // a single element in the expression should be parsable true or false if (elms.Length == 1) { var value = false; if (Parser.TryParseBoolean(elms[0], out value)) return value; else throw new ExpressionException("Could not parse boolean value '" + elms[0] + "'"); } // 2 elements means a function if (elms.Length == 2) { switch (elms[0]) { case "isempty": return string.IsNullOrEmpty(elms[1]); case "not": return !EvaluateExpression(context, elms[1]); case "isbound": return context.CommandHandler.CoreCommands.ContainsKey(elms[1]) || context.CommandHandler.CustomCommands.ContainsKey(elms[1]); default: throw new ExpressionException("Unknown function " + elms[0]); } } string op = elms[1]; if ((op != "<") && (op != ">") && (op != "=") && (op != "!=") && (op != "<=") && (op != ">=") && (op != "[") && (op != "]") && (op != "?") && (op != "!?")) throw new ExpressionException("Invalid operator " + op); // substitute fields and attributes and pull out casting operator and flags string type = "string"; bool ignoreCase = false; bool ignoreDecimal = false; bool round = false; bool ceil = false; bool floor = false; for (int i = 0; i < elms.Length; i++) { if (elms[i].StartsWith("@@")) { var inspector = new ItemInspector(context.CurrentItem); var attr = inspector.GetItemAttribute(elms[i]); if (attr == null) throw new ExpressionException("Unknown attribute " + elms[i]); elms[i] = attr; } else if (elms[i].StartsWith("@")) { elms[i] = context.CurrentItem[elms[i].Substring(1)]; } else { if (elms[i] == "as") { if (elms.Length >= i + 2) type = elms[i + 1]; else throw new ExpressionException("Missing the cast type"); } else if (elms[i] == "with") { if (elms.Length < i + 2) throw new ExpressionException("Missing flags"); switch (elms[i + 1]) { case "ignorecase": ignoreCase = true; break; case "ignoredecimal": ignoreDecimal = true; break; case "round": round = true; break; case "ceiling": ceil = true; break; case "floor": floor = true; break; default: throw new ExpressionException("Unknown flag " + elms[i + 1]); } } } } string val1 = elms[0]; string val2 = elms[2]; // Do we need to convert the strings? switch (type) { case "string": if (ignoreCase) { val1 = val1.ToLower(); val2 = val2.ToLower(); } // Now do the comparison switch (op) { case "=": return val1 == val2; case "<": return string.Compare(val1, val2) < 0; case ">": return string.Compare(val1, val2) > 0; case "!=": return val1 != val2; case "<=": return string.Compare(val1, val2) <= 0; case ">=": return string.Compare(val1, val2) >= 0; case "[": return val1.StartsWith(val2); case "]": return val1.EndsWith(val2); case "?": return val1.Contains(val2); case "!?": return !val1.Contains(val2); } break; case "number": if (val1.Length == 0 || val2.Length == 0) return false; double a = 0; double b = 0; if (!double.TryParse(val1, out a)) throw new ExpressionException(string.Format("{0} is not a number", val1)); if (!double.TryParse(val2, out b)) throw new ExpressionException(string.Format("{0} is not a number", val2)); if (ignoreDecimal) { a = Math.Truncate(a); b = Math.Truncate(b); } if (ceil) { a = Math.Ceiling(a); b = Math.Ceiling(b); } if (floor) { a = Math.Floor(a); b = Math.Floor(b); } if (round) { a = Math.Round(a); b = Math.Round(b); } // Now do the comparison switch (op) { case "=": return a == b; case "<": return a < b; case ">": return a > b; case "!=": return a != b; case "<=": return a <= b; case ">=": return a >= b; case "[": return a.ToString().StartsWith(b.ToString()); case "]": return a.ToString().EndsWith(b.ToString()); case "?": return a.ToString().Contains(b.ToString()); case "!?": return !a.ToString().Contains(b.ToString()); } break; case "date": if (val1.Length == 0 || val2.Length == 0) return false; DateTime aa; DateTime bb; DateTime defaultPassthrough = DateTime.MinValue.AddSeconds(7); var culture = Sitecore.Context.Culture; if (culture.IsNeutralCulture) culture = Thread.CurrentThread.CurrentCulture; aa = Sitecore.DateUtil.ParseDateTime(val1, defaultPassthrough, culture); if (aa == defaultPassthrough) throw new ExpressionException(string.Format("{0} is not a date", val1)); bb = Sitecore.DateUtil.ParseDateTime(val2, defaultPassthrough, culture); if (bb == defaultPassthrough) throw new ExpressionException(string.Format("{0} is not a date", val2)); // Now do the comparison switch (op) { case "=": return aa == bb; case "<": return aa < bb; case ">": return aa > bb; case "!=": return aa != bb; case "<=": return aa <= bb; case ">=": return aa >= bb; } break; } // Something went wrong if we get to here return false; }
public void MultipleCommandChaining() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("ga -a name > replace $~$ B c -c > split -s h $~$ (echo $current$)"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success), result.Message); Assert.That(result.Message, Contains.Substring("ceb")); Assert.That(result.Message, Contains.Substring("ionn")); }
public void SetContext_NumberedChild() { var startItem = _testTreeRoot.Axes.SelectSingleItem("Umbriel"); var context = new Revolver.Core.Context(); context.CurrentItem = startItem; var expectedItem = _testTreeRoot.Axes.SelectSingleItem("Umbriel/*[@title='Skoll 1']"); var result = context.SetContext("skoll[1]"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(context.CurrentDatabase.Name, Is.EqualTo("web")); Assert.That(context.CurrentItem.ID, Is.EqualTo(expectedItem.ID)); Assert.That(context.CurrentLanguage.Name, Is.EqualTo("en")); }
public void AddAliasWithParameters() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.AddCommandAlias("aa", "ls", "-a", "-d"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); // Verify the alias was added var exResult = handler.Execute("aa"); Assert.That(exResult.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(exResult.Message, Contains.Substring(" phobos\r\n+ Luna\r\n Deimos\r\n Adrastea Phobos")); }
public void SetContext_BadVersionNumber() { var context = new Revolver.Core.Context(); context.CurrentItem = _testTreeRoot; var item = _testTreeRoot.Axes.GetChild("Sycorax"); var result = context.SetContext(item.Paths.FullPath + "::&", null); Assert.That(result.Status, Is.EqualTo(CommandStatus.Failure)); Assert.That(context.CurrentDatabase.Name, Is.EqualTo("web")); Assert.That(context.CurrentItem.ID, Is.EqualTo(_testTreeRoot.ID)); Assert.That(context.CurrentLanguage.Name, Is.EqualTo("en")); }
public static string EvaluatePrompt(Context context, string prompt) { return Prompt.EvaluatePrompt(context, prompt); }
public static string PerformSubstitution(Context context, string input, bool autowrap) { return Parser.PerformSubstitution(context, input); }
public void CommandFlagParameter() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("ls -a -d"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Is.EqualTo(" phobos\r\n+ Luna\r\n Deimos\r\n Adrastea Phobos")); }
public static bool EvaluateSingleExpression(Context context, string exp) { return ExpressionParser.EvaluateSingleExpression(context, exp); }
/// <summary> /// Substitute tokens in the input string such as environment variables /// </summary> /// <param name="context">The context to use during substitution</param> /// <param name="input">The input to perform substitution on</param> /// <returns>A string with tokens replaced</returns> public static string PerformSubstitution(Context context, string input) { // Substitute environment variables foreach (string key in context.EnvironmentVariables.Keys) { if (input.Contains(Constants.TokenIndicator + key + Constants.TokenIndicator)) input = input.Replace(Constants.TokenIndicator + key + Constants.TokenIndicator, context.EnvironmentVariables[key]); } // Replace escaped tokens input = input.Replace(Constants.EscapeCharacter + Constants.TokenIndicator, Constants.TokenIndicator); return input; }
public void CommandMixedParameterTypes() { var deimosId = _testContent.Axes.GetChild("Deimos").ID.ToString(); var phobosId = _testContent.Axes.GetChild("phobos").ID.ToString(); var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute(string.Format("find -i {0}|{1} -a name phobos -ns (ga -a id)", deimosId, phobosId)); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Is.EqualTo(phobosId)); }
public void EscapedParameterDelimiter() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); var result = handler.Execute("echo lorem \\(ipsum dolor\\)"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Success)); Assert.That(result.Message, Is.EqualTo("lorem (ipsum dolor)")); }
/// <summary> /// Stores the given context internally /// </summary> /// <param name="context">The context to store</param> private void StoreContext(Context context) { _context = context; _prevItem = context.CurrentItem; _prevLanguage = _context.CurrentLanguage; }
public void SetContext_NumberedChildTooHigh() { var startItem = _testTreeRoot.Axes.SelectSingleItem("Umbriel"); var context = new Revolver.Core.Context(); context.CurrentItem = startItem; var result = context.SetContext("skoll[5]"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Failure)); Assert.That(context.CurrentDatabase.Name, Is.EqualTo("web")); Assert.That(context.CurrentItem.ID, Is.EqualTo(startItem.ID)); Assert.That(context.CurrentLanguage.Name, Is.EqualTo("en")); }
public static string EvaluatePath(Context context, string path) { return PathParser.EvaluatePath(context, path); }
public void AddAliasSameAsAlias() { var ctx = new Mod.Context(); ctx.CurrentItem = _testContent; var handler = new Mod.CommandHandler(ctx, new TextOutputFormatter()); handler.AddCommandAlias("aa", "ls"); var result = handler.AddCommandAlias("aa", "ga"); Assert.That(result.Status, Is.EqualTo(CommandStatus.Failure)); }
public static CommandResult SetContext(Context context, string path, string dbName = null, Language language = null, int? versionNumber = null) { return context.SetContext(path, dbName, language, versionNumber); }
/// <summary> /// Create a new instance of this class /// </summary> /// <param name="context">The Revolver vontext to operate on</param> /// <param name="formatter">The formatter to use</param> public CommandHandler(Context context, ICommandFormatter formatter) { _commands = new Dictionary<string, Type>(); _custcommands = new Dictionary<string, Type>(); _commandAliases = new Dictionary<string, CommandArgs>(); Context = context; _formatter = formatter; ScriptLocator = new ScriptLocator.ScriptLocator(); CommandInspector.FindAllCommands(_commands); }