Install Theme

Your web-browser is very outdated, and as such, this website may not display properly. Please consider upgrading to a modern, faster and more secure browser. Click here to do so.

タンブラー?

image Big Sky

8月 27 '14

C言語の怖い話

夏だし怖い話しようぜ!

#include <stdio.h>
#include <iostream>

int
main() {
  char str[256];

  double a = 123.45;
  int b = 57;
  int c = 89;

  sprintf(str, "a=%f b=%d c=%d”, a, b, c);
  std::cout « str « std::endl;

  sprintf(str, "a=%d b=%f c=%d”, a, b, c);
  std::cout « str « std::endl;

  std::cout « "a=" « a « std::endl;
  std::cout « "b=" « b « std::endl;
  std::cout « "c=" « c « std::endl;

  return 0;
}

コンパイル時に警告は出るだろうけど、ちゃんと動くよね。

$ g++  -Wformat-nonliteral aaaa.cxx && ./a.out
aaaa.cxx: In function ‘int main()’:
aaaa.cxx:16:43: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘double’ [-Wformat]
aaaa.cxx:16:43: warning: format ‘%f’ expects argument of type ‘double’, but argument 4 has type ‘int’ [-Wformat]
a=123.450000 b=57 c=89
a=57 b=123.450000 c=89
a=123.45
b=57
c=89

きぇーーーーーーーーーーーーーーー!

C++ でなく C++ の場合だけ発生します。(Cでも発生しました)

ちなみに 32bit Windows だと gcc4.8, gcc4.9, clang3.4.2, VS2010, VS2012, VS2013 では

123.450000 57 89
-858993459 0.000000 89

こう出力されました。64bit Linux の gcc4.6.3, gcc4.9.1 だと上記の結果が出力されました。wandbox でもこんな結果になります。

だれか理由を教えて下さい…



from Big Sky http://ift.tt/1pgDOAp
8月 22 '14

「便利」と「感極まってきました」だけでプログラムが書ける日本語プログラミング言語「うじひさ」を作った。

誰も作ってくれないので自分で作った。

「便利」と「感極まってきました」だけでプログラム書ける日本語プログラミング言語「うじひさ」の登場が待たれる

— mattn (@mattn_jp)

August 21, 2014
mattn/ujihisa - GitHub


http://ift.tt/1pQeobX

golang で書かれています。go get http://ift.tt/1pQepN1 でインストール出来ます。使い方は

$ ujm [filename]

です。ファイル名が無い場合は標準入力から読み取ります。ベースは whitespace です。スペース文字が 便利、タブ文字が 感極まってきました に置き換わります。whitespace に慣れている人ならスイスイと書けるかと思います。例えば

便利便利便利感極まってきました
感極まってきました
便利感極まってきました



この様なコードなら 1 という数字が出力されます。

なお、便利 という文字を出力するにはこれくらいのコードが必要になります。golang で書かれているので Windows でも動きますし、文字の表示でユニコードを使うと Windows でも問題なく表示されます。

とても便利だと思うので、ぜひ使ってみて下さい。



from Big Sky http://ift.tt/1pQeoc3
7月 31 '14

なんでもシェルで書いちゃう男との人って…。

ShellScript - jq、xmllintコマンドさようなら。俺はパイプが好きだから - Qiita


UNIX哲学の一つとしてよく引用されるマイク・ガンカーズの教義に

  • 1.小さいものは美しい。
  • 2.1つのプログラムには1つのことをうまくやらせよ。

というのがあるが、まずこれができていない

http://ift.tt/OULTKx

昔の UNIX で扱っていたデータはだいたい行思考でした。そして UNIX は行思考データを扱う為の OS と言っても過言ではありませんでした。 しかし JSON はどうでしょう。JSON は行思考ではありません。ならばツールを変えるのが正しい選択だと思いますし、そこでシェルを選ぶのは正直マニアの方しかいませんよね。 入力データがバイナリであれば、ツールも変えるはずです。JSON もそうすべきだと僕は思います。

理由1. 一つのことをうまくやっていない

ShellScript - jq、xmllintコマンドさようなら。俺はパイプが好きだから - Qiita

JSON だけを扱っていますすし、他のデータを扱ってはいないですよね。

理由2. フィルターとして振る舞うようになりきれてない

ShellScript - jq、xmllintコマンドさようなら。俺はパイプが好きだから - Qiita

jq は JSON の grep 的な存在だと思っています。僕は jq を使いこなしている訳ではないし、「便利だなー」くらいにしか思っていませんが、JSON をシェルで扱いたいと思った場合にはJSON が苦無く扱える言語やツールを選びます

ちなみに jq だと上記の問題はどの様に解決出来るか試してみました。

#!/bin/bash

FILE=$1
cat $FILE | jq -r ’paths|map(if type==”number” then “[“+tostring+”]” else “[“+tojson+”]” end)|join(“”)’ |\
while read line; do
    value=`cat $FILE | jq -r ”.$line|if type=="string" or type=="number" then "MATCH:"+tostring else empty end”`
    if [ ”x$value” != ”x” ]; then
        echo $value | sed ”s/^MATCH:/.$line\t/”
    fi
done

実行結果は以下の通り。

.[“会員名”] 文具 太郎
.[“購入品”][0]  はさみ
.[“購入品”][1]  ノート(A4,無地)
.[“購入品”][2]  シャープペンシル
.[“購入品”][3][“取寄商品”]  替え芯
.[“購入品”][4]  クリアファイル
.[“購入品”][5][“取寄商品”]  6穴パンチ

パスは jq のパス式です。短くていいですね。

ネタだったら、マジレスごめんなさい



from Big Sky http://ift.tt/1oPvDtw
7月 30 '14

C++ の JSON ライブラリ json11 は initializer_list が綺麗。

おなじみC/C++から使えるJSONライブラリを紹介するコーナー。まずは過去のまとめ。

今回は json11 というライブラリ。

dropbox/json11 - GitHub


http://ift.tt/1gOo2r2

あの Dropbox が書いてる。C++ から使える JSON ライブラリは幾つかありますが、initializer_list が使える物がなかなか少ない。

json11 は以下の様に書ける。

Json my_json = Json::object {
    { "key1", "value1" },
    { "key2", false },
    { "key3", Json::array { 1, 2, 3 } },
};

前回の jansson の記事で使ったサンプルを json11 で書くと以下の様になります。

※ネットワーク通信部分は前回のコードよりも省略しています

C++11 向けライブラリですのでコンパイル時のコマンドラインオプションに -std=c++11 を付ける必要があります。

#include <iostream>
#include "json11.hpp"
#include <curl/curl.h>

size_t
stream_write(char* ptr, size_t size, size_t nmemb, void* stream) {
  ((std::string*) stream)->append(std::string(ptr, size * nmemb));
  return size * nmemb;
}

int
main() {
  CURL* curl;
  std::string buf;
  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, ”http://ift.tt/12Zb8uT”);
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
  curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl");
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, stream_write);
  curl_easy_perform(curl);
  curl_easy_cleanup(curl);

  std::string err;
  json11::Json v = json11::Json::parse(buf, err);
  for (auto &k : v["repositories"].array_items()) {
    std::cout « k["username"].string_value() « std::endl;
    std::cout « k["name"].string_value() « std::endl;
    std::cout « k["description"].string_value() « std::endl « std::endl;
  }
}

とてもきれい。ライセンスは MIT なので業務でも使えます。



from Big Sky http://ift.tt/1s2cwNT
7月 30 '14

Windows でも色付きでログが出せる golang のライブラリ「go-colorable」書いた。

golang には logger が星の数ほどあるのですが

go言語におけるロギングについて — さにあらず


コマンドラインオプションについて 分かり辛いので、僕の分かった事だけをメモしておきます。 ログの出力処理は glog.go#output を読めば大体分かります。 -logtostderr これを指定…

http://ift.tt/1rXBm1j

その殆どがエスケープシーケンスを使って色を出しており、Windows で動かすと残念な表示になる物ばかりでした。

まさかログに色を付けたいという理由だけで ansicon を使うのは悲し過ぎるし、そもそも「ansicon 使ったら負けだと思ってる」ので、go-colorable というライブラリを書きました。

golang の logger はその殆どが標準パッケージの log を参考にしており、おおよそ SetOutput という、出力先を変えられる関数が用意されています。そこで、それを横取りして Windows でも色を出せる様にしました。

mattn/go-colorable - GitHub


http://ift.tt/1nGg3jv

これを使うと今まで

bad

こんな表示だったのが

good

この様にカラフルな表示になります。使い方はとても簡単で

package main

import (
    "http://ift.tt/1nGg3jA;
    "http://ift.tt/1nGg3jF;
)

func main() {
    logrus.SetOutput(colorable.NewColorableStdout())

    logrus.Info("succeeded")
    logrus.Warn("not correct")
    logrus.Error("something error")
    logrus.Fatal("panic")
}

この様に NewColorableStdout を呼び出して io.Writer を取得し、それを logger 等に渡すだけです。Windows 以外の場合は os.Stdout を返す様になっているのでいちいち Windows かどうか判定する必要もありません。

UNIX で色を標準出力するライブラリ書いたけど、Windows… 知らねぇよ!って人は、ぜひこのライブラリを使ってみて下さい。きっと pull-request を貰うまでもなく、Windows 対応が完了している事になるはずです。



from Big Sky http://ift.tt/1nGfCG3
7月 29 '14

golang で N 個の chan を同時に待つ

あと最近の発見と絶望は、C.selectが呼び出せないこと。select中のdefaultでnonblocking相当にできるけど、可変数なfdをselectしたい相当をどう書けばいいんだろうか。 #golang

— HiroakiKawai (@kwi)

July 28, 2014

reflect.Select を使います。

package main

import (
    "fmt"
    "math/rand"
    "reflect"
    "sync"
    "time"
)

func multpleSelect(chans []chan bool) (int, bool, bool) {
    // chans の数分 select-case 文を作る
    cases := make([]reflect.SelectCase, len(chans))
    for i, ch := range chans {
        cases[i] = reflect.SelectCase{
            Dir: reflect.SelectRecv,
            Chan: reflect.ValueOf(ch),
        }
    }

    // 一括で select
    i, v, ok := reflect.Select(cases)
    return i, v.Interface().(bool), ok
}

func main() {
    rand.Seed(time.Now().UnixNano())

    // 100個の chan を作るよ
    chans := make([]chan bool, 100)
    for i := 0; i < 100; i++ {
        chans[i] = make(chan bool)
    }


    // 非同期で100個の chan を同時に待つ
    var wg sync.WaitGroup
    go func() {
        wg.Add(1)

        if ch, v, ok := multpleSelect(chans); ok {
            fmt.Printf("I am chan-%v, value is %v\n”, ch, v)
        }
        wg.Done()
    }()

    // ランダムな chan に true を送る
    chans[rand.Int() % len(chans)] <- true

    wg.Wait()
}

何度も繰り返して待つ場合は、その都度 SelectCase を作るのがコストになり得るので、予め作ったまま保持しておくのが良いかと思います。



from Big Sky http://ift.tt/1oEjCXC
7月 18 '14

C++ 製 micro web framework「crow」を使って lingr の bot 書いてみた。

先日、github で crow という、python の flask からインスパイアされた C++ 製 micro web framework を見つけました。

ipkn/crow - GitHub


http://ift.tt/TrRD1t

ルーティングの書き方が flask ぽく、かつモダンな C++ な書き方だったの気に入りました。

crow::Crow app;

CROW_ROUTE(app, ”/”)
    .name("hello")
([]{
    return "Hello World!";
});
app.port(18080)
    .multithreaded()
    .run();

何か作ってみたくなったので、lingr の bot を書いてみました。crow には JSON パーサ(シリアライザ)が同梱されているので API サーバを作るのも簡単そうです。

#include "crow.h"
#include "json.h"

#include <iostream>
#include <sstream>
#include <regex>

static std::vector<std::string>
str_split(const string s, const string d) {
  std::vector<string> r;
  std::string::size_type n;
  std::string b = s;
  while ((n = b.find_first_of(d)) != b.npos) {
    if(n > 0) r.push_back(b.substr(0, n));
    b = b.substr(n + 1);
  }
  if(b.length() > 0) r.push_back(b);
  return r;
}

static std::string&
str_replace(std::string& s, const std::string p, const std::string r) {
  std::string::size_type n(s.find(p));
  while (n != std::string::npos) {
    s.replace(n, p.length(), r);
    n = s.find(p, n + r.length());
  }
  return s;
}

class logger : public crow::ILogHandler {
public:
  void log(string message, crow::LogLevel level) override {
    cerr « message;
  }
};

int
main() {
  std::vector<std::pair<const std::regex, const std::string» resp;
  std::ifstream ifs("pattern.txt");
  if (ifs.fail()) return 1;
  string buf;
  while(ifs && getline(ifs, buf)) {
    auto t = str_split(buf, ”\t”);
    if (t.size() != 2) continue;
    std::cout « "Loading pattern: " « t[0] « ”=” « t[1] « std::endl;
    resp.push_back(make_pair(std::regex(t[0]), t[1]));
  }
  ifs.close();

  crow::Crow app;

  CROW_ROUTE(app, ”/”)
    ([]{
        return "lingr-cppbot";
    });

  CROW_ROUTE(app, "/lingr")
    ([&](const crow::request& req){
      auto x = crow::json::load(req.body);
      if (!x) return crow::response(400);

      std::stringstream os;
      for (const auto& e : x["events"]) {
        std::string t = e["message"]["text"].s();
        for (const auto& r : resp) {
          std::smatch matches;
          if (!regex_match(t, matches, r.first)) continue;
          std::string output = r.second;
          for (std::smatch::size_type i = 0; i < matches.size(); ++i) {
            std::stringstream ss;
            ss « ”$” « i;
            str_replace(output, ss.str(), matches[i]);
          }
          os « output;
          break;
        }
      }
      return crow::response{os.str()};
    });

  crow::logger::setLogLevel(crow::LogLevel::INFO);
  crow::logger::setHandler(std::make_shared<logger>());

  uint16_t port;
  std::stringstream ss;
  ss « getenv("PORT");
  ss » port;
  if (port == 0) port = 8080;
  app.port(port).multithreaded().run();
}

// vim:set et:

仕組みは至って簡単で、カレントディレクトリにある pattern.txt という、以下の様なファイルを読み込み、正規表現(タブ文字で区切られた左側)に対する置換文字列(右側)を設定します。

^あー$  いー
^いー$  うー
^うー$  えー
^えー$  おー
^おー$  もうええやろ!
^(.+)(大好き|だいすき)  $1は俺の物だ。勝手に呼び捨てにするな。

起動して、正規表現にマッチする発言を受信すると、置換文字列をサブマッチなどで入れ替えて返答します。

cppbot

サブマッチ置換が使えるので、ある程度人間っぽい発言も可能ですし、gh:mattn という文字列から http://ift.tt/1zOZhDR という返答をさせてアンカーを作る等の応用例もあります。(参考資料)

crow は内部でスレッドを使っており、複数同時リクエストにも応答出来る様です。色々遊べそうなので試してみてはいかがでしょうか。



from Big Sky http://ift.tt/1lapnHx
7月 11 '14

Vim scriptテクニックバイブル ~Vim使いの魔法の杖

こんにちわ。Vim scriptサポーターズの mattn です。

ちょうど3年程前、Vimテクニックバイブルという書籍を執筆させて頂きました。

Big Sky :: Vimテクニックバイブル ~作業効率をカイゼンする150の技


http://ift.tt/1dcpDXv

おかげ様で、色んな方から反響を頂き執筆して良かったと思いました。初めて自分が書いた書籍が販売されるという高揚感に包まれる中、書籍の販売からたった数週間後、何を思ったか僕と KoRoN さんは github 上に vim-users-jp というオープングループを作る事になりました。

Big Sky :: github上にvim-users-jpというorganizationを作った。


http://ift.tt/1sFQtLw

そして数日後、vim-jp が誕生します。

vim-jp » Vimのユーザーと開発者を結ぶコミュニティサイト


http://vim-jp.org/

今から思えば、かなり思い切った事をやったもんだなーと我ながら思います。あの思いっきりが無かったら vim-jp は生まれなかったと思います。

あれからVim界隈は人気に陰りが出るどころか、さらなる進展を遂げ、vim-jp から提供するパッチが vim_dev に溢れ、多くの contribute authors を排出し、多くの優秀な Vim プラグインが作られ、毎週 vimrc 読書会が開催され、本当に20年も昔に作られたテキストエディタなのか?と疑いたくなる状況となりました。

Vim script の知名度についてはどうでしょうか?プラグインを書く人が増えたものの、ちゃんとした誘導書が無い為に色んなテクニックが氾濫し、その為に敷居があがり「変態言語」と呼ばれる部類に入れられる事も多い様です。

そして個々の力技により色んなハックが生まれ、時に Vimmer は怖いと言われる事も目にします。しかしそれ程に Vimmer は Vim script を愛しているのです。

ただし良く考えて下さい。

プログラミング言語 Vim script は本来、vimrc を記述する為の言語なのです。

ちゃんとした vimrc を書く為にはちゃんとした Vim script を書く必要があるのです。そして誰かがちゃんとしたハックを何処かに記し、皆が同じハックを共有出来るべきだと思うのです。

Vimテクニックバイブルは Vim の凄さを広める為に生まれましたが、Vim script を皆に知って貰う為にはしっかりとした誘導書が必要なんだ、そんな風に思った事もありました。

そしてVimテクニックバイブル発売から3年、あの時にお世話になった技術評論社様にまたお力をお貸し頂き、今回「Vim scriptテクニックバイブル」という書籍の執筆をお手伝いをさせて頂きました。


Vim Script テクニックバイブルVim Script テクニックバイブル
VimScriptサポーターズ
技術評論社 / ¥ 2,786 (2014-08-06)
 
発送可能時間:近日発売 予約可


実は今回、Vim scriptサポーターズという著者名となっておりますが、かつてない程に Vim script に詳しい人間が揃いました。


Shougo

ご存じ「暗黒美夢王」です。色んな所で有名な Vimmer で、特に補完系のプラグインには絶大な拘りのある人です。

おそらく日本 Vim 界隈では年に一番 Vim script を書いている人だと思います。


thinca

こちらもご存じ「マンボウ」です。vim-jp では Vim script の挙動を一番良く知っている人だと思います。vimrc 読書会でも thinca さんの指摘内容は確実で、皆から「安心と信頼の thinca」と呼ばれています。(※要出典)

彼は基本的に Vim script を書くスピードは速くありません。しかし一つ一つが確実で、他の Vimmer に例を見ない程の慎重派です。だからこそ巷に溢れた vimrc に散乱するダメな Vim script には厳しく指摘が飛ぶのだと思います。


KoRoN

僕のこのブログをホストしている「香り屋」の店主であり、vim-jp 発起者でもあります。

十数年前から vim のバイナリ配布を始め、お世話になった Vimmer も多いと思います。僕もネット上でお付き合いを初めて10数年になりました。去年は大阪でお好み焼きを食べ、知り合った頃の懐かしい話等をさせて頂きました。

Vim の内部構造にめちゃくちゃ詳しい人です。vim-jp でもパッチ屋と呼ばれている部類の人です。

今回、書籍執筆のリーダとして仕切って頂きました。


「これだけ揃えばもうお腹いっぱいだろ!」というメンツが揃い、実践的なテクニックを惜しげも無く記してあります。

人の vimrc からコピペして自分の vimrc を作るのは簡単です。しかし自分だけの Vim を作り上げる為には自分で vimrc を書く必要があるのです。

本書はテクニックバイブルという名前は付いていますが実際は

Vimmer が自分だけの Vim 探しのお手伝いをする際の誘導書

的な存在となります。

ぜひお手に取って付箋紙をベタベタと貼って、自分だけの Vim を作り上げて下さい。



from Big Sky http://ift.tt/1oJTKHa
7月 9 '14

Vim で flappyvird 書いた。

前回、「幅跳び」が好評だったので、あの有名なゲーム「Flappy〇ird」を Vim で出来る flappyvird-vim を書いてみました。

mattn/flappyvird-vim ・ GitHub


http://ift.tt/1lTypYP

flappyvird
画像は開発中の物で、実際のキャラクタは異なります

良かったら遊んで下さい。

:FlappyVird

でゲームスタート、スペースキーでジャンプ、p で一時停止、q もしくは ESC でゲーム終了です。


from Big Sky http://ift.tt/1lTypYT
7月 8 '14

Vim で peco する「veco」書いた。

vimでpecoりたい

— Yoichi Fujimoto ? (@wozozo)

July 8, 2014
って事で書いた。
mattn/ctrlp-veco ・ GitHub


http://ift.tt/1munCZx

実行には CtrlP が必要。

peco の代わりに vim を使う。ただそれだけ。

veco



from Big Sky http://ift.tt/1kyXicB
7月 8 '14

Rob Pike のプログラミングに関する5つの掟

掟1

プログラムの時間を費やす箇所がどこにあるのかは知り得ない。ボトルネックは意外な場所で発生するため後知恵で批判してはならないし、ボトルネックがどこにあるか証明出来るまではスピードハックを入れてはいけない。

掟2

測定しよう。測定し終えるまでは、さらにはコードの一部分が残りのコードの支配的な量とならないならばチューニングを行ってはいけない。

掟3

Fancy アルゴリズムは、n が小さいときに低速となり、通常 n は小さい。Fancy アルゴリズムは大きな定数を有する。n は頻繁に大きくなり得ることを知るまでは fancy アルゴリズムを得てはならない。 (n が大きくなる場合であっても、まず掟 2 を行いなさい)

掟4

Fancy アルゴリズムは単純なものよりもバギーであり、実装が非常に難しい。簡単なアルゴリズムだけでなく、単純なデータ構造を使用すること。

掟5

データが支配する。もし正しいデータ構造と組織的な物事を上手く選択したとすれば、アルゴリズムは殆どの場合自明となる。データ構造はアルゴリズムとは違いプログラミングの中心である。

Pike の掟 1 と 2 は Tony Hoare の有名な格言「早まった最適化は諸悪の根源である。」の言い換えであり、Ken Thompson は Pike の掟 3 と 4 を「疑わしいならばブルートフォースを使用すべきだ」と言い換えた。掟 3 と 4 は、the design philosophy KISS (Keep It Simple, Stupid)の具現。掟 5 は、The Mythical Man-Month で Fred Brooks が述べた。掟 5 は、多くの場合、「スマートオブジェクトを使うと愚かなコードを書く」に短縮される。

参照:

Rob Pike’s 5 Rules of Programming

from Big Sky http://ift.tt/1thJPzh
7月 8 '14

git で pull-request を clone する設定が覚えられないので alias 書いた。

github の pull-request を clone する設定をいつも思い出せなくて、毎回ググってるので alias を書いた。
Checkout github pull requests locally


Here’s fetch : 1 git fetch From github.com:gittip/www.gittip.com * [new ref] refs/pull/100/head -> o…

http://ift.tt/Y9PDKf

$ git config —global alias.pr-setup “config —add remote.origin.fetch +refs/pull/*/head:refs/remotes/origin/pr/*”

とすれば alias がインストールされるので、以後は pull-request を監視したいリポジトリを clone した後

$ git pr-setup

とすれば .git/config に上記リンク先の設定が入るので後は普通に

$ git fetch origin
$ git checkout pr/999

とかすればいい。ちなみに clone した瞬間に設定する方法無いかなーと思ったけど、clone したいだけのリポジトリで勝手に fetch されて太っても嫌だなーと思ったので手動で pr-setup を叩く事にする。

from Big Sky http://ift.tt/1k0JYOb
7月 7 '14

Vim でたんざくを作ろう

:echo webapi#json#decode(webapi#http#get(”http://ift.tt/1lMySvP”, {"q": "カッコイイVimmerになれますように"}).content).c

┏┷┓
┃ ┃
┃カ┃
┃ッ┃
┃コ┃
┃イ┃
┃イ┃
┃V┃
┃i┃
┃m┃
┃m┃
┃e┃
┃r┃
┃に┃
┃な┃
┃れ┃
┃ま┃
┃す┃
┃よ┃
┃う┃
┃に┃
┃ ┃
┗━┛



from Big Sky http://ift.tt/1rFBJOY
7月 6 '14

Re: 断続的にデータを受けながら並行で時間差リアクションを行う

断続的にデータを受けながら並行で時間差リアクションを行う - すぎゃーんメモ


断続的にデータを受けながら並行で時間差リアクションを行う Go はじめて、の次のGo - すぎゃーんメモ にて作った go-genki-bot 、UserStreamから Tweet 取得して返信する…

http://ift.tt/1vGi1jX

ちょっと動きは違うんだけど、こういうパターンもあるよねー。という事で。

package main

import (
    "bufio"
    "fmt"
    "os"
    "runtime"
    "time"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())

    queue := make(chan rune, 5)

    t := time.AfterFunc(-1, func() {
        // ある分だけ読み込む
        leave: for {
            select {
            case r := <-queue:
                fmt.Println("recv", string(r))
            case <-time.After(100 * time.Millisecond):
                // 100ms 読めなかったら諦める
                break leave
            }
        }
    })

    // タイマーは止めておく
    t.Stop()

    in := bufio.NewReader(os.Stdin)
    for {
        // 何かキー入力
        r, _, err := in.ReadRune()
        if err != nil {
            break
        }

        // LFはいらない
        if r == 0x0A {
            continue
        }

        // タイマーを活性化(3秒後)
        t.Reset(3 * time.Second)

        // タイマーに読んで貰う為に入力したキーをchanで送信しておく
        queue<-r
    }
}

入力を得たらタイマーを活性化する。タイマーは一つしか使わなくて、データが来るたびに更新するのでデータが最後の入力から3秒間何も更新がなければ発動する。タイマーは発動すると100ms内に見つかった分だけ抜き取って表示。

$ go run jisa.go 

recv あ
あいうえ
recv あ
recv い
recv う
recv え

この手法は gof の画面表示部分で使われていて、連続するキー入力に対して毎回描画を行っていると画面がチラ付くという問題を回避出来る。

詳しくは以下を参照して下さい。
Golang でコマンドライン Fuzzy Finder 「gof」作った。 - Qiita


この記事は Go Advent Calendar 2013 の 10 日目の投稿です。 はじめに 業務のツールや連携させる一部の機能として golang を使い出している方もチラホラ現れ始めました。 …

http://ift.tt/1feEizg

Go Advent Day 19 - Eject the Web - The Gopher Academy Blog


Other Articles Next article Go Advent Day 20 - Go in Academia: Emulating Wireless Networks Previous …

http://ift.tt/19UB0wq



from Big Sky http://ift.tt/1oabp9l
7月 3 '14

Windows で便利な clib パッケージを3つ程書いた

先日、C言語向けのパッケージマネージャ clib を紹介したのですが、その後 Windows で使えそうなパッケージを3つ程書きました。
Big Sky :: clib の使い勝手にマジ感動した


C言語でアプリケーションを書くのは他の言語と比べて少し気合が必要ですよね。例えば HTTPからデータを取得する 取得したデータを json パースする 結果の一部を色付きで表示する こんな場合、C言語…

http://ift.tt/1mlyUuG

locale-string.c 最近のライブラリは文字列が utf-8 前提で書かれている物が多く、Windows だと「それ、ツライわー(汗)」だったりするのですが、かと言ってこれだけの為に変換ライブラリを入れるのはアレですし、iconv 入れちゃったら GPL(LGPL) だし仕事で使えねー、みたいな事が起きてしまいます。
でもロケール文字列と utf-8 との変換なら mbstowcs や wcstombs があれば出来るし、Windows なら MultiByteToWideChar や WideCharToMultiByte があれば出来るので、それだけのライブラリを書きました。
mattn/locale-string.c - GitHub


http://ift.tt/1iZ6QCO

使い方は簡単。

setlocale(LC_CTYPE, ””);
const char* ptr = "こんにちわ世界";
char* mbs = utf8_to_locale_alloc(ptr);
assert(NULL != mbs);
char* utf8 = utf8_from_locale_alloc(mbs);
assert(NULL != utf8);
assert(0 == strcmp(ptr, utf8));

使い終わったら free が必要。utf8_to_locale_alloc で utf-8 文字列をロケール文字列へ、utf8_from_locale_alloc でロケール文字列から utf-8 へ変換します。
Linux や Mac だと必要ない機能なのでマクロを用意してあります。

#ifdef _WIN32
# define UTF8_ALLOC(p) utf8_from_locale_alloc(p)
# define UTF8_FREE(p) free(p)
# define LOCALE_ALLOC(p) utf8_to_locale_alloc(p)
# define LOCALE_FREE(p) free(p)
#else
# define UTF8_ALLOC(p) (p)
# define UTF8_FREE(p)
# define LOCALE_ALLOC(p) (p)
# define LOCALE_FREE(p)
#endif

Windows 以外ならばメモリ確保も解放も行いません。

wcwidth.c 皆さんしってる wcwidth です。
wcwidth, wcswidth, wcwidth_cjk, wcswidth_cjk がそろっていますが、オマケで utf-8 文字列の幅を求める string_width と string_width_cjk も付いてきます。

assert(14 == string_width("こんにちわ世界"));
assert(20 == string_width("こ★ん■に●ち▲わ☆世◆界"));
assert(26 == string_width_cjk("こ★ん■に●ち▲わ☆世◆界"));

こんな感じに使います。

ansicolor-w32 最近の Linux のアプリケーションでコンソールに色付きで出力される物も最近では珍しくなくなってきました。
ただ Windows だと API が超メンドクサイので Constellation さんの console-colors.c を使うのが良いのですが、UNIX 系ツールを移植していてなるべくオリジナルコードを触りたくない場合にはツライんです。
mattn/ansicolor-w32.c - GitHub


http://ift.tt/1iZ6Se3

そこで ansicolor-w32.c というのを書きました。ansicolor-w32.h を include すると、エスケープシーケンスを解析して Windows でも色付けで表示してくれます。
ansicon というツールも存在しますが、このライブラリはそれ無しでも色付け可能です。

fprintf, fputs, printf, puts だけ対応しています。

#include <stdio.h>
#ifdef _WIN32
# include "ansicolor-w32.h"
#endif

int
main(int argc, char* argv[]) {
  printf(”\x1b[2J\x1b[10,10H\x1b[24m\x1b[30m”);
  printf(”\x1b[42m博\x1b[43m多\x1b[46mの\x1b[45m塩\x1b[0m”); 
  return 0;
}

例えばこんなコードを書いて実行すると

博多の塩

この様に表示されます。

よろしければお使い下さい。MIT ライセンスです。


from Big Sky http://ift.tt/1oc4yxx