@@ -1173,50 +1173,137 @@ var BracePairs = [][2]rune{
11731173 {'[' , ']' },
11741174}
11751175
1176- func (b * Buffer ) findMatchingBrace (braceType [2 ]rune , start Loc , char rune ) (Loc , bool ) {
1177- var i int
1178- if char == braceType [0 ] {
1179- for y := start .Y ; y < b .LinesNum (); y ++ {
1180- l := []rune (string (b .LineBytes (y )))
1181- xInit := 0
1182- if y == start .Y {
1183- xInit = start .X
1184- }
1185- for x := xInit ; x < len (l ); x ++ {
1186- r := l [x ]
1187- if r == braceType [0 ] {
1188- i ++
1189- } else if r == braceType [1 ] {
1190- i --
1191- if i == 0 {
1192- return Loc {x , y }, true
1193- }
1176+ func (b * Buffer ) findOpeningBrace (braceType [2 ]rune , start Loc ) (Loc , bool ) {
1177+ // Bound guard
1178+ start = clamp (start , b .LineArray )
1179+ if len (b .lines ) == 0 {
1180+ return start , false
1181+ }
1182+
1183+ i := 1
1184+ // If we are on a closing brace, let the counter be incremented below when we traverse
1185+ curLine := []rune (string (b .LineBytes (start .Y )))
1186+ if start .X >= 0 && start .X < len (curLine ) {
1187+ startChar := curLine [start .X ]
1188+ if startChar == braceType [1 ] {
1189+ i = 0
1190+ }
1191+ }
1192+
1193+ for y := start .Y ; y >= 0 ; y -- {
1194+ l := []rune (string (b .lines [y ].data ))
1195+ xInit := len (l ) - 1
1196+ if y == start .Y && start .X < len (curLine ) {
1197+ xInit = start .X
1198+ }
1199+ for x := xInit ; x >= 0 ; x -- {
1200+ r := l [x ]
1201+ if r == braceType [1 ] {
1202+ i ++
1203+ } else if r == braceType [0 ] {
1204+ i --
1205+ if i == 0 {
1206+ return Loc {x , y }, true
11941207 }
11951208 }
11961209 }
1197- } else if char == braceType [1 ] {
1198- for y := start .Y ; y >= 0 ; y -- {
1199- l := []rune (string (b .lines [y ].data ))
1200- xInit := len (l ) - 1
1201- if y == start .Y {
1202- xInit = start .X
1210+ }
1211+ return start , false
1212+ }
1213+
1214+ // Returns the opening brace in current brace scope starting at the start location and a boolean
1215+ // indicating if an opening brace is found
1216+ func (b * Buffer ) FindOpeningBrace (start Loc ) (Loc , bool ) {
1217+ currentDist := - 1
1218+ currentMb := Loc {- 1 , - 1 }
1219+ for _ , bp := range BracePairs {
1220+ mb , found := b .findOpeningBrace (bp , start )
1221+ if found {
1222+ dist := DiffLA (start , mb , b .LineArray )
1223+ if currentDist < 0 || dist < currentDist {
1224+ currentMb = mb
1225+ currentDist = dist
12031226 }
1204- for x := xInit ; x >= 0 ; x -- {
1205- r := l [x ]
1206- if r == braceType [1 ] {
1207- i ++
1208- } else if r == braceType [0 ] {
1209- i --
1210- if i == 0 {
1211- return Loc {x , y }, true
1212- }
1227+ }
1228+ }
1229+
1230+ if currentDist == - 1 {
1231+ return start , false
1232+ } else {
1233+ return currentMb , true
1234+ }
1235+ }
1236+
1237+ func (b * Buffer ) findClosingBrace (braceType [2 ]rune , start Loc ) (Loc , bool ) {
1238+ // Bound guard
1239+ start = clamp (start , b .LineArray )
1240+ if len (b .lines ) == 0 {
1241+ return start , false
1242+ }
1243+
1244+ i := 1
1245+ // If we are on an opening brace, let the counter be incremented below when we traverse
1246+ curLine := []rune (string (b .LineBytes (start .Y )))
1247+ if start .X >= 0 && start .X < len (curLine ) {
1248+ startChar := curLine [start .X ]
1249+ if startChar == braceType [0 ] {
1250+ i = 0
1251+ }
1252+ }
1253+
1254+ for y := start .Y ; y < b .LinesNum (); y ++ {
1255+ l := []rune (string (b .LineBytes (y )))
1256+ xInit := 0
1257+ if y == start .Y && start .X >= 0 {
1258+ xInit = start .X
1259+ }
1260+ for x := xInit ; x < len (l ); x ++ {
1261+ r := l [x ]
1262+ if r == braceType [0 ] {
1263+ i ++
1264+ } else if r == braceType [1 ] {
1265+ i --
1266+ if i == 0 {
1267+ return Loc {x , y }, true
12131268 }
12141269 }
12151270 }
12161271 }
12171272 return start , false
12181273}
12191274
1275+ // Returns the closing brace in current brace scope starting at the start location and a boolean
1276+ // indicating if an closing brace is found
1277+ func (b * Buffer ) FindClosingBrace (start Loc ) (Loc , bool ) {
1278+ currentDist := - 1
1279+ currentMb := Loc {- 1 , - 1 }
1280+ for _ , bp := range BracePairs {
1281+ mb , found := b .findClosingBrace (bp , start )
1282+ if found {
1283+ dist := DiffLA (start , mb , b .LineArray )
1284+ if currentDist < 0 || dist < currentDist {
1285+ currentMb = mb
1286+ currentDist = dist
1287+ }
1288+ }
1289+ }
1290+
1291+ if currentDist == - 1 {
1292+ return start , false
1293+ } else {
1294+ return currentMb , true
1295+ }
1296+ }
1297+
1298+ func (b * Buffer ) findMatchingBrace (braceType [2 ]rune , start Loc , char rune ) (Loc , bool ) {
1299+ if char == braceType [0 ] {
1300+ return b .findClosingBrace (braceType , start )
1301+ } else if char == braceType [1 ] {
1302+ return b .findOpeningBrace (braceType , start )
1303+ }
1304+ return start , false
1305+ }
1306+
12201307// If there is a brace character (for example '{' or ']') at the given start location,
12211308// FindMatchingBrace returns the location of the matching brace for it (for example '}'
12221309// or '['). The second returned value is true if there was no matching brace found
0 commit comments