diff --git a/lib/bracket-matcher-view.coffee b/lib/bracket-matcher-view.coffee index b1acb83..0528c47 100644 --- a/lib/bracket-matcher-view.coffee +++ b/lib/bracket-matcher-view.coffee @@ -277,11 +277,16 @@ class BracketMatcherView startPosition = startRange.end endPosition = endRange.start + + startPositionExternal = startRange.start + endPositionExternal = endRange.end else if startPosition = @findAnyStartPair(@editor.getCursorBufferPosition()) + startPositionExternal = startPosition startPair = @editor.getTextInRange(Range.fromPointWithDelta(startPosition, 0, 1)) - endPosition = @findMatchingEndPair(startPosition, startPair, @matchManager.pairedCharacters[startPair]) startPosition = startPosition.traverse([0, 1]) + endPosition = @findMatchingEndPair(startPosition, startPair, @matchManager.pairedCharacters[startPair]) + endPositionExternal = endPosition.traverse([0, 1]) else if pair = @tagFinder.findStartEndTags(true) # NOTE: findEnclosingTags is not used as it has a scope check # that will fail on very long lines @@ -292,8 +297,14 @@ class BracketMatcherView startPosition = startRange.end endPosition = endRange.start + startPositionExternal = startRange.start + endPositionExternal = endRange.end + if startPosition? and endPosition? rangeToSelect = new Range(startPosition, endPosition) + if rangeToSelect.isEqual(@editor.getSelectedBufferRange()) + # Expand selection + rangeToSelect = new Range(startPositionExternal, endPositionExternal) @editor.setSelectedBufferRange(rangeToSelect) # Insert at the current cursor position a closing tag if there exists an diff --git a/lib/tag-finder.coffee b/lib/tag-finder.coffee index 29378c9..be865b2 100644 --- a/lib/tag-finder.coffee +++ b/lib/tag-finder.coffee @@ -27,7 +27,7 @@ class TagFinder # 4. Attributes (ids, classes, etc. - optional) # 5. Tag suffix # 6. Self-closing tag (optional) - @tagPattern = /(<(\/)?)(.+?)(\s+.*?)?((\/)?>|$)/ + @tagPattern = /(<(\/)?)(.+?)(\s+.*?)?((\/)?>|$)/g @wordRegex = /.*?(>|$)/ patternForTagName: (tagName) -> @@ -122,12 +122,37 @@ class TagFinder findStartEndTags: (fullRange=false) -> ranges = null - endPosition = @editor.getLastCursor().getCurrentWordBufferRange({@wordRegex}).end + unpairedCount = 0 + endPosition = @editor.getCursorBufferPosition() + {scopes} = @editor.scopeDescriptorForBufferPosition(endPosition) + for scope in scopes + if scope.startsWith('meta.tag') + endPosition = @editor.getLastCursor().getCurrentWordBufferRange({wordRegex: /(.|\s)*?>/}).end + break + @editor.backwardsScanInBufferRange @tagPattern, [[0, 0], endPosition], ({match, range, stop}) => - stop() + return if @isRangeCommented(range) [entireMatch, prefix, isClosingTag, tagName, attributes, suffix, isSelfClosingTag] = match + if isSelfClosingTag or SelfClosingTags.includes(tagName) + if range.containsPoint(@editor.getCursorBufferPosition()) and not range.isEqual(@editor.getSelectedBufferRange()) + stop() + else + return + else if isClosingTag + if range.start.isEqual(@editor.getCursorBufferPosition()) or range.containsPoint(@editor.getCursorBufferPosition(), true) + return + + unpairedCount++ + return + else + unpairedCount-- + if unpairedCount < 0 + stop() + else + return + startRange = range unless fullRange if range.start.row is range.end.row @@ -138,7 +163,7 @@ class TagFinder else startRange = Range.fromObject([range.start.translate([0, prefix.length]), [range.start.row, Infinity]]) - if isSelfClosingTag + if isSelfClosingTag or SelfClosingTags.includes(tagName) endRange = startRange else if isClosingTag endRange = @findStartTag(tagName, startRange.start, fullRange) @@ -148,6 +173,33 @@ class TagFinder ranges = {startRange, endRange} if startRange? and endRange? ranges + findCurrentTags: -> + ranges = null + endPosition = @editor.getLastCursor().getCurrentWordBufferRange({@wordRegex}).end + @editor.backwardsScanInBufferRange @tagPattern, [[0, 0], endPosition], ({match, range, stop}) => + stop() + + [entireMatch, prefix, isClosingTag, tagName, attributes, suffix, isSelfClosingTag] = match + + startRange = range + if range.start.row is range.end.row + # Move the start past the initial < + startRange.start = startRange.start.translate([0, prefix.length]) + # End right after the tag name + startRange.end = startRange.start.translate([0, tagName.length]) + else + startRange = Range.fromObject([range.start.translate([0, prefix.length]), [range.start.row, Infinity]]) + + if isSelfClosingTag or SelfClosingTags.includes(tagName) + endRange = startRange + else if isClosingTag + endRange = @findStartTag(tagName, startRange.start) + else + endRange = @findEndTag(tagName, startRange.end) + + ranges = {startRange, endRange} if startRange? and endRange? + ranges + findEnclosingTags: -> if ranges = @findStartEndTags() if @isTagRange(ranges.startRange) and @isTagRange(ranges.endRange) @@ -156,7 +208,7 @@ class TagFinder null findMatchingTags: -> - @findStartEndTags() if @isCursorOnTag() + @findCurrentTags() if @isCursorOnTag() # Parses a fragment of html returning the stack (i.e., an array) of open tags #