@@ -1140,50 +1140,137 @@ var BracePairs = [][2]rune{
11401140 {'[' , ']' },
11411141}
11421142
1143- func (b * Buffer ) findMatchingBrace (braceType [2 ]rune , start Loc , char rune ) (Loc , bool ) {
1144- var i int
1145- if char == braceType [0 ] {
1146- for y := start .Y ; y < b .LinesNum (); y ++ {
1147- l := []rune (string (b .LineBytes (y )))
1148- xInit := 0
1149- if y == start .Y {
1150- xInit = start .X
1151- }
1152- for x := xInit ; x < len (l ); x ++ {
1153- r := l [x ]
1154- if r == braceType [0 ] {
1155- i ++
1156- } else if r == braceType [1 ] {
1157- i --
1158- if i == 0 {
1159- return Loc {x , y }, true
1160- }
1143+ func (b * Buffer ) findOpeningBrace (braceType [2 ]rune , start Loc ) (Loc , bool ) {
1144+ // Bound guard
1145+ start = clamp (start , b .LineArray )
1146+ if len (b .lines ) == 0 {
1147+ return start , false
1148+ }
1149+
1150+ i := 1
1151+ // If we are on a closing brace, let the counter be incremented below when we traverse
1152+ curLine := []rune (string (b .LineBytes (start .Y )))
1153+ if start .X >= 0 && start .X < len (curLine ) {
1154+ startChar := curLine [start .X ]
1155+ if startChar == braceType [1 ] {
1156+ i = 0
1157+ }
1158+ }
1159+
1160+ for y := start .Y ; y >= 0 ; y -- {
1161+ l := []rune (string (b .lines [y ].data ))
1162+ xInit := len (l ) - 1
1163+ if y == start .Y && start .X < len (curLine ) {
1164+ xInit = start .X
1165+ }
1166+ for x := xInit ; x >= 0 ; x -- {
1167+ r := l [x ]
1168+ if r == braceType [1 ] {
1169+ i ++
1170+ } else if r == braceType [0 ] {
1171+ i --
1172+ if i == 0 {
1173+ return Loc {x , y }, true
11611174 }
11621175 }
11631176 }
1164- } else if char == braceType [1 ] {
1165- for y := start .Y ; y >= 0 ; y -- {
1166- l := []rune (string (b .lines [y ].data ))
1167- xInit := len (l ) - 1
1168- if y == start .Y {
1169- xInit = start .X
1177+ }
1178+ return start , false
1179+ }
1180+
1181+ // Returns the opening brace in current brace scope starting at the start location and a boolean
1182+ // indicating if an opening brace is found
1183+ func (b * Buffer ) FindOpeningBrace (start Loc ) (Loc , bool ) {
1184+ currentDist := - 1
1185+ currentMb := Loc {- 1 , - 1 }
1186+ for _ , bp := range BracePairs {
1187+ mb , found := b .findOpeningBrace (bp , start )
1188+ if found {
1189+ dist := DiffLA (start , mb , b .LineArray )
1190+ if currentDist < 0 || dist < currentDist {
1191+ currentMb = mb
1192+ currentDist = dist
11701193 }
1171- for x := xInit ; x >= 0 ; x -- {
1172- r := l [x ]
1173- if r == braceType [1 ] {
1174- i ++
1175- } else if r == braceType [0 ] {
1176- i --
1177- if i == 0 {
1178- return Loc {x , y }, true
1179- }
1194+ }
1195+ }
1196+
1197+ if currentDist == - 1 {
1198+ return start , false
1199+ } else {
1200+ return currentMb , true
1201+ }
1202+ }
1203+
1204+ func (b * Buffer ) findClosingBrace (braceType [2 ]rune , start Loc ) (Loc , bool ) {
1205+ // Bound guard
1206+ start = clamp (start , b .LineArray )
1207+ if len (b .lines ) == 0 {
1208+ return start , false
1209+ }
1210+
1211+ i := 1
1212+ // If we are on an opening brace, let the counter be incremented below when we traverse
1213+ curLine := []rune (string (b .LineBytes (start .Y )))
1214+ if start .X >= 0 && start .X < len (curLine ) {
1215+ startChar := curLine [start .X ]
1216+ if startChar == braceType [0 ] {
1217+ i = 0
1218+ }
1219+ }
1220+
1221+ for y := start .Y ; y < b .LinesNum (); y ++ {
1222+ l := []rune (string (b .LineBytes (y )))
1223+ xInit := 0
1224+ if y == start .Y && start .X >= 0 {
1225+ xInit = start .X
1226+ }
1227+ for x := xInit ; x < len (l ); x ++ {
1228+ r := l [x ]
1229+ if r == braceType [0 ] {
1230+ i ++
1231+ } else if r == braceType [1 ] {
1232+ i --
1233+ if i == 0 {
1234+ return Loc {x , y }, true
11801235 }
11811236 }
11821237 }
11831238 }
11841239 return start , false
11851240}
11861241
1242+ // Returns the closing brace in current brace scope starting at the start location and a boolean
1243+ // indicating if an closing brace is found
1244+ func (b * Buffer ) FindClosingBrace (start Loc ) (Loc , bool ) {
1245+ currentDist := - 1
1246+ currentMb := Loc {- 1 , - 1 }
1247+ for _ , bp := range BracePairs {
1248+ mb , found := b .findClosingBrace (bp , start )
1249+ if found {
1250+ dist := DiffLA (start , mb , b .LineArray )
1251+ if currentDist < 0 || dist < currentDist {
1252+ currentMb = mb
1253+ currentDist = dist
1254+ }
1255+ }
1256+ }
1257+
1258+ if currentDist == - 1 {
1259+ return start , false
1260+ } else {
1261+ return currentMb , true
1262+ }
1263+ }
1264+
1265+ func (b * Buffer ) findMatchingBrace (braceType [2 ]rune , start Loc , char rune ) (Loc , bool ) {
1266+ if char == braceType [0 ] {
1267+ return b .findClosingBrace (braceType , start )
1268+ } else if char == braceType [1 ] {
1269+ return b .findOpeningBrace (braceType , start )
1270+ }
1271+ return start , false
1272+ }
1273+
11871274// If there is a brace character (for example '{' or ']') at the given start location,
11881275// FindMatchingBrace returns the location of the matching brace for it (for example '}'
11891276// or '['). The second returned value is true if there was no matching brace found
0 commit comments