Posts Tagged ‘Syntax’

The style I use has a nice black background...

The style I use has a nice black background...

A while back Thell Fowler (with a little help, and a lot of testing from me) wrote a very good PowerShell Lexer for Notepad++ 5.2 and later… it’s very thorough, has good code-folding, and full support for PowerShell 2.0 syntax highlighting.

I mention this because Notepad++ 5.6 just released yesterday, and it has built-in support for PowerShell syntax courtesy of Scintilla ... but it’s very, very bad. The scintilla PowerShell lexer is probably the most minimal PowerShell lexer I’ve seen (it’s worse than the old “user style” I had created for Notepad++) and has no support for:

  • The ` escape character
  • Here-strings (which can contain quotes, etc)
  • The difference between strings and literal strings and literal here-strings
  • The begin/process/end block keywords and Param()
  • PowerShell operators (like -is or -gt or -notcontains)
  • [System.Namespace.Class]::Method() syntaxes
  • Nested $variables inside strings
  • Nested $( code blocks ) inside strings (with strings inside those, and …)
  • Any of the new PowerShell 2 syntax like:
    • multi-line comments
    • [Parameter()] and [Alias()] and [Validate …. ]
  • [CmdletBinding()]

There’s probably more, but I couldn’t be bothered to spend more than a couple of minutes with it. As you can probably guess … all of those features are supported by the external PowerShell Lexer plugin that Thell wrote, so if you’re a PowerShell and Notepad++ user, I apologize for not drawing your attention to our PowerShell Lexer for Notepad++ before :) .

Incidentally, I stuck a screenshot in this post so you can see how I use it, but there’s one a more complete example of the PowerShell Syntax Highlighting on that lexer download page. ;-)

Reblog this post [with Zemanta]

WPF uses a concept called “Attached Properties” to handle certain things, like when you put controls into a DockPanel. Basically, anything you put inside a DockPanel has a property “Dock” which you can set … but because the property is actually defined by the DockPanel, it doesn’t show up in PowerBoots, so you can’t just say -Dock "Bottom" when you create the child items … at least, not yet.

I’m still thinking about the best way for me to expose this in PowerBoots, because the problem is that attached properties can get attached several ways, and not just on direct children of an element. So I wanted to show you a way that you can do it for now so you can at least use the DockPanel effectively:

Boots {
   DockPanel -LastChildFill $true {
      DockPanel -LastChildFill $true {
         Button "OK" -Padding "2,0,2,0" |
            ForEach-Object { $_.SetValue(
               [System.Windows.Controls.DockPanel]::DockProperty,
               [System.Windows.Controls.Dock]::Right)
               $_
            }
         TextBox -HorizontalAlignment Stretch
      } | ForEach-Object { $_.SetValue(
               [System.Windows.Controls.DockPanel]::DockProperty,
               [System.Windows.Controls.Dock]::Bottom)
               $_
            }
      TextBox -AcceptsReturn $true -minWidth 300 -minHeight 200
   }
}

A better way …

Here’s what I’m thinking about for the next release of PowerBoots (you can take this and use it now, if you like it, but I’m really looking for, uhm … better ideas). Basically, I have written a function: Set-AttachedProperty, which takes an attached property and a value, and passes through the element on the pipeline. You may want to use this in conjunction with the module I published awhile back for creating type accelerators, because it lets you run a line like this:

Add-Accelerator DockPanel System.Windows.Controls.DockPanel

Which will let you substitute [DockPanel] for [System.Windows.Controls.DockPanel] … and of course, you can use it for all the types you want to use attached properties from, and it’s a real lifesaver if you need to use a bunch of them. Of course, in this particular example, we really only need to use a single attached property, so it’s enough to define that property ahead of time:

$DockProperty = [System.Windows.Controls.DockPanel]::DockProperty

Then you can use the Set-AttachedProperty function through an alias sap, and rewrite that huge block above like this:

Boots {
   DockPanel -LastChildFill $true {
      DockPanel -LastChildFill $true {
         Button "OK" -Padding "2,0,2,0" | sap $DockProperty Right
         TextBox -HorizontalAlignment Stretch
      } | sap $DockProperty Bottom
      TextBox -AcceptsReturn $true -minWidth 300 -minHeight 200
   }
}

Pretty slick, right? And it will even print out the list of values in the error message if you invoke it with an invalid value against an enum property like dock: sap $DockProperty "" … The problem I have with it is that you have to predefine your $DockProperty variable, and you can’t just define it against the root class. So I’m trying to find a way to tweak the dynamic property generation to make it so that the pipe into | sap $DockProperty Bottom can just be a parameter to the original element: -Dock Bottom … if I can’t find that, in the worst case scenario, I’ll just add an -AttachedProperties parameter with a hashtable of $DockProperty,“Bottom” or something … what do you think?

In any case, here’s the sap function, for now, and remember to use it as part of the pipeline:


function Set-AttachedProperty {
[CmdletBinding()]
PARAM(
   [Parameter(Position=0,Mandatory=$true)
   [System.Windows.DependencyProperty]
   $Property
,
   [Parameter(Mandatory=$true,ValueFromPipeline=$true)
   $Element
)
DYNAMICPARAM {
   $paramDictionary = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
   $Param1 = new-object System.Management.Automation.RuntimeDefinedParameter
   $Param1.Name = "Value"
   # $Param1.Attributes.Add( (New-ParameterAttribute -Position 1) )
   $Param1.Attributes.Add( (New-Object System.Management.Automation.ParameterAttribute -Property @{ Position = 1 }) )
   $Param1.ParameterType = $Property.PropertyType
           
   $paramDictionary.Add("Value", $Param1)
   
   return $paramDictionary
}
PROCESS {
   $Element.SetValue($Property, $Param1.Value)
   $Element
}
}

New-Alias sap Set-AttachedProperty
 
Search My Content