# A procedure that creates a new clipboard for me,
# containing the declaration of a class.
proc make_class {name base} {
clip $name {
cb_puts "class $name : public $base\n\{\n"
plug CLASS_BODY {
cb_puts "public:\n"
plug PUBLIC
cb_puts "private:\n"
plug PRIVATE
}
cb_puts "\};\n"
}
}
# Create a class, then fill in its plugs with code.
make_class A B
add A PUBLIC {
cb_puts " A() // Default constructor\n"
cb_puts " \{\n"
cb_puts " i= 5;\n"
cb_puts " \}\n"
}
add A PRIVATE {cb_puts " int i; // Some member variable\n"}
# Send result to output.
cb_output AThe procedure clip creates a new clipboard. Its final argument is like the body of an "if" or other control statement: it gets executed in the caller's scope. That's how you can nest plugs and text in a clipboard. The call to plug adds a new plug to the current clipboard, given the plug's name and again a body of statements to execute. Note how I can add code to the existing class body at a later time using add.The intended output of the above code is this: class A : public B
{
public:
A() // Default constructor
{
i= 5;
}
private:
int i; // Some member variable
};but you probably guessed that :-)The power of these clipboards comes from- their text-only approach. They do not know anything about C++, they just contain freeform text. That makes them very flexible.
- the buffering of text so that you can change it over and over before outputting it.
- the simple interface.
# Create new clipboard called $name, with top plug called $plug_name
proc cb_new {name {plug_name MAIN}} {
global cb__start
set cb__start($name) $plug_name
set cb_name "cb_${name}"
upvar #0 $cb_name the_cb
# A clipboard is an array
set the_cb($plug_name) [list]
return $cb_name
}
# Remove a clipboard. I know, This can be automated with 'trace'
proc cb_delete {name} {
set cb_name "cb_${name}"
upvar #0 $cb_name the_cb
unset the_cb
}
# Add a new tuple to plug $where of clipboard $name.
# The tuple can be text ($what == "t"), a new plug
# ($what == "p") or a reference to another plug ($what == "r").
# $content is the text content, or the plug name,
# or the referenced clipboard name.
proc cb_add {name where what content} {
set cb_name "cb_${name}"
upvar #0 $cb_name the_cb
if { ![info exists the_cb] } {
return
}
if { $what == "p" } {
if { [info exists the_cb($content)] } {
# Plug with that name already exists
return
}
set the_cb($content) [list]
}
lappend the_cb($where) [list $what $content]
}
# Remove contents of plug $where of clipboard $name
proc cb_clear {name where} {
set cb_name "cb_${name}"
upvar #0 $cb_name the_cb
if { ![info exists the_cb] } {
return
}
set the_cb($where) [list]
}
# Does clipboard $name have a plug called $where ?
proc cb_exists {name where} {
set cb_name "cb_${name}"
upvar #0 $cb_name the_cb
if { ![info exists the_cb] } {
return 0
}
return [info exists the_cb($where)]
}
# Output the entire clipboard $name to a file
proc cb_output {name {fid stdout}} {
set cb_name "cb_${name}"
upvar #0 $cb_name the_cb
if { ![info exists the_cb] } {
return
}
global cb__start
set start $cb__start($name)
cb__output $cb_name $start $fid
}
proc cb__output {cb_name pt fid} {
upvar #0 $cb_name the_cb
foreach elt $the_cb($pt) {
if { [lindex $elt 0] == "t" } {
puts -nonewline $fid "[lindex $elt 1]"
} elseif { [lindex $elt 0] == "r" } {
cb_output [lindex $elt 1] $fid
} elseif { [lindex $elt 0] == "p" } {
cb__output $cb_name [lindex $elt 1] $fid
}
}
}Interface procedures:
set cb_curr_clip ""
set cb_curr_plug ""
# Write text to current plug of current clipboard
proc cb_puts {txt} {
global cb_curr_clip cb_curr_plug
cb_add $cb_curr_clip $cb_curr_plug t $txt
}
# New clipboard.
proc clip {clipname args} {
set plugname "MAIN"
if { [llength $args] > 1 } {
set plugname [lindex $args 0]
}
cb_new $clipname $plugname
global cb_curr_clip
set tmp_clip $cb_curr_clip
set cb_curr_clip $clipname
global cb_curr_plug
set tmp_plug $cb_curr_plug
set cb_curr_plug $plugname
uplevel [lindex $args end]
set cb_curr_clip $tmp_clip
set cb_curr_plug $tmp_plug
}
# New plug in current clipboard
proc plug {plugname args} {
global cb_curr_clip
global cb_curr_plug
cb_add $cb_curr_clip $cb_curr_plug p $plugname
if { [llength $args] == 0 } {
return
}
set tmp_plug $cb_curr_plug
set cb_curr_plug $plugname
uplevel [lindex $args end]
set cb_curr_plug $tmp_plug
}
# At current plug of current clipboard, insert references
# to other clipboards.
proc ref {args} {
global cb_curr_clip
global cb_curr_plug
foreach othername $args {
cb_add $cb_curr_clip $cb_curr_plug r $othername
}
}
# Add new text to an existing plug of a clipboard.
proc add {clipname args} {
set plugname "MAIN"
if { [llength $args] > 1 } {
set plugname [lindex $args 0]
}
global cb_curr_clip
set tmp_clip $cb_curr_clip
set cb_curr_clip $clipname
global cb_curr_plug
set tmp_plug $cb_curr_plug
set cb_curr_plug $plugname
uplevel [lindex $args end]
set cb_curr_clip $tmp_clip
set cb_curr_plug $tmp_plug
}
# Add new plug to an existing plug of a clipboard.
# Take that plug as the new default.
proc add_plug {clipname args} {
set plugname "MAIN"
set newname [lindex $args 0]
if { [llength $args] > 2 } {
set plugname [lindex $args 0]
set newname [lindex $args 1]
}
cb_add $clipname $plugname p $newname
global cb_curr_clip
set tmp_clip $cb_curr_clip
set cb_curr_clip $clipname
global cb_curr_plug
set tmp_plug $cb_curr_plug
set cb_curr_plug $newname
uplevel [lindex $args end]
set cb_curr_clip $tmp_clip
set cb_curr_plug $tmp_plug
}
# Replace existing text in a plug by something new.
proc replace {clipname args} {
set plugname "MAIN"
if { [llength $args] > 1 } {
set plugname [lindex $args 0]
}
cb_clear $clipname $plugname
global cb_curr_clip
set tmp_clip $cb_curr_clip
set cb_curr_clip $clipname
global cb_curr_plug
set tmp_plug $cb_curr_plug
set cb_curr_plug $plugname
uplevel [lindex $args end]
set cb_curr_clip $tmp_clip
set cb_curr_plug $tmp_plug
}
