Skip to content

Commit

Permalink
feat(block): allow templates for filler text
Browse files Browse the repository at this point in the history
This change allows the user to specify a template for filler so that
different behavior can be configured when the block is handling an
overflow.

An example configuration might be:

```yaml
- type: prompt
  alignment: right
  filler: "{{ if .Overflow }} {{ else }}<#3d59a1,transparent>━</>{{ end }}"
  overflow: break
```

This would draw filler text ("-") when there is no overflow and empty
space when there is an overflow.
  • Loading branch information
dusktreader authored and JanDeDobbeleer committed Nov 28, 2024
1 parent be875e0 commit da5b612
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/prompt/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ type Engine struct {
activeSegment *config.Segment
previousActiveSegment *config.Segment
rprompt string
Overflow config.Overflow
prompt strings.Builder
currentLineLength int
rpromptLength int
Padding int
Plain bool
}

Expand Down Expand Up @@ -157,7 +159,13 @@ func (e *Engine) shouldFill(filler string, padLength int) (string, bool) {
return "", false
}

if padLength <= 0 {
tmpl := &template.Text{
Template: filler,
Context: e,
}

var err error
if filler, err = tmpl.Render(); err != nil {
return "", false
}

Expand Down Expand Up @@ -218,6 +226,7 @@ func (e *Engine) renderBlock(block *config.Block, cancelNewline bool) bool {

// we can't print the right block as there's not enough room available
if !OK {
e.Overflow = block.Overflow
switch block.Overflow {
case config.Break:
e.writeNewline()
Expand All @@ -234,6 +243,7 @@ func (e *Engine) renderBlock(block *config.Block, cancelNewline bool) bool {

defer func() {
e.currentLineLength = 0
e.Overflow = ""
}()

// validate if we have a filler and fill if needed
Expand Down
111 changes: 111 additions & 0 deletions src/prompt/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package prompt

import (
"errors"
"strings"
"testing"

"github.com/jandedobbeleer/oh-my-posh/src/cache"
"github.com/jandedobbeleer/oh-my-posh/src/color"
"github.com/jandedobbeleer/oh-my-posh/src/config"
"github.com/jandedobbeleer/oh-my-posh/src/maps"
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
Expand Down Expand Up @@ -276,3 +278,112 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
assert.Equal(t, tc.Expected, got)
}
}

func TestShouldFill(t *testing.T) {
cases := []struct {
Case string
Overflow config.Overflow
ExpectedFiller string
Block config.Block
Padding int
ExpectedBool bool
}{
{
Case: "Plain single character with no padding",
Padding: 0,
ExpectedFiller: "",
ExpectedBool: true,
Block: config.Block{
Overflow: config.Hide,
Filler: "-",
},
},
{
Case: "Plain single character with 1 padding",
Padding: 1,
ExpectedFiller: "-",
ExpectedBool: true,
Block: config.Block{
Overflow: config.Hide,
Filler: "-",
},
},
{
Case: "Plain single character with lots of padding",
Padding: 200,
ExpectedFiller: strings.Repeat("-", 200),
ExpectedBool: true,
Block: config.Block{
Overflow: config.Hide,
Filler: "-",
},
},
{
Case: "Plain multi-character with some padding",
Padding: 20,
ExpectedFiller: strings.Repeat("-^-", 6) + " ",
ExpectedBool: true,
Block: config.Block{
Overflow: config.Hide,
Filler: "-^-",
},
},
{
Case: "Template conditional on overflow with no overflow",
Padding: 3,
ExpectedFiller: strings.Repeat("X", 3),
ExpectedBool: true,
Block: config.Block{
Overflow: config.Hide,
Filler: "{{ if .Overflow -}} O {{- else -}} X {{- end }}",
},
},
{
Case: "Template conditional on overflow with an overflow",
Overflow: config.Break,
Padding: 3,
ExpectedFiller: strings.Repeat("O", 3),
ExpectedBool: true,
Block: config.Block{
Overflow: config.Hide,
Filler: "{{ if .Overflow -}} O {{- else -}} X {{- end }}",
},
},
{
Case: "Template conditional on overflow break",
Overflow: config.Break,
Padding: 3,
ExpectedFiller: strings.Repeat("O", 3),
ExpectedBool: true,
Block: config.Block{
Overflow: config.Break,
Filler: `{{ if eq .Overflow "break" -}} O {{- else -}} X {{- end }}`,
},
},
}

for _, tc := range cases {
env := new(mock.Environment)
env.On("Shell").Return(shell.GENERIC)

engine := &Engine{
Env: env,
Overflow: tc.Overflow,
}

template.Cache = &cache.Template{
Shell: shell.GENERIC,
Segments: maps.NewConcurrent(),
}
template.Init(env, nil)

terminal.Init(shell.GENERIC)
terminal.Plain = true
terminal.Colors = &color.Defaults{}

gotFiller, gotBool := engine.shouldFill(tc.Block.Filler, tc.Padding)

assert.Equal(t, tc.ExpectedFiller, gotFiller, tc.Case)
assert.Equal(t, tc.ExpectedBool, gotBool, tc.Case)
}
}
21 changes: 21 additions & 0 deletions website/docs/configuration/block.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ to be repeated to this property. Add this property to the _right_ aligned block.
}}
/>

Filler allows you to specify a template to tweak the text used as filler. This template behaves the same as
Segment templates, however, fewer properties are available.

| Name | Type | Description |
| ----------- | ------ | --------------------------------------------------------------------- |
| `.Overflow` | `text` | if no overflow was needed, this is empty. Otherwise `hide` or `break` |
| `.Padding` | `int` | the computed length of the padding between left and right blocks |

This can be very useful if you wish to use a filler text when there is no overflow and use
empty space when the right block is hidden or drawn on a newline due to overflow.

<Config
data={{
block: {
alignment: "right",
overflow: "hide",
filler: "{{ if .Overflow }} {{ else }}-{{ end }}",
},
}}
/>

### Overflow

- `break`
Expand Down

0 comments on commit da5b612

Please sign in to comment.