vimでRustを書く(環境構築)
周囲の人たちから「Rustいいよ」、「Rust書こうよ」とポツポツ言われるので流れにのって入門してみることにしました。
といっても今回やるのは環境構築のみ。Rustさっぱりなので、慣れてきたら適当にメモを書いていきます。
私が普段vimでコードを書いているのでvimで書くまでを目標にします。
やること
Rustのインストール
macでhomebrewを使うと以下でできるみたいですが、私はmac使いじゃないので公式ページに書かれてる方法を使います
brew install rust
公式ページは以下
インストール方法は以下
curl https://sh.rustup.rs -sSf | sh
上記のコマンドで、rustrcとcargoが入ります。
rustfmtとracerのインストール
rustfmtとracerについて簡単に説明すると、rustfmtはRustのガイドラインにしたがって、Rustで書かれたソースをフォーマットしてくれるツールです。racerはRustのコード補完ツールみたいです(詳しいことは知らない)
これらはそれぞれcargoで入れられます。cargoはRustのパッケージ管理ツールです。 rustfmtとracerのインストールは以下
cargo install rustfmt cargo install racer
難しいこと考えなくていいのでいいんですね。こういうの好きです。
rust.vimとvim-racerのインストール
私がdein.vimを使ってるのでそれに準ずる方法でインストールします。toml使ってplugin管理してる人が多いと思いますが、めんどくさかったのでvimrcに直書きしてます。すいません。
vimrcに追記したのは以下
call dein#add('rust-lang/rust.vim') call dein#add('racer-rust/vim-racer')
自動でフォーマットするようにする
rustfmtを入れたのでどうせなら保存したら自動でフォーマットしてくれると助かります。
追記したのは以下
let g:rustfmt_autosave = 1
まとめ
今回は自動フォーマットまでをまとめました。結局のところ、まだRust書いてないので、ぼちぼち書いていこうと思います。
追記
衝撃の事実。homebrewでインストールしたrustのcargoを使って、rustfmtをインストールしようとするとエラーで落ちるっぽいです。
goでconnpassのイベントを検索するslackbotを作ってみた
つい最近のGoogle I/Oでkotlinがandroidアプリ開発の公式言語に追加された影響か、大したこと書いてないですが意外にアクセスが来ていて嬉しい限りです。 とりあえず間違った情報は流さないようにしたいと思います。
今回は今までのandroid + kotlin押しとは打って変わって、golangでslackbotを作ってみたというお話です。
最近仕事でslackを使い始めたので、slackに慣れるついでにslackbotを作ってみましたというのがモチベーションです。 connpassを選んだ理由はAPIで提供している機能が検索しかないので、とりあえずで実装してみる分にはそこまで難しくなさそうというだけです。
書いたコードは以下
実装内容
使用したライブラリ
goからslackのapiを扱うためにslackを使用 github.com
APIリクエストを投げるためにgoreqを使用 github.com
詰まったところ
今回botを作る上で実装したいと考えていたのは以下の二点です。 - botを呼び出した人にmentionを飛ばすようにする - コマンドを幾つか用意する
この中で「botを呼び出した人にmentionを飛ばすようにする」で若干つまりました。
やってみると意外に簡単で飛ばすメッセージに"<@飛ばす先のアカウントID>“を付加するだけで大丈夫でした。
まとめ
だいぶざっくりした感じになってしましましたが、やってみると意外に簡単にできるので試しに作ってみてもいいかもしれません。
spark(web framework)で遊んでみようとしたら最初の実行で怒られた
sparkで簡単なWebアプリを作ってみようと思ったのですが、詰まったのでメモ。
詰まったのは起動方法です。 ただHello Worldをさせようと思ったのですが、そこで詰まりました。 エラーは以下です。
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
調べてみると、gradleに記述したライブラリでslf4jを使用しているものがあり、slf4jをインストールする必要があるみたいです。 加えて、slf4jの設定ファイルをsrc/main/resourcesに追加する必要があります。
以下の記事を参考にさせていただきました。
onBackPressedの落とし穴
onKeyDownをonBackPressedに切り替えて使ってみたら、問答無用で遷移前のActivityに戻されてしまう現象に遭遇しました。正直中途半端な知識で使うのはどうかと思っていたので、内部でどのような動作をしているか少し調べてみました。
ソースコードをどんどん辿っていったところ、onBackPressedが定義されているのは、Activity.javaの内部です。同様にonKeyDownもActivity.javaにありました。
実装されていたonBackPressedは以下です。
コメントを見るだけで何やら不穏な空気が漂っていますね。とりあえず簡単な実装として、何かするためにonBackPressedをoverrideできるときは現在のActivityを終了しますとのこと。
/** * Called when the activity has detected the user's press of the back * key. The default implementation simply finishes the current activity, * but you can override this to do whatever you want. */ public void onBackPressed() { if (mActionBar != null && mActionBar.collapseActionView()) { return; } if (!mFragments.getFragmentManager().popBackStackImmediate()) { finishAfterTransition(); } }
終了処理は、finishAfterTransitionっぽいですね。Fragmentのスタックから何も取り出せないとき(addToBackStackとかしてない)にこの処理に入ります。次にfinishAfterTransitionを見てみます。
ActivityTransitionStateはActivityの遷移状況を管理しているんですかね。ソース眺めてみましたが、他のものと違って色々知識が必要なので、メソッド名の字面から判断します。
/** * Reverses the Activity Scene entry Transition and triggers the calling Activity * to reverse its exit Transition. When the exit Transition completes, * {@link #finish()} is called. If no entry Transition was used, finish() is called * immediately and the Activity exit Transition is run. * @see android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, android.util.Pair[]) */ public void finishAfterTransition() { if (!mActivityTransitionState.startExitBackTransition(this)) { finish(); } }
すべてを理解しきれたわけではありませんが、onBackPressedの行き着く先にはfinishがいることがわかりました。ちらっとonKeyDownも眺めてみましたが、実のところ、内部でonBackPressedを呼んでいたので使う際は注意が必要かもしれません。
PS Android Studioのどんどんメソッドを辿っていける機能、ソース読むときにかなり便利だということに気づきました。
SearchViewの背景色を変更する
SearchViewを導入して、クエリを入力して検索するところまで出来たので、今度はSearchViewの見た目自体を変更しようとしたのですが、かなり詰まったので、その際に調べた内容をまとめます。
SearchViewは他のViewとは微妙に異なっていて、SearchView自体が複数のViewから構成されるViewになっています。具体例で言うと、実際にクエリを入力するEditTextや検索アイコンのImageViewなどが内部で定義されています。なので、アイコンを変えたり背景色を変えたいという場合は、その内部で定義されているViewを変更してあげれば大丈夫です。
今回、SearchViewの背景色を変更したかったので、以下のようにしました。
override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.main, menu) val menuItem = menu.findItem(R.id.action_search) val searchView = MenuItemCompat.getActionView(menuItem) as SearchView searchView.findViewById(android.support.v7.appcompat.R.id.search_edit_frame) .setBackgroundColor(R.color.white) // 以下任意の処理 }
これでSearchViewの背景色を変更することができました。他にもsearch_mag_icon(検索アイコン)だったり、search_close_button(☓ボタン)があったりします。SearchViewの何かしらを変更する際は、SearchViewの子要素を色々変更するといいかもしれません。
SearchViewを使用する
GmailやFacebookアプリみたいな検索窓を実装したいなーと考え色々調べていると、SearchViewを使用する方法がだいぶ簡単そうだったので、試してみた。
SearchViewのdocumentは以下 SearchView | Android Developers
配置するだけならすごく簡単でToolbarのxmlにSearchViewのitemを配置するだけ。肝心なのは、actionViewClassにSearchViewのクラスを指定してあげることです。
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:title="Search" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="always"/> </menu>
次にSearchViewからのアクションを扱う方法です。今回使用したのは、onQueryTextSubmitです。検索するクエリを入力したあとでsubmitした時に呼ばれるメソッドです。何かを検索する場合、onQueryTextSubmitをoverrideして、内部でAPIを叩く処理を書いたりするいいと思います(間違ってたらごめんなさい)。あとは検索したときのProgressBarを見えるようにするとかかな。
override fun onQueryTextSubmit(query: String?): Boolean { // queryがsubmitされたときに期待する動作を記述する }
WebViewでロード時にProgressBarを表示する
WebViewロード時にProgressBarを表示する WebViewでローディングしているときの画面が真っ白でほんとにローディングしているのか不安になるので,ProgressBarを表示してローディングしているっぽくすることにしました.
WebViewは設定するWebViewClientをいじることである程度の操作を行うことができるみたいです(まだ全容は把握していない)
今回は,ページのローディングの開始時(onPageStarted)と終了時(onPageFinished)の処理をいじることでProgressBarを表示します.
具体的なコードは以下
webView.setWebViewClient(object : WebViewClient() { override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) progressBar.visibility = View.VISIBLE } override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) progressBar.visibility = View.GONE } })
これでなんとなくローディングしてるっぽい感じになりました!