0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【vim】最近作ったプラグインの話

Posted at

チュートリアルアニメーション

のプラグインを作りました。
基本操作を、vim上のpopupなどでアニメーションさせるものです。

ちょっと紹介

最初にテスト用ドキュメントを開きます。
時間を直接指定して、⚪︎秒後にポップアップ、、等をしているだけ。

let s:training_popup_cursor1_winid = 0
let s:training_popup_cursor2_winid = 0
let s:training_popup_window1_winid = 0
let s:training_popup_window2_winid = 0
let s:training_popup_mode1_winid = 0
let s:training_popup_mode2_winid = 0
let s:training_popup_search_winid = 0
let s:training_popup_opeobj_winid = 0
let s:training_popup_tips_winid = 0
let s:training_popup_tips_win_flg = 0
let s:training_popup_tips_win_tid = 0

fu! s:trainingWheelsPopupsActivate()
    cal s:trainingWheelsPracticeFileCreate()
    cal s:trainingWheelsPopupsAllClose()
    let s:training_info_idx = 0
    hi TrainingNotification ctermfg=green guifg=green
    hi Traininginfo ctermfg=cyan guifg=cyan cterm=BOLD gui=BOLD
    cal popup_notification([
        \'             = Infomation =          ',
        \' Training Wheels Protocol Activated.',
        \'  ↓Create and Open practice file. ',
        \'   ~/practice.md. ',
        \'  ',
        \' To DeActivate',
        \' :TrainingWheelsProtocol deactive'
        \],#{border:[],
        \zindex:999,
        \highlight:'TrainingNotification',
        \time:3000})
    cal timer_start(1000, function('s:trainingInfo'))
    cal timer_start(6000, function('s:trainingInfo'))
    cal timer_start(6500, function('s:trainingPopupCursor1'))
    cal timer_start(6500, function('s:trainingPopupCursor1SampleMv'))
    cal timer_start(10000, function('s:trainingInfo'))
    cal timer_start(10500, function('s:trainingPopupCursor2'))
    cal timer_start(10500, function('s:trainingPopupCursor2SampleMv'))
    cal timer_start(15000, function('s:trainingInfo'))
    cal timer_start(15500, function('s:trainingPopupWindow1'))
    cal timer_start(15500, function('s:trainingPopupWindow1SampleMv'))
    cal timer_start(20000, function('s:trainingInfo'))
    cal timer_start(20500, function('s:trainingPopupWindow2'))
    cal timer_start(20500, function('s:trainingPopupWindow2SampleMv'))
    cal timer_start(26000, function('s:trainingInfo'))
    cal timer_start(29000, function('s:trainingInfo'))
    cal timer_start(29500, function('s:trainingPopupMode1'))
    cal timer_start(32000, function('s:trainingInfo'))
    cal timer_start(35000, function('s:trainingInfo'))
    cal timer_start(35500, function('s:trainingPopupMode2'))
    cal timer_start(35500, function('s:trainingPopupMode2SampleMv'))
    cal timer_start(38000, function('s:trainingInfo'))
    cal timer_start(38500, function('s:trainingPopupSearch'))
    cal timer_start(38500, function('s:trainingPopupSearchSampleMv'))
    cal timer_start(42000, function('s:trainingInfo'))
    cal timer_start(45000, function('s:trainingInfo'))
    cal timer_start(45500, function('s:trainingPopupOpeObj'))
    cal timer_start(45500, function('s:trainingPopupOpeObjSampleMv'))
    cal timer_start(49000, function('s:trainingInfo'))
    let s:training_popup_tips_win_tid = timer_start(49500, function('s:trainingPopupTips'))
    cal timer_start(49500, function('s:trainingPopupTipsCursor'))
    cal timer_start(52000, function('s:trainingInfo'))
endf

といった感じ。各関数では、呼び出されると
ポップアップ表示に加えて、実際のテスト用ドキュメントに操作を行います。

例えば一番最初にカーソルの動かし方をポップアップしますが

    cal timer_start(6500, function('s:trainingPopupCursor1'))
    cal timer_start(6500, function('s:trainingPopupCursor1SampleMv'))

ここで呼び出している関数は以下のようになっています。

trainingPopupCursor1.vim
" cursor move
fu! s:trainingPopupCursor1(timer)
    let s:training_popup_cursor1_winid = popup_create([
        \'     ↑ k ',
        \' h ←   → l ',
        \'   j ↓  ',
        \],#{title: ' cursor move ',
        \border: [], zindex: 1,
        \line: 3,
        \col: &columns - 46
        \})
    cal matchaddpos("Identifier", [[1,10],[2,2],[2,14],[3,4]], 16, -1, #{window: s:training_popup_cursor1_winid})
endf
trainingPopupCursor1SampleMv.vim
fu! s:trainingPopupCursor1SampleMv(timer)
    execute("norm gg")
    cal cursor(26, 6)
    cal timer_start(600, function('s:trainingPopupCursor1SampleMv1'))
    cal timer_start(1200, function('s:trainingPopupCursor1SampleMv2'))
    cal timer_start(1800, function('s:trainingPopupCursor1SampleMv3'))
    cal timer_start(2400, function('s:trainingPopupCursor1SampleMv4'))
endf
fu! s:trainingPopupCursor1SampleMv1(timer)
    execute("norm h")
    echo("h   cursor move")
endf
fu! s:trainingPopupCursor1SampleMv2(timer)
    execute("norm j")
    echo("j   cursor move")
endf
fu! s:trainingPopupCursor1SampleMv3(timer)
    execute("norm l")
    echo("l   cursor move")
endf
fu! s:trainingPopupCursor1SampleMv4(timer)
    execute("norm k")
    echo("k   cursor move")
endf

このように、ポップアップ(+色付け)の表示後に、
execute("norm h")のようにしてサンプル操作を行います。

※ポップアップに色付けしたサンプル
image.png

ほんとは動かすタイミングで、ポップアップの色付けも押してるキーの色だけつける、とかしたかったんですが
長いので断念しました。。

完成イメージ

アニメーションが全て終わると
image.png
こんな感じになります。

左側が空いてるので、実際の操作をしながらチートシートを見られる感じ。

結構殴り書きで作った感じがあるので、本当に初心者がチュートリアルにできるのかは分からないです、、あくまでネタ的なものですね。。

キーマップ多すぎ問題改善系

忘れる、というより久しぶりに使うときにパッとキーを思い出せずにストレスなことがあるのではないでしょうか?

いつもは使わないが、ここぞという時に使いたいものを
メニューにまとめてしまおうということでプラグインに。

もともと自分用にvimrcにいたものをプラグインに吐き出しただけでもあります。

IDE メニュー

※README等いろいろ置き去りになってて、今ではもっと機能が多いです

image.png

基本的に、IDE系にするプラグインではLSPの機能が多すぎて
全てをkeymapするのは無理です。
だいたいみなさん

  • ファイラ<leader>f
  • エクスプローラ<leader>e
  • 定義元に飛ぶgd <leader>d
  • 参照元一覧だすgr <leader>r
  • 次/前のエラーに<leader>, <leader>.
  • 関数のドキュメント見る<leader>?

などしてると思います。私はほぼこれの通りにしてます。
では

  • フォーマット
  • リネーム

はというと、
formatfはファイラと被り、renamerも参照元と被りです。
けどいうほどフォーマッタもリネームもしないと思いますので、メニューから呼び出すでよくね?という思想。
ついでに、スニペットの編集やプログラム実行、デバッグも入れちゃいました。

依存プラグイン等、詳細はREADMEを参照ください。

どういう内容?

メニューのリストと、選んだ時どうするかを
popup_menuにしているだけ。

メニュー内容を定義.vim
let s:idemenu = #{
    \ pmenu_default: [],
    \ menuid: 0, mttl: ' IDE MENU (j / k) Enter choose ',
    \ menu: [
        \ '[⚖️  Format]   format CocActionAsync',
        \ '[♻️  ReName]   rename CocActionAsync',
        \ '[🎨 Snippet]  ultisnips edit',
        \ '[⚡️ Run]      quickrun',
        \ '[⚙️  Debug]    vimspector',
    \ ],
    \ }
ポップアップつくる.vim
fu! s:idemenu.open() abort
    let self.menuid = popup_menu(self.menu, #{title: self.mttl, border: [], borderchars: ['─','│','─','│','╭','╮','╯','╰'],
        \ callback: 's:idemenu_exe'})
    cal setwinvar(self.menuid, '&wincolor', 'String')
    hi DarkRed ctermfg=204
    cal matchadd('DarkRed', '\[.*\]', 16, -1, #{window: self.menuid})
    let self.pmenu_default = execute('hi PmenuSel')[1:]->split(' ')->filter({_,v->stridx(v, '=')!=-1})
    hi PmenuSel ctermbg=232 ctermfg=114
endf
コールバックで、選ばれた時の挙動.vim
fu! s:idemenu_exe(_, idx) abort
    if a:idx == 1
        cal CocActionAsync('format')
    elseif a:idx == 2
        cal CocActionAsync('rename')
    elseif a:idx == 3
        exe 'UltiSnipsEdit'
    elseif a:idx == 4
        let args = input('stdin>')
        cal system('touch .quickrun.tmp.stdin.txt && echo "'.args.'" > .quickrun.tmp.stdin.txt')
        sil! exe 'QuickRun <.quickrun.tmp.stdin.txt'
        cal system('rm .quickrun.tmp.stdin.txt')
    elseif a:idx == 5
        cal vimspector#LaunchWithSettings({'configuration': &filetype})
    endif
    exe 'hi PmenuSel '.join(s:idemenu.pmenu_default, ' ')
    retu 0

あとは、これを増やしたければどんどん増やすだけです。

作っては無いですが
メニュー内容をjsonとかで別ファイルに持ち、読み込むようにすれば
汎用的なメニュー作成プラグインとなりますが

まぁ需要がそこまでなさそくなので各自フォークしてソースいじった方がはやそう。

さらにデバッグメニュー

ついでに作りました。
※これもREADME等いろいろ置き去りになってて、今ではもっと機能が多いです

image.png

input outputファイルがある時等、競技プログラミングみたいな状況だと便利なので用意しました。
これは特に汎用的ではないですが、acc ojコマンドの呼び出しインターフェースとして作った機能がvimrcの中に溜まっていて行数かさんでいたので、外だししました。

結局これらも

  • vim内でコマンド作ったが覚えてないので呼び出せない
  • にしてはキーマップも、余っているキーがない

のでメニューにしたという流れ。
機能の詳細はやっぱりレポを参照ください。

(紹介)which-key

公式デモ
image.png

キーを押して、「あれ、次何押すんだっけ?」としている間にメニューが出てくれます。
自分用のkeymapチートシートなんて作る必要がなくなります!

(紹介)コマンドパレット

VSCodeやchrome等のdevツールのように、コマンドをfuzzy検索して実行できるというもの。
キーバインドというより、増えすぎて思い出しにくいコマンドを呼ぶ時に便利。

最後に

自分用に機能を作ると、vimrcが膨れ上がるので
積極的にプラグインにして[vim-plug](https://github.com/junegunn/vim-plug)などで管理しましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?