WebDesign Dackel

Atomでマルチカーソルの連番入力をするパッケージ「sequential-number」をリリースしました

Atomでマルチカーソルの連番入力をするパッケージ「sequential-number」をリリースしました

Hatena0
Google+0
Pocket0
Feedly0

つい先日Visual Studio CodeOSS化されたり、数ヶ月前にAtomが正式のバージョンである1.0を迎えたり、エディタ界の盛り上がりにはワクワクしますね。

僕は最近AtomSublime Text 3Vimあたりをふらふらとしていて、なんとも落ち着かないコーディングライフを送っていました。

Vimはまだまだ使いこなせない…。そのためGitの連携がデフォルトでも充分優秀、設定が簡単、しかも無料で使えちゃうところに惹かれてAtom率が高くなってきました。


Atomを使い続けてみて、地味に不便を感じていたのが連番入力が出来ないところでした。
具体的にはMarkdownのリストを<ul>から<ol>に変える、みたいなやつです。

# Before
* 米を炊く
* フライパンを温める
* 油をしく

# After
1. 米を炊く
2. フライパンを温める
3. 油をしく

3つくらいならどうってことないですが、数が多いと面倒くさいです…。

Sublime Textを使っていたときにInsertNumsInputSequenceなどのプラグインで実現できましたが、Atomではそれらしいのが見当たらないようなので自作してみました。

AtomGitのリポジトリは以下です。

インストール方法

パッケージはatom.ioに登録しているので、Install Packagesのページで「sequential-number」と検索、このブログでも使っている犬のアイコンが出てきたら、Installを選択すればOKです。

普段Atomをお使いの方であれば、お馴染みの方法なので特に問題無いと思います!

使い方

タイトルにもちらっと書きましたが、Atomのマルチカーソル機能を使ったものになります。

以下は、デフォルトのAtomを想定していますが、sublime-style-column-selectionmulti-cursorと組み合わせると、使いやすいです。

ざっくりと使い方を書くと以下の様な感じです。

  1. 連番入力したい箇所をCtrl-Dで複数選択
  2. Alt-Ctrl-0sequential-numberの入力パネルを開く
  3. 連番を生成するための構文を入力
  4. Enterを押下!

スクリーンショット

上記を実際に試すと、以下の様な動作になります。

sequential-numberのスクリーンショット

連番の生成構文

パネル内で入力する構文は以下です。

<開始番号> <足し算or引き算> <加算する数値> : <最小桁数>

上記の内、必須なのは<開始番号>のみで、あとは全てオプション扱いとなっています。

連番の入力なんて、文章やコードを書く上で重要な作業では無いので、極力シンプルで直感的に使えるように意識してみました。

構文のサンプル

先ほどの構文だけ見ても、イメージが湧きづらいので幾つかサンプルを用意しました。
カーソルが5つある前提で書いていきます。

ちなみに、実際の入力を実行する前に、テキストエリアの下に適用される値が3つプレビューされるので、ちゃんと構文を覚えていなくても安心(?)です。

適用される値の確認

入力 => 1

結果

1
2
3
4
5

開始番号のみ入力すると、指定した開始番号から1ずつ加算した数値が入力されます。

入力 => 1--

結果

1
0
-1
-2
-3

プログラミングでよく使われる、インクリメント(++)とデクリメント(--)の記号を指定することができます。

入力 => 0027 + 3

結果

0027
0030
0033
0036
0039

オプションで最小の桁数を指定できますが、開始番号の先頭に0を付けると自動で桁数を合わせてくれます。

入力 => 10 - 1 : 2

結果

10
09
08
07
06

最小の桁数を指定することで、0埋めした数値の入力も簡単です。


インストール、使い方は以上です!

開発時に詰まった点・参考サイトなど

以下、次に何かパッケージを作るとき、忘れている可能性大なので、開発時に詰まった点など、まとまり無いですが書いておきます。

ドキュメントに載っていないAPIがちょいちょいある

テスト中に書く、パッケージをアクティベートするためのメソッド(activatePackage())や、入力エリアを管理するために用意されたatom-editor-elementなど、ドキュメントには載っていませんでした。

そのため、コアのソースを読むことになるのは必須に感じました。 APIを網羅してくれるとドキュメントを眺めるだけでさくさく開発できてとっても助かる気がします…。

複数のカーソルの取得は簡単、問題はそのあと

展開されている複数のカーソルを取得するのは簡単です。
以下のコードで、カーソルオブジェクトが入った配列が取得できました。

cursors = atom.workspace.getActivePane().activeItem.cursors

「よし、これをforで回してinsertText()だ!」って思っていたのですが、以下の様な出力となってしまい駄目でした。

12345
12345
12345
12345
12345

insertTextの代わりに、TextEditor::setTextInBufferRange()を使うことで、カーソル毎に違う内容を入力することができました。

editor = atom.workspace.getActivePane().activeItem

# それぞれのカーソル毎に異なる数値を入力する
for cursor, index in editor.cursors
  editor.setTextInBufferRange new Range(point, point), index + 1

これでもまだ問題があって、入力後Cmd-zUndoした時に、カーソルの数だけ戻らないと入力前の状態に戻せませんでした。

Undoのトランザクション

上記のUndoへの対策として、TextEditorの履歴系APIに、トランザクションが出来そうなメソッド、trasact()が生えていました。

これを以下のような感じで使うことで、カーソル分の入力を「一つの入力」として扱うことができました。

editor = atom.workspace.getActivePane().activeItem

# カーソル毎の入力履歴をまとめる
editor.transact =>
  for cursor, index in editor.cursors
    editor.setTextInBufferRange new Range(point, point), index + 1

参考になったサイト

おわりに

Atomのパッケージは日々増え続けていると思います。
それなのに、これまで無かったという事は、そもそも需要が無いという事だと思います。笑
全世界で5人くらいに「これ便利!」と思ってもらえらたら大満足です。

もし奇跡的に「使ってみたよ!」という方がいて、バグ報告や機能改善の要望などありましたら、Twitter(@wadackel)やブログのコメント、Issueいただけると嬉しいです。