-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathProfile.ps1
348 lines (299 loc) · 12.5 KB
/
Profile.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# ██╗ ██╗██╗███╗ ██╗██████╗ ██████╗ ████████╗███████╗
# ██║ ██║██║████╗ ██║██╔══██╗██╔═══██╗╚══██╔══╝██╔════╝
# ██║ █╗ ██║██║██╔██╗ ██║██║ ██║██║ ██║ ██║ ███████╗
# ██║███╗██║██║██║╚██╗██║██║ ██║██║ ██║ ██║ ╚════██║
# ╚███╔███╔╝██║██║ ╚████║██████╔╝╚██████╔╝ ██║ ███████║
# ╚══╝╚══╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
# Profile.ps1 - Scott McKendry
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Aliases 🔗
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Set-Alias -Name cat -Value bat
Set-Alias -Name df -Value Get-Volume
Set-Alias -Name ff -Value Find-File
Set-Alias -Name grep -Value Find-String
Set-Alias -Name l -Value Get-ChildItemPretty
Set-Alias -Name la -Value Get-ChildItemPretty
Set-Alias -Name ll -Value Get-ChildItemPretty
Set-Alias -Name ls -Value Get-ChildItemPretty
Set-Alias -Name rm -Value Remove-ItemExtended
Set-Alias -Name su -Value Update-ShellElevation
Set-Alias -Name tif Show-ThisIsFine
Set-Alias -Name touch -Value New-File
Set-Alias -Name up -Value Update-Profile
Set-Alias -Name us -Value Update-Software
Set-Alias -Name vi -Value nvim
Set-Alias -Name vim -Value nvim
Set-Alias -Name which -Value Show-Command
# Putting the FUN in Functions 🎉
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function Find-WindotsRepository {
<#
.SYNOPSIS
Finds the local Windots repository.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$ProfilePath
)
Write-Verbose "Resolving the symbolic link for the profile"
$profileSymbolicLink = Get-ChildItem $ProfilePath | Where-Object FullName -EQ $PROFILE.CurrentUserAllHosts
return Split-Path $profileSymbolicLink.Target
}
function Update-Profile {
<#
.SYNOPSIS
Gets the latest changes from git, reruns the setup script and reloads the profile.
Note that functions won't be updated, this requires a full PS session restart. Alias: up
#>
Write-Verbose "Storing current working directory in memory"
$currentWorkingDirectory = $PWD
Write-Verbose "Updating local profile from Github repository"
Set-Location $ENV:WindotsLocalRepo
git stash | Out-Null
git pull | Out-Null
git stash pop | Out-Null
Write-Verbose "Rerunning setup script to capture any new dependencies."
if (Get-Command -Name sudo -ErrorAction SilentlyContinue) {
sudo pwsh ./Setup.ps1
}
else {
Start-Process wezterm -Verb runAs -WindowStyle Hidden -ArgumentList "start --cwd $PWD pwsh -NonInteractive -Command ./Setup.ps1"
}
Write-Verbose "Reverting to previous working directory"
Set-Location $currentWorkingDirectory
Write-Verbose "Re-running profile script from $($PROFILE.CurrentUserAllHosts)"
.$PROFILE.CurrentUserAllHosts
}
function Update-Software {
<#
.SYNOPSIS
Updates all software installed via Winget & Chocolatey. Alias: us
#>
Write-Verbose "Updating software installed via Winget & Chocolatey"
sudo winget upgrade --all --include-unknown --silent --verbose
sudo choco upgrade all -y
$ENV:SOFTWARE_UPDATE_AVAILABLE = ""
}
function Find-File {
<#
.SYNOPSIS
Finds a file in the current directory and all subdirectories. Alias: ff
#>
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline, Mandatory = $true, Position = 0)]
[string]$SearchTerm
)
Write-Verbose "Searching for '$SearchTerm' in current directory and subdirectories"
$result = Get-ChildItem -Recurse -Filter "*$SearchTerm*" -ErrorAction SilentlyContinue
Write-Verbose "Outputting results to table"
$result | Format-Table -AutoSize
}
function Update-ShellElevation {
<#
.SYNOPSIS
Elevates the current shell to run as an administrator. Alias: su
#>
Write-Verbose "Elevating shell to run as administrator"
sudo -E pwsh -NoLogo -Interactive -NoExit -c "Clear-Host"
}
function Find-String {
<#
.SYNOPSIS
Searches for a string in a file or directory. Alias: grep
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$SearchTerm,
[Parameter(ValueFromPipeline, Mandatory = $false, Position = 1)]
[string]$Directory,
[Parameter(Mandatory = $false)]
[switch]$Recurse
)
Write-Verbose "Searching for '$SearchTerm' in '$Directory'"
if ($Directory) {
if ($Recurse) {
Write-Verbose "Searching for '$SearchTerm' in '$Directory' and subdirectories"
Get-ChildItem -Recurse $Directory | Select-String $SearchTerm
return
}
Write-Verbose "Searching for '$SearchTerm' in '$Directory'"
Get-ChildItem $Directory | Select-String $SearchTerm
return
}
if ($Recurse) {
Write-Verbose "Searching for '$SearchTerm' in current directory and subdirectories"
Get-ChildItem -Recurse | Select-String $SearchTerm
return
}
Write-Verbose "Searching for '$SearchTerm' in current directory"
Get-ChildItem | Select-String $SearchTerm
}
function New-File {
<#
.SYNOPSIS
Creates a new file with the specified name and extension. Alias: touch
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Name
)
Write-Verbose "Creating new file '$Name'"
New-Item -ItemType File -Name $Name -Path $PWD | Out-Null
}
function Show-Command {
<#
.SYNOPSIS
Displays the definition of a command. Alias: which
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Name
)
Write-Verbose "Showing definition of '$Name'"
Get-Command $Name | Select-Object -ExpandProperty Definition
}
function Get-OrCreateSecret {
<#
.SYNOPSIS
Gets secret from local vault or creates it if it does not exist. Requires SecretManagement and SecretStore modules and a local vault to be created.
Install Modules with:
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore
Create local vault with:
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore
Set-SecretStoreConfiguration -Authentication None -Confirm:$False
https://devblogs.microsoft.com/powershell/secretmanagement-and-secretstore-are-generally-available/
.PARAMETER secretName
Name of the secret to get or create. It is recommended to use the username or public key / client id as secret name to make it easier to identify the secret later.
.EXAMPLE
$password = Get-OrCreateSecret -secretName $username
.EXAMPLE
$clientSecret = Get-OrCreateSecret -secretName $clientId
.OUTPUTS
System.String
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$secretName
)
Write-Verbose "Getting secret $secretName"
$secretValue = Get-Secret $secretName -AsPlainText -ErrorAction SilentlyContinue
if (!$secretValue) {
$createSecret = Read-Host "No secret found matching $secretName, create one? Y/N"
if ($createSecret.ToUpper() -eq "Y") {
$secretValue = Read-Host -Prompt "Enter secret value for ($secretName)" -AsSecureString
Set-Secret -Name $secretName -SecureStringSecret $secretValue
$secretValue = Get-Secret $secretName -AsPlainText
}
else {
throw "Secret not found and not created, exiting"
}
}
return $secretValue
}
function Get-ChildItemPretty {
<#
.SYNOPSIS
Runs eza with a specific set of arguments. Plus some line breaks before and after the output.
Alias: ls, ll, la, l
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $false, Position = 0)]
[string]$Path = $PWD
)
Write-Host ""
eza -a -l --header --icons --hyperlink --time-style relative $Path
Write-Host ""
}
function Show-ThisIsFine {
<#
.SYNOPSIS
Displays the "This is fine" meme in the console. Alias: tif
#>
Write-Verbose "Running thisisfine.ps1"
Show-ColorScript -Name thisisfine
}
function Remove-ItemExtended {
<#
.SYNOPSIS
Removes an item and (optionally) all its children. Alias: rm
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[switch]$rf,
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path
)
Write-Verbose "Removing item '$Path' $($rf ? 'and all its children' : '')"
Remove-Item $Path -Recurse:$rf -Force:$rf
}
# Environment Variables 🌐
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ENV:WindotsLocalRepo = Find-WindotsRepository -ProfilePath $PSScriptRoot
$ENV:STARSHIP_CONFIG = "$ENV:WindotsLocalRepo\starship\starship.toml"
$ENV:_ZO_DATA_DIR = $ENV:WindotsLocalRepo
$ENV:OBSIDIAN_PATH = "$HOME\git\obsidian-vault"
$ENV:BAT_CONFIG_DIR = "$ENV:WindotsLocalRepo\bat"
$ENV:FZF_DEFAULT_OPTS = '--color=fg:-1,fg+:#ffffff,bg:-1,bg+:#3c4048 --color=hl:#5ea1ff,hl+:#5ef1ff,info:#ffbd5e,marker:#5eff6c --color=prompt:#ff5ef1,spinner:#bd5eff,pointer:#ff5ea0,header:#5eff6c --color=gutter:-1,border:#3c4048,scrollbar:#7b8496,label:#7b8496 --color=query:#ffffff --border="rounded" --border-label="" --preview-window="border-rounded" --height 40% --preview="bat -n --color=always {}"'
# Prompt & Shell Configuration 🐚
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Start background jobs for dotfiles and software update checks
Start-ThreadJob -ScriptBlock {
Set-Location -Path $ENV:WindotsLocalRepo
$gitUpdates = git fetch && git status
if ($gitUpdates -match "behind") {
$ENV:DOTFILES_UPDATE_AVAILABLE = " "
}
else {
$ENV:DOTFILES_UPDATE_AVAILABLE = ""
}
} | Out-Null
Start-ThreadJob -ScriptBlock {
<#
This is gross, I know. But there's a noticible lag that manifests in powershell when running the winget and choco commands
within the main pwsh process. Running this whole block as an isolated job fails to set the environment variable correctly.
The compromise is to run the main logic of this block within a threadjob and get the output of the winget and choco commands
via two isolated jobs. This sets the environment variable correctly and doesn't cause any lag (that I've noticed yet).
#>
$wingetUpdatesString = Start-Job -ScriptBlock { winget list --upgrade-available | Out-String } | Wait-Job | Receive-Job
$chocoUpdatesString = Start-Job -ScriptBlock { choco upgrade all --noop -y | Out-String } | Wait-Job | Receive-Job
if ($wingetUpdatesString -match "upgrades available" -or $chocoUpdatesString -notmatch "can upgrade 0/") {
$ENV:SOFTWARE_UPDATE_AVAILABLE = " "
}
else {
$ENV:SOFTWARE_UPDATE_AVAILABLE = ""
}
} | Out-Null
function Invoke-Starship-TransientFunction {
&starship module character
}
Invoke-Expression (&starship init powershell)
Enable-TransientPrompt
Invoke-Expression (& { ( zoxide init powershell --cmd cd | Out-String ) })
$colors = @{
"Operator" = "`e[35m" # Purple
"Parameter" = "`e[36m" # Cyan
"String" = "`e[32m" # Green
"Command" = "`e[34m" # Blue
"Variable" = "`e[37m" # White
"Comment" = "`e[38;5;244m" # Gray
"InlinePrediction" = "`e[38;5;244m" # Gray
}
Set-PSReadLineOption -Colors $colors
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -PredictionViewStyle InlineView
Set-PSReadLineKeyHandler -Function AcceptSuggestion -Key Alt+l
Import-Module -Name CompletionPredictor
# Skip fastfetch for non-interactive shells
if ([Environment]::GetCommandLineArgs().Contains("-NonInteractive")) {
return
}
fastfetch