@@ -27,8 +27,8 @@ const (
27
27
defaultHeight = 6
28
28
defaultWidth = 40
29
29
defaultCharLimit = 400
30
- maxHeight = 99
31
- maxWidth = 500
30
+ defaultMaxHeight = 99
31
+ defaultMaxWidth = 500
32
32
)
33
33
34
34
// Internal messages for clipboard operations.
@@ -182,6 +182,14 @@ type Model struct {
182
182
// accept. If 0 or less, there's no limit.
183
183
CharLimit int
184
184
185
+ // MaxHeight is the maximum height of the text area in rows. If 0 or less,
186
+ // there's no limit.
187
+ MaxHeight int
188
+
189
+ // MaxWidth is the maximum width of the text area in columns. If 0 or less,
190
+ // there's no limit.
191
+ MaxWidth int
192
+
185
193
// If promptFunc is set, it replaces Prompt as a generator for
186
194
// prompt strings at the beginning of each line.
187
195
promptFunc func (line int ) string
@@ -239,6 +247,8 @@ func New() Model {
239
247
240
248
m := Model {
241
249
CharLimit : defaultCharLimit ,
250
+ MaxHeight : defaultMaxHeight ,
251
+ MaxWidth : defaultMaxWidth ,
242
252
Prompt : lipgloss .ThickBorder ().Left + " " ,
243
253
style : & blurredStyle ,
244
254
FocusedStyle : focusedStyle ,
@@ -248,7 +258,7 @@ func New() Model {
248
258
Cursor : cur ,
249
259
KeyMap : DefaultKeyMap ,
250
260
251
- value : make ([][]rune , minHeight , maxHeight ),
261
+ value : make ([][]rune , minHeight , defaultMaxHeight ),
252
262
focus : false ,
253
263
col : 0 ,
254
264
row : 0 ,
@@ -332,6 +342,10 @@ func (m *Model) insertRunesFromUserInput(runes []rune) {
332
342
lstart := 0
333
343
for i := 0 ; i < len (runes ); i ++ {
334
344
if runes [i ] == '\n' {
345
+ // Queue a line to become a new row in the text area below.
346
+ // Beware to clamp the max capacity of the slice, to ensure no
347
+ // data from different rows get overwritten when later edits
348
+ // will modify this line.
335
349
lines = append (lines , runes [lstart :i :i ])
336
350
lstart = i + 1
337
351
}
@@ -343,8 +357,8 @@ func (m *Model) insertRunesFromUserInput(runes []rune) {
343
357
}
344
358
345
359
// Obey the maximum height limit.
346
- if len (m .value )+ len (lines )- 1 > maxHeight {
347
- allowedHeight := max (0 , maxHeight - len (m .value )+ 1 )
360
+ if m . MaxHeight > 0 && len (m .value )+ len (lines )- 1 > m . MaxHeight {
361
+ allowedHeight := max (0 , m . MaxHeight - len (m .value )+ 1 )
348
362
lines = lines [:allowedHeight ]
349
363
}
350
364
@@ -353,7 +367,7 @@ func (m *Model) insertRunesFromUserInput(runes []rune) {
353
367
return
354
368
}
355
369
356
- // Save the reminder of the original line at the current
370
+ // Save the remainder of the original line at the current
357
371
// cursor position.
358
372
tail := make ([]rune , len (m .value [m .row ][m .col :]))
359
373
copy (tail , m .value [m .row ][m .col :])
@@ -450,7 +464,7 @@ func (m *Model) CursorDown() {
450
464
m .row ++
451
465
m .col = 0
452
466
} else {
453
- // Move the cursor to the start of the next line. So that we can get
467
+ // Move the cursor to the start of the next line so that we can get
454
468
// the line information. We need to add 2 columns to account for the
455
469
// trailing space wrapping.
456
470
m .col = min (li .StartColumn + li .Width + 2 , len (m .value [m .row ])- 1 )
@@ -539,7 +553,7 @@ func (m *Model) Focus() tea.Cmd {
539
553
return m .Cursor .Focus ()
540
554
}
541
555
542
- // Blur removes the focus state on the model. When the model is blurred it can
556
+ // Blur removes the focus state on the model. When the model is blurred it can
543
557
// not receive keyboard input and the cursor will be hidden.
544
558
func (m * Model ) Blur () {
545
559
m .focus = false
@@ -549,14 +563,18 @@ func (m *Model) Blur() {
549
563
550
564
// Reset sets the input to its default state with no input.
551
565
func (m * Model ) Reset () {
552
- m .value = make ([][]rune , minHeight , maxHeight )
566
+ startCap := m .MaxHeight
567
+ if startCap <= 0 {
568
+ startCap = defaultMaxHeight
569
+ }
570
+ m .value = make ([][]rune , minHeight , startCap )
553
571
m .col = 0
554
572
m .row = 0
555
573
m .viewport .GotoTop ()
556
574
m .SetCursor (0 )
557
575
}
558
576
559
- // rsan initializes or retrieves the rune sanitizer.
577
+ // san initializes or retrieves the rune sanitizer.
560
578
func (m * Model ) san () runeutil.Sanitizer {
561
579
if m .rsan == nil {
562
580
// Textinput has all its input on a single line so collapse
@@ -852,12 +870,16 @@ func (m *Model) moveToEnd() {
852
870
// whether or not line numbers are being shown.
853
871
//
854
872
// Ensure that SetWidth is called after setting the Prompt and ShowLineNumbers,
855
- // If it important that the width of the textarea be exactly the given width
873
+ // It is important that the width of the textarea be exactly the given width
856
874
// and no more.
857
875
func (m * Model ) SetWidth (w int ) {
858
- m .viewport .Width = clamp (w , minWidth , maxWidth )
876
+ if m .MaxWidth > 0 {
877
+ m .viewport .Width = clamp (w , minWidth , m .MaxWidth )
878
+ } else {
879
+ m .viewport .Width = max (w , minWidth )
880
+ }
859
881
860
- // Since the width of the textarea input is dependant on the width of the
882
+ // Since the width of the textarea input is dependent on the width of the
861
883
// prompt and line numbers, we need to calculate it by subtracting.
862
884
inputWidth := w
863
885
if m .ShowLineNumbers {
@@ -872,7 +894,11 @@ func (m *Model) SetWidth(w int) {
872
894
}
873
895
874
896
inputWidth -= m .promptWidth
875
- m .width = clamp (inputWidth , minWidth , maxWidth )
897
+ if m .MaxWidth > 0 {
898
+ m .width = clamp (inputWidth , minWidth , m .MaxWidth )
899
+ } else {
900
+ m .width = max (inputWidth , minWidth )
901
+ }
876
902
}
877
903
878
904
// SetPromptFunc supersedes the Prompt field and sets a dynamic prompt
@@ -894,13 +920,18 @@ func (m Model) Height() int {
894
920
895
921
// SetHeight sets the height of the textarea.
896
922
func (m * Model ) SetHeight (h int ) {
897
- m .height = clamp (h , minHeight , maxHeight )
898
- m .viewport .Height = clamp (h , minHeight , maxHeight )
923
+ if m .MaxHeight > 0 {
924
+ m .height = clamp (h , minHeight , m .MaxHeight )
925
+ m .viewport .Height = clamp (h , minHeight , m .MaxHeight )
926
+ } else {
927
+ m .height = max (h , minHeight )
928
+ m .viewport .Height = max (h , minHeight )
929
+ }
899
930
}
900
931
901
932
// InsertNewline inserts a newline character at the cursor.
902
933
func (m * Model ) InsertNewline () {
903
- if len (m .value ) >= maxHeight {
934
+ if m . MaxHeight > 0 && len (m .value ) >= m . MaxHeight {
904
935
return
905
936
}
906
937
m .col = clamp (m .col , 0 , len (m .value [m .row ]))
@@ -1223,7 +1254,7 @@ func (m Model) cursorLineNumber() int {
1223
1254
return line
1224
1255
}
1225
1256
1226
- // mergeLineBelow merges the current line with the line below.
1257
+ // mergeLineBelow merges the current line the cursor is on with the line below.
1227
1258
func (m * Model ) mergeLineBelow (row int ) {
1228
1259
if row >= len (m .value )- 1 {
1229
1260
return
0 commit comments