Account: (login)

More Channels


Are you the publisher? Claim this channel

Search in 125,958,551 RSS articles:

Channel Description:

システム開発屋がひっそり語るぼやき

Latest Articles in this Channel:

  • 01/27/12--04:00: Vim scriptはウェブアプリケーション記述言語やったんやー (chan 1718684)
  • こんにちわ。昨今、ウェブ開発の進化はすざましいですね。PythonやPerlやJava、色んな言語で書かれていると思います。
    もちろん編集にはVimを使っているかと思います。
    でも編集だけ?

    違うよね!
    Vim scriptはウェブアプリケーション記述言語なんだよ!

    Plack::App::Vim

    package Plack::App::Vim;
    use strict;
    use warnings;
    use parent qw/Plack::Component/;
    use Plack::Request;
    use Encode;
    use JSON::PP;

    sub prepare_app {
        my $self = shift;
        $self->{vim} ||= 'vim';
        if (!$self->{server}) {
            open(my $f"vim --serverlist|");
            my $server = <$f>;
            close($f);
            chomp $server;
            $self->{server} = $server;
        }
        if (!$self->{encoding}) {
            open(my $fsprintf("%s --servername %s --remote-expr \"&encoding\"|",
                $self->{vim}$self->{server}));
            my $encoding = <$f>;
            close($f);
            chomp $encoding;
            $self->{encoding} = $encoding;
        }
        $self;
    }

    sub call {
        my ($self$env) = @_;
        my $req = Plack::Request->new($env);
        my $json = JSON::PP->new->ascii
            ->allow_singlequote->allow_blessed->allow_nonref;
        my $str = $json->encode({
            uri => $env->{PATH_INFO}||'',
            method => $req->method,
            headers => [split/\n/$req->headers->as_string)],
            content => $req->content,
        });
        $str =~ s!"!\\x22!g;

        my $command;
        if ($^O eq 'MSWin32') {
            $command = sprintf(
                '%s --servername %s --remote-expr "vimplack#handle("""%s""")"',
                $self->{vim}$self->{server},
                encode($self->{encoding} || 'utf8'$str));
        } else {
            $command = sprintf(
                "%s --servername %s --remote-expr 'vimplack#handle(\"%s\")'",
                $self->{vim}$self->{server},
                encode($self->{encoding} || 'utf8'$str));
        }
        open(my $f"$command|");
        binmode $f':utf8';
        my $out = <$f>;
        close $f;
        my $res = $json->decode($out);
        $res->[2][0] = encode_utf8 $res->[2][0] if $res;
        $res || [500, ['Content-Type' => 'text/plain'], ['Internal Server Error']];
    }

    1;

    __END__

    =head1 NAME

    Plack::App::Vim - The Vim App in Plack

    =head1 SYNOPSIS

      use Plack::Builder;
      use Plack::App::Vim;

      builder {
        mount "/" => Plack::App::Vim->new(server => 'VIM');
      };

    =head1 DESCRIPTION

    Plack::App::Vim allows you to write web application with Vim script.

    =head1 AUTHOR

    Yasuhiro Matsumoto

    =head1 SEE ALSO

    L<Plack>

    =cut
    Plack::Appのアプリケーションハンドラを書いたよ。これを起動するpsgiファイルを用意するよ!

    app.psgi
    #!perl
    use lib qw/lib/;
    use Plack::Builder;
    use Plack::App::Vim;

    builder {
        mount "/" => Plack::App::Vim->new(server => 'VIM');
    };
    引数のserverにはclientserver機能が使えるVimを立ち上げ、そのサーバIDを指定しておく必要があるよ!
    そしてVim側にハンドラを書くよ!

    autoload/vimplack.vim
    scriptencoding utf-8

    function! vimplack#handle(req)
      let req = json#decode(a:req)
      let res = [200, [], ["hello world"]]
      return json#encode(res)
    endfunction
    PSGIプロトコルそのままですね!便利!

    起動しよう!
    # plackup app.psgi
    HTTP::Server::PSGI: Accepting connections at http://0:5000/
    ブラウザでhttp://localhost:5000を開こう!
    Vim on PSGI
    やたー!
    あとはアプリケーション書き放題ですね!
    試しに掲示板書いてみるよ!

    autoload/vimplack.vim
    scriptencoding utf-8

    let s:comments = get(s:, 'comments', [])

    function! vimplack#handle(req)
      let req = json#decode(a:req)
      if req.uri == "/"
        let res = [200, ["Content-Type""text/html; charset=utf-8"], [""
    \."<html>"
    \."<body>"
    \."<form action='/regist' method='post'>"
    \."コメント:<input type='text' name='comment' value='' /><br />"
    \."<input type='submit' value='登録' />"
    \."</form>"
    \.join(map(copy(s:comments)'html#encodeEntityReference(v:val)')'<br />')
    \."</body>"
    \."</html>"
    \]]
      elseif req.uri == '/regist' && req.method == 'POST'
        let params = {}
        for _ in map(split(req.content, '&')'split(v:val,"=")')
          let params[_[0]] = iconv(http#decodeURI(_[1])'utf-8', &encoding)
        endfor
        if has_key(params, 'comment')
          call add(s:comments, params['comment'])
        endif
        let res = [302, ["Location""/"], [""]]
      else
        let res = [404, [], ["404 Dan Not Found"]]
      endif
      return json#encode(res)
    endfunction
    アプリケーションの更新はVimを再起動するかautoload/vimplack.vimを開いている常態なら
    :so %
    で行けるよ!
    Vim on PSGI

    知らんかったー
    Vim scriptはウェブアプリケーション記述言語やったんやー
    mattn/p5-Plack-App-Vim - GitHub

    Vim Application Handler for PSGI

    https://github.com/mattn/p5-Plack-App-Vim

  • 02/07/12--23:24: Vimで編集中のMarkdownをプレビュー出来るプラグイン書いた (chan 1718684)
  • Vimが良くも悪くも「エディタだ」と言われる要因として「画像や異なるグリフのフォントを同時に出せない」ことを上げられます。つまりVimはHTMLやマークダウン等のプレビューを確認する為にいちいちブラウザを起動して確認し、ファイルを更新した際には読み込み直すという面倒な手間が掛かる事を意味しています。
    まぁ専用ブラウザを作ればいいんだけど面倒で腰が重かったんだけど、ちょいと作ってみました。

    mattn/mkdpreview-vim - GitHub

    MkdPreview Markdown previewer for vimmer

    https://github.com/mattn/mkdpreview-vim
    ファイルタイプがmarkdownなバッファで
    :MkdPreview!
    と実行するとプレビューワが起動します。
    mkdpreview-vim
    プレビューワが一度起動している状態なら、以後は他のVimからでも
    :MkdPreview
    でプレビューが表示される様になっています。MkdPreview!を実行したVimに関してはBufWritePostに 対してプレビュー更新が行われる様になっているので:wで自動更新されます。この辺は使い勝手で変えていくかも知れない。
    仕組みはpythonスクリプトで書かれたウェブサーバ兼Qt4を使ったプレビューワになっていて POSTを受けたらそれをmarkdown-jsを使ってQtWebkitに反映させています。 複数起動とかうっとおしいだろうなと思ったので、ポートは固定にしています。 起動に必要な物としては
    • python (2.7 or later) http://python.org/
    • PyQt4 http://www.riverbankcomputing.co.uk/software/pyqt/download
    • curl command http://curl.haxx.se/libcurl/
    • webapi-vim http://github.com/mattn/webapi-vim
    • markdown-js https://github.com/evilstreak/markdown-js
    となります。pythonスクリプトは短いのでコードを貼り付けておきます。
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import os
    import sys
    import json
    import cgi
    from threading import Thread
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from PyQt4.QtWebKit import *
    from PyQt4.QtNetwork import *
    from BaseHTTPServer import HTTPServer
    from SimpleHTTPServer import SimpleHTTPRequestHandler

    os.chdir(os.path.dirname(__file__))

    port = int(os.getenv("mkdpreview_port"or "8081")

    QNetworkProxyFactory.setUseSystemConfiguration(True)
    app = QApplication(sys.argv)
    webview = QWebView()
    webview.setWindowTitle('Markdown Previewer')
    webview.load(QUrl("http://localhost:8081"))
    def do_eval(js):
      webview.page().mainFrame().evaluateJavaScript(
          "preview(%s)" % json.dumps(unicode(js, 'utf-8')))
    QObject.connect(webview, SIGNAL("preview(QString)"), do_eval)
    webview.show()

    class PreviewHandler(SimpleHTTPRequestHandler):
      def do_POST(self):
        s = self.rfile.read(int(self.headers.getheader('content-length')))
        p = cgi.parse_qs(s)
        webview.emit(SIGNAL("preview(QString)"), p["data"][0])
        self.wfile.write("")

    class WebServer(QThread):
      def __init__(self):
        QThread.__init__(self)
        self.server = HTTPServer(("", port), PreviewHandler)

      def run(self):
        self.server.serve_forever()

    server = WebServer()
    server.start()

    sys.exit(app.exec_())

    # vim:set et sw=2 ts=2:
    良かったら使ってみて下さい。 なお、ベースとなるHTMLはstaticフォルダにあるのでスタイル等をカスタマイズしたい人はじゃんじゃんやっちゃって下さい。 こうすればもっと使い勝手が良くなるよなどあればpull requestお願いします。

    追記
    Windowsじゃない人はstatic/mkdpreview.pyに実行権限与えて下さい。
    markdown-jsじゃなくpython側でparseする様にしました。

  • 02/09/12--05:21: Vim で XML Reformat (chan 1718684)
  • たとえばこういう XML があったとして、

    <status><created_at>Mon Feb 06 21:07:52 +0000 2012</created_at><id>166629198054690816</id><text>Post-Bowl Twitter analysis http://t.co/OYYSRSew http://t.co/M0AtLQVd</text><source>web</source><truncated>false</truncated><favorited>false</favorited><in_reply_to_status_id></in_reply_to_status_id><in_reply_to_user_id></in_reply_to_user_id><in_reply_to_screen_name></in_reply_to_screen_name><retweet_count>454</retweet_count><retweeted>false</retweeted><user><id>783214</id><name>Twitter</name><screen_name>twitter</screen_name><location>San Francisco, CA</location><description>Always wondering what's happening. </description><profile_image_url>http://a0.twimg.com/profile_images/1124040897/at-twitter_normal.png</profile_image_url><profile_image_url_https>https://si0.twimg.com/profile_images/1124040897/at-twitter_normal.png</profile_image_url_https><url>http://blog.twitter.com/</url><protected>false</protected><followers_count>7625563</followers_count><profile_background_color>ACDED6</profile_background_color><profile_text_color>333333</profile_text_color><profile_link_color>038543</profile_link_color><profile_sidebar_fill_color>F6F6F6</profile_sidebar_fill_color><profile_sidebar_border_color>EEEEEE</profile_sidebar_border_color><friends_count>822</friends_count><created_at>Tue Feb 20 14:35:54 +0000 2007</created_at><favourites_count>16</favourites_count><utc_offset>-28800</utc_offset><time_zone>Pacific Time (US &amp; Canada)</time_zone><profile_background_image_url>http://a1.twimg.com/profile_background_images/378245879/Twitter_1544x2000.png</profile_background_image_url><profile_background_image_url_https>https://si0.twimg.com/profile_background_images/378245879/Twitter_1544x2000.png</profile_background_image_url_https><profile_background_tile>true</profile_background_tile><profile_use_background_image>true</profile_use_background_image><notifications>false</notifications><geo_enabled>true</geo_enabled><verified>true</verified><following>true</following><statuses_count>1266</statuses_count><lang>en</lang><contributors_enabled>true</contributors_enabled><follow_request_sent>false</follow_request_sent><listed_count>68708</listed_count><show_all_inline_media>true</show_all_inline_media><default_profile>false</default_profile><default_profile_image>false</default_profile_image><is_translator>false</is_translator></user><geo/><coordinates/><place/><possibly_sensitive>false</possibly_sensitive><contributors><user_id>7694352</user_id></contributors></status>
    見づらいので vimrc に1行書いてあげると、
    map <Leader>x !python -m BeautifulSoup<CR>
    範囲選択してから <Leader> x でキレイに整形してくれます。
    <status>
     <created_at>
      Mon Feb 06 21:07:52 +0000 2012
     </created_at>
     <id>
      166629198054690816
     </id>
     <text>
      Post-Bowl Twitter analysis http://t.co/OYYSRSew http://t.co/M0AtLQVd
     </text>
     <source>
      web
     </source>
     <truncated>
      false
     </truncated>
     <favorited>
      false
     </favorited>
     <in_reply_to_status_id>
     </in_reply_to_status_id>
     <in_reply_to_user_id>
     </in_reply_to_user_id>
     <in_reply_to_screen_name>
     </in_reply_to_screen_name>
     <retweet_count>
      454
     </retweet_count>
     <retweeted>
      false
     </retweeted>
     <user>
      <id>
       783214
      </id>
      <name>
       Twitter
      </name>
      <screen_name>
       twitter
      </screen_name>
      <location>
       San Francisco, CA
      </location>
      <description>
       Always wondering what's happening.
      </description>
      <profile_image_url>
       http://a0.twimg.com/profile_images/1124040897/at-twitter_normal.png
      </profile_image_url>
      <profile_image_url_https>
       https://si0.twimg.com/profile_images/1124040897/at-twitter_normal.png
      </profile_image_url_https>
      <url>
       http://blog.twitter.com/
      </url>
      <protected>
       false
      </protected>
      <followers_count>
       7625563
      </followers_count>
      <profile_background_color>
       ACDED6
      </profile_background_color>
      <profile_text_color>
       333333
      </profile_text_color>
      <profile_link_color>
       038543
      </profile_link_color>
      <profile_sidebar_fill_color>
       F6F6F6
      </profile_sidebar_fill_color>
      <profile_sidebar_border_color>
       EEEEEE
      </profile_sidebar_border_color>
      <friends_count>
       822
      </friends_count>
      <created_at>
       Tue Feb 20 14:35:54 +0000 2007
      </created_at>
      <favourites_count>
       16
      </favourites_count>
      <utc_offset>
       -28800
      </utc_offset>
      <time_zone>
       Pacific Time (US &amp; Canada)
      </time_zone>
      <profile_background_image_url>
       http://a1.twimg.com/profile_background_images/378245879/Twitter_1544x2000.png
      </profile_background_image_url>
      <profile_background_image_url_https>
       https://si0.twimg.com/profile_background_images/378245879/Twitter_1544x2000.png
      </profile_background_image_url_https>
      <profile_background_tile>
       true
      </profile_background_tile>
      <profile_use_background_image>
       true
      </profile_use_background_image>
      <notifications>
       false
      </notifications>
      <geo_enabled>
       true
      </geo_enabled>
      <verified>
       true
      </verified>
      <following>
       true
      </following>
      <statuses_count>
       1266
      </statuses_count>
      <lang>
       en
      </lang>
      <contributors_enabled>
       true
      </contributors_enabled>
      <follow_request_sent>
       false
      </follow_request_sent>
      <listed_count>
       68708
      </listed_count>
      <show_all_inline_media>
       true
      </show_all_inline_media>
      <default_profile>
       false
      </default_profile>
      <default_profile_image>
       false
      </default_profile_image>
      <is_translator>
       false
      </is_translator>
     </user>
     <geo>
      <coordinates>
       <place>
        <possibly_sensitive>
         false
        </possibly_sensitive>
        <contributors>
         <user_id>
          7694352
         </user_id>
        </contributors>
       </place>
      </coordinates>
     </geo>
    </status>

    ネタ元: http://wozozo.hatenablog.com/entry/2012/02/08/121504

    ちなみに-mだけでやる場合は細かい制御はできなさそう。

  • 02/14/12--00:43: VimでMessagePack/RPC (chan 1718684)
  • Vimが無いと夜も安心して眠れないVimキチガイの皆さんこんにちわ。

    Twitter
    ShougoMatsu

    そういえば、VimもMessagePackで通信できると面白いのではないか。


    https://twitter.com/#!/ShougoMatsu/statuses/168691297601863681
    こうですかわかりません。
    mattn/msgpack-vim - GitHub

    MessagePack implements for vim

    https://github.com/mattn/msgpack-vim
    Vim scriptは型が豊富ではないので、可逆圧縮ではありませんが簡単な物ならば動きます。
    # -*- coding: utf-8 -*-
    require 'msgpack/rpc'
    class MyHandler
      def add(x,y) x+y end
    end
    svr = MessagePack::RPC::Server.new
    svr.listen('0.0.0.0'18800MyHandler.new)
    svr.run

    こんなサーバを走らせておき
    let mp = msgpack#client("127.0.0.1"18800)
    echo mp.call("add", 1, 2)
    call mp.close()
    Vimからこのように実行します。すると
    3
    おぉ... もちろん配列、ディクショナリ、浮動小数点、文字列、整数は当たり前で扱えます。
    # -*- coding: utf-8 -*-
    require 'msgpack/rpc'
    class MyHandler
      def get_dict()
        {:foo => "ばー"}
      end
    end
    svr = MessagePack::RPC::Server.new
    svr.listen('0.0.0.0'18800MyHandler.new)
    svr.run
    こんなコードなら
    let mp = msgpack#client("127.0.0.1"18800)
    echo mp.call("get_dict")
    call mp.close()
    {'foo': 'ばー'}
    と表示されます。日本語もバッチリですね!

    msgpack#client に関しては通信に vimproc を使ってますが、ここはちょっと弄れば nc でも通信可能ですし、xxd なんかを使えばバイナリファイルとしても保存可能です。 また msgpack#packmsgpack#unpack は単体関数として使えるのでいろんな物に利用出切るかと思います。

    誰得度がかなり高いですが、よろしければどうぞ。

  • 02/15/12--16:38: THE GO TOOL (chan 1718684)
  • 先日、Go言語開発チームはリポジトリ内にあった殆どのMakefileを削除した。私(訳者)は混乱したし不安にもなった。しかしそれは私がこれまでの習慣と異なる場面に遭遇した事による物だと気付いた。その事を色濃く書かれたいる記事があったので紹介したい。Go言語を知らない人でも面白く読めると思います。

    Are You Fuckign Coding Me!? - The go tool
    http://areyoufuckingcoding.me/2012/02/14/the-go-tool/
    本訳を許諾してくれたnu7hatchに感謝したい。(Thanks to nu7hatch)

    THE GO TOOL

    毎週リリースされる最新版に新しいgoコマンドが導入され話題になっていたので、ちょっとこれについて書くことにした。 私は初め、このgo toolを統一しようというアイデアを聞いた時、少し懐疑的になり不安でいっぱいになった事を認めざるを得ない。 それが他の言語固有のパッケージマネージャの様にめちゃくちゃになるのではないかと心配した。 それらパッケージマネージャのほとんどは私の知る限り車輪の再発明であり、そのオペレーティングシステム上のPMがコーディングする事でシステム管理者を生活苦にしているのだ。 さらに言うと、私はmakefileが好きだった。本当に好きだった。単純明快だったしうまく動いた。 幸運にも新しいのgo toolが私の恐怖の全てを拭い去った!

    繰り返すな...

    新しいgo toolに関する情報の多くはgo nutsメーリングリストに流れている。 公式のgoのドキュメントにも現在、go toolを使ってのコードの書き方が短めの記事となって幾らか含まれている。

    現時点ではドキュメントとのギャップがかなりあると思うので、新しいgo toolの採用と幾らかの便利なトリックを逸早く書くことが合理的だと思う。

    設定よりも取り決め

    私の最大の恐怖の源、その理由はRuby on Railsの経験によるものだ。 Railsをよく理解しる開発者は、ちょっとしたハックや、言ってしまえばルールに沿わないちょっとしたトリッキーな何かをしようとする場合、その全ての時間を費やす事に同意しなければならない。

    IMPOSSIBRU!

    しかし良い練習について説明して行こう。まず第一にgo toolの各々は一つの物事だけを行う。そしてそれは正しい。あるべき物はそこにある:

    • go build - パッケージのビルド
    • go get - 依存の解決とインストール
    • go test - テストスーツの実行とベンチマーク
    • go install - パッケージのインストール
    • go doc - ドキュメントの生成
    • go fmt - コードの整形
    • go run - アプリケーションのビルドと実行
    • go tool - その他ツールの呼び出し
    • その他...

    Goのパッケージはビルドの設定といった物を全く持っていない。 makefileもない。その他、依存性の記述も無い。 じゃぁどの様になるのか。全てはソースコードから検索される。 マジックを起こすには、最初に行わなければならない事が一つある。 goのスタッフがどこにあるのかを明示する必要がある。 GOPATH環境変数でgoのツリーへのパスを定義する。 例えば、~/.bashrcの中での以下の様に:

    GOPATH="/home/nu7/gocode"

    ...はgoのツリーが指定した場所に存在する事をgo toolに教えているのだ。 goのツリーって実際なに?と聞くかもしれない。簡単に言うと 君のソース、パッケージ、コマンドの全てが格納される場所だと答えておこう。 まぁ見なさい:

    ls /home/nu7/gocode/
    bin   pkg   src

    全てのソースはsrcフォルダーの中に位置するであろう。これはアプリケーション、パッケージ、そして依存している物、全てのソースという意味だ。 pkgフォルダーはコンパイルされてインストールされたパッケージが含まれ、cmdにはコマンドがインストールされる。

    GOPATH変数はPATHに非常に似ており、必要なだけ多数のgoパスを設定出来る。 君はそれらの内、最初の一つをメインである覚えておかなけいけない。なぜならgo installでインストールされる全てはそこに入るからだ。

    依存の解決

    依存を明示する設定ファイルは無い... じゃぁどうやってgo toolはそれをどこからダウンロードして、どこにインストールしているのかを知り得るんだよ! リポジトリだろって思った?ノー、そんな物は無い。 Goはimportpathと呼ばれる物を導入している。 まぁ見なさい:

    import "github.com/nu7hatch/gouuid"

    import pathはツーインワンだ。 リポジトリURLでもあり、パッケージがローカルにインストールされる場所へのパスでもある。 go getツールはどこにフェッチすべき依存物があるかをimport pathを見て知る。 またgo buildはローカルにあるそれらをインポートする場所を知る。

    システムに依存している物をインストールするには次のようにgo getツールを使う必要がある:

    $ go get package-name

    待った待った、ちょっと待った... このパッケージ名って何? これはインストールしたい依存物のパッケージ名だ。 例えばgoのソースとしてfooという名前のパッケージがあった場合、go get fooを呼び出す事で全ての依存物がインストールされる。 パッケージから直接このツールを使う事も出来る:

    $ cd ~/gocode/src/foo
    $ go get .

    その他の全てのgo toolは同じ様に動作し、パッケージ、あるいはそのimport pathの指定から直接呼び出せる。 また ... ワイルドカード(3つのドット)を使ってネストされたパッケージのグループにおいても使う事ができ、fooパッケージがいくつかの入れ子のパッケージを含んでいる場合、それら依存する全てはこれをやるだけで同時にインストールすることが出来る:

    $ go get ./...

    goのツリーに指定した依存物が既にインストールされている場合、明示的に要求しない限り更新されない。 依存しているパッケージを更新するにはgo get-uフラグを付ける:

    $ go get -u package-name

    簡単でしょ?

    依存地獄!

    go toolを好きであると同時に恐れている、もう一つの取り決めがある。 Go toolはリポジトリのHEADバージョンをチェックして依存を解決する。 これはパッケージメンテナに後方互換性を維持する事を強要する。

    GREEN MASTER MOTHERFUCKER! DO YOU HAVE IT?

    グリーンマスターポリシーは私が仕事で常に主張していた事だった。 デフォルトブランチは人々がまず最初にチェックする物であり、したがってそれはグリーン(テストが全てパスした状態)であるべきでそれを動作させる為には少なくとも最新でなければならない! 一度公けに公開した、もしくは十分開発した段階ならば、後方互換性を持つべきだ。 我々は何かを廃止したり、パッチやマイナーバージョンである中でAPIの変更をする事は出来ない。

    でも我々は練習の中でそれがどの様になるのかの全てを得て知る。 多くの人々は後方互換性なんて糞の様な物は提供しないし、彼らは遊び場としてデフォルトブランチを使う。 彼らの為に、そして新しいgo toolで平穏に暮らしたい開発者の為に、この取り決めのセットを

    君がプログラマ人生を送る中で守るべきバカバカしいルール:

    • マスターブランチを常にグリーンにしとけよ!バカ
    • 新機能は別ブランチでやれ!ボケ
    • 一度コード公開しといて誰かが使ってるのにAPI変えるなクソがぁ!
    • API変えたいとか、どうして変える必要があるならメジャーバージョンで変えろよ。んでもってオリジナルブランチから派生ブランチに分けて作業しろよ!カス
    • もしどうしても、どうしても特別なタグやブランチ、もしくは依存としてコミットする必要があるなら、デフォルトに指定したリポジトリを自分でforkしてコミットに使えよ!このウンコが!
    • おいおい...笑顔でいろよ マザコン!

    エルサレムの本を思い出しちゃうから何度も言わせないでくれ...

    ビルドとインストール

    Ok。goコマンドに話を戻そう。go buildコマンドはパッケージをコンパイルするのに使われる。 パッケージをビルドするだけでインストールはしない。 重要なのはパッケージはローカルソースツリーの中でチェックされなければならないという事。 代わりにリモートパッケージのインストールにはgo getが使われる:

    $ go get github.com/nu7hatch/gouuid

    ローカルのパッケージをインストールするためにはgo installツールが使われる。 これは最初にパッケージをビルドし(必要な場合)、$GOPATH/pkg、あるいは$GOPATH/cmd配下の物をインストールする。

    go toolはフラグや特別な設定をしない限り特定のファイルをビルドから除外する事も出来る。 無視する為にやるべき事は、名前の先頭にアンダースコアを付けるだけ:

    $ ls
    _bar.go foo.go
    $ go build .

    上の例の_bar.goのはビルドからは無視される。

    ふむ。この通り。これに関して言う事は何もない。先に進もう。

    CGOによるC言語拡張

    cgoコマンドによるC言語拡張の作成はかなり素晴らしい。 実際にC言語アプリケーションの殆どをビルドするのにcgoについてもっと知っておく必要は無く、go buildツールで十分なのだ。

    素直に言うとcgoに関してはあまり言うことは無く、それらの殆どはだいたいドキュメント、そしてgo users wikiにある記事の中に記述されている。

    まず言っておくべき事として私がそれが好きではない。オフィシャルの殆どの例で示される様にコメントの中にC言語のソースコードをそのまま配置している。 マジで本当に好きになれない。 主としてコードの量を最小化し、かつ単一のファイルで各例を示すために、サンプルがこの方法で提供されている事を知っておくべきだ。 現実のアプリケーションではC言語のコードはコメントブロックに配置すべきじゃないgo buildツールはパッケージ内の.h.cといったファイルをちゃんとスマートに扱ってくれるんだ。

    例がいる? stdio.hにある関数printfを使って引数を画面に表示する単純なechoコマンドを書こう。 wikiページで言及されている様に、goはC言語の可変長引数の関数を呼び出す事は許していない。 よってprintf関数の小さなラッパを書かなければならない。 コードはgithubにある物の様になるだろう:

    echo.h:

    #ifndef _ECHO_H_
    #define _ECHO_H_

    #include <stdio.h>

    void echo(char*);

    #endif /* _ECHO_H_ */

    echo.c:

    #include "echo.h"

    void echo(char* s)
    {
        printf("%s\n", s);
    }

    echo.go:

    package main

    /*
    #include <stdlib.h>
    #include "echo.h"
    */
    import "C"

    import (
        "flag"
        "unsafe"
        "strings"
    )

    func main() {
        flag.Parse()
        cs := C.CString(strings.Join(flag.Args(), " "))
        C.echo(cs)
        C.free(unsafe.Pointer(cs))
    }

    これで君もgo buildツールでシームレスにビルド出来る様になる。 パッケージにある全てのC言語ファイルを認識し、コンパイルする。 つまりはこれだけでいいんだ!

    NOT BAD

    プラットフォーム固有のビルド

    もう一つ素晴らしく興味深い事にgo buildはプラットフォーム固有のファイルについてのコンパイルをハンドリング出来る事だ。ファイルを名前から解析している。(こんな感じ: file_GOOS_GOARCH.go もしくは file_GOARCH.go):

    foo_darwin_amd64.go
    foo_386.go
    foo.go

    この機能はC言語のファイルでもちゃんと動く:

    foo_amd64.c
    foo_386.c
    foo.h
    foo.go

    ドキュメントの中で言われている通り、これらの機能は必要ない。しかし go toolが単純なわりに如何に柔軟なのかを色濃く表している事を言及しておきたい。

    Ok。でも君はきっとこう聞くだろう。もしコンパイラのフラグや幾つかの設定など、何かトリッキーな事が必要な場合は?と

    救うべきMakefile!

    そう、makefileを使う事を恐れてはいけない! これは拡張設定による取り決めや、先行条件等に対処する為の、最も簡単で全く便利な方法だ。 Makefileは、C言語の拡張にだけ役立つ物ではなく、色んなパッケージにおいても同様に適用出来る(例えばwebrocketのトップレベルでは作業を楽にする為にmakefileを使っている)。

    より明示的な例... それをベースとしているコアパッケージやコマンドラインツー ルを含んでいるアプリケーションを想像してみて欲しい。 このechoの例だとモジュールが多くてもやり遂げられるだろう:

    echo/
    pkg/
    echo/
    echo.c
    echo.h
    echo.go
    cmd/
    echo/
    echo.go

    pkg/echoパッケージはC言語のprintf関数を再利用出 来る様にラップし、そのソースは前述の例と殆ど同じであるとしよう。 cmd/echoコマンドはコアパッケージを使って画面に何かを出力する実行モジュールとしよう。 cmd/echoコマンドはこんな感じになるだろう:

    package main

    import (
        "github.com/nu7hatch/cgoecho2/pkg/echo"
        "flag"
    )

    func main() {
        flag.Parse()
        echo.Echo(flag.Args()...)
    }

    Note: slice... の意味を知らない人々のために言うと、引数の数に相当する変数へsliceをマップする物だ。Rubyで言うと*argsの様な物だ。

    話を戻そう。Makefileが必要なパッケージの為に私達が用意しなければならない簡単な物、それは以下の様な物だ:

    all: echo-pkg echo-cmd

    echo-pkg:
        go build ./pkg/echo

    echo-cmd:
        go build ./cmd/echo

    これによりmakeを呼び出すだけで両方を瞬時にコンパイルでき、もっと重要な事を言うとリモートからそれらをインストールするのにもgoコマンドを使う事が出来るんだ。:

    $ go get github.com/nu7hatch/cgoecho2/cmd/echo

    もちろんこれは非常に単純な例だ。ソースの全てを俊敏にビルドするにはワイルドカード使う事も出来る。慌てずに:

    $ go build ./...

    しかし、多くのパッケージおよび(または)コマンドを含む巨大なアプリケーションを配布するのはトリッキーになりがちだ。 その際makefileやシェルスクリプト、君の好きな他のビルドツールを使うのは妥当な事なのだ。

    まとめ

    ハッキリと言おう。私は新しいgo toolをマジで愛してやまない。! 初め、それを触って遊んでいる間に山の様に問題に遭遇した。 しかしほとんどの問題は、他のパッケージマネージャ/ツールを使用する間に、私が得てきた幾つかの悪い習慣によって引き起こされた物だった。 はぁ...最近、go-nutsのIRCチャネルで愚かな質問を沢山してしまったよ。 そして私が得る答えは馬鹿らしく明白で単純だった...

    以前使っていたeasy_installrubygemsbuilderといったこれまでのツールを担う物と考えていている。 私の心の中に一枚だけ写真がある... あぁ、でも嫌いになられそうなので公開しない方がよさそうだ。 :) 代わりといってはなんだが、新しいgo toolを私がどの様に感じているかをお見せしよう...

    ...

    私はgoが正しい向に向かっている事を見る事が出来てとてもうれしい。今日はこの辺にしておく。ごきげんよう。Gophers!