Add replace to project and buffer

This commit is contained in:
Ben Ogle
2013-11-08 12:20:43 -08:00
parent affcb5ff4a
commit ddd560b785
4 changed files with 116 additions and 0 deletions

View File

@@ -296,6 +296,67 @@ describe "Project", ->
expect(project.getPath()?).toBeFalsy()
expect(project.getRootDirectory()?).toBeFalsy()
describe ".replace()", ->
[filePath, commentFilePath, sampleContent, sampleCommentContent] = []
beforeEach ->
project.setPath(project.resolve('../'))
filePath = project.resolve('sample.js')
commentFilePath = project.resolve('sample-with-comments.js')
sampleContent = fs.readFileSync(filePath).toString()
sampleCommentContent = fs.readFileSync(commentFilePath).toString()
afterEach ->
fs.writeFileSync(filePath, sampleContent)
fs.writeFileSync(commentFilePath, sampleCommentContent)
describe "when called with unopened files", ->
it "replaces properly", ->
results = []
waitsForPromise ->
project.replace /items/gi, 'items', [filePath], (result) ->
results.push(result)
runs ->
expect(results).toHaveLength 1
expect(results[0].filePath).toBe filePath
expect(results[0].replacements).toBe 6
describe "when a buffer is already open", ->
it "replaces properly and saves when not modified", ->
editSession = project.openSync('sample.js')
expect(editSession.isModified()).toBeFalsy()
results = []
waitsForPromise ->
project.replace /items/gi, 'items', [filePath], (result) ->
results.push(result)
runs ->
expect(results).toHaveLength 1
expect(results[0].filePath).toBe filePath
expect(results[0].replacements).toBe 6
expect(editSession.isModified()).toBeFalsy()
it "does NOT save when modified", ->
editSession = project.openSync('sample.js')
editSession.buffer.change([[0,0],[0,0]], 'omg')
expect(editSession.isModified()).toBeTruthy()
results = []
waitsForPromise ->
project.replace /items/gi, 'okthen', [filePath], (result) ->
results.push(result)
runs ->
expect(results).toHaveLength 1
expect(results[0].filePath).toBe filePath
expect(results[0].replacements).toBe 6
expect(editSession.isModified()).toBeTruthy()
describe ".scan(options, callback)", ->
describe "when called with a regex", ->
it "calls the callback with all regex results in all files in the project", ->

View File

@@ -336,6 +336,35 @@ class Project
deferred.promise
replace: (regex, replacementText, filePaths, iterator) ->
deferred = Q.defer()
openPaths = (buffer.getPath() for buffer in @buffers)
outOfProcessPaths = _.difference(filePaths, openPaths)
inProcessFinished = !openPaths.length
outOfProcessFinished = !outOfProcessPaths.length
checkFinished = ->
deferred.resolve() if outOfProcessFinished and inProcessFinished
unless outOfProcessFinished.length
flags = 'g'
flags += 'i' if regex.ignoreCase
task = Task.once require.resolve('./replace-handler'), outOfProcessPaths, regex.source, flags, replacementText, ->
outOfProcessFinished = true
checkFinished()
task.on 'replace:path-replaced', iterator
for buffer in @buffers
buffer.replace(regex, replacementText, iterator)
inProcessFinished = true
checkFinished()
deferred.promise
# Private:
buildEditSessionForBuffer: (buffer, editSessionOptions) ->
editSession = new EditSession(_.extend({buffer}, editSessionOptions))

View File

@@ -0,0 +1,13 @@
{PathReplacer} = require 'scandal'
module.exports = (filePaths, regexSource, regexFlags, replacementText) ->
callback = @async()
replacer = new PathReplacer()
regex = new RegExp(regexSource, regexFlags)
replacer.on 'path-replaced', (result) ->
emit('replace:path-replaced', result)
replacer.replacePaths regex, replacementText, filePaths, ->
callback()

View File

@@ -538,6 +538,19 @@ class TextBuffer
result.lineTextOffset = 0
iterator(result)
replace: (regex, replacementText, iterator) ->
doSave = !@isModified()
replacements = 0
@transact =>
@scan regex, ({matchText, replace}) ->
replace(matchText.replace(regex, replacementText))
replacements++
@save() if doSave
iterator({filePath: @getPath(), replacements})
# Scans for text in a given range, calling a function on each match.
#
# regex - A {RegExp} representing the text to find