@@ -119,6 +119,11 @@ type Model struct {
119119 // General settings.
120120
121121 // Prompt is printed at the beginning of each line.
122+ //
123+ // When changing the value of Prompt after the model has been
124+ // initialized, ensure that SetWidth() gets called afterwards.
125+ //
126+ // See also SetPromptFunc().
122127 Prompt string
123128
124129 // Placeholder is the text displayed when the user
@@ -152,6 +157,13 @@ type Model struct {
152157 // accept. If 0 or less, there's no limit.
153158 CharLimit int
154159
160+ // If promptFunc is set, it replaces Prompt as a generator for
161+ // prompt strings at the beginning of each line.
162+ promptFunc func (line int ) string
163+
164+ // promptWidth is the width of the prompt.
165+ promptWidth int
166+
155167 // width is the maximum number of characters that can be displayed at once.
156168 // If 0 or less this setting is ignored.
157169 width int
@@ -694,10 +706,26 @@ func (m *Model) SetWidth(w int) {
694706 // Account for base style borders and padding.
695707 inputWidth -= m .style .Base .GetHorizontalFrameSize ()
696708
697- inputWidth -= rw .StringWidth (m .Prompt )
709+ if m .promptFunc != nil {
710+ m .promptWidth = rw .StringWidth (m .Prompt )
711+ }
712+
713+ inputWidth -= m .promptWidth
698714 m .width = clamp (inputWidth , minWidth , maxWidth )
699715}
700716
717+ // SetPromptFunc supersedes the Prompt field and sets a dynamic prompt
718+ // instead.
719+ // If the function returns a prompt that is shorter than the
720+ // specified promptWidth, it will be padded to the left.
721+ // If it returns a prompt that is longer, display artifacts
722+ // may occur; the caller is responsible for computing an adequate
723+ // promptWidth.
724+ func (m * Model ) SetPromptFunc (promptWidth int , fn func (lineIdx int ) string ) {
725+ m .promptFunc = fn
726+ m .promptWidth = promptWidth
727+ }
728+
701729// Height returns the current height of the textarea.
702730func (m Model ) Height () int {
703731 return m .height
@@ -860,6 +888,7 @@ func (m Model) View() string {
860888
861889 var newLines int
862890
891+ displayLine := 0
863892 for l , line := range m .value {
864893 wrappedLines := wrap (line , m .width )
865894
@@ -870,7 +899,10 @@ func (m Model) View() string {
870899 }
871900
872901 for wl , wrappedLine := range wrappedLines {
873- s .WriteString (style .Render (m .style .Prompt .Render (m .Prompt )))
902+ prompt := m .getPromptString (displayLine )
903+ prompt = m .style .Prompt .Render (prompt )
904+ s .WriteString (prompt )
905+ displayLine ++
874906
875907 if m .ShowLineNumbers {
876908 if wl == 0 {
@@ -919,7 +951,10 @@ func (m Model) View() string {
919951 // Always show at least `m.Height` lines at all times.
920952 // To do this we can simply pad out a few extra new lines in the view.
921953 for i := 0 ; i < m .height ; i ++ {
922- s .WriteString (m .style .Prompt .Render (m .Prompt ))
954+ prompt := m .getPromptString (displayLine )
955+ prompt = m .style .Prompt .Render (prompt )
956+ s .WriteString (prompt )
957+ displayLine ++
923958
924959 if m .ShowLineNumbers {
925960 lineNumber := m .style .EndOfBuffer .Render ((fmt .Sprintf (m .lineNumberFormat , string (m .EndOfBufferCharacter ))))
@@ -932,6 +967,19 @@ func (m Model) View() string {
932967 return m .style .Base .Render (m .viewport .View ())
933968}
934969
970+ func (m Model ) getPromptString (displayLine int ) (prompt string ) {
971+ prompt = m .Prompt
972+ if m .promptFunc == nil {
973+ return prompt
974+ }
975+ prompt = m .promptFunc (displayLine )
976+ pl := rw .StringWidth (prompt )
977+ if pl < m .promptWidth {
978+ prompt = fmt .Sprintf ("%*s%s" , m .promptWidth - pl , "" , prompt )
979+ }
980+ return prompt
981+ }
982+
935983// placeholderView returns the prompt and placeholder view, if any.
936984func (m Model ) placeholderView () string {
937985 var (
@@ -940,7 +988,8 @@ func (m Model) placeholderView() string {
940988 style = m .style .Placeholder .Inline (true )
941989 )
942990
943- prompt := m .style .Prompt .Render (m .Prompt )
991+ prompt := m .getPromptString (0 )
992+ prompt = m .style .Prompt .Render (prompt )
944993 s .WriteString (m .style .CursorLine .Render (prompt ))
945994
946995 if m .ShowLineNumbers {
@@ -957,6 +1006,8 @@ func (m Model) placeholderView() string {
9571006 // The rest of the new lines
9581007 for i := 1 ; i < m .height ; i ++ {
9591008 s .WriteRune ('\n' )
1009+ prompt := m .getPromptString (i )
1010+ prompt = m .style .Prompt .Render (prompt )
9601011 s .WriteString (prompt )
9611012
9621013 if m .ShowLineNumbers {
0 commit comments