ycl

ycl , short for Yorick's Computing tooLkit, is PYK's collection of miscellaneous procedures and programs.

Installation

To download ycl:

fossil clone http://chiselapp.com/user/pooryorick/repository/ycl ycl.fossil

Then, open the fossil and add /path/to/opened/fossil/packages to $auto_path

There is also a helper script, .../ycl/bin/yclrun, which will automatically adjust $auto_path, and can be used as wrapper:

tclsh /path/to/opened/fossil/packages/ycl/bin/yclrun myscript.tcl

There is another helper script for an interactive shell:

tclsh /path/to/opened/fossil/packages/ycl/bin/yclsh

Zipguy 2013-11-24: How about if you put all those files into a folder structure? Even one folder, named 'ycl', or 'app-ycl' would work good. Then you could either zip them (or you could have gz'ed them), or SDX them (into a starkit) which would make it a lot easier to download them? There are way too many files for me to chase, individually, even though they look quite interesting. Probably a version would be good too, so you could check it, and see if you've already downloaded the latest version.

pyk: you can get this by logging into the repository as anonymous, and then choosing to download the zip or tarball for the commit you're interested in.

Usage

The documentation appears in the source code immediately prior to each function declaration. It is in a text format which is intended to be reasonably intuitive even without much knowledge of Tcl.

Most packages have test suites (look for files ending in .test), which provide examples.

ycl/bin/ycl

The script ycl/bin/ycl can be used to call a command in ycl from a shell.

synopsis

ycl/bin/ycl cmd package command ?args?

command is a command available in package

Example

From an sh shell:

$ tclsh /cygdrive/c/Users/yorick/Documents/ycl/src/packages/ycl/bin/ycl cmd 'math rand' randprint_256
BUV9z#[email protected]^ytLk1LrTKRp35tbqN^LgqkH7Z6

Contents

chan

connect
Connect the output of one channel to the input of another. Uses a separate thread to avoid deadlocks.
interp
Given a channel connected to a Tcl interpreter, evaluate scripts in that interpreter.
osin chan
Using chan pipe, creates an os channel to feed $chan, and returns the writable end of the pipe, configured to -translation binary -blocking 0. Useful, for example, with exec where only real os channel can be used in a redirection.
osout chan
Using chan pipe, creates an os channel fed by $chan, and returns the readable end of the pipe, configured to -translation binary -blocking 0.
both chan
osin and osout combined. Returns a readable channel and a writable channel, both configured to -translation binary -blocking 0.
tee
Transforms a channel into another channel whose output is asynchronously duplicated to a third channel.
chunked
A reflected channel that wraps another channel, translating its contents from HTTP chunked format. Written as a reflected channel instead of a channel transform so that the wrapped channel can persist after the chunked wrapper is closed. This feature is useful for persistent HTTP connections.
clib pushTransform
A Critcl C function that can be used by another Critcl package to push a channel transform onto a channel:
package require {ycl chan clib}
critcl::api import ycl_chan_clib
critcl::cproc someproc ... {
        pushTransform(..., mytransform ...)
        ...
}

The signature for pushTransform is:

int pushTransform(Tcl_Interp interp
        ,ClientData clientData
        ,ycl_chan_transform_eofProc eof
        ,ycl_chan_transform_closedProc closed
)

The transform routine has the following signature:

int transform(Tcl_UniChar uchar ,Tcl_DString output)

It is called once for each character encountered while reading the channel, and should append the transformation to ˇoutputˇ. The transform routine can maintain its own state and append to output each time it receives enough meaningful information to complete the next piece of the transformation.

wrap
A skeleton reflected channel that wraps another channel.

chan clib

package require {ycl chan clib}
::critcl::api import ycl_chan_clib 0.1

Provides the following C functions:

filter(Tcl_Interp *interp ,Tcl_Channel inchan ,Tcl_Channel outchan ,(process)(Tcl_Interp *interp ,Tcl_UniChar *uchar ,Tcl_DString *output))
Filters data as it passes from inchan to outchan. process recieves one character and modifies output , which is then written to outchan.

comm

ycl comm http
An http client that makes use of coroutines and reflected channels.

context

Deprecated in favor of ycl shelf

package require {ycl context}
namespace import [yclprefix]::context::context

proc fly {ns args} {
    puts  "$ns is flying!"
}

proc nofly {ns args} {
    puts "$ns can't fly!"
}

context bird
bird method fly
bird fly

bird derive eagle
eagle fly

bird derive emu
emu method fly nofly
emu fly

#remove emu's restriction
set emumethods [namespace ensemble configure emu -map]
set emumethods [dict remove $emumethods fly]
namespace ensemble configure emu -map $emumethods

emu fly

coro

async: A distillation of the ycl coro relay system into three commands
wait, reply, and async. This provides all the functionality of Javascript promises but without all the extra syntax.
caller
Returns the name of the coroutine that executed the current coroutine.
callers
Returns a list of the chan of executing coroutines leading to the current coroutine.
eval
Evaluate a script in the calling coroutine, and return the result.
event
An event loop for coroutines. Tries to play nice with Tcl's event loop. This system was created to avoid the performance penalty of using Tcl's event loop as a queue for communication between coroutines.
relay
A small but complete system that allows cooperating coroutines to make and deliver orders amongst themselves.
return
Execute return in the calling coroutine.
suspend
Suspend the calling coroutine and return its name. when the coroutine is resumed, arguments are passed to return. This provides control over how the coroutine resumes.

coro call

coro call is a small system that implements synchronous call semantics among coroutines that might be communicating with asynchronous processes.

call
Calls a ycl coro call coroutine by yielding to it, passing the name of the current coroutine as the final argument. When the coroutine resumes, arguments are passed to return`
hi
Answers a call, storing the name of the caller away in a certain local variable.
bye
Deletes the curent coroutine and signals the caller to break.
reply
Sends a response to the caller and yields until executed again.

eav

eav
An entity-attribute-value system built on sqlite, featuring a Tcl-ish interface and query capabilities, and traces for maintaining data constraints and reacting in other ways to record updates.

Daerth

Daerth
creates and manages minions of threaded asynchronous pipelined backpressure-mediated compute stations.

dict

search
Like lsearch, but searches keys, and returns results in reverse order.
setm
Like dict set, but doesn't deduplicate other keys in the dictionary.
unsetm
Like dict unset, but doesn't deduplicate other keys in the dictionary.

dict deep

get
Retrieve an item from a deep dict.
merge
Merge deep dicts
pretty
Pretty-print a deep dict
set
Set an item in a deep dict

dir

package require {ycl dir}
namespace import [yclprefix]::dir
copynode
Copy a file or directory into an archive location, faithfully duplicating any symbolic links, recursively, in the path of the file. Does not copy the contents of a directory, just the directory node itself, which may be a symbolic link. In order to accomodate arbitrary symbolic links in the path of the file or directory, It is placed in the archive at the same absolute location, with the archive directory as the root.
duplicates
find duplicate files
deduplicate
remove duplicate files
iter
iterate over items in a directory tree.
for item in [dir iter /my/dir] {
    #do stuff
}
listing
A drop-in replacement for glob that provides a new type specifier, +hidden, to include hidden files all results.

entropy

A "daemon" coroutine that collects entropy when the system is idle.

exec

filter ?exec command? script
Invoke a new interpreter and evaluate script in it. Returns a read/write channel connected to the new process. If exec command is provided, it must return a new ineractive interpreter.
invoke
invoke a child program and asynchronously handle stdio, stderr, and exit code. See example at [open].

eval

block ?argspec? body ?args?
Like lambda, but also executes immediately.
block {
        db eval {select * from resources} {
                puts [list $path $owner]
        }
}
eset varname args
Execute a args and assign the result to a variable.
lambda ?argspec? body ?args?
An implementation of lambda. Returns a command prefix.
lambdacurry
Captures the namespace of the caller and returns a command prefix that executes the given commandprefix from that namespace.
upcall ?level? `args
Treats args as a prepared command , finds a routine for a command at the current level, as tailcall does, and executes the command at the specified level, as uplevel does.

iter

Very similar in spirit to Generator. Can be used with [for ... in]

package require {ycl iter}

A set of iterators

file
iterate over a file, by line or arbitrary function
string
iterate over the characters in a string

format

sh::shtotcl
converts the words of a value in sh syntax to a Tcl list.

interp process

Manage intepreters as if they were processes, with each interpreter given its own thread.

eval
Evaluate a script in an existing process. Yields to await the result or interruption of the evaluation.
new
Create a new process and evaluate a script in that process. Options: Keep the process alive after evalution. Provide the name of the process.
kill
Kill an existing process
list
List running processes

iter::for

package require {ycl iter for}
for ... in
a convenient loop construct for working with iterators

knit

See knit.

list

package require {ycl list}
add
Like lappend, but only adds the item if it isn't in the list.
addp
Like add, but prepends the item.
all
Returns true if all the items in one list are in another or pass the provided test.
any
Returns true if any items in one list are in another or pass the provided test.
are
Returns a list of indices of items that are in another list or pass the provided test.
compare
Uses a provided function to determine whether two lists are comparble.
complement
Given the name of list A and the name of list B, return a list of members of A that are not members of B.
consume
Like foreach, but accepts the names of lists and consumes their contents incrementally. If the lists being operated on are modified in the process, the results are affected. Stops as soon as one list is empty.
dedent
Removes common initial whitespace from the items in a list.
dedent_exact
Like dedent, but only removes identical whitespace.
deep
An implementation of a deep list. Provides index, insert, is struct, range and set.
filter
Uses one list to filter items from another.
foreach
Like foreach, but accepts list names and consumes items from them.
head
Given the name of list A, assign to that name of A items in A that precede to the final items, which much form the tail B.
join
Like join, but accepts the name of a list and assigns the result to that name.
lappend
Like lappend, but each argument is the name of a value to append to the list.
lappend*
Like lappend, but each argument is the name of a list of items to append to the list.
layer
Add and remove layers of list structure.
lindex
Like lindex, but accepts the name of a list and assigns the result to that name. Each index must be the index of an existing item.
linsert
Like linsert, but accepts the name of a list and assigns the result to that name.
llength
Like llength, but accepts the name of a list and assigns the result to that name.
list
An implementation of a general "sequence" data type. Provides advance, cursor, has, next, peek, and value.
lmap
Like lmap, but accepts list names, incrementally consumes those lists, and assigns the result to the first name.
lrange
Like lrange, but accepts the name of a list and assigns the result to that name.
lreplace
Like lreplace, but accepts the name of a list and assigns the result to that name.
lreverse
Like lreverse, but accepts the name of a list and assigns the result to that name.
lsort
Like lsort, but accepts the name of a list and assigns the result to that name.
merge
Merge items in the second list into the first.
order
Given the name of list A, and the name list B providing an order, orders the items in A according to the indexes in B, and assigns the result to the name of A.
pick
Pick certain elements from a list by index or by range, with an optional step.
pop
Given the name of a list, removes items from the list and assigns them to the provided names. Alternatively, removes one item from the end of the list and returns it.
prefix
Given th name of list A and the name of list B determine whether A is a prefix in B.
prepend
Prepend an item to a list.
rangecheck
Given the name of a length and the name of an index, determine whether the index is within range.
randidx
Given the name of list A, returns copies of the requested number of items selected randomly from A.
reorder
Reorders a list according to a given list of indices.
rlindex
Like lindex, but returns an error when an index is out of bounds.
sl
scripted list.
split
Like split, but accepts the name of a list and assigns the result to that name.
ss
A building block of sl. Takes one argument, treats it as a script, splits it into commands, discards comments, performs substitutions on the words in the commands, and returns a list of the commands.
subset
Given the name of list A and the name of list B, determine whether A constitutes a subset of B.
tail
Given the name of list A and the name of list B, assign to the name of A all the items in A that follow the initial items which must form prefix B.
take
Like lassign but accepts the name of list A and assigns the result to the name of list A. Returns an error when there are not as many in the A as given variable names.
trim
Given the name of list A, removes initial whitespace from items in A. Unlike string trim, removes only true whitespace.
take
Given the name of list A, takes items from A, assigns them to the provided names, and assigns the remainder of the items to the name of A. Alternatively, removes one item from A.
unique
Removes duplicate items in a list without sorting it.
unpack
Like lassign, but produces an error if there are not enough items to assign to the provided names.
unpackvar
Like unpack, but accepts the name of a list and assigns the result to that name.
unset
Given the name of list A, remove the item in A a given index, an assign the result to the name of A.
unset
Returns the indices of items in one list that are in another or pass the provided test.
which
Given the name of list A and the name of list B, return the items in A that are in B. Alternatively, return the items in A that pass the provided test.

list deep

index
Retrieves an item from a deep list.
insert
Inserts an item into a deep list.
is deep
Determines whether an item in a list is a deep list.
pretty
Pretty-prints a deep list.
scripted
Applies list sl to a deep list.
set
Sets an item in a deep list.

matrix

A close-to-drop-in replacement for tcllib's matrix, but with better performance characteristics since it's more careful about avoiding duplication of data during operation.

math

expr
A more concise version of expr. Assigns the result to the provided variable name. If no variable name is provided, $expr is used.

math rand

flip
Randomly produces a 1 or 0. The output is intended to have the same high entropy as as true random numbers and to be suitable for cryptographic use. This command is analagous to /dev/random.
rng
Cryptogphic random number generator using a seed produced by flip. Analagous to /dev/urandom.
rand
A cryptographically-strong alternative to the built-in rand() function.

ns

package require {ycl ns}
dupcmds
Copy all commands in a namespace to another namespace, refusing to overwrite any existing commands, and ignoring commands named in in $args. In contrast to oo::copy <cloned>, if a command is both an alias and a procedure, it is treated as an alias.
ensemble duplicate
Copy a namespace ensemble, and if necessary, the namespace that's backing it, along with any child namespaces, recursively. Also replaces in the ensemble map occurrences of the old ensemble name with the new ensemble name. dupensemble can be used as the simplese form of object system, where each namespace hierarchy is treated as an object. Tcl's copy-on-write semantics make this system much more efficient than one would expect at first blush. dupensemble is used by ycl::shelf
call
Resolve and call a command in some namespace without adding a level like namespace eval does.
ensemble subcommands
List the currently-available subcommands of a namespace ensemble.
dupvars
duplicates all variables in a namespace to another namespace

package

vcomp
like package vcompare, but accepts just about anything as a version string.

parse

tcl commands
Split a Tcl script into its components. This is scriptsplit
tcl iter
Uses ycl coro relay to deliver the comands in a script read from a channel.
tcl words
Split a Tcl command into its components. This is cmdSplit.
tcl wordparts
Split a logical word from a Tcl command into its literal, escape-sequence, and substitution components. This is wordparts.
tcl stream
Incrementally parse a Tcl script from a channel.
xml
An xml parser based on ycl parser graph. -relax true enables a forgiving mode when trying to make it through an document.
xml util validCharExpr varname
Returns an expression that evaluates to true if the character in $varname is a valid XML character, and false otherwise.
xml util encodeInvalidChars inchanname outchanname
A filter between channels that converts characters that are invalid in XML to their XML character representations. Accelerated with Critcl when it's available. Uses ycl chan clib filter.
xml util chanEncodeInvalidChars
A stacked channel that encodes invalid XML characters into character entities. Uses ycl chan clib pushTransform.

parser

package require {ycl parser graph}
graph
A framework for extracting graphs from data. -transient false instructs the parser to leave behind a hierarchy of namespaces representing the graph, and commands like children, path, and traverse provide an interface to the graph. This system facilitates the creation of parsers that ignore text outside the target syntax of a given parser.
interp
Adapted from Config file using slave interp.

proc

package require ycl::dir
namespace import [yclprefix]::dir
checkargs
functional documentation for procedures. Somewhat like tepam, with additional aspects of literate programming. Examples include ycl::dir::iter , and ycl::ns::object
alias
an analogue of interp alias that avoids the potential negative performance impact. In contrast to interp alias, extra arguments can not be tacked on to the alias.
const name value
Creates a routine that always returns value.
lproc
Like proc, except that the body is a list of lists and no string representation of the body is generated.
tcl step
A drop-in replacement for proc that provides a pre-evaluation hook and an error handling hook for each command in the script.

quicktcl

shelf

See ycl shelf

set

package require {ycl set}

In the following descriptions, a word that is a single capital letter represents a ycl list list command.

complement
Items in A that are not in B. If $name is provided, creates a ycl coro call routine that produces the resulting items. Otherwise, returns the result as a list.
equal
Determine whether A and B are equal.
subset
Determine whether A is a subset of B.
tail
Returns a ycl coro call routine that produces the remaining items in B after skipping through the initial items, which must correspond to A. Alternatively, return the result as a list.

string

package require {ycl string}
cmp
Like the Unix cmp command, compares two strings and returns the index at which they differ, or -1 if they are identical. Uses a bisect strategy for performance, and for memory efficiency does not extract substrings. Short-circuits when a difference is found.
decode
Like encoding convertfrom, but takes the name of a variable containing string to decode, and assigns the result to that variable. Returns an error if some character can't be faithfully decoded.
dedent
Removes common newline-whitespace, taking tabs into consideration.
dedent_exact
Removes common whitespace.
delimit
split (partition) a string into substrings using any combination of string, match, or regular expressions, returning both the substrings and the delimiters.
encode
Like encoding convertto, but takes the name of a variable containing string to encode, and assigns the result to that variable. Returns an error if some character can't be faithfully encoded.
expand
Provides a concise syntax for embedding and expanding templated text, the primary target being Tcl scripts. One unusual feature is that operators are embedded in the chunks of text they operate on. Based on ycl parser graph.
isdecimal
Determines whether a value is a decimal number
isnumeric
Determines whether a value is a number as understood by expr, except that a leading zero does not signify an octal number.
iter
A ycl coro call string iterator.
map
Like string map but the map is a sequence of arguments rather than a list, and the last argument is the name of a string to operate on rather than the string itself, and the result is assigned to that name.
printable
Convert the backslash character and non-printing characters in $string into \x or \u escaped form. By default each Tcl special character is escaped.
range
Like string range, but accepts the name of a string assigns the result to that name.
regsub
Like regsub, but accepts the name of a string and assigns the result to that name.
replace
Like string replace, but accepts the name of a string and assigns the result to that name.
requiredecimal
Return an error if the value of the named value not a decimal number.
reverse
Like string reverse, but accepts the name of a value and assigns the result to that name.
shortmatch
Like string match, but returns -1 if $string doesn't match, and the index of the last char of the shortest match if it does.
split
Like split, but accepts the name of a value and assigns the result to that name.
template
Like string map but accepts the name of each replacement value and derives a placeholder value from each name. Provides default delimiters, and automatically quotes each replacement value with list.
to hex
Given the name of a value, convert the value to its hexadecimal representation and assign the result to that name.
trim
Like trim, but accepts the name of a value and assigns the result to name.
tolower
Like string tolower, but accepts the name of a value and assigns the result to that name.
set a 5
set b 7
set expr {[set a]}
eval [template a b # c {
    set a @[email protected]
    set b @[email protected]
    expr {$a + $b + @[email protected]}
}]

