# encoding: utf-8
# api: powershell
# title: Write-ASCII-Letters
# description: I initially wrote this ASCII art character script to be used with a modified version of PowerBot 2.0 (ID 2510 on poshcode). It outputs ASCII art letters from what you supply as a parameter (if the characters are supported). Either to STDOUT with Write-Host (colors are supported) or to the pipeline. It’s useless without the XML that’s found at powershelladmin.com. The full article is in my wiki: http://www.powershelladmin.com/wiki/Ascii_art_characters_powershell_script
# version: 0.1
# type: script
# author: Joakim Svendsen, Svendsen Tech
# license: CC0
# function: Parse-LetterXML
# x-poshcode-id: 6217
# x-archived: 2016-03-19T17:34:16
# x-published: 2016-02-15T09:22:00
#
#
#
#.SYNOPSIS
# Svendsen Tech's PowerShell ASCII art script creates ASCII art characters
# from a subset of common letters, numbers and punctuation characters.
# You can add new characters by editing the XML and updating the
# $AcceptedChars regexp.
#
# Author: Joakim Svendsen, Svendsen Tech
#
#.DESCRIPTION
# This script reads characters (it started out as letters so the variable
# names are not precise) from an XML file. If you include new characters
# in the XML, you will need to add them to the regular expression assigned
# to the variable $AcceptedChars.
#
# It was written to be used in conjunction with a modified version of
# PowerBot (http://poshcode.org/2510), a simple IRC bot framework written
# using SmartIrc4Net; that's why it prepends an apostrophe by default
# because somewhere along the way the leading spaces get lost before it
# hits the IRC channel.
#
# Currently the XML only contains lowercase letters.
#
# Example:
# PS E:\ASCII-letters> .\Write-ASCII-Letters.ps1 -NoPrependChar "ASCII!"
# _ _ _
# __ _ ___ ___ (_)(_)| |
# / _` |/ __| / __|| || || |
# | (_| |\__ \| (__ | || ||_|
# \__,_||___/ \___||_||_|(_)
# PS E:\ASCII-letters>
#
#.PARAMETER InputText
# String(s) to convert to ASCII.
#.PARAMETER NoPrependChar
# Makes the script not prepend an apostrophe.
#.PARAMETER TextColor
# Optional. Console only. Changes color of output.
#>
param(
[string[]] $InputText,
[switch] $NoPrependChar,
[string] $TextColor = 'Default'
#[int] $MaxChars = '25'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
# Populate the $Letters hashtable with character data from the XML.
Function Parse-LetterXML {
$LetterFile = '.\letters.xml'
$Xml = [xml] (Get-Content $LetterFile)
$Xml.Letters.Letter | ForEach-Object {
$Letters.($_.Name) = New-Object PSObject -Property @{
'Lines' = $_.Lines
'ASCII' = $_.Data
'Width' = $_.Width
}
}
}
# Algorithm from hell... This was painful. I hope there's a better way.
function Create-ASCII-Text {
param([string] $Text)
$LetterArray = [char[]] $Text.ToLower()
#Write-Host -fore green $LetterArray
# Find the letter with the most lines.
$MaxLines = 0
$LetterArray | ForEach-Object { if ($Letters.([string] $_).Lines -gt $MaxLines ) { $MaxLines = $Letters.([string] $_).Lines } }
$LetterWidthArray = $LetterArray | ForEach-Object { $Letter = [string] $_; $Letters.$Letter.Width }
$LetterLinesArray = $LetterArray | ForEach-Object { $Letter = [string] $_; $Letters.$Letter.Lines }
#$LetterLinesArray
$Lines = @{
'1' = ''
'2' = ''
'3' = ''
'4' = ''
'5' = ''
'6' = ''
}
#$LineLengths = @(0, 0, 0, 0, 0, 0)
$LetterPos = 0
foreach ($Letter in $LetterArray) {
# We need to work with strings for indexing the hash by letter
$Letter = [string] $Letter
# Each ASCII letter can be from 4 to 6 lines.
# If the letter has the maximum of 6 lines, populate hash with all lines.
if ($LetterLinesArray[$LetterPos] -eq 6) {
foreach ($Num in 1..6) {
$StringNum = [string] $Num
$LineFragment = [string](($Letters.$Letter.ASCII).Split("`n"))[$Num-1]
if ($LineFragment.Length -lt $Letters.$Letter.Width) {
$LineFragment += ' ' * ($Letters.$Letter.Width - $LineFragment.Length)
}
$Lines.$StringNum += $LineFragment
}
}
# Add padding for line 6 for letters with 5 lines and populate lines 2-6.
elseif ($LetterLinesArray[$LetterPos] -eq 5) {
$Padding = ' ' * $LetterWidthArray[$LetterPos]
$Lines.'1' += $Padding
foreach ($Num in 2..6) {
$StringNum = [string] $Num
$LineFragment = [string](($Letters.$Letter.ASCII).Split("`n"))[$Num-2]
if ($LineFragment.Length -lt $Letters.$Letter.Width) {
$LineFragment += ' ' * ($Letters.$Letter.Width - $LineFragment.Length)
}
$Lines.$StringNum += $LineFragment
}
}
# Here we deal with letters with four lines.
# Dynamic algorithm that places four-line letters on the bottom line if there are
# 4 or 5 lines only in the letter with the most lines.
else {
# Default to putting the 4-liners at line 3-6
$StartRange, $EndRange, $IndexSubtract = 3, 6, 3
$Padding = ' ' * $LetterWidthArray[$LetterPos]
# If there are 4 or 5 lines...
if ($MaxLines -lt 6) {
$Lines.'2' += $Padding
}
# There are 6 lines maximum, put 4-line letters in the middle.
else {
$Lines.'1' += $Padding
$Lines.'6' += $Padding
$StartRange, $EndRange, $IndexSubtract = 2, 5, 2
}
# There will always be at least four lines. Populate lines 2-5 or 3-6 in the hash.
foreach ($Num in $StartRange..$EndRange) {
$StringNum = [string] $Num
$LineFragment = [string](($Letters.$Letter.ASCII).Split("`n"))[$Num-$IndexSubtract]
if ($LineFragment.Length -lt $Letters.$Letter.Width) {
$LineFragment += ' ' * ($Letters.$Letter.Width - $LineFragment.Length)
}
$Lines.$StringNum += $LineFragment
}
}
$LetterPos++
} # end of LetterArray foreach
# Return stuff
$Lines.GetEnumerator() | Sort Name | Select -ExpandProperty Value | ?{ $_ -match '\S' } | %{ if ($NoPrependChar) { $_ } else { "'" + $_ } }
}
# Get ASCII art letters/characters and data from XML.
$Letters = @{}
Parse-LetterXML
# Turn the [string[]] into a [string] the only way I could figure out how... wtf
$Text = ''
$InputText | ForEach-Object { $Text += "$_ " }
# Limit to 30 characters
$MaxChars = 30
if ($Text.Length -gt $MaxChars) { "Too long text. There's a maximum of $MaxChars characters."; exit }
# Replace spaces with underscores.
$Text = $Text -replace ' ', '_'
# Define accepted characters (which are found in XML).
$AcceptedChars = '[^a-z0-9 _,!?./;:<>(){}\[\]''\-\\"æøå]' # æøå only works when sent as UTF-8 on IRC
if ($Text -match $AcceptedChars) { "Unsupported character, using this 'accepted chars' regex: $AcceptedChars."; exit }
# Filthy workaround (now worked around in the foreach creating the string).
#if ($Text.Length -eq 1) { $Text += '_' }
$Lines = @()
$ASCII = Create-ASCII-Text $Text
if ($TextColor -ne 'Default') { Write-Host -ForegroundColor $TextColor ($ASCII -join "`n") }
else { $ASCII }