Add selections

This commit is contained in:
EnumDev 2025-06-08 20:01:27 +03:00
parent 1620b6c2b9
commit 8f85e0991a
3 changed files with 195 additions and 4 deletions

View File

@ -12,11 +12,17 @@ type Buffer struct {
Name string
Contents string
CursorPos int
Selection *Selection
canSave bool
filename string
}
type Selection struct {
selectionStart int
selectionEnd int
}
var Buffers = make(map[int]*Buffer)
var LastBufferId int
@ -54,6 +60,25 @@ func (buffer *Buffer) Save() error {
return nil
}
func (buffer *Buffer) GetSelectedText() string {
if buffer.Selection == nil {
return ""
}
if len(buffer.Contents) == 0 {
return ""
}
start := buffer.Selection.selectionStart
end := buffer.Selection.selectionEnd
if start <= end {
return buffer.Contents[buffer.Selection.selectionStart : buffer.Selection.selectionEnd+1]
} else {
return buffer.Contents[buffer.Selection.selectionEnd : buffer.Selection.selectionStart+1]
}
}
func GetOpenFileBuffer(filename string) *Buffer {
// Replace tilde with home directory
if filename != "~" && strings.HasPrefix(filename, "~/") {

View File

@ -29,4 +29,5 @@ func main() {
for window.screen != nil {
window.Draw()
}
}

View File

@ -26,6 +26,8 @@ type Window struct {
screen tcell.Screen
}
var mouseHeld = false
func CreateWindow() (*Window, error) {
window := Window{
ShowTopMenu: true,
@ -80,7 +82,10 @@ func (window *Window) drawCurrentBuffer() {
width, _ := window.screen.Size()
for _, r := range []rune(buffer.Contents) {
normalStyle := tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.Color234)
selectedStyle := tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.Color243)
for i, r := range []rune(buffer.Contents) {
if x >= width || r == '\n' {
x = 0
if window.ShowLineIndex {
@ -89,7 +94,13 @@ func (window *Window) drawCurrentBuffer() {
y++
}
window.screen.SetContent(x, y, r, nil, tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.Color234))
if buffer.Selection != nil && buffer.Selection.selectionEnd >= buffer.Selection.selectionStart && i >= buffer.Selection.selectionStart && i <= buffer.Selection.selectionEnd {
window.screen.SetContent(x, y, r, nil, selectedStyle)
} else if buffer.Selection != nil && i <= buffer.Selection.selectionStart && i >= buffer.Selection.selectionEnd {
window.screen.SetContent(x, y, r, nil, selectedStyle)
} else {
window.screen.SetContent(x, y, r, nil, normalStyle)
}
if r != '\n' {
x++
@ -156,17 +167,75 @@ func (window *Window) Draw() {
func (window *Window) input(ev *tcell.EventKey) {
if ev.Key() == tcell.KeyRight { // Navigation Keys
if window.CursorMode == CursorModeBuffer {
// Add to selection
if ev.Modifiers() == tcell.ModShift {
if window.CurrentBuffer.Selection == nil {
window.CurrentBuffer.Selection = &Selection{
selectionStart: window.CurrentBuffer.CursorPos,
selectionEnd: window.CurrentBuffer.CursorPos,
}
return
} else {
window.CurrentBuffer.Selection.selectionEnd = window.CurrentBuffer.CursorPos + 1
}
// Prevent selecting dummy character at the end of the buffer
if window.CurrentBuffer.Selection.selectionEnd >= len(window.CurrentBuffer.Contents) {
window.CurrentBuffer.Selection.selectionEnd = len(window.CurrentBuffer.Contents) - 1
}
} else if window.CurrentBuffer.Selection != nil {
// Unset selection
window.CurrentBuffer.Selection = nil
return
}
// Move cursor
window.SetCursorPos(window.CurrentBuffer.CursorPos + 1)
}
} else if ev.Key() == tcell.KeyLeft {
if window.CursorMode == CursorModeBuffer {
// Add to selection
if ev.Modifiers() == tcell.ModShift {
if window.CurrentBuffer.Selection == nil {
window.CurrentBuffer.Selection = &Selection{
selectionStart: window.CurrentBuffer.CursorPos,
selectionEnd: window.CurrentBuffer.CursorPos,
}
return
} else {
window.CurrentBuffer.Selection.selectionEnd = window.CurrentBuffer.CursorPos - 1
}
} else if window.CurrentBuffer.Selection != nil {
// Unset selection
window.CurrentBuffer.Selection = nil
return
}
// Move cursor
window.SetCursorPos(window.CurrentBuffer.CursorPos - 1)
}
} else if ev.Key() == tcell.KeyUp {
// Move cursor
x, y := window.GetCursorPos2D()
window.SetCursorPos2D(x, y-1)
if window.CursorMode == CursorModeBuffer {
x, y := window.GetCursorPos2D()
window.SetCursorPos2D(x, y-1)
// Get original cursor position
pos := window.CurrentBuffer.CursorPos
// Add to selection
if ev.Modifiers() == tcell.ModShift {
// Add to selection
if window.CurrentBuffer.Selection == nil {
window.CurrentBuffer.Selection = &Selection{
selectionStart: window.CurrentBuffer.CursorPos,
selectionEnd: pos,
}
} else {
window.CurrentBuffer.Selection.selectionEnd = window.CurrentBuffer.CursorPos
}
} else if window.CurrentBuffer.Selection != nil {
// Unset selection
window.CurrentBuffer.Selection = nil
return
}
} else if window.CursorMode == CursorModeDropdown {
dropdown := ActiveDropdown
dropdown.Selected--
@ -190,8 +259,31 @@ func (window *Window) input(ev *tcell.EventKey) {
}
} else if ev.Key() == tcell.KeyDown {
if window.CursorMode == CursorModeBuffer {
// Get original cursor position
pos := window.CurrentBuffer.CursorPos
// Move cursor
x, y := window.GetCursorPos2D()
window.SetCursorPos2D(x, y+1)
// Add to selection
if ev.Modifiers() == tcell.ModShift {
// Add to selection
if window.CurrentBuffer.Selection == nil {
window.CurrentBuffer.Selection = &Selection{
selectionStart: pos,
selectionEnd: window.CurrentBuffer.CursorPos,
}
} else {
window.CurrentBuffer.Selection.selectionEnd = window.CurrentBuffer.CursorPos
}
// Prevent selecting dummy character at the end of the buffer
if window.CurrentBuffer.Selection.selectionEnd >= len(window.CurrentBuffer.Contents) {
window.CurrentBuffer.Selection.selectionEnd = len(window.CurrentBuffer.Contents) - 1
}
} else if window.CurrentBuffer.Selection != nil {
// Unset selection
window.CurrentBuffer.Selection = nil
return
}
} else if window.CursorMode == CursorModeDropdown {
dropdown := ActiveDropdown
dropdown.Selected++
@ -337,8 +429,36 @@ func (window *Window) mouseInput(ev *tcell.EventMouse) {
// Ensure click was in buffer area
x1, y1, x2, y2 := window.GetTextAreaDimensions()
if mouseX >= x1 && mouseY >= y1 && mouseX <= x2 && mouseY <= y2 {
if mouseHeld {
// Add to selection
if window.CurrentBuffer.Selection == nil {
window.CurrentBuffer.Selection = &Selection{
selectionStart: window.CurrentBuffer.CursorPos,
selectionEnd: window.CursorPos2DToCursorPos(bufferMouseX, bufferMouseY),
}
return
} else {
window.CurrentBuffer.Selection.selectionEnd = window.CursorPos2DToCursorPos(bufferMouseX, bufferMouseY)
}
// Prevent selecting dummy character at the end of the buffer
if window.CurrentBuffer.Selection.selectionEnd >= len(window.CurrentBuffer.Contents) {
window.CurrentBuffer.Selection.selectionEnd = len(window.CurrentBuffer.Contents) - 1
}
} else {
// Clear selection
if window.CurrentBuffer.Selection != nil {
window.CurrentBuffer.Selection = nil
}
}
// Move cursor
window.SetCursorPos2D(bufferMouseX, bufferMouseY)
}
mouseHeld = true
} else if ev.Buttons() == tcell.ButtonNone {
if mouseHeld {
mouseHeld = false
}
}
}
@ -362,6 +482,51 @@ func (window *Window) GetTextAreaDimensions() (int, int, int, int) {
return x1, y1, x2, y2
}
func (window *Window) CursorPos2DToCursorPos(x, y int) int {
// Ensure x and y are positive
x = max(x, 0)
y = max(y, 0)
// Set cursor position to 0 buffer is empty
if len(window.CurrentBuffer.Contents) == 0 {
return 0
}
// Create line slice from buffer contents
lines := make([]struct {
charIndex int
str string
}, 0)
var str string
for i, char := range window.CurrentBuffer.Contents {
str += string(char)
if char == '\n' || i == len(window.CurrentBuffer.Contents)-1 {
lines = append(lines, struct {
charIndex int
str string
}{charIndex: i - len(str) + 1, str: str})
str = ""
}
}
// Append extra character or line
if window.CurrentBuffer.Contents[len(window.CurrentBuffer.Contents)-1] == '\n' {
lines = append(lines, struct {
charIndex int
str string
}{charIndex: len(window.CurrentBuffer.Contents), str: " "})
} else {
lines[len(lines)-1].str += " "
}
// Limit x and y
y = min(y, len(lines)-1)
x = min(x, len(lines[y].str)-1)
return lines[y].charIndex + x
}
func (window *Window) AbsolutePosToBufferArea(x, y int) (int, int) {
x1, y1, _, _ := window.GetTextAreaDimensions()