Example #1
0
        /// <summary>
        /// Enumerates the objects in the captured console in a stream fashion.
        /// The enumeration order is as follows:
        /// 1. ConsoleLog object.
        /// 2. For each line:
        ///    a. Line object.
        ///    b. Each Span object.
        ///    c. A null.
        /// The null is used to indicate termination of a line.
        /// Note that when ConsoleLog/Line objects are first enumerated,
        /// their children Line/Span objects are not yet ready. Enumeration
        /// must proceed for the tree structure to be completed.
        /// When "populate" is set to $False, this method is GC-efficient in
        /// that if you discard an object after receiving it, the object
        /// immediately becomes eligible for garbage collection.
        /// The effect is that the tree structure is never populated.
        /// </summary>
        /// <param name="host">$Host from PowerShell.</param>
        /// <param name="includeCurrentLine">Whether the current line should be included.
        /// This can be set to $False if the command is used interactively.</param>
        /// <param name="behavior">Behavior of trailing space characters.</param>
        /// <param name="populate">Whether the tree structure is populated.</param>
        /// <returns>Enumerated objects.</returns>
        public static IEnumerable <object> StreamCapture(PSHost host,
                                                         bool includeCurrentLine,
                                                         TrailingSpaceBehavior behavior,
                                                         bool populate)
        {
            if (host.Name != "ConsoleHost")
            {
                throw new NotSupportedException("This method only supports the console host.");
            }
            if ((int)behavior < 0 || (int)behavior > 2)
            {
                throw new ArgumentOutOfRangeException("behavior");
            }
            PSHostRawUserInterface ui = host.UI.RawUI;
            int width = ui.BufferSize.Width;
            int y     = ui.CursorPosition.Y + (includeCurrentLine ? 1 : 0);

            if (width < 1)
            {
                throw new ArgumentOutOfRangeException("host.UI.RawUI.BufferSize.Width");
            }
            if (y < 1)
            {
                throw new ArgumentOutOfRangeException("host.UI.RawUI.CursorPosition.Y");
            }
            return(StreamCaptureImpl(behavior,
                                     ui.GetBufferContents(new Rectangle(0, 0, width - 1, y - 1)),
                                     ui.ForegroundColor, ui.BackgroundColor, width, y, populate));
        }
Example #2
0
 private Capturer(TrailingSpaceBehavior tsb, int w, ConsoleColor fg, ConsoleColor bg)
 {
     behavior  = tsb;
     width     = w;
     fgDefault = fg;
     bgDefault = bg;
     fgCurrent = fg;
     bgCurrent = bg;
     space     = 0;
     cjk       = 0;
     sb        = new StringBuilder(width + 1);
     pending   = new List <PendingSpan>(width + 1);
 }
Example #3
0
        /// <summary>
        /// Captures the console as a ConsoleLog object.
        /// </summary>
        public static ConsoleLog Capture(PSHost host,
                                         bool includeCurrentLine,
                                         TrailingSpaceBehavior behavior)
        {
            ConsoleLog result = null;

            foreach (object obj in StreamCapture(host, includeCurrentLine, behavior, true))
            {
                if (obj is ConsoleLog)
                {
                    result = (ConsoleLog)obj;
                }
                /* Continue enumeration to populate the structure. */
            }
            return(result);
        }
Example #4
0
        public static IEnumerable <string> Capture(PSHost host,
                                                   bool includeCurrentLine,
                                                   TrailingSpaceBehavior behavior)
        {
            StringBuilder sb = new StringBuilder();

            foreach (object obj in Capturer.StreamCapture(host, includeCurrentLine, behavior, false))
            {
                if (ReferenceEquals(obj, null))
                {
                    yield return(sb.ToString());

                    sb.Clear();
                }
                Span span = obj as Span;
                if (!ReferenceEquals(span, null))
                {
                    sb.Append(span.Content);
                }
            }
        }
Example #5
0
 public static string GetInteractiveHtml(PSHost host,
                                         bool includeCurrentLine, TrailingSpaceBehavior behavior)
 {
     return(string.Concat(GetInteractiveHtmlImpl(
                              Capturer.StreamCapture(host, includeCurrentLine, behavior, false))));
 }
Example #6
0
 /// <summary>
 /// Captures the console as a string.
 /// </summary>
 public static string Capture(PSHost host,
                              bool includeCurrentLine,
                              TrailingSpaceBehavior behavior)
 {
     return(string.Concat(StreamCapture(host, includeCurrentLine, behavior)));
 }
