Once again my employeer forces me to work from an inferior platform, so what are my options to get the best possible working environment? Heres some tips to what I’ve done so far.
The windows terminal is one of the better things produced by Microsoft the last couple of years. I have already written a bit about it before, so search for windows terminal, and you will get the other articles. Even though the terminal is nice, there are some minor annoyances, when you are used to work in a bash environment.
- No nice “inline” editor
- Does not obey ctrl-d to exit the session
- Does not have tab completion on entries in the ssh config file
To fix these three annoyances, we need to download vim from www.vim.org, install it and the rest is done creating and configuring a powershell profile, lets dive into it.
Not only do I have to work from a windows machine (my department does primarily FOSS solutions) I also don’t have any elevated permissions on my machine. IT proffesionlas are treated just the same as office workers š
This means I cannot install any software, besides whats picked by the Windows admins. Luckily vim is not picky, and you can install it in your own home folder. So lauch the installer and change the install path accordingly.
When vim is installed, all we need to do is to create a powershell profile file. The file has to be named Microsoft.PowerShell_Profile.ps1 and has to be placed under $home\Documents\PowerShell\
When placed here it will be a user specific profile, you can also do system-wide profiles, take a look at $pshome.
The profile file I have created looks like this:
using namespace System.Management.Automation # Set aliases Set-Alias -name vim $home\Vim\vim90\vim.exe Set-Alias -name vi $home\Vim\vim90\vim.exe # Obey ctrl-d Set-PSReadlineKeyHandler -Key ctrl+d -Function ViExit # Enable ssh tab completion # Credits to backerman and contributers at github for creating the code Register-ArgumentCompleter -CommandName ssh,scp,sftp -Native -ScriptBlock { param($wordToComplete, $commandAst, $cursorPosition) function Get-SSHHostList($sshConfigPath) { Get-Content -Path $sshConfigPath ` | Select-String -Pattern '^Host ' ` | ForEach-Object { $_ -replace 'Host ', '' } ` | ForEach-Object { $_ -split ' ' } ` | Sort-Object -Unique ` | Select-String -Pattern '^.*[*!?].*$' -NotMatch } function Get-SSHConfigFileList ($sshConfigFilePath) { $sshConfigDir = Split-Path -Path $sshConfigFilePath -Resolve -Parent $sshConfigFilePaths = @() $sshConfigFilePaths += $sshConfigFilePath $pathsPatterns = @() Get-Content -Path $sshConfigFilePath ` | Select-String -Pattern '^Include ' ` | ForEach-Object { $_ -replace 'Include ', '' } ` | ForEach-Object { $_ -replace '~', $Env:USERPROFILE } ` | ForEach-Object { $_ -replace '\$Env:USERPROFILE', $Env:USERPROFILE } ` | ForEach-Object { $_ -replace '\$Env:HOMEPATH', $Env:USERPROFILE } ` | ForEach-Object { $sshConfigFilePaths += $(Get-ChildItem -Path $sshConfigDir\$_ -File -ErrorAction SilentlyContinue -Force).FullName ` | ForEach-Object { Get-SSHConfigFileList $_ } } if (($sshConfigFilePaths.Length -eq 1) -and ($sshConfigFilePaths.item(0) -eq $sshConfigFilePath) ) { return $sshConfigFilePath } return $sshConfigFilePaths | Sort-Object -Unique } $sshPath = "$Env:USERPROFILE\.ssh" $hosts = Get-SSHConfigFileList "$sshPath\config" ` | ForEach-Object { Get-SSHHostList $_ } ` # For now just assume it's a hostname. $textToComplete = $wordToComplete $generateCompletionText = { param($x) $x } if ($wordToComplete -match "^(?<user>[-\w/\\]+)@(?<host>[-.\w]+)$") { $textToComplete = $Matches["host"] $generateCompletionText = { param($hostname) $Matches["user"] + "@" + $hostname } } $hosts ` | Where-Object { $_ -like "${textToComplete}*" } ` | ForEach-Object { [CompletionResult]::new((&$generateCompletionText($_)), $_, [CompletionResultType]::ParameterValue, $_) }}
Exit your terminal and lauch it again, hopefully you can be a bit more productive with the new “features”