diff --git a/spec/atom/command-interpreter-spec.coffee b/spec/atom/command-interpreter-spec.coffee index 9f8552453..bc1caa0a2 100644 --- a/spec/atom/command-interpreter-spec.coffee +++ b/spec/atom/command-interpreter-spec.coffee @@ -38,13 +38,13 @@ describe "CommandInterpreter", -> interpreter.eval(editor, '.') expect(editor.getSelection().getBufferRange()).toEqual [[1,1], [2,2]] - # editor.getSelection().setBufferRange([[1,1], [2,2]]) - # interpreter.eval(editor, '.,') - # expect(editor.getSelection().getBufferRange()).toEqual [[1,1], [12,2]] + editor.getSelection().setBufferRange([[1,1], [2,2]]) + interpreter.eval(editor, '.,') + expect(editor.getSelection().getBufferRange()).toEqual [[1,1], [12,2]] - # editor.getSelection().setBufferRange([[1,1], [2,2]]) - # interpreter.eval(editor, ',.') - # expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [2,2]] + editor.getSelection().setBufferRange([[1,1], [2,2]]) + interpreter.eval(editor, ',.') + expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [2,2]] describe "/regex/", -> it 'selects text matching regex after current selection', -> @@ -78,6 +78,18 @@ describe "CommandInterpreter", -> interpreter.eval(editor, ',') expect(editor.getSelection().getBufferRange()).toEqual [[0, 0], [12, 2]] + describe "x/regex/", -> + it "sets the current selection to every match of the regex in the current selection", -> + interpreter.eval(editor, '6,7 x/current/') + + selections = editor.getSelections() + expect(selections.length).toBe 4 + + expect(selections[0].getBufferRange()).toEqual [[5,6], [5,13]] + expect(selections[1].getBufferRange()).toEqual [[6,6], [6,13]] + expect(selections[2].getBufferRange()).toEqual [[6,34], [6,41]] + expect(selections[3].getBufferRange()).toEqual [[6,56], [6,63]] + describe "substitution", -> it "does nothing if there are no matches", -> editor.getSelection().setBufferRange([[6, 0], [6, 44]]) diff --git a/src/atom/command-interpreter/select-all-matches.coffee b/src/atom/command-interpreter/select-all-matches.coffee new file mode 100644 index 000000000..0815433f7 --- /dev/null +++ b/src/atom/command-interpreter/select-all-matches.coffee @@ -0,0 +1,39 @@ +Command = require 'command-interpreter/command' +Range = require 'range' + +module.exports = +class SelectAllMatches extends Command + @regex: null + + constructor: (pattern) -> + @regex = new RegExp(pattern) + + execute: (editor) -> + selectedText = editor.getSelectedText() + selectionStartIndex = editor.buffer.characterIndexForPosition(editor.getSelection().getBufferRange().start) + + matchingRanges = @findMatchingRanges(editor, selectedText, selectionStartIndex) + return unless matchingRanges.length + editor.setSelectionBufferRange(matchingRanges[0]) + editor.addSelectionForBufferRange(range) for range in matchingRanges[1..] + + + findMatchingRanges: (editor, text, startIndex) -> + console.log text + return [] unless match = text.match(@regex) + + console.log match + console.log match[0] + + matchStartIndex = startIndex + match.index + matchEndIndex = matchStartIndex + match[0].length + + buffer = editor.buffer + startPosition = buffer.positionForCharacterIndex(matchStartIndex) + endPosition = buffer.positionForCharacterIndex(matchEndIndex) + range = new Range(startPosition, endPosition) + + text = text[(match.index + match[0].length)..] + startIndex = matchEndIndex + [range].concat(@findMatchingRanges(editor, text, startIndex)) + diff --git a/src/atom/commands.pegjs b/src/atom/commands.pegjs index 6d2f85a52..8bc1d1c42 100644 --- a/src/atom/commands.pegjs +++ b/src/atom/commands.pegjs @@ -6,16 +6,14 @@ var EofAddress = require('command-interpreter/eof-address'); var CurrentSelectionAddress = require('command-interpreter/current-selection-address') var RegexAddress = require('command-interpreter/regex-address') + var SelectAllMatches = require('command-interpreter/select-all-matches') } -start - = address:address? _ command:substitution? { - var commands = []; - if (address) commands.push(address); - if (command) commands.push(command); +start = expressions:(expression+) { + return new CompositeCommand(expressions) +} - return new CompositeCommand(commands); - } +expression = _ expression:(address / command) _ { return expression; } address = addressRange / primitiveAddress @@ -32,11 +30,16 @@ primitiveAddress / '.' { return new CurrentSelectionAddress() } / '/' pattern:pattern '/'? { return new RegexAddress(pattern)} +command = substitution / selectAllMatches + substitution = "s" _ "/" find:pattern "/" replace:pattern "/" _ options:[g]* { return new Substitution(find, replace, options); } +selectAllMatches + = 'x' _ '/' pattern:pattern '/'? { return new SelectAllMatches(pattern) } + pattern = pattern:[^/]* { return pattern.join('') } diff --git a/src/atom/editor.coffee b/src/atom/editor.coffee index 8b4608794..fd26c7a69 100644 --- a/src/atom/editor.coffee +++ b/src/atom/editor.coffee @@ -356,6 +356,7 @@ class Editor extends View getCursorBufferPosition: -> @getCursor().getBufferPosition() getSelection: (index) -> @compositeSelection.getSelection(index) + getSelections: -> @compositeSelection.getSelections() getSelectedText: -> @compositeSelection.getSelection().getText() setSelectionBufferRange: (bufferRange, options) -> @compositeSelection.setBufferRange(bufferRange, options) addSelectionForBufferRange: (bufferRange, options) -> @compositeSelection.addSelectionForBufferRange(bufferRange, options)