PowerShell: Writing code snippets in the ISE

This is my scratchpad for a simple talk I’ll be doing on creating code snippets for use in the ISE.

Code

PsPresentation01

Code

PsPresentation02.PNG

code

PsPresentation05.PNG

Example with intentional error to show the contrast:

PsPresentation04.PNG

Advertisements

Visual Studio Code: code snippets

Found this (admittedly staring me in the face right now… but it wasn’t a while back, I’m sure)

So looking in VSCode:

So lest I make a mess of it, quick back up of the text:

{
// Place your snippets for C# here. Each snippet is defined under a snippet name and has a prefix, body and
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, ${id} and ${id:label} and ${1:label} for variables. Variables with the same id are connected.
// Example:
"Print to console": {
"prefix": "log",
"body": [
"console.log('$1');",
"$2"
],
"description": "Log output to console"
}

Then add a simple property snippet, using a slightly different shortcut than [prop], as that automatically gets picked up, I’ll find out how another time.

You don’t need to restart VSCode to get this working. It updates on the fly. The ONE thing this lacks right now is the ReSharper type macro language that is very useful for doing the private backing field/public property thing (I know what I mean 🙂 )

"Simple Property by Dennis": {
"prefix": "propdennis",
"body": [
"public ${type:string} ${name} {get;set;}"
],
"description": "Create a Dennis simple property"
}


In fact I will show you exactly what I mean...

My standards say that a private variable starts with an underscore followed by a lower case character, as shown above. However, the best that I can achieve with this snippet manager, with the minimum number of keystrokes, is this, because unlike ReSharper, there is no macro language or mechanism to achieve the above, so I get this:

CodeSnippetsinVsCode11

And this is how you achieve the immediately above anyway:

CodeSnippetsinVsCode12

In the docs, they talk about using $1 etc to represent tab-stops, but that doesn’t work for me, and they have not included a working example. This is good enough:

"Simple Property by Dennis": {
"prefix": "propWithBacker",
"body": [
"\t\tprivate ${type:string} _${name};\n",
"\t\tpublic ${type:string} ${name} {",
"\t\t\tget {",
"\t\t\t\treturn _${name};",
"\t\t\t}",
"\t\t\tset { ",
"\t\t\t\t_${name} = ${name};",
"\t\t\t}",
"\t\t}\n"
],
"description": "Create a property with backing field"
}

Hm, actually you don’t need that string of tabs. The snippet placement is sensitive to the position of your cursor, so this will do:

"Simple Property by Dennis": {
"prefix": "propWithBacker",
"body": [
"private ${type:string} _${name};\n",
"public ${type:string} ${name} {",
"\tget {",
"\t\treturn _${name};",
"\t}",
"\tset { ",
"\t\t_${name} = ${name};",
"\t}",
"}\n"
],
"description": "Create a property with backing field"
}


May 2016...
I didn't want to start a new page, but this is a good starting set of Angular and BootStrap er things, to get started (in Emmet and VSC - this goes in the html.json page)

{
 "Basic HTML boilerplate": {
 "prefix": "BasicHtml",
 "body": [
 "<!DOCTYPE html>",
 "<html>",
 "\t<head>",
 "\t\t<title>From the snippets location in Visual Studio Code</title>",
 "\t\t<meta charset=\"utf-8\">",
 "\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
 "\t\thttps://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.jsx",
 "\t\t<link rel=\"stylesheet\" href=\"http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css\"></link>",
 "\t\thttp://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js",
 "\t\thttp://BasicStuff.js",
 "\t</head>",
 "\t<body>",
 "\t\t<input type=\"button\" value=\"Press me\" id=\"BasicHtmlPressMeId\">",
 "\t\t<input type=\"text\" value=\"Press mex\" id=\"BasicHtmlCapacityId\">",
 "\t</body>",
 "</html>",
 "<!-- https://validator.w3.org/nu/#textarea -->",
 "<!-- Location is [file:///e:/sandbox/javascript/test.html] -->"
 ],
 "description": "A basic snippet of HTML"
 },
 "BSButtons": {
 "prefix": "B01",
 "body": [
 "
“, “\t

A bunch of big Bootstrap buttons

“, ”

“, “<p>”, “\t<button type=\”button\” class=\”btn btn-lg btn-default\”>Default</button>”, “\t<button type=\”button\” class=\”btn btn-lg btn-primary\”>Primary</button>”, “\t<button type=\”button\” class=\”btn btn-lg btn-success\”>Success</button>”, “\t<button type=\”button\” class=\”btn btn-lg btn-info\”>Info</button>”, “\t<button type=\”button\” class=\”btn btn-lg btn-warning\”>Warning</button>”, “\t<button type=\”button\” class=\”btn btn-lg btn-danger\”>Danger</button>”, “</p>” ], “description”: “Initial bootstrap buttons” }, “Ang01”: { “prefix”: “Ang01”, “body”: [ “\thttps://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.js” ], “description”: “Angular CDN” }, “BSScriptTags”: { “prefix”: “BSScript”, “body”: [ “\t\thttps://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.jsx“, “\t\t<link rel=\”stylesheet\” href=\”http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css\”></link>”, “\t\thttp://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js” ], “description”: “The Bootstrap src, css and jquery bits” } }

PowerShell: The basic template in ISE

The basic Ctrl-J template in the PowerShell ISE is a bit noisier than I need. This is all I want:

PSTemplate01

<#
.Synopsis
Drop set of databases
.Example
Drop-Database -DatabasePrefix “TestSet”
#>
function Drop-Database
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param (
[Parameter(Mandatory=$true)]
$DatabasePrefix
)
Begin {
}
Process {
}
End {
}
}

Beyond that, you can use the New-IseSnippet function to make it part of the ISE, and use Ctrl-J to invoke it. Straight from msdn…

$m = @'
Param
(
  [parameter(Mandatory=$true)]
  [String[]]
  $<ParameterName>
)
'@

PS C:\>New-ISESnippet -Text $m -Title Mandatory -Description "Adds a mandatory function parameter." -Author "Kim Akers, Fabrikam Corp." -Force

So applying that principle to our very basic snippet at the top, we get..


$m = @'
<# .Synopsis Drop set of databases .Example Drop-Database -DatabasePrefix "TestSet" #>
function Drop-Database {
[CmdletBinding(SupportsShouldProcess)]
Param (
[Parameter(Mandatory)]
$DatabasePrefix
)
Begin {
}
Process {
}
End {
}
}
'@

New-ISESnippet -Text $m -Title DropDatabases -Description “A snippet to drop databases.” -Author “Dennis Wells, The Things I Do” -Force

Not so fast… So this was OK to execute…

PowerShellSnippetISE01

 

But then…

PowerShellSnippetISE02

Exception calling “Load” with “1” argument(s): “Unable to find or access the file C:\Users\denni\Documents\WindowsPowerShell\Snippets\DropDatabases.snippets.ps1xml”
At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ISE\ISE.psm1:102 char:9
+ $psise.CurrentPowerShellTab.Snippets.Load($params[“FilePath”] …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException

Looking at the file location, the offending file is clearly there…

PowerShellSnippetISE03

, with this content:

PowerShellSnippetISE04

Executing the command line a second time also gives the error.

Hang on…

I recently rebuilt this machine.

If we try this…

New-Item -ItemType File -Path $profile -Force

PowerShellSnippetISE05

And from then on just refer to my old post here

PowerShellSnippetISE07

PowerShellSnippetISE08

PowerShellSnippetISE09

, and as admin..

PowerShellSnippetISE10

Now we shall try again…

PowerShellSnippetISE11

That means I expect to find a snippet with a title of [Mandatory] when I press Ctrl-J in the ISE.

PowerShellSnippetISE12

Hm, so that all works, but it doesn’t seem keen on the carats in the $<parametername>. Fine, don’t care.

I won’t bother with the evidence, but following that little trial, I then ran the DropDatabases snippet through the New-ISESnippet command, and it also appears in the selection list, and can be invoked.

No matter how irritating it is to get these automation-related things working, they SO pay you back for the effort.

PowerShell: simple folder structure for an html project

I liked the folder template that Deborah Kurata outlined for an html project in her PluralSight course on LOB applications in  Angular.

As I might want to do that a number of times, it feels like creating an identical folder structure for each application we write is a good candidate for a PowerShell cmdlet. For now, let’s just get the raw commands. Below, $htmlDevRoot would normally be constant on any one machine, and therefore would be a default parameter, $appDir is the name of the folder immediately below that, and which is not defaulted, and everything else follows her pattern:

# user defined…
$htmlDevRoot = “d:\build\HtmlDevDir” #defaulted once configuration is done for the current machine, assumes that $htmlDevRoot exists by the time PS gets to it: fail and exit if path not found
$appDir = “BikeMaintenance” # parameter – different for each new application
# don’t edit below here..
$fullAppDirPathRoot = “$htmlDevRoot\$appDir”
New-Item -Path $fullAppDirPathRoot -ItemType Dir
New-Item -Path $fullAppDirPathRoot\index.html -ItemType File
New-Item -Path “$fullAppDirPathRoot\app” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\app\feature1” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\app\feature2” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\common” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\common\services” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\css” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\fonts” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\images” -ItemType Dir
New-Item -Path “$fullAppDirPathRoot\js” -ItemType Dir
gci $fullAppDirPathRoot -Recurse

Since the original edit, I’ve added a line to create an empty index.html. Why not.

index01

HtmlPs02

That can be reduced to this, comments removed this time:

$htmlDevRoot = "d:\build\HtmlDevDir"
$appDir = "BikeMaintenance"
$fullAppDirPathRoot = "$htmlDevRoot\$appDir"
New-Item -Path $fullAppDirPathRoot -ItemType Dir
$subfolders = @("app","app\feature1", "app\feature2", "common", "common\services","css","fonts","images","js")
$subfolders | % {New-Item -Path "$fullAppDirPathRoot\$_" -ItemType Dir}

HtmlPs03

HtmlPs04