新人エンジニアのためのエディタ入門

もうクリスマス当日ですが、 [Fringe81 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/fringe81) の10日目の記事です。

大幅に遅れてしまってFringeneerの皆さん本当にごめんなさい。

## 最初に

入社してからエンジニアデビューした新人から、こんな声を聞くことがあります。

- どのエディタがいいんです？
- Vim / Emacsってよく聞くけど、よく分からないです
- Vim / Emacsが苦手です
- キーバインドが覚えられないです
- カスタマイズって敷居が高いです

こういった声に答えるべく、エディタよもやま話から、Vimの基本的な操作、Atomのカスタマイズの方法とかについて書きました。

すでにVimやAtomをバリバリ使っている方は対象読者ではありませんので悪しからず。

## エディタよもやま話

### VimとEmacs

エンジニアにとってエディタと言えば、Vim(vi含む)かEmacsです。
誰が決めたかは知りませんが、大昔からそう決まっています。

ちなみに僕が好きなエディタもEmacsです。

ただ、両者はともに高機能ですが、独特のキーバインド、最初のうちほとんど上昇しない学習曲線、使い始めの生産性の低さから、初心者のやる気をくじきます。
一方で、一度学習曲線が上を向き始めると、どんどん使いこなせるようになり、生産性もそれに伴い急激に上昇するエディタでもあります。

カスタマイズにはそれぞれVim scriptやEmacs Lispという若干マイナーな言語を覚える必要があり、カスタマイズのハードルは高めです。

個人的なイメージではありますが、両者の特色として下記を挙げます。

- Vim
    - 究極のエディタ
    - 合理的な操作体系（ゆえにコツを覚えると類推しながら操作できるようになる）
    - たいていの作業環境で既にインストールされている
    - キーの同時押しが少なく指に優しい
- Emacs
    - 究極の環境（カスタマイズしまくることが前提）
    - デフォルトの操作体系はVimほど合理的ではない（と思う）
    - インストールされていない作業環境も多い
    - キーの同時押しが多くて指がつる（けど1週間程度で慣れる）

色々と違いはありますが、どちらのエディタも達人の域になると、視線の動きとカーソルがほとんどシンクロしています。

ちなみに、よくVimユーザーとEmacsユーザー間の「エディタ戦争」とか言われますが、正直なところガチのエディタ戦争を目にしたことはありません。
「これだからEmacsは・・・」などとユーザー同士で揶揄したりもしますが、冗談ぽくいじり合う感じが多く、どちらかというとEclipseなどのIDE（統合開発環境）が彼らの共通の敵だったりします。


### 3つめの選択肢 Atom

そんな使いこなすのが難しいVimやEmacsですが、同じくらい高機能でありながら、近年台頭してきて、初心者にもとっつきやすいエディタがあります。
Atomです。

キーバインドもとても常識的ですし、カスタマイズに使う言語はJava ScriptやCSSというおそらく最も競技人口が多い言語を使うため、カスタマイズも容易です。

サイズの大きなファイルをいじったりする場合は動きがもっさりして辛かったりしますが、それ以外の面であれば、2大エディタとほとんど遜色ないレベルの高機能さです。
これからプログラミングを始めようとしている方から、VimやEmacsをバリバリ使っている方まで、広いユーザー層を満足させられるエディタだと思います。

### おすすめエディタ

好きなエディタはEmacs、と言っておいてアレですが、新人からおすすめエディタを聞かれたらVimとAtomを勧めています。

その理由は下記です。

- Vim
    - ターミナルからサーバーにログインして作業をする時のデファクトスタンダード
    - とっつきにくい印象をもたれがちだが、一度考え方に慣れるとEmacsより操作を覚えやすい
    - 大きいサイズのファイルを扱う時に、Atomはもちろん、Emacsよりも動作が軽い
- Atom
    - 一般的なアプリケーションと同じキーバインドが多い
    - パッケージの導入も簡単で、初心者エンジニアが「エディタを育てていく」ことの楽しさを学びやすい
        - プログラミングの学習に役立つパッケージを簡単に入れられる
    - エディタを簡単にカスタマイズできる

以降では、あえてEmacsではなく、VimとAtomの基礎的な使い方やTipsを紹介したいと思います。

それほど詳しいわけではないので役者不足だと自覚していますが、まぁご容赦ください。

## Vimと仲良くなる

Vimと仲良くなるために押さえておいた方がよい概念やTipsを新人エンジニア向けに紹介します。

