Setup fancy terminal using OhMyPosh

CC(ChenChih)
Chen-Chih’s Portfolio Page
56 min readJun 14, 2024

Today I want to write a post related to setting up the terminal, especially under the window. As you can see the topic I am discussing is my posh you will know it is related to window terminal, however, it also supports many different shells like Linux or Mac zsh. I have been playing around with it for about weeks, and see many tutorials or YouTube videos on it, and would like to write a note on setup.

I have been looking through many fancy terminal tutorials and would like to write a tutorial in this post. In this part, I will focus on Window Powershell oh-my-posh. I have been playing around with oh-my-zsh under Linux and Mac, probably I will write a separate post on this.

Ohmyposh: using PowerShell, which allows setup on multiple platforms Windows, Linux, and more.

Ohmyzsh: using zsh shell, which allows use under Linux or Mac. However, if you want to use Linux, then you might need to install WSL(Windows sub Linux).

But anyway I will show how to set up ohmyposh, which was designed to be used under windows. I have been watching Scott Hanselman, various YouTube channels, and blogs on this tutorial. I will cover many stuff in this post, and so I will keep it simple. You can always select the link below to jump on a specific option or section. I will contain some additional sections, like how to install wget, scoop, and some other window commands in case you do not know it.

So why do we need to change our terminal or prompt to fancy? Well because of productivity, and much comfortable when typing in the terminal with the cli command. If you ever use the Linux command or cli command, if there terminal is colorful, then what’s the feeling like? There are many benefits of it one of the major benefits is the visual prompt and the plugin. There are many cool plugins and settings that allow you to use window with Linux command. I will mention it and stick with this post.

I try my best to drive all major points of setting the terminal however there are many settings that are optional. I just doesn’t wish to miss any part in case some of them you might be important and useful.

Below the picture is what I mean by a visual prompt or what oh-my-posh looks like. As you can see it is colorful and indicates version, datetime, git status, etc. At the end of this post, you would be able to design like this awesome prompt. I also have update note in github page.

ohmyposh theme

Below is the content in this post, please click on the part you’re interested in, which allows to to come back and forth to the page.

Content:
Part1 window install related Tools and setting
Part2 Basic Setting Oh-my-posh (PowerShell)
Part 3–1 WSL Linux Setup (bash)
Part 3–2 Command Prompt (CMD)
Part4 Plugin
Part5 Segment for the customized theme
Part 6 Window other setting(error or command)
Conclusion
Reference

All of these environments will be using Windows 10 or Windows 11, you use which prefer your preference. I will also show the WSL setting, which is related to the Linux setting.

So below is what I will be using, everything will be done in Windows.

Part1 window install related Tools and setting ¹

 1. Download and Installation Tool 
Method1: winget Command
Method2: Microsoft Store
2. Window Terminal Setting
2.1 Window terminal Setting - startup
2.2 Setting Terminal's profile
2.2.1 How to adjust the shell's order (profile)?
2.2.2 How to hide the shell option?
2.2.3 How to change terminal profile and it's option?
cursorShape
terminal appearance color
change the theme of the terminal color
Window Terminal Hotkey
2.2.4 Adding Ananconda Profile

We need to install some tools to let Ohmyposh work properly, if not the styling will display strangely. In this section need to install:

  • Window Terminal
  • PowerShell Core

Window Terminal will let the prompt show properly, if you set everything, but do not use Window Terminal the font text show incorrectly like the below example:

So as you can see above in comparison with the window terminal, the prompt shows perfectly, whereas with the window terminal will show awkward or ugly. In the window, the default already has installed PowerShell, however, that’s Powershell 5.x version, but if you want to use many cool plugins some of them might not work. So instead of letting it work, you can install Powershell core which is version 7.x.

Now you should have an understanding of why we need to install Powershell and Window Terminal, so let me show you how to install the Window Terminal and Powershell in this section.

Before teaching how to set it, please make sure your winget is been installed by going to the command prompt or Powershell and typing winget. Below from the wingetofficial site and documentation, if your Windows version 10 1709 later will be installed. If you’re winget not installed or has an error, please refer below section on window package settings, I talk about the installation of the window packager tool.

The winget command line tool is only supported on Windows 10 1709 (build 16299) or later at this time.

I like using winget, which is like Linux’s apt-get this tool allows you to install tools by command.

1. Download and Installation Tool ¹

There are a couple of ways you can download a Windows Terminal and PowerShell, you can use the Windows Store, or use winget method.

Method1: winget Command ¹

window terminal: winget install Microsoft.WindowsTerminal
PowerShell Core: winget install Microsoft.Powershel

Method2: Microsoft Store ¹

Go to Microsoft Store and search Windows Terminal and PowerShell Core, which will look below:

The default Powershell will be called: Microsoft Powershell , version 5.x.
The Powershell just installed will be called Powershell, version 7.x

You can check the version like this: $PSVersionTable

2. Window Terminal Setting ¹

After installing PowerShell and terminal we can do many settings on the window terminal according to your preference; it’s optional.

Basically in this section, I will show some of the window terminal settings you can set, like profile, font, default terminal, etc.

2.1 Window terminal Setting — startup ²

Let's navigate to the window terminal, and go to the settings page

Access the startup option, change the Default profile to PowerShell Core and Default terminal to window terminal just like below, and save it.

Next time you open the window terminal it will use Powershell core as default, and when press the new tab the + button will use PowerShell core as default.

2.2 Setting Terminal’s Profile ²

In the previous method I set the default to PowerShell core this means when you press a new tab will use the default shell. But actually, you can press the V button next to the tab, to choose a different shell you want to want to use, such as (WSL PowerShell, PowerShell Core, or Command Prompt). The Shell will occur only if you have installed it, please keep this in mind.

All of the configuration in the window terminal has it’s own profile setting.json. So I will show how to set some of the great settings by modifying the JSON file. We also can set some settings using the UI setting(window terminal), but for some special settings, you still need to modify the JSON file. All the UI settings will be written into the settingsjson file.

Below I will show many different types of settings with the window terminal

2.2.1 How to adjust the shell's order (profile)?
2.2.2 How to hide shell option?
2.2.3 How to change terminal profile?
2.2.4 Adding Ananconda Profile

2.2.1 How to adjust the shell’s order (profile)?³

We can modify the profile JSON file, which is much more powerful. It allows you to change the order of the shell, hidden shell, and many more features. To understand the WSL shell setting I will show it in below WSL section below. Navigate your window terminal, press the v button, click settings, and click on open JSON file.

You can even use a shortcut to see the terminal shortcut ctrl+shift+p and scroll down and select an open setting or ctrl+alt+comman

window terminal configure setting file
hotkey open settings

You might need a text editor like vscode , notepad++, or another you prefer text editor else might not be able to open, which will display like the below picture.

Error no text edior
profile setting

From the above setting, we adjust the order of each profile, the one on the top is going to order the topest the first one. So as you can see Windows PowerShell is ordered the first one, it’s because the profile’s file Window PowerShell is the first order. So if I change the order it will move to the bottom according to which order you want.

change the shell order

2.2.2 How to hide the shell option? ³

As you can see there’s a hidden option, that option will allow the shell to display or hidden. Default all the hidden:false, which means will not be hidden. Let me show you how happens if i set hidden:true, the shell will not display on the terminal tab.

2.2.3 How to change the terminal profile and its option? ³

In this section will cover these profile settings:

cursorShape
terminal appearance color
change the theme of the terminal color
Window Terminal Hotkey

Below is what the window terminal profile looks like, so will this option,

    {
"hidden": false,
"name": "Windows PowerShell",
"cursorShape":"bar",
"fontSize": 14,
"opacity": 66,
"useAcrylic": true
}
  • cursorShape

There is a different option on cursor shape like the below picture.

cursorShape
  • terminal appearance color

We can set the background and tab’s color, so let's change the background to a transparent color on your background using opacity and useAcrylic like the below setting:

let's enable acrylic for the tab

you can change the color using the settings.json file.

  • change the theme of the terminal color

We can use the default theme for the window terminal which provides the color below

window Terminal schemes

You can change the color theme, however, if none of the themes you don’t like you can still download other themes in this link which has many various themes. Basically just click the copy button, and it will copy the snippet code that is in json format, and you just have to paste it into settings.json under schemes just like below.

So when you go back to the window terminal, the aurora theme will display out like below picture, which now you can use it.

So this is about the window terminal setting, which you can play around with the font, color, theme,etc to fit your needs.

  • Window Terminal Hotkey

I would like to mention some hotkey for the Window Terminal, you can find all the hotkey by pressing ctrl+shift+p or modify in settings.js on under actions part. To open the setting in hotkey: ctrl+alt+,

settings.json for hotkey

These are the common hotkeys you can use:

