PoshCode Logo PowerShell Code Repository

Test-BufferBox 2.0 by Joel Bennett 3 years ago
View followups from Joel Bennett | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/730"></script>download | new post

A tech demo: a scrolling buffer where you can type while it’s scrolling…

  1. ## Test-BufferBox 2.0
  2. ####################################################################################################
  3. ## This script is just a demonstration of some of the things you can do with the buffer
  4. ## in the default PowerShell host... it serves as a reminder of how much work remains on
  5. ## PoshConsole, and as an inspirations to anyone who is thinking about trying to create
  6. ## "interactive" PowerShell applications.
  7. ##
  8. ## Imagine it's a chat window: you can type, but the whole time, the ongoing conversation in the
  9. ## chat room you have joined is going on in the background.
  10. ##
  11. ## NOTE: because this is a "chat" demo, we treat your input as text, and to execute script in-line
  12. ## you have to enclose it inside $() braces.
  13. ##
  14. ####################################################################################################
  15. PARAM(   $title = "PowerShell Interactive Buffer Demo" )
  16.  
  17. $global:fore  = $Host.UI.RawUI.ForegroundColor
  18. $global:back  = $Host.UI.RawUI.BackgroundColor
  19.  
  20. Function New-Box ($Height, $Width, $Title="") {
  21.    $box = &{ "¯¯$Title$('¯'*($Width-($Title.Length+2)))";
  22.             1..($Height - 2) | % {(' ' * $Width)};
  23.             ('_' * $Width);
  24.             1..2 | % {(' ' * $Width)};
  25.             }
  26.    $boxBuffer = $Host.UI.RawUI.NewBufferCellArray($box,'Green','Black')
  27.    ,$boxBuffer
  28. }
  29.  
  30. Function Scroll-Buffer ($origin,$Width,$Height,$Scroll=-1){
  31.    $re = new-object $RECT $origin.x, $origin.y, ($origin.x + $width-2), ($origin.y + $height)
  32.    $origin.Y += $Scroll
  33.    $Host.UI.RawUI.ScrollBufferContents($re, $origin, $re, $blank)
  34. }
  35.  
  36. Function Out-Buffer {
  37. PARAM ($Message, $Foreground = 'White',$Background = 'Black',[switch]$noscroll)
  38. BEGIN {
  39.    if($Message) {
  40.       $Message | Out-Buffer -Fore $Foreground -Back $Background -NoScript:$NoScroll
  41.    }
  42. }
  43. PROCESS { if($_){$Message = $_
  44.  
  45.    if ( -not $NoScroll) {
  46.       Scroll-Buffer $ContentPos ($WindowSize.Width -2) ($WindowSize.Height - 4)
  47.    }
  48.  
  49.    # "{0},{1} {2},{3} -{4}" -f $script:pos.X, $script:pos.Y, $MessagePos.X, $MessagePos.Y, $message
  50.    $host.ui.rawui.SetBufferContents(
  51.       $MessagePos,
  52.       $Host.UI.RawUI.NewBufferCellArray(
  53.          @($message.PadRight($WindowSize.Width)),
  54.          $Foreground,
  55.          $Background)
  56.    )
  57. }}}
  58.  
  59. Function Clear-Prompt () {
  60.    $Host.UI.RawUI.SetBufferContents( $PromptPos, $prompt )
  61.    $Host.UI.RawUI.CursorPosition = $CursorPos
  62. }
  63.  
  64. ###################################################################################################
  65. ##### Initialize a lot of settings
  66. ###################################################################################################
  67.    $RECT  = "system.management.automation.host.rectangle"
  68.    $blank = new-object System.Management.Automation.Host.BufferCell(' ','Gray','Black','complete')
  69.  
  70.    $WindowSize = $Host.UI.RawUI.WindowSize;
  71.    "`n" * $WindowSize.Height
  72.    $ContentPos = $Host.UI.RawUI.WindowPosition;
  73.  
  74.    $Host.UI.RawUI.ForegroundColor = "Yellow"
  75.    $Host.UI.RawUI.BackgroundColor = "Black"
  76.  
  77.    $ContentPos.Y += 1 # Keep the title in the top row
  78.    $ContentPos.X += 2 # 2 cell left padding on output
  79.    # The Message is written into the very last line of the ContentBox
  80.    $MessagePos = $ContentPos
  81.    $MessagePos.Y += ($WindowSize.Height - 4)
  82.    
  83.    $PromptPos = $ContentPos
  84.    $PromptPos.X = 0
  85.    $PromptPos.Y += $WindowSize.Height - 2
  86.    $prompt = $Host.UI.RawUI.NewBufferCellArray( @(&{"> "+(" " * ($WindowSize.Width-3))}), "Yellow", "Black")
  87.    $CursorPos = $PromptPos
  88.    $CursorPos.X += 2
  89. ###################################################################################################
  90. ##### We only need this for the purposes of the demo...
  91. ##### In a real script you would, presumably, be getting stuff from somewhere else to display
  92.    $noise = Get-Content ($MyInvocation.MyCommand.Path)
  93.    $index = 0;
  94.    $random = New-Object "Random"
  95.  
  96. ###################################################################################################
  97. ##### The loop starts by clearing the screen ...
  98. $Host.UI.RawUI.SetBufferContents($Host.UI.RawUI.WindowPosition, (New-Box ($WindowSize.Height - 1) $WindowSize.Width $title))
  99. ##### Printing a "How to Exit" message
  100. Out-Buffer "  " -Fore DarkGray -Back Cyan
  101. Out-Buffer "     This is just a demo. " -Fore Black -Back Cyan
  102. Out-Buffer "     We will stream in the source code of this script ... " -Fore Black -Back Cyan
  103. Out-Buffer "     And you can type at the bottom while it's running. " -Fore Black -Back Cyan
  104. Out-Buffer "     Imagine this as an n-way chat application like IRC, except that " -Fore Black -Back Cyan
  105. Out-Buffer "  FOR THIS PERFORMANCE ONLY: " -Fore Black -Back Cyan
  106. Out-Buffer "         The part of your chatting friends is played by my source code. " -Fore DarkGray -Back Cyan
  107. Out-Buffer "  " -Fore DarkGray -Back Cyan
  108. Out-Buffer "     Press ESC to exit, or enter 'exit' and hit Enter" -Fore Black -Back Cyan
  109. Out-Buffer "  " -Fore DarkGray -Back Cyan
  110. ##### Setting the prompt
  111. Clear-Prompt
  112. ##### And initializing our two variables ...
  113. $line=""
  114. $exit = $false
  115. while(!$exit){
  116.    while(!$exit -and $Host.UI.RawUI.KeyAvailable) {
  117.       $char = $Host.UI.RawUI.ReadKey("IncludeKeyUp,IncludeKeyDown,NoEcho");
  118.       # we don't want the key up events, but we do want to get rid of them
  119.       if($char.KeyDown) {
  120.       switch([int]$char.Character) {
  121.          13 { # Enter
  122.                if($line.Trim() -eq "exit") { $exit = $true; break; }
  123. ###################################################################################################
  124. ###################################################################################################
  125. ############# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING #############
  126. ############# This executes the user input!                                           #############
  127. ############# Don't use this on, say, content you got from a web page or chat room    #############
  128.             iex "Out-Buffer `"$line`" -Fore Red";                                     #############
  129. ###################################################################################################
  130. ###################################################################################################
  131.             $line = "";
  132.             Clear-Prompt
  133.          }
  134.          27 { # Esc
  135.             $exit = $true; break;
  136.          }
  137.            8 { # Backspace
  138.             if($line.Length -gt 0) {
  139.                $line = $line.SubString(0,$($line.Length-1))
  140.             }
  141.             # $pos = $Host.UI.RawUI.CursorPosition
  142.             $Host.UI.RawUI.SetBufferContents( $PromptPos, $Host.UI.RawUI.NewBufferCellArray( @(&{ "> $($line)$(' ' * ($WindowSize.Width-3-$line.Length))"}), "Yellow", "Black") )
  143.          }
  144.          0 { # Not actually a key
  145.             # Out-Buffer $($Char | Out-String)
  146.          }
  147.          default {
  148.             $line += $char.Character
  149.             $Host.UI.RawUI.SetBufferContents( $PromptPos, $Host.UI.RawUI.NewBufferCellArray( @(&{ "> $($line)$(' ' * ($WindowSize.Width-3-$line.Length))"}), "Yellow", "Black") )
  150.          }
  151.       }
  152.       }
  153.    }
  154.    # Simulate doing useful things 25% of the time
  155.    if($random.NextDouble() -gt 0.75) {
  156.       $noise[($index)..($index++)] | Out-Buffer
  157.       if($index -ge $noise.Length){$index = 0}
  158.    }
  159.    sleep -milli 100
  160. }
  161.  
  162. # set the colors back ...
  163. $Host.UI.RawUI.ForegroundColor = $fore
  164. $Host.UI.RawUI.BackgroundColor = $back

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me