Tag Archive: “tcl”

Yojimbo to Password Safe

I’ve written a script called yj2pwsafe which adds passwords exported from Yojimbo to Password Safe format database files. Password Safe is an open source password manager developed in part by Bruce Schneier. Many programs are compatible with Password Safe files. My script relies on code from Password Gorilla, a compatible application written in Tcl/Tk.

Downloads, details, and instructions on Github.

yj2pwsafe screenshot

I’ve updated yj2pwsafe to be more user-friendly since I first posted this announcement; it is now packaged as an Applescript app that presents a series of dialogs like the one pictured above.

Additionally, I’ve updated yj2pwsafe so that it can import serial number items exported from Yojimbo as well as password items.

Posted on Tuesday, August 20th, 2013.

An arcencode example

Arcencode is my Tcl implementation of the compression algorithm used by both MapQuest and the Google Maps API to encode a list of coordinates as a printable string. It can be used, for example, to obtain a relatively compact representation of a route that can be passed as a single parameter value to a web map.

path-700

Here is a GPX file exported from a map created with MapMyRun. It contains a track representing a route through a nearby park, pictured above. The track consists of 790 points, listed here in plain text form. If the contents of that plain text coordinate list are assigned to a variable named coordinates, the encoded form can be obtained with:

set encoded [arcencode $coordinates]

With line breaks added, the contents of encoded are:

q}g`GrlfnMPDND\DJ?L?T?P?N?N?N?P?VAPANANAPANAPANATGNELGXENANANCNANA^BNDPDNBNDNDND
NDPDNDNBNDNDPDNDNDNDVHNFPFNFNFNFPFNFNFNFPFNFNFNFPFNDNFNFPFNFNFNFVFNBPBNBNBNBVFND
PDNDPDNFPDNDPDNDPDNDPDNDPDNDPDNFPDNDPDNFPFNDPFNFPFNDPFNFPFNDZLHFJDNFPHNFNHPFNH\F
LAJ?V?F?PFNFNDNFNHZNLHNHLHLHLHNJLHLHT?N?PAN?PAPAVDPFNDNDPDNFNDPDNDNFPDNDPDNFNDPD
ND\JLDNBNDLDNDNBTFNDLBLDVDN@PBN@PBN@PBNBP@XHNHLFNHNFNFLHNFNFPVBNPVJFHHRLHFPANCPC
PAPAR?L@R@P@P?N@P@P@P@P@VFLDLFRHNFNFPFNFNFNFNFNFNFTLHFLPLNJLRTJHPJJDPBTAJCPGPGNE
PGNGPGNGNEPGNGPGNEPGNGNGPGNEPGZIJAJAVJLDLDRAPENCPCNCPENCPCNEPCXGNCLCNCNCPDPHTTJJ
HLHJLNJLLLRLLBPFRNJLJJJLJLTHL@T@L?N@THLHLHLHNLNJLLLJNJ\LL@N@N@L?N@ZALENCLCNENCRI
NGNELGZKNGNGNGNGNGNGNENGNGNGNGNGNGNGTUFQHOHOFQN[HOFMPYHKHINQJKLLHRHPHPHRJPHPHRHP
J^BPDRDPDVJVHNHPPNNJLHLHLJRFPFNDNDPFNDNDPFXHLFLDLDRFNFNDNDRBNBN@RENCPEPCNEXCH@P@
VJJHHHFBEWCSEUGSIUO[KOIMIMUWKMMKMMKMMMMKKMMMMMSMOGMIOIOGOIYQMIMIMGMIKIUMMKOIOKMI
OIOKMIOIOKOISKOEMGOEUCOCQAOAQCQAYCMAMCSEOEOEQCOEWCM@WBMBOBODOBUJMFMHMHMLOJMLWPMF
MFMFWFMBOBODYBO@O?O@O@O@SCOAOCQEOEQEQEOGQEOGWGMAU?M@O@QDODQBWFQBOBO@QBOBOBQBOBSB
O@QB[DOBOBODOBOBOBOBUDQDOBOBQDOBOBW?KEQGMGQ@QBQFOD_@NODOFODOFOFODOFODOFODOFOFODO
FODYJK@Q?SGKCOMKKQQKMKOKMOKUMOGOGOGOGOGOGOGQGOGWKIEOGWEQ?OAQAOAQ?OAQAOAQ?W?SGIIK
GKOKQMOOMMISCUHGFQGOGOIOGOIOGOIQIOGUGQAOCQAOCQAOCQAOC[GOEOEQEOCOEOEOEOEOEOESEOGQ
EOEQGOEQEOEQGUGOEQGOEOEOEQGOEU?Q?O@Q?O@O@YIOIMKMIOIMIOIMIMKQGQGOGOGOGYEM?M?Q@[GM
GOGMGMGMGUIMGOGWMKEMCQIQEOGOGQEOGOGOGQE[KQEOEOEQEOEOEQEOEOEQEOEOEQEOEOEQEOGOEQEO
EWEOCQCOEOCOC_@KOGOGOGOEOGOGQGOGOGOGOGOGOGOEOGOGOGOGOGOGOGWGOEQEOEQEOEQEOEQEOEQE
OEQEOEQEOE[AK@M@Q@Q@OBQ@QFOFOFWBO@Q@O@Q@O@Q@Q@U?O?Q?Q?O?Q?Q?O?]CKEMCME

Succinct, considering it encodes detailed geometry. A coordinate list of 790 corresponding points can be recovered from this block of text with the complementary arcdecode procedure:

set decoded [arcdecode $encoded]

The decoded coordinate list can be examined here.

An important proviso: this encoding scheme is lossy. Specifically, coordinate values are rounded to five decimal places. Compare the input coordinates to the decoded output for an example. Any precision can optionally be specified, but greater precision compromises the amount of compression. (Note that the Google Maps API is only compatible with five-digit precision).

How does this algorithm work? Google offers a technical step-by-step explanation. Essentially, compression is achieved by storing only the difference between each coordinate value and the previous value in the sequence; this requires fewer digits than storing each value in full, especially since precision is limited to a fixed number of digits. The values are packed into a printable Base64 representation in a way that eliminates the need for delimiters between coordinate values: values are bit-shifted left before output, and the ones place is used to mark whether the subsequent character represents a new coordinate or a continuation of the same value.


I updated my WheresThatSat site to use JavaScript and (on the Twitter bot side) Ruby implementations of this algorithm. It’s an appropriate application – previously, satellite ground tracks were encoded as a repetitive sequence of separate point parameters. In addition to yielding somewhat shorter URLs, this compression method ensures the correct point sequence is preserved even if the URL parameters are re-ordered.

Posted on Sunday, March 3rd, 2013.

Tcl Doctools for BBEdit

Doctools syntax highlighting and preview filter screenshot

Doctools is a Tcl-based markup language suitable for writing software documentation. BBEdit is a Macintosh text editor. I made a Doctools language module (for syntax highlighting) and preview filter and posted them on Github as Tcl Doctools for BBEdit.

Posted on Thursday, December 13th, 2012.

Screenshots of Selected TKLib Examples

Tcllib (the Tcl Standard Library) includes a number of user interface components, known collectively as TKLib. The documentation is good, but includes no illustrations or screenshots. Here are images of how a few of the visually interesting examples appear on Mac OS X 10.6.4 with Tcl/Tk 8.5.7.

Ctext

Ctext is an enhanced text widget with support for syntax highlighting and other features. Here’s the example (it displays its own main procedure code):

Plotchart

Plotchart is a package for creating charts and graphs. Here’s the xy plot from the description:

Here is the bar chart from the resizing example:

Swaplist

Swaplist provides a canned dialog for exchanging items between two lists. Here’s the example:

Posted on Wednesday, June 30th, 2010.

Kitgen Build System for Tcl/Tk

In the past I have written a variety of posts about Starkits and Starpacks. Briefly, Starkits provide a way to package complex Tcl/Tk programs in a single file, and Starpacks allow those packages to be combined with self-contained interpreters to deliver stand-alone applications. However, the Tclkit interpreters I originally used for this purpose have not generally been maintained, at least for Mac OS X (Pat Thoyts has done a good job providing current Windows and Linux versions).

Of course, there are various ways to build your own Tclkit equivalent, but I usually found the process slightly too tedious to sustain my interest (although I did succeed with Pat’s version of kitgen shortly before discovering the method described below).

As it turns out, self-contained Tcl/Tk installations functionally equivalent to Tclkits can quite easily be created with the kitgen build system. This comprises a single Tcl script (kbs.tcl) that automates the process of downloading, compiling, and assembling the elements of a “kbskit”. The script is robust – it worked successfully on the first try, without any knowledge of what options to use beyond those given in the Quick Start examples.

If you simply run a fresh copy of kbs.tcl, it will retrieve the Tcl/Tk sources.

Build a Metakit-based kbskit (like Tclkit) with:

./kbs.tcl -r -mk install kbskit8.5

Build a Vlerq-based kbskit (like Tclkit Lite) with:

./kbs.tcl -r -vq install kbskit8.5

In either case, three executables will actually be built:

  1. A Tcl-only executable, denoted by -cli suffix
  2. An executable that loads Tk from an external library if needed, denoted by -dyn suffix
  3. An all-in-one Tcl/Tk executable, denoted by -gui

On Mac OS X, these executables are found in the buildDarwin subdirectory relative to kbs.tcl. The subdirectory name will presumably differ on other operating systems.

Happily, the kbskits created with the kitgen build system can be used with Starpacker. Check the “Other” box and select the kbskit you prefer to use as the executable in your Starpack:

You can bundle other packages into your kbskits using the -mk-bi or -vq-bi options (-bi stands for “Batteries Included”). This will ensure that those packages (typically useful extensions) are always available to code being run by that kit. Of course, a different approach, with different advantages and disadvantages, is to bundle packages in your application Starkit, which can be executed with different kits.

Additional topics to explore include building the --enable-aqua option and the best method to update both kbs.tcl and the source code it retrieves.

Posted on Sunday, January 10th, 2010.

LDTrim

LDTrim is a simple program that condenses or formats LDraw code by trimming extraneous characters like spaces – or inserting them to align values in columns.

LDTrim was developed to help “pretty-print” examples for documentation or discussion, but it could also be used to reduce file size or to standardize the format of many models.

Much of what LDTrim does is already possible with LDraw Design Pad. For example, see “Trim Lines” and “Auto Round Selection” under the “Tools” menu.

Usage

Here is the output of ldtrim -help:

LDTrim 1.1
Usage: ldtrim                         Default:
    [-in FILE]  | [-in FILE FILE...]    stdin (use -ing to glob wildcards)
    [-out FILE] | [-out DIRECTORY]      stdout
    [-precision DIGITS]                 all significant digits preserved
    [-trim zeros|none]                  zeros (trims redundant trailing zeros)
    [-justify left|right|none]          none (alignment of values in field)
    [-invalid omit|keep]                omit (keep retains unrecognized lines)
    [-width CHARACTERS|max]             variable (minimum width of all fields)
    [-1..15 CHARACTERS]                 variable (override width for one field)
    [-h|--h|-help|--help]               display this usage summary

If multiple input files are specified without -out, they are modified in place.
If -out is given with multiple input files, output is saved to that directory.

The -precision option causes values to be rounded down and may append zeros to
reach the specified precision unless -trim zeros is explicitly specified.

Whitespace between fields is condensed to a single space.

The -width option pads values with spaces to reach the specified field width.
If -width max is given, the widest value is used as the width for all fields.
(Sub-part names are ignored for this comparison.) If a field value exists that
is wider than the requested width, that width is used as the field width.

Right justification is used if -width or -1..15 is specified without -justify.
If none of -width, -1..15, or -justify is specified, fields are unaligned.

If environment variable GATEWAY_INTERFACE is defined, LDTrim is a CGI script.

Example

Suppose you have saved this LDraw code as sample.ldr:

1 0 20.000000 0.000000 20.000000 0.000000 -1.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 4085c.dat 1 1 28.000000 7.000000 27.000000 0.000000 -1.000000 0.000000 0.500000 0.000000 -0.866025 0.866025 0.000000 0.500000 3023.dat 1 25 36.000000 -5.000000 11.000000 0.000000 -1.000000 0.000000 0.707106 0.000000 -0.707106 0.707106 0.000000 0.707106 2412b.dat 

Running ldtrim -in sample.ldr -out trimmed.ldr will save the following as trimmed.ldr:

1 0 20 0 20 0 -1 0 1 0 0 0 0 1 4085c.dat 1 1 28 7 27 0 -1 0 0.5 0 -0.866025 0.866025 0 0.5 3023.dat 1 25 36 -5 11 0 -1 0 0.707106 0 -0.707106 0.707106 0 0.707106 2412b.dat 

The default behavior is to condense the code as much as possible without modifying the model. Alternatively, you can use LDTrim to reformat code. For instance, ldtrim -precision 2 -width 5 -1 1 -2 3 -in trimmed.ldr -out aligned.ldr outputs the following as aligned.ldr:

1 0 20.00 0.00 20.00 0.00 -1.00 0.00 1.00 0.00 0.00 0.00 0.00 1.00 4085c.dat 1 1 28.00 7.00 27.00 0.00 -1.00 0.00 0.50 0.00 -0.87 0.87 0.00 0.50 3023.dat 1 25 36.00 -5.00 11.00 0.00 -1.00 0.00 0.71 0.00 -0.71 0.71 0.00 0.71 2412b.dat 

Giving a minimum field -width argument implies -justify right. Similarly, decimal -precision implies -trim none, leaving trailing zeros intact. The -1 and -2 options override the minimum width for the first two columns.

Batch Mode

If LDTrim is given multiple input files, it will process them all, saving the results to files of the same name in the directory given by -out or overwriting the input files if no output folder is given.

ldtrim -in $LDRAWDIR/parts/*.dat -out /trimmed/parts/ 

Note that with a single -in file, -out is interpreted as a single output file, but with multiple -in files, -out is interpreted as a directory to contain the results.

Web Interface

LDTrim has a rudimentary web interface built in. If the GATEWAY_INTERFACE environment variable is detected, LDTrim will behave like a CGI script. Specifically, it will print an HTML form with controls that roughly correspond to its command-line options. LDraw code posted via this form (to itself, as the action ldtrim) is processed according to the selected options. The results are returned in the same form.

Download

LDTrim is also available as a platform-independent Starkit (50 KB) which requires an 8.5 Tclkit.

The current version of LDTrim is 1.1; it fixes a bug that caused malformed line endings to be output on Windows.

Posted on Saturday, May 10th, 2008.

List splicing with foreach

Tcl’s foreach command is commonly used to iterate through items in a list. However, I had not realized that it can step through more than one list at once. Here’s a handy application of this property based on an example from the documentation:

proc splice {l1 l2} {
    set s {}
    foreach i $l1 j $l2 {
        lappend s $i $j
    }
    return $s
}

This procedure combines two lists into a new list comprised of alternating items from each input:

% splice {a b c} {1 2 3}
a 1 b 2 c 3

One use for this is to join a list of keys to a list of values to establish a dictionary or an array:

% set dimensions [splice {length width height} {10 16 33}]
length 10 width 16 height 33

% dict get $dimensions height
33

% array set d $dimensions
% set d(width)
16

So if you’ve got an ordered list of values you’d like to access as named fields, you can combine it with a list of field names using foreach and be on your way.

Posted on Monday, April 28th, 2008.

Starpacker

Starpacker is a utility that helps join Starkits and Tclkits to create stand-alone Starpacks. This can already be done with SDX, which is a superior tool in many ways, but Starpacker provides a simpler interface to this particular aspect of SDX.

Starpacker Mac OS X Screenshot Starpacker Windows Screenshot

More extensive help is included with the program.

Demonstration

Drag an application Starkit onto Starpacker, select a Tclkit, and click Pack to create a stand-alone executable for the indicated platform. The Tclkit is downloaded automatically if needed. (May not work with all Starkits.)

I recommend watching the video full screen for maximum clarity.

Download

Posted on Wednesday, March 26th, 2008.

Pascal’s Triangle

Recently I was introduced (or perhaps reintroduced) to Pascal’s Triangle, an arrangement of integers that lends itself to a variety of purposes, including binomial expansion. I’ve written a little program to explore this aspect of the idea.

Explanation? Bah. Experiment!

Features

Screenshots

Mac OS X looking at a large expansion Windows as seen on WINE X11 (has font issues)

Download

Posted on Monday, February 25th, 2008.

Msgcat and Mac OS X

The Tcl core library includes msgcat, a package which facilities program localization. msgcat provides means to define a catalog of messages in multiple languages and a procedure to retrieve messages appropriate to a specific locale, typically determined by cues from the operating system.

In general, to localize puts "Hello, world!", you provide equivalent strings for each supported locale and select the appropriate one at runtime by stating puts [mc "Hello, world!"]. For example, this command might print ¡Hola, mundo! if the locale is es. Default strings in the programmer’s native language can usually be used as keys to the message catalog.

Anyway, msgcat looks at a couple environment variables (or the Windows registry) to determine the proper locale. On Mac OS X, this works fine for scripts launched from the command line, but spiffy desktop applications don’t necessarily have access to the same environment variables. If no supported environment variables are available, msgcat uses the locale implied by the “Region” setting of the “Formats” pane of Mac OS X’s “International” system preferences. You can query this string from the command line with:

defaults read 'Apple Global Domain' AppleLocale

It is also available from within Tcl as the variable ::tcl::mac::locale.


To test localized Tcl desktop applications on Mac OS X without changing your system region, you can define the locale in ~/.MacOSX/environment.plist. Environment variables specified in this file are available to programs launched from the Finder, so msgcat will see these settings before resorting to the system locale. For instance, to set the locale to es, add this property to environment.plist:

<key>LANG</key>
<string>es</string>

See QA1067 for more information about environment.plist, including how to create it if it does not already exist. Note that variables defined in this file will be visible to all programs, and may therefore affect other applications.


Here’s how I usually comment the code I use to initialize msgcat:

# localization courtesy of Message Cat:
#
#  |\        /|
#  | \______/ |
#  /  _    _  \
#  | <l>  <l> |
#  \    __    /
# ----- \/ -----
#  --\__/\__/--
#

Posted on Tuesday, January 29th, 2008.