Example #7
0
        /// <summary>
        /// Enumerates the substrings of HTML-formatted ConsoleLog.
        /// </summary>
        /// <param name="host">$Host from PowerShell.</param>
        /// <param name="includeCurrentLine">Whether the current line should be included.
        /// This can be set to $False if the command is used interactively.</param>
        /// <param name="behavior">Behavior of trailing space characters.</param>
        public static IEnumerable <string> StreamCapture(PSHost host,
                                                         bool includeCurrentLine,
                                                         TrailingSpaceBehavior behavior)
        {
            ConsoleColor fgDefault = ConsoleColor.White, bgDefault = ConsoleColor.Black;
            ConsoleColor fgLine = ConsoleColor.White, bgLine = ConsoleColor.Black;
            ConsoleColor fg = ConsoleColor.White, bg = ConsoleColor.Black;
            bool         emptyLine = true;

            /* The loop directly walks the tree, so we do not need
            ** the tree to be stored in the returned objects.
            ** Setting "populate" to $False make it GC-efficient. */
            foreach (object obj in Capturer.StreamCapture(host, includeCurrentLine, behavior, false))
            {
                ConsoleLog console = obj as ConsoleLog;
                if (!ReferenceEquals(console, null))
                {
                    yield return("<pre class=\"gl-console gl-console-fg-");

                    yield return(Helper.ColorToName(fgDefault = console.Foreground));

                    yield return(" gl-console-bg-");

                    yield return(Helper.ColorToName(bgLine = bgDefault = console.Background));

                    yield return("\" data-width=\"");

                    yield return(console.Width.ToString(CultureInfo.InvariantCulture));

                    yield return("\">\n");

                    continue;
                }
                Line line = obj as Line;
                if (!ReferenceEquals(line, null))
                {
                    yield return("<code class=\"gl-console-line");

                    if ((fgLine = line.Foreground) != fgDefault)
                    {
                        yield return(" gl-console-fg-");

                        yield return(Helper.ColorToName(fgLine));
                    }
                    yield return(" gl-console-bg-");

                    ConsoleColor bgLine2 = line.Background;
                    if (bgLine != bgLine2)
                    {
                        yield return("change gl-console-bg-");
                    }
                    yield return((bgLine = bgLine2) != bgDefault
                        ? Helper.ColorToName(bgLine2) : "none");

                    yield return("\">");

                    emptyLine = true;
                    continue;
                }
                Span span = obj as Span;
                if (!ReferenceEquals(span, null))
                {
                    emptyLine = false;
                    fg        = span.Foreground;
                    bg        = span.Background;
                    if (fg == fgLine && bg == bgLine)
                    {
                        yield return("<span>");

                        yield return(Helper.HtmlEncode(span.Content));

                        yield return("</span>");
                    }
                    else if (fg == fgLine && bg != bgLine)
                    {
                        yield return("<span class=\"gl-console-bg-");

                        yield return(Helper.ColorToName(bg));

                        yield return("\">");

                        yield return(Helper.HtmlEncode(span.Content));

                        yield return("</span>");
                    }
                    else if (fg != fgLine && bg == bgLine)
                    {
                        yield return("<span class=\"gl-console-fg-");

                        yield return(Helper.ColorToName(fg));

                        yield return("\">");

                        yield return(Helper.HtmlEncode(span.Content));

                        yield return("</span>");
                    }
                    else
                    {
                        yield return("<span class=\"gl-console-fg-");

                        yield return(Helper.ColorToName(fg));

                        yield return(" gl-console-bg-");

                        yield return(Helper.ColorToName(bg));

                        yield return("\">");

                        yield return(Helper.HtmlEncode(span.Content));

                        yield return("</span>");
                    }
                    continue;
                }
                /* A line has ended. */
                yield return(emptyLine ? "<span> </span></code>\n" : "</code>\n");
            }
            yield return("</pre>");
        }
Example #8
0
        private static IEnumerable <object> StreamCaptureImpl(TrailingSpaceBehavior behavior,
                                                              BufferCell[,] cells,
                                                              ConsoleColor fg, ConsoleColor bg,
                                                              int width, int y,
                                                              bool populate)
        {
            List <Line>        lines     = populate ? new List <Line>(y) : null;
            Capturer           automaton = new Capturer(behavior, width, fg, bg);
            List <PendingSpan> pending   = automaton.pending;

            yield return(new ConsoleLog(fg, bg, width,
                                        populate ? lines.AsReadOnly() : EmptyLineList));

            for (int line = 0; line != y; ++line)
            {
                for (int column = 0; column != width; ++column)
                {
                    BufferCell target = cells[line, column];
                    char       ch     = target.Character;
                    if (target.BufferCellType == BufferCellType.Complete || ch != '\0')
                    {
                        automaton.AddCharacter(ch,
                                               target.ForegroundColor, target.BackgroundColor);
                    }
                    else
                    {
                        automaton.AddCJK();
                    }
                }
                automaton.CompleteCurrentSpan();
                Line ln;
                /* This should not happen, but just being safe. */
                if (pending.Count == 0)
                {
                    ln = new Line(fg, bg, EmptySpanList);
                    if (populate)
                    {
                        lines.Add(ln);
                    }
                    yield return(ln);

                    yield return(null);

                    continue;
                }
                ConsoleColor fgLine, bgLine;
                automaton.ResolveLineColors(out fgLine, out bgLine);
                automaton.RemoveTrailingSpace(bgLine);
                List <Span> spans = populate ? new List <Span>(pending.Count) : null;
                ln = new Line(fgLine, bgLine, populate ? spans.AsReadOnly() : EmptySpanList);
                if (populate)
                {
                    lines.Add(ln);
                }
                yield return(ln);

                foreach (PendingSpan sp in pending)
                {
                    if (sp.Trimmed.Length == 0)
                    {
                        sp.Foreground = fgLine;
                    }
                    Span span = sp.ToSpan();
                    if (populate)
                    {
                        spans.Add(span);
                    }
                    yield return(span);
                }
                yield return(null);

                pending.Clear();
            }
        }