<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox where print preview displays the noscript content */
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

Also see [[AdvancedOptions]]
[[.javarc]] set's the users CLASSPATH Environment variable for the training system's [[Java Runtime|http://www.google.com/search?q=Java+Runtime]] Environment.
setenv CLASSPATH .:/home/fts/joal/comFidessaInf.jar
*[[sources|]] the Java Runtime
*set's the users shell to bash,
*and command prompt to report
**the ''us''er id,
**the short version of the ''h''ost computer name
**the short version of the ''w''orking directoy
*and adds ''~/student/bin'' to the user's PATH
source  .javarc
setenv  SHELL   bash
setenv  PS1     '\u@\h.\w\$ '
# ~ Champions are Leaders...so if the candidate is leading a ~ related project, a ~ community, or an online ~ portal they will be considered.
# ~ Champions are Luminaries in their field.... so the candidate should be a ~ engineer or architect that is relatively senior and has lots of experience, they should be considered.
# ~ Champions should have Credibility. The candidate can be neutral, for, or against a vendor. Also, a Champions can still write anything or publish any material that may be pro, neutral or con towards a vendor; unless there is a litigious issue. (We've had a lot of Champions ask about this...so we state this here).
# ~ Champions are involved with some "really cool" applications of ~ Technology or are involved with some sort of humanitarian or educational effort. The application must be openly available to the ~ Community (online or in print) vice a company proprietary or government classified project
# ~ Champions are able to Evangelize or influence other developers through their own professional activities (Example: Consulting, University Professors, Book Authorship, etc.) 
Tonight, I discovered the SPA family of tools, of which this Wiki is an excellent example. My first addition to the tools is from [[NextAction|http://www.trimpath.com/project/wiki/NextAction]]. It's my ToDoList and DoneList replacement. Let's see how this goes down.
It's early ( < 8 am ) on Monday morning. I arrived on the same elevator as Carol T, our office manager. She is telling her story of that day, 5 years ago, when it was her duty to call everyone on the staff to verify their where-abouts. She said they had five employees at the Trade Center, all of whom made it out. The only loss from the day, was a woman who'd started the day before, and was not yet at the office. She turned around on the way in and didn't stop until she got to the midwest, and is now in California.
I've wrapped this up on Tuesday, the second day of our New Hire Training. Sandi A and I are confident we can give the first three days, anyway.
A day on which Patty and I returned from Fran and Scott C in Ashburn VA. This was their 3rd (of four) annual New Year's Eve we've been able to attend. Guests include Ed and Carol B, of NYC, Carol's sister Jean, and new boyfriend Tim M, us folks, and for last night's party, Kevin J and his new girlfriend, Bolling. There was lots of bridge played. I am able to get "into it" much better than I used to, and after the first few rubbers, where I feel particularly competitive, the hands this morning were much more easy going and enjoyable.

Also, and in other quarters, I'm working on the programming language, cummings. It grew out of my work with my current company (fidessa)'s expression evaluator. 
Just a thought, as my boss describes a video game to an office-mate. Maybe Don R (recent Defense Secy) bought the myth: that the subject of war had been reduced to a video game. For a while, I've been among those lauding our fighting power because "Our toys are more able than their best weapons". The inapplicability of that statement to present reality is favorably compared to my cold-war (60s - 70s) observation that we were playing football while the Soviets were playing chess. While the results of that game are in -- the football players beat the chess players, except the chess players did it for a lot less effort. 

So, the question of well-trained video gamers is still up for grabs.
Idea du jour: which I may have had previously, but at least now it's concrete:
*a macro-processor editor, based on M4, which
*simultaneously displays the source text and the expanded text.
*it could be done in emacs:
**everytime a key is written, it updates another buffer, or
**at a minimum, a batch process to read-write
The idea of a separate process, with an eye on the raw and expanded text is attractive. Frankly, the idea developed while looking at the highly redundant text of the Fidessa Expression Evaluator FBL Fields configuration file.

And here's a documentation, user interface idea, less well imagined: in addition to the static pix in the document, present the features as a mini-application where the separate features may be called in. 
Today I read KurtVonnegut's SlaughterhouseFive.   He died earlier this month, and I was in need of some reading, it was a good trip.  He and BillyPilgrim were in Dresden the night of Feb 13, 1945 when I was six months old!  It was the moment of his life.
Today I've made a spreadsheet ( Ah -- to Google docs! ) which captures the distribution of my ratings on the [[LibraryThing|http://www.librarything.com/catalog/applemcg]].  The goal is to force myself to objectively rate my books in a binomial distribution.  Not all books can be a "5", the maximum.   While it's likely that a reading program promotes reading better books, it's not unreasonable some are better than others.    Forcing a binomial distribution means that I will have few 5's than 4.5's etc..  From the bottom, lets say no book is worse than a 2.5,  then there will be more 3's than 2.5's etc.

Let's take a minute to put the [[spreadsheet on Google Docs|https://spreadsheets.google.com/ccc?key=pKsWDeZ9dHGGdwsh9sZHoVA&hl=en]], as promised, and you can look for yourself.
Let's begin with just a few words today, in the likelyhood that we can save some for tomorrow.

[[Scott Simon|http://www.npr.org/templates/story/story.php?storyId=3874941]]'s just closing down his show on the radio upstairs, from where I just came to this HP pavilion notebook Katie brought home from Seattle a few years ago. I've got my coffee resting on [[Anthony Arthur|http://www.anthonyarthur.net/works.htm]]'s essay in today's NYT:  Blood and Oil, a review, a brief history on how //There Will be Blood// came to the screen and Oscar prominence.
Today, Sunday, thoughts come from the editorial pages of the NYT.  Don't worry, since we get the weekend edition, we'll find other sources.  Friday, during [[The Holy Hour|http://www.pbs.org/newshour/bb/white_house/jan-june08/sbdebate_02-22.html]], Pat was a little upset about the implications of what it takes to get people's attention in a scandal -- this one being the nature of John McCain's relationship with a 30-something lobbyist.   In today's NYT's //Public Editor// we receive a fairly easy-to-follow timeline of events, and the level of involvement.   Since only one person went on record, she was concerned about how biased the media was in jumping to conclusions.   After 3 passes at the piece with the Tivo, we felt we pretty much had the some impression:  it was more "in the mind of the beholder" than in Ms Iseman's behavior.

Which today's [[Public Editor|http://www.nytimes.com/2008/02/24/opinion/24pubed.html?ref=todayspaper]] confirmed while handing down the judgement the NY Times (and its managing editor, Bill Keller) were too hasty in their haste publish.    
I'm writing this on my "new" (2nd attempt, which may still be faulty) iMac, as the fan in running at 5:43 a.m.    

The thought of the day is to write a chastening letter to Stephen Carter for his rather spiteful treatment of journalism as a profession in his book: //Integrity//.   I'll let the letter eventually speak for itself.   In the very next chapter, he takes on the legal profession, but not with the same enthusiasm he affords his arguments against journalism.   The thread of my piece with be that despite plenty of evidence in support of his claims, journalism is about truth, honesty, and by implication integrity.   The law is merely about justice, and that claim is usually tempered with an apology like, "we're not here for the truth, merely justice."
with a few minutes to spare.

the machine is working.  it was the last-week-familiar [P] [R] [alt] [opt] in combination with the power key.  first power and release; then wait for the 2nd beep, really a horny chime!   we're on the air, and time for bed.

carter was a little better, if not tedious, today, and his dicussion about the marriage contract.  did you feel he was repeating himself?    

and cummings is now back in the local source tree.   time to get my sql working in here?!

good night mrs calabash....
Tis a fine day indeed.

to return home to a working computer!   

and not having to spend a minute in the classroom.   david is good in that he's willing to spend time in the needed team-building with sandi and me.    but it's still the knee that's bothering me.    

now my "commuting book" spends the night in the car, saving me from having to think about it going out the door in the yet-to-see-my-first-cup morning.   and in the evening, it's now, on the 5:05 - 5:46 to linden possible to acheive elizabeth before the sun sets.  and really, the first evening where it was visible coming out of the tunnel.   but sleep was so short last night, i was dozing for a good way
art's booklist:
> fluxx, San juan, Russia rails, munchkin, and robo rally,
> Innovator's Dilemma,
> //Art of Unix Programming//, by Eric Raymond
by the way,  they (art protin and barb howe) tell us they are leaving for New Zealand.  art next month, barb and daughter lucy when they either sell the house, or art get's a job.
good luck,
AmericanGods, is by NeilGaiman, from HarperTorch, 2002.  Gaiman had collaborated with TerryPratchett on GoodOmens in 1993.   Our MIT book club read the later for our September 2008 gathering.  Norm B loaned me the Gaiman solo.  This is mostly for Norm, and cross-posted on [[The Library Thing|http://www.librarything.com/catalog.php?view=applemcg&deepsearch=gaiman]].  

Norm, I get it.   Or let me tell you how I get it.   Gaiman (and possibly Pratchett) believe we all have Nine Lives  (that was a plot spoiler), but never come out and say so.   When is someone dead?  seems to be one of the questions.   And how does one become a (small 'g') god?    Well, here's what I think.

We all have a supply of //lives//, at least one lived in what we perceive as //living//.  Some are lived in what we call //dead//, except we're not really dead, as in the classic sense.   I got to wondering how all these dead or semi-dead people wandering around aren't spotted by us, the living.    Well they (or we :-)) are spotted.  Looking at the bag-ladies, the derelicts on the One Line to South Ferry, the many marginal-looking,  these are the favored among us, who get "other" chances.   And there are others.  Some more //conscious// of their other-ness than most.    And how does one become a god?    Well there are initiation ceremonies, such as hanging on a tree for nine days.   Apparently, the theme in this book is that all these gods, old and new, were elevated to their godly status by persisting in their subsequent lives until they scammed enough people and other later-lifers they were indeed special, a cut above the others.   Once in the later-life state, you were more savvy than the normal living, your aging processes slowed, if not halted, but your biological needs continued, though for some reason, you couldn't really starve or "die" of thirst.  You did gain access to magic //waters// that were ordinary to ordinary folks.   You ate food for some sort of satisfaction, but not really for taste, either.  Strange.    

Of course the point of the climatic battle was for Gaiman have Shadow utter some of his own philosophy -- that someone else, offstage has really set this all up as another two-player, seemingly hostile opponents, scam.   I now recall (actually from time to time, but this time memorably, thanks Norm) of an old farmer at the '59 or '60 Swift Co fair in my home state of MN (another reason why I liked AmericanGods -- Gaiman, not unlike WilliamLeastHeatMoon in BlueHighways spent a good deal of time on the roads there) was being button-holed by an organizer of the JohnBirchSociety.   Well, the bircher was convincing the poor farmer that this seeming conflict between China and Russia on their looooonggggg common border was just a sham to lull the western allies, the free world, if you will, into a sleep so they could pounce on us.  A modern Trojan horse, outside the walls as it were.   So that's what Gaiman's telling us about the apocalyptic battle between the old and new gods.   Some had arranged it just to feed their own ego and sense of power.

And as for re-incarnation.  Gaiman sort of suggests it's what's happening when gods migrate, from the old world to the new, for example.   One god come over in the head of a normal living person, who of course doesn't know it, and probably didn't exhibit any signs of the god while inhabited, as it seems the more practiced were skilled in anonymity.    Like a spider.  But that sort of inhabiting isn't reincarnation, it's just transportation.    One can later assume a recognizable form.  But not as "someone else".    You are who you are.   Over the centuries, you can change your name to keep up with the times.     

I read this book on the heels of GunsGermsandSteel, in which JaredDiamond pins down the moment when all continents started off with the same potential for developing modern civilization.  Gaiman dramatizes the final scenes in this history with the migration of the clan (not yet tribe) over the land bridge in the Bering Strait.  Gaiman's points about why America isn't good territory for gods may be what Diamond is saying as well.   It leads one to speculate what will happen in Eurasia for the next thousand years.  If Gaiman is right, some of us can count on being witness.

Also, in the last month, anticipating the club's next meeting, we read GabrialMariaMarquez' OneHundredYearsofSolitude, another fantastic view of life and death.   Only with Marquez'  ..Years, there are no gods, as such, but only magicians, readers of the future, and some who drop in an out of the present.   There, it's more visionary.  What those of us in this life are granted to see.   In Gaiman's ..Gods, not only does one see this other existence, if you know precisely when and where to take that right turn, when and where (without thinking about it) to pluck the gold coin from the air, ...   Where Marquez operates on the surface, Gaiman operates //in// the earth, as when Shadow hangs on the tree, or plunges into the lake.   

In both books, characters re-appear.  In ..gods, you wonder who is who.   "Who is that in the shadows?"    

And, back on earth, and in the book, Gaiman's prose is much more accessible to the American reader, than I felt was the case with Pratchett's.  His is for those who know the alternate meaning of a phrase, making up, "chestnuts roasting caught the old krone's eye".   With Pratchett, you need to know if the chestnuts came with catcher's mitts or was it the other way 'round.

Good night Ms Calabash.
Note the three month interval between journal entries. Well about 3 weeks ago, I soaked my 256 MB stick in a Manhattan. It didn't take long for the alcohol to degauss the memory.

OK, here's another way to screw it up: have the PC's on the floor. Today, [[1 August 2006]], with my thumbdrive in the front of the PC, at my feet, I hooked the neck cord with my foot as I was swinging it past the PC. The momentum yanked the thumb out, and bent the USB connector within an obtuse angle of it's life. Thank god for the designers. I'm still able to write.

So that's the lesson: back up the memory stick daily. 

The big problem with keeping track of it seemed solved. Though, the current edtion was a 128-er I'd bought the prior year, and handn't used since the summer. Also, it's a pocket model, as the neck dongle attachment is missing.
A half-dozen trips back and forth to school persuade me I can hang on to it.

Time for an upgrade! Since October '06, while at royal''blue'' Fidessa, I'm now up to 512 MB!
I don't look at a directory -- visual (Mac OS X or winDoz), emacs, or shell ls, where I don't feel it's time to invent a //balanced directory// metric and tool to help shape up my trees.   A strategy would be to develop and report a metric.  The better way to do focus on reducing the imbalance is produce an imbalance index:  0 is balanced, large numbers are more imbalanced.  Here are the metric elements:
*a directory with only files has 0 imbalance
*a directory with on only directories has imbalance inherited from it's children;
**the largest
**the //n//th largest
**the median
**the average
**the geometric mean
*a directory with files and directories has imbalance by adding a factor times the files to the imbalance of the children directories.
seeing as how it's only worth doing on a unix machine, we can assume
*//dot//files dont count, and
*we can take advantage of the files to collect results in a file ''.imbalance'' which has the result for the subdirectories
I was introduced to his work, only recently, and thoroughly enjoyed his "Guess Who's Coming? ...", which was set in Cranford, but more for his turning the tables on the original, with Tracy, Hepburn, and Poitier, speaking of class.  Watching his role there critically, he was up to it, never had to play it down, and was a credit to his craft.  

I was hoping to see more of his work; now it will have to be a retrospective.

See ya 'round, Bernie.
<html><a target="_blank" href="http://www.google.com/calendar/render?cid=marty.mcgowan%40gmail.com"><img src="http://www.google.com/calendar/images/ext/gc_button1_en.gif" border=0></a></html>
<<tiddler LaTexEqn with: "a^2 + b^2 = c^2">>
Reading CornelWest's 2004 DemocracyMatters inspires me to write this review, a good deal in support of RayDubuque's LiberalsLikeChrist.

West's central ideas:
*in any group, such as a religion, state, political party, artistic community, ethnic group, ... there are two kinds of people -- the democrats and the imperialists.   speaking of religion, he divides them as the prophetic voices and the Constantinian voices,
*as a sequel to RaceMatters, DemocracyMatters may be viewed through the lens of racism
*//matters// is both a verb and a noun -- which reminded me of //Like// in LiberalsLikeChrist.  e.g. DemocracyMatters:
**verb:  as in democracy //does// matter, and
**noun:  as in //things// of democracy.
*it will be necessary to engage the youth culture, and engage them where they are.  for example, hip-hop has both //democratic// and //imperialistic// components.
*a quatro of writers, classically Emerson and Melville, and lately JamesBaldwin and ToniMorrison have been democratic, anti-imperialist voices of strong influence.
*West, himself a Christian, highlights Jesus prophetic and //democratic// message.   
*he offers insights to the Palestinian/Israel dilema, pointing to democratic 
January 01, 2006
Thoughts on Language Design
New challenges require new solutions
Guy L. Steele Jr.
Guy Steele, an engineer who knows something about designing programming languages, explains why new challenges require new solutions.

Guy is a Sun Fellow, Distinguished Engineer, and Principal Investigator at Sun Microsystems Laboratories. Along with James Gosling and Bill Joy, he wrote the original specification for Java. Guy is also the recipient of the 2005 Dr. Dobb's Journal Excellence in Programming Award. He can be contacted at guy.steele@sun.com.

It was back in Fall of 1971 that I began to write my first Lisp interpreter, for a 16-bit minicomputer, the IBM 1130. I based my design on documents from MIT about its Lisp system for the PDP-10, but I fiddled a bit with the language, partly because the 1132 printer on my IBM 1130 didn't have the same character set as on the Teletypes at MIT. In particular, the printer didn't have double quotes, and single quotes are used for something else in Lisp, so in the end I had to use commas as my string delimiters. (Fortunately, Lisp syntax didn't use commas for anything else at the time.) 

Source: [[Dr. Dobb's : Thoughts on Language Design : January 1, 2006|http://www.ddj.com/architect/184406382;jsessionid=XALVYY5L0KCKQQSNDLRSKH0CJUNN2JVN?_requestid=173560]]
after an 11-person ladder:
#Sherry H
#John H
#Joe H
#Dickie H
Lessons learned: pair people in the first round by
*rounding up to the next power of two = 16
*add one = 17
*pair people off from the bottom so their rank = 17
**11 and 6, 10 and 7, 9 and 8.
**others get a bye
*remaining brackets proceed for the declining powers of two, plus one, as if the higher ranks had won.
**deliclining powers: 9, 5, 3
**therefore 8 and 1, 7 and 2, 6 and 3, 5 and 4
**next 4 and 1, 3 and 2,
**finals 2 and 1
Go to Clinton vs. McCain
Previous report
Next report
Main page

Source: [[Election 2008: Presidential, Senate and House Races Updated Daily|http://www.electoral-vote.com/evp2008/Obama/Maps/May17.html]]
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Description|interactively select/export tiddlers to a separate file|
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
2009.04.30 [2.9.1] custom fields in CSV output
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 [0.0.0] development started
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 9, revision: 0, date: new Date(2009,4,19)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers='<<exportTiddlers inline>>';

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		tooltip:'Export selected tiddlers to another file',
		content:'<<exportTiddlers inline>>'

config.macros.exportTiddlers = {
	$: function(id) { return document.getElementById(id); }, // abbreviation
	label: 'export tiddlers',
	prompt: 'Copy selected tiddlers to an export document',
	okmsg: '%0 tiddlers written to %1',
	failmsg: 'An error occurred while creating %1',
	mergeprompt: '%0\nalready contains tiddlers.\n'
		+'\nPress OK to merge new/revised tiddlers into existing file.'
		+'\nor, press Cancel to completely replace the file contents',
	mergestatus: 'Merged %0 new/revised tiddlers with %1 previously saved tiddlers',
	statusmsg: '%0 tiddler%1 - %2 selected for export',
	newdefault: 'export.html',
	datetimefmt: '0MM/0DD/YYYY 0hh:0mm:0ss',  // for 'filter date/time' edit fields
	type_TW: "tw", type_PS: "ps", type_TX: "tx", type_CS: "cs", type_NF: "nf", // file type tokens
	type_map: { // maps type param to token values
		tiddlywiki:"tw", tw:"tw", wiki: "tw",
		purestore: "ps", ps:"ps", store:"ps",
		plaintext: "tx", tx:"tx", text: "tx",
		comma:     "cs", cs:"cs", csv:  "cs",
		newsfeed:  "nf", nf:"nf", xml:  "nf", rss:"nf"
	handler: function(place,macroName,params) {
		if (params[0]!='inline')
			{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
		var panel=this.createPanel(place);
	createPanel: function(place) {
		var panel=this.$('exportPanel');
		if (panel) { panel.parentNode.removeChild(panel); }
		var fn=this.$('exportFilename');
		if (window.location.protocol=='file:' && !fn.value.length) {
			// get new target path/filename
			var newPath=getLocalPath(window.location.href);
			var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\'); 
			if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		return panel;
	togglePanel: function(e) { var e=e||window.event;
		var cme=config.macros.exportTiddlers; // abbrev
		var parent=resolveTarget(e).parentNode;
		var panel=cme.$('exportPanel');
		if (panel==undefined || panel.parentNode!=parent)
		var isOpen=panel.style.display=='block';
			anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,'none'));
			panel.style.display=isOpen?'none':'block' ;
		if (panel.style.display!='none') {
		e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
	css: '\
		#exportPanel {\
			display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\
			background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
			border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
			padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;\
		#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
		#exportPanel table { \
			width:100%; border:0px; padding:0px; margin:0px;\
			font-size:8pt; line-height:110%; background:transparent;\
		#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
		#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
		#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
		#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }\
		#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }\
		#exportPanel .box { \
			border:1px solid black; padding:3px; margin-bottom:5px; \
			background:#f8f8f8; -moz-border-radius:5px;-webkit-border-radius:5px; }\
		#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
		#exportPanel .rad { width:auto;border:0 }\
		#exportPanel .chk { width:auto;border:0 }\
		#exportPanel .btn { width:auto; }\
		#exportPanel .btn1 { width:98%; }\
		#exportPanel .btn2 { width:48%; }\
		#exportPanel .btn3 { width:32%; }\
		#exportPanel .btn4 { width:24%; }\
		#exportPanel .btn5 { width:19%; }\
	html: '\
		<!-- target path/file  -->\
		export to path/filename:<br>\
		<input type="text" id="exportFilename" size=40 style="width:93%"><input \
			type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
			onclick="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
		<!-- output format -->\
		output file format:\
		<select id="exportFormat" size=1>\
			<option value="TW">TiddlyWiki HTML document (includes core code)</option>\
			<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>\
			<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>\
			<option value="CS">Comma-Separated Value (CSV) data file</option>\
			<option value="NF">RSS NewsFeed XML file</option>\
		<!-- notes -->\
		<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
		<!-- list of tiddlers -->\
		<table><tr align="left"><td>\
			<a href="JavaScript:;" id="exportSelectAll"\
				onclick="config.macros.exportTiddlers.process(this)" title="select all tiddlers">\
			<a href="JavaScript:;" id="exportSelectChanges"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">\
				&nbsp;changes&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectOpened"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">\
				&nbsp;opened&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectRelated"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">\
				&nbsp;related&nbsp;</a> \
			<a href="JavaScript:;" id="exportToggleFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="show/hide selection filter">\
				&nbsp;filter&nbsp;</a>  \
		</td><td align="right">\
			<a href="JavaScript:;" id="exportListSmaller"\
				onclick="config.macros.exportTiddlers.process(this)" title="reduce list size">\
			<a href="JavaScript:;" id="exportListLarger"\
				onclick="config.macros.exportTiddlers.process(this)" title="increase list size">\
		<select id="exportList" multiple size="10" style="margin-bottom:5px;"\
		<!-- selection filter -->\
		<div id="exportFilterPanel" style="display:none">\
		<table><tr align="left"><td>\
			selection filter\
		</td><td align="right">\
			<a href="JavaScript:;" id="exportHideFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>\
		<div class="box">\
		<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>\
		<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
			<select size=1 id="exportFilterStartBy" \
				<option value="0">today</option>\
				<option value="1">yesterday</option>\
				<option value="7">a week ago</option>\
				<option value="30">a month ago</option>\
				<option value="file">file date</option>\
				<option value="other">other (mm/dd/yyyy hh:mm)</option>\
		</td><td width="50%">\
			<input type="text" id="exportStartDate" onfocus="this.select()"\
		<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>\
		<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
			<select size=1 id="exportFilterEndBy" \
				<option value="0">today</option>\
				<option value="1">yesterday</option>\
				<option value="7">a week ago</option>\
				<option value="30">a month ago</option>\
				<option value="file">file date</option>\
				<option value="other">other (mm/dd/yyyy hh:mm)</option>\
		</td><td width="50%">\
			<input type="text" id="exportEndDate" onfocus="this.select()"\
		<input type="checkbox" class="chk" id=exportFilterTags value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>\
		<input type="text" id="exportTags" onfocus="this.select()">\
		<input type="checkbox" class="chk" id=exportFilterText value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> match titles/tiddler text<br>\
		<input type="text" id="exportText" onfocus="this.select()">\
		</div> <!--box-->\
		</div> <!--panel-->\
		<!-- action buttons -->\
		<div style="text-align:center">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportFilter" value="apply filter">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportStart" value="export tiddlers">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportDelete" value="delete tiddlers">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportClose" value="close">\
	process: function(which) { // process panel control interactions
		var theList=this.$('exportList'); if (!theList) return;
		var count = 0;
		var total = store.getTiddlers('title').length;
		switch (which.id) {
			case 'exportFilter':
				var panel=this.$('exportFilterPanel');
				if (count==-1) { panel.style.display='block'; break; }
				if (count==0) { alert('No tiddlers were selected'); panel.style.display='block'; }
			case 'exportStart':
			case 'exportDelete':
			case 'exportHideFilter':
			case 'exportToggleFilter':
				var panel=this.$('exportFilterPanel')
			case 'exportSelectChanges':
				var lastmod=new Date(document.lastModified);
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=='') continue;
					var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
					count += (tiddler.modified>lastmod)?1:0;
				if (count==0) alert('There are no unsaved changes');
			case 'exportSelectAll':
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=='') continue;
					count += 1;
			case 'exportSelectOpened':
				for (var t=0; t<theList.options.length; t++) theList.options[t].selected=false;
				var tiddlerDisplay=this.$('tiddlerDisplay');
				for (var t=0; t<tiddlerDisplay.childNodes.length;t++) {
					var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
					for (var i=0; i<theList.options.length; i++) {
						if (theList.options[i].value!=tiddler) continue;
						theList.options[i].selected=true; count++; break;
				if (count==0) alert('There are no tiddlers currently opened');
			case 'exportSelectRelated':
				// recursively build list of related tiddlers
				function getRelatedTiddlers(tid,tids) {
					var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
					if (!t.linksUpdated) t.changed();
					for (var i=0; i<t.links.length; i++)
						if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
					return tids;
				// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
				var tids=[];
				for (var i=0; i<theList.options.length; i++)
					if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
				// select related tiddlers (includes original selected tiddlers)
				for (var i=0; i<theList.options.length; i++)
			case 'exportListSmaller':	// decrease current listbox size
				var min=5;
			case 'exportListLarger':	// increase current listbox size
				var max=(theList.options.length>25)?theList.options.length:25;
			case 'exportClose':
	displayStatus: function(count,total) {
		var txt=this.statusmsg.format([total,total!=1?'s':'',!count?'none':count==total?'all':count]);
		clearMessage();	displayMessage(txt);
		return txt;
	refreshList: function(selectedIndex) {
		var theList = this.$('exportList'); if (!theList) return;
		// get the sort order
		var sort;
		if (!selectedIndex)   selectedIndex=0;
		if (selectedIndex==0) sort='modified';
		if (selectedIndex==1) sort='title';
		if (selectedIndex==2) sort='modified';
		if (selectedIndex==3) sort='modifier';
		if (selectedIndex==4) sort='tags';

		// unselect headings and count number of tiddlers actually selected
		var count=0;
		for (var t=5; t < theList.options.length; t++) {
			if (!theList.options[t].selected) continue;
			if (theList.options[t].value!='')
			else { // if heading is selected, deselect it, and then select and count all in section
				for ( t++; t<theList.options.length && theList.options[t].value!=''; t++) {

		// disable 'export' and 'delete' buttons if no tiddlers selected

		// show selection count
		var tiddlers = store.getTiddlers('title');
		if (theList.options.length) this.displayStatus(count,tiddlers.length);

		// if a [command] item, reload list... otherwise, no further refresh needed
		if (selectedIndex>4) return;

		// clear current list contents
		while (theList.length > 0) { theList.options[0] = null; }
		// add heading and control items to list
		var i=0;
		var indent=String.fromCharCode(160)+String.fromCharCode(160);
			new Option(tiddlers.length+' tiddlers in document', '',false,false);
			new Option(((sort=='title'   )?'>':indent)+' [by title]', '',false,false);
			new Option(((sort=='modified')?'>':indent)+' [by date]', '',false,false);
			new Option(((sort=='modifier')?'>':indent)+' [by author]', '',false,false);
			new Option(((sort=='tags'    )?'>':indent)+' [by tags]', '',false,false);

		// output the tiddler list
		switch(sort) {
			case 'title':
				for(var t = 0; t < tiddlers.length; t++)
					theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			case 'modifier':
			case 'modified':
				var tiddlers = store.getTiddlers(sort);
				// sort descending for newest date first
				tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
				var lastSection = '';
				for(var t = 0; t < tiddlers.length; t++) {
					var tiddler = tiddlers[t];
					var theSection = '';
					if (sort=='modified') theSection=tiddler.modified.toLocaleDateString();
					if (sort=='modifier') theSection=tiddler.modifier;
					if (theSection != lastSection) {
						theList.options[i++] = new Option(theSection,'',false,false);
						lastSection = theSection;
					theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			case 'tags':
				var theTitles = {}; // all tiddler titles, hash indexed by tag value
				var theTags = new Array();
				for(var t=0; t<tiddlers.length; t++) {
					var title=tiddlers[t].title;
					var tags=tiddlers[t].tags;
					if (!tags || !tags.length) {
						if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
					else for(var s=0; s<tags.length; s++) {
						if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
				for(var tagindex=0; tagindex<theTags.length; tagindex++) {
					var theTag=theTags[tagindex];
					theList.options[i++]=new Option(theTag,'',false,false);
					for(var t=0; t<theTitles[theTag].length; t++)
						theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
		theList.selectedIndex=selectedIndex; // select current control item
	askForFilename: function(here) {
		var msg=here.title; // use tooltip as dialog box message
		var path=getLocalPath(document.location.href);
		var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\'); 
		if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
		var filetype=this.$('exportFormat').value.toLowerCase();
		var defext='html';
		if (filetype==this.type_TX) defext='txt';
		if (filetype==this.type_CS) defext='csv';
		if (filetype==this.type_NF) defext='xml';
		var file=this.newdefault.replace(/html$/,defext);
		var result='';
		if(window.Components) { // moz
			try {
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeSave);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
			catch(e) { alert('error during local file access: '+e.toString()) }
		else { // IE
			try { // XPSP2 IE only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
				if (s.showOpen()) var result=s.FileName;
			catch(e) {  // fallback
				var result=prompt(msg,path+file);
		return result;
	initFilter: function() {
		this.$('exportFilterStart').checked=false; this.$('exportStartDate').value='';
		this.$('exportFilterEnd').checked=false;  this.$('exportEndDate').value='';
		this.$('exportFilterTags').checked=false; this.$('exportTags').value='';
		this.$('exportFilterText').checked=false; this.$('exportText').value='';
	showFilterFields: function(which) {
		var show=this.$('exportFilterStart').checked;
		var val=this.$('exportFilterStartBy').value;
		if (which && (which.id=='exportFilterStartBy') && (val=='other'))

		var show=this.$('exportFilterEnd').checked;
		var val=this.$('exportFilterEndBy').value;
		 if (which && (which.id=='exportFilterEndBy') && (val=='other'))

		var show=this.$('exportFilterTags').checked;

		var show=this.$('exportFilterText').checked;
	getFilterDate: function(val,id) {
		var result=0;
		switch (val) {
			case 'file':
				result=new Date(document.lastModified);
			case 'other':
				result=new Date(this.$(id).value);
			default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
				var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
				var oneday=86400000;
				if (id=='exportStartDate')
					result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
					result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
		return result;
	filterExportList: function() {
		var theList  = this.$('exportList'); if (!theList) return -1;
		var filterStart=this.$('exportFilterStart').checked;
		var val=this.$('exportFilterStartBy').value;
		var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
		var filterEnd=this.$('exportFilterEnd').checked;
		var val=this.$('exportFilterEndBy').value;
		var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
		var filterTags=this.$('exportFilterTags').checked;
		var tags=this.$('exportTags').value;
		var filterText=this.$('exportFilterText').checked;
		var text=this.$('exportText').value;
		if (!(filterStart||filterEnd||filterTags||filterText)) {
			alert('Please set the selection filter');
			return -1;
		if (filterStart&&filterEnd&&(startDate>endDate)) {
			var msg='starting date/time:\n'
			msg+='is later than ending date/time:\n'
			return -1;
		// if filter by tags, get list of matching tiddlers
		// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
		// otherwise use getTaggedTiddlers() for simple tag matching
		if (filterTags) {
			var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
			var t=fn.apply(store,[tags]);
			var tagged=[];
			for (var i=0; i<t.length; i++) tagged.push(t[i].title);
		// scan list and select tiddlers that match all applicable criteria
		var total=0;
		var count=0;
		for (var i=0; i<theList.options.length; i++) {
			// get item, skip non-tiddler list items (section headings)
			var opt=theList.options[i]; if (opt.value=='') continue;
			// get tiddler, skip missing tiddlers (this should NOT happen)
			var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
			var sel=true;
			if ( (filterStart && tiddler.modified<startDate)
			|| (filterEnd && tiddler.modified>endDate)
			|| (filterTags && !tagged.contains(tiddler.title))
			|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
		return count;
	deleteTiddlers: function() {
		var list=this.$('exportList'); if (!list) return;
		var tids=[];
		for (i=0;i<list.length;i++)
			if (list.options[i].selected && list.options[i].value.length)
		if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
			msg+='Removing this tiddler may cause unexpected results.  Are you sure?'
			if (tid.tags.contains('systemConfig') && !confirm(msg)) continue;
		alert(tids.length+' tiddlers deleted');
		this.refreshList(0); // reload listbox
		store.notifyAll(); // update page display
	go: function() {
		if (window.location.protocol!='file:') // make sure we are local
			{ displayMessage(config.messages.notFileUrlError); return; }
		// get selected tidders, target filename, target type, and notes
		var list=this.$('exportList'); if (!list) return;
		var tids=[]; for (var i=0; i<list.options.length; i++) {
			var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
			var tid=store.getTiddler(opt.value); if (!tid) continue;
		if (!tids.length) return; // no tiddlers selected
		var target=this.$('exportFilename').value.trim();
		if (!target.length) {
			displayMessage('A local target path/filename is required',target);
		var filetype=this.$('exportFormat').value.toLowerCase();
		var notes=this.$('exportNotes').value.replace(/\n/g,'<br>');
		var total={val:0};
		var out=this.assembleFile(target,filetype,tids,notes,total);
		var link='file:///'+target.replace(/\\/g,'/');
		var samefile=link==decodeURIComponent(window.location.href);
		var p=getLocalPath(document.location.href);
		if (samefile) {
			if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
		var ok=saveFile(target,out);
		+'Created:\n\t%3 by %4\n'
		+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
		'- - - - - - - - - - - - - - -\n'
		+'|     title: %0\n'
		+'|   created: %1\n'
		+'|  modified: %2\n'
		+'| edited by: %3\n'
		+'|      tags: %4\n'
		+'- - - - - - - - - - - - - - -\n'
		 '<'+'?xml version="1.0"?'+'>\n'
		+'<rss version="2.0">\n'
		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
		+'<style type="text/css">'
		+'	#storeArea {display:block;margin:1em;}'
		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
		+'<div id="pureStoreHeading">'
		+'	TiddlyWiki "PureStore" export file<br>'
		+'	Source'+': <b>%0</b><br>'
		+'	Title: <b>%1</b><br>'
		+'	Subtitle: <b>%2</b><br>'
		+'	Created: <b>%3</b> by <b>%4</b><br>'
		+'	TiddlyWiki %5 / %6 %7<br>'
		+'	Notes:<hr><pre>%8</pre>'
		+'<div id="storeArea">',
	assembleFile: function(target,filetype,tids,notes,total) {
		var revised='';
		var now = new Date().toLocaleString();
		var src=convertUnicodeToUTF8(document.location.href);
		var title = convertUnicodeToUTF8(wikifyPlain('SiteTitle').htmlEncode());
		var subtitle = convertUnicodeToUTF8(wikifyPlain('SiteSubtitle').htmlEncode());
		var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
		var twver = version.major+'.'+version.minor+'.'+version.revision;
		var v=version.extensions.ExportTiddlersPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
		var headerargs=[src,title,subtitle,now,user,twver,'ExportTiddlersPlugin',pver,notes];
		switch (filetype) {
			case this.type_TX: // plain text
				var header=this.plainTextHeader.format(headerargs);
				var footer=this.plainTextFooter;
			case this.type_CS: // comma-separated
				var fields={};
				for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
				var names=['title','created','modified','modifier','tags','text'];
				for (var f in fields) names.push(f);
				var header=names.join(',')+'\n';
				var footer='';
			case this.type_NF: // news feed (XML)
				var header=this.newsFeedHeader.format(headerargs);
				var footer=this.newsFeedFooter;
			case this.type_PS: // PureStore (no code)
				var header=this.pureStoreHeader.format(headerargs);
				var footer=this.pureStoreFooter;
			case this.type_TW: // full TiddlyWiki
				var currPath=getLocalPath(window.location.href);
				var original=loadFile(currPath);
				if (!original) { displayMessage(config.messages.cantSaveError); return; }
				var posDiv = locateStoreArea(original);
				if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
				var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
				var footer = '\n'+original.substr(posDiv[1]);
		var out=this.getData(target,filetype,tids,fields);
		var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
		// if full TW, insert page title and language attr, and reset all MARKUP blocks...
		if (filetype==this.type_TW) {
			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
			revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
				titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
				titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
		return revised;
	getData: function(target,filetype,tids,fields) {
		// output selected tiddlers and gather list of titles (for use with merge)
		var out=[]; var titles=[];
		var url=store.getTiddlerText('SiteUrl','');
		for (var i=0; i<tids.length; i++) {
		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
		if (filetype==this.type_TW || filetype==this.type_PS) {
			var text=loadFile(target);
			if (text && text.length) {
				var remoteStore=new TiddlyWiki();
				if (remoteStore.importTiddlyWiki(convertUTF8ToUnicode(text))
					&& confirm(this.mergeprompt.format([target]))) {
					var existing=remoteStore.getTiddlers('title');
					for (var i=0; i<existing.length; i++)
						if (!titles.contains(existing[i].title))
		return out;
	formatItem: function(s,f,t,u,fields) {
		if (f==this.type_TW)
			var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS)
			var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
		if (f==this.type_NF)
			var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
		if (f==this.type_TX)
			var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
				t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
		if (f==this.type_CS) {
			function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
			var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
				toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
			for (var f in fields) out.push(toCSV(t.fields[f]||''));
			var r=out.join(',');
		return r||"";
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Description|Documentation for ExportTiddlersPlugin|
interactively select and extract tiddlers from your ~TiddlyWiki document, and write them into another file, using one of several different file formats:
* ~TiddlyWiki - a complete, stand-alone, standard TiddlyWiki HTML document
* ~PureStore - a small HTML archive file containing tiddler data only (no core code)
* ~PlainText - a simple TXT text file with tiddler source listings
* Comma - a "Comma Separated Value" data/spreadsheet file
* ~NewsFeed  - an XML-format file that can be published for RSS syndication.
<<exportTiddlers>> (sidebar menu item)
<<exportTiddlers inline>> (embedded control panel)

Inline control panel (live):
<<exportTiddlers inline>>

Optional "special tiddlers" used by this plugin:
* SiteUrl<br>URL for official server-published version of document being viewed (used in XML export). Default: //none//
2009.04.30 [2.9.1] custom fields in CSV output
2009.04.19 [2.9.0] added CSV format
2009.02.26 [2.8.5] use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.29 [2.8.4] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
2008.09.26 [2.8.3] in go(), if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively.
2008.09.24 [2.8.2] in assembleFile(), make sure that markup block is updated if corresponding Markup* tiddler is exported.
2008.09.19 [2.8.1] in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.11 [2.8.0] extensive code cleanup: moved all global functions inside macro object. Re-wrote file generator and I/O to support TiddlyWiki, PlainText, PureStore, and NewsFeed file formats.  Replaced inline 'match tags' code with use of getMatchingTiddlers() from [[MatchTagsPlugin]] (if installed), with fallback to core getTaggedTiddlers() otherwise.
2008.05.27 [2.7.0] added ability to 'merge' with existing export file.  Also, revised 'matchTags' functionality to be more robust and more efficient
2008.05.12 [2.6.1] automatically add 'export' task to backstage (moved from BackstageTweaks)
2008.03.10 [2.6.0] added "delete tiddlers" button
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.11.10 [2.5.1] removed debugging alert messages from promptForExportFilename()
2007.10.31 [2.5.0] code reduction: removed incomplete/unused interface and supporting functions for exporting directly to http, https or ftp servers.  Plugin now supports exporting to local file only.  Also, updated TW document output to generate TW2.2 compatible file format.
2007.10.30 [2.4.2] added automatic shadow tiddler definition for [[ExportTiddlers]]
2007.07.16 [2.4.1] in exportTWHeader(), reset HTML source 'markup' so installed markup is NOT copied to new file.
2007.06.30 [2.4.0] added "select related tiddlers" feature.  Recursively scans the tiddler links[] info to find all tiddlers referenced by any of the currently selected tiddler, and then selects them all (including the original tiddlers).
2007.04.19 [2.3.0] in exportData(), pass SiteURL value as param to saveToRss().  Fixes 'undefined' appearing in tiddler link in XML output.  Also, in refreshExportList(), added 'sort by tags'.  Also, added 'group select'... selecting a heading (date,author,tag) auto-selects all tiddlers in that group.
2007.03.02 [2.2.6] in onClickExportButton(), when selecting open tiddlers for TW2.2, look for "storyDisplay" with fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.03.01 [2.2.5] removed hijack of store.saveChanges()
2006.11.08 [2.2.4] added promptForExportFilename() and replaced type="file" control with edit field + browse button ("...").
2006.10.12 [2.2.3] in exportDIVFooter(), write POST-BODY-START/END markers for compatibility with TW2.1 core file format.
2006.05.11 [2.2.2] in createExportPanel, removed call to addNotification() to reduce unneeded feedback messages and increase overall document performance.
2006.05.02 [2.2.1] Use displayMessage() to show number of selected tiddlers instead of updating listbox 'header' item after each selection.  Prevents awkward 'scroll-to-top' behavior that made multi-select via ctrl-click nearly impossible.
2006.04.29 [2.2.0] New features: free-form "Notes" text inserted in the header of PureStore files.
2006.03.29 [2.1.3] added calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.
2006.02.12 [2.1.2] more FF1501 bug fixes.
2006.02.04 [2.1.1] added var to unintended globals to avoids FireFox1501 crash bug
2006.02.02 [2.1.0] Added support for output of complete TiddlyWiki documents
2006.01.21 [2.0.1] Defer initial panel creation and only register a notification function when panel first is created
in saveChanges 'hijack', create panel as needed.  Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.
2005.12.27 [2.0.0] Update for TW2.0.
2005.12.24 [0.9.5] Minor adjustments to CSS to force correct link colors regardless of TW stylesheet selection
2005.12.16 [0.9.4] Dynamically create/remove exportPanel so only one instance exists at a time
2005.11.15 [0.9.2] added non-Ajax post to bypass cross-domain security restrictions.
2005.11.08 [0.9.1] moved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time.
2005.10.28 [0.9.0] added 'select opened tiddlers' feature. Based on a suggestion by Geoff Slocock
2005.10.24 [0.8.3] Corrected hijack of 'save changes' when using http:
2005.10.18 [0.8.2] added AJAX functions
2005.10.18 [0.8.1] Corrected timezone handling and error checking/reporting when filtering tiddlers. More style tweaks, minor text changes and some assorted layout cleanup.
2005.10.17 [0.8.0] First pre-release.
2005.10.16 [0.7.0] filter by tags
2005.10.15 [0.6.0] filter by title/text
2005.10.14 [0.5.0] export to local file (DIV or XML)
2005.10.14 [0.4.0] filter by start/end date
2005.10.13 [0.3.0] panel interaction
2005.10.11 [0.2.0] panel layout
2005.10.10 [0.1.0] code framework
2005.10.09 [0.0.0] development started
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Requires|TemporaryTiddlersPlugin (optional, recommended)|
|Description|retrieve and wikify content from external files or remote URLs|
This plugin extends the {{{<<tiddler>>}}} macro syntax so you can retrieve and wikify content directly from external files or remote URLs.  You can also define alternative "fallback" sources to provide basic "import on demand" handling by automatically creating/importing tiddler content from external sources when the specified ~TiddlerName does not already exist in your document.
>see [[ExternalTiddlersPluginInfo]]
<<option chkExternalTiddlersImport>> automatically create/import tiddlers when using external fallback references
{{{usage: <<option chkExternalTiddlersImport>>}}}
<<option chkExternalTiddlersQuiet>> don't display messages when adding tiddlers ("quiet mode")
{{{usage: <<option chkExternalTiddlersQuiet>>}}}
<<option chkExternalTiddlersTemporary>> tag retrieved tiddlers as 'temporary'(requires [[TemporaryTiddlersPlugin]])
{{{usage: <<option chkExternalTiddlersTemporary>>}}}
tag retrieved tiddlers with: <<option txtExternalTiddlersTags>>
{{{usage: <<option txtExternalTiddlersTags>>}}}

__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[LoadTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
2008.10.27 [1.3.1] in insertTiddler(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
|please see [[ExternalTiddlersPluginInfo]] for additional revision details|
2007.11.25 [1.0.0] initial release - moved from CoreTweaks
version.extensions.ExternalTiddlersPlugin= {major: 1, minor: 3, revision: 1, date: new Date(2008,10,27)};

// optional automatic import/create for missing tiddlers
if (config.options.chkExternalTiddlersImport==undefined) config.options.chkExternalTiddlersImport=true;
if (config.options.chkExternalTiddlersTemporary==undefined) config.options.chkExternalTiddlersTemporary=true;
if (config.options.chkExternalTiddlersQuiet==undefined) config.options.chkExternalTiddlersQuiet=false;
if (config.options.txtExternalTiddlersTags==undefined) config.options.txtExternalTiddlersTags="external";
if (config.options.txtRemoteUsername==undefined) config.options.txtRemoteUsername="";
if (config.options.txtRemotePassword==undefined) config.options.txtRemotePassword="";

config.macros.tiddler.externalTiddlers_handler = config.macros.tiddler.handler;
config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
	params = paramString.parseParams("name",null,true,false,true);
	var names = params[0]["name"];
	var list = names[0];
	var items = list.split("|"); 
	var className = names[1] ? names[1] : null;
	var args = params[0]["with"];

	function extract(text,tids) { // get tiddler source content from plain text or TW doc
		if (!text || !tids || !tids.length) return text; // no text or no tiddler list... return text as-is
		var remoteStore=new TiddlyWiki();
		if (!remoteStore.importTiddlyWiki(text)) return text; // not a TW document... return text as-is
		var out=[]; for (var t=0;t<tids.length;t++)
			{ var txt=remoteStore.getTiddlerText(tids[t]); if (txt) out.push(txt); }
		return out.join("\n");
	function substitute(text,args) { // replace "substitution markers" ($1-$9) with macro param values (if any)
		if (!text || !args || !args.length) return text;
		var n=args.length; if (n>9) n=9;
		for(var i=0; i<n; i++) { var re=new RegExp("\\$" + (i + 1),"mg"); text=text.replace(re,args[i]); }
		return text;
	function addTiddler(src,text,tids) { // extract tiddler(s) from text and create local copy
		if (!config.options.chkExternalTiddlersImport) return; // not enabled... do nothing
		if (!text || !tids || !tids.length) return; // no text or no tiddler list... do nothing
		var remoteStore=new TiddlyWiki();
		if (!remoteStore.importTiddlyWiki(text)) // not a TW document... create a single tiddler from text
		else // TW document with "permaview-like" suffix... copy tiddler(s) from remote store
			for (var t=0;t<tids.length;t++)
	function makeTiddler(src,text,title) { // create a new tiddler object from text
		var who=config.options.txtUserName; var when=new Date();
		var msg="/%\n\nThis tiddler was automatically created using ExternalTiddlersPlugin\n";
		msg+="by %0 on %1\nsource: %2\n\n%/";
		var tags=config.options.txtExternalTiddlersTags.readBracketedList();
		if (config.options.chkExternalTiddlersTemporary) tags.pushUnique(config.options.txtTemporaryTag); 
		if (!config.options.chkExternalTiddlersQuiet) displayMessage("Created new tiddler '"+title+"' from text file "+src);
	function insertTiddler(src,t) { // import a single tiddler object into the current document store
		if (!t) return;
		var who=config.options.txtUserName; var when=new Date();
		var msg="/%\n\nThis tiddler was automatically imported using ExternalTiddlersPlugin\n";
		msg+="by %0 on %1\nsource: %2\n\n%/";
		var newtags=new Array().concat(t.tags,config.options.txtExternalTiddlersTags.readBracketedList());
		if (config.options.chkExternalTiddlersTemporary) newtags.push(config.options.txtTemporaryTag);
		if (!config.options.chkExternalTiddlersQuiet) displayMessage("Imported tiddler '"+t.title+"' from "+src);
	function getGUID()  // create a Globally Unique ID (for async reference to DOM elements)
		 { return new Date().getTime()+Math.random().toString(); }

	// loop through "|"-separated list of alternative tiddler/file/URL references until successful
	var fallback="";
	for (var i=0; i<items.length; i++) { var src=items[i];
		// if tiddler (or shadow) exists, replace reference list with current source name and apply core handler
		if (store.getTiddlerText(src)) {
			arguments[2][0]=src; // params[] array
			var p=arguments[4].split(list); arguments[4]=p[0]+src+p[1]; // paramString
			break; // stop processing alternatives
		// tiddler doesn't exist, and not an external file/URL reference... skip it
		if (!config.formatterHelpers.isExternalLink(src)) {
			if (!fallback.length) fallback=src; // title to use when importing external tiddler
		// separate 'permaview' list of tiddlers (if any) from file/URL (i.e., '#name name name..." suffix)
		var p=src.split("#"); src=p[0]; var tids=p[1]?p[1].readBracketedList(false):[];
		// if reference is to a remotely hosted document or the current document is remotely hosted...
		if (src.substr(0,4)=="http" || document.location.protocol.substr(0,4)=="http") {
			if (src.substr(0,4)!="http") // fixup URL for relative remote references
				{ var h=document.location.href; src=h.substr(0,h.lastIndexOf("/")+1)+src; }
			var wrapper = createTiddlyElement(place,"span",getGUID(),className); // create placeholder for async rendering
			var callback=function(success,params,text,src,xhr) { // ASYNC CALLBACK
				if (!success) { displayMessage(xhr.status); return; } // couldn't read remote file... report the error 
				if (params.fallback.length)
					addTiddler(params.url,text,params.tids.length?params.tids:[params.fallback]); // import tiddler
				var wrapper=document.getElementById(params.id); if (!wrapper) return; 
				wikify(substitute(extract(text,params.tids),params.args),wrapper); // ASYNC RENDER
			var callbackparams={ url:src, id:wrapper.id, args:args, tids:tids, fallback:fallback }  // ASYNC PARAMS
			var name=config.options.txtRemoteUsername; // optional value
			var pass=config.options.txtRemotePassword; // optional value
			var x=doHttp("GET",src,null,null,name,pass,callback,callbackparams,null)
			if (typeof(x)=="string") // couldn't start XMLHttpRequest... report error
				{ displayMessage("error: cannot access "+src); displayMessage(x); }
			break; // can't tell if async read will succeed.... stop processing alternatives anyway.
		else { // read file from local filesystem
			var text=loadFile(getLocalPath(src));
			if (!text) { // couldn't load file... fixup path for relative reference and retry...
				var h=document.location.href;
				var text=loadFile(getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)))+src);
			if (text) { // test it again... if file was loaded OK, render it in a class wrapper
				if (fallback.length) // create new tiddler using primary source name (if any)
				var wrapper=createTiddlyElement(place,"span",null,className);
				wikify(substitute(extract(text,tids),args),wrapper); // render
				break; // stop processing alternatives
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Description|documentation for ExternalTiddlersPlugin|
This plugin extends the {{{<<tiddler>>}}} macro syntax so you can retrieve and wikify content directly from external files or remote URLs.  You can also define alternative "fallback" sources to provide basic "import on demand" handling by automatically creating/importing tiddler content from external sources when the specified ~TiddlerName does not already exist in your document.
>see ExternalTiddlersPlugin
The standard TiddlyWiki core syntax for the {{{<<tiddler>>}}} macro is:
>{{{<<tiddler TiddlerName with: param param param ...>>}}}
where the optional {{{with: param param param...}}} values are used to replace any corresponding "substitution markers" ($1 to $9) that may be embedded in the referenced tiddler content.

This plugin allows the {{{<<tiddler>>}}} macro to ''use external file/URL references in place of the usual ~TiddlerName parameter'', so that you can render wiki-formatted source content retrieved from an external file/URL reference (as determined by the core's isExternalLink() test function), ''//as if// it had come from a tiddler in the current document''.  The external file/URL can be either ''a relative or absolute reference'' and can contain ''"plain text" or a full TiddlyWiki document''.  When using a TiddlyWiki document, you must specify which tiddlers should be included in the output by appending a permaview-like suffix to the file or URL reference, e.g.:
>{{{<<tiddler "myfile.txt" with: param param param...>>}}}
>{{{<<tiddler "myfile.html#TiddlerName TiddlerName..." with: param param param...>>}}}
>{{{<<tiddler "http://www.TiddlyWiki.com/index.html#HelloThere" with: param param param...>>}}}
If the plugin-enhanced {{{<<tiddler>>}}} macro is unable to retrieve the external content --  perhaps because the file doesn't exist or doesn't contain the requested tiddler(s), or cross-domain security blocked file access, or the network/server "timed out", etc., -- then it produces no output (i.e., just as when the standard {{{<<tiddler>>}}} macro is given a ~TiddlerName does not exist in the current document.)
!!!!!Using alternative "fallback" references
In addition to using external file/URL references in place of the usual ~TiddlerName, the plugin also allows you to use a ''fallback list'' consisting of a combination of alternative sources: tiddlers, local files, and/or URL references, each separated by "|".  The first reference in a fallback list is the "primary source"; the remaining references are "fallback sources".  The plugin will attempt to retrieve content from each fallback source until one is successfully retrieved or all alternatives have been tried.

For example, if you create a tiddler called [[HelloThere]], as well as a remotely-hosted TW document containing a published tiddler, also called [[HelloThere]], then you can write:
>{{{<<tiddler [[HelloThere|http://www.TiddlyWiki.com/#HelloThere]]>>}}}
When [[HelloThere]] is present in the local document, it is processed in the normal manner.  However, if you delete the  local [[HelloThere]] tiddler, the plugin will attempt to retrieve the [[HelloThere]] tiddler from the indicated remote URL.

Please note: although you can list any number of alternative sources, in whatever order you prefer, retrieval from a remote URL occurs asynchronously via XMLHttpRequest() processing.  As a consequence, there can be ''no more than one remote URL reference in the fallback list'', and any alternatives that follow a remote URL reference will not be processed.
!!!!!Automatically import/create missing tiddlers
When content is retrieved from an external fallback source, the plugin can automatically import/create tiddler(s) containing that content into your document, allowing you to display, modify, save and/or search for text in that tiddler from within your own document, without needing to retrieve it again from the external source.

If no local ~TiddlerName(s) are specified in the fallback list (i.e., only direct file/URL references are present), then a tiddler will NOT be created, so that each time you render the tiddler display the external source will be re-read in order to render the most recently saved external file content.  To illustrate using the example from above:
>&nbsp;&nbsp;&nbsp;{{{<<tiddler [[HelloThere|http://www.TiddlyWiki.com/#HelloThere]]>>}}}
will automatically create a locally-stored [[HelloThere]] tiddler, so that the external source is only accessed the first time the content is rendered, while:
>&nbsp;&nbsp;&nbsp;{{{<<tiddler [[http://www.TiddlyWiki.com/#HelloThere]]>>}}}
will re-load the content from the external source each time the display is rendered.

For easy identification, any tiddlers that are automatically created/imported are tagged with <<tag external>> (or other custom-defined tag values).  These tiddlers can also be automatically tagged with <<tag temporary>> for use with [[TemporaryTiddlersPlugin]], which will skip over those tiddlers when saving changes to your document so that when you reload the document, the temporary tiddlers will no longer be present and will be retrieved anew from the external source, on demand, when (or if) they are needed.  Important reminder: ''If you modify a temporary tiddler and want to retain it in your local document, be sure to remove the <<tag temporary>> tag from the tiddler before saving.''
!!!!!~XMLHttpRequest: performance and security issues
This plugin uses asynchronous XMLHttpRequest() processing to access external content directly from URLs hosted on remote web servers.  This often creates delays ranging from mere moments to many minutes while waiting for the remote web server to transfer the requested file.  This performance can vary greatly depending upon the size of the remote file, how the remote server responds to repeated requests for the same URL (e.g, with a //"304 - no change"// response code), as well as how your ''browser's cache mechanism'' has been configured (to avoid repeated downloads).

In addition to server-originated delays, ''cross-domain access from one remote domain to another using XMLHttpRequest() processing is generally restricted for security reasons''.  As a result, if you publish your document to a remote web server, then external file/URL references contained in that document will not work if they are not located on the same server as the hosted document.

Fortunately, this security restriction does NOT usually apply when accessing remote URLs rendered into a locally-viewed document, since blocking such access would interfere with normal browser functions!  As a "rule of thumb", in order to ensure that external content included in server-hosted documents will be displayed as intended, you should ''always use either a relative path/file reference or an http: reference located on the same domain as the published document.'' for any document you intend to publish.

Note: Some hosting providers, such as http://www.TiddlySpot.com/ offer ''"proxy" services that may allow you to bypass the security restrictions'' for certain designated remote web sites.  Consult your hosting service for information regarding their proxy arrangments (if any).
2008.10.27 [1.3.1] in insertTiddler(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ExternalTiddlersPluginInfo
2008.01.03 [1.3.0] use lower-level doHttp() instead loadRemoteFile() so that optional username/password values can be used in XMLHttpRequest
2007.12.22 [1.2.2] in handler(), when reading from local file with relative path fixup, use decodeURIComponent() instead of decodeURI 
2007.11.30 [1.2.1] lots of code/docmentation cleanup.  renamed option cookies.  changed auto tag value to "external".
2007.11.27 [1.2.0] added support for automatically importing external tiddlers
2007.11.26 [1.1.1] improved XMLHttpRequest() error reporting for cross-domain security issues
2007.11.26 [1.1.0] added support for multiple alternative fallback references
2007.11.25 [1.0.0] initial release - moved from CoreTweaks
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Description|select and display FAQ tiddlers from a droplist, sorted by date|
{{{<<faqViewer startwith:TiddlerName tagname classname sortby dateformat>>}}}
*''startwith:TiddlerName'' (optional)<br>
*''tagname'' (optional)<br>specifies the set of tiddlers to include in the FAQ list (default='faq')
*''classname'' (optional)<br>specifies a CSS class to be applied surrounding the FAQ tiddler content
*''sortby'' (optional)<br>specifies the name of a tiddler field to sort by.  Use '+' or '-' as a prefix on the fieldname to indicate ascending or descending order, respectively (default='-modified').  You can also use the special keyword, ''Description'', to sort alphabetically based on the value of a slice named 'Description', that can be defined in each FAQ tiddler.  Note: if a particular FAQ tiddler has no description slice, the title of the tiddler is used as a fallback.
*''dateformat'' (optional)<br>specifies the formatting for dates displayed in the list.  Use " " (a single space) to suppress the date display.
{{smallform small{<<faqViewer>>}}}
{{{<<faqViewer package outline +title " ">>}}}
{{smallform small{<<faqViewer package outline +title " ">>}}}
2009.06.14 [1.4.3] moved html definition to tiddler section (saves space)
2008.10.21 [1.4.2] removed animation (was interfering with 'overflow:scroll' CSS)
2008.09.30 [1.4.1] corrected filter by tag handling broken in 1.4.0
2008.09.29 [1.4.0] added optional 'startwith:TiddlerName' param
2008.09.24 [1.3.1] added animation when opening/closing faq content panel
2008.09.21 [1.3.0] sort by 'description' slice values.  also added 'previous' and 'next' buttons for sequential viewing of FAQ articles
2008.09.20 [1.2.0] optional 'sortby' and 'dateformat' params
2008.01.20 [1.1.0] support for alternative 'target' tag instead of 'faq' (default)
2007.10.15 [1.0.0] converted to true plugin
2007.02.01 [0.0.0] inline script
version.extensions.FAQViewerPlugin={major: 1, minor: 4, revision: 3, date: new Date(2009,6,14)};


config.macros.faqViewer= {
	dateFormat:'YYYY.0MM.0DD 0hh:0mm - ',
	startparam: 'startwith:',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		// create form
		if (params[0]&&params[0].substr(0,this.startparam.length)==this.startparam)
			{ var startwith=params[0].substr(this.startparam.length); params.shift(); }
		var console=createTiddlyElement(place,'span');
		this.go(console.getElementsByTagName('form')[0],startwith, params[0],params[2],params[3]);
	go: function(f,startwith,targetType,sortby,dateformat) {
		var targetType=targetType||'faq';
		var sortby=sortby||'-modified';
		var dateformat=dateformat||this.dateFormat;
		var datefield=sortby.indexOf('created')!=-1?'created':'modified';
		var lists=f.getElementsByTagName('select'); if (!lists.length) return;
		var FAQList=lists[0]; var taglist=lists[1];
		while (FAQList.options[0]) FAQList.options[0]=null; // empty FAQList
		if (f.search.value!=f.search.defaultValue) var find=f.search.value;
		var tiddlers=store.getTaggedTiddlers(targetType,'modified').reverse();
		if (tiddlers && sortby) {
			if (sortby.indexOf('escription')==-1)	// sort by tiddler field
				tiddlers.sort(function(a,b){	// sort by description slice (or title, if no slice)
					var da=store.getTiddlerSlice(a.title,'Description')||a.title;
					var db=store.getTiddlerSlice(b.title,'Description')||b.title;
					return da==db?0:(da>db?+1:-1);
		var matchcount=0; var tags=[]; var selectedIndex=0;
		FAQList.options[0]=new Option('select an item...','',false,false);
		for (var i=0; i<tiddlers.length; i++) {
			for (var t=0; t<tiddlers[i].tags.length; t++)
				tags.pushUnique(tiddlers[i].tags[t]); // collect other tags
			if (find && find.length && tiddlers[i].text.indexOf(find)==-1) continue;
			if (taglist.value && taglist.value.length && !tiddlers[i].tags.contains(taglist.value)) continue;
			var d=store.getTiddlerSlice(tiddlers[i].title,'Description')||tiddlers[i].title;
			FAQList.options[FAQList.options.length]=new Option(d,tiddlers[i].title,false,false);
			if (tiddlers[i].title==startwith) selectedIndex=i+1;
		FAQList.options[0].text='select an item... ['+tiddlers.length+' item'+(tiddlers.length!=1?'s':'');
		if (find && find.length || taglist.value.length)
			FAQList.options[0].text+=', '+matchcount+' match'+(matchcount!=1?'es':'');
		if (selectedIndex) config.macros.faqViewer.show(f,startwith);

		if (!taglist.options.length) { // only load tag list the first time, since it doesn't change
			while (taglist.options[0]) taglist.options[0]=null; // empty taglist
			taglist.options[0]=new Option('filter by tag...','',false,false);
			var tagcount=0;
			for (var t=0; t<tags.length; t++) {
				if (tags[t].toLowerCase()==targetType) continue;
				if (tags[t].indexOf('exclude')!=-1) continue;
					=new Option(tags[t],tags[t],false,false);
			if (!tagcount) taglist.options[taglist.options.length]
				=new Option('no category tags found','',false,false);
	show: function(f,v) {
		var fmt=this.faqlayout;
		if (store.getTaggedTiddlers(v).length) fmt=this.packagelayout;
		var target=f.getElementsByTagName('div')[0];
		'{{toolbar floatright fine{//now viewing: //[[%0]] &nbsp;}}}<<tiddler [[%0]]>>',
		'{{toolbar floatright fine{//now viewing: //[[%0]] &nbsp;}}}\n'
			+'{{floatright borderleft fine{<<tagging [[%0]]>>}}}<<tiddler [[%0]]>>{{clear block{}}}'
<form onsubmit='return false;' style='display:inline;margin:0;padding:0;white-space:nowrap;'><!--
--><input type='hidden' name='targetType' value='faq'><!--
--><input type='hidden' name='sortBy' value='-modified'><!--
--><input type='hidden' name='dateFmt' value='YYYY.0MM.0DD 0hh:0mm - '><!--
--><select name='list' size=1 style='width:50%'
	onchange='if (!this.value.length) this.form.done.onclick();
		else config.macros.faqViewer.show(this.form,this.value);'><!--
--><select name='taglist' size=1 style='width:12%'
	title='list only items that have a specific category tag'
	onchange='var f=this.form; f.done.onclick();
--><input type='text' name='search' value='enter search text...' style='width:20%'
	title='list only items that contain the search text (use blank to match all)'
	onkeyup=' if (event.keyCode==13) this.form.find.onclick();
		if (!this.value.length) {this.value=this.defaultValue; this.select(); this.form.find.onclick();}'><!--
--><input type='button' name='find' value='find' style='width:6%'
	title='list only items that contain the search text '
	onclick='var f=this.form; f.done.onclick();
--><input type='button' name='reset' value='reset' style='width:6%'
	title='reset FAQViewer to default '
	onclick='var f=this.form; f.done.onclick();
		f.search.value=f.search.defaultValue; f.taglist.selectedIndex=0;
--><input type='button' name='done' value='done' disabled style='width:6%'
	title='hide current item display'
	onclick='var target=this.form.getElementsByTagName("div")[0];
		target.style.display="none"; removeChildren(target);
		this.form.list.selectedIndex=0; this.disabled=true;'><!--
--><div class="%classname%" style="display:none;white-space:normal;"></div><!--
--><span style='text-align:right;display:none;overflow:auto;'><!--
--><input type='button' name='prev' value='&#x25C4 prev' style='float:left;font-size:80%;'
	title='view previous item'
	onclick='var f=this.form; var i=f.list.selectedIndex-1;
		f.list.selectedIndex=i<0?f.list.length-1:i; f.list.onchange();'><!--
--><input type='button' name='next' value='next &#x25BA;' style='float:right;font-size:80%;'
	title='view next item'
	onclick='var f=this.form; var i=f.list.selectedIndex+1;
		f.list.selectedIndex=i>f.list.length-1?0:i; f.list.onchange();'><!--
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Requires|ToolbarCommands, FAQViewerPlugin|
|Description|custom version of view template used to display tiddlers tagged with 'faq'|
<span class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></span>
<span class='title' macro='view title'></span>
<span class='subtitle'>
	<span style='white-space:nowrap' macro='view modified date [[DDD, MMM DDth YYYY]]'></span>
<div class='viewer smallform' macro='faqViewer {{"startwith:"+tiddler.title}}' title=' '></div>
<div class='toolbar' style='line-height:100%;margin-top:.5em;'><a href="javascript:;"
	onclick="window.scrollTo(0,ensureVisible(story.findContainingTiddler(this)));return false;"
	onmouseover="this.title='scroll to top of '+story.findContainingTiddler(this).getAttribute('tiddler')">&#x25b2;</a>
**replace soft link with hard links to backup on the remote system, thusly:
***move the ''current and different'' .bak/* files to the remote system
***link the .bak/* to the .ver/Whatever/* on the remote system, 
**thus preserving the notion of only linking to the latest file
**giving //bkup// the remote facility??
**greatly trim, if not elminate infolib from the distribution
** add2files -- notion of dotfiles, PRIMARY sources
See the <<slider ckfa FeaturesAdded "Features Added">>
Basically I wanted to create a ~TiddlyWiki that 
*Allows me to sort and index tiddlers by major topics but also by specific subtopics within each topic. See [[here|Computer / technology]] for an example of an index.
*Also allows me to sort tiddlers by type of note: glossary, statistics, quotes, humorous, questions I have, and personal reflections.
*Allows me to add bibliographic entries if I wish, similar to [[BibblyWiki|http://www.giffmex.org/bibblywiki.html]]. 
*Has a collapsible and expandable menu in case my list(s) of topics gets long.
*@@New!@@ Allows me to format text quickly. See [[Easy formatting]].
So I added various plugins and macros and got it the way I wanted. You can see my own notes at http://www.giffmex.org/dbn/davesnotesoneverything.html to get an idea of what this looks like in practice. But if you want an empty version, this file is it.
=====   2009-03-26 22:27:23 Thursday    ==

  added hard and soft links; hard to the local file system, soft to a remote.
  see FeatureRequests: need to put a copy on the remote system and link to that.

=====   2009-03-14 12:19:45 Saturday    ==

respond to 12 March 09 Feature requests:

  + lastVer
  + lastNameVer
  + lastVerDirectory [lastVer]
  + absorb "de" from ...lib
  + remove adminlib, collectlib from qvs
Here is [[Fidessa|http://www.fidessa.com]].  (we were royalblue until the first of May /07)

I'm here since [[10 July 2006]], and in this brief period, I've learned a few things which affect my view of TheTrade. Notably, since each execution from our customer's book's point of view, is the accumulation of a number of orders, tracing the buyers and sellers of a share will be difficult, but not impossible. The data is all available. A business case may be made to our customers: is there a service here, for which a client will pay?
|''Version:''|1.0.5 (2006-02-05)|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|[[ForEachTiddlerMacro]] v1.0.5|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|

Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.

|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|

See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].

!Revision history
* v1.0.5
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features: 
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen) 
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features: 
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs: 
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features: 
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version


// ForEachTiddlerPlugin

// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {

version.extensions.ForEachTiddlerPlugin = {major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), source: "http://tiddlywiki.abego-software.de/#ForEachTiddlergPlugin"};

// For backward compatibility with TW 1.2.x
if (!TiddlyWiki.prototype.forEachTiddler) {
 TiddlyWiki.prototype.forEachTiddler = function(callback) {
 for(var t in this.tiddlers) {

// forEachTiddler Macro

version.extensions.forEachTiddler = {major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), provider: "http://tiddlywiki.abego-software.de"};

// ---------------------------------------------------------------------------
// Configurations and constants 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler = {
 // Standard Properties
 label: "forEachTiddler",
 prompt: "Perform actions on a (sorted) selection of tiddlers",

 // actions
 actions: {
 addToList: {},
 write: {}

// ---------------------------------------------------------------------------
// The forEachTiddler Macro Handler 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler.getContainingTiddler = function(e) {
 while(e && !hasClass(e,"tiddler"))
 e = e.parentNode;
 var title = e ? e.getAttribute("tiddler") : null; 
 return title ? store.getTiddler(title) : null;

config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
 // config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);

 if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
 // --- Parsing ------------------------------------------

 var i = 0; // index running over the params
 // Parse the "in" clause
 var tiddlyWikiPath = undefined;
 if ((i < params.length) && params[i] == "in") {
 if (i >= params.length) {
 this.handleError(place, "TiddlyWiki path expected behind 'in'.");
 tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");

 // Parse the where clause
 var whereClause ="true";
 if ((i < params.length) && params[i] == "where") {
 whereClause = this.paramEncode((i < params.length) ? params[i] : "");

 // Parse the sort stuff
 var sortClause = null;
 var sortAscending = true; 
 if ((i < params.length) && params[i] == "sortBy") {
 if (i >= params.length) {
 this.handleError(place, "sortClause missing behind 'sortBy'.");
 sortClause = this.paramEncode(params[i]);

 if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
 sortAscending = params[i] == "ascending";

 // Parse the script
 var scriptText = null;
 if ((i < params.length) && params[i] == "script") {
 scriptText = this.paramEncode((i < params.length) ? params[i] : "");

 // Parse the action. 
 // When we are already at the end use the default action
 var actionName = "addToList";
 if (i < params.length) {
 if (!config.macros.forEachTiddler.actions[params[i]]) {
 this.handleError(place, "Unknown action '"+params[i]+"'.");
 } else {
 actionName = params[i]; 
 // Get the action parameter
 // (the parsing is done inside the individual action implementation.)
 var actionParameter = params.slice(i);

 // --- Processing ------------------------------------------
 try {
 place: place, 
 inTiddler: tiddler,
 whereClause: whereClause, 
 sortClause: sortClause, 
 sortAscending: sortAscending, 
 actionName: actionName, 
 actionParameter: actionParameter, 
 scriptText: scriptText, 
 tiddlyWikiPath: tiddlyWikiPath});

 } catch (e) {
 this.handleError(place, e);

// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
// The action is not yet performed.
// @parameter see performMacro
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {

 var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);

 var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
 context["tiddlyWiki"] = tiddlyWiki;
 // Get the tiddlers, as defined by the whereClause
 var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
 context["tiddlers"] = tiddlers;

 // Sort the tiddlers, when sorting is required.
 if (parameter.sortClause) {
 this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);

 return {tiddlers: tiddlers, context: context};

// Returns the (sorted) tiddlers selected by the parameter.
// The action is not yet performed.
// @parameter see performMacro
config.macros.forEachTiddler.getTiddlers = function(parameter) {
 return this.getTiddlersAndContext(parameter).tiddlers;

// Performs the macros with the given parameter.
// @param parameter holds the parameter of the macro as separate properties.
// The following properties are supported:
// place
// whereClause
// sortClause
// sortAscending
// actionName
// actionParameter
// scriptText
// tiddlyWikiPath
// All properties are optional. 
// For most actions the place property must be defined.
config.macros.forEachTiddler.performMacro = function(parameter) {
 var tiddlersAndContext = this.getTiddlersAndContext(parameter);

 // Perform the action
 var actionName = parameter.actionName ? parameter.actionName : "addToList";
 var action = config.macros.forEachTiddler.actions[actionName];
 if (!action) {
 this.handleError(parameter.place, "Unknown action '"+actionName+"'.");

 var actionHandler = action.handler;
 actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);

// ---------------------------------------------------------------------------
// The actions 
// ---------------------------------------------------------------------------

// Internal.
// --- The addToList Action -----------------------------------------------
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
 // Parse the parameter
 var p = 0;

 // Check for extra parameters
 if (parameter.length > p) {
 config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);

 // Perform the action.
 var list = document.createElement("ul");
 for (var i = 0; i < tiddlers.length; i++) {
 var tiddler = tiddlers[i];
 var listItem = document.createElement("li");
 createTiddlyLink(listItem, tiddler.title, true);

// Internal.
// --- The write Action ---------------------------------------------------
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
 // Parse the parameter
 var p = 0;
 if (p >= parameter.length) {
 this.handleError(place, "Missing expression behind 'write'.");

 var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);

 // Parse the "toFile" option
 var filename = null;
 var lineSeparator = undefined;
 if ((p < parameter.length) && parameter[p] == "toFile") {
 if (p >= parameter.length) {
 this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
 filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
 if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
 if (p >= parameter.length) {
 this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
 lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
 // Check for extra parameters
 if (parameter.length > p) {
 config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);

 // Perform the action.
 var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
 var count = tiddlers.length;
 var text = "";
 for (var i = 0; i < count; i++) {
 var tiddler = tiddlers[i];
 text += func(tiddler, context, count, i);
 if (filename) {
 if (lineSeparator !== undefined) {
 lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
 text = text.replace(/\n/mg,lineSeparator);
 saveFile(filename, convertUnicodeToUTF8(text));
 } else {
 var wrapper = createTiddlyElement(place, "span");
 wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

// Internal.
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
 return {
 place : placeParam, 
 whereClause : whereClauseParam, 
 sortClause : sortClauseParam, 
 sortAscending : sortAscendingParam, 
 script : scriptText,
 actionName : actionNameParam, 
 actionParameter : actionParameterParam,
 tiddlyWikiPath : tiddlyWikiPathParam,
 inTiddler : inTiddlerParam

// Internal.
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of 
// the given path.
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
 if (!idPrefix) {
 idPrefix = "store";
 var lenPrefix = idPrefix.length;
 // Read the content of the given file
 var content = loadFile(this.getLocalPath(path));
 if(content === null) {
 throw "TiddlyWiki '"+path+"' not found.";
 // Locate the storeArea div's
 var posOpeningDiv = content.indexOf(startSaveArea);
 var posClosingDiv = content.lastIndexOf(endSaveArea);
 if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
 throw "File '"+path+"' is not a TiddlyWiki.";
 var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
 // Create a "div" element that contains the storage text
 var myStorageDiv = document.createElement("div");
 myStorageDiv.innerHTML = storageText;
 // Create all tiddlers in a new TiddlyWiki
 // (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
 var tiddlyWiki = new TiddlyWiki();
 var store = myStorageDiv.childNodes;
 for(var t = 0; t < store.length; t++) {
 var e = store[t];
 var title = null;
 title = e.getAttribute("tiddler");
 if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
 title = e.id.substr(lenPrefix);
 if(title && title !== "") {
 var tiddler = tiddlyWiki.createTiddler(title);
 tiddlyWiki.dirty = false;

 return tiddlyWiki;

// Internal.
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
// (tiddler, context, count, index)
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
 var script = context["script"];
 var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
 var fullText = (script ? script+";" : "")+functionText+";theFunction;";
 return eval(fullText);

// Internal.
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
 var result = [];
 var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
 tiddlyWiki.forEachTiddler(function(title,tiddler) {
 if (func(tiddler, context, undefined, undefined)) {
 return result;

// Internal.
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
 var message = "Extra parameter behind '"+actionName+"':";
 for (var i = firstUnusedIndex; i < parameter.length; i++) {
 message += " "+parameter[i];
 this.handleError(place, message);

// Internal.
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
 var result = 
 (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
 ? 0
 : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
 ? -1 
 : +1; 
 return result;

// Internal.
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
 var result = 
 (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
 ? 0
 : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
 ? +1 
 : -1; 
 return result;

// Internal.
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
 // To avoid evaluating the sortClause whenever two items are compared 
 // we pre-calculate the sortValue for every item in the array and store it in a 
 // temporary property ("forEachTiddlerSortValue") of the tiddlers.
 var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
 var count = tiddlers.length;
 var i;
 for (i = 0; i < count; i++) {
 var tiddler = tiddlers[i];
 tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);

 // Do the sorting
 tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);

 // Delete the temporary property that holds the sortValue. 
 for (i = 0; i < tiddlers.length; i++) {
 delete tiddlers[i].forEachTiddlerSortValue;

// Internal.
config.macros.forEachTiddler.trace = function(message) {

// Internal.
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
 var message ="<<"+macroName;
 for (var i = 0; i < params.length; i++) {
 message += " "+params[i];
 message += ">>";

// Internal.
// Creates an element that holds an error message
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
 var message = (exception.description) ? exception.description : exception.toString();
 return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);

// Internal.
// @param place [may be null]
config.macros.forEachTiddler.handleError = function(place, exception) {
 if (place) {
 this.createErrorElement(place, exception);
 } else {
 throw exception;

// Internal.
// Encodes the given string.
// Replaces 
// "$))" to ">>"
// "$)" to ">"
config.macros.forEachTiddler.paramEncode = function(s) {
 var reGTGT = new RegExp("\\$\\)\\)","mg");
 var reGT = new RegExp("\\$\\)","mg");
 return s.replace(reGTGT, ">>").replace(reGT, ">");

// Internal.
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
 // Remove any location part of the URL
 var hashPos = originalPath.indexOf("#");
 if(hashPos != -1)
 originalPath = originalPath.substr(0,hashPos);
 // Convert to a native file format assuming
 // "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
 // "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
 // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
 // "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
 var localPath;
 if(originalPath.charAt(9) == ":") // pc local file
 localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
 else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
 localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
 else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
 localPath = unescape(originalPath.substr(7));
 else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
 localPath = unescape(originalPath.substr(5));
 else // pc network file
 localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\"); 
 return localPath;

// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
 ".forEachTiddlerError{color: #ffffff;background-color: #880000;}",

// End of forEachTiddler Macro

// String.startsWith Function
// Returns true if the string starts with the given prefix, false otherwise.
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
String.prototype.startsWith = function(prefix) {
 var n = prefix.length;
 return (this.length >= n) && (this.slice(0, n) == prefix);

// String.endsWith Function
// Returns true if the string ends with the given suffix, false otherwise.
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
String.prototype.endsWith = function(suffix) {
 var n = suffix.length;
 return (this.length >= n) && (this.right(n) == suffix);

// String.contains Function
// Returns true when the string contains the given substring, false otherwise.
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
String.prototype.contains = function(substring) {
 return this.indexOf(substring) >= 0;

// Array.indexOf Function
// Returns the index of the first occurance of the given item in the array or 
// -1 when no such item exists.
// @param item [may be null]
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
Array.prototype.indexOf = function(item) {
 for (var i = 0; i < this.length; i++) {
 if (this[i] == item) {
 return i;
 return -1;

// Array.contains Function
// Returns true when the array contains the given item, otherwise false. 
// @param item [may be null]
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
Array.prototype.contains = function(item) {
 return (this.indexOf(item) >= 0);

// Array.containsAny Function
// Returns true when the array contains at least one of the elements 
// of the item. Otherwise (or when items contains no elements) false is returned.
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
Array.prototype.containsAny = function(items) {
 for(var i = 0; i < items.length; i++) {
 if (this.contains(items[i])) {
 return true;
 return false;

// Array.containsAll Function
// Returns true when the array contains all the items, otherwise false.
// When items is null false is returned (even if the array contains a null).
// @param items [may be null] 
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
Array.prototype.containsAll = function(items) {
 for(var i = 0; i < items.length; i++) {
 if (!this.contains(items[i])) {
 return false;
 return true;

} // of "install only once"

// Used Globals (for JSLint) ==============
// ... DOM
/*global document */
// ... TiddlyWiki Core
/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, 
 displayMessage, endSaveArea, hasClass, loadFile, saveFile, 
 startSaveArea, store, wikify */

!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

Gov Richardson;

Your support for Death Penalty repeal may be made on many grounds:  you're looking for clergy input; I can't help you there other than let you know I'm a practicing Catholic, and am led by our national bishops, when they instruct on the "whole fabric of life".   
I believe, and have asked many involved, there seems to be no data, but it seems our wave of youth -- in particular school -- violence, is we've taught teens that justice may be done by taking a life.   "If the state can do it, why can't I?"  

  +=+-- Marty McGowan
<<gradient vert #00ddcc #cccccc>>00ddcc cccccc
and more Stuff
<<gradient vert #ffffff #00ddcc >>ffffff 00ddcc 
Further STUFFF...............
<<gradient vert #cccccc #ffffff  >> 
And even MORE  .=
cccccc ffffff >>
<<include "Beta.html">>
|''Version:''|1.0.1 (2007-04-30)|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IncludePlugin Documentation|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]]|
|''Community:''|([[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23IncludePlugin]]) ([[Support|http://groups.google.com/group/TiddlyWiki]])|
|''Copyright:''|&copy; 2007 [[abego Software|http://www.abego-software.de]]|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Browser:''|Firefox or better; Internet Explorer 6.0|
This plugin's source code is compressed (and hidden). Use this [[link|http://tiddlywiki.abego-software.de/archive/IncludePlugin/Plugin-Include-src.1.0.0.js]] to get the readable source code.
if(!window.abego){window.abego={};}var invokeLater=function(_1,_2,_3){return abego.invokeLater?abego.invokeLater(_1,_2,_3):setTimeout(_1,_2);};abego.loadFile=function(_4,_5,_6){var _7=function(_8,_9,_a,_b,_c){return _8?_5(_a,_b,_9):_5(undefined,_b,_9,"Error loading %0".format([_b]));};if(_4.search(/^((http(s)?)|(file)):/)!=0){if(_4.search(/^((.\:\\)|(\\\\)|(\/))/)==0){_4="file://"+_4;}else{var _d=document.location.toString();var i=_d.lastIndexOf("/");_4=_d.substr(0,i+1)+_4;}_4=_4.replace(/\\/mg,"/");}loadRemoteFile(_4,_7,_6);};abego.loadTiddlyWikiStore=function(_f,_10,_11,_12){var _13=function(_14,_15){if(_12){_12(_14,"abego.loadTiddlyWikiStore",_15,_f,_11);}};var _16=function(_17,_18){var _19=_18.indexOf(startSaveArea);var _1a=_18.indexOf("<!--POST-BODY-END--"+">");var _1b=_18.lastIndexOf(endSaveArea,_1a==-1?_18.length:_1a);if((_19==-1)||(_1b==-1)){return config.messages.invalidFileError.format([_f]);}var _1c="<html><body>"+_18.substring(_19,_1b+endSaveArea.length)+"</body></html>";var _1d=document.createElement("iframe");_1d.style.display="none";document.body.appendChild(_1d);var doc=_1d.document;if(_1d.contentDocument){doc=_1d.contentDocument;}else{if(_1d.contentWindow){doc=_1d.contentWindow.document;}}doc.open();doc.writeln(_1c);doc.close();var _1f=doc.getElementById("storeArea");_17.loadFromDiv(_1f,"store");_1d.parentNode.removeChild(_1d);return null;};var _20=function(_21){_13("Error when loading %0".format([_f]),"Failed");_10(undefined,_f,_11,_21);return _21;};var _22=function(_23){_13("Loaded %0".format([_f]),"Done");_10(_23,_f,_11);return null;};var _24=function(_25,_26,_27,_28){if(_25===undefined){_20(_28);return;}_13("Processing %0".format([_f]),"Processing");var _29=config.messages.invalidFileError;config.messages.invalidFileError="The file '%0' does not appear to be a valid TiddlyWiki file";try{var _2a=new TiddlyWiki();var _2b=_16(_2a,_25);if(_2b){_20(_2b);}else{_22(_2a);}}catch(ex){_20(exceptionText(ex));}finally{config.messages.invalidFileError=_29;}};_13("Start loading %0".format([_f]),"Started");abego.loadFile(_f,_24,_11);};(function(){if(abego.TiddlyWikiIncluder){return;}var _2c="waiting";var _2d="loading";var _2e=1000;var _2f=-200;var _30=-100;var _31=-300;var _32;var _33=[];var _34={};var _35=[];var _36;var _37=[];var _38;var _39=function(){if(_32===undefined){_32=config.options.chkUseInclude===undefined||config.options.chkUseInclude;}return _32;};var _3a=function(url){return "No include specified for %0".format([url]);};var _3c=function(){var _3d=_35;_35=[];if(_3d.length){for(var i=0;i<_37.length;i++){_37[i](_3d);}}};var _3f;var _40=function(){if(_36!==undefined){clearInterval(_36);}_3f=0;var _41=function(){abego.TiddlyWikiIncluder.sendProgress("","","Done");};_36=setInterval(function(){_3f++;if(_3f<=10){return;}clearInterval(_36);_36=undefined;abego.TiddlyWikiIncluder.sendProgress("Refreshing...","","");refreshDisplay();invokeLater(_41,0,_2f);},1);};var _42=function(_43){var _44;for(var i=0;i<_33.length;i++){var _46=abego.TiddlyWikiIncluder.getStore(_33[i]);if(_46&&(_44=_43(_46,_33[i]))){return _44;}}};var _47=function(){if(!window.store){return invokeLater(_47,100);}var _48=store.fetchTiddler;store.fetchTiddler=function(_49){var t=_48.apply(this,arguments);if(t){return t;}if(config.shadowTiddlers[_49]!==undefined){return undefined;}if(_49==config.macros.newTiddler.title){return undefined;}return _42(function(_4b,url){var t=_4b.fetchTiddler(_49);if(t){t.includeURL=url;}return t;});};if(_33.length){_40();}};var _4e=function(){if(!window.store){return invokeLater(_4e,100);}var _4f=store.getTiddlerText("IncludeList");if(_4f){wikify(_4f,document.createElement("div"));}};var _50=function(_51){var _52=function(){var _53=store.forEachTiddler;var _54=function(_55){var _56={};var _57;var _58=function(_59,_5a){if(_56[_59]){return;}_56[_59]=1;if(_57){_5a.includeURL=_57;}_55.apply(this,arguments);};_53.call(store,_58);for(var n in config.shadowTiddlers){_56[n]=1;}_56[config.macros.newTiddler.title]=1;_42(function(_5c,url){_57=url;_5c.forEachTiddler(_58);});};store.forEachTiddler=_54;try{return _51.apply(this,arguments);}finally{store.forEachTiddler=_53;}};return _52;};var _5e=function(_5f,_60){return _5f[_60]=_50(_5f[_60]);};abego.TiddlyWikiIncluder={};abego.TiddlyWikiIncluder.setProgressFunction=function(_61){_38=_61;};abego.TiddlyWikiIncluder.getProgressFunction=function(_62){return _38;};abego.TiddlyWikiIncluder.sendProgress=function(_63,_64,_65){if(_38){_38.apply(this,arguments);}};abego.TiddlyWikiIncluder.onError=function(url,_67){displayMessage("Error when including '%0':\n%1".format([url,_67]));};abego.TiddlyWikiIncluder.hasPendingIncludes=function(){for(var i=0;i<_33.length;i++){var _69=abego.TiddlyWikiIncluder.getState(_33[i]);if(_69==_2c||_69==_2d){return true;}}return false;};abego.TiddlyWikiIncluder.getIncludes=function(){return _33.slice();};abego.TiddlyWikiIncluder.getState=function(url){var s=_34[url];if(!s){return _3a(url);}return typeof s=="string"?s:null;};abego.TiddlyWikiIncluder.getStore=function(url){var s=_34[url];if(!s){return _3a(url);}return s instanceof TiddlyWiki?s:null;};abego.TiddlyWikiIncluder.include=function(url,_6f){if(!_39()||_34[url]){return;}var _70=this;_33.push(url);_34[url]=_2c;var _71=function(_72,_73,_74,_75){if(_72===undefined){_34[url]=_75;_70.onError(url,_75);return;}_34[url]=_72;_35.push(url);invokeLater(_3c);};var _76=function(){_34[url]=_2d;abego.loadTiddlyWikiStore(url,_71,null,_38);};if(_6f){invokeLater(_76,_6f);}else{_76();}};abego.TiddlyWikiIncluder.forReallyEachTiddler=function(_77){var _78=function(){store.forEachTiddler(_77);};_50(_78).call(store);};abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler=_50;abego.TiddlyWikiIncluder.useForReallyEachTiddler=_5e;abego.TiddlyWikiIncluder.addListener=function(_79){_37.push(_79);};abego.TiddlyWikiIncluder.addListener(_40);if(config.options.chkUseInclude===undefined){config.options.chkUseInclude=true;}config.shadowTiddlers.AdvancedOptions+="\n<<option chkUseInclude>> Include ~TiddlyWikis (IncludeList | IncludeState | [[help|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]])\n^^(Reload this ~TiddlyWiki to make changes become effective)^^";config.shadowTiddlers.IncludeState="<<includeState>>";var _7a=function(e,_7c,_7d){if(!anim||!abego.ShowAnimation){e.style.display=_7c?"block":"none";return;}anim.startAnimating(new abego.ShowAnimation(e,_7c,_7d));};abego.TiddlyWikiIncluder.getDefaultProgressFunction=function(){setStylesheet(".includeProgressState{\n"+"background-color:#FFCC00;\n"+"position:absolute;\n"+"right:0.2em;\n"+"top:0.2em;\n"+"width:7em;\n"+"padding-left:0.2em;\n"+"padding-right:0.2em\n"+"}\n","abegoInclude");var _7e=function(){var e=document.createElement("div");e.className="includeProgressState";e.style.display="none";document.body.appendChild(e);return e;};var _80=_7e();var _81=function(_82){removeChildren(_80);createTiddlyText(_80,_82);_7a(_80,true,0);};var _83=function(){invokeLater(function(){_7a(_80,false,_2e);},100,_30);};var _84=function(_85,_86,_87,url,_89){if(_87=="Done"||_87=="Failed"){_83();return;}if(_86=="abego.loadTiddlyWikiStore"){_3f=0;if(_87=="Processing"){_81("Including...");}}else{_81(_85);}};return _84;};abego.TiddlyWikiIncluder.setProgressFunction(abego.TiddlyWikiIncluder.getDefaultProgressFunction());config.macros.include={};config.macros.include.handler=function(_8a,_8b,_8c,_8d,_8e,_8f){_8c=_8e.parseParams("url",null,true,false,true);var _90=parseInt(getParam(_8c,"delay","0"));var _91=_8c[0]["url"];var _92=getFlag(_8c,"hide",false);if(!_92){createTiddlyText(createTiddlyElement(_8a,"code"),_8d.source.substring(_8d.matchStart,_8d.nextMatch));}for(var i=0;_91&&i<_91.length;i++){abego.TiddlyWikiIncluder.include(_91[i],_90);}};config.macros.includeState={};config.macros.includeState.handler=function(_94,_95,_96,_97,_98,_99){var _9a=function(){var s="";var _9c=abego.TiddlyWikiIncluder.getIncludes();if(!_9c.length){return "{{noIncludes{\nNo includes or 'include' is disabled (see AdvancedOptions)\n}}}\n";}s+="|!Address|!State|\n";for(var i=0;i<_9c.length;i++){var inc=_9c[i];s+="|{{{"+inc+"}}}|";var t=abego.TiddlyWikiIncluder.getState(inc);s+=t?"{{{"+t+"}}}":"included";s+="|\n";}s+="|includeState|k\n";return s;};var _a0=function(){removeChildren(div);wikify(_9a(),div);if(abego.TiddlyWikiIncluder.hasPendingIncludes()){invokeLater(_a0,500,_31);}};var div=createTiddlyElement(_94,"div");invokeLater(_a0,0,_31);};var _a2=Tiddler.prototype.isReadOnly;Tiddler.prototype.isReadOnly=function(){return _a2.apply(this,arguments)||this.isIncluded();};Tiddler.prototype.isIncluded=function(){return this.includeURL!=undefined;};Tiddler.prototype.getIncludeURL=function(){return this.includeURL;};var _a3={getMissingLinks:1,getOrphans:1,getTags:1,reverseLookup:1,updateTiddlers:1};for(var n in _a3){_5e(TiddlyWiki.prototype,n);}var _a5=function(){if(abego.IntelliTagger){_5e(abego.IntelliTagger,"assistTagging");}};var _a6=function(){if(config.macros.forEachTiddler){_5e(config.macros.forEachTiddler,"findTiddlers");}};_47();invokeLater(_4e,100);invokeLater(_a5,100);invokeLater(_a6,100);})();
!About the ~IncludePlugin
Include other ~TiddlyWikis in your (main) TiddlyWiki, link to included tiddlers, view them in your (main) TiddlyWiki, without opening another TiddlyWiki. Even „search“ looks for included tiddlers. 

A great way to share tiddlers, to speed up "save changes" and to keep your ~TiddlyWikis small.
!Smaller ~TiddlyWikis
Other than „imported“ tiddlers, included tiddlers are not copied into your main ~TiddlyWiki. This keeps your individual ~TiddlyWikis small. 

Since your TiddlyWikis will become smaller (if you reorganize your TiddlyWikis using the IncludePlugin) also "save changes" becomes faster. You may even consider switching on "AutoSave" or "SaveBackups" again.
!Sharing ~TiddlyWikis
You may include one ~TiddlyWiki in several other ~TiddlyWikis. Changes you make to this shared ~TiddlyWiki are automatically reflected the next time you open the other ~TiddlyWikis, without any extra „import“ step or so.

* you may want to have a single „~TiddlyWikiHelp“ ~TiddlyWiki that you include in all your ~TiddlyWikis. So you can quickly find help information without looking into other files, and without blowing up your ~TiddlyWikis.
* You "archive" your old journal tiddlers into an extra TiddlyWiki (e.g. one per month) and just include the archived journals in you "current month diary/blog". This way you still have access to the old information (e.g. to reference historic information) but you avoid your diary/blog will get to large.
* ...

See also:
* [[How to use the IncludePlugin]]
* [[How Tiddlers are found]]
* [[IncludePlugin Options]]
* [[The "include" Macro]]
* [[The "includeState" Macro]]
* [[Programming with the IncludePlugin]]
* [[Troubleshooting the IncludePlugin]]
Using the AdvancedOptions page you have an easy way to configure the IncludePlugin options. 

You will find a section like this:
<<option chkUseInclude>> Include ~TiddlyWikis (IncludeList | IncludeState | [[help|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]])
^^(Reload this ~TiddlyWiki to make changes become effective)^^
* By default the IncludePlugin is enabled. If you uncheck the checkbox external TiddlyWikis are not included.
* The IncludeList is the preferred place for your {{{<<include ...>>}}} lines.
* The IncludeState page gives you can an overview what TiddlyWikis are included etc.
* The help directs you to the online documentation of the Include Plugin.
This InstallableShellFile (the block text below), may be copied to a Unix server, any directory, mode set to executable, and run.   This shell installs the QuickVersionSystem and the [[bkup]] tool that it depends on in your ''$HOME/tmp/bin'', edit the text: //tmp/bin// to a directory of your choosing with these caveats:
*the final path component must be a ''bin'', (no //sbin// silliness),
*the ''inpath'' tool must be invoked prefaced with that //bin// in the pathname, following the example here.
Also, the steps following and including ''source qvslib'' below are a sample testcase, where the all the files in the installation ''bin'' are stored in a version named //test//
set -x
QVS_BIN=$INSTALL_QVS/bin        # where its installed TO                                        

mkdir -p  $QVS_BIN      # install in ~/tmp, change to suit                                      
cd $QVS_BIN             # but NEEDS to be in some ../bin                                        
cp $from/qvs.tar.gz .
gunzip  qvs.tar.gz
tar xvf qvs.tar
   ../bin/inpath        # this one insists on it                                                
# ------------------------------------------- TEST CASE --                                      
source qvslib           # USER's GUIDE                                                          
rm -fr .ver/test        # or qvs doesn't create a version                                       
qvs test                # creates a complete copy of Files in .ver/test, see .bak               
ls -l .ver/*
ls -l .ver
Read, if not already, the Installation section of the QuickVersionSystem to obtain the source.
<<tiddler DefaultTiddlers >>
* <<slider ckMenu Communications  time&distance     "Click to Open or CLOSE">>
* <<slider ckMenu TheNetwork         network                "Click to Open or CLOSE">>
* <<slider ckMenu ThisWiki               self-reference      "Click to Open or CLOSE">>

<<tiddler MartyMcGowan>>
This is now my notepad of ideas for the foreseeable future.  As a //note to self//, unless frankly name-dropping, friends show up as First L.

[[Share on Facebook|http://www.facebook.com/share.php?u=http://mcgowans.org/marty3/notepad.html&t=Marty McGowans Public Notepad]]
  <a href="http://twitter.com/applemcg" id="twitter-link" style="display:block;text-align:left;">follow me on Twitter</a>


<a href="http://www.facebook.com/people/Marty-McGowan/666827844" 
      title="Marty McGowan's Facebook profile" 
   <img src="http://badge.facebook.com/badge/666827844.723.765903323.png" 
        alt="Marty McGowan's Facebook profile"></a>

Now, I'm a trainer at [[Fidessa]]. Here's my ShortBio for the company departmental marketing. Prior to July '06, I was the Technology Director at [[BenedictineAcademy|http://www.benedictineacad.org]] in Elizabeth NJ.
<<tiddler MartyMcGowan>>
My wife, Patricia and I visited Montpelier last Saturday, and enjoyed our visit.

In the garden I was sad to see the sundial had been bent.   I'm hoping you can replace it.   Anticipating that, I measured the elevation of the dial's  gnomon.  It's about 49 degrees. To be most accurate, the elevation of the gnomon should be the latitude of the site, which in your case is 38.22 degrees.

I thought of sending this to other departments:  General, Construction, ... Garden?.. but, to me, it's Architectural, and there's some question as to was this there in Madison's time anyway.

We are very interested in your work, and will follow the development of Montpelier.

For me, personally, standing in Madison's library evoked memory of a long-ago visit to Ephesus and placing my feet in the stone where Paul spoke to the Ephesians.  While young in comparison to the epistles, the story of the Constitution has much more fruit yet to bear
What's My Most Important Project:
*from December 6, 2006: cummings
**on [[Windows|src\cummings\ExpressionEvaluator.html]]
**on [[MacOS-X|src/cummings/eeCummings.html]]
*http://www.facebook.com/profile.php?id=667168523  -- Bill Anderson
*http://mcgowans.org/sean_t/ -- Brother Sean's Memorial Site
*this is the [[notepad|./notepad.html]]
*[[My Other Notepad|./mon.html]]
*[[Time To Get Liberal|./ttgl.html]]
*[[On Building Software|./OnBuildingSoftware.html]]
This can only improve.    Your Email network is more sluggish than your train service. _NOT_ a recommendation for your communication skills! CK the TIMES!!
Delivered-To: marty.mcgowan@gmail.com
Received: by with SMTP id g12cs57442bkh;
        Fri, 24 Oct 2008 13:32:54 -0700 (PDT)
Received: by with SMTP id b12mr2156748ybg.109.1224880373398;
        Fri, 24 Oct 2008 13:32:53 -0700 (PDT)
Return-Path: <njt_alert@njtransit.com>
Received: from alum-1.mit.edu (ALUM-1.MIT.EDU [])
        by mx.google.com with ESMTP id 2si234021gxk.48.2008.;
        Fri, 24 Oct 2008 13:32:53 -0700 (PDT)
Received-SPF: neutral (google.com: is neither permitted nor denied by best guess record for domain of njt_alert@njtransit.com) client-ip=;
Authentication-Results: mx.google.com; spf=neutral (google.com: is neither permitted nor denied by best guess record for domain of njt_alert@njtransit.com) smtp.mail=njt_alert@njtransit.com
Received: from nwkalert03-new (nwkalert02-new.njtransit.com [])
	by alum-1.mit.edu (8.13.6/8.12.8) with ESMTP id m9OKTBXt009040
	for <mcgowan@alum.mit.edu>; Fri, 24 Oct 2008 16:32:43 -0400 (EDT)
Received: from nwkalert02-new (unverified []) by nwkalert03-new
 (Rockliffe SMTPRA 9.0.1) with ESMTP id <B0000013986@nwkalert03-new> for <mcgowan@alum.mit.edu>;
 Fri, 10 Oct 2008 13:53:00 -0400
Message-ID: <B0000013986@nwkalert03-new>
x-njtalert_appserver: nwkalert02-new
x-njtalert_timesent: 10/10/2008 3:57:44 PM
mime-version: 1.0
from: njt_alert@njtransit.com
date: 10 Oct 2008 15:57:44 -0400
subject: UPDATED: North Jersey Coast Line - Trains Will Operate Normally Saturday,
 October 11 and Sunday October 12, 2008
content-type: text/plain; charset=us-ascii
content-transfer-encoding: quoted-printable
X-Spam-Score: 2.521
X-Spam-Level: ** (2.521)
X-Spam-Flag: NO
X-Scanned-By: MIMEDefang 2.42
AdriaQuinones is recently back from a UK visit for RoyalBlue. Her chat with SandiApplbaum and I about AuthorIt brought up some old memories. About the value of a name space, as we practiced it at INteractiveSystems in the early, mid-80s. Our technical architects were [[Heinz Lyclama|http://www.osta.com/heinz.htm]] and TedDolata, who had cut some Unix teeth at BellLabs. My site manager at the Boston Technical Office was LeeCooprider.
The application that I recall is any name in software had four (if five, I can't remember it) potential uses in naming something:
# as a # define: # ifndef N_''name''
# in the source code as part of a function name ''name''_read, ...
# in the SCCS tree, at the //bottom//,
# in the src tree, near the top in orthogonal, order-independent directory names, and
The orthogonality of the names arose:
* ''port'', //AIWS//, //Beehive//, ...
* ''system'', V3, V5, ...
* ''arch'', x86, sparc, ..., and
* ''feature'', nothread, ...
While a given name might occupy more than one instance in a portion of either the SCCS or src tree, it likely would be found in all uses over the whole tree.
The idea was a developer could create a directory, offtheir home, named //v3/sparc//, issue a ''Get'' command, and the entire SCCS tree would be picked for the current version of system=v3, arch=sparc for every file.
Readers may recognize the name the name //get//, capitalzed here to represent the name-smart version of the [[SCCS get command|http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.cmds/doc/aixcmds5/sccs.htm]]. Key tools had name-smart wrappers: //Make, Sccs, Cp, Ln, Mv, ...//. I recall we had a small-ish configuration file to create name equivalences or restrictions on the use of names.
Fundamentally, there was no difference or penalty to the use who created a director //sparc/v3// instead of //v3/sparc// to hold the properly picked source tree.
One can imagine the progression of a name through various stages: 1 thru 4, as first it showed up as a small difference, indpendent of feature, system, or other taxonomy. It then may achieve the status of functional support; realize this was before ObjectOriented programming was the rage, then the feature would move to the status of a separate file in the sccs tree, where a //com// folder would hold those files of exactly the same name to be picked where there was no match. Finally, the feature might propagate to a major disintguishing characteristic of the architecture. For example ''ENAMETOOLONG'' may not have been available in V3, but standard in V5. 
The nameing convention for //#ifdef//s was to use a double negative. This requried the name to be treated as a negation. This avoided collision with a positive value of the name, (e.g. use of ENAMETOOLONG was controlled by N_ENAMETOOLONG), and the default compiler behavior of including only properly defined and excluding undefined. Again, if the name is invoked as a negation, a programmer would explictly have to turn off the feature:

 cc ... -DN_ENAMETOOLONG ...

would be required to turn off the expansion. The default behavior would be to include it. More would be required on the inside (rather then in the build instructions) to turn off the new feature.
what is the need for ObjectOrientedNotation, as it currently stands, in which ''objects'' invoke their ''methods'' with zero or more ''arguments''.   UML asserts it is now the [[standard notation|http://www.objectcentral.com/oobook/Chapter1.html]].  Since this statement was designed to get the backs up of object-oriented developers, let me say it's the ''notation'' i'm after, not the object orientation.   //How can one separate the two?// you might ask.   Now we have something to talk about.

The traditional, current, and likely only notation most developers are familiar with looks like:
    object.method( argument, ... )
where the ''method'' is an active property of the ''object'' which takes zero or more ''argument''s. An example might be:
    sensor.temperature( in-one-milli-second )
The challenge of this note is the following question.   {{{  Does ObjectOrientedNotation need a separate, and potentially non-uniform syntactic element to distinguish itself? }}}   I contend the following notation is equally effective, and in some non-trivial cases, more relevant to the problem.   Consider:
   method( object, argument, ... )   // for example
   temperature( sensor, in-one-milli-second )
as an equally valid, if not more meaningful notation for the same phenomenon.   Readers familiar with C++, Java, etc... will recognize the {{{ // and everything to the end of the line
}}} as an un-executed comment.

A detractor will observe that the dotted notation places the "method" as a property of the "object", where as the purely functional notation:   {{{   f( x, y, ... ) }}} does not properly distinguish  //x// as the object, and //f// as it's method.   In functional notation, the object seems to be a property of the method.    A few replies suggest themselves:
*"so what?",  or
*"doesn't the method operate on the object anyway?",  or
*"who's to say which argument is the real object?", or
*"you can't distinguish the object from any other arguments"
These last two criticisms of the functional notation are the basis for my contention that it's the more appropriate notation.

Consider this statement:
     a.distance( b)   // ON(dis, 1)
compared to
     b.distance( a)   // ON(dis, 2)
In most of the geometries we use, these should produce the same result.   I believe even relativistic geometries produce an identical result.   And compare these with a similar object-method:
     a.direction( b)  // ON(dir, 1)
is surely not identical to
     b.direction( a)  // ON(dir, 2)
Summarizing, the distance from ''a'' to '''b'' will be identical with the distance from ''b'' to ''a'', where the directions will be directly opposite.    So, consider the alternative notation:
    distance( a, b)    // FN( dis, 1)   vs.
    distance( b, a)    // FN( dis, 2)   should be equal, while
    direction( a, b)    // FN( dir, 1)   differs from
    direction( b, a)    // FN( dir, 2)    
In all these cases the objects ''a'' and ''b'' are likely a type of ''POINT'', where //distance// and //direction// are methods of that type.  A user of the FN is no more likely than a user of the ON to know that xx( dis,1) and xx(dis, 2) produce identical results.    The point is, that in the xx( dis, n)  invocations, neither object ''a'', nor ''b'' is the central object of the //distance// method.   This may be a little fine-scale for many, but //distance// is a property of a pair of objects.   And, in Euclidean geometry,   a //plane// is a property of three points, none of which need (nor should) be considered the primary, or fundamental object.    In FN, the objects may be properly interchanged in any of these invocations and violate no laws of the underlying mathematics or the language notation. 

It seems entirely proper to introduce a notation that doesn't compel a method to invariably have to prefer one of it's objects to another, when all are equal.   As a design concept, at the possible sacrifice of some polymorphism, to introduce a generic property of a method,  N, the number of interchangeable objects it accepts.    For most, in the current notation, the number will remain one, where we've seen examples here of two and three.   It's not too difficult to imagine zero.

For those interested in describing the differences in the properties of ''distance'' and ''direction'', this FN should suffice:
   assert( equal( distance( a, b), distance( b,a)))   

   assert( equal( distance( ORIGIN, vector( direction( a,b), direction( b,a)))))
since a ''vector'', similar to a ''direction'' can be constructed from a sequence of ''direction''s.  Imagine that ''equal'' returns a scalar result, as does ''distance'', and that ''ORIGIN'' is a special point at the center of a co-ordinate system, such that a vector constructed from two opposite direction returns to the origin, or center.
You're probably familiar with the so-called [[80/20Problem|http://en.wikipedia.org/wiki/Pareto_principle]], where 80 percent of the resources are consumed by 20 percent of the population, for example, or possibly the other way around.   When you hear a statistic such as, //the United States, with 6% of the world's population consumes 60% of the resources//, you may wonder at how this is arrived at, and are encouraged to find out.   We won't discuss that here.   We will try to introduce a single number which suggests how skewed that datapoint ( 6, 60) might be.   For example if you heard that the US only consumed 6% (rather than 60%), you'd be assured the rest of the world had an equal bite at the apple.  We expect that's not the case.   

In the early '80s, I worked in a company in Rochester NY, where the marketing department observed the sales department //has solved the 80-20 problem, they (the sales department) are talking to the 80 percent of the market who has 20 percent of the business.//    The 80-20 problem is easily understood, but it's only an example of the wider class of problem.  

We'll develop a single number, which, for the moment, we'll call the ParetoCompression.   We'll define it so the larger the number, the more skewed is the distribution.   For example, if you heard there was a 90-10 distribution, you'd expect that was more skewed than a 70-30, which is less skewed than the classic 80-20.    But, what if you heard a statistic whose datapoint was 55-23?   What would you make of that?   Could you compare it to what we'll call a ParetoPair? [>img[The Pareto 80-20 problem|./image/Pareto3Egs-65,75,80.jpg]]
|For example, it could be called the 90-10 problem, or the 95-5 problem.   It's usually expressed as a percentage (of 100) followed by the complementary percent.  In what we'll call a ParetoPair, the two numbers sum to 100 percent.    If you have a curve from 0 to 100 percent on the horizontal axis, and 0 to 100 on the vertical,  at some point it intersects the line drawn from (0,1) to (1,0).   The example to the right shows three:   So, a pareto curve is simply expressed by the point on the curve x-y, where x+y = 100.|three examples of the 80-20 problem: <html><strong>65-35,<br>75-25</strong>, and the classic <br><strong>80-20</strong></html>|

When expressed as a decimal fraction, instead of a percent, the numbers range from 0.00 to 1.00, so the 80-20 problem becomes the //0.80 - 0.20 problem//.   I choose to write it this way to make it easy to express in a mathematical formula.    As it turns out, this expression:
<<tiddler LaTexEqn with: "y = x^n">>
is sufficient.    When ''x'' is 0.0, ''y'' is 0.0 for any value of ''n'', and similarly, when x is1.00, so is y. Let's call the ParetoCompression somehow related to the value of ''n''.    The higher the value of ''n'', the further from a straight line, and the more skewed the distribution.  So, for the simplest equation:
<<tiddler LaTexEqn with: "y = x">>
The value of ''n'' is implicitly 1.   For any given value of the ParetoPair (e.g. 80, 20, where the sum is 100), there is a single value of n.  For a concave curve, such as the example, let's say y = 20 ( or 0.20 ) and x = 80 ( 0.80).   Solving for ''n'':
<<tiddler LaTexEqn with: "n = \frac{log(y)}{log(x)}">>
for the 80-20 case, we see that {{{ n = 7.21 }}}.    Recalling that for y = x  ( for n = 1 ), the equation is a straight line, where there is no compression, let's call the ParetoCompression (C~~p~~) = ''n - 1'', so for the simple equation C~~p~~ = 0, and for the 80-20 case C~~p~~ is 6.21.  The higher the compression, the more the distribution varies from a straight line.

And what about a [[particular case]] where only 4% of the population makes 40% of the income.   Conversely, the lowest 96% of the population makes only 60% of the income.  Let's investigate this case, and see what the value of the ParetoPair is and the ParetoCompression for that special case.   Note, these are all based on the idealization that the equation {{{ y = x ^ n }}} holds for all ''x'' and that ''n'' is a constant over the range zero to one.    In general, Pareto analysis suggests it's not.
To find the day-of-week of a given date,
#Treat January and February as belonging to the ''prior'' year. e.g. if you want the calendar for Jan 2008, use 2007 for the year calculation:
#look up the number ''N'' (0 thru 6) associated with of the Century ''(~YYxx)'', the ''Mon''th, and the ''Year'',
#add them together with the Day of the month, (1 - 31),
#take the remainder, modulo seven, at any step
#the remainder is the day of the Week: 0 = Sun, ... 6 = Sat.
|! ~YYxx |! N |! DY|! Mon |! Year |
| 21 | ''0 ''| Sun | Mar, Nov | 0 | 6 | | 17 | 23 | 28 | 56 | 84 |
| | ''1'' | Mon | Jun, Feb | 1 | 7 | 12 | 18 | | | | |
| 20 | ''2'' | Tue | Sep, Dec | 2 | | 13 | 19 | 24 | | | |
| 19 | ''3'' | Wed | Apr, Jul | 3 | 8 | 14 | | 25 | | | |
| | ''4'' | Thu | Oct | | 9 | 15 | 20 | 26 | | | |
| 18 | ''5'' | Fri | May, Jan | 4 | 10 | | 21 | 27 | | | |
| | ''6'' | Sat | Aug | 5 | 11 | 16 | 22 | | | | |

e.g. //27 October 1986//
|! Table |! month |!~YYxx|! Year |
| Cal: | Oct | 19 | 86 |
| ''N'' | 4 | 3 | 2 |
27 + 4 + 3 + 2 => 6 ( 21+6) + 0 (4+3) + 2 = 8 => 1 = ''Monday''
*[[Marty Jr memorial|http://mcgowans.tiddlyspot.com/]] -- yet another family collaboration!
*[[Marty's Other Notepad -- MON|./mon.html]]
*[[The New Trade|http://mcgowans.org/marty3/TheNewTrade.html]]
After googling ''powerpoint highlight text'' I found [[this helpful site|http://office.microsoft.com/en-au/assistance/HP011492981033.aspx]]

Microsoft Office PowerPoint does not include the text effects for highlighting on the Format menu that come with Microsoft Office Word. You can reproduce these effects by using the Drawing toolbar, however.

 1. Display the slide with the text you want to show as highlighted.
 2. From the Drawing toolbar in the lower-left corner of the screen, choose the Rectangle tool.
 3. Draw a rectangle over the text you want to highlight.
 4. Double-click the rectangle, and, in the Format Autoshape dialog box, do the following:
 * Choose the highlight color you want from the Fill color list.
 * Choose 50% in the Transparency box.
 * In the Line Color box, choose No Line.
Each of the PrimaryFiles is a PrimarySource.   The set of PrimaryFiles  is the minimum set of files to build, document or drive a data table.   Furthermore, no other files are needed if you have appropriate, and executable instructions to create the intermediate and final product files.   The primary files alone, with the appropriate instructions and tools in  a directory are sufficient to produce the results.
A file is a  'PrimarySource' file when no other explanation for its existence is available other than ''somebody entered it's ascii source by editing a file'' (or copying fragments they previously wrote or copied from someone else).   Various means for doing this go under the guise of one's  favorite, or not-so-favorite text edtior.   This has been the case for the better part of 50 years of computing. Presumably, spoken and other means of creating text will be available shortly.  In any case, it was the editing by a human which created the ascii text.   The inevitable reference to ascii serves notice on the so-called "word processors" which process words (whatever it is to process a word) but cannot "edit text".   

A PrimarySource undergoes transformations on it's way to becoming a useful component of a computer program, document, or data table. A bad habit of mine is to always look for the tighter factor.    On seeing a like fragment of text for the third time, I'm struck with the urge to generalize, to seek the common factor, remove it into a template managed by some other tool, and begin re-using the more general fragment.    The primary source has moved back up the food chain by a notch.   The template is now a primary source as the the invoking fragment.   Hopefully, these can be managed at the file level, so that the invoking text is either oft-repeated in a separate file, or a process may be arranged to have the combining tool pass over the invoking text, and expand the template.  

A common example of a PrimarySource is the text of a C, C++, or Java program.  Also, the text of this file is a primary source.   to the extent an image is included in this file, the instructions (HTML at bottom) to include the picture may, or may not be primary source.   Consider them primary if I have typed the HTML, copied it from someone or somewhere, and maintain the HTML souce as my maintenance means.  On the other hand, this being a TiddlyWiki, which has a meta-language for including files, and in particular images, the HTML souce may be ephemeral, and created on the fly by the underlying JavaScript in the body of this file.   This file viewed in it's ascii source is the PrimarySource. 

A consequence of this fact:   I have typed a good deal of what you see here, requires me to backup my work.   Fortunately, the TiddlyWiki tool provides a ready means to do that,  saving me from destroying my prior work, or doing inadvertent mayhem.

[[click here|QVSUsersManual]] to return to the QVSUsersManual.
Display the function description by clicking on the highlighted text.  It operates as a toggle.  After {{{ source qvslib }}} these functions become available to the user on the command line.
!!The User Functions
Characterized by standard alpha-numeric function names:
<<slider qvsfl [[QVSbflist]] "bflist - Backup File LIST">>
<<slider qvsfl [[QVScleanlist]] "cleanlist - what is the list of files to CLEAN up">>
<<slider qvsfl [[QVSde]] "de  - Diary Entry">>
<<slider qvsfl [[QVSdotfile]] "dotfile - create a DOT File">>
<<slider qvsfl [[QVSlastNameVer]] "lastNameVer - what's name of the LASTNAMEdVERsion">>
<<slider qvsfl [[QVSlastVer]] "lastVer - what's the name of the LASTVERsion">>
<<slider qvsfl [[QVSok2ver]] "ok2ver - is it OK to VERsion">>
<<slider qvsfl [[QVSqvs]] "qvs -  run the Quick Version System">>
<<slider qvsfl [[QVSqvs_help]] "qvs_help - help me with QVS">>
<<slider qvsfl [[QVSqvsfrom]] "qvsfrom - set the locations of VER_BASE, HOME, from and stored">>
<<slider qvsfl [[QVSqvsto]] "qvsto - set the location of the VER_HOME, where the versions are stored">>
<<slider qvsfl [[QVSrollupV]] "rollupV - ROLL UP all Versions with the same name">>
<<slider qvsfl [[QVSthisSecond]] "thisSecond - ">>
<<slider qvsfl [[QVSverDirectory]] "verDirectory - What is the VERsion Directory">>
<<slider qvsfl [[QVSver_rwd]] "ver_rwd - the Relative Working Directory">>
<<slider qvsfl [[QVSverbase]] "verbase - what is the VERsion BASE, of the files needing version history">>
<<slider qvsfl [[QVSverfiles]] "verfiles - the FileofFiles list of VERsioned FILES">>
<<slider qvsfl [[QVSverhome]] "verhome -  what is the VERsion HOME, where the versions are stored">>
<<slider qvsfl [[QVSverlocn]] "verlocn - the directory dependent Location of the Version copies">>
The QVS ENVIRONMENT Variables control the source and destination of the versioned files.   A user working in a sub-directory of their ''HOME'' directory may ignore these until there is need to either do save versions in another location, or when it may be necessary to save your versions in another place in the current or other file system.
<<slider qvsfl [[VER_HOME]] "VER_HOME -what is the VERsion HOME, where the versions are stored">>
<<slider qvsfl [[VER_BASE]] "VER_BASE -what is the common root, or BASE from where the development is taking place">>
!!!Version Query functions
!!!Version Setting Functions
QVS is the barest collection of bash functions providing individual users with a QuickVersionSystem.   The QVS saves selected set of files from the user's current directory in a versioned location.  The default version names are ''~YYYYMMDDhhmmss'', or a name of the user's choosing.  The system is sufficiently transparent so the informed bash user may manually override any defaults.   

The principal problem solved by the QVS is to give a version-conscious user means to quickly (little overhead in time and distraction) save their own versions of PrimarySource files in anticipation of subsequent checkin to a mandated version system.   The user's environment is a Unix server with a bash shell and tclsh.   These have been developed on ~SunOS and my own ~IMac running Mac OS X, both of which satisfy these requirements.   See the discussion of PrimarySource to better understand the files requiring versioned backup.

While QVS was not designed for shared use, a collection feature, implying the need for user's to plan their version names, allows these milestones to be simultaneously collected for movement into the more formal version systems.  

QVS is a command-line system (is there any other?).  Since QVS is implemented as a bash function library, here's the [[user function reference|QVSFunctionLibrary]] See the [[installation instructions|QuickVersionSystem]] to obtain and  install a copy.    Before proceeding, you may want to read these QVS_UseCases.  From the command line issue these commands:
   % source qvslib            # once logged in, only once, and then
   % qvs                      # or
   % qvs aMomentToRemember    # no spaces in the names
In the first instance, //source qvslib// loads the function library and displays the help file.  When using it routinely, you will create a backed-up  version of all PrimaryFiles in a VersionDirectory named for the current second: //~YYYYMMDDhhmmss//,  in the later,  the version will be named, with case signifcant: //aMomentToRemember// .   A user needs to list their PrimaryFiles in a FileOfFiles whose name defaults to ''.files''.   As a practical matter, the file itself should be among the list of files.   For example, the first thing you will want to do, before starting to save your version history is:
   % echo .files > .files
Then, as you add files to the saveable collection, simply add their name to the list.   A utility ''add2files'' has been provided. 
   % add2files   anImportantFile    # you might have first said:
   % add2files .files
It's sufficiently benign so that repeated uses don't cause duplication in the list, which is kept sorted.

The list of files may certainly be manually edited, as an example of QVS transparency.   Also if necessary, any name may be chosen for the FileOfFiles by setting the environment variable VERFILES, and used by the user-function ''verfiles''.  e.g.
     % setenv  VERFILES .files
     % verfiles     #   echo's
When collaborating with partners, each of you working in separate locations, plan to share a set of version names, representing milestones, not necessarily in time, but in common, or necessary features.   If working in reasonable close location, on the same server,  then use a tool ''rollupV'' which collects the separately created versions, all with an identical name:
    % cd /common/ancestor          # of all like versions
    % rollupV aParticularVersion   # creates a directory tree:
                                 #  ./Version/aParticularVersion with all instances
see the source code for a complete understanding.

Again, here is the [[function library details|QVSFunctionLibrary]]
So, what problems does QVS solve:
*your project's official version system is so unwieldy, such that committing an intermittent change is either time, paper, or process-prohibitive, not to mention possibly confounding others.
*you'd like to save a current snap-shot of your work and do some experimenting where you don't necessarily want to expose this work to a larger system
*you're running a demonstration where you'd like to toggle different versions of a small number of files through a sequence of changes.
*you just like to be careful with your changes in your own time and fashion.
What does QVS ''not'' do:
*so-called network backup -- try a remote mount though,
*hierarchical version names -- just a single list of names (or timestamp)
*diff versioned files -- you can do it yourself
*restore a particular version -- " ditto "

The simplest use of QVS is by the single user on one or two related projects.   If the user is working in a sub-directory of their HOME directory, there is no need to be aware of controlling ENVIRONMENT variables.   (If this ever does become a need, to work elsewhere than in a HOME directory, see the discussion of ENVIRONMENT Variables in the QVSFunctionLibrary).  

For our purposes, a project is in a single directory.  Rather, the unit of a version is in a single directory.   This is not to say that multiple directories may not use identical version names.  In fact, this is how projects may be synchronized.   But remember QVS is a ''quick'' version system, with emphasis on the //quick//.  Regardless of the size of a project, from time to time, a single user in a single directory will enter a command:
    $   qvs     # or
    $   qvs  SomeMeaningfulName
In the first case, the user creates a version whose name is the current ''~YYYYMMDDhhmmss'', in the later, the version is named ''~SomeMeaningfulName''.   The single user may readily retrieve a given version:
    $ cp  */SomeMeaningfulName/* .
and all the files of that version are restored to the current directory.

So, how might QVS be used:
*a single user with a limited number of related directories.
*a single user with projects destined for a more formal system
*a few users collaborating in the same environment, possibly in the same group on the same server,
*a number of users collaborating and expecting to formally collect their work under self-selected feature-set names.
In all cases, users act on their own, or in teams small enough to share source files.  QVS is not a  //wait-for-me-to-check-this-in// type of version system.   If we both have to make fixes, we collaborate on the same source file.   QVS is able enough to make a quick version, so that as different hands pass over the same file, there is almost no expense to saving an easily retrieved copy.

In the cases where a more formal system: CVS, or such will hold featured milestones, and users don't have momentary access to one another's source, then QVS can hold all the intermediate steps, and using pre-determined feature-set names, collect the disparate pieces and store them from their original location to the more formal system.

Where users have occaisional access to one another's work on related systems, networked as one, and in particular where systems may be cross-mounted and accessible with symbolic links, then features allow the separate work to be collected as one "clean" source tree. 

QVS pre-supposes only a Unix<html>&reg;</html> environment, the ''bash'' shell, and a commitment to use //ascii//.   

QVS may store non-ascii files, but, one asks, what is the purpose of version control for those files whose differences may not be tracked to changing a line of text.

[[Return|QVSUsersManual]] to the QVSUsersManual.
   $ _de_hdr
returns a decorated, sortable date stamp.
[[_doqvs|QVS_doqvs]]: a local function
   $ _doqvs [file ... ]
the heart of the [[qvs|QVSqvs]] tool.  
It first calls [[bkup]] on the //file ...// arguments, such that changed files are pushed onto the backup history.
This is the one piece of code that knows the backup location, so the names of the backed-up files are listed for the user.
USAGE: a local function
   $ _doqvs_at  a-versioned-directory
creates //a-versioned-directory// then links the backed up files to that directory. The list of files was returned from calling [[_doqvs|QVS_doqvs]] with the list of files returned from [[bflist|QVSbflist]].
USAGE: a local function
   $ _mkVername candidate-version-name
returns the //candidate-version-name// to the caller if a directory does not exist with this name in the [[verlocn|QVSverlocn]], otherwise it returns announcement of an existing version and exits with an error.
USAGE: a local function
   $ _qvfnames [name ...]
returns the list of files from the list of //names ... //.
    % add2files name   # e.g. 
    % add2files .files
puts no more than a single name in the [[dotfile|QVSdotfile]] named //.name//  
In the second example the name //.files// is added to the file ''.files'', namely itself.

see [[rmFmfiles|QVSrmFmfiles]]
   $ bflist [file ... ]
lists the current BackupFileList, a list of files, defaulting to the list in the FileofFiles given by [[verfiles|QVSverfiles]], or if not existant, the //file ...// arguments on the command line, and if no arguments, all the files in the current directory.  Absent a [[verfiles|QVSverfiles]], it uses [[_qvfnames|QVS_qvfnames]] to return the list of existing file arguments.
   $ cleanlist
produces the list of un-versioned files, not in the [[verfiles|QVSverfiles]].   Presumably, if all the PrimaryFiles are in the list of ''verfiles'', and [[qvs|QVSqvs]] has been executed after all changes are made,  then one could safely {{{ rm -f $(cleanlist) }}}.
   $ de 
Create a Diary Entry.   Opens the user's EDITOR Environment variable named editor, defaulting to ''vi'' on a /tmp file where the user is free to insert comments.  The time-stamped comments are inserted at the head of a ''.diary'' file in the current directory.   An  {{{ $ }}}  [[add2files|QVSadd2files]] ''diary'' will insure the diary is also saved in the version history. It uses [[_de_hdr|QVS_de_hdr]] to supply the diary entry header.
   $ dotfile name      # e.g. dotfile files
creates two user functions: ''add2''//name//, and ''rmFm''//name//, which respectively add and remove a single name from the dotfile named //.name// 
It is used in the [[qvslib]] to create two functions:  [[add2files|QVSadd2files]] and [[rmFmfiles|QVSrmFmfiles]], which respectively add or remove a single name from the file ''.files''
   $ lastNameVer ...
returns the most recent ''named'' version, one which does not match a sequence of digits beginning with the regular expression: {{{ 2[0-9][0-9]* }}}
   $ lastVer ...
returns the most recent version, ''named'' or not.
   $ ok2ver 
returns true if the VER_BASE is a parent of the current working directory.
[[verbase|QVSverbase]] -- shows the value of VER_BASE
[[qvsfrom|QVSqvsfrom]] -- sets VER_BASE and VER_HOME
The main user entry in the QuickVersionSystem.
   $ qvs [versionName]
stores the list of files, returned by the [[bflist|QVSbflist]] command in the //versionName//, which defaults to [[thisSecond|QVSthisSecond]].
It first runs [[bkup]] on the selected files, and takes advantage of knowing the ''backup'' directory location, linking the current list (not necessarily all) files to the version directory given by [[verlocn|QVSverlocn]]

[[ok2ver|QVSok2ver]], [[verlocn|QVSverlocn]], [[thisSecond|QVSthisSecond]], [[_doqvs_at|QVS_doqvs_at]], [[_mkVername|QVS_mkVername]]
   $ qvs_help 
produces a text summary for the top functions.  Grauitously supplied when the users sources the library:
   $ source qvslib
a necessary first step to use these functions.
   $ qvsfrom [directory]
sets the VER_HOME and VER_BASE environment variables, both defaulting to the user's HOME directory.   If working in a subdirectory of the HOME directory, it needn't be set.  Otherwise, set it to an appropriate parent of the working directory.  This might be the root of a group or project.   Typically VER_HOME and VER_BASE are the same parent directory.   If you are using a separate HOME and BASE, set both first, with ''qvsfrom'', then set the distant HOME with [[qvsto|QVSqvsto]]

VER_BASE must be a parent of the current directory

[[verbase|QVSverbase]] -- returns the VER_BASE environment's value.
[[qvsto|QVSqvsto]] -- sets VER_HOME
[[ok2ver|QVSok2ver]] -- tests the assertion that VER_BASE is a parent directory.
   $ qvsto [directory]
sets the VER_HOME environment variable, defaulting to the user's HOME directory.   If working in a subdirectory of the HOME directory, it needn't be set.  Otherwise, set it to an appropriate parent of the working directory.  This might be the root of a group or project.

[[verhome|QVSverhome]] -- returns the VER_HOME environment's value.
[[qvsfrom|QVSqvsfrom]] -- sets both VER_BASE and VER_HOME
    % rmFmfiles name   # e.g. 
    % rmFmfiles .files
removes a single name in the [[dotfile|QVSdotfile]] named //.name//  
In the second example the name //.files// is removed from the file ''.files'', namely itself.

See [[add2files|QVSadd2files]].
   $ rollupV anExistingVersion
working in a common parent of some existing versioned files
   $ thisSecond
returns the date, to the second, in ''~YYYYMMDDhhmmss'' format
   $ verDirectory { verisionfunction [lastVer] }
returns the path to the current version directory, given the current ''working'' directory, the version function argument, and the ENVIRONMENT Variables VER_BASE and VER_HOME.     A user editing text in a sub-directory of their HOME directory will see the version direction is merely the {{{ .ver/ }}} subdirectory, where the namedVerions and the dated versions are all stored.

The version fuction argument defaults to [[lastVer|QVSlastVer]] and can also accept [[lastNameVer|QVSlastNameVer]].
   $ ver_rwd
returns the Relative Working Directory of the version source.  obtain by removing the VER_BASE leading portion of the current directory.
   $ verbase 
returns the value of the VER_BASE environment variable, which is the common parent of the user's version environment.

[[qvsfrom|QVSqvsfrom]] -- sets VER_BASE (and VER_HOME)
   $ verfiles
returns the VERFILES Environment variable value, and if not set, the file ''.files''
   $ verhome 
returns the root, or home location where versions are stored.  The name is held in the ''VER_HOME'' Environment variable, defaulting to the users HOME directory.

[[qvsto|QVSqvsto]] -- sets VER_HOME
   $ verlocn 
returns the directory location of the stored versions for the files in the current directory.  It may be nearby, if VER_BASE and VER_HOME are identical (usually, both set to HOME);  for distant versioning, set VER_HOME to a non-parent directory.   VER_BASE must be a parent of the current directory.
Here's a picture:
   verlocn:    VER_HOME + (  PWD - VER_BASE)   # the latter is the ver_rwd portion
[[verbase|QVSverbase]] -- the value of VER_BASE
[[verhome|QVSverhome]] -- the value of VER_HOME
[[ver_rwd|QVSver_rwd]] -- the Relative Working Directory
#Download the archive: <html><a href="qvs.tar.gz">qvs.tar.gz</a></html> to a ./tmp directory
#open the archive {{{ gunzip qvs.tar.gz; tar -xvf qvs.tar; }}}
#read the [[install.sh|InstallableShellFile]]
#change the "tmp/bin"   to simply "bin",  if you want it in your HOME/bin. "inpath" properly executed, adds it's location  (provided "/bin" is in the name when it's invoked ) into your PATH variable.  (SHELL=bash)

You have two  essential tools:
* [[bkup]], and
* qvs
detailed here:
Here's the whole QVSUsersManual, This is the short version:
    source qvslib    # NECESSARY, and shows help message

    bkup  file ...   # e.g.   bkup $(< .files)   backups up the changed files
                     # in the list of ".files",  down the ever-deeper chain of
                     #  .bak/.bak ... directories,  where

    qvs [ name ]     #  first does a 'bkup $(< .files)', followed by linking the 
                     # current, latest backup, to a named version, defaulting
                     # to  YYYYMMDDhhmmss in the ".ver" directory

                     # the one "gotcha" is you have to be working in some
                     # subdirectory of your HOME, or set one (or two) VER_
                     # environment variables to your source and destination
                     # of the version base. 
judicious use of version names (e.g. qvs //~PickAMeaningfulName//)  used in mulitple directories allows the easy collection of separate activities, eg.
         cd /group/home
         find .  -type f | grep PickAMeaningfulName 
delivers the entire list of files (in their versioned location) to the output, where presumably they could be linked into a separate tree, suitable for checking to any corporate, conventional source control.
!maintenance guide:
ocassionally you will want to trim the backup list (provided you've done some "versioning",   e.g.
    find .bak/.bak/.bak/.bak/.bak | xargs rm -f  # leaves 5 copies
where the backup tree looks like this:
[img[Backup File Tree|image/backupdirectorytree.gif]]
[[send me|mailto:mcgowan AT alum DOT mit DOT edu]] your FeatureRequests
use msconfig from the Start, Run menu
formerly Benedictine Technology tiddler:
[[ Core Curriculum | http://www.state.nj.us/njded/cccs/s8_tech.htm ]] 
[[ On-line Typing Lessons | http://www.senselang.com/ ]]
[[Access Examples|http://www.access-programmers.co.uk/learning2/sample.htm]]
I'm working on a shell tutorial, which promotes ideas of why and how to [[factor a shell|http://mcgowans.org/m4site/shelleg.html]]
Marty ~McGowan joined Fidessa (FDSA,L),  then known as royal''blue'' in July '06. At Fidessa, working with Enterprise management, Service Delivery, Development Hosted, Compliance, Marketing, UK training, and in collaboration with his US training partner developed the New Hire Training.  In addition, he now trains the Tcl programming language, the Windows client design, and the Fidessa infrastructure. 

Marty came to Fidessa directly from 4 years as the Technology Director at Benedictine Academy in Elizabeth NJ. Prior to that, in a nearly 20 year telecommunications career, he frequently trained programmers, and lately, broadband telecommunications users, provisioning and network management in North and South America. 

As an adjunct instructor, he has taught college courses in programming languages, data structures, and in the math-intensive Celestial Mechanics and Astrodynamics. 

He has considerable experience in the Unix operating system and its development utilities, notably serving on the IEEE standards committees from 1987 through 1991, then while with AT&T.  He contributed to and voted on the OS, Utilities, and Test Methods POSIX (IEEE P1003.x) standards. He was a product manager for AT&T C Programmer Programming Utilities, bringing out the first commercially successful profiling and browsing tools for the Unix/C environment. As a developer, he maintained one of the more successful intranet applications: AT&T's global 300,000-entry corporate directory, serving more than 1 million queries per month. 

He is a co-holder, with AT&T (now Lucent Technologies) associates of US Patent #5,559,520  [[Wireless information system for acquiring location related information|http://www.google.com/search?q=patent+5559520]]
Public ~NotePad
Marty ~McGowan
*[[Library Thing|http://librarything.com/profile/applemcg]]
*[[@ Online Journalism Review|http://www.ojr.org/ojr/people/AppleMcG/]]
OK, here i sit, reading [[They Write the Right Stuff|http://www.fastcompany.com/online/06/writestuff_Printer_Friendly.html]] feeling i should take something away.  How about:
*the database is the software base.  think of [[cummings]] as a database
*don't just fix the mistakes -- fix whatever prompted them in the first place. implication:  the //BUG:// database.
Katie, at [[StoryCorps|http://storycorps.net]] is giving us lots of pride with her accomplishments there.   This page is a reflection of her outreach to the [[Contemporary Jewish Museum in SF|http://www.thecjm.org/index.php?option=com_ccevents&scope=exbt&task=detail&oid=7]]
.smiconsize img { width:24px;}
.iconsize img { width:40px;}
.pixsize img { width:64px;}
# A Program to take
# INPUT:   "S" strings [R0] of from 1 thru C unique [R1] characters each, such that
#     0 < c(i) <= C for the s(i),
# with the
# CONSTRAINT: the size of H [R2], which is the universe of characters = S
# and produce as
# OUTPUT:  the K permissible single-character lists, each of length S,
#    such that each of the single-character h(i) appear only once, having
#    been a member of s(i).
# and implemented with:
puts $argv
puts [string length $argv]
set S [llength $argv]   ;puts "S: $S" ; # [R0]
set H [list]                     ;# R2.a   a list
proc pickH { l str nth } {
            global H
            global where
            puts "$l: $str"
            while { $l > 0 } {
proc collectH { l str nth } {
            global H
            global where
            global plength
            set plength($nth)
            puts "$l: $str"
            while { $l > 0 } {
                        incr l -1
                        set c [string range $str $l $l]
                        if { [lsearch [string range $str 1 [expr $l - 1]] $c] >= 0 } {
                                    # it's nolonger unique [R1], so
                                    puts stderr "found $c duplicate in $str"

                        lappend where($c) $nth               ;# impliments [I0]
                        if { [lsearch $H $c] < 0 } {
                                    # it's not in universe of characters [R2], so
                                    lappend H $c                    
set scount 0
foreach str $argv {
            # a number of strings [R0]
            collectH [string length $str] $str $scount
            incr scount
puts "H: $H"
foreach chr $H {
            global where
            foreach str $where($chr) {
                        puts "$chr, $str: [lrange $argv $str $str]"
# recursion begins right here.
# pass down the remaining strings, starting with the argv,
# along with a vector of the remaining elements in each position
set scount 0
foreach str $argv {
            pickH [string length $str] $str $scount
            incr scount
go here for the IncludeList
[[Upgrade|http://tiddlywiki.com/#HowToUpgrade]] <<version>>
Often, in election times being the best example, we see statistics expressed as a percentage of the electorate.   Or as a fraction of a given population.   

In this recent election of 2008, for example, we saw the % of African-American (black) voters who voted for the republican candidate.   And compared to the elections since 1980, the reagan revolution.   reagan gained a high of 14%.  this year it was down to 4%.  some would observe this is a difference of 10%.    but it's not the same 10% as the difference between 45 and 55%.    it's a much harder group to reach.   as don douglas used to say, "there's always more catsup in the bottle".   but that last drop is harder to get out than any before, with the possible exception of the first.

So, i propose a simple numeric scale  (positive numbers above 50%, negative below), where the proportions are respected.  Note, at the low (and high) end, the difference between say 4 and 14 percent is 2 1/2 times.   14% is 250% of 4%.     That's the proportion we're trying to get at.

If we make 50% equal to zero, that suggests an even distribution, half on one side, half on the other.   50% equals one half, or 1 / 2.   Let's make each inverse fraction one more step down.  Therefore if 1/2 = 0, then 1/3 = -1, 1/4 = -2, 1/5 = -3, 1/6 = -4, etc... On the plus side, 2/3 = 1, 3/4 = 2, 4/5 = 3, etc.   Where I wrote ''='' this of course means //map to//.  All that remains is the mapping function.   Starting with this one (which has been modified as i've thought about this):
   y = (2x - 1) / min ( x, 1-x )
With this formula, we see that 14% = -5.14, and 4% = -23.00.   The ratio of 5 to 23 is much more impressive than 14 to 4, and gives,  I believe, a much better representation of the swing in support for the candidates.
The reciprocal, or inverse function is:
   x = 1 / ( 2 - y ),         (y < 0) and
     = ( y + 1 ) / ( y + 2 )  (y > 0)
So, what do you do when sleep is hard to come by?   extend the model in your otherwise dream time.   "y" is now "M", here it is:
   M(x,p) = p * (x - p/2) / x *(p - x)
   0 < x < p

or another way:

   M(x,p) = - (p/x) * (x - p/2) / (x - p)

so {{{ y(x) = M(x,1) }}}

M has the properties of y, except I thought it useful to add "p", typically either 1 (or 100, as in percent with the same outcome).  M is asymptotic to plus and minus infinity at zero and "p", and zero at p/2.

just a note on the development of the function.   i was first thinking of it as y = y (x) where x was expressed as a percent.  after a month, coinciding with my recover from surgery, i thought of generalizing to a non-unit (i.e. other than one) maximum limit.  just this morning (as in the hours after midnight), tossing the formula in my head, i realized i'd left the ''p'' factor out of the numerator.
where "this morning" was 12/27/2008, having composed this on a private site.
A new view of the Trade postulates a time-value, similar to the theory of interest. A seller needn't warrant the price of stock, but takes an exponentially declining interest in the price over time. If the price appreciates or depreciates outside normal bounds, a seller can expect either to receive or pay compensation.

It is even possible the amount can be recorded for each subsequent trade of an issue, with forward consequences for the sellers over generations as well as backward compensations for the sellers. The business case is that at some level, the cost of recording this time-value is more than the amount of subsequent settlement. The ability to do this for profit, for a customer is the business case.

I learned of the LoopbackOption in our USMarkets course at royal''blue'' [[Fidessa|http://www.fidessa.com]]. This seems to be a model of an aspect of the new trade.
Email from Wellstone Action -- 090706
*join us on twitter
**cleaning up my //following// twitterers
***reading the API FAQ
# Installation Guide
# Configuration Guide
# Usage Guide
# TiddlySpot & UploadPlugin Guide

Source: [[TiddlySnip - User Guides|http://tiddlysnip.com/#%5B%5BUser%20Guides%5D%5D]]
TiddlyWiki was developed by Jeremy Ruston. As noted on the official [[TiddlyWiki website|http://www.tiddlywiki.com]], 
>"A TiddlyWiki is like a blog because it's divided up into neat little chunks, but it encourages you to read it by hyperlinking rather than sequentially: if you like, a non-linear blog analogue that binds the individual microcontent items into a cohesive whole." TiddlyWiki represents a novel medium for writing.
If you're not familiar with TiddlyWikis, visit the official TiddlyWiki website. Have a look at these other useful resources for TiddlyWiki beginners:
* Dave Gifford's [[TiddlyWiki for the Rest of Us|http://www.giffmex.org/twfortherestofus.html]]
* Morris Gray's [[TiddlyWiki Help File for Beginners|http://tiddlyspot.com/twhelp/]]
> To decrease your learning curve, you might find Dave Gifford's brief guide on [[How to Read TiddlyWiki's on the Internet|http://www.giffmex.org/twfortherestofus.html#%5B%5BFor%20beginners%3A%20reading%20TiddlyWikis%20on%20the%20Internet%5D%5D]] a useful and quick read.
borrowed from Cynthia Russel's  [[My Qualitative TiddlyWiki| http://technology-escapades.net/qualitative.htm#TiddlyWiki]]
What would it take to get the major media to "balance" their coverage based on economic and practical realities?

To wit:  when I see a letter to the editor of a major metropolitan paper that Bush considered oil shale as an energy source and we should do it now, _someone_ has to point out that a. it was tried, and b. economics says shelve it till we approach $300/bbl (or some other #)

In summary:  who is standing up for reason vs. the purely political?
      April 19th, 2009 at 9:55 pm


      [[superb stuff again|http://www.madkane.com/madness/2009/04/19/yet-another-ode-to-republican-hypocrisy/]]. you sure keep on top of this stuff. i credit you with pointing this one out to me. (even while reading other sources on the TX Ed Dept kerfuffle) Thanks.

      I”m movin my nest from the NewsDarkTime to “it’ Time To Get Liberal”, no Dot Com in this age of retrenchment, but one more leaf on the tree, i’ve updated my website on the form: http://mcgowans.org/marty3/ttgl.html. and starting to get feedback.


      +=+– marty
I'm a life-long Democrat, growing up in Minnesota, where the Republican Convention will be held.  Minnesota is among the most progressive states in the US, well-recognized for its care and consideration for all it's citizens.  One of the labels there is "Minnie-sober" for all the abuse treatment centers there.   Even Republicans from MN have been among the more progressive.  

When Paul Wellstone died six years ago, I was (I believe) the originator of the saying, WWWD -- What Would Wellstone Do?

My seven-second resume:  MIT, DOD (the NSA), NORAD, UNIX, AT&T, Nokia, and now, approaching retirement, Wall St, where I'm the Lead Technical Trainer for the UK-based Fidessa, a financial services firm who handles order and trades for most all the big banks, reportedly more 90% of the LSE and greater than 1/3 of the NYSE, NASDAQ.

I've worked on a few congressional campaigns, notably in '74 for Bob Ferris and against Chuck Wiggins, of Watergate "Smoking Gun" fame, and this year, with Linda Stender, here in NJ.  In the immediate family, my father was a state legislator in MN, a first cousin represented a district in congress from MN, and a cousin is now in the MN state legislature.  

I am a partisan liberal, who never flinched from being identified with the L word, and have two sayings about our republican opponents, the first is about my voting record, the second more philosophical:

  "I've never met a Republican who _needed_ my vote".

  "Never has an increase in public cynicism failed to benefit the Republican party".

  I'll be voting for Obama, supporting him from the moment Edwards dropped out of the race.

  Why?  take energy policy for instance:  aside from Obama's sop to the political winds with an "I'll drill" option, his policy is based on technical and economic realities.

  But, more important, a President's only job requirement is "to lead".   Obama established that by his campaign and his careful rhetoric. He draws people to him, in healthy ways.   When things are going against him, you can see his frustation rise, but not in either self- of policy-destructive ways.

  I read "Audacity of Hope"; it's been out a few years.  It would be hard to read that and not be  persuaded, particularly in the chapter where he  reveals how much he's come to understand his reliance on Michelle and her sacrifices for their family.   He says it in a way that blunts any attempt to label it "self-serving".

  Also, he freely admits the title of the book comes from none other than the very controversial Jeremiah Wright.  Considering when it was published it may have been an easier admission; I consider its honesty part of the strong Obama character.

  Not to mention the need for healing in this country and with our international partners whose support necessarily wavers.  None of this can really get started with anything other than a President Obama.

+=+-- Marty McGowan
Upload users
From MoodleDocs

Location: Administration > Users > Accounts > Upload users

The upload users page allows you to import a list of users via a text file. Moodle creates an account for each user and, if you want, can also enrol students in courses and arrange them in groups.

The user data text file must follow a certain format, as described below.


    * 1 Flat file format
    * 2 Updating existing accounts
    * 3 Encoding
    * 4 Hints
          o 4.1 Spreadsheet
          o 4.2 Country
    * 5 See also

Source: [[Upload users - MoodleDocs|http://docs.moodle.org/en/Upload_users]]
The EnvironmentVariable VER_BASE is the local base of versioned files.   It should not include the current directory.  e.g. if the working directory requiring version control is, say {{{ /home/me/package/src/component}}}, and you expect to include this work in a group-wide {{{ package}}}, then HOME, assuming {{{ HOME=/home/me }}} is the default, and a logical choice.  

VER_BASE must always be a leading component of the current directory.  QVS warns you if it is not.

See Also:
The EnvironmentVariable VER_HOME is the destination of versioned files.  It is the HOME base of the version controlled files.   It may be identical to the user's VER_BASE, or it may be remote (and on separate file system).  e.g. if the working directory requiring version control is, say {{{ /home/me/package/src/component}}}, and you expect to include this work in a group-wide {{{ package}}}, then HOME, assuming {{{ HOME=/home/me }}} is the default, and a logical choice.  

VER_HOME must always be a full path name, e.g.  {{{ VER_HOME=/home/group}}}.

See Also:
*Paste the copied fields in the DatePost column of the WachoviaIn sheet. 
*propagate the last four digits of the account number in the Acct column
*enter the names of check recepients in the Notes column
*copy the new DatePost entries into the CvtDate sheet (in the mm/dd/yyyy column)
**propogate the formula in columns TRIM, MM/DD, and yymmdd
**copy the result from the yyyymmdd column (on CvtDate) and
**PasteSpecial the results in the Date column (back on WachoviaIn)
Symbols, links from the [[TV Show|http://wealthtrack.com]]

##Black Swan -- Nasim Taleb
##large cap growth -- IVV
##national Treasury BILLS
##Gold: IPU 
   USB         "Top Trio"                                      MyUSB
   friends     "Friends, weblogs"                        MyFriends 
   social       "My Network Memberships"         SocialNetwork
  personal   "Personal Sites, Articles, Weblogs"  PersonalSites 

[[What is it When]] we’ve become too anonymous to chasten one another?

How big is a town where you feel restrained to tell your overly obnoxious fellow traveler their behavior needs restraint?

Today was a good case in point: on the south-ferry-bound 1 line, a pair got on at 14th street, she with the king of hearts on her back, he with a gold cross.  When the trip was over,  and coming up the escalator at the ferry stop, I was thinking of asking them, it only being 8 am, how difficult it might be to keep up their act for a whole day.   For me it began when they sat down three seats to my left; the girl in between got up and left.  An amiable grandfather and grandson headed out to the platform for the next car; I, more slowly, followed going through the illegal-while-moving inter-car door.   The obnoxious couple was filling their car  with their conversation, which wasn’t that expletively-laced.  And a waft of bourbon was easily detectable at my range.   For a moment I was in awe; surely this glee is short-lived, the conversation being about how lucky they were to have seats, apparently having gotten off the packed express across the platform.  On reflection, that must have been an experience for their fellow passengers.

It’s over now; the couple strolled, not sauntered off in the direction of the ferry slip, no doubt to entertain others on the public conveyances NYC offers.   And this only took 15 minutes of my day and my company’s time.    It’s like a tax, isn’t it?

-- Fri, May 15 '09

*TiddlyWiki -- the mother ship
*[[TiddlerToddler|http://tiddlertoddler.tiddlyspot.com/]] -- but not for dummys
*[[twhelp|http://tiddlyspot.com/twhelp/]] -- climbing the ladder
*[[markup|http://tiddlywiki.org/wiki/TiddlyWiki_Markup]] -- terse user guide
*[[the Tool Shed|http://www.tiddlytools.com/]] -- busy start-up; not for the casual
*© [[osmosoft|http://www.osmosoft.com]] 2005
The [[bkup]] tool solves the ''where-can-i-put-this-file'' problem, caused when a program picks a naming convention to save a backup.  Sooner or later, you will run out of names.  This tool, [[bkup]] postpones that moment indefinitely.  Here's the picture:
[img[Backup filesystem|image/bkup-theIdea.png]]
When the user issues this command
  $ bkup file.suf   # in someNamedDirectory
then ''bkup'' compares the two files:  {{{ ./file.suf }}} and {{{./.bak/file.suf }}}.  If they are different, then successively lower versions of {{{.bak/ ... /file.suf}}} are moved down one level of backup until exhausted, and the current file {{{ ./file.suf }}} is moved to {{{ .bak/file.suf}}}, and a copy is created in the current directory.

This tree is virtually inexhaustable.   Sooner or later, a user will want to remove the backups below a certain level.  Realize they were all created by moving the file, so each modification time reflects the time the file was last modified, not the time it was moved into place.  

A user quickly realizes versions of a file may be compared with the "diff" command:
   $ diff file.suf ./.bak      # shows NO differences unless file.suf changes, OR
   $ diff file.suf ./.bak/.bak # is guaranteed to show differences.
All files current at a given age may be exposed by:
   $ find .bak -mtime +N | xargs ls -lrt
will list the files no newer than N days old.
[[inpath]] adds the current directory (see [[.sturc]]) to the user's ''PATH'' [[Environment Variable|http://en.wikipedia.org/wiki/Environment_variable]].
comment ()      { echo "$@" 1>&2; }
_presolve ()    { cd $1; PWD=`pwd`; case $PATH in
        *:$PWD:*|*:$PWD|$PWD:*) ;;
        *)      PATH=$PATH:$PWD; export PATH ; exec ${SHELL:-/bin/sh};;
        esac; }
case $0 in
*/bin/*) _presolve `dirname $0` ;;
*)      comment  "USAGE: {some}/bin/`basename $0`";;
source          qvslib  > /dev/null
cleanlist()     { (grep '^\.' .files; ls) | sort | comm -3 - .files; }
add2files()     { (echo $1; cat .files) | sort -u >.y; mv .y .files; }
rmFmfiles()     { grep -v "^$1\$" .files          >.y; mv .y .files; }

existing()  { [[ -f $1 ]]; }
nonempty()  { [[ -s $1 ]]; }
waiting()       { echo "$@" >> .waiting.log; }
newer() {  # newer Name Other ...  echos Other... NEWER than Name
        existing $1 || return 1
        set -- $(ls -drt $* | awk "
        printing > 0    { print; next }
        \$1 ~ /^$1\$/   { printing++ }")
        echo $* 1>&2
        return $#
waiting()       { echo "$@" >> .waiting.log; }
doit()          { echo "$@" 1>&1; eval "$@"; }

mfgd()  { rmFmFiles $1; }
jc()    { doit javac ${JAVA_CFLAGS} $1.java 2> $1.err
          add2files $1.java
tc()    { newer ${JAVA_TEST}.$1.out ${JAVA_TEST}.class || {
                TC_OUTPUT=${JAVA_TEST}.$1.out; shift
                doit java  ${JAVA_TEST} "$@" | tee $TC_OUTPUT
jj()    {
        newer $1.class $1.java  || jc $1
        nonempty $1.err         && {
                ${EDITOR:-vi} $1.err $1.java
mj()    {
        jj "$@"
        JAVA_TEST=$1; shift
        tc 00 "$@"
help_mklib()    { cat <<EOF

  Mklib is a Java compiler -- runtime engine.

  "jc" is the simple Java compiler, and leaves the error messages in
       {file}.err, when invoked as jc {file}, assuming {file}.java exists.

        it uses JAVA_CFLAGS.

  "jj" -- Just Java -- compiles the class when required.

  "mj" is the higher level run-time call, avoiding an unnecessary
        re-compilation, and runs java on the command arguments OR
        invokes the editor on a non-empty error file.
        it also creates a ".out" file; if this is newer than the ".class"
        file, then the test is skipped. Calls "jj" and "tc".

        Sets "JAVA_TEST" so succesive "tc" calls can be separate testcases.

  "tc" is  a separate TestCase with the current Executable {JAVA_TEST}
        supply successive NN (01, 02, ... ) for separte output files, supplying
        only the aruguments to the successive testcases.

  Remember to:

 % source mklib         # since this is
 % help_mklib

 also,   add2files, rmFmfiles, newer, doit, ...

I'm working on these various [[topic]]s.   They may be reviews, biography, thoughts of the way things should be (or at least represented).