2010年6月18日金曜日

autopair, paredit

職場のWindowsに導入してみた。

ついでに、選択範囲を上書きする (delete-selection-mode 1) も。

参考

  • http://trey-jackson.blogspot.com/2009/09/emacs-tip-33-paredit.html
  • http://emacs-fu.blogspot.com/2010/06/automatic-pairing-of-brackets-and.html
  • http://www.emacswiki.org/emacs/AutoPairs

課題

  • skkでの入力中は無効にしたい(カッコ/コッカが入力できないため) ← adviceで対応
(defadvice skk-mode (around disable-autopairs-around (arg))
  "Disable autopairs mode when skk-mode is on"
  ad-do-it
  (if skk-mode
      (autopair-mode 0)
    (autopair-mode 1)
    ))
(ad-activate 'skk-mode)

2010年6月7日月曜日

BOM の存在を消去する(Perlの場合)

BOM存在のチェックと、その除去を行うプログラム(Perl)

一口にBOMと言っても、エンコードに応じて実体は様々あるらしい(utf8なら 0xEF 0xBB 0xBF)

1. BOMチェックスクリプト

#!/usr/bin/perl
@bom = (
  chr(0x00).chr(0x00).chr(0xFE).chr(0xFF),
  chr(0xFF).chr(0xFE).chr(0x00).chr(0x00),
  chr(0x00).chr(0x00).chr(0xFF).chr(0xFE),
  chr(0xFE).chr(0xFF).chr(0x00).chr(0x00),
  chr(0xFE).chr(0xFF),
  chr(0xFF).chr(0xFE),
  chr(0xEF).chr(0xBB).chr(0xBF)
);

if(-f $ARGV[0]){
  open(FILE, $ARGV[0]) or die;
  $dat = <FILE>;
  for(my $i = 0; $i <= $#bom; $i++){
    if(index($dat, $bom[$i]) == 0){
      print "$ARGV[0]\n";
      last;
    }
  }
  close(FILE);
}

2. BOM除去スクリプト(いちおうバックアップを取る仕様)

#!/usr/bin/perl
if(-f $ARGV[0]){
    my $f = $ARGV[0];
    my $new = $f . '.new';
    my $flg = 1;
    open(OLD, $f) or die;
    open(NEW, "> $new")         or die "can't open $new: $!";
    while (<OLD>) {
        if($flg) {
            print NEW substr($_, 3) or die "can't write $new: $!";
            $flg = 0;
        } else {
            print NEW $_            or die "can't write $new: $!";
        }
    }
    close(OLD)                  or die "can't close $old: $!";
    close(NEW)                  or die "can't close $new: $!";
    rename($f, "$f.orig")       or die "can't rename $old to $old.orig: $!";
    rename($new, $f)            or die "can't rename $new to $old: $!";
} else {
    die 'no argument';
}

PHPのレアな関数

* error_get_last()
(PHP 5 >= 5.2.0)
error_get_last — 最後に発生したエラーを取得する。

* simplexml_load_file()
(PHP 5)
simplexml_load_file — XMLファイルをパースし、オブジェクトに代入する

* PHPバージョン5以上だとini_set()、.htaccessでallow_url_fopenを有効にできない
管理者にphp.iniを変更してもらわなければ file_get_contents() や simplexml_load_file() が使えない。
↓こんな感じのエラーが発生(failed to open steream

Array ( [type] => 2 [message] => file_get_contents(http://twitter.com/statuses/user_timeline/138673716.rss) [function.file-get-contents]: failed to open stream: no suitable wrapper could be found [file] => /virtual/www/2012/lib/twjson.php [line] => 12 )

2010年6月6日日曜日

Caching and Memoization

Higher Order Perl.

inline caching
memoization
marshalling
orcish maneuver ( || and cache 戦略、||= 演算子)
semipredicate problem

memoizationではsymbol tableも書き換えないといけない(再帰関数の場合に、内部で古い関数定義が呼び出されてしまうから)

"Partition problem" - 面白い例題。Chapter1, 3, 4 で徐々に改善されていく。NP-complete problem らしい(Nondeterministic Polynomial)

2010年6月3日木曜日

ul要素内のliをランダムに並び替えるJavaScript

  // random image
  if($('body#home').length){
    var ul = $('div.category > ul');
    if(!ul) return;

    var chi = ul.children();
    for(var i = 0, n = chi.length; i < n; i++){
      var r = Math.floor( i + Math.random() * (n - i) );
      var tmp = chi[i];
      chi[i] = chi[r];
      chi[r] = tmp;
    }

    ul.html(chi);
  }

htmlタグを除いてマルチバイト150文字にtruncateする関数

htmlタグを除き、さらにマルチバイト文字150文字を取り出す。


/********************************************************************************************
myTruncate() : 
- 用途 : truncate string considering HTML tag.
- 引数 : html string, maxlength, url
- 戻値 : truncated string
********************************************************************************************/
function myTruncate($html, $maxLength, $url) {
    $printedLength = 0;
    $position = 0;
    $tags = array();
    $printstr = '';

    mb_internal_encoding("UTF-8");

    // while ($printedLength < $maxLength && preg_match('{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}', $html, $match, PREG_OFFSET_CAPTURE, $position))
    // ここの preg_match を等価なマルチバイト処理に変更すればうまくいく(たぶん)
    while ($printedLength < $maxLength && $this->mb_preg_match('{</?([^>]+)>|&#?[a-zA-Z0-9]+;}', $html, $match, PREG_OFFSET_CAPTURE, $position))
        {
            list($tag, $tagPosition) = $match[0];

            // Print text leading up to the tag.
            $str = mb_substr($html, $position, $tagPosition - $position);
            if ($printedLength + mb_strlen($str) > $maxLength)
                {
                    //print(mb_substr($str, 0, $maxLength - $printedLength));
                    $printstr .= mb_substr($str, 0, $maxLength - $printedLength);
                    $printedLength = $maxLength;
                    break;
                }

            //print($str);
            $printstr .= $str;
            $printedLength += mb_strlen($str);

            if ($tag[0] == '&')
                {
                    // Handle the entity.
                    //print($tag);
                    $printstr .= $tag;
                    $printedLength++;
                }
            else
                {
                    // Handle the tag.
                    $tagName = $match[1][0];
                    $tagName = mb_ereg_replace(' .*', '', $tagName);
                    if ($tag[1] == '/')
                        {
                            // This is a closing tag.

                            $openingTag = array_pop($tags);
                            if($openingTag != $tagName) die;
                            assert($openingTag == $tagName); // check that tags are properly nested.

                            //print($tag);
                            $printstr .= $tag;
                        }
                    else if ($tag[mb_strlen($tag) - 2] == '/')
                        {
                            // Self-closing tag.
                            //print($tag);
                            $printstr .= $tag;
                        }
                    else
                        {
                            // Opening tag.
                            //print($tag);
                            $printstr .= $tag;
                            $tags[] = $tagName;
                        }
                }

            // Continue after the tag.
            $position = $tagPosition + mb_strlen($tag);
        }

    // Print any remaining text.
    if ($printedLength < $maxLength && $position < mb_strlen($html))
        //print(mb_substr($html, $position, $maxLength - $printedLength));
        $printstr .= mb_substr($html, $position, $maxLength - $printedLength);

    // Close any open tags.
    while (!empty($tags)) //printf('</%s>', array_pop($tags));
        $printstr .= sprintf('</%s>', array_pop($tags));

    if(mb_strlen($html) > mb_strlen($printstr)){
        $readmore = '<p class="nav"><a href="' . $url . '" title="続きを読む">続きを読む</a></p>';
    } else {
        $readmore = '';
    }

    return '<p>' . $printstr . '</p>' . $readmore;
}

2010年6月2日水曜日

Smarty反復構文での制御変数参照方法

for文のような、制御変数を明示的に利用する反復構文がない。

1. sectionを使う

{section name=cnt start=0 loop=10}
{$smarty.section.cnt.index}
{/section}

2. foreachのプロパティを使う

{foreach from=emps item=emp name=emploop}
{$smarty.foreach.emploop.index}
{/section}

どちらの場合も、breakとcontinueに相当するものはない。