Skip to content
This repository was archived by the owner on Apr 6, 2018. It is now read-only.

Commit f218c3c

Browse files
author
Max Brunsfeld
committed
Merge pull request #783 from jacekkopecky/check-motion-inclusiveness
Inclusiveness fixes
2 parents 10dc44f + 2698424 commit f218c3c

File tree

5 files changed

+34
-37
lines changed

5 files changed

+34
-37
lines changed

lib/motions/find-motion.coffee

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
{Point, Range} = require 'atom'
44

55
class Find extends MotionWithInput
6+
operatesInclusively: true
7+
68
constructor: (@editor, @vimState, opts={}) ->
79
super(@editor, @vimState)
810
@offset = 0

lib/motions/general-motions.coffee

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class MotionError
1111
@name = 'Motion Error'
1212

1313
class Motion
14-
operatesInclusively: true
14+
operatesInclusively: false
1515
operatesLinewise: false
1616

1717
constructor: (@editor, @vimState) ->
@@ -20,7 +20,9 @@ class Motion
2020
value = for selection in @editor.getSelections()
2121
if @isLinewise()
2222
@moveSelectionLinewise(selection, count, options)
23-
else if @isInclusive()
23+
else if @vimState.mode is 'visual'
24+
@moveSelectionVisual(selection, count, options)
25+
else if @operatesInclusively
2426
@moveSelectionInclusively(selection, count, options)
2527
else
2628
@moveSelection(selection, count, options)
@@ -61,17 +63,35 @@ class Motion
6163
selection.setBufferRange([[newStartRow, 0], [newEndRow + 1, 0]])
6264

6365
moveSelectionInclusively: (selection, count, options) ->
66+
return @moveSelectionVisual(selection, count, options) unless selection.isEmpty()
67+
68+
selection.modifySelection =>
69+
@moveCursor(selection.cursor, count, options)
70+
return if selection.isEmpty()
71+
72+
if selection.isReversed()
73+
# for backward motion, add the original starting character of the motion
74+
{start, end} = selection.getBufferRange()
75+
selection.setBufferRange([start, [end.row, end.column + 1]])
76+
else
77+
# for forward motion, add the ending character of the motion
78+
selection.cursor.moveRight()
79+
80+
moveSelectionVisual: (selection, count, options) ->
6481
selection.modifySelection =>
6582
range = selection.getBufferRange()
6683
[oldStart, oldEnd] = [range.start, range.end]
6784

85+
# in visual mode, atom cursor is after the last selected character,
86+
# so here put cursor in the expected place for the following motion
6887
wasEmpty = selection.isEmpty()
6988
wasReversed = selection.isReversed()
7089
unless wasEmpty or wasReversed
7190
selection.cursor.moveLeft()
7291

7392
@moveCursor(selection.cursor, count, options)
7493

94+
# put cursor back after the last character so it is also selected
7595
isEmpty = selection.isEmpty()
7696
isReversed = selection.isReversed()
7797
unless isEmpty or isReversed
@@ -80,10 +100,15 @@ class Motion
80100
range = selection.getBufferRange()
81101
[newStart, newEnd] = [range.start, range.end]
82102

103+
# if we reversed or emptied a normal selection
104+
# we need to select again the last character deselected above the motion
83105
if (isReversed or isEmpty) and not (wasReversed or wasEmpty)
84106
selection.setBufferRange([newStart, [newEnd.row, oldStart.column + 1]])
107+
108+
# if we re-reversed a reversed non-empty selection,
109+
# we need to keep the last character of the old selection selected
85110
if wasReversed and not wasEmpty and not isReversed
86-
selection.setBufferRange([[newStart.row, oldEnd.column - 1], newEnd])
111+
selection.setBufferRange([[oldEnd.row, oldEnd.column - 1], newEnd])
87112

88113
# keep a single-character selection non-reversed
89114
range = selection.getBufferRange()
@@ -104,9 +129,6 @@ class Motion
104129
else
105130
@operatesLinewise
106131

107-
isInclusive: ->
108-
@vimState.mode is 'visual' or @operatesInclusively
109-
110132
class CurrentSelection extends Motion
111133
constructor: (@editor, @vimState) ->
112134
super(@editor, @vimState)
@@ -159,15 +181,11 @@ class MotionWithInput extends Motion
159181
@complete = true
160182

161183
class MoveLeft extends Motion
162-
operatesInclusively: false
163-
164184
moveCursor: (cursor, count=1) ->
165185
_.times count, ->
166186
cursor.moveLeft() if not cursor.isAtBeginningOfLine() or settings.wrapLeftRightMotion()
167187

168188
class MoveRight extends Motion
169-
operatesInclusively: false
170-
171189
moveCursor: (cursor, count=1) ->
172190
_.times count, =>
173191
wrapToNextLine = settings.wrapLeftRightMotion()
@@ -196,15 +214,11 @@ class MoveDown extends Motion
196214
cursor.moveDown()
197215

198216
class MoveToPreviousWord extends Motion
199-
operatesInclusively: false
200-
201217
moveCursor: (cursor, count=1) ->
202218
_.times count, ->
203219
cursor.moveToBeginningOfWord()
204220

205221
class MoveToPreviousWholeWord extends Motion
206-
operatesInclusively: false
207-
208222
moveCursor: (cursor, count=1) ->
209223
_.times count, =>
210224
cursor.moveToBeginningOfWord()
@@ -221,7 +235,6 @@ class MoveToPreviousWholeWord extends Motion
221235

