Skip to content

Instantly share code, notes, and snippets.

@blakeNaccarato
Last active January 12, 2024 20:40
Show Gist options
  • Save blakeNaccarato/3e94daba251c128ab65fda184af7ccd4 to your computer and use it in GitHub Desktop.
Save blakeNaccarato/3e94daba251c128ab65fda184af7ccd4 to your computer and use it in GitHub Desktop.
Windows dev machine setup

Windows dev machine setup

It is recommended that you install "Windows Terminal" from the Windows Store to get a more sensible terminal experience. Be sure to visit the "For developers" menu in your Windows machine settings and toggle some important flags:

  • Change settings to show file extensions
  • Change settings to show hidden and system files
  • Change settings to show full path in title bar
  • Choose the default terminal app (I suggest "Windows Terminal")
  • Change execution policy to allow local PowerShell scripts to run without signing. Require signing for remote scripts.

Copy the contents of the scripts below to files named as such. The Install-PythonPwshAndGit.ps1 script below can be run from the built-in Windows PowerShell prompt (run as administrator) to install Git, Python, and PowerShell 7. The new PowerShell is much more user-friendly and actively developed. VSCode will default to PowerShell 7 (over the barebones system PowerShell) if you have it installed. You can edit the flags in the install script below to customize your unattended install of Python/Git/PowerShell. Be sure to modify the hardcoded Python version number as well.

The PowerShell profile is like .bashrc but for PowerShell. If you put it in the right place, these commands will run whenever you start the shell. Run Initialize-Profile (once per dev machine) to install a helper utility Set-PSEnv which enables environment variables to be loaded from .env files in the working directory. See also the experimental features which improve the auto-completion experience. The most important part is the environment function, which will automatically activate the virtual environment in the current working directory.

I have left some commented aliases and environment variable settings as examples on how you might customize those things. Then there's a hacky UTF-8 fix. You can read the linked issue in the comment for detail, but it basically fixes some Windows encoding frustrations. Then there's the prompt bit (function prompt), which if uncommented will modify your prompt to trim all but the closest few directories from the prompt. Then there's PSREADLINE configs which facilitate completion at the terminal. Keybinds can be modified as needed.

