2016/06/08


某 slack で x-tag を教えて貰ったのでちょっと遊んでみた。
X-Tag ★ Web Components

Docs Table of Contents Getting Started Registration - Where it All Begins The most important method ...

http://x-tag.github.io/

X-Tag は Web Component を簡単きれいに作れるライブラリで、Microsoft からのサポートを受けている事をウリにしているらしいです。動作に必要なのはカスタムタグがサポートされているブラウザというだけで、polyfills も使う事が出来ます。

簡単なチュートリアルが Docs に書かれているのでパッと見ただけでだいたい API が予想できます。自前のメソッドや属性、イベントを定義する事が出来るのでコンパクトながら強力な Web Component を作る事が出来ます。何が良いかって1ファイルで動くのが良いですね。

xtag.register('x-foo'{
  content'‹input/›',
  lifecycle:{
    createdfunction(){},
    insertedfunction(){},
    removedfunction(){},
    attributeChangedfunction(){}
  },
  methods{
    someMethodfunction(){}
  },
  accessors{
    someAccessor{
      // links to the 'some-accessor' attribute
      attribute{},
      setfunction(){},
      getfunction(){}
    }
  },
  events{
    tapfunction(){},
    focusfunction(){}
  }
});

簡単な例として、入力値のバリデーションを行うコンポーネントを作って見ました。HTML は以下の様に記述します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>俳句</title>
<script src="x-tag-core.min.js"></script>
</head>
<body>
<p>例: 古池や蛙飛び込む水の音</p>

<x-haiku value=""></x-haiku>
<input type="button" value="送信" />

<script src="xtag-haiku.js"></script>
<script>
</script>
</body>
</html>

そしてソース