222236
class MoveToNextWord extends Motion
223237
wordRegex: null
224-
operatesInclusively: false
225238

226239
moveCursor: (cursor, count=1, options) ->
227240
_.times count, =>
@@ -252,6 +265,7 @@ class MoveToNextWholeWord extends MoveToNextWord
252265
wordRegex: WholeWordOrEmptyLineRegex
253266

254267
class MoveToEndOfWord extends Motion
268+
operatesInclusively: true
255269
wordRegex: null
256270

257271
moveCursor: (cursor, count=1) ->
@@ -276,8 +290,6 @@ class MoveToEndOfWholeWord extends MoveToEndOfWord
276290
wordRegex: WholeWordRegex
277291

278292
class MoveToNextParagraph extends Motion
279-
operatesInclusively: false
280-
281293
moveCursor: (cursor, count=1) ->
282294
_.times count, ->
283295
cursor.moveToBeginningOfNextParagraph()
@@ -300,8 +312,6 @@ class MoveToAbsoluteLine extends MoveToLine
300312
cursor.moveToEndOfLine() if cursor.getBufferColumn() is 0
301313

302314
class MoveToRelativeLine extends MoveToLine
303-
operatesLinewise: true
304-
305315
moveCursor: (cursor, count=1) ->
306316
{row, column} = cursor.getBufferPosition()
307317
cursor.setBufferPosition([row + (count - 1), 0])
@@ -316,23 +326,18 @@ class MoveToScreenLine extends MoveToLine
316326
cursor.setScreenPosition([@getDestinationRow(count), 0])
317327

318328
class MoveToBeginningOfLine extends Motion
319-
operatesInclusively: false
320-
321329
moveCursor: (cursor, count=1) ->
322330
_.times count, ->
323331
cursor.moveToBeginningOfLine()
324332

325333
class MoveToFirstCharacterOfLine extends Motion
326-
operatesInclusively: false
327-
328334
moveCursor: (cursor, count=1) ->
329335
_.times count, ->
330336
cursor.moveToBeginningOfLine()
331337
cursor.moveToFirstCharacterOfLine()
332338

333339
class MoveToFirstCharacterOfLineAndDown extends Motion
334340
operatesLinewise: true
335-
operatesInclusively: true
336341

337342
moveCursor: (cursor, count=0) ->
338343
_.times count-1, ->
@@ -341,8 +346,6 @@ class MoveToFirstCharacterOfLineAndDown extends Motion
341346
cursor.moveToFirstCharacterOfLine()
342347

343348
class MoveToLastCharacterOfLine extends Motion
344-
operatesInclusively: false
345-
346349
moveCursor: (cursor, count=1) ->
347350
_.times count, ->
348351
cursor.moveToEndOfLine()
@@ -369,7 +372,6 @@ class MoveToLastNonblankCharacterOfLineAndDown extends Motion
369372

370373
class MoveToFirstCharacterOfLineUp extends Motion
371374
operatesLinewise: true
372-
operatesInclusively: true
373375

374376
moveCursor: (cursor, count=1) ->
375377
_.times count, ->

lib/motions/move-to-mark-motion.coffee

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
module.exports =
66
class MoveToMark extends MotionWithInput
7-
operatesInclusively: false
8-
97
constructor: (@editor, @vimState, @linewise=true) ->
108
super(@editor, @vimState)
119
@operatesLinewise = @linewise

lib/motions/search-motion.coffee

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ SearchViewModel = require '../view-models/search-view-model'
66
settings = require '../settings'
77

88
class SearchBase extends MotionWithInput
9-
operatesInclusively: false
10-
119
constructor: (@editor, @vimState, options = {}) ->
1210
super(@editor, @vimState)
1311
@reverse = @initiallyReversed = false

spec/operators-spec.coffee

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,7 @@ describe "Operators", ->
737737
keydown('c')
738738
keydown('%')
739739
editor.insertText('x')
740-
# this differs from VIM, which deletes the character originally under cursor
741-
expect(editor.getText()).toBe("12345x67)8\nabcx)e\nAx)BCDE")
740+
expect(editor.getText()).toBe("12345x7)8\nabcxe\nAxBCDE")
742741
expect(vimState.mode).toBe "insert"
743742

744743
describe "after or without brackets", ->
@@ -774,15 +773,13 @@ describe "Operators", ->
774773
it "repeats correctly inside brackets", ->
775774
editor.setCursorScreenPosition([1, 4])
776775
keydown('.')
777-
# this differs from VIM, which deletes the character originally under cursor
778-
expect(editor.getText()).toBe("1x8\nabcxd)e\nA()BCDE")
776+
expect(editor.getText()).toBe("1x8\nabcx)e\nA()BCDE")
779777
expect(vimState.mode).toBe "normal"
780778

781779
it "repeats correctly on the closing bracket", ->
782780
editor.setCursorScreenPosition([1, 5])
783781
keydown('.')
784-
# this differs from VIM, which deletes the character originally under cursor
785-
expect(editor.getText()).toBe("1x8\nabcx)e\nA()BCDE")
782+
expect(editor.getText()).toBe("1x8\nabcxe\nA()BCDE")
786783
expect(vimState.mode).toBe "normal"
787784

788785
it "does nothing when repeated after a bracket", ->

0 commit comments

Comments
 (0)