Edited at

narrow つくった

More than 1 year has passed since last update.


narrow

これは僕が最近かなりパワーを注いで開発していた、narrow という Atom package の宣伝記事です。


めちゃくちゃ良いです。ぜひ使ってください.( lazy-motion 作った時もそう思ってたけど結局使わななくなったが、今回は違うはず! )

基本的なドキュメントは wiki にアップデートしていく予定。


ですので、この記事の情報は古くなっていきます。


  • 絞込み UI 自体は目新しくもない。Vim なら ctrlP や unite.vim( denite ), Emacs なら anything, helm があるし、CLI ツールでもそういうの( percol, peco, fzf ...) がある。

  • 因みに僕は Emacs の頃に anything を、Vim の頃に unite.vim を使っていた。

  • そもそも僕が最初に作ったのも、Vim の時に使っていた unite 的なものを Atom でも作れないかと実験的に作ったのだった。

  • 2016年5月頃になんとなく作って、リリースした後、ずっと放置していた。僕自身は出来に満足しておらず、全く使っていなかった。

  • 当時は vim-mode-plus でやることが沢山あり、narrow にかけている時間はなかった。

  • 今年(2017年)になって、vim-mode-plus も年末一段落したのと、飽きてきたので、narrow の実験を本格的に再開することにした。

  • 2ヶ月間ぶっ通しで narrow ばかりやっていた。お陰で自分自身はかなり気に入る出来になった。

commit-graph.png


概要


用語と役割達



  • narrow-provider: アイテムを提供する。アイテムを決定するとそのアイテム(ファイル/ポジション)が開く。


  • narrow-ui: 殆どの文脈で、narrow-editor とイコール。


    • ユーザーの絞込みクエリに応じて、アイテムリストを更新する。


    • narrow-editorcontrol-bar やシンタックスハイライト( Grammar で提供 ) を管理する




  • narrow-editor: アイテムが表示されるテキストエディタ。クエリは最初の行に入力する。


active-editor と narrow-editor の関係

overview


コントロールバー( Control bar )

それぞれショートカットが用意されていて、マウスオーバーするとツールチップ上にショートカットが表示されるが、覚えるまではマウスが便利です.

control-bar


特徴


  • helm や unite のような絞り込み UI を提供

  • コードナビゲーションに重点を置いている

  • 単一ファイルと紐づく provider は アクティブなテキストエディタが変わるとアイテムリストも自動更新される


    • このお陰で、symbols は常に現在アクティブなエディタのシンボルが表示されるので minimap 的、table of content for current code 的に使える.



  • アクティブエディタのカーソル位置と、narrow-editor の "選択中アイテム" を自動同期


    • まず narrow:next-item, narrow:previous-itemnarrow-editor にフォーカスがなくても、次、前のアイテムに移動できる様にしている

    • この時 narrow 以外のコマンドでカーソル移動しても、"次のアイテム"、"前のアイテム" が現在のカーソル位置を考慮して "次"、"前" を選んでくれる

    • 複数のファイルをまたいで検索、編集している時に「あれ、今何やってたっけ?」とか「いまアイテムリスト中のどこにいるんだっけか?」とならないように



  • 直編集・反映機能( Direct edit )



    • narrow-editor で編集して、保存すると、実際のファイルを更新

    • 編集用に別の専用バッファを開かないで済むようにしている。直接編集、保存、反映の最短フローになる様に.



  • キーボードナビゲーション



    • narrow-editor にフォーカスしていない状態で、tab, shift-tab で次、前のアイテムに移動したり、narrow-editor を閉じたり出来る



  • 作者(僕)が拡張性にモチベーションがない


    • 最近「それほんとに必要?」という考えになってきた。少数の組み込み provider がいい感じにちゃんと動けば、それで僕はとりあえず満足。




組み込みの provider

僕が普段使いしているのは scan, search, symbols, git-diff-all です。

概要と画像は以下にまとまっている

https://github.com/t9md/atom-narrow/wiki/Provider



  • scan: 現在のエディタをスキャン( 最初 narrow:lines がこの役割を担っていたが、こっちの方が良いので lines は削除した )


  • search: ag の検索結果を提供( ag は自分で入れる必要ある )


  • atom-scan: search と一緒だが、Atom の atom.workspace.scan を使って同じことをやっている。ちょっと遅いけど、ag 入れずに使える。


  • fold: Fold の開始行をアイテムとして提供


  • git-diff: 現在アクティブなエディタの git-diff が情報元。コアパッケージの git-diff の情報を利用


  • git-diff-all: git-diff をプロジェクト全体で。( こっちはあとから作った。結果、単なる git-diff は僕は使わなくなった。)


  • bookmarks: コアパッケージの bookmarks が情報元. なんちゃって provider であんまり便利じゃない。( 僕は bookmarks 機能使ってない )


  • symbols: ctags で取れる関数定義箇所をアイテムとして提供. コアパッケージの symbols-view:toggle-file-symbols の narrow 版。


  • project-symbols: プロジェクト全体の tags ファイルからアイテムを提供


  • linter: linter パッケージの情報を利用


ユースケース

Use case and flow of keystrokes にも幾つか例がある


minimap 的、 table of content for code 的な使い方( 常に開いておく )

atom-narrow-minimap-like.gif


関数の引数を一括で変更

narrow-direct-save-practical.gif


同一ファイル内の関数の使用箇所、定義箇所を quick preview

helm-swoopish.gif


やっぱり使わなくなった関数の削除

保存するとアイテムリストが変更されるので最初に検索しておいて、検索結果の narrow-editor を見ながら

編集、保存、ctrl-cmd-n( or tab )で次のアイテムに移動を繰り返し、narrow-editor のアイテムリストが空になれば DONE!

usecase-remove-unused-function.gif


仕様( 作った後からかんがえた )


  • Provider はアイテムを提供する

  • 各アイテムは必ずファイルと、ポジションに紐付いていなければならない


    • つまり "どのファイルのどのポジションを開く" という形式でオープンで出来る必要がある。

    • "絞込UIでコマンド絞り込んで実行" みたいなのは対象外。やらない。



  • 2種類の Provider ( boundToSingleFile vs Not boundToSingleFile )がある。

  • 単一ファイルに紐付けられる( boundToSingleFile ) provider


    • e.g. scan, fold, symbols.

    • プロジェクトや、ファイル名のヘッダ行は表示しない( 不要だから ).

    • 基本的にこのプロバイダはバッファの内容が変更されるとアイテムリストが更新される( 保存の必要なし ).


    • symbols は例外。保存しないと更新されない



  • 複数ファイルに紐付けられる( Not boundToSingleFile ) provider


    • e.g. search, atom-scan, git-diff-all.

    • プロジェクトヘッダやファイルヘッダを表示する

    • 基本的にアイテムリストの更新はファイルの保存時に行われる. 保存の必要あり.



  • 各 provider はそれ専用の( dedicated ) narro-ui インスタンスを持つ。つまり Ui インスタンスは共有しない。


  • narrow-ui常に 現在アクティブ( focus されている )なテキストエディタに紐付けられる( bound to editor).


    • そして、アクティブなエディタのカーソル移動を検知して、"選択中アイテム"をアップデートする( 自動同期 ).




  • narrow-editor普通の エディタでなければならない


    • 通常のエディタで利用できている移動・編集コマンドやパッケージの機能を例外なく使える為にとても重要

    • e.g. vim-mode-plus のコマンドが narrow-editor でも使えるように.

    • これまでに narrow-editor の Uiの改善や query-area と item-area の分離を試みて数回トライして毎回失敗したので学んだ.

    • https://github.com/t9md/atom-narrow/pull/89

    • https://github.com/t9md/atom-narrow/pull/133

    • 本当は、query-editor と アイテムレンダリング用エディタを分けたかった。だがチャレンジして何度も負けて諦めた。

    • Atom では エディタは pane-item で HTMLElement ならなんでもマウントできるので、Custom Element を作り、そこに Query input 用のミニエディタと、アイテムレンダリング用の mini じゃないエディタを埋め込んで、pane-item として pane に追加することもできて、実際やってみたら内部的には実装がスッキリするし、良い面もたくさんあった。しかし、これをやると、もう narrow-editor普通のエディタ としては扱われない。具体的には atom.workspace.observeTextEditors とかで observe できなくなるので、これを監視している vim-mode-plus や他の多くのパッケージが narrow-editor 上で有効にならない。




スタートアップの流れ



  1. narrow:scan を実行


  2. Scan が実体化( instantiation ) され、専用の Ui も実体化される


  3. narrow-editorが開く