Skip to content
This repository was archived by the owner on Apr 6, 2018. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions lib/motions/search-motion.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ class SearchBase extends MotionWithInput
operatesInclusively: false
@currentSearch: null

constructor: (@editor, @vimState) ->
constructor: (@editor, @vimState, @reverse=false) ->
super(@editor, @vimState)
Search.currentSearch = @
@reverse = @initiallyReversed = false
@initiallyReversed = @reverse

repeat: (opts = {}) =>
reverse = opts.backwards
Expand All @@ -21,10 +21,6 @@ class SearchBase extends MotionWithInput
@reverse = reverse or @initiallyReversed
@

reversed: =>
@initiallyReversed = @reverse = true
@

moveCursor: (cursor, count=1) ->
ranges = @scan(cursor)
if ranges.length > 0
Expand Down Expand Up @@ -71,11 +67,10 @@ class SearchBase extends MotionWithInput
new RegExp(_.escapeRegExp(term), modFlags)

class Search extends SearchBase
constructor: (@editor, @vimState) ->
super(@editor, @vimState)
constructor: (@editor, @vimState, @reverse=false) ->
super(@editor, @vimState, @reverse)
@viewModel = new SearchViewModel(@)
Search.currentSearch = @
@reverse = @initiallyReversed = false

compose: (input) ->
super(input)
Expand All @@ -84,10 +79,9 @@ class Search extends SearchBase
class SearchCurrentWord extends SearchBase
@keywordRegex: null

constructor: (@editor, @vimState) ->
super(@editor, @vimState)
constructor: (@editor, @vimState, @reverse=false) ->
super(@editor, @vimState, @reverse)
Search.currentSearch = @
@reverse = @initiallyReversed = false

# FIXME: This must depend on the current language
defaultIsKeyword = "[@a-zA-Z0-9_\-]+"
Expand Down
7 changes: 4 additions & 3 deletions lib/view-models/search-view-model.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
module.exports =
class SearchViewModel extends ViewModel
constructor: (@searchMotion) ->
super(@searchMotion, class: 'search')
@prefixChar = if @searchMotion.initiallyReversed then '?' else '/'
super(@searchMotion, class: 'search', prefixChar: @prefixChar)
@historyIndex = -1

@view.editor.on('core:move-up', @increaseHistorySearch)
@view.editor.on('core:move-down', @decreaseHistorySearch)

restoreHistory: (index) ->
@view.editor.setText(@history(index).value)
@view.editor.setText(@prefixChar + @history(index).value)

history: (index) ->
@vimState.getSearchHistoryItem(index)
Expand All @@ -24,7 +25,7 @@ class SearchViewModel extends ViewModel
if @historyIndex <= 0
# get us back to a clean slate
@historyIndex = -1
@view.editor.setText('')
@view.editor.setText(@prefixChar)
else
@historyIndex -= 1
@restoreHistory(@historyIndex)
Expand Down
1 change: 1 addition & 0 deletions lib/view-models/view-model.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ViewModel
#
# - singleChar {Boolean} - tells the view whether it should only listen for a single
# character or an entire string
# - prefixChar {Char} - to be shown in the beginning
constructor: (@operation, opts={}) ->
{@editor, @vimState} = @operation

Expand Down
21 changes: 18 additions & 3 deletions lib/view-models/vim-command-mode-input-view.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,28 @@ class VimCommandModeInputView extends View

@singleChar = opts.singleChar
@defaultText = opts.defaultText ? ''
@prefixChar = opts.prefixChar ? ''

@panel = atom.workspace.addBottomPanel(item: this, priority: 100)

@focus()
@handleEvents()
@editor.setText @prefixChar

handleEvents: ->
if @singleChar?
@editor.find('input').on 'textInput', @autosubmit
if @prefixChar != ''
@editor.find('input').on 'keyup', @checkPrefix
@editor.on 'core:confirm', @confirm
@editor.on 'core:cancel', @cancel
@editor.find('input').on 'blur', @cancel

stopHandlingEvents: ->
if @singleChar?
@editor.find('input').off 'textInput', @autosubmit
if @prefixChar != ''
@editor.find('input').off 'keyup', @checkPrefix
@editor.off 'core:confirm', @confirm
@editor.off 'core:cancel', @cancel
@editor.find('input').off 'blur', @cancel
Expand All @@ -40,10 +46,19 @@ class VimCommandModeInputView extends View
@editor.setText(event.originalEvent.data)
@confirm()

checkPrefix: =>
text = @editor.getText()
if text.length < 1 || text[0] != @prefixChar
@cancel()