「使いこなす」とまではいかなくても、ここに書いてあることを読めば「苦手意識がなくなる」程度には、Vimと仲良くなれると思います。
僕自身それほどVimと仲良しなわけではないですが、それでも苦手意識は特にありません。

`h` `j` `k` `l` と `i` と `Esc` と `:wq` と `:q!` しか覚えていない、そんな貴方に読んでいただきたいです。

### モード

一にも二にも、「モード」という概念がVimへの敷居を上げていると言ってもいいでしょう。

初めてVimに触れ、 `hoge` と打とうとしても思うように入力できない時の絶望感を、誰しも一度は味わったことがあるのではないでしょうか。

Vimには以下のモードがあります。

- ノーマルモード
- 入力モード
- コマンドモード
- 検索モード
- ビジュアルモード

書籍やサイトによっては、ノーマルモード・入力モード・コマンドモードの3つのモードと言っていたりもします。
どれが正しいのかは知りません。（公式ドキュメントでも読めば書いてあるでしょうが）

まずは、ノーマルモードとその他のモードがある、と覚えましょう。

ノーマルモードから各モードには下記のキーバインドで移行できます。

| モード           | キーバインド                 |
| :--------------- | :--------------------------- |
| 入力モード       | `i` `I` `a` `A` `o` `O` など |
| コマンドモード   | `:`                          |
| 検索モード       | `/` `?`                      |
| ビジュアルモード | `v` `V` `Ctrl + v` など      |

一方、現在どのモードであっても、ノーマルモードに戻るには `Esc` を使います。
が、実は `Ctrl + [` でも戻ることができます。
`Esc` キーが押しづらいため、自分は `Ctrl + [` を使っています。

以降では、各モードについて少し個別に紹介します。

#### ノーマルモード

カーソル移動のためのモードですが、非ノーマルモードから他の非ノーマルモードに移行するためには、多くの場合は一度ノーマルモードに移行する必要があるため、キーボードで言うところのホームポジション的なモードでもあります。

カーソル移動の主なコマンドをおさらいしておきましょう。

| キーバインド | 振る舞い                                          |
| :--- | :------------------------------------------------ |
| `h`  | カーソルを左に移動する          |
| `j`  | カーソルを下に移動する          |
| `k`  | カーソルを上に移動する          |
| `l`  | カーソルを右に移動する          |
| `^`  | カーソル行の先頭に移動する (正規表現と一緒)     |
| `$`  | カーソル行の先頭に移動する (正規表現と一緒)     |
| `gg` | ファイルの先頭に移動する        |
| `G`  | ファイルの最終行に移動する      |
| `Ctrl + f`  | 1ページ分進む (Forward?)           |
| `Ctrl + b`  | 1ページ分戻る (Backward?)           |
| `w`  | 1単語進む (Word)                     |
| `b`  | 1単語戻る (Back word?)                     |

ちなみにVimのカーソル移動の方法はめちゃくちゃたくさんあります。
興味が出てきたら調べてみてください。（ `f` なんかも便利です）

#### 入力モード

文字を入力するためのモードです。

Vimを使ったことがある人であれば、おそらくどんな人も `i` くらいは知っていると思いますが、実は色々なキーバインドがあります。

メジャーなところだと、 `i` `a` `o` あたりでしょうか。

それぞれ、以下の動きをします。

| キーバインド | 振る舞い                                          |
| :--- | :------------------------------------------------ |
| `i`  | カーソル位置から文字を入力する (Insert)     |
| `a`  | カーソル位置の次から文字を入力する (Append)     |
| `o`  | カーソル行の次に1行挿入して文字を入力する        |
| `I`  | カーソル行の先頭から文字を入力する (Insert) |
| `A`  | カーソル行の末尾から文字を入力する (Append)  |
| `O`  | カーソル行の前に1行挿入して文字を入力する         |

最初にすべて覚える必要はないと思いますが、入力モードへの移行に `i` しか使っていない、というのも勿体ない話です。

段々と慣れて使いこなせるようになりましょう。

#### コマンドモード

exというラインエディタのコマンドを使うモードなので、Exモードとも呼ばれたりします。
ファイル保存や置換の時に使われることが多いです。

exコマンドは多岐に渡り、軽く紹介できるものでもないので、ここでは割愛します。
とりあえずはファイル保存と置換ができればよいと思います。

置換は下記です。

```
:%s/before/after/g
```

セパレータは `/` の代わりに `:` を使うこともできるため、 `/` を含んだ文字列を置換したい時は `:` を使うと便利です。
他にも、上記の `%` や `g` などについては解説が必要ですが、ネット上にいくらでも解説があるので、そちらを参照してください。

ちなみに、ファイル保存する際には `:wq` を使っている方が多いと思いますが、ノーマルモードで `ZZ` でも同じことができます。

#### 検索モード

`/` や `?` を押すことで移行することができるモードです。
`/` はファイル末尾に向かって検索し、 `?` はファイル先頭に向かって検索します。

検索中に `n` で次の候補に移動でき、 `N` で一つ前の候補に戻ることができます。


#### 範囲選択モード

`v` や `V` や `Ctrl + v` で移行することができるモードです。

一般的なエディタだと `Shift` を押しながらカーソル移動するのと同じイメージです。

| キーバインド | 振る舞い                                          |
| :--- | :------------------------------------------------ |
| `v`  | 範囲選択モードに移行                              |
| `V`  | 行単位の範囲選択モードに移行                      |
| `Ctrl + v` | 矩形選択モードに移行                        |

範囲選択した状態で、 `y` (yank) でコピー、 `c` (change) で変更、 `d` (delete) で削除ができます。

また、矩形選択している状態で `I` を押して入力モードに移行し、文字列を入力してから入力モードを抜けると、矩形選択していたすべての場所に入力した文字列が挿入されます。

### Shiftを使った時の挙動

Vimでは、元々のキーバインドにShiftを組み合わせることで、元々の動きが少し変化した振る舞いをすることが多いです。

大きく分けると、

- 正反対の振る舞いをする（ex. 検索モードに移行する時の `/` と `?` や、検索後の `n` と `N` など）
- もともとの振る舞いの対象範囲を拡大する（ex. 入力モードに移行する時の `i` と `I` （挿入対象が、文字から行に拡大）など）

のどちらかが大半な印象です。

元々の操作と、Shiftを同時に押した時の動作を、セットで覚えるとより多くの操作がラクに身につくと思います。

### operator

`y` `c` `d` `v` などの操作はoperatorと呼ばれ、カーソル移動操作（motion）やtext-objectというものと組み合わせることで、便利な使い方ができます。

以降で、ほんの触りですが紹介してみたいと思います。

#### motionとの組み合わせ

operatorに続けて、カーソル移動操作のキーバインドを入力することで、カーソル位置から移動先までを対象として、コピー・変更・操作・選択ができます。

例えば、カーソル位置から行末尾までを削除したいときは `d$` と入力することで実現できますし、単語の先頭にカーソルがある状態で `cw` と入力すれば単語の変更が行えます。

#### text-objectとの組み合わせ

operatorに続けて、text-object（色々種類があります）を指定することで、そのtext-objectを対象として、コピー・変更・操作・選択ができます。

text-objectは説明が難しいのですが、`a` (冠詞のa) または `i` (innerの略) と、それに `"` や `[` などの特定の文字を続けたものになります。

text-objectとして最初に指定する `a`または `i` のアルファベット1文字の意味は下記です。

- `a`: 指定した特定の文字が表す対象をtext-objectとして指定する
- `i`: 指定した特定の文字が表す対象の内側をtext-objectとして指定する

例を示した方が分かりやすいと思うので、いくつか例を示します。

- 「"」で囲まれた位置にカーソルがある時
    - 「"」で囲まれた範囲を「"」を含めて選択したい: `va"`
    - 「"」で囲まれた内側の範囲を選択したい: `vi"`
- 「HTMLタグ」で囲まれた位置にカーソルがある時
    - 「HTMLタグ」で囲まれた範囲を「HTMLタグ」を含めてコピーしたい: `yat`
    - 「HTMLタグ」で囲まれた内側の範囲をコピーしたい: `yit`

なんとなく分かってもらえたでしょうか。

説明の便宜のために一部不正確に書いてしまっている箇所もあるため、詳しく知りたくなったら調べてみてください。

### その他よく使うキーバインド

他にも、よく使うキーバインドとして、

- `u`: 直前の操作を取り消す、Undo
- `*`: カーソル位置の単語が次に現れる箇所まで移動する
- `J`: カーソル行と次の行をつなげる

などがあります。


...ここまででVimの基本的な操作はそれなりに紹介できたのではないかと思いますが、Vimの世界は大変ディープです。ここで紹介できたのはその1%程度だと思います。

書籍やサイトも数多くありますので、「Vimともっと仲良くなりたい！」と思ったら、ぜひご自分でVim道を極めていってください。


## Atomと仲良くなる

Vimと異なり、Atomの操作方法は最初から一般ユーザーに親しみやすいものになっているので、操作の仕方については割愛します。

以降では、Atomのカスタマイズの方法とおすすめパッケージについて紹介します。
簡単な独自機能を追加してみることで、エディタをカスタマイズする楽しさを知ってもらえれば嬉しいです。

（予想外にVimについての記述が多くなってしまったので、ここからはあっさりめで行かせていただきます。）

### カスタマイズのいろは

Atomのカスタマイズという時、大きく分けて以下の種類があると個人的には考えています。

- キーマップ（キーバインド）の変更
- コマンド（機能）の変更・追加
- 見た目の変更

それぞれをどうカスタマイズしていけばいいか、見ていきましょう。

#### キーマップの変更

キーマップに変更を加えることで、色々なコマンド（後述）を任意の操作で呼び出すことができるようになります。

メニューから、 `Atom -> Keymap...` を選択すると `~/.atom/keymap.cson` が開かれ、このファイルを編集することでキーマップをカスタマイズできます。 `keymap.cson` というファイル名からも分かるように、cson形式で定義します。

トップレベルのプロパティ名には、そのキーマップを有効にする文脈をCSSセレクタで指定し、その値に `キー: 呼び出しコマンド名` という形でキーとコマンド名のマッピングを定義したオブジェクトを指定します。

説明だけでは分からないと思いますので、とりあえず例を見てみましょう。

```cson
'.platform-darwin, .platform-linux, .platform-win32':
  'ctrl-g': 'core:cancel'
  'ctrl-p': 'core:move-up'
  'ctrl-n': 'core:move-down'
  'ctrl-b': 'core:move-left'

（略）

'atom-text-editor':
  'ctrl-d': 'core:delete'

（略）
```

##### セレクタ

CSONのトップレベルのプロパティですが、
`'.platform-darwin, .platform-linux, .platform-win32'` や `'atom-text-editor'` など、
たしかにCSSセレクタのように見えますね。

AtomはElectronで作られており、Chromiumベースで一種のブラウザになっています。
メニューから `View -> Developer -> Toggle Developer Tools` と選択すると、フロントエンドエンジニアにはお馴染みのDeveloper Toolsが表示されます。
Developer ToolsのElementsのタブとにらめっこしていると、たしかにMacの場合は `body` に `platform-darwin` というクラスが付いていることが分かります。

つまり、上記のCSONでは、まず「どんな要素内でキーが押された時のキーマップを定義するのか」をトップレベルのプロパティで定義しています。
例では、 `.platform-darwin` `.platform-linux` `.platform-win32` というクラスが付加されている要素内と、 `atom-text-editor` という要素内でのキーマップについて定義しているわけです。

##### キー＆コマンド

では、 `atom-text-editor` 要素内のキーマップについて見てみましょう。

`'ctrl-d': 'core:delete'` と1行だけ内容の記述があります。

これは「 `ctrl-d` というキーで `core:delete` という名前のコマンドを呼び出す」という定義になっています。

コマンドというのは、atomに登録されている関数です。

https://atom.io/docs/api/v1.0.0/CommandRegistry#instance-add を読んでもらえば分かりますが、Atomでは `atom.commands.add(target, commandName, callback)` といういかにもな名前のメソッドがあります。
このメソッドを通じて登録されたcallback関数がコマンドであり、この時に `commandName` として指定したものがコマンドの名前になります。

コマンドには、パッケージによって提供されるコマンドと、自分で追加するコマンドがあります。

###### コマンド名の確認方法

Atomに登録されているコマンドは、コマンドパレット（ メニュー上で `Packages -> Command Palette` で出るかと ）から確認できます。

また、Macだと `⌘ + .` で、Key Binding Resolverというペインが開き、操作をする度に今自分が呼んでいるコマンドを確認できます。

#### コマンドの追加

コマンドを追加することで、エディタに新しい機能を追加することができます。Atomカスタマイズの醍醐味です。

ここからは、簡単な自作コマンドを作ってみましょう。

##### 初期化スクリプト

Atomが起動すると、 `~/.atom/init.js` ないし `~/.atom/init.coffee` という初期化スクリプトが読み込まれます。

このスクリプトに処理を記述することで、Atomの機能を拡張していきます。

なお、このスクリプトはメニュー上の `Atom -> Init Script...` から開くことができますが、ファイルがない状態でこのメニューを選ぶとCoffee Scriptのファイルが作成されてしまうため、Java Scriptを使いたい場合は `touch ~/.atom/init.js` などを実行してからメニューを選びましょう。

##### 「日誌を開く」機能の追加

さて、エンジニアであれば、一日の作業メモファイルを残す習慣のある方も多いかと思います。

そこで、Atomに「日誌を開く」という機能を追加してみましょう。

今日の日付のファイルをホームディレクトリ以下に作成する、下記のようなコードを書いてみましょう。

```js
atom.commands.add(
  'atom-workspace',
  'my-commands:open-journal',
  ev => {
    const today = new Date();
    const homeDir = process.env[process.platform == "win32" ? "USERPROFILE" : "HOME"];
    atom.workspace.open(`${homeDir}/Journals/${today.getFullYear()}/${today.getMonth() + 1}/${today.getDate()}.md`);
  }
);
```

Atomを再起動してコマンドパレットを開いて「Open Journal」と検索すると、おそらく上記で登録したコマンドが表示されると思います。
そしてそのコマンドを選択すると、めでたく `~/Journals/2017/12/25.md` といったファイルを開いてくれるはずです。

ここまでで、コマンドの追加は完了です。

##### コマンドとキーの関連付け

`my-commands:open-journal` というコマンドは追加できましたが、日誌を開く度にコマンドパレットを開くというまだるっこしいことは、できればやりたくありません。
一発で日誌を開きたいところです。

ここでもう一度 `keymap.cson` を開いて、下記のような記述を追加してみましょう。

```cson
'atom-workspace':
  'ctrl-shift-j': 'my-commands:open-journal'
```

JournalのJから、 `Ctrl + Shift + j` というキーをマッピングしてみました。
保存すると即座に設定は反映されるので、 `Ctrl + Shift + j` を入力してみましょう。

...どうでしょう、日誌は開けたでしょうか？


#### 見た目の変更

キーマップの設定のための `keymap.cson` や 初期化スクリプトの `init.js` と同様に、
見た目をカスタマイズするためのファイルとして `~/.atom/styles.less` というファイルが用意されています。

メニューから `Atom -> Stylesheet...` を選択すると、lessファイルが開かれて、色々な見た目を制御できるようになります。

好みで色々といじってみるとよいと思います。

等幅フォントに設定しておくと、環境がより快適になります。


### エディタカスタマイズの楽しさ

ここまでAtomの独自カスタマイズに必要な最低限のことを、ざっくり紹介できたかと思います。

パッケージが豊富なエディタですから、たいていの機能は誰かしらがパッケージで提供してくれているかもしれません。
ですが、それでも「あー、○○○できる機能があればいいのに・・・なんでないんだ・・・」と思うことは、そのうちきっとあるでしょう。

先に上げたVimやEmacsはVim scriptやEmacs Lispを学習しなければカスタマイズできませんが、AtomではJavaScriptとlessさえ使えれば、どんな機能でも自分で追加が可能です。

もしも欲しい機能がパッケージになかった時は、ぜひ自分でスクリプトを書いてカスタマイズして、「自分の欲しいものを自分で作る」というDIYの楽しさを味わってください。
そして、その機能が世の中の人達にも有用だと思ったら、ぜひパッケージとして公開してみましょう。

Atomはパッケージの作成もとても簡単にできます。

### おすすめパッケージ

独自のカスタマイズのやり方について説明しましたが、カスタマイズの基本はどちらかと言えばパッケージの追加かもしれません。
メニュー上で `Atom -> Preferences -> Install` を選択して、パッケージを検索するだけで簡単にインストールできるので、色々なパッケージを試してみてください。

以下に個人的なおすすめパッケージを紹介しておきます。

- https://atom.io/packages/script : Atomで書いたコードを瞬時に実行できるパッケージです。プログラミングの学習には最適です。
- https://atom.io/packages/advanced-open-file : ファイルを開く効率が上がります。
- https://atom.io/packages/file-icons : ファイルのアイコンが見やすくなります。
- https://atom.io/packages/language-plantuml & https://atom.io/packages/plantuml-viewer : PlantUMLユーザーな貴方に。
- https://atom.io/packages/multi-cursor : マルチカーソル機能を追加してくれます。
- https://atom.io/packages/markdown-hopper : Markdownファイルの目次を表示したり各見出しにジャンプしたりできる自作パッケージです。Atom素人の頃に突貫で作ったもので、これ以上ないくらいコード汚いので中身は見ないでください。そのうちメンテします。


## 最後に

書き始めたら長いエントリーになってしまいましたが、楽しんでもらえたら嬉しいです！

皆様よいクリスマス＆お正月を！！！