diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 35e650fd..54fc266f 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -1180,7 +1180,11 @@ func (b *Buffer) Retab() { } l = bytes.TrimLeft(l, " \t") + + b.Lock() b.lines[i].data = append(ws, l...) + b.Unlock() + b.MarkModified(i, i) dirty = true } diff --git a/internal/buffer/line_array.go b/internal/buffer/line_array.go index 7323dc1d..9897e720 100644 --- a/internal/buffer/line_array.go +++ b/internal/buffer/line_array.go @@ -75,6 +75,7 @@ type LineArray struct { lines []Line Endings FileFormat initsize uint64 + lock sync.Mutex } // Append efficiently appends lines together @@ -206,6 +207,9 @@ func (la *LineArray) newlineBelow(y int) { // Inserts a byte array at a given location func (la *LineArray) insert(pos Loc, value []byte) { + la.lock.Lock() + defer la.lock.Unlock() + x, y := runeToByteIndex(pos.X, la.lines[pos.Y].data), pos.Y for i := 0; i < len(value); i++ { if value[i] == '\n' || (value[i] == '\r' && i < len(value)-1 && value[i+1] == '\n') { @@ -251,6 +255,9 @@ func (la *LineArray) split(pos Loc) { // removes from start to end func (la *LineArray) remove(start, end Loc) []byte { + la.lock.Lock() + defer la.lock.Unlock() + sub := la.Substr(start, end) startX := runeToByteIndex(start.X, la.lines[start.Y].data) endX := runeToByteIndex(end.X, la.lines[end.Y].data) @@ -374,6 +381,16 @@ func (la *LineArray) SetRehighlight(lineN int, on bool) { la.lines[lineN].rehighlight = on } +// Locks the whole LineArray +func (la *LineArray) Lock() { + la.lock.Lock() +} + +// Unlocks the whole LineArray +func (la *LineArray) Unlock() { + la.lock.Unlock() +} + // SearchMatch returns true if the location `pos` is within a match // of the last search for the buffer `b`. // It is used for efficient highlighting of search matches (separately