Skip to content

v1.0.0-beta1

Pre-release
Pre-release

Choose a tag to compare

@SeeminglyScience SeeminglyScience released this 08 Mar 19:22
· 5 commits to 0.5.0 since this release
160c960

v1.0.0-beta1

Refactorings

This module now has (optionally) a single entry point. The Invoke-DocumentRefactor editor command/function
will present a menu of context based (e.g. cursor position, current selection, etc) options to refactor
the current script.

This can be accessed by directly invoking the Invoke-DocumentRefactor command, selecting the Get Context Specific Refactor Options editor command, or with a key press bindable from keybinds.json:

{
    "key": "ctrl+shift+.",
    "command": "PowerShell.InvokeRegisteredEditorCommand",
    "args": { "commandName": "Invoke-DocumentRefactor" },
    "when": "editorLangId == 'powershell'",
},

Settings

There are now many different settings for the various refactor options/editor commands. The settings
file can be scoped at the project, user, and machine level. To create a settings file, use the New-CommandSuiteSettingsFile command.

Here is an example default file:

@{
    # The relative path from the current workspace to the root directory of the module.
    # MainModuleDirectory = '.\module'

    # The relative path from the current workspace to the main module manifest file.
    # SourceManifestPath = '.\module\*.psd1'

    # The relative path from the current workspace to the string localization psd1 file.
    # StringLocalizationManifest = '.\module\en-US\Strings.psd1'

    # The relative path from the current workspace to the directory where markdown files are stored.
    # MarkdownDocsPath = '.\docs'

    # The relative path(s) from the current workspace to the directory(ies) where functions are stored.
    # FunctionPaths = '.\module\Public', '.\module\Private'

    # The string used to created line breaks. Defaults to "[Environment]::NewLine"
    # NewLine = [Environment]::NewLine

    # The string used to created indents. Defaults to four spaces.
    # TabString = '    '

    # Specifies whether namespaces will automatically be removed when writing type literal
    # expressions. Removed namespaces will be automatically added as a using statement.
    # EnableAutomaticNamespaceRemoval = $true

    CommandSplatRefactor = @{
        # The variable name to use when creating the splat expression variable. The default behavior
        # is to name the string similar to "getCommandNameHereSplat". Setting this to $null will
        # enforce the default behavior.
        # VariableName = $null

        # Specifies whether a new line should be placed between the hashtable and the original command
        # expression.
        # NewLineAfterHashtable = $true

        # Specifies if additional parameters that have not been should be added to the splat
        # expression. The following options are available:
        #     "None" - Only bound parameters. This is the default.
        #     "Mandatory" - Mandatory parameters that have not yet been bound will be added.
        #     "All" - All resolved parameters will be added.
        # AdditionalParameters = "None"

        # Specifies whether the value for additional unbound parameters should be a variable of the
        # same name as the parameter, or if it should be decorated with mandatoriness and parameter
        # type.
        #     $true - Path = $path
        #     $false - Path = $mandatoryStringPath
        # ExcludeHints = $false
    }

    ExpandMemberExpression = @{
        # AllowNonPublicMembers = $false
    }

    UsingStatements = @{
        # Specifies whether groups of using statement types should be separated with a new line character.
        # SeparateGroupsWithNewLine = $true

        # Specifies whether using statements that start with "System" should be ordered first
        # regardless of alphabetical order.
        # SystemNamespaceFirst = $true

        # The order in which groups of using statement types will appear.
        # UsingKindOrder = 'Assembly', 'Module', 'Namespace'
    }
}

New refactor options

Splat all or mandatory parameters

An additional option for the original splat refactor is to include all other resolved parameters (or only resolved mandatory parameters).

Many thanks to @Jawz84 for contributing this really awesome feature!

For example, splatting Get-ChildItem with the all resolved parameters option looks like this:

$getChildItemSplat = @{
    Path = $stringArrayPath
    Filter = $stringFilter
    Include = $stringArrayInclude
    Exclude = $stringArrayExclude
    Recurse = $switchParameterRecurse
    Depth = $uInt32Depth
    Force = $switchParameterForce
    Name = $switchParameterName
    Attributes = $flagsExpressionAttributes
    FollowSymlink = $switchParameterFollowSymlink
    Directory = $switchParameterDirectory
    File = $switchParameterFile
    Hidden = $switchParameterHidden
    ReadOnly = $switchParameterReadOnly
    System = $switchParameterSystem
}

Get-ChildItem @getChildItemSplat

Change string enclosure type

Presented when the cursor is within a string expression, allows conversions between single quote,
double quote, and both here-string variants. When converting double quote to single quote, nested
expressions will be converted to a format expression.

For example this:

"This is a long $complicated string
$(2 + 3) ${testing}"

When converted to a literal (single quote) will translate to:

'This is a long {0} string
{1} {2}' -f $complicated, $(2 + 3), ${testing}

Drop namespace

Presented when the cursor is within a type expression (e.g. [System.Text.StringBuilder]), this will
remove the namespace (System.Text) and add a using namespace statement to the top of the file.

If the type expression is already simplified but the using statement is missing, an option will be presented
to add it. If the using statement is not missing, the option will be to fully qualify the type expression.

[System.Text.StringBuilder]
using namespace System.Text

[StringBuilder]

Format method arguments

Presented when the cursor is within an invoke method expression with multiple arguments (e.g. ''.StartsWith('something', [StringComparision]::OrdinalIgnoreCase)), selecting this option will allow formatting each argument
on it's own line or the reverse.

[string]::Format([cultureinfo]::CurrentCulture, '{0}{1}{2}{3}', 'one', 'two', 'three', 'four')
[string]::Format(
    [cultureinfo]::CurrentCulture,
    '{0}{1}{2}{3}',
    'one',
    'two',
    'three',
    'four')

Name unnamed block

When the cursor is within a script block that does not contain an begin, process or end block,
an option to add an end block around it will be presented.

Get-ChildItem
end {
    Get-ChildItem
}

Change block type

When the cursor is hovering over the name of a block (e.g. begin, process or end) the option will
be presented to change it to one of the other two.

end {
    Get-ChildItem
}
process {
    Get-ChildItem
}

Surround selection

When text has been selected, an option will be presented to surround the selection. Some of the options include:

  • if
  • while
  • foreach
  • paren expression (())
  • array expression (@())
  • subexpression ($())
Get-ChildItem
foreach ($ in $all) {
    Get-ChildItem
}

Currently missing editor commands

In the overhaul mentioned above, every editor command needed to be rewritten from scratch. Some editor
commands are not yet included.

This includes the following:

  • ConvertTo-LocalizedString
  • ConvertTo-MarkdownHelp
  • Add-PinvokeMethod
  • Expand-Expression
  • Remove-Semicolon
  • Set-HangingIndent

The priority in which these come back is determined by voting in this issue. If you miss one of these commands, please vote for it!