Repository: JanDeDobbeleer/oh-my-posh
Pull request #538 (2021-03-17 07:16:56)

feat(java): add segment
### 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



Patch:
diff --git a/docs/docs/contributing-started.mdx b/docs/docs/contributing-started.mdx
index 7f2cbdc4..923c24a6 100644
--- a/docs/docs/contributing-started.mdx
+++ b/docs/docs/contributing-started.mdx
@@ -11,58 +11,18 @@ import TabItem from "@theme/TabItem";
 
 ### go
 
-The code base is in [go][go], meaning we need a working go setup before we can do anything else.
+The codebase is in [go][go], meaning we need a working go setup before we can do anything else.
 Have a look at the [go guide][go-started] to get up and running with go in no time!
 
+:::info
+Oh my Posh needs at least go 1.16.
+:::
+
 ### golangci-lint
 
 To make sure we keep on writing quality code, [golang-ci lint][golang-ci-lint] is used to validate the changes.
 Have a look at the [local installation guide][golang-ci-lint-local] to make sure you can validate this yourself as well.
 
-### go-bindata
-
-Oh my Posh packs the initialization scipts for the different shells, but go does not ship with the ability to add
-files other than go code to your compiled binary. [go-bindata][go-bindata] allows us to add initialization files and
-ship them in the source code to easily bootstrap your shell with Oh my Posh.
-
-There are multiple ways to install go-bindata.
-
-<Tabs
-  defaultValue="homebrew"
-  values={[
-    { label: 'homebrew', value: 'homebrew', },
-    { label: 'linux', value: 'linux', },
-    { label: 'source', value: 'source', },
-  ]
-}>
-<TabItem value="homebrew">
-
-```bash
-brew install go-bindata
-```
-
-</TabItem>
-<TabItem value="linux">
-
-```bash
-curl --silent --location --output /usr/local/bin/go-bindata https://github.com/kevinburke/go-bindata/releases/download/v3.11.0/go-bindata-linux-amd64
-chmod 755 /usr/local/bin/go-bindata
-```
-
-</TabItem>
-<TabItem value="source">
-
-```bash
-go get -u github.com/kevinburke/go-bindata/...
-```
-
-Be careful as executing this inside the Oh my Posh repository will adjust the `go.mod` file with this dependency.
-Today, there's no way to install a dependency system wide for go, although that's [in the works][go-global].
-Make sure to remove this before submitting a PR as there's [a check][pr-go-mod] in place to avoid adding unused dependencies.
-
-</TabItem>
-</Tabs>
-
 ## Get the source code
 
 The source is hosted on [Github][omp]. When you want to contribute, create a [fork][gh-fork] so you can make changes in
