Software_tcl

☆tcl/tk

※tclのGUIツールキット tk についてはこちら

◎tcl

◆文法

_◇文と行
①コマンドと引数はスペースで区切る。
│ command arg1 arg2…

②一行に複数のコマンドをならべる場合は、;で区切る。

③複数行にわたる場合は、行末に\をおくことで継続行となる。
│ command arg1\
│  arg2 arg3 …

_◇コメント

ハッシュ記号「#」からその物理行の末まで
⇒文字列リテラルの内部においた#は単なるハッシュ文字となる

_◇文字列
①文字列には改行も含むことができる。
“あほ
馬鹿”

②1行に\nを使って書くこともできる。
“あほ\n馬鹿”

_◇リスト
{と}で囲まれたもの。文字列とほとんど同じに扱えるが、入れ子構造をとれるところが文字列とは違う。

例)
{a {b c} d}

_◇ダブルクオート
複数の文字列からなるブロックを作る。その際、変数置換($)とコマンド置換[]は行われる。\により[と$の置換を無効化できる。

※文字列を読み込むときにダブルクオート内の変数置換やコマンド置換が処理されてしまう。実行時に置換されるわけでないことに注意

_◇バックスラッシュ置換

\a ベル
\b バックスペース
\f フォームフィード
\n 改行
\r キャリッジリターン
\t タブ
\v 垂直タブ
\\ バックスラッシュ
\000 8進文字コード
\xHH 16進文字コード
\改行 空白文字1個

_◇コマンド置換
大括弧は、大括弧内のコマンドをコマンドの出力結果で置換する。
│ 例)
│ set pi [expr 2.0 * asin(1.0)]

_◇中括弧
複数の文字列からなるブロックを作るが、変数置換($)とコマンド置換[]は行われない。
│ 例)
│ puts {a = $var}
│ 文字列のまま表示

※読み込んだ時点では、置換が行われないが、ifなどの引数としてブロックが与えられたときには、ifが{}内をevalに渡すので、実行時には評価される。

_◇変数、変数置換
変数には型が無い。変数の参照は変数名に$をつける。(変数置換)

例)
│ $var

※set
変数への代入
│ set 変数 値

例)
│ ⇒変数varに値をセット
│ set var 値

│ ⇒変数の参照
│ set var

│ set x [expr $x – 3 ]

※unset
│ 変数を削除
│ unset var

_◇演算

※expr
式を評価する
│ expr 式
│ 例)
│  set x [expr $x – 3 ]

_◇定数

※10進数
│ 例)123

※8進数
│ 例)077

※16進数
│ 例)0xabc

※浮動小数点数
│ 例)7.91e+16

※エスケープシーケンス
①\0 NULL
②\xhhh 16進数
③\xy 8進数
④\t 水平タブ
⑤\uwxyz ユニコード
⑥\r キャリッジリターン
⑦\e エスケープ
⑧\\ \

※ブーリアン
⇒true/false
⇒yes/no
⇒on/off

_◇配列
添え字は文字列。
│ set a(文字列) 値
│ array set a {
│  文字列 値
│  …
│ }

例)
│ set a(this) 1
│ set a(that) 2
│ expr $a(this) + $a(that)

※parray 配列名
配列要素を表示する。

※unsetで配列要素毎もしくは、全配列(添え字なし)で削除することもできる

※array

array exists 名前
│ 存在すれば1
array size 名前
│ 要素数を返す
array get 名前
│ 配列の全内容をリストにして返す
array get 名前 パターン
│ パターンマッチするものだけを返す
array names 名前
array names 名前 パターン
│ 添え字だけを返す
array set 名前 リスト
│ array getの返す形のリストで値を設定する
array startsearch 名前
│ 順にarrayから添え字を取り出すために探索IDを返す
array nextelement 名前 探索ID
│ 次の添え字を取り出す。なければ空文字列を返す。
array donesearch 名前 探索ID
│ 取り出し完了

例)

