ycl

Difference between version 139 and 140 - Previous - Next
'''[https://chiselapp.com/user/pooryorick/repository/ycl/dir?ci=tip%|%ycl]''', 
short
 for '''Y'''orick's '''C'''omputing too'''L'''kit, is  [PYK%|%PYK's] 
collection of
 miscellaneous procedures and programs.


** License **

Most things in '''`ycl`''' are currently unlicensed.  Those wishing to put them
into production should contact the author to obtain a license.  Some things are
licensed under the [GPL], and some things are licensed under the
[https://chiselapp.com/user/pooryorick/repository/ycl/file?name=packages/support/licenses/FSUL&ci=4f0c591bf3c24cbd63ed97effd3e74d6e0ba2b38%|%Free
Software Utilization License] (FSUL), which grants the freedom to do anything
at all with the software and for productive use of the software imposes a
utilization fee that accrues as the software is used.



** Installation **

To download ycl:

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

Then, in a Tcl interpreter add `/path/to/opened/fossil/packages` to
[auto_path%|%$auto_path%|%] 

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

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

There is another helper script for an interactive shell:

======none
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 load into namespaces that follow thes pattern:


======
[yclprefix]::name1::name2::...
======

Each ''name'' is an item in the name of the package, excuding `ycl`, which is
item
0.

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

Some packages provide a directory named `demo`, which constains 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:

======none
$ tclsh /cygdrive/c/Users/yorick/Documents/ycl/src/packages/ycl/bin/ycl cmd 'math rand' randprint_256
BUV9z#=Zu=dAi@y^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 [Hypertext Transfer Protocol%|%HTTP] chunked format.  Written as a reflected channel instead of a [transchan%|%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 [coroutine%|%coroutines] and [reflected channel%|%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
======

======
package require {ycl chan clib}
======


*** `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.

   '''`drive`''' `''script''`:   Creates a coroutine to evaluate the script, schedules the coroutine, enters the event loop, and returns the results when the coroutine completes.

   '''`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.

   '''`[ycl coro relay%|%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.

   '''`suspendall`''':   Suspends all coroutines on the call stack and returns the name of a command to restart them all and return control to the caller of `suspendall`.

   '''`upcoro`''':   Evaluate a script in the calling coroutine, and return the result.


   '''`vsproc`''':   A convenience wrapper around `[proc]` that creates a `vstack`-enabled procedure. 


   '''`vstack`''':   Creates a virtual call stack between the current routine and its caller by suspending all coroutines on the call stack and arranging for the result of the current coroutine to propagte back through that call stack.  I.e. creates synchronous call semantics between a coroutine and its caller while allowing the current coroutine to yield as needed to wait for events, e.g. channel events. 




** coro interp **

======
package require {ycl coro}
======

   '''`interp`''' ''`name`'' ''`options`'':   Creates a new intepreter coroutine.

The available options are:
 

   '''`init`''' ''`script`'':   Evaluate ''`$script`'' at level #0.


A new interpreter provides the following routines:

   '''`add`''' ''`name`'' ''`script`'':   Adds a routine.  ''`script`'' is evaluated at level #1 in the coroutine.

   '''`eval`''':   Evaluates a script at level #0.

   '''`local`''':   Evaluates a script at level #1.

   '''`remove`''' ''`name`'':   Removes a routine.

   '''`return`''' ''`args`'':   Returns from the coroutine.



*** 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 `[yield%|%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 [yield%|%yields] until executed again.




*** [ycl eav%|%eav] ***

   '''`[ycl 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.



*** eval *** 

   '''`block`''' ?''`argspec`''? ''`body`'' ?''`args`''?:   Like '''`lambda`''', but also executes immediately.

======
block {
        db eval {select * from resources} {
                puts [list $path $owner]
        }
}
======

   '''`call`''' ''level'' ?''arg ...''?:   calls ''args'' as a command at the given level.  Unlikc `[eval]`, ''args'' are not evaluated as a script.

   '''`eset`''' ''`varname`'' ''`args`'':   Execute a ''`args`'' and assign the result to a ''`variable`''.

   '''`overlay`''' ''`script`'':   [eval%|%Evaluates] the given script leaving the values of any existing variables unchanged afterwards.

   '''`untraced`''' ''`name`'' ''`script`'':   Removes [trace%|%traces] from the [routine] named ''`name`''', evaluates ''`script`'', replaces the traces, and returns the result of the evaluation.

   '''`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.


*** exec ***

======
package require {ycl exec}
namespace import [yclprefix]::exec
======

   '''`cexec`''' ''`channel configuration`'' ''?`arg`? ...'':   Like `[exec]`, but performs no translation on redirected input, and allows configuration of the output channel, making it suitable for use with [binary] [data].

   '''`eval`''' ''`script`'':   Evaluates a script in a new process and returns the result.  The exit status is the [return%|%return code] of the script.

   '''`filter`''' ?`exec` ''`command`''? ''`script`'':   Invokes a new interpreter and evaluates ''`script`'' in it.  Returns a read/write channel connected to the new process.  If `exec` ''`command`'' is provided, it must return a new interactive interpreter.

   '''`invoke`''':   Invoke a child program and asynchronously handle [stdio], [stderr], and exit code.  See example at [[`[open]`].


*** graph ***

   '''`navigate`''':   Takes the shortest path from the current node to some other node in a graph while keeping track of and avoiding dead ends.


*** iter ***

Very similar in spirit to [Generator].  Can be used with [[[for in%|%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 main ***

A script that sets up a coroutine arranges for another script to be evaluated under that coroutine after entering the [event loop], and uses the return options of the evaluation as the return value of the program:

 tclsh /path/to/interp/bin/main myscript arg1 arg2



*** 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%|%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.

   '''`product`''' ''`{list variables}`'':   Stores the product of the lists in the named variables, and stores the result in the first named variable, and stores the empty string in the remaining variables.

   '''`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.

   '''`zip`'''  ''`list var` ...'':   Interleaves the items in the named lists, stores the result in the first variable, and stores the empty string in the remaining variables.



*** 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.



*** list lcs ***

   '''`diff`''' ''first list'' ''`second list`'' ''`options ...`'':   Produces on [stdout] a traditional diff in a format indicated by the given options.  There are options to choose output format, number of lines of context, whether to take initial and trailing whitespace into account, whether to consolidate small breaks into larger differences, and whether to print line numbers.

   '''`diff file`''' ''`first file`'', ''`second file`'', ''`options ...`'':   Uses `diff` to process the named files.

   '''`lcs`''' ''`first list`''  ''`second list`'':   Returns the index in the first list, index in the second list, and length of the [longest common substring].  Instead of using a [dynamic programming] approach it creates a [dict%|%dictionary] of the items in the first list and then iterates through the second list and using the dictionary to find points in the first list to begin a comparison.

   '''`lcsmatch`''':   Uses `lcs` to divide and conquer to return all matching subsequences.



*** list ordered ***

======
package require {ycl list ordered}
======

   '''`ensure`''' `''list name''` `''value''` :   Inserts the given value into the right place in the named ordered list if it isn't already there.

   '''`insert`''' `''list name''` `''value''` :   Inserts the given value into the right place in the named ordered list.



*** math ***

======
package require {ycl math}
======

   '''`=`''' ''`variable name`?'' ''`args ...`'' :   A more concise version of `[expr]`.  Assigns the result to the provided variable name.  The default variable name is '''`expr`'''.

   '''`base`''' ''from'' ''to'' ''placesvar'':   Sums up the values in the variable named ''placesvar'' to obtain a value, converts it from one base to another, and assigns the result to the same variable.  Each place is a decimal value that is multiplied by the base to the power that place, where the last place is the smallest power.

   '''`count`''' ''`value operator`'':   Given a value and an operator that returns the size of a number of units, efficiently counts the units in the value, and returns the nuber of units and their aggregate size, as reported by the operator.



*** 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 `[expr%|%rand()]` function.



*** matrix ***

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



*** 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 create`''':   Create an ensemble for the given namespace named by the given name relative to the namespace of the caller.

   '''`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 orientation%|%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.

   '''`dupvars`''':   duplicates all variables in a namespace to another namespace

   '''`ensemble subcommands`''':   List the currently-available subcommands of a [namespace ensemble].

   '''`facade .new`''' ''`name`'' ''`object`'':   Creates a new routine named ''`name`'' relative to the namespace of the caller and extends ''`object`'' with a new routine, ''`facade`''.  The new routine acts as an interface to ''`object`'', making some subset of routines available.  When the facade is deleted, the object is also deleted.

   '''`object`''' ''`?name?`'' ''`?ns?`'':   Creates a new namespace and a new routine named ''name'' relative to the caller.  When the routine is called, the first argument is the name of a subroutine, which is resolved relative to the namespace of the object and called with the name of the object as its first argument and any remaining arguments after that.  Subroutines should not be defined in the namespace of the object, but in a separate namespace which can then be added to the routine lookup list of the object using ''`object`'' `extend` ''`namespace`''.



*** `ns public facade` interface ***

The `facade` routine added to an object by `public facade` supports the following routines:

   '''`add`''' ''name'':   Adds the named routine to the facade if it doesn't already exist.

   '''`name`''':   Returns the name of the facade.

   '''`remove`''' ''name'':   Removes the named routine from the facade if it exists.



*** package ***

   '''vcomp''':   like `[package vcompare]`, but accepts just about anything as a version string.



*** parse ***

   '''`tcl commands commands`''':   Split a Tcl [script] into its components.  This is `[cmdSplit%|%scriptsplit]`

   '''`tcl commands filter`''' ''`name`'':   Creates a new routine that filters incoming data into commands.  A filter understands `feed` and `bufer`.  `feed` adds data to the current buffer and returns any commands found so far.  `buffer` returns the current value of the buffer.

   '''`tcl commands iter`''':   Uses `ycl coro relay` to deliver the comands in a script read from a [chan%|%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 `[cmdSplit%|%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 [expr%|%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 [http://chiselapp.com/user/pooryorick/repository/ycl/artifact/93cdea1aac40f022%|%ycl::dir::iter], and  [http://chiselapp.com/user/pooryorick/repository/ycl/artifact/90bca3673c69e35d%|%ycl::ns::object]

   '''`after`''' ''`ms`'' ''`script`'':   A drop-in replacement for `[after]`  that associates the scheduled script with the current procedure, and automatically cancels the event when the procedure is deleted.

   '''`after proc`''' ''`name`'' ''`ms`'' ''`script`'':   This variation binds the scheduled task to the named procedure rather than to the current procedure.

   '''`[proc alias%|%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`''.

   '''`current`''':   Returns the fully-qualified name of the current procedure.

   '''`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.

   '''`[lproc]`''':   Like proc, except that the body is a list of lists and no string representation of the body is generated.

   '''`[procstep%|%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.



*** [Quick-Tk%|%quicktcl] ***



*** [ycl shelf%|%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}
======

   '''`{base decode 58 bitcoin}` ''`data var`'' ''`alphabet`'':   

   '''`{base decode 58 flickr}` ''`data var`'' ''`alphabet`'':   

   '''`{base decode 58 ripple}` ''`data var`'' ''`alphabet`'':   

   '''`base decode varname characters`''':   The inverse of `base encode`.   Decodes the sequence of bytes in the named variable using the givn list of characters, and sotres the result in the named variable.

   '''`{base encode 58 bitcoin}` ''`data var`'' ''`alphabet`'':   Encodes the data in the given variable into the base 58 alphabet of Bitcoin, and stores the result in the same variable.

   '''`{base encode 58 flickr}` ''`data var`'' ''`alphabet`'':   Encodes the data in the given variable into base 58 alphabet of Flickr, and stores the result in the same variable.

   '''`{base encode 58 ripple}` ''`data var`'' ''`alphabet`'':   Encodes the data in the given variable into the base 58 alphabet of Ripple, and stores the result in the same variable.

   '''`base encode varname characters`''':   Encodes the sequence of bytes in the named variable using the given list of characters, of which there should typically be some power of 2 up to 256, and stores the result in the named variable.  The encoding scheme is that the binary representation of ordinal value of each character in the list represents the next bit sequence.  All bit sequences are concatenated in order to produced the encoded value.  The number of bits in each sequence, i.e. the base, is derived from the number of characters provided to encode with.  In the last encoded character, only enough bits to bring the current bit count to 8 are part of the value.  The limitation of this scheme is that it can only encode bytes having an ordinal value up to one minus the length of the given alphabet.


   '''`{base decode mod bignum}`''' ''`data var`'' ''`alphabet`'':   Decodes the data in the given variable using the given alphabet, and assigns the result to the same variable.

   '''`{base encode mod bignum}`''' ''`data var`'' ''`alphabet`'':   Encodes the data in the given variable using the given alphabet, and assigns the result to the same variable.

   '''`cmp`''':   Like the [Unix] [http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cmp.html%|%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`''' ''`stringname`'' ?''`encoding`''?:   The inverse of `encode`, below.

   '''`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`''' ''`stringname`'' ?''`encoding`''?:   converts the the string stored in ''stringname'' to ''encoding'', which by default is the [encoding system%|%system encoding], assigns the result to that ''stringname'', returning an error if ''stringname'' can't be faithfully encoded. 

   '''`[ycl string expand%|%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.

   '''`prefix`''' ''`stringvar suffixvar`'':   Extracts from the value stored in the variable named `$stringvar` the prefix that precedes the suffix in the variable named `$suffixvar`, and store the result in `$stringvar`

   '''`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.

   '''`regsplit`''' ''exprs'' ''textvar'':   Splits the value of the variable named ''variable'' according to ''exprs'', which may be a branching expression but which must not contain any capturing parenthesis, and assigns resulting to ''variable''. 

   '''`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.

   '''`suffix`''' ''`stringvar prefixvar`'':   Extracts from the value stored in the variable named `$stringvar` the suffix that follows the prefix in the variable named `$prefixvar`, and store the result in `$stringvar`
   
   '''`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 @a@
    set b @b@
    expr {$a + $b + @expr@}
}]
======

*** string hash [blake3] ***
======
package require {ycl string hash blake3}
======

A [critcl] interface to the [blake3] reference implementation in [C].

   '''`string`''' ''`string`'':   Returns the [blake3] hash of the given string.

   '''`chan`''' ''`chan`'':   Configures the given channel to `-translation binary` and returns the [blake3] hash of the data in the given channel.



*** 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 [Dodekalogue%|%backslash-escaped] representation, and backslash is also escaped.


*** time ***

   '''`count`''' ''seconds'' ''report'':   Counts in `$seconds` the things listed in `$report`, which may be, `years`, `months`, `days`, `hours`, `minutes`, `seconds`, `weeks`, or `weekdays`.  Each item is calculated using the time remaining from the results of the previous calculation.  Returns a list of results in the order they appear in `$report`.  For accuracy, relies on `[clock]` for all time calculations.

   '''`diff`''' ''time'' ''time'' ''report'':   Calculates the differences between the two provided times, each of which is a list of arguments to `[clock scan]` and passes that result to `count` to produce the requested report.


*** tk_combobox_oakley ***

Assimilated from [Bryan Oakley%|%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
======


*** var ***

   '''`let`''' ''`varname?`'' ''`{inputvar alias?} ...?`'' ''`body`'':   When ''`varname`'' is needed and the variable does not exist or the value of any of the named variables has changed, [apply%|%applies] ''body'' with values of named variables as arguments and assigns the result to ''`varname`''.  If ''alias'' is provided for a variable the value of the variable is aliased to that for the evaluation.


*** visual ***

   '''`slides`''':   A simple [presentation program%|%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.




<<categories>>