struct

env
create, savigate, and manipulate hierarchical data structures. Implemented over tDOM.
nxs
Nested heterogeneous structures. Example: nxs get $mystruct l {0 3 1} d {name Bob friends} l 5. To set a nested vale: nxs set mystruct l {0 3 1} d {name Bob friends} = l end Jane. Extend the functions to additional types of nested structures by adding keys to nxs::get, nxs::set, and nxs::unset. To specialize the library, use ycl ns dupensemble to create a copy of it.

switch

lswitch
Like switch, but each pattern is a list of patterns to match against the item in string at the corresponding position. All switch options are supported.

test

cleanup1
Returns the current namespace to the state it was in before the test was run.

example:

test sometest {} -body {
} -cleanup [cleanup1] -result ...

text

ftclp
Formats a string as a printable Tcl string. Non-printable characters are transformed into their most simple backslash-escaped representation, and backslash is also escaped.

tk_combobox_oakley

Assimilated from Bryan Okley's combobox.

upobj

Together with proc::methods, proc::upmethods, and var::upmethods, compromises an object system much like ycl::context. Its method calling style provides for uplevel 1 to be the object's namespace, and uplevel 2 to be the caller of the method. This turned out to be a little clunky, and ycl shelf is now preferred to this system.

#! /bin/env tclsh

