Fix search not working without a closing delimiter

This commit is contained in:
jazzpi 2016-08-16 12:55:19 +02:00
parent f22ae13cfd
commit 0f91ab5ae0
3 changed files with 83 additions and 14 deletions

View file

@ -8,14 +8,15 @@ class Command
@selections = @exState.getSelections() @selections = @exState.getSelections()
@viewModel = new ExViewModel(@, Object.keys(@selections).length > 0) @viewModel = new ExViewModel(@, Object.keys(@selections).length > 0)
parseAddr: (str, curPos) -> parseAddr: (str, cursor) ->
row = cursor.getBufferRow()
if str is '.' if str is '.'
addr = curPos.row addr = row
else if str is '$' else if str is '$'
# Lines are 0-indexed in Atom, but 1-indexed in vim. # Lines are 0-indexed in Atom, but 1-indexed in vim.
addr = @editor.getBuffer().lines.length - 1 addr = @editor.getBuffer().lines.length - 1
else if str[0] in ["+", "-"] else if str[0] in ["+", "-"]
addr = curPos.row + @parseOffset(str) addr = row + @parseOffset(str)
else if not isNaN(str) else if not isNaN(str)
addr = parseInt(str) - 1 addr = parseInt(str) - 1
else if str[0] is "'" # Parse Mark... else if str[0] is "'" # Parse Mark...
@ -26,13 +27,21 @@ class Command
throw new CommandError("Mark #{str} not set.") throw new CommandError("Mark #{str} not set.")
addr = mark.getEndBufferPosition().row addr = mark.getEndBufferPosition().row
else if str[0] is "/" else if str[0] is "/"
addr = Find.findNextInBuffer(@editor.buffer, curPos, str[1...-1]) str = str[1...]
if str[str.length-1] is "/"
str = str[...-1]
addr = Find.scanEditor(str, @editor, cursor.getCurrentLineBufferRange().end)[0]
unless addr? unless addr?
throw new CommandError("Pattern not found: #{str[1...-1]}") throw new CommandError("Pattern not found: #{str}")
addr = addr.start.row
else if str[0] is "?" else if str[0] is "?"
addr = Find.findPreviousInBuffer(@editor.buffer, curPos, str[1...-1]) str = str[1...]
if str[str.length-1] is "?"
str = str[...-1]
addr = Find.scanEditor(str, @editor, cursor.getCurrentLineBufferRange().start, true)[0]
unless addr? unless addr?
throw new CommandError("Pattern not found: #{str[1...-1]}") throw new CommandError("Pattern not found: #{str[1...-1]}")
addr = addr.start.row
return addr return addr
@ -76,8 +85,8 @@ class Command
\$| # Last line \$| # Last line
\d+| # n-th line \d+| # n-th line
'[\[\]<>'`"^.(){}a-zA-Z]| # Marks '[\[\]<>'`"^.(){}a-zA-Z]| # Marks
/.*?[^\\]/| # Regex /.*?(?:[^\\]/|$)| # Regex
\?.*?[^\\]\?| # Backwards search \?.*?(?:[^\\]\?|$)| # Backwards search
[+-]\d* # Current line +/- a number of lines [+-]\d* # Current line +/- a number of lines
)((?:\s*[+-]\d*)*) # Line offset )((?:\s*[+-]\d*)*) # Line offset
)? )?
@ -96,7 +105,7 @@ class Command
[match, addr1, off1, addr2, off2] = cl.match(addrPattern) [match, addr1, off1, addr2, off2] = cl.match(addrPattern)
curPos = @editor.getCursorBufferPosition() cursor = @editor.getLastCursor()
# Special case: run command on selection. This can't be handled by simply # Special case: run command on selection. This can't be handled by simply
# parsing the mark since vim-mode doesn't set it (and it would be fairly # parsing the mark since vim-mode doesn't set it (and it would be fairly
@ -106,10 +115,10 @@ class Command
else else
runOverSelections = false runOverSelections = false
if addr1? if addr1?
address1 = @parseAddr(addr1, curPos) address1 = @parseAddr(addr1, cursor)
else else
# If no addr1 is given (,+3), assume it is '.' # If no addr1 is given (,+3), assume it is '.'
address1 = curPos.row address1 = cursor.getBufferRow()
if off1? if off1?
address1 += @parseOffset(off1) address1 += @parseOffset(off1)
@ -119,7 +128,7 @@ class Command
throw new CommandError('Invalid range') throw new CommandError('Invalid range')
if addr2? if addr2?
address2 = @parseAddr(addr2, curPos) address2 = @parseAddr(addr2, cursor)
if off2? if off2?
address2 += @parseOffset(off2) address2 += @parseOffset(off2)

View file

@ -1,3 +1,40 @@
_ = require 'underscore-plus'
getSearchTerm = (term, modifiers = {'g': true}) ->
escaped = false
hasc = false
hasC = false
term_ = term
term = ''
for char in term_
if char is '\\' and not escaped
escaped = true
term += char
else
if char is 'c' and escaped
hasc = true
term = term[...-1]
else if char is 'C' and escaped
hasC = true
term = term[...-1]
else if char isnt '\\'
term += char
escaped = false
if hasC
modifiers['i'] = false
if (not hasC and not term.match('[A-Z]') and \
atom.config.get("vim-mode:useSmartcaseForSearch")) or hasc
modifiers['i'] = true
modFlags = Object.keys(modifiers).filter((key) -> modifiers[key]).join('')
try
new RegExp(term, modFlags)
catch
new RegExp(_.escapeRegExp(term), modFlags)
module.exports = { module.exports = {
findInBuffer : (buffer, pattern) -> findInBuffer : (buffer, pattern) ->
found = [] found = []
@ -23,4 +60,26 @@ module.exports = {
return found[found.length - 1].start.row return found[found.length - 1].start.row
else else
return null return null
# Returns an array of ranges of all occurences of `term` in `editor`.
# The array is sorted so that the first occurences after the cursor come
# first (and the search wraps around). If `reverse` is true, the array is
# reversed so that the first occurence before the cursor comes first.
scanEditor: (term, editor, position, reverse = false) ->
[rangesBefore, rangesAfter] = [[], []]
editor.scan getSearchTerm(term), ({range}) ->
if reverse
isBefore = range.start.compare(position) < 0
else
isBefore = range.start.compare(position) <= 0
if isBefore
rangesBefore.push(range)
else
rangesAfter.push(range)
if reverse
rangesAfter.concat(rangesBefore).reverse()
else
rangesAfter.concat(rangesBefore)
} }

View file

@ -118,9 +118,10 @@ describe "the commands", ->
submitNormalModeInputText '/def' submitNormalModeInputText '/def'
expect(editor.getCursorBufferPosition()).toEqual [1, 0] expect(editor.getCursorBufferPosition()).toEqual [1, 0]
editor.setCursorBufferPosition([2, 0])
openEx() openEx()
submitNormalModeInputText '?abc' submitNormalModeInputText '?def'
expect(editor.getCursorBufferPosition()).toEqual [0, 0] expect(editor.getCursorBufferPosition()).toEqual [1, 0]
editor.setCursorBufferPosition([3, 0]) editor.setCursorBufferPosition([3, 0])
openEx() openEx()