From 1b877234dada9f14cebc486cc426db892beae152 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 4 May 2009 12:15:55 +0000 Subject: Refactor. Make ConsoleBase a true base class. Create CommandConsole as a simple console capable of processing commands. Create LocalConsole as a console that uses cursor control and context help. Precursor to a distributed console system for the new grid services. No functional change intended :) --- OpenSim/Framework/Console/LocalConsole.cs | 470 ++++++++++++++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 OpenSim/Framework/Console/LocalConsole.cs (limited to 'OpenSim/Framework/Console/LocalConsole.cs') diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs new file mode 100644 index 0000000..9dde969 --- /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; + } + } + } + } + } +} -- cgit v1.1