set i [array startsearch a]
while { [set x [array nextelement a $i] != "" } {
    puts $x
}
array donesearch a $i

_◇漢字コード指定

例)
kanji defaultInputCode EUC

◆スクリプト引数

set スクリプト名 $argv0
set 引数の数 $argc
set 第1引数 [lindex $argv 0]
set 第2引数 [lindex $argv 1]
set 第3引数 [lindex $argv 2]

◆算術演算

_◇演算子
– + ~ !
負符号、正符号、補数、否定
* / %
乗算、除算、剰余

+ –
加算、減算
<< >>
左シフト、右シフト
< > <= >=
左不等、右不等、等価左不等、等価右不等
== !=
等価、非等価
&
ビット積(AND)
^
ビット差(XOR)
|
ビット和(OR)
&&
積結合
||
和結合
x?y:z
条件

_◇expr
│ 演算、比較を行う。

_◇incr
incr 変数名
incr 変数名 足しこまれる数

◆制御文

_◇if

if 条件ブロック thenブロック elseブロック

かならずしも各ブロックは{ }で囲う必要はないが、{}で囲んでおけば、ifの実行まで評価されない。””だと読み込んだ時点で評価されてしまう。

注意)複数行にわたる場合以下のように書くとelseにつながらない。2個目の}でifが終わってしまう。

if { } {
}
else { }

かならずifから連続していることを示すため
} else {
と書く

例)

if {$var == "壱"} {
    puts stdout 1
} elseif {$var == "弐"} {
    puts stdout 2
} else {
    puts stdout 3
}

_◇for

for 初期設定 条件 更新 ループ本体

例)

for {set i 1} {$i <= 3} {incr i} {
    puts stdout $i
}

_◇continue
例)

for {set i 1} {$i <= 5} {incr i} {
    if {$i < 3} {
        continue
    }
    puts stdout $i
}

│ i < 3のときはputsされない。

_◇break
例)

for {set i 1} {$i <= 5} {incr i} {
    if {$i > 3} {
        break
    }
    puts stdout $i
}

│ i > 3のときはループ脱出

_◇foreach

foreach 変数 リスト ループ本体

例)

foreach {i j} {A B C D E F} {
    puts stdout "$i $j"
}

例)変数置換を使った構文
foreach e $list {
│ …
}

_◇while

while 条件 ループ本体

例)

while {$i != 0} {
    puts stdout $i
    incr i -1
}

_◇switch

switch オプション 文字列
│  比較パターン1 {ボディ}
│  …
│  default {ボディ}

※オプション
-exact デフォルト。正確に比較
-glob string matchと同じ方法で比較
-regexp 正規表現で比較
— オプション末尾の印。この後に「-」で始まる引数があっても文字列と見なす。

例)

switch りんご {
りんご
    {puts 100円}
みかん
    {puts 80円}
バナナ
    {puts 30円}
default
    {puts 不明}
}

_◇catch
エラーをキャッチする。エラー発生時には1を返す。それ以外は0.
例)
catch {expr 1/0} var

⇒error
│ エラーを発生する

エラー処理例)

# エラーを返すコマンド(その1)
proc foo1 {} {
return -code error -errorcode 1 -errorinfo info message
}

# エラーを返すコマンド(その2)
proc foo2 {} {
error message info 1
}

# エラーを想定した処理(その1)

if [catch foo1] {
    puts "errorCode = $errorCode"
    puts "errorInfo = $errorInfo"
}

# エラーを想定した処理(その2)

if [catch foo2] {
    puts "errorCode = $errorCode"
    puts "errorInfo = $errorInfo"
}

例)外部コマンド実行時のエラーのキャッチ
catch { cd $dir exec $exe & } err_code
⇒エラーが起こると $err_codeにメッセージが入っている

_◇eval
引数をコマンドとして実行する。引数のリストレベルは1浅くなる。

◆プロシージャ

_◇proc
proc 手続き名 引数リスト 本体

①プロシジャ内で定義された変数は、ローカル変数となる。