Close pane: ctrl+shift+w

New tab: ctrl+shift+t
Different shell:
ctrl+shift+# , # is the list shell priority
Vertical pane:
alt+shif+minus(-)
Horizontal pane:
alt+shift+plus(+)
Resize pane:
alt+shift+arrow-keys
Show all hotkey:
Ctrl+shift+p
Clear screen:
ctr+l

2.2.4 Adding Ananconda Profile ³

If you ever use Anaconda Powershell and want to add an inside window terminal. When you manually click from the Anaconda Start menu, it will display weirdly. To fix it, you need to add to the window terminal.

Please add these items to the new profile in the Window Terminal profile for Anaconda. I add three profiles cmd, PowerShell, and PowerShell core. Please add all of this into settings.json on the window terminal.

Note: Some of the locations for Anaconda might be a different location from mine, just change it.

Below are some examples of how to set anaconda in the window terminal profile. The above example, it’s used powershell 5, you can change it to powershell7 with pwsh.exe or reference below command :

Powershell7 : pwsh.exe
powershell5:
powershell.exe


#anaconda location: C:\Users\test\anaconda3
#Powershell_7_2
"commandline": "powershell.exe -ExecutionPolicy ByPass -NoExit -Command \"& 'C:\\Users\\test\\anaconda3\\shell\\condabin\\conda-hook.ps1' ; conda activate 'C:\\Users\\test\\anaconda3' \"",


#anaconda location: C:\ProgramData\Anaconda3New
#Command prompt
"commandline": "cmd.exe /K \"C:\\ProgramData\\Anaconda3New\\Scripts\\activate.bat\""

#powershell
"powershell.exe -ExecutionPolicy ByPass -NoExit -Command \"& '\"C:\\ProgramData\\Anaconda3New\\shell\\condabin\\conda-hook.ps1\"' ; conda activate 'C:\\ProgramData\\Anaconda3New'\""

#Powershell7
"commandline": "pwsh.exe -ExecutionPolicy ByPass -NoExit -Command \"& '\"C:\\ProgramData\\Anaconda3New\\shell\\condabin\\conda-hook.ps1\"' ; conda activate 'C:\\ProgramData\\Anaconda3New'\""

Part2 Basic Setting Oh-my-posh (PowerShell) ¹

Now after installing Window Terminal, and PowerShell Core, now time to move forward on installing some more tools and setting up Ohmyposh. But before downloading and installing oh-my-posh we still need to install some fonts used for oh-my-posh.

 1. Setting and installing Font Nerd 
2. oh-my-posh Setup
Step1: installing oh-my-posh
Step2: check oh-my-posh is installed properly
Step3: activate the theme
Step4: setting theme
Method1: Assign Full path
Method2:Url method in case of local theme location
Method3: using $env environment variable
Understand the $env prefix variable
Step 5 Prompt - adding a profile (oh-my-posh-theme)
5.1 creating profile
5.2 edit profile update theme
5.3 Reassign profile to another location (optional)
Step 6 Adding function and alias to profile
6.1 Remove curl and wget alias (Only For window powershell 5.x)
6.2 Adding Shortcut for Edit Host
6.3 Adding alias or function
6.4 adding utility function which command
3. (Summary)Let me recap the faster way to set up the ohmyposh

1. Setting and installing Font Nerd ²

This is an important step, we need to install the nerd font, without installing it will not display correctly. There are many nerd fonts we can use depending on which you prefer.

Nerd Fonts are a collection of glyphs (icons) designed to appear like logos on your terminal. These glyphs represent tools, frameworks, or other computer-related concepts, providing a visual way to identify them at a glance.

Nerd Font Link to download, you can choose which URL to download nerd font: git page, official site. When you download it might be a compression file or .ttf format file. You just have to extract and install it, or drag it into C:\Windows\Fonts

download nerd font

You can install it by dragging it into C:\Windows\Fonts or right-click and click installed.

install the font

let’s change the font to nerd font in the window terminal like the below picture

Now let me show with and without using the nerd font what will it look like, or else you might not know the purpose of using it. Please look below picture to be more intuitive.

From above you can see without using nerd font, the font will display incorrectly, so if you want to use a fancy theme then you will need nerd font.

2. oh-my-posh Setup ²

Now everything we need has already been installed and set up, and let's move forward to install and set up Ohmyposh.

Please navigate your window terminal, and switch to power shell core, I assume you set it as default.

Step1: installing oh-my-posh ³

This is oh-my-posh official site which contains documentation, in case my command does not work, then please refer to the official site. The official site might have a recommended command.

Install ohmyposh: winget install JanDeDobbeleer.OhMyPosh -s winget
Update :winget upgrade JanDeDobbeleer.OhMyPosh -s winget

installation command official site

Note: One reminder in case your PC or laptop winget not working, please refer below section on how to install winget.

Step2: check oh-my-posh is installed properly ³

After installation please type oh-my-posh in your command prompt or window terminal should not see any error message, then it means it is successfully installed.

Step3: activate the theme ³

Now let's activate the oh-my-posh theme with this command: oh-my-posh init pwsh | invoke-expression this is the default theme, as shown below, and now your terminal should display a fancy terminal

activate default theme: oh-my-posh init pwsh | invoke-expression

default theme

You can get all the themes by this command: Get-PoshThemes , this will show what the themes look like, or refer to this link.

Get-PoshThemes: Show all themes look like
Get-PoshThemes --List: will list and show theme location

All the themes will stored in this location :

C:\Users\<username>\AppData\Local\Programs\oh-my-posh\themes

Step4: setting theme ³

There are various methods that we can set the theme, which i will cover in this section, and you can choose which one you prefer.

Method1: Assign Full path

oh-my-posh init pwsh --config 'C:\Users\test\AppData\Local\Programs\oh-my-posh\themes\atomic.omp.json' | Invoke-Expression
#or cd to theme folder and assign json
cd "C:\Users\test\AppData\Local\Programs\oh-my-posh\themes\"
oh-my-posh init pwsh --config "atomic.omp.json" | Invoke-Expression

I don’t like this method, because it’s too long and hard to read. By the way, you can also move the .json config into any location, it doesn’t have to be in the default location.

You can also assign themes with different locations, and store the path as a variable just like below :

$themepath = 'C:\Users\test\Documents\PowerShell\shanselman_v3-v2.json'
oh-my-posh --init --shell pwsh --config $themepath | Invoke-Expression

We can also store the same location as $profile(which will cover the next step), then you can use this command, better than the above command. I will explain more in the next step.

$omp_config = Join-Path $PSScriptRoot ".\theme.json"
oh-my-posh --init --shell pwsh --config $omp_config | Invoke-Expression

Method2: Url method in case of local theme location

You can also set the theme by URL, rather than local side.

oh-my-posh init pwsh --config 'https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/jandedobbeleer.omp.json' | Invoke-Expression

Method3: using $env environment variable

In method1 we assign the full path of the theme .json file, but we can use the $env variable to replace the full path, because the $env:POSH_THEMES_PATH record the default path of the theme.

oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\iterm2.omp.json" | Invoke-Expression

This variable will allow you to not type the full path name because it’s an environment variable. You might see many people use it. Let me show some common $env: variable you can use to be more clear. Let me show you some of the $env prefix:

  • home directory: $env:USERPROFILE ==>C:\Users\<username>
  • posh theme path: $env:POSH_THEMES_PATH

Understand the $env prefix variable

We will use the $env, because of shortens the command, since it is stored as a variable, and you can indeed access environment variables.

Syntax : $env:<VariableName> it is the proper way to access environment variables.

If you don’t know which $envprefix you can use, please use this command Get-ChildItem env: it will list all environment variable names, so it allows us to discover the name we can use.

When setting the oh-my-posh we will use the $env:POSH_THEMES_PATH because it’s the default theme location, we just type in $env:POSH_THEMES_PATH\<themename>.json it will set the theme.

There’s one thing I want to mention about the $profile, if you add $env prefix set-Item -Path env:MYCUSTOMVAR –Value inside $profile, it will only take effect if you add to the $profile. In case you want to remove specific prefixes by this command use this $env:<name> = $null or remove it from the $profile.

All of the Get-ChildItem env: will not be added/removed unless you add it into $profile. As you can see in the example belowAnaconda_home, this is been set under environment variables(System-Wide). So when I show it will display, then I went and removed it, it will be removed. I reopen a new session it appears again. The reason is that when removed it is only temporary remove.

environment variable

So the adding $env prefix by adding command will be temporary, by $profile only takes effect if added inside, and by environment variable will be default setting, to remove it go to an environment variable to remove it. Below is a diagram generated by Ai prompt of comparison between each:

Step 5 Prompt — adding a profile (oh-my-posh-theme) ³

