PowerShell.exeの出力をHTMLに変換する

これからPowerShellについて書いていくにあたり、PowerShell.exeの画面をHTMLに変換するスクリプトを作ってみました。$hostを使っているので、PowerShell.exe以外ではうまく動かないかもしれません。というか、PowerShell.exeのGetBufferContentsと、SetBufferContentsのマルチバイト文字を含んだ場合の挙動は明らかにおかしいので、本来は不要な処理が入っています。

function add_r($text) { [void]$sb.Append(([string]$text).Replace(">", "&gt;").Replace("<", "&lt;")) }
function add($text) { [void]$sb.Append($text) }

function color($cell) { 
  if($cell.ForegroundColor -ne "DarkYellow"){ $f = $cell.ForegroundColor }
  else{ if($rui.ForegroundColor -ne "DarkYellow") { $f = $rui.ForegroundColor } else { $f = "White" } }

  if($cell.BackgroundColor -ne "DarkMagenta"){ $b = $cell.BackgroundColor }
  else{ if($rui.BackgroundColor -ne "DarkMagenta") { $b = $rui.BackgroundColor } else { $b = "#012456" } }

  return "background-color: $b ; color: $f ;"
}

$rui    = $host.UI.RawUI
$width  = $rui.WindowSize.Width
$height = $rui.CursorPosition.Y

$sb = New-Object System.Text.StringBuilder

add "<html><head><title>出力</title></head>`n"
add "<body>`n"
add ("<pre style='font-family: monospace; padding: 3px; " + (color $rui) + "'>`n")

$sta = 0
if($args[0] -ne $null){ $sta = $height - [int]($args[0]) }

for($i = $sta; $i -lt $height; $i++){
  $scr = $rui.GetBufferContents((New-Object System.Management.Automation.Host.Rectangle -ArgumentList 0, $i, $width, $i))
  add ("<span style='" + (color $scr[0, 0]) + "'>")

  for($j = $w = 0; ($j + $w) -lt $width; $j++){
    if($rui.LengthInBufferCells(($scr[0, $j]).Character) -eq 2){$w++}

    if($j -ne 0 -and
      (($scr[0, ($j - 1)].ForegroundColor -ne $scr[0, $j].ForegroundColor) -or ($scr[0, ($j - 1)].BackgroundColor -ne $scr[0, $j].BackgroundColor))){
      add ("</span><span style='" + (color $scr[$j, 0]) + "'>")
    }
    add_r ($scr[0, $j]).Character
  }

  add "</span>"
  add "`n"
}

add "</pre>`n"
add "</body>`n"
add "</html>`n"

$sb.ToString()

ものすごく遅いので、文字列の連結をStringBuilderにしてみたりしたのですが、全く改善されませんでした。初めて使用するときは一度Clear-Hostするなどして、コンソールの出力を減らしてから動かしたほうがいいかもしれません。
使用すると、こういう感じのHTMLを生成します。


Windows PowerShell
Copyright (C) 2006 Microsoft Corporation. All rights reserved.

2008/02/23 00:17:03 C:\work\ps
> .\ss.ps1 > out.html
引数に数字を渡すと、現在のn行前からHTMLに変換します。

> buono!
用語 'buono!' は、コマンドレット、関数、操作可能なプログラム、またはスクリプト ファイルとして認識さ
れません。用語を確認し、再試行してください。
発生場所 行:1 文字:6

+ buono! <<<<
2008/02/23 00:18:51 C:\work\ps
> .\ss.ps1 7 > out.html

はてなで使う場合は、<pre>の中でも脚注記法などが作用してしまうので、改善の必要があります。