Skip to content

Commit

Permalink
feat(textarea) Add multiline placeholder
Browse files Browse the repository at this point in the history
Add the capability to show a multiline placeholder. Some refactoring was
required to improve readability and improve logic.

End of line buffer character was only shown when line numbers were
displayed which requires some verification whether this is the intended
outcome. This change resolves this issue.
  • Loading branch information
mikelorant committed Dec 6, 2022
1 parent e78f923 commit c5687de
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 21 deletions.
54 changes: 33 additions & 21 deletions textarea/textarea.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,36 +1078,48 @@ func (m Model) getPromptString(displayLine int) (prompt string) {
func (m Model) placeholderView() string {
var (
s strings.Builder
p = rw.Truncate(m.Placeholder, m.width, "...")
p = m.Placeholder
style = m.style.Placeholder.Inline(true)
)

prompt := m.getPromptString(0)
prompt = m.style.Prompt.Render(prompt)
s.WriteString(m.style.CursorLine.Render(prompt))
// split string by new lines
plines := strings.Split(p, "\n")

if m.ShowLineNumbers {
s.WriteString(m.style.CursorLine.Render(m.style.CursorLineNumber.Render((fmt.Sprintf(m.lineNumberFormat, 1)))))
}

m.Cursor.TextStyle = m.style.Placeholder
m.Cursor.SetChar(string(p[0]))
s.WriteString(m.style.CursorLine.Render(m.Cursor.View()))

// The rest of the placeholder text
s.WriteString(m.style.CursorLine.Render(style.Render(p[1:] + strings.Repeat(" ", max(0, m.width-rw.StringWidth(p))))))

// The rest of the new lines
for i := 1; i < m.height; i++ {
s.WriteRune('\n')
for i := 0; i < m.height; i++ {
// render prompt
prompt := m.getPromptString(i)
prompt = m.style.Prompt.Render(prompt)
s.WriteString(prompt)
s.WriteString(m.style.CursorLine.Render(prompt))

// render line numbers
if m.ShowLineNumbers {
eob := m.style.EndOfBuffer.Render((fmt.Sprintf(m.lineNumberFormat, string(m.EndOfBufferCharacter))))
s.WriteString(eob)
s.WriteString(m.style.CursorLine.Render(m.style.CursorLineNumber.Render((fmt.Sprintf(m.lineNumberFormat, i+1)))))
}

switch {
// first line
case i == 0:
// first character of first line as cursor with character
m.Cursor.TextStyle = m.style.Placeholder
m.Cursor.SetChar(string(plines[0][0]))
s.WriteString(m.style.CursorLine.Render(m.Cursor.View()))

// the rest of the first line
s.WriteString(m.style.CursorLine.Render(style.Render(plines[0][1:] + strings.Repeat(" ", max(0, m.width-rw.StringWidth(plines[0]))))))
// remaining lines
case len(plines) > i:
// current line placeholder text
if len(plines) > i {
s.WriteString(m.style.CursorLine.Render(style.Render(plines[i] + strings.Repeat(" ", max(0, m.width-rw.StringWidth(plines[i]))))))
}
}

// end of line buffer character
eob := m.style.EndOfBuffer.Render((fmt.Sprintf(m.lineNumberFormat, string(m.EndOfBufferCharacter))))
s.WriteString(eob)

// terminate with new line
s.WriteRune('\n')
}

m.viewport.SetContent(s.String())
Expand Down
23 changes: 23 additions & 0 deletions textarea/textarea_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,29 @@ func TestRendersEndOfLineBuffer(t *testing.T) {
}
}

func TestRendersMultilinePlaceholder(t *testing.T) {
lines := []string{
"the first line",
"the second line",
"the third line",
}

textarea := newTextArea()
textarea.Placeholder = strings.Join(lines, "\n")
view := textarea.View()

for i, line := range strings.Split(view, "\n") {
if i == len(lines) {
break
}

if !strings.Contains(line, lines[i][1:]) {
t.Log(view)
t.Error("Expected to see line in placeholder")
}
}
}

func newTextArea() Model {
textarea := New()

Expand Down

0 comments on commit c5687de

Please sign in to comment.