#---------------
# lshift.tcl
#---------------
proc lshift {l i} {
# if the item already exists, just return the list back
if {![lsearch $l $i]} {return $l}
# insert new item at the top
set l [linsert $l 0 $i]
# delete the one at the end
return [lrange $l 0 end-1]
}
#---------------
# the ubiquitous demo
#---------------
proc demo {} {
# just for the linux users
catch {console show}
# create a list
foreach a {apple pear bannana} {
lappend fruit $a
}
# the list before changes
puts $fruit
# cherry will be added, bannana will go
set fruit [lshift $fruit cherry]
puts $fruit
# we already have cherry, no change
set fruit [lshift $fruit cherry]
puts $fruit
}
demoMG Apr 17 2006 - Did you know you can use lrange $list 0 end-1 to trim the last element from the list, and avoid the expr? A couple of suggestions, too: it might be better if you could specify a maximum length instead (recent document/history lists won't always be fully populated, and the user may clear it). Also, if an item is already in the list, it could be better to bring it to the beginning, rather than do nothing.WJG(17/April/2006) Following your comment, I have changed the lrange statement as you suggested. The overall list length; well, that could be adjusted by simply adding a new items to the list elsewhere. The suggestion about swapping is a good one. After all, if a file is to be re-loaded, it usually is the last one worked on.WJG(17/April/2006) So, here we go. Here's a more complete example. Using the comments made by MG. It also concatenated the filepath listing in the cascade menu.AK (17/April/2006) Note that the updated version also fixed a bug in the first version above. The "!lsearch" is wrong. The result of lsearch is '-1' for a non-existing element, and '>=0' for an existing one. An existing element at index 0 is not recognized as existing. This seems to be fixed in the new version below. Note that tcllib's list op package (struct::list) has a shift command as well, but with completely different semantics. I consider the command here useful enough for inclusion into that tcllib module, however we will then have to find a different name for it.WJG (18/April/2006) I admit that I tend to post things to the wiki before they're well tested. I know that if I don't then I'll just move onto something else. In terms of inclusion of any ideas of tcllib, be my guest. I'm delighted to think that my code could be useful to others.
#---------------
# recentfiles.tcl
#---------------
# Created by William J Giddings
# 17/Apr/2006
#---------------
#---------------
# somewhere to keep private info
#---------------
namespace eval recent {
set cmd puts ;# default command called in menu
set max 5 ;# maximum of 5 files in the list
# build list to hold filenames
for {set i 1} {$i<=$max} {incr i} {
lappend files "--"
}
}
#---------------
# update menus
#---------------
proc recent:update {mnu fname} {
# recreate the menu
destroy $mnu
menu $mnu -tearoff 0
# make changes
# 1) to the file list
set recent::files [lshift $recent::files $fname]
# 2) to the appropriate menu
set i 1
foreach n $recent::files {
# truncate the filename
set j "[string range $n 0 10]../[file tail $n]"
$mnu add command -label "$i) $j" -command "$recent::cmd \{$n\}"
incr i
}
}
#---------------
# lshift.tcl
# http://wiki.tcl.tk/15758
# this modified version will bring existing
# entries to the top
#---------------
proc lshift {l i} {
# if the item already exists, just return the list back
set swap [lsearch $l $i]
if {$swap!=-1} {
set tmp [lindex $l $swap]
# delete the old location
set l [lreplace $l $swap $swap]
# bring it to the front
set l [linsert $l 0 $i]
return $l
}
# insert new item at the top
set l [linsert $l 0 $i]
# delete the one at the end
return [lrange $l 0 end-1]
}
#---------------
# the ubiquitous demo
#---------------
proc demo {} {
catch {console show}
menu .menu
. configure -menu .menu
menu .menu.file -tearoff 0
.menu add cascade -menu .menu.file -label File
.menu.file add command -label New.. -command fileNew
.menu.file add command -label Open.. -command fileOpen
.menu.file add cascade -label "Recent Documents" -menu .menu.file.recent
.menu.file add separator
.menu.file add command -label "Save As.." -command fileSave
.menu.file add command -label Save -command fileSave
.menu.file add separator
.menu.file add command -label Exit -command fileExit
set path {C:/Documents and Settings/William J Giddings/My Documents/}
recent:update .menu.file.recent ${path}apple.odt
recent:update .menu.file.recent ${path}bannana.odt
recent:update .menu.file.recent ${path}cherry.odt
recent:update .menu.file.recent ${path}damson.odt
recent:update .menu.file.recent ${path}elder.odt
recent:update .menu.file.recent ${path}fig.odt
recent:update .menu.file.recent ${path}damson.odt ;# this one should have no effect
recent:update .menu.file.recent ${path}grapefruit.odt
recent:update .menu.file.recent ${path}fig.odt ;# this one, too, should have no effect
}
#---------------
# the ubiquitous demo!
#---------------
demoSee also histlist, taken from AlphaTcl.
Category Example

