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

9月 22 '14

21 世紀のエディタである Atom を最強にする

Atom 最高ですね!!

でも、Atom は 21 世紀のエディタです。まだ 21 世紀になって 14 年しか経っていないので、20 世紀最強のエディタに比べてまだまだ足りない機能があるのはしょうがないですね!!

86 年後に勝負しよう!!

って感じですね。

みんなが拡張書けば 86 年がドンドン縮んでくると思うのですが、ぶっちゃけまだまだです。 なので、最強にするための拡張書いてみました。

open-vim

Atom で今開いているファイルを Vim で開く拡張です。

「あー、Vim だと xxx 出来るのに〜」

とか脳みそがまだ 20 世紀な時とか

「あー、このファイルデカすぎて Atom で編集すると重い……」

みたいなかわいそうな作業している時とか(2050 年位のマシンだとさくさくだと思いますけど!!)にお使いください。

21 世紀に戻る

command! OpenAtom !start atom %

こんな感じのを .vimrc に書いておけばいいんじゃないでしょうか?

Back To The Future !!!

p.s.

Emacs の話はしていません

参考資料: 21 世紀のエディタである Atom を最強にする - yoshiori.github.io



from Big Sky http://ift.tt/1uwPu0G
9月 18 '14

Windows でも PDCurses で UTF-8 を表示出来るようにした。

PDCurses はその名の通り Public Domain な curses 実装な訳ですが、Windows の実装こそありますが如何ともし難い問題がありました。

PDCurses には、ワイド文字列関数とバイト列で貰う実装があります。UNIX 系アプリケーションの多くは内部文字列がほぼ UTF-8 となり、C言語で受け渡される文字列は既成事実として UTF-8 になってしまいました。

しかしながら日本の Windows ではバイト列と言えば Shift_JIS な訳で、そのまま移植してしまうと文字化けが発生します。各アプリケーション側がワイド文字列でコードを書いてくれれば良いのですが、そんな事を気にする人はまずいません。ましてや各アプリケーションが UTF-8 と MBCS (Multi Byte Character Set) の変換を行うのは酷な話です。出来れば内部文字列は UTF-8 のままで Windows でも正しく表示されて欲しいのです。

mattn/pdcurses - GitHub


http://ift.tt/1tl5dSp

という訳で pdcurses に手を入れてみました。もし pdcurses.dll をリンクしていて表示が文字化けしているアプリケーションがあれば、dll を入れ替えるだけで文字化けが解消するかと思います。

今日はこれを使って、コマンドラインベースのプレゼンテーションツールである mdp を Windows で動かしてみました。

visit1985/mdp · GitHub


A command-line based markdown presentation tool.

http://ift.tt/1md1hCa

mdp 自身は大した事をやってないので、ncurses の代わりに pdcurses をリンクする様な修正を入れただけです。

diff —git a/Makefile b/Makefile
index 63a1feb..54f8327 100644
—- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@
 
 CFLAGS   = -O3 -Wall
 LDFLAGS  = -s
-LDLIBS   = -lncurses
+LDLIBS   = -lpdcurses
 OBJECTS  = cstring.o cstack.o markdown.o parser.o viewer.o mdp.o
 DESTDIR ?= /usr/bin
 
diff —git a/include/viewer.h b/include/viewer.h
index 68c7a13..f6e70fb 100644
—- a/include/viewer.h
+++ b/include/viewer.h
@@ -32,7 +32,7 @@
  *
  */
 
-#include <ncurses.h>
+#include <curses.h>
 
 #include “parser.h”
 #include “cstack.h”
diff —git a/viewer.c b/viewer.c
index ba76f2f..ed83196 100644
—- a/viewer.c
+++ b/viewer.c
@@ -22,7 +22,6 @@
  */
 
 #include <locale.h> // setlocale
-#include <ncurses.h>
 #include <stdlib.h>
 #include <string.h> // strchr
 #include <unistd.h>

sample.md も日本語にして正しく動作する事が確認出来ました。

mdp1
mdp2
mdp3
mdp4