diff --git a/docs/docs/segment-java.md b/docs/docs/segment-java.md
new file mode 100644
index 00000000..b88c24c5
--- /dev/null
+++ b/docs/docs/segment-java.md
@@ -0,0 +1,45 @@
+---
+id: java
+title: Java
+sidebar_label: Java
+---
+
+## What
+
+Display the currently active java version.
+
+## Sample Configuration
+
+```json
+{
+  "type": "java",
+  "style": "powerline",
+  "powerline_symbol": "\uE0B0",
+  "foreground": "#ffffff",
+  "background": "#4063D8",
+  "properties": {
+    "prefix": " \uE738 "
+  }
+}
+```
+
+## Properties
+
+- display_version: `boolean` - display the java version - defaults to `true`
+- display_error: `boolean` - show the error context when failing to retrieve the version information - defaults to `true`
+- missing_command_text: `string` - text to display when the java command is missing - defaults to empty
+- display_mode: `string` - determines when the segment is displayed
+  - `always`: the segment is always displayed
+  - `files`: the segment is only displayed when one of the following files is present:
+    - `build.gradle.kts`
+    - `build.sbt`
+    - `.java-version`
+    - `.deps.edn`
+    - `project.clj`
+    - `build.boot`
+    - `*.java`
+    - `*.class`
+    - `*.gradle`
+    - `*.jar`
+    - `*.clj`
+    - `*.cljc`
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 588ab7b6..7c8d32bb 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -19,6 +19,7 @@ module.exports = {
         "exit",
         "git",
         "golang",
+        "java",
         "julia",
         "kubectl",
         "node",
diff --git a/src/init/omp.bash b/src/init/omp.bash
index 5fa20519..a148331a 100644
--- a/src/init/omp.bash
+++ b/src/init/omp.bash
@@ -12,7 +12,7 @@ function _update_ps1() {
         omp_elapsed=$(($omp_now-$omp_start_time))
         rm $TIMER_START
     fi
-    PS1="$(::OMP:: --config $POSH_THEME --error $? --execution-time $omp_elapsed)"
+    PS1="$(::OMP:: --config $POSH_THEME --error $? --execution-time $omp_elapsed --shell bash)"
 }
 
 if [ "$TERM" != "linux" ] && [ -x "$(command -v ::OMP::)" ]; then
diff --git a/src/init/omp.fish b/src/init/omp.fish
index a188f0f3..5be42360 100644
--- a/src/init/omp.fish
+++ b/src/init/omp.fish
@@ -1,4 +1,4 @@
 function fish_prompt
     set -l omp_duration "$CMD_DURATION$cmd_duration"
-    ::OMP:: --config ::CONFIG:: --error $status --execution-time $omp_duration
+    ::OMP:: --config ::CONFIG:: --error $status --execution-time $omp_duration --shell fish
 end
diff --git a/src/init/omp.zsh b/src/init/omp.zsh
index e30b9fe3..c869a94b 100644
--- a/src/init/omp.zsh
+++ b/src/init/omp.zsh
@@ -11,7 +11,7 @@ function omp_precmd() {
     omp_now=$(::OMP:: --millis)
     omp_elapsed=$(($omp_now-$omp_start_time))
   fi
-  eval "$(::OMP:: --config $POSH_THEME --error $omp_last_error --execution-time $omp_elapsed --eval)"
+  eval "$(::OMP:: --config $POSH_THEME --error $omp_last_error --execution-time $omp_elapsed --eval --shell zsh)"
   unset omp_start_time
   unset omp_now
   unset omp_elapsed
diff --git a/src/segment.go b/src/segment.go
index 11592fdd..9a9128b3 100644
--- a/src/segment.go
+++ b/src/segment.go
@@ -94,6 +94,8 @@ const (
 	Ruby SegmentType = "ruby"
 	// Aws writes the active aws context
 	Aws SegmentType = "aws"
+	// Java writes the active java version
+	Java SegmentType = "java"
 )
 
 func (segment *Segment) string() string {
@@ -216,6 +218,7 @@ func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
 		ExecutionTime: &executiontime{},
 		Ruby:          &ruby{},
 		Aws:           &aws{},
+		Java:          &java{},
 	}
 	if writer, ok := functions[segment.Type]; ok {
 		props := &properties{
diff --git a/src/segment_java.go b/src/segment_java.go
new file mode 100644
index 00000000..73f73603
--- /dev/null
+++ b/src/segment_java.go
@@ -0,0 +1,57 @@
+package main
+
+import "fmt"
+
+type java struct {
+	language *language
+}
+
+func (j *java) string() string {
+	return j.language.string()
+}
+
+func (j *java) init(props *properties, env environmentInfo) {
+	javaRegex := `\((?P<version>(?P<major>[0-9]+)\.(?P<minor>[0-9]+)\.(?P<patch>[0-9]+)).*\).*(?:built|from)`
+	javaCmd := &cmd{
+		executable: "java",
+		args:       []string{"-Xinternalversion"},
+		regex:      javaRegex,
+	}
+	j.language = &language{
+		env:   env,
+		props: props,
+		extensions: []string{
+			"pom.xml",
+			"build.gradle.kts",
+			"build.sbt",
+			".java-version",
+			".deps.edn",
+			"project.clj",
+			"build.boot",
+			"*.java",
+			"*.class",
+			"*.gradle",
+			"*.jar",
+			"*.clj",
+			"*.cljc",
+		},
+	}
+	javaHome := j.language.env.getenv("JAVA_HOME")
+	if len(javaHome) > 0 {
+		java := fmt.Sprintf("%s/bin/java", javaHome)
+		j.language.commands = []*cmd{
+			{
+				executable: java,
+				args:       []string{"-Xinternalversion"},
+				regex:      javaRegex,
+			},
+			javaCmd,
+		}
+		return
+	}
+	j.language.commands = []*cmd{javaCmd}
+}
+
+func (j *java) enabled() bool {
+	return j.language.enabled()
+}
diff --git a/themes/schema.json b/themes/schema.json
index fdc1c051..9551716b 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -154,7 +154,8 @@
             "ruby",
             "ytm",
             "executiontime",
-            "aws"
+            "aws",
+            "java"
           ]
         },
         "style": {
@@ -715,6 +716,32 @@
             }
           }
         },
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "java" }
+            }
+          },
+          "then": {
+            "title": "Julia Segment",
+            "description": "https://ohmyposh.dev/docs/java",
+            "properties": {
+              "properties": {
+                "properties": {
+                  "display_version": {
+                    "$ref": "#/definitions/display_version"
+                  },
+                  "display_mode": {
+                    "$ref": "#/definitions/display_mode"
+                  },
+                  "missing_command_text": {
+                    "$ref": "#/definitions/missing_command_text"
+                  }
+                }
+              }
+            }
+          }
+        },
         {
           "if": {
             "properties": {


Test patch:
diff --git a/src/segment_java_test.go b/src/segment_java_test.go
new file mode 100755
index 00000000..55b7395b
--- /dev/null
+++ b/src/segment_java_test.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestJava(t *testing.T) {
+	cases := []struct {
+		Case            string
+		ExpectedString  string
+		Version         string
+		JavaHomeVersion string
+		JavaHomeEnabled bool
+	}{
+		{
+			Case:           "OpenJDK macOS",
+			ExpectedString: "1.8.0",
+			Version:        "OpenJDK 64-Bit Server VM (25.275-b01) for bsd-amd64 JRE (1.8.0_275-b01), built on Nov  9 2020 12:07:35 by \"jenkins\" with gcc 4.2.1",
+		},
+		{
+			Case:           "OpenJDK macOS with JAVA_HOME, no executable",
+			ExpectedString: "1.8.0",
+			Version:        "OpenJDK 64-Bit Server VM (25.275-b01) for bsd-amd64 JRE (1.8.0_275-b01), built on Nov  9 2020 12:07:35 by \"jenkins\" with gcc 4.2.1",
+		},
+		{
+			Case:            "OpenJDK macOS with JAVA_HOME and executable",
+			ExpectedString:  "1.7.0",
+			JavaHomeEnabled: true,
+			JavaHomeVersion: "OpenJDK 64-Bit Server VM (25.275-b01) for bsd-amd64 JRE (1.7.0_275-b01), built on Nov  9 2020 12:07:35 by \"jenkins\" with gcc 4.2.1",
+			Version:         "OpenJDK 64-Bit Server VM (25.275-b01) for bsd-amd64 JRE (1.8.0_275-b01), built on Nov  9 2020 12:07:35 by \"jenkins\" with gcc 4.2.1",
+		},
+	}
+	for _, tc := range cases {
+		env := new(MockedEnvironment)
+		env.On("hasCommand", "java").Return(true)
+		env.On("runCommand", "java", []string{"-Xinternalversion"}).Return(tc.Version, nil)
+		env.On("hasFiles", "pom.xml").Return(true)
+		if tc.JavaHomeEnabled {
+			env.On("getenv", "JAVA_HOME").Return("/usr/java")
+			env.On("hasCommand", "/usr/java/bin/java").Return(true)
+			env.On("runCommand", "/usr/java/bin/java", []string{"-Xinternalversion"}).Return(tc.JavaHomeVersion, nil)
+		} else {
+			env.On("getenv", "JAVA_HOME").Return("")
+		}
+		props := &properties{
+			values: map[Property]interface{}{
+				DisplayVersion: true,
+			},
+		}
+		j := &java{}
+		j.init(props, env)
+		assert.True(t, j.enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
+		assert.Equal(t, tc.ExpectedString, j.string(), fmt.Sprintf("Failed in case: %s", tc.Case))
+	}
+}