package require ycl::ns
namespace import ycl::ns::object
package require ycl::proc

namespace import ycl::proc::*method


upmethod die {} {} {} {
    puts "$_ dies."
}

object chessman import {name die}
chessman $ name unknown

namespace eval chessman {
    upmethod move {} {} {} {
        puts "$_ doesn't know how to move!"
    }
}

object pawn
pawn parent chessman
namespace eval pawn {
    upmethod move {} {} {} {
        puts "$_ is plodding forward"
    }
}

object knight 
knight parent chessman
namespace eval knight {
    upmethod move {} {} {} {
        puts "$_ gallops forward and to the side"
    }
}

object amazon
namespace eval amazon {
    upmethod move {args} {} {} {
        dict with args {}
        if {$as ni {knight queen}} {
            puts "$_ can not move as a $as"
        } else {
            puts "$_ is moving as a $as"
        }
    }
}

puts "chessman name is: [chessman $ name]"
# -> unknown

chessman move
# -> ::chessman doesn't know how to move! 

object pawn1 
pawn1 parent pawn
pawn1 move 
# -> ::pawn1 is plodding forward

puts "pawn1 name is: [pawn1 $ name]"
# -> unknown

pawn1 $ name {white a}
puts "pawn1 name is now: [pawn1 $ name]"
# -> white a

object knight1
knight1 parent knight
knight1 move 
# -> ::knight1 gallops forward and to the side 

object knight3
knight3 parent knight2
knight3 parent amazon
knight3 move as queen
knight3 move as bishop

visual

slides
A simple presentation system in Tk.

anonymous - 2016-08-26 01:25:05

What is the license on your ycl toolkit? It's not totally clear and there are some GPL'd items hidden in it.

PYK 2016-08-30: Contributors license their contributions independently. As for my contributions, I'm currently handling license requests on a case-by-case basis.