②プロシジャ内でグローバル変数を参照するには、global宣言が必要。
例)

proc add {a b} {
    global foo
    return [expr $a + $b + $foo]
}

※global 変数名1 変数名2 …

③プロシジャは、デフォルト付き引数や可変長引数を取ることもできる。
例)

proc plus {a {b 1}} {
    upvar $a r
    set r [expr $r + $b]
    return $r
}

│ b デフォルトつき
│ a 参照型

例)

proc sum {args} {
    set s 0
    foreach i $args {
        set s [expr $s + $i]
    }	
    return $s
}

│ args 可変長引数

_◇return
値を返す

│ return 値

_◇global

│ global 大域変数

指定した変数は大域変数としてアクセスされる

_◇upvar

│ upvar レベル 変数 名前…

指定したレベルの変数を対応する名前でアクセスできるようにする。
│ レベル
│  数値N Nレベル上
│  #N レベルN

※現在のレベルは
│ info level
で調べることができる

_◇uplevel

│ uplevel レベル 動作

指定した動作を指定したレベルで行う

◆組み込み関数

_◇算術/数学関数

※abs(arg)
絶対値。

※ acos
※ cos
※ hypot
※ sinh
※ asin()
※ cosh()
※ log()
※ sqrt()
※ atan()
※ exp()
※ log10()
※ tan()
※ atan2()
※ floor()
※ pow()
※ tanh()
※ ceil()
※ fmod()
※ sin()

※double(arg)
倍精度値

※int(arg)
整数値

※rand()
乱数値

※round(arg)
整数への丸め値

※srand(arg)
乱数の初期値

◆ファイル、ディレクトリ操作、入出力

_◇open
ファイル名を指定してファイルを開き、ファイル識別子を返す。

open ファイル名 アクセス モード

※ファイル名が「|」で始まっているときは、パイプであるので、コマンドを実行し、パイプを開く

※アクセスモード
r, r+, w, w+, a, a+

※モードはファイルの保護モード8進3桁形式
例)0755

例)
set fd [open [tk_getOpenFile]]

_◇close
ファイルを閉じる

close 識別子

_◇gets
ファイルから一行読み出し変数に格納、読み込んだバイト数を返す。ファイル末尾で-1を返す。変数指定しないと読み込んだ文字列(末尾では空文字列を返す)

gets 識別子 変数

_◇read
ファイルから指定したバイト数を読み込んで文字列として返す。

read 識別子 バイト数

_◇eof
ファイルの終端に達したかどうかを返す。

eof 識別子

_◇flush
ファイルバッファの書き出し

flush 識別子

_◇puts
ファイルへ文字列を書き出す

puts 識別子 文字列

例)
│ puts stdout “Hello.”
│ puts stderr “Error.”
│ puts “Hello.”

※識別子を省略すると標準出力に向かう

_◇source
ファイルをtclのスクリプトとして読み込む

source filename

_◇file

file copy -force — ソース ターゲット
オプションはなくてもよい。ファイルをコピーする。

file delete -force — パス
オプションはなくてもよい。ファイルを削除する。

file exists ファイル名
存在すれば1を返す。

※他にもいろいろ。

_◇cd

_◇socket
ソケットを開きチャネル識別子を返す。チャネル識別子はflush, read, putsで使える。

※クライアント側
socket オプション ホスト ポート
│ -myaddr アドレス
│  省略時はシステム選択
│ -myport ポート
│  省略時はシステム選択
│ -async
│  接続が完了するまで待たない

※サーバ側
socket -server コマンド オプション ポート
│ -myaddr アドレス
│  省略時は自ホスト宛のどのような指定も受け入れる

※使用例
http://www.geocities.co.jp/SiliconValley/4137/dir1/wincomm.html

①サーバ

proc accepted {handle cliehost clieport} {
    puts "accepted connection from: <$cliehost:$clieport>"
    set bun [gets $handle]
    flush $handle
    if {[catch {set result [expr $bun]} err]} {
        puts $handle "ERROR $err\n"
    } else {
        puts $handle "OK $result\n"
    }
    close $handle
}
set serversock [socket -server accepted 5544]
vwait zzz

②クライアント

set sock [socket localhost 5544]
puts  $sock 3*5
flush $sock
puts  [gets $sock]
close $sock

_◇fconfigure
ソケットチャネルから構成オプションを取得する

-error
│ エラー状態を取得。エラーがなければ空文字列。

-sockname
│ ソケットのアドレスとホスト名とポート番号のリストを返す。

-peername
クライアントのみ。受信ソケットに対して、アドレス、ホスト名、ソケットが接続あるいはバインドするポートのリストを返す

◆リスト操作
リストとは、中括弧あるいはダブルクォートを使ってスペースで区切られた文字列
例)
set var {りんご みかん バナナ}
set var “りんご みかん バナナ”
│ 結果は同じ

_◇list
引数文字列からリストを生成
例)
[list りんご みかん バナナ]

_◇concat
引数の文字列からスペースを区切りとしてリストを作成。listとくらべるとリストレベルは1つ浅くなる。
例)
[concat “りんご みかん バナナ”]

_◇llength
リストの要素数を返す。
例)
llength $var

_◇lindex
リストの要素番号の要素を取り出す。 lindex リスト 要素番号
例)
│ set x [lindex $lis 0]

※要素は0から始まる。

例)

proc car {lis} {
    lindex $lis 0
}

_◇lrange
リストの指定された範囲の要素をリストで返す。
例)
lrange $var 1 end

proc cdr {lis} {
    lrange $lis 1 end
}

_◇lappend
リストの最後に要素を追加する。
│ lappend リスト 要素
│ 例)
│ lappend list メロン

_◇linsert
リストの指定されたインデックスに要素を挿入
│ 例)
│ linsert $var 1 要素

_◇lreplace
リストの指定されたインデックスの要素を置換
│ 例)
│ lreplace $var 1 2 要素1 要素2
│ 例)
│ lreplace $var 1 1
│ ⇒要素1削除

_◇lsearch
リストの要素を検索する。
│ 例)
│ lsearch $var みかん
⇒正規表現の使用
│ 例)
│ lsearch -glob $var み*
│ lsearch -regexp $var み+

_◇lsort
リストをソートする。
│ 例)
│ lsort $lis
⇒オプション
-ascii アスキーコード順
(デフォルト)
-dictionary 辞書順
-integer 整数として
-real 浮動少数点数として
-increasing 昇順
(デフォルト)
-decreasing 降順
-index index 要素がリストの場合、ソート対象のインデックスを指定する
-unique 重複する要素を1つにする

◆文字列操作

_◇代入(set)
set str abc
=>abc

_◇連結(append)
append str xyz
=>abcxyz

_◇split
指定された区切り文字で文字列を分割したリストを返す。
例)
split usr/local/bin /
=>usr local bin

例)
split $pa :

※空文字列を指定した場合、1文字毎に分割する。

_◇join
リストの各要素を指定された区切り文字で連結した文字列を返す。

例)
join {a b c}
=>a b c

例)
join {usr local bin} /
=>usr/local/bin

例)
join {a b c} {}
=>abc
※{}空リストでつないだのでくっつく

例)
join $pa :

_◇string

string compare 文字列1 文字列2
│ 文字列の大、等、小に応じて1, 0, -1を返す

string index 文字列 数値
│ 文字列の指定番目の文字を返す

string range 文字列 数値1 数値2
│ 数値の間の部分文字列を返す

string first 文字列1 文字列2
│ 文字列1のもっとも先頭に近い文字列2の位置を返す。マッチしなければ-1を返す。

string last 文字列1 文字列2
│ 文字列1のもっとも末尾に近い文字列2の位置を返す。マッチしなければ-1を返す。

string wordstart 文字列 数値
│ 指定した位置を含む語の先頭位置を返す。

string wordend 文字列 数値
│ 指定した位置を含む語の末尾位置を返す。

string match パターン 文字列
│ マッチするところがあれば1なければ0を返す。マッチは、*, ?, []がとエスケープキャラの\が使える。

string tolower 文字列
│ 小文字に置き換える

string toupper 文字列
│ 大文字に置き換える

string trimleft 文字列 文字
│ 文字列の先頭部の指定文字を取り除く。文字は複数でもよく、文字を指定しないと、空白、タブ、改行となる。
string trimright 文字列 文字
│ 文字列の末尾部の指定文字を取り除く。文字は複数でもよく、文字を指定しないと、空白、タブ、改行となる。
string trim 文字列 文字列
│ 一度に先頭と末尾の両方を処理

例)

if ![string compare -nocase "abc" "ABC"] {
    puts 等しい
}
=>等しい
string toupper "abc"
=>ABC
string length "xyz"
=>3
string length "みかん"
=>3

_◇regexp
文字列が正規表現にマッチすれば1、マッチしなければ0を返す。マッチした場合、変数1にマッチした部分が入る。正規表現中の()部とマッチした部分は、変数2以降に入る。

regexp 正規表現 文字列 変数1 変数2…

※正規表現の中の文字クラス[…]がコマンド置換として解釈されぬよう、正規表現は{}で囲むとよい。

※オプション
-nocase 大文字を小文字とみなす
-indices マッチ文字列の代わりに開始位置と終了位置からなるリストを入れる。
— オプションの終わり

_◇regsub
正規表現にマッチした部分を置換文字列に置き換えて結果を変数に入れ、置き換えのおきた回数を返す。

regsub 正規表現 文字列 置換文字列 変数

※置換文字列の中の&もしくは\0は元の文字列のマッチ部分に置き換えられ、正規表現の()にマッチした部分は\1~\9に入る。

例)
regsub -all {[aeiou]+} “footprint” “<&>” x
⇒2
⇒xの内容は f<oo>tpr<i>nt となる

※オプション
-nocase 大文字を小文字とみなす
-all マッチするところが複数あった場合に処理を繰り返す
— オプションの終わり

_◇format
Cのsprintfのフォーマット文字列のスタイルで文字列をフォーマットして返す。

│ format フォーマット文字列 引数…

_◇scan

scan string formstr arg…

文字列をフォーマット書式に従い入力する。
│ 例)
│ scan “123.456” “%d.%d” a b

※フォーマット文字列はCのsscanfと同等

◆バイナリ操作

# ASCII to Binary
set bin [binary format i 0x12345678]
# Binary to ASCII
binary scan $bin H2H2H2H2 var1 var2 var3 var4
puts 0x$var4$var3$var2$var1
=>0x12345678

◆処理系制御

_◇exit
インタプリタを終了する

exit 戻り値

_◇rename
コマンドの名前を付け替える。コマンド名を空文字列とすれば使えなくなる。

rename コマンド名 新コマンド名

_◇pid
ファイル識別子を与えると、openしているプロセスのPIDが帰る。なにも識別子を与えないとインタプリタのPIDが帰る。

pid 識別子

_◇time
コマンドを実行し、かかった時間を返す。

time コマンド 実行回数

※実行回数を省略すると1回

_◇clock

clock clicks

clock seconds

clock formant 経過秒数 [-foramt 書式] [-gmt 真偽]

clock scan 文字列

_◇info

info args 手続き名
│ 定義時の引数リストを返す
info body 手続き名
│ 定義時の本体を返す
info cmdcount
│ 実行したコマンド数を返す
info commands パターン
│ パターンにマッチするコマンド、手続き名のリストを返す

_◇eval

│ eval 引数

引数をコマンドとして実行する

_◇subst

│ subst 文字列

文字列に置換を行い結果を返す。以下のオプションにより特有の置換を抑止。
│ -nobackslash
│ -nocommands
│ -novariables

_◇source

│ source ファイル名

ファイルからtclコマンドを読み込んで解釈実行する

_◇interp
子供のインタプリタを生成、制御する。最初のインタプリタは{}という名で、以後、親子関係は空白で区切られた名前の並びによる

interp create [-safe] [–] パス名

│ –はパス名が-で始まる場合に使う
│ -safeつけるとexecなど危険なコマンドが使えない

interp delete パス名

interp exists パス名

interp slaves パス名

interp eval パス名 コマンド
│ 指定したインタプリタ上で指定したコマンドを実行させる

interp alias パス名1 名前1 パス名2 名前2 引数
│ パス名1で名前1のコマンドを実行すると、パス名2で名前2のコマンドに引数とパス名1の名前1の引数を加えたものが渡されて実行される。

interp alias パス名 名前 {}
│ aliasの削除

interp alias パス名 名前
│ aliasに対応するコマンドと引数をリストにして返す

interp target パス名 名前
│ aliasを実行するインタプリタのパス名を返す

interp aliases パス名
│ alias名をリストにして返す

interp share パス名1 識別子 パス名2
│ パス名1で指定した識別子をパス名2でも使えるようにする。

interp transfer パス名1 識別子 パス名2
│ パス名1で指定した識別子をパス名2に渡してしまう。

_◇ライブラリとパッケージ

auto_execok コマンド
│ 指定したコマンドが実行可能か否かを返す

auto_load コマンド
│ 変数$auto_loadもしくは環境変数TCLLIBPATHに指定されているディレクトリから自動ロードする

auto_mkindex ディレクトリ パターン
│ 指定したディレクトリに自動ロード用ファイルtclIndexを作成する。パターンにマッチしたファイルのみが設定される

auto_reset
│ auto_execokがキャッシュしている情報をクリア

※parray 配列名
│ 指定配列の内容を標準出力に書き出す

│ auto_execs auto_execokのキャッシュ配列
│ auto_index auto_loadが保守する配列
│ auto_noexec Unixコマンドの自動実行禁止
│ auto_noload 自動ロード禁止
│ auto_path 自動ロードの参照パス
│ unknown_active unknownがアクティブか否か

package require [-exact] パッケージ [バージョン]
│ パッケージの使用
package ifneeded パッケージ バージョン スクリプト
package unknown コマンド
package provide パッケージ バージョン
│ パッケージ内での宣言
package forget パッケージ
package names
package versions パッケージ
package vcompare バージョン1 バージョン2
package vsatisfies バージョン1 バージョン2

※パッケージの中身は、tclスクリプトであればsourceで、バイナリであればloadでロードされる。

load ファイル名
load ファイル名 パッケージ
│ ロード後にパッケージ名_Initが呼ばれる
load ファイル名 パッケージ パス名
│ 子供インタプリタにロードする
│ safeな場合パッケージ名_SafeInitが呼ばれる

※パッケージの自動ロード設定

pkg_mkIndex ディレクトリ パターン
│ 指定したディレクトリのパターンにマッチするファイル群からファイルpkgIndex.tclを生成する。

pkgIndex.tcl生成後、ライブラリディレクトリを変数tcl_pkgPathに指定されたいずれかのディレクトリのサブディレクトリにすれば、

①パッケージを使用するコードがpackage requireする。
②パッケージがまだロードされていなければ、package unknownにより指定されたコマンドがauto_path以下を探し、pkgIndex.tclを実行する。
③pkgIndex.tcl内にはpackage ifneededコマンド群があり、各パッケージの自動ローディングが設定される
④実際にどれかのコマンドが呼び出されようとすると、自動ローディングによりコードが読み込まれる。

_◇unknown
tclは存在しないコマンドにあたると、そのコマンドと引数全体をパラメータとしてunknownコマンドに渡す。unknownコマンドを定義することで未定義動作に対する対処がきまるが、標準のunknownは、

①同名のライブラリ手続きをロードして実行しようとする。
②無ければ同名のunixコマンドが実行可能かどうか調べて実行する。
③コマンドが!!などのヒストリ参照の型であれば、historyを実行する。

_◇エラー処理
tclインタプリタは、各命令毎に完了コードをチェックし、TCL_OK以外のコードが返された場合、例外として以後の命令列の実行を中断、呼出し側に返る。この中でTCL_RETURNや、TCL_BREAKなどは、処理しているインタプリタまで戻るとそこで受け止められる。TCL_ERRORは受け止めるものがないのでトップレベルまで戻る

※完了コード
TCL_OK(0)
TCL_ERROR(1)
TCL_BREAK(2)
TCL_CONTINUE(3)
TCL_RETURN(4)
他のアプリ定義

_◇error
エラーを発生させる。

error メッセージ [スタック情報] [説明コード]

スタック情報は広域変数 errorInfoに文字列として連結される。

_◇catch
スクリプト実行中の例外をキャッチする

catch スクリプト [変数名]

例外コードを返す。変数名を指定すると例外の説明情報が入る。

※breakやreturnなども捕まえるので注意

_◇bgerror
部品コマンドの-commandスクリプトや、イベントバインディングで起動される非同期的スクリプトは直接の親を持たないのでcatchできない。しかし、これらのスクリプトでエラーが出た場合は、手続きbgerrorが、引数1つを与えられて呼ばれる。通常、bgerrorはダイアログを出すが、bgerrorを書き換えることで処理をすることができる。、

_◇日本語
tcl処理系は日本語コード、JIS,SJIS,EUCを自動判別する。また変換も可能。

kanji code 文字列
│ JIS/EUC/SJIS/ANY(漢字なし)を返す
kanji conversion 入力 出力 文字列
│ 入力コードの文字列を出力コードに変換する
kanji internalCode コード
│ 内部処理コード
kanji defaultInputCode コード
│ デフォルトの入力コード(既定はANY)
kanji inputCode 識別子 コード
│ 指定チャネルの入力コード
kanji defaultOutputCode コード
│ デフォルトの出力コード(既定はANY)
kanji outputCode 識別子 コード
│ 指定チャネルの出力コード
kanji lsearch リスト パターン
│ lsearchの漢字版
kanji lsort リスト
│ lsortの漢字版
kanji split 文字列 [文字]
│ splitの漢字版
kanji string
│ stringの漢字版

file kanjiCode ファイル名
│ ファイルが含んでいる漢字コードを返す

※カット&ペースト時には、COMPOUND_TEXTを使用する。通常のSTRINGだと漢字は除外される。

◆イベントハンドラと変数スコープ

イベントハンドラを使ってコマンドを実行する場合
│ after
│ bind
│ button -command
│ 等
イベントハンドラはglobalスコープで実行される。

_◇イベントハンドラ

※イベント
│ <B1-Motion> ドラッグ

※イベントハンドラの中では、 %x, %y はマウスの座標に変換される

_◇物理イベント
直接入力や窓の状態変化に対応する。

書式 <イベント指定>

①ButtonPressまたはButton マウスボタンの押し下げ
②ButtonRelease マウスボタン離し
③Motion ドラッグ
④KeyPressまたはKey キーの押し下げ
⑤KeyRelease キーの離し

上記の後にボタン番号またはキーの名前(Keysym)を指定してもよい。
例)
<Key-comma> コンマキー押し下げ
<ButtonRelease-3> ボタン3(右ボタン)リリース

さらに上記を以下で修飾してもよい
Control
Shift
Lock
Button1~Button5
Mod1~Mod5
Meta
Alt
Double
Triple

_◇仮想イベントとevent
プログラムに固有な論理事象に名前をつけて扱う

書式 <<名前>>

※eventコマンド
event generate 窓 イベント オプション
│ プログラムで発生。仮想イベントでなくても発生できる。
│ オプション
│  -keycod 番号
│  -keysym 名前
│  -x 座標
│  -y 座標
event add 仮想イベント 物理イベント
│ 物理イベントと結びつける
event delete 仮想イベント 物理イベント
│ 対応付けを削除
event info 仮想イベント
│ 対応付けを表示

_◇after

atter msec
│ 指定された時間 (単位は msec) だけ待つ
after msec command
│ 指定した時間経過後コマンドを実行 (固有番号を返す)
after cancel 固有番号
│ 固有番号のコマンド実行待ちを取り消す
after cancel コマンド
│ コマンドの実行待ちを取り消す
after info [固有番号]
│ 固有番号の実行待ちコマンド情報を返す

※プロシージャの定期的繰り返し
例)

proc a {} {
    .....
    after 500 a
}

_◇bind
イベントにコマンドをバインディングする
│ bind タグ イベント スクリプト
│ bind タグ イベント +スクリプト

※タグ
例)
│ . トップレベルの窓に対応する
│ .l0 リストボックス.l0に対応する

※イベントは、キー入力、マウス操作など
※スクリプトに+を付け加えると、既に定義されているコマンドに追加する。+がないと置き換える。

※bindスクリプト内でイベント情報を参照するためには
│ %○
という書式を使う
│ %b マウスボタンの番号
│ %x マウスカーソルの座標
│ %y
│ %X ルートウインドウ上での座標
│ %Y
│ %A キーに対応する文字
│ %K キーに対応するKeysym
│ %% %1文字

例)
bind . <KeyPress> {if { “%A” >= “a” && “%A” <= “z” } { script_name “%A” }

_◇イベントタグとbindtags
部品毎にイベントタグのリストを持つ。イベントタグ毎にイベントとバインディングを保持している

※初期状態、各部品は4つのタグを持つ
①窓の名前と同名のタグ
②クラス名(Buttonなど)と同名のタグ
③その部品を含む直近のトップレベルの窓と同名のタグ
④all

※タグリストの参照と変更

bindtags 窓
bindtags 窓 タグリスト

例)
│ bindtags .l0 { .l0 Listbox all }

◆外部プログラムの起動

_◇exec

exec プログラム名 引数…

例)
button .b1 -text “oclock” -command “exec oclock &”
※execの末尾の&によりバックグラウンドで動作する。

※ヒアドキュメント
│ 「<<」により外部コマンドの標準ドキュメントに送り込むことができる。

│ 例)
│ com << [.t0 get 1.0 end]
│  entry .t0内のテキスト全てを流し込む

_◇外部変数、ファイル名の参照例

※procの中で

global ext.Ed
set fnam [tk_getOpenFile ~ ]
if {$fnam != '' }{
    exec $ext.Ed $fnam &
}

◆待ち合わせ

_◇fileevent
ファイルに対する入出力ができるようになるまで待つ。(他プロセスにより生成中のファイルなど)

fileevent チャネル readable コマンド
fileevnet チャネル writable コマンド

│ チャネルはopenで返されるファイル識別子

※サーバソケット例

proc accepted {handle cliehost clieport} {
    puts "accepted connection from: <$cliehost:$clieport>"
    fileevent $handle readable "react $handle"
    puts "waiting..."
}

proc react handle {
    puts "been reactable!"
    set bun [gets $handle]
    flush $handle
    if {[catch {set result [expr $bun]} err]} {
        puts $handle "ERROR $err\n"
    } else {
        puts $handle "OK $result\n"
    }
    close $handle
}
socket -server accepted 5544
vwait zzz
# end.

例)

#!/usr/local/bin/tclsh

proc serverAdd {sock addr port} {
    fileevent $sock readable "serverHandle $sock"
    fconfigure $sock -buffering line
}

proc serverHandle {sock} {
    set line [gets $sock]

    if {[eof $sock]} {
        close $sock
    } else {
│ puts $sock "test from server: $line"
    }
}

socket -server serverAdd 8823
vwait forever


fconfigure $sock -buffering line -blocking 0

_◇vwait

vwait 変数名
│ 変数に書き込まれるまで待つ

_◇update

update
│ 全ての待ちイベントを処理する
update ideltasks
│ after idleで指定されたコマンド群をすべて処理するがイベント処理は行わない。