Skip to content

Commit

Permalink
main
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Nov 30, 2024
1 parent 116b668 commit 6cf07b7
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 9 deletions.
8 changes: 7 additions & 1 deletion docs/document/Powershell/docs/Alias.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ New-Alias <alias> <cmd_name>
## Override an Alias

```ps1
Set-Alias <alias> <cmd_name>
Set-Alias vim 'nvim --clean -c "source ~/.vimrc"'
```

Or use `Set-Item` to manipulate the alias provider directly:

```ps1
si alias:vim 'nvim --clean -c "source ~/.vimrc"'
```

> [!TIP]
Expand Down
8 changes: 8 additions & 0 deletions docs/document/Powershell/docs/File System/5.Write to File.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ ls > foo.txt
# equivalent to
ls | Out-File foo.txt
```

## Write Binary Data from External Command<Badge type="info" text="PowerShell 7.4+" />

PowerShell 7.4 added a experimental feature called `PSNativeCommandPreserveBytePipe` to work with external cli that pipes binary stream.

```ps1
curl -s -L 'I am a url' > haha.tar.gz
```
7 changes: 6 additions & 1 deletion docs/document/Powershell/docs/Language/Array.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ So it can be another way to spread out arrays into one.
## Access an Item

Powershell allows
Powershell allows indexer syntax to access one or more items at a time.

```ps1
@(1,2,3)[0] # 1
@(1,2,3)[0, 2] # 1, 3
```

## Concatenation

Expand Down
64 changes: 64 additions & 0 deletions docs/document/Powershell/docs/Language/Control Flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,49 @@
## Newline Indicator
Use `` ` `` to indicate a new line if you do want to finish a long command invocation across multiple lines.
```ps1
gci `
-File `
-Filter '*.mp4'
```
> [!warning]
> **A space is required before the backtick.**
> **And no any chacracter is allowed after the backtick.**
> [!TIP]
> Stop using backticks! They're ugly! Use hashtable splatting instead.
>```ps1
>$table = {
> Filter = '*.mp4';
> File = $true
>}
>gci -file @table
>```
## Multi-Line Piping
### Trailing Piper
In multiple piping, we can use trailing `|` to indicate the new line, PowerShell regconizes these lines as a whole command piping.
```ps1
gps |
foreach CPU |
sort -desc
```
### Leading Piper <Badge type="info" text="PowerShell 7+" />

Starting with PowerShell 7, `|` is allowed as the first non-space chacracter in a new line.

```ps1
gps | foreach CPU
| sort -desc # [!code highlight]
```

## Command Chaining

### Multi-Command in Single Line
Expand All @@ -30,3 +73,24 @@ cd ..; gci -rec -file; echo hello
### Chaining And & Or <Badge type="info" text="PowerShell 7+" />

In PowerShell 7, `&&` and `||` were introduced to do the same command chaining as bash does.


## Pattern Matching

Switch statement behaves similarly when the input is a singular object but can enumerate when the input is a collection.
It has a few different patterns available:

- Constant: matching by primitive literal.
- Type: matching by target type with `-is` operator.
- Regex: matching by regex string, specifically for `string`.
- Wildcard: matching by wildcard string, specifically for `string`.

### Constant Pattern

### Type Pattern

### Regex Pattern

### Wildcard Pattern


84 changes: 82 additions & 2 deletions docs/document/Powershell/docs/Language/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ function Foo {
>
> Default type of a parameter is `System.Object`.
### Implicit Parameter

If no parameter name was set, all value passed in will be captured by `$args`, an `object[]`.

The following example makes an alias for Neovim to mimic the original Vim cli.

```ps1
function vim {
nvim --clean -c 'source ~/.vimrc' @args
}
vim ./foo.txt
```

### Positional Parameter

Positional parameters allows passing values with explicit names.
Expand All @@ -69,6 +83,24 @@ Foo -Foo foo -Bar bar
Foo foo bar # it's the same # [!code highlight]
```

Or use a explicit position argument on attribute.

```ps1
function Foo {
param (
[Parameter(Position=1)] # [!code highlight]
[string] $Bar
[Parameter(Position=0)] # [!code highlight]
[string] $Foo,
)
Write-Output "$Foo $Bar"
}
Foo -Foo foo -Bar bar
Foo foo bar # it's the same # [!code highlight]
```

### Default Parameter

```ps1
Expand Down Expand Up @@ -97,6 +129,12 @@ function Foo {
Foo -Foo -Bar $true # [!code highlight]
```

Manual assignment is also available:

```ps1
Foo -f:$false -b $true
```

### Required Parameter

All parameters are optional by default. Use `[Parameter(Mandatory=$true)]` to mark it as required.
Expand All @@ -108,17 +146,26 @@ param (
)
```

> [!NOTE]
> You can omit assignment for boolean attribute parameter.
>```ps1
>param (
> [Parameter(Mandatory)] # Mandatory is true now # [!code highlight]
> [string]$RequiredName
>)
>```
### Parameter Alias
Parameters can have aliases. It's not needed for most of time though since pwsh can distinguish option by leading string.
```ps1
function Person {
param (
[Alias("n")] # [!code highlight]
[Alias('n')] # [!code highlight]
[string]$Name,
[Alias("a")] # [!code highlight]
[Alias('a', 'yearsold')] # can have multiple aliases! # [!code highlight]
[int]$Age
)
Write-Host "Name: $Name, Age: $Age"
Expand All @@ -127,6 +174,39 @@ function Person {
Person -n "Alice" -a 30 # [!code highlight]
```
### Parameter Validation

Pass a validation logic as script block to `ValidateScript` attribute, `$_` represents singular value of the parameter or current item of a collection.
Will throw an error if any parameter does not satisfies the condition.

```ps1
param (
[ValidateScript({ ($_ % 2) -ne 0 })]
[int[]]$Odd
[ValidateScript({ $_.Length < 5 })]
[string]$Name
)
```

## Named Blocks

In a simple function where there's only one series of parameters being taken, we don't have to use any complex logic.
But things will explode when we're dealing with a pipeline input which might bring multiple objects.

The pipeline mechanism is essentially based on the `Enumerator` so if we collect all items into a new collection as parameter value, it can be a huge performance issue.
So named blocks are essentially to defined a shared process logic for each object in the pipeline input, and other logic like initializationa and finalization.

> [!NOTE]
> When no named block were specified, `end` block is used to represent the whole logic of a simple function.
```ps1
function Foo {
begin {}
process {}
end {}
}
```

## Lifetime

- Function should be define before it was called.
33 changes: 29 additions & 4 deletions docs/document/Powershell/docs/Understanding Pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,48 @@ Overview of pipeline in powershell:
## Pipeline Parameter Binding


## How Cmdlet Accept a Pipeline Input
## How Cmdlet Accept Pipeline Input

There's two solution when a pipeline input comes in as a fallback:

- ByValue: accepts when the coming object can be cast to the target type of the parameter.
- ByValue: the default strategy. Accepts when the coming object can be cast or converted to the target type of the parameter.
- ByPropertyName: accepts when the coming object has property name matched to any parameter name of the cmdlet.

### By Value



### By PropertyName

```ps1
spps -Name (gci -File | foreach Name)
# is equivalent to
# is equivalent to the following
# because FileInfo has Name which matches to -Name parameter of spps cmdlet
gci -File | spps
```


> [!WARNING]
> If multiple matches exist on ByPropertyName solution, powershell throws an error since these paramters might not be allowed to be used together.
By value is always tried first, and then use ByPropertyName, or it finally throws.
ByValue is always tried first, and then use ByPropertyName, or it finally throws.
A parameter accepts pipeline input does not necessarily have both solutions, it can have at least one of them.

## How PowerShell Enumerate Pipeline Input

As we know, PowerShell can handle multiple objects from an enumerator from object that implements `IEnumerable` or `IEnumerable<T>`, or even duck typed with `GetEnumerator`.

While for types that are not linear collection, manually invoking `GetEnumerator` is required when being passed as pipeline input.

- `IDictionary<,>` and `IDictionary`
- HashTable has dynamic typing so we can't presume a uniformed calculation for our cmdlet
- `string` is `IEnumerable` but we surely don't expect the auto enumeration.

```ps1
$table = @{ Name = 'foo'; Age = 18 }
($table | measure).Count # 1
($table.GetEnumerator() | measure).Count # 2 # [!code highlight]
```

This is simply because these types are more likely to be treated as a whole object, even when dictionaries are `IEnumerable<KeyValuePair<,>>`.

2 changes: 1 addition & 1 deletion docs/services/ISidebarService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ export interface ISidebarService {
getSidebarOfDocument(name: DocumentName): DefaultTheme.SidebarItem[];
transformFolderToSidebarItem(
folder: File.DirectoryInfo,
baseLink: string
baseLink: string,
): DefaultTheme.SidebarItem[];
}

0 comments on commit 6cf07b7

Please sign in to comment.