Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tracking where proc defined and jumping to its source

66 views
Skip to first unread message

budd...@gmail.com

unread,
Oct 11, 2015, 8:23:55 AM10/11/15
to
Hi!

I'm new to tcl, but I use Common Lisp (CL) for many years.

There is one very good utility in CL IDEs I use.

When insertion cursor is at some currently existing
function name, I press just one hotkey and IDE opens
a place in a source file where that function is defined.

IDE does not grep files, it uses location information
collected at compilation time, so this information is
precisely exact (unless file have been edited since compilation).

I undertaken some minimalistic search for a similar feature in tcl,
but I was unable to find it.

So I implemented it myself.

Code is here:

https://bitbucket.org/budden/clcon/src/default/record_definition.tcl

It consists of two main parts: tracking definitions and jumping to definition.
Tracking code should work everywhere, but jumping to definition depends
on my clcon's infrastructure so you might want to rewrite EditProcedure
function for yourself.

It looks like my code works - I loaded entire clcon which uses snit
and tablelist, with tracking enabled and all seem to work.

TODOs are to jump to variable definition. Jumping to place where
widget is instantiated seem to be possible too, but it needs to be
done separatedly for each widget type.

I'd like to hear comments on code quality. If there is more professional-quality implementation of source tracking, I'd like to drop my implementation
and use that better one.

Rich

unread,
Oct 11, 2015, 11:08:38 AM10/11/15
to
budd...@gmail.com wrote:
> Hi!

> I'm new to tcl, but I use Common Lisp (CL) for many years.

> There is one very good utility in CL IDEs I use.

> When insertion cursor is at some currently existing
> function name, I press just one hotkey and IDE opens
> a place in a source file where that function is defined.

> IDE does not grep files, it uses location information
> collected at compilation time, so this information is
> precisely exact (unless file have been edited since compilation).

> I undertaken some minimalistic search for a similar feature in tcl,
> but I was unable to find it.

> So I implemented it myself.

> Code is here:

> https://bitbucket.org/budden/clcon/src/default/record_definition.tcl

> ...

> I'd like to hear comments on code quality.

proc showVar {name} {
puts "sV:$name=[uplevel 1 [string cat {format %s $} $name]]"
}

Do not do this. This will work, but only as long as the name of the
variable does not contain any Tcl metacharacters. Tcl has much in
common with Lisp in that regard in that variable names can be almost
anything:

$ rlwrap tclsh
% set x 20
20
% set {$x} 30
30
% set {x Y} 50
50

% set x
20
% set {$x}
30
% set {x Y}
50
%

For your 'showvar' you want to do this instead:
proc showVar {name} {
upvar 1 $name local
puts "sV:$name=[format %s $local]"
}

Assuming you always want to 'format' as a string. If you just want to
output the variable, you can do:

puts "sV:$name=$local"

The reason why your uplevel version will fail is you are building a tcl
command using string operations (string cat). That works, 99% of the
time, until the 1% when a Tcl metacharacter causes the eval of the
string to fail. The canonical method of building up Tcl commands for
evaluation is to use [list] (which will assure that any metacharacters
are properly quoted to prevent them from being interpreted as
metacharacters.

Scanning through the code, you have more instances where you are using
string operations to build items for evaluation. Many of them will be
just as fragile as showVar when variable names contain unusual
characters.

For instance, your defvar would be better written this way, and would
avoid the same possibilities for odd errors based upon data content:

proc defvar {name delicate_value} {
if {![uplevel 1 [list info exists $name]]} {
uplevel 1 [list set $name $delicate_value]
} else {
return -code error "variable '$name' already exists"
}
}

> If there is more professional-quality implementation of source
> tracking, I'd like to drop my implementation and use that better one.

I've heard that the Geany editor (http://www.geany.org/) includes a
"jump to Tcl proc defn" function. I do not know how it performs the
jump (most likely by 'grep' type operations).

budd...@gmail.com

unread,
Oct 11, 2015, 2:17:00 PM10/11/15
to
Thanks, I've fixed my code and pushed to repo. Seem to work.
Geany is Scintilla based, but I found that scintillatk does not build at current tcl/tk versions, so I abandoned idea using Scintilla.

I hope text widget is good enough to go.

Do you mean to say that subst -nocommands is generally a bad idea? If so, I might need to change my code in some other places too.

Rich

unread,
Oct 11, 2015, 2:59:28 PM10/11/15
to
budd...@gmail.com wrote:
> Thanks, I've fixed my code and pushed to repo. Seem to work.

> Geany is Scintilla based, but I found that scintillatk does not build
> at current tcl/tk versions, so I abandoned idea using Scintilla.

I don't use it, just heard that it did something similar.

> Do you mean to say that subst -nocommands is generally a bad idea?

No, "subst -nocommands" is perfectly fine. What is not generally a
good idea in all situations is using the output from string functions
(and subst is a 'string' function) to construct text that will be
evaluated. Doing so introduces subtle bugs that can lie dormant for a
very long time, until just the right data pattern comes through one
day, and boom.

There is a loose similarity to SQL injection attacks.

> If so, I might need to change my code in some other places too.

That depends upon how you use the output of subst -nocommands. As a
string, nothing wrong. As something to be evaluated, then that can be
dangerous, esp. if you do not control the input data.

budd...@gmail.com

unread,
Oct 11, 2015, 3:02:03 PM10/11/15
to
Yes, I mean just evaluation. Ok, I see I'll have to look at the places where I use the pattern. It is a pity, as pattern looks very fine on the screen and is easily readable.

Rich

unread,
Oct 11, 2015, 3:15:43 PM10/11/15
to
budd...@gmail.com wrote:

[note - it is considered polite on Usenet to actually quote some
contextual lines of the message one is replying to - the entire world
does not read Usenet via google groups, and so no context makes it very
hard to figure out what a sentence is isolation is referencing. Note
how your prior statement is quoted below to provide a contextual basis
for my reply.]

> Yes, I mean just evaluation. Ok, I see I'll have to look at the
> places where I use the pattern. It is a pity, as pattern looks very
> fine on the screen and is easily readable.

The fact is that you might go for many years and never encounter an
issue. But, that does not make the bug go away, it just means that
nothing triggered it. These bugs, however, are ones that are very
likely to get triggered when you have no time to go figure out what is
going on, and long after you've forgotten what it was you wrote in the
first place.

There's a term for it in the Tcl world: Quoting Hell
(http://wiki.tcl.tk/1726)

A small tidbit about using [list] for dynamically generating code at
runtime: http://wiki.tcl.tk/440#pagetocb3ad4aa3

Some more info on dynamic code generation:
http://wiki.tcl.tk/37332#pagetoc04c6ab3f

budd...@gmail.com

unread,
Oct 12, 2015, 11:58:14 AM10/12/15
to
> > Yes, I mean just evaluation. Ok, I see I'll have to look at the
> > places where I use the pattern. It is a pity, as pattern looks very
> > fine on the screen and is easily readable.
>
> ...
> There's a term for it in the Tcl world: Quoting Hell
> (http://wiki.tcl.tk/1726)
>
> A small tidbit about using [list] for dynamically generating code at
> runtime: http://wiki.tcl.tk/440#pagetocb3ad4aa3
>
> Some more info on dynamic code generation:
> http://wiki.tcl.tk/37332#pagetoc04c6ab3f

Thanks a lot!
0 new messages