xtag.register("x-haiku"{
  content'<input type="text" placeholder="俳句を入力して下さい"/>',
  lifecycle{
    insertedfunction() {
      xtag.fireEvent(this"blur");
    }
  },
  methods{
    validateHaikufunction() {
      if (this.value.length > 0{
        var s = document.createElement('script');
        var xhr = new XMLHttpRequest();
        xhr.open('GET''http://127.0.0.1:8888/check?text=' + encodeURIComponent(this.value), false);
        xhr.send();
        return JSON.parse(xhr.responseText).result;
      }
      return false;
    }
  },
  events{
    blurfunction(){
      if (this.validateHaiku())
        this.firstElementChild.style.borderColor = '';
      else
        this.firstElementChild.style.borderColor = 'red';
    }
  },
  accessors{
    value{
      attribute{},
      getfunction(){
        return this.firstElementChild.value;
      },
      setfunction(value){
        this.firstElementChild.value = value;
      }
    }
  }
});

プレースホルダの通り、俳句を入力して貰い俳句でない場合には入力ボックスを赤枠表示する Web Component です。さすがに js だけで俳句かどうかを検証するのは難しいので golang でサーバを書きました。

package main

import (
    "encoding/json"
    "net/http"
    "strings"

    "github.com/mattn/go-haiku"
)

func main() {
    http.HandleFunc("/check"func(w http.ResponseWriter, r *http.Request) {
        params := r.URL.Query()
        ts, ok := params["text"]
        if !ok || len(ts) != 1 {
            http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
            return
        }
        s := strings.TrimSpace(ts[0])
        if s == "" {
            http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
            return
        }
        w.Header().Set("Access-Control-Allow-Origin""*")
        json.NewEncoder(w).Encode(
            struct {
                Result bool `json:"result"`
            }{
                haiku.Match(s, []int{575}),
            },
        )
    })

    http.Handle("/", http.FileServer(http.Dir(".")))

    http.ListenAndServe(":8888"nil)
}

最初は Google Appengine で動かそうと思ったのですが、1ファイル32MB制限だったり、メモリ不足で動かなかったり色々起きたのでローカルで動かしています。

俳句

割と簡単に実装できるし他と干渉しないので仕事でも使って行けそうです。あと Microsoft がサポートしているので暫くは消えて無くならないってのも良いですね。

Posted at by



2016/06/03


僕はもっぱらコマンドラインで作業するので peco を使う事が多いです。

Big Sky :: Windows のコマンドプロンプトを10倍便利にするコマンド「peco」

Windows ユーザのごく一部には、コマンドプロンプトが無いと生きられない民族がいます。そしてその民族の一部には cygwin や msys bash 等といった、サードパーティなシェル(power...

http://mattn.kaoriya.net/software/peco.htm
GitHub - mattn/pcd: peco + cd = awesome!

README.md pcd peco + cd = awesome! Requirements peco Windows Installation Copy pcd.bat into your fav...

https://github.com/mattn/pcd

ただユースケースとして peco だと若干大げさになる事があって、絞り込んだりしなくて良くただ単純に候補を選ぶだけでいいって事がたまにあります。例えば画面に表示された内容を見ながら候補を選びたいであったり、「以下の中から選んで下さい」といった説明のあとユーザに数個の候補から選ばせるといったバッチコマンドを作る場合です。peco だと画面が隠れてしまうんです。さらに peco は termbox-go を使っていて termbox-go のバグっぽい物を踏んだりするし、Windows でワイド文字 API を使っている手前ラスタフォントを使わないと画面が崩れる事があります。正直エスケープシーケンスを使えば候補を選ぶくらいなら出来るし、Windows でも go-colorable があればある程度のエスケープシーケンスは扱えると分かっていたので peco とは違う路線で薄いコマンドラインセレクタを作ってみました。

GitHub - mattn/cho

README.md cho choice! Why cho? Why not choice ? Because Windows already have choice command. Why not...

https://github.com/mattn/cho

はじめは「choice」というコマンド名で開発していたのだけど、よく考えたら Windows には choice コマンドが既にあって、「じゃぁ choic?」「いやいや」「では choi は?」「ダメだろ」「それなら cho だ!」くらいの感覚でネーミングしました。ただ適当に名付けた割にキーボードのホームポジションからそれ程手を動かさなくてもいいので実はちょっと気に入っています。使い方は peco と変わりません。ただし絞り込み機能は提供していませんので、ながーいファイルから1つ選びたいなら頑張って j/k するか大人しく peco を使って下さい。

cho

Windows、Linux、BSD、Mac OSX で動作します。go-colorable にいくらか修正を入れているので最新版を使ったほうがいいです。

おまけ

例えば Windows でコマンドを実行し cho で選んだ結果を変数に入れる様にしたい場合(UNIX の FOO=`ls | cho`)は以下の様なバッチファイル「setvar.bat」を用意しておくと便利です。

@echo off
for /f "delims=;" %%i in ('%2 ^| nkf -Sw ^| cho -cl ^| nkf -Ws') do set %1=%%i

nkf 持ってない人はコチラ(結果がUTF-8になっちゃうけど

@echo off
for /f "delims=;" %%i in ('%2 ^| cho -cl') do set %1=%%i

すると以下のコマンドで dir の出力結果を cho で選んだ内容が変数 foo に入ります。

setvar foo "dir /b"
Posted at by



2016/05/30


C言語とか C++ でマイクロフレームワークとか聞くと鼓動の高鳴りを抑えられなくなるmattnですこんにちわ。

Balde — A microframework for C based on GLib and bad intentions.

Features Simple templating engine, that converts markup to C code that is linked directly to the app...

https://balde.rgm.io/

2016年に glib で Web だと?と言われそうな気がしなくないですが面白そうな物を見つけました。特徴は

  • 簡単なテンプレートエンジンを提供し、マークアップからC言語のコードへ変換されアプリケーションのバイナリに直接埋め込まれる。
  • 静的リソースはアプリケーションのバイナリに埋め込まれサーブされる。
  • RESTful なリクエストのディスパッチを行い、ほぼ全ての HTTP メソッドをサポート。
  • URL の逆引き。 (Flask の "url_for" 関数に似ている)
  • セキュアクッキー(クライアントサイドセッション)
  • ファイルのアップロード
  • SCGI や CGI サーバとの親和性
  • GLib が稼働するあらゆるシステムで稼働する

まずは簡単なアプリケーションから。

#include <balde.h>

balde_response_t*
hello(balde_app_t *app, balde_request_t *request) {
  return balde_make_response("Hello World! I'm the balde! :D");
}

int
main(int argc, char *argv[]) {
  balde_app_t *app = balde_app_init();
  balde_app_add_url_rule(app, "hello""/", BALDE_HTTP_GET, hello);
  balde_app_run(app, argc, argv);
  balde_app_free(app);
  return 0;
}

pkg-config が提供されるのでコンパイルも楽ちん。

$ gcc -o app `pkg-config --cflags balde` main.c `pkg-config --libs balde`

静的ファイルを扱うには少し癖があり、定義ファイルからリソースとしてコンパイルする必要があります。

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
    <gresource prefix="/static">
        <file>foo.js</file>
        <file>foo.css</file>
        <file>asd/bola.txt</file>
    </gresource>
</gresources>

もちろんこの XML と同様に static/foo.js, static/foo.css, static/asd/bola.txt が置かれているとします。リソースの生成方法は以下の通り。

$ glib-compile-resources --generate --sourcedir static --target static-resources.c static-resources.xml

ソースファイルは以下の様にルーティングを変更します。

#include <balde.h>
#include "static-resources.h"

balde_response_t*
hello(balde_app_t *app, balde_request_t *request) {
  return balde_make_response("Hello World! I'm the balde! :D");
}

int
main(int argc, char *argv[]) {
  balde_app_t *app = balde_app_init();
  balde_resources_load(app, static_resources_get_resource());
  balde_app_add_url_rule(app, "hello""/", BALDE_HTTP_GET, hello);
  balde_app_run(app, argc, argv);
  balde_app_free(app);
  return 0;
}

そしてコンパイル

$ gcc -o app `pkg-config --cflags balde` main.c static-resources.c `pkg-config --libs balde`

テンプレートを使う場合は専用ツールを利用します。templates/hello.html というファイルを用意します。

<h1>Hello, {{ name }}!</h1>

コマンドラインから balde-template-gen コマンドを実行します。

$ balde-template-gen templates/hello.html templates/hello.h
$ balde-template-gen templates/hello.html templates/hello.c

ソースコードを修正します。

#include <balde.h>
#include "static-resources.h"
#include "templates/hello.h"

balde_response_t*
hello(balde_app_t *app, balde_request_t *request) {
  balde_response_t *response = balde_make_response("");
  const gchar *name = balde_request_get_arg(request, "name");
  balde_response_set_tmpl_var(response, "name", name != NULL ? name : "World");
  balde_template_hello(app, request, response);
  return response;
}

int
main(int argc, char *argv[]) {
  balde_app_t *app = balde_app_init();
  balde_resources_load(app, static_resources_get_resource());
  balde_app_add_url_rule(app, "hello""/", BALDE_HTTP_GET, hello);
  balde_app_run(app, argc, argv);
  balde_app_free(app);
  return 0;
}

そしてコンパイル。

$ gcc -o app `pkg-config --cflags balde` main.c static-resources.c templates/hello.c `pkg-config --libs balde`

出来上がったアプリケーションに -s オプションを付けるとスタンドアローンサーバとして起動します。ブラウザから http://localhost:8080/?name=mattn の様なURLを開くとちゃんと動作しているのが分かるかと思います。尚、msys2 でビルドして見ましたが問題なく動作しています。glib がインストールされている同じOS同士ならばバイナリ1つでデプロイが完了します。便利そうですね。

LGPL 2.1 のライセンスのもと利用出来ます。

Posted at by