🎼

Flutterの自動生成ファイルと実装ファイルを切り替えできるようにVimのマッピングを設定した

2023/03/14に公開

最近また改めてFlutterでアプリを作ったりしてまして、Riverpodも結構進化しているらしくキャッチアップしてます。なにやらriverpod_generatorでコード生成するのがおすすめらしいみたいな話があり試してます。

riverpod_generator

riverpod_generatorの使い方やメリットは以前購入した村松さんの記事が参考になりました(該当箇所はいまのところ無料です)。プロバイダのホットリロードが可能になるあたりは嬉しいですね。

https://zenn.dev/riscait/books/flutter-riverpod-practical-introduction/viewer/riverpod-generator

切り替えるのは簡単で、たとえばシンプルなFutureProviderを作りたい場合…以下のコードは Isarっていデータベース を開くコードなんですが、

Before
final isarProvider = FutureProvider<Isar>((ref) async {
  return Isar.open([MemoSchema]);
});
After
(keepAlive: true)
Future<Isar> isar(IsarRef ref) async {
  return Isar.open([MemoSchema]);
}

という感じで、従来まで使っていたisarProviderみたなやつは、自動生成されたファイルのほうに記述されるようになりました。ちなみに、このサンプルでコード生成すると、以下のようなファイルが生成されていました。

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'isar_provider.dart';

// **************************************************************************
// RiverpodGenerator
// **************************************************************************

String _$isarHash() => r'222169261f8ccbaf7b55c3ada3ca3b7c8cb5aa81';

/// See also [isar].
(isar)
final isarProvider = FutureProvider<Isar>.internal(
  isar,
  name: r'isarProvider',
  debugGetCreateSourceHash:
      const bool.fromEnvironment('dart.vm.product') ? null : _$isarHash,
  dependencies: null,
  allTransitiveDependencies: null,
);

typedef IsarRef = FutureProviderRef<Isar>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions

実際にこのProviderを使いたい場面では、従来通りisarProviderを呼び出して使います。

困っていること

でまあここからがようやく本題なんですが、例えばこういったProviderを使っている側のクラスなりをいじってる時に「このProviderってどんな実装だったっけ?」って確認したいことあるじゃないですか。で、まあLSPなりの機能を使って定義ジャンプしますよね。

するとどうでしょう、当然ながら自動生成されたほうのファイルを開いちゃうわけです。俺は実装のほうを見たいんだ、ってなるじゃないですか。こっちじゃねーっすよと。

しかしながらですよ。定義ジャンプする時によしなにしてくれればいいんだけど、それはなかなか難しそうな気がするんですねきっと。

というわけで、xxx.g.dartxxx.dartというファイルを交互に開けるようなキーマップを追加しましたという話になるわけです。

Vimスクリプトのコード

シンプルに関数一個でdartでしか使わないので、以下のようなファイルを~/.vim/ftplugin/dart.vimに突っ込んで使ってます。キーマッピングはgaとかやってますけど、お好みにあわせて変更してください。

~/.vim/ftplugin/dart.vim
if exists("b:dart_ftplugin") | finish | endif

let b:dart_ftplugin = 1

command! -buffer -nargs=? SwitchPart call <SID>SwitchPartFile()

nnoremap <buffer> <silent> ga :cal<SID>SwitchPartFile()<cr>

if exists('*s:SwitchPartFile') | finish | endif

function! s:SwitchPartFile()
  let current_file = expand('%')

  let target_file = substitute(current_file, '\v(\.g)?\.dart$', '.g.dart', '')
  if target_file == current_file
    let target_file = substitute(current_file, '\v(\.g)?\.dart$', '.dart', '')
  endif

  if filereadable(target_file)
    exe 'e '.fnameescape(target_file)
  else
    echoh ErrorMsg | echo 'Target file not readable.' | echoh None
  endif
endfunction

まだ使い込んでいるわけじゃないんで便利かよくわからないんですけども、同じように困っている方の助けになれば。

GitHubで編集を提案

Discussion