前置き
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 で実装したもの。
classMotionconstructor: (@editor) ->getStartPoint: ->@editor.getCursorBufferPosition()getEndPoint: ->throw"Motion must implement `getEndPoint()`"getRange: ->newRange(@getStartPoint(),@getEndPoint())execute: ->@editor.setCursorBufferPosition(@getEndPoint())classTextObjectextendsMotiongetStartPoint: ->throw"TextObject must implement `getStartPoint()`"classOperatorconstructor: (@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) ->@operatetarget.getRange()# Visual mode's implict TextObject and OperatorclassTextObjectSelectionextendsTextObjectgetRange: ->@editor.getSelectedBufferRange()classOperatorSelectextendsOperatoroperate: (range) ->@editor.setSelectedBufferRangerange