typeof Diary

VimとかJSとか。やったことのメモ。自分のため。

Observableの結合のこと

今年はブログ書くって言うたので書いてみます。
ネタは別のとこに書いたやつではあるけど。

前の記事でも触れていますが、昨年の秋ごろからAngularを触っています。 Angularでngrx使いつつです。

ことのなりゆき

(本題だけなら飛ばしてね)

年末にふとng-japanのSlackに以下の質問。

  • ngrxのeffects内でstoreのデータを使いたい場面に出くわした。
  • withLatestFrom(this.store$.select(fromRoot.getSelectedId))みたいにして繋げてしまうのはありなのか?

背景的には、選択中のカテゴリに属する記事を一覧表示。
その一覧から記事を削除したとき、表示中の一覧を更新したい。
更新用のAPI呼びたいけど、選択中のカテゴリIDがほしい。  みたいな、結構あるあるな状況ではないでしょうか?

もらった回答が、

  • withLatestFromでも良いけど、このケースならActionのpayloadにID含めて渡すのはどうか?

言われてみれば、確かに。。。

いざ実装してみると、payloadを次に渡してあげないといけなくて、どうするんだろう?

foo$: this.actions$.pipe(
  ofType(ActionName),
  map(action => action.payload),
  mergeMap(payload => {
    return this.api.fetchList().pipe(
      map(...)
      catchError(...)
    )
  }),
  mergeMap( /*ここにpayloadがほしい */
  ...

forkJoinを使ってまとめたらとやりたいことはできたのですが、テストが通らない。。。
なんで・・・?

理由は、結合方法にも何パターンかあって、それぞれの動きが異なるから。
この辺りちゃんと理解せずやったのでハマりました。

結合方法

Observableを結合するには、何パターンか方法があります。

  1. zip
  2. combineLatest
  3. forkJoin
  4. withLatestFrom

ざっくりこの4つ。

こんなObservableがあるとして・・・

const observable1 = Rx.Observable.interval(1000).map(x => x).take(5)
const observable2 = Rx.Observable.interval(2000).map(y => y + 1).take(5)

それぞれsubscribeすると、

observable1.subscribe(x => console.log(x))
// 0 - 1秒間隔で
// 1
// 2
// 3
// 4

observable2.subscribe(y => console.log(y))
// 1 - 2秒間隔で
// 2
// 3
// 4
// 5

こんな感じでobservable1は1秒間隔で0〜4observable21〜5が出力されます。
これを使ってそれぞれの違いを見ていきます。

zip

まずはzip

Observableのそれぞれの値から順に値が計算されるObservableを返す。

訳はChromeの翻訳。
意味を汲み取りましょう。

Rx.Observable.zip(observable1, observable2).subscribe(value => console.log('zip', value))

// 出力間隔を見るためのカウンター
const counter = 0
const interval = setInterval(() => {
  console.log(counter++)
  if (counter === 10) clearInterval(interval)
})

コンソールの出力は以下。[x, y]の形になっています。

0
1
zip [0, 1]
2
3
zip [1, 2]
4
5
zip [2, 3]
6
7
zip [3, 4]
8
9
zip [4, 5]

普通にsubscribeしたやつが、配列になっただけのような感じです。
間隔に注目してみると、observable1も2秒間隔になっています。

zipは、observable2を待って、1ペアずつ出力されている!

combineLatest

次、combineLatest

Observableのそれぞれの最新値から計算されるObservableを返す。

Rx.Observable.combineLatest(observable1, observable2).subscribe(value => console.log('combineLatest', value))

これを同じように出力してみます。

0
combineLatest [1, 1]
1
combineLatest [2, 1]
2
combineLatest [3, 1]
combineLatest [3, 2]
3
combineLatest [4, 2]
4
combineLatest [4, 3]
5
6
combineLatest [4, 4]
7
8
combineLatest [4, 5]
9

zipよりも出力回数が増えています。
zipobservable1observable2が揃って出力されていたのに対して、combineLatestはお構いなしに、その時の最新の値を出してきます。
ところどころ2連続で出力があるところはobservable2の間隔。
observable1が先に終わるので、最後の出力回数が減っているのも分かりますね。

forkJoin

次、forkJoin

全てのObservableが完了するのを待って、最後の値を返す。

Rx.Observable.forkJoin(observable1, observable2).subscripbe(value => console.log('forkJoin', value))

同じく出力します。

0
1
2
3
4
5
6
7
8
9
forkJoin [4, 5]

0〜9の間の出力がなくなりました。
observable1observable2の両方が完了したタイミングで出力されています。

withLatestFrom

withLatestFromも見ておきましょう。

ソースObservableが値を発行するたびに、その値と他の入力Observablesからの最新の値を使用して式を計算し、次にその式の出力を発行します。

これは前の3つとは少し違っています。
今回はobservable2observable1を入れて使ってみます。

observable2.withLatestFrom(observable1, (y, x) => y * x)
  .subscribe(value => console.log('withLatestFrom', value))

出力は

0
1
withLatestFrom 1 -- 1 * 1
2
3
withLatestFrom 6 -- 2 * 3
4
5
withLatestFrom 12 -- 3 * 4
6
7
withLatestFrom 16 -- 4 * 4
8
9
withLatestFrom 20 -- 5 * 4

2秒間隔で、observable2 * observable1が行われていますね。

まとめ

ユニットテストforkJoinが上手くいかなかったのは、おそらく完了を待ち続けていたのかな?
値が揃えばOKなら、zip
常に最新値でやってほしいならcombineLatest
1つのObservableに別のObservableを急に入れたいみたいな場合はwithLatestFrom

今回のも似てるようで全然違う挙動をするので、使い分けできるようにならないとなーと思いました。

mergeMapswitchMapあたりも怪しい・・・。

2018年まとめ

ブログ放置しまくってました。
2018年のまとめしときます。

2018年にやったこと

Vue.js

昨年末ぐらいからVue.jsをちまちまと触っていたこともあって、年明けからギョームの方でもVue.js使いました。 このときはVuexはまだ触っていなくて、busを使って、イベントでやり取りするような構成でやってました。

1年経って、そこそこ辛さが目立ってきました。

UIはElementUI使いました。

Electron

 GWぐらいでElectron触りました。
とはいってもrendererばっかりで、mainはほぼ書いてないので、あまりこっちの知識はつかずな感じに。
丁度Vue.js使ったあとだったこともあり、その流れでelectron-vue使って書いてました。

こっちはVuex使ってみましたが、あまり使い方が良くなかったようで、結構微妙な感じに・・・。
UIはこっちもElementUIでさくっと。

Angular

秋ぐらいからAngular触りはじめました。
あわせてTypeScriptも。

Angular + ngrxみたいな環境で絶賛やってます。
触り始める前は学習コスト高くてなんだかなーと思ってましたが、いざ触ってみると結構楽しいです。

Dart

なんとなく、触りだけやってみた。
結構サクサク書けるけど、読みやすいかと言われると微妙な印象でした。

Docker

今更!?って感じではあるのですが、やっと開発環境をDockerに作るようにできました。
やっとです。

エディタ

3/4Vim残りがVSCode

Angularをやると必然的にTypeScriptを書くことになるわけですが、やっぱりここはVSCodeの方が楽でした。
VSCodeにはVimキーバインドにするプラグインを放り込んで使ってます。
ただキーバインド(hjkl)真似てあるだけではなくて、そこそこ機能が使えるので、あまり不自由なく使えています。

1点問題があって、行数が多いファイルのとき、文字入力のラグが目立って使い物にならないのです・・・。

その他

jQueryはできず。
ReactもVueもAngularも一通り軽く触って、抜けられるような感じにはしていっていますが、jQueryガンガン使って書いたやつから、脱jQueryとはなかなかいかず、辛さだけが増している状態です。

あまりに辛くて、一部にVue.js入れてやってみたりもしました。
結構楽にはなるけど、それはそれでややこしくなって・・・。

参加したカンファレンス

PHPカンファレンス関西、Vue Fes Japan、VimConf、HTML5Confに参加しました。
来年もいろいろと参加していきたいです。

Angularのカンファレンスも行きたいな。

2019年は・・・

以前のようにブログちょいちょい書いていきたいかも。
丁度Angularやってるし。

それでは良いお年を。

PHPカンファレンス関西2018に参加した

なんやかんやで都合が合わずに参加できてなかったPHPカンファレンス関西。
今年は問題なく参加できたので、そのレポ。

脱「なんちゃって」フロントエンド / 榊原昌彦

脱「なんちゃって」フロントエンド

PHPカンファレンスなんですけどね?
朝一からフロントエンドの話を聞くモノ好き。

自分自身がフロントエンドばっかりの人間なので、聞きたかったセッション。

SPAから最近流行りのPWAまで。
SPAはそこそこ知ってたけど、PWAのことはあまり知らなかったので参考になった。

PWA

  • オフライン表示
    • キャッシュ表示。
  • Background Sync
    • オフライン時に送信したデータを持ち続ける。
    • オンラインに復帰したら自動的に送信。
  • Push通知
    • Push通知のためにモバイルアプリ化する必要がなくなった。
  • ホーム画面に追加
  • GPSやカメラなどのNative機能へのアクセス

単に、Webアプリでホーム画面に追加できるぐらいの知識しかなかった。

プラットフォームのはなし

CRDOVACapacitorなど。

CORDOVA

オープンソースモバイル開発フレームワーク
HTML5JavaScriptCSSといったWeb開発技術でモバイルアプリ開発ができる。

Capacitor

これも似たような感じ。
Web開発技術でモバイルアプリ開発ができる。

この辺りの技術を使えば、SPAでしっかりアプリを作れば...
SPA → Capacitor → PWA、iOSAndroid、Electron...などなど。
各プラットフォームに対応させられる。

エモい。

その他

・ユーザだけでなくサーバにも優しく
ViewをPHP(サーバ)でレンダリングするのは重い。

・自由自在なエラーハンドリング
サーバ側のどこかでエラーがあると、そこで止まる。
REST APIでHTTP Response、Status Codeをちゃんとコントロールすれば、その辺りは解決できる。

いずれ、PHPでフロントエンドを描画するのはアンチパターンかも?
だから、フロントエンド学びましょう。

若干極論感はあるけども。

質疑応答のターン。
せっかくSPAの話もあったし。良い機会なのでSPAに関する疑問をぶつけてみた。
ワシ
「SPA、SPAって言われてるけど、ネガティブな意見に'メモリリークするから・・・'みたいなのを聞くんですが。あれって実際のところどうなの?」

メモリリークするから、SPAじゃなくて、ページだけ切り分けといた方が。
っていう意見があって、結局PHPでルーティング、webpackでページごとにJSファイル作るみたいなことをしたことがある。

回答としては、あまり気にしなくても良いとのこと。
フレームワークがそれなりによしなにしてくれるのもあるみたい。

周りにフロントエンドの相談持ちかけられるような人もいないので、疑問視してたとこが吹き飛んでよかった。
しょうもない疑問に答えていただいて感謝。

続・SOLIDの原則ってどんなふうに使うの? / 後藤秀宣

続・SOLIDの原則ってどんなふうに使うの?

こういう話、最近大好き。
コードをいかに保守性とかを考えて綺麗に書けるようになるか。

無限に考えるけど、なかなかできなくって、すぐに散らかってしまう。

SOLIDの原則の中でも、「オープン・クローズドの原則」に絞ったセッション内容。
そもそもオープン・クローズドの原則とは...

・オープン = 拡張できる
・クローズド = 拡張するとき、既存コードが影響を受けない

モジュールに新たな振る舞いを追加する際、既存コードを修正せず、
単に新しいコードを追加するだけで、目的を達成できる状態になっていること。

バリエーションからコードを保護
①バリエーションによって変化する部分は?
②バリエーションの軸にそってまとめられているか

このあたりに着目。

これ実践できたら、いいけど、なかなか難しい。
こういう設計系の話は、試してみないことには・・・ってことが大半なので一度試してみる。

フロントエンドエンジニアが伝たない最近の事情 / 大原壯太

フロントエンドエンジニアが伝えたい最近の事情

フロントエンドPart2。
セッションタイトル通り、最近の事情をざっくりと。

途中までは知ってることが大半なので、「そうだなー」ぐらいの感覚で聞いていた。

得たモノ→ Swagger
REST APIを構築するためのオープンソースフレームワーク
これは便利そうだ。

HerokuでPHPアプリ開発速度を倍にする / 岡本充洋

現場編として、後藤知宏さんによるセッションとのスイッチ形式。

デモの内容としては、LaravelのアプリをHeroku上に上げるとこ。DBも使うようなやつ。
一瞬だった。

めちゃくちゃ便利そうに感じた。
Herokuのアカウントは持っているけど、全然使っていないし、この際に一度やってみたい。

GAE に PHPアプリを継続的デプロイする / 岸田健一郎

GAEにPHPアプリを継続的デプロイする

↑がHerokuなら、今度はGAE。
こっちも似たような感じで、GAEに上げましょうっていう内容。

この時間、うさみさんのpixivのやつ聞く予定だったけど、人多すぎて断念。

感想

お前、PHPカンファレンスってちゃんと読めてる?感じのセッション巡りなのはお許しを。
午前中のセッションにはVue.jsのセッションもあったし、フロントエンドの需要ってまだまだあるんだなと実感。

最近、自分の持ってるフロントエンドの技術って需要あんの?って悲観的だったけど、
まだまだ需要ありそうで安心。

とはいえ、フロントエンドのことを相談できる人が身近にほしい。
コミュニティ参加がベストかな。

そんなことを思ったPHPカンファレンス

Vue.js / Nuxt.js Meetup Osaka #0に参加した

Vue.js / Nuxt.js Meetup Osaka #0に参加したので、そのレポ。

デザイナーの私が Vue.js を触ってみた / Yasui Risaさん

資料→ デザイナーの私が Vue.js を触ってみた

タイトル通り。内容は初心者向け。
環境構築のやり方は飛ばして、CodePenで実演しつつの発表。

なぜCodePenか?→環境構築からやると難しくて心が折れる可能性が・・・

この考え方には納得。
自分も何か作るときは、JSFiddleで断片を作ってというのが多い。

Vue.jsを始めるキッカケにはとても良いセッションだった。
データの表示から、各ディレクティブの説明が丁寧。

AVAでのテストとpuppeteer / 豊川 泰弘さん

AVAでJavaScriptのテストとE2Eテストのこと。

AVA → JavaScriptのテストフレームワーク
mochaと比べるとassertの書き方が見やすい?

どんなときにテストを書いていたか?
→ コードレビュー時とか。テストケースの追加、バグの発見などにつながるかも。
puppeteer
Chrome Devtools Protocolでブラウザの情報を取得・操作するためのライブラリ。

自分は、vue-cliでてきとーに作って、E2E環境はNightWatch。
puppeteer試してみたい。

全体的にJavaScriptでテスト書いてる人は少ない感じだった。
理由は様々。テストの書き方が分からないとかから、時間がないなど。

自分も分からないなりに探り探りでやってる状態。
書き出して思うのは、「これ、書かないと一生書けないし、書かないな」。
Qiitaとかにテストの書き方みたいな記事は溢れているけど・・・。
結局add(a, b) assert(add(1,2)).to.equal(3)みたいな単純なもの。
これじゃ書けないよなとも思う。

Nuxt ディレクトリ設計パターン / andoshin11さん

資料→ Nuxt ディレクトリ設計パターン

Clear Architectureについて。
Clear Architectureは初めて聞いた。

アーキテクチャ周り、しっかりと見に付けてあげると、良い設計ができそうだと感じた。
セッション内でもあった通り、2、3人程度でならない方が良い。

結局VuexだとActionsにロジックが集中して太っていくのは実体験としてあって、どうにかならないかなとは思っていた。
例えば、ファイルアップロードするAPIを叩くにしても、
Viewでファイル受け取って、それをActionsのfileUploadみたいなのに渡す。
何も考えずにできるならそれだけで終わるけど、ならそのファイルのバリデーション系はどこに置くの?みたいな悩み。

またそのバリデーション内でもAPI叩いて、同名の存在確認とか容量確認とかしなきゃならないみたいな。。。
canUploadFileみたいなのをActionsに書いて、Promise返してresolveされたらfileUploadみたいにした。

なんかおかしいなと思いつつ・・・。安易にUtilsみたいなのは怖い。

こういった悩みの解決にも繋がる考えな気もするので、役立つセッションだった。

Vue.js とはなにか、Nuxt.js とはなにか / 後藤知宏さん

Vue.jsとNuxt.jsのことを分かりやすく。
いったいどんなことができるのか。どういったものなのか。

Vue.jsはCDNで読み込むだけで使える。

普段、vue-cliで一からVueを使うということをやっているが、CDNで読み込む方は盲点だった。
new Vueだけして、データバインディングとカスタムコンポーネントを軽く入れられる。
jQueryガリガリ書かれた辛いコードでも、これなら少し楽になりそうだと感じた。
実務でjQueryで辛くなってしまったPJがあるので、そこに導入して試したい。
(API一気に8個とか叩くんですよ・・・それ整形して画面に・・・辛い)

Vue.jsでスタイルを動的に変更する3つの方法(LT) / qwerty8tさん

Vue.jsのスタイル変更方法。

classオブジェクトがいいよ!っていう結論。
あれ初めて使い方知ったときは感動したのを思い出した。

Vue.jsのmethodsとcomputed(LT) / ショウノシオリさん

methodsのcomputedの違いについて。

あまり考えないとmethodsだけでもどうにでもできてしまう。
computedはキャッシュされるので、毎回処理が走らない。computedで使っているデータが変化したときだけ走る。
methodsは毎回。

全体的な感想

参加者の様子、Vue.jsを触ったことがある人もちらほら。
まだない人のほうがちょっと多めな印象だった。

触ってない人も多いところから考えると、Vue.jsに対する関心は高まっているのだなと感じた。

もっと難しいことを話さないといけないのかなと思っていたが、connpassのページにも書いてある通り、
「難しい話をしないと...!」ではなかった。

あ、こういうのでも良いんだ。と感じた。
Vueを使ってるなら当たり前なことでも全然大丈夫そう。
登壇のハードルは今回参加してみて自分中ではぐっと下がった。

何か話したいことがあったら、LTでもしてみたいな。

次回が楽しみ!

にしても、関西圏でVue.jsの勉強会は嬉しすぎた。

NativeScript-Vueを触った

久々の更新。

2月にこんな発表がありました。
Announcing NativeScript-Vue 1.0

要約。「nativescript-vueの1.0が出たよ」

NativeScript

JavaScriptとかTypeScript、Angularを使って、ネイティブなモバイルアプリを作ることができるフレームワークです。
詳しいことは公式参照

JavaScriptでモバイルアプリと聞くと、React Nativeなんかもありますね。

で、今回はそれをVueで書けるでっていうやつです。
最近Vue推しの自分にとっては格好のおもちゃですね。

早速遊びます。

準備

まずはNativeScriptがないと始まりません。

npm install -g native-script

次にモバイルアプリなので、こっちもやっておいてください。
IOSだけなら、JDKは入れなくてもまぁOK。
NativeScript Advanced Setup: macOS

長いのでカット。

次に、vue-cli放り込みましょう。プロジェクトのテンプレート作ってくれます。

npm install -g @vue/cli @vue/cli-init
vue init nativescript-vue/vue-cli-template <project-name>
cd <project-name>
npm install

npm installまで終わったら、npm run watch:<platform>を実行します。
今回はIOSなので、npm run watch:iosとします。

すると、シミュレーターが開くはず。
f:id:lisia:20180310220241p:plain

ひとまずここまで。
基本はここの通りです。

アプリを動かす

シミュレーター動いたのは良いけど、アプリないやん!って話ですよね。
多分そもそもビルドされてないから・・・?

package.jsonのscript内を見てみると、使えるコマンドが分かります。
package.json抜粋

  "scripts": {
    "build": "webpack --env.tnsAction build",
    "build:android": "npm run build -- --env.android",
    "build:ios": "npm run build -- --env.ios",
    "debug": "webpack --watch --env.tnsAction debug",
    "debug:android": "npm run debug -- --env.android",
    "debug:ios": "npm run debug -- --env.ios",
    "watch": "webpack --watch --env.tnsAction run",
    "watch:android": "npm run watch -- --env.android",
    "watch:ios": "npm run watch -- --env.ios",
    "clean": "rimraf dist"
  },

それっぽいnpm run debug:ios叩いてみます。

f:id:lisia:20180310220514p:plain

こんな感じでサンプルアプリが立ち上がりました。
(この後、watchしたら大丈夫でした。)

ちょっとサンプルを作ってみる

APIも叩きたいので、GiphyのAPI叩いてgifを表示するようなものにしてみます。
Vuexのサンプルで作ったことがあるこれが元ネタ。

サンプルなので、ひとつのコンポーネントにまとめてしまいます。

とりあえず画面を作る

src以下がコードを書くところです。
src/components以下にGiphy.vueを作成します。
touch src/components/Giphy.vue

<template>
 <Page class="page">
    <ActionBar class="action-bar" title="Giphy">
      <NavigationButton
        text="Go Back"
        android.systemIcon="ic_menu_back"
        @tap="$router.push('/home')"
      />
    </ActionBar>

    <StackLayout>
      <label text="Welcome to GiphyPage!"/>
    </StackLayout>
  </Page>
</template>

HelloWorldを真似て、こんな感じでtemplateを書いておきます。
次に、ページへのルーティングが必要なのでsrc/router/index.jsに書き加えます。

// ...
import Giphy from '../components/Giphy'

const router = new VueRouter({
  pageRouting: true,
  routes: [
    // ...
    {
      path: '/giphy',
      component: Giphy,
      meta: {
        title: 'Giphy'
      }
    }
  ]
}) 
// ...

homeの画面もボタンを追加しておかないとですね。

<StackLayout>
  <Button class="btn btn-primary" @tap="$router.push('/counter')">Counter</Button>
  <Button class="btn btn-primary" @tap="$router.push('/hello')">Hello World</Button>
  <Button class="btn btn-primary" @tap="$router.push('/giphy')">Giphy</Button>
</StackLayout>

画面を確認してみましょう。
f:id:lisia:20180310220536p:plain

タップして、画面が遷移することを確認します。
f:id:lisia:20180310220549p:plain

文字見えにくいけど気にしない。とりあえず、画面遷移を文字が表示できました。

処理とか入れていく

テンプレートに関しては、検索用のテキストボックスと表示領域があれば事足ります。
処理の流れは、テキストが入力されたらGhipyのAPIを叩いて、その結果をテンプレートに表示する。

これだけです。
では早速、まずはテンプレート。

<template>
  <Page class="page">
    <ActionBar class="action-bar" title="Giphy">
      <NavigationButton text="Go Back" android.systemIcon="ic_menu_back" @tap="$router.push('/home')"/>
    </ActionBar>

    <ScrollView>
      <StackLayout>
        <SearchBar
          :text="searchWord"
          hint="Please input search word"
          color="#000"
          margin="20"
          v-model="searchWord"
          @textChange="handleChangeSearchWord"
        />
        <template v-if="gifList.length">
          <Image
            v-for="(gif, index) in gifList"
            :src="gif.images.fixed_height_still.url" stretch="none"
          />
        </template>
      </StackLayout>
    </ScrollView>
  </Page>
</template>

続いて、script部分。

export default {
  name: 'Giphy',

  data() {
    return {
      searchWord: '',
      gifList: []
    }
  },

  methods: {
    handleChangeSearchWord() {
      const params = encodeURIComponent(this.searchWord).replace(/%20/g, '+')
      const url = `https://api.giphy.com/v1/gifs/search?api_key=YOURAPIKEY&q=${params}`

      fetch(url)
      .then(res => res.json())
      .then(json => {
        this.gifList = json.data
      })
    }
  }
}

軽く説明。

テンプレート側は、スクロールさせたいので、<ScrollView>で囲んでいます。
検索は<TextFiled>を最初は使っていたのですが、ドキュメント読んでると、<SearchBar>なるものがあったので、こちらを採用。

script側も特に言うことはなくて、単純にAPIを叩いているだけです。
結果をdataのgifListに放り込みます。

完成!

f:id:lisia:20180310220403g:plain

まとめ

  • JavaScriptでモバイルアプリ書ける 便利
  • しかもVue使える 便利
  • 慣れ親しんだもので書けるのはやっぱり 便利

以上!

VimConf 2017に参加した話

2年ぶりの投稿。随分と放置していました。

さて、ようやくVim Confに参加することができました。 始発の新幹線はなかなか辛かったですが・・・。

f:id:lisia:20171104091741j:plain

高まるVim熱。 f:id:lisia:20171104091903j:plain f:id:lisia:20171104175813j:plain

会場に入ると、Osaka.vimで顔馴染みの方々と合流できました。

セッション

Vim, Me and Community

haya14busaさんによるセッション。

プログラミングを始めたころから、今までの活動のまとめといった内容でした。 数年前まで、一緒にOsaka.vimにいた気がするのですが、すごいものです。

いろいろな方の助けを借りながら、ひとつひとつ小さなことを積み重ねるのは大事だなと感じました。 incsearch、Vim本体に入って本当に良かった!

The Past and Future of Vim-go

fatihさんによるセッション。

vim-goについてでした。 開発理由の中に、いろんなライブラリが乱立していることもあり、始めるときにこれ全部入れないといけないの?があったと思います。 確かになーと思ったのを覚えています。

にしてもgoCoverageすごい。見やすかった・・・! 寄付の件についても触れられていました。 「積極的に寄付を受けるべきだよ」の理由に「自由な時間使って価値を生み出している」という話が印象的でした。

セッションが終わると、Go言語が書きたくなっていました。(不思議) Goは少し書いたことがあるのですが、このvim-goを入れて、もう少し踏み込んでみようと思いました。   vim-goのチュートリアルをやろう!

Round Table Discussion 鼎談

mattnさん、k_takataさん、そしてkaoriyaさんのトークショー

Vim.2.0~使われている話であったり、皆さんWindowsVimを使用していることもあり、Windows系の苦労話が多かったように思います。

vim-devじゃなくてvim-jpでやる理由の項で、「英語での意思疎通には間違いがおきる」ということでした。 「共通言語のC言語があるじゃないか」はイケメンすぎました。

Creating your lovely color scheme

cocoponさんによるセッション。

color scheme愛が溢れていたセッションでした。 発表している中でも、すごい楽しそうに見えました。

自分は、cocoponさんの書いた[vim] 黒背景好きの僕の心を揺さぶるカラースキーム「hybrid」を読んでからというもの、ずっとhybridを使っていたりします。

「人生の33%はカラースキームを見ている」が印象的でした。

個人的にはcolor schemeって意外とやる気に直結してしまう派なので、ためになるセッションでした。 お題はcolor schemeについてですが、デザイン方面の考え方(色であったり、カラーパレットの作り方であったり)も一緒に学べて良かったです。

  • カラースキームを作るときはコンセプトを決める
  • カラーパレットを決める
  • rgbで決めない。HSB/HSLの方が選び良い
  • 色相だけを変える

などなど。

vim-mode-plus: The most ambitious vim emulator in the world

t9mdさんによるセッション。

Atomの拡張、「vim-mode-plus」についての発表。 ただ単にVimの操作を追加しているだけではなく、さらに使いやすいように趣向が凝らされているのが印象的でした。

edgeモーションがすごい便利そうでした。

Vim and Compatibility

senopenさんによるセッション。

スピードが速かった・・・。勢いがありました。 POSIX原理主義の話?

いろんな環境で、そのまま使えるように書くためには、ものすごい労力がいるんだなと感じました。 さすがにどこかは切りたくなるレベル・・・。

neosnippet.vim + deoppet.nvim

Shougoさんによるセッション。

諸事情により、歌はありませんでした。残念。 暗黒美夢王の発音にも言及されてましたね。 アンコックビムオー?

スニペットにはタイプがあり、 マーカータイプのスニペットはバッファーにマーカーを埋め込んでジャンプ。→実装しやすい。 パフォーマンスの問題もないし、実装も楽。

neosnippetでバックする実装が辛い。さらにソースも辛い。 deoppet作るよ。といった感じだった模様。

それと、オマケで、deopleteがvim8で動く話。 その代わり、windowsではめっちゃ遅い(プロセス間通信使いまくるため)

deoplete入れてみよう。

How ordinary Vim user contributed to Vim

daisuzuさんによるセッション。

小さなことからコツコツととはこのことかと感じたセッションでした。

パッチを送るのに大事なのはパッション! パッチに自分の名前が入るのには憧れますね。

バグfixは取り込まれやすい?

自前にVimをビルドして使おうかなと思いました。

あと、会社でVimトークすると良いという話もありましたが、その前にVim使い増やさないとですね・・・。 3人?いや2人しかいないです。

The new syntax highlighter for Vim

pockeさんによるセッション。

iro.vimについて。 シンタックスハイライトが上手くいかないところがあるのを直したい。 だけど、問題を解決するのに正規表現を使うと問題が2つになる。 →人類に正規表現ははやすぎる。

iro.vimは、シンタックスハイライターのプラグイン正規表現よりは理解しやすい?

このセッションで、長文のファイルの最後がシンタックスハイライトされない理由を知りました。 勉強になりました。

You've been Super Viman. After this talk, you could say you are Super Viman 2 -- Life with gina.vim

トリはAlisueさんによるセッション。

gina.vimについて。 つい数日前にgina.vimを入れたばかりで、使い方というか、丁度知りたかったところで、すごい良いタイミングでした。

確かにいろいろ覚えるのは辛いのです。 gina.vim便利そうだなーと改めて思いました。 使っていきます。

会社の紹介で、フリードリンク良いなー・・・ビールとかビールとかビールとか!

次に、お昼と懇親会のことも触れておきます。

お昼!

今半さんの"すき焼弁当"!美味しかった! f:id:lisia:20171104122359j:plain f:id:lisia:20171104122856j:plain

白い恋人はお土産です。

コーヒー!

カップにはステータスバー。 f:id:lisia:20171104125237j:plain スリーブもVimConf。細かい。 f:id:lisia:20171104124942j:plain

懇親会!

f:id:lisia:20171104180406j:plain

LTが始まったりと終始良い雰囲気でした。 もっといろいろな人と話せたら良かったのですが、正直緊張してしまい断念・・・。 勿体無い。来年こそは!

まとめ

朝から晩までVim尽くしの1日でした。 こういったカンファレンスに参加すること自体が初めてでしたが、良い経験になりました。

最近、仕事以外でのプログラミングはあまりやっていなくて、やばいと思っていたところで、モチベーションも上がったように感じます。

その他、今回は同時通訳も入っていました。 sandkattさん、ujihisaさん、本当にお疲れ様でした。

ujihisaさんの通訳は、言い回しが独特である意味ひとつのコンテンツでした。

来年も参加したいです。

東京から新幹線の最終で帰路についたのですが、戻ったら朝までカラオケということになりました。。。 さすがに疲れた!

Gulpを触ってみた

ひっさびさにこっちのブログを書きます。
Gulpを少し触ってみたので、備忘録として、導入からJavaScriptの結合とミニファイまでを書いておきます。

Gulpってなんぞや。
フロントエンドのビルドツールで良いのかな。
Gruntで気になったところが改善されているとかされてないとか。。。
Gruntも一応、結合ミニファイぐらいまでは触ってはみましたが。

ひとまず、ググッてもらえれば!

ではでは先に進みましょう。

Node.jsは入れていること前提。
%brew install node

導入

%npm install -g gulp
gulp -vでバージョン確認しておきましょう。

ここでgulpとか打って、not found的なこと言われたら、%npm link gulpとかで多分。。。
あとは%npm initして、package.jsonも作っておきましょう。

準備

使い方を軽くやるだけなので、試すためのディレクトリを作成しておきます。 ここはなんでも。
中にはgulpfile.jsを作成しておきます。

タスクを作ってみる

お決まりのHello Worldやっておきます。

// gulpfile.js
var gulp = require('gulp');

// タスクを登録
gulp.task('hello', function () {
  console.log('Hello World');
});

gulp.task('default', ['hello']);

ここまでで保存して、%gulpを叩けば、Hello Worldと出力されるはずです。
%gulp helloでも構いません。

gulp.task('task_name', function () { /* 処理 */ });みたいなイメージ。
defaultに登録したものは%gulpとした場合に実行されます。

動くことが確認できたので、次いきます。

結合、ミニファイを行う

プラグインを導入

プラグインを導入します。
%npm install gulp-concat --save-dev
%npm install gulp-uglify --save-dev

タスクを書く

先ほどはgulpfileに直接書きましたが、今回はファイルを分けます。 さっき作ったディレクトリ内に、tasksディレクトリを作ります。(好きな名前で良いです) 今回は結合→ミニファイをするタスクということで、tasks/concat-minify.jsみたいにしておきましょう。

module.exports = function (gulp) {
  // プラグイン
  var concat = require('gulp-concat'),
      uglify = require('gulp-uglify');

  // タスク登録
  gulp.task('concat-minify', function () {
    gulp.src('js/*.js') // 対象ファイル
        .pipe(concat('sample.min.js')) // 出力ファイル名
        .pipe(uglify()) // ミニファイ
        .pipe(gulp.dest('js/min')); // 出力先ディレクトリ
  });
};

内容はコメント通りです。 今回はjs以下の.jsファイルをjs/min以下にsample.min.jsとして出力させます。

gulpfile.jsを書き換えます。

var gulp = require('gulp');

require('./tasks/concat-minify.js')(gulp);

gulp.task('default', ['concat-minify']);

こんな感じで。

実行

ここまでできたら後は実行するだけです。 %gulp concat-minifyまたは%gulpで。。。

すると、js以下のjsファイルが結合され、ミニファイされたものがjs/min以下に出力されているのが確認できるはずです。

// js/sample1.js
var sample1 = function () {};

sample1.prototype = {
  showSample: function () {
    alert('Sample1');
  }
};

// js/sample2.js
var sample2 = function () {};

sample2.prototype = {
  showSample: function () {
    alert('Sample2');
  }
};

↑例えばこんなファイル。

実行後に

// js/min/sample.min.js
var sample1=function(){};sample.prototype={showSample:function(){alert("Sample1")}};var sample2=function(){};sample.prototype={showSample:function(){alert("Sample2")}};

こんな感じになっていれば!

さいご

簡単にですが、結合ミニファイまで。 今回は簡単やりたいので、結合とミニファイを同時にやりましたが、 これを結合は結合、ミニファイはミニファイなど分けることも可能です。

また、watchなんかを使えば、ファイルを監視して、編集されたら自動実行なんてのも可能です。

結合→ミニファイを手動でやるのは正直手間ですし、不具合の元なので、 このように自動化できると便利ですね。

あと、まとめたものを即時関数で囲いたい!場合は、concatよりも、concat-utilプラグインが良さそうです。

また別のところで似たような記事を書きそうです・・・w