These guidelines are about readability. Some of them are arbitrary rules, but they are based on decades of traditions in programming, so while you may disagree with some rules (and should always follow the rules of individual projects), when we ask you to leave an empty line after a closing function brace, or two lines before functions, we're not being capricious, we're doing so because it makes it easier for experienced developers to scan your code.
Rules about indentation, line length, and capitalization are about consistency across code bases. Long practice has shown that it's easier to read and understand code when it looks familiar and you're not being distracted by details, which means that it's better for everyone in the community to follow a single set of rules.
We don't expect everyone to follow these guidelines, and rules for individual projects always trump these. Whether for legacy reasons, or to match guidelines for multiple languages in a single project, different projects may have different style guidelines. Since the goal is consistency, you should always abide by any style rules that are in place on the project you are contributing to.
If you do have a legacy project that is in source control and you decide to reformat code to adopt these rules, try to make all of your whitespace changes in a single a commit that does nothing but edit the whitespace. You should never reformat the whitespace on a file as part of a content change because it makes the changes hard to spot.
PowerShell is not case sensitive, but we follow capitalization conventions to make code easy to read. They are based on the capitalization conventions Microsoft created for the .NET framework, since PowerShell is a .NET scripting language, and PowerShell cmdlets are primarily written in .NET languages following those guidelines.
- lowercase - all lowercase, no word separation
- UPPERCASE - all capitals, no word separation
- PascalCase - capitalize the first letter of each word
- camelCase - capitalize the first letter of each word except the first.
PowerShell uses PascalCase for all public identifiers: module names, function or cmdlet names, class, enum, and attribute names, public fields or properties, global variables and constants, etc. In fact, since the parameters to PowerShell commands are actually properties of .Net classes, even parameters use PascalCase rather than camelCase.
PowerShell language keywords are written in lower case (yes, even foreach
and dynamicparam
), as well as operators such as -eq
and -match
. The keywords in comment-based help are written in UPPERCASE to make it easy to spot them among the dense prose of documentation.
function Write-Host {
<#
.SYNOPSIS
Writes customized output to a host.
.DESCRIPTION
The Write-Host cmdlet customizes output. You can specify the color of text by using
the ForegroundColor parameter, and you can specify the background color by using the
BackgroundColor parameter. The Separator parameter lets you specify a string to use to
separate displayed objects. The particular result depends on the program that is
hosting Windows PowerShell.
#>
[CmdletBinding()]
param(
[Parameter(Position=0, ValueFromPipeline=$true, ValueFromRemainingArguments=$true)]
[PSObject]
$Object,
[Switch]
$NoNewline,
[PSObject]
$Separator,
[System.ConsoleColor]
$ForegroundColor,
[System.ConsoleColor]
$BackgroundColor
)
begin
{
...
As stated previously, PowerShell uses PascalCase for all public identifiers. Function names should follow PowerShell's Verb-Noun
naming conventions, using PascalCase within both Verb and Noun.
A special case is made for two-letter acronyms in which both letters are capitalized, as in the variable $PSBoundParameters
or the command Get-PSDrive
. Note that (as specified in the .NET guidelines) this does not affect the commonly capitalized (but not acronym) words "OK" and "ID" . You should also not extend it to compound acronyms, such as when Azure's Resource Manager (RM) meets a Virtual Machine (VM) in Start-AzureRmVM
...
We are aware that there are many places where these conventions have not been followed properly for various reasons -- you should consider these exceptions (such as for COM interop) or mistakes (such as
System.Data.SqlClient.SQLDebugging
), but not a reason for you to disregard the conventions.
If you wish, you may use camelCase for variables within your functions (or modules) to distinguish private variables from parameters, but this is a matter of taste. Shared variables should be distinguished by using their scope name, such as $Script:PSBoundParameters
or $Global:DebugPreference
. If you are using camelCase for a variable that starts with a two-letter acronym (where both letters are capitalized), both letters should be set to lowercase (such as adComputer
).
All of your scripts or functions should start life as something like this snippet:
[CmdletBinding()]param()
process{}
end{}
You can always delete or ignore one of the blocks (or add the begin
block), add parameters and so on, but you should avoid writing scripts or functions without CmdletBinding, and you should always at least consider making it take pipeline input.
Code folding is nicer in many editors. (TODO: This is in discussion in #24)
Because that's how they're supposed to be! (TODO: This is in discussion in #24)
That's the order PowerShell will execute it in (TODO)
This is what PowerShell ISE does and understands, and it's the default for most code editors. As always, existing projects may have different standards, but for public code, please stick to 4 spaces, and the rest of us will try to do the same.
The 4-space rule is optional for continuation lines. Hanging indents (when indenting a wrapped command which was too long) may be indented more than one indentation level, or may even be indented an odd number of spaces to line up with a method call or parameter block.
# This is ok
$MyObj.GetData(
$Param1,
$Param2,
$Param3,
$Param4
)
# This is better
$MyObj.GetData($Param1,
$Param2,
$Param3,
$Param4)
Limit lines to 115 characters when possible.
The PowerShell console is, by default, 120 characters wide, but it allows only 119 characters on output lines, and when entering multi-line text, PowerShell uses a line continuation prompt: >>>
and thus limits your line length to 116 anyway.
Most of us work on widescreen monitors these days, and there is little reason to keep a narrow line width, however, keeping files relatively narrow allows for side-by-side editing, so even narrower guidelines may be established by a given project. Be sure to check when you're working on someone else's project.
The preferred way to avoid long lines is to use splatting (see About Splatting) and PowerShell's implied line continuation inside parentheses, brackets, and braces -- these should always be used in preference to the backtick for line continuation when applicable, even for strings:
Write-Host ("This is an incredibly important, and extremely long message. " +
"We cannot afford to leave any part of it out, nor do we want line-breaks in the output. " +
"Using string concatenation let's us use short lines here, and still get a long line in the output")
Surround function and class definitions with two blank lines.
Method definitions within a class are surrounded by a single blank line.
Blank lines may be ommitted between a bunch of related one-liners (e.g. empty functions)
Additional blank lines may be used sparingly to separate groups of related functions, or within functions to indicate logical sections (e.g. before a block comment).
End each file with a single blank line.
Lines should not have trailing whitespace. Extra spaces result in future edits where the only change is a space being added or removed, making the analysis of the changes more difficult for no reason.
You should use a single space around parameter names and operators, including comparison operators and math and assignment operators, even when the spaces are not necessary for PowerShell to correctly parse the code.
One notable exception is when using colons to pass values to switch parameters:
# Do not write:
$variable=Get-Content $FilePath -Wai:($ReadCount-gt0) -First($ReadCount*5)
# Instead write:
$variable = Get-Content -Path $FilePath -Wait:($ReadCount -gt 0) -TotalCount ($ReadCount * 5)
White-space is (mostly) irrelevant to PowerShell, but its proper use is the key to writing easily readable code.
Use a single space after commas and semicolons, and around pairs of curly braces.
Avoid extra spaces inside parenthesis or square braces.
Nested expressions $( ... )
and script blocks { ... }
should have a single space inside them to make code stand out and be more readable.
Nested expressions $( ... )
and variable delimiters ${...}
inside strings do not need spaces outside, since that would become a part of the string.
PowerShell will not complain about extra semicolons, but they are unnecessary, and get in the way when code is being edited or copy-pasted. They also result in extra do-nothing edits in source control when someone finally decides to delete them.
They are also unecessary when declaring hashtables if you are already putting each element on it's own line:
# This is the preferred way to declare a hashtable if it must go past one line:
$Options = @{
Margin = 2
Padding = 2
FontSize = 24
}