diff options
author | Steve Bennett <steveb@workware.net.au> | 2010-10-26 10:09:57 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2010-12-02 09:04:54 +1000 |
commit | 064ec299a9f7b1016ed7c24e5a014d94271281b3 (patch) | |
tree | 65925898533b35a1e730f0dfb5eee57de7c5328a | |
parent | d160ac7e0cdd776e46c502ab1ad33aa5366acc99 (diff) | |
download | jimtcl-064ec299a9f7b1016ed7c24e5a014d94271281b3.zip jimtcl-064ec299a9f7b1016ed7c24e5a014d94271281b3.tar.gz jimtcl-064ec299a9f7b1016ed7c24e5a014d94271281b3.tar.bz2 |
Add the [exists] command
Especially simplifies checking for the existence of procs.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | Tcl_shipped.html | 38 | ||||
-rw-r--r-- | jim.c | 46 | ||||
-rw-r--r-- | jim_tcl.txt | 12 | ||||
-rw-r--r-- | tests/exists.test | 78 |
4 files changed, 162 insertions, 12 deletions
diff --git a/Tcl_shipped.html b/Tcl_shipped.html index b0a1f85..a7baa5a 100644 --- a/Tcl_shipped.html +++ b/Tcl_shipped.html @@ -726,6 +726,11 @@ Add <em>info channels</em> The <em>bio</em> extension is gone. Now <em>aio</em> supports <em>copyto</em>.
</p>
</li>
+<li>
+<p>
+Add <em>exists</em> command
+</p>
+</li>
</ol></div>
<div class="paragraph"><p>Since v0.62:</p></div>
<div class="olist arabic"><ol class="arabic">
@@ -2713,6 +2718,7 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_exec">exec</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_exists">exists</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_exit">exit</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_expr">expr</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_file">file</a></p></td>
@@ -2720,9 +2726,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_flush">flush</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_for">for</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_foreach">foreach</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_format">format</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_format">format</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_getref">getref</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_gets">gets</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_glob">glob</a></p></td>
@@ -2730,9 +2736,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_if">if</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_incr">incr</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_info">info</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_join">join</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_join">join</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_kill">kill</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lambda">lambda</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lappend">lappend</a></p></td>
@@ -2740,9 +2746,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_lindex">lindex</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_linsert">linsert</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_list">list</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_llength">llength</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_llength">llength</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lmap">lmap</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_load">load</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_local">local</a></p></td>
@@ -2750,9 +2756,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_lrepeat">lrepeat</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lreplace">lreplace</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lreverse">lreverse</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_lsearch">lsearch</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_lsearch">lsearch</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lset">lset</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_lsort">lsort</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_open">open</a></p></td>
@@ -2760,9 +2766,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#cmd_1">os.gethostname</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#cmd_1">os.getids</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#cmd_1">os.uptime</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#cmd_1">os.wait</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1">os.wait</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_package">package</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_pid">pid</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#cmd_1">posix</a></p></td>
@@ -2770,9 +2776,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_puts">puts</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_pwd">pwd</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_rand">rand</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_range">range</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_range">range</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_read">read</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_ref">ref</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_regexp">regexp</a></p></td>
@@ -2780,9 +2786,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_rename">rename</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_return">return</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_scan">scan</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_seek">seek</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_seek">seek</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_set">set</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_setref">setref</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_signal">signal</a></p></td>
@@ -2790,9 +2796,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_socket">socket</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_source">source</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_split">split</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_stackdump">stackdump</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_stackdump">stackdump</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_stacktrace">stacktrace</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_string">string</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_subst">subst</a></p></td>
@@ -2800,9 +2806,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#_syslog">syslog</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_tailcall">tailcall</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_tell">tell</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#_throw">throw</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#_throw">throw</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_time">time</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_try">try</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_unknown">unknown</a></p></td>
@@ -2810,9 +2816,9 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"><a href="#cmd_2">update</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_uplevel">uplevel</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_upvar">upvar</a></p></td>
-<td align="left" valign="top"><p class="table"><a href="#cmd_2">vwait</a></p></td>
</tr>
<tr>
+<td align="left" valign="top"><p class="table"><a href="#cmd_2">vwait</a></p></td>
<td align="left" valign="top"><p class="table"><a href="#_while">while</a></p></td>
<td align="left" valign="top"><p class="table"></p></td>
<td align="left" valign="top"><p class="table"></p></td>
@@ -2820,7 +2826,6 @@ cellspacing="0" cellpadding="4"> <td align="left" valign="top"><p class="table"></p></td>
<td align="left" valign="top"><p class="table"></p></td>
<td align="left" valign="top"><p class="table"></p></td>
-<td align="left" valign="top"><p class="table"></p></td>
</tr>
</tbody>
</table>
@@ -3533,6 +3538,15 @@ option in <em>catch</em>) will be set to a list, as follows:</p></div> this variable is unset, in which case the original environment is used).</p></div>
</div>
<div class="sect2">
+<h3 id="_exists">exists</h3>
+<div class="paragraph"><p><tt><strong>exists ?-var|-proc|-command?</strong> <em>name</em></tt></p></div>
+<div class="paragraph"><p>Checks the existence of the given variable, procedure or command
+respectively and returns 1 if it exists or 0 if not. This command
+provides a more simplified/convenient version of <em>info exists</em>,
+<em>info procs</em> and <em>info commands</em>.</p></div>
+<div class="paragraph"><p>If the type is omitted, a type of <em>-var</em> is used. The type may be abbreviated.</p></div>
+</div>
+<div class="sect2">
<h3 id="_exit">exit</h3>
<div class="paragraph"><p><tt><strong>exit</strong> <em>?returnCode?</em></tt></p></div>
<div class="paragraph"><p>Terminate the process, returning <strong>returnCode</strong> to the
@@ -6806,7 +6820,7 @@ official policies, either expressed or implied, of the Jim Tcl Project.</tt></pr <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Last updated 2010-11-15 11:22:37 EST
+Last updated 2010-11-22 20:39:26 EST
</div>
</div>
</body>
@@ -12995,6 +12995,51 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg return JIM_OK; } +/* [exists] */ +static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + static const char * const options[] = { + "-command", "-proc", "-var", NULL + }; + enum + { + OPT_COMMAND, OPT_PROC, OPT_VAR + }; + int option; + + if (argc == 2) { + option = OPT_VAR; + objPtr = argv[1]; + } + else if (argc == 3) { + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + objPtr = argv[2]; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?option? name"); + return JIM_ERR; + } + + /* Test for the the most common commands first, just in case it makes a difference */ + switch (option) { + case OPT_VAR: + Jim_SetResultBool(interp, Jim_GetVariable(interp, objPtr, 0) != NULL); + break; + + case OPT_COMMAND: + case OPT_PROC: { + Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); + Jim_SetResultBool(interp, cmd != NULL && (option == OPT_COMMAND || !cmd->cmdProc)); + break; + } + } + return JIM_OK; +} + /* [split] */ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -13501,6 +13546,7 @@ static const struct { {"dict", Jim_DictCoreCommand}, {"subst", Jim_SubstCoreCommand}, {"info", Jim_InfoCoreCommand}, + {"exists", Jim_ExistsCoreCommand}, {"split", Jim_SplitCoreCommand}, {"join", Jim_JoinCoreCommand}, {"format", Jim_FormatCoreCommand}, diff --git a/jim_tcl.txt b/jim_tcl.txt index 0834a57..737485a 100644 --- a/jim_tcl.txt +++ b/jim_tcl.txt @@ -64,6 +64,7 @@ Since v0.63: 2. Add aio '$handle filename' 3. Add 'info channels' 4. The 'bio' extension is gone. Now 'aio' supports 'copyto'. +5. Add 'exists' command Since v0.62: @@ -2059,6 +2060,17 @@ option in 'catch') will be set to a list, as follows: The environment for the executed command is set from $::env (unless this variable is unset, in which case the original environment is used). +exists +~~~~~~ ++*exists ?-var|-proc|-command?* 'name'+ + +Checks the existence of the given variable, procedure or command +respectively and returns 1 if it exists or 0 if not. This command +provides a more simplified/convenient version of 'info exists', +'info procs' and 'info commands'. + +If the type is omitted, a type of '-var' is used. The type may be abbreviated. + exit ~~~~ +*exit* '?returnCode?'+ diff --git a/tests/exists.test b/tests/exists.test new file mode 100644 index 0000000..ae35a87 --- /dev/null +++ b/tests/exists.test @@ -0,0 +1,78 @@ +source [file dirname [info script]]/testing.tcl + +needs cmd exists + +test exists-1.1 "Exists var" { + set a 1 + exists a +} 1 + +test exists-1.1 "Exists var" { + unset -nocomplain b + exists b +} 0 + +test exists-1.1 "Exists -var" { + exists -var a +} 1 + +test exists-1.1 "Exists -var" { + exists -var b +} 0 + +test exists-1.1 "Exists in proc" { + proc a {name} { exists $name } + a ::a +} 1 + +test exists-1.1 "Exists in proc" { + a ::b +} 0 + +test exists-1.1 "Exists in proc" { + a name +} 1 + +test exists-1.1 "Exists in proc" { + a none +} 0 + +test exists-1.1 "Exists -proc" { + exists -proc a +} 1 + +test exists-1.1 "Exists -proc" { + exists -proc bogus +} 0 + +test exists-1.1 "Exists -proc" { + exists -proc info +} 0 + +test exists-1.1 "Exists -command" { + exists -command a +} 1 + +test exists-1.1 "Exists -command" { + exists -command info +} 1 + +test exists-1.1 "Exists -command" { + exists -command bogus +} 0 + +test exists-1.1 "Exists local lambda after exit" { + proc a {} { + local lambda {} {dummy} + } + exists -proc [a] +} 0 + +test exists-1.1 "Exists local lambda" { + proc a {} { + exists -proc [local lambda {} {dummy}] + } + a +} 1 + +testreport |