from Big Sky http://ift.tt/XmePiM
9月 16 '14

html をコマンドラインからパースするなら pup が便利

2014年でも html を解析してゴニョゴニョするなんて要件はまだまだある訳で、そんな時に便利なのが pup というコマンドです。

EricChiang/pup - GitHub


README.md pup pup is a command line tool for processing HTML. It reads from stdin, prints to stdout,…

http://ift.tt/1tMEnQH

通常、こういったツールは perl や ruby、python 等で提供されランタイムがインストールされていない環境で動かすのはちょっとした手間が発生していました。しかし pup ならば golang で出来ているのでバイナリ1つあれば動かせます。

使い方は、例えばこのサイトのパーマリンクのテキストを得たいならば

curl -s http://ift.tt/KElEz5 | pup a.permalink

image

とするだけ。CSS セレクタで指定します。またテキストを得たいならば

curl -s http://ift.tt/KElEz5 | pup a.permalink text{}

といった具合です。一応バイナリリリースもされていますが現状 Windows で色付き表示(-c フラグ)でエスケープシーケンスが表示されてしまいます。

pull-request を送ってあるので、うまく行けばマージして貰えると思います。



from Big Sky http://ift.tt/1qGXo9U
9月 4 '14

MinGW コンパイラで argv をワイルドカード展開させない方法

コマンドラインから「あ*」等とワイルドカードを使用してコマンドを起動した場合、UNIX とは異なり Windows ではプロセス自身が引数を展開します(内部的にではありますが)。

main 関数の argc/argv は MSVC コンパイラであれば setargv.obj というオブジェクトファイルをリンクする事で展開される様になりますが、MinGW ではデフォルトでワイルドカード展開が実行されてしまいます。しかしながら、このワイルドカード展開は各コンパイラベンダーの実装次第という所があり、時に異なる挙動となる場合があります。

そこでワイルドカードは自前でプログラムで展開するのが一番良い訳ですが、MinGW の場合は既述の通り、デフォルトが展開動作となっています。しかし以下のたった1行のおまじないを入れる事で、引数展開が無効となります。

#include <stdio.h>

#define WIN32_LEAN_AND_MEAN  1
#include <windows.h>

int _CRT_glob = 0; // おまじない

int
main(int argc, char **argv) {
  int i;
  printf("command line: %s\n”, GetCommandLine());
  for (i = 0; i < argc; i++)
    printf( "argv[%d]: %s\n”, i, argv[i]);
  return 0;
}

おまじないの行をコメントアウトした場合

C:\dev>a あ*
command line: a  あ*
argv[0]: a
argv[1]: あ.txt

おまじないを実行した場合

C:\dev>a あ*
command line: a  あ*
argv[0]: a
argv[1]: あ*

アドホックすぎてかなり嫌ですね。どのコンパイラでも同じ動作をさせたいのならば、GetCommandLineW()CommandLineToArgvW() を使うべきだと思います。



from Big Sky http://ift.tt/Ye0lTC
9月 2 '14

C言語から golang の chan っぽい事が出来るライブラリ「chan」

名前そのままやん感がすごいですが。

tylertreat/chan - GitHub


http://ift.tt/1tUyHp3

golang の chan をC言語から使える様にするライブラリです。やはりC言語というだけあって、受け渡す値の型は void* ですがそこは目をつむりましょう。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include ”./src/chan.h”

#ifndef _WIN32
#include <unistd.h>
#include <termios.h>

char
getch() {
  char c = 0;
  struct termios old = {0};
  fflush(stdout);
  if (tcgetattr(0, &old) < 0)
    perror("tcsetattr()");
  old.c_lflag &= ~ICANON;
  old.c_lflag &= ~ECHO;
  old.c_cc[VMIN] = 1;
  old.c_cc[VTIME] = 0;
  if (tcsetattr(0, TCSANOW, &old) < 0)
    perror("tcsetattr ICANON");
  if (read(0, &c, 1) < 0)
    perror("read()");
  old.c_lflag |= ICANON;
  old.c_lflag |= ECHO;
  if (tcsetattr(0, TCSADRAIN, &old) < 0)
    perror ("tcsetattr ~ICANON");
  return c;
}
#endif

void*
capture(void *p) {
  chan_t* r = (chan_t*) p;
  while (!chan_is_closed(r)) {
    char c = getch();
    if (c == 'q') break;
    chan_send(r, (void*) &c);
  }
  chan_close(r);
  return NULL;
}

void*
fizzbuzz(void *p) {
  chan_t* r = (chan_t*) p;
  int n;
  for (n = 1; n <= 100 && !chan_is_closed(r); n++) {
    char buf[20] = {0};
    if (n % 3 == 0) strcat(buf, "Fizz");
    if (n % 5 == 0) strcat(buf, "Buzz");
    if (buf[0] == 0) sprintf(buf, ”%d”, n);
    chan_send(r, (void*) buf);
    sleep(1);
  }
  chan_close(r);
  return NULL;
}


int
main(int argc, char* argv[]) {
  chan_t* chans[2] = {chan_init(0), chan_init(0)};
  pthread_t th[2];

  if (pthread_create(&th[0], NULL, fizzbuzz, chans[0]) !=0) {
    perror("pthread_create");
    exit(1);
  }

  if (pthread_create(&th[1], NULL, capture, chans[1]) !=0) {
    perror("pthread_create");
    exit(1);
  }

  while (!chan_is_closed(chans[0]) && !chan_is_closed(chans[1])) {
    void* v = NULL;
    switch(chan_select(chans, 2, &v, NULL, 0, NULL)) {
    case 0:
      printf("FizzBuzz: %s\n”, (char*) v);
      break;
    case 1:
      printf("KeyTyped: %c\n”, *(char*) v);
      break;
    default:
      break;
    }
  }
  chan_close(chans[0]);
  chan_close(chans[1]);
  pthread_join(th[0], NULL);
  pthread_join(th[1], NULL);
  return 0;
}

1秒毎に更新される FizzBuzz を表示しながら、キーボードで入力された文字を表示します。FizzBuzz が100を超えるか、q をタイプすると終了します。FizzBuzz もキーボード入力もどちらもスレッドで実行しており非同期に処理されます。golang の様に go と書くだけで非同期処理が実行される訳ではないので pthread_create なんて長ったらしい名前を書く必要があります。C++ なら std::sync あたりを使えば簡単に書けそうな気もしますね。

pthread まわりをもうちょっと隠蔽すれば、まぁまぁかっこいい非同期処理が書ける様になるんじゃないかと思います。ただし golang の様に OS のスレッドとコルーチンをうまく切り替えたりはしないのでその辺は頑張る他無いです。

メッセージングを一から作るとなると結構大変なのでそこそこ使えるライブラリだと思います。

ただし void* で値を受け渡すということは、ヒープがそのまま渡るので、chan のバッファを1以上で動かす際には都度確保したメモリを渡さないと上書きされてしまいます。上記の例では説明の手間を省くために簡略化していますが、実際はもっと malloc/free が入り組んだコードになるかと思います。



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

kill で立つハッカー、シェルを濁す

shell - 立つハッカー、シェルを濁さず - Qiita


おことわり このTipsは不作法だとして異論が出るかもしれないが、私自身がよくやるのでここで公開してみる。それは一体何かというと…… コマンドヒストリーが残るのイヤだ! と思うことってよくないだろうか…

http://ift.tt/1qhVf31

man bash によると

HISTFILE
       The name of the file in which command history is saved (see HIS‐
       TORY below).  The default value is ~/.bash_history.   If  unset,
       the  command  history  is  not  saved  when an interactive shell
       exits.

HISTFILE を unset (HISTFILE=)したらヒストリは保存されないよと書いてある。

shell芸、嫌いではないけど、出来ればそういうのを tips として広めないで欲しい。kill -9 で殺してしまったら trap で後処理としてテンポラリファイルを消してる処理が走らなくなってしまうのではないですか?それって濁さないとは言わないのでは。



from Big Sky http://ift.tt/1qTsMN9
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