DELAEMON BLOG

Live as if you were to die tomorrow. Learn as if you were to live forever.

NeoVim Install On Ubuntu14.04

Linuxbrewが必要でrubypython-setuptoolsまで入れたら、
結局不要で、Ubuntuはパッケージ用意されてた

Installing · neovim/neovim Wiki · GitHub
Homebrew/linuxbrew · GitHub

sudo apt-get install curl ruby python-setuptools
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/linuxbrew/go/install)"
#/path/.linuxbrew/binにパスを通す
brew tap neovim/homebrew-neovim
brew install --HEAD neovim
#省略
make[2]: *** [CMakeFiles/busted.dir/all] Error 2
make[2]: Leaving directory `/tmp/neovim-yzfKc0/.deps'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/tmp/neovim-yzfKc0/.deps'
make: *** [deps] Error 2

READ THIS: https://github.com/Homebrew/linuxbrew/blob/master/share/doc/homebrew/Troubleshooting.md#troubleshooting
If reporting this issue please do so at (not Homebrew/homebrew):
  https://github.com/neovim/homebrew-neovim/issues

Linuxbrewで入れるのかと思ったら時間かかるし、途中でコケる。
Ubuntuはパッケージ用意されてる。

sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt-get update
sudo apt-get install neovim

PHPで色付きdump

書きなぐり

<?php
//  echo -e '\e[VALUE[;VALUE..]mSTRINGS\e[m'
/*
    Text attributes
    0   All attributes off
    1   Bold on
    4   Underscore (on monochrome display adapter only)
    5   Blink on
    7   Reverse video on
    8   Concealed on

    Foreground colors
    30  Black
    31  Red
    32  Green
    33  Yellow
    34  Blue
    35  Magenta
    36  Cyan
    37  White

    Background colors
    40  Black
    41  Red
    42  Green
    43  Yellow
    44  Blue
    45  Magenta
    46  Cyan
    47  White
 */

$output = null;
$indent = null;
function color($value = null)
{
    global $output;
    global $indent;
    switch (true) {
    case is_int($value):
        $type = '(int)';
        $color = 36; // Cyan
        break;
    case is_string($value):
        $type = '(str)';
        $color = 31; // Red
        break;
    case is_bool($value):
        $type = '(bool)';
        $color = 32; // Green
        $value = $value ? 'true' : 'false';
        break;
    case is_array($value):
        $output .= "$indent(array) => [\n";
        $indent .= "  ";
        foreach ($value as $v) {
            color($v);
        }
        $indent  = substr($indent , 0 , strlen($indent) - 2);
        $output .= "$indent]\n";
        return;
    case is_object($value):
        break;
    default:
        if (is_null($value)) {
            $type = '(null)';
            $value = 'null';
        }
        $color = 33; // Yellow
        break;
    }
    $output .= sprintf("\e[%dm%s%s %s \e[m\n", $color, $indent, $type, $value);
}

color(123);
color('abc');
color(true);
color();
color([1,'1',false]);
color([[1,2,3], ['a', 'b', 'c'], [true, false, null]]);

echo $output . "\n";

こんな感じ
f:id:delaemon:20150207184846p:plain

golang wiki

http://golang.org/dl/go1.3.darwin-amd64-osx10.8.pkg でインストールした

% go version
go version go1.3 darwin/amd64

http://golang.jp/codelab-wiki
やってみたけど、現在は存在しない関数、構造体使っていたので動くようにしたコードが以下

package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
    "html/template"
    "regexp"
)

const lenPath = len("/view/")

type Page struct {
    Title string
    Body[]byte
}

var templates = make(map[string]*template.Template)

var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$")

func (p *Page) save() (err error) {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    body,err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there I Love %s!", r.URL.Path[1:])
}

func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
    p, err := loadPage(title)
    if err != nil {
        http.Redirect(w, r, "/edit/" + title, http.StatusFound)
        return
    }
    renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request, title string) {
    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }
    renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
    body := r.FormValue("body")
    p := &Page{Title: title, Body: []byte(body)}
    err := p.save()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
    err := templates[tmpl].Execute(w,p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func makeHandler(fn func (http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        title := r.URL.Path[lenPath:]
        if !titleValidator.MatchString(title) {
            http.NotFound(w, r)
            return
        }
        fn(w, r, title)
    }
}

func init() {
    for _, tmpl := range []string{"edit", "view"} {
        t := template.Must(template.ParseFiles(tmpl + ".html"))
        templates[tmpl] = t
    }
}

func main() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/view/", makeHandler(viewHandler))
    http.HandleFunc("/edit/", makeHandler(editHandler))
    http.HandleFunc("/save/", makeHandler(saveHandler))
    http.ListenAndServe(":8080", nil)
}

こいつ・・・動くぞ

go tool 6g wiki.go
go tool 6l wiki.6
./6.out

もっと簡単にできた

go build wiki.go
./wiki

実行ファイル作らないでも動かせる

go run wiki.go

アクセス
http://localhost:8080/edit/hoge

hhvm install on OSX 10.8 (UNSUPPORTED)

OSXは正式にはサポートされてない
http://docs.hhvm.com/manual/en/install.macosx.php
jit対応してないから速さは体感できないけど、機能試したり開発はできる。
ローカルで開発したくてOSXにしたけど、UbuntuとかDebianでやる方がよさげ。

ここ見てインストール
https://github.com/facebook/hhvm/wiki/Building-and-installing-HHVM-on-OSX-10.8

1時間以上かかる。何回か途中でこけるけど、再実行で先に進む。

brew update
brew upgrade
brew tap homebrew/dupes
brew tap homebrew/versions
brew tap mcuadros/homebrew-hhvm
brew install hhvm --HEAD

エラーで止まる。

--HEADは現在使用不能。3.1.0の変更に追従出来ていない。
https://github.com/mcuadros/homebrew-hhvm/issues/87

とりあえず動かしたいので最新じゃなくていい。

brew install hhvm

確認

hhvm --version
HipHop VM 3.0.1 (rel)
Compiler: heads/master-0-g6ea18c3ef056ff8b863a56f8ec4940b7b320f351
Repo schema: e69de29bb2d1d6434b8b29ae775ad8c2e48c5391


型エラーになるか動かしてみる。
sample.hh

<?hh

// Hack functions are annotated with types.
function my_negation(bool $x): bool {
  return !$x;
}

// and return with the type 'int'.
function add_one(bool $x): int {
// function add_one(int $x): int { // success
  return $x+1;
}

print(add_one(1));
hhvm sample.hh
Fatal error: Argument 1 passed to add_one() must be an instance of bool, int given in /path/sample.hh on line 11

phpでも動くよ。
sample.php

<?php
function add_one(int $x): int {
  return $x+1;
}

print(add_one(1));
hhvm sample.php

Fatal error: Syntax only allowed with -v Eval.EnableHipHopSyntax=true in /Users/dela/Documents/develop/hhvm/sample.php on line 2

オプション付ければね。

hhvm -v Eval.EnableHipHopSyntax=true sample.php
2

混合もOK。
sample.php

<?php
function add_one(int $x): int {
  return $x+1;
}

$list = [1,10,100];
$r = array_map('add_one', $list);
var_dump($r);
hhvm -v Eval.EnableHipHopSyntax=true sample.php
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(11)
  [2]=>
  int(101)
}

OSXでも試すくらいは出来る。
でも試すだけならtutorialある。
http://hacklang.org/tutorial

お疲れさまでした。

MySQL UDF UDF_ARGS, UDF_INIT

mysql_com.h

487 typedef struct st_udf_args
488 {
489   unsigned int arg_count;>-->---/* Number of arguments */
490   enum Item_result *arg_type;>-->---/* Pointer to item_results */
491   char **args;>->--->--->---/* Pointer to argument */
492   unsigned long *lengths;>-->---/* Length of string arguments */
493   char *maybe_null;>>--->---/* Set to 1 for all maybe_null args */
494   char **attributes;                    /* Pointer to attribute name */
495   unsigned long *attribute_lengths;     /* Length of attribute arguments */
496   void *extension;
497 } UDF_ARGS;
498
499   /* This holds information about the result */
500
501 typedef struct st_udf_init
502 {
503   my_bool maybe_null;          /* 1 if function can return NULL */
504   unsigned int decimals;       /* for real functions */
505   unsigned long max_length;    /* For string functions */
506   char *ptr;                   /* free pointer for function data */
507   my_bool const_item;          /* 1 if function always returns the same value */
508   void *extension;
509 } UDF_INIT;

MySQL UserDefinedFunction

http://dev.mysql.com/doc/refman/4.1/ja/adding-udf.html

単純関数のUDFでhello world的なものを作ってみる。

orz.c

#include <string.h>
#include <mysql/mysql.h>

my_bool orz_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
    return 0;
}

void orz_deinit(UDF_INIT *initid)
{

}

char* orz(UDF_INIT *initid, UDF_ARGS *args, char *res, unsigned long *res_length, char *is_null, char *error)
{
    strcpy(res, "orz...orz...orz...");
    *res_length = strlen(res);
    return res;
}

pluginのディレクトリを調べる

mysql> SHOW VARIABLES LIKE 'plugin_dir';
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| plugin_dir    | /usr/lib/mysql/plugin/ |
+---------------+------------------------+
1 row in set (0.00 sec)

コンパイルして*.soをpluginのディレクトリに置く

$ gcc -o orz.so orz.c `mysql_config --cflags` -shared -fPIC
$ sudo cp orz.so /usr/lib/mysql/plugin/

mysqlに作った関数を登録

mysql> CREATE FUNCTION orz RETURNS STRING SONAME "orz.so";

実行

mysql> SELECT orz();
+--------------------+
| orz()              |
+--------------------+
| orz...orz...orz... |
+--------------------+
1 row in set (0.00 sec)

この本が詳しいらしいので、あとで読む

Mysql 5.1 Plugin Development

Mysql 5.1 Plugin Development

Apache Module logging

前回のままだとエラーメッセージを画面に出力してるので、ログファイルに書き出すように変更。

読み込み

#include "http_log.h

エラー

    int code = apr_dbd_select(dbd->driver, r->pool, dbd->handle, &res, stmt, 0);
    if (code != 0) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "failed. error_code:%d", code);
        return;
    }

デバック

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "finish.");

デバック出す場合はhttpd.confのログレベルを変更

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel debug

ap_log_rerrorの引数の順番やAPLOG_MARKとかAPLOG_ERRのマクロは何?と思ったら
ap_log_XXX関数、APLOG_XXXマクロについて書かれた以下を参照
http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__LOG.html