VimScriptざっくりチュートリアル(if文と真偽値編)
VimScriptざっくりチュートリアル(データ型)
まずはここを読む
help eval
データ型の確認方法
let test = 1 echo type(test)
以下の6種類が数値で返ってくる
- 数値 : 0
- 文字列 : 1
- Funcref : 2 (関数リファレンス)
- リスト : 3
- 辞書 : 4
- 浮動小数点数 : 5
数値型
32bit or 64bit の符号付き整数
- 32bit なら、−2147483648 〜 2147483647
" 16進 echo 0x10 " 10進 echo 16 " 8進 echo 020
" サイズ越えの場合 -1 を返す echo 999999999999999999999999999999999999999999999999
数値演算
" 四則演算 echo (1+1)-1*10/10 " 余り echo 100%3 " 整数型の割り算は整数型を返す echo 10/3 "| -> 3 " 0 除算すると 0 を返す echo 1/0 "複合演算子は、+= と、-= だけ let test = 0 let test += 1 echo test-=1
数値⇔文字列
文字列 -> 数値
" それぞれ 16 を返す echo str2nr("0x10", 16) echo str2nr("16", 10) echo str2nr("020", 8) " 123 を返す echo str2nr("123abc", 10) " 0 を返す echo str2nr("abc123", 10)
数値 -> 文字列
echo printf("0x%x",16) | " -> "0x10" echo printf("%d",16) | " -> "16" echo printf("0%o",16) | " -> "020" echo printf("%02d",8) | " ->" "08"
文字列型
宣言
let test = "123" let test = '123' " ダブルクォーテーション文字列の場合、特殊文字を入力できる let test = "改行:\n タブ:\t バックスラッシュ:\\ 等..." " ダブルクォーテーション文字列中にダブルクォーテーションを入れたい場合 let test = "\"123\"" let test = '"123"' " シングルクォーテーション文字列中にシングルクォーテーションを入れたい場合 let test = 'test''test'
ヒアドキュメントは無い
文字列操作
" 結合 echo 'abc'. '123' " バイト数取得 echo strlen('abc') |" -> 3 echo strlen('2バイト文字') |" -> 16 " 正規表現検索 echo stridx('123abc', 'bc') |" -> indexが返る(ない場合は-1) " 正規表現置換 echo substitute('123abc', 'a', 'z', 'g') |" -> 123zbc
正規表現については、後述
Funcref型
関数の項で解説
リスト型
宣言
let test = [1,'abc',[1,2,3]]
参照
echo test[0] " 要素の参照 echo test[99] " 範囲外を参照するとエラー " get 関数を使用すると、範囲外の場合 0 を返す echo get(test, 99) " デフォルト値も定義可能 echo get(test, 99, 'NONE') " 部分リスト echo test[1:2] echo test[1:] " 1〜末尾まで echo test[:1] " 先頭〜1まで
リスト操作
" 要素を変更したい時は let を使う let test[1] = "123" " 要素数 echo len(test) " 空であるか? echo empty(test) echo empty([]) echo add(test, 'add') | " 末尾に追加 echo insert(test, 'add') | " 先頭に追加 echo remove(test, -1) | " 末尾を削除(remove の戻り値は消した要素) echo remove(test, 0) | " 先頭を削除 " ソート echo sort(test) " split/join " -> "1\t2\t3\t4" echo join(split('1,2,3,4', ','), "\t")
配列の繰り返し(for,map)
for i in [1,2,3,4] echo i unlet i " i にいろんなデータ型が来るとエラーになるので毎回 unlet する必要がある endfor
echo map([1,2,3,4], '1+v:val')
第1引数の各要素を、第2引数の文字列をevalした結果に置き換えた結果を返す
v:val は、要素の値を格納する組み込み変数
辞書型
hashみたいなの
宣言
" キーは数値も定義できるけど、文字列に置換される let hash = {'key1': 'val1', 2: 'val2'}
参照
echo hash['key1'] " キーがアルファベット、数値、アンダースコアだけの場合、以下でも参照できる echo hash.key1
要素の再定義、追加
let hash.key2 = 'val' let hash.key3 = 'val3' echo hash
辞書操作
echo keys(hash) | " キーをリストに echo keys(hash) | " 値をリストに echo items(hash) | " 辞書をリストのリストに変換 " items を使って、辞書のループ for [key, value] in items(hash) echo key . ': ' . value endfor echo has_key(hash, 'key1') | " 存在確認 echo remove(hash, 'key1') | " 削除
不動小数点数型
int と同じく、64 or 32bit
let test = 0.1 let test = 1.0e3 " 指数もOK
" 数値型で割り算すると戻り値は数値型 echo 1/10 " 浮動小数点数型で割り算すれば良い echo 1.0/10
異なる型の変数への再代入
文字列型 ⇔ 数値型は交互に再代入ができる
let test = 1
let test = "abc"
let test = 1
それ以外は例外になる
- 古いvimでは、文字列型と数値型しか無かったのが理由???
let test = 1
let test = ["abc", "def"] |" 変数の型が一致しません" 一度変数を削除する必要がある
unlet test
let test = ["abc", "def"] |" OK
異なる型の配列を for する時に大事
for i in [1,'test',0.1,[1,2,3]] # 毎回内部でletされている
echo i
unlet i
endfor
VimScriptざっくりチュートリアル(初回編)
10年近く Vim 使ってきていまだに習得していないのでそろそろ
VimScriptって何?
Vimの設定を記述する為の独自言語
実態はExコマンドの羅列で、 if 等の制御構文も全てがExコマンド
何が出来るの?
Exコマンドでできること全部。引いては Vim でできること、設定できること全部
- テキストの編集
- 各種設定の変更
- etc...
詳しくは以下
:help ex-cmd-index
ざっくり言えば、vimの機能拡張や、テキストの編集が出来るよ! で良いのかな?
Exコマンドって何?
Vimのコマンドラインモードで実行できるコマンド群のこと
Vim起動して、
:echo "hello!"
何でExコマンドって言うかというと、Vimの元ネタのラインエディタ ex で使えたコマンドが元になっているから
【vimの歴史】 ex(ラインエディタ) -> vi(exの機能を内包したテキストエディタ) -> Vim(viの改良版clone)
ちなみに、vi が入力モードとコマンドモードに分かれているのも、コマンドモードでは、ex の機能。入力モードでは、vi の機能という分け方をしたため
ラインエディタって?
モニターではなく1行づつコマンドの結果をプリントするテレタイプ端末というもので実行することを前提としたエディタ
なので、そういう命令を打たない限り全体を表示しないし、各種コマンドを入力することで、テキストの編集を行うエディタ
VimScriptのリファレンスとかあるの?
help usr_41
コメント
:echo " ダブルクォーテーションはコメント :echo "test" " 引用符が前にあったり、いくつかのコマンドの後ろにはコメントは付けられない :echo "test" |" こうすればどのコマンドの後ろにもコメント可(パイプは、コマンドを区切って次のコマンドに行く)
ファイルからVimScriptを実行
:source 01.vim " 拡張子は vim
変数宣言のやり方
:let test = 1 " グローバル変数(デフォルト) :let g:test = 1 " グローバル変数(明示的) :let s:test = 1 " スクリプトローカル変数(1スクリプトファイル内でのみ有効) :let l:test = 1 " 関数内ローカル変数(関数内のデフォルト) :let b:test = 1 " バッファローカル変数 :let w:test = 1 " ウインドウローカル変数 :let t:test = 1 " タブローカル変数
上にあるバッファ、ウインドウ、タブって?
- バッファ : ファイルを編集する仮想的な領域。ファイルを開くとバッファに格納される
- ウインドウ : バッファを編集する表示領域。:sp で分割すると2つになる
- タブ : ウィンドウの配置の状態を保持する領域。
わかりにくいので実例
:enew " 新規にバッファを開く :sp " ウインドウを分割 :tabedit " 新規にタブを生成 :tabNext " 次のタブに移動(上で分割したウィンドウが保持される) :ls " バッファの一覧 :tabs " タブの一覧
変数の削除
:unlet test " test が宣言されていないとエラー :unlet! test " test が宣言されていなくても OK
変数の存在確認
" existsは、exコマンドではなく関数。 " echo 関数 で、関数の戻り値を echo する " 関数については後述 :echo exists("test") |" 0:なし 1:あり
変数の再代入
:let test = 1 :let test = 2 " もう一度代入する場合は、毎回 let が必要
今日はここまで
vimperator の環境整備
環境を整備したのでその時のTIPS等を
バージョンあげたら、copy.js が動かなくなった
githubに最新のが上がってるので取得した
ついでに国内の vimperator 使いのプラグインが色々上がってたので git clone して必要なのをシンボリックリンクで plugin ディレクトリに入れた
使ってるプラグイン
copy.js
title や URL をいろんなテンプレートでコピーできるプラグイン
はてな記法や、redmine 用の設定を用意して使ってる
javascript <<EOM liberator.globalVariables.copy_templates = [ {label:'Url', value:'%URL%'}, {label:'TitleAndUrl', value:'%TITLE% %URL%'}, {label:'hatena', value:'[%URL%:title=%TITLE%]'}, {label:'wiki', value:'[[%TITLE%|%URL%]]'}, {label:'redmine', value:'"%TITLE%":%URL%'}, {label:'Title', value:'%TITLE%'}, {label:'HTML', value:'<a href=%URL%>%TITLE%</a>'} ] EOM noremap <C-h> :copy hatena<CR><CR> noremap <C-w> :copy wiki<CR><CR> noremap <C-r> :copy redmine<CR><CR>
node.jsデプロイQ&A
実践に当たって軽く調査。実践編はまた今度
nodeで書いたwebサーバを公開したいけど、デプロイってみんなどうしてるの?
forever っていうデーモン化ツールがあるから、それを使うのが一般的っぽい
nodeアプリって通常はシングルスレッドだから、マルチコアのCPUパワーを100%生かせない?
Clusterモジュールを使えば、複数のプロセスの起動と、通信をサポートしてくれる
複数マシンでスケールしたいんだけど
node-http-proxyってnpmがあるから、それを使うとnode.jsで、リバースプロキシと、ロードバランサーが実装できる
リバースプロキシ?
クライアントからのリクエストを受けて、特定のサーバに転送する役割のサーバ
ロードバランサ?
クライアントからのリクエストを複数のサーバに分散して、転送するサーバ
静的ファイルはnode使わないで、通常のhttpサーバを使ってnode側の負荷を軽減したい
nginx 使って特定のリクエストは、nodeサーバにリバースプロキシしてあげれば良いよ
ver 1.3.13 から、WebSocketもリバースプロキシしてくれるようになったよ!
Apacheでは?
ざっと見た感じ、WebSocketに対応していないっぽい?
複数マシンでnodeを分散した場合、セッションってどうなるの?
後で調査
nodeで書いたサーバを更新したい
- forever ならば、-w オプションでコードの更新をチェックして、リスタートしてくれる
ホットデプロイしたい!
qilinモジュールなるものがアツいらしい
ワーカープロセスを複数個起動して、そこでサーバを走らせる
メインプロセスにSIGUSR2(ユーザ定義シグナル)を送ると、子プロセスの内、リクエストが無くなったものから再起動してくれる
- upモジュールなるものもあるらしいけど、未調査。性能に多少難があるとかなんとか
自前で環境作成するのが面倒なのでnode使えるPaaS教えて
- Node Ninja - Node.js専用PaaS型クラウドサービス
- dotCloud - One home for all your apps
- あと、AWS Elastic Beanstalk が最近nodeに対応した
- Heroku は、webSoket非対応らしい
- Soket.IO の設定でロングポーリングで通信するように設定すれば、Soket.IOは使える
- Using Socket.IO with Node.js on Heroku | Heroku Dev Center
- 当然性能は落ちるけど
- webSoketのPUSH通信だけ試したいなら、Pusherでも良いかも
macのライブラリ関係覚え書き
拡張子.bundleって?
ローダブルバンドル
ダイナミックリンクライブラリへのリンクと関連ファイルやデータをひとまとめにしたものらしい
.bundleがリンクしている.bylibをリストアップしたい
otoolコマンドを使う
$ otool -L /Users/kobayashi/.rvm/rubies/ruby-1.8.7-p174/lib/ruby/1.8/i686-darwin10.8.0/iconv.bundle /Users/kobayashi/.rvm/rubies/ruby-1.8.7-p174/lib/ruby/1.8/i686-darwin10.8.0/iconv.bundle: /Users/kobayashi/.rvm/rubies/ruby-1.8.7-p174/lib/libruby.dylib (compatibility version 1.8.0, current version 1.8.7) /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
.bundleがリンクしている.bylibを変更する
標準のライブラリから、Homebrewでインストールしたライブラリを使いたい時とか
install_name_tool -change を使う
例 : .rvmにある、iconv.bundle がリンクしている標準の libiconv.2.dylibから、Homebrewのライブラリに変更
$ install_name_tool -change /Users/kobayashi/.rvm/rubies/ruby-1.8.7-p174/lib/ruby/1.8/i686-darwin10.8.0/iconv.bundle \ /usr/lib/libiconv.2.dylib \ /usr/local/Cellar/libiconv/1.13/lib/libiconv.2.dylib
node.js覚書
いろいろ調べたのでメモする
node.js ってなあに?
JavaScriptを用いた Non-blocking I/O な環境
Non-blocking I/O?
CPUと他の入出力装置(I/O)において、データの送受信を待たずに、次の処理に移行する方式のこと。
逆に、入出力が完了するまで待つことを「ブロッキング」と呼ぶ
例えば、こんなのがブロッキング
require 'open-uri' p "1: #{Time.now}" open("http://www.ruby-lang.org/") {|f| p "2: #{Time.now}" } p "3: #{Time.now}" # output "1: 2013-03-10 11:58:16 +0900" "2: 2013-03-10 11:58:19 +0900" "3: 2013-03-10 11:58:19 +0900"
上記の場合、2の処理が終わるまで、3が実行されない(ブロックされてる)
node.js の場合はどうなるの?
こうなる
var http = require("http"); console.log('1' + new Date()); http.get( { host : 'www.google.com', path : '/' }, function(res){ console.log('2' + new Date()); } ); console.log('3' + new Date()); # output 1Sun Mar 10 2013 12:04:00 GMT+0900 (JST) 3Sun Mar 10 2013 12:04:00 GMT+0900 (JST) 2Sun Mar 10 2013 12:04:01 GMT+0900 (JST)
http.get でブロックされずに、先に3の処理が実行されている
ブロックされないのは分かったけど、それだと何がお得なの?
Non-blocking だと、待ちが無いので、結果が帰ってくるまでの間、他の処理が実行できる
つまり、シングルスレッドで複数のリクエストを同時に捌く事が可能になる
それだと何が良いの? ハイスペックなマシンでスレッドたくさん作って富豪的に解決すれば良いんじゃ?
1台のマシンだと大量のスレッドを作成すると、1個1個のスレッドの処理が軽くて、
メモリ的に余裕があっても、大量のスレッドそのものがマシン性能を圧迫する問題がある
→ C10K問題
C10K問題の回答の一つとして、Non-blocking である node.js が作られた
なんで JavaScript なの?
nodeを作るに当たって、実装側でブロックが発生する処理は書けないようにしたかった
他の言語だとファイルシステムへのアクセスとか、ブロックが発生しえる処理が実装出来てしまうけど、
JavaScriptにはそれがなかった(標準入出力の仕様が無い)し、基本的にイベント駆動な書き方しか出来ないので、nodeの思想と相性が良かったから
後、JavaScriptにした副作用として
- 採用したV8エンジンが早い
- クライアントサイドと、言語が統一された
- jQueryとか既存の便利なライブラリが使える
node.js 向けのアプリってどんなの?
逆に向かない処理は?
最後に一言
サーバサイド JavaScript っていうのは結果であって、それが売りじゃないよ!
本当の売りは、Non-blocking I/O だよ! って中の人が言ってた
参考
- 10分でわかる Node.js
- 大変わかりやすいプレゼン資料
- Node.jsのコンセプトとは? ライアン・ダール氏による東京Node学園祭 基調講演(前編) − Publickey
- 中の人による講演。目的や、JavaScriptを選んだ理由とか
- node.js とは何か - I am Bad at Math