# encoding: utf-8
# api: powershell
# title: Test-BufferBox
# description: A tech demo: a scrolling buffer where you can type while it’s scrolling…
# version: 2.0
# type: script
# author: Joel Bennett
# license: CC0
# function: New-Box
# x-poshcode-id: 730
# x-archived: 2016-07-15T09:50:06
# x-published: 2009-12-12T13:31:00
#
#
## Test-BufferBox 2.0
####################################################################################################
## This script is just a demonstration of some of the things you can do with the buffer
## in the default PowerShell host... it serves as a reminder of how much work remains on
## PoshConsole, and as an inspirations to anyone who is thinking about trying to create
## "interactive" PowerShell applications.
##
## Imagine it's a chat window: you can type, but the whole time, the ongoing conversation in the
## chat room you have joined is going on in the background.
##
## NOTE: because this is a "chat" demo, we treat your input as text, and to execute script in-line
## you have to enclose it inside $() braces.
##
####################################################################################################
PARAM( $title = "PowerShell Interactive Buffer Demo" )
$global:fore = $Host.UI.RawUI.ForegroundColor
$global:back = $Host.UI.RawUI.BackgroundColor
Function New-Box ($Height, $Width, $Title="") {
$box = &{ "¯¯$Title$('¯'*($Width-($Title.Length+2)))";
1..($Height - 2) | % {(' ' * $Width)};
('_' * $Width);
1..2 | % {(' ' * $Width)};
}
$boxBuffer = $Host.UI.RawUI.NewBufferCellArray($box,'Green','Black')
,$boxBuffer
}
Function Scroll-Buffer ($origin,$Width,$Height,$Scroll=-1){
$re = new-object $RECT $origin.x, $origin.y, ($origin.x + $width-2), ($origin.y + $height)
$origin.Y += $Scroll
$Host.UI.RawUI.ScrollBufferContents($re, $origin, $re, $blank)
}
Function Out-Buffer {
PARAM ($Message, $Foreground = 'White',$Background = 'Black',[switch]$noscroll)
BEGIN {
if($Message) {
$Message | Out-Buffer -Fore $Foreground -Back $Background -NoScript:$NoScroll
}
}
PROCESS { if($_){$Message = $_
if ( -not $NoScroll) {
Scroll-Buffer $ContentPos ($WindowSize.Width -2) ($WindowSize.Height - 4)
}
# "{0},{1} {2},{3} -{4}" -f $script:pos.X, $script:pos.Y, $MessagePos.X, $MessagePos.Y, $message
$host.ui.rawui.SetBufferContents(
$MessagePos,
$Host.UI.RawUI.NewBufferCellArray(
@($message.PadRight($WindowSize.Width)),
$Foreground,
$Background)
)
}}}
Function Clear-Prompt () {
$Host.UI.RawUI.SetBufferContents( $PromptPos, $prompt )
$Host.UI.RawUI.CursorPosition = $CursorPos
}
###################################################################################################
##### Initialize a lot of settings
###################################################################################################
$RECT = "system.management.automation.host.rectangle"
$blank = new-object System.Management.Automation.Host.BufferCell(' ','Gray','Black','complete')
$WindowSize = $Host.UI.RawUI.WindowSize;
"`n" * $WindowSize.Height
$ContentPos = $Host.UI.RawUI.WindowPosition;
$Host.UI.RawUI.ForegroundColor = "Yellow"
$Host.UI.RawUI.BackgroundColor = "Black"
$ContentPos.Y += 1 # Keep the title in the top row
$ContentPos.X += 2 # 2 cell left padding on output
# The Message is written into the very last line of the ContentBox
$MessagePos = $ContentPos
$MessagePos.Y += ($WindowSize.Height - 4)
$PromptPos = $ContentPos
$PromptPos.X = 0
$PromptPos.Y += $WindowSize.Height - 2
$prompt = $Host.UI.RawUI.NewBufferCellArray( @(&{"> "+(" " * ($WindowSize.Width-3))}), "Yellow", "Black")
$CursorPos = $PromptPos
$CursorPos.X += 2
###################################################################################################
##### We only need this for the purposes of the demo...
##### In a real script you would, presumably, be getting stuff from somewhere else to display
$noise = Get-Content ($MyInvocation.MyCommand.Path)
$index = 0;
$random = New-Object "Random"
###################################################################################################
##### The loop starts by clearing the screen ...
$Host.UI.RawUI.SetBufferContents($Host.UI.RawUI.WindowPosition, (New-Box ($WindowSize.Height - 1) $WindowSize.Width $title))
##### Printing a "How to Exit" message
Out-Buffer " " -Fore DarkGray -Back Cyan
Out-Buffer " This is just a demo. " -Fore Black -Back Cyan
Out-Buffer " We will stream in the source code of this script ... " -Fore Black -Back Cyan
Out-Buffer " And you can type at the bottom while it's running. " -Fore Black -Back Cyan
Out-Buffer " Imagine this as an n-way chat application like IRC, except that " -Fore Black -Back Cyan
Out-Buffer " FOR THIS PERFORMANCE ONLY: " -Fore Black -Back Cyan
Out-Buffer " The part of your chatting friends is played by my source code. " -Fore DarkGray -Back Cyan
Out-Buffer " " -Fore DarkGray -Back Cyan
Out-Buffer " Press ESC to exit, or enter 'exit' and hit Enter" -Fore Black -Back Cyan
Out-Buffer " " -Fore DarkGray -Back Cyan
##### Setting the prompt
Clear-Prompt
##### And initializing our two variables ...
$line=""
$exit = $false
while(!$exit){
while(!$exit -and $Host.UI.RawUI.KeyAvailable) {
$char = $Host.UI.RawUI.ReadKey("IncludeKeyUp,IncludeKeyDown,NoEcho");
# we don't want the key up events, but we do want to get rid of them
if($char.KeyDown) {
switch([int]$char.Character) {
13 { # Enter
if($line.Trim() -eq "exit") { $exit = $true; break; }
###################################################################################################
###################################################################################################
############# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING #############
############# This executes the user input! #############
############# Don't use this on, say, content you got from a web page or chat room #############
iex "Out-Buffer `"$line`" -Fore Red"; #############
###################################################################################################
###################################################################################################
$line = "";
Clear-Prompt
}
27 { # Esc
$exit = $true; break;
}
8 { # Backspace
if($line.Length -gt 0) {
$line = $line.SubString(0,$($line.Length-1))
}
# $pos = $Host.UI.RawUI.CursorPosition
$Host.UI.RawUI.SetBufferContents( $PromptPos, $Host.UI.RawUI.NewBufferCellArray( @(&{ "> $($line)$(' ' * ($WindowSize.Width-3-$line.Length))"}), "Yellow", "Black") )
}
0 { # Not actually a key
# Out-Buffer $($Char | Out-String)
}
default {
$line += $char.Character
$Host.UI.RawUI.SetBufferContents( $PromptPos, $Host.UI.RawUI.NewBufferCellArray( @(&{ "> $($line)$(' ' * ($WindowSize.Width-3-$line.Length))"}), "Yellow", "Black") )
}
}
}
}
# Simulate doing useful things 25% of the time
if($random.NextDouble() -gt 0.75) {
$noise[($index)..($index++)] | Out-Buffer
if($index -ge $noise.Length){$index = 0}
}
sleep -milli 100
}
# set the colors back ...
$Host.UI.RawUI.ForegroundColor = $fore
$Host.UI.RawUI.BackgroundColor = $back