Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/Example+Scripts+Everybody+Should+Have?V=61
QUERY_STRINGV=61
CONTENT_TYPE
DOCUMENT_URI/revision/Example+Scripts+Everybody+Should+Have
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR162.158.78.65
REMOTE_PORT25368
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR174.129.59.198
HTTP_CF_RAY86b9d9b269ab0a09-IAD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP174.129.59.198
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {Example Scripts Everybody Should Have} There\ are\ many\ simple\ example\ scripts\ that\ every\ Tcl/Tk\ programmer\ should\ keep\naround\ for\ reference.\ \ They\ are\ good\ examples\ of\ Tcl/Tk\ techniques,\ and\ they're\njust\ plain\ handy\ sometimes.\ \ (Thanks\ to\ Harald\ Kirsch\ for\ suggesting\ the\ncollection\ on\ comp.lang.tcl)\ \ Also\ think\ about\ \[The\ RC\ File\].\n\n\n\n**\ Description\ **\n\n\[LV\]:\ today\ I\ am\ only\ partially\ able\ to\ access\ the\ internet\ -\ it\ would\ be\ useful\nfor\ someone\ with\ full\ access\ to\ look\ through\ the\ following\ list\ and\ submit\nFeature\ Requests\ to\ http://tcllib.sf.net/\ to\ get\ some\ of\ this\ great\ code\ into\ a\ntcllib\ distribution.\n\n\n\n**\ Unix-like\ utilities\ **\n\n\[http://www.perl.com/language/ppt/%|%here%|%\]\ is\ \[Perl\]'s\ rendition\ of\ the\nsame.\n\n\ \ \ \[awk\]:\ \ \ \n\n\ \ \ \[diff\ in\ Tcl\]:\ \ \ a\ trifle\ long,\ so\ it's\ off\ in\ its\ own\ page.\n\n\ \ \ find:\ \ \ see\ \[fileutil\],\ a\ module\ in\ \[tcllib\]\n\n\ \ \ \[grep\]:\ \ \ See\ also\ \[fileutil\],\ a\ module\ in\ \[tcllib\]\n\n\ \ \ \[ls\ -l\ in\ Tcl\]:\ \ \ also\ a\ trifle\ long,\ and\ off\ on\ its\ own\ page.\n\n\ \ \ od:\ \ \ \[Dump\ a\ file\ in\ hex\ and\ ASCII\]\n\n\ \ \ sed:\ \ \ \n\n\ \ \ sort:\ \ \ \n\n\ \ \ \[tr\]:\ \ \ \n\n\ \ \ uniq:\ \ \ \n\n\ \ \ wc:\ \ \ \n\n\ \ \ \[anytop\]:\ \ \ indirectly\ Unix-inspired\ and\ perhaps\ a\ useful\ stub\n\n\n\n**\ Miscellaneous\ **\n\n\ \ \ Debugging:\ \ \ \n\n\ \ \ Tk\ events:\ \ \ \n\n\ \ \ Balloon\ help:\ \ \ \n\n\ \ \ Re-encoding\ strings:\ \ \ \n\n\ \ \ Advanced\ split:\ \ \ \n\n\ \ \ simple\ socket\ communication:\ \ \ \n\n\ \ \ \[Sample\ Math\ Programs\]:\ \ \ \n\n\ \ \ \[try\ ...\ finally\ ...\]:\ \ \ \n\n\n\n**\ find\ **\n\n======\nproc\ find\ \{\{basedir\ .\}\ \{filterScript\ \{\}\}\}\ \{\n\ \ \ \ set\ oldwd\ \[pwd\]\n\ \ \ \ cd\ \$basedir\n\ \ \ \ set\ cwd\ \[pwd\]\n\ \ \ \ set\ filenames\ \[glob\ -nocomplain\ *\ .*\]\n\ \ \ \ set\ files\ \{\}\n\ \ \ \ set\ filt\ \[string\ length\ \$filterScript\]\n\ \ \ \ foreach\ filename\ \$filenames\ \{\n\ \ \ \ \ \ \ \ if\ \{!\$filt\ ||\ \[eval\ \$filterScript\ \[list\ \$filename\]\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ files\ \[file\ join\ \$cwd\ \$filename\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ if\ \{\[file\ isdirectory\ \$filename\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ files\ \[concat\ \$files\ \[find\ \$filename\ \$filterScript\]\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ cd\ \$oldwd\n\ \ \ \ return\ \$files\n\}\n======\n\nFP:\ \ This\ (slighty\ modified)\ code\ is\ now\ included\ in\ \[Tcllib\]\ \n\n======\npackage\ require\ tcllib\ \nset\ listOfFiles\ \[fileutil::find\ \$_basedir\ \$_filterScript\]\n======\n\nstaale:\ I\ had\ to\ change\ (using\ windows\ ActiveState)\ the\ first\ line\ above\ to:\n\n======\npackage\ require\ fileutil\n======\n\nAs\ I'm\ new\ to\ tcl\ I\ would\ not\ know\ if\ the\ original\ syntax\ would\ work\ on\ other\nplatforms.\n\n\[arjen\]\ It\ is\ safer\ to\ use\ `package\ require\ fileutil`,\ since\ you\ can\ install\ and\ use\ individual\ packages\ from\ \[Tcllib\].\n\ \n***\ Example\ usage:\ ***\n\nAll\ *.txt\ files:\n\n======\nfind\ .\ \{string\ match\ *.txt\}\n======\n\nAll\ ordinary\ files:\n\n======\nfind\ .\ \{file\ isfile\}\n======\n\nAll\ readable\ files:\n\n======\nfind\ .\ \{file\ readable\}\n======\n\nAll\ non-empty\ files:\n\n======\nfind\ .\ \{file\ size\}\n======\n\nAll\ ordinary,\ non-empty,\ readable,\ *.txt\ files:\n\n======\nproc\ criterion\ filename\ \{\n\ \ \ \ expr\ \{\n\ \ \ \ \ \ \ \ \[file\ isfile\ \$filename\]\ \ \ &&\ \[file\ size\ \$filename\]\ &&\n\ \ \ \ \ \ \ \ \[file\ readable\ \$filename\]\ &&\ \[string\ match\ *.txt\ \$filename\]\n\ \ \ \ \}\n\}\nfind\ .\ criterion\n======\n\nAll\ directories\ containing\ a\ description.txt\ file:\n\n======\nproc\ isDirWithDescription\ filename\ \{\n\ \ \ \ if\ \{!\[file\ isdirectory\ \$filename\]\}\ \{return\ -code\ continue\ \{\}\}\n\ \ \ \ cd\ \$filename\n\ \ \ \ set\ l\ \[llength\ \[glob\ -nocomplain\ description.txt\]\]\n\ \ \ \ cd\ ..\n\ \ \ \ return\ \$l\n\}\nfind\ .\ isDirWithDescription\n======\n\n\n**\ sed\ **\n\nDoing\ a\ full\ sed\ replacement\ is\ hard.\ \ It\ is\ better\ to\ just\ write\ a\ Tcl\nprogram/procedure\ from\ scratch\ that\ implements\ the\ functionality.\ \ This\ is\nprobably\ easier\ though\ if\ someone\ implements\ some\ kind\ of\ line\ iterator\n(suitable\ for\ most\ simple\ uses\ of\ sed\ where\ all\ you\ want\ to\ do\ is\ apply\ a\nsubstitution\ to\ each\ line\ of\ a\ file/stream\ or\ only\ print\ some\ lines.)\ \ It\ is\nprobably\ easier\ to\ just\ run\ sed\ externally\ (with\ \[\[exec\]\])\ for\ anything\ that\ is\nvery\ complex\ and\ where\ you've\ not\ the\ time\ to\ reimplement.\n\nHowever,\ as\ a\ little\ goodie,\ here\ are\ some\ alternatives\ to\ very\ common\ sed\ncommands...\n\n`sed\ \"s/RE/replacement/\"\ <inputFile\ >outputFile`\n\n======\nproc\ substFile\ \{regexp\ replacement\ inputFile\ outputFile\}\ \{\n\ \ \ \ set\ fin\ \[open\ \$inputFile\ r\]\n\ \ \ \ set\ fout\ \[open\ \$outputFile\ w\]\n\ \ \ \ while\ \{\[gets\ \$fin\ linein\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ regsub\ \$regexp\ \$linein\ \$replacement\ lineout\n\ \ \ \ \ \ \ \ puts\ \$fout\ \$lineout\n\ \ \ \ \}\n\ \ \ \ close\ \$fin\n\ \ \ \ close\ \$fout\n\}\n======\n\n`sed\ \"s/RE/replacement/g\"\ <inputFile\ >outputFile`\n\n======\nproc\ substGlobalFile\ \{regexp\ replacement\ inputFile\ outputFile\}\ \{\n\ \ \ \ set\ fin\ \[open\ \$inputFile\ r\]\n\ \ \ \ set\ fout\ \[open\ \$outputFile\ w\]\n\ \ \ \ while\ \{\[gets\ \$fin\ linein\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ regsub\ -all\ \$regexp\ \$linein\ \$replacement\ lineout\n\ \ \ \ \ \ \ \ puts\ \$fout\ \$lineout\n\ \ \ \ \}\n\ \ \ \ close\ \$fin\n\ \ \ \ close\ \$fout\n\}\n======\n\n`sed\ \"y/abc/xyz/\"\ <inputFile\ >outputFile`\n\n======\nproc\ transformFile\ \{from\ to\ inputFile\ outputFile\}\ \{\n\ \ \ \ set\ map\ \{\}\n\ \ \ \ foreach\ f\ \[split\ \$from\ \{\}\]\ t\ \[split\ \$to\ \{\}\]\ \{\n\ \ \ \ \ \ \ \ lappend\ map\ \$f\ \$t\n\ \ \ \ \}\n\ \ \ \ set\ fin\ \[open\ \$inputFile\ r\]\n\ \ \ \ set\ fout\ \[open\ \$outputFile\ w\]\n\ \ \ \ while\ \{\[gets\ \$fin\ line\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ puts\ \$fout\ \[string\ map\ \$map\ \$line\]\n\ \ \ \ \}\n\ \ \ \ close\ \$fin\n\ \ \ \ close\ \$fout\n\}\n======\n\n\n**\ sort\ **\n\nYet\ again,\ we\ have\ a\ little\ program\ that\ really\ does\ an\ awful\ lot.\ \ If\ we\ don't\ncare\ about\ options\ and\ argument\ processing,\ it\ can\ be\ done\ as\ a\ one-liner:\n\n======\nputs\ -nonewline\ \[join\ \[lsort\ \[split\ \[read\ stdin\]\ \\n\]\]\ \\n\]\n======\n\nA\ full\ \[http://linux.die.net/man/1/sort%|%sort%|%\]\ has\ plenty\ of\ options\ for\ncontrolling\ the\ various\ parts\ of\ this\ process.\ \ Mapping\ the\ whole\ of\ the\nfunctionality\ is\ tricky,\ but\ we\ can\ build\ the\ core\ of\ it\ and\ still\ get\nsomething\ useful.\n\n======\nproc\ sort\ \{args\}\ \{\n\ \ \ \ \n\ \ \ \ ###\ Parse\ the\ arguments\n\ \ \ \ set\ idx\ \[lsearch\ -exact\ \$args\ --\]\n\ \ \ \ if\ \{\$idx\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ set\ files\ \[lrange\ \$args\ \[expr\ \{\$idx+1\}\]\ end\]\n\ \ \ \ \ \ \ \ set\ opts\ \ \[lrange\ \$args\ 0\ \[expr\ \{\$idx-1\}\]\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ #\ We\ need\ to\ guess\ which\ are\ files\ and\ which\ are\ options\n\ \ \ \ \ \ \ \ set\ files\ \[list\]\n\ \ \ \ \ \ \ \ set\ opts\ \[list\]\n\ \ \ \ \ \ \ \ foreach\ arg\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ incr\ idx\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[file\ exists\ \$arg\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ files\ \[lrange\ \$args\ \$idx\ end\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ break\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ opts\ \$arg\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ \n\ \ \ \ ###\ Read\ the\ files\n\ \ \ \ set\ lines\ \[list\]\n\ \ \ \ if\ \{\[llength\ \$files\]\ ==\ 0\}\ \{\n\ \ \ \ \ \ \ \ #\ Read\ from\ stdin\n\ \ \ \ \ \ \ \ while\ \{\[gets\ stdin\ line\]\ >=\ 0\}\ \{lappend\ lines\ \$line\}\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ foreach\ file\ \$files\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[string\ equal\ \$file\ \"-\"\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ f\ stdin\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ close\ 0\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ f\ \[open\ \$file\ r\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ close\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ while\ \{\[gets\ \$f\ line\]\ >=\ 0\}\ \{lappend\ lines\ \$line\}\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$close\}\ \{close\ \$f\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ \n\ \ \ \ ###\ Sort\ the\ lines\ in-place\ (need\ 8.3.0\ or\ later\ for\ efficiency)\n\ \ \ \ set\ lines\ \[eval\ \[list\ lsort\]\ \$opts\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \[lrange\ \[list\ \$lines\ \[set\ lines\ \{\}\]\]\ 0\ 0\]\]\n\n\ \ \ \ ###\ Write\ the\ sorted\ lines\ out\ to\ stdout\n\ \ \ \ foreach\ line\ \$lines\ \{\n\ \ \ \ \ \ \ \ puts\ stdout\ \$line\n\ \ \ \ \}\n\}\n=======\n\n''e.g.''\ Sort\ two\ files\ of\ numbers,\ producing\ a\ single\ file\ sorted\ in\ndecreasing\ order\ sort\ -integer\ -decreasing\ --\ numberfile1.txt\ numberfile2.txt\n\n\n**\ uniq\ **\n\nThis\ is\ actually\ one\ of\ the\ simplest\ Unix\ utilities,\ but\ even\ so\ I\ will\ only\nproduce\ a\ cut-down\ version\ here.\ \ The\ only\ option\ I\ support\ is\ `-c`\ (to\ precede\neach\ line\ by\ the\ number\ of\ times\ in\ sequence\ it\ occurs.)\n\n======\nproc\ uniq\ args\ \{\n\ \ \ \ ###\ Parse\ the\ arguments\n\ \ \ \ if\ \{\[llength\ \$args\]\ &&\ \[string\ equal\ \[lindex\ \$args\ 0\]\ \"-c\"\]\}\ \{\n\ \ \ \ \ \ \ \ set\ count\ 1\n\ \ \ \ \ \ \ \ set\ args\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ set\ count\ 0\n\ \ \ \ \}\n\ \ \ \ #\ No\ args\ is\ equivalent\ to\ specifying\ stdin\n\ \ \ \ if\ \{!\[llength\ \$args\]\}\ \{set\ args\ -\}\n\n\ \ \ \ set\ last\ \{\}\n\ \ \ \ set\ line\ \{\}\n\ \ \ \ set\ n\ 0\n\ \ \ \ foreach\ file\ \$args\ \{\n\ \ \ \ \ \ \ \ if\ \{\[string\ equal\ \$file\ \"-\"\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ f\ stdin\n\ \ \ \ \ \ \ \ \ \ \ \ set\ closeme\ 0\n\ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ f\ \[open\ \$file\ r\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ closeme\ 1\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ while\ \{\[gets\ \$f\ line\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[string\ equal\ \$line\ \$last\]\ &&\ \$n>0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ incr\ n\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$count\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$n>0\}\ \{puts\ \[format\ \"%4d\ %s\"\ \$n\ \$last\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \$line\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ last\ \$line\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ n\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ if\ \{\$closeme\}\ \{close\ \$f\}\n\ \ \ \ \}\n\ \ \ \ if\ \{\$count\ &&\ \$n>0\}\ \{\n\ \ \ \ \ \ \ \ puts\ \[format\ \"%4d\ %s\"\ \$n\ \$last\]\n\ \ \ \ \}\n\}\n======\n\n\n**\ tr\ **\n\nThe\ following\ implementation\ of\ '''tr'''\ shows\ how\ \[\[string\ map\]\]\ can\ be\ used\nto\ transliterate\ characters.\ \ A\ production\ implementation\ would\ probably\nmaintain\ a\ cache\ of\ the\ translation\ list\ going\ into\ \[\[string\ map\]\],\ but\ this\nimplementation\ gives\ the\ basics.\ \ Note\ that\ the\ implementation\ didn't\ need\ to\ndo\ anything\ special\ to\ be\ Unicode-aware\;\ you\ can,\ for\ instance,\ use\ it\ to\nsubstitute\ Katakana\ for\ Hiragana\ by\ doing\ `\[\[tr\ \\u3041-\\u309e\ \\u30a1-\\u30fe\n\$japaneseString\]\]`\n\n======\n#\ This\ procedure\ implements\ a\ \[\[tr\]\]\ command\ akin\ to\ the\ shell\ one.\nproc\ tr\ \{\ from\ to\ string\ \}\ \{\n\ \ \ \ set\ mapping\ \[list\]\n\ \ \ \ foreach\ c1\ \[trExpand\ \$from\]\ c2\ \[trExpand\ \$to\]\ \{\n\ \ \ \ \ \ \ lappend\ mapping\ \$c1\ \$c2\n\ \ \ \ \}\n\ \ \ \ return\ \[string\ map\ \$mapping\ \$string\]\n\}\n\n#\ This\ helper\ procedure\ takes\ a\ string\ of\ characters\ like\ A-F0-9_\ and\ expands\ it\ to\ a\ list\ of\ characters\ like\ \{A\ B\ C\ D\ E\ F\ 0\ 1\ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9\ _\}\n\nproc\ trExpand\ \{\ chars\ \}\ \{\n\ \ \ \ set\ state\ noHyphen\n\ \ \ \ set\ result\ \[list\]\n\ \ \ \ foreach\ c\ \[split\ \$chars\ \{\}\]\ \{\n\ \ \ \ \ \ \ switch\ -exact\ --\ \$state\ \{\n\ \ \ \ \ \ \ \ \ \ \ noHyphen\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ lastChar\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ state\ wantHyphen\n\ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ wantHyphen\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\ \[string\ equal\ -\ \$c\]\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ state\ sawHyphen\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ lastChar\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ sawHyphen\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scan\ \$lastChar\ %c\ from\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ incr\ from\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scan\ \$c\ %c\ to\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\ \$from\ >\ \$to\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ error\ \"\$lastChar\ does\ not\ precede\ \$c.\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ \{\ set\ i\ \$from\ \}\ \{\ \$i\ <=\ \$to\ \}\ \{\ incr\ i\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \[format\ %c\ \$i\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ state\ noHyphen\n\ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ if\ \{\ \[string\ equal\ sawHyphen\ \$state\]\ \}\ \{\n\ \ \ \ \ \ \ lappend\ result\ -\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n\ \n#\ The\ following\ call\ shows\ that\ rot13\ works\n\nputs\ \[tr\ A-Za-z\ N-ZA-Mn-za-m\ \{Guvf\ vf\ n\ grfg\}\]\n\n#\ The\ following\ call\ shows\ the\ use\ of\ tr\ to\ eliminate\ certain\ characters\ \n\nputs\ \[tr\ A-Z\ \{\}\ \{THISthis\ ISis\ Aa\ TESTtest\}\]\n======\n\n----\n\nThere\ are\ at\ least\ two\ other\ ways\ to\ achieve\ tr\ worth\ mentioning\ \[TclX\]\nimplements\ it,\ and\ if\ tr\ is\ available\ externally,\ it's\ quick\ to\ write\n\n======\nproc\ tr\ \{\ from\ to\ string\ \}\ \{\n\ \ \ \ return\ \[exec\ tr\ \$from\ \$to\ <<\ \$string\]\n\}\n======\n\n**\ wc\ **\n\nThe\ following\ implements\ the\ default\ behavior\ of\ '''wc''',\ i.e.\ when\ called\nwithout\ any\ flags.\n\n======\nproc\ wc\ \{filename\}\ \{\n\ \ \ \ foreach\ i\ \{l\ w\ c\}\ \{\n\ \ \ \ \ \ \ \ set\ \$i\ 0\n\ \ \ \ \}\n\n\ \ \ \ set\ f\ \[open\ \$filename\]\n\n\ \ \ \ while\ true\ \{\n\ \ \ \ \ \ \ \ set\ txt\ \[gets\ \$f\]\n\ \ \ \ \ \ \ \ if\ \[eof\ \$f\]\ break\n\n\ \ \ \ \ \ \ \ incr\ l\n\ \ \ \ \ \ \ \ incr\ w\ \[regexp\ -all\ \{\[^\[:space:\]\]+\}\ \$txt\]\n\ \ \ \ \ \ \ \ incr\ c\ \[expr\ \{\[string\ length\ \$txt\]\ +\ 1\}\]\n\ \ \ \ \}\n\n\ \ \ \ close\ \$f\n\ \ \ \ return\ \[list\ \$l\ \$w\ \$c\]\n\}\n======\n\n**\ Debugging\ **\n\n======\nproc\ Exec\ \{args\}\ \{\n\ \ puts\ stderr\ \$args\n\ \ eval\ exec\ \$args\n\}\n======\n\n''DKF:''\ If\ you\ want\ to\ do\ more\ advanced\ debugging\ (like\ determining\ exactly\nhow\ a\ piece\ of\ code\ is\ compiled\ and\ executed)\ then\ it\ is\ more\ easily\ done\ using\nthe\ following\ script:\n\n======\nproc\ tracedEval\ \{script\ \{execLevel\ 3\}\ \{compileLevel\ 2\}\}\ \{\n\ \ \ \ global\ tcl_traceCompile\ tcl_traceExec\ errorCode\ errorInfo\n\n\ \ \ \ #\ Set\ the\ debugging\ levels\n\ \ \ \ set\ tcl_traceCompile\ \$compileLevel\n\ \ \ \ set\ tcl_traceExec\ \$execLevel\n\n\ \ \ \ #\ Execute\ the\ script,\ handling\ any\ failures\n\ \ \ \ set\ code\ \[catch\ \{uplevel\ \$script\}\ msg\]\n\n\ \ \ \ #\ Restore\ the\ debugging\ levels\ to\ normal\ running.\n\ \ \ \ #\ I\ assume\ that\ you\ normally\ have\ these\ vars\ set\ to\ 0\n\ \ \ \ set\ tcl_traceExec\ 0\n\ \ \ \ set\ tcl_traceCompile\ 0\n\n\ \ \ \ #\ Pass\ on\ all\ errors\ thrown\ in\ the\ script\ to\ our\ caller\n\ \ \ \ return\ -code\ \$code\ -errorcode\ \$errorCode\ -errorinfo\ \$errorInfo\ \$msg\n\}\n======\n\nPlease\ note\ that\ you\ only\ get\ results\ if\ you\ have\ a\ real\ console\ attached.\ \ On\nsome\ platforms,\ this\ is\ a\ pain...\n\n\n**\ Tk\ Events\ **\n\n—\ especially\ ''keypress''\ events\n\nThis\ little\ script\ will\ echo\ all\ keyboard\ events\ to\ stdout:\n\n======\nbind\ .\ <KeyPress>\ \{\n\ \ \ \ set\ dec\ \"\"\;\ scan\ %A\ %%c\ dec\n\ \ \ \ puts\ \"keysym:%K\ prints:%A\ (\$dec)\"\n\}\ \;#--------------\ and\ to\ turn\ this\ off\ again:\nbind\ .\ <KeyPress>\ \{\}\n======\n\nThis\ proc\ will\ bind\ a\ new\ event\ to\ \".\".\ \ It\ can\ show\ you\ when\ mouse\ events\noccur,\ if\ you\ bind\ it\ to\ things\ like\ Enter\ or\ Motion.\n\n======\nproc\ unk\ \{e\}\ \{bind\ .\ <\$e>\ \"puts\ \$e\"\}\n======\n\n----\n\nIf\ you\ have\ an\ event\ driven\ program,\ end\ it\ with\ tclx\ mainloop.\n\nThen\ you\ can\n\n======none\ntcl>\ source\ program.tcl\n======\n\n(churnchurnchurn)\n\n======none\ntcl>\ \n======\n\nYou\ have\ an\ event\ driven\ command\ prompt\ while\ the\ program\ is\ running.\ \ You\ can\ndump\ arrays,\ invoke\ routines,\ run\ profile,\ all\ sorts\ of\ things.\ \ Mainloop\ is\nsmart\ enough\ so\ that\ when\ you\ run\ it\ stand-alone\n\n======\ntcl\ program.tcl\n======\n\nIt\ does\ the\ right\ thing.\n\nMay\ all\ your\ programs\ be\ event\ driven.\n\n\[DKF\]:\ \ Note\ that\ people\ running\ wish\ on\ Unix\ platforms\ can\ simply\ use\ \[\[send\]\]\nas\ a\ way\ to\ attach\ a\ console\ to\ a\ running\ Tcl/Tk\ program.\ \ The\ distributed\ demo\nscript,\ ''rmt''\ does\ this,\ (and\ is\ perfectly\ adequate\ for\ a\ lot\ use),\ or\ you\ncould\ use\ Jeff\ Hobbs's\ \[http://tkcon.sourceforge.net%|%tkcon%|%\]\ which\ is\ more\nsophisticated.\n\nJDG:\ \ If\ you\ want\ a\ very\ simple\ command\ line,\ you\ can\ also\ use\ the\ interp.tcl\nscript\ for\ the\ plain-text\ interface\ to\n\[http://www.jstrack.org/jstrack/%|%JStrack%|%\],\ which\ hasn't\ been\ touched\ for\nalmost\ a\ decade.\ \ Download\ the\ JStrack\ source\ from\ jstrack.org\ and\ look\ in\ the\ntracker/lib\ directory.\ \ ''interp.tcl''\ is\ there.\ \ This\ is\ part\ of\ JStrack\ (a\nvery\ ancient\ part,\ I\ might\ add),\ and\ was\ originally\ provided\ by\ Jeff\ Hobbs,\nwith\ a\ lot\ of\ help\ from\ Brent\ Welch\ (et\ al)\ in\ expanding\ it.\ \ Just\ source\ it\ as\nthe\ *LAST*\ line\ in\ your\ script.\n\nJDG\ 2010-06-25:\ \ FWIW,\ I\ now\ use\ Jeff\ Hobbs's\ tkcon.tcl\ and\ the\ tkcon_wrap.tcl\n...\ and\ really\ need\ to\ update\ JStrack\ to\ use\ these,\ as\ well.\n\n\n**\ Re-encoding\ strings\ **\n\nIf\ (in\ tcl\ 8.1\ or\ above)\ tcl\ has\ misinterpreted\ the\ charset\ of\ some\ string\ngotten\ from\ an\ external\ program\ or\ system\ function,\ and\ you\ are\ left\ with\ a\nstring\ with\ Latin-1\ accented\ characters\ (\\u0080-\\u00FF)\ instead\ of\ your\nlanguage\ letters,\ you\ can\ fix\ the\ string\ using\n\n======\nset\ fixed_string\ \[encoding\ convertfrom\ \$right_encoding\ \[encoding\ convertto\ \$wrongencoding\ \$string\]\]\n======\n\nwhere\ variable\ `\$right_encoding`\ contains\ the\ name\ of\ the\ encoding\ string\nreally\ had\ (typically\ same\ as\ your\ encoding\ system)\ and\ wrong_encoding\ is\nencoding\ tcl\ assumed\ string\ has\ (typically\ iso8859-1).\ \n\n\n**\ Re-encoding\ files\ **\n\nHere's\ a\ unix-style\ filter\ that\ reencodes\ text.\n\n======\n#!\ /usr/bin/tclsh\n#\ (or\ whatever\ incantation\ works\ for\ you)\n\nproc\ main\ \{fromTransl\ fromEnc\ toTransl\ toEnc\}\ \{\n\ \ \ \ fconfigure\ stdin\ -translation\ \$fromTransl\ -encoding\ \$fromEnc\n\ \ \ \ fconfigure\ stdout\ -translation\ \$toTransl\ -encoding\ \$toEnc\n\ \ \ \ fcopy\ stdin\ stdout\n\}\nmain\ \{*\}\$argv\ \;\ #\ Leverage\ error\ thrown\ by\ procs\ for\ reminder\ of\ correct\ syntax\n======\n\nExamples:\n\n======\ncat\ macClassicFile.txt\ |\ ''scriptname''\ cr\ macRoman\ lf\ utf-8\ >macOSXFile.txt\ncat\ macOSXFile.txt\ |\ ''scriptname''\ lf\ utf-8\ cr\ macRoman\ >macClassicFile.txt\n======\n\n\n**\ Advanced\ split\ **\n\nIf\ you\ need\ to\ split\ string\ into\ list\ using\ some\ more\ complicated\ rule\ than\nbuiltin\ split\ command\ allows,\ use\ following\ function\n\n======\nproc\ xsplit\ \[list\ str\ \[list\ regexp\ \"\\\[\\t\ \\r\\n\\\]+\"\]\]\ \{\n\ \ \ \ set\ list\ \ \{\}\n\ \ \ \ while\ \{\[regexp\ -indices\ --\ \$regexp\ \$str\ match\ submatch\]\}\ \{\n\ \ \ \ \ \ \ lappend\ list\ \[string\ range\ \$str\ 0\ \[expr\ \[lindex\ \$match\ 0\]\ -1\]\]\n\ \ \ \ \ \ \ if\ \{\[lindex\ \$submatch\ 0\]>=0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ lappend\ list\ \[string\ range\ \$str\ \[lindex\ \$submatch\ 0\]\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[lindex\ \$submatch\ 1\]\]\ \n\ \ \ \ \ \ \ \}\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ set\ str\ \[string\ range\ \$str\ \[expr\ \[lindex\ \$match\ 1\]+1\]\ end\]\ \n\ \ \ \ \}\n\ \ \ \ lappend\ list\ \$str\n\ \ \ \ return\ \$list\n\}\n======\n\ncary:\ \ It\ mimics\ Perl\ split\ operator\ which\ allows\ regexp\ as\ element\ separator,\ but,\nlike\ builtin\ split,\ it\ expects\ string\ to\ split\ as\ first\ arg\ and\ regexp\ as\nsecond\ (optional).\n\nBy\ default,\ it\ splits\ by\ any\ amount\ of\ whitespace.\n\nNote\ that\ if\ you\ add\ parenthesis\ into\ regexp,\ parenthesed\ part\ of\ separator\nwould\ be\ added\ into\ list\ as\ additional\ element.\ Just\ like\ in\ Perl.\n\n\n**\ Simple\ socket\ communication\ **\n\nVolker:\ \ The\ beauty\ of\ scripting\ lies\ (a.o.)\ in\ the\ fact\ that\ you\ can\ have\ lots\nof\ little\ programs\ cooperating\ with\ each\ other.\ For\ this,\ a\ simple\ means\ of\ncommunication\ is\ necessary.\ This\ simple\ server\ (and\ even\ simpler\ client)\ show\nhow\ it\ works:\n\n''Server:''\n\n======\n#!/bin/sh\n#\ \\\nexec\ tclsh\ \"\$0\"\ \"\$@\"\nproc\ serveConnection\ \{Handle\}\ \{\n\ \ \ \ set\ LineLength\ \[gets\ \$Handle\ Line\]\n\ \ \ \ if\ \{\$LineLength>=0\}\ \{\n\ \ \ \ \ \ \ \ #This\ is\ where\ you\ finally\ can\ do\ something\ with\ the\ data.\n\ \ \ \ \ \ \ \ #We\ simply\ put\ it\ back\ where\ it\ came\ from.\n\ \ \ \ \ \ \ \ puts\ \$Handle\ \"Received:\ \$Line\"\;\ flush\ \$Handle\ \n\ \ \ \ \}\ elseif\ \{\[eof\ \$Handle\]\}\ \{\n\ \ \ \ \ \ \ \ catch\ \{close\ \$Handle\}\n\ \ \ \ \}\n\}\nproc\ acceptConnections\ \{ConnectionFileHandle\ ClientAddress\ ClientPort\}\ \{\n\ \ \ \ fconfigure\ \$ConnectionFileHandle\ -blocking\ 0\n\ \ \ \ fileevent\ \$ConnectionFileHandle\ readable\ \[list\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ catch\ \[list\ serveConnection\ \$ConnectionFileHandle\]\]\n\}\nsocket\ -server\ acceptConnections\ 2000\nvwait\ Dummyvariable\n======\n\nThe\ server\ above\ is\ good\ enough\ for\ single\ line\ requests.\ It\ handles\ all\ the\ninteraction\ between\ gets,\ eof\ and\ fileevent\ correctly\ (IMHO)\ and\ can\ certainly\nserve\ several\ connections\ at\ once.\ It\ can\ cope\ with\ clients\ closing\ their\nsockets\ at\ any\ time.\n\nIf\ you\ don't\ specify\ the\ port\ number\ explicitly\ (2000\ in\ this\ case),\ but\nspecify\ 0,\ the\ socket\ finds\ the\ first\ free\ port.\ You\ can\ then\ ask\ the\ handle\nfor\ its\ port\ number\ and\ try\ to\ get\ it\ to\ your\ clients.\ for\ instance\ by\ writing\nit\ into\ a\ file\ or\ something.\n\nThe\ handle\ is\ the\ (ignored\ above)\ return\ value\ of\ the\ socket\ command.\n\n''Client:''\n\n======\n#!/bin/sh\n#\ \\\nexec\ tclsh\ \"\$0\"\ \"\$@\"\n\nset\ Handle\ \[socket\ localhost\ 2000\]\nputs\ -nonewline\ \$Handle\ \"Hello\"\;\ flush\ \$Handle\ \nputs\ \$Handle\ \"\ Dolly\"\;\ flush\ \$Handle\ \nputs\ \[gets\ \$Handle\]\nclose\ \$Handle\ \n======\n\nThe\ client\ demonstrates\ that\ the\ server\ does\ indeed\ accumulate\ a\ complete\ line\nfirst,\ before\ it\ gets\ processed.\ the\ magic\ behavior\ of\ gets\ is\ largely\nresponsible\ for\ that,\ which\ makes\ the\ server\ so\ simple.\n\nWell,\ that's\ it!\ :-)\n\n----\n\nPelle\ Otterholm:\ Here\ is\ another\ version\ of\ the\ server\ part\ that\ you\ might\ want\nto\ use.\n\n======\n#!/usr/bin/env\ tclsh\n\nproc\ done\ \{\}\ \{\ set\ ::done\ 1\ \}\n\nproc\ process\ \{fd\ ip\ port\}\ \{\n\ \ \ \ if\ \{!(\[eof\ \$fd\]\ ||\ \[catch\ \{gets\ \$fd\ line\ \}\])\ \}\ \{\n\ \ \ \ \ \ \ \ if\ \{\[string\ length\ \$line\]\ ==\ 0\}\ \{\ return\ \}\n\ \ \ \ \ \ \ \ if\ \{\[string\ match\ exit\ \$line\]\}\ \{\ close\ \$fd\ \;\ return\ \}\n\ \ \ \ \ \ \ \ if\ \{\[string\ match\ done\ \$line\]\}\ \{\ close\ \$fd\ \;\ done\ \;\ return\ \}\n\ \ \ \ \ \ \ \ puts\ \$fd\ \"input\ :\ \$line\"\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ catch\ \{\ close\ \$fd\ \}\n\ \ \ \ \}\n\}\n\nproc\ accept\ \{fd\ ip\ port\}\ \{\n\ \ \ \ fconfigure\ \$fd\ -blocking\ 0\ -buffering\ line\n\ \ \ \ fileevent\ \$fd\ readable\ \[list\ process\ \$fd\ \$ip\ \$port\]\n\}\nproc\ listen\ \{port\}\ \{\n\ \ \ \ socket\ -myaddr\ 127.0.0.1\ -server\ accept\ \$port\n\ \ \ \ vwait\ done\n\}\n\nlisten\ 2000\n======\n\n\[AMG\]:\ \ Shouldn't\ the\ \[\[\[eof\]\]\]\ come\ ''after''\ the\ \[\[\[gets\]\]\]?\ \ \ The\ \[\[eof\]\]\nman\ page\ \[http://www.tcl.tk/man/tcl8.6/TclCmd/eof.htm\]\ says:\n\n\"Returns\ 1\ if\ an\ end\ of\ file\ condition\ occurred\ during\ the\ most\ recent\ input\noperation\ on\ ''channelId''\ (such\ as\ '''gets'''),\ 0\ otherwise.\"\n\nAlso,\ the\ return\ value\ of\ \[\[gets\]\]\ should\ be\ checked\ so\ that\ you\ can\ndifferentiate\ between\ receiving\ a\ blank\ line\ and\ having\ an\ error\ or\nend-of-file.\ \ Two-argument\ \[\[gets\]\]\ will\ return\ -1\ on\ error\ and\ end-of-file\n(use\ \[\[eof\]\]\ to\ tell\ the\ difference),\ 0\ on\ blank\ line\ or\ no-data-available\n(when\ the\ channel\ is\ nonblocking\;\ use\ \[\[\[fblocked\]\]\]\ to\ test\ this).\n\nPelle\ Otterholm:\ \ the\ code\ is\ based\ on\ same\ coding\ idea\ as\ \[Simple\ TCP/IP\ proxy\],\ also\ changed\ to\ line\ buffering\ and\ move\ gets\ \$fd\ file\ into\ the\ check,\ getting\ :\ \"`if\ \{!(\[\[eof\ \$fd\]\]\ ||\ \[\[catch\ \{gets\ \$fd\}\]\])\ \}`\"\n\n----\n\n\[DKF\]:\ \ There\ is\ a\ more\ advanced\ version\ of\ this\ on\ the\ \[telnet\]\ page.\n\n\[SDW\]:\ \ has\ put\ together\ an\ example\ of\ \[Remote\ Script\ Execution\]\ using\ safe\ninterpreters.\n\n----\n\n\ \ \ *\ \[A\ Server\ Template\]\n\n----\n\nCheck\ out\ the\ verbose_eval\ script\ over\ on\ \[eval\]\ page!\n\n<<categories>>\ Example regexp2} CALL {my render {Example Scripts Everybody Should Have} There\ are\ many\ simple\ example\ scripts\ that\ every\ Tcl/Tk\ programmer\ should\ keep\naround\ for\ reference.\ \ They\ are\ good\ examples\ of\ Tcl/Tk\ techniques,\ and\ they're\njust\ plain\ handy\ sometimes.\ \ (Thanks\ to\ Harald\ Kirsch\ for\ suggesting\ the\ncollection\ on\ comp.lang.tcl)\ \ Also\ think\ about\ \[The\ RC\ File\].\n\n\n\n**\ Description\ **\n\n\[LV\]:\ today\ I\ am\ only\ partially\ able\ to\ access\ the\ internet\ -\ it\ would\ be\ useful\nfor\ someone\ with\ full\ access\ to\ look\ through\ the\ following\ list\ and\ submit\nFeature\ Requests\ to\ http://tcllib.sf.net/\ to\ get\ some\ of\ this\ great\ code\ into\ a\ntcllib\ distribution.\n\n\n\n**\ Unix-like\ utilities\ **\n\n\[http://www.perl.com/language/ppt/%|%here%|%\]\ is\ \[Perl\]'s\ rendition\ of\ the\nsame.\n\n\ \ \ \[awk\]:\ \ \ \n\n\ \ \ \[diff\ in\ Tcl\]:\ \ \ a\ trifle\ long,\ so\ it's\ off\ in\ its\ own\ page.\n\n\ \ \ find:\ \ \ see\ \[fileutil\],\ a\ module\ in\ \[tcllib\]\n\n\ \ \ \[grep\]:\ \ \ See\ also\ \[fileutil\],\ a\ module\ in\ \[tcllib\]\n\n\ \ \ \[ls\ -l\ in\ Tcl\]:\ \ \ also\ a\ trifle\ long,\ and\ off\ on\ its\ own\ page.\n\n\ \ \ od:\ \ \ \[Dump\ a\ file\ in\ hex\ and\ ASCII\]\n\n\ \ \ sed:\ \ \ \n\n\ \ \ sort:\ \ \ \n\n\ \ \ \[tr\]:\ \ \ \n\n\ \ \ uniq:\ \ \ \n\n\ \ \ wc:\ \ \ \n\n\ \ \ \[anytop\]:\ \ \ indirectly\ Unix-inspired\ and\ perhaps\ a\ useful\ stub\n\n\n\n**\ Miscellaneous\ **\n\n\ \ \ Debugging:\ \ \ \n\n\ \ \ Tk\ events:\ \ \ \n\n\ \ \ Balloon\ help:\ \ \ \n\n\ \ \ Re-encoding\ strings:\ \ \ \n\n\ \ \ Advanced\ split:\ \ \ \n\n\ \ \ simple\ socket\ communication:\ \ \ \n\n\ \ \ \[Sample\ Math\ Programs\]:\ \ \ \n\n\ \ \ \[try\ ...\ finally\ ...\]:\ \ \ \n\n\n\n**\ find\ **\n\n======\nproc\ find\ \{\{basedir\ .\}\ \{filterScript\ \{\}\}\}\ \{\n\ \ \ \ set\ oldwd\ \[pwd\]\n\ \ \ \ cd\ \$basedir\n\ \ \ \ set\ cwd\ \[pwd\]\n\ \ \ \ set\ filenames\ \[glob\ -nocomplain\ *\ .*\]\n\ \ \ \ set\ files\ \{\}\n\ \ \ \ set\ filt\ \[string\ length\ \$filterScript\]\n\ \ \ \ foreach\ filename\ \$filenames\ \{\n\ \ \ \ \ \ \ \ if\ \{!\$filt\ ||\ \[eval\ \$filterScript\ \[list\ \$filename\]\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ files\ \[file\ join\ \$cwd\ \$filename\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ if\ \{\[file\ isdirectory\ \$filename\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ files\ \[concat\ \$files\ \[find\ \$filename\ \$filterScript\]\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ cd\ \$oldwd\n\ \ \ \ return\ \$files\n\}\n======\n\nFP:\ \ This\ (slighty\ modified)\ code\ is\ now\ included\ in\ \[Tcllib\]\ \n\n======\npackage\ require\ tcllib\ \nset\ listOfFiles\ \[fileutil::find\ \$_basedir\ \$_filterScript\]\n======\n\nstaale:\ I\ had\ to\ change\ (using\ windows\ ActiveState)\ the\ first\ line\ above\ to:\n\n======\npackage\ require\ fileutil\n======\n\nAs\ I'm\ new\ to\ tcl\ I\ would\ not\ know\ if\ the\ original\ syntax\ would\ work\ on\ other\nplatforms.\n\n\[arjen\]\ It\ is\ safer\ to\ use\ `package\ require\ fileutil`,\ since\ you\ can\ install\ and\ use\ individual\ packages\ from\ \[Tcllib\].\n\ \n***\ Example\ usage:\ ***\n\nAll\ *.txt\ files:\n\n======\nfind\ .\ \{string\ match\ *.txt\}\n======\n\nAll\ ordinary\ files:\n\n======\nfind\ .\ \{file\ isfile\}\n======\n\nAll\ readable\ files:\n\n======\nfind\ .\ \{file\ readable\}\n======\n\nAll\ non-empty\ files:\n\n======\nfind\ .\ \{file\ size\}\n======\n\nAll\ ordinary,\ non-empty,\ readable,\ *.txt\ files:\n\n======\nproc\ criterion\ filename\ \{\n\ \ \ \ expr\ \{\n\ \ \ \ \ \ \ \ \[file\ isfile\ \$filename\]\ \ \ &&\ \[file\ size\ \$filename\]\ &&\n\ \ \ \ \ \ \ \ \[file\ readable\ \$filename\]\ &&\ \[string\ match\ *.txt\ \$filename\]\n\ \ \ \ \}\n\}\nfind\ .\ criterion\n======\n\nAll\ directories\ containing\ a\ description.txt\ file:\n\n======\nproc\ isDirWithDescription\ filename\ \{\n\ \ \ \ if\ \{!\[file\ isdirectory\ \$filename\]\}\ \{return\ -code\ continue\ \{\}\}\n\ \ \ \ cd\ \$filename\n\ \ \ \ set\ l\ \[llength\ \[glob\ -nocomplain\ description.txt\]\]\n\ \ \ \ cd\ ..\n\ \ \ \ return\ \$l\n\}\nfind\ .\ isDirWithDescription\n======\n\n\n**\ sed\ **\n\nDoing\ a\ full\ sed\ replacement\ is\ hard.\ \ It\ is\ better\ to\ just\ write\ a\ Tcl\nprogram/procedure\ from\ scratch\ that\ implements\ the\ functionality.\ \ This\ is\nprobably\ easier\ though\ if\ someone\ implements\ some\ kind\ of\ line\ iterator\n(suitable\ for\ most\ simple\ uses\ of\ sed\ where\ all\ you\ want\ to\ do\ is\ apply\ a\nsubstitution\ to\ each\ line\ of\ a\ file/stream\ or\ only\ print\ some\ lines.)\ \ It\ is\nprobably\ easier\ to\ just\ run\ sed\ externally\ (with\ \[\[exec\]\])\ for\ anything\ that\ is\nvery\ complex\ and\ where\ you've\ not\ the\ time\ to\ reimplement.\n\nHowever,\ as\ a\ little\ goodie,\ here\ are\ some\ alternatives\ to\ very\ common\ sed\ncommands...\n\n`sed\ \"s/RE/replacement/\"\ <inputFile\ >outputFile`\n\n======\nproc\ substFile\ \{regexp\ replacement\ inputFile\ outputFile\}\ \{\n\ \ \ \ set\ fin\ \[open\ \$inputFile\ r\]\n\ \ \ \ set\ fout\ \[open\ \$outputFile\ w\]\n\ \ \ \ while\ \{\[gets\ \$fin\ linein\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ regsub\ \$regexp\ \$linein\ \$replacement\ lineout\n\ \ \ \ \ \ \ \ puts\ \$fout\ \$lineout\n\ \ \ \ \}\n\ \ \ \ close\ \$fin\n\ \ \ \ close\ \$fout\n\}\n======\n\n`sed\ \"s/RE/replacement/g\"\ <inputFile\ >outputFile`\n\n======\nproc\ substGlobalFile\ \{regexp\ replacement\ inputFile\ outputFile\}\ \{\n\ \ \ \ set\ fin\ \[open\ \$inputFile\ r\]\n\ \ \ \ set\ fout\ \[open\ \$outputFile\ w\]\n\ \ \ \ while\ \{\[gets\ \$fin\ linein\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ regsub\ -all\ \$regexp\ \$linein\ \$replacement\ lineout\n\ \ \ \ \ \ \ \ puts\ \$fout\ \$lineout\n\ \ \ \ \}\n\ \ \ \ close\ \$fin\n\ \ \ \ close\ \$fout\n\}\n======\n\n`sed\ \"y/abc/xyz/\"\ <inputFile\ >outputFile`\n\n======\nproc\ transformFile\ \{from\ to\ inputFile\ outputFile\}\ \{\n\ \ \ \ set\ map\ \{\}\n\ \ \ \ foreach\ f\ \[split\ \$from\ \{\}\]\ t\ \[split\ \$to\ \{\}\]\ \{\n\ \ \ \ \ \ \ \ lappend\ map\ \$f\ \$t\n\ \ \ \ \}\n\ \ \ \ set\ fin\ \[open\ \$inputFile\ r\]\n\ \ \ \ set\ fout\ \[open\ \$outputFile\ w\]\n\ \ \ \ while\ \{\[gets\ \$fin\ line\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ puts\ \$fout\ \[string\ map\ \$map\ \$line\]\n\ \ \ \ \}\n\ \ \ \ close\ \$fin\n\ \ \ \ close\ \$fout\n\}\n======\n\n\n**\ sort\ **\n\nYet\ again,\ we\ have\ a\ little\ program\ that\ really\ does\ an\ awful\ lot.\ \ If\ we\ don't\ncare\ about\ options\ and\ argument\ processing,\ it\ can\ be\ done\ as\ a\ one-liner:\n\n======\nputs\ -nonewline\ \[join\ \[lsort\ \[split\ \[read\ stdin\]\ \\n\]\]\ \\n\]\n======\n\nA\ full\ \[http://linux.die.net/man/1/sort%|%sort%|%\]\ has\ plenty\ of\ options\ for\ncontrolling\ the\ various\ parts\ of\ this\ process.\ \ Mapping\ the\ whole\ of\ the\nfunctionality\ is\ tricky,\ but\ we\ can\ build\ the\ core\ of\ it\ and\ still\ get\nsomething\ useful.\n\n======\nproc\ sort\ \{args\}\ \{\n\ \ \ \ \n\ \ \ \ ###\ Parse\ the\ arguments\n\ \ \ \ set\ idx\ \[lsearch\ -exact\ \$args\ --\]\n\ \ \ \ if\ \{\$idx\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ set\ files\ \[lrange\ \$args\ \[expr\ \{\$idx+1\}\]\ end\]\n\ \ \ \ \ \ \ \ set\ opts\ \ \[lrange\ \$args\ 0\ \[expr\ \{\$idx-1\}\]\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ #\ We\ need\ to\ guess\ which\ are\ files\ and\ which\ are\ options\n\ \ \ \ \ \ \ \ set\ files\ \[list\]\n\ \ \ \ \ \ \ \ set\ opts\ \[list\]\n\ \ \ \ \ \ \ \ foreach\ arg\ \$args\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ incr\ idx\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[file\ exists\ \$arg\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ files\ \[lrange\ \$args\ \$idx\ end\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ break\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ opts\ \$arg\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ \n\ \ \ \ ###\ Read\ the\ files\n\ \ \ \ set\ lines\ \[list\]\n\ \ \ \ if\ \{\[llength\ \$files\]\ ==\ 0\}\ \{\n\ \ \ \ \ \ \ \ #\ Read\ from\ stdin\n\ \ \ \ \ \ \ \ while\ \{\[gets\ stdin\ line\]\ >=\ 0\}\ \{lappend\ lines\ \$line\}\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ foreach\ file\ \$files\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[string\ equal\ \$file\ \"-\"\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ f\ stdin\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ close\ 0\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ f\ \[open\ \$file\ r\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ close\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ while\ \{\[gets\ \$f\ line\]\ >=\ 0\}\ \{lappend\ lines\ \$line\}\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$close\}\ \{close\ \$f\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ \n\ \ \ \ ###\ Sort\ the\ lines\ in-place\ (need\ 8.3.0\ or\ later\ for\ efficiency)\n\ \ \ \ set\ lines\ \[eval\ \[list\ lsort\]\ \$opts\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \[lrange\ \[list\ \$lines\ \[set\ lines\ \{\}\]\]\ 0\ 0\]\]\n\n\ \ \ \ ###\ Write\ the\ sorted\ lines\ out\ to\ stdout\n\ \ \ \ foreach\ line\ \$lines\ \{\n\ \ \ \ \ \ \ \ puts\ stdout\ \$line\n\ \ \ \ \}\n\}\n=======\n\n''e.g.''\ Sort\ two\ files\ of\ numbers,\ producing\ a\ single\ file\ sorted\ in\ndecreasing\ order\ sort\ -integer\ -decreasing\ --\ numberfile1.txt\ numberfile2.txt\n\n\n**\ uniq\ **\n\nThis\ is\ actually\ one\ of\ the\ simplest\ Unix\ utilities,\ but\ even\ so\ I\ will\ only\nproduce\ a\ cut-down\ version\ here.\ \ The\ only\ option\ I\ support\ is\ `-c`\ (to\ precede\neach\ line\ by\ the\ number\ of\ times\ in\ sequence\ it\ occurs.)\n\n======\nproc\ uniq\ args\ \{\n\ \ \ \ ###\ Parse\ the\ arguments\n\ \ \ \ if\ \{\[llength\ \$args\]\ &&\ \[string\ equal\ \[lindex\ \$args\ 0\]\ \"-c\"\]\}\ \{\n\ \ \ \ \ \ \ \ set\ count\ 1\n\ \ \ \ \ \ \ \ set\ args\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ set\ count\ 0\n\ \ \ \ \}\n\ \ \ \ #\ No\ args\ is\ equivalent\ to\ specifying\ stdin\n\ \ \ \ if\ \{!\[llength\ \$args\]\}\ \{set\ args\ -\}\n\n\ \ \ \ set\ last\ \{\}\n\ \ \ \ set\ line\ \{\}\n\ \ \ \ set\ n\ 0\n\ \ \ \ foreach\ file\ \$args\ \{\n\ \ \ \ \ \ \ \ if\ \{\[string\ equal\ \$file\ \"-\"\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ f\ stdin\n\ \ \ \ \ \ \ \ \ \ \ \ set\ closeme\ 0\n\ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ f\ \[open\ \$file\ r\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ closeme\ 1\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ while\ \{\[gets\ \$f\ line\]\ >=\ 0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[string\ equal\ \$line\ \$last\]\ &&\ \$n>0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ incr\ n\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$count\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$n>0\}\ \{puts\ \[format\ \"%4d\ %s\"\ \$n\ \$last\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \$line\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ last\ \$line\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ n\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ if\ \{\$closeme\}\ \{close\ \$f\}\n\ \ \ \ \}\n\ \ \ \ if\ \{\$count\ &&\ \$n>0\}\ \{\n\ \ \ \ \ \ \ \ puts\ \[format\ \"%4d\ %s\"\ \$n\ \$last\]\n\ \ \ \ \}\n\}\n======\n\n\n**\ tr\ **\n\nThe\ following\ implementation\ of\ '''tr'''\ shows\ how\ \[\[string\ map\]\]\ can\ be\ used\nto\ transliterate\ characters.\ \ A\ production\ implementation\ would\ probably\nmaintain\ a\ cache\ of\ the\ translation\ list\ going\ into\ \[\[string\ map\]\],\ but\ this\nimplementation\ gives\ the\ basics.\ \ Note\ that\ the\ implementation\ didn't\ need\ to\ndo\ anything\ special\ to\ be\ Unicode-aware\;\ you\ can,\ for\ instance,\ use\ it\ to\nsubstitute\ Katakana\ for\ Hiragana\ by\ doing\ `\[\[tr\ \\u3041-\\u309e\ \\u30a1-\\u30fe\n\$japaneseString\]\]`\n\n======\n#\ This\ procedure\ implements\ a\ \[\[tr\]\]\ command\ akin\ to\ the\ shell\ one.\nproc\ tr\ \{\ from\ to\ string\ \}\ \{\n\ \ \ \ set\ mapping\ \[list\]\n\ \ \ \ foreach\ c1\ \[trExpand\ \$from\]\ c2\ \[trExpand\ \$to\]\ \{\n\ \ \ \ \ \ \ lappend\ mapping\ \$c1\ \$c2\n\ \ \ \ \}\n\ \ \ \ return\ \[string\ map\ \$mapping\ \$string\]\n\}\n\n#\ This\ helper\ procedure\ takes\ a\ string\ of\ characters\ like\ A-F0-9_\ and\ expands\ it\ to\ a\ list\ of\ characters\ like\ \{A\ B\ C\ D\ E\ F\ 0\ 1\ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9\ _\}\n\nproc\ trExpand\ \{\ chars\ \}\ \{\n\ \ \ \ set\ state\ noHyphen\n\ \ \ \ set\ result\ \[list\]\n\ \ \ \ foreach\ c\ \[split\ \$chars\ \{\}\]\ \{\n\ \ \ \ \ \ \ switch\ -exact\ --\ \$state\ \{\n\ \ \ \ \ \ \ \ \ \ \ noHyphen\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ lastChar\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ state\ wantHyphen\n\ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ wantHyphen\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\ \[string\ equal\ -\ \$c\]\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ state\ sawHyphen\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ lastChar\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \$c\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ sawHyphen\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scan\ \$lastChar\ %c\ from\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ incr\ from\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ scan\ \$c\ %c\ to\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\ \$from\ >\ \$to\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ error\ \"\$lastChar\ does\ not\ precede\ \$c.\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ \{\ set\ i\ \$from\ \}\ \{\ \$i\ <=\ \$to\ \}\ \{\ incr\ i\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ result\ \[format\ %c\ \$i\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ state\ noHyphen\n\ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ if\ \{\ \[string\ equal\ sawHyphen\ \$state\]\ \}\ \{\n\ \ \ \ \ \ \ lappend\ result\ -\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n\ \n#\ The\ following\ call\ shows\ that\ rot13\ works\n\nputs\ \[tr\ A-Za-z\ N-ZA-Mn-za-m\ \{Guvf\ vf\ n\ grfg\}\]\n\n#\ The\ following\ call\ shows\ the\ use\ of\ tr\ to\ eliminate\ certain\ characters\ \n\nputs\ \[tr\ A-Z\ \{\}\ \{THISthis\ ISis\ Aa\ TESTtest\}\]\n======\n\n----\n\nThere\ are\ at\ least\ two\ other\ ways\ to\ achieve\ tr\ worth\ mentioning\ \[TclX\]\nimplements\ it,\ and\ if\ tr\ is\ available\ externally,\ it's\ quick\ to\ write\n\n======\nproc\ tr\ \{\ from\ to\ string\ \}\ \{\n\ \ \ \ return\ \[exec\ tr\ \$from\ \$to\ <<\ \$string\]\n\}\n======\n\n**\ wc\ **\n\nThe\ following\ implements\ the\ default\ behavior\ of\ '''wc''',\ i.e.\ when\ called\nwithout\ any\ flags.\n\n======\nproc\ wc\ \{filename\}\ \{\n\ \ \ \ foreach\ i\ \{l\ w\ c\}\ \{\n\ \ \ \ \ \ \ \ set\ \$i\ 0\n\ \ \ \ \}\n\n\ \ \ \ set\ f\ \[open\ \$filename\]\n\n\ \ \ \ while\ true\ \{\n\ \ \ \ \ \ \ \ set\ txt\ \[gets\ \$f\]\n\ \ \ \ \ \ \ \ if\ \[eof\ \$f\]\ break\n\n\ \ \ \ \ \ \ \ incr\ l\n\ \ \ \ \ \ \ \ incr\ w\ \[regexp\ -all\ \{\[^\[:space:\]\]+\}\ \$txt\]\n\ \ \ \ \ \ \ \ incr\ c\ \[expr\ \{\[string\ length\ \$txt\]\ +\ 1\}\]\n\ \ \ \ \}\n\n\ \ \ \ close\ \$f\n\ \ \ \ return\ \[list\ \$l\ \$w\ \$c\]\n\}\n======\n\n**\ Debugging\ **\n\n======\nproc\ Exec\ \{args\}\ \{\n\ \ puts\ stderr\ \$args\n\ \ eval\ exec\ \$args\n\}\n======\n\n''DKF:''\ If\ you\ want\ to\ do\ more\ advanced\ debugging\ (like\ determining\ exactly\nhow\ a\ piece\ of\ code\ is\ compiled\ and\ executed)\ then\ it\ is\ more\ easily\ done\ using\nthe\ following\ script:\n\n======\nproc\ tracedEval\ \{script\ \{execLevel\ 3\}\ \{compileLevel\ 2\}\}\ \{\n\ \ \ \ global\ tcl_traceCompile\ tcl_traceExec\ errorCode\ errorInfo\n\n\ \ \ \ #\ Set\ the\ debugging\ levels\n\ \ \ \ set\ tcl_traceCompile\ \$compileLevel\n\ \ \ \ set\ tcl_traceExec\ \$execLevel\n\n\ \ \ \ #\ Execute\ the\ script,\ handling\ any\ failures\n\ \ \ \ set\ code\ \[catch\ \{uplevel\ \$script\}\ msg\]\n\n\ \ \ \ #\ Restore\ the\ debugging\ levels\ to\ normal\ running.\n\ \ \ \ #\ I\ assume\ that\ you\ normally\ have\ these\ vars\ set\ to\ 0\n\ \ \ \ set\ tcl_traceExec\ 0\n\ \ \ \ set\ tcl_traceCompile\ 0\n\n\ \ \ \ #\ Pass\ on\ all\ errors\ thrown\ in\ the\ script\ to\ our\ caller\n\ \ \ \ return\ -code\ \$code\ -errorcode\ \$errorCode\ -errorinfo\ \$errorInfo\ \$msg\n\}\n======\n\nPlease\ note\ that\ you\ only\ get\ results\ if\ you\ have\ a\ real\ console\ attached.\ \ On\nsome\ platforms,\ this\ is\ a\ pain...\n\n\n**\ Tk\ Events\ **\n\n—\ especially\ ''keypress''\ events\n\nThis\ little\ script\ will\ echo\ all\ keyboard\ events\ to\ stdout:\n\n======\nbind\ .\ <KeyPress>\ \{\n\ \ \ \ set\ dec\ \"\"\;\ scan\ %A\ %%c\ dec\n\ \ \ \ puts\ \"keysym:%K\ prints:%A\ (\$dec)\"\n\}\ \;#--------------\ and\ to\ turn\ this\ off\ again:\nbind\ .\ <KeyPress>\ \{\}\n======\n\nThis\ proc\ will\ bind\ a\ new\ event\ to\ \".\".\ \ It\ can\ show\ you\ when\ mouse\ events\noccur,\ if\ you\ bind\ it\ to\ things\ like\ Enter\ or\ Motion.\n\n======\nproc\ unk\ \{e\}\ \{bind\ .\ <\$e>\ \"puts\ \$e\"\}\n======\n\n----\n\nIf\ you\ have\ an\ event\ driven\ program,\ end\ it\ with\ tclx\ mainloop.\n\nThen\ you\ can\n\n======none\ntcl>\ source\ program.tcl\n======\n\n(churnchurnchurn)\n\n======none\ntcl>\ \n======\n\nYou\ have\ an\ event\ driven\ command\ prompt\ while\ the\ program\ is\ running.\ \ You\ can\ndump\ arrays,\ invoke\ routines,\ run\ profile,\ all\ sorts\ of\ things.\ \ Mainloop\ is\nsmart\ enough\ so\ that\ when\ you\ run\ it\ stand-alone\n\n======\ntcl\ program.tcl\n======\n\nIt\ does\ the\ right\ thing.\n\nMay\ all\ your\ programs\ be\ event\ driven.\n\n\[DKF\]:\ \ Note\ that\ people\ running\ wish\ on\ Unix\ platforms\ can\ simply\ use\ \[\[send\]\]\nas\ a\ way\ to\ attach\ a\ console\ to\ a\ running\ Tcl/Tk\ program.\ \ The\ distributed\ demo\nscript,\ ''rmt''\ does\ this,\ (and\ is\ perfectly\ adequate\ for\ a\ lot\ use),\ or\ you\ncould\ use\ Jeff\ Hobbs's\ \[http://tkcon.sourceforge.net%|%tkcon%|%\]\ which\ is\ more\nsophisticated.\n\nJDG:\ \ If\ you\ want\ a\ very\ simple\ command\ line,\ you\ can\ also\ use\ the\ interp.tcl\nscript\ for\ the\ plain-text\ interface\ to\n\[http://www.jstrack.org/jstrack/%|%JStrack%|%\],\ which\ hasn't\ been\ touched\ for\nalmost\ a\ decade.\ \ Download\ the\ JStrack\ source\ from\ jstrack.org\ and\ look\ in\ the\ntracker/lib\ directory.\ \ ''interp.tcl''\ is\ there.\ \ This\ is\ part\ of\ JStrack\ (a\nvery\ ancient\ part,\ I\ might\ add),\ and\ was\ originally\ provided\ by\ Jeff\ Hobbs,\nwith\ a\ lot\ of\ help\ from\ Brent\ Welch\ (et\ al)\ in\ expanding\ it.\ \ Just\ source\ it\ as\nthe\ *LAST*\ line\ in\ your\ script.\n\nJDG\ 2010-06-25:\ \ FWIW,\ I\ now\ use\ Jeff\ Hobbs's\ tkcon.tcl\ and\ the\ tkcon_wrap.tcl\n...\ and\ really\ need\ to\ update\ JStrack\ to\ use\ these,\ as\ well.\n\n\n**\ Re-encoding\ strings\ **\n\nIf\ (in\ tcl\ 8.1\ or\ above)\ tcl\ has\ misinterpreted\ the\ charset\ of\ some\ string\ngotten\ from\ an\ external\ program\ or\ system\ function,\ and\ you\ are\ left\ with\ a\nstring\ with\ Latin-1\ accented\ characters\ (\\u0080-\\u00FF)\ instead\ of\ your\nlanguage\ letters,\ you\ can\ fix\ the\ string\ using\n\n======\nset\ fixed_string\ \[encoding\ convertfrom\ \$right_encoding\ \[encoding\ convertto\ \$wrongencoding\ \$string\]\]\n======\n\nwhere\ variable\ `\$right_encoding`\ contains\ the\ name\ of\ the\ encoding\ string\nreally\ had\ (typically\ same\ as\ your\ encoding\ system)\ and\ wrong_encoding\ is\nencoding\ tcl\ assumed\ string\ has\ (typically\ iso8859-1).\ \n\n\n**\ Re-encoding\ files\ **\n\nHere's\ a\ unix-style\ filter\ that\ reencodes\ text.\n\n======\n#!\ /usr/bin/tclsh\n#\ (or\ whatever\ incantation\ works\ for\ you)\n\nproc\ main\ \{fromTransl\ fromEnc\ toTransl\ toEnc\}\ \{\n\ \ \ \ fconfigure\ stdin\ -translation\ \$fromTransl\ -encoding\ \$fromEnc\n\ \ \ \ fconfigure\ stdout\ -translation\ \$toTransl\ -encoding\ \$toEnc\n\ \ \ \ fcopy\ stdin\ stdout\n\}\nmain\ \{*\}\$argv\ \;\ #\ Leverage\ error\ thrown\ by\ procs\ for\ reminder\ of\ correct\ syntax\n======\n\nExamples:\n\n======\ncat\ macClassicFile.txt\ |\ ''scriptname''\ cr\ macRoman\ lf\ utf-8\ >macOSXFile.txt\ncat\ macOSXFile.txt\ |\ ''scriptname''\ lf\ utf-8\ cr\ macRoman\ >macClassicFile.txt\n======\n\n\n**\ Advanced\ split\ **\n\nIf\ you\ need\ to\ split\ string\ into\ list\ using\ some\ more\ complicated\ rule\ than\nbuiltin\ split\ command\ allows,\ use\ following\ function\n\n======\nproc\ xsplit\ \[list\ str\ \[list\ regexp\ \"\\\[\\t\ \\r\\n\\\]+\"\]\]\ \{\n\ \ \ \ set\ list\ \ \{\}\n\ \ \ \ while\ \{\[regexp\ -indices\ --\ \$regexp\ \$str\ match\ submatch\]\}\ \{\n\ \ \ \ \ \ \ lappend\ list\ \[string\ range\ \$str\ 0\ \[expr\ \[lindex\ \$match\ 0\]\ -1\]\]\n\ \ \ \ \ \ \ if\ \{\[lindex\ \$submatch\ 0\]>=0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ lappend\ list\ \[string\ range\ \$str\ \[lindex\ \$submatch\ 0\]\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[lindex\ \$submatch\ 1\]\]\ \n\ \ \ \ \ \ \ \}\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ set\ str\ \[string\ range\ \$str\ \[expr\ \[lindex\ \$match\ 1\]+1\]\ end\]\ \n\ \ \ \ \}\n\ \ \ \ lappend\ list\ \$str\n\ \ \ \ return\ \$list\n\}\n======\n\ncary:\ \ It\ mimics\ Perl\ split\ operator\ which\ allows\ regexp\ as\ element\ separator,\ but,\nlike\ builtin\ split,\ it\ expects\ string\ to\ split\ as\ first\ arg\ and\ regexp\ as\nsecond\ (optional).\n\nBy\ default,\ it\ splits\ by\ any\ amount\ of\ whitespace.\n\nNote\ that\ if\ you\ add\ parenthesis\ into\ regexp,\ parenthesed\ part\ of\ separator\nwould\ be\ added\ into\ list\ as\ additional\ element.\ Just\ like\ in\ Perl.\n\n\n**\ Simple\ socket\ communication\ **\n\nVolker:\ \ The\ beauty\ of\ scripting\ lies\ (a.o.)\ in\ the\ fact\ that\ you\ can\ have\ lots\nof\ little\ programs\ cooperating\ with\ each\ other.\ For\ this,\ a\ simple\ means\ of\ncommunication\ is\ necessary.\ This\ simple\ server\ (and\ even\ simpler\ client)\ show\nhow\ it\ works:\n\n''Server:''\n\n======\n#!/bin/sh\n#\ \\\nexec\ tclsh\ \"\$0\"\ \"\$@\"\nproc\ serveConnection\ \{Handle\}\ \{\n\ \ \ \ set\ LineLength\ \[gets\ \$Handle\ Line\]\n\ \ \ \ if\ \{\$LineLength>=0\}\ \{\n\ \ \ \ \ \ \ \ #This\ is\ where\ you\ finally\ can\ do\ something\ with\ the\ data.\n\ \ \ \ \ \ \ \ #We\ simply\ put\ it\ back\ where\ it\ came\ from.\n\ \ \ \ \ \ \ \ puts\ \$Handle\ \"Received:\ \$Line\"\;\ flush\ \$Handle\ \n\ \ \ \ \}\ elseif\ \{\[eof\ \$Handle\]\}\ \{\n\ \ \ \ \ \ \ \ catch\ \{close\ \$Handle\}\n\ \ \ \ \}\n\}\nproc\ acceptConnections\ \{ConnectionFileHandle\ ClientAddress\ ClientPort\}\ \{\n\ \ \ \ fconfigure\ \$ConnectionFileHandle\ -blocking\ 0\n\ \ \ \ fileevent\ \$ConnectionFileHandle\ readable\ \[list\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ catch\ \[list\ serveConnection\ \$ConnectionFileHandle\]\]\n\}\nsocket\ -server\ acceptConnections\ 2000\nvwait\ Dummyvariable\n======\n\nThe\ server\ above\ is\ good\ enough\ for\ single\ line\ requests.\ It\ handles\ all\ the\ninteraction\ between\ gets,\ eof\ and\ fileevent\ correctly\ (IMHO)\ and\ can\ certainly\nserve\ several\ connections\ at\ once.\ It\ can\ cope\ with\ clients\ closing\ their\nsockets\ at\ any\ time.\n\nIf\ you\ don't\ specify\ the\ port\ number\ explicitly\ (2000\ in\ this\ case),\ but\nspecify\ 0,\ the\ socket\ finds\ the\ first\ free\ port.\ You\ can\ then\ ask\ the\ handle\nfor\ its\ port\ number\ and\ try\ to\ get\ it\ to\ your\ clients.\ for\ instance\ by\ writing\nit\ into\ a\ file\ or\ something.\n\nThe\ handle\ is\ the\ (ignored\ above)\ return\ value\ of\ the\ socket\ command.\n\n''Client:''\n\n======\n#!/bin/sh\n#\ \\\nexec\ tclsh\ \"\$0\"\ \"\$@\"\n\nset\ Handle\ \[socket\ localhost\ 2000\]\nputs\ -nonewline\ \$Handle\ \"Hello\"\;\ flush\ \$Handle\ \nputs\ \$Handle\ \"\ Dolly\"\;\ flush\ \$Handle\ \nputs\ \[gets\ \$Handle\]\nclose\ \$Handle\ \n======\n\nThe\ client\ demonstrates\ that\ the\ server\ does\ indeed\ accumulate\ a\ complete\ line\nfirst,\ before\ it\ gets\ processed.\ the\ magic\ behavior\ of\ gets\ is\ largely\nresponsible\ for\ that,\ which\ makes\ the\ server\ so\ simple.\n\nWell,\ that's\ it!\ :-)\n\n----\n\nPelle\ Otterholm:\ Here\ is\ another\ version\ of\ the\ server\ part\ that\ you\ might\ want\nto\ use.\n\n======\n#!/usr/bin/env\ tclsh\n\nproc\ done\ \{\}\ \{\ set\ ::done\ 1\ \}\n\nproc\ process\ \{fd\ ip\ port\}\ \{\n\ \ \ \ if\ \{!(\[eof\ \$fd\]\ ||\ \[catch\ \{gets\ \$fd\ line\ \}\])\ \}\ \{\n\ \ \ \ \ \ \ \ if\ \{\[string\ length\ \$line\]\ ==\ 0\}\ \{\ return\ \}\n\ \ \ \ \ \ \ \ if\ \{\[string\ match\ exit\ \$line\]\}\ \{\ close\ \$fd\ \;\ return\ \}\n\ \ \ \ \ \ \ \ if\ \{\[string\ match\ done\ \$line\]\}\ \{\ close\ \$fd\ \;\ done\ \;\ return\ \}\n\ \ \ \ \ \ \ \ puts\ \$fd\ \"input\ :\ \$line\"\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ catch\ \{\ close\ \$fd\ \}\n\ \ \ \ \}\n\}\n\nproc\ accept\ \{fd\ ip\ port\}\ \{\n\ \ \ \ fconfigure\ \$fd\ -blocking\ 0\ -buffering\ line\n\ \ \ \ fileevent\ \$fd\ readable\ \[list\ process\ \$fd\ \$ip\ \$port\]\n\}\nproc\ listen\ \{port\}\ \{\n\ \ \ \ socket\ -myaddr\ 127.0.0.1\ -server\ accept\ \$port\n\ \ \ \ vwait\ done\n\}\n\nlisten\ 2000\n======\n\n\[AMG\]:\ \ Shouldn't\ the\ \[\[\[eof\]\]\]\ come\ ''after''\ the\ \[\[\[gets\]\]\]?\ \ \ The\ \[\[eof\]\]\nman\ page\ \[http://www.tcl.tk/man/tcl8.6/TclCmd/eof.htm\]\ says:\n\n\"Returns\ 1\ if\ an\ end\ of\ file\ condition\ occurred\ during\ the\ most\ recent\ input\noperation\ on\ ''channelId''\ (such\ as\ '''gets'''),\ 0\ otherwise.\"\n\nAlso,\ the\ return\ value\ of\ \[\[gets\]\]\ should\ be\ checked\ so\ that\ you\ can\ndifferentiate\ between\ receiving\ a\ blank\ line\ and\ having\ an\ error\ or\nend-of-file.\ \ Two-argument\ \[\[gets\]\]\ will\ return\ -1\ on\ error\ and\ end-of-file\n(use\ \[\[eof\]\]\ to\ tell\ the\ difference),\ 0\ on\ blank\ line\ or\ no-data-available\n(when\ the\ channel\ is\ nonblocking\;\ use\ \[\[\[fblocked\]\]\]\ to\ test\ this).\n\nPelle\ Otterholm:\ \ the\ code\ is\ based\ on\ same\ coding\ idea\ as\ \[Simple\ TCP/IP\ proxy\],\ also\ changed\ to\ line\ buffering\ and\ move\ gets\ \$fd\ file\ into\ the\ check,\ getting\ :\ \"`if\ \{!(\[\[eof\ \$fd\]\]\ ||\ \[\[catch\ \{gets\ \$fd\}\]\])\ \}`\"\n\n----\n\n\[DKF\]:\ \ There\ is\ a\ more\ advanced\ version\ of\ this\ on\ the\ \[telnet\]\ page.\n\n\[SDW\]:\ \ has\ put\ together\ an\ example\ of\ \[Remote\ Script\ Execution\]\ using\ safe\ninterpreters.\n\n----\n\n\ \ \ *\ \[A\ Server\ Template\]\n\n----\n\nCheck\ out\ the\ verbose_eval\ script\ over\ on\ \[eval\]\ page!\n\n<<categories>>\ Example} CALL {my revision {Example Scripts Everybody Should Have}} CALL {::oo::Obj1014752 process revision/Example+Scripts+Everybody+Should+Have} CALL {::oo::Obj1014750 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4