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

I can't parray in a text widget

68 views
Skip to first unread message

Luc

unread,
Nov 16, 2022, 9:43:03 AM11/16/22
to
I am really struggling with this:

--------------------
package require Tk

text .t -width 40 -height 6 -font "FreeSans 18"
pack .t

array set file_1 {name file1 date today size 100k}
array set file_2 {name file2 date today size 200k}
array set file_3 {name file3 date today size 300k}

proc p.printfiles argNumber {
.t delete 1.0 end
.t insert end ::file_$argNumber
.t insert end "\n"
.t insert end "parray: [parray ::file_$argNumber]"
.t insert end "[set ::file_[set argNumber](size)]"
parray ::file_$argNumber
}

p.printfiles 2
--------------------

Result:
::file_2
argNumber
parray:
200k

I've tried all kinds of formats and escaping and can't get the code to
insert the output of [parray] into the text widget.


And the plot thickens. If I include [info vars] in those insert lines, the
only var it finds is argNumber. What about the global vars? Where are they?

Maybe that is why it can't print [parray]?

No, that is not the reason because

1) the parray line at the end works fine in stdout.

2) this line works as expected:

.t insert end "[set ::file_[set argNumber](size)]"

What am I doing wrong?

--
Luc
>>

clt.to...@dfgh.net

unread,
Nov 16, 2022, 10:11:20 AM11/16/22
to
>From: Luc <n...@no.no>
>Date: Wed Nov 16 14:42:56 GMT 2022
>Subject: I can't parray in a text widget


parray prints the array (like puts). It returns an empty string result.
Try:

array set aa {a 1 b 2 c 3}
set rr [parray aa]

<< see array printed on console>>

set rr

<< see empty string>>

Dave B

Helmut Giese

unread,
Nov 16, 2022, 10:29:17 AM11/16/22
to
Hi Luc,
no, you cannot 'parray into a text widget':
'parray' writes to stdout and a text widget wants
'$t insert <index where> <text>'.
I think the simplest solution is:
- look into the file 'parray.tcl' (on my installation it is located in
<path to my installation>/lib/tcl8.6
- rename the parray function, add another parameter to it
and replace the line 'puts stdout ...' with '$t insert ...'

HTH
Helmut

Luc

unread,
Nov 16, 2022, 10:54:35 AM11/16/22
to
OK, I had a wrong understanding of parray.

Thank you for the clarifications.

I am doing

foreach i [array names ::file_$argNumber] {
.t insert end "[set ::file_[set argNumber]($i)]\n"
}

A little ugly and hard to read, but it works.


Thank you.

--
Luc
>>

Robert Heller

unread,
Nov 16, 2022, 11:20:27 AM11/16/22
to
The parray function is *hard wired* to *print* an array to stdout. It is
really only meant to debugging use. You will need to write your own
parray-like proc to insert the array into the text widget in the format you
like. Maybe something like:

proc insertArray {textwidget arrayname {pattern *}} {
upvar $arrayname array
set l 0
foreach k [array names array $pattern] {
set l [expr {max($l,[string length $k])}]
}
foreach k [array names array $pattern] {
set space [string repeat " " [expr {$l-[string length $k]}]]
$textwidget insert end [format "%s(%s)%s = %s\n" \
$arrayname $k "$space" $array($k)]
}
}


--
Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services
hel...@deepsoft.com -- Webhosting Services

Ralf Fassel

unread,
Nov 16, 2022, 11:28:03 AM11/16/22
to
* Luc <n...@no.no>
| foreach i [array names ::file_$argNumber] {
| .t insert end "[set ::file_[set argNumber]($i)]\n"
| }
>
| A little ugly and hard to read, but it works.

May I suggest

foreach {key val} [array get ::file_$argNumber] {
.t insert end "$val\n"
}

Prettier, IMHO ;-)

R'

Christian Gollwitzer

unread,
Nov 16, 2022, 11:30:59 AM11/16/22
to
Am 16.11.22 um 16:54 schrieb Luc:
> Thank you for the clarifications.
>
> I am doing
>
> foreach i [array names ::file_$argNumber] {
> .t insert end "[set ::file_[set argNumber]($i)]\n"
> }
>
> A little ugly and hard to read, but it works.

In order to iterate over an array, you can also use array get:

foreach {key val} [array get yourarray] {
puts "$key = $val"
}

which should be more readable.

Christian

Luc

unread,
Nov 16, 2022, 12:16:50 PM11/16/22
to
Yes, I wrote my own syntatic sugar:

proc p.fileinfo {argNumber argInfo} {
if {$argInfo == "all"} {
return "[set ::files_[set argNumber](name) \
[set ::files_[set argNumber](size) \
[set ::files_[set argNumber](datetime) \
[set ::files_[set argNumber](type) \
[set ::files_[set argNumber](permission)"
}
return "[set ::files_[set argNumber]($argInfo)]"
}


% puts [p.fileinfo 15 size]
256636


Thank you again!

--
Luc
>>

Rich

unread,
Nov 16, 2022, 12:32:48 PM11/16/22
to
Luc <n...@no.no> wrote:
> proc p.printfiles argNumber {
> .t delete 1.0 end
> .t insert end ::file_$argNumber
> .t insert end "\n"
> .t insert end "parray: [parray ::file_$argNumber]"
> .t insert end "[set ::file_[set argNumber](size)]"
> parray ::file_$argNumber
> }
>
> And the plot thickens. If I include [info vars] in those insert
> lines, the only var it finds is argNumber. What about the global
> vars? Where are they?

As no one has yet answer this, I'll add.

The reason 'info vars' only shows argNumber is because this is how
'info vars' is defined to behave:

man n info:

info vars ?pattern?
If pattern is not specified, returns a list of all the
names of currently-visible variables. This includes
locals and currently-visible globals. ...

Do recall that in Tcl, global variables are not visible inside proc's
by default. Since your proc has a single arg (argNumber) and no calls
to "global" to make any globals visible, the only 'currently-visible
variables' inside the proc is the single 'argNumber'.

If you want to see all the globals, you have to ask for all the
globals:

man n info:

info globals ?pattern?
If pattern is not specified, returns a list of all the
names of currently-defined global variables. Global
variables are variables in the global namespace. ...

You want 'info globals' if you want to see all the globals from inside
a proc.

et4

unread,
Nov 16, 2022, 3:09:05 PM11/16/22
to
On 11/16/2022 7:29 AM, Helmut Giese wrote:

> - look into the file 'parray.tcl' (on my installation it is located in
> <path to my installation>/lib/tcl8.6


Regarding parray, it also nicely formats the output and takes a pattern.

It also does a sort, however I find it's a bit ugly IMHO with numerical indices. So, I modify it to use a -dictionary sort rather than the default -ascii where 10 sorts before 2.

Mike Griffiths

unread,
Nov 16, 2022, 4:45:56 PM11/16/22
to
After a little introspection in the console to see how [parray works]:

catch {parray ;# command is only autoloaded on demand}
# You could build the arglist here programatically, but if it's ever changed to be different, the [string map] will likely be out of date too anyway
proc tarray {a textWidget {pattern *}} [string map [list "puts stdout" "\$textWidget insert end {\n} {} "] [info body parray]]

array set myArray [list foo bar baz boing]

parray myArray
tarray myArray $textWidget

Ralf Fassel

unread,
Nov 17, 2022, 5:28:18 AM11/17/22
to
* Luc <n...@no.no>
| proc p.fileinfo {argNumber argInfo} {
| if {$argInfo == "all"} {

NB. Using 'eq' instead of '==' saves some CPU cycles when TCL is trying
a numerical comparison first with "==".

| return "[set ::files_[set argNumber](name) \
| [set ::files_[set argNumber](size) \
| [set ::files_[set argNumber](datetime) \
| [set ::files_[set argNumber](type) \
| [set ::files_[set argNumber](permission)"
| }
| return "[set ::files_[set argNumber]($argInfo)]"
| }

If you will ever use this function for other purposes than printing the
result, like in

lassign [p.fileinfo foo all] name size datetime type permission

I would strongly suggest to use [list] to build the return value
in the 'all' case. Otherwise it's a data-dependent bug waiting to
happen if some array(name) or any other field contains spaces.

R'
0 new messages