mirror of
https://github.com/zyedidia/micro.git
synced 2024-09-17 15:07:41 +03:00
Merge pull request #3224 from JoeKar/fix/line-synchronization
buffer: Add proper lock mechanism to lock the full `LineArray` instead of single lines
This commit is contained in:
commit
467c71dbb8
@ -1180,7 +1180,11 @@ func (b *Buffer) Retab() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l = bytes.TrimLeft(l, " \t")
|
l = bytes.TrimLeft(l, " \t")
|
||||||
|
|
||||||
|
b.Lock()
|
||||||
b.lines[i].data = append(ws, l...)
|
b.lines[i].data = append(ws, l...)
|
||||||
|
b.Unlock()
|
||||||
|
|
||||||
b.MarkModified(i, i)
|
b.MarkModified(i, i)
|
||||||
dirty = true
|
dirty = true
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,7 @@ type operation struct {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ulua.L = lua.NewState()
|
ulua.L = lua.NewState()
|
||||||
// TODO: uncomment InitRuntimeFiles once we fix races between syntax
|
config.InitRuntimeFiles(false)
|
||||||
// highlighting and buffer editing.
|
|
||||||
// config.InitRuntimeFiles(false)
|
|
||||||
config.InitGlobalSettings()
|
config.InitGlobalSettings()
|
||||||
config.GlobalSettings["backup"] = false
|
config.GlobalSettings["backup"] = false
|
||||||
config.GlobalSettings["fastdirty"] = true
|
config.GlobalSettings["fastdirty"] = true
|
||||||
|
@ -48,7 +48,6 @@ type Line struct {
|
|||||||
|
|
||||||
state highlight.State
|
state highlight.State
|
||||||
match highlight.LineMatch
|
match highlight.LineMatch
|
||||||
rehighlight bool
|
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
|
||||||
// The search states for the line, used for highlighting of search matches,
|
// The search states for the line, used for highlighting of search matches,
|
||||||
@ -75,6 +74,7 @@ type LineArray struct {
|
|||||||
lines []Line
|
lines []Line
|
||||||
Endings FileFormat
|
Endings FileFormat
|
||||||
initsize uint64
|
initsize uint64
|
||||||
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append efficiently appends lines together
|
// Append efficiently appends lines together
|
||||||
@ -150,7 +150,6 @@ func NewLineArray(size uint64, endings FileFormat, reader io.Reader) *LineArray
|
|||||||
data: data,
|
data: data,
|
||||||
state: nil,
|
state: nil,
|
||||||
match: nil,
|
match: nil,
|
||||||
rehighlight: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Last line was read
|
// Last line was read
|
||||||
@ -160,7 +159,6 @@ func NewLineArray(size uint64, endings FileFormat, reader io.Reader) *LineArray
|
|||||||
data: data[:dlen-1],
|
data: data[:dlen-1],
|
||||||
state: nil,
|
state: nil,
|
||||||
match: nil,
|
match: nil,
|
||||||
rehighlight: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
n++
|
n++
|
||||||
@ -193,19 +191,20 @@ func (la *LineArray) newlineBelow(y int) {
|
|||||||
data: []byte{' '},
|
data: []byte{' '},
|
||||||
state: nil,
|
state: nil,
|
||||||
match: nil,
|
match: nil,
|
||||||
rehighlight: false,
|
|
||||||
})
|
})
|
||||||
copy(la.lines[y+2:], la.lines[y+1:])
|
copy(la.lines[y+2:], la.lines[y+1:])
|
||||||
la.lines[y+1] = Line{
|
la.lines[y+1] = Line{
|
||||||
data: []byte{},
|
data: []byte{},
|
||||||
state: la.lines[y].state,
|
state: la.lines[y].state,
|
||||||
match: nil,
|
match: nil,
|
||||||
rehighlight: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserts a byte array at a given location
|
// Inserts a byte array at a given location
|
||||||
func (la *LineArray) insert(pos Loc, value []byte) {
|
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
|
x, y := runeToByteIndex(pos.X, la.lines[pos.Y].data), pos.Y
|
||||||
for i := 0; i < len(value); i++ {
|
for i := 0; i < len(value); i++ {
|
||||||
if value[i] == '\n' || (value[i] == '\r' && i < len(value)-1 && value[i+1] == '\n') {
|
if value[i] == '\n' || (value[i] == '\r' && i < len(value)-1 && value[i+1] == '\n') {
|
||||||
@ -233,24 +232,26 @@ func (la *LineArray) insertByte(pos Loc, value byte) {
|
|||||||
|
|
||||||
// joinLines joins the two lines a and b
|
// joinLines joins the two lines a and b
|
||||||
func (la *LineArray) joinLines(a, b int) {
|
func (la *LineArray) joinLines(a, b int) {
|
||||||
la.insert(Loc{len(la.lines[a].data), a}, la.lines[b].data)
|
la.lines[a].data = append(la.lines[a].data, la.lines[b].data...)
|
||||||
la.deleteLine(b)
|
la.deleteLine(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// split splits a line at a given position
|
// split splits a line at a given position
|
||||||
func (la *LineArray) split(pos Loc) {
|
func (la *LineArray) split(pos Loc) {
|
||||||
la.newlineBelow(pos.Y)
|
la.newlineBelow(pos.Y)
|
||||||
la.insert(Loc{0, pos.Y + 1}, la.lines[pos.Y].data[pos.X:])
|
la.lines[pos.Y+1].data = append(la.lines[pos.Y+1].data, la.lines[pos.Y].data[pos.X:]...)
|
||||||
la.lines[pos.Y+1].state = la.lines[pos.Y].state
|
la.lines[pos.Y+1].state = la.lines[pos.Y].state
|
||||||
la.lines[pos.Y].state = nil
|
la.lines[pos.Y].state = nil
|
||||||
la.lines[pos.Y].match = nil
|
la.lines[pos.Y].match = nil
|
||||||
la.lines[pos.Y+1].match = nil
|
la.lines[pos.Y+1].match = nil
|
||||||
la.lines[pos.Y].rehighlight = true
|
|
||||||
la.deleteToEnd(Loc{pos.X, pos.Y})
|
la.deleteToEnd(Loc{pos.X, pos.Y})
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes from start to end
|
// removes from start to end
|
||||||
func (la *LineArray) remove(start, end Loc) []byte {
|
func (la *LineArray) remove(start, end Loc) []byte {
|
||||||
|
la.lock.Lock()
|
||||||
|
defer la.lock.Unlock()
|
||||||
|
|
||||||
sub := la.Substr(start, end)
|
sub := la.Substr(start, end)
|
||||||
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
|
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
|
||||||
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
|
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
|
||||||
@ -327,11 +328,11 @@ func (la *LineArray) End() Loc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LineBytes returns line n as an array of bytes
|
// LineBytes returns line n as an array of bytes
|
||||||
func (la *LineArray) LineBytes(n int) []byte {
|
func (la *LineArray) LineBytes(lineN int) []byte {
|
||||||
if n >= len(la.lines) || n < 0 {
|
if lineN >= len(la.lines) || lineN < 0 {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
return la.lines[n].data
|
return la.lines[lineN].data
|
||||||
}
|
}
|
||||||
|
|
||||||
// State gets the highlight state for the given line number
|
// State gets the highlight state for the given line number
|
||||||
@ -362,16 +363,14 @@ func (la *LineArray) Match(lineN int) highlight.LineMatch {
|
|||||||
return la.lines[lineN].match
|
return la.lines[lineN].match
|
||||||
}
|
}
|
||||||
|
|
||||||
func (la *LineArray) Rehighlight(lineN int) bool {
|
// Locks the whole LineArray
|
||||||
la.lines[lineN].lock.Lock()
|
func (la *LineArray) Lock() {
|
||||||
defer la.lines[lineN].lock.Unlock()
|
la.lock.Lock()
|
||||||
return la.lines[lineN].rehighlight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (la *LineArray) SetRehighlight(lineN int, on bool) {
|
// Unlocks the whole LineArray
|
||||||
la.lines[lineN].lock.Lock()
|
func (la *LineArray) Unlock() {
|
||||||
defer la.lines[lineN].lock.Unlock()
|
la.lock.Unlock()
|
||||||
la.lines[lineN].rehighlight = on
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchMatch returns true if the location `pos` is within a match
|
// SearchMatch returns true if the location `pos` is within a match
|
||||||
|
@ -77,6 +77,8 @@ type LineStates interface {
|
|||||||
State(lineN int) State
|
State(lineN int) State
|
||||||
SetState(lineN int, s State)
|
SetState(lineN int, s State)
|
||||||
SetMatch(lineN int, m LineMatch)
|
SetMatch(lineN int, m LineMatch)
|
||||||
|
Lock()
|
||||||
|
Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Highlighter contains the information needed to highlight a string
|
// A Highlighter contains the information needed to highlight a string
|
||||||
@ -303,7 +305,13 @@ func (h *Highlighter) HighlightString(input string) []LineMatch {
|
|||||||
|
|
||||||
// HighlightStates correctly sets all states for the buffer
|
// HighlightStates correctly sets all states for the buffer
|
||||||
func (h *Highlighter) HighlightStates(input LineStates) {
|
func (h *Highlighter) HighlightStates(input LineStates) {
|
||||||
for i := 0; i < input.LinesNum(); i++ {
|
for i := 0; ; i++ {
|
||||||
|
input.Lock()
|
||||||
|
if i >= input.LinesNum() {
|
||||||
|
input.Unlock()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
line := input.LineBytes(i)
|
line := input.LineBytes(i)
|
||||||
// highlights := make(LineMatch)
|
// highlights := make(LineMatch)
|
||||||
|
|
||||||
@ -316,6 +324,7 @@ func (h *Highlighter) HighlightStates(input LineStates) {
|
|||||||
curState := h.lastRegion
|
curState := h.lastRegion
|
||||||
|
|
||||||
input.SetState(i, curState)
|
input.SetState(i, curState)
|
||||||
|
input.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +333,9 @@ func (h *Highlighter) HighlightStates(input LineStates) {
|
|||||||
// This assumes that all the states are set correctly
|
// This assumes that all the states are set correctly
|
||||||
func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int) {
|
func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int) {
|
||||||
for i := startline; i <= endline; i++ {
|
for i := startline; i <= endline; i++ {
|
||||||
|
input.Lock()
|
||||||
if i >= input.LinesNum() {
|
if i >= input.LinesNum() {
|
||||||
|
input.Unlock()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,6 +350,7 @@ func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
input.SetMatch(i, match)
|
input.SetMatch(i, match)
|
||||||
|
input.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,9 +362,17 @@ func (h *Highlighter) ReHighlightStates(input LineStates, startline int) int {
|
|||||||
|
|
||||||
h.lastRegion = nil
|
h.lastRegion = nil
|
||||||
if startline > 0 {
|
if startline > 0 {
|
||||||
|
input.Lock()
|
||||||
h.lastRegion = input.State(startline - 1)
|
h.lastRegion = input.State(startline - 1)
|
||||||
|
input.Unlock()
|
||||||
}
|
}
|
||||||
for i := startline; i < input.LinesNum(); i++ {
|
for i := startline; ; i++ {
|
||||||
|
input.Lock()
|
||||||
|
if i >= input.LinesNum() {
|
||||||
|
input.Unlock()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
line := input.LineBytes(i)
|
line := input.LineBytes(i)
|
||||||
// highlights := make(LineMatch)
|
// highlights := make(LineMatch)
|
||||||
|
|
||||||
@ -366,6 +386,7 @@ func (h *Highlighter) ReHighlightStates(input LineStates, startline int) int {
|
|||||||
lastState := input.State(i)
|
lastState := input.State(i)
|
||||||
|
|
||||||
input.SetState(i, curState)
|
input.SetState(i, curState)
|
||||||
|
input.Unlock()
|
||||||
|
|
||||||
if curState == lastState {
|
if curState == lastState {
|
||||||
return i
|
return i
|
||||||
@ -377,6 +398,9 @@ func (h *Highlighter) ReHighlightStates(input LineStates, startline int) int {
|
|||||||
|
|
||||||
// ReHighlightLine will rehighlight the state and match for a single line
|
// ReHighlightLine will rehighlight the state and match for a single line
|
||||||
func (h *Highlighter) ReHighlightLine(input LineStates, lineN int) {
|
func (h *Highlighter) ReHighlightLine(input LineStates, lineN int) {
|
||||||
|
input.Lock()
|
||||||
|
defer input.Unlock()
|
||||||
|
|
||||||
line := input.LineBytes(lineN)
|
line := input.LineBytes(lineN)
|
||||||
highlights := make(LineMatch)
|
highlights := make(LineMatch)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user