Edited at

Motion, TextObject, Operator とは何なのか?

More than 3 years have passed since last update.


前置き

Atom で自分の Package 以外に最も気にして PR を投げたりしているのは vim-mode なのですが、色々と事を進めるにあたり、リファクタリングの必要も感じています(自分ができるかどうかはおいといて)。

今回、表題の件について自分なりに考え、vim-mode の issue に記録として書いておきました。

[NOTE] What is Motion, TextObject, Operator

以下は、その翻訳です。私はそれほど英語は得意ではないですが、英語でまず最初に書いて、日本語に訳すという流れになっている。

翻訳をする理由は2つあり、ひとつは自分の理解をさらに確かめ、深める為と、もうひとつは、日本人からのフィードバックを期待しているからです。


Motion, TextObject, Operator とは何なのか?

このノートは、Vim の主要な概念である Motion, TextObject, Operator についてまとめたものである。

今後のリファクタリングや、TextObject, Motion, Operator オブジェクトをサービスAPIで公開する際に役に立てば嬉しい。


TextObject と Motion

両方共とても似ている。概念も実装も。


  • Motion も TextObject も end(ターゲット位置)ポジションを持つ.

  • TextObject は start ポジションを要求する。Motion はしない。言い換えれば、Motion の start ポジションは常に現在のカーソル位置になる。

  • 全ての TextObject は Motion のスーパーセットである。

  • よって、全ての TextObject は Motion としても使用可能。逆は出来ない。

    e.g. TextObject for function は、function body(=TextObject) を yank, delete するのに使える。また、次や、前の function 位置に移動(=Motion)するのにも使える。

  • Motion も TextObject も Operator のターゲット(=対象)として使える。


Operator


  • Operator はアクションである。アクションはターゲットを要求する。

  • ターゲットは、通常 Motion か TextObject である、概念的には、範囲を返す全てのオブジェクトはターゲットになることが出来る。


Visual mode

Visual mode は特別である。暗黙的な Operator と、TextObject を持っているという点において。


  • 本質的には、visual-mode は modal エディタである Vim のモードの一つである。

  • Visual-mode で Operator コマンドが実行(invoke)されると、暗黙的な "TextObject for selection" が Operator のターゲットとして使われる。

  • Visual-mode で i(inside) や a(a or around)を使って、TextObject コマンドが実行(invoke)されると、暗黙的な "select Operator" が Operator として使用される。

  • TextObject for selection は現在の visual area(選択範囲)を返す。

  • Select Operator は visual area(選択範囲) を TextObject が返した範囲に拡張する。


コンセプト実装

上記の概念を CoffeeScript で実装したもの。

class Motion

constructor: (@editor) ->

getStartPoint: ->
@editor.getCursorBufferPosition()

getEndPoint: ->
throw "Motion must implement `getEndPoint()`"

getRange: ->
new Range(@getStartPoint(), @getEndPoint())

execute: ->
@editor.setCursorBufferPosition(@getEndPoint())

class TextObject extends Motion
getStartPoint: ->
throw "TextObject must implement `getStartPoint()`"

class Operator
constructor: (@editor) ->

operate: (range) ->
throw "Operator must implement `operate(range)`"

# target is Motion or TextObject, but all object can be target as long as
# its respond to getRange().
execute: (target) ->
@operate target.getRange()

# Visual mode's implict TextObject and Operator
class TextObjectSelection extends TextObject
getRange: ->
@editor.getSelectedBufferRange()

class OperatorSelect extends Operator
operate: (range) ->
@editor.setSelectedBufferRange range