Repository: JanDeDobbeleer/oh-my-posh
Pull request #1228 (2021-11-15 05:52:30)

feat: sysinfo segment
### Prerequisites

- [x] I have read and understood 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

SysInfo segments based on gopsutil. Replaces the current memory segment. By default, looks like the old memory segment.
<!---

Tips:

If you're not comfortable with working with Git, we're working a guide (https://ohmyposh.dev/docs/contributing_git) to help you out.
Oh My Posh advises GitKraken (https://www.gitkraken.com/invite/nQmDPR9D) as your preferred cross platform Git GUI power tool.

-->

[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary


lnu: ![image](https://user-images.githubusercontent.com/1829553/142021690-d1ce91ff-9077-49f7-9d2b-9c5e2a7176ae.png)

```
        {
          "type":"sysinfo",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#819c09",
          "invert_powerline": true,
          "properties": {
            "prefix": " \uf9c4 ",
            // "template":"{{ round .Times 2 }}({{ .Cores }} {{.Mhz }}Mhz)"
            "template":"{{ round .Times 2 }}({{ .Cores }} cores {{.Mhz }}Mhz)"
          },
          "style":"powerline"
        },
        {
          "type":"sysinfo",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#9c1a09",
          "invert_powerline": true,
          "properties": {
            "postfix": " ",
            // "template":"{{ round .Times 2 }}({{ .Cores }} {{.Mhz }}Mhz)"
            "template":"{{ round .Load1 2 }} {{round .Load5 2}} {{round .Load15 2}}"
          },
          "style":"powerline"
        },
        {
          "type":"sysinfo",
          "powerline_symbol": "",
          "foreground": "#ffffff",
          "background": "#8f43f3",
          "invert_powerline": true,
          "properties": {
            "prefix": " \uf85a ",
            "postfix": "% ",
            // "template":"{{ round .Load 2 }}({{ .Cores }} {{.Mhz }}Mhz)"
            "template":"{{ round .PhysicalPercentUsed 2 }}"
          },
          "style":"powerline"
        },
```
lnu: still have to update all memory segment used in themes

Patch:
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index fae05d32..cc31ea0f 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -47,6 +47,7 @@
 
   // Add the IDs of extensions you want installed when the container is created.
   "extensions": [
+    "eamodio.gitlens",
     "github.vscode-pull-request-github",
     "esbenp.prettier-vscode",
     "davidanson.vscode-markdownlint",
diff --git a/docs/docs/config-transient.mdx b/docs/docs/config-transient.mdx
index a1779ece..65e2d8a1 100644
--- a/docs/docs/config-transient.mdx
+++ b/docs/docs/config-transient.mdx
@@ -49,7 +49,7 @@ The configuration has the following properties:
 - template: `string` - A go [text/template][go-text-template] template extended with [sprig][sprig] utilizing the
 properties below. Defaults to `{{ .Shell }}> `
 
-### Template Properties
+## Template Properties
 
 - `.Root`: `boolean` - is the current user root/admin or not
 - `.Path`: `string` - the current working directory
diff --git a/docs/docs/memory.md b/docs/docs/memory.md
deleted file mode 100644
index 85aee598..00000000
--- a/docs/docs/memory.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-id: memory
-title: Memory
-sidebar_label: Memory
----
-
-## Memory
-
-Display physical memory or swap usage percentage.
-
-## Sample Configuration
-
-```json
-{
-  "type": "memory",
-  "style": "powerline",
-  "foreground": "#26C6DA",
-  "background": "#2f2f2f",
-  "properties": {
-    "precision": 1,
-    "prefix": " \uf85a ",
-    "postfix": "% "
-  }
-}
-```
-
-## Properties
-
-- precision: `int` - the number of decimal places to show - defaults to `0`
-- use_available: `boolean` - whether to use available or free memory on Linux - defaults to `true`
-- memory_type: `enum` - whether to show `physical` memory or `swap` memory - defaults to `physical`
diff --git a/docs/docs/segment-dotnet.md b/docs/docs/segment-dotnet.md
index 899d4eb1..a8300c14 100644
--- a/docs/docs/segment-dotnet.md
+++ b/docs/docs/segment-dotnet.md
@@ -41,7 +41,7 @@ properties below. Defaults does nothing(backward compatibility).
 - version_url_template: `string` - A go [text/template][go-text-template] template extended
 with [sprig][sprig] utilizing the properties below. Defaults does nothing(backward compatibility).
 
-### Template Properties
+## Template Properties
 
 - `.Major`: `string` - is the major version
 - `.Minor`: `string` - is the minor version
diff --git a/docs/docs/sysinfo.md b/docs/docs/sysinfo.md
new file mode 100644
index 00000000..22cae13c
--- /dev/null
+++ b/docs/docs/sysinfo.md
@@ -0,0 +1,49 @@
+---
+id: sysinfo
+title: SysInfo
+sidebar_label: SysInfo
+---
+
+## SysInfo
+
+Display SysInfo.
+
+## Sample Configuration
+
+```json
+{
+  "type":"sysinfo",
+  "powerline_symbol": "",
+  "foreground": "#ffffff",
+  "background": "#8f43f3",
+  "invert_powerline": true,
+  "properties": {
+    "prefix": " \uf85a ",
+    "postfix": "% ",
+    "precision": 2,
+    "template":"{{ round .PhysicalPercentUsed .Precision }}"
+  },
+  "style":"powerline"
+},
+```
+
+## Properties
+
+- Precision: `int` - The precision used for any float values - defaults to 2
+- template: `string` - A go [text/template][go-text-template] template extended with [sprig][sprig] utilizing the
+properties below - defaults to `{{ round .PhysicalPercentUsed .Precision }}> `
+
+## Template Properties
+
+- `.PhysicalTotalMemory`: `int` - is the total of used physical memory
+- `.PhysicalFreeMemory`: `int` - is the total of free physical memory
+- `.PhysicalPercentUsed`: `float64` - is the percentage of physical memory in usage
+- `.SwapTotalMemory`: `int` - is the total of used swap memory
+- `.SwapFreeMemory`: `int` - is the percentage of swap memory in usage
+- `.SwapPercentUsed`: `float64` - is the current user root/admin or not
+- `.Load1`: `float64` - is the current load1 (can be empty on windows)
+- `.Load5`: `float64` - is the current load5 (can be empty on windows)
+- `.Load15`: `float64` - is the current load15 (can be empty on windows)
+- `.CPU`: `[]struct` - an array of [InfoStat][cpuinfo] object, you can use any property it has e.g. `(index .CPU 0).Cores`
+
+[cpuinfo]: https://github.com/shirou/gopsutil/blob/78065a7ce2021f6a78c8d6f586a2683ba501dcec/cpu/cpu.go#L32
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 8f151a2c..f30570ca 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -54,7 +54,7 @@ module.exports = {
         "java",
         "julia",
         "kubectl",
-        "memory",
+        "sysinfo",
         "nbgv",
         "node",
         "os",
diff --git a/src/environment.go b/src/environment.go
index b4a431fe..e1d9ec6b 100644
--- a/src/environment.go
+++ b/src/environment.go
@@ -17,7 +17,7 @@ import (
 	"time"
 
 	"github.com/distatus/battery"
-	"github.com/shirou/gopsutil/process"
+	process "github.com/shirou/gopsutil/v3/process"
 )
 
 const (
diff --git a/src/environment_unix.go b/src/environment_unix.go
index d47ce380..9f82c05f 100644
--- a/src/environment_unix.go
+++ b/src/environment_unix.go
@@ -7,7 +7,7 @@ import (
 	"os"
 	"time"
 
-	"github.com/shirou/gopsutil/host"
+	"github.com/shirou/gopsutil/v3/host"
 	terminal "github.com/wayneashleyberry/terminal-dimensions"
 )
 
diff --git a/src/go.mod b/src/go.mod
index 349dfa45..3b500024 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -19,11 +19,9 @@ require (
 	github.com/gookit/config/v2 v2.0.27
 	github.com/gookit/goutil v0.4.0 // indirect
 	github.com/huandu/xstrings v1.3.2 // indirect
-	github.com/jan0660/memory v0.1.2
 	github.com/mitchellh/copystructure v1.2.0 // indirect
 	github.com/mitchellh/mapstructure v1.4.2
 	github.com/sergi/go-diff v1.2.0 // indirect
-	github.com/shirou/gopsutil v3.21.9+incompatible
 	github.com/stretchr/objx v0.3.0 // indirect
 	github.com/stretchr/testify v1.7.0
 	github.com/tklauser/go-sysconf v0.3.9 // indirect
@@ -36,6 +34,8 @@ require (
 	howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect
 )
 
+require github.com/shirou/gopsutil/v3 v3.21.10
+
 require (
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/semver/v3 v3.1.1 // indirect
@@ -43,6 +43,7 @@ require (
 	github.com/go-ole/go-ole v1.2.6 // indirect
 	github.com/imdario/mergo v0.3.12 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/mattn/go-isatty v0.0.14 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/reflectwalk v1.0.2 // indirect
diff --git a/src/go.sum b/src/go.sum
index 7a8b64b7..1574ed71 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -5,8 +5,6 @@ github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw
 github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/JanDeDobbeleer/battery v0.10.0-2 h1:nmFASq8Rmo0sHz6gLT3pXHh7uNABLEgEozKb2tRPgVY=
 github.com/JanDeDobbeleer/battery v0.10.0-2/go.mod h1:STnSvFLX//eEpkaN7qWRxCWxrWOcssTDgnG4yqq9BRE=
-github.com/JanDeDobbeleer/gopsutil v3.21.9-1+incompatible h1:XaJExIJleF33D1WSjle30LBqegcy2Pguge3wu4wZB7A=
-github.com/JanDeDobbeleer/gopsutil v3.21.9-1+incompatible/go.mod h1:7cScMdSKcXHocZHUVqp7KI/2RMf0ZIhl8BGd7Hj3AFQ=
 github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
 github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
 github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
@@ -42,6 +40,8 @@ github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
@@ -65,8 +65,6 @@ github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq
 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/jan0660/memory v0.1.2 h1:Dxc2p3DJIJ+w2D2/OSqg3rf+ZQZ/lcYxiSXfiCNGRnA=
-github.com/jan0660/memory v0.1.2/go.mod h1:I9fFv85Tlthw0cS4nXzY9kCtCpNLuYsVVIxhejK50Cg=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -77,6 +75,8 @@ 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/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
@@ -105,6 +105,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
 github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/shirou/gopsutil/v3 v3.21.10 h1:flTg1DrnV/UVrBqjLgVgDJzx6lf+91rC64/dBHmO2IA=
+github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew=
 github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/shopspring/decimal v1.3.0 h1:KK3gWIXskZ2O1U/JNTisNcvH+jveJxZYrjbTsrbbnh8=
 github.com/shopspring/decimal v1.3.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@@ -164,6 +166,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211020064051-0ec99a608a1b h1:byBDhtWGQmWDrv1MlEv/BzGRMkw36h9QqsNnZQcDhRw=
 golang.org/x/sys v0.0.0-20211020064051-0ec99a608a1b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -176,6 +179,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/src/segment.go b/src/segment.go
index 073e30ea..2b0dfd58 100644
--- a/src/segment.go
+++ b/src/segment.go
@@ -124,8 +124,8 @@ const (
 	Rust SegmentType = "rust"
 	// OWM writes the weather coming from openweatherdata
 	OWM SegmentType = "owm"
-	// Memory writes used memory percentage
-	Memory SegmentType = "memory"
+	// SysInfo writes system information (memory, cpu, load)
+	SysInfo SegmentType = "sysinfo"
 	// Angular writes which angular cli version us currently active
 	Angular SegmentType = "angular"
 	// PHP writes which php version is currently active
@@ -260,7 +260,7 @@ func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
 		Dart:          &dart{},
 		Nbgv:          &nbgv{},
 		Rust:          &rust{},
-		Memory:        &memory{},
+		SysInfo:       &sysinfo{},
 		Angular:       &angular{},
 		PHP:           &php{},
 	}
diff --git a/src/segment_memory.go b/src/segment_memory.go
deleted file mode 100644
index 1162e9b3..00000000
--- a/src/segment_memory.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package main
-
-import (
-	"strconv"
-
-	mem "github.com/jan0660/memory"
-)
-
-type memory struct {
-	props       *properties
-	env         environmentInfo
-	TotalMemory uint64
-	FreeMemory  uint64
-}
-
-const (
-	// Precision number of decimal places to show
-	Precision Property = "precision"
-	// UseAvailable if available memory should be used instead of free on Linux
-	UseAvailable Property = "use_available"
-	// MemoryType either physical or swap
-	MemoryType Property = "memory_type"
-)
-
-func (n *memory) enabled() bool {
-	if n.TotalMemory == 0 || n.FreeMemory == 0 {
-		// failed to get memory information
-		return false
-	}
-	return true
-}
-
-func (n *memory) string() string {
-	// 100.0 / total * used
-	percentage := 100.0 / float64(n.TotalMemory) * float64(n.TotalMemory-n.FreeMemory)
-	text := strconv.FormatFloat(percentage, 'f', n.props.getInt(Precision, 0), 64)
-	return text
-}
-
-func (n *memory) init(props *properties, env environmentInfo) {
-	n.props = props
-	n.env = env
-	if props.getString(MemoryType, "physical") == "physical" {
-		n.TotalMemory = mem.TotalMemory()
-		if props.getBool(UseAvailable, true) {
-			n.FreeMemory = mem.AvailableMemory()
-			return
-		}
-		n.FreeMemory = mem.FreeMemory()
-		return
-	}
-	n.TotalMemory = mem.TotalSwap()
-	n.FreeMemory = mem.FreeSwap()
-}
diff --git a/src/segment_sysinfo.go b/src/segment_sysinfo.go
new file mode 100644
index 00000000..398c9d51
--- /dev/null
+++ b/src/segment_sysinfo.go
@@ -0,0 +1,90 @@
+package main
+
+import (
+	cpu "github.com/shirou/gopsutil/v3/cpu"
+	load "github.com/shirou/gopsutil/v3/load"
+	mem "github.com/shirou/gopsutil/v3/mem"
+)
+
+type sysinfo struct {
+	props     *properties
+	env       environmentInfo
+	Precision int
+	// mem
+	PhysicalTotalMemory uint64
+	PhysicalFreeMemory  uint64
+	PhysicalPercentUsed float64
+	SwapTotalMemory     uint64
+	SwapFreeMemory      uint64
+	SwapPercentUsed     float64
+	// cpu
+	Times float64
+	CPU   []cpu.InfoStat
+	// load
+	Load1  float64
+	Load5  float64
+	Load15 float64
+}
+
+const (
+	// Precision number of decimal places to show
+	Precision Property = "precision"
+)
+
+func (s *sysinfo) enabled() bool {
+	if s.PhysicalPercentUsed == 0 && s.SwapPercentUsed == 0 {
+		return false
+	}
+	return true
+}
+
+func (s *sysinfo) string() string {
+	// keep old memory segment template
+	segmentTemplate := s.props.getString(SegmentTemplate, "{{ round .PhysicalPercentUsed .Precision }}")
+	template := &textTemplate{
+		Template: segmentTemplate,
+		Context:  s,
+		Env:      s.env,
+	}
+	text, err := template.render()
+	if err != nil {
+		return err.Error()
+	}
+	return text
+}
+
+func (s *sysinfo) init(props *properties, env environmentInfo) {
+	s.props = props
+	s.env = env
+	s.Precision = s.props.getInt(Precision, 2)
+	// mem
+	memStat, err := mem.VirtualMemory()
+	if err == nil {
+		s.PhysicalTotalMemory = memStat.Total
+		s.PhysicalFreeMemory = memStat.Free
+		s.PhysicalPercentUsed = memStat.UsedPercent
+	}
+	swapStat, err := mem.SwapMemory()
+	if err == nil {
+		s.SwapTotalMemory = swapStat.Total
+		s.SwapFreeMemory = swapStat.Free
+		s.SwapPercentUsed = swapStat.UsedPercent
+	}
+	// load
+	loadStat, err := load.Avg()
+	if err == nil {
+		s.Load1 = loadStat.Load1
+		s.Load5 = loadStat.Load5
+		s.Load15 = loadStat.Load15
+	}
+	// times
+	processorTimes, err := cpu.Percent(0, false)
+	if err == nil {
+		s.Times = processorTimes[0]
+	}
+	// cpu
+	processors, err := cpu.Info()
+	if err == nil {
+		s.CPU = processors
+	}
+}
diff --git a/themes/schema.json b/themes/schema.json
index 252d81f4..6cd4d6fe 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -53,10 +53,7 @@
       "default": ""
     },
     "template": {
-      "type": "string",
-      "title": "Template text",
-      "description": "The template to use to render the segment text",
-      "default": ""
+      "$ref": "#/definitions/template"
     },
     "block": {
       "type": "object",
@@ -169,7 +166,7 @@
             "dart",
             "rust",
             "owm",
-            "memory",
+            "sysinfo",
             "angular",
             "php"
           ]
@@ -1643,12 +1640,12 @@
         {
           "if": {
             "properties": {
-              "type": { "const": "memory" }
+              "type": { "const": "sysinfo" }
             }
           },
           "then": {
-            "title": "Get used memory percentage",
-            "description": "https://ohmyposh.dev/docs/memory",
+            "title": "Get sysinfo",
+            "description": "https://ohmyposh.dev/docs/sysinfo",
             "properties": {
               "properties": {
                 "properties": {
@@ -1658,18 +1655,8 @@
                     "description": "number of decimal places to show",
                     "default": 0
                   },
-                  "use_available": {
-                    "type": "boolean",
-                    "title": "Use available memory",
-                    "description": "whether to use available or free memory on Linux",
-                    "default": true
-                  },
-                  "memory_type": {
-                    "type": "string",
-                    "enum": ["physical", "swap"],
-                    "title": "Memory type",
-                    "description": "whether to show physical or swap memory",
-                    "default": "physical"
+                  "template": {
+                    "$ref": "#/definitions/template"
                   }
                 }
               }


Test patch:
diff --git a/src/segment_memory_test.go b/src/segment_memory_test.go
deleted file mode 100644
index 2557c190..00000000
--- a/src/segment_memory_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package main
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestMemory(t *testing.T) {
-	cases := []struct {
-		Case           string
-		ExpectedString string
-		ExpectDisabled bool
-		Memory         memory
-		Precision      int
-	}{
-		{Case: "50", ExpectedString: "50", Memory: memory{FreeMemory: 50, TotalMemory: 100}},
-		{Case: "50.0", ExpectedString: "50.0", Memory: memory{FreeMemory: 50, TotalMemory: 100}, Precision: 1},
-		{Case: "not enabled", ExpectDisabled: true, Memory: memory{FreeMemory: 0, TotalMemory: 0}},
-	}
-
-	for _, tc := range cases {
-		tc.Memory.env = new(MockedEnvironment)
-		tc.Memory.props = &properties{
-			values: map[Property]interface{}{
-				Precision: tc.Precision,
-			},
-		}
-		if tc.ExpectDisabled {
-			assert.Equal(t, false, tc.Memory.enabled(), tc.Case)
-		} else {
-			assert.Equal(t, tc.ExpectedString, tc.Memory.string(), tc.Case)
-		}
-	}
-}
diff --git a/src/segment_sysinfo_test.go b/src/segment_sysinfo_test.go
new file mode 100644
index 00000000..1a876728
--- /dev/null
+++ b/src/segment_sysinfo_test.go
@@ -0,0 +1,52 @@
+package main
+
+import (
+	"testing"
+
+	"github.com/shirou/gopsutil/v3/cpu"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestSysInfo(t *testing.T) {
+	cases := []struct {
+		Case           string
+		ExpectedString string
+		ExpectDisabled bool
+		SysInfo        sysinfo
+		Precision      int
+		Template       string
+	}{
+		{Case: "physical mem", ExpectedString: "50", SysInfo: sysinfo{PhysicalPercentUsed: 50}},
+		{Case: "physical mem 2 digits", ExpectedString: "60.51", SysInfo: sysinfo{Precision: 2, PhysicalPercentUsed: 60.51}},
+		{Case: "physical meme rounded", ExpectedString: "61", SysInfo: sysinfo{Precision: 0, PhysicalPercentUsed: 61}},
+		{
+			Case:           "load",
+			ExpectedString: "0.22 0.12 0",
+			Template:       "{{ round .Load1 .Precision }} {{round .Load5 .Precision }} {{round .Load15 .Precision }}",
+			SysInfo:        sysinfo{Precision: 2, Load1: 0.22, Load5: 0.12, Load15: 0}},
+		{Case: "not enabled", ExpectDisabled: true, SysInfo: sysinfo{PhysicalPercentUsed: 0, SwapPercentUsed: 0}},
+		{
+			Case:           "2 physical cpus",
+			ExpectedString: "1200 1200 ",
+			Template:       "{{range $cpu := .CPU}}{{round $cpu.Mhz 2 }} {{end}}",
+			SysInfo:        sysinfo{CPU: []cpu.InfoStat{{Mhz: 1200}, {Mhz: 1200}}},
+		},
+	}
+
+	for _, tc := range cases {
+		tc.SysInfo.env = new(MockedEnvironment)
+		tc.SysInfo.props = &properties{
+			values: map[Property]interface{}{
+				Precision: tc.Precision,
+			},
+		}
+		if tc.Template != "" {
+			tc.SysInfo.props.values[SegmentTemplate] = tc.Template
+		}
+		if tc.ExpectDisabled {
+			assert.Equal(t, false, tc.SysInfo.enabled(), tc.Case)
+		} else {
+			assert.Equal(t, tc.ExpectedString, tc.SysInfo.string(), tc.Case)
+		}
+	}
+}