Struct tcl::interp::Interpreter
source · pub struct Interpreter(/* private fields */);
Expand description
Tcl interpeter which has ownership.
Implementations§
source§impl Interpreter
impl Interpreter
sourcepub fn new() -> Result<Self, Enum2<NullInterp, TclInitError>>
pub fn new() -> Result<Self, Enum2<NullInterp, TclInitError>>
Creates a Tcl interpeter.
sourcepub fn into_raw_non_null(self) -> NonNull<Tcl_Interp>
pub fn into_raw_non_null(self) -> NonNull<Tcl_Interp>
Consumes the interpreter, returning a wrapped raw nonnull pointer.
Methods from Deref<Target = Interp>§
pub fn after_ms(&self, ms: c_int) -> Result<(), InterpError>
sourcepub fn after<Scripts, Tag>(
&self,
ms: c_int,
scripts: Scripts
) -> Result<Obj, InterpError>where
Scripts: IntoHomoTuple<Obj> + NonZeroLen<Tag>,
<Scripts as IntoHomoTuple<Obj>>::Output: Into<Obj>,
pub fn after<Scripts, Tag>(
&self,
ms: c_int,
scripts: Scripts
) -> Result<Obj, InterpError>where
Scripts: IntoHomoTuple<Obj> + NonZeroLen<Tag>,
<Scripts as IntoHomoTuple<Obj>>::Output: Into<Obj>,
In this form the command returns immediately, but it arranges for a Tcl command to be executed ms milliseconds later as an event handler. The command will be executed exactly once, at the given time. The delayed command is formed by concatenating all the script arguments in the same fashion as the concat command. The command will be executed at global level (outside the context of any Tcl procedure). If an error occurs while executing the delayed command then the background error will be reported by the command registered with interp bgerror. The after command returns an identifier that can be used to cancel the delayed command using after cancel.
§Example
use tcl::*;
use tuplex::*;
let interp = Interpreter::new().unwrap();
interp.eval( "set ::foo 1; set ::bar 2;" )?;
tclfn!( interp, cmd: "set_foo", fn set_foo() -> TclResult<()> {
let interp = tcl_interp!();
interp.set( "foo", 3 );
Ok(())
});
tclfn!( interp, cmd: "set_bar", fn set_bar() -> TclResult<()> {
let interp = tcl_interp!();
interp.set( "bar", 4 );
Ok(())
});
interp.after( 1000, ( "set_foo", ))?;
interp.after( 1000, ( "set_bar", ))?;
unsafe{ clib::Tcl_DoOneEvent( 0 ); }
assert_eq!( interp.get_int("foo")?, 3 );
assert_eq!( interp.get_int("bar")?, 4 );
pub fn after_cancel_id(&self, id: impl Into<Obj>) -> Result<(), InterpError>
pub fn after_cancel<Scripts, Tag>(
&self,
scripts: Scripts
) -> Result<(), InterpError>where
Scripts: IntoHomoTuple<Obj> + NonZeroLen<Tag>,
<Scripts as IntoHomoTuple<Obj>>::Output: Into<Obj>,
pub fn after_idle<Scripts, Tag>(
&self,
scripts: Scripts
) -> Result<(), InterpError>where
Scripts: IntoHomoTuple<Obj> + NonZeroLen<Tag>,
<Scripts as IntoHomoTuple<Obj>>::Output: Into<Obj>,
pub fn after_info_id(&self, id: Obj) -> Result<Obj, InterpError>
pub fn after_info(&self) -> Result<Vec<Obj>, Enum2<InterpError, NotList>>
sourcepub fn as_ptr(&self) -> *mut Tcl_Interp
pub fn as_ptr(&self) -> *mut Tcl_Interp
Obtains a raw pointer, required in Tcl’s C API.
sourcepub fn error(&self) -> InterpError
pub fn error(&self) -> InterpError
Returns the result and options of interpreter as an error.
sourcepub fn eval(&self, code: impl Into<Obj>) -> Result<Obj, InterpError>
pub fn eval(&self, code: impl Into<Obj>) -> Result<Obj, InterpError>
Executes the code
until either an error occurs or the end of the script is reached.
Returns a value stored in obj on success.
sourcepub fn eval_with_flags(
&self,
code: impl Into<Obj>,
flags: c_int
) -> Result<Obj, InterpError>
pub fn eval_with_flags( &self, code: impl Into<Obj>, flags: c_int ) -> Result<Obj, InterpError>
Executes the code
until either an error occurs or the end of the script is reached.
Additional options can be specified using flags TCL_EVAL_GLOBAL
and TCL_EVAL_DIRECT
.
Set environment variable TCL_DISPLAY_RUNNING_COMMANDS to “stdout” or “stderr” to check what commands are running.
sourcepub fn run(&self, code: impl Into<Obj>) -> Result<(), InterpError>
pub fn run(&self, code: impl Into<Obj>) -> Result<(), InterpError>
Executes the code
until either an error occurs or the end of the script is reached.
Returns ()
on success.
Set environment variable TCL_DISPLAY_RUNNING_COMMANDS to “stdout” or “stderr” to check what commands are running.
sourcepub fn get(&self, var: impl Into<Obj>) -> Result<Obj, InterpError>
pub fn get(&self, var: impl Into<Obj>) -> Result<Obj, InterpError>
Reads the value of variable named var
defined in the interpreter.
sourcepub fn arr_get(
&self,
arr: impl Into<Obj>,
elem: impl Into<Obj>
) -> Result<Obj, InterpError>
pub fn arr_get( &self, arr: impl Into<Obj>, elem: impl Into<Obj> ) -> Result<Obj, InterpError>
Reads the value of elem
of array arr
defined in the interpreter.
sourcepub fn set(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
pub fn set(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
Sets the value of variable named lhs
defined in the interpreter to be rhs
.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
let x = Obj::from("{");
interpreter.set( "x", "{" );
assert_eq!( interpreter.get("x").unwrap().to_string(), "{" );
sourcepub fn set_list_elem(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
pub fn set_list_elem(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
Sets the value of variable named lhs
defined in the interpreter to be rhs
.
The value will be converted to a list element.
See https://www.tcl.tk/man/tcl/TclLib/SetVar.htm#M10 for more.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
interpreter.set_list_elem( "x", "{" );
assert_eq!( interpreter.get("x").unwrap().to_string(), "\\{" );
sourcepub fn arr_set(
&self,
arr: impl Into<Obj>,
elem: impl Into<Obj>,
rhs: impl Into<Obj>
) -> Obj
pub fn arr_set( &self, arr: impl Into<Obj>, elem: impl Into<Obj>, rhs: impl Into<Obj> ) -> Obj
Sets the value of elem
of array arr
defined in the interpreter, to be rhs
.
§Examples
use tcl::*;
let interp = Interpreter::new().unwrap();
interp.arr_set( "color", "red" , 0xff0000 );
interp.arr_set( "color", "green", 0x00ff00 );
interp.arr_set( "color", "blue" , 0x0000ff );
assert_eq!( interp.arr_get( "color", "red" ).unwrap().as_u32(), 0xff0000 );
assert_eq!( interp.arr_get( "color", "green" ).unwrap().as_u32(), 0x00ff00 );
assert_eq!( interp.arr_get( "color", "blue" ).unwrap().as_u32(), 0x0000ff );
tclfn!( &interp, fn rust_fn() -> TclResult<()> {
let interp = tcl_interp!();
assert_eq!( interp.arr_get( "color", "red" ).unwrap().as_u32(), 0xff0000 );
assert_eq!( interp.arr_get( "color", "green" ).unwrap().as_u32(), 0x00ff00 );
assert_eq!( interp.arr_get( "color", "blue" ).unwrap().as_u32(), 0x0000ff );
Ok(())
});
interp.run( "rust_fn" ).unwrap();
sourcepub fn arr_set_list_elem(
&self,
arr: impl Into<Obj>,
elem: impl Into<Obj>,
rhs: impl Into<Obj>
) -> Obj
pub fn arr_set_list_elem( &self, arr: impl Into<Obj>, elem: impl Into<Obj>, rhs: impl Into<Obj> ) -> Obj
Sets the value of elem
of array arr
defined in the interpreter, to be rhs
.
The value will be converted to a list element.
See https://www.tcl.tk/man/tcl/TclLib/SetVar.htm#M10 for more.
sourcepub fn append(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
pub fn append(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
Append value rhs
to the variable lhs
defined in the interpreter.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
interpreter.append( "x", 0 );
interpreter.append( "x", 0 );
assert_eq!( interpreter.get("x").unwrap().to_string(), "00" );
sourcepub fn append_list_elem(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
pub fn append_list_elem(&self, lhs: impl Into<Obj>, rhs: impl Into<Obj>) -> Obj
Append value rhs
to the variable lhs
defined in the interpreter.
The value will be converted to a list element.
See https://www.tcl.tk/man/tcl/TclLib/SetVar.htm#M10 for more.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
interpreter.append_list_elem( "x", 0 );
interpreter.append_list_elem( "x", 0 );
assert_eq!( interpreter.get("x").unwrap().to_string(), "0 0" );
sourcepub fn arr_append(
&self,
arr: impl Into<Obj>,
elem: impl Into<Obj>,
rhs: impl Into<Obj>
) -> Obj
pub fn arr_append( &self, arr: impl Into<Obj>, elem: impl Into<Obj>, rhs: impl Into<Obj> ) -> Obj
Append value rhs
to the variable elem
of array arr
, defined in the interpreter.
sourcepub fn arr_append_list_elem(
&self,
arr: impl Into<Obj>,
elem: impl Into<Obj>,
rhs: impl Into<Obj>
) -> Obj
pub fn arr_append_list_elem( &self, arr: impl Into<Obj>, elem: impl Into<Obj>, rhs: impl Into<Obj> ) -> Obj
Append value rhs
to the variable elem
of array arr
, defined in the interpreter.
The value will be converted to a list element.
See https://www.tcl.tk/man/tcl/TclLib/SetVar.htm#M10 for more.
sourcepub fn unset(&self, var_name: &str) -> Result<(), InterpError>
pub fn unset(&self, var_name: &str) -> Result<(), InterpError>
This command removes one variable named var_name
. If a name refers to an
element of an array then that element is removed without affecting the rest of
the array. If a name consists of an array name with no parenthesized index, then
the entire array is deleted. An error can occur when the named variable does not
exist, or the name refers to an array element but the variable is a scalar, or
the name refers to a variable in a non-existent namespace.
sourcepub fn unset_nocomplain(&self, var_name: &str)
pub fn unset_nocomplain(&self, var_name: &str)
This command removes one variable named var_name
. If a name refers to an
element of an array then that element is removed without affecting the rest of
the array. If a name consists of an array name with no parenthesized index, then
the entire array is deleted.
sourcepub fn arr_unset(
&self,
arr_name: &str,
elem_name: &str
) -> Result<(), InterpError>
pub fn arr_unset( &self, arr_name: &str, elem_name: &str ) -> Result<(), InterpError>
This command removes an element named elem_name
of an array named arr_name
.
An error can occur when the element does not exist, or the name refers to an
array element but the variable is a scalar, or the name refers to the array in a
non-existent namespace.
sourcepub fn arr_unset_nocomplain(&self, arr_name: &str, elem_name: &str)
pub fn arr_unset_nocomplain(&self, arr_name: &str, elem_name: &str)
This command removes an element named elem_name
of an array named arr_name
.
sourcepub fn boolean(&self, val: impl Into<Obj>) -> Result<bool, InterpError>
pub fn boolean(&self, val: impl Into<Obj>) -> Result<bool, InterpError>
Converts val
into a boolean value.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
assert_eq!( interpreter.boolean( false ).unwrap(), false );
assert_eq!( interpreter.boolean( true ).unwrap(), true );
assert_eq!( interpreter.boolean( 0 ).unwrap(), false );
assert_eq!( interpreter.boolean( 1 ).unwrap(), true );
assert_eq!( interpreter.boolean( 2 ).unwrap(), true );
assert_eq!( interpreter.boolean( "0" ).unwrap(), false );
assert_eq!( interpreter.boolean( "1" ).unwrap(), true );
assert_eq!( interpreter.boolean( "false" ).unwrap(), false );
assert_eq!( interpreter.boolean( "true" ).unwrap(), true );
assert_eq!( interpreter.boolean( "FaLsE" ).unwrap(), false );
assert_eq!( interpreter.boolean( "tRuE" ).unwrap(), true );
assert!( interpreter.boolean( "Trueman" ).is_err() );
sourcepub fn get_boolean(&self, var: impl Into<Obj>) -> Result<bool, InterpError>
pub fn get_boolean(&self, var: impl Into<Obj>) -> Result<bool, InterpError>
Gets boolean value of variable var
defined in the intepreter.
sourcepub fn int(&self, val: impl Into<Obj>) -> Result<c_int, InterpError>
pub fn int(&self, val: impl Into<Obj>) -> Result<c_int, InterpError>
Converts val
into a c_int
value.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
assert_eq!( interpreter.int( 0 ).unwrap(), 0 );
assert_eq!( interpreter.int( "0" ).unwrap(), 0 );
assert_eq!( interpreter.int( false ).unwrap(), 0 );
assert_eq!( interpreter.int( true ).unwrap(), 1 );
assert!( interpreter.int( "zero" ).is_err() );
sourcepub fn get_int(&self, var: impl Into<Obj>) -> Result<c_int, InterpError>
pub fn get_int(&self, var: impl Into<Obj>) -> Result<c_int, InterpError>
Gets c_int
value of variable var
defined in the intepreter.
sourcepub fn set_int(&self, lhs: impl Into<Obj>, rhs: c_int) -> Obj
pub fn set_int(&self, lhs: impl Into<Obj>, rhs: c_int) -> Obj
Sets the variable lhs
’s value to be rhs
, which is a c_int
.
sourcepub fn longlong(&self, val: impl Into<Obj>) -> Result<c_longlong, InterpError>
pub fn longlong(&self, val: impl Into<Obj>) -> Result<c_longlong, InterpError>
Converts val
into a c_longlong
value.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
assert_eq!( interpreter.longlong( 0 ).unwrap(), 0 );
assert_eq!( interpreter.longlong( "0" ).unwrap(), 0 );
assert_eq!( interpreter.longlong( false ).unwrap(), 0 );
assert_eq!( interpreter.longlong( true ).unwrap(), 1 );
assert!( interpreter.longlong( "zero" ).is_err() );
sourcepub fn get_longlong(
&self,
var: impl Into<Obj>
) -> Result<c_longlong, InterpError>
pub fn get_longlong( &self, var: impl Into<Obj> ) -> Result<c_longlong, InterpError>
Gets c_longlong
value of variable var
defined in the intepreter.
sourcepub fn set_longlong(&self, lhs: impl Into<Obj>, rhs: c_longlong) -> Obj
pub fn set_longlong(&self, lhs: impl Into<Obj>, rhs: c_longlong) -> Obj
Sets the variable lhs
’s value to be rhs
, which is a c_longlong
.
sourcepub fn double(&self, val: impl Into<Obj>) -> Result<c_double, InterpError>
pub fn double(&self, val: impl Into<Obj>) -> Result<c_double, InterpError>
Converts val
into a c_double
value.
§Examples
use tcl::*;
let interpreter = Interpreter::new().unwrap();
assert_eq!( interpreter.double( 0.0 ).unwrap(), 0.0 );
assert_eq!( interpreter.double( "0.0" ).unwrap(), 0.0 );
assert_eq!( interpreter.double( false ).unwrap(), 0.0 );
assert_eq!( interpreter.double( true ).unwrap(), 1.0 );
assert!( interpreter.double( "zero" ).is_err() );
sourcepub fn get_double(&self, var: impl Into<Obj>) -> Result<c_double, InterpError>
pub fn get_double(&self, var: impl Into<Obj>) -> Result<c_double, InterpError>
Gets c_double
value of variable var
defined in the intepreter.
sourcepub fn set_double(&self, lhs: impl Into<Obj>, rhs: c_double) -> Obj
pub fn set_double(&self, lhs: impl Into<Obj>, rhs: c_double) -> Obj
Sets the variable lhs
’s value to be rhs
, which is a c_double
.
sourcepub unsafe fn def_proc_with_client_data(
&self,
name: &str,
proc: ObjCmdProc,
data: ClientData,
deleter: Tcl_CmdDeleteProc
)
pub unsafe fn def_proc_with_client_data( &self, name: &str, proc: ObjCmdProc, data: ClientData, deleter: Tcl_CmdDeleteProc )
Registers Rust function proc
as a Tcl proc, with optional client data and destructor.
§Safety
According to https://doc.rust-lang.org/nomicon/ffi.html#ffi-and-panics,
a panic!
across an FFI boundary is undefined behavior.
Any user provided proc
should not panic!
.
However, a #[proc] fn
uses abort instead of panic, which is safe to register.
sourcepub unsafe fn def_proc(&self, name: &str, proc: ObjCmdProc)
pub unsafe fn def_proc(&self, name: &str, proc: ObjCmdProc)
Registers Rust function proc
as a Tcl proc, without client data nor destructor.
§Safety
According to https://doc.rust-lang.org/nomicon/ffi.html#ffi-and-panics,
a panic!
across an FFI boundary is undefined behavior.
Any user provided proc
should not panic!
.
However, a #[proc] fn
uses abort instead of panic, which is safe to register.
sourcepub fn package_load(
&self,
name: &str,
path: impl AsRef<Path>
) -> Result<Obj, InterpError>
pub fn package_load( &self, name: &str, path: impl AsRef<Path> ) -> Result<Obj, InterpError>
This command is typically invoked by Tcl code that wishes to use a particular version of a particular package. The arguments indicate which package is wanted, and the command ensures that a suitable version of the package is loaded into the interpreter. If the command succeeds, it returns the version number that is loaded; otherwise it generates an error.
Note: path
will be appended to auto_path
.
sourcepub fn package_provide(&self, name: &str, version: &str) -> c_int
pub fn package_provide(&self, name: &str, version: &str) -> c_int
This is equivalent to calling “package provide” with the specified package name and version.
sourcepub fn source(&self, path: impl AsRef<Path>) -> Result<Obj, InterpError>
pub fn source(&self, path: impl AsRef<Path>) -> Result<Obj, InterpError>
This command takes the contents of the specified file or resource and passes it to the Tcl interpreter as a text script. The return value from source is the return value of the last command executed in the script. If an error occurs in evaluating the contents of the script then the source command will return that error. If a return command is invoked from within the script then the remainder of the file will be skipped and the source command will return normally with the result from the return command.
The end-of-file character for files is “\32” (^Z) for all platforms. The source command will read files up to this character. This restriction does not exist for the read or gets commands, allowing for files containing code and data segments (scripted documents). If you require a “^Z” in code for string comparison, you can use “\032” or “\u001a”, which will be safely substituted by the Tcl interpreter into “^Z”.
A leading BOM (Byte order mark) contained in the file is ignored for unicode encodings (utf-8, unicode).
sourcepub fn make_safe(&self) -> Result<(), InterpError>
pub fn make_safe(&self) -> Result<(), InterpError>
Marks interp as “safe”, so that future calls to Interp::is_safe()
will return
true. It also removes all known potentially-unsafe core functionality (both
commands and variables) from interp. However, it cannot know what parts of an
extension or application are safe and does not make any attempt to remove those
parts, so safety is not guaranteed after calling Interp::make_safe()
. Callers
will want to take care with their use of Interp::make_safe()
to avoid false
claims of safety. For many situations, Interp::create_child()
may be a better
choice, since it creates interpreters in a known-safe state.
§Example
use tcl::*;
let interpreter = Interpreter::new().unwrap();
assert!( !interpreter.is_safe() );
interpreter.make_safe().unwrap();
assert!( interpreter.is_safe() );
sourcepub fn create_child(
&self,
name: &str,
is_safe: bool
) -> Result<Interpreter, NullInterp>
pub fn create_child( &self, name: &str, is_safe: bool ) -> Result<Interpreter, NullInterp>
Creates a new interpreter as a child of interp. It also creates a child command
named name
in interp which allows interp to manipulate the new child. If
is_safe
is false, the command creates a trusted child in which Tcl code has
access to all the Tcl commands. If it is true, the command creates a “safe”
child in which Tcl code has access only to set of Tcl commands defined as
“Safe Tcl”; see the manual entry for the Tcl interp command for details.
§Example
use tcl::*;
let interpreter = Interpreter::new().unwrap();
let unsafe_child = interpreter.create_child( "an_unsafe_child", false ).unwrap();
unsafe_child.run("puts {hello,world!}").unwrap(); // ok
let safe_child = interpreter.create_child( "a_safe_child", true ).unwrap();
assert!( safe_child.run("puts {hello,world!}").is_err() ); // safe interp not allowed to output
sourcepub unsafe fn get_child(&self, name: &str) -> Option<Interp>
pub unsafe fn get_child(&self, name: &str) -> Option<Interp>
Returns a child interp, which is identified by childName.
§Safety
Don’t access to the child Interp
after the dropping of child Interpreter
.
use tcl::*;
let interpreter = Interpreter::new().unwrap();
let child_interp;
{
let child_interpreter = interpreter.create_child( "a_child_interp", false ).unwrap();
child_interpreter.run("puts {hello,world!}").unwrap(); // ok
child_interp = unsafe{ interpreter.get_child( "a_child_interp" ).unwrap() };
child_interp.run("puts {hello,world!}").unwrap(); // ok
}
// DO NOT DO THIS: child_interp.run("puts {hello,world!}").unwrap(); // oops!
sourcepub unsafe fn get_parent(&self) -> Option<Interp>
pub unsafe fn get_parent(&self) -> Option<Interp>
Returns the parent interp.
§Safety
Don’t access to the parent Interp
after the dropping of parent Interpreter
.
use tcl::*;
let parent_interp;
{
let parent_interpreter = Interpreter::new().unwrap();
let child_interpreter = parent_interpreter.create_child( "a_child_interp", false ).unwrap();
parent_interp = unsafe{ child_interpreter.get_parent().unwrap() };
parent_interp.run("puts {hello,world!}").unwrap(); // ok
}
// DO NOT DO THIS: parent_interp.run("puts {hello,world!}").unwrap(); // oops!
sourcepub fn expose_command(
&self,
hidden_cmd_name: &str,
cmd_name: &str
) -> Result<(), InterpError>
pub fn expose_command( &self, hidden_cmd_name: &str, cmd_name: &str ) -> Result<(), InterpError>
Moves the command named hidden_cmd_name
from the set of hidden commands to the
set of exposed commands, putting it under the name cmd_name
. hidden_cmd_name
must be the name of an existing hidden command, or Err
will be returned.
cmd_name
already exists, the operation returns Err
. After executing this
command, attempts to use cmd_name
in any script evaluation mechanism will
again succeed.
use tcl::*;
let interpreter = Interpreter::new().unwrap();
interpreter.make_safe().unwrap();
assert!( interpreter.run("pwd").is_err() );
interpreter.expose_command( "pwd", "do_pwd" ).unwrap();
assert!( interpreter.run("do_pwd").is_ok() );
sourcepub fn hide_command(
&self,
cmd_name: &str,
hidden_cmd_name: &str
) -> Result<(), InterpError>
pub fn hide_command( &self, cmd_name: &str, hidden_cmd_name: &str ) -> Result<(), InterpError>
Moves the command named cmd_name
from the set of exposed commands to the set
of hidden commands, under the name hidden_cmd_name
. cmd_name
must be the
name of an existing exposed command, or Err
will be returned. Currently both
cmd_name
and hidden_cmd_name
must not contain namespace qualifiers, or Err
will be returned. The cmd_name
will be looked up in the global namespace, and
not relative to the current namespace, even if the current namespace is not the
global one. If a hidden command whose name is hidden_cmd_name
already exists,
Err
will also be returned. After executing this command, attempts to use
cmd_name
in any script evaluation mechanism will fail.
use tcl::*;
let interpreter = Interpreter::new().unwrap();
assert!( interpreter.run("pwd").is_ok() );
interpreter.hide_command( "pwd", "hide_pwd" ).unwrap();
assert!( interpreter.run("pwd").is_err() );