In step4 is to set the theme, however, you will realize if you open a new session then the theme you set will disappear, and also oh-my-posh fancy theme seems to disappear. The reason is that when we set the theme with a command it only temporarily takes effect, we need to write it into a profile.

In this part, I will show how to write or update into profile. If you are debugging I think setting a temporary like in step 4 is a great fit, especially when adding a plugin to see what’s looks like.

You can find more details in the oh-my-posh site under the prompt section, like below:

oh-my-posh prompt section

5.1 Creating Profile

Now let's create a profile, the profile is like a configuration for the shell, in this case, our shell is a PowerShell Core. The profile is pretty important because oh-my-posh will first load the profile, before activating it. The profile can put which theme to use, plugins, aliases, etc, and more. I will discuss more in the plugin section for more settings. In this section, I will only add basic settings like the oh-my-posh theme.

Different versions of the PowerShell profile are stored in different locations:

#PowerShell (default)5.X
C:\Users\test\Documents\PowerShell
#PowerShell core 7.x
C:\Users\test\Documents\PowerShell

You can manually create it by creating the file in this directory, but I prefer using this command which will autogenerate the profile in this directory.

Create a new profile the first time only :
New-Item -Path $PROFILE -Type File –Force

This will only generate a file in the location with empty content, and display the location like below picture. As you can see the size of the file is empty it’s because it only generates the file or profile.

Now you have to edit this profile, you can edit using notepad $profile, which means editing with Notepad. You can also edit with other text editors like vim, nano, etc but you need to install the editor first.

From above you will realize the profile’s name is too long and hard to memorize, instead, we can use the $profile. You can use this command to check the profile location Get-Item -Path $PROFILE which will have the same output as above.

5.2 edit profile update theme

Let's add the theme to the profile, in step3 set the theme, now instead of setting, you put the command inside the $profile, like this:

save it and active by this command: . $profile , now open a new session that will update the theme according to what you set in your profile. If you don’t activate it, you need to reopen new window terminal.

If occur error message, please run this command Set-ExecutionPolicy RemoteSigned. I will explain this in part 6 on installation occur Error for the Execution policy if you’re interested, or you can refer link on Microsoft doc.

5.3 Reassign profile to another location (optional)

I saw some people will try to change the default profile location to a specific location, but I prefer using the default. But in case you want to reassign your profile location(instead of the default location), you can use the below method. If you want to reassign your profile location to assign a new location to the profile like .config\powershell\user_profile.ps1 , basically, follow the below steps.

Step1: Edit this file notepad $PROFILE.CurrentUserAllHosts
Step2: add your new profile file location in the profile
.config\powershell\user_profile.ps1

New-Item -ItemType Directory -Force -Path ".config\powershell" | Out-Null; New-Item -ItemType File -Force -Path ".config\powershell\user_profile.ps1" -Value ""

So since we added the config file, it will first read user_profile.ps1 , $profile you can leave it empty or no need to generate it.

let's see this diagram below on the priority reading profile. Because I have assigned a new location, it will go to a new location to run the profile.ps1 file.

In step4 I have mentioned different methods of adding a theme with a full path or with $env prefix. But we can also put the same location as the $profile, with the below command:

$omp_config = Join-Path $PSScriptRoot ".\theme.json"
oh-my-posh --init --shell pwsh --config $omp_config | Invoke-Expression

Let me explain this command, please also refer to the picture below with a clear understanding.

Syntax: Join-Path $PSScriptRoot <current location .theme.json>

$PSScriptRoot: will record your current full path (current path), ex: if you run at c:/test
.\filename.json
: your theme file name

So basically this is using the theme same location as your $profile . Let's look at the below, as you can see $PSScriptRoot will be your full path for $profile, and theme.json is the theme you want to load. This method is pretty convenient, no need to add a complicated path, or remember where to put your theme.

same path for profile and theme

Step 6 Adding function and alias to profile

in Step 4 and Step 5 already learn how to add themes by cli command or by adding to the $profile. Now in this section, I will add more stuff to the profile. There are many things you can add inside the profile not just the theme.

If you have ever used Linux commands there are many useful commands, I will add some of them there. In the plugin section, I will add more modules to the profile.

If you add it to the $profile it will take effect, or else it will not take effect. So if you want to add an alias or function, without adding it into $profile nothing will happen.

6.1 Remove curl and wget alias (Only For window powershell 5.x)

If you use Window Powershell as a shell, then I highly suggest you need to add this one. The purpose of this is to remove the alias for wget and curl, because it’s not the real curl and get. Window set wget and curl as invoke-webrequest, but if you don’t use this tool then it doesn’t matter.

wget and curl been set as nvoke-webrequest to download, so we can remove the alias to work a standalone command. Please add these in $profile

If (Test-Path Alias:curl) {Remove-Item Alias:curl}
If (Test-Path Alias:wget) {Remove-Item Alias:wget}\

6.2 Adding Shortcut for Edit Host

If you ever need to edit the DNS in the hosts file, you need to access many directories. I add a function you just type in hosts it will automatically open this file.

function hosts { notepad c:\windows\system32\drivers\etc\hosts }

6.3 Adding alias or function

Let's add some alias in the profile, which allows us to use some hotkey on specific commands which alias is used for. You can add any alias you like, but I will only use the common alias I used.

# Alias
Set-alias tt tree
Set -Alias ll ls
Set-Alias g git
#Set alias vim nvim
Set-Alias grep findstr
Set-Alias tig 'C:\Program Files\Git\usr\bin\tig.exe'
Set-Alias less 'C:\Program Files\Git\usr\bin\less.exe'
Set-Alias grep findstr #findstr <string search> <filename>
Set-Alias ip ipconfig

Now you can also add using the function method to add a shortcut, I refer to many great functions from this ChrisTitusTech-automation config

function head {
param($Path, $n = 10)
Get-Content $Path -Head $n
}

function tail {
param($Path, $n = 10)
Get-Content $Path -Tail $n
}

function grep($regex, $dir) {
if ( $dir ) {
Get-ChildItem $dir | select-string $regex
return
}
$input | select-string $regex
}

#show virtual env
function envar () {Get-ChildItem env:}

function df {
get-volume
}
#get $env variable
function getenv {ChildItem env:}

#add the ohmyposh
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\iterm2.omp.json" | Invoke-Expression

6.4 adding utility function which command

In Linux we often use the which command, you can also add it by function

# Ultilities (Optional)
function which ($command) {
Get-Command -Name $command -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Path -ErrorAction SilentlyContinue
}

#example:
#whereis node
#whereis python
#whereis $profile

3. (Summary)Let me recap the faster way to set up the ohmyposh ²

This should be the basis of setting up oh-my-posh. To move further there’s a plugin section if you’re interested in it, which I will keep updating the profile file. The above is $profile is the basic, I have a link for my full $profile : full profile.

I will make a summary of the cheatsheet on what you learn about how to set up ohmyposh; a short version.

Step1: Install window terminal and power shell core
Step2: Navigate the window terminal, change the default terminal to the window terminal, and prompt to window PowerShell
Step3: Install nerd font to show font properly and change the window terminal to nerd font
Step4: Install oh-my-posh and setup

winget install JanDeDobbeleer.OhMyPosh -s winget

Step5: create a profile file

#auto generate or create first time
New-Item -Path $PROFILE -Type File –Force

#check profile location, display same as above
Get-Item -Path $PROFILE

# change policy
get-ExecutionPolicy RemoteSigned

Step6: update the theme to the profile notepad $profile


#activate ohmyposh with default theme
oh-my-posh init pwsh | invoke-expression
# assign theme using url method
oh-my-posh init pwsh --config 'https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/jandedobbeleer.omp.json' | Invoke-Expression
#assign theme in local path
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\iterm2.omp.json" | Invoke-Expression
# assign theme same location as profile
$omp_config = Join-Path $PSScriptRoot ".\theme.json"
oh-my-posh --init --shell pwsh --config $omp_config | Invoke-Expression

Full basic profile

#ohmyposh
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\iterm2.omp.json" | Invoke-Expression

# Alias
Set-alias tt tree
Set -Alias ll ls
Set-Alias g git
#Set alias vim nvim
Set-Alias grep findstr
Set-Alias tig 'C:\Program Files\Git\usr\bin\tig.exe'
Set-Alias less 'C:\Program Files\Git\usr\bin\less.exe'
Set-Alias grep findstr #findstr <string search> <filename>
Set-Alias ip ipconfig

This is the overall setting, I believe using the step should be able to work.

Part 3–1 WSL Linux Setup (bash) ¹

Now let's move on to set WSL Ubuntu on oh-my-posh, it’s the same as setting on Ubuntu. You just need to install a window terminal, you don’t need a power shell.

WSL stands for window subsystem for Linux, which can run Linux under Windows 10 or Windows 11. Overall WSL is a powerful tool that allows users to use both Windows and Linux in a system. So I will show some of the basic WSL commands before installing and setting up Oh-My-Posh.

Please refer to this link for more detailed WSL command information.

 1. WSL Command - Basic 
List and Install OS
2. window terminal changing home or root directory
3. export or import wsl environment
4. Setup Oh-my-posh
Step1: Set xterm-256color
Step2: Download and Install OH-MY-POSH
Step3 Install nerd font
Step4 setup oh-my-posh theme and prompt

1. WSL Command — Basic ²

By default, WSL command can work, but WSL is not enabled, restricting a lot of Linux commands. So we need to let wsl enable, so please go to the control pannel>program>program and feature, and enable the window subsystem for Linux (WSL), and virtual machine platform(VMP)for wsl like the below picture. You can also use this command to enable these two items.

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
subsystem for Linux & virtual machine platform

WSL: acts as a software layer that translates Linux system calls for Windows to understand, which mean window can communcation with linux. It relies on the Windows kernel, shares some resources with the Windows kerne and have slower performance compare to WSL2
WSL2(VMP): lightweight Linux virtual machine managed by the Virtual Machine Platform (VMP), which will enable WSL2. It runs its own linux kernel, seperate from window, leading to improved performance and compatibility with Linux applications.

You can use wsl --status to check wsl version, since I enable vmp it will be wsl2 as default.

  • List and Install OS ³

check your current PC-installed Linux distros:
wsl --list or wslconfig /list

List available Linux distributions for download through the online store:
wsl --list --online

list of os

Installed the OS:
wsl --install -d <Distro> , so you can install the OS from the above list of distro or OS that are available to install. Let me show you how to install Ubuntu on WSL

We can also list or install OS under the Windows Store or use the WSL command line depending on your preference.

Microsoft store

2. window terminal changing home or root directory ²

Linux file explorer default is stored under this location network/wsl$, you can press window+r or explorer and type \\wsl$ or \\wsl.localhost\Ubuntu which will look like below.

In Ubuntu, the window filesystem is stored in /mnt/ which will contain different drives, which means you can access your Windows system. In the same way, the window is also able to navigate the Ubuntu filesystem in \\wsl$ location

Let's open the window terminal and see the profile for Ubuntu the default will not mention the root directory

check the current home directory: /homer/username

Changing your default directory to root or home, you can use the commandline or startingdirectory in the window terminal, let me show you what it mean.

Startingdirectory- Change starting directory to /home

"source": "Windows.Terminal.Wsl",
"startingDirectory": "\\\\wsl$\\Ubuntu\\home\\",
"useAcrylic": true

command line : you can access with below option

wsl ~:linux directory /home/user
Wsl or wsl: window home directory /mnt/c/Users/test
wsl ~ -u root: access root user
wsl ~ -d <other_distro>: different distribution

"source": "Windows.Terminal.Wsl",
//"startingDirectory": "\\\\wsl$\\Ubuntu\\home\\",
"commandline": "wsl ~",
"useAcrylic": true

3. export or import wsl environment ²

If you have a wsl Linux environment and want to export and import to another PC then this is a great method to learn.

Export: wsl --export t <DistributionName> <export location and file name>
Import: wsl --import <DistributionName> <InstallLocation> <FileName>

For more detail on the command, you can refer to this post which talks about many commands and settings.

4. Setup Oh-my-posh ²

Now after understanding the basics of the WSL command, let's move to the next level of setting up oh-my-posh, which is a bit different from Window Powershell. I used the shell as bash, you can also change to zsh.

Additional shell command:

check your current shell: echo $SHELL or echo $0
check support shell: cat /etc/shells
change default shell:
chsh -s /bin/bash

Step1: Set xterm-256color ³

you can check your xterm: echo $TERM , set your environment variable to 256 colors:$term to xterm-256color

Step2: Download and Install OH-MY-POSH ³

Please install unzip first: sudo apt-get install unzip . Please create add bin folder mkdir bin and then install it.

install oh my posh on spefcic location
curl -s https://ohmyposh.dev/install.sh | bash -s --d ~/bin
note: You can change other location you like

Now if you don’t create a directory binwithout--d which means assign directory, then it will occur error like the below picture:

Now after installing it, we need to assign the PATH to it, else oh-my-posh will not be able to run in any location except the bin directory. Let me show that I mean the path, you can echo $PATH

As you can see there’s no oh-my-posh, so we need to add it.

There are a couple of way to add it, you can add it under .bashrc or create .bash_profile these files both work.

Create and edit .bash_profile and add this inside
export PATH=$PATH:/home/test/bin

let's activate it by source .bash_profile , now you can echo $PATH oh-my-posh bin will exist

Now execute the command oh-my-posh should work

The reason we need it is that under the bin file containing the oh-my-posh this tool, we need this tool to run this command in all locations.

Step3 Install nerd font ³

If you have already been set it up with PowerShell, then I think no need to install it again, just go to the window terminal, select Ubuntu profile and change font to nerd font.

If you are using Ubuntu to setup then this is how to install nerd font in Linux is partially different, please use this command to install

oh-my-posh font install

now choose the font you like and it will installed. After it go to the window terminal to choose your nerd font

Step4 setup oh-my-posh theme and prompt ³

You can use this command to activate the default theme: eval "$(oh-my-posh init bash)" . In Linux, there’s no command to show all themes like Get-PoshThemesto see all themes, please refer official site.

default activate theme

Now to apply the theme need to write into the profile, so we need to update the command.bashrc or .bash_profile .

As you can see in my profile, I commented on many themes, the first one you just type the theme name in POSH_THEME which will store it as a variable. This is great for not typing long filenames. The second is just to assign the full path and filename, and the last one is the default.

export PATH=$PATH:/home/test/bin

POSH_THEME="paradox"
eval "$(oh-my-posh init bash --config ~/themes/$POSH_THEME.omp.json)"

#full path
#eval "$(oh-my-posh init bash --config ~/themes/powerline_2.omp.json)"

#default
#eval "$(oh-my-posh init bash)"

Part 3–2 Command Prompt (CMD) ¹

I would like to talk about other shell setups like fish and cmd, but going to keep it short and simple, because it’s not quite important unless you need to use it.

CMD command prompt

You can also set ohmyposh under cmd with clink this tool.

  • Search clink: winget search clink
  • Install clink: winget install chrisant996.Clink

After installing it check where’s the profile or configure the file store location: clink info

  • update the theme into the profile shown in above
#url location
load(io.popen('oh-my-posh init cmd --config "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/M365Princess.omp.json'):read("*a"))()

#local location
load(io.popen('oh-my-posh --config="D:/agnoster_modify.json" --init --shell cmd'):read("*a"))()

#enable autosuggestion
clink set autosuggest.enable true

More reference information: https://www.cnblogs.com/hongdada/p/16826311.html

Part4 Plugin ¹

Let's move to an advanced section on adding some powerful modules or plugins. In this section I will introduce you to some more productive tools, you can decide whether to use them or not.

You can search on Google to see many more modules or plugins with this keyword: PowerShell module recommend

module command check package
1. Terminal Icons
2. Psreadline (auto-completion)
3. Fuzzy file finder or FZF
4. Z or zoxide, directory jumper
5. Fastfetch

module command check package ²

You might be using a lot of these commands to find to install the plugin tool:

- Install the module by name: Install-Module<module name> -Force
- Check specfic modules is available : Get-Module -Name <packagename> -ListAvailable
- list all aviable module install or not: Get-Module -ListAvailable
- List module installed: get-installmodule
- Uninstall module by name: Uninstall-Module <pkg name>

These are the modules I have installed:

get-installmodule
Get-module -ListAvailable

uninstall modules like using this example


#uninstall module
uninstall-Module -Name oh-my-posh
Uninstall-Module posh-git

#use pipeline to uninstall module
Get-InstalledModule -Name oh-my-posh | Uninstall-Module

1. Terminal Icons ²

This tool allows you to see different file types of folders using icons to represent them. From the below picture you can see before there’s no logo beside the directory or file, after installing it will see the logo of a specific folder displayed.

Install terminal icon:
Install-Module -Name Terminal-Icons -Repository PSGallery -Force

Import module into profile or command line:
Import-Module Terminal-Icons

2. Psreadline (auto-completion) ²

This is a powerful module, which has many functions on it. I will not use all of them, I will only pick important ones or useful ones. If you’re interested you can study on the official site. PSReadline basely is developed by Microsoft and used under PowerShell.

Essential PSReadline will automatically show what command you want to enter, it will predict it. Psreadline has many modules, I won’t mention all of them, so if you’re interested please refer to the link below.

-https://learn.microsoft.com/zh-tw/powershell/module/psreadline/get-psreadlinekeyhandler?view=powershell-7.4
-
https://github.com/PowerShell/PSReadLine

  • Install command:
# install psreadline 
Install-Module PSREadLine -Force
#or below more detail which recommend
Install-Module -Name PSReadLine -AllowPrerelease -Scope CurrentUser -Force -SkipPublisherCheck
import module: Import-Module PSReadLine

you can also use this to add to your profile, to check when to import

if ($host.Name -eq 'ConsoleHost')
{
Import-Module PSReadLine
}
  • Disable module: Set-PSReadLineOption -PredictionSource None
  • check all psreadline hotkey: Get-PSReadLineKeyHandler
    You can check this command to see the default hotkey of psreadline , in this section will set psreadline option, and it will update the key also. Please use this command wisely and it’s useful to check each function.

Let me explain some great options for psreadline, you can import in cli which will temporarily take effect, or be written into $profile to take effect. I will not explain all of the options, please keep them in mind, if interested please refer above link.

2.1 PSReadlineOption

Note: This will only work if you use Powershell core, if you use Windows Powershell it will run into an error, just keep this in mind.

#Import-Module PSREadLine
if ($host.Name -eq 'ConsoleHost')
{
Import-Module PSReadLine
}

# Set PSREadLine option
#support powershell7.0, 5.0 will not work
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption –PredictionViewStyle ListView

Set-PSReadLineKeyHandler -key Tab -Function Complete
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete

# Set-PSReadLineOption -EditMode emac
Set-PSReadLineOption -EditMode window

2.1.1 Set-PSReadLineOption -EditMode

EditMode specifies the command line editing mode, which means it allows you to use some hotkey to move the cursor to a different position. In the editmode there are these modes emac, window, and vi mode. You can refer to this link from Microsoft documentation for more detailed information on how to use the psreadline option.

Let me show you some examples of adding edit mode, when adding it when you type in the command line or terminal you can use like

For more functions please refer to this link, I think it mentions a lot, or you can use the command I mentioned earlier: Get-PSReadLineKeyHandler to show all functions and usage.

Note: The Set-PSReadLineOption -EditMode emac conflict with fzf

If you want to use the fuzzy finder which I will mention plugin section, then you either remove the emac mode or change to window mode. The reason is that the emac alt+c hotkey will conflict with the fzf alt+c, and emac will get a higher priority. I will explain how to check the conflict keys in fzf section.

You don’t have to add PSReadLineOption -EditMode , because there are also some alternative, methods that I will discuss below on changing the key instead in below. like

2.1.2 Set-PSReadLineOption-PredictionHistory

command add into profile or command line:
Set-PSReadLineOption-PredictionHistory

This module will predict and display suggestions generated based on previous commands in the command history. For example if the last I ever type cd /home, then when I type cd it will give me /home my previous suggestion, so it will predict what command you will be using.

PredictionHistory

2.1.3 Set-PSReadLineOption-PredictionViewStyle ListView

command add into profile or command line:
Set-PSReadLineOption -PredictionViewStyle ListView

When set to ListView, PowerShell displays predictive suggestions in a list format below the command line interface. This allows for easier navigation through suggestions using the arrow keys (up or down), providing a more interactive way to select from multiple options.

PredictionViewStyle ListView

2.1.4 HistoryNoDuplicates

command add into profile or command line:
Set-PSReadLineOption -HistoryNoDuplicates

This option allows not to show duplicate history command

2.1.5 colors option

you can change the display psreadline color by using the below command. If you’re interested in more detail, please go to link in the example4 and 5 sections. You can use the below command to check the current option or default value.

Check the current color or option: get-PSReadLineOption

Set-PSReadLineOption -Colors @{ InLinePrediction = [ConsoleColor]::Cyan }
# this is the color default
Set-PSReadLineOption -Colors @{ InlinePrediction = "`e[38;5;238m" }

From above the color format is called ANSI escape code, you can search online for more resources. You can use the below code to see the color.

If you see some parameters the color is light, like when I use git commit -m 'message', the message is so light, you can try with below to set the color:

# you can try like this as example
Set-PSReadLineOption -Colors @{
Command = 'Yellow'
Parameter = 'Green'
String = 'DarkCyan'
}

Please look at the below example to know what I mean, when I change the string option to green, typing the string inside the quote of the message, it will change to green(default is grey). I changed the color to grey (second sample) you will see what I mean, you partially couldn’t see the word because of the color. Each theme might have its color, so if it’s hard to see you can adjust color using this method. You can add it to our profile or on the command line

Here is another example, this is using the default theme without assigning other themes, it’s the default parameter I barely can’t see, this time you can use the above example to change color.

2.2 PSReadLineKeyHandler

in this module will introduce two option:
-
key tab: allows you to remap keyboard shortcuts used for tab completion. In other word it like press tab will give auto completion.
-
key : allows you to remap keyboard shortcuts used for other function
-
cord: allows you to define custom keyboard shortcuts (chords) allot to add specific keyword to trigger powershell. In other word mean to assign hotkey or shortcut key.

2.2.1 PSReadLineKeyHandler key

Please add this to your $profile, or else some functions might not work or will cause an error. You can get the full profile on my github page. The are more useful functions on this link, but I am not going to mention all of them.

Please add this item to $profile else some of the keys will not work properly

using namespace System.Management.Automation
using namespace System.Management.Automation.Language

2.2.1-1 key Tab

  • Key Tab -Function Complete

command:
Set-PSReadLineKeyHandler -key Tab -Function Complete

When I enter ca and tab it will show related commands, these commands might be global or system commands and also use it for filtering files. Like typing we with tab key, CLI recognizes that multiple files in the current directory start with we and display based on that prefix file.

This method will show the related keyword file you type, but unfortunately, you aren’t able to select the file name, the next option solves this problem.

  • Key Tab -Function MenuComplete

command:
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete

If you are finding files that start with weather, you can press we with tab you can use tab or arrow up and arrow down to navigate to the suggestion and select the filename.

Essentially it’s used when you have a related or similar name of multiple files. This is a great approach to the original method using a tab keep on selecting one file at a time and display it in the terminal, instead, this method will show all the results on the menu you just have to select your match.

MenuComplete

The difference between function complete and menu complete is they both will display all the related files you filter, but menu complete allows you to use the up , down, and tabs key to select the filename, which you do not need to type the full name of the file.

2.2.1–2 uparrow and downarrow display related history

This command is basely when press command + arrow up or down will show previous history. For example: if I press cd <folder> or cd .., then when I press cd with arrow up or down it will only show the cd command’s history other commands not related will not show. When you press command +arrow, the color of the command will change

Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward

2.2.1–3 F1 for help command

If you not know how to use the command and need help, you can type a command + F1 for hep, which will pop a help command, like below picture, in this case using Set-ExecutionPolicy as example.


# F1 for help on the command line - naturally
Set-PSReadLineKeyHandler -Key F1 `
-BriefDescription CommandHelp `
-LongDescription "Open the help window for the current command" `
-ScriptBlock {
param($key, $arg)

$ast = $null
$tokens = $null
$errors = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$errors, [ref]$cursor)

$commandAst = $ast.FindAll( {
$node = $args[0]
$node -is [CommandAst] -and
$node.Extent.StartOffset -le $cursor -and
$node.Extent.EndOffset -ge $cursor
}, $true) | Select-Object -Last 1

if ($commandAst -ne $null)
{
$commandName = $commandAst.GetCommandName()
if ($commandName -ne $null)
{
$command = $ExecutionContext.InvokeCommand.GetCommand($commandName, 'All')
if ($command -is [AliasInfo])
{
$commandName = $command.ResolvedCommandName
}

if ($commandName -ne $null)
{
Get-Help $commandName -ShowWindow
}
}
}
}

However, there’s an alternative command that also achieves a relate function without adding a long function, by adding it into $profile.

Set-PSReadLineKeyHandler -Chord Ctrl+F1 -Function ShowCommandHelp

2.2.1–4 F7 list history in grid

This will pop up like grid which will list all history, and allow you to scroll down or up to find your history.

# This key handler shows the entire or filtered history using Out-GridView. The
# typed text is used as the substring pattern for filtering. A selected command
# is inserted to the command line without invoking. Multiple command selection
# is supported, e.g. selected by Ctrl + Click.
Set-PSReadLineKeyHandler -Key F7 `
-BriefDescription History `
-LongDescription 'Show command history' `
-ScriptBlock {
$pattern = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$pattern, [ref]$null)
if ($pattern)
{
$pattern = [regex]::Escape($pattern)
}

$history = [System.Collections.ArrayList]@(
$last = ''
$lines = ''
foreach ($line in [System.IO.File]::ReadLines((Get-PSReadLineOption).HistorySavePath))
{
if ($line.EndsWith('`'))
{
$line = $line.Substring(0, $line.Length - 1)
$lines = if ($lines)
{
"$lines`n$line"
}
else
{
$line
}
continue
}

if ($lines)
{
$line = "$lines`n$line"
$lines = ''
}

if (($line -cne $last) -and (!$pattern -or ($line -match $pattern)))
{
$last = $line
$line
}
}
)
$history.Reverse()

$command = $history | Out-GridView -Title History -PassThru
if ($command)
{
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert(($command -join "`n"))
}
}

2.2.1–5 Auto-add SmartCloseBrace

Adding a single or double quote will auto-give you the end notation which means you don’t have to type the ending quote. You can also type the string first and then highlight or select the string again and add a quote it will auto-add a quote around the text.

Example1: Type ' it will automatically add ending ' notation
Example2: select string will auto add start and end quote

Set-PSReadLineKeyHandler -Key '"',"'" `
-BriefDescription SmartInsertQuote `
-LongDescription "Insert paired quotes if not already on a quote" `
-ScriptBlock {
param($key, $arg)

$quote = $key.KeyChar

$selectionStart = $null
$selectionLength = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetSelectionState([ref]$selectionStart, [ref]$selectionLength)

$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

# If text is selected, just quote it without any smarts
if ($selectionStart -ne -1)
{
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $quote + $line.SubString($selectionStart, $selectionLength) + $quote)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
return
}

$ast = $null
$tokens = $null
$parseErrors = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$parseErrors, [ref]$null)

function FindToken
{
param($tokens, $cursor)

foreach ($token in $tokens)
{
if ($cursor -lt $token.Extent.StartOffset) { continue }
if ($cursor -lt $token.Extent.EndOffset) {
$result = $token
$token = $token -as [StringExpandableToken]
if ($token) {
$nested = FindToken $token.NestedTokens $cursor
if ($nested) { $result = $nested }
}

return $result
}
}
return $null
}

$token = FindToken $tokens $cursor

# If we're on or inside a **quoted** string token (so not generic), we need to be smarter
if ($token -is [StringToken] -and $token.Kind -ne [TokenKind]::Generic) {
# If we're at the start of the string, assume we're inserting a new string
if ($token.Extent.StartOffset -eq $cursor) {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$quote$quote ")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
return
}

# If we're at the end of the string, move over the closing quote if present.
if ($token.Extent.EndOffset -eq ($cursor + 1) -and $line[$cursor] -eq $quote) {
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
return
}
}

if ($null -eq $token -or
$token.Kind -eq [TokenKind]::RParen -or $token.Kind -eq [TokenKind]::RCurly -or $token.Kind -eq [TokenKind]::RBracket) {
if ($line[0..$cursor].Where{$_ -eq $quote}.Count % 2 -eq 1) {
# Odd number of quotes before the cursor, insert a single quote
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($quote)
}
else {
# Insert matching quotes, move cursor to be in between the quotes
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$quote$quote")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
return
}

# If cursor is at the start of a token, enclose it in quotes.
if ($token.Extent.StartOffset -eq $cursor) {
if ($token.Kind -eq [TokenKind]::Generic -or $token.Kind -eq [TokenKind]::Identifier -or
$token.Kind -eq [TokenKind]::Variable -or $token.TokenFlags.hasFlag([TokenFlags]::Keyword)) {
$end = $token.Extent.EndOffset
$len = $end - $cursor
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($cursor, $len, $quote + $line.SubString($cursor, $len) + $quote)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($end + 2)
return
}
}

# We failed to be smart, so just insert a single quote
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($quote)
}

Adding a parenthesis(), braces{}, and bracket[], will auto-give you the end notation just like the quote above, which means you don’t have to type the ending notation. The same you can type the string first, select the string, and then add notation it will auto-wrap the string around the notation. This means you just add a single notation it will auto-add the ending for you

Example1: Type [ it will automatically add ending ] , same as other notation
Example2:select string will auto add start and end notation

Set-PSReadLineKeyHandler -Key '(','{','[' `
-BriefDescription InsertPairedBraces `
-LongDescription "Insert matching braces" `
-ScriptBlock {
param($key, $arg)

$closeChar = switch ($key.KeyChar)
{
<#case#> '(' { [char]')'; break }
<#case#> '{' { [char]'}'; break }
<#case#> '[' { [char]']'; break }
}

$selectionStart = $null
$selectionLength = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetSelectionState([ref]$selectionStart, [ref]$selectionLength)

$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

if ($selectionStart -ne -1)
{
# Text is selected, wrap it in brackets
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $key.KeyChar + $line.SubString($selectionStart, $selectionLength) + $closeChar)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
} else {
# No text is selected, insert a pair
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)$closeChar")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
}

Set-PSReadLineKeyHandler -Key ')',']','}' `
-BriefDescription SmartCloseBraces `
-LongDescription "Insert closing brace or skip" `
-ScriptBlock {
param($key, $arg)

$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

if ($line[$cursor] -eq $key.KeyChar)
{
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)")
}
}

2.2.1–6 Auto-add SmartBackspace

This function is when you only leave out empty strings just notation like "" or () you can delete the start notation, which will automatically help you auto-delete your end notation.

Set-PSReadLineKeyHandler -y Backspace `
-BriefDescription SmartBackspace `
-LongDescription "Delete previous character or matching quotes/parens/braces" `
-ScriptBlock {
param($key, $arg)

$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

if ($cursor -gt 0)
{
$toMatch = $null
if ($cursor -lt $line.Length)
{
switch ($line[$cursor])
{
<#case#> '"' { $toMatch = '"'; break }
<#case#> "'" { $toMatch = "'"; break }
<#case#> ')' { $toMatch = '('; break }
<#case#> ']' { $toMatch = '['; break }
<#case#> '}' { $toMatch = '{'; break }
}
}

if ($toMatch -ne $null -and $line[$cursor-1] -eq $toMatch)
{
[Microsoft.PowerShell.PSConsoleReadLine]::Delete($cursor - 1, 2)
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::BackwardDeleteChar($key, $arg)
}
}
}

2.2.2 PSReadLineKeyHandler -Chord

This is just like PSReadLineOption which assigns custom function keys to specific key combinations according to your preference. Linux has these types of shortcuts, if you want to use them in the window then just add this using the chord option:

ctrl+d: exit terminal
ctrl+w: type a word and clear the string
ctrl+a: type word move to start
ctrl+e: type word move to end

At the beginning in PSreadlineoption I mention editmode like emac, vi, or window mode, these function key has it’s own hotkeys, so to not conflict with these hotkeys you can decide not to use the edit mode, and instead add your key using this chord option.

These are the examples of keys, but there are still more, please refer to the documentation for more details.

# Ctrl+x edxit powershell
Set-PSReadlineKeyHandler -Chord ctrl+x -Function ViExit
Set-PSReadLineKeyHandler -Chord 'Ctrl+d' -Function DeleteChar 
Set-PSReadlineKeyHandler -Chord ctrl+w -Function BackwardDeleteWord
Set-PSReadlineKeyHandler -Chord ctrl+e -Function EndOfLine
Set-PSReadlineKeyHandler -Chord ctrl+a -Function BeginningOfLine
# select word backward
Set-PSReadLineKeyHandler -Key Alt+B -Function SelectShellBackwardWord
# select word afterward
Set-PSReadLineKeyHandler -Key Alt+F -Function SelectShellForwardWord
# CaptureScreen is good for blog posts or email showing a transaction
# of what you did when asking for help or demonstrating a technique.
#ctrl+c and ctrl+d to copy terminal
#ctrl+v to paste
Set-PSReadLineKeyHandler -Chord 'Ctrl+d,Ctrl+c' -Function CaptureScreen

3. Fuzzy file finder or FZF ²

This is a powerful tool, but I won’t explain all the features, I will only explain the important part. FZF it’s a find command that can help you find your file, but more powerful than find.

This is a tool like an interactive search bar on your terminal command line which allows regex matching, and filter files or directories.

Imagine you’re typing a command in the terminal, but you can’t quite remember the exact name. Fuzzy finder acts like a smart search bar that helps you find what you’re looking for, even if you mistype a letter or two. It suggests commands or filenames based on what you start typing, making it much faster and easier to find what you need.

PSFzf is a PowerShell module that wraps fzf, a fuzzy file finder for the command line. Since I am using Windows, so I will use PSfzf, if you’re using Linux or Mac, you can just use fzf instead. Please refer official site for more details.

Installation ³

If you never install scoop, please refer below section or use this command to install as below:
scoop command:
irm get.scoop.sh | iex
install fzf : scoop install fzf
install psfzf: Install-Module -Name PSFzf -Scope CurrentUser -Force

Please restart terminal, else scoop command will not work.

If using fzf every time you need to invoke the fzf command in PowerShell command line, to fix this problem we can install PSFzf. Basely this is a wrapper around FZF module which can be used by the PowerShell

import module into the profile to use it ³

import module into profile:

Import-Module PSFzf
Set-PsFzfOption -PSReadlineChordProvider 'Ctrl+f' -PSReadlineChordReverseHistory 'Ctrl+r'

Let me explain in simply way of these hotkey shortcuts to be more clear:

Ctrl+f (Forward Fuzzy Search) :to fuzzily search for a file or directory in your home directory and select it will get the path of it
Ctrl+r(Reverse Fuzzy Search):to fuzzily search your command searches your history, similar to the history command, and run select or use it
Alt+c ( Set Location): fuzzily search for a directory in your home directory and allow to cd to directory. Basely this is quickly select to subdirectory.

As you can see this is pretty a powerful tool that allows you to search files, access directories or files, and show history.

Layout FZF ³

From the above know how to use fzf, Let's move some great commands with the layout of the fzf we can adjust the height rather than the default full height. If you want to adjust add these into $profile

  • height and reverse

height as 40% with reverse: $(fzf — height 40% — reverse)
height as 50%: $(fzf — height 40%)
reverse is just the total result which i mark as red in below

  • adding border

If you want to use the specific key to enable it you have to declare like function as below, so when I press f2 it will display with a border like the below picture

adding border and layout:
function f2{$(fzf — height 60% — layout=reverse — border)}

Preview ³

Preview allows you to read files without opening them, but we need to install bat module using this command : scoop install bat .

This is just command will temporary take effect:
Preview file
: fzf --preview='cat {}'
Preview and edit file (change your prefer text editor):
notepad $(fzf — preview=’cat {}’)

Now if you want to use this module you have to add a function or set it as the default fzf command like below. To use this preview need to add to $Profile, you just press ff it will switch to preview mode like below picture.

#seat as function
function ff{
nvim $(fzf --preview 'bat --style=numbers --color=always --line-range :500 {}')
}

#set as fzf default value
$env:FZF_DEFAULT_OPTS=' - height 40% - layout=reverse - border'

from the above picture when you select on specific file, it will preview what the file looks like, you can also enter to modify it since I added nvim in front of it. If your textedior is not nvim, change to your editor like notepad.

Search syntax ³

Search syntax, as below to help search specific file:

Add fd to fzf ³

FD is another plugin that I will not cover in this post, basically it’s like fzf but faster than fzf. You can add an .ignore file to ignore the file not to search, and use the ! to unignore.

Let me show what I mean when I add the directory or filename inside .ignore when fzf search these items will get ignored.

Another example of not ignoring using ! in front of a file or directory, so in this case, I add !GUI, which means will not ignore GUI, only ignoret1/ directory. So in this case all files or directories only t1/ and its subdirectory will not be found.

FD as file discover:
This is a powerful tool better than find command, the
default fzf uses the find command (in linux), but in window it uses PowerShell cmdlets like Get-ChildItem. , instead we can use the fd which is quicker and smarter than find, ignoring directories like .git and using your .gitignore options while searching.
Install: scoop install fd or winget install sharkdp.fd
Please refer url

in order to use fd just use fd command, but we can let fzf uses fd as default find command like this:

#fzf default to fd command: 
$env:FZF_DEFAULT_COMMAND='fd --type file'
# exclude .git
$env:FZF_DEFAULT_COMMAND = 'fd --type file --follow --exclude .git'
#include hidden files, exclude .git
$env:FZF_DEFAULT_COMMAND = 'fd --type file --follow --hidden --exclude .git'

#fzf default to ag command
$env:FZF_DEFAULT_COMMAND="ag -l --hidden --ignore .git"

So overall we can set the default fzf either using one of them:

fd: Designed specifically for searching filenames based on patterns (globbing patterns and regular expressions).

ag(silver search): Powerful tool for searching the content of files using regular expressions.

Problem with Alt+C conflict emacs command ³

However, there’s one thing that I mentioned earlier if you use the psreadline -EditMode as emac then the alt+c key might not work, due to a conflict with emac default alt+c command as CapitalizeWord.

But actually, you can set a manual key like below,
Set-PSReadLineKeyHandler -Chord ‘Alt+Shift+C’ -Function CapitalizeWord, but unfortunately in this case editmode emac will have a high priority.

In the below picture, you can see the left picture is the default hotkey alt+c was not added. When I add emac to editmode, it implements it, and then I add fzf command, it also implements it. So as you can see both of them gain alt+c hotkey, this is what I mean by conflict.

command for default value: Get-PSReadLineKeyHandler

Now let me implement emacs, and change the hotkey to a different key, you will see the old alt+c will still exist not remove it, please refer picture and command below

#set editmode to emacs 
Set-PSReadLineOption -EditMode Emacs
# set a different hotkey to CapitalizeWord
Set-PSReadLineKeyHandler -Chord 'Alt+Shift+C' -Function CapitalizeWord
# add fzf
Set-PsFzfOption -PSReadlineChordProvider 'Ctrl+t' -PSReadlineChordReverseHistory 'Ctrl+r'

As you can see when I assign a new key it still uses the old key.

Now to solve this problem there are two solution:
Case1: remove emac and change to other mode
Case2: use emac, but you need to add this command :
#access directory alt+c and add into function so you can use it
Case3:
access directory:function FzfNav { Get-ChildItem . -Recurse -Attributes Directory | Invoke-Fzf | Set-Location }
edit file in editor :Get-ChildItem . -Recurse -Attributes !Directory | Invoke-Fzf | % { notepad $_ }

4. Z or zoxide, directory jumper ²

This lets you navigate the file system based on your cd command history, which just remembers your last command’s directory.

Install: Install-Module -Name Z –Force

We don’t need to import the module, we can use the z command directly. It will remember your command the next time use z. So imagine every time go to a specific location like cd C:\Users\User\Downloads . But if we visit the directory once, it will remember it, so next time you can just type z with the directory or file name, like z Download, it will access to cd C:\Users\User\Downloads. It will recognize the path already.

Fastfetch ²

It’s an alternative to neofetch, basely it is to show system information, official link . This page is awesome-fetch has many different types of fetch.

install fast fetch: winget install fastfetch

#generate config: 
fastfetch --gen-config
# window: C:\Users\test\.config\fastfetch\ config.jsonc

#load customer cfg:
fastfetch -load-config /path/to/config_file
fastfetch -load-config .\aa.jsonc

#SHOW ONLY HARDWARE:
fastfetch -c hardware

#PRINT LOGOS:
fastfetch - print-logos

#USE LOGO:
fastfetch - logo sparky
#print all logo:
fastfetch - print-logos
# no logo:
fastfetch --logo none
# picture as logo
pghoto: fastfetch - logo ~/Pictures/avatar-transparency.png - logo-type iterm - logo-width 30 - logo-height 15

#USE CERTAIN COLOR :
fastfetch - color blue

#COLORS 1–9, 5 BLINKING:
fastfetch - color 5

#HELP - BUNCH OF OPTIONS:
fastfetch - help

#All filesytem paths can be:
fastfetch - list-data-paths

You can refer more preset on this link :
Preset:
https://github.com/fastfetch-cli/fastfetch/tree/dev/presets
https://github.com/fastfetch-cli/fastfetch/tree/dev/presets/examples

Part 5 Segment for the customized theme ¹

In the theme section, all of the theme is the official theme, however, if you don’t like it, you can customize your theme using the segment.

There are many different segments available in the documentation. Please note, the more the function you put the more loading the terminal will take to load.

segments

Below is a diagram I try to distinguish between block and segment, for more understanding.

Create your theme: vi newfile.omp.json, you can copy the clean json code like below and edit: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/themes/clean-detailed.omp.json

if you are trying to design it, you can use this command to debug for temporary take effect:
oh-my-posh — init — shell pwsh — config ./file.omp.json | Invoke-Expression

The below is a basic config, you can refer to the segment style documentation to see more on how to add more settings. It supports Json, YAML, and toml format.

Json format

{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"final_space": true,
"version": 2,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"type": "path",
"style": "diamond",
"powerline_symbol": "\uE0B0",
"foreground": "#ffffff",
"background": "#61AFEF",
"template": " {{ .Path }} ",
"properties": {
"style": "folder"
}
}
]
}
]
}

Yaml Format

$schema: https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json
final_space: true
version: 2
blocks:
- type: prompt
alignment: left
segments:
- type: path
style: diamond
powerline_symbol: "\uE0B0"
foreground: "#ffffff"
background: "#61AFEF"
template: " {{ .Path }} "
properties:
style: folder

Let me show some important or useful effects after setting it:

Style syntax: style: <powerline>| <diamond> | <plain> |<accordion>

Start and ending Diamond :

Add powerline symbol

”powerline_symbol”: “\uE0B0”

If you use the style powerline, then you can add logo, by adding powerline symbol. When you see the /u this means utf, you can go to the nerd font page and see what the logo looks like, just remove the /u and search for the code, which looks like this:

Sometimes the logo or symbol can’t show on your text editor, you can try with visual code it will show, if not you can use the UTF code, I organized the common uses are:

  • Adding a battery into another segment

there are many segments you can add, just copy and paste will be fine

  • block type: <prompt>|<rprompt>

Let me talk about the block’s type which will be prompt and rprompt . Let's have a look at my theme, in which I created three blocks, let look at the second lock. I set my alignment to the right and changed the type to prompt. The reason is if I don’t change the type to prompt, it will lay on the right side on block 1 as soon as I move to a different path it will overlap.

This is what I mean without rprompt,

prompt and promop

As you can see I set alignment to the right, which this is stores the datetime, and memory. It will be the same line block and block 1, as long as i get longer stuff, one part will block overlap which looks messy, so rpromp twill move the prompt to the right side, and this is the reason for the prompt.

Let me show some of the themes I find on youtube or other blogs, if you’re interested you can take a look at it.

Part 6 Window other settings ¹

In this section, I want to explain some other window settings that might be useful with the terminal setting.

 Window Terminal Profile 
select will auto-copy
copy and paste multiply line without pop warming message
Clear-Hidden showing the terminal logo
Installation occurs Error - Execution Policies
Window package setting
1.Winget
Download and install winget
winget command
Search available package winget support
Install package
2. Scoop and chocolately
Scoop installation
scoop command
scoop list installed package
Scoop install package
3. Install tool

Window Terminal Profile ²

There are some settings you can add to the terminal profile file to take effect these settings, to open the window terminal setting you can press ctrl+shift+p scroll down or typeopen settings file or even use ctrl+alt+, to open setting.json

  • select will auto-copy ³

This is a great method when selecting the string it will auto copy, you don’t have to right-click copy. You can establish two methods, one is to enable copyonselect inside the window terminal profiles file, and another method is to add a function to your $profile.

Method1: adding into settings.json in window terminal
Default
“copyOnSelect”: false , so change it to True to enable auto copy

copyOnSelect enable

Method2: add the below function into $profile

  • copy and paste multiply line without pop warming message ³

So when you copy multiple lines and paste into the window terminal it will pop a Warming message, to avoid the warming, please refer to below picture to what meant about the warming message

paster multiply line

please add this line to disable warming:"multiLinePasteWarning": false

multiLinePasteWarning disable not pop warming
  • Clear-Hidden showing the terminal logo ³

When loading Powershell, you will notice that the top of the terminal will have a Powershell version or logo like the below picture.

We can hide the message by adding -nologo this option is like the below picture.

window terminal setting
command two version powershell

Installation occurs Error — Execution Policies ²

IF you download and install occur fail Error on Execution Policies, please use this to fix the resolution on changing the policy.

You can first check your current policy: get-ExecutionPolicy and list all policy:Get-ExecutionPolicy -List

We need to set LocalMachine to RemoteSigned to solve this issue:
get-ExecutionPolicy RemoteSigned

To understand each Scope, this is a list of descriptions, to see more detail please refer to this link

Restricted (Default): This is the most secure option. No scripts are allowed to run, not even ones you write yourself.
RemoteSigned: This allows scripts signed by a trusted source (like Microsoft) to run. It’s like having a guard who checks IDs — only scripts with valid “signatures” (like an artist’s signature) are allowed. Scripts you write yourself won’t work unless you sign them with a special certificate. Files that are downloaded from the internet must be signed by a trusted publisher or must be unblocked.
AllSigned: This allows any script with a valid signature to run, regardless of who signed it. It’s less secure than RemoteSigned because it trusts any “signature,” even from unknown sources. Imagine a guard who just checks for a valid ID but doesn’t care who issued it. Scripts must be signed by a trusted publisher, like Microsoft or a well-known software vendor. Think of it like a document requiring a verified signature from a recognized authority.
Bypass (Not Recommended): This completely disables script execution restrictions. It’s like having no security guard at all! Any script can run, which is very risky and not recommended unless you fully understand the potential dangers.

Window package setting ²

There are many window packages too that allow us to download specific tools or packages to use. Below are the most common commands we can use to download packages. In this section, I am just going to mention some of them, but not all.

1. Winget ³

The winget command line tool enables users to discover, install, upgrade, remove, and configure applications on Windows 10 and Windows 11 computers. The winget the command line tool is only supported on Windows 10 1709 (build 16299) or later at this time. Winget is like Linux’s apt-get.

Download and install winget
There are a couple of ways to download and install it:

Method 1: store and type app installer
https://apps.microsoft.com/detail/9nblggh4nns1
Method2: Microsoft offical site to downlaod it
https://learn.microsoft.com/en-us/windows/package-manager/winget/

Install winget: Add-AppPackage

winget command

Winget version: winget –version
Search pkg: winget search <packagname>
Install pkg:
winget install <packagname>
you can also access this link to see available package

  • Search available package winget support

If you want to install a specific package or tool using Winget, you can search name package. Syntax: winget search <appname> below is an example search git
winget search --id=github
or winget search --name=github

If the package is not available, you can try with the other window package like Scoop or Choco.

  • Install package

Since you have searched for package, now you can use the install command to install the package:

Syntax: winget install <appname>
install git: winget install --id=Git.Git –e –source winget

2 Scoop and Chocolatey³

2.1 Scoop installation

We need to install Scoop in order to use it, the command is :
installation command: iwr -useb get.scoop.sh | iex

if it’s can’t install please first run this command: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

Install chocolatey:

 Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

2.2 scoop command

Now scoop command should be able to be used, let's try some commands.

  • scoop list installed package: scoop list
  • Scoop install package

so we can use it to install packages, like curl, sudo like below.

Install curl/sudo/jq : scoop install curl sudo jq

search specific installed package: Scoop search <package>
show package detail information, author: Scoop info <package>
uninstall package, -p delete cfg: Scoop uninstall <package>
update all installed package: Scoop update *

3. Install tool ³

#install git: 
winget install --id Git.Git -e --source winget

# nodejs
WINGET INSTALL OPENJS.NODEJS.ltS

#nano text edior
#winget
winget winget install -e --id GNU.Nano
#choco
Choco choco install nano -y

Conclusion ¹

There are many stuff that i cover installing terminal, PowerShell, setup oh-my-posh, theme, wsl environment, window command, and many more stuff. I know there’s a lot i cover especially the plugin section. Below is the the diagram to understand the roadmap of this post.

You will need to window Terminal, and Powershell to run oh-my-posh, if not the font will look weird. All of the settings need to be added inside the $profile to take effect and think as configuration, and indeed it will load the file.

I have created an annotation to set up and profile file, you just have to run the setup file which will download and install the tool and load the profile. You can also change the profile of yours.

setup_testing_automation_me.ps1 : install related application, if you have your own profile change this part
Invoke-RestMethod <your fileMicrosoft.PowerShell_profile.ps1> -OutFile $PROFILE

These are pretty useful terminal environments for people who often use Linux or Windows terminals, which will make your work more productive. If you ever have been using zsh using ohmyzsh it has the same effect. There are many more commands and tools I didn’t convert like warp which is a powerful AI terminal and its default has added autocomplete.

One of the key points on this setup you get to know many great plugins like autocomplete, fzf, window package manager, and more stuff.


#install oh-my-posh
winget install JanDeDobbeleer.OhMyPosh -s winget
winget upgrade JanDeDobbeleer.OhMyPosh -s winget

# activate it
oh-my-posh init pwsh | invoke-expression
# get all oh-my-posh theme
Get-PoshThemes –List
# change theme
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\iterm2.omp.json" | Invoke-Expression

#install scoop
iwr -useb get.scoop.sh | iex
# install chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
# get envirnoment variable
Get-ChildItem env:

#powershell or application run error
Get-ExecutionPolicy -List
Set-ExecutionPolicy RemoteSigned

# plugin terminal Icon
Install-Module -Name Terminal-Icons -Repository PSGallery -Force
Import-Module Terminal-Icons

Install-Module<module name> -Force
get-installmodule

# plugin psreadline
Install-Module PSREadLine -Force
Install-Module -Name PSReadLine -AllowPrerelease -Scope CurrentUser -Force -SkipPublisherCheck
Import-Module PSReadLine
Get-PSReadLineKeyHandler

#install fzf
scoop install fzf
Install-Module -Name PSFzf -Scope CurrentUser -Force #install psfzf
# install fd
scoop install fd
winget install sharkdp.fd

# install z
Install-Module -Name Z –Force

#install fastfetch
winget install fastfetch

Reference ¹

--

--