mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-22 08:28:41 +03:00
Match $ in command regexes as end of line. Don't infinitely loop on substituting zero-width matches
This commit is contained in:
parent
7d969e145a
commit
5e89c44477
@ -11,25 +11,34 @@ describe "CommandInterpreter", ->
|
||||
interpreter = new CommandInterpreter()
|
||||
|
||||
describe "addresses", ->
|
||||
beforeEach ->
|
||||
editor.addSelectionForBufferRange([[7,0], [7,11]])
|
||||
editor.addSelectionForBufferRange([[8,0], [8,11]])
|
||||
|
||||
describe "a line address", ->
|
||||
it "selects the specified line", ->
|
||||
interpreter.eval(editor, '4')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[3, 0], [4, 0]]
|
||||
|
||||
describe "0", ->
|
||||
it "selects the zero-length string at the start of the file", ->
|
||||
interpreter.eval(editor, '0')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [0,0]]
|
||||
|
||||
interpreter.eval(editor, '0,1')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [1,0]]
|
||||
|
||||
describe "$", ->
|
||||
it "selects EOF", ->
|
||||
interpreter.eval(editor, '$')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[12,2], [12,2]]
|
||||
|
||||
interpreter.eval(editor, '1,$')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [12,2]]
|
||||
|
||||
describe ".", ->
|
||||
@ -50,32 +59,38 @@ describe "CommandInterpreter", ->
|
||||
it 'selects text matching regex after current selection', ->
|
||||
editor.getSelection().setBufferRange([[4,16], [4,20]])
|
||||
interpreter.eval(editor, '/pivot/')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[6,16], [6,21]]
|
||||
|
||||
it 'does not require the trailing slash', ->
|
||||
editor.getSelection().setBufferRange([[4,16], [4,20]])
|
||||
interpreter.eval(editor, '/pivot')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[6,16], [6,21]]
|
||||
|
||||
describe "address range", ->
|
||||
describe "when two addresses are specified", ->
|
||||
it "selects from the begining of the left address to the end of the right address", ->
|
||||
interpreter.eval(editor, '4,7')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[3, 0], [7, 0]]
|
||||
|
||||
describe "when the left address is unspecified", ->
|
||||
it "selects from the begining of buffer to the end of the right address", ->
|
||||
interpreter.eval(editor, ',7')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[0, 0], [7, 0]]
|
||||
|
||||
describe "when the right address is unspecified", ->
|
||||
it "selects from the begining of left address to the end file", ->
|
||||
interpreter.eval(editor, '4,')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[3, 0], [12, 2]]
|
||||
|
||||
describe "when the neither address is specified", ->
|
||||
it "selects the entire file", ->
|
||||
interpreter.eval(editor, ',')
|
||||
expect(editor.getSelections().length).toBe 1
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[0, 0], [12, 2]]
|
||||
|
||||
describe "x/regex/", ->
|
||||
@ -130,6 +145,14 @@ describe "CommandInterpreter", ->
|
||||
expect(buffer.lineForRow(5)).toBe '!!!!!!current!=!items.shift();'
|
||||
expect(buffer.lineForRow(6)).toBe ' current < pivot ? left.push(current) : right.push(current);'
|
||||
|
||||
describe "when the regex matches a zero-width string", ->
|
||||
it "does not infinitely loop when looking for the next match", ->
|
||||
interpreter.eval(editor, ',s/$/!!!/g')
|
||||
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {!!!'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return items;!!!'
|
||||
expect(buffer.lineForRow(6)).toBe ' current < pivot ? left.push(current) : right.push(current);!!!'
|
||||
expect(buffer.lineForRow(12)).toBe '};!!!'
|
||||
|
||||
describe ".repeatRelativeAddress()", ->
|
||||
it "repeats the last search command if there is one", ->
|
||||
interpreter.repeatRelativeAddress(editor) # don't raise an exception
|
||||
|
@ -3,6 +3,8 @@ Command = require 'command-interpreter/command'
|
||||
module.exports =
|
||||
class Address extends Command
|
||||
execute: (editor) ->
|
||||
editor.getSelection().setBufferRange(@getRange(editor))
|
||||
range = @getRange(editor)
|
||||
editor.clearSelections()
|
||||
editor.setSelectionBufferRange(range)
|
||||
|
||||
isAddress: -> true
|
||||
|
@ -3,3 +3,6 @@ _ = require 'underscore'
|
||||
module.exports =
|
||||
class Command
|
||||
isAddress: -> false
|
||||
|
||||
regexForPattern: (pattern) ->
|
||||
new RegExp(pattern, 'm')
|
||||
|
@ -6,7 +6,7 @@ class RegexAddress extends Address
|
||||
regex: null
|
||||
|
||||
constructor: (pattern) ->
|
||||
@regex = new RegExp(pattern)
|
||||
@regex = @regexForPattern(pattern)
|
||||
|
||||
getRange: (editor) ->
|
||||
selectedRange = editor.getSelection().getBufferRange()
|
||||
|
@ -6,7 +6,7 @@ class SelectAllMatches extends Command
|
||||
@regex: null
|
||||
|
||||
constructor: (pattern) ->
|
||||
@regex = new RegExp(pattern)
|
||||
@regex = @regexForPattern(pattern)
|
||||
|
||||
execute: (editor) ->
|
||||
rangesToSelect = []
|
||||
|
@ -5,7 +5,7 @@ class Substitution extends Command
|
||||
global: false
|
||||
|
||||
constructor: (@findText, @replaceText, @options) ->
|
||||
@findRegex = new RegExp(@findText)
|
||||
@findRegex = @regexForPattern(@findText)
|
||||
@global = 'g' in @options
|
||||
|
||||
execute: (editor) ->
|
||||
@ -27,7 +27,10 @@ class Substitution extends Command
|
||||
buffer.change([startPosition, endPosition], @replaceText)
|
||||
|
||||
if @global
|
||||
text = text[(match.index + match[0].length)..]
|
||||
startIndex = matchStartIndex + @replaceText.length
|
||||
offset = if match[0].length then 0 else 1
|
||||
startNextStringFragmentAt = match.index + match[0].length + offset
|
||||
return if startNextStringFragmentAt >= text.length
|
||||
text = text[startNextStringFragmentAt..]
|
||||
startIndex = matchStartIndex + offset + @replaceText.length
|
||||
@replace(editor, text, startIndex)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user