confirm: =>
@value = @editor.getText() or @defaultText
@viewModel.confirm(@)
@remove()
text = @editor.getText()
if @prefixChar != '' && !(text && text.length > 0 && text[0] == @prefixChar)
@cancel()
else
@value = if text == @prefixChar then @defaultText else if @prefixChar == '' then text else text.substr(1)
@viewModel.confirm(@)
@remove()

focus: =>
@editorContainer.find('.editor').focus()
Expand Down
8 changes: 4 additions & 4 deletions lib/vim-state.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ class VimState
'repeat-find': (e) => @currentFind.repeat() if @currentFind?
'repeat-find-reverse': (e) => @currentFind.repeat(reverse: true) if @currentFind?
'replace': (e) => new Operators.Replace(@editor, @)
'search': (e) => new Motions.Search(@editor, @)
'reverse-search': (e) => (new Motions.Search(@editor, @)).reversed()
'search-current-word': (e) => new Motions.SearchCurrentWord(@editor, @)
'search': (e) => new Motions.Search(@editor, @, false)
'reverse-search': (e) => new Motions.Search(@editor, @, true)
'search-current-word': (e) => new Motions.SearchCurrentWord(@editor, @, false)
'reverse-search-current-word': (e) => new Motions.SearchCurrentWord(@editor, @, true)
'bracket-matching-motion': (e) => new Motions.BracketMatchingMotion(@editor,@)
'reverse-search-current-word': (e) => (new Motions.SearchCurrentWord(@editor, @)).reversed()

# Private: Register multiple command handlers via an {Object} that maps
# command names to command handler functions.
Expand Down
50 changes: 25 additions & 25 deletions spec/motions-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ describe "Motions", ->
it "moves the cursor to the specified search pattern", ->
keydown('/')

editor.commandModeInputView.editor.setText 'def'
editor.commandModeInputView.editor.setText '/def'
editor.commandModeInputView.editor.trigger 'core:confirm'

expect(editor.getCursorBufferPosition()).toEqual [1, 0]
Expand All @@ -965,15 +965,15 @@ describe "Motions", ->
it "loops back around", ->
editor.setCursorBufferPosition([3, 0])
keydown('/')
editor.commandModeInputView.editor.setText 'def'
editor.commandModeInputView.editor.setText '/def'
editor.commandModeInputView.editor.trigger 'core:confirm'

expect(editor.getCursorBufferPosition()).toEqual [1, 0]

it "uses a valid regex as a regex", ->
keydown('/')
# Cycle through the 'abc' on the first line with a character pattern
editor.commandModeInputView.editor.setText '[abc]'
editor.commandModeInputView.editor.setText '/[abc]'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [0, 1]
keydown('n')
Expand All @@ -983,7 +983,7 @@ describe "Motions", ->
# Go straight to the literal [abc
editor.setText("abc\n[abc]\n")
keydown('/')
editor.commandModeInputView.editor.setText '[abc'
editor.commandModeInputView.editor.setText '/[abc'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
keydown('n')
Expand All @@ -993,7 +993,7 @@ describe "Motions", ->
editor.setText('one two three')
keydown('v')
keydown('/')
editor.commandModeInputView.editor.setText 'th'
editor.commandModeInputView.editor.setText '/th'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [0, 9]
keydown('d')
Expand All @@ -1003,7 +1003,7 @@ describe "Motions", ->
editor.setText('line1\nline2\nline3')
keydown('v')
keydown('/')
editor.commandModeInputView.editor.setText 'line'
editor.commandModeInputView.editor.setText '/line'
editor.commandModeInputView.editor.trigger 'core:confirm'
{start, end} = editor.getSelectedBufferRange()
expect(start.row).toEqual 0
Expand All @@ -1020,37 +1020,37 @@ describe "Motions", ->
keydown('/')

it "works in case sensitive mode", ->
editor.commandModeInputView.editor.setText 'ABC'
editor.commandModeInputView.editor.setText '/ABC'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [2, 0]
keydown('n')
expect(editor.getCursorBufferPosition()).toEqual [2, 0]

it "works in case insensitive mode", ->
editor.commandModeInputView.editor.setText '\\cAbC'
editor.commandModeInputView.editor.setText '/\\cAbC'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
keydown('n')
expect(editor.getCursorBufferPosition()).toEqual [2, 0]

it "works in case insensitive mode wherever \\c is", ->
editor.commandModeInputView.editor.setText 'AbC\\c'
editor.commandModeInputView.editor.setText '/AbC\\c'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
keydown('n')
expect(editor.getCursorBufferPosition()).toEqual [2, 0]

