Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
morse code in powershell
Symbol Sequence
A 01
B 1000
C 1010
D 100
E 0
F 0010
G 110
H 0000
I 00
J 0111
K 101
L 0100
M 11
N 10
O 111
P 0110
Q 1101
R 010
S 000
T 1
U 001
V 0001
W 011
X 1001
Y 1011
Z 1100
function ShowHelp() {
echo "Insufficient arguments passed."
echo ""
echo "Usage: "
echo " .\morse.ps1 ""words"" [path\to\table.csv]"
echo ""
echo "``morse`` takes a series of words as input through the first command line"
echo "parameter and causes the Caps Lock key to blink accordingly."
echo ""
echo " words the words to display"
echo " [path\to\table.csv] uses the referenced file as the morse table."
echo " default: $DefaultCsvPath"
echo ""
echo "Examples:"
echo " .\morse.ps1 ""SOS send help"""
echo " .\morse.ps1 ""wot is this???"" .\punct.csv"
}
# Definitions:
# - A `symbol` is one of $LongBlinkSymbol or $ShortBlinkSymbol
# - A `sequence` is a series of concatenated symbols
# - A `letter` is any character
# - A `letter` is valid if and only if it occurs in MorseTable
# - A `word` is a series of concatenated letters
# - A `sentence` is a series of `words` joined by whitespace characters
$TimeUnit = 200 # in milliseconds
$ShortBlinkDuration = 1 * $TimeUnit
$LongBlinkDuration = 3 * $TimeUnit
$BetweenSymbolsDuration = 1 * $TimeUnit
$BetweenLettersDuration = 3 * $TimeUnit
$BetweenWordsDuration = 7 * $TimeUnit
$LongBlinkSymbol = '1'
$ShortBlinkSymbol = '0'
$DefaultCsvPath = ".\morse.csv"
# strings which match this regex are valid symbol strings
$ValidSymbolRegex = "^($(
[Regex]::Escape($LongBlinkSymbol)
)|$(
[Regex]::Escape($ShortBlinkSymbol)
))*$"
# error types
$EmptyTableError = 1
$MalformedHeaderError = 2
$InvalidSequenceError = 3
$InvalidCharacterError = 4
$NoArgumentsPassedError = 5
# WScript interface for sending keys
$wshell = New-Object -ComObject wscript.shell
function SendKeys([string] $keys) {
$wshell.SendKeys($keys)
}
function CapsLock() {
SendKeys("{CAPSLOCK}")
}
function IsValidSequence([string] $code) {
$code -match $ValidSymbolRegex
}
# NOTE: MorseTable is indexed by characters, **not** singleton strings
$MorseTable = @{}
function LoadMorseTable([string] $pathToCsv) {
$csv = Import-Csv "$pathToCsv"
# ensure non-empty csv
if($csv.length -eq 0) {
Write-Error "Table read was empty"
exit $EmptyTableError
}
# ensure proper column naming
$head = $csv[0] # sample csv; we know the first element must exist
if($head.Symbol -eq $null -or $head.Sequence -eq $null) {
Write-Error "Malformed table header"
exit $MalformedHeaderError
}
# update $MorseTable
$csv | foreach {
# ensure proper formatting of Sequence
if(-not (IsValidSequence($_.Sequence))) {
Write-Error "Entry '$($_.Symbol)' has an invalid sequence '$($_.Sequence)'"
exit $InvalidSequenceError
}
$MorseTable[[char] $_.Symbol] = $_.Sequence
}
}
# given sequence of $LongBlinkSymbol and $ShortBlinkSymbol, blinks the light
# for the appropriate duration
function BlinkSequence([string] $code) {
for($i = 0; $i -lt $code.length; $i++) {
$char = $code[$i]
CapsLock
if($char -eq $LongBlinkSymbol) {
Sleep -m $LongBlinkDuration
}
else {
Sleep -m $ShortBlinkDuration
}
CapsLock
# do not wait after the last symbol
if($i + 1 -ne $code.length) {
Sleep -m $BetweenSymbolsDuration
}
}
}
function GetSequence([char] $char) {
return $MorseTable[$char]
}
function BlinkWord([string] $word) {
for($i = 0; $i -lt $word.length; $i++) {
$char = $word[$i]
$code = GetSequence($char)
BlinkSequence($code)
# do not wait after the last letter
if($i + 1 -ne $word.length) {
Sleep -m $BetweenLettersDuration
}
}
}
function BlinkSentence([string] $sentence) {
$words = $sentence.ToUpper().split()
# verify that no invalid symbols occur
$letterset = $words | % { $_.ToCharArray() } | Sort-Object | Get-Unique
$letterset | foreach {
if($MorseTable[$_] -eq $null) {
Write-Error "Input contains the invalid character '$_'"
exit $InvalidCharacterError
}
}
# all symbols must be valid
for($i = 0; $i -lt $words.length; $i++) {
$word = $words[$i]
BlinkWord($word)
# do not wait after the last word
if($i + 1 -ne $words.length) {
Sleep -m $BetweenWordsDuration
}
}
}
if($args.length -eq 0) {
ShowHelp
exit $NoArgumentsPassedError
}
$input = $args[0]
$pathToCsv = $DefaultCsvPath
if($args.length -ge 2) {
$pathToCsv = $args[1]
}
LoadMorseTable $pathToCsv
BlinkSentence $input
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment