在Tcl文件中列出所有过程的方法

在Tcl文件中列出所有过程的方法,tcl,expect,Tcl,Expect,是否有任何方法可以使用另一个tcl文件或同一文件列出myFile.tcl中的所有过程(proc)。是的,尽管不是那么容易。基本思想是在修改的从属interp中生成文件,该从属interp只执行一些命令: proc proc_handler {name arguments body} { puts $name } set i [interp create -safe] interp eval $i {proc unknown args {}} interp alias $i proc {}

是否有任何方法可以使用另一个tcl文件或同一文件列出myFile.tcl中的所有过程(proc)。

是的,尽管不是那么容易。基本思想是在修改的从属interp中生成文件,该从属interp只执行一些命令:

proc proc_handler {name arguments body} {
    puts $name
}
set i [interp create -safe]
interp eval $i {proc unknown args {}}
interp alias $i proc {} proc_handler
interp invokehidden source yourfile.tcl
如果文件需要其他包(
package require
将不起作用),依赖于一些通常自动加载的命令等的结果,这种方法将失败

它也不考虑名称空间。(
namespace eval::foo{proc bar a{}
创建一个名为
::foo::bar


对于更复杂的实现,您可以查看具有类似目标的auto_mkindex。

这里有一种不同的方法:

  • 创建一个临时名称空间
  • 来源(包括)有问题的脚本,然后
  • 使用
    info procs
    命令获取过程列表
  • 完成后删除临时命名空间
  • 这是我的脚本*list_procs.tcl*:

    #!/usr/bin/env tclsh
    
    # Script to scan a Tcl script and list all the procs
    
    proc listProcsFromFile {fileName} {
        namespace eval TempNamespace {
            source $fileName
            set procsList [info procs]
        }
        set result $::TempNamespace::procsList
        namespace delete TempNamespace
        return $result
    }
    
    set fileName [lindex $::argv 0]
    set procsList [listProcsFromFile $fileName]
    puts "File $fileName contains the following procs: $procsList"
    
    例如,如果您有以下脚本procs.tcl:

    然后运行脚本将生成:

    $ tclsh list_procs.tcl procs.tcl 
    File procs.tcl contains the following procs: foo bar
    

    您可以在查找相关文件之前和之后使用
    [info procs]
    ,并比较结果以确定添加了哪些程序。例如:

    proc diff {before after} {
        set result [list]
        foreach name $before {
            set procs($name) 1
        }
        foreach name $after {
            if { ![info exists procs($name)] } {
                lappend result $name
            }
        }
        return [lsort $result]
    }
    
    set __before [info procs]
    source myFile.tcl
    set __after  [info procs]
    puts "Added procs: [diff $__before $__after]"
    

    我喜欢这个解决方案的一点是,
    diff
    过程实际上只是一个通用的集合差分实用程序——它并不特定于比较已定义过程的列表。

    最便宜的方法是打开文件,然后使用
    regexp
    来选择名称。这不是非常准确,但它相当有用d工作

    set f [open "sourcefile.tcl"]
    set data [read $f]
    close $f
    
    foreach {dummy procName} [regexp -all -inline -line {^[\s:]*proc (\S+)} $data] {
        puts "Found procedure $procName"
    }
    

    它处理所有情况吗?不。它处理有用的子集吗?是的。子集对您来说足够大吗?很可能。

    您想要进程名称,还是需要查看arg列表和/或进程体?如果您的系统有它,
    包需要struct::set
    并使用
    struct::set difference
    而不是编写自己的代码n
    diff
    .Pro:不必编写,可重复使用。缺点:只需使用一个函数,就必须导入大量代码。使用子interp更好。大多数Tcl文件使用全名,因此它们忽略您的命名空间。
    set f [open "sourcefile.tcl"]
    set data [read $f]
    close $f
    
    foreach {dummy procName} [regexp -all -inline -line {^[\s:]*proc (\S+)} $data] {
        puts "Found procedure $procName"
    }