Neovimに移行したしせっかくなのでGoでプラグインを書いてみた

github.com

Google翻訳APIを使ってテキストを翻訳するプラグイン。
作ったあとにVim & Go界隈で著名なhaya14busaさんがほぼ同じプラグインを作ってることに気づきました。

trans_nvim_previe_log

neovim/go-clientを使っていてNeovimでしか動きません。
(python-clientの方だとNeovim/Vim8で手軽に両立するやり方がある模様)
プラグインのインストールにGoが必要です。

サンプルが手薄だったり実装の参考になりそうな他のプラグインがzchee/nvim-goくらいしかみつからなかった(とはいえめっちゃ参考になった)ので、わりとneovim/go-clientのコードとにらめっこしながら書きました。

苦労したところは、previewってどうやってつくるんだろう?とかvim的な知識の足りなさ。一体何をどうするのが正解なのか未だによく分からんです。
ちなみに自分の行き着いたpreviewの作り方は次のとおり。

trans.go#L175:L203

  1. silent pclose
    • previewをとりあえず閉じる
  2. silent pedit +set noswapfile buftype=nofile translated
    • ファイルなしでpreviewを開く
  3. wincmd P
    • previewに移動する
  4. neovim/go-clientのメソッドを使って文字列をクリアして書き込む
  5. wincmd p
    • previewから抜ける

果たしてこれで合っているのか...?という気持ちですが、今のところ動いてるので良し。もしダメだったらpull-reqください。
あと誰かこの泥臭い部分を隠蔽するいい感じのラッパー作ってください!

おわり

Goだけで完結できるわけではない(vimのコマンドを直接叩いたりする)
それでもvim scriptを書くより敷居は低いし楽しい。

twitchtv/twirp を試した

github.com

gRPCのようなフレームワークで、違いはHTTP 1.1で動くこととJSONをサポートしてること。

インストール

protoc-gen-twirpの他にprotocとprotoc-gen-goも必要。

$ go get github.com/twitchtv/twirp/protoc-gen-twirp

$ brew install protobuf
$ go get github.com/golang/protobuf/protoc-gen-go

protoファイル

まずprotoファイルを書く。

$ mkdir proto
$ vi proto/hello.proto
syntax = "proto3";
package utahta.twirp.example.helloworld;
option go_package = "helloworld";

service HellowWorld {
  rpc Hello(HelloReq) returns (HelloResp);
}

message HelloReq {
  string subject = 1;
}

message HelloResp {
  string test = 1;
}

protocする

protoファイルからgoファイルをつくる。

$ mkdir helloworld
$ protoc --proto_path=./proto --twirp_out=./helloworld --go_out=./helloworld ./proto/hello.proto
$ ls helloworld
hello.pb.go    hello.twirp.go

サーバを書く

$ mkdir server
$ vi server/main.go
package main

import (
    "context"
    "fmt"
    "net/http"

    "github.com/utahta/twirp-example/helloworld"
)

type Server struct{}

func (s *Server) Hello(ctx context.Context, req *helloworld.HelloReq) (*helloworld.HelloResp, error) {
    return &helloworld.HelloResp{
        Test: fmt.Sprintf("Subject: %s", req.Subject),
    }, nil
}

func main() {
    s := &Server{}
    handler := helloworld.NewHellowWorldServer(s, nil)
    http.ListenAndServe(":8881", handler)
}

クライアントを書く

$ mkdir client
$ vi client/main.go
package main

import (
    "context"
    "fmt"
    "net/http"

    "github.com/utahta/twirp-example/helloworld"
)

func main() {
    c := helloworld.NewHellowWorldProtobufClient("http://localhost:8881", http.DefaultClient)
    resp, err := c.Hello(context.Background(), &helloworld.HelloReq{Subject: "hello twirp"})
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v\n", resp)
}

最終的に次のようなディレクトリ構成になった。

.
├── client
│   └── main.go
├── helloworld
│   ├── hello.pb.go
│   └── hello.twirp.go
├── proto
│   └── hello.proto
└── server
    └── main.go

実行する

まずサーバを実行。

$ go run server/main.go

次にクライアントを実行する。 すると結果が返ってくる。

$ go run client/main.go
&helloworld.HelloResp{Test:"Subject: hello twirp"}

curlで実行する

JSONに対応しているのでcurlを使ってさくっとリクエストできる。

$ curl -H 'Content-Type:application/json' -X POST -d '{"subject":"hello curl"}' "http://127.0.0.1:8881/twirp/utahta.twirp.example.helloworld.HellowWorld/Hello"

雑感

シュッと書いたらProtocolBuffersとJSONで会話できるようになってすごい。便利。
学習コストの低さがなによりいい。

ももクロ有安杏果さんの卒業について思うこと

地味に書きます。

2011年の11月頃にももクロを好きになりました。
www.ninxit.com 振り返るとなつかしい。

この頃は生活も不安定でなかなかつらい時期でしたが、彼女たちをみていて元気をもらったし、がんばろうという気持ちになりました。いまでも感謝してます。

生活が安定してからは、いけるライブはいくし買えるものは買いました。自分のできる範囲ですこしでも恩返しできたらという気持ちから。ライブによく行くようになって、知り合いが増えました。日本各地にいったし一人だったら絶対いかないようなところにもいきました。恩返しのつもりが逆に何倍も与えてもらいました。

有安杏果さんの卒業を知って、正直とてもショックです。

応援の気持ちが逆に負担になっていたのだとしたら、なんて本末転倒なことだろうと...。
申し訳なさと5人のももクロではなくなってしまう事実がただただ悲しい。

けれど固い決意で卒業を表明した有安さんに対して、ぼくにはもはやここで感謝の言葉を述べることしかできません。

有安杏果さん今までたくさんの笑顔と素敵な歌声をありがとうございました。

どうか幸せな人生を歩まれますように。
本当にお疲れ様でした。