diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2024-03-09 09:53:25 +0100 |
---|---|---|
committer | Stefan Haller <stefan@haller-berlin.de> | 2024-03-09 10:00:07 +0100 |
commit | 99ad6005e82e49e84121121feb4255e09dbb8673 (patch) | |
tree | 2f20bc7b60054a4cf5380177d67722129f62bebb /vendor/github.com | |
parent | dc9ee186f4d56f5a971012063ae27d2dd3ce276a (diff) |
Bump gocui
Diffstat (limited to 'vendor/github.com')
-rw-r--r-- | vendor/github.com/gdamore/tcell/v2/console_win.go | 6 | ||||
-rw-r--r-- | vendor/github.com/jesseduffield/gocui/text_area.go | 168 |
2 files changed, 157 insertions, 17 deletions
diff --git a/vendor/github.com/gdamore/tcell/v2/console_win.go b/vendor/github.com/gdamore/tcell/v2/console_win.go index 92ae4e5c2..e2652509e 100644 --- a/vendor/github.com/gdamore/tcell/v2/console_win.go +++ b/vendor/github.com/gdamore/tcell/v2/console_win.go @@ -341,12 +341,12 @@ func (s *cScreen) disengage() { } } else if !s.disableAlt { s.clearScreen(StyleDefault, s.vten) + s.setCursorPos(0, 0, false) } + s.setCursorInfo(&s.ocursor) + s.setBufferSize(int(s.oscreen.size.x), int(s.oscreen.size.y)) s.setInMode(s.oimode) s.setOutMode(s.oomode) - s.setBufferSize(int(s.oscreen.size.x), int(s.oscreen.size.y)) - s.setCursorPos(0, 0, false) - s.setCursorInfo(&s.ocursor) _, _, _ = procSetConsoleTextAttribute.Call( uintptr(s.out), uintptr(s.mapStyle(StyleDefault))) diff --git a/vendor/github.com/jesseduffield/gocui/text_area.go b/vendor/github.com/jesseduffield/gocui/text_area.go index ca4809107..ebd6a6bfa 100644 --- a/vendor/github.com/jesseduffield/gocui/text_area.go +++ b/vendor/github.com/jesseduffield/gocui/text_area.go @@ -11,11 +11,59 @@ const ( WORD_SEPARATORS = "*?_+-.[]~=/&;!#$%^(){}<>" ) +type CursorMapping struct { + Orig int + Wrapped int +} + type TextArea struct { - content []rune - cursor int - overwrite bool - clipboard string + content []rune + wrappedContent []rune + cursorMapping []CursorMapping + cursor int + overwrite bool + clipboard string + AutoWrap bool + AutoWrapWidth int +} + +func AutoWrapContent(content []rune, autoWrapWidth int) ([]rune, []CursorMapping) { + estimatedNumberOfSoftLineBreaks := len(content) / autoWrapWidth + cursorMapping := make([]CursorMapping, 0, estimatedNumberOfSoftLineBreaks) + wrappedContent := make([]rune, 0, len(content)+estimatedNumberOfSoftLineBreaks) + startOfLine := 0 + indexOfLastWhitespace := -1 + + for currentPos, r := range content { + if r == '\n' { + wrappedContent = append(wrappedContent, content[startOfLine:currentPos+1]...) + startOfLine = currentPos + 1 + indexOfLastWhitespace = -1 + } else { + if r == ' ' { + indexOfLastWhitespace = currentPos + 1 + } else if currentPos-startOfLine >= autoWrapWidth && indexOfLastWhitespace >= 0 { + wrapAt := indexOfLastWhitespace + wrappedContent = append(wrappedContent, content[startOfLine:wrapAt]...) + wrappedContent = append(wrappedContent, '\n') + cursorMapping = append(cursorMapping, CursorMapping{wrapAt, len(wrappedContent)}) + startOfLine = wrapAt + indexOfLastWhitespace = -1 + } + } + } + + wrappedContent = append(wrappedContent, content[startOfLine:]...) + + return wrappedContent, cursorMapping +} + +func (self *TextArea) autoWrapContent() { + if self.AutoWrap { + self.wrappedContent, self.cursorMapping = AutoWrapContent(self.content, self.AutoWrapWidth) + } else { + self.wrappedContent, self.cursorMapping = self.content, []CursorMapping{} + } } func (self *TextArea) TypeRune(r rune) { @@ -27,6 +75,7 @@ func (self *TextArea) TypeRune(r rune) { append([]rune{r}, self.content[self.cursor:]...)..., ) } + self.autoWrapContent() self.cursor++ } @@ -37,6 +86,7 @@ func (self *TextArea) BackSpaceChar() { } self.content = append(self.content[:self.cursor-1], self.content[self.cursor:]...) + self.autoWrapContent() self.cursor-- } @@ -46,6 +96,7 @@ func (self *TextArea) DeleteChar() { } self.content = append(self.content[:self.cursor], self.content[self.cursor+1:]...) + self.autoWrapContent() } func (self *TextArea) MoveCursorLeft() { @@ -123,6 +174,10 @@ func (self *TextArea) MoveCursorDown() { } func (self *TextArea) GetContent() string { + return string(self.wrappedContent) +} + +func (self *TextArea) GetUnwrappedContent() string { return string(self.content) } @@ -144,14 +199,24 @@ func (self *TextArea) DeleteToStartOfLine() { self.content = append(self.content[:self.cursor-1], self.content[self.cursor:]...) self.cursor-- + self.autoWrapContent() return } + // otherwise, if we're at a soft line start, skip left past the soft line + // break, so we'll end up deleting the previous line. This seems like the + // only reasonable behavior in this case, as you can't delete just the soft + // line break. + if self.atSoftLineStart() { + self.cursor-- + } + // otherwise, you delete everything up to the start of the current line, without // deleting the newline character newlineIndex := self.closestNewlineOnLeft() self.clipboard = string(self.content[newlineIndex+1 : self.cursor]) self.content = append(self.content[:newlineIndex+1], self.content[self.cursor:]...) + self.autoWrapContent() self.cursor = newlineIndex + 1 } @@ -159,18 +224,30 @@ func (self *TextArea) DeleteToEndOfLine() { if self.atEnd() { return } + + // if we're at the end of the line, delete just the newline character if self.atLineEnd() { self.content = append(self.content[:self.cursor], self.content[self.cursor+1:]...) + self.autoWrapContent() return } + // otherwise, if we're at a soft line end, skip right past the soft line + // break, so we'll end up deleting the next line. This seems like the + // only reasonable behavior in this case, as you can't delete just the soft + // line break. + if self.atSoftLineEnd() { + self.cursor++ + } + lineEndIndex := self.closestNewlineOnRight() self.clipboard = string(self.content[self.cursor:lineEndIndex]) self.content = append(self.content[:self.cursor], self.content[lineEndIndex:]...) + self.autoWrapContent() } func (self *TextArea) GoToStartOfLine() { - if self.atLineStart() { + if self.atSoftLineStart() { return } @@ -181,15 +258,21 @@ func (self *TextArea) GoToStartOfLine() { } func (self *TextArea) closestNewlineOnLeft() int { + wrappedCursor := self.origCursorToWrappedCursor(self.cursor) + newlineIndex := -1 - for i, r := range self.content[0:self.cursor] { + for i, r := range self.wrappedContent[0:wrappedCursor] { if r == '\n' { newlineIndex = i } } - return newlineIndex + unwrappedNewlineIndex := self.wrappedCursorToOrigCursor(newlineIndex) + if unwrappedNewlineIndex >= 0 && self.content[unwrappedNewlineIndex] != '\n' { + unwrappedNewlineIndex-- + } + return unwrappedNewlineIndex } func (self *TextArea) GoToEndOfLine() { @@ -198,12 +281,22 @@ func (self *TextArea) GoToEndOfLine() { } self.cursor = self.closestNewlineOnRight() + + // If the end of line is a soft line break, we need to move left by one so + // that we end up at the last whitespace before the line break. Otherwise + // we'd be at the start of the next line, since the newline character + // doesn't really exist in the real content. + if self.cursor < len(self.content) && self.content[self.cursor] != '\n' { + self.cursor-- + } } func (self *TextArea) closestNewlineOnRight() int { - for i, r := range self.content[self.cursor:] { + wrappedCursor := self.origCursorToWrappedCursor(self.cursor) + + for i, r := range self.wrappedContent[wrappedCursor:] { if r == '\n' { - return self.cursor + i + return self.wrappedCursorToOrigCursor(wrappedCursor + i) } } @@ -215,11 +308,23 @@ func (self *TextArea) atLineStart() bool { (len(self.content) > self.cursor-1 && self.content[self.cursor-1] == '\n') } +func (self *TextArea) atSoftLineStart() bool { + wrappedCursor := self.origCursorToWrappedCursor(self.cursor) + return wrappedCursor == 0 || + (len(self.wrappedContent) > wrappedCursor-1 && self.wrappedContent[wrappedCursor-1] == '\n') +} + func (self *TextArea) atLineEnd() bool { return self.atEnd() || (len(self.content) > self.cursor && self.content[self.cursor] == '\n') } +func (self *TextArea) atSoftLineEnd() bool { + wrappedCursor := self.origCursorToWrappedCursor(self.cursor) + return wrappedCursor == len(self.wrappedContent) || + (len(self.wrappedContent) > wrappedCursor+1 && self.wrappedContent[wrappedCursor+1] == '\n') +} + func (self *TextArea) BackSpaceWord() { if self.cursor == 0 { return @@ -246,16 +351,50 @@ func (self *TextArea) BackSpaceWord() { self.clipboard = string(self.content[self.cursor:right]) self.content = append(self.content[:self.cursor], self.content[right:]...) + self.autoWrapContent() } func (self *TextArea) Yank() { self.TypeString(self.clipboard) } +func origCursorToWrappedCursor(origCursor int, cursorMapping []CursorMapping) int { + prevMapping := CursorMapping{0, 0} + for _, mapping := range cursorMapping { + if origCursor < mapping.Orig { + break + } + prevMapping = mapping + } + + return origCursor + prevMapping.Wrapped - prevMapping.Orig +} + +func (self *TextArea) origCursorToWrappedCursor(origCursor int) int { + return origCursorToWrappedCursor(origCursor, self.cursorMapping) +} + +func wrappedCursorToOrigCursor(wrappedCursor int, cursorMapping []CursorMapping) int { + prevMapping := CursorMapping{0, 0} + for _, mapping := range cursorMapping { + if wrappedCursor < mapping.Wrapped { + break + } + prevMapping = mapping + } + + return wrappedCursor + prevMapping.Orig - prevMapping.Wrapped +} + +func (self *TextArea) wrappedCursorToOrigCursor(wrappedCursor int) int { + return wrappedCursorToOrigCursor(wrappedCursor, self.cursorMapping) +} + func (self *TextArea) GetCursorXY() (int, int) { cursorX := 0 cursorY := 0 - for _, r := range self.content[0:self.cursor] { + wrappedCursor := self.origCursorToWrappedCursor(self.cursor) + for _, r := range self.wrappedContent[0:wrappedCursor] { if r == '\n' { cursorY++ cursorX = 0 @@ -278,15 +417,15 @@ func (self *TextArea) SetCursor2D(x int, y int) { } newCursor := 0 - for _, r := range self.content { + for _, r := range self.wrappedContent { if x <= 0 && y == 0 { - self.cursor = newCursor + self.cursor = self.wrappedCursorToOrigCursor(newCursor) return } if r == '\n' { if y == 0 { - self.cursor = newCursor + self.cursor = self.wrappedCursorToOrigCursor(newCursor) return } y-- @@ -304,11 +443,12 @@ func (self *TextArea) SetCursor2D(x int, y int) { return } - self.cursor = newCursor + self.cursor = self.wrappedCursorToOrigCursor(newCursor) } func (self *TextArea) Clear() { self.content = []rune{} + self.wrappedContent = []rune{} self.cursor = 0 } |