mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
CommandPanel commands have optional error messages
This commit is contained in:
@@ -172,17 +172,21 @@ describe "CommandInterpreter", ->
|
||||
runs ->
|
||||
expect(interpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/a\\Sray/i"
|
||||
|
||||
it "is case-sentive when the pattern contains a non-escaped uppercase letters (behavior copied from vim)", ->
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/arRay', editSession)
|
||||
runs ->
|
||||
expect(interpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/arRay/"
|
||||
describe "when no match is found", ->
|
||||
it "it returns an error messages", ->
|
||||
errorMessages = null
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/garbage!', editSession).done (results) -> { errorMessages } = results
|
||||
|
||||
runs ->
|
||||
expect(errorMessages.length).toBe 1
|
||||
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/Array', editSession)
|
||||
runs ->
|
||||
expect(interpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/Array/"
|
||||
|
||||
|
||||
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", ->
|
||||
@@ -278,16 +282,6 @@ describe "CommandInterpreter", ->
|
||||
expect(selections[2].getBufferRange()).toEqual [[6,34], [6,41]]
|
||||
expect(selections[3].getBufferRange()).toEqual [[6,56], [6,63]]
|
||||
|
||||
describe "when nothing is matched", ->
|
||||
it "preserves the existing selection", ->
|
||||
previousSelections = null
|
||||
waitsForPromise ->
|
||||
previousSelections = editSession.getSelectedBufferRanges()
|
||||
interpreter.eval(',x/this will match nothing', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRanges()).toEqual previousSelections
|
||||
|
||||
describe "substitution", ->
|
||||
it "does nothing if there are no matches", ->
|
||||
waitsForPromise ->
|
||||
@@ -400,13 +394,13 @@ describe "CommandInterpreter", ->
|
||||
project = new Project(fixturesProject.resolve('dir/'))
|
||||
interpreter = new CommandInterpreter(project)
|
||||
|
||||
operations = null
|
||||
operationsToPreview = null
|
||||
waitsForPromise ->
|
||||
interpreter.eval("X x/a+/").done (ops) -> operations = ops
|
||||
interpreter.eval("X x/a+/").done (result) -> {operationsToPreview} = result
|
||||
|
||||
runs ->
|
||||
expect(operations.length).toBeGreaterThan 3
|
||||
for operation in operations
|
||||
expect(operationsToPreview.length).toBeGreaterThan 3
|
||||
for operation in operationsToPreview
|
||||
editSession = project.buildEditSessionForPath(operation.getPath())
|
||||
editSession.setSelectedBufferRange(operation.execute(editSession))
|
||||
expect(editSession.getSelectedText()).toMatch /a+/
|
||||
@@ -414,3 +408,14 @@ describe "CommandInterpreter", ->
|
||||
operation.destroy()
|
||||
|
||||
editSession = null
|
||||
|
||||
describe "nested commands", ->
|
||||
describe "/regex/ /regex", ->
|
||||
it "returns an error message if the last regex has no matches", ->
|
||||
previousSelections = null
|
||||
errorMessages = null
|
||||
waitsForPromise ->
|
||||
previousSelections = editSession.getSelectedBufferRanges()
|
||||
interpreter.eval('/sort/ /no match', editSession).done (results) -> { errorMessages } = results
|
||||
runs ->
|
||||
expect(errorMessages.length).toBe 1
|
||||
|
||||
@@ -35,6 +35,7 @@ class CommandPanel extends View
|
||||
@content: (rootView) ->
|
||||
@div class: 'command-panel tool-panel', =>
|
||||
@subview 'previewList', new PreviewList(rootView)
|
||||
@ul class: 'errorMessages', outlet: 'errorMessages'
|
||||
@div class: 'prompt-and-editor', =>
|
||||
@div ':', class: 'prompt', outlet: 'prompt'
|
||||
@subview 'miniEditor', new Editor(mini: true)
|
||||
@@ -107,7 +108,7 @@ class CommandPanel extends View
|
||||
|
||||
execute: (command=@escapedCommand())->
|
||||
try
|
||||
@commandInterpreter.eval(command, @rootView.getActiveEditSession()).done (operationsToPreview) =>
|
||||
@commandInterpreter.eval(command, @rootView.getActiveEditSession()).done ({operationsToPreview, errorMessages}) =>
|
||||
@history.push(command)
|
||||
@historyIndex = @history.length
|
||||
if operationsToPreview?.length
|
||||
|
||||
@@ -7,10 +7,13 @@ class Address extends Command
|
||||
compile: (project, buffer, ranges) ->
|
||||
deferred = $.Deferred()
|
||||
deferred.resolve ranges.map (range) =>
|
||||
newRange = @getRange(buffer, range)
|
||||
|
||||
new Operation
|
||||
project: project
|
||||
buffer: buffer
|
||||
bufferRange: @getRange(buffer, range)
|
||||
bufferRange: newRange
|
||||
errorMessage: @errorMessage
|
||||
|
||||
deferred.promise()
|
||||
|
||||
|
||||
@@ -3,5 +3,7 @@ _ = require 'underscore'
|
||||
module.exports =
|
||||
class Command
|
||||
isAddress: -> false
|
||||
|
||||
errorMessage: null
|
||||
preserveSelections: false
|
||||
previewOperations: false
|
||||
@@ -15,26 +15,37 @@ class CompositeCommand
|
||||
|
||||
currentCommand.compile(project, editSession?.buffer, ranges).done (operations) =>
|
||||
if remainingCommands.length
|
||||
nextRanges = operations.map (operation) ->
|
||||
operation.destroy()
|
||||
operation.getBufferRange()
|
||||
@executeCommands(remainingCommands, project, editSession, nextRanges).done ->
|
||||
deferred.resolve()
|
||||
errorMessages = @errorMessagesForOperations(operations)
|
||||
nextRanges = operations.map (operation) -> operation.getBufferRange()
|
||||
operations.forEach (operation) -> operation.destroy()
|
||||
|
||||
@executeCommands(remainingCommands, project, editSession, nextRanges).done ({errorMessages: moreErrorMessages})->
|
||||
errorMessages.push(moreErrorMessages...) if moreErrorMessages
|
||||
deferred.resolve({errorMessages})
|
||||
else
|
||||
errorMessages = @errorMessagesForOperations(operations)
|
||||
|
||||
if currentCommand.previewOperations
|
||||
deferred.resolve(operations)
|
||||
deferred.resolve({operationsToPreview: operations, errorMessages})
|
||||
else
|
||||
bufferRanges = []
|
||||
errorMessages = @errorMessagesForOperations(operations)
|
||||
for operation in operations
|
||||
bufferRange = operation.execute(editSession)
|
||||
bufferRanges.push(bufferRange) if bufferRange
|
||||
operation.destroy()
|
||||
if bufferRanges.length and not currentCommand.preserveSelections
|
||||
editSession.setSelectedBufferRanges(bufferRanges)
|
||||
deferred.resolve()
|
||||
|
||||
if bufferRanges.length and not currentCommand.preserveSelections
|
||||
editSession.setSelectedBufferRanges(bufferRanges)
|
||||
|
||||
deferred.resolve({errorMessages})
|
||||
|
||||
deferred.promise()
|
||||
|
||||
errorMessagesForOperations: (operations) ->
|
||||
operationsWithErrorMessages = operations.filter (operation) -> operation.errorMessage?
|
||||
operationsWithErrorMessages.map (operation) -> operation.errorMessage
|
||||
|
||||
reverse: ->
|
||||
new CompositeCommand(@subcommands.map (command) -> command.reverse())
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ class RegexAddress extends Address
|
||||
regex: null
|
||||
reverse: null
|
||||
|
||||
constructor: (pattern, isReversed, options) ->
|
||||
constructor: (@pattern, isReversed, options) ->
|
||||
flags = ""
|
||||
pattern = pattern.source if pattern.source
|
||||
|
||||
@@ -27,14 +27,19 @@ class RegexAddress extends Address
|
||||
buffer[scanMethodName] @regex, rangeToSearch, (match, range) ->
|
||||
rangeToReturn = range
|
||||
|
||||
if rangeToReturn
|
||||
rangeToReturn
|
||||
else
|
||||
if not rangeToReturn
|
||||
rangeToSearch = if @isReversed then rangeAfter else rangeBefore
|
||||
buffer[scanMethodName] @regex, rangeToSearch, (match, range) ->
|
||||
rangeToReturn = range
|
||||
|
||||
rangeToReturn or range
|
||||
if not rangeToReturn
|
||||
flags = ""
|
||||
flags += "i" if @regex.ignoreCase
|
||||
flags += "g" if @regex.global
|
||||
flags += "m" if @regex.multiline
|
||||
@errorMessage = "Pattern not found /#{@regex.source}/#{flags}"
|
||||
|
||||
rangeToReturn or range
|
||||
|
||||
isRelative: -> true
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
module.exports =
|
||||
class Operation
|
||||
constructor: ({@project, @buffer, bufferRange, @newText, @preserveSelection}) ->
|
||||
constructor: ({@project, @buffer, bufferRange, @newText, @preserveSelection, @errorMessage}) ->
|
||||
@buffer.retain()
|
||||
@anchorRange = @buffer.addAnchorRange(bufferRange)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user