Fix search not working without a closing delimiter
This commit is contained in:
parent
f22ae13cfd
commit
0f91ab5ae0
3 changed files with 83 additions and 14 deletions
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue