endaaman.com

2017-11-28

Tips

Neomakeを使いこなせ!

syntasticから移行した

syntasticのlintが同期的にしか実行できなくて非同期でできるものを探していて、aleは微妙に設定に苦しいところがあったのでNeomakeに移行した。

基本設定

[[plugins]]
repo = 'neomake/neomake'
if = ''' 1 '''
hook_add = '''
  let g:neomake_open_list = 0
  autocmd! BufWritePost,BufEnter * Neomake
  let g:neomake_error_sign = {
  \ 'text': '',
  \ 'texthl': 'Error',
  \ }
  let g:neomake_warning_sign = {
  \ 'text': '',
  \ 'texthl': 'Error',
  \ }
  let g:neomake_info_sign = {
  \ 'text': '',
  \ 'texthl': 'Title',
  \ }
  let g:neomake_message_sign = {
  \ 'text': '',
  \ 'texthl': 'Operator',
  \ }
'''

Deinではtomlでプラグインを管理してるので、こんな感じのエントリを追加する。

Quickfixは使わないけど、使う可能性もあるかもしれないので記述だけ残しておく。NerdFontを使っているので、ブラウザだと記号が読めないかも。

ryanoasis/nerd-fontsを見ながらインサートで <C-v>u を続けて押すとユニコードを直接打てるようになるので、そこで使いたいグリフのコードを入力していく。

使う色は

so $VIMRUNTIME/syntax/hitest.vim

を見て好きなものを使う。

各言語の設定

自分はプロジェクトの.vim/をignoreしていて、.vim/init.vimがあれば実行するようにしている。こういう設定はプロジェクごとに異なるのでそこに書いていく。

C言語

gcc -fsyntax-only を使う。

let g:cflags = system('pkg-config --libs --cflags gtk+-3.0 vte-2.91 lua53')
let g:neomake_c_enabled_makers = ['gcc']
let g:neomake_c_gcc_args = split(g:cflags) + [
  \ '-fsyntax-only',
  \ '-std=c11',
  \ '-Wall',
  \ '-Wbad-function-cast',
  \ '-Wcast-align',
  \ '-Wdisabled-optimization',
  \ '-Wextra',
  \ '-Wfloat-equal',
  \ '-Wformat=2',
  \ '-Winline',
  \ '-Wno-missing-field-initializers',
  \ '-Wno-pointer-sign',
  \ '-Wno-sign-compare',
  \ '-Wno-unused-parameter',
  \ '-Wpointer-arith',
  \ '-Wredundant-decls',
  \ '-Wstrict-aliasing=2',
  \ '-I./include',
  \ ]
let g:c_syntax_for_h = 1

たとえば自分が開発してるendaaman/tymなら、pkg-configを使っているので、コンパイルに必要なオプションをg:cflagsに入れてg:g:neomake_c_gcc_args に渡す。

headerファイルはcppとCで区別が点かないので、Cとして扱うことをNeomakeに教えてあげる。

Android

javac -Xlint を使う。

準備として、gradleプラグインを書いてチェックに必要なclasspathとsourcepathを書き出す。

// cp.gradle
class ClasspathPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.task('cp') {
            doLast {
                def pair = project
                    .rootProject
                    .allprojects
                    .findResult {
                        def a = it.getExtensions().findByName('android')
                        a ? [a, it] : null
                    }
                if (!pair) {
                    println 'can not find android plugin'
                    return
                }
                def (android, targetProject) = pair
                def cp = [android.getBootClasspath()[0]]
                def sp = []
                android.applicationVariants.all { v ->
                    if (v.metaClass.respondsTo(v, 'getApkLibraries')) {
                        cp += v.getApkLibraries()
                    } else {
                        cp += v.getCompileClasspath().collect { it.getPath() }
                    }
                    def dir = new File("${targetProject.buildDir}/generated/source")
                    if (dir.exists()) {
                        dir.traverse([maxDepth: 0, type: groovy.io.FileType.DIRECTORIES]) {
                            sp += "${it.getPath()}/${v.getName()}"
                        }
                    }
                }
                def cp_str = cp.collect({ ":${it}" }).join('')
                def sp_str = sp.collect({ ":${it}" }).join('')
                new File('.vim/classpath.vim').write("let g:classpath = '${cp_str}'")
                new File('.vim/sourcepath.vim').write("let g:sourcepath = '${sp_str}'")
            }
        }
    }
}

rootProject {
    apply plugin: ClasspathPlugin
}

Androidプラグインのバージョンによって、ApplicationVariantからの依存ライブラリのパスのとり方が変わるところ(古いのはgetApkLibraries()、新しいのはgetCompileClasspath()を使う)、あと一回ビルドしないとR.javaとかが見つからないので、その辺りに気をつける。

$ ./gradlew -I cp.gradle -q cp

で実行し、.vim/classpath.vim.vim/sourcepath.vimに追加のclasspathをsourcepathを書き出す。

execute 'source ' . getcwd() . '/.vim/sourcepath.vim'
execute 'source ' . getcwd() . '/.vim/classpath.vim'

let g:neomake_java_enabled_makers = ['javac']
let g:neomake_java_javac_classpath = g:classpath
let g:neomake_java_javac_options = ['-Xlint', '-sourcepath', getcwd() . '/app/src/main/java:' . g:sourcepath]

Androidは少しclasspathやsourcepathの取り方が普通のJavaとは少し違うのに注意したい。


©2024 endaaman.com