<#
.SYNOPSIS
Install programs.
.DESCRIPTION
Requires Windows App Installer (winget). Install it from the Windows store or at:
https://apps.microsoft.com/store/detail/app-installer/9NBLGGH4NNS1
Run this script as administrator with the built-in "Windows PowerShell" (blue window) so
we can bootstrap installation of the modern PowerShell 7.
#>
# Install VSCode
winget install --id 'Microsoft.VisualStudioCode'
# Install Python
winget install --id 'Python.Python.3.11' --override '/quiet PrependPath=0'
# Install PowerShell 7
$PowerShellOverrides = @(
'/quiet'
'ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1'
'ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL=1'
'ADD_PATH=1'
'ENABLE_MU=1'
'ENABLE_PSREMOTING=1'
'REGISTER_MANIFEST=1'
'USE_MU=1'
)
winget install --id 'Microsoft.PowerShell' --override "$PowerShellOverrides"
# Install git
@'
[Setup]
Lang=default
Dir=C:/Program Files/Git
Group=Git
NoIcons=0
SetupType=default
Components=ext,ext\shellhere,ext\guihere,gitlfs,assoc,assoc_sh,autoupdate,windowsterminal,scalar
Tasks=
EditorOption=VisualStudioCode
CustomEditorPath=
DefaultBranchOption=main
PathOption=Cmd
SSHOption=OpenSSH
TortoiseOption=false
CURLOption=OpenSSL
CRLFOption=CRLFAlways
BashTerminalOption=MinTTY
GitPullBehaviorOption=Merge
UseCredentialManager=Enabled
PerformanceTweaksFSCache=Enabled
EnableSymlinks=Disabled
EnablePseudoConsoleSupport=Disabled
EnableFSMonitor=Enabled
'@ > ($inf = New-TemporaryFile)
winget install --id 'Git.Git' --override "/SILENT /LOADINF=$inf"
<#
.SYNOPSIS
My custom PowerShell user profile.
.DESCRIPTION
The first time setting up this profile on a new computer, modify developer options to
allow scripts to run and run the following:
. "Microsoft.PowerShell_profile.ps1"
Initialize-Profile
Place this profile at `C:\Users\<you>\Documents\PowerShell`, or wherever $PROFILE points to.
#>
function Initialize-Profile {
<#.SYNOPSIS
Setup for my PowerShell profile.
#>
# Required to use Set-PSEnv in the ENVIRONMENT section
Install-Module -Name Set-PSEnv
# See `Get-ExperimentalFeature` for details. Once enabled, they stay enabled.
Enable-ExperimentalFeature PSCommandNotFoundSuggestion
Enable-ExperimentalFeature PSLoadAssemblyFromNativeCode
Enable-ExperimentalFeature PSNativeCommandErrorActionPreference
Enable-ExperimentalFeature PSSubsystemPluginModel # For PSREADLINE section
# For up-to-date help and useful keybinds (F1, Alt+H, etc.)
Update-Help -Force # Need force because some issues w/ PSReadLine
}
# * -------------------------------------------------------------------------------- * #
# * ENVIRONMENT
function Set-Env {
<#
.SYNOPSIS
Load environment variables from `.env`, activate virtual environments.
#>
# If there is an `.env` file in the PWD, load environment variables from it
Set-PsEnv
# Look for a virtual environment
$Activate = '.venv/scripts/activate.ps1'
if (Test-Path $Activate) {
# If there is a Python virtual environment in the PWD, activate it
& $Activate
}
}
Set-Env
# * -------------------------------------------------------------------------------- * #
# * ALIASES AND SHORTHAND COMMANDS
# New-Alias -Name 'codei' -Value 'code-insiders'
# Remove-Alias -Force 'gc' # Read-only alias for Get-Content
# function gc {
# git commit @args
# }
# Remove-Alias -Force 'gps' # Read-only alias for Get-Unique
# function gps {
# git push @args
# try { dvc push } catch [System.Management.Automation.CommandNotFoundException] {}
# }
# function gpl {
# git pull @args
# try { dvc pull } catch [System.Management.Automation.CommandNotFoundException] {}
# }
# * -------------------------------------------------------------------------------- * #
# * DEFAULT ENVIRONMENT VARIABLES
# $MY_PROFILE = $PROFILE
# $Env:PIP_DISABLE_PIP_VERSION_CHECK = 1
# $Env:POWERSHELL_TELEMETRY_OPTOUT = 'true'
# $Env:PYDEVD_DISABLE_FILE_VALIDATION = 1
# $Env:PYTHONWARNDEFAULTENCODING = 1
# * -------------------------------------------------------------------------------- * #
# *
# Fix leaky UTF-8 encoding settings, now PowerShell pipes will be UTF-8. Note that
# fixing it from Control Panel and system-wide has buggy downsides.
# See: https://github.com/PowerShell/PowerShell/issues/7233#issuecomment-640243647
[console]::InputEncoding = [console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
# $ErrorActionPreference = 'Stop'
# $ErrorView = 'NormalView'
# $ErrorView | Out-Null # https://github.com/PowerShell/PSScriptAnalyzer/issues/1749
# * -------------------------------------------------------------------------------- * #
# * PROMPT
function Edit-Location {
<#.SYNOPSIS
Return the current directory, showing the root drive followed by an ellipsis and
only as many folders back from the current folder (inclusive) as desired.
#>
Param(
# The number of folders back from the current folder (inclusive) to keep.
[int][Parameter(Mandatory)]$count
)
$lookbehind = '(?<=\\)' # Look behind for a backslash.
$match = '[\s\S]+' # Match anything at least one character long.
# Look ahead for a backslash,
# followed by anything (at least one char.) except a backslash,
# for $count occurrences.
$lookahead = "(?=(\\[^\\]+){$count})"
# This replaces the match with an ellipsis. The lookbehind ensures the backslash is
# kept before the folders replaced by an ellipsis, while the lookahead ensures the
# desired $count of folders closest to the current folder (inclusive) are kept.
return $((Get-Location) -replace "$lookbehind$match$lookahead", '...')
}
# function prompt {
# <#.SYNOPSIS
# This function is called by PowerShell to display the prompt.
# #>
# $(if (Test-Path variable:/PSDebugContext) { '[DBG]: ' } else { '' }) +
# 'PS ' + $(Edit-Location 3) + $(if ($NestedPromptLevel -ge 1) { '>>' }) + '> '
# }
# * -------------------------------------------------------------------------------- * #
# * PSREADLINE
# *
# * Press F2 to toggle between prediction view styles (PredictionViewStyle).
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineKeyHandler -Chord Tab -Function AcceptNextSuggestionWord
Set-PSReadLineKeyHandler -Chord Shift+Tab -Function TabCompleteNext # Rebind this
# To avoid VSCode keybind conflicts.
Set-PSReadLineKeyHandler -Chord Shift+F1 -Function ShowCommandHelp # Also on F1
Set-PSReadLineKeyHandler -Chord F4 -Function CharacterSearch # Also on F3
Set-PSReadLineKeyHandler -Chord Shift+F4 -Function CharacterSearchBackward # Also on Shift+F3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment