Repository: JanDeDobbeleer/oh-my-posh
Pull request #550 (2021-03-20 18:32:23)

feat: multiple config formats
### Prerequisites

- [x] I have read and understand the `CONTRIBUTING` guide
- [x] The commit message follows the [conventional commits][cc] guidelines
- [x] Tests for the changes have been added (for bug fixes / features)
- [x] Docs have been added / updated (for bug fixes / features)

### Description

[Description of the change]

[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary


JanDeDobbeleer: @lnu @TravisTX when you have some time available, I'd love some additional manual validation on this one :-) I tested everything and "works on my machine" 😓 
TravisTX: Everything seems to be working correctly. I can't figure out how to get the $schema to work in yaml using vscode.  My understanding is the json schema should also work with yaml.  I do have the `vscode-yaml` extension, which gives me coloring, but seems to not be giving me the context from the schema.  Have you had any luck with this?
lnu: Will give a try tomorrow morning. Good work 👍 
JanDeDobbeleer: Vscode autocomplete is on my list. Didn't look at it yet.
lnu: <img width="415" alt="image" src="https://user-images.githubusercontent.com/1829553/111895524-719c1c00-8a13-11eb-9337-195cb0b06c3c.png">

json can be removed
lnu: > Everything seems to be working correctly. I can't figure out how to get the $schema to work in yaml using vscode. My understanding is the json schema should also work with yaml. I do have the `vscode-yaml` extension, which gives me coloring, but seems to not be giving me the context from the schema. Have you had any luck with this?

It works here when setting the schema url in user config. But it fails when set at the top of the yaml file(it should work):
# yaml-language-server: $schema=<urlToTheSchema>
lnu: The only downside of yaml and toml is the lack of inline schema definition like the json one. Should work with yaml but somewhat fails and toml supports only schema uploaded to a central repo.
For the pull, looks good to me.
lnu: even better toml extension supports toml schema but not inline. https://github.com/tamasfe/taplo/issues/95.
JanDeDobbeleer: Ok. So, on my to-do list:
- Add inline schemas for supported languages if it's not present
- Create helper functions to avoid adding your current config (like pwsh does)
lnu: Tested all your changes(export_poshconfig and export-poshtheme) and it works well 👍 
JanDeDobbeleer: @lnu maybe I should also align the name, no? `Export-PoshConfig` makes sense.

Patch:
diff --git a/docs/docs/installation.mdx b/docs/docs/installation.mdx
index 3b10448d..f01d8082 100644
--- a/docs/docs/installation.mdx
+++ b/docs/docs/installation.mdx
@@ -326,7 +326,7 @@ Or, when using `~/.profile`.
 It's advised to be on the latest version of fish. Versions below 3.1.2 have issues displaying the prompt.
 :::
 
-Redefine `fish_prompt` in `~/.config/fish/config.fish`:
+Initialize Oh my Posh in `~/.config/fish/config.fish`:
 
 ```bash
 oh-my-posh --init --shell fish --config ~/.poshthemes/jandedobbeleer.omp.json | source
@@ -376,17 +376,17 @@ available options first, by starting with the [configuration guide][configuratio
   groupId="env"
   values={[
     { label: 'powershell', value: 'powershell', },
-    { label: 'windows', value: 'windows', },
-    { label: 'macOS', value: 'macos', },
-    { label: 'unix', value: 'unix', },
+    { label: 'zsh', value: 'zsh', },
+    { label: 'bash', value: 'bash', },
+    { label: 'fish', value: 'fish', },
   ]
 }>
 <TabItem value="powershell">
 
-You can output the current theme to its `JSON` representation which can be used to tweak and store as your custom theme.
+You can output the current theme to the format you like (`json`, `yaml` or `toml`) which can be used to tweak and store as your custom theme.
 
 ```powershell
-Export-PoshTheme -FilePath ~/.mytheme.omp.json
+Export-PoshTheme -FilePath ~/.mytheme.omp.json -Format json
 ```
 
 Once you're done editing, adjust your `$PROFILE` to use your newly created theme.
@@ -396,51 +396,66 @@ Set-PoshPrompt -Theme ~/.mytheme.omp.json
 ```
 
 </TabItem>
-<TabItem value="windows">
+<TabItem value="zsh">
 
-Afterwards, the easiest way to go about this is to print the current config and store it elsewhere first (for example `~/.mytheme.omp.json`).
+You can output the current theme to the format you like (`json`, `yaml` or `toml`) which can be used to tweak and store as your custom theme.
 
-```powershell
-oh-my-posh --print-config
+```bash
+export_poshconfig "~/.mytheme.omp.json" json
 ```
 
-This will write the current configuration in your shell, allowing you to copy paste it in a new file
-and store it somewhere. Once adjusted to your liking, [change the prompt setting][prompt] to use the newly created file.
+Once you're done editing, adjust `~/.zshrc` to use your newly created theme.
 
-```powershell
-oh-my-posh --config ~/.mytheme.omp.json
+```bash
+eval "$(oh-my-posh --init --shell zsh --config ~/.mytheme.omp.json)"
+```
+
+When adjusted, reload your profile for the changes to take effect.
+
+```bash
+. ~/.zshrc
 ```
 
 </TabItem>
-<TabItem value="macos">
+<TabItem value="bash">
+
+You can output the current theme to the format you like (`json`, `yaml` or `toml`) which can be used to tweak and store as your custom theme.
 
-Afterwards, the easiest way to go about this is to print the current config and store it elsewhere first (for example `~/.mytheme.omp.json`).
+```bash
+export_poshconfig "~/.mytheme.omp.json" json
+```
+
+Once you're done editing, adjust `~/.bashrc` to use your newly created theme.
 
 ```bash
-oh-my-posh --print-config
+eval "$(oh-my-posh --init --shell bash --config ~/.mytheme.omp.json)"
 ```
 
-This will write the current configuration in your shell, allowing you to copy paste it in a new file
-and store it somewhere. Once adjusted to your liking, [change the prompt setting][prompt] to use the newly created file.
+When adjusted, reload your profile for the changes to take effect.
 
 ```bash
-oh-my-posh --config ~/.mytheme.omp.json
+. ~/.bashrc
 ```
 
 </TabItem>
-<TabItem value="unix">
+<TabItem value="fish">
 
-Afterwards, the easiest way to go about this is to print the current config and store it elsewhere first (for example `~/.mytheme.omp.json`).
+You can output the current theme to the format you like (`json`, `yaml` or `toml`) which can be used to tweak and store as your custom theme.
 
 ```bash
-oh-my-posh --print-config
+export_poshconfig "~/.mytheme.omp.json" json
 ```
 
-This will write the current configuration in your shell, allowing you to copy paste it in a new file
-and store it somewhere. Once adjusted to your liking, [change the prompt setting][prompt] to use the newly created file.
+Once you're done editing, adjust `config.fish` to use your newly created theme.
 
 ```bash
-oh-my-posh --config ~/.mytheme.omp.json
+oh-my-posh --init --shell fish --config ~/.mytheme.omp.json | source
+```
+
+Once adjusted, reload your config for the changes to take effect.
+
+```bash
+. ~/.config/fish/config.fish
 ```
 
 </TabItem>
diff --git a/packages/powershell/oh-my-posh/oh-my-posh.psd1 b/packages/powershell/oh-my-posh/oh-my-posh.psd1
index 54e8391e..e0463e1c 100644
--- a/packages/powershell/oh-my-posh/oh-my-posh.psd1
+++ b/packages/powershell/oh-my-posh/oh-my-posh.psd1
@@ -31,7 +31,7 @@
     # Aliases to export from this module
     AliasesToExport   = '*'
     # Functions to export from this module
-    FunctionsToExport = @('Get-PoshThemes', 'Set-PoshPrompt', 'Export-PoshTheme', 'Set-PoshContext', 'Get-PoshInfoForV2Users')
+    FunctionsToExport = @('Get-PoshThemes', 'Set-PoshPrompt', 'Get-PoshInfoForV2Users')
     # Private data to pass to the module specified in RootModule. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
     PrivateData       = @{
         PSData = @{
diff --git a/packages/powershell/oh-my-posh/oh-my-posh.psm1 b/packages/powershell/oh-my-posh/oh-my-posh.psm1
index d05e51e7..5371b8c7 100644
--- a/packages/powershell/oh-my-posh/oh-my-posh.psm1
+++ b/packages/powershell/oh-my-posh/oh-my-posh.psm1
@@ -3,10 +3,6 @@
         Generates the prompt before each line in the console
 #>
 
-# Powershell doesn't default to UTF8 just yet, so we're forcing it as there are too many problems
-# that pop up when we don't
-[console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
-
 function Get-PoshCommand {
     if ($IsMacOS) {
         return "$PSScriptRoot/bin/posh-darwin-amd64"
@@ -93,28 +89,6 @@ function Get-PoshThemes {
     Write-Host ""
 }
 
-function Export-PoshTheme {
-    param(
-        [Parameter(Mandatory = $true)]
-        [string]
-        $FilePath
-    )
-
-    $config = $global:PoshSettings.Theme
-    $poshCommand = Get-PoshCommand
-
-    # Save current encoding and swap for UTF8 without BOM
-    $originalOutputEncoding = [Console]::OutputEncoding
-    [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
-
-    # Create Config File
-    $configString = & $poshCommand -config $config -print-config
-    [IO.File]::WriteAllLines($FilePath, $configString)
-
-    # Restore initial encoding
-    [Console]::OutputEncoding = $originalOutputEncoding
-}
-
 # Helper function to create argument completion results
 function New-CompletionResult {
     param(
diff --git a/src/console_title.go b/src/console_title.go
index 09145a9d..ec621b57 100644
--- a/src/console_title.go
+++ b/src/console_title.go
@@ -6,9 +6,9 @@ import (
 )
 
 type consoleTitle struct {
-	env      environmentInfo
-	settings *Settings
-	formats  *ansiFormats
+	env     environmentInfo
+	config  *Config
+	formats *ansiFormats
 }
 
 // ConsoleTitleStyle defines how to show the title in the console window
@@ -25,7 +25,7 @@ const (
 
 func (t *consoleTitle) getConsoleTitle() string {
 	var title string
-	switch t.settings.ConsoleTitleStyle {
+	switch t.config.ConsoleTitleStyle {
 	case FullPath:
 		title = t.getPwd()
 	case Template:
@@ -53,14 +53,14 @@ func (t *consoleTitle) getTemplateText() string {
 
 	// load environment variables into the map
 	envVars := map[string]string{}
-	matches := findAllNamedRegexMatch(`\.Env\.(?P<ENV>[^ \.}]*)`, t.settings.ConsoleTitleTemplate)
+	matches := findAllNamedRegexMatch(`\.Env\.(?P<ENV>[^ \.}]*)`, t.config.ConsoleTitleTemplate)
 	for _, match := range matches {
 		envVars[match["ENV"]] = t.env.getenv(match["ENV"])
 	}
 	context["Env"] = envVars
 
 	template := &textTemplate{
-		Template: t.settings.ConsoleTitleTemplate,
+		Template: t.config.ConsoleTitleTemplate,
 		Context:  context,
 	}
 	return template.render()
diff --git a/src/engine.go b/src/engine.go
index 50f8f92f..f30cd3f0 100644
--- a/src/engine.go
+++ b/src/engine.go
@@ -8,7 +8,7 @@ import (
 )
 
 type engine struct {
-	settings              *Settings
+	config                *Config
 	env                   environmentInfo
 	color                 *AnsiColor
 	renderer              *AnsiRenderer
@@ -135,7 +135,7 @@ func (e *engine) setStringValues(segments []*Segment) {
 }
 
 func (e *engine) render() {
-	for _, block := range e.settings.Blocks {
+	for _, block := range e.config.Blocks {
 		// if line break, append a line break
 		switch block.Type {
 		case LineBreak:
@@ -157,15 +157,15 @@ func (e *engine) render() {
 			e.rprompt = e.renderBlockSegments(block)
 		}
 	}
-	if e.settings.ConsoleTitle {
+	if e.config.ConsoleTitle {
 		e.renderer.write(e.consoleTitle.getConsoleTitle())
 	}
 	e.renderer.creset()
-	if e.settings.FinalSpace {
+	if e.config.FinalSpace {
 		e.renderer.write(" ")
 	}
 
-	if !e.settings.OSC99 {
+	if !e.config.OSC99 {
 		e.print()
 		return
 	}
@@ -190,14 +190,14 @@ func (e *engine) debug() {
 	segmentTiming := SegmentTiming{
 		name:            "ConsoleTitle",
 		nameLength:      12,
-		enabled:         e.settings.ConsoleTitle,
+		enabled:         e.config.ConsoleTitle,
 		stringValue:     consoleTitle,
 		enabledDuration: 0,
 		stringDuration:  duration,
 	}
 	segmentTimings = append(segmentTimings, segmentTiming)
 	// loop each segments of each blocks
-	for _, block := range e.settings.Blocks {
+	for _, block := range e.config.Blocks {
 		for _, segment := range block.Segments {
 			err := segment.mapSegmentWithWriter(e.env)
 			if err != nil || !segment.shouldIncludeFolder(e.env.getcwd()) {
diff --git a/src/go.mod b/src/go.mod
index 24716251..f8294d96 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -14,20 +14,17 @@ require (
 	github.com/go-ole/go-ole v1.2.5 // indirect
 	github.com/google/uuid v1.2.0 // indirect
 	github.com/gookit/color v1.3.8
+	github.com/gookit/config/v2 v2.0.22
 	github.com/huandu/xstrings v1.3.2 // indirect
-	github.com/imdario/mergo v0.3.11 // indirect
-	github.com/mattn/go-isatty v0.0.12 // indirect
 	github.com/mitchellh/copystructure v1.1.1 // indirect
 	github.com/sergi/go-diff v1.1.0 // indirect
 	github.com/shirou/gopsutil v3.21.1+incompatible
 	github.com/stretchr/objx v0.3.0 // indirect
 	github.com/stretchr/testify v1.7.0
 	golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
-	golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46
+	golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48
 	golang.org/x/text v0.3.5
-	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 	howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect
-	muzzammil.xyz/jsonc v0.0.0-20201229145248-615b0916ca38
 )
 
 replace github.com/distatus/battery v0.10.0 => github.com/JanDeDobbeleer/battery v0.10.0-1
diff --git a/src/go.sum b/src/go.sum
index 7337d510..e3e6e207 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -1,3 +1,5 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/JanDeDobbeleer/battery v0.10.0-1 h1:3N3i3xgvrrb3eCuX4kJnmbKzOiqkH1Ly1D7lAJJJTqA=
 github.com/JanDeDobbeleer/battery v0.10.0-1/go.mod h1:STnSvFLX//eEpkaN7qWRxCWxrWOcssTDgnG4yqq9BRE=
 github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@@ -8,66 +10,112 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC
 github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
 github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY=
 github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
 github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
 github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
 github.com/alecthomas/colour v0.1.0 h1:nOE9rJm6dsZ66RGWYSFrXw461ZIt9A6+nHgL7FRrDUk=
 github.com/alecthomas/colour v0.1.0/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
 github.com/alecthomas/repr v0.0.0-20201120212035-bb82daffcca2 h1:G5TeG64Ox4OWq2YwlsxS7nOedU8vbGgNRTRDAjGvDCk=
 github.com/alecthomas/repr v0.0.0-20201120212035-bb82daffcca2/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
+github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
+github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
+github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
 github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
 github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gookit/color v1.3.6/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
 github.com/gookit/color v1.3.8 h1:w2WcSwaCa1ojRWO60Mm4GJUJomBNKR9G+x9DwaaCL1c=
 github.com/gookit/color v1.3.8/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
+github.com/gookit/config/v2 v2.0.22 h1:1aduOOpo4GVIhgnx/lo7ChZZuaLgoc5rxmk7M1OyvbY=
+github.com/gookit/config/v2 v2.0.22/go.mod h1:2TBsB3y8hR4SQEQ8W7TqGsmeScRHr2/fQsBLbHTs9T4=
+github.com/gookit/goutil v0.3.8/go.mod h1:8pmV0itRPVrL6qWJ84RG+E7ZZBP4wvTl6cjjps9hgaE=
+github.com/gookit/goutil v0.3.10 h1:silPdWxf02FpAeQQSOS9zVMLn48j20oMK+4WSsKLRa4=
+github.com/gookit/goutil v0.3.10/go.mod h1:ITj7Lw0muhJNOX+QRa+j+HH0+RNoQVuTmZx5d5LE1vE=
+github.com/gookit/ini/v2 v2.0.9/go.mod h1:qYxT/pBi+32lc0tps2dxKcgitv8g+47peszZi4NOEkM=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
 github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
 github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
-github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
 github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4=
 github.com/mitchellh/copystructure v1.1.1/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
 github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/shirou/gopsutil v3.21.1+incompatible h1:2LwXWdbjXwyDgq26Yy/OT4xozlpmssQfy/rtfhWb0bY=
 github.com/shirou/gopsutil v3.21.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
 github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
+github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
 golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 h1:V066+OYJ66oTjnhm4Yrn7SXIwSCiDQJxpBxmvqb1N1c=
-golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48 h1:70qalHWW1n9yoI8B8zEQxFJO/D6NUWIX8SNmJO+rvNw=
+golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
@@ -75,13 +123,12 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
 howett.net/plist v0.0.0-20201203080718-1454fab16a06 h1:QDxUo/w2COstK1wIBYpzQlHX/NqaQTcf9jyz347nI58=
 howett.net/plist v0.0.0-20201203080718-1454fab16a06/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
-muzzammil.xyz/jsonc v0.0.0-20201229145248-615b0916ca38 h1:RTgkUbDUEKgkFlwK9NsUAmI1t0zUo+kWKSm9bAbr0TQ=
-muzzammil.xyz/jsonc v0.0.0-20201229145248-615b0916ca38/go.mod h1:rFv8tUUKe+QLh7v02BhfxXEf4ZHhYD7unR93HL/1Uvo=
diff --git a/src/init/omp.bash b/src/init/omp.bash
index c9896e18..6677bc72 100644
--- a/src/init/omp.bash
+++ b/src/init/omp.bash
@@ -28,3 +28,12 @@ function _omp_runonexit() {
 }
 
 trap _omp_runonexit EXIT
+
+function export_poshconfig() {
+    [ $# -eq 0 ] && { echo "Usage: $0 \"filename\""; return; }
+    format=$2
+    if [ -z "$format" ]; then
+      format="json"
+    fi
+    ::OMP:: --config $POSH_THEME --print-config --config-format $format > $1
+}
diff --git a/src/init/omp.fish b/src/init/omp.fish
index e2897381..03c4a885 100644
--- a/src/init/omp.fish
+++ b/src/init/omp.fish
@@ -1,3 +1,5 @@
+set -g posh_theme ::CONFIG::
+
 function fish_prompt
     set -l omp_duration "$CMD_DURATION$cmd_duration"
     # check if variable set, < 3.2 case
@@ -12,7 +14,7 @@ function fish_prompt
       set -gx omp_last_status_generation $status_generation
     end
 
-    ::OMP:: --config ::CONFIG:: --error $status --execution-time $omp_duration
+    ::OMP:: --config $posh_theme --error $status --execution-time $omp_duration
 end
 
 function postexec_omp --on-event fish_postexec
@@ -20,3 +22,17 @@ function postexec_omp --on-event fish_postexec
   # pre and postexec not fired for empty command in fish >=3.2
   set -gx omp_lastcommand $argv
 end
+
+
+function export_poshconfig
+  set -l file_name $argv[1]
+  set -l format $argv[2]
+  if not test -n "$file_name"
+    echo "Usage: export_poshconfig \"filename\""
+    return
+  end
+  if not test -n "$format"
+    set format "json"
+  end
+  ::OMP:: --config $posh_theme --print-config --config-format $format > $file_name
+end
diff --git a/src/init/omp.ps1 b/src/init/omp.ps1
index 746d5e44..27c2fafa 100644
--- a/src/init/omp.ps1
+++ b/src/init/omp.ps1
@@ -69,3 +69,20 @@ function global:Write-PoshDebug {
     $standardOut = @(&$omp --error=1337 --pwd="$cleanPWD" --pswd="$cleanPSWD" --execution-time=9001 --config="$config" --debug 2>&1)
     $standardOut -join "`n"
 }
+
+function global:Export-PoshTheme {
+    param(
+        [Parameter(Mandatory = $true)]
+        [string]
+        $FilePath,
+        [Parameter(Mandatory = $false)]
+        [ValidateSet('json','yaml','toml')]
+        [string]
+        $Format = 'json'
+    )
+
+    $config = $global:PoshSettings.Theme
+    $omp = "::OMP::"
+    $configString = @(&$omp --config="$config" --config-format="$Format" --print-config 2>&1)
+    [IO.File]::WriteAllLines($FilePath, $configString)
+}
diff --git a/src/init/omp.zsh b/src/init/omp.zsh
index c869a94b..0002a47f 100644
--- a/src/init/omp.zsh
+++ b/src/init/omp.zsh
@@ -37,3 +37,12 @@ function install_omp_hooks() {
 if [ "$TERM" != "linux" ]; then
   install_omp_hooks
 fi
+
+function export_poshconfig() {
+    [ $# -eq 0 ] && { echo "Usage: $0 \"filename\""; return; }
+    format=$2
+    if [ -z "$format" ]; then
+      format="json"
+    fi
+    ::OMP:: --config $POSH_THEME --print-config --config-format $format > $1
+}
diff --git a/src/main.go b/src/main.go
index 219ef302..dfe51926 100644
--- a/src/main.go
+++ b/src/main.go
@@ -2,12 +2,13 @@ package main
 
 import (
 	_ "embed"
-	"encoding/json"
 	"flag"
 	"fmt"
 	"os"
 	"strings"
 	"time"
+
+	"github.com/gookit/config/v2"
 )
 
 // Version number of oh-my-posh
@@ -37,6 +38,7 @@ const (
 type args struct {
 	ErrorCode     *int
 	PrintConfig   *bool
+	ConfigFormat  *string
 	PrintShell    *bool
 	Config        *string
 	Shell         *string
@@ -61,6 +63,10 @@ func main() {
 			"print-config",
 			false,
 			"Print the current config in json format"),
+		ConfigFormat: flag.String(
+			"config-format",
+			config.JSON,
+			"The format to print the config in. Valid options are:\n- json\n- yaml\n- toml\n"),
 		PrintShell: flag.Bool(
 			"print-shell",
 			false,
@@ -127,12 +133,11 @@ func main() {
 		fmt.Print(init)
 		return
 	}
-	settings := GetSettings(env)
 	if *args.PrintConfig {
-		theme, _ := json.MarshalIndent(settings, "", "    ")
-		fmt.Println(string(theme))
+		fmt.Print(exportConfig(*args.Config, *args.ConfigFormat))
 		return
 	}
+	cfg := GetConfig(env)
 	if *args.PrintShell {
 		fmt.Println(env.getShellName())
 		return
@@ -149,15 +154,15 @@ func main() {
 	}
 	colorer := &AnsiColor{
 		formats:            formats,
-		terminalBackground: settings.TerminalBackground,
+		terminalBackground: cfg.TerminalBackground,
 	}
 	title := &consoleTitle{
-		env:      env,
-		settings: settings,
-		formats:  formats,
+		env:     env,
+		config:  cfg,
+		formats: formats,
 	}
 	engine := &engine{
-		settings:     settings,
+		config:       cfg,
 		env:          env,
 		color:        colorer,
 		renderer:     renderer,
@@ -171,22 +176,22 @@ func main() {
 	engine.render()
 }
 
-func initShell(shell, config string) string {
+func initShell(shell, configFile string) string {
 	executable, err := os.Executable()
 	if err != nil {
 		return noExe
 	}
 	switch shell {
 	case pwsh:
-		return fmt.Sprintf("Invoke-Expression (@(&\"%s\" --print-init --shell=pwsh --config=\"%s\") -join \"`n\")", executable, config)
+		return fmt.Sprintf("Invoke-Expression (@(&\"%s\" --print-init --shell=pwsh --config=\"%s\") -join \"`n\")", executable, configFile)
 	case zsh, bash, fish:
-		return printShellInit(shell, config)
+		return printShellInit(shell, configFile)
 	default:
 		return fmt.Sprintf("echo \"No initialization script available for %s\"", shell)
 	}
 }
 
-func printShellInit(shell, config string) string {
+func printShellInit(shell, configFile string) string {
 	executable, err := os.Executable()
 	// On Windows, it fails when the excutable is called in MSYS2 for example
 	// which uses unix style paths to resolve the executable's location.
@@ -197,20 +202,20 @@ func printShellInit(shell, config string) string {
 	}
 	switch shell {
 	case pwsh:
-		return getShellInitScript(executable, config, pwshInit)
+		return getShellInitScript(executable, configFile, pwshInit)
 	case zsh:
-		return getShellInitScript(executable, config, zshInit)
+		return getShellInitScript(executable, configFile, zshInit)
 	case bash:
-		return getShellInitScript(executable, config, bashInit)
+		return getShellInitScript(executable, configFile, bashInit)
 	case fish:
-		return getShellInitScript(executable, config, fishInit)
+		return getShellInitScript(executable, configFile, fishInit)
 	default:
 		return fmt.Sprintf("echo \"No initialization script available for %s\"", shell)
 	}
 }
 
-func getShellInitScript(executable, config, script string) string {
+func getShellInitScript(executable, configFile, script string) string {
 	script = strings.ReplaceAll(script, "::OMP::", executable)
-	script = strings.ReplaceAll(script, "::CONFIG::", config)
+	script = strings.ReplaceAll(script, "::CONFIG::", configFile)
 	return script
 }
diff --git a/src/segment.go b/src/segment.go
index 9a9128b3..3e36b768 100644
--- a/src/segment.go
+++ b/src/segment.go
@@ -7,17 +7,17 @@ import (
 
 // Segment represent a single segment and it's configuration
 type Segment struct {
-	Type                SegmentType              `json:"type"`
-	Style               SegmentStyle             `json:"style"`
-	PowerlineSymbol     string                   `json:"powerline_symbol"`
-	InvertPowerline     bool                     `json:"invert_powerline"`
-	Foreground          string                   `json:"foreground"`
-	ForegroundTemplates []string                 `json:"foreground_templates"`
-	Background          string                   `json:"background"`
-	BackgroundTemplates []string                 `json:"background_templates"`
-	LeadingDiamond      string                   `json:"leading_diamond"`
-	TrailingDiamond     string                   `json:"trailing_diamond"`
-	Properties          map[Property]interface{} `json:"properties"`
+	Type                SegmentType              `config:"type"`
+	Style               SegmentStyle             `config:"style"`
+	PowerlineSymbol     string                   `config:"powerline_symbol"`
+	InvertPowerline     bool                     `config:"invert_powerline"`
+	Foreground          string                   `config:"foreground"`
+	ForegroundTemplates []string                 `config:"foreground_templates"`
+	Background          string                   `config:"background"`
+	BackgroundTemplates []string                 `config:"background_templates"`
+	LeadingDiamond      string                   `config:"leading_diamond"`
+	TrailingDiamond     string                   `config:"trailing_diamond"`
+	Properties          map[Property]interface{} `config:"properties"`
 	props               *properties
 	writer              SegmentWriter
 	stringValue         string
diff --git a/src/settings.go b/src/settings.go
index da57d757..6c03d92b 100644
--- a/src/settings.go
+++ b/src/settings.go
@@ -1,22 +1,29 @@
 package main
 
 import (
-	"encoding/json"
+	// "encoding/json"
+
+	"bytes"
+	json2 "encoding/json"
 	"errors"
+	"fmt"
 	"os"
 
-	"muzzammil.xyz/jsonc"
+	"github.com/gookit/config/v2"
+	"github.com/gookit/config/v2/json"
+	"github.com/gookit/config/v2/toml"
+	"github.com/gookit/config/v2/yaml"
 )
 
-// Settings holds all the theme for rendering the prompt
-type Settings struct {
-	FinalSpace           bool              `json:"final_space"`
-	OSC99                bool              `json:"osc99"`
-	ConsoleTitle         bool              `json:"console_title"`
-	ConsoleTitleStyle    ConsoleTitleStyle `json:"console_title_style"`
-	ConsoleTitleTemplate string            `json:"console_title_template"`
-	TerminalBackground   string            `json:"terminal_background"`
-	Blocks               []*Block          `json:"blocks"`
+// Config holds all the theme for rendering the prompt
+type Config struct {
+	FinalSpace           bool              `config:"final_space"`
+	OSC99                bool              `config:"osc99"`
+	ConsoleTitle         bool              `config:"console_title"`
+	ConsoleTitleStyle    ConsoleTitleStyle `config:"console_title_style"`
+	ConsoleTitleTemplate string            `config:"console_title_template"`
+	TerminalBackground   string            `config:"terminal_background"`
+	Blocks               []*Block          `config:"blocks"`
 }
 
 // BlockType type of block
@@ -42,46 +49,97 @@ const (
 
 // Block defines a part of the prompt with optional segments
 type Block struct {
-	Type             BlockType      `json:"type"`
-	Alignment        BlockAlignment `json:"alignment"`
-	HorizontalOffset int            `json:"horizontal_offset"`
-	VerticalOffset   int            `json:"vertical_offset"`
-	Segments         []*Segment     `json:"segments"`
+	Type             BlockType      `config:"type"`
+	Alignment        BlockAlignment `config:"alignment"`
+	HorizontalOffset int            `config:"horizontal_offset"`
+	VerticalOffset   int            `config:"vertical_offset"`
+	Segments         []*Segment     `config:"segments"`
 }
 
-// GetSettings returns the default configuration including possible user overrides
-func GetSettings(env environmentInfo) *Settings {
-	settings, err := loadUserConfiguration(env)
+// GetConfig returns the default configuration including possible user overrides
+func GetConfig(env environmentInfo) *Config {
+	cfg, err := loadConfig(env)
 	if err != nil {
-		return getDefaultSettings(err.Error())
+		return getDefaultConfig(err.Error())
 	}
-	return settings
+	return cfg
 }
 
-func loadUserConfiguration(env environmentInfo) (*Settings, error) {
-	var settings Settings
-	settingsFile := *env.getArgs().Config
-	if settingsFile == "" {
+func loadConfig(env environmentInfo) (*Config, error) {
+	var cfg Config
+	configFile := *env.getArgs().Config
+	if configFile == "" {
 		return nil, errors.New("NO CONFIG")
 	}
-	if _, err := os.Stat(settingsFile); os.IsNotExist(err) {
+	if _, err := os.Stat(configFile); os.IsNotExist(err) {
 		return nil, errors.New("INVALID CONFIG PATH")
 	}
 
-	_, j, err := jsonc.ReadFromFile(settingsFile)
+	config.AddDriver(yaml.Driver)
+	config.AddDriver(json.Driver)
+	config.AddDriver(toml.Driver)
+	config.WithOptions(func(opt *config.Options) {
+		opt.TagName = "config"
+	})
+
+	err := config.LoadFiles(configFile)
 	if err != nil {
 		return nil, errors.New("UNABLE TO OPEN CONFIG")
 	}
 
-	err = json.Unmarshal(j, &settings)
+	err = config.BindStruct("", &cfg)
 	if err != nil {
 		return nil, errors.New("INVALID CONFIG")
 	}
-	return &settings, nil
+
+	return &cfg, nil
+}
+
+func exportConfig(configFile, format string) string {
+	if len(format) == 0 {
+		format = config.JSON
+	}
+
+	config.AddDriver(yaml.Driver)
+	config.AddDriver(json.Driver)
+	config.AddDriver(toml.Driver)
+
+	err := config.LoadFiles(configFile)
+	if err != nil {
+		return fmt.Sprintf("INVALID CONFIG:\n\n%s", err.Error())
+	}
+
+	schemaKey := "$schema"
+	if format == config.JSON && !config.Exists(schemaKey) {
+		data := config.Data()
+		data[schemaKey] = "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json"
+		config.SetData(data)
+	}
+
+	buf := new(bytes.Buffer)
+	_, err = config.DumpTo(buf, format)
+	if err != nil {
+		return "UNABLE TO DUMP CONFIG"
+	}
+
+	switch format {
+	case config.JSON:
+		var prettyJSON bytes.Buffer
+		err := json2.Indent(&prettyJSON, buf.Bytes(), "", "  ")
+		if err == nil {
+			return prettyJSON.String()
+		}
+	case config.Yaml:
+		prefix := "# yaml-language-server: $schema=https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\n\n"
+		content := buf.String()
+		return prefix + content
+	}
+
+	return buf.String()
 }
 
-func getDefaultSettings(info string) *Settings {
-	settings := &Settings{
+func getDefaultConfig(info string) *Config {
+	cfg := &Config{
 		FinalSpace:        true,
 		ConsoleTitle:      true,
 		ConsoleTitleStyle: FolderName,
@@ -193,5 +251,5 @@ func getDefaultSettings(info string) *Settings {
 			},
 		},
 	}
-	return settings
+	return cfg
 }
diff --git a/themes/schema.json b/themes/schema.json
index 9551716b..050d23a8 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -808,6 +808,12 @@
                 "properties": {
                   "template": {
                     "$ref": "#/definitions/template"
+                  },
+                  "display_default": {
+                    "type": "boolean",
+                    "title": "Display Default User Profile",
+                    "description": "Display the segment when default user or not",
+                    "default": true
                   }
                 }
               }
@@ -1103,7 +1109,7 @@
             }
           },
           "then": {
-            "title": "Node Segment",
+            "title": "Python Segment",
             "description": "https://ohmyposh.dev/docs/python",
             "properties": {
               "properties": {
@@ -1111,6 +1117,12 @@
                   "display_version": {
                     "$ref": "#/definitions/display_version"
                   },
+                  "display_default": {
+                    "type": "boolean",
+                    "title": "Display Default Env",
+                    "description": "Show the name of the virtualenv when it's default (`system`, `base`)",
+                    "default": true
+                  },
                   "display_virtual_env": {
                     "type": "boolean",
                     "title": "Display Virtual Env",
@@ -1195,7 +1207,7 @@
                     "description": "The name of the default user",
                     "default": ""
                   },
-                  "display_default_user": {
+                  "display_default": {
                     "type": "boolean",
                     "title": "Display Default User",
                     "description": "Display the segment when default user or not",


Test patch:
diff --git a/src/console_title_test.go b/src/console_title_test.go
index f9f159cb..8d5f77da 100644
--- a/src/console_title_test.go
+++ b/src/console_title_test.go
@@ -49,7 +49,7 @@ func TestGetConsoleTitle(t *testing.T) {
 	}
 
 	for _, tc := range cases {
-		settings := &Settings{
+		config := &Config{
 			ConsoleTitleStyle:    tc.Style,
 			ConsoleTitleTemplate: tc.Template,
 		}
@@ -65,9 +65,9 @@ func TestGetConsoleTitle(t *testing.T) {
 		formats := &ansiFormats{}
 		formats.init(tc.ShellName)
 		ct := &consoleTitle{
-			env:      env,
-			settings: settings,
-			formats:  formats,
+			env:     env,
+			config:  config,
+			formats: formats,
 		}
 		got := ct.getConsoleTitle()
 		assert.Equal(t, tc.Expected, got)
@@ -104,7 +104,7 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
 	}
 
 	for _, tc := range cases {
-		settings := &Settings{
+		config := &Config{
 			ConsoleTitleStyle:    tc.Style,
 			ConsoleTitleTemplate: tc.Template,
 		}
@@ -120,9 +120,9 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
 		formats := &ansiFormats{}
 		formats.init(tc.ShellName)
 		ct := &consoleTitle{
-			env:      env,
-			settings: settings,
-			formats:  formats,
+			env:     env,
+			config:  config,
+			formats: formats,
 		}
 		got := ct.getConsoleTitle()
 		assert.Equal(t, tc.Expected, got)
diff --git a/src/segment_test.go b/src/segment_test.go
index 7a447856..7765162d 100644
--- a/src/segment_test.go
+++ b/src/segment_test.go
@@ -32,7 +32,7 @@ func TestMapSegmentWriterCannotMap(t *testing.T) {
 	assert.Error(t, err)
 }
 
-func TestParseTestSettings(t *testing.T) {
+func TestParseTestConfig(t *testing.T) {
 	segmentJSON :=
 		`
 		{