   constructor: (@message) ->
     @name = "Operator Error"
 
-#
-# It deletes everything selected by the following motion.
-#
-class Delete
+class Operator
+  vimState: null
   motion: null
   complete: null
-  vimState: null
+  selectOptions: null
+
+  # selectOptions - The options object to pass through to the motion when
+  #                 selecting.
+  constructor: (@editor, @vimState, {@selectOptions}={}) ->
+    @complete = false
+
+  # Public: Determines when the command can be executed.
+  #
+  # Returns true if ready to execute and false otherwise.
+  isComplete: -> @complete
+
+  # Public: Marks this as ready to execute and saves the motion.
+  #
+  # motion - The motion used to select what to operate on.
+  #
+  # Returns nothing.
+  compose: (motion) ->
+    if not motion.select
+      throw new OperatorError("Must compose with a motion")
+
+    @motion = motion
+    @complete = true
+
+
+  # Protected: Wraps the function within an single undo step.
+  #
+  # fn - The function to wrap.
+  #
+  # Returns nothing.
+  undoTransaction: (fn) ->
+    @editor.getBuffer().transact(fn)
+#
+# It deletes everything selected by the following motion.
+#
+class Delete extends Operator
   allowEOL: null
-  selectOptions: null
-
-  constructor: (@editor, @vimState, {@motion, @allowEOL, @selectOptions}={}) ->
+
+  # allowEOL - Determines whether the cursor should be allowed to rest on the
+  #            end of line character or not.
+  constructor: (@editor, @vimState, {@allowEOL, @selectOptions}={}) ->
     @complete = false
 
-  isComplete: -> @complete
-
   # Public: Deletes the text selected by the given motion.
   #
   # count - The number of times to execute.

  execute: (count=1) ->
    text = ""
    type = if @motion.isLinewise then 'linewise' else 'character'

    originalPosition = @editor.getCursorScreenPosition()
    _.times count, =>
      if _.last(@motion.select())
        text += @editor.getSelection().getText()

  # Returns nothing.
  execute: (count=1) ->
    cursor = @editor.getCursor()

    @undoTransaction =>
      _.times count, =>
        if _.last(@motion.select(1, @selectOptions))
          @editor.getSelection().delete()
