diff --git a/src/segments/cf_target.go b/src/segments/cf_target.go index 9ef8e0e8..1c1d252f 100644 --- a/src/segments/cf_target.go +++ b/src/segments/cf_target.go @@ -1,7 +1,8 @@ package segments import ( - "regexp" + "errors" + "strings" "github.com/jandedobbeleer/oh-my-posh/src/platform" "github.com/jandedobbeleer/oh-my-posh/src/properties" @@ -31,54 +32,63 @@ func (c *CfTarget) Init(props properties.Properties, env platform.Environment) { } func (c *CfTarget) Enabled() bool { - return c.setCFTargetStatus() -} - -func (c *CfTarget) getCFTargetCommandOutput() string { if !c.env.HasCommand("cf") { - return "" - } - - output, err := c.env.RunCommand("cf", "target") - - if err != nil { - return "" - } - - return output -} - -func (c *CfTarget) setCFTargetStatus() bool { - output := c.getCFTargetCommandOutput() - - if output == "" { return false } - regex := regexp.MustCompile(`API endpoint:\s*(?Phttp[s].*)|user:\s*(?P.*)|org:\s*(?P.*)|space:\s*(?P(.*))`) - match := regex.FindAllStringSubmatch(output, -1) - result := make(map[string]string) + displayMode := c.props.GetString(DisplayMode, DisplayModeAlways) + if displayMode != DisplayModeFiles { + return c.setCFTargetStatus() + } - for i, name := range regex.SubexpNames() { - if i == 0 || len(name) == 0 { + manifest, err := c.env.HasParentFilePath("manifest.yml") + if err != nil || manifest.IsDir { + return false + } + + return c.setCFTargetStatus() +} + +func (c *CfTarget) setCFTargetStatus() bool { + output, err := c.getCFTargetCommandOutput() + + if err != nil { + return false + } + + lines := strings.Split(output, "\n") + for _, line := range lines { + splitted := strings.SplitN(line, ":", 2) + if len(splitted) < 2 { continue } - - for j, val := range match[i-1] { - if j == 0 { - continue - } - - if val != "" { - result[name] = val - } + key := splitted[0] + value := strings.TrimSpace(splitted[1]) + switch key { + case "API endpoint": + c.URL = value + case "user": + c.User = value + case "org": + c.Org = value + case "space": + c.Space = value } } - c.URL = result["api_url"] - c.Org = result["org"] - c.Space = result["space"] - c.User = result["user"] - return true } + +func (c *CfTarget) getCFTargetCommandOutput() (string, error) { + output, err := c.env.RunCommand("cf", "target") + + if err != nil { + return "", err + } + + if len(output) == 0 { + return "", errors.New("cf command output is empty") + } + + return output, nil +} diff --git a/src/segments/cf_target_test.go b/src/segments/cf_target_test.go index 39047cba..81d435ae 100644 --- a/src/segments/cf_target_test.go +++ b/src/segments/cf_target_test.go @@ -1,11 +1,13 @@ package segments import ( + "errors" "fmt" "os/exec" "testing" "github.com/jandedobbeleer/oh-my-posh/src/mock" + "github.com/jandedobbeleer/oh-my-posh/src/platform" "github.com/jandedobbeleer/oh-my-posh/src/properties" "github.com/stretchr/testify/assert" @@ -13,34 +15,51 @@ import ( func TestCFTargetSegment(t *testing.T) { cases := []struct { - Case string - Template string - ExpectedString string - ExpectedEnabled bool - TargetOutput string - CommandError error + Case string + Template string + ExpectedString string + DisplayMode string + FileInfo *platform.FileInfo + TargetOutput string + CommandError error }{ { - Case: "1) not logged in to CF account", - ExpectedString: "", - ExpectedEnabled: false, - TargetOutput: `Not logged in`, - CommandError: &exec.ExitError{}, + Case: "not logged in to CF account", + TargetOutput: `Not logged in`, + CommandError: &exec.ExitError{}, }, { - Case: "2) logged in, default template", - ExpectedString: "12345678trial/dev", - ExpectedEnabled: true, - TargetOutput: "API endpoint: https://api.cf.eu10.hana.ondemand.com\nAPI version: 3.109.0\nuser: user@some.com\norg: 12345678trial\nspace: dev", - CommandError: nil, + Case: "logged in, default template", + ExpectedString: "12345678trial/dev", + TargetOutput: "API endpoint: https://api.cf.eu10.hana.ondemand.com\nAPI version: 3.109.0\nuser: user@some.com\norg: 12345678trial\nspace: dev", }, { - Case: "3) logged in, full template", - Template: "{{.URL}} {{.User}} {{.Org}} {{.Space}}", - ExpectedString: "https://api.cf.eu10.hana.ondemand.com user@some.com 12345678trial dev", - ExpectedEnabled: true, - TargetOutput: "API endpoint: https://api.cf.eu10.hana.ondemand.com\nAPI version: 3.109.0\nuser: user@some.com\norg: 12345678trial\nspace: dev", - CommandError: nil, + Case: "no output from command", + }, + { + Case: "logged in, full template", + Template: "{{.URL}} {{.User}} {{.Org}} {{.Space}}", + ExpectedString: "https://api.cf.eu10.hana.ondemand.com user@some.com 12345678trial dev", + TargetOutput: "API endpoint: https://api.cf.eu10.hana.ondemand.com\nAPI version: 3.109.0\nuser: user@some.com\norg: 12345678trial\nspace: dev", + }, + { + Case: "files and no manifest file", + DisplayMode: DisplayModeFiles, + TargetOutput: "API endpoint: https://api.cf.eu10.hana.ondemand.com\nAPI version: 3.109.0\nuser: user@some.com\norg: 12345678trial\nspace: dev", + }, + { + Case: "files and a manifest file", + ExpectedString: "12345678trial/dev", + DisplayMode: DisplayModeFiles, + FileInfo: &platform.FileInfo{}, + TargetOutput: "API endpoint: https://api.cf.eu10.hana.ondemand.com\nAPI version: 3.109.0\nuser: user@some.com\norg: 12345678trial\nspace: dev", + }, + { + Case: "files and a manifest directory", + DisplayMode: DisplayModeFiles, + FileInfo: &platform.FileInfo{ + IsDir: true, + }, }, } @@ -50,9 +69,16 @@ func TestCFTargetSegment(t *testing.T) { env.On("RunCommand", "cf", []string{"target"}).Return(tc.TargetOutput, tc.CommandError) env.On("Pwd", nil).Return("/usr/home/dev/my-app") env.On("Home", nil).Return("/usr/home") + var err error + if tc.FileInfo == nil { + err = errors.New("no such file or directory") + } + env.On("HasParentFilePath", "manifest.yml").Return(tc.FileInfo, err) cfTarget := &CfTarget{} - props := properties.Map{} + props := properties.Map{ + DisplayMode: tc.DisplayMode, + } if tc.Template == "" { tc.Template = cfTarget.Template() @@ -61,7 +87,7 @@ func TestCFTargetSegment(t *testing.T) { cfTarget.Init(props, env) failMsg := fmt.Sprintf("Failed in case: %s", tc.Case) - assert.Equal(t, tc.ExpectedEnabled, cfTarget.Enabled(), failMsg) + assert.Equal(t, len(tc.ExpectedString) > 0, cfTarget.Enabled(), failMsg) assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, cfTarget), failMsg) } } diff --git a/themes/schema.json b/themes/schema.json index 5ae6c43a..517901fe 100644 --- a/themes/schema.json +++ b/themes/schema.json @@ -2863,7 +2863,16 @@ }, "then": { "title": "Clound Foundry Target segment", - "description": "https://ohmyposh.dev/docs/segments/cftarget" + "description": "https://ohmyposh.dev/docs/segments/cftarget", + "properties": { + "properties": { + "properties": { + "display_mode": { + "$ref": "#/definitions/display_mode" + } + } + } + } } }, { diff --git a/website/docs/segments/cftarget.mdx b/website/docs/segments/cftarget.mdx index a73d8879..9e21188a 100644 --- a/website/docs/segments/cftarget.mdx +++ b/website/docs/segments/cftarget.mdx @@ -21,6 +21,12 @@ Display the details of the logged [Cloud Foundry endpoint][cf-target] (`cf targe } ``` +## Properties + +| Name | Type | Description | +| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `display_mode` | `string` |
  • `always`: the segment is always displayed (**default**)
  • `files`: the segment is only displayed when a `manifest.yml` file is present
| + ## Template ([info][templates]) :::note default template