Hatena::ブログ(Diary)

cooldaemonの備忘録 RSSフィード

2007-05-20

勝手に返信 - viの操作体系は効率がいいんだろうか

viの操作体系は効率がいいんだろうか:メモランダム

話が飛んだけど、vi使いの人は「入力モードからコマンドードに移行するたびにEscを押すこと」「コピー・切り取りの方法」この2点をどう考えているのか知りたい。

一応、vi 使いなので、返信してみます。

ESC

普段 HHK を使っているので、ESC を押しても苦にならないです。

普通のキーボードを使う時は、C-[ を使います。

COPY

v で範囲選択を使ってます。

v でビジュアルモードに移行した後、/ でコピーしたい範囲の末尾まで移動して y でヤンク。

ビジュアルモード では、/ で検索以外にも、移動系のコマンドは全て使えるので便利です。

vim が使えず vi しか入ってない時は、文字数数えたり、単語数数えたり、行数数えたり…。

2007-05-17

:make を使う

vim 使いには、当たり前の事なんでしょうけど、当たり前の事ができてなかったので反省。

以前、適当に作った、yaml_checker.pl や css_checker.pl も、quickfix で扱いやすい出力に変更。

map ,m :call SyntaxCheck()<CR>

function SyntaxCheck()
  if &syntax == 'perl'
    set makeprg=~/.vim/tools/efm_perl.pl\ -c\ %
  elseif &syntax == 'ruby'
    set makeprg=ruby\ -cW\ %
  elseif &syntax == 'javascript'
    set makeprg=/usr/local/bin/jslint\ --laxLineEnd\ %
  elseif &syntax == 'yaml'
    set makeprg=~/.vim/tools/yaml_checker.pl\ %
  elseif &syntax == 'html'
    set makeprg=tidy\ -quiet\ --errors\ --gnu-emacs\ yes\ %
  elseif &syntax == 'css'
    set makeprg=~/.vim/tools/css_checker.pl\ %
  endif

  execute ':w'
  execute ':make'
  execute ':cw5'
endf

問題がある場合に限り、5 行の quickfix window が表示されます。

quickfix window 内で修正したい箇所にカーソルを合わせて enter を押すと、source 内の該当行にカーソルが移動します。

rails.vim が設定してくれる makeprg を上書きしてしまうので、後で対処方法考えようっと・・・。

Download

http://labs.miu.vc/svn/cooldaemon/env/.vimrc

http://labs.miu.vc/svn/cooldaemon/env/.vim/tools/yaml_checker.pl

http://labs.miu.vc/svn/cooldaemon/env/.vim/tools/css_checker.pl

参考 URI

Vim Tips@猫がびっくり

コマンド一発で、screen を起動して Catalyst の各種ディレクトリに移動

Catalyst Teamwork with Screen and VIM

この記事を見て、便利そうだと思ったので、即興ですが、こんなん作ってみました。

http://labs.miu.vc/svn/cooldaemon/env/bin/start_working_with_catalyst.pl

ちゃんと動作確認してませんが、手元の環境では問題なさげ・・・。

このコマンドを、Catalyst のディレクトリ名を引数にして実行すると screen を起動し、下記ディレクトリを開きます。

/path/to/MyApp-Web/

/path/to/MyApp-Web/lib/MyApp/Schema

/path/to/MyApp-Web/root

/path/to/MyApp-Web/lib/MyApp/Web/Controller

.screenrc を読んで、.screenrc に必要な内容を追加して、.screenrc.tmp に吐き出し、screen -c .screenrc.tmp を実行してます。

各 window にタイトルを付ける場合は、screenrc.tmp 吐き出しの際の screen の行を、screen -t [好きな名前] とかにします。

bind key にも対応しました。

例えば・・・ <C-a><C-c>c で Controller のディレクトリに移動します。

参考URI

アキレス亀日記 - 2004/05c Diary

2007-05-11

svk commit file の syntax ファイルを追加してみた

なんとなく、Subversion の commit 時みたいに色を付けたかったので。

まず、filetype.vim に下記を追加

au BufNewFile,BufRead svk-commit*.tmp setf svk

次に、syntax/svk.vim を作成する。

syntax/svn.vim をコピーしてきて、下記みたいに適当に修正。

20,24c20,24
< syn region svnRegion    start="^--.*--$" end="\%$" contains=ALL
< syn match svnRemoved    "^D    .*$" contained
< syn match svnAdded      "^A[ M]   .*$" contained
< syn match svnModified   "^M[ M]   .*$" contained
< syn match svnProperty   "^_M   .*$" contained
---
> syn region svkRegion    start="^===.*===$" end="\%$" contains=ALL
> syn match svkRemoved    "^D    .*$" contained
> syn match svkAdded      "^A[ M]   .*$" contained
> syn match svkModified   "^M[ M]   .*$" contained
> syn match svkProperty   "^_M   .*$" contained
28c28
< syn sync match svnSync  grouphere svnRegion "^--.*--$"me=s-1
---
> syn sync match svkSync  grouphere svkRegion "^===.*===$"me=s-1
33c33
< if version >= 508 || !exists("did_svn_syn_inits")
---
> if version >= 508 || !exists("did_svk_syn_inits")
35c35
<     let did_svn_syn_inits = 1
---
>     let did_svk_syn_inits = 1
41,45c41,45
<   HiLink svnRegion      Comment
<   HiLink svnRemoved     Constant
<   HiLink svnAdded       Identifier
<   HiLink svnModified    Special
<   HiLink svnProperty    Special
---
>   HiLink svkRegion      Comment
>   HiLink svkRemoved     Constant
>   HiLink svkAdded       Identifier
>   HiLink svkModified    Special
>   HiLink svkProperty    Special
50c50
< let b:current_syntax = "svn"
---
> let b:current_syntax = "svk"

不具合があるかも?

私が利用しているファイルは、下記に置いておきます。

http://labs.miu.vc/svn/cooldaemon/env/.vim/filetype.vim

http://labs.miu.vc/svn/cooldaemon/env/.vim/syntax/svk.vim

snippetsEmu.vim の簡単な使い方

snippet_emu.txt を読んだので自分用の備忘録

人様が見る事を考えてないです。ごめんなさい。

基本の前に・・・

snippetsEmu.vim をロードすると、編集モードの時に <TAB> を押した場合 <{}> にカーソルが飛ぶ。

適当にファイルを開いて、<{}> を入力して、遠くは離れた行まで移動して、コマンドモードで、i<TAB> と押すと挙動が確認できる。

<{}> を幾つも入力して <TAB> を押しまくると、ファイルの先頭にある <{}> から順にカーソルが移動して行く。

基本 Snippet でトリガーを登録する

:Snippet hoge HOGE <{}> HOGE

編集モードから hoge<TAB> と入力すると、HOGE [カーソル] HOGE になる。

:Iabbr hoge HOGE <{}> HOGE

でもいける。


タグ名を付けると、同名のタグを置換してくれる

:Snippet hoge HOGE <{fuga}> HOGE <{fuga}>

編集モードから hoge<TAB> と入力すると、一つ目の fuga が選択された状態になる。

ここで、aaa とか入力して <TAB> を押すと、二つ目の fuga も aaa に置換される。

一つ目の fuga が選択された状態で、何も入力せずに <TAB> を押すと、fuga のままになるので、デフォルト値としても使える?

タグを引数に関数を実行する

:Snippet hoge Hoge <{fuga}> Hoge. HOGE <{fuga:substitute(@z,'.','\u&','g')}>! HOGE

一つ目の fuga で入力した内容が、@z レジスタに入るので、@z を substitute の第一引数として渡す。

mmmmm とか入力すると、Hoge mmmmm Hoge. HOGE MMMMM HOGE となる。

下記でも動く。

:Snippet hoge HOGE <{fuga:substitute(@z,'.','\u&','g')}>! HOGE

関数を実行する

:Snippet hoge HOGE ``strftime("%Y/%m/%d")`` HOGE

HOGE 2007/05/11 HOGE となる。

ユーザ定義関数で <{}> を返すと・・・

    function! Count(haystack, needle)
        let counter = 0
        let index = match(a:haystack, a:needle)
        while index > -1
            let counter = counter + 1
            let index = match(a:haystack, a:needle, index+1)
        endwhile
        return counter
    endfunction

    function! PyArgList(count)
        if a:count == 0
            return "(,)"
        else
            return '('.repeat('<{}>, ', a:count).')'
        endif
    endfunction

    Snippet pf print "<{s}>" % <{s:PyArgList(Count(@z, '%[^%]'))}><CR><{}>

面倒なので、詳しい説明は書かないが % の数を数えて個数分 <{}> を出力してくれる。

xxxx.py とか開いて pf<TAB> って入力した後に '%s %s %s %s' とか入力すると挙動が確認できる。

2007-05-04

inflate_column

ブログが続かないわけ | DBIC で+select と+as : ああ、今頃気づくなんて...

でも、どうにも不便だと思ってDBIx::Class::ResultsetのPODを読んでいると、+select と+as なるものがあるじゃないですか。これだと、まさに先ほど直感的に書いたような方法で書けるのです。

$c->model('DBIC::TranDiary')->search(
    $query_ref,
    {
        '+select' => [
            { date_format => 'me.create_date,\'%Y/%m/%d\'' },
        ],
        '+as' => [
            qw/create_date/
        ]
    }
);

これって常識なんだろな。だってPODに書いてあるんだもん。

ちょっとへこみました。

+select と +as なんて、あるんだなー便利だなーと思いつつ、それは、inflate_column を使った方が良いんじゃないかと思いました。

上記の例であれば、xxxxx::Model::DBIC::TranDiary に下記を追加。

__PACKAGE__->inflate_column(
  'create_date',
  {
    inflate => sub { DateTime::Format::xxx->parse_datetime(shift);  },
    deflate => sub { DateTime::Format::xxx->format_datetime(shift); },
  }
);

DateTime::Format::xxx の、xxx の箇所は、Pg、MySQLOracleDB2 等が CPAN にあるので、環境にあわせて選択。

search メソッドだけでなく、create メソッドでも使えるので、こちらの方が便利かと。

参考URI

Perl/DBIC - Nekokak’s core dump

2007-05-02

MochiKit を使う際に、追加している関数を晒してみる(その2.partial)

id:cooldaemon:20070429:1177857285 の続き。

Mochikit.Base.partial は、前方から引数を束縛するのですが、任意の位置の引数を束縛したかったので、my_partial を作ってみました。

source の前に実例

var base_func = function () {
  map(function (arg, i) {log(i + ' = ' + arg);}, arguments, count());
};

var lazy_base_func = function () {
  var str = '';
  forEach(arguments, function (arg) {str += arg;})
  return str;
};

var new_func = my_partial(base_func, 'a', hole, 'c', hole, lazy(lazy_base_func, 2));
new_func('b', 'd', 'e', 'f', 'g');

上記を実行すると…

0 = a
1 = b
2 = c
3 = d
4 = ef
5 = g

と出力されます。

Mochikit.Base.partial と似ている箇所

my_partial は、第一引数に引数を束縛したい関数、第二引数以降に束縛したい引数を渡して使います。

Mochikit.Base.partial と明らかに異なる箇所

hole を第二引数以降にすると、その箇所に、新しく my_partial で作った関数の引数が渡されます。

また、lazy 関数の戻り値を引数として渡すと、my_partial で作った関数を実行する度に、lazy 関数の第一引数として渡した関数を実行し、その戻り値を、my_partial で作った関数の引数とします。

lazy 関数の第二引数は、第一引数に渡した関数に、my_partial で作った関数に渡した引数を幾つ渡すのか?を指定します。(省略すると、0 個になります)

で、source

下記、名前空間無視してます。ゴメンナサイ。

その他の突っ込み大歓迎です。

var Lazy = function (func) {
  var m = MochiKit.Base;
  this.func = func;
  this.arg_count = m.isUndefinedOrNull(arguments[1]) ? 0 : arguments[1];
};

var hole = {};
var lazy = function (func, arg_count) {
  return new Lazy(func, arg_count);
};

var my_partial = function (func) {
  var m = MochiKit.Base;
  var it = MochiKit.Iter;

  var base_args = m.extend(null, arguments, 1);

  return function () {
    var args = arguments;
    args.shift = Array.prototype.shift;

    var new_args = [];

    it.forEach(base_args, function (arg) {
      if (arg !== hole && !(arg instanceof Lazy)) {
        new_args.push(arg);
        return;
      }

      if (arg == hole) {
        if (!m.isUndefinedOrNull(args[0])) {
          new_args.push(args.shift());
        }
        return;
      }

      var lazy_args = [];
      for (var count = 0; count < arg.arg_count; count++) {
        if (m.isUndefinedOrNull(args[0])) {
          break;
        }
        lazy_args.push(args.shift());
      }
      new_args.push(arg.func.apply(this, lazy_args));
    });

    it.forEach(args, function (arg) {
      new_args.push(arg);
    });

    func.apply(this, new_args);
  }
}

関数呼び出す度に、こんなんしてたら重いなぁ…。

Connection: close