it "uses case insensitive search if useSmartcaseForSearch is true and searching lowercase", ->
atom.config.set 'vim-mode.useSmartcaseForSearch', true
editor.commandModeInputView.editor.setText 'abc'
editor.commandModeInputView.editor.setText '/abc'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
keydown('n')
expect(editor.getCursorBufferPosition()).toEqual [2, 0]

it "uses case sensitive search if useSmartcaseForSearch is true and searching uppercase", ->
atom.config.set 'vim-mode.useSmartcaseForSearch', true
editor.commandModeInputView.editor.setText 'ABC'
editor.commandModeInputView.editor.setText '/ABC'
editor.commandModeInputView.editor.trigger 'core:confirm'
expect(editor.getCursorBufferPosition()).toEqual [2, 0]
keydown('n')
Expand All @@ -1063,7 +1063,7 @@ describe "Motions", ->

beforeEach ->
keydown('/')
editor.commandModeInputView.editor.setText 'def'
editor.commandModeInputView.editor.setText '/def'
editor.commandModeInputView.editor.trigger 'core:confirm'

describe "the n keybinding", ->
Expand All @@ -1083,14 +1083,14 @@ describe "Motions", ->
it "composes with operators", ->
keydown('d')
keydown('/')
editor.commandModeInputView.editor.setText('def')
editor.commandModeInputView.editor.setText('/def')
editor.commandModeInputView.editor.trigger('core:confirm')
expect(editor.getText()).toEqual "def\nabc\ndef\n"

it "repeats correctly with operators", ->
keydown('d')
keydown('/')
editor.commandModeInputView.editor.setText('def')
editor.commandModeInputView.editor.setText('/def')
editor.commandModeInputView.editor.trigger('core:confirm')

keydown('.')
Expand All @@ -1099,14 +1099,14 @@ describe "Motions", ->
describe "when reversed as ?", ->
it "moves the cursor backwards to the specified search pattern", ->
keydown('?')
editor.commandModeInputView.editor.setText('def')
editor.commandModeInputView.editor.setText('?def')
editor.commandModeInputView.editor.trigger('core:confirm')
expect(editor.getCursorBufferPosition()).toEqual [3, 0]

describe "repeating", ->
beforeEach ->
keydown('?')
editor.commandModeInputView.editor.setText('def')
editor.commandModeInputView.editor.setText('?def')
editor.commandModeInputView.editor.trigger('core:confirm')

describe 'the n keybinding', ->
Expand All @@ -1124,34 +1124,34 @@ describe "Motions", ->
describe "using search history", ->
beforeEach ->
keydown('/')
editor.commandModeInputView.editor.setText('def')
editor.commandModeInputView.editor.setText('/def')
editor.commandModeInputView.editor.trigger('core:confirm')
expect(editor.getCursorBufferPosition()).toEqual [1, 0]

keydown('/')
editor.commandModeInputView.editor.setText('abc')
editor.commandModeInputView.editor.setText('/abc')
editor.commandModeInputView.editor.trigger('core:confirm')
expect(editor.getCursorBufferPosition()).toEqual [2, 0]

it "allows searching history in the search field", ->
keydown('/')
editor.commandModeInputView.editor.trigger('core:move-up')
expect(editor.commandModeInputView.editor.getText()).toEqual('abc')
expect(editor.commandModeInputView.editor.getText()).toEqual('/abc')
editor.commandModeInputView.editor.trigger('core:move-up')
expect(editor.commandModeInputView.editor.getText()).toEqual('def')
expect(editor.commandModeInputView.editor.getText()).toEqual('/def')
editor.commandModeInputView.editor.trigger('core:move-up')
expect(editor.commandModeInputView.editor.getText()).toEqual('def')
expect(editor.commandModeInputView.editor.getText()).toEqual('/def')

it "resets the search field to empty when scrolling back", ->
keydown('/')
editor.commandModeInputView.editor.trigger('core:move-up')
expect(editor.commandModeInputView.editor.getText()).toEqual('abc')
expect(editor.commandModeInputView.editor.getText()).toEqual('/abc')
editor.commandModeInputView.editor.trigger('core:move-up')
expect(editor.commandModeInputView.editor.getText()).toEqual('def')
expect(editor.commandModeInputView.editor.getText()).toEqual('/def')
editor.commandModeInputView.editor.trigger('core:move-down')
expect(editor.commandModeInputView.editor.getText()).toEqual('abc')
expect(editor.commandModeInputView.editor.getText()).toEqual('/abc')
editor.commandModeInputView.editor.trigger('core:move-down')
expect(editor.commandModeInputView.editor.getText()).toEqual ''
expect(editor.commandModeInputView.editor.getText()).toEqual '/'

describe "the * keybinding", ->
beforeEach ->
Expand Down