Home > PowerShell, Windows 7, Windows Server > Updated: PowerShell “Code-Cat” With Colors and Line Breaks

Updated: PowerShell “Code-Cat” With Colors and Line Breaks

October 13, 2009

Motivated by Jeffery Hicks’ fun with my original “code-cat” version, I decided to fill in a few of the original updates I had floating in my head.

The full code is available here via CodePaste.Net.

First off, I loved the idea of colorizing the comments in a file; however, I wanted to keep my line numbers out of the “coloring” and simply color the comments.  To do this, I had to break apart the line numbers from the actual output.

Coloring Code Cat Comments

Second, I really wanted a cleaner way to wrap lines in my code and to have those lines still lineup with everything else. 

Line Wraps

The full code is available via CodePaste.Net (click here), but let’s step through it and see how things work.

SplitString Function

You’ll notice at the top, I’ve included a custom helper function that takes a string and splits it into an array.  I use this to break up “long” strings into window-sized strings.

function splitString([string]$string, [int]$length)
{
 $lines = @();
 $stringLength = $string.Length;
 $position = 0;

 while ($position -lt $stringLength)
 {
  if (($position + $length) -lt $stringLength)
  {
   $lines += $string.substring($position, $length);
  }
  else
  {
   $lines += $string.substring($position);
  }
  $position += $length;
 }

 return $lines;
}

This method is actually in my PowerShell profile for use in numerous parsing activities.

Colors and Window Size

Unlike the original method, I’ve pulled out the colors into variables so they are easily configured.  I am also using the built-in PowerShell $Host object to determine the width of my console window.  I’ll use this later for the line breaks.

$codeColor = “Gray”;                
$counterColor = “White”;
$commentColor = “Green”;
$newLineColor = “Yellow”;

# Window size, minus the counter, spacing, and a bit extra padding.
$maxLineSize = $Host.UI.RawUI.WindowSize.Width – 12;

Parsing The Code File

There are a few important points in the $content body, here we go!

Replacing Tabs With Spaces

I found that the Substring and Length functions got really quirkly (is a tab 1 character or five, etc) when they came across several tabs (which, tabbing is pretty common in a code file, especially some SQL files).  To remedy this, I replace tabs with five spaces.  This also allows me to control the tabs a bit more, so if I wanted to ease my code output to the left, I could use three or four spaces.

# remove tabs, they’re counted as one character, not five.
$currentLine = $_.Replace(“`t”, ”    “);

Setting the Color of Comments

Using Jeffery’s example, I’m also setting my comments (for PowerShell, C#, and TSQL) to a bright color.

# Color-code comments green (PowerShell, C#, SQL)
if ($currentLine.Trim().StartsWith(“#”) -or `
    $currentLine.Trim().StartsWith(“//”) -or `
    $currentLine.Trim().StartsWith(“–“))
{
     $foregroundColor = $commentColor;
}

Separating Line Numbers From Content

I didn’t want my line numbers to show up green for comments and I wanted to treat them with a different color than the rest of the code body, so I’m taking advantage of the “-nonewline” feature of write-host. This returns the content without forcing a new line break into the result.  Very handy.

write-host (“{0:d4} | ” -f $counter) -nonewline -foregroundColor $counterColor;

Checking for Line Breaks and Handling Them

The next bit is in “beta” for the time being.  The gist is that it looks at the length of the current line vs. the maximum line size we specified in the variables. 

If the current line is longer, it breaks the line into an array of “max line size” lines.  The first line is output using our normal methods—we want our counter to show up, right?  The ‘overflow’ lines are output using a fancy arrow “\—>” and do not include a counter—simply because they are not ‘new lines’.

Of course, if our line is shorter than our window size, it is simply output.

if ($currentLine.Length -ge $maxLineSize)
{
 $splitLines = splitString $currentLine $maxLineSize;
    $countOfLines = $splitLines.Length;
 for ($i = 0; $i -lt $countOfLines; $i++)
    {
  if ($i -eq 0)
  {
   # our first line doesn’t look any different.
   write-host (“{0}” -f $splitLines[$i]) -foregroundColor $foregroundColor;
  }
  else
  {
   # next lines are using the fancy arrow.
   write-host (“\–> |   “) -nonewline -foregroundColor $newLineColor;
   write-host (“{0}`n” -f $splitLines[$i]) -nonewline -foregroundColor $foregroundColor;
  }
 }
}
else
{
 write-host (“{0}” -f $_) -foregroundColor $foregroundColor;
}

Again, the full code is available here via CodePaste.Net.

Like all things, a work in progress!

%d bloggers like this: