deoplete環境でneosnippetを使えるようにする
neosnippetはスニペットを挿入できるプラグインだが、機能的にdeopleteと干渉する部分があるので少し工夫をする必要がある。
メモ程度に設定方法を残しておく。
参考:neovim で deoplete + neosnippet の連携をする
導入
dein.tomlとdein_lazy.tomlに以下のとおりに追記する。
※tomlファイルを活用しているが、hook_post_source内のスクリプトをinit.vim内に書けば同じことである。
[dein.toml] [[plugins]] # snippets repo = 'Shougo/neosnippet-snippets'
[dein_lazy.toml] [[plugins]] # neosnippet repo = 'Shougo/neosnippet.vim' hook_source = ''' "Ctrl+Kにターゲットジャンプ割当 imap <C-k> <Plug>(neosnippet_expand_or_jump) smap <C-k> <Plug>(neosnippet_expand_or_jump) xmap <C-k> <Plug>(neosnippet_expand_target) if has('conceal') set conceallevel=2 concealcursor=niv endif ''' on_i = 1 on_ft = ['snippet'] depends = ['neosnippet-snippets'] [[plugins]] # deoplete repo = 'Shougo/deoplete.nvim' hook_source = ''' let g:deoplete#enable_at_startup = 1 "Tab補完の設定 inoremap <expr><tab> pumvisible() ? "\<C-n>" : \ neosnippet#expandable_or_jumpable() ? \ "\<Plug>(neosnippet_expand_or_jump)" : "\<tab>" ''' on_i = 1
操作方法
- Ctrl+Nで候補切り替え
- 候補を選択した状態でCtrl+Kでスニペット挿入
- 以後Ctrl+Kで入力位置移動
deinを真面目に設定してみる(TOML)
deinはvimrcに設定を書くだけでも使える。
しかし、一般的にはTOMLと呼ばれる外部ファイルに書くらしい。
TOMLファイルを利用する
とりあえずTOMLを使う準備をしよう。
init.vimに以下の記述を追加する。
set runtimepath+=~/.vim/dein/repos/github.com/Shougo/dein.vim let s:dein_dir = expand('~/.vim/dein') let s:toml_dir = expand('~/.config/nvim') "dein settings if dein#load_state(s:dein_dir) call dein#begin(s:dein_dir) "Load TOML let s:toml = s:toml_dir . '/dein.toml' let s:lazy_toml = s:toml_dir '/dein_lazy.toml' call dein#load_toml(s:toml, {'lazy': 0}) call dein#load_toml(s:lazy_toml, {'lazy': 1}) "finalize call dein#end() call dein#save_state() endif
この設定では、
となっている。必要に応じて該当箇所を変更すること。
起動時ロードと遅延ロード
次は、TOMLファイルに使いたいプラグインを列挙する。
ここで一つ注意する必要があるのが「遅延ロード」の存在だ。
今まで普通にdeinを使っていれば、プラグインは起動時にロードされていた。
しかし、「遅延ロード」を用いると、起動時より少し後にプラグインがロードされる。
これを用いることにより、起動時のロードを最小限にできることで起動速度が上がるらしい。
では、実際にTOMLを書いてみよう。
まずは起動時用。
# [dein.toml] #以下のようにレポジトリ名を書くだけで良い [[plugins]] repo = 'Shougo/dein.vim' [[plugins]] # Lighline repo = 'itchyny/lightline.vim' [[plugins]] # tender repo = 'jacoborus/tender.vim'
ここでは利用していないが、他にもカスタマイズができるらしい。
参考:dein.vimによるプラグイン管理のマイベストプラクティス - Qiita
次に、遅延ロード用。
# [dein_lazy.toml] [[plugins]] # deoplete repo = 'Shougo/deoplete.nvim' hook_post_source = ''' let g:deoplete#sources#clang#libclang_path = '/usr/lib/llvm-3.8/lib/libclang-3.8.so.1' let g:deoplete#sources#clang#clang_header = '/usr/include/clang' let g:deoplete#enable_at_startup = 1 ''' [[plugins]] # deoplete-clang repo = 'zchee/deoplete-clang'
基本は起動時用と同じだが、遅延ロードでは「hook_post_source」というオプションが利用できる。
これは、プラグインが遅延ロードされた直後に実行するコマンドを指定するものである。
プラグインの追加設定をiniv.vimに書くとロード前に実行されてしまうので、それを防ぐためにここに書く。
とりあえず導入だけをやってみた。
有り難みもそのうちわかってくるようになるんだろう、多分。
Doxygenを導入してみる
Doxygenはソースに埋め込んだコメントを元にドキュメントを作成するツール。
メモ程度に導入方法をまとめておく。
導入
sudo apt -y install doxygen doxygen-gui graphviz
あとは、
doxywizard
を実行すればGUIが出てくるので、ウィザード通りにすすめる。
スニペット
ファイル
/** * @file * @brief * @author * @date * @details */
@file ファイル名(必須) @brief 一行説明(必須) @author 作成者 @date 作成日 @details 詳細説明
関数
/** * @fn * @brief * @param * @retval * @details */
@fn プロトタイプ宣言(必須) @brief 一行説明(必須) @param 引数 構文:@param[in/out] <引数名> <説明> @retval 戻り値 構文:@retval <値> <説明> @details 詳細説明
変数
//! 説明
変数宣言行の上に書く。
クラスとかは上3つを組み合わせればいける。
参考文献
補助ライブラリでサクッとOpenGL(GLFW,GLEW)
OpenGLはプラットフォーム独立のライブラリだが、ウィンドウ管理などの面倒は見てくれない。
また、シェーダーを使うのには拡張機能を有効化する必要がある。
ウィンドウ管理や拡張機能の取得はプラットフォームごとに違うので、生のGLを扱うとそれなりに労力がかかる。
そこで、補助ライブラリを使ってサクッとこの問題を解決する。
1.入力・ウィンドウ管理:GLFW
GLFWはOpenGLの補助ライブラリで、
- ウィンドウ管理や入力デバイスの制御を担当
- 出来る限りシンプルな機能構成(Teapotや文字出力なし)
- 2017年8月現在もメンテナンスが続いている
といった特徴がある。
導入
linuxならaptで入れる。
sudo apt -y install libglfw3-dev
Windowsならバイナリを直接入手できるらしい。 VSならNuGetもアリ。
2.拡張機能管理:GLEW
GLEWはGLFWと名前が似ていて紛らわしいが、
という感じである。
ちなみにOpenGLの拡張機能取得はそれ自体が結構面倒なので、それを簡略化してくれるGLEWはマルチプラットフォームを視野に入れていなくても十分有用である。
導入
こいつもaptで可。
sudo apt -y install libglew-dev
Windowsの場合はGLFWと同様バイナリを取ってくる。 やはりこいつもNuGetパッケージがある。
とりあえず初期化だけやってみる
C++で書くとこんな感じか。
#include <iostream> #include <string> #include <GL/glew.h> #include <GLFW/glfw3.h> class LogManager { public: LogManager(){}; //Info out void LOGI(std::string msg) { std::cout << msg << std::endl; } //Error out void LOGE(std::string msg) { std::cerr << msg << std::endl; } }; class App { public: App(LogManager *log) : m_log(log) {}; bool run() { if(!init()) return false; while(glfwWindowShouldClose(m_win) == GL_FALSE) { glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(m_win); glfwWaitEvents(); } terminate(); return true; }; private: LogManager *m_log; GLFWwindow *m_win; bool init() { if(!init_glfw()) { m_log->LOGE("Failed to initialize GLFW."); terminate(); return false; } m_log->LOGI("GLFW Initialized."); if(!init_window(640, 480, "SAMPLE")) { m_log->LOGE("Failed to initialize window."); terminate(); return false; } m_log->LOGI("Window Initialized."); //必ずGLEW初期化より前 glfwMakeContextCurrent(m_win); if(!init_glew()) { m_log->LOGE("Failed to initialize GLEW."); terminate(); return false; } m_log->LOGI("GLEW Initialized."); glClearColor(1.0f, 1.0f, 1.0f, 0.0f); return true; } void terminate() { glfwTerminate(); } bool init_glfw(void) { if(glfwInit() == GL_FALSE) return false; return true; } bool init_window(int width, int height, std::string title) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); m_win = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); if(m_win == nullptr) return false; return true; } bool init_glew(void) { GLenum err; err = glewInit(); if(err != GLEW_OK) { m_log->LOGE( "GLEW Error :" + std::string((char*)glewGetErrorString(err)) ); return false; } return true; } }; static LogManager s_logman; int main(void) { App app(&s_logman); return app.run() ? 0 : -1; }
初期化の順としては
- GLFW初期化
- GLFWでウィンドウ初期化
- GLFWでコンテキスト有効化(glfwMakeContextCurrent)
- GLEW初期化
となる。
特に、GLEWの初期化にはコンテキストが有効である必要があるので注意する。
以降は、App.run()のようにループを組み、自由にOpenGLを利用する。
追記:コンパイルオプション
ライブラリ名の指定が迷いそうになるが、
$(LDFLAGS) = -lglfw -lGLEW -lGL
でOK。
タブ独立のファイルツリーで快適コーディング
やはり、ファイルツリーをVim内で開いておけると何かと便利だ。
ファイルツリーといえばNERDTreeが有名だが、それのタブ独立版があるそうなので試してみた。
vim-nerdtree-tabsのインストール
まずはプラグイン導入から。
vimrcに追加
call dein#add('scrooloose/nerdtree') call dein#add('jistr/vim-nerdtree-tabs')
そして、
call dein#install()
で完了。
使い方
:NERDTreeTabsOpen
で即座に開く。操作方法は通常のNERDTreeと全く同じである。
本家と違うのは、新規にタブを生成したり、画面を分割したりしても一切影響を受けないという点だ。
ファイルフィルタ
中間生成ファイルが見えると邪魔なことがある。そのようなときにはフィルタを活用しよう。
例えば*.oファイルをフィルタするには、vimrcに以下の行を追加する。
let g:NERDTreeIgnore = ['\.o']
そして、NERDTree内で「f」キーを押すとフィルタの有無が切り替わる。
C++補完用にdeoplete-clangを導入する
コードを書くにはやっぱり補完がないと辛い。
C++をNeoVimで書くならdeoplete-clangがベストチョイスのようだ。
導入
deopleteはNeoVimのRemotePlugin機能を使うのでpython-clientを入れておく必要がある。
以下のコマンドでインストールできる。
sudo apt -y install python3-pip
pip3 install neovim
次はプラグイン導入。
init.vimに以下を追加する。
call dein#begin() "(中略) call dein#add('Shougo/deoplete.nvim') call dein#add('zchee/deoplete-clang') "(中略) call dein#end() "deoplete settings let g:deoplete#sources#clang#libclang_path = '/usr/lib/llvm-3.8/lib/libclang-3.8.so.1' let g:deoplete#sources#clang#clang_header = '/usr/include/clang'
続いて、インストール作業。
:call dein#install() :UpdateRemotePlugins
これで正しくdeoplete及びdeoplete-clangがインストールされた。
所感
外部ライブラリのヘッダ等もちゃんと解析している模様。
Intellisenseとも遜色なく、十分に使い勝手が良いと思う。
ただ、#includeディレクティブそのものの補完はしないのでneoincludeも組み合わせるといいだろう。