Ashwin
Ashwin

Reputation: 1013

Way to list all procedures in a Tcl file

Is there any way to list all the procedures(proc) in a myFile.tcl using another tcl file or in the same file.

Upvotes: 2

Views: 2858

Answers (4)

Donal Fellows
Donal Fellows

Reputation: 137627

The cheapest way is to just open the file and use regexp to pick out the names. It's not perfectly accurate, but it does a reasonably good job.

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"
}

Does it deal with all cases? No. Does it deal with a useful subset? Yes. Is the subset large enough for you? Quite possibly.

Upvotes: 1

Eric Melski
Eric Melski

Reputation: 16790

You can use [info procs] before and after sourcing the file in question and compare the results to determine which procs were added. For example:

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]"

One thing I like about this solution is that the diff procedure is really just a generic set differencing utility -- it's not specific to comparing lists of defined procedures.

Upvotes: 1

Hai Vu
Hai Vu

Reputation: 40733

Here is a different approach:

  1. Create a temporary namespace
  2. Source (include) the script in question, then
  3. Use the info procs command to get a list of procs
  4. Delete the temporary namespace upon finish

Here is my script, *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"

For example, if you have the following script, procs.tcl:

proc foo {a b c} {}
proc bar {a} {}

Then running the script will produce:

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

Upvotes: 0

Johannes Kuhn
Johannes Kuhn

Reputation: 15173

Yes it is, although not that easy. The basic idea is to source the file in a modified slave interp that only executes some commands:

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

This approach will fail if the file requires other packages (package require will not work), relies on the result of some usually auto_load'ed commands etc..

It also does not take namespaces into account. (namespace eval ::foo {proc bar a {}} creates a proc with the name ::foo::bar

For a more complex implementation you could look into auto.tcl's auto_mkindex, which has a similar goal.

Upvotes: 0

Related Questions