diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs new file mode 100644 index 0000000000..0c314b9752 --- /dev/null +++ b/OpenSim/Framework/Console/CommandConsole.cs @@ -0,0 +1,467 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Text; +using System.Threading; +using log4net; + +namespace OpenSim.Framework.Console +{ + public delegate void CommandDelegate(string module, string[] cmd); + + public class Commands + { + /// + /// Encapsulates a command that can be invoked from the console + /// + private class CommandInfo + { + /// + /// The module from which this command comes + /// + public string module; + + /// + /// Whether the module is shared + /// + public bool shared; + + /// + /// Very short BNF description + /// + public string help_text; + + /// + /// Longer one line help text + /// + public string long_help; + + /// + /// Full descriptive help for this command + /// + public string descriptive_help; + + /// + /// The method to invoke for this command + /// + public List fn; + } + + /// + /// Commands organized by keyword in a tree + /// + private Dictionary tree = + new Dictionary(); + + /// + /// Get help for the given help string + /// + /// Parsed parts of the help string. If empty then general help is returned. + /// + public List GetHelp(string[] cmd) + { + List help = new List(); + List helpParts = new List(cmd); + + // Remove initial help keyword + helpParts.RemoveAt(0); + + // General help + if (helpParts.Count == 0) + { + help.AddRange(CollectHelp(tree)); + help.Sort(); + } + else + { + help.AddRange(CollectHelp(helpParts)); + } + + return help; + } + + /// + /// See if we can find the requested command in order to display longer help + /// + /// + /// + private List CollectHelp(List helpParts) + { + string originalHelpRequest = string.Join(" ", helpParts.ToArray()); + List help = new List(); + + Dictionary dict = tree; + while (helpParts.Count > 0) + { + string helpPart = helpParts[0]; + + if (!dict.ContainsKey(helpPart)) + break; + + //m_log.Debug("Found {0}", helpParts[0]); + + if (dict[helpPart] is Dictionary) + dict = (Dictionary)dict[helpPart]; + + helpParts.RemoveAt(0); + } + + // There was a command for the given help string + if (dict.ContainsKey(String.Empty)) + { + CommandInfo commandInfo = (CommandInfo)dict[String.Empty]; + help.Add(commandInfo.help_text); + help.Add(commandInfo.long_help); + help.Add(commandInfo.descriptive_help); + } + else + { + help.Add(string.Format("No help is available for {0}", originalHelpRequest)); + } + + return help; + } + + private List CollectHelp(Dictionary dict) + { + List result = new List(); + + foreach (KeyValuePair kvp in dict) + { + if (kvp.Value is Dictionary) + { + result.AddRange(CollectHelp((Dictionary)kvp.Value)); + } + else + { + if (((CommandInfo)kvp.Value).long_help != String.Empty) + result.Add(((CommandInfo)kvp.Value).help_text+" - "+ + ((CommandInfo)kvp.Value).long_help); + } + } + return result; + } + + /// + /// Add a command to those which can be invoked from the console. + /// + /// + /// + /// + /// + /// + public void AddCommand(string module, bool shared, string command, + string help, string longhelp, CommandDelegate fn) + { + AddCommand(module, shared, command, help, longhelp, + String.Empty, fn); + } + + /// + /// Add a command to those which can be invoked from the console. + /// + /// + /// + /// + /// + /// + /// + public void AddCommand(string module, bool shared, string command, + string help, string longhelp, string descriptivehelp, + CommandDelegate fn) + { + string[] parts = Parser.Parse(command); + + Dictionary current = tree; + + foreach (string s in parts) + { + if (current.ContainsKey(s)) + { + if (current[s] is Dictionary) + { + current = (Dictionary)current[s]; + } + else + return; + } + else + { + current[s] = new Dictionary(); + current = (Dictionary)current[s]; + } + } + + CommandInfo info; + + if (current.ContainsKey(String.Empty)) + { + info = (CommandInfo)current[String.Empty]; + if (!info.shared && !info.fn.Contains(fn)) + info.fn.Add(fn); + + return; + } + + info = new CommandInfo(); + info.module = module; + info.shared = shared; + info.help_text = help; + info.long_help = longhelp; + info.descriptive_help = descriptivehelp; + info.fn = new List(); + info.fn.Add(fn); + current[String.Empty] = info; + } + + public string[] FindNextOption(string[] cmd, bool term) + { + Dictionary current = tree; + + int remaining = cmd.Length; + + foreach (string s in cmd) + { + remaining--; + + List found = new List(); + + foreach (string opt in current.Keys) + { + if (remaining > 0 && opt == s) + { + found.Clear(); + found.Add(opt); + break; + } + if (opt.StartsWith(s)) + { + found.Add(opt); + } + } + + if (found.Count == 1 && (remaining != 0 || term)) + { + current = (Dictionary)current[found[0]]; + } + else if (found.Count > 0) + { + return found.ToArray(); + } + else + { + break; +// return new string[] {""}; + } + } + + if (current.Count > 1) + { + List choices = new List(); + + bool addcr = false; + foreach (string s in current.Keys) + { + if (s == String.Empty) + { + CommandInfo ci = (CommandInfo)current[String.Empty]; + if (ci.fn.Count != 0) + addcr = true; + } + else + choices.Add(s); + } + if (addcr) + choices.Add(""); + return choices.ToArray(); + } + + if (current.ContainsKey(String.Empty)) + return new string[] { "Command help: "+((CommandInfo)current[String.Empty]).help_text}; + + return new string[] { new List(current.Keys)[0] }; + } + + public string[] Resolve(string[] cmd) + { + string[] result = cmd; + int index = -1; + + Dictionary current = tree; + + foreach (string s in cmd) + { + index++; + + List found = new List(); + + foreach (string opt in current.Keys) + { + if (opt == s) + { + found.Clear(); + found.Add(opt); + break; + } + if (opt.StartsWith(s)) + { + found.Add(opt); + } + } + + if (found.Count == 1) + { + result[index] = found[0]; + current = (Dictionary)current[found[0]]; + } + else if (found.Count > 0) + { + return new string[0]; + } + else + { + break; + } + } + + if (current.ContainsKey(String.Empty)) + { + CommandInfo ci = (CommandInfo)current[String.Empty]; + if (ci.fn.Count == 0) + return new string[0]; + foreach (CommandDelegate fn in ci.fn) + { + if (fn != null) + fn(ci.module, result); + else + return new string[0]; + } + return result; + } + + return new string[0]; + } + } + + public class Parser + { + public static string[] Parse(string text) + { + List result = new List(); + + int index; + + string[] unquoted = text.Split(new char[] {'"'}); + + for (index = 0 ; index < unquoted.Length ; index++) + { + if (index % 2 == 0) + { + string[] words = unquoted[index].Split(new char[] {' '}); + foreach (string w in words) + { + if (w != String.Empty) + result.Add(w); + } + } + else + { + result.Add(unquoted[index]); + } + } + + return result.ToArray(); + } + } + + // A console that processes commands internally + // + public class CommandConsole : ConsoleBase + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public Commands Commands = new Commands(); + + public CommandConsole(string defaultPrompt) : base(defaultPrompt) + { + Commands.AddCommand("console", false, "help", "help []", + "Get general command list or more detailed help on a specific command", Help); + } + + private void Help(string module, string[] cmd) + { + List help = Commands.GetHelp(cmd); + + foreach (string s in help) + Output(s); + } + + public void Prompt() + { + string line = ReadLine(m_defaultPrompt, true, true); + + if (line != String.Empty) + { + m_log.Info("Invalid command"); + } + } + + public void RunCommand(string cmd) + { + string[] parts = Parser.Parse(cmd); + Commands.Resolve(parts); + } + + public override string ReadLine(string p, bool isCommand, bool e) + { + System.Console.Write("{0}", prompt); + string cmdinput = System.Console.ReadLine(); + + if (isCommand) + { + string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); + + if (cmd.Length != 0) + { + int i; + + for (i=0 ; i < cmd.Length ; i++) + { + if (cmd[i].Contains(" ")) + cmd[i] = "\"" + cmd[i] + "\""; + } + return String.Empty; + } + } + return cmdinput; + } + } +} diff --git a/OpenSim/Framework/Console/ConsoleBase.cs b/OpenSim/Framework/Console/ConsoleBase.cs index fda2037e11..30493fca37 100644 --- a/OpenSim/Framework/Console/ConsoleBase.cs +++ b/OpenSim/Framework/Console/ConsoleBase.cs @@ -35,388 +35,11 @@ using log4net; namespace OpenSim.Framework.Console { - public delegate void CommandDelegate(string module, string[] cmd); - - public class Commands - { - /// - /// Encapsulates a command that can be invoked from the console - /// - private class CommandInfo - { - /// - /// The module from which this command comes - /// - public string module; - - /// - /// Whether the module is shared - /// - public bool shared; - - /// - /// Very short BNF description - /// - public string help_text; - - /// - /// Longer one line help text - /// - public string long_help; - - /// - /// Full descriptive help for this command - /// - public string descriptive_help; - - /// - /// The method to invoke for this command - /// - public List fn; - } - - /// - /// Commands organized by keyword in a tree - /// - private Dictionary tree = - new Dictionary(); - - /// - /// Get help for the given help string - /// - /// Parsed parts of the help string. If empty then general help is returned. - /// - public List GetHelp(string[] cmd) - { - List help = new List(); - List helpParts = new List(cmd); - - // Remove initial help keyword - helpParts.RemoveAt(0); - - // General help - if (helpParts.Count == 0) - { - help.AddRange(CollectHelp(tree)); - help.Sort(); - } - else - { - help.AddRange(CollectHelp(helpParts)); - } - - return help; - } - - /// - /// See if we can find the requested command in order to display longer help - /// - /// - /// - private List CollectHelp(List helpParts) - { - string originalHelpRequest = string.Join(" ", helpParts.ToArray()); - List help = new List(); - - Dictionary dict = tree; - while (helpParts.Count > 0) - { - string helpPart = helpParts[0]; - - if (!dict.ContainsKey(helpPart)) - break; - - //m_log.Debug("Found {0}", helpParts[0]); - - if (dict[helpPart] is Dictionary) - dict = (Dictionary)dict[helpPart]; - - helpParts.RemoveAt(0); - } - - // There was a command for the given help string - if (dict.ContainsKey(String.Empty)) - { - CommandInfo commandInfo = (CommandInfo)dict[String.Empty]; - help.Add(commandInfo.help_text); - help.Add(commandInfo.long_help); - help.Add(commandInfo.descriptive_help); - } - else - { - help.Add(string.Format("No help is available for {0}", originalHelpRequest)); - } - - return help; - } - - private List CollectHelp(Dictionary dict) - { - List result = new List(); - - foreach (KeyValuePair kvp in dict) - { - if (kvp.Value is Dictionary) - { - result.AddRange(CollectHelp((Dictionary)kvp.Value)); - } - else - { - if (((CommandInfo)kvp.Value).long_help != String.Empty) - result.Add(((CommandInfo)kvp.Value).help_text+" - "+ - ((CommandInfo)kvp.Value).long_help); - } - } - return result; - } - - /// - /// Add a command to those which can be invoked from the console. - /// - /// - /// - /// - /// - /// - public void AddCommand(string module, bool shared, string command, - string help, string longhelp, CommandDelegate fn) - { - AddCommand(module, shared, command, help, longhelp, - String.Empty, fn); - } - - /// - /// Add a command to those which can be invoked from the console. - /// - /// - /// - /// - /// - /// - /// - public void AddCommand(string module, bool shared, string command, - string help, string longhelp, string descriptivehelp, - CommandDelegate fn) - { - string[] parts = Parser.Parse(command); - - Dictionary current = tree; - - foreach (string s in parts) - { - if (current.ContainsKey(s)) - { - if (current[s] is Dictionary) - { - current = (Dictionary)current[s]; - } - else - return; - } - else - { - current[s] = new Dictionary(); - current = (Dictionary)current[s]; - } - } - - CommandInfo info; - - if (current.ContainsKey(String.Empty)) - { - info = (CommandInfo)current[String.Empty]; - if (!info.shared && !info.fn.Contains(fn)) - info.fn.Add(fn); - - return; - } - - info = new CommandInfo(); - info.module = module; - info.shared = shared; - info.help_text = help; - info.long_help = longhelp; - info.descriptive_help = descriptivehelp; - info.fn = new List(); - info.fn.Add(fn); - current[String.Empty] = info; - } - - public string[] FindNextOption(string[] cmd, bool term) - { - Dictionary current = tree; - - int remaining = cmd.Length; - - foreach (string s in cmd) - { - remaining--; - - List found = new List(); - - foreach (string opt in current.Keys) - { - if (remaining > 0 && opt == s) - { - found.Clear(); - found.Add(opt); - break; - } - if (opt.StartsWith(s)) - { - found.Add(opt); - } - } - - if (found.Count == 1 && (remaining != 0 || term)) - { - current = (Dictionary)current[found[0]]; - } - else if (found.Count > 0) - { - return found.ToArray(); - } - else - { - break; -// return new string[] {""}; - } - } - - if (current.Count > 1) - { - List choices = new List(); - - bool addcr = false; - foreach (string s in current.Keys) - { - if (s == String.Empty) - { - CommandInfo ci = (CommandInfo)current[String.Empty]; - if (ci.fn.Count != 0) - addcr = true; - } - else - choices.Add(s); - } - if (addcr) - choices.Add(""); - return choices.ToArray(); - } - - if (current.ContainsKey(String.Empty)) - return new string[] { "Command help: "+((CommandInfo)current[String.Empty]).help_text}; - - return new string[] { new List(current.Keys)[0] }; - } - - public string[] Resolve(string[] cmd) - { - string[] result = cmd; - int index = -1; - - Dictionary current = tree; - - foreach (string s in cmd) - { - index++; - - List found = new List(); - - foreach (string opt in current.Keys) - { - if (opt == s) - { - found.Clear(); - found.Add(opt); - break; - } - if (opt.StartsWith(s)) - { - found.Add(opt); - } - } - - if (found.Count == 1) - { - result[index] = found[0]; - current = (Dictionary)current[found[0]]; - } - else if (found.Count > 0) - { - return new string[0]; - } - else - { - break; - } - } - - if (current.ContainsKey(String.Empty)) - { - CommandInfo ci = (CommandInfo)current[String.Empty]; - if (ci.fn.Count == 0) - return new string[0]; - foreach (CommandDelegate fn in ci.fn) - { - if (fn != null) - fn(ci.module, result); - else - return new string[0]; - } - return result; - } - - return new string[0]; - } - } - - public class Parser - { - public static string[] Parse(string text) - { - List result = new List(); - - int index; - - string[] unquoted = text.Split(new char[] {'"'}); - - for (index = 0 ; index < unquoted.Length ; index++) - { - if (index % 2 == 0) - { - string[] words = unquoted[index].Split(new char[] {' '}); - foreach (string w in words) - { - if (w != String.Empty) - result.Add(w); - } - } - else - { - result.Add(unquoted[index]); - } - } - - return result.ToArray(); - } - } - public class ConsoleBase { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private readonly object m_syncRoot = new object(); - - private int y = -1; - private int cp = 0; - private int h = 1; - private string prompt = "# "; - private StringBuilder cmdline = new StringBuilder(); - public Commands Commands = new Commands(); - private bool echo = true; - private List history = new List(); - private bool gui = false; + protected string prompt = "# "; public object ConsoleScene = null; @@ -433,22 +56,6 @@ namespace OpenSim.Framework.Console public ConsoleBase(string defaultPrompt) { DefaultPrompt = defaultPrompt; - - Commands.AddCommand("console", false, "help", "help []", - "Get general command list or more detailed help on a specific command", Help); - } - - public void SetGuiMode(bool mode) - { - gui = mode; - } - - private void AddToHistory(string text) - { - while (history.Count >= 100) - history.RemoveAt(0); - - history.Add(text); } /// @@ -458,10 +65,9 @@ namespace OpenSim.Framework.Console /// /// arbitrary string for input /// an ansii color - private static ConsoleColor DeriveColor(string input) + protected virtual ConsoleColor DeriveColor(string input) { - int colIdx = (input.ToUpper().GetHashCode() % 6) + 9; - return (ConsoleColor) colIdx; + return ConsoleColor.White; } /// @@ -559,280 +165,58 @@ namespace OpenSim.Framework.Console WriteNewLine(DeriveColor(sender), sender, ConsoleColor.Gray, format, args); } - private int SetCursorTop(int top) + protected virtual void WriteNewLine(ConsoleColor senderColor, string sender, ConsoleColor color, string format, params object[] args) { - if (top >= 0 && top < System.Console.BufferHeight) - { - System.Console.CursorTop = top; - return top; - } - else - { - return System.Console.CursorTop; - } + WritePrefixLine(senderColor, sender); + WriteConsoleLine(color, format, args); } - private int SetCursorLeft(int left) + protected virtual void WriteNewLine(ConsoleColor color, string format, params object[] args) { - if (left >= 0 && left < System.Console.BufferWidth) - { - System.Console.CursorLeft = left; - return left; - } - else - { - return System.Console.CursorLeft; - } + WriteConsoleLine(color, format, args); } - private void WriteNewLine(ConsoleColor senderColor, string sender, ConsoleColor color, string format, params object[] args) - { - lock (cmdline) - { - if (y != -1) - { - y=SetCursorTop(y); - System.Console.CursorLeft = 0; - - int count = cmdline.Length; - - System.Console.Write(" "); - while (count-- > 0) - System.Console.Write(" "); - - y=SetCursorTop(y); - System.Console.CursorLeft = 0; - } - WritePrefixLine(senderColor, sender); - WriteConsoleLine(color, format, args); - if (y != -1) - y = System.Console.CursorTop; - } - } - - private void WriteNewLine(ConsoleColor color, string format, params object[] args) - { - lock (cmdline) - { - if (y != -1) - { - y=SetCursorTop(y); - System.Console.CursorLeft = 0; - - int count = cmdline.Length; - - System.Console.Write(" "); - while (count-- > 0) - System.Console.Write(" "); - - y=SetCursorTop(y); - System.Console.CursorLeft = 0; - } - WriteConsoleLine(color, format, args); - if (y != -1) - y = System.Console.CursorTop; - } - } - - private void WriteConsoleLine(ConsoleColor color, string format, params object[] args) + protected virtual void WriteConsoleLine(ConsoleColor color, string format, params object[] args) { try { - lock (m_syncRoot) - { - try - { - if (color != ConsoleColor.White) - System.Console.ForegroundColor = color; - - System.Console.WriteLine(format, args); - System.Console.ResetColor(); - } - catch (ArgumentNullException) - { - // Some older systems dont support coloured text. - System.Console.WriteLine(format, args); - } - catch (FormatException) - { - System.Console.WriteLine(args); - } - } + System.Console.WriteLine(format, args); } catch (ObjectDisposedException) { } } - private void WritePrefixLine(ConsoleColor color, string sender) + protected virtual void WritePrefixLine(ConsoleColor color, string sender) { try { - lock (m_syncRoot) - { - sender = sender.ToUpper(); + sender = sender.ToUpper(); - System.Console.WriteLine("[" + sender + "] "); + System.Console.WriteLine("[" + sender + "] "); - System.Console.Write("["); + System.Console.Write("["); - try - { - System.Console.ForegroundColor = color; - System.Console.Write(sender); - System.Console.ResetColor(); - } - catch (ArgumentNullException) - { - // Some older systems dont support coloured text. - System.Console.WriteLine(sender); - } + System.Console.Write(sender); - System.Console.Write("] \t"); - } + System.Console.Write("] \t"); } catch (ObjectDisposedException) { } } - private void Help(string module, string[] cmd) + public virtual void LockOutput() { - List help = Commands.GetHelp(cmd); - - foreach (string s in help) - Output(s); } - private void Show() + public virtual void UnlockOutput() { - lock (cmdline) - { - if (y == -1 || System.Console.BufferWidth == 0) - return; - - int xc = prompt.Length + cp; - int new_x = xc % System.Console.BufferWidth; - int new_y = y + xc / System.Console.BufferWidth; - int end_y = y + (cmdline.Length + prompt.Length) / System.Console.BufferWidth; - if (end_y / System.Console.BufferWidth >= h) - h++; - if (end_y >= System.Console.BufferHeight) // wrap - { - y--; - new_y--; - System.Console.CursorLeft = 0; - System.Console.CursorTop = System.Console.BufferHeight-1; - System.Console.WriteLine(" "); - } - - y=SetCursorTop(y); - System.Console.CursorLeft = 0; - - if (echo) - System.Console.Write("{0}{1}", prompt, cmdline); - else - System.Console.Write("{0}", prompt); - - SetCursorLeft(new_x); - SetCursorTop(new_y); - } } - public void LockOutput() + public virtual void Output(string text) { - Monitor.Enter(cmdline); - try - { - if (y != -1) - { - y = SetCursorTop(y); - System.Console.CursorLeft = 0; - - int count = cmdline.Length + prompt.Length; - - while (count-- > 0) - System.Console.Write(" "); - - y = SetCursorTop(y); - System.Console.CursorLeft = 0; - - } - } - catch (Exception) - { - } - } - - public void UnlockOutput() - { - if (y != -1) - { - y = System.Console.CursorTop; - Show(); - } - Monitor.Exit(cmdline); - } - - public void Output(string text) - { - lock (cmdline) - { - if (y == -1) - { - System.Console.WriteLine(text); - - return; - } - - y = SetCursorTop(y); - System.Console.CursorLeft = 0; - - int count = cmdline.Length + prompt.Length; - - while (count-- > 0) - System.Console.Write(" "); - - y = SetCursorTop(y); - System.Console.CursorLeft = 0; - - System.Console.WriteLine(text); - - y = System.Console.CursorTop; - - Show(); - } - } - - private bool ContextHelp() - { - string[] words = Parser.Parse(cmdline.ToString()); - - bool trailingSpace = cmdline.ToString().EndsWith(" "); - - // Allow ? through while typing a URI - // - if (words.Length > 0 && words[words.Length-1].StartsWith("http") && !trailingSpace) - return false; - - string[] opts = Commands.FindNextOption(words, trailingSpace); - - if (opts[0].StartsWith("Command help:")) - Output(opts[0]); - else - Output(String.Format("Options: {0}", String.Join(" ", opts))); - - return true; - } - - public void Prompt() - { - string line = ReadLine(m_defaultPrompt, true, true); - - if (line != String.Empty) - { - m_log.Info("Invalid command"); - } + System.Console.WriteLine(text); } public string CmdPrompt(string p) @@ -850,19 +234,23 @@ namespace OpenSim.Framework.Console } // Displays a command prompt and returns a default value, user may only enter 1 of 2 options - public string CmdPrompt(string prompt, string defaultresponse, string OptionA, string OptionB) + public string CmdPrompt(string prompt, string defaultresponse, List options) { bool itisdone = false; + string optstr = String.Empty; + foreach (string s in options) + optstr += " " + s; + string temp = CmdPrompt(prompt, defaultresponse); while (itisdone == false) { - if ((temp == OptionA) || (temp == OptionB)) + if (options.Contains(temp)) { itisdone = true; } else { - System.Console.WriteLine("Valid options are " + OptionA + " or " + OptionB); + System.Console.WriteLine("Valid options are" + optstr); temp = CmdPrompt(prompt, defaultresponse); } } @@ -876,167 +264,12 @@ namespace OpenSim.Framework.Console return ReadLine(p, false, false); } - public void RunCommand(string cmd) + public virtual string ReadLine(string p, bool isCommand, bool e) { - string[] parts = Parser.Parse(cmd); - Commands.Resolve(parts); - } + System.Console.Write("{0}", prompt); + string cmdinput = System.Console.ReadLine(); - public string ReadLine(string p, bool isCommand, bool e) - { - h = 1; - cp = 0; - prompt = p; - echo = e; - int historyLine = history.Count; - - if (gui) - { - System.Console.Write("{0}", prompt); - string cmdinput = System.Console.ReadLine(); - - if (isCommand) - { - string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); - - if (cmd.Length != 0) - { - int i; - - for (i=0 ; i < cmd.Length ; i++) - { - if (cmd[i].Contains(" ")) - cmd[i] = "\"" + cmd[i] + "\""; - } - return String.Empty; - } - } - return cmdinput; - } - - System.Console.CursorLeft = 0; // Needed for mono - System.Console.Write(" "); // Needed for mono - - lock (cmdline) - { - y = System.Console.CursorTop; - cmdline.Remove(0, cmdline.Length); - } - - while (true) - { - Show(); - - ConsoleKeyInfo key = System.Console.ReadKey(true); - char c = key.KeyChar; - - if (!Char.IsControl(c)) - { - if (cp >= 318) - continue; - - if (c == '?' && isCommand) - { - if (ContextHelp()) - continue; - } - - cmdline.Insert(cp, c); - cp++; - } - else - { - switch (key.Key) - { - case ConsoleKey.Backspace: - if (cp == 0) - break; - cmdline.Remove(cp-1, 1); - cp--; - - System.Console.CursorLeft = 0; - y = SetCursorTop(y); - - System.Console.Write("{0}{1} ", prompt, cmdline); - - break; - case ConsoleKey.End: - cp = cmdline.Length; - break; - case ConsoleKey.Home: - cp = 0; - break; - case ConsoleKey.UpArrow: - if (historyLine < 1) - break; - historyLine--; - LockOutput(); - cmdline.Remove(0, cmdline.Length); - cmdline.Append(history[historyLine]); - cp = cmdline.Length; - UnlockOutput(); - break; - case ConsoleKey.DownArrow: - if (historyLine >= history.Count) - break; - historyLine++; - LockOutput(); - if (historyLine == history.Count) - { - cmdline.Remove(0, cmdline.Length); - } - else - { - cmdline.Remove(0, cmdline.Length); - cmdline.Append(history[historyLine]); - } - cp = cmdline.Length; - UnlockOutput(); - break; - case ConsoleKey.LeftArrow: - if (cp > 0) - cp--; - break; - case ConsoleKey.RightArrow: - if (cp < cmdline.Length) - cp++; - break; - case ConsoleKey.Enter: - System.Console.CursorLeft = 0; - y = SetCursorTop(y); - - System.Console.WriteLine("{0}{1}", prompt, cmdline); - - lock (cmdline) - { - y = -1; - } - - if (isCommand) - { - string[] cmd = Commands.Resolve(Parser.Parse(cmdline.ToString())); - - if (cmd.Length != 0) - { - int i; - - for (i=0 ; i < cmd.Length ; i++) - { - if (cmd[i].Contains(" ")) - cmd[i] = "\"" + cmd[i] + "\""; - } - AddToHistory(String.Join(" ", cmd)); - return String.Empty; - } - } - - AddToHistory(cmdline.ToString()); - return cmdline.ToString(); - default: - break; - } - } - } + return cmdinput; } } } diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs new file mode 100644 index 0000000000..9dde9695e7 --- /dev/null +++ b/OpenSim/Framework/Console/LocalConsole.cs @@ -0,0 +1,470 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Text; +using System.Threading; +using log4net; + +namespace OpenSim.Framework.Console +{ + // A console that uses cursor control and color + // + public class LocalConsole : CommandConsole + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private readonly object m_syncRoot = new object(); + + private int y = -1; + private int cp = 0; + private int h = 1; + private string prompt = "# "; + private StringBuilder cmdline = new StringBuilder(); + private bool echo = true; + private List history = new List(); + + public LocalConsole(string defaultPrompt) : base(defaultPrompt) + { + } + + private void AddToHistory(string text) + { + while (history.Count >= 100) + history.RemoveAt(0); + + history.Add(text); + } + + /// + /// derive an ansi color from a string, ignoring the darker colors. + /// This is used to help automatically bin component tags with colors + /// in various print functions. + /// + /// arbitrary string for input + /// an ansii color + protected override ConsoleColor DeriveColor(string input) + { + int colIdx = (input.ToUpper().GetHashCode() % 6) + 9; + return (ConsoleColor) colIdx; + } + + private int SetCursorTop(int top) + { + if (top >= 0 && top < System.Console.BufferHeight) + { + System.Console.CursorTop = top; + return top; + } + else + { + return System.Console.CursorTop; + } + } + + private int SetCursorLeft(int left) + { + if (left >= 0 && left < System.Console.BufferWidth) + { + System.Console.CursorLeft = left; + return left; + } + else + { + return System.Console.CursorLeft; + } + } + + protected override void WriteNewLine(ConsoleColor senderColor, string sender, ConsoleColor color, string format, params object[] args) + { + lock (cmdline) + { + if (y != -1) + { + y=SetCursorTop(y); + System.Console.CursorLeft = 0; + + int count = cmdline.Length; + + System.Console.Write(" "); + while (count-- > 0) + System.Console.Write(" "); + + y=SetCursorTop(y); + System.Console.CursorLeft = 0; + } + WritePrefixLine(senderColor, sender); + WriteConsoleLine(color, format, args); + if (y != -1) + y = System.Console.CursorTop; + } + } + + protected override void WriteNewLine(ConsoleColor color, string format, params object[] args) + { + lock (cmdline) + { + if (y != -1) + { + y=SetCursorTop(y); + System.Console.CursorLeft = 0; + + int count = cmdline.Length; + + System.Console.Write(" "); + while (count-- > 0) + System.Console.Write(" "); + + y=SetCursorTop(y); + System.Console.CursorLeft = 0; + } + WriteConsoleLine(color, format, args); + if (y != -1) + y = System.Console.CursorTop; + } + } + + protected override void WriteConsoleLine(ConsoleColor color, string format, params object[] args) + { + try + { + lock (m_syncRoot) + { + try + { + if (color != ConsoleColor.White) + System.Console.ForegroundColor = color; + + System.Console.WriteLine(format, args); + System.Console.ResetColor(); + } + catch (ArgumentNullException) + { + // Some older systems dont support coloured text. + System.Console.WriteLine(format, args); + } + catch (FormatException) + { + System.Console.WriteLine(args); + } + } + } + catch (ObjectDisposedException) + { + } + } + + protected override void WritePrefixLine(ConsoleColor color, string sender) + { + try + { + lock (m_syncRoot) + { + sender = sender.ToUpper(); + + System.Console.WriteLine("[" + sender + "] "); + + System.Console.Write("["); + + try + { + System.Console.ForegroundColor = color; + System.Console.Write(sender); + System.Console.ResetColor(); + } + catch (ArgumentNullException) + { + // Some older systems dont support coloured text. + System.Console.WriteLine(sender); + } + + System.Console.Write("] \t"); + } + } + catch (ObjectDisposedException) + { + } + } + + private void Show() + { + lock (cmdline) + { + if (y == -1 || System.Console.BufferWidth == 0) + return; + + int xc = prompt.Length + cp; + int new_x = xc % System.Console.BufferWidth; + int new_y = y + xc / System.Console.BufferWidth; + int end_y = y + (cmdline.Length + prompt.Length) / System.Console.BufferWidth; + if (end_y / System.Console.BufferWidth >= h) + h++; + if (end_y >= System.Console.BufferHeight) // wrap + { + y--; + new_y--; + System.Console.CursorLeft = 0; + System.Console.CursorTop = System.Console.BufferHeight-1; + System.Console.WriteLine(" "); + } + + y=SetCursorTop(y); + System.Console.CursorLeft = 0; + + if (echo) + System.Console.Write("{0}{1}", prompt, cmdline); + else + System.Console.Write("{0}", prompt); + + SetCursorLeft(new_x); + SetCursorTop(new_y); + } + } + + public override void LockOutput() + { + Monitor.Enter(cmdline); + try + { + if (y != -1) + { + y = SetCursorTop(y); + System.Console.CursorLeft = 0; + + int count = cmdline.Length + prompt.Length; + + while (count-- > 0) + System.Console.Write(" "); + + y = SetCursorTop(y); + System.Console.CursorLeft = 0; + + } + } + catch (Exception) + { + } + } + + public override void UnlockOutput() + { + if (y != -1) + { + y = System.Console.CursorTop; + Show(); + } + Monitor.Exit(cmdline); + } + + public override void Output(string text) + { + lock (cmdline) + { + if (y == -1) + { + System.Console.WriteLine(text); + + return; + } + + y = SetCursorTop(y); + System.Console.CursorLeft = 0; + + int count = cmdline.Length + prompt.Length; + + while (count-- > 0) + System.Console.Write(" "); + + y = SetCursorTop(y); + System.Console.CursorLeft = 0; + + System.Console.WriteLine(text); + + y = System.Console.CursorTop; + + Show(); + } + } + + private bool ContextHelp() + { + string[] words = Parser.Parse(cmdline.ToString()); + + bool trailingSpace = cmdline.ToString().EndsWith(" "); + + // Allow ? through while typing a URI + // + if (words.Length > 0 && words[words.Length-1].StartsWith("http") && !trailingSpace) + return false; + + string[] opts = Commands.FindNextOption(words, trailingSpace); + + if (opts[0].StartsWith("Command help:")) + Output(opts[0]); + else + Output(String.Format("Options: {0}", String.Join(" ", opts))); + + return true; + } + + public override string ReadLine(string p, bool isCommand, bool e) + { + h = 1; + cp = 0; + prompt = p; + echo = e; + int historyLine = history.Count; + + System.Console.CursorLeft = 0; // Needed for mono + System.Console.Write(" "); // Needed for mono + + lock (cmdline) + { + y = System.Console.CursorTop; + cmdline.Remove(0, cmdline.Length); + } + + while (true) + { + Show(); + + ConsoleKeyInfo key = System.Console.ReadKey(true); + char c = key.KeyChar; + + if (!Char.IsControl(c)) + { + if (cp >= 318) + continue; + + if (c == '?' && isCommand) + { + if (ContextHelp()) + continue; + } + + cmdline.Insert(cp, c); + cp++; + } + else + { + switch (key.Key) + { + case ConsoleKey.Backspace: + if (cp == 0) + break; + cmdline.Remove(cp-1, 1); + cp--; + + System.Console.CursorLeft = 0; + y = SetCursorTop(y); + + System.Console.Write("{0}{1} ", prompt, cmdline); + + break; + case ConsoleKey.End: + cp = cmdline.Length; + break; + case ConsoleKey.Home: + cp = 0; + break; + case ConsoleKey.UpArrow: + if (historyLine < 1) + break; + historyLine--; + LockOutput(); + cmdline.Remove(0, cmdline.Length); + cmdline.Append(history[historyLine]); + cp = cmdline.Length; + UnlockOutput(); + break; + case ConsoleKey.DownArrow: + if (historyLine >= history.Count) + break; + historyLine++; + LockOutput(); + if (historyLine == history.Count) + { + cmdline.Remove(0, cmdline.Length); + } + else + { + cmdline.Remove(0, cmdline.Length); + cmdline.Append(history[historyLine]); + } + cp = cmdline.Length; + UnlockOutput(); + break; + case ConsoleKey.LeftArrow: + if (cp > 0) + cp--; + break; + case ConsoleKey.RightArrow: + if (cp < cmdline.Length) + cp++; + break; + case ConsoleKey.Enter: + System.Console.CursorLeft = 0; + y = SetCursorTop(y); + + System.Console.WriteLine("{0}{1}", prompt, cmdline); + + lock (cmdline) + { + y = -1; + } + + if (isCommand) + { + string[] cmd = Commands.Resolve(Parser.Parse(cmdline.ToString())); + + if (cmd.Length != 0) + { + int i; + + for (i=0 ; i < cmd.Length ; i++) + { + if (cmd[i].Contains(" ")) + cmd[i] = "\"" + cmd[i] + "\""; + } + AddToHistory(String.Join(" ", cmd)); + return String.Empty; + } + } + + AddToHistory(cmdline.ToString()); + return cmdline.ToString(); + default: + break; + } + } + } + } + } +} diff --git a/OpenSim/Framework/Console/MainConsole.cs b/OpenSim/Framework/Console/MainConsole.cs index 15df6997f4..b438089b2e 100644 --- a/OpenSim/Framework/Console/MainConsole.cs +++ b/OpenSim/Framework/Console/MainConsole.cs @@ -29,9 +29,9 @@ namespace OpenSim.Framework.Console { public class MainConsole { - private static ConsoleBase instance; + private static CommandConsole instance; - public static ConsoleBase Instance + public static CommandConsole Instance { get { return instance; } set { instance = value; } diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index e03713ec67..0261146f48 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -60,7 +60,7 @@ namespace OpenSim.Framework.Servers /// private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); - protected ConsoleBase m_console; + protected CommandConsole m_console; protected OpenSimAppender m_consoleAppender; /// diff --git a/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs b/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs index 2687af6022..8f4b9a08c4 100644 --- a/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs +++ b/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs @@ -55,7 +55,7 @@ namespace OpenSim.Grid.AssetInventoryServer { ConfigFile = config; - m_console = new ConsoleBase("AssetInventory"); + m_console = new LocalConsole("AssetInventory"); MainConsole.Instance = m_console; } diff --git a/OpenSim/Grid/AssetServer/Main.cs b/OpenSim/Grid/AssetServer/Main.cs index 5b23d5a936..82a6078612 100644 --- a/OpenSim/Grid/AssetServer/Main.cs +++ b/OpenSim/Grid/AssetServer/Main.cs @@ -76,7 +76,7 @@ namespace OpenSim.Grid.AssetServer public OpenAsset_Main() { - m_console = new ConsoleBase("Asset"); + m_console = new LocalConsole("Asset"); MainConsole.Instance = m_console; } diff --git a/OpenSim/Grid/GridServer.Modules/GridServerPlugin.cs b/OpenSim/Grid/GridServer.Modules/GridServerPlugin.cs index 1a4fe727e8..420249de57 100644 --- a/OpenSim/Grid/GridServer.Modules/GridServerPlugin.cs +++ b/OpenSim/Grid/GridServer.Modules/GridServerPlugin.cs @@ -53,7 +53,7 @@ namespace OpenSim.Grid.GridServer.Modules protected IGridServiceCore m_core; - protected ConsoleBase m_console; + protected CommandConsole m_console; #region IGridPlugin Members diff --git a/OpenSim/Grid/GridServer/GridServerBase.cs b/OpenSim/Grid/GridServer/GridServerBase.cs index a1170f8bc8..a281a37154 100644 --- a/OpenSim/Grid/GridServer/GridServerBase.cs +++ b/OpenSim/Grid/GridServer/GridServerBase.cs @@ -70,7 +70,7 @@ namespace OpenSim.Grid.GridServer public GridServerBase() { - m_console = new ConsoleBase("Grid"); + m_console = new LocalConsole("Grid"); MainConsole.Instance = m_console; } diff --git a/OpenSim/Grid/InventoryServer/Main.cs b/OpenSim/Grid/InventoryServer/Main.cs index fa316b1764..b2ed6d39b5 100644 --- a/OpenSim/Grid/InventoryServer/Main.cs +++ b/OpenSim/Grid/InventoryServer/Main.cs @@ -60,7 +60,7 @@ namespace OpenSim.Grid.InventoryServer public OpenInventory_Main() { - m_console = new ConsoleBase("Inventory"); + m_console = new LocalConsole("Inventory"); MainConsole.Instance = m_console; } diff --git a/OpenSim/Grid/MessagingServer/Main.cs b/OpenSim/Grid/MessagingServer/Main.cs index c92dd6e60d..6fe0c8f43d 100644 --- a/OpenSim/Grid/MessagingServer/Main.cs +++ b/OpenSim/Grid/MessagingServer/Main.cs @@ -69,7 +69,7 @@ namespace OpenSim.Grid.MessagingServer public OpenMessage_Main() { - m_console = new ConsoleBase("Messaging"); + m_console = new LocalConsole("Messaging"); MainConsole.Instance = m_console; } diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs index 0a5abd323b..d9185cb9ce 100644 --- a/OpenSim/Grid/UserServer/Main.cs +++ b/OpenSim/Grid/UserServer/Main.cs @@ -84,7 +84,7 @@ namespace OpenSim.Grid.UserServer public OpenUser_Main() { - m_console = new ConsoleBase("User"); + m_console = new LocalConsole("User"); MainConsole.Instance = m_console; } @@ -126,7 +126,7 @@ namespace OpenSim.Grid.UserServer m_httpServer = new BaseHttpServer(Cfg.HttpPort); - RegisterInterface(m_console); + RegisterInterface(m_console); RegisterInterface(Cfg); //Should be in modules? diff --git a/OpenSim/Grid/UserServer/UserServerCommandModule.cs b/OpenSim/Grid/UserServer/UserServerCommandModule.cs index f73b3deb32..1d74c802bc 100644 --- a/OpenSim/Grid/UserServer/UserServerCommandModule.cs +++ b/OpenSim/Grid/UserServer/UserServerCommandModule.cs @@ -49,7 +49,7 @@ namespace OpenSim.Grid.UserServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected ConsoleBase m_console; + protected CommandConsole m_console; protected UserConfig m_cfg; protected UserDataBaseService m_userDataBaseService; @@ -88,8 +88,8 @@ namespace OpenSim.Grid.UserServer m_loginService = loginService; } - ConsoleBase console; - if ((m_core.TryGet(out console)) && (m_cfg != null) + CommandConsole console; + if ((m_core.TryGet(out console)) && (m_cfg != null) && (m_userDataBaseService != null) && (m_loginService != null)) { RegisterConsoleCommands(console); @@ -101,7 +101,7 @@ namespace OpenSim.Grid.UserServer } - private void RegisterConsoleCommands(ConsoleBase console) + private void RegisterConsoleCommands(CommandConsole console) { m_console = console; m_console.Commands.AddCommand("userserver", false, "create user", diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index d3941d6302..5ba377bc90 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -92,8 +92,10 @@ namespace OpenSim //GCSettings.LatencyMode = GCLatencyMode.Batch; //m_log.InfoFormat("[OPENSIM MAIN]: GC Latency Mode: {0}", GCSettings.LatencyMode.ToString()); - m_console = new ConsoleBase("Region"); - m_console.SetGuiMode(m_gui); + if (m_gui) // Driven by external GUI + m_console = new CommandConsole("Region"); + else + m_console = new LocalConsole("Region"); MainConsole.Instance = m_console; RegisterConsoleCommands(); diff --git a/OpenSim/TestSuite/BotManager.cs b/OpenSim/TestSuite/BotManager.cs index 0838214378..c4d5babc63 100644 --- a/OpenSim/TestSuite/BotManager.cs +++ b/OpenSim/TestSuite/BotManager.cs @@ -44,7 +44,7 @@ namespace OpenSim.TestSuite { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected ConsoleBase m_console; + protected CommandConsole m_console; protected List m_lBot; protected Thread[] m_td; protected bool m_verbose = true; diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs index c015bbc854..2cd947ee9a 100644 --- a/OpenSim/Tools/pCampBot/BotManager.cs +++ b/OpenSim/Tools/pCampBot/BotManager.cs @@ -47,7 +47,7 @@ namespace pCampBot { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected ConsoleBase m_console; + protected CommandConsole m_console; protected List m_lBot; protected Thread[] m_td; protected bool m_verbose = true; @@ -206,9 +206,9 @@ namespace pCampBot /// Standard CreateConsole routine /// /// - protected ConsoleBase CreateConsole() + protected CommandConsole CreateConsole() { - return new ConsoleBase("Region"); + return new LocalConsole("Region"); } private void HandleShutdown(string module, string[] cmd)