* look at the dates on the files....\n* {{{ls -l}}} gives a lot of information, not very focussed on date..\n* what if we had a histogram of the dates, then we could easily see if there was a problem.\n<<slider chklhhistog "Print a modification date histogram" "Show: Print a modification date histogram">>\n\n
!Welcome to your ''tiddlyspot.com'' ~TiddlyWiki!\n''[[tiddlyspot.com|http://tiddlyspot.com]]'' gives you an instant [[TiddlyWiki|http://tiddlywiki.com]] hosted on our ''tiddlyspot.com'' servers.\n\nWant to work online? No problem, you can go to your ''tiddlyspot.com'' URL (which is http://DaveG.tiddlyspot.com/index.html ) and start editing. Click "save to web" and your changes are saved directly to your ''tiddlyspot.com'' home -- no messing about with local files or ftp.\n\nWant to work offline? No problem, your ''tiddlyspot.com'' ~TiddlyWiki is a real, fully functioning ~TiddlyWiki that you can save onto your hard drive or USB stick. Use the link below to save to your local computer. As you make changes, use the "save to disk" button to save to your local file. Whenever you're ready to sync up again, just click "save to web".\n\n!To save online\nEnter the upload password provided when you created your ~TiddlyWiki. Then click the "save to web" button below (or in the right side column) to save your ~TiddlyWiki.\nUpload Password: <<option pasUploadPassword>>\n<<upload http://DaveG.tiddlyspot.com/store.cgi index.html . . daveg>>\n\n!To save offline\nTo take this ~TiddlyWiki offline, right click on this link: http://DaveG.tiddlyspot.com/index.html and choose "save as.."\n\n!Learn more about ~TiddlyWiki\nFind out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki Guides|http://tiddlywikiguides.org]] for documentation on learning and using ~TiddlyWiki.\n\nThe [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]] is an excellent place to ask questions and get help.\n\n!Enjoy!\nWe hope you like using your ''tiddlyspot.com'' ~TiddlyWiki. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments.\n\n----
<<<\nNo. \nI have tried to use Unix commands available on all versions of Unix, and actually this is not hard to do, because the common, most-useful, commands came in to the Unix world early on and are universally available.\n\nIt is not true to say that all their options are the same (or mean the same across versions). So, if you see examples from this talk failing first check your systems man pages <<man man>>.\nAn obvious place where you may see this is in commands using cut because it is dependent on output being in fixed columns and the output of {{{ls -l}}} and {{{ps}}} for example are system dependent.\n\nThe few shell examples are run on [[Korn shell|http://en.wikipedia.org/wiki/Korn_shell]] which is becoming more widely available since it the source was opened by Lucent. The [[Bash shell|http://en.wikipedia.org/wiki/Bash_shell]] is widely available and is pretty compatible with Korn. Both of these shells descend from the Bourne Shell (sh), and can run Bourne shell scripts without change.\nThey have significant advantages over it for programming and interactive use.\n<<<\n\n\n\n
This macro allows you to define custom environments with a title that are auto-numbered along a tiddler. Each environment can be styled by defining two classes in your CSS, one for the all environment and another for the title. To see the styles used in this example check the BoxesStyleSheet.\n\n<<box Theorem 'Given the integer //n//>2, the equation //x//^^n^^+//y//^^n^^=//z//^^n^^ has no positive integer solutions.'>>\n<<box Example 'Let //X// and //Y// be random variables that . . .'>>\n<<box Exercise 'Show that, if //X// and //Y// are independent random variables, then:\n# ...\n## ...\n## ...\n# ...'>>\n<<box Theorem 'P(A or B)=P(A)+P(B)-P(A and B)'>>\nThe auto-numbering can be replaced by a label.\n\n<<box Example 'Sorry, I have no space here for the demonstration...' '1 (//cont.//)'>>\nOr you can simply skip the auto-numbering.\n\n<<box Question 'Do you like these colorful boxes?' ' '>>\nAt last, the title can also be removed in the stylesheet.\n\n<<box Frame 'Hey, where is my title? And why did you put me in this dark corner?'>>
//{{{\nversion.extensions.BoxesPlugin = {\n major: 1, minor: 0, revision: 0,\n date: new Date(2006, 3, 8), \n type: 'macro',\n source: "http://www.math.ist.utl.pt/~psoares/addons.html#BoxesPlugin"\n};\n\nconfig.macros.box = {counter: {}};\n\nconfig.macros.box.handler= function(place,macroName,params) {\n if(params.length<2){return;}\n var number;\n if(!place.getAttribute('counting')) config.macros.box.counter={};\n place.setAttribute('counting',true);\n var env=params[0];\n var text=params[1];\n if(params.length==3) number=params[2];\n var p = createTiddlyElement(place,"div",null,env);\n var header = createTiddlyElement(p,"div",null,env+" envHeader");\n if(!number){\n if(!config.macros.box.counter[env]){\n config.macros.box.counter[env]=0;\n }\n number=++config.macros.box.counter[env];\n }\n wikify( env+" "+number, header, null, place);\n wikify( text, p, null, place);\n}\n//}}}
.Theorem {\nborder: 1px #666 dashed;\npadding: 0.5em;\nwidth: 55%;\nmargin-left: auto;\nmargin-right: auto;\n}\n\n.Theorem .envHeader{\nbackground: none;\nborder: none;\ncolor: blue;\nmargin: 0 0 0.25em 0;\npadding: 0;\nfont-family: arial;\nfont-size: 1.5em;\nfont-weight: bold;\nwidth: 100%;\n}\n\n.Example {\nbackground: #ffffcc;\npadding: 0.5em;\n}\n\n.Example .envHeader{\nbackground: none;\ncolor: orange;\nmargin: 0 0 0.25em 0;\npadding: 0;\nfont-family: arial;\nfont-size: 1.5em;\nfont-weight: bold;\n}\n\n.Exercise {\nbackground: #e8ffd2;\npadding: 0.5em 0.5em 0.5em 0.6em;\n border-top:solid #e8ffd2 1px;\n border-left:solid #e8ffd2 1px;\n border-bottom:solid green 2px;\n border-right:solid green 2px;\n -moz-border-radius: 1.0em;\nwidth: 20em;\n}\n\n.Exercise .envHeader{\nbackground: none;\nborder: none;\ncolor: green;\nmargin: 0 0 0.25em 0;\npadding: 0;\nfont-family: arial;\nfont-size: 1.5em;\nfont-weight: bold;\nwidth: 100%;\n}\n\n.Frame {\nbackground: #000000;\ncolor: #ffffff;\npadding: 0.5em 0.5em 0.5em 0.6em;\nwidth: 20em;\nmargin-left: auto;\nmargin-right: 0;\n}\n\n.Frame .envHeader{\ndisplay: none;\n}\n\n.Question {\npadding: 0.5em 0.5em 0.5em 0.5em;\nbackground: #ffffcc;\nfont-size: 1.5em;\n}\n\n.Question .envHeader{\nmargin-bottom: 0.25em;\ncolor: red;\nfont-family: arial;\nfont-size: 1.5em;\nfont-weight: bold;\nborder: 2px red solid;\ntext-align: right;\n}
!!!! try this gawk program\n* it assumes the date the file was written is in a line containing the program file path, which begins with ''/report/'' (the path is {{{report/efficay}}} or {{{report/safety}}})\n* On these lines there is a data - which is the file write date \n* we need to find the lines with a date (why not match on lines conatining a date?)\n* then extract the date from the line...\n* this is done with the match function: it returns 1 if it found a matching string, and \n* puts the location into [[awk]] variables that we can plug in to the substring function to get the date into a variable.\n* then the if tests if we found a date on the line and prints the file & date\n{{{\n gawk '/report\s// { match($0,"report[/].*\ssas"); \n file=substr($0,RSTART,RLENGTH);\n ok=match($0,"[0-9]+[A-Z]+[0-9]+"); \n date=substr($0,RSTART,RLENGTH);\n if (ok ) print date, file } ' *.rtf |\n sort -t" " | \n uniq\n}}}\n\n!!!! NOTE:\n* this test does not catch RTF files that are empty or do not have a date.\n* extend this test or make a second test for [[Is this RTF file Empty?]]\n* extra lines added for readability beware if cutting&pasting\n
{{{\nls *.sas7bdat | sed 's/\s(.*\s)\s.sas7bdat/%cmpall\s(ds=\s1);/'\n}}}\n\n* we use sed to add a ''prefix'' and //postfix// to each @@filename@@ (dropping the type)\n* abc.sas7bdat -> ''%cmpall''(@@abc@@//);// \n* The parentheses in the sed expression mark part of the regular expresssion for later reference - it is 'called' by the \s1 in the second string argument to s (substitute)\n* There are many other ways to do this, eg in VSlick, but this is fast and the resulting lines can easily be pasted into SAS.
Yes. If the command runs when you type its name you can see the content with this trick:\n\n{{{\nmore $(whence <script>)\n}}}
Yes.\n\nUse the apply command and list the programs in the order you want. Alternatively just use wild cards if the order doesn't matter.\nOne at a time:\n{{{\napply 'sas -noterminal -noovp %1' *qc*.sas\n}}}\n\nAs subprocesses...\n{{{\napply 'sas -noterminal -noovp %1 &' *qc*.sas\n}}}\nThis could overload the machine!!!\n\nAs one subprocess...\n{{{\napply 'sas -noterminal -noovp %1 ' *qc*.sas &\n}}}\n\nbetter. Even better might be :\n{{{\nnohup nice apply 'sas -noterminal -noovp %1 ' *qc*.sas &\n}}}
!!!! Copy or concatenate: <<man print>>, <<man echo>>, <<man cat>>, $(< //file//)\n!!!! Wrap long rows to fixed length <<man fold>> \n!!!! Take many rows and put more than one-per-line: <<man paste>>\n!!!! Split a big file into named files, by number of lines or [[RE]]: <<man csplit>>\n!!!! Delete duplicated lines: <<man uniq>> (whole line), <<man sort>> -u (lines with duplicated keys -like nodupkey)\n!!!! Transform content : <<man tr>>, <<man iconv>>, <<man expand>>, <<man unexpand>> (sed, awk)\n!!!! Reorder rows: <<man sort>>\n!!!! Select //rows// (only): <<man head>>, <<man tail>>, <<man comm>>, <<man grep>>, <<man uniq>>\n!!!! Select //columns// only: \n* By column number: <<man col>>, <<man colrm>>, <<man paste>>\n* By field or column number: <<man cut>>\n!!!! Select //rows// and / or //columns//\n* By matching content of field(s) only \n** <<man join>> <<man sort>> (with -u option like nodupkey)\n* By RE and with programming: <<wikipedia sed>>, <<wikipedia awk>>, <<wikipedia perl>>, <<wikipedia Ruby_programming_language>>\n* man pages at <<man sed>>, <<man awk>>, <<man perl>>\n** N.B. if you are considering learning perl consider [[ruby|http://www.ruby-lang.org]] instead.\n!!! See Also sortable table in [[UnixTextTools table]]\n//more about awk, nawk about more//
''CheckboxPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman\nsource: http://www.TiddlyTools.com/#CheckboxPlugin \nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nAdd checkboxes to your tiddler content. Checkbox states can be preserved in the document by either automatically modifying the tiddler content or setting/removing tags on specified tiddlers, or they may be saved as local cookies by assigning an optional 'chkID' to the checkbox. Add custom javascript for programmatic initialization and onClick handling for any checkbox. Also provides access to checkbox DOM element data and tracks the checkbox state in TiddlyWiki's config.options[] internal data.\n\n!!!!!Usage\n<<<\nThe checkbox syntax, including all optional parameters, is contained inside a matched set of [ and ] brackets.\n{{{ [x=id(title:tag){init_script}{onclick_script}] }}}\n\nAn alternative syntax lets you place the optional parameters ''outside'' the [ and ] brackets, and is provided for backward-compatibility with existing content that may include checkbox definitions based on earlier releases of this plugin:\n{{{ [x]=id(title:tag){init_script}{onclick_script} }}}\n\n//{{{\n[ ]or[_] and [x]or[X]\n//}}}\nSimple checkboxes. The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked). When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets\n//{{{\n[x=id]\n//}}}\nAssign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}. If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value). If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.\n//{{{\n[x(title:tag)]\n//}}}\nInitializes and tracks the current checkbox state by setting or removing ("TogglyTagging") a particular tag value from a specified tiddler. If you omit the tiddler title (and the ":" separator), the specified tag is assigned to the current tiddler. If you omit the tag value, as in {{{(title:)}}}, the default tag, {{{checked}}}, is assumed. Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler. When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If a tiddler title named in the tag does not exist, the checkbox state defaults to //unselected//. When the checkbox is subsequently changed to //selected//, it will automatically (and silently) create the missing tiddler and then add the tag to it.\n//{{{\n[x{javascript}{javascript}]\n//}}}\nYou can define optional javascript code segments to add custom initialization and/or 'onClick' handling to a checkbox. The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to the default context-object, 'this'.\n\nThe first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state. The second code segment (if present) is executed whenever the checkbox is clicked, so that you can perform programmed responses or intercept and override the checkbox state based on complex logic using the TW core API or custom functions defined in plugins (e.g. testing a particular tiddler title to see if certain tags are set or setting some tags when the checkbox is clicked).\n\nNote: if you want to use the default checkbox initialization processing with a custom onclick function, use this syntax: {{{ [x=id{}{javascript}] }}} \n<<<\n!!!!!Examples\n<<<\n//{{{\n[X] label\n[_] label\n//}}}\nchecked and unchecked static default values\n[X] label\n[_] label\n\n//{{{\n[_=demo] label\n//}}}\ndocument-based value (id='demo', no cookie)\n[_=demo] label\n\n//{{{\n[_=chkDemo] label\n//}}}\ncookie-based value (id='chkDemo')\n[_=chkDemo] label\n\n//{{{\n[_(CheckboxPlugin:demotag)] toggle 'demotag'\n//}}}\ntag-based value (TogglyTagging)\n[_(CheckboxPlugin:demotag)] toggle 'demotag'\ncurrent tags: <script>return store.getTiddler(story.findContainingTiddler(place).id.substr(7)).tags.toString();</script>\n\n//{{{\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n//}}}\ncustom init and onClick functions\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n\nRetrieving option values:\nconfig.options['demo']=<script>return config.options['demo']?"true":"false";</script>\nconfig.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>\n\n!!!!!Installation\nimport (or copy/paste) the following tiddlers into your document:\n''CheckboxPlugin'' (tagged with <<tag systemConfig>>)\n<<<
/***\n''CheckboxPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman\nsource: http://www.TiddlyTools.com/#CheckboxPlugin \nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nAdd checkboxes to your tiddler content. Checkbox states can be preserved in the document by either automatically modifying the tiddler content or setting/removing tags on specified tiddlers, or they may be saved as local cookies by assigning an optional 'chkID' to the checkbox. Add custom javascript for programmatic initialization and onClick handling for any checkbox. Also provides access to checkbox DOM element data and tracks the checkbox state in TiddlyWiki's config.options[] internal data.\n\n!!!!!Usage\n<<<\nThe checkbox syntax, including all optional parameters, is contained inside a matched set of [ and ] brackets.\n{{{ [x=id(title:tag){init_script}{onclick_script}] }}}\n\nAn alternative syntax lets you place the optional parameters ''outside'' the [ and ] brackets, and is provided for backward-compatibility with existing content that may include checkbox definitions based on earlier releases of this plugin:\n{{{ [x]=id(title:tag){init_script}{onclick_script} }}}\n\n//{{{\n[ ]or[_] and [x]or[X]\n//}}}\nSimple checkboxes. The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked). When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets\n//{{{\n[x=id]\n//}}}\nAssign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}. If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value). If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.\n//{{{\n[x(title:tag)]\n//}}}\nInitializes and tracks the current checkbox state by setting or removing ("TogglyTagging") a particular tag value from a specified tiddler. If you omit the tiddler title (and the ":" separator), the specified tag is assigned to the current tiddler. If you omit the tag value, as in {{{(title:)}}}, the default tag, {{{checked}}}, is assumed. Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler. When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If a tiddler title named in the tag does not exist, the checkbox state defaults to //unselected//. When the checkbox is subsequently changed to //selected//, it will automatically (and silently) create the missing tiddler and then add the tag to it.\n//{{{\n[x{javascript}{javascript}]\n//}}}\nYou can define optional javascript code segments to add custom initialization and/or 'onClick' handling to a checkbox. The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to the default context-object, 'this'.\n\nThe first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state. The second code segment (if present) is executed whenever the checkbox is clicked, so that you can perform programmed responses or intercept and override the checkbox state based on complex logic using the TW core API or custom functions defined in plugins (e.g. testing a particular tiddler title to see if certain tags are set or setting some tags when the checkbox is clicked).\n\nNote: if you want to use the default checkbox initialization processing with a custom onclick function, use this syntax: {{{ [x=id{}{javascript}] }}} \n<<<\n!!!!!Examples\n<<<\n//{{{\n[X] label\n[_] label\n//}}}\nchecked and unchecked static default values\n[X] label\n[_] label\n\n//{{{\n[_=demo] label\n//}}}\ndocument-based value (id='demo', no cookie)\n[_=demo] label\n\n//{{{\n[_=chkDemo] label\n//}}}\ncookie-based value (id='chkDemo')\n[_=chkDemo] label\n\n//{{{\n[_(CheckboxPlugin:demotag)] toggle 'demotag'\n//}}}\ntag-based value (TogglyTagging)\n[_(CheckboxPlugin:demotag)] toggle 'demotag'\ncurrent tags: <script>return store.getTiddler(story.findContainingTiddler(place).id.substr(7)).tags.toString();</script>\n\n//{{{\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n//}}}\ncustom init and onClick functions\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n\nRetrieving option values:\nconfig.options['demo']=<script>return config.options['demo']?"true":"false";</script>\nconfig.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>\n\n!!!!!Installation\nimport (or copy/paste) the following tiddlers into your document:\n''CheckboxPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n2006.02.23 - 2.0.4\nwhen toggling tags, force refresh of the tiddler containing the checkbox.\n\n2006.02.23 - 2.0.3\nwhen toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.\n\n2006.02.23 - 2.0.2\nwhen using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:\n"""[x([[Tiddler with spaces]]:[[tag with spaces]])]"""\n\n2006.01.10 - 2.0.1\nwhen toggling tags, force refresh of the 'tagging tiddler'. For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.\n\n2006.01.04 - 2.0.0\nupdate for ~TW2.0\n\n2005.12.27 - 1.1.2\nFix lookAhead regExp handling for """[x=id]""", which had been including the "]" in the extracted ID. \nAdded check for "chk" prefix on ID before calling saveOptionCookie()\n\n2005.12.26 - 1.1.2\nCorrected use of toUpperCase() in tiddler re-write code when comparing """[X]""" in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.\n\n2005.12.26 - 1.1.0\nRevise syntax so all optional parameters are included INSIDE the [ and ] brackets. Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin. Based on a suggestion by GeoffSlocock\n\n2005.12.25 - 1.0.0\nadded support for tracking checkbox state using tags ("TogglyTagging")\nRevised version number for official post-beta release.\n\n2005.12.08 - 0.9.3\nsupport separate 'init' and 'onclick' function definitions.\n\n2005.12.08 - 0.9.2\nclean up lookahead pattern\n\n2005.12.07 - 0.9.1\nonly update tiddler source content if checkbox state is actually different. Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)\n\n2005.12.07 - 0.9.0\ninitial BETA release\n<<<\n!!!!!Credits\n<<<\nThis feature was created by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.CheckboxPlugin = {major: 2, minor: 0, revision:4 , date: new Date(2006,2,23)};\n//}}}\n\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n//{{{\nconfig.formatters.push( {\n name: "checkbox",\n match: "\s\s[[xX_ ][\s\s]\s\s=\s\s(\s\s{]",\n lookahead: "\s\s[([xX_ ])(\s\s])?(=[^\s\ss\s\s(\s\s]{]+)?(\s\s([^\s\s)]*\s\s))?({[^}]*})?({[^}]*})?(\s\s])?",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n // get params\n var checked=lookaheadMatch[1];\n var id=lookaheadMatch[3];\n var tag=lookaheadMatch[4];\n var fn_init=lookaheadMatch[5];\n var fn_click=lookaheadMatch[6];\n // create checkbox element\n var c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick=onClickCheckbox;\n c.srcpos=w.matchStart+1; // remember location of "X"\n w.output.appendChild(c);\n // set default state\n c.checked=(checked.toUpperCase()=="X");\n // get/set state by ID\n if (id) {\n c.id=id.substr(1); // trim off leading "="\n if (config.options[c.id]!=undefined)\n c.checked=config.options[c.id];\n else\n config.options[c.id]=c.checked;\n }\n // get/set state by tag\n if (tag) {\n c.tiddler=story.findContainingTiddler(w.output).id.substr(7);\n c.tag=tag.substr(1,tag.length-2).trim(); // trim off parentheses\n var pos=c.tag.indexOf(":");\n if (pos==0) { c.tag=tag.substr(1); }\n if (pos>0) { c.tiddler=c.tag.substr(0,pos).replace(/\s[\s[/g,"").replace(/\s]\s]/g,""); c.tag=c.tag.substr(pos+1); }\n c.tag.replace(/\s[\s[/g,"").replace(/\s]\s]/g,"");\n if (!c.tag.length) c.tag="checked";\n var t=store.getTiddler(c.tiddler);\n c.checked = (t && t.tags)?(t.tags.find(c.tag)!=null):false;\n }\n if (fn_init) c.fn_init=fn_init.trim().substr(1,fn_init.length-2); // trim off surrounding { and } delimiters\n if (fn_click) c.fn_click=fn_click.trim().substr(1,fn_click.length-2);\n c.onclick(); // compute initial state and save in tiddler/config/cookie\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n }\n)\n//}}}\n\n//{{{\nfunction onClickCheckbox()\n{\n if (this.fn_init)\n // custom function hook to set initial state (run only once)\n { try { eval(this.fn_init); this.fn_init=null; } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }\n else if (this.fn_click)\n // custom function hook to override or react to changes in checkbox state\n { try { eval(this.fn_click) } catch(e) { displayMessage("Checkbox click error: "+e.toString()); } }\n if (this.id)\n // save state in config AND cookie (only when ID starts with 'chk')\n { config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }\n if ((!this.id || this.id.substr(0,3)!="chk") && !this.tag) {\n // save state in tiddler content only if not using cookie or tag tracking\n var t=store.getTiddler(story.findContainingTiddler(this).id.substr(7));\n if (this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed\n t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);\n store.setDirty(true);\n }\n }\n if (this.tag) {\n var t=store.getTiddler(this.tiddler);\n if (!t) { t=(new Tiddler()); t.set(this.tiddler,"",config.options.txtUserName,(new Date()),null); store.addTiddler(t); } \n var tagged=(t.tags && t.tags.find(this.tag)!=null);\n if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }\n if (!this.checked && tagged) { t.tags.splice(t.tags.find(this.tag),1); store.setDirty(true); }\n // if tag state has been changed, force a display update\n if (this.checked!=tagged) {\n story.refreshTiddler(this.tiddler,null,true); // the TAGGED tiddler\n story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler\n if (t=store.getTiddler(story.findContainingTiddler(this).id.substr(7)))\n if (t.title!=this.tiddler) story.refreshTiddler(t.title,null,true); // the tiddler CONTAINING the checkbox\n }\n }\n return true;\n}\n//}}}
* we want to select rows and print them...\n* grep \n* we have lots of possible conditions, we can specify alterrnatives with the ''|'' syntax.\n* some standard [[grep]]s do not allow expressions, you may have <<man egrep>>; otherwise you can do this with [[awk]]\n{{{\n>grep -i -E '^WARNING:|^ERROR:|UNINITIALIZED|converted to|referenced|repeats of|invalid|mathematical operations|converted|NOREPLACE|[0-9]+ observations' itt10_10.log\n}}}\n{{{\nNOTE: The data set WORK.NONE has 4 observations and 1 variables.\nNOTE: The data set WORK.NONE1 has 8 observations and 1 variables.\nNOTE: The data set WORK.NONE2 has 4 observations and 1 variables.\nNOTE: The data set WORK.CRITERIA has 8 observations and 3 variables.\nNOTE: There were 2219 observations read from the data set DATA_A.A_LRS.\nNOTE: The data set WORK.LRS has 2219 observations and 87 variables.\nNOTE: There were 2219 observations read from the data set WORK.LRS.\nNOTE: The data set WORK.LRS has 2219 observations and 87 variables.\nNOTE: There were 2219 observations read from the data set WORK.LRS.\nNOTE: The data set WORK.LRS1 has 2219 observations and 88 variables.\nNOTE: The data set WORK.NONE has 4 observations and 1 variables.\nNOTE: The data set WORK.NONE1 has 8 observations and 1 variables.\nNOTE: The data set WORK.NONE2 has 4 observations and 1 variables.\n>\n}}}\n* No errors, but you can see the flow of observations\n
{{{\ngrep ^ERROR: *.log | grep -v "limit set by errors" | grep -v "errors printed on pages" >| _check.error.txt\ngrep ^STLERROR: *.log >| _check.stlerror.txt\ngrep ^WARNING: *.log | grep -v compression >| _check.warning.txt\ngrep ^NOTE: *.log | grep uninit >| _check.uninit.txt\ngrep ^NOTE: *.log | grep invalid >| _check.invalid.txt\ngrep ^NOTE: *.log | grep repeat >| _check.repeat.txt\ngrep ^DEVELOPER_WARNING: *.log >| _check.developer_warning.txt\n}}}\n\nOriginal from StevePike\n\nSee also [[chklogs]] which has a summary printing code added, and faster searching by using [[regular expressions]] to replace the pipelines and many checks shown here.
!!! print space on sastmp as GB total & GB free\n* For rows with a /dev. at start convert the 3rd & 4th field by dividing by 1024^^2^^\n{{{\ngbl df -k /proj/sastmp | awk '{ if ( $1 ~ /\s// ) { print $1"\st" $2 / 1024 /1024 , "\st"$3 /1024 / 1024 ,"\st" $4 " " $5 " "$6, $7} else print }'\n\n gbl running on the all my hosts : h1 h2 h3 h4 h5\n\nExecuting command on h1 -----------------------------------------------------------------------\nFilesystem 1024-blocks Free %Used Iused %Iused Mounted on\n/dev/lv_sastmp 12.75 7.92882 38% 5344 1% /proj/sastmp\n\nExecuting command on h2 -----------------------------------------------------------------------\nFilesystem 1024-blocks Free %Used Iused %Iused Mounted on\n/dev/lv_sastmp 64 59.67 7% 12915 1% /proj/sastmp\n\nExecuting command on h3 -----------------------------------------------------------------------\nFilesystem 1024-blocks Free %Used Iused %Iused Mounted on\n/dev/lv05 65 59.9316 8% 27023 1% /proj/sastmp\n\nExecuting command on h4 -----------------------------------------------------------------------\nFilesystem 1024-blocks Free %Used Iused %Iused Mounted on\n/dev/lv_proj 4 1.96415 51% 6497 2% /proj\n\nExecuting command on h5 -----------------------------------------------------------------------\nFilesystem 1024-blocks Free %Used Iused %Iused Mounted on\n/dev/lv03 15 11.8174 22% 10146 1% /proj/sastmp\n>\n}}}\n\n* convert titles from 1024-k blovks\n{{{\n gbl df -k /proj/sastmp | awk '/^File/ {sub("1024-blocks"," - GB") } { if ( $1 ~ /\s// && ! /^File/ ) { print $1"\st" $2 / 1024 /1024 , "\st"$3 /1024 / 1024 ,"\st" $4 " " $5 " "$6, $7} e\nlse print }\n}}}
\n* to edit the footer of the RTF or listing containing the sas program name and time of running\n{{{\ngawk '/report\s/pgm/ { sub("@@[a-zA-Z0-9/]* "," ");sub("[0-9]+[A-Za-z]+[0-9]+:[0-9]+:[0-9]+","date_suppressed")} {print}'\n}}}\n!!!!! ''Note'' change the date to 'date_suppressed' and just drop the version information from ClearCase (it is after the @@)\n** the RE looks for a line with a time stamp at the end\n= :dd:dd \sn\n** and a string beginning ''report/pgm'' from which it deletes the stuff after @@\n{{{\n[/vob/CLAF237A/pool/pool_003/report/export/pgm_saf]\ngarbuda1@ichn21> gawk '/report\s/pgm/ { sub("@@[a-zA-Z0-9/]* "," ");sub("[0-9]+[A-Za-z]+[0-9]+:[0-9]+:[0-9]+","date_suppressed")} {print}' x1t4_6_11a.rtf \n{\srtf1\sansi \sdeff0\sdeflang1024{\sfonttbl{\sf0\sfmodern Courier New;}}\n{\scolortbl;\sred0\sgreen0\sblue0;}\n\spaperw16840\spaperh11907\n\smargl2160\smargr1140\smargt1701\smargb1140\swidowctrl\sftnbj\n\ssectd \slndscpsxn\slinex0\sheadery1701\sfootery1140\scolsx709\sendhere\n\spard\splain\sf0\sfs18\ssa20\ssl-180\sslmult0\swidctlpar\sadjustleft\scgrid\n{CLAF237A SCS FINAL}\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 Appendix 1 Table 4.6-11a (Page 1 of 1)}\n\spar {\sf0\sfs18 Muscle pain-related events during the randomized double-blind period by treatment}\n\spar {\sf0\sfs18 Monotherapy safety population}\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 Vilda Vilda Vilda Vilda Met up Rosi}\n\spar {\sf0\sfs18 25mg BID 50mg QD 50mg BID 100mg QD to 1g BID 8mg QD Placebo}\n\spar {\sf0\sfs18 Preferred N=121 N=323 N=1292 N=238 N=252 N=267 N=255}\n\spar {\sf0\sfs18 term n (%) n (%) n (%) n (%) n (%) n (%) n (%)}\n\spar {\sf0\sfs18 _____________________________________________________________________________}\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 Total 4( 3.3) 5( 1.5) 21( 1.6) 4( 1.7) 2( 0.8) 3( 1.1) 5( 2.0)}\n\spar {\sf0\sfs18 Myalgia 4( 3.3) 5( 1.5) 21( 1.6) 4( 1.7) 2( 0.8) 3( 1.1) 5( 2.0)}\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 - Preferred terms are sorted alphabetically.}\n\spar {\sf0\sfs18 - A patient with multiple occurrences of an AE under one treatment is counted only once in the AE category}\n\spar {\sf0\sfs18 for that treatment.}\n\spar {\sf0\sfs18 Muscle pain-related events considered are Myalgia and Polymyalgia}\n\spar {\sf0\sfs18 Note: Treatment groups which do not contribute events are not displayed.}\n\spar {\sf0\sfs18 }\n\spar {\sf0\sfs18 report/pgm_saf/t_aev1j.sas - date_suppressed}\n}\n}}}\nSee Also [[ExtractFirstPageOfListing]]*
This Tiddlywiki was built at tiddlyspot using the MPTW version.\n\nThe Extensions used are listed in the Extensions control Centre:\n<<tiddler ExtensionsControlCentre>>\n\n* There are some stylesheet changes\n** the main font is Trebuchet Ms\n** long names in the side bar tabs are indented after the first line\n** the sidebar tab is wider by default (20 vs 16em)\n* the hove menu and related plugins allow easy navigation and also switching of focus by hiding the title bar and sidebars\n* main extra is the plugin for running a slide show\n* the tiddlerExcerpt is used to give the first line of a tiddler as tooltip rather than the default time & author info.\n* the timeline is removed from tabs menu\n* the author & time info is taken out of ViewTemplate because it is not needed\n* the sortable table plugin is used for the [[UnixtextTools table]]. this means it is easy to focus on alphabetical reference //or// processing type as wished.\n* QUOTD plugin is used to display a tip from [[BrianEno]]'s ObliqueStrategies. Often more cryptic than Unix :-)\n\n\n
[[from|http://wks.uts.ohio-state.edu/unix_course/intro-137.html]]\nBut see also \n!! 11.1 Unix Commands\n----\n In the table below we summarize the more frequently used commands on a Unix system. In this table, as in general, for most Unix commands, ''file'', could be an actual file name, or a list of file names, or input/output could be redirected to or from the command. \n|>|!Unix Commands|\n|!Command/Syntax|!What it will do|\n|''awk/nawk'' [options] //file//|scan for patterns in a file and process the results|\n|''cat'' [options] //file//|concatenate (list) a file|\n|''cd'' [directory]|change directory|\n|''chgrp'' [options] //group file//|change the group of the file|\n|''chmod'' [options] //file//|change file or directory access permissions|\n|''chown'' [options] //owner file//|change the ownership of a file; can only be done by the superuser|\n|''chsh'' (''passwd -e/-s'') //username login_shell//|change the user's login shell (often only by the superuser)|\n|''cmp'' [options] //file1 file2//|compare two files and list where differences occur (text or binary files)|\n|''compress'' [options] //file//|compress file and save it as //file.Z//|\n|''cp'' [options] //file1 file2//|copy //file1// into //file2//; //file2// shouldn't already exist. This command creates or overwrites //file2//.|\n|''cut'' (options) [//file//(s)]|cut specified field(s)/character(s) from lines in file(s)|\n|''date'' [options]|report the current date and time|\n|''dd'' [if=infile] [of=outfile] [operand=value]|copy a file, converting between ASCII and EBCDIC or swapping byte order, as specified|\n|''diff'' [options] //file1 file2//|compare the two files and display the differences (text files only)|\n|''df'' [options] [resource]|report the summary of disk blocks and inodes free and in use|\n|''du'' [options] [//directory// or //file//]|report amount of disk space in use|\n|''echo'' [text string]|echo the text string to stdout|\n|''ed'' or ''ex'' [options] //file//|Unix line editors|\n|''emacs'' [options] //file//|full-screen editor|\n|''expr'' //arguments//|evaluate the arguments. Used to do arithmetic, etc. in the shell.|\n|''file'' [options] //file//|classify the file type|\n|''find directory'' [options] [actions]|find files matching a type or pattern|\n|''finger'' [options] //user[@hostname]//|report information about users on local and remote machines|\n|''ftp'' [options] //host//|transfer file(s) using file transfer protocol|\n|''grep'' [options] 'search string' //argument//''egrep ''[options] 'search string' //argument//''fgrep ''[options] 'search string' //argument//|search the argument (in this case probably a file) for all occurrences of the search string, and list them. |\n|''gzip'' [options] //file//<P>''gunzip ''[options] //file//<P>''zcat ''[options] //file//|compress or uncompress a file. Compressed files are stored with a .''gz'' ending|\n|''head'' [-number] //file//|display the first 10 (or number of) lines of a file|\n|''hostname''|display or set (super-user only) the name of the current machine|\n|''kill'' [options] [-SIGNAL] [pid#] [%job]|send a signal to the process with the process id number (pid#) or job control number (%n). The default signal is to kill the process.|\n|''ln'' [options] //source_file target//|link the //source_file// to the //target//|\n|''lpq'' [options]<P>''lpstat// //''[options]|show the status of print jobs|\n|''lpr'' [options] //file//<P>''lp// //''[options] //file//|print to defined printer|\n|''lprm'' [options]<P>''cancel ''[options]|remove a print job from the print queue|\n|''ls'' [options] [//directory// or //file//]|list //directory// contents or //file// permissions|\n|''mail'' [options] [user]<P>''mailx ''[options] [user]<P>''Mail ''[options] [user]|simple email utility available on Unix systems. Type a period as the first character on a new line to send message out, question mark for help.|\n|''man'' [options] //command//|show the manual (''man'') page for a command|\n|''mkdir'' [options] //directory//|make a //directory//|\n|''more'' [options] //file//<P>''less ''[options] //file//<P>''pg ''[options] //file//|page through a text file|\n|''mv'' [options] //file1 file2//|move //file1// into //file2//|\n|''od'' [options] //file//|octal dump a binary file, in octal, ASCII, hex, decimal, or character mode.|\n|''passwd'' [options]|set or change your password|\n|''paste'' [options] //file//|paste field(s) onto the lines in //file//|\n|''pr'' [options] //file//|filter the file and print it on the terminal|\n|''ps'' [options]|show status of active processes|\n|''pwd''|print working (current) directory|\n|''rcp'' [options] //hostname//|remotely copy files from this machine to another machine|\n|''rlogin'' [options] //hostname//|login remotely to another machine|\n|''rm'' [options] //file//|remove (delete) a file or directory (''-r ''recursively deletes the directory and its contents) (''-i'' prompts before removing files)|\n|''rmdir'' [options] //directory//|remove a //directory//|\n|''rsh'' [options] //hostname//|remote shell to run on another machine|\n|''script'' //file//|saves everything that appears on the screen to file until ''exit'' is executed|\n|''sed'' [options] //file//|stream editor for editing files from a script or from the command line|\n|''sort'' [options] //file//|sort the lines of the //file// according to the options chosen|\n|''source'' //file//<P>''.'' //file//|read commands from the //file// and execute them in the current shell. ''source'': C shell, ''.'': Bourne shell.|\n|''strings'' [options] //file//|report any sequence of 4 or more printable characters ending in <NL> or <NULL>. Usually used to search binary files for ASCII strings.|\n|''stty'' [options] |set or display terminal control options|\n|''tail'' [options] //file//|display the last few lines (or parts) of a file|\n|''tar'' key[options] [//file//(s)]|tape archiver--refer to man pages for details on creating, listing, and retrieving from archive files. Tar files can be stored on tape or disk.|\n|''tee'' [options] //file//|copy stdout to one or more files|\n|''telnet'' [host [port]]|communicate with another host using telnet protocol|\n|''touch'' [options] [date] //file//|create an empty file, or update the access time of an existing file|\n|''tr'' [options] //string1 string2//|translate the characters in string1 from stdin into those in string2 in stdout|\n|''uncompress'' //file.Z//|uncompress //file.Z// and save it as a file|\n|''uniq'' [options] //file//|remove repeated lines in a file|\n|''uudecode'' [//file//]|decode a uuencoded file, recreating the original file |\n|''uuencode'' [//file//] //new_name//|encode binary file to 7-bit ASCII, useful when sending via email, to be decoded as new_name at destination|\n|''vi'' [options] //file//|visual, full-screen editor|\n|''wc'' [options] [//file//(s)]|display word (or character or line) count for //file//(s)|\n|''whereis'' [options] //command//|report the binary, source, and man page locations for the command named|\n|''which'' //command//|reports the path to the command or the shell alias in use |\n|''who'' or ''w''|report who is logged in and what processes are running|\n|''zcat'' //file.Z//|concatenate (list) uncompressed file to screen, leaving file compressed on disk|
/***\nJust some bits and pieces\n***/\n//{{{\nconfig.messages.messageClose.text = "X"; // default is "close"\nconfig.views.wikified.defaultText = ""; // default is "The tiddler '%0' doesn't yet exist. Double-click to create it"\nconfig.options.chkHttpReadOnly = false; // Enable editing so that visitors can experiment with it\n//}}}
[[PageTemplate]]\n|>|>|[[SiteTitle]] - [[SiteSubtitle]]|\n|[[MainMenu]]|[[DefaultTiddlers]] <html><br><br><br><br></html>[[ViewTemplate]] <html><br><br></html> [[EditTemplate]]|[[SideBarOptions]]|\n|~|~|[[OptionsPanel]]|\n|~|~|[[AdvancedOptions]]|\n|~|~|<<tiddler Configuration.SideBarTabs>>|\n''~StyleSheet:'' [[StyleSheet]] - [[StyleSheetColors]] - [[StyleSheetLayout]] - [[StyleSheetPrint]]\n[[SiteUrl]]
[[SideBarTabs]]\n|[[TabTimeline]]|[[TabAll]]|[[TabTags]]|<<tiddler Configuration.TabMore>>|
|>|[[TabMore]]|\n|TabMoreMissing|TabMoreOrphans|
{{{\nawk '/^[ ]+[A-Z]+\s/[0-9]+\s/[0-9]+/ {print "| "$5, $6, $7, "| " $1}' x5l2_01.lst | sort -t"|" -2 +3 | awk -F"|" '{print $2}"' | uniq -c\n}}}\nfor example:\n{{{ \n 35 PIOGLITAZONE 30MG OD \n 87 VILDA 50MG BID \n 78 VILDA 50MG OD \n}}}\n\n!!!! add the total!\n* add to the end of the command: {{{|awk '{print; total+= $1} END {print "------\sn "total}' }}}\ngiving \n{{{\n 35 PIOGLITAZONE 30MG OD \n 87 VILDA 50MG BID \n 78 VILDA 50MG OD \n------\n 200\n}}}
* The strategy is:\n## get the lines from top of each page giving the Treatment: and save the treatment label in a variable.\n## get the lines with a patient id and print just the patient id from theat line, but add the filename and treatment label first.\n## run uniq to one line per patients (per file and treatment). This is because patients are more than once in a listing if the program has split parameters into two sections\n## run uniq again with -c to count how many pats per file and treatment\n## add an awk to end of pipe to print filename once and tabs to lay output out ''NICELY''\n\n{{{\ngawk '/^[tT]reatment:/ {sub("Treatment[ ]*:",""); trt = $0 } # store the treatment\n /[A-Za-z]+[/][0-9]+[/].+/ {print "|"FILENAME"|"trt"|"$1 } \n # print file & treat for every line with an id\n ' x7l1_2?.lst | # check listings 20 - 29\n sort | \n uniq | # could be more than one line per patient\n awk -F"|" '{ print $2": "$3} ' | #\n uniq -c | # now count patients per file & treatment\n awk '{ if ( oldfile != $2 ) print "\snFile ",$2" :"; oldfile = $2} # print fle name once when it changes \n {print "\st"$1"\st" $3,$4,$5,$6,$7,$8} # add tabs for first tow fields but not others (part of treatment name) \n '\n}}}\n\nmight output:\n{{{\n\nFile x7l1_21.lst: :\n 35 Bio 30mg qd (core) + combination\n 87 Draino 50mg bid (core) + combination\n 78 Draino 50mg qd (core) + combination\n\nFile x7l1_22.lst: :\n 35 Bio 30mg qd (core) + combination\n 87 Draino 50mg bid (core) + combination\n 78 Draino 50mg qd (core) + combination\n\nFile x7l1_23.lst: :\n 35 Bio 30mg qd (core) + combination\n 87 Draino 50mg bid (core) + combination\n 78 Draino 50mg qd (core) + combination\n\nFile x7l1_24.lst: :\n 2 Bio 30mg qd (core) + combination\n 4 Draino 50mg bid (core) + combination\n 2 Draino 50mg qd (core) + combination\n\nFile x7l1_25.lst: :\n 27 Bio 30mg qd (core) + combination\n 67 Draino 50mg bid (core) + combination\n 61 Draino 50mg qd (core) + combination\n\n\n}}}\n* pasteable version:\n{{\ngawk '/^[tT]reatment:/ {sub("Treatment[ ]*:",""); trt = $0 } /[A-Za-z]+[/][0-9]+[/].+/ {print "|"FILENAME"|"trt"|"$1 } ' x7l1_2?.lst |\n sort | uniq | awk -F"|" '{ print $2": "$3} ' | uniq -c | awk '{ if ( oldfile != $2 ) print "\snFile ",$2" :"; oldfile = $2} {print "\st"$1"\st" $\n3,$4,$5,$6,$7,$8} '\n}}}\n\nSee also: [[How can I count how many patients actually appear in a listing?]] \nand [[count how patients per treamrnt in the randomisation listing]]
David J Garbutt\nBusiness & Decision\nCH - 8001 Zürich\nWork Phone: +41 44 390 3721 \nFax: +41 44 390 3722\n\nEmail: [[=djg|http://public.xdi.org/=djg]]\nWeb: [[www.businessdecision.ch/Lifescience|http://www.businessdecision.ch/Lifescience]]\nWeb: [[www.lifescienceforumbasel.ch|http://www.lifescienceforumbasel.ch]]\n\n
PhUSE-Talks2006 [[Gnit your own]] [[Tag Cloud]] DaveG Colophon
<!---\n| Name:|~TagglyTaggingEditTemplate |\n| Version:|1.1 (12-Jan-2006)|\n| Source:|http://simonbaird.com/mptw/#TagglyTaggingEditTemplate|\n| Purpose:|See TagglyTagging for more info|\n| Requires:|You need the CSS in TagglyTaggingStyles to make it look right|\n--->\n<!--{{{-->\n<div class="toolbar" macro="toolbar +saveTiddler closeOthers cancelTiddler deleteTiddler"></div>\n<div class="title" macro="view title"></div>\n<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>\n<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>\n<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>\n<div class="editor" macro="edit text"></div>\n<br/>\n<!--}}}-->
!!!! efficiency for 8448 lines\n* the pipe with awk and grep is slightly faster! But using one and making it gawk is 30% faster.\n* to get usage statistics use the time command. This is the [[Korn shell]] version and can time a whole pipeline\n{{{\n> time awk '/[A-Za-z]+\s/[0-9]+\s/.+\s// { print $1}' x7l1_18.lst | sort | uniq -c |wc -l\n 179\n\nreal 0m0.15s\nuser 0m0.11s\nsys 0m0.02s\n> time grep -E '[A-Za-z]+/[0-9]+/.+/' x7l1_18.lst | awk '{print $1}' | sort | uniq -c |wc -l\n 179\n\nreal 0m0.10s\nuser 0m0.09s\nsys 0m0.03s\n> wc -l x7l1_18.lst\n 8448 x7l1_18.lst\n> time grep -E '[A-Za-z]+/[0-9]+/.+/' x7l1_18.lst | awk '{print $1}' | sort | uniq -c |wc -l\n 179\n\nreal 0m0.10s\nuser 0m0.09s\nsys 0m0.00s\n> \n}}}
<<ExtensionsPlugin plugin plugin.config translation>>
<<ExtensionsPlugin plugin plugin.config translation>>
//{{{\nversion.extensions.ExtensionsPlugin = {\n major: 0, minor: 3, revision: 0,\n date: new Date(2006, 3, 3), \n type: 'macro',\n source: "http://www.math.ist.utl.pt/~psoares/addons.html#ExtensionsPlugin"\n};\n\nconfig.macros.ExtensionsPlugin = {};\n\nconfig.macros.ExtensionsPlugin.options = {\n dateFormat: "0DD/0MM/YYYY"\n}\n\nonClickUpdate=function(){\n var name=this.getAttribute("name");\n var url=this.getAttribute("url");\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n loadImportFile(url,"tiddler:"+name,"","ask","force",autoImportTiddlers);\n return;\n}\n\nconfig.macros.pluginUpdater = {};\nconfig.macros.pluginUpdater.handler = function(place,macroName,params) {\n var button=createTiddlyButton(place,"go","Update "+params[0],onClickUpdate);\n button.setAttribute("name", params[0]);\n button.setAttribute("url", params[1]);\n return;\n}\n\nconfig.macros.ExtensionsPlugin.handler= function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length==0) return;\n var plugin;\n var table= "|!Status|!Extension|!Type|!Version|!Date|!Source|!Docs|!Update|\sn";\n var tiddlers = new Array();\n for (var i=0; i<params.length; i++) {\n var temp = store.getTaggedTiddlers(params[i], "title");\n for(var j=0; j<temp.length; j++){\n if(tiddlers.indexOf(temp[j].title)==-1) tiddlers.push(temp[j].title);\n }\n }\n tiddlers.sort();\n for (var i=0; i<tiddlers.length; i++) {\n plugin = config.macros.ExtensionsPlugin.getInfo(tiddlers[i]);\n table += "| [x("+plugin.name+":systemConfig)] |[[" + plugin.name+ "]]|"+ plugin.type +"| "+ plugin.version + "| "+ plugin.date + "| " + plugin.source + " | "+ plugin.docs +" | "+plugin.update+" |\sn";\n }\n wikify(table, place);\n}\n\nconfig.macros.ExtensionsPlugin.getInfo = function(tiddler) {\n var plugin = {name: tiddler, type: '', version: '', date: '', source: '', docs: '', update:''};\n if(version.extensions[plugin.name]){\n var place = version.extensions[plugin.name];\n plugin.version = place.major + "." +place.minor + "." + place.revision;\n if(place.source){\n plugin.source="[[source|"+ place.source +"]]";\n var temp=place.source.split("#");\n plugin.update="<<pluginUpdater "+plugin.name+" "+temp[0]+">>";\n }\n if(place.docs){\n plugin.docs="[[docs|"+ place.docs +"]]";\n }\n if(place.type){\n plugin.type=place.type;\n }\n if(place.date){\n plugin.date=place.date.formatString(config.macros.ExtensionsPlugin.options.dateFormat) ;\n }\n }\n return plugin;\n}\n//}}}
! How?\n* page one has a string giving the game away.. \n* and there is a ^L (ASCII character octal 14) between each page.\n* so we need to print the record (between page throws) if it is page 1\n\n{{{gawk 'BEGIN { FS= "\sn" ; RS = "\s014"} /Page 1 of/ { print "\s014"FILENAME": " $0 } ' *.lst}}}\n\ngives:\n{{{\n\n[]x8t2_11.lst: DRAINO03578 (Draft)\n\n Appendix 8 Table 2-11 (Page 1 of 8)\n Laboratory normal and notable ranges (in conventional US unit) and relevant percent change criteria\n by laboratory identification number and laboratory group\n\nLaboratory identification number: 1002, Laboratory group: Hematology\n\n Relevant Relevant\n Laboratory Normal Normal Notable Notable percent percent\n test US Lower Upper Lower Upper change change\n Laboratory test abbreviation unit Sex limit limit Limit Limit increase* decrease*\n ______________________________________________________________________________________________________\n\n Basophils BAS % Male 0 2\n\n Eosinophils EOS % Male 0 6 14\n\n Erythrocytes(RBC) RBC 10E12/L Female 4.2 5.8\n 10E12/L Male 4.5 6.3\n\n Hematocrit HCT % Female 34 50 32 >50% >25%\n % Male 39 53 37 >50% >25%\n\n Hemoglobin HGB g/dL Female 12 16 9.5 >50% >25%\n g/dL Male 14 18 11.5 >50% >25%\n\n Lymphocytes LYM % Male 25 45\n\n Monocytes MON % Male 2 10\n\n Platelet count DPLCNT 10E9/L Male 144 440 75 700 >50% >25%\n (direct)\n\n Total WBC 10E9/L Male 4.3 11 2.8 16 >50% >25%\n leukocytes(WBC)\n\n Total neutrophils NEU % Male 50 65\n\n* Refers to post-baseline values as compared to baseline value\nprograms/safety/x8t2_11.sas - 24MAR2005:11:49\n}}}\n* [] means there is box printed, it is ^L (page feed) so when printed each page is separated\n\n!!!! See also [[Extract first page of isting for one file in all studies]]
{{{\n#!/bin/ksh\n# get first page of all versions of a listing across a set of studies\n# not parameterised for studies \n# Parameter 1 is the file name to be sought and extracted across all views\n# DJ Garbutt - 2006\nif (( $# != 1 ))\nthen\n print "Usage: I need one parameter - file name of an output , with no .lst extension"\nelse\ngawk 'BEGIN { FS= "\sn" ; RS = "\s014"} /Page 1 of/ { print "\s014"FILENAME": " $0 } ' /view/*_view/vob/myproj/*Extn/progs/safety/$1.lst >|${1}_xsection.txt\nfi\n}}}
!!!! make a readable version (keeping ) line structure\n* setting the field and record separators like this makes a blank line terminate the record.\n* so you don't need a fixed number of title lines across files, but any listings with no gap will give you an issue.\n\n>{{{gawk 'BEGIN { FS= "\sn" ; RS = ""} /Page 1 of/ { print FILENAME": " $0 } ' *.lst}}}\n!!!! A simpler version (may not work with your grep version (OK on [[AIX]])\n>{{{ grep -p '(Page 1 of' *.lst }}} \nGiving (extract only)\n{{{\nx9t3_10.lst:\n Appendix 9 Table 3-10 (Page 1 of 501)\n Patients with abnormal biochemistry values (in conventional US unit) by treatment\n Extension Safety population\n\nx9t3_11.lst:\n Appendix 9 Table 3-11 (Page 1 of 8)\n Laboratory normal and notable ranges (in conventional US units) and relevant percent change criteria\n by laboratory identification number and laboratory group\n}}}\n!!!! create a one line per tiddler-table output with filename and | between titles and no leading or trailing spaces around the fields. \n{{{\n gawk 'BEGIN { FS= "\sn" ; RS = ""} /Page 1 of/ { sub("[(]Page 1.*\s)","",$1);sub("^ +","",$1);sub("^ +","",$2);sub("^ +","",$3);sub("^ +","",$4);sub("^ +","",$5) ;print FILENAME"("NF") : \sn" $1"|"$2\n"|"$3"|"$4"|"$5} ' *.lst >|extracted-titles.txt\n}}}\n\n!!!! There is an open source script with similar intent by RolandRashleighBerry [[here|http://www.datasavantconsulting.com/roland/spectre/scripts/getitles]]. \n* It has more options than the one-liner above. \n* It doesn't use the "(Page 1 of" text to pick up the block of titles but assumes titles start with the words appendix, table or listing. \n* It prints a fixed number of lines to follow the first title line.\n
This is a simple cheat sheet gleened from the [[TiddlyWiki Tutorial|http://www.blogjones.com/TiddlyWikiTutorial.html]]. It's also helpful when you are working on your StyleSheet.\n\n!Text formatting\n|!Example|>|>|!How|\n|''Bold Text''|' ' (without space)|words|' '|\n|==strikethrough text==| ==|words|==|\n|__underlined text__| __|words|__|\n|//italic text//| //|word|//|\n|^^superscript text^^| ^^|words|^^|\n|~~subscript text~~| ~~|words|~~|\n|@@color(green):colored text@@| @@|color(yourcolorhere):words|@@|\n|@@bgcolor(green):Background@@| @@|bgcolor(yourcolorhere):words|@@|\n|{{{Monospaced}}}| {{{|words|}}}|\n|~DewikifyAWikiWord| ~|~WikiLikeWord||\n|[[wikify a word]] | [[|non-wiki words|]]|\n\n!Monospaced block\n{{{\n {{{\n Just a silly example\n }}}\n}}}\n{{{\nJust a silly example\n}}}\n\n!Horizontal line\n{{{\n----\n}}}\n----\n\n!Lists and outlines\n{{{\n* Begin a list\n* List with subitems\n** Sub item 1\n** Sub item 2\n}}}\n* Begin a list\n* List with subitems\n** Sub item 1\n** Sub item 2\n\n!Numbered lists and outlines\n{{{\n# Begin a list\n# List with subitems\n## Sub item 1\n## Sub item 2\n}}}\n# Begin a list\n# List with subitems\n## Sub item 1\n## Sub item 2\n\n!External link\n{{{\n[[alternate text|image URL]]\n[[TiddlyWiki|http://tiddlywiki.com]]\n}}}\n[[TiddlyWiki|http://tiddlywiki.com]]\n\n!Embed image\n{{{\n[img[alternate text|image URL]]\n}}}\n\n!Tables\nYou can create a table by enclosing text in sets of vertical bars (||, or shift-backslash on your keyboard). \n{{{\n|!Headings: add an exclamation point (!) right after the vertical bar.|!Heading2|!Heading3|\n|Row 1, Column 1|Row 1, Column 2|Row 1, Column 3|\n|>|>|Have one row span multiple columns by using a >|\n|Have one column span multiple rows by using a ~|>| Use a space to right-align text in a cell|\n|~|>| Enclose text in a cell with spaces to center it |\n|>|>|bgcolor(green):Add color to a cell using bgcolor(yourcolorhere):|\n|Add a caption by ending the table with a vertical bar followed by a c|c\n}}}\n\n|!Headings: add an exclamation point (!) right after the vertical bar.|!Heading2|!Heading3|\n|Row 1, Column 1|Row 1, Column 2|Row 1, Column 3|\n|>|>|Have one row span multiple columns by using a >|\n|Have one column span multiple rows by using a ~|>| Use a space to right-align text in a cell|\n|~|>| Enclose text in a cell with spaces to center it |\n|>|>|bgcolor(green):Add color to a cell using bgcolor(yourcolorhere):|\n|Add a caption by ending the table with a vertical bar followed by a c|c\n\n!Block quotes\n{{{\n<<<\n"Beware the Jabberwock, my son!\nThe jaws that bite, the claws that catch!\nBeware the Jubjub bird, and shun\nThe frumious Bandersnatch!"\n<<<\n}}}\n<<<\n"Beware the Jabberwock, my son!\nThe jaws that bite, the claws that catch!\nBeware the Jubjub bird, and shun\nThe frumious Bandersnatch!"\n<<<\n\n!Headings\n{{{\n!Heading\n!!Sub-heading\n!!!Sub-heading 2\n!!!!Sub-heading 3\n!!!!!Sub-heading 4\n}}}\n!Heading\n!!Sub-heading\n!!!Sub-heading 2\n!!!!Sub-heading 3\n!!!!!Sub-heading 4
This tiddler shows some more complex effects that can be obtained with cunning use of CSS. Not all of these will work properly on all browsers because of differences in CSS implementation, but they should fail gracefully.\n\nYou can have special formatting for a specific, named tiddler like this:\n{{{\n#tiddlerHelloThere .title {\nbackground-color: #99aaee;\n}\n}}}\n\nOr for the first displayed tiddler:\n{{{\ndiv.tiddler:first-child .title {\nfont-size: 28pt;\n}\n}}}\n\nOr just for the first line of every tiddler:\n{{{\n.viewer:first-line {\nbackground-color: #999999;\n}\n}}}\n\nOr just for the first letter of every tiddler:\n{{{\n.viewer:first-letter {\nfloat: left;\nfont-size: 28pt;\nfont-weight: bold;\n}\n}}}\n\nOr just for tiddlers tagged with a particular tag (note that this won't work for tags that contain spaces):\n{{{\ndiv[tags~="welcome"].viewer {\nbackground-color: #ffccaa;\n}\n\ndiv[tags~="features"].viewer {\nbackground-color: #88aaff;\n}\n}}}
/***\n|Name|FullScreenPlugin|\n|Created by|SaqImtiaz|\n|Location|http://lewcid.googlepages.com/lewcid.html#FullScreenPlugin|\n|Version|1.1|\n|Requires|~TW2.x|\n!Description:\nToggle between viewing tiddlers fullscreen and normally. Very handy for when you need more viewing space.\n\n!Demo:\nClick the ↕ button in the toolbar for this tiddler. Click it again to turn off fullscreen.\n\n!Installation:\nCopy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.\nEdit the ViewTemplate to add the fullscreen command to the toolbar.\n\n!History:\n*25-07-06: ver 1.1\n*20-07-06: ver 1.0\n\n!Code\n***/\n//{{{\nvar lewcidFullScreen = false;\n\nconfig.commands.fullscreen =\n{\n text:" ↕ ",\n tooltip:"Fullscreen mode"\n};\n\nconfig.commands.fullscreen.handler = function (event,src,title)\n{\n if (lewcidFullScreen == false)\n {\n lewcidFullScreen = true;\n setStylesheet('#sidebar, .header, #mainMenu{display:none;} #displayArea{margin:0em 0 0 0 !important;}',"lewcidFullScreenStyle");\n }\n else\n {\n lewcidFullScreen = false;\n setStylesheet(' ',"lewcidFullScreenStyle");\n }\n}\n\nconfig.macros.fullscreen={};\nconfig.macros.fullscreen.handler = function(place,macroName,params,wikifier,paramString,tiddler)\n{\n var label = params[0]||" ↕ ";\n var tooltip = params[1]||"Fullscreen mode";\n createTiddlyButton(place,label,tooltip,config.commands.fullscreen.handler);\n}\n\nvar lewcid_fullscreen_closeTiddler = Story.prototype.closeTiddler;\nStory.prototype.closeTiddler =function(title,animate,slowly)\n{\n lewcid_fullscreen_closeTiddler.apply(this,arguments);\n if (story.isEmpty() && lewcidFullScreen == true)\n config.commands.fullscreen.handler();\n}\n\n\nSlider.prototype.lewcidStop = Slider.prototype.stop;\nSlider.prototype.stop = function()\n{\n this.lewcidStop();\n if (story.isEmpty() && lewcidFullScreen == true)\n config.commands.fullscreen.handler();\n}\n//}}}
This is an awk script which parses a delimited text file containing metadata concerning outputs to be generated, and creates the SAS program files which are necessary in order to craete the specified outputs.\n\nThe script is relatively simple, and works as follows:\n*Awk script reads the specified delimited data file, using comma as the record separator\n*When records are found which identify a particular type of SAS program to be generated (stltableor listing) then the script creates a new SAS program file\n*The SAS program file created contains partly text which is hard-coded into the awk script, partly data parsed and read form the delimited textfile, and also the results of some basic system commands (e.g. uname, date)\n*The resulting SAS program file can be executed in order to create the deliverable specified in the delimited text file, given that the appropriate SAS runtime environment has first been created.\n*This is intended to be used in conjuction with a corresponding SAS setup / runtime environment, which provides the STL parameter settings separately, and does not embed them directly into the program code.\n\nHere is an example of the script used to generate such program files:\n{{{\n#!/bin/ksh\n# -----------------------------------------------------------------------\n# Script: generate_programs_safety_stl.ksh\n# Written by: Steve Pike\n# Date written: 25.02.2004\n#\n# Protocol: CHTF919A\n# Study: CHTF919ASCS\n# ----------------------------------------------------------------------\n# Notes: - Generates a series of program file templates based on\n# the contents of the tracking sheet\n# - Intended to minimise setup time for a study, and\n# standardise program headers / layout\n# - Could also be linked to more detailed programmming\n# information in the tracking sheet, in order to allow\n# default STL programs to be generated (needs STL macro\n# name and STL parameter defintions in tracking sheet)\n# ----------------------------------------------------------------------\n# Ongoing: - autocomplete further fields as available in the .csv\n# file\n#\n# Edited by: Gavin Frisby\n# Date: 09.12.2003\n# - removed call to stl_titles_footnotes macro\n# - inserted code to define %let TITLE1 statements here.\n# therefore if outputs are re-numbered just have to re-run this script.\n# ----------------------------------------------------------------------\n\n\nBASE=/proj/genesis/data/devl/CHTF919A\nXCONTROL=$BASE/CHTF919ASC/final/data_a/metadata.csv\nDEST=$BASE/CHTF919ASC/final\n\nPROGRAM=$0\nUSER=$LOGNAME\nHOST=$(uname -n)\nDATE=$(date +"%d.%m.%Y %T")\n\n\n# Note: First line of filter selects the outputs for which to generate programs\n# -----------------------------------------------------------------------------\n# all stl tables and listings\nawk -F, '$5 ~ /^stl/ && ( $10 ~ /table$/ || $10 ~ /listing$/ ) {\n\n #check if target filename is present in metadata\n if( $3 ~ /^[a-z,A-Z]/ ) {\n\n # create the full pathname of the current program to be created\n if( $9 ~ /^safety/ ) dest_file = dest_root "/pgm_saf/" $3 ".sas"\n\n # test to see if the current program file already exists\n if( system( "test -e " dest_file " 2>&1" ) == 0 ) exists = "true"\n else exists = "false"\n\n # create program files that do not already exist\n if( exists == "false" )\n {\n print "/*" > dest_file\n print " *******************************************************************************" >> dest_file\n print " *********************** PROGRAM GENERATED AUTOMATICALLY ***********************" >> dest_file\n print " *******************************************************************************" >> dest_file\n print " Generated by program: " pgm >> dest_file\n print " Generated by user: " user >> dest_file\n print " Executing on host: " host >> dest_file\n print " Date/time generated: " date "\sn" >> dest_file\n print " -------------------------------------------------------------------------------" >> dest_file\n print " Filename: " $3 ".sas\sn" >> dest_file\n print " SAS: SAS 8.2 (TS2M0)" >> dest_file\n print " Platform: AIX / Windows NT4 SP5" >> dest_file\n print " Project/Study: CHTF919A SCS\sn" >> dest_file\n print " Output: " $8 ".rtf\sn" >> dest_file\n print " Macros used: " $6 "\sn" >> dest_file\n print " -------------------------------------------------------------------------------" >> dest_file\n print " MODIFICATION HISTORY:" >> dest_file\n print " <DD-MON-YYYY>, <Firstname Lastname>" >> dest_file\n print " <Description>\sn" >> dest_file\n print " <DD-MON-YYYY>, <Firstname Lastname>" >> dest_file\n print " <Description>" >> dest_file\n print " *******************************************************************************" >> dest_file\n print "*/\sn" >> dest_file\n print "*** set program identification;" >> dest_file\n print "%let pgmname = " $3 ";\sn\sn" >> dest_file\n print "*** standard program initialisation;" >> dest_file\n print "%include \s"_autorun.sas\s";" >> dest_file\n print "%_debug( options source source2 mprint );\sn\sn" >> dest_file\n if( $7 ~ /^[a-z,A-Z]/ ) {\n print "*** include pre-processing code;" >> dest_file\n print "%include \s"" $7 ".sas\s";\sn\sn" >> dest_file\n }\n if( $21 ~ /^[a-z,A-Z]/ ) {\n print "*** auto-generated STL parameters;" >> dest_file\n print "%let TITLE1 = \s"" $21 " (#PAGE_NO#)\s";\sn\sn" >> dest_file\n }\n if( $6 ~ /^[a-z,A-Z]/ ) {\n print "*** call STL;" >> dest_file\n print "%stlrun( stltype=" $6 " );\sn\sn" >> dest_file\n }\n print "*** export the contents of work;" >> dest_file\n print "%_debug( %nrstr( %_xptwork(); ));\sn\sn" >> dest_file\n if( $6 ~ /^[a-z,A-Z]/ ) {\n print "*** move rtf file to export directory;" >> dest_file\n print "%stllst2rtf(lstfile=" $3 ", rtffile=" $8 " );\sn " >> dest_file\n }\n }\n }\n}' dest_root=$DEST pgm=$PROGRAM user=$USER host=$HOST date="$DATE" $XCONTROL\n}}}\n\n\nAnd here, and example of the typeof SAS program which is generatedthrough this process:\n{{{\n/*\n *******************************************************************************\n *********************** PROGRAM GENERATED AUTOMATICALLY ***********************\n *******************************************************************************\n Generated by program: generate_programs_safety_stl.ksh\n Generated by user: frisbga1\n Executing on host: ichn03\n Date/time generated: 02.06.2004 10:49:09\n\n -------------------------------------------------------------------------------\n Filename: t_aevsev01_sdb5s.sas\n\n SAS: SAS 8.2 (TS2M0)\n Platform: AIX / Windows NT4 SP5\n Project/Study: CHTF919A SCS\n\n Output: x1t04_2_06e2.rtf\n\n Macros used: t_aev009\n\n -------------------------------------------------------------------------------\n MODIFICATION HISTORY:\n <DD-MON-YYYY>, <Firstname Lastname>\n <Description>\n\n <DD-MON-YYYY>, <Firstname Lastname>\n <Description>\n *******************************************************************************\n*/\n\n*** set program identification;\n%let pgmname = t_aevsev01_sdb5s;\n\n\n*** standard program initialisation;\n%include "_autorun.sas";\n%_debug( options source source2 mprint );\n\n\n*** auto-generated STL parameters;\n%let TITLE1 = "Appendix 1 table 4.2-6E2 (#PAGE_NO#)";\n\n\n*** call STL;\n%stlrun( stltype=t_aev009 );\n\n\n*** export the contents of work;\n%_debug( %nrstr( %_xptwork(); ));\n\n\n*** move rtf file to export directory;\n%stllst2rtf(lstfile=t_aevsev01_sdb5s, rtffile=x1t04_2_06e2 );\n}}}
* Regular expressions are a formalised and developed version of the wild cards used by many systems for filename searching. Actually they were formalised before systems we use now were even thought of.\n> See [[http://en.wikipedia.org/wiki/Regular_expression]] for maths and useful links.\n* the concept is not hard: use some characters to define sets of characters that can match **others**\n> Example: {{{*.sas}}} matches all filenames ending in {{{sas}}}. The ''*'' means any sequence of characters (allowed in a filename ;-)\n* the regular expressions we use will get more complicated than that, but not much more.\n[[Next|How to build a regular expression]]\n
* Welcome to a Tiddly wiki contianing my talks from the PhUSE conference this year.\n* For more about the ~TiddlyWiki hosting service ~TiddlySpot see [[http://www.tiddlyspot.com/]]\n* For more about ~TiddlyWiki see my talk under the PhUSE-talks2006 and accessible from the menu. And also:\n!Learn more about ~TiddlyWiki\nFind out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki Guides|http://tiddlywikiguides.org]] for documentation on learning and using ~TiddlyWiki.\n\n* the talks run as slideshows - click the slideshow button.\n\n> for information on how this site is constructed, what [[TiddlyWiki|http://www.tiddlywiki.com]] plugins are used (and why) see [[Colophon]]\n\nFor internal info : [[GettingStarted at TiddlySpot]]\n\n! [[Contact Me|DaveG]]\n\n
Welcome to your brand new [[MonkeyPirateTiddlyWiki|http://simonbaird.com/mptw/]]. This is the standard empty [[TiddlyWiki|http://www.tiddlywiki.com/]] (version <<version>>) preconfigured with a few bits and pieces from MPTW, in particular the layout, the colours, and the popular [[TagglyTagging|http://simonbaird.com/mptw/#TagglyTagging]]. If you're new to ~TagglyTagging then try the (slightly out-of-date) [[FAQ|http://simonbaird.com/mptw/#TagglyTaggingFAQ]] and [[Tutorial|http://simonbaird.com/mptw/#TagglyTaggingTutorial]].\n\nTo get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:\n* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)\n* MainMenu: The menu (usually on the left)\n* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened\nYou'll also need to enter your username for signing your edits: <<option txtUserName>>\n\nTo create your own tiddlers, click 'new tiddler' in the right sidebar. To edit a tiddler click the 'edit' button in the tiddler's toolbar. To save all your tiddlers click 'save changes' in the right sidebar. If you're new to TiddlyWiki check out the formatting info [[here|http://www.tiddlywiki.com/#MainFeatures]].\nSee also info and PW settings in: AboutTiddlySpot\n\nUse this to import tiddlers from another TiddlyWiki. You can use a local file (click Browse...) or type the url of an online TiddlyWiki.\n<<importTiddlers inline>>\nTo change your colour scheme you can edit the styles in StyleSheet. (Refer to StyleSheetColors and StyleSheetLayout for all styles used).\n\n
!!! try this one-liner:\n* strategy:\n# use the [[lh|lh - an alias to print a modification date histogram]] and execute in a loop \n# once for each filetype in the directory\n# get the set of filetypes from the ls command by deleting the filename off the front\n# the sed regular expression {{{s/.*\s.\s(.*\s)/\s1/'}}} does that. \n\n{{{\napply 'print "%1 :";ls -l -H ./*.%1 | sed 1d | cut -c 44-51 | sort |uniq -c ' $( ls -1 . | sed 's/.*\s.\s(.*\s)/\s1/' | sort -u)\n}}}\n!!!!! example output\n{{{\nhtml :\n 1 Jul 7 \n 113 Jul 14 \n 13 Jul 17 \nrtf :\n 113 Jul 14 \n 13 Jul 17 \n 1 Jun 30 \ntxt :\n 1 Jul 17 \nzip :\n}}}\n\n
This text is copied out of the presentation file, I will gradually unify it with the draft version in [[Gnit your own]], adding the untransferred text and making the commands and results into popups.\n\n<<slideShow>>\n--s--\n!Gnit your own - creative uses of Unix Text Tools for everyday problems\n!Dave Garbutt\n\n\nTU04 @ PhUSE 2006, Dublin\n--s--\n!Introduction\n# What commands are available, and\n# Which problems they solve, with\n# Relevant examples of\n# How you can put them together to solve problems.\n# And lastly introduce you to\n# !the power of regular expressions (RE).\n*This is a little different from programming in SAS -\n* but learning a new way to think about, and solve problems\n* is only going to help your programming in SAS, or out of it.\n--s--\n! These Examples\n*I have written the following examples during my everyday work as a SAS programmer. They have already helped me. I hope they will help you too.\n*Experiment!\n* Find an example that tackles a problem you have (or near to it at least) and copy it to your system. With command pipelines it is very easy to take them apart and see what each step does.\n*Then modify the steps and see the effect.\n*I have added a > character at the start of lines that are commands, this is to separate the commands from their output better.\n* Do not paste this character!\n*Other shells might start the line with a different character\n--s--\n! In short...\n*Quick solutions for problems where writing a SAS program is not worthwhile.\n* The ability to process text files before reading them into SAS by using the pipe facility of Filename can also save you a lot of SAS programming.\n*Practice with regular expressions outside of SAS\n--s--\n!Unix text commands\n*What they operations do they do?\n*Commands on the whole file\n*tr, iconv, wc, expand, cat, tee, split, sort, spell\n*Commands (only) selecting observations\n*comm, join, uniq, grep\n*Commands selecting variables\n*cut -c, cut -f, colrm\n*Commands that can select obs, vars or derive new variables\n*sed,awk,shells (eg korn), perl,ruby\n--s--\n!How do they fit together?\n*Unix commands can all be fitted together in long sequences\n*| Separated by the vertical bar character.\n*The output of each program becomes the input of the next\n{{{\ncommand 1 -options files | command2 -options | command3 -options [>redirect to file]\n}}}\n*These sequences are known as pipes.\n*By combining a few text commands very flexible and powerful processing can be written quickly\n*So quickly that all kinds of tasks not worth automating become available for solution\n*Fast\n--s--\n!Regular expressions- wild, wild cards\n* Like: *.sas\n*Extended… but different rules from file matching\n*Normally we control an action (keep, drop) with the RE, but\n*We can also extract the exact matched text\n*Confusion points\n*Dot(.) means *, I.e. any character\n*labl*.sas --> lablllzsas!\n*labl.*\s.sas\n*Much less coding than typical with SAS character functions\n--s--\n!Build up bit by bit\n*No match = silence ''means //always// test'' on data with some known matches in\n\n--s--\n!RE syntax\n*Rules:\n*Patterns are applied line-by-line\n*Matches are found anywhere on the line unless there is an anchor\n*Expressions to be matched have these components (all optional)\n\n{{{ ^Abc.+[abc]*\s (big|small)present{2,3}$ }}}\n\n--s--\n!Characters, ranges,alternatives repetitions, anchors, escapes\n\n\n--s--\n!Simple RE examples:\n*[_A-Za-z][_A-Za-z0-9]{0,7}\n*matches a V6 SAS variable identifier\n\n*.*\s.sas7b[cd]at\n*matches the file names of SAS catalogues and datasets\n\n*population\n*matches the string 'population', anywhere on the line\n--s--\n!RE example: Searching SAS logs\n*Your boss asks you to check Wiley T. Programmers' logs because he has gone home…\n*They haven't even finished printing yet!\n1.{{{> grep ERROR wtpsas.log}}}\n2.{{{> grep -E `^ERROR:` wtpsas.log}}}\n3.{{{> grep -E '^ERROR[ ]*:' wtpsas.log}}}\n4.{{{> grep -E '^[Ee][Rr]+[Oo][Rr][ ]*:' wtpsas.log}}}\n5.{{{> grep -i -E '^ERROR[ ]*:' wtpsas.log}}}\n6.{{{> grep -i -E '^ERROR[ ]*:' *.log}}}\n*No output!\n*"Yes, that fast ☺". 17:18 - out of the door.\n\n--s--\n!Frequently Posed Worries\n*Do I have to learn all these commands before I can get anything done?\n*Are your tips only for one kind of Unix, or one kind of shell?\n*What about Windows?\n*Won't this take a long time, (my log files are taking up about 500KB) to run on my 200 listings?\n*It looks like Chinese, how can I ever understand that gobbledygook?\n\n--s--\n!So with the worries gone, let's look at examples\n*These are hard to show well in PowerPoint\n*So read the text paper\n*And see them online at [[here|http://daveg.tiddlyspot.com/]]\n*More text is in the slide notes\n--s--\n! EG 1: Can I see who has access to my studies?\n*On my home system a clinical project has a single group. So if we check the group membership we will get the answer.\n{{{> lsgroup MYPROJ}}}\n{{{MYPROJ id=8996 admin=false users=scott,ccadmin,flopsy,mopsy,cottontailo\n,peter registry=files}}}\n*But it isn't exactly easy to read. To just get the list of users:\n{{{> lsgroup -a users meproj}}}\n{{{MYPROJ users=scott,ccadmin,flopsy,mopsy,cottontailo ,peter}}}\n----\n* These examples are all fictionalised, and you can tell from this one because a\nUnix user name must be 8 characters or less.\n --s--\n!Eg1 page 2\n*Let us drop scott and sort by user id, but first we have to get every user on a separate line.\n* The octal for line-feed is '\s012', using tr we can translate commas to line\nends.\n* We delete the first line with the sed program, 1d means for line 1, do a delete.\n{{{> lsgroup -a users MYPROJ | tr ',' '\s012' |sed '1d' | sort }}}\n*gives:\n{{{\nccadmin\ncottontailo\n!flopsy\n!mopsy\npeter\n}}}\n*Much more readable!\n--s--\n!A file I copied from Windows gives me strange messages\n\n*All text files are not equal.\n!Windows uses two characters to mark the end-of-line and Unix only one.\nThis extra ^M (control+M, ASCII 15 (octal)) character is a legal character in a\nfile name so it causes all sorts of issues.\n*There are various ways to fix it perhaps the simplest is:\n{{{\n!tr -d '\s015' <inputfile >cleaned_file ; mv -f cleaned_file inputfile\n}}}\n--s--\n!I am programming the flagging of lab values…\n*how can I see just the lines with flags?\n*The file is 12,000 lines long!\n*We want to select rows that have at least once the pattern:\n{{{'number<space>flagchar'}}}\n*no lines with only {{{number<space>number}}} should show\n{{{\ngrep -E '[0-9]+[ ]*[#$^+]+' labl*.lst\n}}}\n* labl_23.lst:\n{{{\nWeek 64 22MAY2006/378 09:12 404# 465# 443# 755 88 137\nlabl_23.lst:\nWeek -2 09NOV2004/-105 08:42 467 551 $ 521 $ 717 130 154\n}}}\n--s--\n!Did I remember to run the formats program?\n# {{{> ls ../../report/pgm_a/format* ../../report/pgm_s/format*\n../../report/data_a/format*\n -r--r----- 1 CCadmin this-study 507904 Feb 4 09:04 /vob/myproj/this..sas\n-r--r----- 1 CCadmin this-study 507904 Feb 1 07:34 /vob/myproj/this…cat\n}}}\n# {{{> ls ../../report/*/format*}}}\n# {{{> ls -l /vob/this-study/report/@(data|pgm)_[sa]/formats.@(sas|sas7bcat)}}}\n* {{{@(data|pgm)}}} means {{{data}}} or {{{pgm}}},\n*{{{[sa]}}} means an {{{s}}} or an {{{a}}}, but no other character at this position,\n*{{{@(sas|sas7bcat){{{ means one of {{{sas}}} and {{{sas7bcat}}}\n!The directories searched are\n{{{\n!report/data_a,report/data_s,report/pgm_a,report/pgm_s\n}}}\n\n\n--s--\n!Did I remember…?\n*Another approach would be to use compound (shell) commands.\n{{{\ncd /vob/myproj/this-study/report/data_a/\n\n[[formats.sas -nt formats.sas7bcat ]] &&\n print "run the program!"\n}}}\n*{{{[[}}} and {{{]]}}} surround a logical test, meaning the command is evaluated\nas a true/false expression.\n*{{{-nt}}} is true if the left hand file is newer than the right hand file,\n* {{{&&}}} means that if the command is true the second command is run, else, it\nis not.\n--s--\n!Have I run all the SAS programs in the current directory?\n*We could check if there is a log for every program:-\n{{{\n> ls *.sas | wc -l\n200\n> ls *.log | wc -l\n 200\n}}}\n*That's all very well, but what if there are some old listings left?\n*Let's just look at the dates of the listings.\n*Then, if they are not all today we obviously have a problem.\n--s--\n!Have I run all the SAS programs in a directory?\n*We can use ls to get lists of files and information about them.\n{{{\n ls -l *.sas\n120 -rwxr-xr-x 1 dave unknown 55380 6 Dec 1999 A55219.sas\n 40 -rwxr-xr-x 1 dave unknown 18798 27 Mar 2001 clin_stats.sas\n144 -rwxr-xr-x 1 dave unknown 71352 18 Apr 2001 basic_ods.sas\n}}}\n*Let us just get the dates, just to get a feel for how many are today or last week…\n{{{\n> ls -l -H -t *.sas | cut -c 38-49\n 6 Dec 1999\n18 Apr 2001\n27 Mar 2001\n}}}\n--s--\n!Histogram of file dates\n*Count how many files were modified on each date in the current directory\n{{{\nls -l -H -t |\n# list all the files , with date details -l and no header -H, sorted by time . -t\n sed 1d | # delete the first line (total )\n cut -c 44-51 |\n # keep only columns 44 to 51 (where the date is)\n uniq -c |\n # delete duplicate dates (list is already sorted\n}}}\n--s--\n!How do I run every SAS program in a directory?\n*Strategy:\n*Generate a list of all the programs\n*Pass this list to a command to execute the passed names\n1.{{{> apply 'sas -noterminal -noovp %1 &' *.sas }}}\n2.{{{apply 'sas -noterminal -noovp %1 ' *.sas &}}}\n3.{{{sas -noovp -noterminal *.sas &}}\n\n* The {{{&}}} means 'run in background'\n* Note where the {{{&}}} is:\n# runs a separate SAS job for each, but at the same time,\n# runs the whole apply command in the background, it runs one SAS at a time.\n# does this too but calls SAS once, and writes only one log file\n\n--s--\n!How many patients in each lab listing? Consistent?\n*Extract from a lab listing:\n*Every patient is identified like this, so\n*If we count how many patient ids there are\n* we are home.\n*How?\n*The classic : select, sort, de-duplicate\n--s--\n!How many patients in each lab listing? Consistent?\n*Great - but this is the whole line\n*Select a field with awk or cut\n--s--\n!How many patients in each lab listing? Consistent?\n*Great - but there are duplicates\n--s--\n!How many patients in each lab listing? Consistent?\n*Now we just count how many lines…\n*Add wc -l at end of pipe:\n{{{\n> grep -E '[A-Za-z]+/[0-9]+/.+/' llab_21.lst |\n awk '{print $1}'| sort | uniq |\n wc -l\n200\n}}}\n--s--\n!Could we get a count for all the lab listing files?\n*Add a wild card, and scan all lab files:\n{{{\n> grep -E '[A-Za-z]+/[0-9]+/.+/' labl1_2?.lst | head\nllab_21.lst: ROW/0001/00001 49/F/Ca…\nllab_21.lst: ROW/0001/00001 49/F/Ca…\nllab_21.lst: ROW/0002/00010 55/M/Ca…\n}}}\n*This adds the file name at the start of the line\n*Extract the pat id plus file name\n*Sort | uniq\n*Drop the patid and\n*Sort uniq again…\n--s--\n!Could we get a count for all the lab listing files?\n*Two step scan and count\n{{{\n> grep -E '[A-Za-z]+/[0-9]+/.+/' llab_2?.lst | awk '{print $1, $2}' | sort | uniq |\n awk '{print $1}' | uniq -c\n 200 llab_21.lst:\n 200 llab_22.lst:\n 200 llab_23.lst:\n 8 llab_24.lst:\n }}}\n--s--\n!Can I extract the population used from all the listings?\n{{{\n> grep 'population' llab_2[1-9].lst | sort | uniq | head -20\nllab_21.lst: Extension Safety population\nllab_22.lst: Extension Safety population\nllab_23.lst: Safety population\nllab_24.lst: Efficacy population\nllab_25.lst: Extension Safety population\n}}}\n--s--\n!Hmmm, interesting, can I match it up with the patient counts?\n*Save the pops list and the counts in files\n* then list the files to remind ourselves of the layout\n{{{\n> cat file-count.txt\n 200 llab_21.lst:\n 200 llab_22.lst:\n 200 llab_23.lst:\n 8 llab_24.lst:\n 155 llab_25.lst:\n> cat labpops.txt\nllab_21.lst: Extension Safety population\nllab_22.lst: Extension Safety population\nllab_23.lst: Extension Safety population\nllab_24.lst: Extension Safety population\nllab_25.lst: Extension Safety population\n}}}\n* join on file name - in different columns in each file\n{{{\n> join -1 2 -2 1 file-count.txt labpops.txt\nllab_21.lst: 200 Extension Safety population\nllab_22.lst: 200 Extension Safety population\nllab_23.lst: 200 Extension Safety population\n;lab_24.lst: 8 Extension Safety population\nllab_25.lst: 155 Extension Safety population\n}}}\n--s--\n!Could we extend this to count patients per treatments per per file?\n*Here is a solution to this problem. It does a two level summary by using the \n{{{ sort}}} {{{ | }}} {{{uniq}}} sequence twice.\n1.get the lines from top of each page giving the Treatment: and save the treatment label in a variable.\n2.get the lines with a patient id and print just the patient id from that line, but add the filename and treatment label first.\n3.run uniq to get one line per patients (per file and treatment). This is because patients are more than once in a listing if the program has split parameters into two sections\n4.run uniq again with -c to count how many pats per file and treatment\n5.add an awk to end of pipe to print filename once and tabs to lay output out ''NICELY''\n\n--s--\n!Could we extend this to count patients per treatments per per file?\n{{{\ngawk '/^[tT]reatment:/ {sub("Treatment[ ]*:",""); trt = $0 } # store the\ntreatment /[A-Za-z]+[/][0-9]+[/].+/ {print "|"FILENAME"|"trt"|"$1 }\n # print file & treat for every line with an id\n ' app9l1_12?.lst | sort | uniq |\n awk -F"|" '{ print $2": "$3} ' |\n # select just two fields\n uniq -c |\n # and count\n awk '{ if ( oldfile != $2 ) {print "\snFile ",$2" :";\n oldfile = $2}}\n # pattern1 :print file name once, when it changes\n {print "\st"$1"\st" $3,$4,$5,$6,$7,$8} # print for all lines:\n # add tabs (\st) for first two fields but not others '\n}}}\n --s--\n!Could we extend this to count patients per treatments per per file?\n*It might output:\n{{{\nFile app9l1_121.lst: :\n 35 Bio 30mg qd (core) + combination\n 87 Draino 50mg bid (core) + combination\n 78 Draino 50mg qd (core) + combination\n\nFile app9l1_124.lst: :\n 2 Bio 30mg qd (core) + combination\n 4 Draino 50mg bid (core) + combination\n 2 Draino 50mg qd (core) + combination\n\nFile app9l1_125.lst: :\n 27 Bio 30mg qd (core) + combination\n 67 Draino 50mg bid (core) + combination\n 61 Draino 50mg qd (core) + combination\n}}}\n--s--\n!I need to make a last check of all the titles to ensure they match the specifications\n*Is it possible to list the titles, when there are different numbers of title lines in each output?\n*Some versions of grep have the -p option that prints the paragraph (set of lines delimited by a blank lines) around the matched text.\n*If there is text that is on every first page title then\n{{{> grep -ip '(Page 1 of' *.lst}}}\n\n--s--\n!I need to make a last check of all the titles to ensure they match the specifications - no grep -p?\n*The key to this trick is to set he\n*field separator to \sn (line end) and the\n*record separator to null\n(awk interprets this as a blank line).\n*The awk program has two clauses\n*the string to be matched in /…/ followed by the\n*program to be executed when a match is found enclosed in {…}.\n*FILENAME is an awk system variable\n*$0 is the whole record (i.e. a paragraph in this case)\n*BEGIN is a program executed before the scanning of input starts.\n{{{\n > gawk 'BEGIN { FS= "\sn" ; RS = ""}\n /Page 1 of/ { print FILENAME":\sn" $0 } ' *.lst\n}}}\n--s--\n!How can I check for issues that reappear?\n*How about getting the first page?\n*Saving in a date stamped file name\n*Using diff later\n*If we set the RS to page feed and line end as field separator we get one (logical) record per page. Then we can extract all first pages to keep track of changes. "\s014 is ^L, ctrl+L, or page feed.\n{{{ >gawk 'BEGIN { FS= "\sn" ; RS = "\s014"} /Page 1 of/ { print "\s014"FILENAME": " $0 } ' *.lst }}}\n*To save the first 9 pages change {{{/Page 1 0f/}}} to {{{/Page [1-9] of/}}}\n--s--\n!How can I check my RTF files were all re-created today?\n*This example is very interesting for me. When I saw this problem (and not all the RTF files had listings so using the lst files was not an option) I thought there would be no way without learning a lot of RTF and writing a parser (this has already been done for perl, incidentally). But, one day I looked at an RTF file and thought - all I need is the matching string out of the file. The markup doesn't matter.\n*So looked for a way to extract the matching text and there is an awk function to do it.\n--s--\n!How can I check my RTF files were all re-created today?\nI wrote an awk program:\n* It assumes the date the file was written is in a line containing the program file path, which begins with /report/ (the path is report/key or report/tier1, or report/tier2, perhaps)\n* On these lines there is a date - which is the file write date\n* We need to find the lines with a date (why not match on lines containing any date?).\n* Then extract the date from the line...\n* This is done with the match function: it returns 1 if it found a matching string, and then\n* It puts the location into awk system variables that we can plug in to the substring function to get the date into a variable.\n* Then if we found a date on the line the print statement prints the file & date\n\n--s--\n!How can I check my RTF files were all re-created today?\n{{{\n > gawk '/report\s// {\n match($0,"report[/].*\ssas");\n file=substr($0,RSTART,RLENGTH);\n ok=match($0,"[0-9]+[A-Z]+[0-9]+");\n date=substr($0,RSTART,RLENGTH);\n if (ok) print date, file } ' *.rtf|\n sort -t" " |\n uniq\n}}}\n--s--\n!Just one more thing…\n\n*Checks performed like this are measuring directly what is in the deliverable;\n*They make no assumptions about the datasets, variable names etc.\n*They can be applied to many reporting systems if they use the same output conventions\n*And they can be scripted and run automatically so you can keep an up to date summary table or document and perhaps compare it to a version printed from SAS.\n*This adds up to a uniquely powerful way to tackle output validation and testing\n\n--s--\n!Visual Summary\n* see paper version :-)\n--s--\n!Conclusions\n*Gnit your own:\n*Complementary skills to SAS\n*Ideal for restricted, focussed, specific, one-off needs because of speed and readability\n*Good place to learn regular expressions (very interactive) for SAS V9\n*And hashed arrays - also in V9\n*Can be Fun too\n* http://www.tiddlyspot.com\n\n\n--s--\n!Questions?\n\n<<<\nIt is not because things are difficult that we do not dare,\nit is because we do not dare that they are difficult.\n --Seneca\n<<<\n--s--\n!Contact Information\nI would value your comments and questions on this paper. Please contact me\nat: DaveG\n--s--\n
<<slideShow clock:'-40'>>\n\n--s--\n! Creative Unix solutions for SAS programmer\n\n[[Dave Garbutt|DaveG]]\n\n[[TU04|http://www.lexjansen.com/phuse/2006/tu/tu04.pdf]] @ PhUSE 2006, Dublin\n+++^30em^[Abstract]<<moveablePanel>>\nUnix text tools are perhaps partly responsible for its reputation as a system only for experts. I aim to show you how a little knowledge can go a long way to solving your everyday testing and validation problems. These are not tools for developing big user-friendly systems with, they are for getting fast answers for specific questions that will most likely never recur. The Unix one-liner is the epitome of a fast and light programming system and it is a perfect fit as a second skill for SAS programmers. This tutorial will work up from simple beginnings to show you how to gknit your own, but also give you some canned examples that will be useful today. Incidentally, Windows users should still come along because these tools are now available for Windows XP free from Microsoft.\n===\n--s--\n! INTRODUCTION:\nThe hardest thing learning a new system is that lost feeling when you are faced with a problem you have no idea how to tackle.\n!! This talk will\nMy idea in this talk is to give you a fast overview of \n# what commands are available, and \n# which problems they solve, and to\n# how you can put them together to solve problems they cannot do alone.\n# the power of [[regular expressions]]\n--s--\n!! Plumbing with pipes\nBecause [[Unix commands]] all can be fitted together in long sequences it is becomes easy to break complex tasks into sub-problems you know how to solve. \nPerhaps you then find one step you cannot solve, then you can revisit the key tables here to get clues about how to tackle the problem.\n--s--\n!! Examples \nI plan to take some examples, all starting from simple everyday questions, \n* mainly to do with validating your work, and by \n* building them up piece by piece illustrate\n* how you can quickly learn to make fast one-line programs that will really help your everyday work. \n--s--\n!! In short...\n* Quick solutions where writing a SAS program is not worthwhile.\n* Any examples we don't cover here are available from the [[website|http://daveg.tiddlyspot.com/#Gnit your own]] for this talk and in the paper. The web site is hyperlinked and is recommended for browsing and copy&paste to a terminal session for experimenting.\n--s--\n! WHAT ARE UNIX TEXT TOOLS?\n* a group of commands (i.e programs provided with the system) concentrated on reading, writing and selecting text.\n* they are found on pretty well all systems\n* although they fit together well, they are not totally integrated, but \n* they are fast and easy to use after you have some familiarity\n--s--\n! WHAT OPERATIONS DO THEY DO?\n* They do what you can do with SAS, //selecting// ''variables'' and or ''observations''\n* and some tools \n** can transform (edit) the values\n** and calculate totals and other simple statistics \n* and reformat the output\n* and even do sorting and merging\n--s--\n! Classifying the operations Unix Text commands do\n!! Commands that work on the whole file:\n|Change content, by character|send content to pipe or commands|rearrange rows|h\n| [[tr]], [[iconv]], [[wc]], [[expand]], [[unexpand]] | [[print]], [[echo]], [[cat]], [[tee]], $(<//file//) | [[sort]], [[fold]], [[paste]], [[split]], [[csplit]] |\n--s--\n! Classifying the operations Unix Text commands do\n!! Commands that can //only// select observations\n|by observation number|by content of whole line| by [[RE]]|by content of key fields|h\n| [[head]], [[tail]], [[split]] | [[comm]], [[uniq]], [[sort]] -u | [[grep]], [[csplit]] | [[join]], [[comm]], [[sort]] -m |\n--s--\n! Classifying the operations Unix Text commands do\n!! Commands selecting only columns\n|keep by column number|drop by column number|keep by field|h\n| [[cut]], [[col]] | [[colrm]] | [[cut]] |\n--s--\n! Commands able to select columns or observations\n# Pipes constructed using previous commands\n# Commands that are also scripting languages:\n** [[awk]]\n** [[sed]]\n** [[perl]]\n** [[ruby]]\n--s--\n! Classifying the operations Unix Text commands do\n!! for detailed table see [[Capabilities of Unix Text commands]] or [[UnixTextTools table]]\n> <<slider chkUnixcmnds "Capabilities of Unix Text commands" "Reveal: Capabilities of Unix Text commands">>\n+++^30em^[UnixTextTools table]<<moveablePanel>>\n<<tiddler [[UnixTextTools table]]>>\n===\n!! Note on terms\n* observations is approx = to rows \n* but columns are not = to variables, \n!! Unix text commands:\nIn <<wikipedia List_of_Unix_programs>> check the section on text commands. \n\n--s--\n! HOW DO THEY FIT TOGETHER?\n//Piper at the gates of dawn…//\n> [[The pipe of piece]]\n+++^30em^[The pipe of piece] <<moveablePanel>>\n> <<tiddler [[The pipe of piece]]>>\n===\n> \n--s--\n! REGULAR EXPRESSIONS – WILD WILD CARDS \nBuild up piece by piece testing as you go...\n\n+++^30em^[Getting started with Regular Expressions] <<moveablePanel>>\n> <<tiddler [[Getting started with Regular Expressions]]>>\n===\n--s--\n! COMMONEST UNIX COMMANDS\n> <<slider chkcomunicomm "My Commonest Unix Commands" "Reveal: My Commonest Unix Commands">>\n\n--s--\n! HOW DO PATTERNS OF USE OF UNIX TEXT TOOLS COMPARE TO SAS PROGRAMS?\n!! Actually they are very similar!\n** read data with set; add variable, drop variables, derive variables\n** reformat data and print //nicely//\n** sort data\n** select unique observations\n** count observations according to their content to make simple tables\n** Join up datasets with merge\n** Fit nonlinear models \n* ...well it must be said the last is out of scope, but the others are not.\n* although joining files is easier in SAS but \n** for some small problems the text tools will see you through\n** see example : of log checking\n--s--\n! HOW DO PATTERNS OF USE OF UNIX TEXT TOOLS COMPARE TO SAS PROGRAMS?\n!! What is different from SAS about this way?\n* + very fast and light to write and run\n* + easy to test and develop (no compiling)\n** (run, look at result, <up arrow>, edit line, <return>,...)\n* + easy to read \n* + easy to adapt\n* - Not so readable when more than a few lines\n* + program small enough to be self documenting\n* + fast enough to run on significant amounts of data\n--s--\n! What is the Same?\n* just like a complicated data manipulation in SAS\n* you build it bit by bit by \n## checking the output (dataset) as you go\n## analysing what (observations, or variables) you still need to remove\n## this is where the creativity of Gnitting lies, knowing (or guessing) where to start and \n## when to stop cutting...\n\n--s--\n! EXAMPLE PROBLEMS - ILLUSTRATING THE BUILD IT BIT-BY-BIT METHOD:\nList all examples:\n<<tag GnitExample>>\n \n--s--\n! CONVERTING ONE-LINERS TO SCRIPTS\n#When?\n#How?\n--s--\n! FPW (FREQUENTLY POSED WORRIES)\n* [[Are your tips only for one kind of Unix, or one kind of shell?]]\n* [[What about Windows?]]\n* [[Won’t this take a long time, (taking up about 500KB) to run on my 200 listings?]]\n* [[It looks like Chinese, how can I ever understand that gobbledegook?]]\n--s--\n! CONCLUSION\n<<<\nI hope I have convinced you it is worth learning to use Unix text tools for helping in your daily work. \nYes, it does take some effort: but they are light weight and once you have attained a certain level of familiarity you can use them for //ad hoc// problems that would not be worth writing a bigger SAS program for. \nAnd, after getting what you need ''now'' in a few minutes, after a bit of head scratching and typing, and you'll be going home tonight with a bit grin, like the day you first..., well, you get the idea ;-)\n<<<\n* Unix text tools occupy a space complimentary to your SAS skills\n* The rewards are worth the learning effort\n--s--\n! FURTHER READING\n* Unix documentation for your system\n* [[Unix Power Tools]] (OReilly) \n* A shell programming guide\n> <<tag Gnit_readon>>\n
All the examples for the talk 'Gnit your own' can be found here.
> {{{ls *.sas | wc –l}}}\n> {{{ls *.log | wc –l}}}\nThat’s all very well, what if there are some old listings left?\n* What if we could just list all the write dates of the listings? \nThen, if they are not all today we obviously have a problem.\nWe just {{{ls –l}}} but that gives a lot of information to sift through for suspicious dates.\n* A date histogram would be nice!\n* A quick check of {{{man ls}}} shos there is no option to just give the dates.\n* OK, so we take the listing from {{{ls –l}}}, what do we notice? The date is in a fixed column, but it may or may not have a space. This makes it hard to use [[awk]]. (There are ways of course). \n* checking the tables of Unix text [[tools|UnixTextTools table]] shows col can select columns by column number. So let's try [[col]] to extract the columns of interest.\n> {{{ls –l *.log | col –c 8-12 }}}\n> gives something like: \n{{{\n19 Dec 2005 \n29 Aug 14:25 \n12 Mar 2004 \n27 Aug 16:57 \n27 Nov 2005 \n 8 Apr 2005 \n 8 Sep 2005 \n20 Aug 12:33 \n 8 Aug 2005 \n13 Jun 2005 \n 8 Apr 2005 \n30 Jan 2006 \n 5 Sep 2005 \n}}}\nGood – but too many lines now… we just need a count for each distinct date. Sorting and using [[uniq]] will do this nicely:\n> {{{ls –l *.log | col –c 8-12 | sort | uniq –c}}}\n* but the dates ae in date order...\n* a long consultation of the [[sort]] man page can give us this (-M sorts months into the correct order):\n> {{{ls -l | cut -c 38-50 | sort -b +3 -n -4 +2 -M -3 +1 -n -2 }}}\n>\n{{{\n30 Jan 2006 \n28 Apr 2005 \n27 Nov 2005 \n22 Nov 2005 \n19 Dec 2005 \n13 Jun 2005 \n11 Jul 2005 \n 8 Sep 2005 \n 8 Aug 2005 \n 8 Apr 2005 \n 8 Apr 2005 \n 8 Apr 2005 \n 5 Sep 2005 \n31 May 2004 \n12 Mar 2004 \n14 Dec 2003 \n14 Dec 2003 \n27 Aug 16:57 \n29 Aug 14:25 \n20 Aug 12:33 \n15 Jul 09:09 \n}}}\nVoilà\n!!!! Note: times within the last 6 months do not show the year \n* actually a short consultation of the [[ls]] man page should show us the {{{-t}}} option that sorts by time\n> {{{ 2 29 Aug\n 1 27 Aug\n 1 20 Aug\n 1 15 Jul\n 1 30 Jan 2006 \n 1 19 Dec 2005 \n 1 27 Nov 2005 \n 1 22 Nov 2005 \n 1 8 Sep 2005 \n 1 5 Sep 2005 \n 1 8 Aug 2005 \n 1 11 Jul 2005 \n 1 13 Jun 2005 \n 1 28 Apr 2005 \n}}}\n{{{\n
/***\nTo use, add {{{[[HorizontalMainMenuStyles]]}}} to your StyleSheet tiddler, or you can just paste the CSS in directly. See also HorizontalMainMenu and PageTemplate.\n***/\n/*{{{*/\n\n#topMenu br {display:none; }\n#topMenu { background: #39a; }\n#topMenu { padding:2px; }\n#topMenu .button, #topMenu .tiddlyLink {\n margin-left:0.5em; margin-right:0.5em;\n padding-left:3px; padding-right:3px;\n color:white; font-size:115%;\n}\n#topMenu .button:hover, #topMenu .tiddlyLink:hover { background:#178;}\n\n#displayArea { margin: 1em 15.7em 0em 1em; } /* so we use the freed up space */\n\n/* just in case want some QuickOpenTags in your topMenu */\n#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }\n#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }\n#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }\n\n\n/*}}}*/
<<top>>\n<<toggleSideBar>><<renameButton '>' >>\n<<jump j '' top>>\n<<fullscreen f>>\n<<saveChanges>><<renameButton s 'Save TiddlyWiki'>>\n<<newTiddler>><<renameButton n>>\n
/***\n|Name|HoverMenuPlugin|\n|Created by|SaqImtiaz|\n|Location|http://lewcid.googlepages.com/lewcid.html#HoverMenuPlugin|\n|Version|1.11|\n|Requires|~TW2.x|\n!Description:\nProvides a hovering menu on the edge of the screen for commonly used commands, that scrolls with the page.\n\n!Demo:\nObserve the hovering menu on the right edge of the screen.\n\n!Installation:\nCopy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.\nTo customize your HoverMenu, edit the HoverMenu shadow tiddler.\n\nTo customize whether the menu sticks to the right or left edge of the screen, and its start position, edit the HoverMenu configuration settings part of the code below. It's well documented, so don't be scared!\n\nThe menu has an id of hoverMenu, in case you want to style the buttons in it using css.\n\n!Notes:\nSince the default HoverMenu contains buttons for toggling the side bar and jumping to the top of the screen and to open tiddlers, the ToggleSideBarMacro, JumpMacro and the JumpToTopMacro are included in this tiddler, so you dont need to install them separately. Having them installed separately as well could lead to complications.\n\nIf you dont intend to use these three macros at all, feel free to remove those sections of code in this tiddler.\n\n!To Do:\n* rework code to allow multiple hovering menus in different positions, horizontal etc.\n* incorporate code for keyboard shortcuts that correspond to the buttons in the hovermenu\n\n!History:\n*03-08-06, ver 1.11: fixed error with button tooltips\n*27-07-06, ver 1.1 : added JumpMacro to hoverMenu\n*23-07-06\n\n!Code\n***/\n\n/***\nstart HoverMenu plugin code\n***/\n//{{{\nconfig.hoverMenu={};\n//}}}\n\n/***\nHoverMenu configuration settings\n***/\n//{{{\nconfig.hoverMenu.settings={\n align: 'right', //align menu to right or left side of screen, possible values are 'right' and 'left' \n x: 1, // horizontal distance of menu from side of screen, increase to your liking.\n y: 158 //vertical distance of menu from top of screen at start, increase or decrease to your liking\n };\n//}}}\n\n//{{{\n//continue HoverMenu plugin code\nconfig.hoverMenu.handler=function()\n{\n var theMenu = createTiddlyElement(document.getElementById("contentWrapper"), "div","hoverMenu");\n theMenu.setAttribute("refresh","content");\n theMenu.setAttribute("tiddler","HoverMenu");\n var menuContent = store.getTiddlerText("HoverMenu");\n wikify(menuContent,theMenu);\n\n var Xloc = this.settings.x;\n Yloc =this.settings.y;\n var ns = (navigator.appName.indexOf("Netscape") != -1);\n function SetMenu(id)\n {\n var GetElements=document.getElementById?document.getElementById(id):document.all?document.all[id]:document.layers[id];\n if(document.layers)GetElements.style=GetElements;\n GetElements.sP=function(x,y){this.style[config.hoverMenu.settings.align]=x +"px";this.style.top=y +"px";};\n GetElements.x = Xloc;\n GetElements.y = findScrollY();\n GetElements.y += Yloc;\n return GetElements;\n }\n window.LoCate_XY=function()\n {\n var pY = findScrollY();\n ftlObj.y += (pY + Yloc - ftlObj.y)/15;\n ftlObj.sP(ftlObj.x, ftlObj.y);\n setTimeout("LoCate_XY()", 10);\n }\n ftlObj = SetMenu("hoverMenu");\n LoCate_XY();\n};\n\nwindow.old_lewcid_hovermenu_restart = restart;\nrestart = function()\n{\n window.old_lewcid_hovermenu_restart();\n config.hoverMenu.handler();\n};\n\nsetStylesheet(\n"#hoverMenu .button, #hoverMenu .tiddlyLink {border:none; font-weight:bold; background:#18f; color:#FFF; padding:0 5px; float:right; margin-bottom:4px;}\sn"+\n"#hoverMenu .button:hover, #hoverMenu .tiddlyLink:hover {font-weight:bold; border:none; color:#fff; background:#000; padding:0 5px; float:right; margin-bottom:4px;}\sn"+\n"#hoverMenu .button {width:100%; text-align:center}"+\n"#hoverMenu { position:absolute; width:7px;}\sn"+\n"\sn","hoverMenuStyles");\n\n\nconfig.macros.renameButton={};\nconfig.macros.renameButton.handler = function(place,macroName,params,wikifier,paramString,tiddler)\n{\n\n if (place.lastChild.tagName!="BR")\n {\n place.lastChild.firstChild.data = params[0];\n if (params[1]) {place.lastChild.title = params[1];}\n }\n};\n\nconfig.shadowTiddlers["HoverMenu"]="<<top>>\sn<<toggleSideBar>><<renameButton '>' >>\sn<<jump j '' top>>\sn<<saveChanges>><<renameButton s 'Save TiddlyWiki'>>\sn<<newTiddler>><<renameButton n>>\sn";\n//}}}\n//end HoverMenu plugin code\n\n//Start ToggleSideBarMacro code\n//{{{\nconfig.macros.toggleSideBar={};\n\nconfig.macros.toggleSideBar.settings={\n styleHide : "#sidebar { display: none;}\sn"+"#contentWrapper #displayArea { margin-right: 1em;}\sn"+"",\n styleShow : " ",\n arrow1: "«",\n arrow2: "»"\n};\n\nconfig.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)\n{\n var tooltip= params[1]||'toggle sidebar';\n var mode = (params[2] && params[2]=="hide")? "hide":"show";\n var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;\n var label= (params[0]&¶ms[0]!='.')?params[0]+" "+arrow:arrow;\n var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");\n if (mode == "hide")\n { \n (document.getElementById("sidebar")).setAttribute("toggle","hide");\n setStylesheet(this.settings.styleHide,"ToggleSideBarStyles");\n }\n};\n\nconfig.macros.toggleSideBar.onToggleSideBar = function(){\n var sidebar = document.getElementById("sidebar");\n var settings = config.macros.toggleSideBar.settings;\n if (sidebar.getAttribute("toggle")=='hide')\n {\n setStylesheet(settings.styleShow,"ToggleSideBarStyles");\n sidebar.setAttribute("toggle","show");\n this.firstChild.data= (this.firstChild.data).replace(settings.arrow1,settings.arrow2);\n }\n else\n { \n setStylesheet(settings.styleHide,"ToggleSideBarStyles");\n sidebar.setAttribute("toggle","hide");\n this.firstChild.data= (this.firstChild.data).replace(settings.arrow2,settings.arrow1);\n }\n\n return false;\n}\n\nsetStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\sn","ToggleSideBarButtonStyles");\n//}}}\n//end ToggleSideBarMacro code\n\n//start JumpToTopMacro code\n//{{{\nconfig.macros.top={};\nconfig.macros.top.handler=function(place,macroName)\n{\n createTiddlyButton(place,"^","jump to top",this.onclick);\n}\nconfig.macros.top.onclick=function()\n{\n window.scrollTo(0,0);\n};\n\nconfig.commands.top =\n{\n text:" ^ ",\n tooltip:"jump to top"\n};\n\nconfig.commands.top.handler = function(event,src,title)\n{\n window.scrollTo(0,0);\n}\n//}}}\n//end JumpToStartMacro code\n\n//start JumpMacro code\n//{{{\nconfig.macros.jump= {};\nconfig.macros.jump.handler = function (place,macroName,params,wikifier,paramString,tiddler)\n{\n var label = (params[0] && params[0]!=".")? params[0]: 'jump';\n var tooltip = (params[1] && params[1]!=".")? params[1]: 'jump to an open tiddler';\n var top = (params[2] && params[2]=='top') ? true: false; \n\n var btn =createTiddlyButton(place,label,tooltip,this.onclick);\n if (top==true)\n btn.setAttribute("top","true")\n}\n\nconfig.macros.jump.onclick = function(e)\n{\n if (!e) var e = window.event;\n var theTarget = resolveTarget(e);\n var top = theTarget.getAttribute("top");\n var popup = Popup.create(this);\n if(popup)\n {\n if(top=="true")\n {createTiddlyButton(createTiddlyElement(popup,"li"),'Top ↑','Top of TW',config.macros.jump.top);\n createTiddlyElement(popup,"hr");}\n \n story.forEachTiddler(function(title,element) {\n createTiddlyLink(createTiddlyElement(popup,"li"),title,true);\n });\n }\n Popup.show(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return false;\n}\n\nconfig.macros.jump.top = function()\n{\n window.scrollTo(0,0);\n}\n//}}}\n//end JumpMacro code\n\n//utility functions\n//{{{\nPopup.show = function(unused,slowly)\n{\n var curr = Popup.stack[Popup.stack.length-1];\n var rootLeft = findPosX(curr.root);\n var rootTop = findPosY(curr.root);\n var rootHeight = curr.root.offsetHeight;\n var popupLeft = rootLeft;\n var popupTop = rootTop + rootHeight;\n var popupWidth = curr.popup.offsetWidth;\n var winWidth = findWindowWidth();\n if (isChild(curr.root,'hoverMenu'))\n var x = config.hoverMenu.settings.x;\n else\n var x = 0;\n if(popupLeft + popupWidth+x > winWidth)\n popupLeft = winWidth - popupWidth -x;\n if (isChild(curr.root,'hoverMenu'))\n {curr.popup.style.right = x + "px";}\n else\n curr.popup.style.left = popupLeft + "px";\n curr.popup.style.top = popupTop + "px";\n curr.popup.style.display = "block";\n addClass(curr.root,"highlight");\n if(config.options.chkAnimate)\n anim.startAnimating(new Scroller(curr.popup,slowly));\n else\n window.scrollTo(0,ensureVisible(curr.popup));\n}\n\nwindow.isChild = function(e,parentId) {\n while (e != null) {\n var parent = document.getElementById(parentId);\n if (parent == e) return true;\n e = e.parentNode;\n }\n return false;\n};\n//}}}\n\n\n
* You can use flexible wildcards in filenames and ''in directory names'' too.\n\n{{{ \nls -l /vob//this-study/report/@(data|pgm)_[sa]/formats.@(sas|sas7bcat)\n}}}\n{{{\n-r--r----- 1 CCadmin this-study 507904 Feb 4 09:04 /vob/myproj/this-study/report/data_a/formats.sas\n-r--r----- 1 CCadmin this-study 507904 Feb 1 07:34 /vob/myproj/this-study/report/data_s/formats.sas7bcat\n[/vob/myproj/this-study/report/pgm_saf]\n}}}\n* the program is newer!\n!!!! @(data|pgm) means data or pgm \n!!!! [sa] means an s or an a, but no other character at this position\n!!!! @(sas|sas7bcat) means one of 'sas' and 'sas7bcat' ([[Korn shell]] extension)\n<<<\n so the directories searched are \n# report/data_a\n# report/data_s\n# report/pgm_a\n# report/pgm_s\n<<<
* to do this we want to looka at all the lines of a listing where a value is flagged \n* we need a [[regular expresssion|regular expresssions]] that finds all flagged numbers\n* the form of the number is ddd# and # might be #, ^, $, + in any combination\n\n* put this into the VSlick find or [[selective view]]\n{{{\n\s:n[ ]*[#$^+]+\n}}}\n\n* for grep it needs to be changed a little:\n{{{\ngrep -E '[0-9]+[ ]*[#$^+]+' x7l1_23.lst\n}}}\n{{{\nx7l1_23.lst: Week 64 31MAY2006/352 09:03 385# 434 417 786 95 146\nx7l1_23.lst: Week 64 22MAY2006/378 09:12 404# 465# 443# 755 88 137\nx7l1_23.lst: Week 64 10APR2006/369 09:48 407# 443 431 841 96 162\nx7l1_23.lst: Week 24 31MAR2005/84 09:34 393# 442# 425# 790 79 216\nx7l1_23.lst: Week 64 05JAN2006/364 10:06 403# 436# 425# 858 76 216\nx7l1_23.lst: Week 24 25APR2005/91 08:05 346 428# 398 653 86 120\nx7l1_23.lst: Week 64 30MAR2006/395 10:54 382 454# 429 710 93 130\nx7l1_23.lst: Week 64 13MAR2006/369 16:31 378# 432 413 769 83 139\nx7l1_23.lst: Week 24 13JUN2005/84 09:01 368 440# 415 698 88 144\nx7l1_23.lst: Week 16 04JUL2005/32 09:52 407# + 422 417 928 81 135\nx7l1_23.lst: Week 24 23JUN2005/79 07:08 327 411# 381 634 84 132\nx7l1_23.lst: Week 64 29MAR2006/358 06:06 344 394# 376 766 93 133\nx7l1_23.lst: Week 24 12MAY2005/86 09:54 395# 422 413 877 84 151\nx7l1_23.lst: Week 24 12MAY2005/86 09:25 424# 430 428 973 88 153\nx7l1_23.lst: Week 24 26MAY2005/86 08:37 394 413# 406# 912 88 137\nx7l1_23.lst: Week 64 01MAR2006/365 15:22 389 425# 412# 838 96 142\nx7l1_23.lst: Week 24 14JUL2005/71 09:07 382# 418# 406# 836 82 146\nx7l1_23.lst: Week 64 03MAY2006/364 13:34 346 420# 394 679 93 144\nx7l1_23.lst: Week 64 07SEP2005/372 07:53 366# 430 407 724 91 157\nx7l1_23.lst: Week 64 02AUG2005/363 09:51 394 463# 439# 723 76 138\nx7l1_23.lst: Week 16 22MAR2005/28 10:22 393# 392 392 1005 95 175\nx7l1_23.lst: Week 24 29AUG2005/104 10:08 360# 407 391 780 79 188\nx7l1_23.lst: Week 64 16MAY2006/364 11:32 357# 410 392 758 91 177\nx7l1_23.lst: Week 64 21MAR2006/365 10:08 384 425# 411 819 95 191\nx7l1_23.lst: Week 64 16MAY2006/364 07:40 354 436# 407 660 103 154\nx7l1_23.lst: Week 24 16JUN2005/84 11:03 390# 434# 419# 805 90 148\nx7l1_23.lst: BRA/0006/00019 65/M/Ot Week -2 09NOV2004/-105 08:42 467 551 $ 521 $ 717 130 154\nx7l1_23.lst: Week 0 24NOV2004/-90 09:08 466 525 $ 505 $ 788 90 170\n}}}
* use [[cksum]] which calculates a check sum\n## set up a variable with the list of dataset names \n## strip off the filetype with sed\n{{{\ndsall=$(ls ../data_a/*.sas7bdat | sed 's/.sas7bdat//' )\napply 'print -- "---- %1 -----" ;cksum /view/garbuda1_view/$PWD/%1.sas7bdat /view/gopalde1_view/$PWD/%1.sas7bdat ; print ' $dsall >datsetsdifs.txt\n}}}\n\n* [[cksum]] is not perfect, to do a binary byte-by-byte compare use the [[cmp]] command.\n* Do not use [[diff]] it only works on text files.\n\n!!!! Note: \n* SAS datasets include metadata - like modification date, if these are different then these two methods will say the files are different, even though the contents are identical.\n* [[cksum]] and [[cmp]] will also see the datasets as different if one is sorted and the other is not.\n* [[cksum]] does not check every byte so it is, in principle, possible for two different files to have the same checksum. For validation purposes the same cksum is not sufficient to prove identity. \n* if these cases are possible then you must use proc compare.
{{{ grep -E '[A-Za-z]+/[0-9]+/.+/' x7l1_18.lst | awk '{print $1}' | sort | uniq -c |wc -l}}}\n{{{\n 179\n}}}\n\n!!!! to get the list of which they are :\n* remove the {{{| wc -l }}}from the end of the pipe\n** might give (in part) :\n{{{\n 2 USA/0571/00004\n 2 USA/0572/00001\n 2 USA/0573/00001\n 2 USA/0573/00002\n 2 USA/0573/00003\n 2 USA/0573/00004\n 2 USA/0573/00008\n 2 USA/0578/00001\n 2 USA/0578/00008\n 2 USA/0580/00011\n 2 USA/0581/00001\n 2 USA/0581/00002\n 2 USA/0581/00003\n}}}\n\n!!!! that is how it grew, you could take out the grep and just use awk:\n{{{\nawk '/[A-Za-z]+\s/[0-9]+\s/.+\s// { print $1}' x7l1_18.lst | sort | uniq -c |wc -l\n 179\n}}}\n!!!! The awk syntax for a regular expression to match is /[[RegularExpression]]/ so / in the string has to be escaped with a \s (BackSlash)\n\n<<slider chkgrepawkeff "Efficiency of grep and awk" "Show: Efficiency of grep and awk">>
* To be able to scan all the formats.sas programs we have to identify them first. We could type in their names individually but\n** the wild card {{{/vob/CLAF237A/CLAF*E1/report/pgm_a/formats.sas}}} will match all these programs (in extension studies)\n* Then we need to find all the value statements where (for example) trta or trtb is the name (ignoring any proceeding dollar), \n* but if we just search with awk (or grep) we only find the first line of the format, because both these utilities work on single lines by default. But with awk you can specify the [[record separator]] and [[field separator]]. So \n** if we define the record separator to ; and the field sep to <end of line> (= \sn in Unix jargon) then we get a record per value statement and we can print just the one value statement\n{{{\n gawk 'BEGIN {FS="\sn"; RS=";" } /trt[ab] / { print FILENAME"("NF") : \sn" $0} ' /vob/CLAF237A/CLAF*E1/report/pgm_a/formats.sas \n}}}\n\nSample output:\n{{{\n/vob/CLAF237A/CLAF237A2301E1/report/pgm_a/formats.sas(10) : \n\nvalue $trta "V" = "Vilda 50mg qd@(core+ext)"\n "W" = "Vilda 50mg bid@(core+ext)"\n "X" = "Vilda 100mg qd@(core+ext)"\n "Y" = "Placebo@(core)*"\n "Z" = "Vilda 50mg qd@(ext)*"\n "TOTAL" = "Total"\n "STLNOTRT" = "No treatment"\n other = "Missing treatment label"\n \n/vob/CLAF237A/CLAF237A2301E1/report/pgm_a/formats.sas(10) : \n\nvalue $trtb "V" = "Vilda 50mg qd@(core+ext)"\n "W" = "Vilda 50mg bid@(core+ext)"\n "X" = "Vilda 100mg qd@(core+ext)"\n "Y" = "Placebo@(core)"\n "Z" = "Vilda 50mg qd@(ext)"\n "TOTAL" = "Total"\n "STLNOTRT" = "No treatment"\n other = "Missing treatment label"\n \n/vob/CLAF237A/CLAF237A2303E1/report/pgm_a/formats.sas(9) : \n\nvalue $trta "W" = "Vilda 50mg qd@+ Met (core+ext)"\n "X" = "Vilda 50mg bid@+ Met (core+ext)"\n "Y" = "Placebo@+ Met (core)*"\n "Z" = "Vilda 50mg qd@+ Met (ext)*"\n}}}\n\n
! strategy ->\n# get all the first few pages for a listing file\n> {{{gawk 'BEGIN { FS= "\sn" ; RS = "\s014"} /Page 1 of/ { print "\s014"FILENAME": " $0 } ' *.lst}}}\nHow does this awk program work?\n* {{{/Page 1 of/}}} selects records with this string - it is page 1 .-)\n* {{{print "\s014"FILENAME": " $0 }}} the program, between braces ({}) prints all the record ({{{$0}}}) and adds the name of the file and a page separator first. The page separator is given as an octal character number escaped with a backslash : {{{\s014}}} is {{{cntrl-L}}}. This has gone from the listing because the field separator is removed from the data.\n* The normal record separator in awk is the line end character. Because awk is matching per record we have to include more than one line when printing or else we would just get this:\n>{{{grep 'Page 1 of' *.lst}}}\n>might give:\n>{{{\n Appendix 8 Table 2-11 (Page 1 of 8)\n}}}\n* We can set the field separator with a command option {{{-F"|"}}} to use vertical bar for example. But we also need to set the record separator and this must be done from inside the program, clearly it has to be done before reading any data and the BEGIN target is provided for this purpose.:\n>{{{BEGIN { FS= "\sn" ; RS = "\s014"} }}}\n* the FS and RS are awk internal variables that can be reset as shown. FS the field separator is set to line-end, and RS is set to the page separator.\n* the result of this is that each page is one record, and we print the page that says 'Page 1 of'\n* this is realted to the previous trick to get titles.
* On Unix use the [[tail]] command.\n\n{{{tail -f filename }}}\ndisplays the last 10 lines of the file and updates as the file is written.\n[[ps]] to see how much CPU the job has used. If you know what the total should be then this may help.\n{{{ps lwx <process id>}}} will give you more information on just one process (you can find the <process id>>, or [[pid]] from the [[ps]] output).\n\n* You could check modification times on the files it creates\n\n\n
* An if then else test can be written using [[file tests|ConditionalExpressions]] in the [[Korn shell]]\n* but less writing is to write a compound command \n{{{\n apply '( [[ -e %1 ]] || print " NOT exist: %1" ) && print "exists: \st %1"' $(< *target*) \nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_2_pqtest.doc\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/A8T_1_PQTEST.RTF\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/f14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/if_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/int_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/int_2_pqtest.pdf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/it_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1617_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1619_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1621_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1622_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1623_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1624_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1625_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1626_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1627_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1628_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1629_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/s3f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/s3l_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/s3t_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/t14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x51_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x52_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5l_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5l_2_pqtest.sas7bdat\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5t_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8f_1_pqtest.rtf\n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8f_2_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8f_2_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x71_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8t_1_pqtest.rtf\n}}}\n* change first || to && (wrong will do both prints on all lines) except where the file does not exist\n{{{\n/view/garbuda1_view@ichn22> apply '( [[ -e %1 ]] && print " NOT exist: %1" ) && print "exists: \st %1"' $(< *target*) \n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_1_pqtest.rtf\n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_2_pqtest.doc\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_2_pqtest.doc\n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/A8T_1_PQTEST.RTF\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/A8T_1_PQTEST.RTF\n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/f14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/f14_1_pqtest.rtf\n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/if_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/if_1_pqtest.rtf\n}}}\n* change second || to && and change print texts accordingly:\n{{{\n[/vob/CICL670A/CICL670A0106/util]\n/view/garbuda1_view@ichn22> apply '( [[ -e %1 ]] && print "exists: %1" ) || print " NOT exist: \st %1"' $(< *target*) \nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/a8f_2_pqtest.doc\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/A8T_1_PQTEST.RTF\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/f14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/if_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/int_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/int_2_pqtest.pdf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/it_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1617_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1619_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1621_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1622_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1623_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1624_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1625_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1626_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1627_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1628_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/l1629_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/s3f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/s3l_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/s3t_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/t14_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x51_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x52_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5f_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5l_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5l_2_pqtest.sas7bdat\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x5t_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8f_1_pqtest.rtf\n NOT exist: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8f_2_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x71_1_pqtest.rtf\nexists: /vob/CICL670A/CICL670A0106/report/export/pgm_eff/x8t_1_pqtest.rtf\n[/vob/CICL670A/CICL670A0106/util]\n}}}
\n!! find errors and problems in a SAS log\n* The simple (facile ;-)answer is search for the text!\n* but the text that needs to be checked for is quite various so making sure you search for all of the possibilities is not so simple.\n* This is where [[regular expressions]] can help. They allow seach alternatives to be expressed and searched for all together. A | = [[vertical bar]] separates the alternatives. \n* Simple versions: (vertical bar means ''or'')\n{{{ERROR:|WARNING:|\s:b*data .+;|\s:b*proc .+;|\s:b*run\s:b*;|\s:n*\s:b+observations}}}\n\n{{{ERROR:|WARNING:|data\s:b+\s:v+|proc .+;|run;|^NOTE:\s:b+There were}}}\n\n* To Use: copy& paste the line into the VSlick selective view search string box\n* to get this dialog go to View|Selective view (or activate the tool bar for selective view)\n\n!!! Most comprehensive \n\n* add STL warnings and errors, custom DATA ERROR, Char variable truncation warning...\n* lines beginning with : are errors copied to *.prm as errors\n* this version overs all the strings in the [[SAS Program Validation guidelines]] plus others from experience and from STL documentation.\n* the number of obs from each datastep is also shown along with where clauses and the title line (check it is today's listing!)\n\n{{{^WARNING: !([Cc]ompression)|^ERROR:|UNINITIALIZED|converted to|referenced|repeats of|invalid|mathematical operations|converted|NOREPLACE|\s:d+ observations|^PGM WARNING|^PGM ERROR|^[ ]+:|repeats of BY|deleted observations|observations deleted|^ERROR[ ]*:|^NOTE:.*observations|^Entering |^Leaving|^1[ ]+.*\s:d{4,}|^NOTE: %INCLUDE|^DATA ERROR|^STLERR:|^[ ]+Truncation may result|^INFO:[ ]+.*character.*200|^STL ERROR|^PGM WARN|^PGM ERROR|^NOTE: The SAS System used:|^STL NOTE: Including}}}\n\n* you can add an expression by appending |<new RE> at the end of a line.\n!!!! simple check of errors but including most useful SAS program statements\n{{^\s:d+\s:b+[rR]un\s:b*;|^\s:d+\s:b+[pP]roc\s:b+|^\s:d+\s:b+[dD]ata\s:b+|^\s:d+\s:b+[Ss]et\s:b+|^\s:d+\s:b+[Mm]erge\s:b+|^\s:d+\s:b+[Bb]y\s:b+|^NOTE:|^WARNING:|^ERROR:|^MPRINT}}}\n\n''See Also'' CheckSASLogsWithChklogsScript and VSlickEditSelectLinesinMakeLog\n!!!! add STL entering & leaving macro messages and stlrun call and where statements \n{{{\n^WARNING[ ]*: !([Cc]ompression)|^ERROR:|UNINITIALIZED|converted to|referenced|repeats of|invalid|mathematical operations|converted|NOREPLACE|\s:d+ observations|^PGM WARNING|^PGM ERROR|^[ ]+:|repeats of BY|deleted observations|observations deleted|^ERROR[ ]*:|^NOTE:.*observations|^-*[ ]*Entering |^-*[ ]*Leaving|^1[ ]+.*\s:d{4,}|^NOTE: %INCLUDE|^DATA ERROR|^STLERR:|^[ ]+Truncation may result|^INFO:[ ]+.*character.*200|^STL ERROR|^PGM WARN|^PGM ERROR|^NOTE: The SAS System used:|^STL NOTE: Including|%stlrun\s(|^[ ]*WHERE\n}}}\n!!!! Add MPRINT useful when debugging\n{{{\n^WARNING[ ]*: !([Cc]ompression)|^ERROR[ ]*:|UNINITIALIZED|converted to|referenced|repeats of|invalid|mathematical operations|converted|NOREPLACE|\s:d+ observations|^PGM WARNING|^PGM ERROR|^[ ]+:|repeats of BY|deleted observations|observations deleted|^ERROR[ ]*:|^NOTE:.*observations|^-*[ ]*Entering |^-*[ ]*Leaving|^1[ ]+.*\s:d{4,}|^NOTE: %INCLUDE|^DATA ERROR|^STLERR:|^[ ]+Truncation may result|^INFO:[ ]+.*character.*200|^STL ERROR|^PGM WARN|^PGM ERROR|^NOTE: The SAS System used:|^STL NOTE: Including|%stlrun\s(|^[ ]*WHERE|^[ ]*:[ ]*|^MPRINT\s([A-Z_0-9]+\s):\n}}}\n\n!!!! NB you may need to check for other strings if any are used in the programs.\n!!!! NB you must tick the reset lines sel box before it will work\n
* ls does not return full paths\n* but we can construct them using a handy system variable [[$PWD]] {{{-v pth=$PWD}}}\n# first we add the view location at the start: {{{V:/me_view}}} \n# concatenated with the path by writing them next to each other: {{{pth="V:/me_view"pth;}}}\n# then we change all the Unix separators to \s : {{{gsub("/","\s\s",pth);}}} , gsub substitutes every match in the string\n# I added a [[head]] command to just show 10 lines\n\n{{{\nls -1 *.rtf | awk -v pth=$PWD 'BEGIN {pth="V:/me_view"pth; gsub("/","\s\s",pth);} {print pth "\s\s"$1}' | head\n}}}\n{{{\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_1a.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_1b.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_2a.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_2b.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_2c.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_3.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt2_4.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt3_1.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt3_2.rtf\nV:\sme_view\svob\smydrug\spool\spool_003\sreport\sexport\spgm_saf\sitt3_3.rtf\n[/vob/mydrug/pool/pool_003/report/export/pgm_saf]\nme1@host>\n}}}\n* remove [[head]] and store the Windows paths in a [[CSV]] file\n{{{\nls -1 *.rtf | awk -v pth=$PWD 'BEGIN {pth="V:/desigla1_view"pth; gsub("/","\s\s",pth);} {print pth "\s\s"$1}' >|filelist.csv\n}}}
! Patient ids in a lab listing: question is how many pats in each lab listing? \n1. Let’s look at an example lab listing \n2. ooo the patient label is a fixed form, and first on a line: \n3. Lets start by getting list of pat ids (id is of the form {{{AAA/NNN/NNN}}} (country, centre no, pat no): \n4. {{{grep -E '[A-Za-z]+/[0-9]+/.+/' app5l1_18.lst}}} \n5. great – but it gives the whole line which is too much information. \n6. we just need the first field so add {{{awk ‘{print $1}’}}} to get just the patid \n7. great – but one line per occurrence – so hand to uniq & sort ... \n8. great - one line per id – now we can count it: using wc \n9. {{{grep -E '[A-Za-z]+/[0-9]+/.+/' app5l1_18.lst | awk '{print $1}' | sort | uniq -c | wc –l}}}\n10. We can simplify this because the awk and grep step can be done together by awk, but amazingly the original version is faster.
!! Regular expression Rules and Components\n* Regular expressions are often termed //patterns//\n!!! Rules\nThese are informal statement with caveats and exceptions ignored (eg there are ways to match across line boundaries)\n* patterns are applied line by line, therefore they cannot match across a line boundary.\n* matches to a pattern are found anywhere on the line, unless there is an [[anchor]] in the expression \na pattern \n\n\n!!! Components \n* expressions to be matched have characters, counts, ranges, alternatives and anchors\n\n# match these kinds of characters: \n## a normal character matches itself, \n## {{{.}}} matches any character (Note: this replaces the {{{*}}} character normally used for any character in filename matching)\n## \n## {{{[abc]}}} matches {{{a}}}, or {{{b}}}, or {{{c}}} \n## {{{(abc|xyz)}}} matches the three characters {{{abc}}} or the three characters {{{xyz}}}\n# repeated these times\n## match these repetitions\n## {{{*}}} any number of occurences (including none)\n## {{{+}}} 1 or more times\n## {{{ {m.n} }}} match if there are at least m, but at most n, occurences\n# in these places:\n## {{{^}}} the start of the line\n## {{{$}}} or at the end of a line\n* we can express the line scope rule as saying that a pattern is treated as {{{^.*//pattern//.*$}}} unless {{{^}}} or {{{$}}} are explicitly included in the pattern.\n# put it together:\n> {{{[_A-Za-z][_A-Za-z0-9]{0,7} }}} matches a SAS variable identifier\n> {{{.*\s.sas7b[cd]at}}} matches he file names of SAS catalogues and datasets
In the korn shell\n* {{{cd -}}} moves to your previous directory\n* you can use wildcards in a cd command\n{{{cd /vob/CLAF*/2305/rep*/*saf}}}\n* you can make substitutions in the current directory path\n{{{cd 2304 2305}}}\n*there is the DirectoryHistory script (you need to call it from your .kshrc file)\n* there is the old setstudy which creates aliases based on your default study and project \n** it needs to be adapted for GPS II directory layout - ''done'' See test version in [[alst script]]\n\n!!!! See related info in [[How do I quickly change views?]]
* Is it possible to just list the titles, without knowing how many title lines there are per output?\n* Yes, this can be done by changing with the setting of the record and field separators in awk.\n> Give a format like:\n{{{\n[]x8t2_11.lst: CLAF237A2304 (Draft)\n\n Appendix 8 Table 2-11 (Page 1 of 8)\n Laboratory normal and notable ranges (in conventional US unit) and relevant percent change criteria\n by laboratory identification number and laboratory group\n\nLaboratory identification number: 1002, Laboratory group: Hematology\n\n Relevant Relevant\n Laboratory Normal Normal Notable Notable percent percent\n test US Lower Upper Lower Upper change change\n Laboratory test abbreviation unit Sex limit limit Limit Limit increase* decrease*\n ______________________________________________________________________________________________________\n\n Basophils BAS % Male 0 2\n}}}\n* Let us consider how to split up the listing into sections.\n* using just lines will not help \n* using a blank line would work!\n> {{{ BEGIN { FS= "\sn" ; RS = ""} }}} does exactly that. \n> So \n> {{{gawk 'BEGIN { FS= "\sn" ; RS = ""} /Page 1 of/ { print FILENAME": " $0 } ' *.lst}}}\n> Gives:\n{{{\ntest.lst: Appendix 8 Table 2-11 (Page 1 of 8)\n Laboratory normal and notable ranges (in conventional US unit) and relevant percent change criteria\n by laboratory identification number and laboratory group\n}}}\n* so now to get that output into a file just add a >file.txt at the end of the command\n* why can't you use grep for this problem?\n** some greps (e.g. on AIX) have a {{{-p}}} (paragraph) option. They print all of the paragraph when a line matches, this is exactly what we want. \n----
* strategy:\n# strip out the headers and footers with grep\n# write into a temporary file\n# compare two listings via their temporary files\n\n{{{\n grep -E '^ +' x7l1_22.lst | grep -v -E '^[ ]+(Hispanic|Country|Center|Patient|__+|Appendix|Vital|Extension)' >|x7l1_22-dpage.txt\n}}}\n\n* {{{grep -E '^[ ]+' }}} selects only lines with one or more spaces at the start of the line (footnotes are normally left justified)\n* but this leaves footnotes with indents, and separator lines plus the lines we want.\n* the next grep then just takes lines that do not have the listed strings at the start of a line.\n* giving \n{{{\n BRA/0001/00001 49/F/Ca Week -2 21OCT2004/-120 120 90 80 \n Week 0 08NOV2004/-102 130 90 80 \n Week 4 09DEC2004/-71 140 90 68 \n Week 8 13JAN2005/-36 130 85 72 \n Week 12 17FEB2005/-1 130 85 76 \n Baseline 130 85 76 \n Week 16 17MAR2005/28 120 80 60 \n BRA/0002/00010 55/M/Ca Week -2 17FEB2005/-98 112 84 92 \n Week 0 03MAR2005/-84 110 80 88 \n Week 4 31MAR2005/-56 108 78 88 \n Week 8 28APR2005/-28 100 60 88 \n Week 12 25MAY2005/-1 108 72 80 \n Baseline 108 72 80 \n Week 16 23JUN2005/29 108 78 88 \n Week 24 18AUG2005/85 106 68 96 \n Week 36 10NOV2005/169 122 78 80 \n BRA/0002/00010 55/M/Ca Week 52 02MAR2006/281 114 80 92 \n Week 64 25MAY2006/365 128 88 88 \n}}}\n instead of \n{{{\nCLAF237A2329E1 FINAL\n\n Appendix 7.1 Listing 1-22 (Page 1 of 137)\n Vital signs by treatment\n Extension Safety population\n\n\nTreatment: Vilda 50mg qd (core) + combination (ext)\n\n Country/ Age/\n Center/ Sex/ Visit Visit SBP DBP PUL\n Patient Race Week date/day (mmHg) (mmHg) (bpm)\n _______________________________________________________________________________\n\n BRA/0001/00001 49/F/Ca Week -2 21OCT2004/-120 120 90 80 \n Week 0 08NOV2004/-102 130 90 80 \n Week 4 09DEC2004/-71 140 90 68 \n Week 8 13JAN2005/-36 130 85 72 \n Week 12 17FEB2005/-1 130 85 76 \n Baseline 130 85 76 \n Week 16 17MAR2005/28 120 80 60 \n\n BRA/0002/00010 55/M/Ca Week -2 17FEB2005/-98 112 84 92 \n Week 0 03MAR2005/-84 110 80 88 \n Week 4 31MAR2005/-56 108 78 88 \n Week 8 28APR2005/-28 100 60 88 \n Week 12 25MAY2005/-1 108 72 80 \n Baseline 108 72 80 \n Week 16 23JUN2005/29 108 78 88 \n Week 24 18AUG2005/85 106 68 96 \n Week 36 10NOV2005/169 122 78 80 \n\nSBP: systolic blood pressure (mmHg), DBP: diastolic blood pressure (mmHg), PUL: pulse (beats/min).\nNotable abnormality criteria are given in Post-text table 10.4-3a.\nL/H: Indicating clinically notable value/change from baseline (Low/High).\nBaseline = Extension baseline, refers to the measurement obtained at the end of the core study (i.e. Week 12, Visit 5)\nIf week 12 (visit 5) value is missing carry forward the last on-treatment observation\n(scheduled or unscheduled) from Week 8 (visit 4) onwards.\nWeek m.n denotes a repeated/unscheduled visit after Week m.\n}}}\n* the intermediate step is (first page)\n{{{\n Appendix 7.1 Listing 1-22 (Page 1 of 137)\n Vital signs by treatment\n Extension Safety population\n Country/ Age/\n Center/ Sex/ Visit Visit SBP DBP PUL\n Patient Race Week date/day (mmHg) (mmHg) (bpm)\n _______________________________________________________________________________\n BRA/0001/00001 49/F/Ca Week -2 21OCT2004/-120 120 90 80 \n Week 0 08NOV2004/-102 130 90 80 \n Week 4 09DEC2004/-71 140 90 68 \n Week 8 13JAN2005/-36 130 85 72 \n Week 12 17FEB2005/-1 130 85 76 \n Baseline 130 85 76 \n Week 16 17MAR2005/28 120 80 60 \n BRA/0002/00010 55/M/Ca Week -2 17FEB2005/-98 112 84 92 \n Week 0 03MAR2005/-84 110 80 88 \n Week 4 31MAR2005/-56 108 78 88 \n Week 8 28APR2005/-28 100 60 88 \n Week 12 25MAY2005/-1 108 72 80 \n Baseline 108 72 80 \n Week 16 23JUN2005/29 108 78 88 \n Week 24 18AUG2005/85 106 68 96 \n Week 36 10NOV2005/169 122 78 80 \n Hispanic or latino = H/L, Japanese = Jp, Native American = Na, Pacific islander = Pi, Other = Ot\n}}}\n\n!!!!! Extensions:\n* it would be nice to keep the titles of first page with footnotes once, right at the bottom of the file
\n\n\n* Can I do that on every listing to keep tabs on them?\n
/***\n''Import Tiddlers Plugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#ImportTiddlersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nWhen many people share and edit copies of the same TiddlyWiki document, the ability to quickly collect all these changes back into a single, updated document that can then be redistributed to the entire group is very important. This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. It can also be very useful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)\n\n!!!!!Inline interface (live)\n<<<\n<<importTiddlers inline>>\n<<<\n!!!!!Macro Syntax\n<<<\n{{{<<importTiddlers>>}}}\ncreates "import tiddlers" link. click to show/hide import control panel\n\n{{{<<importTiddlers inline>>}}}\ncreates import control panel directly in tiddler content\n\n{{{<<importTiddlers filter source quiet ask>>}}}\nnon-interactive 'automatic' import.\n''filter'' determines which tiddlers will be automatically selected for importing. Use one of the following keywords:\n>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler\n>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)\n>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.\n''source'' is the location of the imported document. It can be either a local document or an URL:\n>filename is any local path/file, in whatever format your system requires\n>URL is any remote web location that starts with "http://" or "https://"\n''"quiet"'' (optional)\n>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.\n''"ask"'' (optional)\n>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.\n\n''Special tag values: importReplace and importPublic''\n\nBy adding these special tags to an existing tiddler, you can precisely control whether or not to allow updates to that tiddler as well as decide which tiddlers in your document can be automatically imported by others.\n*''For maximum safety, the default action is to prevent existing tiddlers from being unintentionally overwritten by incoming tiddlers.'' To allow an existing tiddler to be overwritten by an imported tiddler, you must tag the existing tiddler with ''<<tag importReplace>>''\n*''For maximum privacy, the default action for //outgoing// tiddlers is to NOT automatically share your tiddlers with others.'' To allow a tiddler in your document to be shared via auto-import actions by others, you must tag it with ''<<tag importPublic>>''\n//Note: these tags are only applied when using the auto-import processing. When using the interactive control panel, all tiddlers in the imported document are available in the listbox, regardless of their tag values.//\n<<<\n!!!!!Interactive Usage\n<<<\nWhen used interactively, a control panel is displayed consisting of an "import source document" filename input (text field plus a ''[Browse...]'' button), a listbox of available tiddlers, a "differences only" checkbox, an "add tags" input field and four push buttons: ''[open]'', ''[select all]'', ''[import]'' and ''[close]''.\n\nPress ''[browse]'' to select a TiddlyWiki document file to import. You can also type in the path/filename or a remote document URL (starting with http://)and press ''[open]''. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//\n\nSelect one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.\n\n''select: all, new, changes, or differences''\n\nYou can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:\n>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document\n>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)\n\n''Import Tagging:''\n\nTiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.\n\n''Skip, Rename, Merge, or Replace:''\n\nWhen importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.\n\nTo bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.\n\n//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//\n\n''Import Report History''\n\nWhen tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.\n\nWhen the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.\n\nIf a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.\n\nNote: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.\n\n<<<\n!!!!!Installation\n<<<\ncopy/paste the following tiddlers into your document:\n''ImportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < ImportTiddlers > >" macro^^\n\n''Quick Installation Tip #1:''\nIf you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.\n<<<\n!!!!!Revision History\n<<<\n''2006.02.17 [2.6.0]''\nRemoved "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.\n''2006.02.16 [2.5.4]''\nadded checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.\n''2006.02.14 [2.5.3]''\nFF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()\n''2006.02.10 [2.5.2]''\ncorrected unintended global variable in importReport().\n''2006.02.05 [2.5.1]''\nmoved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2006.01.18 [2.5.0]''\nadded checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.\n''2006.01.15 [2.4.1]''\nadded "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic\n''2006.01.15 [2.4.0]''\nAdded support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.\n''2006.01.15 [2.3.2]''\nAdded "ask" parameter to confirm each tiddler before importing (for use with auto-importing)\n''2006.01.15 [2.3.1]''\nStrip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.\n''2006.01.12 [2.3.0]''\nReorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.\n''2006.01.11 [2.2.0]''\nAdded "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck\n''2006.01.09 [2.1.1]''\nWhen a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.\n''2006.01.08 [2.1.0]''\nIMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.\n''2006.01.06 [2.0.2]''\nWhen refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.\n''2006.01.04 [2.0.1]''\nWhen "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.\n''2005.12.27 [2.0.0]''\nUpdate for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n''2005.12.22 [1.3.1]''\ntweak formatting in importReport() and add 'discard report' link to output\n''2005.12.03 [1.3.0]''\nDynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)\n''2005.11.29 [1.2.1]''\nfixed formatting of 'detail info' in importReport()\n''2005.11.11 [1.2.0]''\nadded 'inline' param to embed controls in a tiddler\n''2005.11.09 [1.1.0]''\nonly load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.\n''2005.10.25 [1.0.5]''\nfixed typo in importReport() that prevented reports from being generated\n''2005.10.09 [1.0.4]''\ncombined documentation with plugin code instead of using separate tiddlers\n''2005.08.05 [1.0.3]''\nmoved CSS and HTML definitions into plugin code instead of using separate tiddlers\n''2005.07.27 [1.0.2]''\ncore update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]''\nadded parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n\n// // Version\n//{{{\nversion.extensions.importTiddlers = {major: 2, minor: 6, revision: 0, date: new Date(2006,2,17)};\n//}}}\n\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n// // IE needs explicit global scoping for functions/vars called from browser events\n//{{{\nwindow.onClickImportButton=onClickImportButton;\nwindow.loadImportFile=loadImportFile;\nwindow.refreshImportList=refreshImportList;\n//}}}\n\n// // default cookie/option values\n//{{{\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n//}}}\n\n\n// // ''MACRO DEFINITION''\n\n//{{{\nconfig.macros.importTiddlers = { };\nconfig.macros.importTiddlers = {\n label: "import tiddlers",\n prompt: "Copy tiddlers from another document",\n countMsg: "%0 tiddlers selected for import",\n src: "", // path/filename or URL of document to import\n inbound: null, // hash-indexed array of tiddlers from other document\n newTags: "", // text of tags added to imported tiddlers\n addTags: true, // add new tags to imported tiddlers\n listsize: 8, // # of lines to show in imported tiddler list\n importTags: true, // include tags from remote source document when importing a tiddler\n keepTags: true, // retain existing tags when replacing a tiddler\n index: 0, // current processing index in import list\n sort: "" // sort order for imported tiddler listbox\n};\n\nconfig.macros.importTiddlers.handler = function(place,macroName,params) {\n // LINK WITH FLOATING PANEL\n if (!params[0]) {\n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n return;\n }\n // INLINE TIDDLER CONTENT\n if (params[0]=="inline") {\n createImportPanel(place);\n document.getElementById("importPanel").style.position="static";\n document.getElementById("importPanel").style.display="block";\n return;\n }\n // NON-INTERACTIVE BATCH MODE\n switch (params[0]) {\n case 'all':\n case 'new':\n case 'changes':\n case 'updates':\n var filter=params.shift();\n break;\n default:\n var filter="updates";\n break;\n } \n if (!params[0]||!params[0].length) return; // filename is required\n config.macros.importTiddlers.src=params.shift();\n var quiet=(params[0]=="quiet"); if (quiet) params.shift();\n var ask=(params[0]=="ask"); if (ask) params.shift();\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n // load storeArea from a hidden IFRAME, then apply import rules and add/replace tiddlers\n loadImportFile(config.macros.importTiddlers.src,filter,quiet,ask,autoImportTiddlers);\n}\n//}}}\n\n// // ''READ TIDDLERS FROM ANOTHER DOCUMENT''\n\n//{{{\nfunction loadImportFile(src,filter,quiet,ask,callback) {\n if (!quiet) clearMessage();\n // LOCAL FILE\n if ((src.substr(0,7)!="http://")&&(src.substr(0,8)!="https://")) {\n if (!quiet) displayMessage("Opening local document: "+ src);\n var txt=loadFile(src);\n if(!txt) { if (!quiet) displayMessage("Could not open local document: "+src); }\n else {\n var s="<html><body>"+txt.substr(txt.indexOf('<div id="storeArea">'));\n if (!quiet) displayMessage(txt.length+" bytes in document. ("+s.length+" bytes used for tiddler storage)");\n config.macros.importTiddlers.inbound = readImportedTiddlers(convertUTF8ToUnicode(s));\n var count=config.macros.importTiddlers.inbound?config.macros.importTiddlers.inbound.length:0;\n if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);\n if (callback) callback(src,filter,quiet,ask);\n }\n return;\n }\n // REMOTE FILE\n var x; // XML object\n try {x = new XMLHttpRequest()}\n catch(e) {\n try {x = new ActiveXObject("Msxml2.XMLHTTP")}\n catch (e) {\n try {x = new ActiveXObject("Microsoft.XMLHTTP")}\n catch (e) { return }\n }\n }\n x.onreadystatechange = function() {\n if (x.readyState == 4) {\n if (x.status == 200) {\n var sa="<html><body>"+x.responseText.substr(x.responseText.indexOf('<div id="storeArea">'));\n if (!quiet) displayMessage(x.responseText.length+" bytes in document. ("+sa.length+" bytes used for tiddler storage)");\n config.macros.importTiddlers.inbound = readImportedTiddlers(sa);\n var count=config.macros.importTiddlers.inbound?config.macros.importTiddlers.inbound.length:0;\n if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);\n if (callback) callback(src,filter,quiet,ask);\n }\n else\n if (!quiet) displayMessage("Could not open remote document:"+ src+" (error="+x.status+")");\n }\n }\n if (document.location.protocol=="file:") { // UniversalBrowserRead only works from a local file context\n try {netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead')}\n catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }\n }\n if (!quiet) displayMessage("Opening remote document: "+ src);\n try {\n var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();\n x.open("GET",url,true);\n x.overrideMimeType('text/html');\n x.send(null);\n }\n catch (e) {\n if (!quiet) {\n displayMessage("Could not open remote document: "+src);\n displayMessage(e.description?e.description:e.toString());\n }\n }\n}\n\nfunction readImportedTiddlers(txt)\n{\n var importedTiddlers = [];\n // create frame\n var f=document.getElementById("importFrame");\n if (f) document.body.removeChild(f);\n f=document.createElement("iframe");\n f.id="importFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\n // get document\n var d=f.document;\n if (f.contentDocument) d=f.contentDocument; // For NS6\n else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6\n // load source into document\n d.open(); d.writeln(txt); d.close();\n // read tiddler DIVs from storeArea DOM element \n var importStore = [];\n var importStoreArea = d.getElementById("storeArea");\n if (!importStoreArea || !(importStore=importStoreArea.childNodes) || (importStore.length==0)) { return null; }\n importStoreArea.normalize();\n for(var t = 0; t < importStore.length; t++) {\n var e = importStore[t];\n var title = null;\n if(e.getAttribute)\n title = e.getAttribute("tiddler");\n if(!title && e.id && (e.id.substr(0,5) == "store"))\n title = e.id.substr(5);\n if(title && title != "") {\n var theImported = new Tiddler();\n theImported.loadFromDiv(e,title);\n importedTiddlers.push(theImported);\n }\n }\n return importedTiddlers;\n}\n//}}}\n\n// // ''NON-INTERACTIVE IMPORT''\n\n// // import all/new/changed tiddlers into store, replacing or adding tiddlers as needed\n//{{{\nfunction autoImportTiddlers(src,filter,quiet,ask)\n{\n var count=0;\n if (config.macros.importTiddlers.inbound) for (var t=0;t<config.macros.importTiddlers.inbound.length;t++) {\n var theImported = config.macros.importTiddlers.inbound[t];\n var theExisting = store.getTiddler(theImported.title);\n\n // only import tiddlers if tagged with "importPublic"\n if (theImported.tags && theImported.tags.find("importPublic")==null)\n { config.macros.importTiddlers.inbound[t].status=""; continue; } // status=="" means don't show in report\n\n // never import the "ImportedTiddlers" history from the other document...\n if (theImported.title=='ImportedTiddlers')\n { config.macros.importTiddlers.inbound[t].status=""; continue; } // status=="" means don't show in report\n\n // check existing tiddler for importReplace, or systemConfig tags\n config.macros.importTiddlers.inbound[t].status="added"; // default - add any tiddlers not filtered out\n if (store.tiddlerExists(theImported.title)) {\n config.macros.importTiddlers.inbound[t].status="replaced";\n if (!theExisting.tags||(theExisting.tags.find("importReplace")==null))\n { config.macros.importTiddlers.inbound[t].status="not imported - tiddler already exists (use importReplace to allow changes)"; continue; }\n if ((theExisting.tags.find("systemConfig")!=null)||(theImported.tags.find("systemConfig")!=null))\n config.macros.importTiddlers.inbound[t].status+=" - WARNING: an active systemConfig plugin has been added or updated";\n }\n\n // apply the all/new/changes/updates filter \n if (filter!="all") {\n if ((filter=="new") && store.tiddlerExists(theImported.title))\n { config.macros.importTiddlers.inbound[t].status="not imported - tiddler already exists"; continue; }\n if ((filter=="changes") && !store.tiddlerExists(theImported.title))\n { config.macros.importTiddlers.inbound[t].status="not imported - new tiddler"; continue; }\n if (store.tiddlerExists(theImported.title) && ((theExisting.modified.getTime()-theImported.modified.getTime())>=0))\n { config.macros.importTiddlers.inbound[t].status="not imported - tiddler is unchanged"; continue; }\n }\n\n // get confirmation if required\n if (ask && !confirm("Import "+(theExisting?"updated":"new")+" tiddler '"+theImported.title+"'\snfrom "+src))\n { config.macros.importTiddlers.inbound[t].status="skipped - cancelled by user"; continue; }\n\n // DO THE IMPORT!!\n store.addTiddler(theImported); count++;\n }\n importReport(quiet); // generate a report (as needed) and display it if not 'quiet'\n if (count) store.setDirty(true); \n // always show final message when tiddlers were actually imported\n if (!quiet||count) displayMessage("Imported "+count+" tiddler"+(count!=1?"s":"")+" from "+src);\n}\n//}}}\n\n// // ''REPORT GENERATOR''\n\n//{{{\nfunction importReport(quiet)\n{\n if (!config.macros.importTiddlers.inbound) return;\n // DEBUG alert('importReport: start');\n\n // if import was not completed, the Ask panel will still be open... close it now.\n var askpanel=document.getElementById('importAskPanel'); if (askpanel) askpanel.style.display='none'; \n // get the alphasorted list of tiddlers\n var tiddlers = config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // gather the statistics\n var count=tiddlers.length;\n var added=0; var replaced=0; var renamed=0; var skipped=0; var merged=0;\n for (var t=0; t<count; t++)\n if (tiddlers[t].status)\n {\n if (tiddlers[t].status=='added') added++;\n if (tiddlers[t].status.substr(0,7)=='skipped') skipped++;\n if (tiddlers[t].status.substr(0,6)=='rename') renamed++;\n if (tiddlers[t].status.substr(0,7)=='replace') replaced++;\n if (tiddlers[t].status.substr(0,6)=='merged') merged++;\n }\n var omitted=count-(added+replaced+renamed+skipped+merged);\n // DEBUG alert('stats done: '+count+' total, '+added+' added, '+skipped+' skipped, '+renamed+' renamed, '+replaced+' replaced, '+merged+' merged');\n // skip the report if nothing was imported\n if (added+replaced+renamed+merged==0) return;\n // skip the report if not desired by user\n if (!config.options.chkImportReport) {\n // reset status flags\n for (var t=0; t<count; t++) config.macros.importTiddlers.inbound[t].status="";\n // refresh display since tiddlers have been imported\n store.notifyAll();\n // quick message area summary report\n var msg=(added+replaced+renamed+merged)+' of '+count+' tiddler'+((count!=1)?'s':"");\n msg+=' imported from '+config.macros.importTiddlers.src.replace(/\s\s/g,'/')\n displayMessage(msg);\n return;\n }\n // create the report tiddler (if not already present)\n var tiddler = store.getTiddler('ImportedTiddlers');\n if (!tiddler) // create new report tiddler if it doesn't exist\n {\n tiddler = new Tiddler();\n tiddler.title = 'ImportedTiddlers';\n tiddler.text = "";\n }\n // format the report header\n var now = new Date();\n var newText = "";\n newText += "On "+now.toLocaleString()+", "+config.options.txtUserName+" imported tiddlers from\sn";\n newText += "[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\sn";\n newText += "<"+"<"+"<\sn";\n newText += "Out of "+count+" tiddler"+((count!=1)?"s ":" ")+" in {{{"+config.macros.importTiddlers.src.replace(/\s\s/g,'/')+"}}}:\sn";\n if (added+renamed>0)\n newText += (added+renamed)+" new tiddler"+(((added+renamed)!=1)?"s were":" was")+" added to your document.\sn";\n if (merged>0)\n newText += merged+" tiddler"+((merged!=1)?"s were":" was")+" merged with "+((merged!=1)?"":"an ")+"existing tiddler"+((merged!=1)?"s":"")+".\sn"; \n if (replaced>0)\n newText += replaced+" existing tiddler"+((replaced!=1)?"s were":" was")+" replaced.\sn"; \n if (skipped>0)\n newText += skipped+" tiddler"+((skipped!=1)?"s were":" was")+" skipped after asking.\sn"; \n if (omitted>0)\n newText += omitted+" tiddler"+((omitted!=1)?"s":"")+((omitted!=1)?" were":" was")+" not imported.\sn";\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newText += "imported tiddlers were tagged with: \s""+config.macros.importTiddlers.newTags+"\s"\sn";\n // output the tiddler detail and reset status flags\n for (var t=0; t<count; t++)\n if (tiddlers[t].status!="")\n {\n newText += "#["+"["+tiddlers[t].title+"]"+"]";\n newText += ((tiddlers[t].status!="added")?("^^\sn"+tiddlers[t].status+"^^"):"")+"\sn";\n config.macros.importTiddlers.inbound[t].status="";\n }\n newText += "<"+"<"+"<\sn";\n // output 'discard report' link\n newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n newText += "onclick=\s"story.closeTiddler('"+tiddler.title+"'); store.deleteTiddler('"+tiddler.title+"');\s" ";\n newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n tiddler.text = newText+((tiddler.text!="")?'\sn----\sn':"")+tiddler.text;\n tiddler.modifier = config.options.txtUserName;\n tiddler.modified = new Date();\n store.addTiddler(tiddler);\n if (!quiet) story.displayTiddler(null,"ImportedTiddlers",1,null,null,false);\n story.refreshTiddler("ImportedTiddlers",1,true);\n // refresh the display\n store.notifyAll();\n}\n//}}}\n\n// // ''INTERFACE DEFINITION''\n\n// // Handle link click to create/show/hide control panel\n//{{{\nfunction onClickImportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("importPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createImportPanel(parent);\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n// // Create control panel: HTML, CSS, register for notification\n//{{{\nfunction createImportPanel(place) {\n var panel=document.getElementById("importPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.importTiddlers.css,"importTiddlers");\n panel=createTiddlyElement(place,"span","importPanel",null,null)\n panel.innerHTML=config.macros.importTiddlers.html;\n store.addNotification(null,refreshImportList); // refresh listbox after every tiddler change\n refreshImportList();\n return panel;\n}\n//}}}\n\n// // CSS\n//{{{\nconfig.macros.importTiddlers.css = '\s\n#importPanel {\s\n display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\s\n padding: 0.5em; margin:0em; text-align:left; font-size: 8pt;\s\n background-color: #eee; color:#000000; \s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px; -moz-border-radius:1em;\s\n}\s\n#importPanel a { color:#009; }\s\n#importPanel input { width: 98%; margin: 1px; font-size:8pt; }\s\n#importPanel select { width: 98%; margin: 1px; font-size:8pt; }\s\n#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\s\n#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\s\n#importAskPanel { display:none; margin:0.5em 0em 0em 0em; }\s\n';\n//}}}\n\n// // HTML\n//{{{\nconfig.macros.importTiddlers.html = '\s\n<span style="float:left; padding:1px; white-space:nowrap">\s\n import from source document\s\n</span>\s\n<span style="float:right; padding:1px; white-space:nowrap">\s\n <input type=checkbox id="chkImportReport" checked style="height:1em; width:auto"\s\n onClick="config.options[\s'chkImportReport\s']=this.checked;">create a report\s\n</span>\s\n<input type="file" id="fileImportSource" size=56\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n<span style="float:left; padding:1px; white-space:nowrap">\s\n select:\s\n <a href="JavaScript:;" id="importSelectAll"\s\n onclick="onClickImportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n added </a> \s\n <a href="JavaScript:;" id="importSelectChanges"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\s\n changes </a> \s\n <a href="JavaScript:;" id="importSelectDifferences"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\s\n differences </a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</span>\s\n<span style="float:right; padding:1px; white-space:nowrap">\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n + </a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n = </a>\s\n</span>\s\n<select id="importList" size=8 multiple\s\n onchange="setTimeout(\s'refreshImportList(\s'+this.selectedIndex+\s')\s',1)">\s\n <!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\s\n</select>\s\n<input type=checkbox id="chkAddTags" checked style="height:1em; width:auto"\s\n onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \s\n<input type=checkbox id="chkImportTags" checked style="height:1em; width:auto"\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \s\n<input type=checkbox id="chkKeepTags" checked style="height:1em; width:auto"\s\n onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags\s\n<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\s\n<div align=center>\s\n <input type=button id="importOpen" class="importButton" style="width:32%" value="open"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importStart" class="importButton" style="width:32%" value="import"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importClose" class="importButton" style="width:32%" value="close"\s\n onclick="onClickImportButton(this)">\s\n</div>\s\n<div id="importAskPanel">\s\n tiddler already exists:\s\n <input type=text id="importNewTitle" size=15 autocomplete=off">\s\n <div align=center>\s\n <input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importRename" class="importButton" style="width:23%" value="rename"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\s\n onclick="onClickImportButton(this)">\s\n </div>\s\n</div>\s\n';\n//}}}\n\n// // refresh listbox\n//{{{\nfunction refreshImportList(selectedIndex)\n{\n var theList = document.getElementById("importList");\n if (!theList) return;\n // if nothing to show, reset list content and size\n if (!config.macros.importTiddlers.inbound) \n {\n while (theList.length > 0) { theList.options[0] = null; }\n theList.options[0]=new Option('please open a document...',"",false,false);\n theList.size=config.macros.importTiddlers.listsize;\n return;\n }\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading\n if (selectedIndex==1) config.macros.importTiddlers.sort='title';\n if (selectedIndex==2) config.macros.importTiddlers.sort='modified';\n if (selectedIndex==3) config.macros.importTiddlers.sort='tags';\n if (selectedIndex>3) {\n // display selected tiddler count\n for (var t=0,count=0; t < theList.options.length; t++) count+=(theList.options[t].selected&&theList.options[t].value!="")?1:0;\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n return; // no refresh needed\n }\n\n // get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)\n var tiddlers=config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n // add heading and control items to list\n var i=0;\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);\n // output the tiddler list\n switch(config.macros.importTiddlers.sort)\n {\n case "title":\n for(var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modified":\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++) {\n var tiddler = tiddlers[t];\n var theSection = tiddler.modified.toLocaleDateString();\n if (theSection != lastSection) {\n theList.options[i++] = new Option(theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n break;\n case "tags":\n var theTitles = {}; // all tiddler titles, hash indexed by tag value\n var theTags = new Array();\n for(var t=0; t<tiddlers.length; t++) {\n var title=tiddlers[t].title;\n var tags=tiddlers[t].tags;\n for(var s=0; s<tags.length; s++) {\n if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }\n theTitles[tags[s]].push(title);\n }\n }\n theTags.sort();\n for(var tagindex=0; tagindex<theTags.length; tagindex++) {\n var theTag=theTags[tagindex];\n theList.options[i++]=new Option(theTag,"",false,false);\n for(var t=0; t<theTitles[theTag].length; t++)\n theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);\n }\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;\n if (theList.size>theList.options.length) theList.size=theList.options.length;\n}\n//}}}\n\n// // Control interactions\n//{{{\nfunction onClickImportButton(which)\n{\n // DEBUG alert(which.id);\n var theList = document.getElementById('importList');\n if (!theList) return;\n var thePanel = document.getElementById('importPanel');\n var theAskPanel = document.getElementById('importAskPanel');\n var theNewTitle = document.getElementById('importNewTitle');\n var count=0;\n switch (which.id)\n {\n case 'fileImportSource':\n case 'importOpen': // load import source into hidden frame\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n if (config.macros.importTiddlers.src=="") break;\n // Load document into hidden iframe so we can read it's DOM and fill the list\n loadImportFile(config.macros.importTiddlers.src,"all",null,null,function(src,filter,quiet,ask){window.refreshImportList(0);});\n break;\n case 'importSelectAll': // select all tiddler list items (i.e., not headings)\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count++;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectNew': // select tiddlers not in current document\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importToggleFilter': // show/hide filter\n case 'importFilter': // apply filter\n alert("coming soon!");\n break;\n case 'importStart': // initiate the import processing\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.index=0;\n config.macros.importTiddlers.index=importTiddlers(0);\n importStopped();\n break;\n case 'importClose': // unload imported tiddlers or hide the import control panel\n // if imported tiddlers not loaded, close the import control panel\n if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n break;\n case 'importSkip': // don't import the tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status='skipped after asking'; // mark item as skipped\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item\n importStopped();\n break;\n case 'importRename': // change name of imported tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status = 'renamed from '+theImported.title; // mark item as renamed\n theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title\n theItem.value = theNewTitle.value; // change the listbox item text\n theItem.text = theNewTitle.value; // change the listbox item text\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importMerge': // join existing and imported tiddler content\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n var theText = theExisting.text+'\sn----\sn^^merged from: [['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\sn^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\sn'+theImported.text;\n var theDate = new Date();\n var theTags = theExisting.getTags()+' '+theImported.getTags();\n theImported.set(null,theText,null,theDate,theTags);\n theImported.status = 'merged with '+theExisting.title; // mark item as merged\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY hh:mm:ss");\n theImported.status += ' by '+theExisting.modifier;\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item\n importStopped();\n break;\n case 'importReplace': // substitute imported tiddler for existing tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n theImported.status = 'replaces '+theExisting.title; // mark item for replace\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY hh:mm:ss");\n theImported.status += ' by '+theExisting.modifier;\n theAskPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importListSmaller': // decrease current listbox size, minimum=5\n if (theList.options.length==1) break;\n theList.size-=(theList.size>5)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListLarger': // increase current listbox size, maximum=number of items in list\n if (theList.options.length==1) break;\n theList.size+=(theList.size<theList.options.length)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListMaximize': // toggle listbox size between current and maximum\n if (theList.options.length==1) break;\n theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;\n break;\n }\n}\n//}}}\n\n// // re-entrant processing for handling import with interactive collision prompting\n//{{{\nfunction importTiddlers(startIndex)\n{\n if (!config.macros.importTiddlers.inbound) return -1;\n\n var theList = document.getElementById('importList');\n if (!theList) return;\n var t;\n // if starting new import, reset import status flags\n if (startIndex==0)\n for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)\n config.macros.importTiddlers.inbound[t].status="";\n for (var i=startIndex; i<theList.options.length; i++)\n {\n // if list item is not selected or is a heading (i.e., has no value), skip it\n if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))\n continue;\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==t) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theImported.title);\n // avoid redundant import for tiddlers that are listed multiple times (when 'by tags')\n if (theImported.status=="added")\n continue;\n // don't import the "ImportedTiddlers" history from the other document...\n if (theImported.title=='ImportedTiddlers')\n continue;\n // if tiddler exists and import not marked for replace or merge, stop importing\n if (theExisting && (theImported.status.substr(0,7)!="replace") && (theImported.status.substr(0,5)!="merge"))\n return i;\n // assemble tags (remote + existing + added)\n var newTags = "";\n if (config.macros.importTiddlers.importTags)\n newTags+=theImported.getTags() // import remote tags\n if (config.macros.importTiddlers.keepTags && theExisting)\n newTags+=" "+theExisting.getTags(); // keep existing tags\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newTags+=" "+config.macros.importTiddlers.newTags; // add new tags\n theImported.set(null,null,null,null,newTags.trim());\n // set the status to 'added' (if not already set by the 'ask the user' UI)\n theImported.status=(theImported.status=="")?'added':theImported.status;\n // do the import!\n store.addTiddler(theImported);\n store.setDirty(true);\n }\n return(-1); // signals that we really finished the entire list\n}\n//}}}\n\n//{{{\nfunction importStopped()\n{\n var theList = document.getElementById('importList');\n var theNewTitle = document.getElementById('importNewTitle');\n if (!theList) return;\n if (config.macros.importTiddlers.index==-1)\n importReport(); // import finished... generate the report\n else\n {\n // DEBUG alert('import stopped at: '+config.macros.importTiddlers.index);\n // import collision... show the ask panel and set the title edit field\n document.getElementById('importAskPanel').style.display='block';\n theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;\n }\n}\n//}}}\n
On Fri Sep 15 22:17:54 2006, DaveGarbutt imported tiddlers from\n[[http://daveg.tiddlyspot.com/|http://daveg.tiddlyspot.com/]]:\n<<<\nOut of 90 tiddlers in {{{http://daveg.tiddlyspot.com/}}}:\n1 new tiddler was added to your document.\n1 existing tiddler was replaced.\n88 tiddlers were not imported.\n#[[DefaultTiddlers]]\n#[[The pipe of piece]]^^\nreplaces The pipe of piece - 9/12/2006 0:2:0 by DaveGarbutt^^\n<<<\n<html><input type="button" href="javascript:;" onclick="story.closeTiddler('ImportedTiddlers'); store.deleteTiddler('ImportedTiddlers');" value="discard report"></html>\n----\nOn Mon Sep 11 22:27:03 2006, DaveGarbutt imported tiddlers from\n[[/Users/dave/Documents/GTD stuff/DaveG_GPS.html|/Users/dave/Documents/GTD stuff/DaveG_GPS.html]]:\n<<<\nOut of 558 tiddlers in {{{/Users/dave/Documents/GTD stuff/DaveG_GPS.html}}}:\n77 new tiddlers were added to your document.\n481 tiddlers were not imported.\n#[[Can I check the actual dates in all the RTF files' footers?]]\n#[[Can I create a macro call for each dataset in a folder?]]\n#[[Can I read the scripts provided on the system so I can learn from them?]]\n#[[Can I run all the sas programs in a directory without creating a batch file or a make file?]]\n#[[CheckSASLogs]]\n#[[CheckSASlogs]]\n#[[CheckSpaceOnSASTmp]]\n#[[CleanFooterOfRTFFileBeforeComparisons]]\n#[[CommonUnixCommands]]\n#[[Count how many patients there are per treatment in the randomisation listing]]\n#[[Count the number of patients appearing in each listing, by treatment]]\n#[[DaveG]]\n#[[ExtractFirstPageOfListing]]\n#[[ExtractFirstPageOfListingForOneFileInAllStudies]]\n#[[ExtractTitlesFromAllListingsInADirectory]]\n#[[FormattingCheatSheet]]\n#[[FormattingUsingCSS]]\n#[[GPSUnixTrainingNotes]]\n#[[GPSUnixUserGuide]]\n#[[GenerateSASProgram]]\n#[[Give me a date histogram by file type!]]\n#[[How can I check the date of a SAS catalog vs its program, they are in different directories?]]\n#[[How can I check the flagging (eg of ECG values) looks OK?]]\n#[[How can I check two datasets are the same without running proc compare?]]\n#[[How can I count how many patients actually appear in a listing?]]\n#[[How can I extract individual formats across studies for comparison?]]\n#[[How can I see how much of a submitted job has been done?]]\n#[[How do I check if a file exists or not?]]\n#[[How do I find errors and warnings in my SASlog?]]\n#[[How do I get full path for output files ]]\n#[[How to change directories easily]]\n#[[I want to compare new and old listings and ignore the titles and footnotes, but how?]]\n#[[Is this RTF file Empty?]]\n#[[Korn shell]]\n#[[ListFiles Script]]\n#[[MakeSparkLineFromPingtotData]]\n#[[Pipes]]\n#[[PowerWayForUnix]]\n#[[RegularExpressions]]\n#[[ShowSASProgramStructure]]\n#[[Tutorial on Regular Expressions]]\n#[[Unix commands]]\n#[[Unix for people used to VMS]]\n#[[Unix intro & tutorial for SAS programmers]]\n#[[Unix tutorials]]\n#[[Using Unix tools]]\n#[[What should SAS programmers know about UNIX?]]\n#[[Which view has the most up-to-date lst (log, rtf...) file?]]\n#[[WhyDoesTheFilenameStartWithADot]]\n#[[WhyDontYouPutSpacesInWords]]\n#[[apply]]\n#[[at]]\n#[[awk]]\n#[[awk scripts]]\n#[[cd]]\n#[[chklogs]]\n#[[cmp]]\n#[[dfgb]]\n#[[file-name expansion]]\n#[[fold]]\n#[[formatting]]\n#[[gawk]]\n#[[grep]]\n#[[if]]\n#[[ksh]]\n#[[ksh93]]\n#[[kshrc]]\n#[[lh - an alias for a modification date histogram]]\n#[[lh - an alias to print a modification date histogram]]\n#[[nawk]]\n#[[regular expressions]]\n#[[sed]]\n#[[sed one liners collection]]\n#[[sort]]\n#[[tee]]\n#[[uniq]]\n#[[who]]\n<<<\n<html><input type="button" href="javascript:;" onclick="story.closeTiddler('ImportedTiddlers'); store.deleteTiddler('ImportedTiddlers');" value="discard report"></html>\n----\nOn Sun Sep 10 23:57:45 2006, DaveGarbutt imported tiddlers from\n[[http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPlugin|http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPlugin]]:\n<<<\nOut of 64 tiddlers in {{{http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPlugin}}}:\n9 new tiddlers were added to your document.\n1 existing tiddler was replaced.\n1 tiddler was skipped after asking.\n53 tiddlers were not imported.\n#[[CheckboxPlugin]]^^\nskipped after asking^^\n#[[Configuration]]\n#[[Configuration.SideBarTabs]]\n#[[Configuration.TabMore]]\n#[[ExtensionsControlCenter]]\n#[[ExtensionsPlugin]]^^\nreplaces ExtensionsPlugin - 7/10/2006 20:15:0 by DaveGarbutt^^\n#[[MySSStyleSheet]]\n#[[PhotoShowPlugin]]\n#[[SlideShowExample]]\n#[[SlideShowPlugin]]\n#[[SlideShowPluginDoc]]\n<<<\n<html><input type="button" href="javascript:;" onclick="story.closeTiddler('ImportedTiddlers'); store.deleteTiddler('ImportedTiddlers');" value="discard report"></html>
\n * this one-liner works pretty OK :\n{{{\ngawk 'BEGIN {RS="\s012"; FS="" } { match($0,"{[^\s\s\s\s][^}]+[{}]+"); line = substr($0,RSTART,RLENGTH); sub("^{","",line); sub("\s\s\s\s(cell|line| \s)*}","",line); if ( line ) print FILENAME": "line }' itt10_13.rtf 2>/dev/null\n}}}\n\nmight give:\n{{{\nitt10_13.rtf: Change from Baseline in QRS >= 25% and\nitt10_13.rtf: resultant QRS > 110 msec\nitt10_13.rtf: Vilda 50mg qd\nitt10_13.rtf: 77\nitt10_13.rtf: 0\nitt10_13.rtf: ( 0.0)\nitt10_13.rtf: 63\nitt10_13.rtf: 0\nitt10_13.rtf: ( 0.0)\nitt10_13.rtf: 63\nitt10_13.rtf: 0\nitt10_13.rtf: ( 0.0)\nitt10_13.rtf: Vilda 50mg bid\n}}}\n\n\n\n# It prints every non-null line having stripped out the RTF markup. \n# Actually it finds the text inside the markup, if any, and prints it all.\n* there could be other markup that does not appear if the exclusion test...\n!!!! refinement : \n* once a non-null line if found stop\n* print only the file names where there is no content\n* record each file name, if have content remove them from the array? \n{{{\n[/vob/CLAF237A/CLAF237A2329E1/report/export/pgm_saf]\n/view/gopalde1_view@ichn21 > \n gawk 'BEGIN{RS="\s012"; FS="" } {files[FILENAME]++} { match($0,"{[^\s\s\s\s][^}]+[{}]+"); line = substr($0,RSTART,RLENGTH); sub("\s\s\s\s(cell|line| \s)*}","",line); if ( line ) files[FILENAME]-- } END {print files[*]} ' itt10_13.rtf ~/empty.rtf 2>/dev/null\n}}}
* leaving aside remarks about how common Mandarin is as a global language...\n* Unix //is// somewhat technical and it was designed with the minimisation of typing as a design goal\n** users of <<wikipedia JCL>> on <<wikipedia MVS>>, <<wikipedia SINTRAN>> or <<wikipedia DCL>> on <<wikipedia VMS>> might remember why this was seen as important...\n* which together leads to a certain lack of redundancy and significance for ''every'' character you type. This can be disconcerting at first.\n* BUT, on the positive side the syntax is designed to be simple and easily parsed and this makes it simpler than human languages to understand once you 'get it'\n* do not try to learn from manuals and man[ual] pages called hlep on more modern systems, these are reference materials.\n* ''DO'' study the examples in this tutorial, try them out with copy&paste on your own data.\n* and modify them for your needs.\n\n* Most Unix books are references, but [[Unix Power Tools|http://www.oreilly.com/catalog/upt2/]] is an [[encylopaedia|http://www.unix.org.ua/orelly/unix/upt/index.htm]] of how-tos organised by application area and task.
a Unix shell, it is the default for all users on GPS\n\ntwo versions ksh88 and ksh93 the latter available on AIX after V 5\n* ksh88 is default for GPS, you ccan request to have yours changed to ksh93 if you wish\n* good articles on Shells & set up at [[here|http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PS2HD-TET1_html/uc8.html]]\n\n*Ksh93 [[FAQ|http://www.kornshell.com/doc/faq.html]]\n\nKSH93 has some extra features over the earlier version. [[docs|http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.doc/aixuser/usrosdev/ksh93.htm]]\n\n<<liveSearch ksh>>
<<list all>>
<<list untagged>>
* This script lists all the files in and below the current directory in a tiddler table format for pasting into a tiddlywiki. It will also work to read into excel if you set the separator to | (vertical bar).\n* It extracts the current directory from the name and puts it with the date in top row as spanning columns.\n* Files in subdirectories are correctly named, ie the common prefix is removed but the relative path is there.\n\n* This version now accepts wild cards if given as a (single) quoted string\n\n{{{garbuda1@ichn21>more bin/listf*}}}\n{{{\n#!/bin/ksh\n# get a list of files below current directory in tiddler table format\n# with count in first column\n# DJ Garbutt 2-Nov-2005\n# date added to top line -Feb 2006\n# ability to pass wildcard for file name added parameters with wildcard must be enclosed in single quotes\n# this uses the way $* is expanded (as a single item) as opposed to $@ \n# the find -name option needs a single parameter with wild cards not expanded\nif [[ $PWD != '/' ]] && [[ $* != '/' ]]\nthen\n case $# in \n 1 ) find $(pwd) -type f -name "$*" -print | sort | awk -v pwd=$(pwd) -v date="$(date )" '\n {if (NR == 1 ) print "|!No.|!File |! OK? |! Notes and comments |! re-done OK? |\sn|>|>|>|" pwd"|"date"|" }\n {sub(pwd,".",$1); print "| "NR"|"$1" | | | |"}' ;;\n 0 ) find $(pwd) -type f -print | sort | awk -v pwd=$(pwd) -v date="$(date )" '\n {if (NR == 1 ) print "|!No.|!File |! OK? |! Notes and comments |! re-done OK? |\sn|>|>|All files in:|" pwd"|"date"|" }\n {sub(pwd,".",$1); print "| "NR"|"$1" | | | |"}' ;;\n * ) print "\snUsage: "\n print "\st listfiles gives all files in the current directory by default. \sn\stYou can specify a wild card but the file name to match must be enclosed in single quotes" \n print "\stFor example: to get all SAS programs you must specify:\sn\st listfiles '*.sas'\sn";;\n esac \nelse \n print "\snUsage: "\n print "\sn\stYou must not start a find command from the root directory when ClearCase is installed. \sn\stExiting.\sn"\nfi \n}}}\n\n\nExample: (some rows removed)\n{{{\n|!No.|!File |! OK? |! Notes and comments |! re-done OK? |\n|>|>|>|/vob/CLAF237A/CLAF237A2329E1/report|Thu Apr 6 17:14:11 DFT 2006|\n| 1|./pgm_a/_autorun.sas | | | |\n| 2|./pgm_a/_stlpop.sas | | | |\n| 3|./pgm_a/_stlsub.sas | | | |\n| 4|./pgm_a/a_aevhgc.sas | | | |\n| 5|./pgm_a/a_ident.sas | | | |\n| 6|./pgm_a/a_rndtgp.sas | | | |\n| 7|./pgm_a/a_tgpdsc.sas | | | |\n| 8|./pgm_a/dummy_rndtgp.sas | | | |\n| 18|./pgm_a/stl3_vsn.sas | | | |\n| 19|./pgm_a/stl4_dmg.sas | | | |\n| 20|./pgm_a/stl5_tr2.sas | | | |\n| 21|./pgm_a/stl9_aev.sas | | | |\n| 22|./pgm_a/stl9_cmd.sas | | | |\n| 23|./pgm_a/stl9_cmp.sas | | | |\n| 24|./pgm_a/stl9_cnd.sas | | | |\n| 25|./pgm_a/stl9_com.sas | | | |\n| 26|./pgm_a/stl9_cve.sas | | | |\n| 27|./pgm_a/stl9_ecg.sas | | | |\n| 28|./pgm_a/stl9_hgc.sas | | | |\n| 29|./pgm_a/stl9_imn.sas | | | |\n| 40|./pgm_eff/s3t_respo.sas | | | |\n| 41|./pgm_eff/x5t_base.sas | | | |\n| 42|./pgm_saf/_autorun.sas | | | |\n| 43|./pgm_saf/s3l10_2_1.sas | | | |\n| 44|./pgm_saf/s3l10_2_2.sas | | | |\n}}}\n\n!!!! Second example: using a wildcard\n{{{\n/view/garbuda1_view@ichn21 > listfiles '*.dat' \n}}}\nGives:\n{{{\n|!No.|!File |! OK? |! Notes and comments |! re-done OK? |\n|>|>|>|/vob/CLAF237A/CLAF237A2329E1/report/pgm_saf|Thu Apr 20 19:59:24 DFT 2006|\n| 1|./x7l1_02.dat | | | |\n| 2|./x7l1_08.dat | | | |\n| 3|./x7l1_09.dat | | | |\n| 4|./x7l1_10.dat | | | |\n}}}\n* or as a table:\n\n|!No.|!File |! OK? |! Notes and comments |! re-done OK? |\n|>|>|>|/vob/CLAF237A/CLAF237A2329E1/report/pgm_saf|Thu Apr 20 19:59:24 DFT 2006|\n| 1|./x7l1_02.dat | | | |\n| 2|./x7l1_08.dat | | | |\n| 3|./x7l1_09.dat | | | |\n| 4|./x7l1_10.dat | | | |\n
GettingStarted PhUSE-Talks2006 [[Tag Cloud]][[Extensions|ExtensionsControlCentre]] Pick a strategy:\n<<QOTD "Oblique Strategies">>
* separate files each run: extract needed lines with grep NB -h option\n\n* simple version\n\n{{{\ntec_cla1@ichn21>grep -h -E 'T3520.*@' pingtot_data/* | awk -F':' 'BEGIN { printf "<<sparkline "} {printf $2 } END {print ">>\sn" }' \n}}}\n\n\n* version with added max \n** ''NB'' field separator to get the '% non-zero'\n** ''gotcha'': lines may wrap and create extra numbers - ouch\n*** could fix by printing \sr every so often from awk. (printf with a format..)\n\n{{{\ntec_cla1@ichn21>grep -h -E 'T3520.*@' pingtot_data/*27* | awk -F'[:,(]' 'BEGIN { max = 0; printf "<<sparkline "} {if ($8 > max ) max = $8 ; printf " " $8 } END {print ">> Max:" max"\sn" }'\n<<sparkline 7.6 5.6 8.4 7.8 6 5.8 1.4 2.2 6.2 6.8 2.8 4 1.6 1.4 2 1.4 1.8 0.8 0.4 1 1.2 1.6 1.8 1.6 1.6 2 4.4 2.2 2.2 1 1.4 1.8 3.4 2.2 5.2 2.6 6.4 2 0.6 2.6 3 3 1.8 4 6.6 5 7 8.2 3.6 2.4 2.4 5.2 7 9.6 8.4 3.4 3.2 3.6 9.6 11.6 10.8 5.6 2 3.4 4.4 3.6 3.6 5.8 11.2 7.4 9.2 9 8.8 7.6 6.4 7 4.6 5.6 5.6 7.4 6.4 8 4.6 5.6 8 5.2 5 1.8 7.2 10 5.4 4.6 \n 3.2 4.2 5.6 6.8 4.8 4.2 3 2.8 2.2 6.8 10 9.6 13.2 11.4 6 3.8 8.4 12.4 11.4 9.4 12.2 15.6 9 13.8 8 10.4 4.6 11.6 10.2 10.2 8.4 3 2.8 7.2 7.4 4.2 4.6 10.4 9.8 10.2 8.8 5.2 1.2 0.4 0.8 0.8 >> Max: 15.6 \n}}}\ndisplays as:\n<<sparkline 7.6 5.6 8.4 7.8 6 5.8 1.4 2.2 6.2 6.8 2.8 4 1.6 1.4 2 1.4 1.8 0.8 0.4 1 1.2 1.6 1.8 1.6 1.6 2 4.4 2.2 2.2 1 1.4 1.8 3.4 2.2 5.2 2.6 6.4 2 0.6 2.6 3 3 1.8 4 6.6 5 7 8.2 3.6 2.4 2.4 5.2 7 9.6 8.4 3.4 3.2 3.6 9.6 11.6 10.8 5.6 2 3.4 4.4 3.6 3.6 5.8 11.2 7.4 9.2 9 8.8 7.6 6.4 7 4.6 5.6 5.6 7.4 6.4 8 4.6 5.6 8 5.2 5 1.8 7.2 10 5.4 4.6 \n 3.2 4.2 5.6 6.8 4.8 4.2 3 2.8 2.2 6.8 10 9.6 13.2 11.4 6 3.8 8.4 12.4 11.4 9.4 12.2 15.6 9 13.8 8 10.4 4.6 11.6 10.2 10.2 8.4 3 2.8 7.2 7.4 4.2 4.6 10.4 9.8 10.2 8.8 5.2 1.2 0.4 0.8 0.8 >> Max: 15.6
/***\n| Name:|''monkeyTagger''|\n| Created by:|SaqImtiaz|\n| Location:|http://lewcid.googlepages.com/lewcid.html|\n| Version:|0.9 (08-Apr-2006)|\n| Requires:|~TW2.07|\n\n!About:\n*an adaptation of TagAdderMacro for monkeyGTD and tagglytagging user, but could be useful to just about anyone!\n*{{{<<monkeyTagger Project>>}}} gives a drop down list of all tags, tagged with Project.\n*The list allows toggling of tags on the current tiddler.\n*logging options for task management.\n\n!Demo:\n<<monkeyTagger Status>>\n\n!Installation:\n*Copy this tiddler to your TW with the systemConfig tag\n*either copy the following to your ViewTemplate:\n{{{<div class='tagged' macro='monkeyTagger tagToTrack'></div>}}}\nor\n*better yet, define your own toolbar class and add as many as you need to create a nice toolbar.\nEg:\n{{{<div class='toolbar' >\n<span style="padding-right:0.15em;" macro='monkeyTagger Project'></span>\n<span style="padding-right:0.15em;" macro='monkeyTagger Status'></span>\n<span macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></span>\n</div>}}}\n (adjust padding to taste)\n\n!Usage:\n\n''Syntax:''\n|>|{{{<<monkeyTagger source:"sourcetag" label:"customlabel" logging:"true/false" anchor:"anchortext" arrow:"true/false">>}}}|\n|label:|quoted text to use as a customlabel|\n|arrow:|add arrow to custom label, values are "true" or "false"|\n|anchor:|quoted text to specify where to add logging text|\n|logging:|enable logging of tags added (for task management), values are "true" or "false"|\n\nthe only parameter you ''have'' to pass is the source. When passing only one parameter, you can write either something like:\n{{{<<monkeyTagger "Project">>}}} or {{{<<monkeyTagger source:"Project">>}}} for <<monkeyTagger Project>>\nAll other parameters are optional, and can be written in any order.\n\n''Defaults:''\n|label:|default label if not specified = source tag + arrow|\n|arrow:|true |\n|logging:|false |\n|anchor:|none used by default, logging text added to end of tiddler |\n\n''Examples:''\n|custom label| {{{<<monkeyTagger source:"Project" label:"customlabel">>}}} |<<monkeyTagger source:"Project" label:"customlabel">>|\n|custom label without arrow| {{{<<monkeyTagger source:"Project" label:"customlabel" arrow:"false">>}}} |<<monkeyTagger source:"Project" label:"customlabel" arrow:"false">>|\n|logging enabled| {{{<<monkeyTagger source:"Project" logging:"true"}}} |<<monkeyTagger source:"Project" logging:"true">>|\n|logging enabled with anchor text|{{{<<monkeyTagger source:"Project" logging:"true" anchor:"anchortext"}}} |<<monkeyTagger source:"Project" logging:"true" anchor:"anchortext">>|\n\n''Tips:''\n*Make sure your anchor text doesn't occur more than once in every tiddler, as the first instance will be used.\n*I recommend using something like {{{/%StatusLog%/}}} as an invisible anchor.\n*Use a tag based template, and add monkeyTagger macro's with logging enabled to the toolbar in just your taskmanagement templates.\n\n!To Do:\n*add sorting options if requested.\n*''add exclude tag feature''!\n\n!History\n*Version 0.9: \n**changed to named parameters to make it more user friendly\n**added option to disable/enable dropdown arrow in custom labels\n**added logging option with anchor text.\n\n!CODE\n***/\n//{{{\n\nconfig.macros.monkeyTagger= {};\n//config.macros.monkeyTagger.dropdownchar = (document.all?"▼":"▾"); // the fat one is the only one that works in IE\nconfig.macros.monkeyTagger.dropdownchar = "▼"; // uncomment previous line and comment this for smaller version in FF\nconfig.macros.monkeyTagger.handler = function(place,macroName,params,wikifier,paramString,tiddler)\n{\n var nAV = paramString.parseParams('test', null, true);\n\n if ((nAV[0].arrow)&&(nAV[0].arrow[0])=='false')\n var arrow=': ';\n else\n var arrow=': '+ config.macros.monkeyTagger.dropdownchar;\n\n if((nAV[0].source)&&(nAV[0].source[0])!='.')\n {var tagToTrack = nAV[0].source[0]}\n else if(params[0]&&(params[0]!='.'))\n {var tagToTrack = params[0]}\n else\n {return false;};\n var monkeylabel = ((nAV[0].label)&&(nAV[0].label[0])!='.')?nAV[0].label[0]+arrow: tagToTrack+arrow;\n var logmode = ((nAV[0].logging)&&(nAV[0].logging[0])!='.')?nAV[0].logging[0]: "false";\n if ((nAV[0].anchor)&&(nAV[0].anchor[0])!='.')\n var anchor = nAV[0].anchor[0];\n var monkeytooltip=tagToTrack + ' :';\n\n\n if(tiddler instanceof Tiddler)\n {var title = tiddler.title;\n \n var addcomment = function(tiddler,newTag){\n var now = new Date();\n var timeFormat= 'DD/0MM/YY 0hh:0mm';\n var formattednow= now.formatString(timeFormat);\n var txt="\sn*''"+tagToTrack+"'' set as ''"+newTag+"'' on "+formattednow;\n if (anchor && anchor!='.')\n {var pos=tiddler.text.indexOf(anchor);\n if (pos!=-1) {pos=pos + anchor.length}\n else if (pos==-1) {pos=tiddler.text.length}}\n else if (!anchor){var pos = tiddler.text.length;};\n\n tiddler.set(null,tiddler.text.substr(0,pos)+txt+tiddler.text.substr(pos));\n story.refreshTiddler(tiddler.title,null,true);\n return false;\n}\n\n var ontagclick = function(e) {\n if (!e) var e = window.event;\n var tag = this.getAttribute("tag");\n var t=store.getTiddler(title);\n if (!t || !t.tags) return;\n if (t.tags.find(tag)==null)\n {t.tags.push(tag)\n if (logmode=="true"){addcomment(t,tag);}}\n else\n {t.tags.splice(t.tags.find(tag),1)};\n story.saveTiddler(title);\n story.refreshTiddler(title,null,true);\n return false;\n };\n var onclick = function(e) {\n if (!e) var e = window.event;\n var popup = Popup.create(this);\n var thistiddler=store.getTiddler(title);\n\n var taggedarray = new Array();\n var tagslabel = new Array();\n\n var taggedtiddlers = store.getTaggedTiddlers(tagToTrack);\n for (var t=0; t<taggedtiddlers.length; t++){\n var taggedtitle= ((taggedtiddlers[t]).title);\n taggedarray.push(taggedtitle);}\n\n for (var t=0; t<taggedarray.length; t++){\n var temptag = taggedarray[t];\n if (thistiddler.tags.find(temptag)==null)\n {var temptag='[ ] '+ temptag;\n tagslabel.push(temptag);}\n else\n {var temptag ='[x] '+ temptag;\n tagslabel.push(temptag);}\n }\n\n if(tagslabel.length == 0)\n createTiddlyText(createTiddlyElement(popup,"li"),('no '+tagToTrack));\n for (var t=0; t<tagslabel.length; t++)\n {\n var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tagslabel[t],("toggle '"+ ([taggedarray[t]]))+"'",ontagclick);\n theTag.setAttribute("tag",taggedarray[t]);\n }\n Popup.show(popup,false);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n};\n //createTiddlyButton(place,monkeylabel,monkeylabel,onclick);\n\nvar createdropperButton = function(place){\nvar sp = createTiddlyElement(place,"span",null,"monkeytaggerbutton");\nvar theDropDownBtn = createTiddlyButton(sp,monkeylabel,monkeytooltip,onclick);\n};\n\ncreatedropperButton(place);\n }\n};\nsetStylesheet(\n ".toolbar .monkeytaggerbutton {margin-right:0em; border:0px solid #fff; padding:0px; padding-right:0px; padding-left:0px;}\sn"+\n ".monkeytaggerbutton a.button {padding:2px; padding-left:2px; padding-right:2px;}\sn"+\n// ".monkeytaggerbutton {font-size:130%;}\sn"+\n//".monkeytaggerbutton .button {color:#703;}\sn"+\n "",\n"MonkeyTaggerStyles");\n\n//}}}
/***\n''MoveablePanelPlugin for TiddlyWiki version 2.x''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#MoveablePanelPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nAdd move, size, max/restore mouse event handling and fold/unfold, hover/scroll, and close/dock toolbar command items to any floating panel or tiddler. (see NestedSlidersPlugin for floating panel syntax/usage).\n\n!!!!!Usage\n<<<\nsyntax: {{{<<moveablePanel>>}}}\n\nexample: //using NestedSlidersPlugin 'floating panel' syntax//\n//{{{\n+++^30em^[panel]<<moveablePanel>>this is a headline for the panel\n----\n this is a moveable floating panel\n with a few lines of text\n as an example for you to try...\n //note: this line is really long so you can see what happens to word wrapping when you re-size this panel//\n===\n//}}}\nTry it: +++^30em^[panel]<<moveablePanel>>this is a headline for the panel\n----\n this is a moveable floating panel\n with a few lines of text\n as an example for you to try...\n //note: this line is really long so you can see what happens to word wrapping when you re-size this panel//\n===\n\n\nWhen the mouse is just inside the edges of the tiddler/panel, the cursor will change to a "crossed-arrows" symbol, indicating that the panel is "moveable". Grab (click-hold) the panel anywhere in the edge area and then drag the mouse to reposition the panel.\n\nTo resize the panel, hold the ''shift'' key and then grab the panel: the cursor will change to a "double-arrow" symbol. Drag a side edge of the panel to stretch horizontally or vertically, or drag a corner of the panel to stretch in both dimensions at once.\n\nDouble-clicking anywhere in the edge area of a panel will 'maximize' it to fit the current browser window.\n\nWhen the mouse is anywhere over a panel (not just near the edge), a 'toolbar menu' appears in the ''upper right corner'', with the following command items:\n*fold/unfold: ''fold'' temporarily reduces the panel height to show just one line of text. ''unfold'' restores the panel height.\n*hover/scroll: when you scroll the browser window, the moveable panels scroll with it. ''hover'' lets you keep a panel in view, while the rest of the page content moves in the window. ''scroll'' restores the default scrolling behavior for the panel. //Note: Due to browser limitations, this feature is not currently available when using Internet Explorer (v6 or lower)... sorry.//\n*close: ''close'' hides a panel from the page display. If you have moved/resized a panel, closing it restores its default position and size.\n*dock: unlike a floating panel, a moveable //tiddler// does not "float" on the page until it has actually been moved from its default position. When moving a tiddler, the ''close'' command is replaced with ''dock'', which restores the tiddler to its default //non-floating// location on the page.\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''MoveablePanelPlugin'' (tagged with <<tag systemConfig>>)\nNote: for compatibility, please also install the current version of ''NestedSlidersPlugin''.\n<<<\n!!!!!Revision History\n<<<\n''2006.05.25 [1.3.3]'' in closePanel(), use p.button.onclick() so that normal processing (updating slider button tooltip, access key, etc.) is performed\n''2006.05.11 [1.3.2]'' doc update\n''2006.05.11 [1.3.1]'' re-define all functions within moveablePanel object (eliminate global window.* function definitions (and some "leaky closures" in IE)\n''2006.05.11 [1.3.0]'' converted from inline javascript to true plugin\n''2006.05.09 [1.2.3]'' in closePanel(), set focus to sliderpanel button (if any)\n''2006.05.02 [1.2.2]'' in MoveOrSizePanel(), calculate adjustments for top and left when inside nested floating panels\n''2006.04.06 [1.2.1]'' in getPanel(), allow redefinition or bypass of "moveable" tag (changed from hard-coded "tearoff")\n''2006.03.29 [1.2.0]'' in getPanel(), require "tearoff" tag to enable floating tiddlers\n''2006.03.13 [1.1.0]'' added handling for floating tiddlers and conditional menu display\n''2006.03.06 [1.0.2]'' set move or resize cursor during mousetracking\n''2006.03.05 [1.0.1]'' use "window" vs "document.body" so mousetracking in FF doesn't drop the panel when moving too quickly\n''2006.03.04 [1.0.0]'' Initial public release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.moveablePanel= {major: 1, minor: 3, revision: 3, date: new Date(2006,5,25)};\n//}}}\n//{{{\nconfig.macros.moveablePanel= { \n handler:\n function(place,macroName,params) {\n var p=this.getPanel(place); if (!p) return;\n\n // remember original panel event handlers, size, location, border\n if (!p.saved) p.saved= {\n mouseover: p.onmouseover,\n mouseout: p.onmouseout,\n dblclick: p.ondblclick,\n top: p.style.top,\n left: p.style.left,\n width: p.style.width,\n height: p.style.height,\n position: p.style.position,\n border: p.style.border\n };\n\n // create control menu items\n var menupos=p.className=="floatingPanel"?"float:right;":"position:absolute;right:2em;top:3em;";\n var menustyle=p.className!="floatingPanel"?'style="border:1px solid #666;background:#ccc;color:#000;padding:0px .5em;"':"";\n var html='<div style="font-size:7pt;display:none;'+menupos+'"> ';\n if (p.className=="floatingPanel")\n html+='<a href="javascript:;" title="reduce panel size" '+menustyle\n +' onclick="return config.macros.moveablePanel.foldPanel(this,event)">fold</a> ';\n if (!config.browser.isIE)\n html+='<a href="javascript:;" title="keep panel in view when scrolling"'+menustyle\n +' onclick="return config.macros.moveablePanel.hoverPanel(this,event)">hover</a> ';\n if (p.className=="floatingPanel")\n html+='<a href="javascript:;" title="close panel and reset to default size and position"'+menustyle\n +' onclick="return config.macros.moveablePanel.closePanel(this,event)">close</a>';\n else\n html+='<a href="javascript:;" title="reset panel to default size and position"'+menustyle\n +' onclick="return config.macros.moveablePanel.closePanel(this,event)">dock</a>';\n html+='</div>';\n p.menudiv=createTiddlyElement(place,"span");\n p.menudiv.innerHTML=html;\n\n // init mouse handling and tooltip\n p.title="drag edge to move, shift key=stretch, double-click=max/restore";\n p.onmouseover=function(event) {\n if (this.className=="floatingPanel"||this.style.position=="absolute"||this.style.position=="fixed") {\n if (this.className!="floatingPanel") this.style.border="1px dotted #999"; // border around tiddler\n this.menudiv.firstChild.style.display="inline";\n }\n if (this.saved.mouseover) return this.saved.mouseover(event);\n };\n p.onmouseout=function(event) {\n this.menudiv.firstChild.style.display="none";\n if (this.className!="floatingPanel") this.style.border=this.saved.border;\n if (this.saved.mouseout) return this.saved.mouseout(event);\n };\n p.ondblclick=function(event) {\n if (!config.macros.moveablePanel.maximizePanel(this,event)) return false; // processed\n return this.saved.dblclick?this.saved.dblclick(event):true;\n };\n p.onmousemove=function(event) { return config.macros.moveablePanel.setCursorPanel(this,event); };\n p.onmousedown=function(event) { return config.macros.moveablePanel.moveOrSizePanel(this,event); };\n },\n\n getPanel:\n function(place) {\n var p=place; while (p && p.className!='floatingPanel') p=p.parentNode; if (p) return p; // floatingPanel\n p=story.findContainingTiddler(place); if (!p || !store.getTiddler(p.getAttribute("tiddler"))) return null; // not in a tiddler\n\n // moveable **tiddlers** in IE have LOTS of problems... DISABLED FOR NOW... but floating panels still work in IE\n if (config.browser.isIE) return null;\n\n // tiddlers tagged (e.g. with "moveable") to allow movement? use null or "" to bypass tag check\n var tag="moveable"; if (!tag || !tag.trim().length) return p;\n return (store.getTiddler(p.getAttribute("tiddler")).tags.find(tag)!=null)?p:null; // tiddler is tagged for moving\n },\n\n processed:\n function(event) {\n event.cancelBubble=true; if (event.stopPropagation) event.stopPropagation(); return false;\n },\n\n getClientWidth:\n function() {\n if(document.width!=undefined) return document.width;\n if(document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth;\n if(document.body && document.body.clientWidth) return document.body.clientWidth;\n if(window.innerWidth!=undefined) return window.innerWidth;\n return 100; // should never get here\n },\n\n closePanel:\n function(place,event) {\n if (!event) var event=window.event;\n var p=this.getPanel(place); if (!p) return true;\n if (p.hover) this.hoverPanel(p.hoverButton,event); \n if (p.folded) this.foldPanel(p.foldButton,event); \n p.maxed=false; \n p.style.top=p.saved.top;\n p.style.left=p.saved.left;\n p.style.width=p.saved.width;\n p.style.height=p.saved.height;\n p.style.position=p.saved.position;\n if (p.button) { p.button.focus(); onClickNestedSlider({target:p.button}); } // click on slider "button" (if any) to close the panel\n return this.processed(event);\n },\n\n foldPanel:\n function(place,event) {\n if (!event) var event=window.event;\n var p=this.getPanel(place); if (!p) return true;\n if (!p.foldButton) p.foldButton=place;\n if (p.folded) {\n p.style.height=p.folded_savedheight;\n p.style.overflow=p.folded_savedoverflow;\n } else {\n p.folded_savedheight=p.style.height; p.style.height="1em"; \n p.folded_savedoverflow=p.style.overflow; p.style.overflow="hidden";\n }\n p.folded=!p.folded;\n place.innerHTML=p.folded?"unfold":"fold";\n place.title=p.folded?"restore panel size":"reduce panel size";\n return this.processed(event);\n },\n\n hoverPanel:\n function(place,event) {\n if (config.browser.isIE) { return this.processed(event); } // 'fixed' position is not handled properly by IE :-(\n if (!event) var event=window.event;\n var p=this.getPanel(place); if (!p) return true;\n if (!p.hoverButton) p.hoverButton=place;\n if (p.hover)\n p.style.position=p.hover_savedposition;\n else\n { p.hover_savedposition=p.style.position; p.style.position="fixed"; }\n p.hover=!p.hover;\n place.innerHTML=p.hover?"scroll":"hover";\n place.title=p.hover?"make panel move with page when scrolling":"keep panel in view when scrolling page";\n return this.processed(event);\n },\n\n maximizePanel:\n function(place,event) {\n if (!event) var event=window.event;\n var p=this.getPanel(place); if (!p) return true;\n var left=findPosX(p); var top=findPosY(p);\n var width=p.offsetWidth; var height=p.offsetHeight;\n var x=!config.browser.isIE?event.pageX:event.clientX;\n var y=!config.browser.isIE?event.pageY:event.clientY;\n if (x<left||x>=left+width||y<top||y>=top+height) return true; // not inside panel, let mousedown bubble through\n var edgeWidth=10; var edgeHeight=10;\n var isTop=(y-top<edgeHeight);\n var isLeft=(x-left<edgeWidth);\n var isBottom=(top+height-y<edgeHeight);\n var isRight=(left+width-x<edgeWidth);\n if (!(isTop||isLeft||isBottom||isRight))\n return true; // not near an edge... let double click bubble through\n if (p.folded) this.foldPanel(p.foldButton,event); // unfold panel first (if needed)\n if (p.maxed) {\n p.style.top=p.max_savedtop;\n p.style.left=p.max_savedleft;\n p.style.width=p.max_savedwidth;\n p.style.height=p.max_savedheight;\n p.style.position=p.max_savedposition;\n } else {\n p.max_savedwidth=p.style.width;\n p.max_savedheight=p.style.height;\n p.max_savedtop=p.style.top;\n p.max_savedleft=p.style.left;\n p.max_savedposition=p.style.position;\n // IE gets the percentage stretch wrong if floating panel is inside a table\n p.style.width=config.browser.isIE?(getClientWidth()*0.95+"px"):"95%";\n p.style.height="95%";\n p.style.top=p.style.left='1em';\n p.style.position="absolute";\n }\n p.maxed=!p.maxed;\n return this.processed(event);\n },\n\n setCursorPanel:\n function(place,event) {\n if (!event) var event=window.event;\n var p=this.getPanel(place); if (!p) return true;\n var left=findPosX(p); var top=findPosY(p);\n var width=p.offsetWidth; var height=p.offsetHeight;\n var x=!config.browser.isIE?event.pageX:event.clientX;\n var y=!config.browser.isIE?event.pageY:event.clientY;\n if (x<left||x>=left+width||y<top||y>=top+height) return true; // not inside panel, let mousedown bubble through\n var edgeWidth=10; var edgeHeight=10;\n var isTop=(y-top<edgeHeight);\n var isLeft=(x-left<edgeWidth);\n var isBottom=(top+height-y<edgeHeight);\n var isRight=(left+width-x<edgeWidth);\n if (!(isTop||isLeft||isBottom||isRight))\n { p.style.cursor="auto"; if (!p.savedtitle) p.savedtitle=p.title; p.title=""; }\n else {\n p.style.cursor=!event.shiftKey?"move":((isTop?'n':(isBottom?'s':''))+(isLeft?'w':(isRight?'e':''))+'-resize');\n if (p.savedtitle) p.title=p.savedtitle;\n }\n return true; // let mouseover event bubble through\n },\n\n moveOrSizePanel:\n function(place,event) {\n if (!event) var event=window.event;\n var p=this.getPanel(place); if (!p) return true;\n var left=findPosX(p); var top=findPosY(p);\n var width=p.offsetWidth; var height=p.offsetHeight;\n var x=!config.browser.isIE?event.pageX:event.clientX;\n var y=!config.browser.isIE?event.pageY:event.clientY;\n if (x<left||x>=left+width||y<top||y>=top+height) return true; // not inside panel, let mousedown bubble through\n var edgeWidth=10; var edgeHeight=10;\n var isTop=(y-top<edgeHeight);\n var isLeft=(x-left<edgeWidth);\n var isBottom=(top+height-y<edgeHeight);\n var isRight=(left+width-x<edgeWidth);\n if (!(isTop||isLeft||isBottom||isRight)) return true; // not near an edge... let mousedown bubble through\n \n // when resizing, change cursor to show directional (NSEW) "drag arrows"\n var sizing=event.shiftKey; // remember this for use during mousemove tracking\n if (sizing) p.style.cursor=((isTop?'n':(isBottom?'s':''))+(isLeft?'w':(isRight?'e':''))+'-resize');\n \n var adjustLeft=0; var adjustTop=0;\n var pp=p.parentNode; while (pp && pp.className!="floatingPanel") pp=pp.parentNode;\n if (pp) { adjustLeft=findPosX(pp); adjustTop=findPosY(pp); }\n \n // start tracking mousemove events\n config.macros.moveablePanel.activepanel=p;\n var target=p; // if 'capture' handling not supported, track within panel only\n if (document.body.setCapture) { document.body.setCapture(); var target=document.body; } // IE\n if (window.captureEvents) { window.captureEvents(Event.MouseMove|Event.MouseUp,true); var target=window; } // moz\n if (target.onmousemove!=undefined) target.saved_mousemove=target.onmousemove;\n target.onmousemove=function(e){\n if (!e) var e=window.event;\n var p=config.macros.moveablePanel.activepanel;\n if (!p) { this.onmousemove=this.saved_mousemove?this.saved_mousemove:null; return; }\n \n // PROBLEM: p.offsetWidth and p.offsetHeight do not seem to account for padding or borders\n // WORKAROUND: subtract padding and border (in px) when calculating new panel width and height\n // TBD: get these values from p.style... convert to px as needed.\n var paddingWidth=10.6667; var paddingHeight=10.6667;\n var borderWidth=1; var borderHeight=1;\n var adjustWidth=-(paddingWidth*2+borderWidth*2);\n var adjustHeight=-(paddingHeight*2+borderHeight*2);\n \n if (p.style.position!="absolute") { // convert relative DIV to movable absolute DIV\n p.style.position="absolute";\n p.style.left=left+"px"; p.style.top=top+"px";\n p.style.width=(width+adjustWidth)+"px"; p.style.top=(height+adjustHeight)+"px";\n }\n var newX=!config.browser.isIE?e.pageX:e.clientX;\n var newY=!config.browser.isIE?e.pageY:e.clientY;\n if (sizing) { // resize panel\n // don't let panel get smaller than edge "grab" zones\n var minWidth=edgeWidth*2-adjustWidth;\n var minHeight=edgeHeight*2-adjustHeight;\n p.maxed=false; // make sure panel is not maximized\n if (p.folded) this.foldPanel(p.foldButton,e); // make sure panel is unfolded\n if (isBottom) var newHeight=height+newY-y+1;\n if (isTop) var newHeight=height-newY+y+1;\n if (isLeft) var newWidth=width-newX+x+1;\n if (isRight) var newWidth=width+newX-x+1;\n if (isLeft||isRight) p.style.width=(newWidth>minWidth?newWidth:minWidth)+adjustWidth+"px";\n if (isLeft) p.style.left=left-adjustLeft+newX-x+1+"px";\n if (isTop||isBottom) p.style.height=(newHeight>minHeight?newHeight:minHeight)+adjustHeight+"px";\n if (isTop) p.style.top=top-adjustTop+newY-y+1+"px";\n } else { // move panel\n p.style.top=top-adjustTop+newY-y+1+"px";\n p.style.left=left-adjustLeft+newX-x+1+"px";\n }\n var status=sizing?("size: "+p.style.width+","+p.style.height):("pos: "+p.style.left+","+p.style.top);\n window.status=status.replace(/(\s.[0-9]+)|px/g,""); // remove decimals and "px"\n return config.macros.moveablePanel.processed(e);\n };\n \n // stop tracking mousemove events\n if (target.onmouseup!=undefined) target.saved_mouseup=target.onmouseup;\n target.onmouseup=function(e){\n if (!e) var e=window.event;\n if (this.releaseCapture) this.releaseCapture(); // IE\n if (this.releaseEvents) this.releaseEvents(Event.MouseMove|Event.MouseUp); // moz\n this.onmousemove=this.saved_mousemove?this.saved_mousemove:null;\n this.onmouseup=this.saved_mouseup?this.saved_mouseup:null;\n config.macros.moveablePanel.activepanel=null;\n window.status="";\n return config.macros.moveablePanel.processed(e);\n };\n return this.processed(event); // mousedown handled\n }\n};\n//}}}
I could find nothing about this in the literature, so I decided to find out for myself.\nI used grep and awk to extract lists of commands from my history file:\nhere are the results: \n* I have surveyed the examples I am including in this tutorial and classified them by the techniques and operations they do\n* Which tools are most useful?\nThis depends what you need to do, but an analysis of my history file shows a distribution like this <<sparkline 69 62 52 33 9 9 5 2 1 >> for [[grep]], [[awk]], [[uniq]], [[sed]] (33), [[wc]](9), [[head]], [[fold]], and [[cut]] .\n(max count 69 for out of 1000 lines of history log, with pipes split into many lines.)\nFor first commands on a line it looks a bit different :\n<<sparkline 117 72 35 34 30 30 29 15 15 15 12 12 12 11 10 9 9 9 7 7 7 7 6 5 5 5 5>>\nfor [[awk]] (117), [[grep]], [[sas]],[[more]], [[apply]], [[alias]], [[exit]], [[aixterm]], [[mkp]], [[lcm]], [[alst]], [[vs]], [[pico]], [[ps]], [[gps_promote_ready_for_qc.sh]], [[man]], [[cp]], [[atq]], [[cd]], [[chklogs]], [[ps]], [[rcp]], [[whence]], [[lload]], [[lh|lh - an alias to print a modification date histogram]], [[history]]\n* this means that you can do a lot with just the 10 commonest commands
body {\n background: #fffaae;\n color: #000;\n}\n\n.tiddler {\n background: #fffaae;\n padding: 1em 1em 0.5em 1em;\n margin-bottom: 1em;\n border: none;\n}\n\n.viewer .button {\n background: #e4ff70;\n color: #000;\n border: none;\n}\n\n.viewer .button:hover {\n background: #228b22;\n color: #fffaae;\n}\n\n.title {\ntext-align: right;\nbackground: #e4ff70;\n -moz-border-radius: 0.5em;\npadding: 0.2em;\n}\n\n#jsMath_button {\ndisplay: none;\n}\n\n/* navigator always visible\n.pageFooterOff #navigator{\n visibility: visible;\n}*/\n\n/* remove clock \n.slideClock{\n display: none;\n}*/
/***\n''NestedSlidersPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman\nsource: http://www.TiddlyTools.com/#NestedSlidersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nQuickly make any tiddler content into an expandable 'slider' panel, without needing to create a separate tiddler to contain the slider content. Optional syntax allows ''default to open'', ''custom button label/tooltip'' and ''automatic blockquote formatting.''\n\nYou can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created. This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.\n\nFor more details, please click on a section headline below:\n++++!!!!![Configuration]>\nDebugging messages for 'lazy sliders' deferred rendering:\n<<option chkDebugLazySliderDefer>> show debugging alert when deferring slider rendering\n<<option chkDebugLazySliderRender>> show debugging alert when deferred slider is actually rendered\n===\n++++!!!!![Usage]>\nWhen installed, this plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content. Use {{{+++}}} and {{{===}}} to delimit the slider content. Additional optional syntax elements let you specify\n*default to open\n*cookiename\n*heading level\n*floater (with optional CSS width value)\n*mouse auto rollover\n*custom class/label/tooltip/accesskey\n*automatic blockquote\n*deferred rendering\nThe complete syntax, using all options, is:\n//{{{\n++++(cookiename)!!!!!^width^*{{class{[label=key|tooltip]}}}>...\ncontent goes here\n===\n//}}}\nwhere:\n* {{{+++}}} (or {{{++++}}}) and {{{===}}}^^\nmarks the start and end of the slider definition, respectively. When the extra {{{+}}} is used, the slider will be open when initially displayed.^^\n* {{{(cookiename)}}}^^\nsaves the slider opened/closed state, and restores this state whenever the slider is re-rendered.^^\n* {{{!}}} through {{{!!!!!}}}^^\ndisplays the slider label using a formatted headline (Hn) style instead of a button/link style^^\n* {{{^width^}}} (or just {{{^}}})^^\nmakes the slider 'float' on top of other content rather than shifting that content downward. 'width' must be a valid CSS value (e.g., "30em", "180px", "50%", etc.). If omitted, the default width is "auto" (i.e., fit to content)^^\n* {{{*}}}^^\nautomatically opens/closes slider on "rollover" as well as when clicked^^\n* {{{{{class{[label=key|tooltip]}}}}}}^^\nuses custom label/tooltip/accesskey. {{{{{class{...}}}}}}, {{{=key}}} and {{{|tooltip}}} are optional. 'class' is any valid CSS class name, used to style the slider label text. 'key' must be a ''single letter only''. Default labels/tootips are: ">" (more) and "<" (less), with no default access key assignment.^^\n* {{{">"}}} //(without the quotes)//^^\nautomatically adds blockquote formatting to slider content^^\n* {{{"..."}}} //(without the quotes)//^^\ndefers rendering of closed sliders until the first time they are opened. //Note: deferred rendering may produce unexpected results in some cases. Use with care.//^^\n\n//Note: to make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the {{{+++}}} 'start slider' or preceding the {{{===}}} 'end slider' sequence are automatically supressed so that excess whitespace is eliminated from the output.//\n===\n++++!!!!![Examples]>\nsimple in-line slider: \n{{{\n+++\n content\n===\n}}}\n+++\n content\n===\n----\nuse a custom label and tooltip: \n{{{\n+++[label|tooltip]\n content\n===\n}}}\n+++[label|tooltip]\n content\n===\n----\ncontent automatically blockquoted: \n{{{\n+++>\n content\n===\n}}}\n+++>\n content\n===\n----\nall options combined //(default open, cookie, heading, sized floater, rollover, class, label/tooltip/key, blockquoted, deferred)//\n{{{\n++++(testcookie)!!!^30em^*{{big{[label=Z|click or press Alt-Z to open]}}}>...\n content\n===\n}}}\n++++(testcookie)!!!^30em^*{{big{[label=Z|click or press Alt-Z to open]}}}>...\n content\n===\n----\ncomplex nesting example:\n{{{\n+++^[get info...=I|click for information or press Alt-I]\n put some general information here, plus a floating slider with more specific info:\n +++^10em^[view details...|click for details]\n put some detail here, which could include a rollover with a +++^25em^*[glossary definition]explaining technical terms===\n ===\n===\n}}}\n+++^[get info...=I|click for information or press Alt-I]\n put some general information here, plus a floating slider with more specific info:\n +++^10em^[view details...|click for details]\n put some detail here, which could include a rollover with a +++^25em^*[glossary definition]explaining technical terms===\n ===\n===\n===\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''NestedSlidersPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.07.28 - 2.0.0'' added custom class syntax around label/tip/key syntax: {{{{{classname{[label=key|tip]}}}}}}\n''2006.07.25 - 1.9.3'' when parsing slider, save default open/closed state in button element, then in onClickNestedSlider(), if slider state matches saved default, instead of saving cookie, delete it. Significantly reduces the 'cookie overhead' when default slider states are used.\n''2006.06.29 - 1.9.2'' in onClickNestedSlider(), when setting focus to first control, skip over type="hidden"\n''2006.06.22 - 1.9.1'' added panel.defaultPanelWidth to save requested panel width, even after resizing has changed the style value\n''2006.05.11 - 1.9.0'' added optional '^width^' syntax for floating sliders and '=key' syntax for setting an access key on a slider label\n''2006.05.09 - 1.8.0'' in onClickNestedSlider(), when showing panel, set focus to first child input/textarea/select element\n''2006.04.24 - 1.7.8'' in adjustSliderPos(), if floating panel is contained inside another floating panel, subtract offset of containing panel to find correct position\n''2006.02.16 - 1.7.7'' corrected deferred rendering to account for use-case where show/hide state is tracked in a cookie\n''2006.02.15 - 1.7.6'' in adjustSliderPos(), ensure that floating panel is positioned completely within the browser window (i.e., does not go beyond the right edge of the browser window)\n''2006.02.04 - 1.7.5'' add 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals\n''2006.01.18 - 1.7.4'' only define adjustSliderPos() function if it has not already been provided by another plugin. This lets other plugins 'hijack' the function even when they are loaded first.\n''2006.01.16 - 1.7.3'' added adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels. While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels. Short-term workaround is to only adjust the position for 'top-level' floaters.\n''2006.01.16 - 1.7.2'' added button property to slider panel elements so that slider panel can tell which button it belongs to. Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends\n''2006.01.14 - 1.7.1'' added optional "^" syntax for floating panels. Defines new CSS class, ".floatingPanel", as an alternative for standard in-line ".sliderPanel" styles.\n''2006.01.14 - 1.7.0'' added optional "*" syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)\n''2006.01.03 - 1.6.2'' When using optional "!" heading style, instead of creating a clickable "Hn" element, create an "A" element inside the "Hn" element. (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)\n''2005.12.15 - 1.6.1'' added optional "..." syntax to invoke deferred ('lazy') rendering for initially hidden sliders\nremoved checkbox option for 'global' application of lazy sliders\n''2005.11.25 - 1.6.0'' added optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)\n''2005.11.21 - 1.5.1'' revised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability. Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.\n''2005.11.20 - 1.5.0'' added (cookiename) syntax for optional tracking and restoring of slider open/close state\n''2005.11.11 - 1.4.0'' added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style\n''2005.11.07 - 1.3.0'' removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other\nformatting extensions) and simplified/improved regular expressions to trim multiple excess newlines\n''2005.11.05 - 1.2.1'' changed name to NestedSlidersPlugin\nmore documentation\n''2005.11.04 - 1.2.0'' added alternative character-mode syntax {{{(((}}} and {{{)))}}}\ntweaked "eat newlines" logic for line-mode {{{+++}}} and {{{===}}} syntax\n''2005.11.03 - 1.1.1'' fixed toggling of default tooltips ("more..." and "less...") when a non-default button label is used\ncode cleanup, added documentation\n''2005.11.03 - 1.1.0'' changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}\nchanged name to EasySlidersPlugin\n''2005.11.03 - 1.0.0'' initial public release\n<<<\n!!!!!Credits\n<<<\nThis feature was implemented by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]] with initial research and suggestions from RodneyGomes, GeoffSlocock, and PaulPetterson.\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.nestedSliders = {major: 2, minor: 0, revision: 0, date: new Date(2006,7,28)};\n//}}}\n\n//{{{\n// options for deferred rendering of sliders that are not initially displayed\nif (config.options.chkDebugLazySliderDefer==undefined) config.options.chkDebugLazySliderDefer=false;\nif (config.options.chkDebugLazySliderRender==undefined) config.options.chkDebugLazySliderRender=false;\n\n// default styles for 'floating' class\nsetStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \s\n background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");\n//}}}\n\n//{{{\nconfig.formatters.push( {\n name: "nestedSliders",\n match: "\s\sn?\s\s+{3}",\n terminator: "\s\ss*\s\s={3}\s\sn?",\n lookahead: "\s\sn?\s\s+{3}(\s\s+)?(\s\s([^\s\s)]*\s\s))?(\s\s!*)?(\s\s^(?:[^\s\s^\s\s*\s\s[\s\s>]*\s\s^)?)?(\s\s*)?(?:\s\s{\s\s{([\s\sw]+[\s\ss\s\sw]*)\s\s{)?(\s\s[[^\s\s]]*\s\s])?(?:\s\s}{3})?(\s\s>)?(\s\s.\s\s.\s\s.)?\s\ss*",\n handler: function(w)\n {\n // defopen=lookaheadMatch[1]\n // cookiename=lookaheadMatch[2]\n // header=lookaheadMatch[3]\n // panelwidth=lookaheadMatch[4]\n // rollover=lookaheadMatch[5]\n // class=lookaheadMatch[6]\n // label=lookaheadMatch[7]\n // blockquote=lookaheadMatch[8]\n // deferred=lookaheadMatch[9]\n\n lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n // location for rendering button and panel\n var place=w.output;\n\n // default to closed, no cookie, no accesskey\n var show="none"; var title=">"; var tooltip="show"; var cookie=""; var key="";\n\n // extra "+", default to open\n if (lookaheadMatch[1])\n { show="block"; title="<"; tooltip="hide"; }\n\n // cookie, use saved open/closed state\n if (lookaheadMatch[2]) {\n cookie=lookaheadMatch[2].trim().slice(1,-1);\n cookie="chkSlider"+cookie;\n if (config.options[cookie]==undefined)\n { config.options[cookie] = (show=="block") }\n if (config.options[cookie])\n { show="block"; title="<"; tooltip="hide"; }\n else\n { show="none"; title=">"; tooltip="show"; }\n }\n\n // parse custom label/tooltip/accesskey: [label=X|tooltip]\n if (lookaheadMatch[7]) {\n title = lookaheadMatch[7].trim().slice(1,-1);\n var pos=title.indexOf("|");\n if (pos!=-1) { tooltip = title.substr(pos+1,title.length); title=title.substr(0,pos); }\n if (title.substr(title.length-2,1)=="=") { key=title.substr(title.length-1,1); title=title.slice(0,-2); }\n if (pos==-1) tooltip += " "+title; // default tooltip: "show/hide <title>"\n }\n\n // create the button\n if (lookaheadMatch[3]) { // use "Hn" header format instead of button/link\n var lvl=(lookaheadMatch[3].length>6)?6:lookaheadMatch[3].length;\n var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,lookaheadMatch[6],title);\n btn.onclick=onClickNestedSlider;\n btn.setAttribute("href","javascript:;");\n btn.setAttribute("title",tooltip);\n }\n else\n var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,lookaheadMatch[6]);\n\n // set extra button attributes\n btn.sliderCookie = cookie; // save the cookiename (if any) in the button object\n btn.defOpen=lookaheadMatch[1]!=null; // save default open/closed state (boolean)\n btn.keyparam=key; // save the access key letter ("" if none)\n if (key.length) {\n btn.setAttribute("accessKey",key); // init access key\n btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus\n }\n\n // "non-click" MouseOver open/close slider\n if (lookaheadMatch[5]) btn.onmouseover=onClickNestedSlider;\n\n // create slider panel\n var panelClass=lookaheadMatch[4]?"floatingPanel":"sliderPanel";\n var panel=createTiddlyElement(place,"div",null,panelClass,null);\n panel.button = btn; // so the slider panel know which button it belongs to\n panel.defaultPanelWidth=(lookaheadMatch[4] && lookaheadMatch[4].length>2)?lookaheadMatch[4].slice(1,-1):""; // save requested panel size\n btn.sliderPanel=panel;\n panel.style.display = show;\n panel.style.width=panel.defaultPanelWidth;\n\n // render slider (or defer until shown) \n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n if ((show=="block")||!lookaheadMatch[9]) {\n // render now if panel is supposed to be shown or NOT deferred rendering\n w.subWikify(lookaheadMatch[8]?createTiddlyElement(panel,"blockquote"):panel,this.terminator);\n // align slider/floater position with button\n adjustSliderPos(place,btn,panel,panelClass);\n }\n else {\n var src = w.source.substr(w.nextMatch);\n var endpos=findMatchingDelimiter(src,"+++","===");\n panel.setAttribute("raw",src.substr(0,endpos));\n panel.setAttribute("blockquote",lookaheadMatch[8]?"true":"false");\n panel.setAttribute("rendered","false");\n w.nextMatch += endpos+3;\n if (w.source.substr(w.nextMatch,1)=="\sn") w.nextMatch++;\n if (config.options.chkDebugLazySliderDefer) alert("deferred '"+title+"':\sn\sn"+panel.getAttribute("raw"));\n }\n }\n }\n }\n)\n\n// TBD: ignore 'quoted' delimiters (e.g., "{{{+++foo===}}}" isn't really a slider)\nfunction findMatchingDelimiter(src,starttext,endtext) {\n var startpos = 0;\n var endpos = src.indexOf(endtext);\n // check for nested delimiters\n while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {\n // count number of nested 'starts'\n var startcount=0;\n var temp = src.substring(startpos,endpos-1);\n var pos=temp.indexOf(starttext);\n while (pos!=-1) { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }\n // set up to check for additional 'starts' after adjusting endpos\n startpos=endpos+endtext.length;\n // find endpos for corresponding number of matching 'ends'\n while (startcount && endpos!=-1) {\n endpos = src.indexOf(endtext,endpos+endtext.length);\n startcount--;\n }\n }\n return (endpos==-1)?src.length:endpos;\n}\n//}}}\n\n//{{{\nwindow.onClickNestedSlider=function(e)\n{\n if (!e) var e = window.event;\n var theTarget = resolveTarget(e);\n var theLabel = theTarget.firstChild.data;\n var theSlider = theTarget.sliderPanel\n var isOpen = theSlider.style.display!="none";\n // if using default button labels, toggle labels\n if (theLabel==">") theTarget.firstChild.data = "<";\n else if (theLabel=="<") theTarget.firstChild.data = ">";\n // if using default tooltips, toggle tooltips\n if (theTarget.getAttribute("title")=="show")\n theTarget.setAttribute("title","hide");\n else if (theTarget.getAttribute("title")=="hide")\n theTarget.setAttribute("title","show");\n if (theTarget.getAttribute("title")=="show "+theLabel)\n theTarget.setAttribute("title","hide "+theLabel);\n else if (theTarget.getAttribute("title")=="hide "+theLabel)\n theTarget.setAttribute("title","show "+theLabel);\n // deferred rendering (if needed)\n if (theSlider.getAttribute("rendered")=="false") {\n if (config.options.chkDebugLazySliderRender)\n alert("rendering '"+theLabel+"':\sn\sn"+theSlider.getAttribute("raw"));\n var place=theSlider;\n if (theSlider.getAttribute("blockquote")=="true")\n place=createTiddlyElement(place,"blockquote");\n wikify(theSlider.getAttribute("raw"),place);\n theSlider.setAttribute("rendered","true");\n }\n // show/hide the slider\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n theSlider.style.display = isOpen ? "none" : "block";\n // reset to default width (might have been changed via plugin code)\n theSlider.style.width=theSlider.defaultPanelWidth;\n // align slider/floater position with target button\n if (!isOpen) adjustSliderPos(theSlider.parentNode,theTarget,theSlider,theSlider.className);\n // if showing panel, set focus to first 'focus-able' element in panel\n if (theSlider.style.display!="none") {\n var ctrls=theSlider.getElementsByTagName("*");\n for (var c=0; c<ctrls.length; c++) {\n var t=ctrls[c].tagName.toLowerCase();\n if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")\n { ctrls[c].focus(); break; }\n }\n }\n if (this.sliderCookie && this.sliderCookie.length) {\n config.options[this.sliderCookie]=!isOpen;\n if (config.options[this.sliderCookie]!=this.defOpen)\n saveOptionCookie(this.sliderCookie);\n else { // remove cookie if slider is in default display state\n var ex=new Date(); ex.setTime(ex.getTime()-1000);\n document.cookie = this.sliderCookie+"=novalue; path=/; expires="+ex.toGMTString();\n }\n }\n return false;\n}\n\n// hijack animation handler 'stop' handler so overflow is visible after animation has completed\nSlider.prototype.coreStop = Slider.prototype.stop;\nSlider.prototype.stop = function() { this.coreStop(); this.element.style.overflow = "visible"; }\n\n// adjust panel position based on button position\nif (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel,panelClass) {\n if (panelClass=="floatingPanel") {\n var left=0;\n var top=btn.offsetHeight; \n if (place.style.position!="relative") {\n var left=findPosX(btn);\n var top=findPosY(btn)+btn.offsetHeight;\n var p=place; while (p && p.className!='floatingPanel') p=p.parentNode;\n if (p) { left-=findPosX(p); top-=findPosY(p); }\n }\n if (left+panel.offsetWidth > getWindowWidth()) left=getWindowWidth()-panel.offsetWidth-10;\n panel.style.left=left+"px"; panel.style.top=top+"px";\n }\n}\n\nfunction getWindowWidth() {\n if(document.width!=undefined)\n return document.width; // moz (FF)\n if(document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) )\n return document.documentElement.clientWidth; // IE6\n if(document.body && ( document.body.clientWidth || document.body.clientHeight ) )\n return document.body.clientWidth; // IE4\n if(window.innerWidth!=undefined)\n return window.innerWidth; // IE - general\n return 0; // unknown\n}\n//}}}
/***\n''NewDocumentPlugin for TiddlyWiki version 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#NewDocumentPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nQuickly create new TiddlyWiki documents from your existing document, with just one click! Use the {{{<<newDocument>>}}} macro to place a "new document" link into your sidebar/mainmenu/any tiddler (wherever you like). Select this command to automatically create a "new.html" document containing a specific set of tagged tiddlers. Optional parameters let you specify an alternate path/filename for the new file, or different tags to match. You can also indicate "ask" for either parameter, which will trigger a prompt for input when the command is selected.\n\n!!!!!Usage\n<<<\n{{{<<newDocument label:text filename tag tag tag...>>}}}\n{{{<<newDocument label:text filename all>>}}}\n{{{<<newDocument label:text filename snap>>}}}\n where:\n* ''label:text'' defines //optional// alternative link text (replaces default "new document" display)\n* ''filename'' is any local path-and-filename. If no parameters are provided, the default is to create the file "new.html" in the current directory. If a filename is provided without a path (i.e., there is no "/" in the input), then the current directory is also assumed. Otherwise, this parameter is expected to contain the complete path and filename needed to write the file to your local hard disk. If ''ask'' is used in place of the filename parameter then, when the command link is selected, a message box will be automatically displayed so you can select/enter the path and filename.\n* ''tag tag tag...'' is a list of one or more space-separated tags (use quotes or {{{[[]]}}} around tags that contain spaces). The new document will include all tiddlers that match at least one of the tags in the list. The default is to include tiddlers tagged with <<tag includeNew>>. The special value ''all'' may be used to match every tiddler (even those without tags). If ''ask'' is used in place of the tags then, when the command link is selected, a message box will be automatically displayed so you can enter the desired tags at that time.\n* When the keyword ''snap'' is used in place of tags to match, the plugin generates a file containing the //rendered// CSS-and-HTML for all tiddlers currently displayed in the document.\n\nNote: as of version 1.4.0 of this plugin, support for selecting tiddlers by using tag *expressions* has been replaced with simpler, more efficient "containsAny()" logic. To create new ~TiddlyWiki documents that contain only those tiddlers selected with advanced AND/OR/NOT Boolean expressions, you can use the filtering features provided by the ExportTiddlersPlugin (see www.TiddlyTools.com/#ExportTiddlersPlugin).\n<<<\n!!!!!Examples:\n<<<\n{{{<<newDocument>>}}}\nequivalent to {{{<<newDocument new.htm includeNew systemTiddlers>>}}}\ncreates default "new.html" containing tiddlers tagged with either<<tag includeNew>>or<<tag systemTiddlers>>\ntry it: <<newDocument>>\n\n{{{<<newDocument empty.html systemTiddlers>>}}}\ncreates "empty.html" containing only tiddlers tagged with<<tag systemTiddlers>>\n//(reproduces old-style (pre 2.0.2) empty file)//\ntry it: <<newDocument empty.html systemTiddlers>>\n\n{{{<<newDocument "label:create Import/Export starter" ask importexport>>}}}\nsave importexport tiddlers to a new file, prompts for path/file\ntry it: <<newDocument "label:create Import/Export starter" ask importexport>>\n\n{{{<<newDocument ask ask>>}}}\nprompts for path/file, prompts for tags to match\ntry it: <<newDocument ask ask>>\n\n{{{<<newDocument ask all>>}}}\nsave all current TiddlyWiki contents to a new file, prompts for path/file\ntry it: <<newDocument ask all>>\n\n{{{<<newDocument ask snap>>}}}\ngenerates snapshot of currently displayed document, prompts for path/file\ntry it: <<newDocument ask snap>>\n\n<<<\n!!!!!Installation\n<<<\nImport (or copy/paste) the following tiddlers into your document:\n''NewDocumentPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.08.03 [1.4.3]'' in promptForFilename(), for IE (WinXP only), added handling for UserAccounts.CommonDialog\n''2006.07.29 [1.4.2]'' in onClickNewDocument(), okmsg display is now linked to newly created file\n''2006.07.24 [1.4.1]'' in promptForFilename(), check for nsIFilePicker.returnCancel to allow nsIFilePicker.returnOK **OR** nsIFilePicker.returnReplace to be processed.\n''2006.05.23 [1.4.0]'' due to very poor performance, support for tag *expressions* has been removed, in favor of a simpler "containsAny()" scan for tags.\n''2006.04.09 [1.3.6]'' in onClickNewDocument, added call to convertUnicodeToUTF8() to better handle international characters.\n''2006.03.15 [1.3.5]'' added nsIFilePicker() handler for selecting filename in moz-based browsers. IE and other non-moz browsers still use simple prompt() dialog\n''2006.03.15 [1.3.0]'' added "label:text" param for custom link text. added special "all" filter parameter for "save as..." handling (writes all tiddlers to output file)\n''2006.03.09 [1.2.0]'' added special "snap" filter parameter to generate and write "snapshot" files containing static HTML+CSS for currently rendered document.\n''2006.02.24 [1.1.2]'' Fix incompatiblity with TW 2.0.5 by removing custom definition of getLocalPath() (which is now part of TW core)\n''2006.02.03 [1.1.1]'' concatentate 'extra' params so that tag expressions don't have to be quoted. moved all text to 'formatted' string definitions for easier translation.\n''2006.02.03 [1.1.0]'' added support for tag EXPRESSIONS. plus improved documentation and code cleanup\n''2006.02.03 [1.0.0]'' Created.\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.newDocument = {major: 1, minor: 4, revision: 3, date: new Date(2006,8,3)};\n\nconfig.macros.newDocument = {\n newlabel: "new document",\n newprompt: "Create a new TiddlyWiki 'starter' document",\n newdefault: "new.html",\n allparam: "all",\n saveaslabel: "save as...",\n saveasprompt: "Save current TiddlyWiki to a different file",\n snapparam: "snap",\n snaplabel: "create a snapshot",\n snapprompt: "Create a 'snapshot' of the current TiddlyWiki display",\n snapdefault: "snapshot.html",\n askparam: "ask",\n labelparam: "label:",\n fileprompt: "Please enter a filename",\n filter: "includeNew",\n filterprompt: "Match one or more tags:\sn(space-separated, use [[...]] around tags containing spaces)",\n filtererrmsg: "Error in tag filter '%0'",\n snapmsg: "Document snapshot written to %1",\n okmsg: "%0 tiddlers written to %1",\n failmsg: "An error occurred while creating %0"\n};\n\nconfig.macros.newDocument.handler = function(place,macroName,params) {\n\n var path=getLocalPath(document.location.href);\n var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\s\s"); \n if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash\n\n if (params[0] && params[0].substr(0,config.macros.newDocument.labelparam.length)==config.macros.newDocument.labelparam)\n var label=params.shift().substr(config.macros.newDocument.labelparam.length)\n var filename=params.shift(); if (!filename) filename=config.macros.newDocument.newdefault;\n if (params[0]==config.macros.newDocument.snapparam) {\n if (!label) var label=config.macros.newDocument.snaplabel;\n var prompt=config.macros.newDocument.snapprompt;\n var defaultfile=config.macros.newDocument.snapdefault;\n }\n if (params[0]==config.macros.newDocument.allparam) {\n if (!label) var label=config.macros.newDocument.saveaslabel;\n var prompt=config.macros.newDocument.saveasprompt;\n var defaultfile=getLocalPath(document.location.href);\n var slashpos=defaultfile.lastIndexOf("/"); if (slashpos==-1) slashpos=defaultfile.lastIndexOf("\s\s");\n if (slashpos!=-1) defaultfile=defaultfile.substr(slashpos+1); // get filename only\n }\n if (!prompt) var prompt=config.macros.newDocument.newprompt;\n if (!label) var label=config.macros.newDocument.newlabel;\n if (!defaultfile) var defaultfile=config.macros.newDocument.newdefault;\n\n var btn=createTiddlyButton(place,label,prompt,onClickNewDocument);\n btn.path=path;\n btn.file=filename;\n btn.defaultfile=defaultfile;\n btn.filter=params.length?params:[config.macros.newDocument.filter]; \n}\n\n// IE needs explicit global scoping for functions called by browser events\nwindow.onClickNewDocument=function(e)\n{\n if (!e) var e = window.event; var btn=resolveTarget(e);\n\n // assemble document content, write file, report result\n var okmsg=config.macros.newDocument.okmsg;\n var failmsg=config.macros.newDocument.failmsg;\n var count=0;\n var out="";\n if (btn.filter[0]==config.macros.newDocument.snapparam) { // HTML+CSS snapshot\n var styles=document.getElementsByTagName("style");\n out+="<html>\sn<head>\sn<style>\sn";\n for(var i=0; i < styles.length; i++)\n out +="/* stylesheet from tiddler:"+styles[i].getAttribute("id")+" */\sn"+styles[i].innerHTML+"\sn\sn";\n out+="</style>\sn</head>\sn<body>\sn\sn"+document.getElementById("contentWrapper").innerHTML+"\sn\sn</body>\sn</html>";\n okmsg=config.macros.newDocument.snapmsg;\n } else { // TW starter document\n // get the TiddlyWiki core code source\n var sourcefile=getLocalPath(document.location.href);\n var source=loadFile(sourcefile);\n if(source==null) { alert(config.messages.cantSaveError); return null; }\n var posOpeningDiv=source.indexOf(startSaveArea);\n var posClosingDiv=source.lastIndexOf(endSaveArea);\n if((posOpeningDiv==-1)||(posClosingDiv==-1)) { alert(config.messages.invalidFileError.format([sourcefile])); return; }\n // get the matching tiddler divs\n var match=btn.filter;\n if (match[0]==config.macros.newDocument.askparam) {\n var newfilt=prompt(config.macros.newDocument.filterprompt,config.macros.newDocument.filter);\n if (!newfilt) return; // cancelled by user\n match=newfilt.readMacroParams();\n }\n var storeAreaDivs=[];\n var tiddlers=store.getTiddlers('title');\n for (var i=0; i<tiddlers.length; i++)\n if (match[0]==config.macros.newDocument.allparam || (tiddlers[i].tags && tiddlers[i].tags.containsAny(match)) )\n storeAreaDivs.push(tiddlers[i].saveToDiv());\n out+=source.substr(0,posOpeningDiv+startSaveArea.length);\n out+=convertUnicodeToUTF8(storeAreaDivs.join("\sn"))+"\sn\st\st";\n out+=source.substr(posClosingDiv);\n count=storeAreaDivs.length;\n }\n // get output path/filename\n var filename=btn.file;\n if (filename==config.macros.newDocument.askparam)\n filename=promptForFilename(config.macros.newDocument.fileprompt,btn.path,btn.defaultfile);\n if (!filename) return; // cancelled by user\n // if specified file does not include a path, assemble fully qualified path and filename\n var slashpos=filename.lastIndexOf("/"); if (slashpos==-1) slashpos=filename.lastIndexOf("\s\s");\n if (slashpos==-1) filename=btn.path+filename;\n var ok=saveFile(filename,out);\n var msg=ok?okmsg.format([count,filename]):failmsg.format([filename]);\n var link=ok?"file:///"+filename.replace(regexpBackSlash,'/'):""; // change local path to link text\n clearMessage(); displayMessage(msg,link);\n e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);\n}\n//}}}\n\n//{{{\nfunction promptForFilename(msg,path,file)\n{\n if(window.Components) { // moz\n try {\n netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');\n var nsIFilePicker = window.Components.interfaces.nsIFilePicker;\n var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);\n picker.init(window, msg, nsIFilePicker.modeSave);\n var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);\n thispath.initWithPath(path);\n picker.displayDirectory=thispath;\n picker.defaultExtension='html';\n picker.defaultString=file;\n picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);\n if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;\n }\n catch(e) { alert('error during local file access: '+e.toString()) }\n }\n else { // IE\n try { // XP only\n var s = new ActiveXObject('UserAccounts.CommonDialog');\n s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';\n s.FilterIndex=3; // default to HTML files;\n s.InitialDir=path;\n s.FileName=file;\n if (s.showOpen()) var result=s.FileName;\n }\n catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE\n }\n return result;\n}\n//}}}
/***\n|Name|NewHereCommand|\n|Source|http://simonbaird.com/mptw/#NewHereCommand|\n|Version|1.0|\n\nCode originally by ArphenLin. Small tweak by SimonBaird\nhttp://aiddlywiki.sourceforge.net/NewHere_demo.html#NewHereCommand\nTo use this you must edit your ViewTemplate and add newHere to the toolbar div, eg\n{{{<div class='toolbar' macro='toolbar ... newHere'></div>}}}\n***/\n\n//{{{\n\nconfig.commands.newHere = {\n text: 'new here',\n tooltip: 'Create a new tiddler tagged as this tiddler',\n handler: function(e,src,title) {\n if (!readOnly) {\n clearMessage();\n var t=document.getElementById('tiddler'+title);\n story.displayTiddler(t,config.macros.newTiddler.title,DEFAULT_EDIT_TEMPLATE);\n story.setTiddlerTag(config.macros.newTiddler.title, title, 0);\n story.focusTiddler(config.macros.newTiddler.title,"title");\n return false;\n }\n }\n};\n\n//}}}
----\n(Organic) machinery.\n----\nA line has two sides.\n----\nA very small object. Its center.\n----\nAbandon normal instruments.\n----\nAccept advice.\n----\nAccretion.\n----\nAllow an easement\n (an easement is the abandonment of a stricture).\n----\nAlways first steps.\n----\nAlways give yourself credit for having more than personality.\n----\nAre there sections?\n----\nConsider transitions.\n----\nAsk people to work against their better judgment.\n----\nAsk your body.\n----\nAssemble some of the elements in a group and treat the group.\n----\nBalance the consistency principle with the inconsistency principle.\n----\nBe dirty.\n----\nBe extravagant.\n----\nBe less critical more often.\n----\nBreathe more deeply.\n----\nBridges\n -//build//\n -//burn.//\n----\nCascades.\n----\nChange instrument roles.\n----\nChange nothing and continue with immaculate consistency.\n----\nChildren\n -//speaking//\n -//singing.//\n----\nCluster analysis.\n----\nConsider different fading systems.\n----\nConsult other sources\n -//promising //\n -//unpromising.//\n----\nConvert a melodic element into a rhythmic element.\n----\nCourage!\n----\nCut a vital connection.\n----\nDecorate, decorate.\n----\nDefine an area as 'safe' and use it as an anchor.\n----\nDestroy\n -//nothing //\n -//the most important thing.//\n----\nDiscard an axiom.\n----\nDisciplined self-indulgence.\n----\nDisconnect from desire.\n----\nDiscover the recipes you are using and abandon them.\n----\nDistorting time.\n----\nDo nothing for as long as possible.\n----\nDo something boring.\n----\nDo the washing up.\n----\nDo the words need changing?\n----\nDo we need holes?\n----\nDon't be afraid of things because they're easy to do.\n----\nDon't be frightened of cliches.\n----\nDon't be frightened to display your talents.\n----\nDon't break the silence.\n----\nDon't stress one thing more than another.\n----\nEmphasize differences.\n----\nEmphasize repetitions.\n----\nEmphasize the flaws.\n----\nFaced with a choice, do both.\n----\nFeed the recording back out of the medium.\n----\nFill every beat with something.\n----\nFrom nothing to more than nothing.\n----\nGet your neck massaged.\n----\nGhost echoes.\n----\nGive the game away.\n----\nGive way to your worst impulse.\n----\nGo outside. Shut the door.\n----\nGo slowly all the way round the outside.\n----\nGo to an extreme, move back to a more comfortable place.\n----\nHonor thy error as a hidden intention.\n----\nHow would you have done it?\n----\nHumanize something free of error.\n----\nIdiot glee (?).\n----\nImagine a caterpillar moving.\n----\nImagine the piece as a set of disconnected events.\n----\nIn total darkness, or in a very large room, very quietly.\n----\nInfinitesimal gradations.\n----\nIntentions\n -//nobility of//\n -//humility of//\n -//credibility of.//\n----\nInto the impossible.\n----\nIs it finished?\n----\nIs the intonation correct?\n----\nIs there something missing?\n----\nIt is quite possible (after all).\n----\nJust carry on.\n----\nLeft channel, right channel, center channel.\n----\nListen to the quiet voice.\n----\nLook at a very small object, look at its center.\n----\nLook at the order in which you do things.\n----\nLook closely at the most embarrassing details and amplify them.\n----\nLost in useless territory.\n----\nLowest common denominator.\n----\nMake a blank valuable by putting it in an exquisite frame.\n----\nMake a sudden, destructive unpredictable action; incorporate.\n----\nMake an exhaustive list of everything you might do and do the last thing on the list.\n----\nMechanize something idiosyncratic.\n----\nMute and continue.\n----\nNot building a wall but making a brick.\n----\nOnce the search is in progress, something will be found.\n----\nOnly a part, not the whole.\n----\nOnly one element of each kind.\n----\nOvertly resist change.\n----\nPut in ear plugs.\n----\nQuestion the heroic approach.\n----\nReevaluation (a warm feeling).\n----\nRemember those quiet evenings.\n----\nRemove ambiguities and convert to specifics.\n----\nRemove specifics and convert to ambiguities.\n----\nRepetition is a form of change.\n----\nRetrace your steps.\n----\nReverse.\n----\nShort circuit\n (//example:// a man eating peas with the idea that they will improve his\nvirility shovels them straight into his lap).\n----\nSimple subtraction.\n----\nSimply a matter of work.\n----\nSpectrum analysis.\n----\nState the problem in words as clearly as possible.\n----\nTake a break.\n----\nTake away the elements in order of apparent non-importance.\n----\nTape your mouth.\n----\nThe inconsistency principle.\n----\nThe most important thing is the thing most easily forgotten.\n----\nThe tape is now the music.\n----\nThink of the radio.\n----\nTidy up.\n----\nTowards the insignificant.\n----\nTrust in the you of now.\n----\nTurn it upside down.\n----\nTwist the spine.\n----\nUse 'unqualified' people.\n----\nUse an old idea.\n----\nUse an unacceptable color.\n----\nUse fewer notes.\n----\nUse filters.\n----\nWater.\n----\nWhat are the sections sections of?\n----\nWhat are you really thinking about just now?\n----\nWhat is the reality of the situation?\n----\nWhat mistakes did you make last time?\n----\nWhat would your closest friend do?\n----\nWhat wouldn't you do?\n----\nWork at a different speed.\n----\nWould anybody want it?\n----\nYou are an engineer.\n----\nYou can only make one dot at a time.\n----\nYou don't have to be ashamed of using your own ideas.\n----\n[[give thanks to Eno|http://www.rtqe.net/ObliqueStrategies/]]\n\n
<!---\nI've just tweaked my gradient colours and the topMenu bit. See HorizontalMainMenu.\n--->\n<!--{{{-->\n<div class='header' macro='gradient vert #000 #069'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> \n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div id='topMenu' refresh='content' tiddler='MainMenu'></div>\n</div>\n<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n<div id='displayArea'>\n<div id='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>\n<!--}}}-->\n
# [[TiddlyWiki - the software I wish I had written]]\n# [[Gnit your own]] - creative uses of Unix Tools in Safety Programming\n** [[Gnit Your Own - final]] (developed version of above but without tables)\n# [[Why Safety Reporting IS like Rocket Science]]
/***\n|!Name:|PhotoShowPlugin |\n|!Version:|1.0.0 - 04/01/2006|\n|!Source:|http://www.math.ist.utl.pt/~psoares/plugins.html |\n|!Authors:|[[Paulo Soares|mailto:psoares@math.ist.utl.pt]]|\n|!Type:|Macro |\n|!Requires:|TiddlyWiki 2.0.0 |\n!Description\nThis plugin is a small companion to the SlideShowPlugin.\n\nThis plugin has been tested in Firefox, Internet Explorer, Safari, and Opera. Let us know if something seems broken.\n!Usage\nTo use this plugin you //must// be using TiddlyWiki 2.0.0. Install this tiddler and drop {{{<<photoShow directory/file-*.jpg a b>>}}} at the beginning of the tiddler. \nCheck this [[PhotoShowExample]].\n!Revision history\nv1.0.0 - 04/01/2006 - initial release\n!Code\n***/\n//{{{\nversion.extensions.PhotoShowPlugin = {\n major: 1, minor: 0, revision: 0,\n date: new Date(2006, 1, 4), \n type: 'macro',\n source: "http://www.math.ist.utl.pt/~psoares/addons.html#PhotoShowPlugin"\n};\n\nconfig.macros.photoShow = {};\nconfig.macros.photoShow.handler= function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length<3) return;\n title = tiddler.title;\n var url = params[0];\n var first = params[1];\n var last = params[2];\n var pos = url.indexOf('*');\n\n // Grab the 'viewer' element\n var tiddlerElements = document.getElementById("tiddler"+title).childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer"){\n viewer = tiddlerElements[i];\n break;\n }\n }\n\n var pictureHolder;\n for(i=first; i<=last; i++){\n viewer.appendChild(document.createElement('H1'));\n pictureHolder = document.createElement('CENTER');\n pictureHolder.appendChild(document.createElement('IMG'));\n pictureHolder.lastChild.src = url.substring(0,pos)+i+url.substring(pos+1);\n viewer.appendChild(pictureHolder);\n }\n}\n//}}}
Pipes are used for the serial processing of data from one command to the next - the standard output of "command 1" is redirected to the standard input of "command 2" and so on.\n{{{\ncommand1 | command2 | command3 ...\n}}}\nThis is a powerful technique. Some examples are included below:\n|!example|!description|\n|{{{last | awk '{print $1}' | sort -u}}}|get list of previous logins, extract the user name, and sort to remove duplicate names|
/***\n|''Name:''|~PopupMacro|\n|''Version:''|1.0.0 (2006-05-09)|\n|''Source:''|http://lewcid.googlepages.com/lewcid.html#PopupMacro|\n|''Author:''|Saq Imtiaz|\n|''Description:''|Create popups with custom content|\n|''Documentation:''|[[PopupMacro Documentation|PopupMacroDocs]]|\n|''~Requires:''|TW Version 2.0.8 or better|\n***/\n// /%\n{{{\nconfig.macros.popup = {};\nconfig.macros.popup.arrow = (document.all?"▼":"▾");\nconfig.macros.popup.handler = function(place,macroName,params,wikifier,paramString,theTiddler) {\n\n if (!params[0] || !params[1]) \n {createTiddlyError(place,'missing macro parameters','missing label or content parameter');\n return false;};\n \n var label = params[0];\n var source = (params[1]).replace(/\s$\s)\s)/g,">>"); \n var nestedId = params[2]? params[2]: 'nestedpopup'; \n\n var onclick = function(event) {\n if(!event){var event = window.event;}\n var theTarget = resolveTarget(event);\n var nested = (!isNested(theTarget));\n \n if ((Popup.stack.length > 1)&&(nested==true)) {Popup.removeFrom(1);}\n else if(Popup.stack.length > 0 && nested==false) {Popup.removeFrom(0);};\n \n var theId = (nested==false)? "popup" : nestedId; \n var popup = createTiddlyElement(document.body,"ol",theId,"popup",null);\n Popup.stack.push({root: button, popup: popup});\n\n wikify(source,popup);\n Popup.show(popup,true);\n event.cancelBubble = true;\n if (event.stopPropagation) event.stopPropagation();\n return false;\n }\n var button = createTiddlyButton(place, label+this.arrow,label, onclick, null);\n};\n\nwindow.isNested = function(e) {\n while (e != null) {\n var contentWrapper = document.getElementById("contentWrapper");\n if (contentWrapper == e) return true;\n e = e.parentNode;\n }\n return false;\n};\n\nsetStylesheet(\n".popup, .popup a, .popup a:visited {color: #fff;}\sn"+\n".popup a:hover {background: #014; color: #fff; border: none;}\sn"+\n".popup li , .popup ul, .popup ol {list-style:none !important; margin-left:0.3em !important; margin-right:0.3em; font-size:100%; padding-top:0.5px !important; padding:0px !important;}\sn"+\n"#nestedpopup {background:#2E5ADF; border: 1px solid #0331BF; margin-left:1em; }\sn"+\n"",\n"CustomPopupStyles");\n\nconfig.shadowTiddlers.PopupMacroDocs="The documentation is available [[here.|http://lewcid.googlepages.com/lewcid.html#PopupMacroDocs]]";\n}}}\n//%/
\n''If you want this documentation available offline, you will need to copy this tiddler to your TW.''\n!Description:\nUsing the popup macro you can create popups with any wiki text. The wiki text can be written in the macro call, can be generated using a different macro, or included from a tiddler.\n\n!Usage:\n*the button label is the first parameter\n*the text to put in the popup is the second parameter\n**embed macro output like forEachTiddler or tiddlerList\n***start macro calls with {{{<<}}} like normal, but end with {{{$))}}}\n**define popup content inline, or embed from a tidder using the core tiddler macro {{{<<tiddler$))}}}\n*you can nest popups up to one level\n**nested popups have an id of 'nestedpopup' for easier styling.\n**specify unique id's for nested popups by passing the id as a third parameter.\n\n----\n!Example's\n\n''Put a forEachTiddler macro generated list in a popup:''\n{{{<<popup forEachTiddlerDemo [[<<forEachTiddler where 'tiddler.tags.contains("systemConfig")']]$))}}}\n<<popup forEachTiddlerDemo [[<<forEachTiddler\nwhere\n'tiddler.tags.contains("systemConfig")'$))]]>>\n\n''Use the core {{{<<tiddler>>}}} macro to put the contents of a tiddler into a popup:''\nMainMenu popup:\n{{{<<popup MainMenu [[<<tiddler MainMenu$))]]>>}}}\n<<popup MainMenu [[<<tiddler MainMenu$))]]>>\n\n''Or create a custom menu in a tiddler using various macro's and normal tiddlylinks.''\n{{{<<popup CustomMenu '<<tiddler CustomMenu$))'>>}}}\n<<popup CustomMenu '<<tiddler CustomMenu$))'>>\nthis menu was created with a combination of forEachTiddler and normal tiddlyLinks!\nNote that the 'Plugins' button opens a second nested popup.\nSource tiddler: CustomMenu\n\n''Or define your custom menu inline.''\n{{{<<popup 'Inline Custom Menu' [[Custom Menu\n*MainMenu\n----\n<<forEachTiddler\n where\n 'tiddler.tags.contains("systemConfig")']]$))]] \n>>}}}\n<<popup 'Inline Custom Menu' [[Custom Menu\n*MainMenu\n----\n<<forEachTiddler where 'tiddler.tags.contains("systemConfig")'$))]] \n>>\n\n''Note: you can pass a third parameter and it will be set as the id of any nested popups''\nBy default, nested popups have an id of 'nestedpopup' to facilitate styling.\n\n----\n!Current Issues:\n*better support for custom classes for popups and nestedpopups\n----\n!Code\nPopupMacro\n\n'
[[Unix power and it's way|http://mercury.ccil.org/~cowan/upc/]]\n\n[[Unix Koans|http://www.catb.org/~esr/writings/unix-koans/]]
How many files in a directory were written today, yesterday, this month...\n{{{\nls -l -H | sed '1d' | cut -c 44-51 | sort |uniq -c\n}}}\n\nGet the date column from \n<<<\n[[ls]], No dir or filespec given so the default is all files in the current directory\n> delete the first line [[sed]]\n>>[[cut]] out the columns with the date in, \n>>>[[sort]] \n>>>>then count each occurrence with [[uniq]] -c.\n<<<\n!!!! Bugs and limitations: \n# you can't specify a subset of files (eg all *.log files)\n** <<slider ckchecklhrtftoday "Give me a date histogram by file type!" "Show: Give me a date histogram by file type!">>\n# Months will be sorted alphabetically not as dates\n# Times are thrown away\n
/***\n''QuoteOfTheDayPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#QuoteOfTheDayPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nDisplay a randomly selected "quote of the day"\n\n!!!!!Usage\n<<<\n{{{<<QOTD //tiddlername//>>}}}\nPut your quotations into a tiddler (called //tiddlername//). Separate each quote by a horizontal rule (use "----" on a line by itself). Each time the macro is rendered it will display a different quotation, selected at random from the specified tiddler.\n<<<\n!!!!!Example\n<<<\n{{{<<QOTD Quotations>>}}}\n<<QOTD Quotations>>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''QuoteOfTheDayPlugin'' (tagged with <<tag systemConfig>>)\n^^documentation and javascript for QuoteOfTheDay handling^^\n<<<\n!!!!!Revision History\n<<<\n''2005.10.21 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].\nBased on a suggestion by M.Russula\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.QOTD = {major: 1, minor: 0, revision: 0, date: new Date(2005,10,21)};\nconfig.macros.QOTD = {};\nconfig.macros.QOTD.handler= function(place,macroName,params) {\n var txt=store.getTiddlerText(params[0]); if (!txt) return;\n var quotes=txt.split("\sn----\sn");\n // then, get a random index number between 0 and N-1 and wikify that text\n wikify(quotes[Math.floor(Math.random()*quotes.length)],place);\n}\n//}}}
/***\n| Name:|QuickOpenTagPlugin|\n| Purpose:|Makes tag links into a Taggly style open tag plus a normal style drop down menu|\n| Creator:|SimonBaird|\n| Source:|http://simonbaird.com/mptw/#QuickOpenTagPlugin|\n| Requires:|TW 2.x|\n| Version|1.1 (7-Feb-06)|\n\n!History\n* Version 1.1 (07/02/2006)\n** Fix Firefox 1.5.0.1 crashes\n** Updated by ~BidiX[at]~BidiX.info\n* Version 1.0 (?/01/2006)\n** First release\n\n***/\n//{{{\n\n//⊻ ⊽ ⋁ ▼ \n\nwindow.createTagButton_orig_mptw = createTagButton;\nwindow.createTagButton = function(place,tag,excludeTiddler) {\n var sp = createTiddlyElement(place,"span",null,"quickopentag");\n createTiddlyLink(sp,tag,true,"button");\n var theTag = createTiddlyButton(sp,config.macros.miniTag.dropdownchar,config.views.wikified.tag.tooltip.format([tag]),onClickTag);\n theTag.setAttribute("tag",tag);\n if(excludeTiddler)\n theTag.setAttribute("tiddler",excludeTiddler);\n return(theTag);\n};\n\nconfig.macros.miniTag = {handler:function(place,macroName,params,wikifier,paramString,tiddler) {\n var tagged = store.getTaggedTiddlers(tiddler.title);\n if (tagged.length > 0) {\n var theTag = createTiddlyButton(place,config.macros.miniTag.dropdownchar,config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);\n theTag.setAttribute("tag",tiddler.title);\n theTag.className = "miniTag";\n }\n}};\n\nconfig.macros.miniTag.dropdownchar = (document.all?"▼":"▾"); // the fat one is the only one that works in IE\n\nconfig.macros.allTags.handler = function(place,macroName,params)\n{\n var tags = store.getTags();\n var theDateList = createTiddlyElement(place,"ul",null,null,null);\n if(tags.length === 0)\n createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);\n for (var t=0; t<tags.length; t++)\n {\n var theListItem =createTiddlyElement(theDateList,"li",null,null,null);\n var theLink = createTiddlyLink(theListItem,tags[t][0],true);\n var theCount = " (" + tags[t][1] + ")";\n theLink.appendChild(document.createTextNode(theCount));\n\n var theDropDownBtn = createTiddlyButton(theListItem," "+config.macros.miniTag.dropdownchar,this.tooltip.format([tags[t][0]]),onClickTag);\n theDropDownBtn.setAttribute("tag",tags[t][0]);\n }\n};\n\n\nsetStylesheet(\n ".quickopentag { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }\sn"+\n ".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }\sn"+\n ".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}\sn"+\n "a.miniTag {font-size:150%;}\sn"+\n "",\n"QuickOpenTagStyles");\n\n//}}}\n\n/***\n<html>⊻ ⊽ ⋁ ▼ ▾</html>\n***/\n
These examples are for matching file names - see also [[file-name expansion]]\n''regular expressions''\n|!pattern|!description|\n|{{{*}}}|match any string|\n|{{{?}}}|match a single character|\n|{{{[...]}}}|match any enclosed character|\n|{{{[!...]}}}|match any character not enclosed|\n|{{{[...-...]}}}|match any character within a lexical range|\n\n''examples''\n|!example|!description|\n|{{{*.c}}}|match all files ending in ".c"|\n|{{{?44}}}|match all files starting with any character, followed by "44"|\n|{{{[a]}}}|match "a"|\n|{{{[!a]}}}|match any character which is not "a"|\n|{{{[a-z]}}}|match any lower-case alphabetic letter|\n\n''quantifiers for patterns''\n|!quantifier|!description|\n|{{{?(pattern)}}}|matches pattern zero or one times|\n|{{{*(pattern)}}}|matches pattern any number of times|\n|{{{+(pattern)}}}|matches pattern one or more times|\n|{{{@(pattern)}}}|matches pattern once only|\n|{{{!(pattern)}}}|matches anything except pattern|\n\n''applications''\n|!example|!description|\n|{{{if [[ $var = fo@(?4*67).c ]];then}}}|interrogate string held within a variable|\n
/***\n| Name:|RenameTagsPlugin|\n| Purpose:|Allows you to easily rename tags|\n| Creator:|SimonBaird|\n| Source:|http://simonbaird.com/mptw/#RenameTagsPlugin|\n| Version:|1.0.1 (5-Mar-06)|\n\n!Description\nIf you rename a tiddler/tag that is tagging other tiddlers this plugin will ask you if you want to rename the tag in each tiddler where it is used. This is essential if you use tags and ever want to rename them. To use it, open the tag you want to rename as a tiddler (it's the last option in the tag popup menu), edit it, rename it and click done. You will asked if you want to rename the tag. Click OK to rename the tag in the tiddlers that use it. Click Cancel to not rename the tag.\n\n!Example\nTry renaming [[Plugins]] or [[CSS]] on this site.\n\n!History\n* 1.0.1 (5-Mar-06) - Added feature to allow renaming of tags without side-effect of creating a tiddler\n* 1.0.0 (5-Mar-06) - First working version\n\n!Code\n***/\n//{{{\n\nversion.extensions.RenameTagsPlugin = {\n major: 1, minor: 0, revision: 0,\n date: new Date(2006,3,5),\n source: "http://simonbaird.com/mptw/#RenameTagsPlugin"\n};\n\nconfig.macros.RenameTagsPlugin = {};\nconfig.macros.RenameTagsPlugin.prompt = "Rename the tag '%0' to '%1' in %2 tidder%3?";\n\n// these are very useful, perhaps they should be in the core\nif (!store.addTag) {\n store.addTag = function(title,tag) {\n var t=this.getTiddler(title); if (!t || !t.tags) return;\n t.tags.push(tag);\n };\n};\n\nif (!store.removeTag) {\n store.removeTag = function(title,tag) {\n var t=this.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)!=null) t.tags.splice(t.tags.find(tag),1);\n };\n};\n\nstore.saveTiddler_orig_tagrename = store.saveTiddler;\nstore.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags) {\n if (title != newTitle && this.getTaggedTiddlers(title).length > 0) {\n // then we are renaming a tag\n var tagged = this.getTaggedTiddlers(title);\n if (confirm(config.macros.RenameTagsPlugin.prompt.format([title,newTitle,tagged.length,tagged.length>1?"s":""]))) {\n for (var i=0;i<tagged.length;i++) {\n store.removeTag(tagged[i].title,title);\n store.addTag(tagged[i].title,newTitle);\n // if tiddler is visible refresh it to show updated tag\n story.refreshTiddler(tagged[i].title,false,true);\n }\n }\n if (!this.tiddlerExists(title) && newBody == "") {\n // dont create unwanted tiddler\n return null;\n }\n }\n return this.saveTiddler_orig_tagrename(title,newTitle,newBody,modifier,modified,tags);\n}\n\n//}}}\n\n
\nThe idea is - what if we could look at parts of the SAS program that relate datasets, and call other programs...\nthese lines tell the main story of the program.\n> proc, data \n>> set, merge\n>>> by\n>>> where \n> run, quit\n> %inc(lude)\n>%macro_calls\n \n* We can do this with [[regular expressions]] using [[grep]] or [[awk]]\n\n!!!! Version without run or Quit (and case of firstletter) (set flags in grep -i VS dialog box to ignore case)\n\n{{{\n^[ ]*proc[ ]*[^;]*;|^[ ]*data[ ]*[^;]*|;^[ ]*merge[ ]*[^;]*;|\n^[ ]*set[ ]*[^;]*;|^[ ]*by[ ]*[^;]*;|^[ ]*where[ ]*[^;]*;|\n^[ ]*run[ ]*[^;]*;|^[ ]*quit[ ]*[^;]*;%let[ ]+|^[ ]%inc\n}}}\n!!!!! changed to multiple lines for readability. Watch it when copy&pasting.\n!!!!! Use with [[grep]] -i to ignore case\n!!!!! the {{{^}}} at the start of each pattern means 'start of line', omit to match anywhere on line. \n* {{{[ ]*}}} means any number of optional blanks\n!!!!! why the pattern after the word so complex? \n> Don't ask. It is a work around for the fact that grep does not have a syntax for non-greedy matching. IE {{{data.*;}}} would match to the last {{{;}}} not the first after {{{data}}}
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<upload http://DaveG.tiddlyspot.com/store.cgi index.html . . daveg>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>\n<html>\n<!--Creative Commons License--><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/"><img alt="Creative Commons License" border="0" src="http://creativecommons.org/images/public/somerights20.png"/></a><br/> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/">Creative Commons </a>.<!--/Creative Commons License--><!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n <Work rdf:about="">\n <license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.5/" />\n <dc:type rdf:resource="http://purl.org/dc/dcmitype/Text" />\n </Work>\n <License rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.5/"><permits rdf:resource="http://web.resource.org/cc/Reproduction"/><permits rdf:resource="http://web.resource.org/cc/Distribution"/><requires rdf:resource="http://web.resource.org/cc/Notice"/><requires rdf:resource="http://web.resource.org/cc/Attribution"/><prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/><permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/><requires rdf:resource="http://web.resource.org/cc/ShareAlike"/></License></rdf:RDF> -->\n</html>
<<tabs txtMainTab All 'All tiddlers' TabAll Tags 'All tags' TabTags More 'More lists' TabMore>>
/***\nThis CSS by DaveBirss.\n***/\n/*{{{*/\n\n.tabSelected {\n background: #fff;\n}\n\n.tabUnselected {\n background: #eee;\n}\n\n#sidebar {\n color: #000;\n}\n\n#sidebarOptions {\n background: #fff;\n}\n\n#sidebarOptions .button {\n color: #999;\n}\n\n#sidebarOptions .button:hover {\n color: #000;\n background: #fff;\n border-color:white;\n}\n\n#sidebarOptions .button:active {\n color: #000;\n background: #fff;\n}\n\n#sidebarOptions .sliderPanel {\n background: transparent;\n}\n\n#sidebarOptions .sliderPanel A {\n color: #999;\n}\n\n#sidebarOptions .sliderPanel A:hover {\n color: #000;\n background: #fff;\n}\n\n#sidebarOptions .sliderPanel A:active {\n color: #000;\n background: #fff;\n}\n\n.sidebarSubHeading {\n color: #000;\n}\n\n#sidebarTabs {`\n background: #fff\n}\n\n#sidebarTabs .tabSelected {\n color: #000;\n background: #fff;\n border-top: solid 1px #ccc;\n border-left: solid 1px #ccc;\n border-right: solid 1px #ccc;\n border-bottom: none;\n}\n\n#sidebarTabs .tabUnselected {\n color: #999;\n background: #eee;\n border-top: solid 1px #ccc;\n border-left: solid 1px #ccc;\n border-right: solid 1px #ccc;\n border-bottom: none;\n}\n\n#sidebarTabs .tabContents {\n background: #fff;\n}\n\n\n#sidebarTabs .txtMoreTab .tabSelected {\n background: #fff;\n}\n\n#sidebarTabs .txtMoreTab .tabUnselected {\n background: #eee;\n}\n\n#sidebarTabs .txtMoreTab .tabContents {\n background: #fff;\n}\n\n#sidebarTabs .tabContents .tiddlyLink {\n color: #999;\n}\n\n#sidebarTabs .tabContents .tiddlyLink:hover {\n background: #fff;\n color: #000;\n}\n\n#sidebarTabs .tabContents {\n color: #000;\n}\n\n#sidebarTabs .button {\n color: #666;\n}\n\n#sidebarTabs .tabContents .button:hover {\n color: #000;\n background: #fff;\n}\n\n/*}}}*/
Talks, Tutorials, blog
DaveG @ PhUSE
http://DaveG.tiddlyspot.com/index.html
! Intro - who am I?\nThis is introduction to me and will be in every presentation.\n* brilliant\n* befuddled\n* prone to garbling\nme\n----
/***\n|!Name:|SlideShowPlugin |\n|!Version:|1.2.1 - 08/02/2006|\n|!Source:|http://www.math.ist.utl.pt/~psoares/addons.html |\n|!Authors:|[[Paulo Soares|mailto:psoares@math.ist.utl.pt]] and [[Clint Checketts|http://www.checkettsweb.com]] |\n|!Type:|Macro |\n|!Requires:|TiddlyWiki >= 2.0.0 |\n!Description\nThis plugin turns a TiddlyWiki tiddler into a simple slide show type display. You can have looping, timed or themed slide shows. It should work in a way that does not interfere with TiddlyWiki. When you close the slide show you get back to your good old TW. \n\nThis plugin has been tested in Firefox, Internet Explorer, Safari, and Opera. Let us know if something seems broken.\n!Usage\nTo use this plugin you //must// be using TiddlyWiki 2.0. Install this tiddler and drop {{{<<slideShow>>}}} at the beginning of the tiddler. Use ! to start each slide with or without a title. Mark the end of your slides with a rule (- - - -). Everything that appears before the first header or after the closing rule is not shown in the slide show. \nThere are also a few navigation buttons and a table of contents that shows up if you click the slide number.\nSee other options in this [[SlideShowExample]].\n!Revision history\nv1.0.0 - 12/11/2005 - initial release\nv1.1.0 Beta 12/12/2005 - added support for IE, added key listeners\n v1.1.5 Beta 12/14/2005 - added mouse support and cleaned up navbar generation\nv1.2.0 07/01/2006 - added a resume feature and themes support\nv1.2.1 08/02/2006 - pause timed slideshow with spacebar, clock with 3 different modes, fixed bugs with style and abbreviation options, general cleanup\n!Todo\n*Incremental advancement within a slide\n*Cross fade effects\n!Code\n***/\n//{{{\n\nconfig.macros.slideShow = {label: "slide show", maxTOCLength: 30};\nconfig.views.wikified.slideShow = {text: "slide show", tooltip: "Start/stop slide show"};\nconfig.views.wikified.slideShow.quit = {text: "end", tooltip: "Quit the slide show"};\nconfig.views.wikified.slideShow.firstSlide = {text: "<<", tooltip: "first slide"};\nconfig.views.wikified.slideShow.previousSlide = {text: "<", tooltip: "previous slide"};\nconfig.views.wikified.slideShow.nextSlide = {text: ">", tooltip: "next slide"};\nconfig.views.wikified.slideShow.lastSlide = {text: ">>", tooltip: "last slide"};\n\nfunction changeStyleSheet(tiddlerName) {\n if (tiddlerName == null) tiddlerName = "StyleSheet";\n setStylesheet(store.getTiddlerText("StyleSheetColors"),"StyleSheetColors");\n setStylesheet(store.getTiddlerText("StyleSheetLayout"),"StyleSheetLayout");\n var theCSS = store.getRecursiveTiddlerText(tiddlerName,"");\n setStylesheet(theCSS,"StyleSheet");\n}\n\n//Excellent (and versatile) reparser created by Paul Petterson for parsing the paramString in a macro\nfunction reparse( params ) {\n var re = /([^:\sss]+)(?:\ss:((?:\ssd+)|(?:["'](?:[^"']+)["']))|\sss|$)/g;\n var ret = new Array() ;\n var m ;\n while( (m = re.exec( params )) != null ) ret[ m[1] ] = m[2]?m[2]:true ;\n return ret ;\n}\n\n// 'keys' code adapted from S5 which in turn was adapted from MozPoint (http://mozpoint.mozdev.org/)\nfunction keys(key) {\n if (!key) {\n key = event;\n key.which = key.keyCode;\n }\n if (document.getElementById('contentWrapper').className == "slideShowMode"){\n switch (key.which) {\n case 32: // spacebar\n if(time>0){\n if(autoAdvance){\n clearInterval(autoAdvance);\n autoAdvance = null;\n } else {\n autoAdvance=setInterval("GoToSlide(1)", time);\n }\n }\n break;\n case 34: // page down\n case 39: // rightkey\n case 40: // downkey\n GoToSlide(1);\n break;\n case 33: // page up\n case 37: // leftkey\n case 38: // upkey\n GoToSlide(-1);\n break;\n case 36: // home\n GoToSlide("f");\n break;\n case 35: // end\n GoToSlide("l");\n break;\n case 27: // escape\n endSlideShow();\n break;\n }\n\n }\n return false;\n}\n\nfunction clicker(e) {\n if (!e) var e = window.event;\n var target = resolveTarget(e);\n //Whenever something is clicked that won't advance the slide make sure that the table of contents gets hidden\n if (target.getAttribute('href') != null || isParentOrSelf(target, 'toc') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object') || isParentOrSelf(target, 'pageFooter') || isParentOrSelf(target, 'navigator')){\n //Don't hide the TOC if the indexNumbers (which trigger the index) is clicked\n if(isParentOrSelf(target,'indexNumbers') || isParentOrSelf(target,'jumpInput')){\n return true;\n }\n showHideTOC('none');\n return true;\n }\n \n //Advance a slide if the TOC is visible otherwise make sure that the TOC gets hidden\n if ((!e.which && e.button == 1) || e.which == 1) {\n if (document.getElementById('toc').style.display != 'block'){\n GoToSlide(1);\n } else {\n showHideTOC('none');\n }\n }\n \n if ((!e.which && e.button == 2) || e.which == 3) {\n if (document.getElementById('toc').style.display != 'block'){\n GoToSlide(-1);\n } else {\n showHideTOC('none');\n }\n return false;\n }\n}\n\nfunction isParentOrSelf(element, id) {\n if (element == null || element.nodeName=='BODY') return false;\n else if (element.id == id) return true;\n else return isParentOrSelf(element.parentNode, id);\n}\n\nfunction GoToSlide(step) {\n var new_pos;\n var slideHolder = document.getElementById('slideContainer');\n //The parse float ensures that the attribute is returned as a number and not a string.\n var cur_pos = parseFloat(slideHolder.getAttribute('currentslide'));\n var numberSlides = slideHolder.getElementsByTagName("div").length;\n switch (step) {\n case "f":\n new_pos=0;\n break;\n case "l":\n new_pos=numberSlides-1;\n break;\n default:\n new_pos=cur_pos+step;\n }\n \n if(slideShowCircularMode && new_pos == numberSlides) new_pos=0;\n if(slideShowCircularMode && new_pos<0) new_pos=(numberSlides - 1);\n if(step!=0 && new_pos>=0 && new_pos<numberSlides) {\n slideHolder.childNodes[cur_pos].style.display='none';\n slideHolder.childNodes[new_pos].style.display='block';\n slideHolder.setAttribute('currentslide',new_pos);\n new_pos++;\n var indexNumbers = document.getElementById('indexNumbers');\n indexNumbers.firstChild.data = new_pos+'/'+numberSlides;\n if((new_pos==numberSlides) && !slideShowCircularMode && autoAdvance) clearInterval(autoAdvance);\n return true;\n }\n return false;\n}\n\nfunction tocShowSlide(e) {\n if (!e) var e = window.event;\n var target = resolveTarget(e);\n var slide = target.getAttribute('slideNumber');\n var cur_pos = document.getElementById('slideContainer').getAttribute('currentslide');\n var step = slide-cur_pos;\n if(step!=0) GoToSlide(step);\n showHideTOC('none');\n return;\n}\n\n//Toggle the display of the table of contents\nfunction showHideTOC(display){\n var toc = document.getElementById('toc');\n //Reset the input box\n document.getElementById('jumpInput').value = "";\n\n if (display == null || display.length == null){\n if (toc.style.display == 'none' || toc.style.display == ''){\n toc.style.display = 'block';\n document.getElementById('jumpInput').focus();\n } else {\n toc.style.display = 'none';\n }\n } else {\n toc.style.display = display;\n if (display == 'block')\n document.getElementById('jumpInput').focus();\n }\n}\n\nfunction makeSignature(title,params){\n var signature = title+store.getTiddler(title).modified;\n if(params['style']) signature += params['style'];\n if(params['repeat']) signature += "repeat";\n if(params['slidePause'] > 0) signature += params['slidePause'];\n if(params['tocLabel']) signature += params['tocLabel'];\n if(params['autostart']) signature += "autostart";\n if(params['clock']) signature += params['clock'];\n return signature;\n}\n\nfunction padZero(par){\n if(par<10) par="0"+par;\n return par;\n}\n\nfunction setClock(){\n var actualTime = new Date();\n var newTime = actualTime - clockStartTime;\n newTime = clockMultiplier*newTime+clockInterval-3600000;\n actualTime.setTime(newTime);\n newTime = padZero(actualTime.getHours()) + ":" + padZero(actualTime.getMinutes())+ ":" + padZero(actualTime.getSeconds());\n var clock = document.getElementById('slideClock');\n clock.firstChild.nodeValue = newTime;\n}\n\nfunction resetClock(){\n var time = new Date(70,1,1,0,0,0);\n if(clockStartTime-time>0) clockStartTime = new Date();\n}\n\nvar title;\nvar place;\nvar autoAdvance=null;\nvar slideClock=null;\nvar time = 0;\nvar slideShowCircularMode;\nvar slideShowStyleSheet;\nvar slideShowParams;\nvar clockMultiplier;\nvar clockInterval;\nvar clockStartTime;\n\nconfig.macros.slideShow.handler = function(aPlace,macroName,params,wikifier,paramString,tiddler){\n if(tiddler instanceof Tiddler){\n var lingo = config.views.wikified.slideShow;\n if (!e) var e = window.event;\n \n place = aPlace;\n title = tiddler.title;\n params = reparse(paramString);\n var onclick = function(){config.macros.slideShow.onClickSlideShow(params);};\n createTiddlyButton(aPlace,lingo.text,lingo.tooltip,onclick);\n \n var tiddler = document.getElementById("tiddler"+title);\n if(params['autostart'] && tiddler.getAttribute('autoStartAgain') == null){\n\n tiddler.setAttribute('autoStartAgain',false)\n slideShowParams = params;\n setTimeout("config.macros.slideShow.onClickSlideShow(slideShowParams);",10);\n \n }\n }\n}\n\nvar disableFunction = function(e){return false;}\nvar enableFunction = function(e){}\n\nconfig.macros.slideShow.onClickSlideShow = function(newParams) {\ndocument.oncontextmenu = disableFunction;\n clockMultiplier = 1;\n clockInterval = 0;\n clockStartTime = new Date(70,1,1,0,0,0);\n slideShowCircularMode = false;\n time = 0;\n slideShowStyleSheet = null;\n if(newParams['style']){\n slideShowStyleSheet = eval(newParams['style']);\n } \n if(newParams['repeat']){\n slideShowCircularMode = true;\n }\n if(newParams['slidePause'] > 0){\n time = newParams['slidePause'];\n }\n if(newParams['clock']){\n clockStartTime = new Date();\n var clockType= eval(newParams['clock']);\n if(clockType != '+') {\n clockMultiplier = -1;\n clockInterval = -clockType*60000;\n }\n }\n\n var contentWrapper = document.getElementById('contentWrapper');\n if (contentWrapper.className != "slideShowMode"){\n clearMessage();\n //Attach the key and mouse listeners\n document.onkeyup = keys;\n document.onmouseup = clicker;\n \n var slideShowHolder = document.getElementById('slideShowWrapper');\n //If no show exist previously, create it\n if(slideShowHolder == null){\n createSlides(newParams);\n //If there was once waiting in the background and it matches the one we just started, resume it\n } else if (slideShowHolder.getAttribute('showSignature') == makeSignature(title,newParams)){\n \n //Remove dblClick on edit function\n var theTiddler = document.getElementById("tiddler"+title);\n theTiddler.ondblclick = function() {};\n\n // Grab the 'viewer' element and give it a signature so the show can be resumed if stopped\n var tiddlerElements = theTiddler.childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer") viewer = tiddlerElements[i];\n }\n theTiddler.insertBefore(slideShowHolder,viewer);\n theTiddler.removeChild(viewer);\n slideShowHolder.style.display = 'block';\n document.getElementById("pageFooter").className = "pageFooterOff";\n \n //If the show we started it totally new than the resumable one, create the new one and kill the resumable one\n } else {\n slideShowHolder.parentNode.removeChild(slideShowHolder);\n createSlides(newParams);\n }\n slideClock=setInterval("setClock()", 1000); \n if(time>0) autoAdvance=setInterval("GoToSlide(1)", time); \n story.closeAllTiddlers(title);\n toggleSlideStyles();\n } else {\n endSlideShow();\n }\n return ;\n \n}\n\nfunction endSlideShow(){\n //Set aside show so it can be resumed later\n var showHolder = document.getElementById('slideShowWrapper');\n showHolder.style.display = 'none';\n document.getElementById('contentWrapper').parentNode.appendChild(showHolder);\n \n document.oncontextmenu = enableFunction;\n if(autoAdvance) clearInterval(autoAdvance);\n if(slideClock) clearInterval(slideClock);\n story.refreshTiddler(title,null,true);\n document.onmouseup = function(){};\n toggleSlideStyles();\n}\n\n\nfunction isInteger(s){\n var i;\n for (i = 0; i < s.length; i++){\n // Check that current character is number.\n var c = s.charAt(i);\n if (((c < "0") || (c > "9"))) return false;\n }\n // All characters are numbers.\n return true;\n}\n\nfunction jumpInputToSlide(e){\n if (!e) {\n e = window.event;\n e.which = e.keyCode;\n }\n if(e.which==13){\n var jumpInput= document.getElementById("jumpInput").value;\n if(isInteger(jumpInput)){\n var step=jumpInput-document.getElementById('slideContainer').getAttribute('currentslide')-1;\n if (GoToSlide(step)){\n showHideTOC('none'); \n }\n }\n }\n return;\n}\n\n//Used to shorten the TOC fields\nfunction abbreviateLabel(label){\n if (label == null) label = "A Slide" //This is just a place holder fix\n var maxTOCLength = config.macros.slideShow.maxTOCLength;\n if(label.length>maxTOCLength) {\n var temp = new Array();\n temp = label.split(' ');\n label = temp[0];\n for(var j=1; j<temp.length; j++){\n if((label.length+temp[j].length)<=maxTOCLength){\n label += " " + temp[j];\n } else {\n label += " ...";\n break;\n }\n }\n }\n return label;\n}\n\ncreateSlides = function(newParams){\n var lingo = config.views.wikified.slideShow;\n\n //Remove dblClick on edit function\n var theTiddler = document.getElementById("tiddler"+title);\n theTiddler.ondblclick = function() {};\n\n // Grab the 'viewer' element and give it a signature so the show can be resumed if stopped\n var tiddlerElements = theTiddler.childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer") viewer = tiddlerElements[i];\n }\n viewer.id = 'slideShowWrapper';\n viewer.setAttribute("showSignature",makeSignature(title,newParams));\n\n //Hide the text that comes before the first H1 element (I think I may put this into a cover page type thing)\n while(viewer.childNodes.length > 0 && viewer.firstChild.nodeName.toUpperCase() != "H1") {\n viewer.removeChild(viewer.firstChild);\n }\n \n //Cycle through the content an each time you hit an H1 begin a new slide div\n var slideNumber = 0;\n var slideHolder = document.createElement('DIV');\n slideHolder.id = "slideContainer";\n \n while(viewer.childNodes.length > 0){\n //Create a new slide a append it to the slide holder\n if (viewer.firstChild.nodeName == "H1"){\n slideNumber++;\n var slide = document.createElement('DIV');\n slide.id = "slideNumber"+slideNumber;\n slide.className = "slide";\n if (slideNumber > 1) {\n slideHolder.setAttribute('currentslide',0);\n slide.style.display='none';\n } else {\n slide.style.display='block';\n }\n slideHolder.appendChild(slide); \n }\n\n //Grab the first thing in the viewer and check to see if its an H1, if so put it in a slide, it will shift everything else forward\n slide.appendChild(viewer.firstChild);\n\nif(viewer.childNodes.length > 0 && viewer.firstChild.className=="slideShowNote") {\n viewer.removeChild(viewer.firstChild);\n }\n\n //If you hit a horizontal rule (HR) remove the remaining elements until you hit an H1\n if(viewer.childNodes.length > 0 && viewer.firstChild.nodeName=="HR") {\n while(viewer.childNodes.length > 0 && viewer.firstChild.nodeName != "H1") {\n viewer.removeChild(viewer.firstChild);\n }\n }\n }\n \n //Stick the slides back into the viewer\n viewer.appendChild(slideHolder);\n\n \n //Create the navigation bar\n var pagefooter = createTiddlyElement(viewer,"DIV","pageFooter","pageFooterOff");\n var navigator = createTiddlyElement(pagefooter,"SPAN","navigator");\n\n //Make it so that when the footer is hovered over the class will change to make it visible\n pagefooter.onmouseover = function () {pagefooter.className = "pageFooterOn"};\n pagefooter.onmouseout = function () {pagefooter.className = "pageFooterOff"};\n\n //Create the control button for the navigation \n var onClickQuit = function(){endSlideShow();};\n createTiddlyButton(navigator,lingo.quit.text,lingo.quit.tooltip,onClickQuit);\n createTiddlyButton(navigator,lingo.firstSlide.text,lingo.firstSlide.tooltip,first_slide);\n createTiddlyButton(navigator,lingo.previousSlide.text,lingo.previousSlide.tooltip,previous_slide);\n createTiddlyButton(navigator,lingo.nextSlide.text,lingo.nextSlide.tooltip,next_slide);\n createTiddlyButton(navigator,lingo.lastSlide.text,lingo.lastSlide.tooltip,last_slide); \n\n var clock = createTiddlyElement(navigator,"SPAN","slideClock","slideClock","");\n clock.onclick = resetClock;\n clock.style.cursor = 'pointer';\n clock.style.padding= '0 5px 0 5px';\n\n var indexNumbers = createTiddlyElement(pagefooter,"SPAN","indexNumbers","indexNumbers","1/"+slideNumber)\n indexNumbers.onclick = showHideTOC;\n\n var toc = createTiddlyElement(pagefooter,"UL","toc");\n\n \n for (var i=0;i<slideHolder.childNodes.length;i++) {\n //Loop through each slide and check the header's content\n var tocLabel = null;\n if(slideHolder.childNodes[i].firstChild.hasChildNodes()){\n tocLabel = abbreviateLabel(slideHolder.childNodes[i].firstChild.firstChild.data);\n } else if (newParams['tocLabel'] != null){\n j=i+1;\n tocLabel = eval(newParams['tocLabel'])+" "+j;\n }\n \n //If the slide doesn't have a title (explicit or generated) don't include it in the table of contents\n if (tocLabel != null){\n var tocItem = createTiddlyElement(toc,"LI",null,"tocLevel1");\n var tocLink = createTiddlyElement(tocItem,"A",null,"tocItem",tocLabel);\n tocLink.setAttribute("slideNumber",i);\n tocLink.onclick=tocShowSlide; \n }\n \n\n for (var j=1;j<slideHolder.childNodes[i].childNodes.length;j++) {\n var node = slideHolder.childNodes[i].childNodes[j];\n if(node.nodeName=="H2" || node.nodeName=="H3" || node.nodeName=="H4") {\n tocLabel = abbreviateLabel(node.firstChild.data);\n switch (node.nodeName) {\n case "H2":\n var tocItem = createTiddlyElement(toc,"LI",null,"tocLevel2");\n break;\n case "H3":\n var tocItem = createTiddlyElement(toc,"LI",null,"tocLevel3");\n break;\n case "H4":\n var tocItem = createTiddlyElement(toc,"LI",null,"tocLevel4");\n }\n var tocLink = createTiddlyElement(tocItem,"A",null,"tocItem",tocLabel);\n tocLink.setAttribute("slideNumber",i);\n tocLink.onclick=tocShowSlide;\n }\n }\n }\n \n\n //Input box to jump to s specific slide\n var tocItem = createTiddlyElement(toc,"LI",null,"tocJumpItem","Go to slide: ");\n var tocJumpInput = createTiddlyElement(tocItem,"INPUT","jumpInput");\n tocJumpInput.type="text";\n tocJumpInput.onkeyup=jumpInputToSlide;\n}\n\nvar next_slide= function(e){GoToSlide(1);}\nvar first_slide= function(e){GoToSlide("f");}\nvar previous_slide= function(e){GoToSlide(-1);}\nvar last_slide= function(e){GoToSlide("l");}\n\nfunction toggleSlideStyles(){\n var contentWrapper = document.getElementById('contentWrapper');\n if (contentWrapper.className == "slideShowMode"){\n contentWrapper.className = "";\n if(slideShowStyleSheet) changeStyleSheet();\n } else{\n contentWrapper.className = "slideShowMode";\n if(slideShowStyleSheet) changeStyleSheet(slideShowStyleSheet);\n }\n}\n\nsetStylesheet("/***\ssn!Slide Mode Styles\ssn***/\ssn/*{{{*/\ssn#contentWrapper.slideShowMode #slideContainer{\ssn display: block;\ssn}\ssn\ssn#jump{\ssn text-align: right;\ssn}\ssn\ssn.pageFooterOff #navigator{\ssn visibility: hidden;\ssn}\ssn\ssn.pageFooterOn #navigator{\ssn visibility: visible;\ssn}\ssn\ssn#contentWrapper.slideShowMode,\ssn #contentWrapper.slideShowMode #displayArea{\ssn width: 100%;\ssn font-size: 1.5em;\ssn margin: 0;\ssn padding: 0;\ssn}\ssn\ssn#slideContainer{\ssn display: none;\ssn}\ssn\ssn#contentWrapper.slideShowMode #sidebar,\ssn#contentWrapper.slideShowMode #mainMenu,\ssn#contentWrapper.slideShowMode .header,\ssn#contentWrapper.slideShowMode #displayArea .toolbar,\ssn#contentWrapper.slideShowMode #displayArea .footer,\ssn#contentWrapper.slideShowMode #displayArea .subtitle,\ssn#contentWrapper.slideShowMode #displayArea .tagged,\ssn#contentWrapper.slideShowMode #displayArea .tagging\ssn{\ssn display:none;\ssn}\ssn\ssn.indexNumbers{\ssn cursor: pointer;\ssn}\ssn\ssn#navigator{\ssn visibility: hidden;\ssn bottom: 0;\ssn}\ssn\ssn#toc{\ssn display: none;\ssn position: absolute;\ssn font-size: .75em;\ssn bottom: 2em;\ssn right: 0;\ssn background: #fff;\ssn border: 1px solid #000;\ssn text-align: left;\ssn}\ssn\ssnul#toc, #toc li{\ssn margin: 0;\ssn padding: 0;\ssn list-style: none;\ssn line-height: 1em;\ssn}\ssn\ssn.tocJumpItem{\ssn margin-right: 2em;\ssn}\ssn\ssn.tocJumpItem input{\ssnmargin-right: 1em;\ssn border: 0;\ssn}\ssn\ssn#toc a,\ssn#toc a.button{\ssn display: block;\ssn padding: .1em;\ssn}\ssn\ssn#toc .tocLevel1{\ssnfont-size: .8em;\ssn}\ssn\ssn#toc .tocLevel2{\ssn margin-left: 1em;\ssn font-size: .75em;\ssn}\ssn\ssn#toc .tocLevel3{\ssn margin-left: 2em;\ssnfont-size: .75em;\ssn}\ssn\ssn#toc .tocLevel4{\ssn margin-left: 3em;\ssnfont-size: .65em;\ssn}\ssn\ssn#toc a{\ssn cursor: pointer;\ssn}\ssn\ssnh1{\ssn min-height: 1em;\ssn}\ssn\ssn.slide h1{\ssn min-height: 0;\ssn}\ssn\ssn/* The '>' selector is ignored by IE6 and earlier so the proper rules are given */\ssn#pageFooter{\ssn position: fixed;\ssn bottom: 2px;\ssn right: 2px;\ssn width: 100%;\ssn text-align: right;\ssn}\ssn\ssn/* This is a hack to trick IE6 and earlier to put the navbar on the bottom of the page */\ssn* html #pageFooter {\ssn position: absolute;\ssn width: 100%;\ssn text-align: right;\ssn right: auto; bottom: auto;\ssn left: expression( ( -20 - pageFooter.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );\ssn top: expression( ( -10 - pageFooter.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );\ssn}\ssn\ssn\ssn\ssn/*}}}*/","slideShowStyles");\n//}}}
<<slideShow>>\n! Intro - who am I?\nThis is introduction to me and will be in every presentation.\n* brilliant\n* befuddled\n* prone to garbling\nme\n----\n! The day begins in bongo land\n* I wake, the call of the lesser bongo is taunting me again\n* when will I be free?\n## now?\n## surely soon?\n## Hooray\n{{{\nsome program code \n\nfixed pitch\n}}}\n----\nSlide notes ignored\n!\n* more of the same\n*\n<<<\nGBS a=said...\n<<<\n----\n
<<slideShow>> - A simple slide show that keeps the TW style \n<<slideShow style:'MySSStyleSheet' clock:'+'>> - A themed slide show with a clock showing the presentation elapsed time\n<<slideShow repeat clock:'-20'>> - A looping slide show with a 20 minutes countdown clock\n<<slideShow slidePause:1000>> - A timed slideshow that runs once\n<<slideShow slidePause:1000 repeat>> - A timed looping slideshow\n--s--\n!The [[SlideShowPlugin]]\nPress F11 to go fullscreen and adjust the font sizes with Ctrl++ Ctrl+- (or Ctrl+mousewheel).\n\nThis plugin was developed by Paulo Soares and Clint Checketts.\n{{Comment{This block is not shown in the slide show.\n@@Don't show me!!!@@}}}\n--s--\n!How slides are separated\nIn a tiddler, you just separate each slide by putting in a new level 1 heading (use a {{{!}}} to delimit H1 headings)\n--s--\nTiddlers don't have to have titles, just put a {{{!}}}alone on its own line (as seen in this tiddler)\n--s--\n!A slide with subsections and a long title\nCheck to TOC below to see how the slide title is abbreviated.\n!!Section 1\nThis is a section\n!!!Subsection 1.1\nThis is a subsection\n!!!Subsection 1.2\nThis is another subsection\n!!!!Subsubsection 1.2.1\nThis is a subsubsection\n--s--\n!Using the keyboard\nThe following keys are defined:\n*Left arrow - previous overlay\n*Down arrow - previous slide\n*Right arrow - next overlay\n*Up arrow - next slide\n*Home - first slide\n*End - last slide\n*Escape - exit slide show\n*Spacebar - pause/resume slide show in auto advance mode\n--s--\n!Slide show parameters\n*The slide show can be themed by providing a ~StyleSheet ({{{<<slideShow style:'MyStyleSheet'>>}}})\n*By default, there is a clock at bottom of the browser window that displays the current time. This clock can also show the presentation elapsed time with {{{<<slideShow clock:'+'>>}}} or a countdown clock with {{{<<slideShow clock:'-20'>>}}} (for 20 minutes). In these two cases, if you click on the clock display it will be restarted\n*The slide show can be set to loop ({{{<<slideShow repeat>>}}})\n*You can set it so each slide changes after X milliseconds ({{{<<slideShow slidePause:X>>}}}) (auto advance mode)\n*Use auto start mode to begin the slideshow the moment the tiddler is opened ({{{<<slideShow autostart>>>}}})\n*You can disable overlays with {{{<<slideShow noOverlays>>}}}\n*These parameters can be mixed and matched in any order: {{{<<slideShow slidePause:1000 repeat>>}}} is the same as {{{<<slideShow repeat slidePause:1000>>}}}\n--s--\n!Overlays\nTo see how incremental display works use the left and right mouse buttons.\n{{Overlay1{You can}}} {{Overlay2{present things}}} {{Overlay1{in an arbitrary order!!!}}}\n{{Overlay3{Its a bit harder with lists but it works:}}}\n<html>\n<ol>\n<li class="Overlay4">First item</li>\n<li class="Overlay5">Second item</li>\n<li class="Overlay4">Last item</li>\n</ol>\n</html>\n{{Comment{\n----\nYou can hide comments on a slide that won't display in the slide show}}}
/***\n|!Name:|SlideShowPlugin |\n|!Version:|1.4.0 - 20/04/2006|\n|!Source:|http://www.math.ist.utl.pt/~psoares/addons.html |\n|!Authors:|[[Paulo Soares|mailto:psoares@math.ist.utl.pt]] and [[Clint Checketts|http://www.checkettsweb.com]] |\n|!Type:|Macro |\n|!Requires:|TiddlyWiki >= 2.0.0 |\n<<tiddler SlideShowPluginDoc>>\n!Code\n***/\n//{{{\nversion.extensions.SlideShowPlugin = {\n major: 1, minor: 4, revision: 0,\n date: new Date(2006, 3, 20), \n type: 'macro',\n source: "http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPlugin"\n};\n\nconfig.macros.slideShow = {label: "slide show", maxTOCLength: 30};\nconfig.macros.slideShow.messages = {gotoLabel: "Go to slide:"};\nconfig.views.wikified.slideShow = {text: "slide show", tooltip: "Start slide show"};\nconfig.views.wikified.slideShow.quit = {text: "end", tooltip: "Quit the slide show"};\nconfig.views.wikified.slideShow.firstSlide = {text: "<<", tooltip: "first slide"};\nconfig.views.wikified.slideShow.previousSlide = {text: "<", tooltip: "previous slide"};\nconfig.views.wikified.slideShow.nextSlide = {text: ">", tooltip: "next slide"};\nconfig.views.wikified.slideShow.lastSlide = {text: ">>", tooltip: "last slide"};\nconfig.views.wikified.slideShow.resetClock = {text: " ", tooltip: "reset"};\n\nconfig.formatters.push( {\n name: "SlideSeparator",\n match: "^--s--+$\s\sn?",\n handler: function(w)\n {\n createTiddlyElement(w.output,"hr",null,'slideSeparator');\n }\n}\n)\n\nfunction changeStyleSheet(tiddlerName) {\n if (tiddlerName == null) tiddlerName = "StyleSheet";\n setStylesheet(store.getTiddlerText("StyleSheetColors"),"StyleSheetColors");\n setStylesheet(store.getTiddlerText("StyleSheetLayout"),"StyleSheetLayout");\n var theCSS = store.getRecursiveTiddlerText(tiddlerName,"");\n setStylesheet(theCSS,"StyleSheet");\n}\n\n//Excellent (and versatile) reparser created by Paul Petterson for parsing the paramString in a macro\nfunction reparse( params ) {\n var re = /([^:\ss]+)(?:\s:((?:\sd+)|(?:["'](?:[^"']+)["']))|\ss|$)/g;\n var ret = new Array() ;\n var m ;\n while( (m = re.exec( params )) != null ) ret[ m[1] ] = m[2]?m[2]:true ;\n return ret ;\n}\n\nfunction getElementsByClass(searchClass,node,tag) {\n var classElements = new Array();\n if ( node == null ) node = document;\n if ( tag == null ) tag = '*';\n var els = node.getElementsByTagName(tag);\n var elsLen = els.length;\n var pattern = new RegExp("(^|\s\ss)"+searchClass+"(\s\ss|$)");\n var j=0;\n for (var i = 0; i < elsLen; i++) {\n if ( pattern.test(els[i].className) ) {\n classElements[j] = els[i];\n j++;\n }\n }\n return classElements;\n}\n\n// 'keys' code adapted from S5 which in turn was adapted from MozPoint (http://mozpoint.mozdev.org/)\nfunction keys(key) {\n if (document.getElementById('contentWrapper').className == "slideShowMode"){\n if (!key) {\n key = event;\n key.which = key.keyCode;\n }\n switch (key.which) {\n case 32: // spacebar\n if(time>0){\n if(autoAdvance){\n clearInterval(autoAdvance);\n autoAdvance = null;\n } else {\n autoAdvance=setInterval("GoToSlide(1)", time);\n }\n }\n break;\n case 34: // page down\n case 39: // rightkey\n GoToSlide("n");\n break;\n case 40: // downkey\n GoToSlide(-1);\n break;\n case 33: // page up\n case 37: // leftkey\n GoToSlide("p");\n break;\n case 38: // upkey\n GoToSlide(1);\n break;\n case 36: // home\n GoToSlide("f");\n break;\n case 35: // end\n GoToSlide("l");\n break;\n case 27: // escape\n endSlideShow();\n break;\n }\n\n }\n return false;\n}\n\nfunction clicker(e) {\n if (!e) var e = window.event;\n var target = resolveTarget(e);\n //Whenever something is clicked that won't advance the slide make sure that the table of contents gets hidden\n if (target.getAttribute('href') != null || isParentOrSelf(target, 'toc') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object') || isParentOrSelf(target, 'pageFooter') || isParentOrSelf(target, 'navigator')){\n //Don't hide the TOC if the indexNumbers (which trigger the index) is clicked\n if(isParentOrSelf(target,'indexNumbers') || isParentOrSelf(target,'jumpInput')){\n return true;\n }\n showHideTOC('none');\n return true;\n }\n \n //Advance a slide if the TOC is visible otherwise make sure that the TOC gets hidden\n if ((!e.which && e.button == 1) || e.which == 1) {\n if (document.getElementById('toc').style.display != 'block'){\n GoToSlide("n");\n } else {\n showHideTOC('none');\n }\n }\n \n if ((!e.which && e.button == 2) || e.which == 3) {\n if (document.getElementById('toc').style.display != 'block'){\n GoToSlide("p");\n } else {\n showHideTOC('none');\n }\n return false;\n }\n}\n\nfunction isParentOrSelf(element, id) {\n if (element == null || element.nodeName=='BODY') return false;\n else if (element.id == id) return true;\n else return isParentOrSelf(element.parentNode, id);\n}\n\nGoToSlide=function(step) {\n var new_pos;\n var slideHolder = document.getElementById('slideContainer');\n //The parse float ensures that the attribute is returned as a number and not a string.\n var cur_pos = parseFloat(slideHolder.getAttribute('currentslide'));\n var numberSlides = parseFloat(slideHolder.getAttribute('numberSlides'));\n switch (step) {\n case "f":\n new_pos=0;\n break;\n case "l":\n new_pos=numberSlides-1;\n break;\n case "n":\n var numberOverlays = parseFloat(slideHolder.childNodes[cur_pos].getAttribute('numberOverlays'));\n var currentOverlay = parseFloat(slideHolder.getAttribute('currentOverlay'));\n if(numberOverlays==0 || currentOverlay==numberOverlays){\n new_pos=cur_pos+1;\n } else {\n var className="Overlay"+currentOverlay;\n var overlay=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(var i=0; i<overlay.length; i++) {overlay[i].className=className+' previousOverlay';}\n currentOverlay++;\n slideHolder.setAttribute('currentOverlay',currentOverlay);\n className="Overlay"+currentOverlay;\n overlay=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(i=0; i<overlay.length; i++) {overlay[i].className=className+' currentOverlay';}\n return false;\n }\n break;\n case "p":\n var numberOverlays = parseFloat(slideHolder.childNodes[cur_pos].getAttribute('numberOverlays'));\n var currentOverlay = parseFloat(slideHolder.getAttribute('currentOverlay'));\n if(numberOverlays==0 || currentOverlay==0){\n new_pos=cur_pos-1;\n } else {\n var className="Overlay"+currentOverlay;\n var overlays=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(var i=0; i<overlays.length; i++) {overlays[i].className=className+' nextOverlay';}\n currentOverlay--;\n className="Overlay"+currentOverlay;\n overlays=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(i=0; i<overlays.length; i++) {overlays[i].className=className+' currentOverlay';}\n slideHolder.setAttribute('currentOverlay',currentOverlay);\n return false;\n }\n break;\n default:\n new_pos=cur_pos+step;\n }\n\n if(slideShowCircularMode && new_pos == numberSlides) new_pos=0;\n if(slideShowCircularMode && new_pos<0) new_pos=(numberSlides - 1);\n if(step!=0 && new_pos>=0 && new_pos<numberSlides) {\n slideHolder.childNodes[cur_pos].style.display='none';\n slideHolder.childNodes[new_pos].style.display='block';\n slideHolder.setAttribute('currentslide',new_pos);\n var numberOverlays = parseFloat(slideHolder.childNodes[new_pos].getAttribute('numberOverlays'));\n if(step=="p"){\n var currentOverlay=numberOverlays;\n var state=' previousOverlay';\n } else {\n var currentOverlay=0;\n var state=' nextOverlay';\n }\n slideHolder.setAttribute('currentOverlay',currentOverlay);\n if(numberOverlays>0) {\n for(var i=1; i<=numberOverlays; i++){\n var className="Overlay"+i;\n var overlays=getElementsByClass(className,slideHolder.childNodes[new_pos]);\n for(var j=0; j<overlays.length; j++) {overlays[j].className=className+state;}\n }\n if(step=="p"){\n var className="Overlay"+numberOverlays;\n var overlays=getElementsByClass(className,slideHolder.childNodes[new_pos]);\n for(var j=0; j<overlays.length; j++) {overlays[j].className=className+' currentOverlay';}\n }\n }\n new_pos++;\n var indexNumbers = document.getElementById('indexNumbers');\n indexNumbers.firstChild.data = new_pos+'/'+numberSlides;\n if((new_pos==numberSlides) && !slideShowCircularMode && autoAdvance) clearInterval(autoAdvance);\n return true;\n }\n return false;\n}\n\nfunction tocShowSlide(e) {\n if (!e) var e = window.event;\n var target = resolveTarget(e);\n var slide = target.getAttribute('slideNumber');\n var cur_pos = document.getElementById('slideContainer').getAttribute('currentslide');\n var step = slide-cur_pos;\n if(step!=0) GoToSlide(step);\n showHideTOC('none');\n return;\n}\n\n//Toggle the display of the table of contents\nfunction showHideTOC(display){\n var toc = document.getElementById('toc');\n //Reset the input box\n document.getElementById('jumpInput').value = "";\n\n if (display == null || display.length == null){\n if (toc.style.display == 'none' || toc.style.display == ''){\n toc.style.display = 'block';\n document.getElementById('jumpInput').focus();\n } else {\n toc.style.display = 'none';\n }\n } else {\n toc.style.display = display;\n if (display == 'block')\n document.getElementById('jumpInput').focus();\n }\n}\n\nfunction makeSignature(title,params){\n var signature = title+store.getTiddler(title).modified;\n if(params['style']) signature += params['style'];\n if(params['repeat']) signature += "repeat";\n if(params['slidePause'] > 0) signature += params['slidePause'];\n if(params['autostart']) signature += "autostart";\n if(params['clock']) signature += params['clock'];\n if(params['noOverlays']) signature += "noOverlays";\n return signature;\n}\n\nfunction padZero(x){\n return (x>=10 || x<0 ? "" : "0")+x;\n}\n\nsetClock=function(){\n var actualTime = new Date();\n var newTime = actualTime.getTime() - clockStartTime;\n newTime = clockMultiplier*newTime+clockInterval+clockCorrection;\n actualTime.setTime(newTime);\n newTime = padZero(actualTime.getHours()) + ":" + padZero(actualTime.getMinutes())+ ":" + padZero(actualTime.getSeconds());\n var clock = document.getElementById('slideClock');\n clock.firstChild.nodeValue = newTime;\n}\n\nresetClock=function(){\n var time = new Date(0);\n if(clockStartTime>time){\n var startTime = new Date();\n clockStartTime=startTime.getTime();\n }\n}\n\nvar title;\nvar place;\nvar autoAdvance=null;\nvar autoStart=null;\nvar slideClock=null;\nvar noOverlays=false;\nvar time = 0;\nvar slideShowCircularMode;\nvar slideShowStyleSheet;\nvar slideShowParams;\nvar clockMultiplier;\nvar clockInterval;\nvar clockCorrection=0;\nvar clockStartTime;\nvar openTiddlers;\n\nconfig.macros.slideShow.handler = function(aPlace,macroName,params,wikifier,paramString,tiddler){\n if(tiddler instanceof Tiddler){\n var lingo = config.views.wikified.slideShow;\n var autostart = false;\n if (!e) var e = window.event;\n \n place = aPlace;\n title = tiddler.title;\n params = reparse(paramString);\n var onclick = function(){config.macros.slideShow.onClickSlideShow(params);};\n createTiddlyButton(aPlace,lingo.text,lingo.tooltip,onclick);\n \n var slideShowHolder = document.getElementById('slideShowWrapper');\n //If no show exist previously, create it\n if(params['autostart']){\n if(slideShowHolder != null){\n var signature = slideShowHolder.getAttribute('showSignature');\n if(signature.indexOf("autostart")==-1) autostart = true;\n } else {autostart = true;}\n if(autostart){\n slideShowParams = params;\n setTimeout(config.macros.slideShow.onClickSlideShow,100);\n }\n }\n }\n}\n\nvar disableFunction = function(e){return false;}\nvar enableFunction = function(e){}\n\nconfig.macros.slideShow.onClickSlideShow = function(newParams) {\n if(typeof(newParams)=="number") newParams=slideShowParams;\n openTiddlers = new Array;\n var viewer=document.getElementById('tiddlerDisplay');\n for(var i=0; i<viewer.childNodes.length; i++){\n var name = viewer.childNodes[i].getAttribute('tiddler');\n openTiddlers.push(name);\n }\n document.oncontextmenu = disableFunction;\n clockMultiplier = 1;\n clockInterval = 0;\n var startTime = new Date(0);\n slideShowCircularMode = false;\n time = 0;\n slideShowStyleSheet = null;\n if(newParams['style']){\n slideShowStyleSheet = eval(newParams['style']);\n } \n if(newParams['repeat']){\n slideShowCircularMode = true;\n }\n if(newParams['slidePause'] > 0){\n time = newParams['slidePause'];\n }\n if(newParams['clock']){\n clockCorrection=startTime.getTimezoneOffset()*60000;\n startTime = new Date();\n var clockType= eval(newParams['clock']);\n if(clockType != '+') {\n clockMultiplier = -1;\n clockInterval = -clockType*60000;\n }\n }\n clockStartTime=startTime.getTime();\n if(newParams['noOverlays']){\n noOverlays = true;\n }\n var contentWrapper = document.getElementById('contentWrapper');\n if (contentWrapper.className != "slideShowMode"){\n clearMessage();\n //Attach the key and mouse listeners\n document.onkeyup = keys;\n document.onmouseup = clicker;\n \n var slideShowHolder = document.getElementById('slideShowWrapper');\n //If no show exist previously, create it\n if(slideShowHolder == null){\n createSlides(newParams);\n //If there was once waiting in the background and it matches the one we just started, resume it\n } else if (slideShowHolder.getAttribute('showSignature') == makeSignature(title,newParams)){\n \n //Remove dblClick on edit function\n var theTiddler = document.getElementById("tiddler"+title);\n theTiddler.ondblclick = function() {};\n\n // Grab the 'viewer' element and give it a signature so the show can be resumed if stopped\n var tiddlerElements = theTiddler.childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer") viewer = tiddlerElements[i];\n }\n theTiddler.insertBefore(slideShowHolder,viewer);\n theTiddler.removeChild(viewer);\n slideShowHolder.style.display = 'block';\n document.getElementById("pageFooter").className = "pageFooterOff";\n \n //If the show we started it totally new than the resumable one, create the new one and kill the resumable one\n } else {\n slideShowHolder.parentNode.removeChild(slideShowHolder);\n createSlides(newParams);\n }\n slideClock=setInterval("setClock()", 1000); \n if(time>0) autoAdvance=setInterval("GoToSlide(1)", time); \n story.closeAllTiddlers(title);\n toggleSlideStyles();\n } else {\n endSlideShow();\n }\n return ;\n \n}\n\nfunction endSlideShow(){\n //Set aside show so it can be resumed later\n var showHolder = document.getElementById('slideShowWrapper');\n showHolder.style.display = 'none';\n document.getElementById('contentWrapper').parentNode.appendChild(showHolder);\n document.oncontextmenu = enableFunction;\n if(autoAdvance) clearInterval(autoAdvance);\n if(slideClock) clearInterval(slideClock);\n story.refreshTiddler(title,null,true);\n story.closeAllTiddlers();\n toggleSlideStyles();\n story.displayTiddlers(null,openTiddlers,DEFAULT_VIEW_TEMPLATE);\n document.onmouseup = function(){};\n}\n\nfunction isInteger(s){\n var i;\n for (i = 0; i < s.length; i++){\n // Check that current character is number.\n var c = s.charAt(i);\n if (((c < "0") || (c > "9"))) return false;\n }\n // All characters are numbers.\n return true;\n}\n\nfunction jumpInputToSlide(e){\n if (!e) {\n e = window.event;\n e.which = e.keyCode;\n }\n if(e.which==13){\n var jumpInput= document.getElementById("jumpInput").value;\n if(isInteger(jumpInput)){\n var step=jumpInput-document.getElementById('slideContainer').getAttribute('currentslide')-1;\n if (GoToSlide(step)){\n showHideTOC('none'); \n }\n }\n }\n return;\n}\n\n//Used to shorten the TOC fields\nfunction abbreviateLabel(label){\n var maxTOCLength = config.macros.slideShow.maxTOCLength;\n if(label.length>maxTOCLength) {\n var temp = new Array();\n temp = label.split(' ');\n label = temp[0];\n for(var j=1; j<temp.length; j++){\n if((label.length+temp[j].length)<=maxTOCLength){\n label += " " + temp[j];\n } else {\n label += " ...";\n break;\n }\n }\n }\n return label;\n}\n\ncreateSlides = function(newParams){\n var lingo = config.views.wikified.slideShow;\n\n //Remove dblClick on edit function\n var theTiddler = document.getElementById("tiddler"+title);\n theTiddler.ondblclick = function() {};\n\n // Grab the 'viewer' element and give it a signature so the show can be resumed if stopped\n var tiddlerElements = theTiddler.childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer") viewer = tiddlerElements[i];\n }\n viewer.id = 'slideShowWrapper';\n viewer.setAttribute("showSignature",makeSignature(title,newParams));\n\n //Hide the text that comes before the first H1 element (I think I may put this into a cover page type thing)\n while(viewer.childNodes.length > 0 && viewer.firstChild.nodeName.toUpperCase() != "HR" && viewer.firstChild.className!="slideSeparator") {\n viewer.removeChild(viewer.firstChild);\n }\n \n //Cycle through the content and each time you hit an H1 begin a new slide div\n var slideNumber = 0;\n var slideHolder = document.createElement('DIV');\n slideHolder.id = "slideContainer";\n \n while(viewer.childNodes.length > 0){\n //Create a new slide a append it to the slide holder\n if (viewer.firstChild.nodeName.toUpperCase() == "HR" && viewer.firstChild.className=="slideSeparator"){\n slideNumber++;\n var slide = document.createElement('DIV');\n slide.id = "slideNumber"+slideNumber;\n slide.className = "slide";\n if (slideNumber > 1) {\n slideHolder.setAttribute('currentslide',0);\n slide.style.display='none';\n } else {\n slide.style.display='block';\n }\n slideHolder.appendChild(slide); \n viewer.removeChild(viewer.firstChild);\n } else {\n if(viewer.firstChild.nodeName=="SPAN" && viewer.firstChild.className=="" && viewer.firstChild.hasChildNodes()) {\n var anchor=viewer.firstChild.nextSibling;\n for (var ii=0;ii<viewer.firstChild.childNodes.length;ii++) {\n var clone=viewer.firstChild.childNodes[ii].cloneNode(true);\n viewer.insertBefore(clone,anchor);\n }\n viewer.removeChild(viewer.firstChild);\n } else {\n slide.appendChild(viewer.firstChild);\n }\n }\n }\n \n //Stick the slides back into the viewer\n viewer.appendChild(slideHolder);\n slideHolder.setAttribute('numberSlides',slideNumber);\n \n //Create the navigation bar\n var pagefooter = createTiddlyElement(viewer,"DIV","pageFooter","pageFooterOff");\n var navigator = createTiddlyElement(pagefooter,"SPAN","navigator");\n\n //Make it so that when the footer is hovered over the class will change to make it visible\n pagefooter.onmouseover = function () {pagefooter.className = "pageFooterOn"};\n pagefooter.onmouseout = function () {pagefooter.className = "pageFooterOff"};\n\n //Create the control button for the navigation \n var onClickQuit = function(){endSlideShow();};\n createTiddlyButton(navigator,lingo.quit.text,lingo.quit.tooltip,onClickQuit);\n createTiddlyButton(navigator,lingo.firstSlide.text,lingo.firstSlide.tooltip,first_slide);\n createTiddlyButton(navigator,lingo.previousSlide.text,lingo.previousSlide.tooltip,previous_slide);\n createTiddlyButton(navigator,lingo.nextSlide.text,lingo.nextSlide.tooltip,next_slide);\n createTiddlyButton(navigator,lingo.lastSlide.text,lingo.lastSlide.tooltip,last_slide); \n createTiddlyButton(navigator,lingo.resetClock.text,lingo.resetClock.tooltip,resetClock,"button","slideClock"); \n\n var indexNumbers = createTiddlyElement(pagefooter,"SPAN","indexNumbers","indexNumbers","1/"+slideNumber)\n indexNumbers.onclick = showHideTOC;\n var toc = createTiddlyElement(pagefooter,"UL","toc");\n var ovl=1;\n for (var i=0;i<slideHolder.childNodes.length;i++) {\n if(!noOverlays) {\n var ovl=1;\n while(1){\n var className="Overlay"+ovl;\n var overlays=getElementsByClass(className,slideHolder.childNodes[i]);\n if(overlays.length>0){\n for(var j=0; j<overlays.length; j++) {overlays[j].className+=' nextOverlay';}\n ovl++;\n } else {break;}\n }\n }\n slideHolder.childNodes[i].setAttribute("numberOverlays",ovl-1);\n slideHolder.setAttribute("currentOverlay",0);\n\n //Loop through each slide and check the header's content\n var tocLabel = null; \n for (var j=0;j<slideHolder.childNodes[i].childNodes.length;j++) {\n var node = slideHolder.childNodes[i].childNodes[j];\n if(node.nodeName=="H1" || node.nodeName=="H2" || node.nodeName=="H3" || node.nodeName=="H4") {\n var htstring = node.innerHTML;\n var stripped = htstring.replace(/(<([^>]+)>)/ig,"");\n tocLabel = abbreviateLabel(stripped);\n var tocLevel="tocLevel"+node.nodeName.charAt(1);\n var tocItem = createTiddlyElement(toc,"LI",null,tocLevel);\n var tocLink = createTiddlyElement(tocItem,"A",null,"tocItem",tocLabel);\n tocLink.setAttribute("slideNumber",i);\n tocLink.onclick=tocShowSlide;\n }\n }\n }\n \n\n //Input box to jump to s specific slide\n var tocItem = createTiddlyElement(toc,"LI",null,"tocJumpItem",config.macros.slideShow.messages.gotoLabel);\n var tocJumpInput = createTiddlyElement(tocItem,"INPUT","jumpInput");\n tocJumpInput.type="text";\n tocJumpInput.onkeyup=jumpInputToSlide;\n}\n\nvar next_slide= function(e){GoToSlide(1);}\nvar first_slide= function(e){GoToSlide("f");}\nvar previous_slide= function(e){GoToSlide(-1);}\nvar last_slide= function(e){GoToSlide("l");}\n\nfunction toggleSlideStyles(){\n var contentWrapper = document.getElementById('contentWrapper');\n if (contentWrapper.className == "slideShowMode"){\n contentWrapper.className = "";\n if(slideShowStyleSheet) changeStyleSheet();\n } else{\n contentWrapper.className = "slideShowMode";\n if(slideShowStyleSheet) changeStyleSheet(slideShowStyleSheet);\n }\n}\n\nsetStylesheet("/***\sn!Slide Mode Styles\sn***/\sn/*{{{*/\sn#contentWrapper.slideShowMode #slideContainer{\sn display: block;\sn}\sn\sn#contentWrapper.slideShowMode .Comment{\sn display: none;\sn}\sn\sn#contentWrapper.slideShowMode .nextOverlay{\sn visibility: hidden;\sn}\sn\sn#contentWrapper.slideShowMode .currentOverlay{\sn visibility: visible;\sn}\sn\sn#contentWrapper.slideShowMode .previousOverlay{\sn visibility: visible;\sn}\sn\sn#jump{\sn text-align: right;\sn}\sn\sn.pageFooterOff #navigator{\sn visibility: hidden;\sn}\sn\sn.pageFooterOn #navigator{\sn visibility: visible;\sn}\sn\sn#contentWrapper.slideShowMode #slideClock{\sn cursor: pointer; margin: 0 5px 0 5px; border: 1px solid #db4\sn}\sn\sn#contentWrapper.slideShowMode,\sn #contentWrapper.slideShowMode #displayArea{\sn width: 100%;\sn font-size: 1.5em;\sn margin: 0 !important;\sn padding: 0;\sn}\sn\sn#slideContainer{\sn display: none;\sn}\sn\sn#contentWrapper.slideShowMode #sidebar,\sn#contentWrapper.slideShowMode #mainMenu,\sn#contentWrapper.slideShowMode .header,\sn#contentWrapper.slideShowMode #displayArea .toolbar,\sn#contentWrapper.slideShowMode #displayArea .footer,\sn#contentWrapper.slideShowMode #displayArea .subtitle,\sn#contentWrapper.slideShowMode #displayArea .tagged,\sn#contentWrapper.slideShowMode #displayArea .tagging\sn{\sn display:none !important;\sn}\sn\sn.indexNumbers{\sn cursor: pointer;\sn}\sn\sn#navigator{\sn visibility: hidden;\sn bottom: 0;\sn}\sn\sn#toc{\sn display: none;\sn position: absolute;\sn font-size: .75em;\sn bottom: 2em;\sn right: 0;\sn background: #fff;\sn border: 1px solid #000;\sn text-align: left;\sn}\sn\snul#toc, #toc li{\sn margin: 0;\sn padding: 0;\sn list-style: none;\sn line-height: 1em;\sn}\sn\sn.tocJumpItem{\sn margin-right: 2em;\sn}\sn\sn.tocJumpItem input{\snmargin-right: 1em;\sn border: 0;\sn}\sn\sn#toc a,\sn#toc a.button{\sn display: block;\sn padding: .1em;\sn}\sn\sn#toc .tocLevel1{\snfont-size: .8em;\sn}\sn\sn#toc .tocLevel2{\sn margin-left: 1em;\sn font-size: .75em;\sn}\sn\sn#toc .tocLevel3{\sn margin-left: 2em;\snfont-size: .75em;\sn}\sn\sn#toc .tocLevel4{\sn margin-left: 3em;\snfont-size: .65em;\sn}\sn\sn#toc a{\sn cursor: pointer;\sn}\sn\snh1{\sn min-height: 1em;\sn}\sn\sn.slide h1{\sn min-height: 0;\sn}\sn\sn/* The '>' selector is ignored by IE6 and earlier so the proper rules are given */\sn#pageFooter{\sn position: fixed;\sn bottom: 2px;\sn right: 2px;\sn width: 100%;\sn text-align: right;\sn}\sn\sn/* This is a hack to trick IE6 and earlier to put the navbar on the bottom of the page */\sn* html #pageFooter {\sn position: absolute;\sn width: 100%;\sn text-align: right;\sn right: auto; bottom: auto;\sn left: expression( ( -20 - pageFooter.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );\sn top: expression( ( -10 - pageFooter.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );\sn}\sn\sn\sn\sn/*}}}*/","slideShowStyles");\n//}}}
!Description\nThis plugin turns a TiddlyWiki tiddler into a simple slide show type display. Most features that are usually found in presentation software are available. It should work in a way that does not interfere with TiddlyWiki. When you close the slide show you get back to your good old TW. \n\nThis plugin has been tested in Firefox and Internet Explorer. Let me know if something seems broken.\n\n@@WARNING:@@ this plugin relies on a standard TW layout. Some changes to that layout may lead to improper and unexpected behaviour.\n!Usage\nTo use this plugin you //must// be using TiddlyWiki 2.0. Some optional features (as the incremental display) require version 2.0.8 or higher. To install the plugin copy this tiddler to your TW, label it with the //systemConfig// tag, save the TW and refresh the browser.\n\nTo make a slide show simply drop {{{<<slideShow>>}}} at the beginning of a tiddler and use {{{--s--}}} to start each slide. \n\nIf you move your mouse over the bottom of the browser window you will see a few navigation buttons, a clock and a table of contents that shows up when you click the slide number.\n\nAny block of text marked as {{{{{Comment{For my eyes only!}}}}}} will not be displayed in the slide show.\n\nSee these and other features in this [[SlideShowExample]].\n!Incremental display\nA succession of overlays (or layers) can be defined in each slide by marking blocks of text with {{{{{Overlay1{...some text...}}}}}}, {{{{{Overlay2{...some text...}}}}}}, {{{{{Overlay3{...some text...}}}}}}, ...\n\nTo costumize the way overlays are shown you can redefine the following CSS classes\n*contentWrapper.slideShowMode .previousOverlay \n*contentWrapper.slideShowMode .currentOverlay \n*contentWrapper.slideShowMode .nextOverlay \nin a ~StyleSheet. The default style simply hides the next overlays and shows the current and the previous ones as normal text.\n!Slide show parameters\n*The slide show can be themed by providing a ~StyleSheet ({{{<<slideShow style:'MyStyleSheet'>>}}})\n*By default, there is a clock at bottom of the browser window that displays the current time. This clock can also show the presentation elapsed time with {{{<<slideShow clock:'+'>>}}} or a countdown clock with {{{<<slideShow clock:'-20'>>}}} (for 20 minutes). In these two cases, if you click on the clock display it will be restarted\n*The slide show can be set to loop ({{{<<slideShow repeat>>}}})\n*You can set it so each slide changes after X milliseconds ({{{<<slideShow slidePause:X>>}}}) (auto advance mode)\n*Use auto start mode to begin the slideshow the moment the tiddler is opened ({{{<<slideShow autostart>>>}}})\n*You can disable overlays with {{{<<slideShow noOverlays>>}}}\n*These parameters can be mixed and matched in any order: {{{<<slideShow slidePause:1000 repeat>>}}} is the same as {{{<<slideShow repeat slidePause:1000>>}}}\n!Slide show navigation\nYou can navigate through a slide show using the keyboard or the mouse. To quickly move to titled sections you can use the table of contents. \n!!Mouse navigation\nLeft (right) clicking on a slide jumps to the next (previous) overlay. To move to the beginning of the next or previous slide you must use the navigation bar at the bottom of the browser's window. If there are no overlays defined both operations are equivalent.\n!!Keyboard navigation\nThe following keys are defined:\n*Left arrow - previous overlay\n*Down arrow - previous slide\n*Right arrow - next overlay\n*Up arrow - next slide\n*Home - first slide\n*End - last slide\n*Escape - exit slide show\n*Spacebar - pause/resume slide show in auto advance mode\n!Revision history\n*v1.4.0 20/04/2006\n**changed to way how slides are separated (slide shows prepared for previous versions must be fixed)\n**now works with content included with the {{{<<tiddler>>}}} macro\n**added incremental display (overlays)\n**improved documentation\n**assorted small fixes\n*v1.3.1 10/03/2006\n**removed empty slide titles\n**fixed wrong numberSlides when slides have div's\n**fixed wrong time in Windows\n*v1.3.0 26/02/2006\n**restore open tiddlers on exit\n**fixed problem with markup in headers (should work with NestedSlidersPlugin)\n**added slide comments (blocks of text in the tiddler that don't show up in the presentation)\n*v1.2.1 28/01/2006\n**pause timed slideshow with spacebar\n**added clock with 3 different modes\n**fixed bugs with style and abbreviation options\n**general cleanup\n*v1.2.0 07/01/2006\n**added a resume feature\n**added themes support\n*v1.1.5 14/12/2005\n**added mouse support\n**cleaned up navbar generation\n*v1.1.0 12/12/2005\n**added support for IE\n**added key listeners\n*v1.0.0 11/12/2005\n**initial release\n!Todo\n*Time code is still very hackerish and unreliable.
A simple slide show that keeps the TW style: <<slideShow>>\nA themed slide show with a clock showing the presentation elapsed time: <<slideShow style:'MySSStyleSheet' clock:'+'>>\nA looping slide show with a 20 minutes countdown clock: <<slideShow repeat clock:'-20'>>\nA timed slideshow that runs once: <<slideShow slidePause:1000>>\nA timed looping slideshow: <<slideShow slidePause:1000 repeat>>\nA slideshow with a customized table of contents labels: <<slideShow tocLabel:'Goto:'>>\n!The [[Slide Show]] Plugin\nPress F11 to go fullscreen and adjust the font sizes with Ctrl++ Ctrl+- (or Ctrl+mousewheel).\n\nThis slideshow was developed by Paulo Soares and Clint Checketts\n%%This block is not shown in the slide show.\n@@Don't show me!!!@@%%\n!How slides are separated\nIn a tiddler, you just separate each slide by putting in a new level 1 heading (use a {{{!}}} to delimit H1 headings)\n!\nTiddlers don't have to have titles, just put a {{{!}}}alone on its own line (as seen in this tiddler)\n!A slide with subsections and a long title\nCheck to TOC below to see how the slide title is abbreviated.\n!!Section 1\nThis is a section\n!!!Subsection 1.1\nThis is a subsection\n!!!Subsection 1.2\nThis is another subsection\n!!!!Subsubsection 1.2.1\nThis is a subsubsection\n!Using the keyboard\n*Use the Right Arrow, Spacebar, or Page Down keys to advance a page\n*Use the Left Arrow and Page Up keys to go back a page\n*Use the Home key to go to the beginning\n*Use the End key to jump to the last slide\n*Use the Escape key to exit Slide Mode\n!Using the mouse\n*Left clicking in a slide advances it forward one slide\n*Right click moves the slideshow back one slide. This can be disabled using a parameter.\n!Slide Show Parameters\n*The slide show can be themed ({{{<<slideMode style:'MyStyleSheet'>>}}})\n*The slide show can be set to loop ({{{<<slideMode repeat>>}}})\n*You can set it so each slide changes after X milliseconds ({{{<<slideShow slidePause:X>>}}})\n*Slide without labels are left out of the Table of Contents by default. To enable them, initialize the slide show with a default label for those slides ({{{<<slideShow tocLabel:'Goto:'>>}}})\n*Use auto start mode to begin the slideshow the moment the tiddler is opened ({{{<<slideMode autostart>>>}}})\n*These parameters can be mixed and matched in any order: {{{<<slideShow slidePause:1000 repeat>>}}} is the same as {{{<<slideShow repeat slidePause:1000>>}}}\n!Future ideas\n*Incremental advancement within a slide\n*Cross fade effects\n----\nYou can hide comments on a slide that won't display in the slide show by placing them after a horizontal break.
// Begin SORTABLE.JS//\n// This Code is://\n// Code downloaded from the Browser Experiments section of kryogenix.org is licenced under the so-called MIT licence. The license is below.//\n////\n// Copyright (c) 1997-date Stuart Langridge//\n////\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this //\n// software and associated documentation files (the "Software"), to deal in the Software //\n// without restriction, including without limitation the rights to use, copy, modify, merge, //\n// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons //\n// to whom the Software is furnished to do so, subject to the following conditions://\n////\n// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //\n// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR //\n// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE //\n// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR //\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //\n// DEALINGS IN THE SOFTWARE.//\n// //\n// //\n// Modified under the same aforementioned terms by Demian Johnston, 2006//\n/*\n! Test Cases\nSortable\nGrid requires the header row to be marked "|h"\n\n|Name |Salary|Extension |Start date|h\n|Bloggs, Fred |$12000.00 |1353|08/19/2003|\n|Bloggs, Fred |$12000.00 |1353|09/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/18/2003|\n|Bloggs, Fred |$12000.00 |1353|07/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/17/2003|\n|Turvey, Kevin |$191200.00 |2342 |02/05/1979|\n|Mbogo, Arnold |$32010.12 |2755 |09/08/1998|\n|Shakespeare, Bill |$122000.00|3211 |12/11/1961|\n|Shakespeare, Hamnet |$9000 |9005|01/01/2002|\n|Fitz, Marvin |$3300 |5554 |05/22/1995|\n\nUnsortableGrid (doesn't mark header row)\n\n|Name |Salary|Extension |Start date|\n|Bloggs, Fred |$12000.00 |1353|08/19/2003|\n|Bloggs, Fred |$12000.00 |1353|09/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/18/2003|\n|Bloggs, Fred |$12000.00 |1353|07/18/2003|\n|Bloggs, Fred |$12000.00 |1353|08/17/2003|\n|Turvey, Kevin |$191200.00 |2342 |02/05/1979|\n|Mbogo, Arnold |$32010.12 |2755 |09/08/1998|\n|Shakespeare, Bill |$122000.00|3211 |12/11/1961|\n|Shakespeare, Hamnet |$9000 |9005|01/01/2002|\n|Fitz, Marvin |$3300 |5554 |05/22/1995|\n\nCredit to Stuart Langridge,November 2003\nhttp://www.kryogenix.org/code/browser/sorttable/\n*/\n//{{{\nversion.extensions.sortableGrid= {major: 1, minor: 0, revision: 0, date: new Date(2006,2,14)};\n//}}}\n//{{{\nconfig.macros.sortableGridPlugin = {SORT_COLUMN_INDEX: 0};\n\nconfig.macros.sortableGridPlugin.ts_makeSortable=function(table) {\n var firstRow;\n if (table.rows && table.rows.length > 0) {\n firstRow = table.rows[0];\n }\n if (!firstRow) return;\n \n // We have a first row: assume it's the header, and make its contents clickable links\n for (var i=0;i<firstRow.cells.length;i++) {\n var cell = firstRow.cells[i];\n var txt = config.macros.sortableGridPlugin.ts_getInnerText(cell);\n cell.innerHTML = '<a href="#" class="sortheader" onclick="config.macros.sortableGridPlugin.ts_resortTable(this);return false;">'+txt+'<span class="sortarrow"> </span></a>';\n }\n};\n//}}}\n\n//{{{\nconfig.macros.sortableGridPlugin.ts_getInnerText=function(el) {\n if (typeof el == "string") return el;\n if (typeof el == "undefined") { return el };\n if (el.innerText) return el.innerText; //Not needed but it is faster\n var str = "";\n \n var cs = el.childNodes;\n var l = cs.length;\n for (var i = 0; i < l; i++) {\n switch (cs[i].nodeType) {\n case 1: //ELEMENT_NODE\n str += config.macros.sortableGridPlugin.ts_getInnerText(cs[i]);\n break;\n case 3: //TEXT_NODE\n str += cs[i].nodeValue;\n break;\n }\n }\n return str;\n};\n\nconfig.macros.sortableGridPlugin.getParent=function(el, pTagName) {\n if (el == null) return null;\n else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase\n return el;\n else\n return config.macros.sortableGridPlugin.getParent(el.parentNode, pTagName);\n};\n//}}}\n\n//{{{\nconfig.macros.sortableGridPlugin.ts_resortTable=function(lnk) {\n // get the span\n var span;\n for (var ci=0;ci<lnk.childNodes.length;ci++) {\n if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];\n }\n var td = lnk.parentNode;\n var column = td.cellIndex;\n var table = config.macros.sortableGridPlugin.getParent(td,'TABLE');\n \n // Work out a type for the column\n if (table.rows.length <= 1) return;\n var itm = config.macros.sortableGridPlugin.ts_getInnerText(table.rows[1].cells[column]);\n var sortfn = config.macros.sortableGridPlugin.ts_sort_caseinsensitive;\n if (itm.match(/^\sd\sd[\s/-]\sd\sd[\s/-]\sd\sd\sd\sd$/)) sortfn = config.macros.sortableGridPlugin.ts_sort_date;\n if (itm.match(/^\sd\sd[\s/-]\sd\sd[\s/-]\sd\sd$/)) sortfn = config.macros.sortableGridPlugin.ts_sort_date;\n if (itm.match(/^[?$]/)) sortfn = config.macros.sortableGridPlugin.ts_sort_currency;\n if (itm.match(/^[\sd\s.]+$/)) sortfn = config.macros.sortableGridPlugin.ts_sort_numeric;\n config.macros.sortableGridPlugin.SORT_COLUMN_INDEX = column;\n var firstRow = new Array();\n var newRows = new Array();\n for (var i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }\n for (var j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }\n\n newRows.sort(sortfn);\n var ARROW;\n if (span.getAttribute("sortdir") == 'down') {\n ARROW = ' ↑';\n newRows.reverse();\n span.setAttribute('sortdir','up');\n } else {\n ARROW = ' ↓';\n span.setAttribute('sortdir','down');\n }\n \n // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones\n // don't do sortbottom rows\n for ( i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}\n // do sortbottom rows only\n for ( i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}\n \n // Delete any other arrows there may be showing\n var allspans = document.getElementsByTagName("span");\n for ( ci=0;ci<allspans.length;ci++) {\n if (allspans[ci].className == 'sortarrow') {\n if (config.macros.sortableGridPlugin.getParent(allspans[ci],"table") == config.macros.sortableGridPlugin.getParent(lnk,"table")) { // in the same table as us?\n allspans[ci].innerHTML = ' ';\n }\n }\n }\n \n span.innerHTML = ARROW;\n};\n//}}}\n\n//{{{\n config.macros.sortableGridPlugin.ts_sort_date=function(a,b) {\n // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX\n var mmdd=1; // US Mode (set to 0) for dd/mm/yyyy\n\n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n var dt1;\n var dt2;\n var yr;\n if (aa.length == 10) {\n if (mmdd)\n dt1 = aa.substr(6,4)+aa.substr(0,2)+aa.substr(3,2);\n else\n dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);\n } else {\n yr = aa.substr(6,2);\n if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }\n if (mmdd)\n dt1 = yr+aa.substr(0,2)+aa.substr(3,2);\n else\n dt1 = yr+aa.substr(3,2)+aa.substr(0,2);\n }\n if (bb.length == 10) {\n if (mmdd)\n dt2 = bb.substr(6,4)+bb.substr(0,2)+bb.substr(3,2);\n else\n dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);\n } else {\n yr = bb.substr(6,2);\n if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }\n if (mmdd)\n dt2 = yr+bb.substr(0,2)+bb.substr(3,2);\n else\n dt2 = yr+bb.substr(3,2)+bb.substr(0,2);\n }\n if (dt1==dt2) return 0;\n if (dt1<dt2) return -1;\n return 1;\n};\n\n config.macros.sortableGridPlugin.ts_sort_currency=function(a,b) { \n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');\n return parseFloat(aa) - parseFloat(bb);\n};\n\n config.macros.sortableGridPlugin.ts_sort_numeric=function(a,b) { \n var aa = parseFloat(config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]));\n if (isNaN(aa)) aa = 0;\n var bb = parseFloat(config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX])); \n if (isNaN(bb)) bb = 0;\n return aa-bb;\n};\n\n config.macros.sortableGridPlugin.ts_sort_caseinsensitive=function(a,b) {\n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).toLowerCase();\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]).toLowerCase();\n if (aa==bb) return 0;\n if (aa<bb) return -1;\n return 1;\n};\n\n config.macros.sortableGridPlugin.ts_sort_default=function(a,b) {\n var aa = config.macros.sortableGridPlugin.ts_getInnerText(a.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n var bb = config.macros.sortableGridPlugin.ts_getInnerText(b.cells[config.macros.sortableGridPlugin.SORT_COLUMN_INDEX]);\n if (aa==bb) return 0;\n if (aa<bb) return -1;\n return 1;\n};\n//}}}\n\n// end Code downloaded from the Browser Experiments section of kryogenix.org is licenced under the so-called MIT licence. The license is below.//\n// //\n// end Copyright (c) 1997-date Stuart Langridge//\n// END SORTABLE.JS//\n\n\n\n//{{{\nconfig.formatters[0].handler=function(w)\n {\n var table = createTiddlyElement(w.output,"table");\n w.nextMatch = w.matchStart;\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n var currRowType = null, nextRowType;\n var rowContainer, rowElement;\n var prevColumns = [];\n var rowCount = 0;\n var want_sortable=0;\n do {\n lookaheadRegExp.lastIndex = w.nextMatch;\n var lookaheadMatch = lookaheadRegExp.exec(w.source);\n var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;\n if(matched)\n {\n nextRowType = lookaheadMatch[2];\nif(nextRowType == "k")\n {\n table.className = lookaheadMatch[1];\n w.nextMatch += lookaheadMatch[0].length+1;\n continue;\n }\n if(nextRowType != currRowType)\n rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);\n currRowType = nextRowType;\n if(currRowType == "c")\n {\n if(rowCount == 0)\n rowContainer.setAttribute("align","top");\n else\n rowContainer.setAttribute("align","bottom");\n w.nextMatch = w.nextMatch + 1;\n w.subWikify(rowContainer,this.rowTerminator);\n table.insertBefore(rowContainer,table.firstChild);\n }\n else\n {\n var rowClass = (rowCount & 1) ? "oddRow" : "evenRow";\n rowElement = createTiddlyElement(rowContainer,"tr",null,rowClass);\n this.rowHandler(w,rowElement,prevColumns);\n }\n if(currRowType == "h") {\n want_sortable=1;\n }\n rowCount++;\n }\n } while(matched);\n if (want_sortable) {\n table.setAttribute("class","sortable");\n config.macros.sortableGridPlugin.ts_makeSortable(table);\n }\n };\n\n//}}}
/***\nCosmetic fixes that probably should be included in a future TW...\n***/\n/*{{{*/\n.viewer .listTitle { list-style-type:none; margin-left:-2em; }\n.editorFooter .button { padding-top: 0px; padding-bottom:0px; }\n/*}}}*/\n/***\nImportant stuff. See TagglyTaggingStyles and HorizontalMainMenuStyles\n***/\n/*{{{*/\n[[TagglyTaggingStyles]]\n[[HorizontalMainMenuStyles]]\n/*}}}*/\n/***\nClint's fix for weird IE behaviours\n***/\n/*{{{*/\nbody {position:static;}\n.tagClear{margin-top:1em;clear:both;}\n/*}}}*/\n/***\nJust colours, fonts, tweaks etc. See SideBarWhiteAndGrey\n***/\n/*{{{*/\nbody {background:#eee; /* font-size:103%; */}\na{ color: #069; }\na:hover{ background: #069; color: #fff; }\n.popup { background: #178; border: 1px solid #069; }\n.headerForeground a { color: #6fc;}\n.headerShadow { left: 2px; top: 2px; }\n.title { padding:0px; margin:0px; }\n.siteSubtitle { padding:0px; margin:0px; padding-left:1.5em; }\n.subtitle { font-size:90%; color:#ccc; padding-left:0.25em; }\nh1,h2,h3,h4,h5 { color: #000; background: transparent; }\n.title {color:black; font-size:2em;}\n.shadow .title {color:#999; }\n.viewer pre { background-color:#f8f8ff; border-color:#ddf; }\n.viewer { padding-top:0px; }\n.editor textarea { font-family:"Lucida Typewriter","Lucida Console",monospace; }\n#sidebarOptions { border:1px #ccc solid; }\n.tiddler {\n border-bottom:1px solid #ccc; border-right:1px solid #ccc; padding-bottom:1em; margin-bottom:1em; margin-right:3em;\n background:#fff; padding-right:1.5em; }\n#messageArea { background-color:#bde; border-color:#8ab; border-width:4px; border-style:dotted; font-size:90%; }\n#messageArea .button { text-decoration:none; font-weight:bold; background:transparent; border:0px; }\n#messageArea .button:hover {background: #acd; }\n[[SideBarWhiteAndGrey]]\n\n#adsense {\n margin: 1em 15.7em 0em 1em; border:1px solid #ddd;\n background:#f8f8f8; text-align:center;margin-bottom:1em;overflow:hidden;padding:0.5em;} \n/*}}}*/\n/*{{{*/\n/* for testing clint's new formatter. eg {{red{asdfaf}}} */\n.red { color:white; background:red; display:block; padding:1em; } \n\n/* FF doesn't need this. but IE seems to want to make first one white */\n.txtMainTab .tabset { background:#eee; }\n.txtMoreTab .tabset { background:transparent; }\n\n/*}}}*/\n
/***\n!Colors Used\n*@@bgcolor(#8cf): #8cf - Background blue@@\n*@@bgcolor(#18f): #18f - Top blue@@\n*@@bgcolor(#04b): #04b - Mid blue@@\n*@@bgcolor(#014):color(#fff): #014 - Bottom blue@@\n*@@bgcolor(#ffc): #ffc - Bright yellow@@\n*@@bgcolor(#fe8): #fe8 - Highlight yellow@@\n*@@bgcolor(#db4): #db4 - Background yellow@@\n*@@bgcolor(#841): #841 - Border yellow@@\n*@@bgcolor(#703):color(#fff): #703 - Title red@@\n*@@bgcolor(#866): #866 - Subtitle grey@@\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n background: #fff;\n color: #000;\n}\n\na{\n color: #04b;\n}\n\na:hover{\n background: #04b;\n color: #fff;\n}\n\na img{\n border: 0;\n}\n\nh1,h2,h3,h4,h5 {\n color: #703;\n background: #8cf;\n}\n\n.button {\n color: #014;\n border: 1px solid #fff;\n}\n\n.button:hover {\n color: #014;\n background: #fe8;\n border-color: #db4;\n}\n\n.button:active {\n color: #fff;\n background: #db4;\n border: 1px solid #841;\n}\n\n/*}}}*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n.header {\n background: #FFF;\n}\n\n.headerShadow {\n color: #000;\n}\n\n.headerShadow a {\n font-weight: normal;\n color: #000;\n}\n\n.headerForeground {\n color: #fff;\n}\n\n.headerForeground a {\n font-weight: normal;\n color: #8cf;\n}\n\n/*}}}*/\n/***\n!General tabs /%=================================================%/\n***/\n/*{{{*/\n\n.tabSelected{\n color: #014;\n background: #eee;\n border-left: 1px solid #ccc;\n border-top: 1px solid #ccc;\n border-right: 1px solid #ccc;\n}\n\n.tabUnselected {\n color: #fff;\n background: #999;\n}\n\n.tabContents {\n color: #014;\n background: #eee;\n border: 1px solid #ccc;\n}\n\n.tabContents .button {\n border: 0;}\n\n/*}}}*/\n/***\n!Sidebar options /%=================================================%/\n~TiddlyLinks and buttons are treated identically in the sidebar and slider panel\n***/\n/*{{{*/\n#sidebar {\n}\n\n#sidebarOptions input {\n border: 1px solid #04b;\n}\n\n#sidebarOptions .sliderPanel {\n background: #8cf;\n}\n\n#sidebarOptions .sliderPanel a {\n border: none;\n color: #04b;\n}\n\n#sidebarOptions .sliderPanel a:hover {\n color: #fff;\n background: #04b;\n}\n\n#sidebarOptions .sliderPanel a:active {\n color: #04b;\n background: #fff;\n}\n/*}}}*/\n/***\n!Message Area /%=================================================%/\n***/\n/*{{{*/\n#messageArea {\n border: 1px solid #841;\n background: #db4;\n color: #014;\n}\n\n#messageArea .button {\n padding: 0.2em 0.2em 0.2em 0.2em;\n color: #014;\n background: #fff;\n}\n\n/*}}}*/\n/***\n!Popup /%=================================================%/\n***/\n/*{{{*/\n.popup {\n background: #18f;\n border: 1px solid #04b;\n}\n\n.popup hr {\n color: #014;\n background: #014;\n border-bottom: 1px;\n}\n\n.popup li.disabled {\n color: #04b;\n}\n\n.popup li a, .popup li a:visited {\n color: #eee;\n border: none;\n}\n\n.popup li a:hover {\n background: #014;\n color: #fff;\n border: none;\n}\n/*}}}*/\n/***\n!Tiddler Display /%=================================================%/\n***/\n/*{{{*/\n.tiddler .defaultCommand {\n font-weight: bold;\n}\n\n.shadow .title {\n color: #866;\n}\n\n.title {\n color: #703;\n}\n\n.subtitle {\n color: #866;\n}\n\n.toolbar {\n color: #04b;\n}\n\n.tagging, .tagged {\n border: 1px solid #eee;\n background-color: #eee;\n}\n\n.selected .tagging, .selected .tagged {\n background-color: #ddd;\n border: 1px solid #bbb;\n}\n\n.tagging .listTitle, .tagged .listTitle {\n color: #014;\n}\n\n.tagging .button, .tagged .button {\n border: none;\n}\n\n.footer {\n color: #ddd;\n}\n\n.selected .footer {\n color: #888;\n}\n\n.sparkline {\n background: #8cf;\n border: 0;\n}\n\n.sparktick {\n background: #014;\n}\n\n.errorButton {\n color: #ff0;\n background: #f00;\n}\n\n.cascade {\n background: #eef;\n color: #aac;\n border: 1px solid #aac;\n}\n\n.imageLink, #displayArea .imageLink {\n background: transparent;\n}\n\n/*}}}*/\n/***\n''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/\n***/\n/*{{{*/\n\n.viewer .listTitle {list-style-type: none; margin-left: -2em;}\n\n.viewer .button {\n border: 1px solid #db4;\n}\n\n.viewer blockquote {\n border-left: 3px solid #666;\n}\n\n.viewer table {\n border: 2px solid #333;\n}\n\n.viewer th, thead td {\n background: #db4;\n border: 1px solid #666;\n color: #fff;\n}\n\n.viewer td, .viewer tr {\n border: 1px solid #666;\n}\n\n.viewer pre {\n border: 1px solid #fe8;\n background: #ffc;\n}\n\n.viewer code {\n color: #703;\n}\n\n.viewer hr {\n border: 0;\n border-top: dashed 1px #666;\n color: #666;\n}\n\n.highlight, .marked {\n background: #fe8;\n}\n/*}}}*/\n/***\n''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/\n***/\n/*{{{*/\n.editor input {\n border: 1px solid #04b;\n}\n\n.editor textarea {\n border: 1px solid #04b;\n width: 100%;\n}\n\n.editorFooter {\n color: #aaa;\n}\n\n/*}}}*/
/***\n!Sections in this Tiddler:\n*Generic rules\n**Links styles\n**Link Exceptions\n*Header\n*Main menu\n*Sidebar\n**Sidebar options\n**Sidebar tabs\n*Message area\n*Popup\n*Tabs\n*Tiddler display\n**Viewer\n**Editor\n*Misc. rules\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n font-size: .75em;\n font-family: "Trebuchet MS",arial,helvetica;\n position: relative;\n margin: 0;\n padding: 0;\n}\n\nh1,h2,h3,h4,h5 {\n font-weight: bold;\n text-decoration: none;\n padding-left: 0.4em;\n}\n\nh1 {font-size: 1.35em;}\nh2 {font-size: 1.25em;}\nh3 {font-size: 1.1em;}\nh4 {font-size: 1em;}\nh5 {font-size: .9em;}\n\nhr {\n height: 1px;\n}\n\na{\n text-decoration: none;\n}\n\nol { list-style-type: decimal }\nol ol { list-style-type: lower-alpha }\nol ol ol { list-style-type: lower-roman }\nol ol ol ol { list-style-type: decimal }\nol ol ol ol ol { list-style-type: lower-alpha }\nol ol ol ol ol ol { list-style-type: lower-roman }\nol ol ol ol ol ol ol { list-style-type: decimal }\n/*}}}*/\n/***\n''General Link Styles'' /%-----------------------------------------------------------------------------%/\n***/\n/*{{{*/\n.externalLink {\n text-decoration: underline;\n}\n\n.tiddlyLinkExisting {\n font-weight: bold;\n}\n\n.tiddlyLinkNonExisting {\n font-style: italic;\n}\n\n/* the 'a' is required for IE, otherwise it renders the whole tiddler a bold */\na.tiddlyLinkNonExisting.shadow {\n font-weight: bold;\n}\n/*}}}*/\n/***\n''Exceptions to common link styles'' /%------------------------------------------------------------------%/\n***/\n/*{{{*/\n\n#mainMenu .tiddlyLinkExisting, \n#mainMenu .tiddlyLinkNonExisting,\n#sidebarTabs .tiddlyLinkExisting,\n#sidebarTabs .tiddlyLinkNonExisting{\n font-weight: normal;\n font-style: normal;\n}\n\n/*}}}*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n\n.header {\n position: relative;\n}\n\n.header a:hover {\n background: transparent;\n}\n\n.headerShadow {\n position: relative;\n padding: 4.5em 0em 1em 1em;\n left: -1px;\n top: -1px;\n}\n\n.headerForeground {\n position: absolute;\n padding: 4.5em 0em 1em 1em;\n left: 0px;\n top: 0px;\n}\n\n.siteTitle {\n font-size: 3em;\n}\n\n.siteSubtitle {\n font-size: 1.2em;\n}\n\n/*}}}*/\n/***\n!Main menu /%==================================================%/\n***/\n/*{{{*/\n#mainMenu {\n position: absolute;\n left: 0;\n width: 10em;\n text-align: right;\n line-height: 1.6em;\n padding: 1.5em 0.5em 0.5em 0.5em;\n font-size: 1.1em;\n}\n\n/*}}}*/\n/***\n!Sidebar rules /%==================================================%/\n***/\n/*{{{*/\n#sidebar {\n position: absolute;\n right: 3px;\n width: 20em;\n font-size: .9em;\n}\n/*}}}*/\n/***\n''Sidebar options'' /%----------------------------------------------------------------------------------%/\n***/\n/*{{{*/\n#sidebarOptions {\n padding-top: 0.3em;\n}\n\n#sidebarOptions a {\n margin: 0em 0.2em;\n padding: 0.2em 0.3em;\n display: block;\n}\n\n#sidebarOptions input {\n margin: 0.4em 0.5em;\n}\n\n#sidebarOptions .sliderPanel {\n margin-left: 1em;\n padding: 0.5em;\n font-size: .85em;\n}\n\n#sidebarOptions .sliderPanel a {\n font-weight: bold;\n display: inline;\n padding: 0;\n}\n\n#sidebarOptions .sliderPanel input {\n margin: 0 0 .3em 0;\n}\n/*}}}*/\n/***\n''Sidebar tabs'' /%-------------------------------------------------------------------------------------%/\n***/\n/*{{{*/\n\n#sidebarTabs .tabContents {\n width: 19em;\n overflow: hidden;\n}\n/* tweak to indent second line of tabs \nfrom http://groups.google.com/group/TiddlyWiki/browse_thread/thread/2aad4167b249312/3785f3f0b1390c73?lnk=gst&q=tweak+sidebar+CSS&rnum=2#3785f3f0b1390c73\nOther changes DJG- make side bar wider, font = Trebuchet MS, preformatted font = Lucida console/typewriter\n*/\n#sidebarTabs .tabContents li {\n text-indent: -10px;\n padding-left: 15px;\n padding-right: 5px;\n word-wrap: word-break; \n}\n\n/*}}}*/\n/***\n!Message area /%==================================================%/\n***/\n/*{{{*/\n#messageArea {\nposition:absolute; top:0; right:0; margin: 0.5em; padding: 0.5em;\n}\n\n*[id='messageArea'] {\nposition:fixed !important; z-index:99;}\n\n.messageToolbar {\ndisplay: block;\ntext-align: right;\n}\n\n#messageArea a{\n text-decoration: underline;\n}\n/*}}}*/\n/***\n!Popup /%==================================================%/\n***/\n/*{{{*/\n.popup {\n font-size: .9em;\n padding: 0.2em;\n list-style: none;\n margin: 0;\n}\n\n.popup hr {\n display: block;\n height: 1px;\n width: auto;\n padding: 0;\n margin: 0.2em 0em;\n}\n\n.popup li.disabled {\n padding: 0.2em;\n}\n\n.popup li a{\n display: block;\n padding: 0.2em;\n}\n/*}}}*/\n/***\n!Tabs /%==================================================%/\n***/\n/*{{{*/\n.tabset {\n padding: 1em 0em 0em 0.5em;\n}\n\n.tab {\n margin: 0em 0em 0em 0.25em;\n padding: 2px;\n}\n\n.tabContents {\n padding: 0.5em;\n}\n\n.tabContents ul, .tabContents ol {\n margin: 0;\n padding: 0;\n}\n\n.txtMainTab .tabContents li {\n list-style: none;\n}\n\n.tabContents li.listLink {\n margin-left: .75em;\n}\n/*}}}*/\n/***\n!Tiddler display rules /%==================================================%/\n***/\n/*{{{*/\n#displayArea {\n margin: 1em 17em 0em 18em;\n}\n\n\n.toolbar {\n text-align: right;\n font-size: .9em;\n visibility: hidden;\n}\n\n.selected .toolbar {\n visibility: visible;\n}\n\n.tiddler {\n padding: 1em 1em 0em 1em;\n}\n\n.missing .viewer,.missing .title {\n font-style: italic;\n}\n\n.title {\n font-size: 1.6em;\n font-weight: bold;\n}\n\n.missing .subtitle {\n display: none;\n}\n\n.subtitle {\n font-size: 1.1em;\n}\n\n/* I'm not a fan of how button looks in tiddlers... */\n.tiddler .button {\n padding: 0.2em 0.4em;\n}\n\n.tagging {\nmargin: 0.5em 0.5em 0.5em 0;\nfloat: left;\ndisplay: none;\n}\n\n.isTag .tagging {\ndisplay: block;\n}\n\n.tagged {\nmargin: 0.5em;\nfloat: right;\n}\n\n.tagging, .tagged {\nfont-size: 0.9em;\npadding: 0.25em;\n}\n\n.tagging ul, .tagged ul {\nlist-style: none;margin: 0.25em;\npadding: 0;\n}\n\n.tagClear {\nclear: both;\n}\n\n.footer {\n font-size: .9em;\n}\n\n.footer li {\ndisplay: inline;\n}\n/***\n''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/\n***/\n/*{{{*/\n* html .viewer pre {\n width: 99%;\n padding: 0 0 1em 0;\n}\n\n.viewer {\n line-height: 1.4em;\n padding-top: 0.5em;\n}\n\n.viewer .button {\n margin: 0em 0.25em;\n padding: 0em 0.25em;\n}\n\n.viewer blockquote {\n line-height: 1.5em;\n padding-left: 0.8em;\n margin-left: 2.5em;\n}\n\n.viewer ul, .viewer ol{\n margin-left: 0.5em;\n padding-left: 1.5em;\n}\n\n.viewer table {\n border-collapse: collapse;\n margin: 0.8em 1.0em;\n}\n\n.viewer th, .viewer td, .viewer tr,.viewer caption{\n padding: 3px;\n}\n\n.viewer pre {\n padding: 0.5em;\n margin-left: 0.5em;\n font-size: 1.2em;\n line-height: 1.4em;\n overflow: auto;\n}\n\n.viewer code {\n font-size: 1.2em;\n line-height: 1.4em;\n}\n/*}}}*/\n/***\n''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/\n***/\n/*{{{*/\n.editor {\nfont-size: 1.1em;\n}\n\n.editor input, .editor textarea {\n display: block;\n width: 100%;\n font: inherit;\n}\n\n.editorFooter {\n padding: 0.25em 0em;\n font-size: .9em;\n}\n\n.editorFooter .button {\npadding-top: 0px; padding-bottom: 0px;}\n\n.fieldsetFix {border: 0;\npadding: 0;\nmargin: 1px 0px 1px 0px;\n}\n/*}}}*/\n/***\n!Misc rules /%==================================================%/\n***/\n/*{{{*/\n.sparkline {\n line-height: 1em;\n}\n\n.sparktick {\n outline: 0;\n}\n\n.zoomer {\n font-size: 1.1em;\n position: absolute;\n padding: 1em;\n}\n\n.cascade {\n font-size: 1.1em;\n position: absolute;\n overflow: hidden;\n}\n/*}}}*/
/***\n''Name:'' TWUpdate\n''Author:'' Tom Otvos\n''Version:'' 0.2\n<<twupdate>>\n***/\n//{{{\n\nversion.extensions.twupdate = {major: 0, minor: 2, revision: 0, date: new Date(2006,3,13,0,0,0,0), source: ""};\n\nconfig.macros.twupdate = { \n label: "update",\n sourceUrl: "http://www.tiddlywiki.com/empty.html", \n lingo: {\n prompt: "Update this TiddlyWiki from TiddlyWiki.com", \n warning: "Are you sure you want to update this document with the latest version of TiddlyWiki?\sn\snIf you want to continue, your document will first be saved with a backup.",\n success: "Update was successful. Click on 'OK' to reload the document",\n errNoHttp: "Unable to allocate an HTTP request object for the update",\n progressLoading: "Getting update from TiddlyWiki.com...",\n progressLoadSuccess: "File successfully loaded",\n progressLoadFailure: "File was not loaded successfully (%0)",\n progressMerging: "Merging with existing document..."\n }\n}\n\nconfig.macros.twupdate.handler = function(place)\n{\n if(!readOnly)\n createTiddlyButton(place, this.label, this.prompt, this.onClick, null, null, null);\n}\n\nconfig.macros.twupdate.onClick = function(e)\n{\n if (!confirm(config.macros.twupdate.lingo.warning)) return;\n\n try {\n // force a save with backup\n var saveBackups = config.options.chkSaveBackups;\n config.options.chkSaveBackups = true;\n saveChanges();\n config.options.chkSaveBackups = saveBackups;\n \n var ajax = new AjaxHelper();\n displayMessage(config.macros.twupdate.lingo.progressLoading);\n ajax.getText(config.macros.twupdate.sourceUrl, config.macros.twupdate.performUpdate); \n }\n catch (e) {\n alert(e);\n }\n\n return false;\n}\n\nconfig.macros.twupdate.performUpdate = function(emptyHtml, status, statusText)\n{\n // note that this is begin called from a callback from an event handler, so\n // "this" is most definitely not defined!\n \n if (status == 200)\n displayMessage(config.macros.twupdate.lingo.progressLoadSuccess);\n else {\n displayMessage(config.macros.twupdate.lingo.progressLoadFailure.format([statusText]));\n return;\n }\n displayMessage(config.macros.twupdate.lingo.progressMerging);\n \n // the bulk of this is cribbed from saveChanges()...\n var originalPath = document.location.toString();\n // Check we were loaded from a file URL\n if (originalPath.substr(0,5) != "file:") {\n alert(config.messages.notFileUrlError);\n if (store.tiddlerExists(config.messages.saveInstructions))\n displayTiddler(null,config.messages.saveInstructions);\n return;\n }\n var localPath = getLocalPath(originalPath);\n\n // Locate the storeArea div's\n var posOpeningDiv = emptyHtml.indexOf(startSaveArea);\n var posClosingDiv = emptyHtml.lastIndexOf(endSaveArea);\n if ((posOpeningDiv == -1) || (posClosingDiv == -1)) {\n alert(config.messages.invalidFileError.format(['empty.html']));\n return;\n }\n\n // Save new file\n var revised = emptyHtml.substr(0,posOpeningDiv + startSaveArea.length) + \n convertUnicodeToUTF8(allTiddlersAsHtml()) + "\sn\st\st" +\n emptyHtml.substr(posClosingDiv);\n var newSiteTitle = convertUnicodeToUTF8((wikifyPlain("SiteTitle") + " - " + wikifyPlain("SiteSubtitle")).htmlEncode());\n revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");\n revised = revised.replaceChunk("<!--PRE-HEAD-START--"+">","<!--PRE-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPreHead","") + "\sn");\n revised = revised.replaceChunk("<!--POST-HEAD-START--"+">","<!--POST-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPostHead","") + "\sn");\n revised = revised.replaceChunk("<!--PRE-BODY-START--"+">","<!--PRE-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPreBody","") + "\sn");\n revised = revised.replaceChunk("<!--POST-BODY-START--"+">","<!--POST-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPostBody","") + "\sn");\n var save = saveFile(localPath, revised);\n if (save) {\n displayMessage(config.messages.mainSaved, "file://" + localPath);\n store.setDirty(false);\n alert(config.macros.twupdate.lingo.success);\n document.location.reload();\n }\n else\n alert(config.messages.mainFailed);\n}\n\nfunction AjaxHelper()\n{\n this.http = null;\n \n try\n {\n this.http = new XMLHttpRequest()\n }\n \n catch(e)\n {\n // if we don't get an internal object, try allocating it using ActiveX, with successive\n // fallbacks to earlier MSXML versions as necessary\n try\n {\n this.http = new ActiveXObject("Msxml2.XMLHTTP.4.0")\n } \n catch(e) \n {\n try\n {\n this.http = new ActiveXObject("MSXML2.XMLHTTP")\n } \n catch(e) \n {\n try\n {\n this.http = new ActiveXObject("Microsoft.XMLHTTP")\n } \n catch(e) \n {\n this.http = null\n }\n }\n }\n }\n \n if (!this.http) throw 'Unable to allocate an HTTP request object';\n}\n\nAjaxHelper.prototype.getText = function(url, callback, async, force)\n{\n if (!this.http) return;\n if (async == undefined) async = true;\n if (force == undefined) force = false;\n // ??? right now, we are not handling "forced" requests\n this._request("GET", url, callback, async, true, false);\n}\n\nAjaxHelper.prototype.getXML = function(url, callback, async, force)\n{\n if (!this.http) return;\n if (async == undefined) async = true;\n if (force == undefined) force = false;\n // ??? right now, we are not handling "forced" requests\n this._request("GET", url, callback, async, true, true);\n}\n\nAjaxHelper.prototype.getHead = function(url, callback, async, force)\n{\n if (!this.http) return;\n if (async == undefined) async = true;\n if (force == undefined) force = false;\n // ??? right now, we are not handling "forced" requests\n this._request("HEAD", url, callback, async, false, false);\n}\n\nAjaxHelper.prototype.abort = function()\n{\n if (this.http) this.http.abort();\n}\n\nAjaxHelper.prototype.setRequestHeader = function(name, value)\n{\n if (this.http) this.http.setRequestHeader(name, value);\n}\n\nAjaxHelper.prototype._request = function(method, url, callback, async, hasResponse, hasResponseXML)\n{\n if (!this.http) return;\n \n // get reference to request object so we can use it in closure\n var xmlHttp = this.http, helper = this;\n xmlHttp.onreadystatechange = function()\n {\n if (!async) return;\n if (xmlHttp.readyState == 4)\n callback((hasResponse ? (hasResponseXML ? xmlHttp.responseXML : xmlHttp.responseText) : null), xmlHttp.status, xmlHttp.statusText, helper._parsedResponseHeaders());\n }\n \n try {\n // need some cross-domain privileges for Firefox\n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n } \n catch (e) \n {\n }\n \n xmlHttp.open(method, url, async);\n xmlHttp.send(null);\n if (!async) callback((hasResponse ? (hasResponseXML ? xmlHttp.responseXML : xmlHttp.responseText) : null), xmlHttp.status, xmlHttp.statusText, this._parsedResponseHeaders());\n }\n \n catch (e)\n {\n alert(e);\n }\n}\n\nAjaxHelper.prototype._parsedResponseHeaders = function()\n{\n if (this.http) {\n var headersArray = new Array();\n var headers = this.http.getAllResponseHeaders().split("\sn");\n for (var i = 0; i < headers.length; i++) {\n var h = headers[i].trim();\n if (h.length == 0) continue;\n // value can have ':' so do not use split here!\n var sep = h.indexOf(':');\n headersArray[h.substring(0, sep).trim()] = h.substr(sep + 1).trim();\n }\n return headersArray;\n }\n else\n return null;\n}\n\n//}}}\n
<<tagglyTagCloud systemConfig excludeLists excludeSearch plugin >>
<<tagglyTagCloud>>
/***\n|''Name:''|~TaggerPlugin|\n|''Version:''|1.0.1 (2006-06-01)|\n|''Source:''|http://lewcid.googlepages.com/lewcid.html/#TaggerPlugin|\n|''Author:''|SaqImtiaz|\n|''Description:''|Provides a drop down listing current tiddler tags, and allowing toggling of tags.|\n|''Documentation:''|[[TaggerPluginDocumentation]]|\n|''Source Code:''|[[TaggerPluginSource]]|\n|''~TiddlyWiki:''|Version 2.0.8 or better|\n***/\n// /%\nconfig.tagger={defaults:{label:"Tags: ",tooltip:"Manage tiddler tags",taglist:"true",excludeTags:"",notags:"tiddler has no tags",aretags:"current tiddler tags:",toggletext:"add tags:"}};config.macros.tagger={};config.macros.tagger.arrow=(document.all?"▼":"▾");config.macros.tagger.handler=function(_1,_2,_3,_4,_5,_6){var _7=config.tagger.defaults;var _8=_5.parseParams("tagman",null,true);var _9=((_8[0].label)&&(_8[0].label[0])!=".")?_8[0].label[0]+this.arrow:_7.label+this.arrow;var _a=((_8[0].tooltip)&&(_8[0].tooltip[0])!=".")?_8[0].tooltip[0]:_7.tooltip;var _b=((_8[0].taglist)&&(_8[0].taglist[0])!=".")?_8[0].taglist[0]:_7.taglist;var _c=((_8[0].exclude)&&(_8[0].exclude[0])!=".")?(_8[0].exclude[0]).readBracketedList():_7.excludeTags.readBracketedList();if((_8[0].source)&&(_8[0].source[0])!="."){var _d=_8[0].source[0];}if(_d&&!store.getTiddler(_d)){return false;}var _e=function(e){if(!e){var e=window.event;}var _11=Popup.create(this);var _12=store.getTags();var _13=new Array();for(var i=0;i<_12.length;i++){_13.push(_12[i][0]);}if(_d){var _15=store.getTiddler(_d);_13=_15.tags.sort();}var _16=_6.tags.sort();var _17=function(_18,_19,_1a){var sp=createTiddlyElement(createTiddlyElement(_11,"li"),"span",null,"tagger");var _1c=createTiddlyButton(sp,_18,_1a+" '"+_19+"'",taggerOnToggle,"button","toggleButton");_1c.setAttribute("tiddler",_6.title);_1c.setAttribute("tag",_19);insertSpacer(sp);if(window.createTagButton_orig_mptw){createTagButton_orig_mptw(sp,_19)}else{createTagButton(sp,_19);}};createTiddlyElement(_11,"li",null,"listTitle",(_6.tags.length==0?_7.notags:_7.aretags));for(var t=0;t<_16.length;t++){_17("[x]",_16[t],"remove tag ");}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");if(_b!="false"){createTiddlyElement(_11,"li",null,"listTitle",_7.toggletext);for(var i=0;i<_13.length;i++){if(!_6.tags.contains(_13[i])&&!_c.contains(_13[i])){_17("[ ]",_13[i],"add tag ");}}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");}var _1f=createTiddlyButton(createTiddlyElement(_11,"li"),("Create new tag"),null,taggerOnToggle);_1f.setAttribute("tiddler",_6.title);if(_d){_1f.setAttribute("source",_d);}Popup.show(_11,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};createTiddlyButton(_1,_9,_a,_e,"button","taggerDrpBtn");};window.taggerOnToggle=function(e){var tag=this.getAttribute("tag");var _22=this.getAttribute("tiddler");var _23=store.getTiddler(_22);if(!tag){var _24=prompt("Enter new tag:","");if(_24!=""&&_24!=null){var tag=_24;if(this.getAttribute("source")){var _26=store.getTiddler(this.getAttribute("source"));_26.tags.pushUnique(_24);}}else{return false;}}if(!_23||!_23.tags){store.saveTiddler(_22,_22,"",config.options.txtUserName,new Date(),tag);}else{if(_23.tags.find(tag)==null){_23.tags.push(tag);}else{if(!_24){_23.tags.splice(_23.tags.find(tag),1);}}store.saveTiddler(_23.title,_23.title,_23.text,_23.modifier,_23.modified,_23.tags);}story.refreshTiddler(_22,null,true);if(config.options.chkAutoSave){saveChanges();}return false;};setStylesheet(".tagger a.button {font-weight: bold;display:inline; padding:0px;}\sn"+".tagger #toggleButton {padding-left:2px; padding-right:2px; margin-right:1px; font-size:110%;}\sn"+"#nestedtagger {background:#2E5ADF; border: 1px solid #0331BF;}\sn"+".popup .listTitle {color:#000;}\sn"+"","TaggerStyles");window.lewcidTiddlerSwapTag=function(_27,_28,_29){for(var i=0;i<_27.tags.length;i++){if(_27.tags[i]==_28){_27.tags[i]=_29;return true;}}return false;};window.lewcidRenameTag=function(e){var tag=this.getAttribute("tag");var _2d=prompt("Rename tag '"+tag+"' to:",tag);if((_2d==tag)||(_2d==null)){return false;}if(store.tiddlerExists(_2d)){if(confirm(config.messages.overwriteWarning.format([_2d.toString()]))){story.closeTiddler(_2d,false,false);}else{return null;}}tagged=store.getTaggedTiddlers(tag);if(tagged.length!=0){for(var j=0;j<tagged.length;j++){lewcidTiddlerSwapTag(tagged[j],tag,_2d);}}if(store.tiddlerExists(tag)){store.saveTiddler(tag,_2d);}if(document.getElementById("tiddler"+tag)){var _2f=document.getElementById(story.idPrefix+tag);var _30=story.positionTiddler(_2f);var _31=document.getElementById(story.container);story.closeTiddler(tag,false,false);story.createTiddler(_31,_30,_2d,null);story.saveTiddler(_2d);}if(config.options.chkAutoSave){saveChanges();}return false;};window.onClickTag=function(e){if(!e){var e=window.event;}var _34=resolveTarget(e);var _35=(!isNested(_34));if((Popup.stack.length>1)&&(_35==true)){Popup.removeFrom(1);}else{if(Popup.stack.length>0&&_35==false){Popup.removeFrom(0);}}var _36=(_35==false)?"popup":"nestedtagger";var _37=createTiddlyElement(document.body,"ol",_36,"popup",null);Popup.stack.push({root:this,popup:_37});var tag=this.getAttribute("tag");var _39=this.getAttribute("tiddler");if(_37&&tag){var _3a=store.getTaggedTiddlers(tag);var _3b=[];var li,r;for(r=0;r<_3a.length;r++){if(_3a[r].title!=_39){_3b.push(_3a[r].title);}}var _3d=config.views.wikified.tag;if(_3b.length>0){var _3e=createTiddlyButton(createTiddlyElement(_37,"li"),_3d.openAllText.format([tag]),_3d.openAllTooltip,onClickTagOpenAll);_3e.setAttribute("tag",tag);createTiddlyElement(createTiddlyElement(_37,"li"),"hr");for(r=0;r<_3b.length;r++){createTiddlyLink(createTiddlyElement(_37,"li"),_3b[r],true);}}else{createTiddlyText(createTiddlyElement(_37,"li",null,"disabled"),_3d.popupNone.format([tag]));}createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var h=createTiddlyLink(createTiddlyElement(_37,"li"),tag,false);createTiddlyText(h,_3d.openTag.format([tag]));createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var _40=createTiddlyButton(createTiddlyElement(_37,"li"),("Rename tag '"+tag+"'"),null,lewcidRenameTag);_40.setAttribute("tag",tag);}Popup.show(_37,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};if(!window.isNested){window.isNested=function(e){while(e!=null){var _42=document.getElementById("contentWrapper");if(_42==e){return true;}e=e.parentNode;}return false;};}config.shadowTiddlers.TaggerPluginDocumentation="The documentation is available [[here.|http://lewcid.googlepages.com/lewcid.html#TaggerPluginDocumentation]]";config.shadowTiddlers.TaggerPluginSource="The uncompressed source code is available [[here.|http://lewcid.googlepages.com/lewcid.html#TaggerPluginSource]]";\n// %/
/***\n|Name|TagglyListPlugin|\n|Created by|SimonBaird|\n|Location|http://simonbaird.com/mptw/#TagglyListPlugin|\n|Version|1.1.1 6-Mar-06|\n|Requires|See TagglyTagging|\n\n!History\n* 1.1.1 (6-Mar-2006) fixed bug with refreshAllVisible closing tiddlers being edited. Thanks Luke Blanshard.\n\n***/\n\n/***\n!Setup and config\n***/\n//{{{\n\nversion.extensions.TagglyListPlugin = {\n major: 1, minor: 1, revision: 1,\n date: new Date(2006,3,6),\n source: "http://simonbaird.com/mptw/#TagglyListPlugin"\n};\n\nconfig.macros.tagglyList = {};\nconfig.macros.tagglyListByTag = {};\nconfig.macros.tagglyListControl = {};\nconfig.macros.tagglyListWithSort = {};\nconfig.macros.hideSomeTags = {};\n\n// change this to your preference\nconfig.macros.tagglyListWithSort.maxCols = 6;\n\nconfig.macros.tagglyList.label = "Tagged as %0:";\n\n// the default sort options. set these to your preference\nconfig.macros.tagglyListWithSort.defaults = {\n sortBy:"title", // title|created|modified\n sortOrder: "asc", // asc|desc\n hideState: "show", // show|hide\n groupState: "nogroup", // nogroup|group\n numCols: 1\n};\n\n// these tags will be ignored by the grouped view\nconfig.macros.tagglyListByTag.excludeTheseTags = [\n "systemConfig",\n "TiddlerTemplates"\n];\n\nconfig.macros.tagglyListControl.tags = {\n title:"sortByTitle", \n modified: "sortByModified", \n created: "sortByCreated",\n asc:"sortAsc", \n desc:"sortDesc",\n hide:"hideTagged", \n show:"showTagged",\n nogroup:"noGroupByTag",\n group:"groupByTag",\n cols1:"list1Cols",\n cols2:"list2Cols",\n cols3:"list3Cols",\n cols4:"list4Cols",\n cols5:"list5Cols",\n cols6:"list6Cols",\n cols7:"list7Cols",\n cols8:"list8Cols",\n cols9:"list9Cols" \n}\n\n// note: should match config.macros.tagglyListControl.tags\nconfig.macros.hideSomeTags.tagsToHide = [\n "sortByTitle",\n "sortByCreated",\n "sortByModified",\n "sortDesc",\n "sortAsc",\n "hideTagged",\n "showTagged",\n "noGroupByTag",\n "groupByTag",\n "list1Cols",\n "list2Cols",\n "list3Cols",\n "list4Cols",\n "list5Cols",\n "list6Cols",\n "list7Cols",\n "list8Cols",\n "list9Cols"\n];\n\n\n//}}}\n/***\n\n!Utils\n***/\n//{{{\n// from Eric\nfunction isTagged(title,tag) {\n var t=store.getTiddler(title); if (!t) return false;\n return (t.tags.find(tag)!=null);\n}\n\n// from Eric\nfunction toggleTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)==null) t.tags.push(tag);\n else t.tags.splice(t.tags.find(tag),1);\n}\n\nfunction addTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n t.tags.push(tag);\n}\n\nfunction removeTag(title,tag) {\n var t=store.getTiddler(title); if (!t || !t.tags) return;\n if (t.tags.find(tag)!=null) t.tags.splice(t.tags.find(tag),1);\n}\n\n// from Udo\nArray.prototype.indexOf = function(item) {\n for (var i = 0; i < this.length; i++) {\n if (this[i] == item) {\n return i;\n }\n }\n return -1;\n};\nArray.prototype.contains = function(item) {\n return (this.indexOf(item) >= 0);\n}\n//}}}\n/***\n\n!tagglyList\ndisplays a list of tagged tiddlers. \nparameters are sortField and sortOrder\n***/\n//{{{\n\n// not used at the moment...\nfunction sortedListOfOtherTags(tiddler,thisTag) {\n var list = tiddler.tags.concat(); // so we are working on a clone..\n for (var i=0;i<config.macros.hideSomeTags.tagsToHide.length;i++) {\n if (list.find(config.macros.hideSomeTags.tagsToHide[i]) != null)\n list.splice(list.find(config.macros.hideSomeTags.tagsToHide[i]),1); // remove hidden ones\n }\n for (var i=0;i<config.macros.tagglyListByTag.excludeTheseTags.length;i++) {\n if (list.find(config.macros.tagglyListByTag.excludeTheseTags[i]) != null)\n list.splice(list.find(config.macros.tagglyListByTag.excludeTheseTags[i]),1); // remove excluded ones\n }\n list.splice(list.find(thisTag),1); // remove thisTag\n return '[[' + list.sort().join("]] [[") + ']]';\n}\n\nfunction sortHelper(a,b) {\n if (a == b) return 0;\n else if (a < b) return -1;\n else return +1;\n}\n\nconfig.macros.tagglyListByTag.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n\n var sortBy = params[0] ? params[0] : "title"; \n var sortOrder = params[1] ? params[1] : "asc";\n\n var result = store.getTaggedTiddlers(tiddler.title,sortBy);\n\n if (sortOrder == "desc")\n result = result.reverse();\n\n var leftOvers = []\n for (var i=0;i<result.length;i++) {\n leftOvers.push(result[i].title);\n }\n\n var allTagsHolder = {};\n for (var i=0;i<result.length;i++) {\n for (var j=0;j<result[i].tags.length;j++) {\n\n if ( \n result[i].tags[j] != tiddler.title // not this tiddler\n && config.macros.hideSomeTags.tagsToHide.find(result[i].tags[j]) == null // not a hidden one\n && config.macros.tagglyListByTag.excludeTheseTags.find(result[i].tags[j]) == null // not excluded\n ) {\n if (!allTagsHolder[result[i].tags[j]])\n allTagsHolder[result[i].tags[j]] = "";\n allTagsHolder[result[i].tags[j]] += "**[["+result[i].title+"]]\sn";\n\n if (leftOvers.find(result[i].title) != null)\n leftOvers.splice(leftOvers.find(result[i].title),1); // remove from leftovers. at the end it will contain the leftovers...\n }\n }\n }\n\n\n var allTags = [];\n for (var t in allTagsHolder)\n allTags.push(t);\n\n allTags.sort(function(a,b) {\n var tidA = store.getTiddler(a);\n var tidB = store.getTiddler(b);\n if (sortBy == "title") return sortHelper(a,b);\n else if (!tidA && !tidB) return 0;\n else if (!tidA) return -1;\n else if (!tidB) return +1;\n else return sortHelper(tidA[sortBy],tidB[sortBy]);\n });\n\n var markup = "";\n\n if (sortOrder == "desc") {\n allTags.reverse();\n }\n else {\n // leftovers first...\n for (var i=0;i<leftOvers.length;i++)\n markup += "*[["+leftOvers[i]+"]]\sn";\n } \n\n for (var i=0;i<allTags.length;i++)\n markup += "*[["+allTags[i]+"]]\sn" + allTagsHolder[allTags[i]];\n\n if (sortOrder == "desc") {\n // leftovers last...\n for (var i=0;i<leftOvers.length;i++)\n markup += "*[["+leftOvers[i]+"]]\sn";\n }\n\n wikify(markup,place);\n}\n\nconfig.macros.tagglyList.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n var sortBy = params[0] ? params[0] : "title"; \n var sortOrder = params[1] ? params[1] : "asc";\n var numCols = params[2] ? params[2] : 1;\n\n var result = store.getTaggedTiddlers(tiddler.title,sortBy);\n if (sortOrder == "desc")\n result = result.reverse();\n\n var listSize = result.length;\n var colSize = listSize/numCols;\n var remainder = listSize % numCols;\n\n var upperColsize;\n var lowerColsize;\n if (colSize != Math.floor(colSize)) {\n // it's not an exact fit so..\n lowerColsize = Math.floor(colSize);\n upperColsize = Math.floor(colSize) + 1;\n }\n else {\n lowerColsize = colSize;\n upperColsize = colSize;\n }\n\n var markup = "";\n var c=0;\n\n var newTaggedTable = createTiddlyElement(place,"table");\n var newTaggedBody = createTiddlyElement(newTaggedTable,"tbody");\n var newTaggedTr = createTiddlyElement(newTaggedBody,"tr");\n\n for (var j=0;j<numCols;j++) {\n var foo = "";\n var thisSize;\n\n if (j<remainder)\n thisSize = upperColsize;\n else\n thisSize = lowerColsize;\n\n for (var i=0;i<thisSize;i++) \n foo += ( "*[[" + result[c++].title + "]]\sn"); // was using splitList.shift() but didn't work in IE;\n\n var newTd = createTiddlyElement(newTaggedTr,"td",null,"tagglyTagging");\n wikify(foo,newTd);\n\n }\n\n};\n\n/* snip for later.....\n //var groupBy = params[3] ? params[3] : "t.title.substr(0,1)";\n //var groupBy = params[3] ? params[3] : "sortedListOfOtherTags(t,tiddler.title)";\n //var groupBy = params[3] ? params[3] : "t.modified";\n var groupBy = null; // for now. groupBy here is working but disabled for now.\n\n var prevGroup = "";\n var thisGroup = "";\n\n if (groupBy) {\n result.sort(function(a,b) {\n var t = a; var aSortVal = eval(groupBy); var aSortVal2 = eval("t".sortBy);\n var t = b; var bSortVal = eval(groupBy); var bSortVal2 = eval("t".sortBy);\n var t = b; var bSortVal2 = eval(groupBy);\n return (aSortVal == bSortVal ?\n (aSortVal2 == bSortVal2 ? 0 : (aSortVal2 < bSortVal2 ? -1 : +1)) // yuck\n : (aSortVal < bSortVal ? -1 : +1));\n });\n }\n\n if (groupBy) {\n thisGroup = eval(groupBy);\n if (thisGroup != prevGroup)\n markup += "*[["+thisGroup+']]\sn';\n markup += "**[["+t.title+']]\sn';\n prevGroup = thisGroup;\n }\n\n\n\n*/\n\n\n//}}}\n\n/***\n\n!tagglyListControl\nUse to make the sort control buttons\n***/\n//{{{\n\nfunction getSortBy(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.sortBy;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["title"])) return "title";\n else if (tiddler.tags.contains(usetags["modified"])) return "modified";\n else if (tiddler.tags.contains(usetags["created"])) return "created";\n else return defaultVal;\n}\n\nfunction getSortOrder(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.sortOrder;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["asc"])) return "asc";\n else if (tiddler.tags.contains(usetags["desc"])) return "desc";\n else return defaultVal;\n}\n\nfunction getHideState(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.hideState;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["hide"])) return "hide";\n else if (tiddler.tags.contains(usetags["show"])) return "show";\n else return defaultVal;\n}\n\nfunction getGroupState(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.groupState;\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n if (tiddler.tags.contains(usetags["group"])) return "group";\n else if (tiddler.tags.contains(usetags["nogroup"])) return "nogroup";\n else return defaultVal;\n}\n\nfunction getNumCols(title) {\n var tiddler = store.getTiddler(title);\n var defaultVal = config.macros.tagglyListWithSort.defaults.numCols; // an int\n if (!tiddler) return defaultVal;\n var usetags = config.macros.tagglyListControl.tags;\n for (var i=1;i<=config.macros.tagglyListWithSort.maxCols;i++)\n if (tiddler.tags.contains(usetags["cols"+i])) return i;\n return defaultVal;\n}\n\n\nfunction getSortLabel(title,which) {\n // TODO. the strings here should be definable in config\n var by = getSortBy(title);\n var order = getSortOrder(title);\n var hide = getHideState(title);\n var group = getGroupState(title);\n if (which == "hide") return (hide == "show" ? "−" : "+"); // 0x25b8;\n else if (which == "group") return (group == "group" ? "normal" : "grouped");\n else if (which == "cols") return "cols±"; // ±\n else if (by == which) return which + (order == "asc" ? "↓" : "↑"); // ↑ ↓\n else return which;\n}\n\nfunction handleSortClick(title,which) {\n var currentSortBy = getSortBy(title);\n var currentSortOrder = getSortOrder(title);\n var currentHideState = getHideState(title);\n var currentGroupState = getGroupState(title);\n var currentNumCols = getNumCols(title);\n\n var tags = config.macros.tagglyListControl.tags;\n\n // if it doesn't exist, lets create it..\n if (!store.getTiddler(title))\n store.saveTiddler(title,title,"",config.options.txtUserName,new Date(),null);\n\n if (which == "hide") {\n // toggle hide state\n var newHideState = (currentHideState == "hide" ? "show" : "hide");\n removeTag(title,tags[currentHideState]);\n if (newHideState != config.macros.tagglyListWithSort.defaults.hideState)\n toggleTag(title,tags[newHideState]);\n }\n else if (which == "group") {\n // toggle hide state\n var newGroupState = (currentGroupState == "group" ? "nogroup" : "group");\n removeTag(title,tags[currentGroupState]);\n if (newGroupState != config.macros.tagglyListWithSort.defaults.groupState)\n toggleTag(title,tags[newGroupState]);\n }\n else if (which == "cols") {\n // toggle num cols\n var newNumCols = currentNumCols + 1; // confusing. currentNumCols is an int\n if (newNumCols > config.macros.tagglyListWithSort.maxCols || newNumCols > store.getTaggedTiddlers(title).length)\n newNumCols = 1;\n removeTag(title,tags["cols"+currentNumCols]);\n if (("cols"+newNumCols) != config.macros.tagglyListWithSort.defaults.groupState)\n toggleTag(title,tags["cols"+newNumCols]);\n }\n else if (currentSortBy == which) {\n // toggle sort order\n var newSortOrder = (currentSortOrder == "asc" ? "desc" : "asc");\n removeTag(title,tags[currentSortOrder]);\n if (newSortOrder != config.macros.tagglyListWithSort.defaults.sortOrder)\n toggleTag(title,tags[newSortOrder]);\n }\n else {\n // change sortBy only\n removeTag(title,tags["title"]);\n removeTag(title,tags["created"]);\n removeTag(title,tags["modified"]);\n\n if (which != config.macros.tagglyListWithSort.defaults.sortBy)\n toggleTag(title,tags[which]);\n }\n\n store.setDirty(true); // save is required now.\n story.refreshTiddler(title,false,true); // force=true\n}\n\nconfig.macros.tagglyListControl.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n var onclick = function(e) {\n if (!e) var e = window.event;\n handleSortClick(tiddler.title,params[0]);\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return false;\n };\n createTiddlyButton(place,getSortLabel(tiddler.title,params[0]),"Click to change sort options",onclick,params[0]=="hide"?"hidebutton":"button");\n}\n//}}}\n/***\n\n!tagglyListWithSort\nput it all together..\n***/\n//{{{\nconfig.macros.tagglyListWithSort.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n if (tiddler && store.getTaggedTiddlers(tiddler.title).length > 0)\n // todo make this readable\n wikify(\n "<<tagglyListControl hide>>"+\n (getHideState(tiddler.title) != "hide" ? \n '<html><span class="tagglyLabel">'+config.macros.tagglyList.label.format([tiddler.title])+' </span></html>'+\n "<<tagglyListControl title>><<tagglyListControl modified>><<tagglyListControl created>><<tagglyListControl group>>"+(getGroupState(tiddler.title)=="group"?"":"<<tagglyListControl cols>>")+"\sn" + \n "<<tagglyList" + (getGroupState(tiddler.title)=="group"?"ByTag ":" ") + getSortBy(tiddler.title)+" "+getSortOrder(tiddler.title)+" "+getNumCols(tiddler.title)+">>" // hacky\n // + \sn----\sn" +\n //"<<tagglyList "+getSortBy(tiddler.title)+" "+getSortOrder(tiddler.title)+">>"\n : ""),\n place,null,tiddler);\n}\n\n//}}}\n/***\n\n!hideSomeTags\nSo we don't see the sort tags.\n(note, they are still there when you edit. Will that be too annoying?\n***/\n//{{{\n\n// based on tags.handler\nconfig.macros.hideSomeTags.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n var theList = createTiddlyElement(place,"ul");\n if(params[0] && store.tiddlerExists[params[0]])\n tiddler = store.getTiddler(params[0]);\n var lingo = config.views.wikified.tag;\n var prompt = tiddler.tags.length == 0 ? lingo.labelNoTags : lingo.labelTags;\n createTiddlyElement(theList,"li",null,"listTitle",prompt.format([tiddler.title]));\n for(var t=0; t<tiddler.tags.length; t++)\n if (!this.tagsToHide.contains(tiddler.tags[t])) // this is the only difference from tags.handler...\n createTagButton(createTiddlyElement(theList,"li"),tiddler.tags[t],tiddler.title);\n\n}\n\n//}}}\n/***\n\n!Refresh everything when we save a tiddler. So the tagged lists never get stale. Is this too slow???\n***/\n//{{{\n\nfunction refreshAllVisible() {\n story.forEachTiddler(function(title,element) {\n if (element.getAttribute("dirty") != "true") \n story.refreshTiddler(title,false,true);\n });\n}\n\nstory.saveTiddler_orig_mptw = story.saveTiddler;\nstory.saveTiddler = function(title,minorUpdate) {\n var result = this.saveTiddler_orig_mptw(title,minorUpdate);\n refreshAllVisible();\n return result;\n}\n\nstore.removeTiddler_orig_mptw = store.removeTiddler;\nstore.removeTiddler = function(title) {\n this.removeTiddler_orig_mptw(title);\n refreshAllVisible();\n}\n\n//}}}\n\n// // <html>▸▾−±</html>
/***\n''Plugin:'' TagglyTag Cloud Macro\n''Author:'' Clint Checketts\n''Source URL:''\n\n//Note the macro name was changed to stop it from clashing with the original TagCloud plugin//\n\n!Usage\n{{{<<tagglyTagCloud>>}}}\n<<tagglyTagCloud>>\n\n{{{<<tagglyTagCloud tag1 tag2 tag3 tag4>>}}}\nwill exclude tag1, tag2 and tag3 from the cloud listing.\nAll tiddlers tagged with tag4, the last param will not have their tags counted. You can also pass the last param as "" to avoid excluding tiddlers.\n\n!History\n*12-08-06, version 1.1, modified by Saq, can now exclude tiddlers from having their tags counted. \n\n!Code\n***/\n//{{{\nversion.extensions.tagglyTagCloud = {major: 1, minor: 0 , revision: 0, date: new Date(2006,2,4)};\n//Created by Clint Checketts, contributions by Jonny Leroy and Eric Shulman\n\nconfig.macros.tagglyTagCloud = {\n noTags: "No tag cloud created because there are no tags.",\n tooltip: "%1 tiddlers tagged with '%0'"\n};\n\nconfig.macros.tagglyTagCloud .handler = function(place,macroName,params) {\n \nvar tagCloudWrapper = createTiddlyElement(place,"div",null,"tagCloud",null);\n\nvar excludeTaggedTiddler = params[params.length-1];\nif (excludeTaggedTiddler == ".") excludeTaggedTiddler = undefined;\nvar tags = store.getFilteredTags(undefined,excludeTaggedTiddler);\nfor (var t=0; t<tags.length; t++) {\n for (var p=0;p<params.length-1; p++) if (tags[t][0] == params[p]) tags[t][0] = "";\n}\n\n if(tags.length == 0) \n createTiddlyElement(tagCloudWrapper,"span",null,null,this.noTags);\n //Findout the maximum number of tags\n var mostTags = 0;\n for (var t=0; t<tags.length; t++) if (tags[t][0].length > 0){\n if (tags[t][1] > mostTags) mostTags = tags[t][1];\n }\n //divide the mostTags into 4 segments for the 4 different tagCloud sizes\n var tagSegment = mostTags / 4;\n\n for (var t=0; t<tags.length; t++) if (tags[t][0].length > 0){\n var tagCloudElement = createTiddlyElement(tagCloudWrapper,"span",null,null,null);\n tagCloudWrapper.appendChild(document.createTextNode(" "));\n var theTag = createTiddlyLink(tagCloudElement,tags[t][0],true);\n theTag.className += " tagCloudtag tagCloud" + (Math.round(tags[t][1]/tagSegment)+1);\n\n// theTag.setAttribute("tag",tags[t][0]);\n }\n\n};\n\nsetStylesheet(".tagCloud span{height: 1.8em;margin: 3px;}.tagCloud1{font-size: 1.2em;}.tagCloud2{font-size: 1.4em;}.tagCloud3{font-size: 1.6em;}.tagCloud4{font-size: 1.8em;}.tagCloud5{font-size: 1.8em;font-weight: bold;}","tagCloudsStyles");\n\n// Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurances\nTiddlyWiki.prototype.getFilteredTags = function(exclude,excludeTaggedTiddler)\n{\n var results = [];\n this.forEachTiddler(function(title,tiddler) {\n if (excludeTaggedTiddler==undefined || !tiddler.isTagged(excludeTaggedTiddler))\n {\n for(var g=0; g<tiddler.tags.length; g++)\n {\n var tag = tiddler.tags[g];\n if (exclude!=undefined && store.tiddlerExists(tag) && (store.getTiddler(tag)).isTagged(exclude))\n {return false;}\n var f = false;\n for(var c=0; c<results.length; c++)\n if(results[c][0] == tag)\n {\n f = true;\n results[c][1]++;\n }\n if(!f)\n results.push([tag,1]);\n }\n }});\n results.sort(function (a,b) {if(a[0].toLowerCase() == b[0].toLowerCase()) return(0); else return (a[0].toLowerCase() < b[0].toLowerCase()) ? -1 : +1; });\n return results;\n}\n\n//}}}
/***\nTo use, add {{{[[TagglyTaggingStyles]]}}} to your StyleSheet tiddler, or you can just paste the CSS in directly. See also ViewTemplate, EditTemplate and TagglyTagging.\n***/\n/*{{{*/\n.tagglyTagged li.listTitle { display:none;}\n.tagglyTagged li { display: inline; font-size:90%; }\n.tagglyTagged ul { margin:0px; padding:0px; }\n.tagglyTagging { padding-top:0.5em; }\n.tagglyTagging li.listTitle { display:none;}\n.tagglyTagging ul { margin-top:0px; padding-top:0.5em; padding-left:2em; margin-bottom:0px; padding-bottom:0px; }\n\n/* .tagglyTagging .tghide { display:inline; } */\n\n.tagglyTagging { vertical-align: top; margin:0px; padding:0px; }\n.tagglyTagging table { margin:0px; padding:0px; }\n\n\n.tagglyTagging .button { display:none; margin-left:3px; margin-right:3px; }\n.tagglyTagging .button, .tagglyTagging .hidebutton { color:#aaa; font-size:90%; border:0px; padding-left:0.3em;padding-right:0.3em;}\n.tagglyTagging .button:hover, .hidebutton:hover { background:#eee; color:#888; }\n.selected .tagglyTagging .button { display:inline; }\n\n.tagglyTagging .hidebutton { color:white; } /* has to be there so it takes up space */\n.selected .tagglyTagging .hidebutton { color:#aaa }\n\n.tagglyLabel { color:#aaa; font-size:90%; }\n\n.tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }\n.tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}\n.tagglyTagging ul ul li {margin-left:0.5em; }\n\n.editLabel { font-size:90%; padding-top:0.5em; }\n/*}}}*/\n
<<<\nThe pipe is a Unix method of combining programs (often called filters) together so they run in sequence with the output from one program being the input to the next program.\n<<<\n\n* this method of running program sequences has many advantages.\n## easy to set up, and add or delete components, which typically occupy just one command line\n## no need to mess around with temporary files\n## the pipe components actually run in parallel as communicating processes\n## because the buffers are connected to each other directly data passing is fast\n!!!! Examples are throughout this tutorial - try searching for ''|'' or look for the <<monkeyTagger '|'>>\n\n* count how many files were modified in August in the current directory\n> {{{ls -l -H -t |# }}} list all the files , with date details {{{-l}}} and no header {{{-H}}}, sorted by time . {{{-t}}}\n>> {{{ sed 1d | #}}} delete the first line (total )\n>>> {{{ cut -c 44-51 | # }}} keep only columns 44 to 51 (where the date is)\n>>>> {{{ uniq -c | # }}} delete duplicate dates (list is already sorted \n>>>>> {{{ grep -i aug # }}} print only August lines, ignore case {{{-i}}}...\n** pastable version:\n{{{ls -l -H -t |sed 1d |cut -c 44-51 | uniq -c | grep -i aug | wc -l}}}\n!!!! Syntax\n> {{{command [-options] [files] [| command... ]}}}\n> Vertical bar (''|'') is the pipe character. On some systems it may be displayed as a broken vertical bar.\n> Normally a command expecting input will continue on the next line. Generally I write them here on one line for easy pasting.\n> See also: article about Unix pipes in [[wikipedia|http://en.wikipedia.org/wiki/Pipeline_(Unix)]]
/***\n| Name:|TiddlerExcerptTooltip|\n| Source:|http://simonbaird.com/mptw/#TiddlerExcerptTooltip|\n| Author:|Simon Baird, adapted from original version posted to mailing list by Udo Borkowski|\n| Version:|1.0.0|\n| Description:|Make tooltip of tiddler links the first line or excerpt of the tiddler content|\n***/\n//{{{\n\n// adjust the following to your preference\nconfig.TiddlerExcerptTooltip = {\n trimLength: 80,\n dateFormat:"DD-MM-YY"\n}\n\n// %0 is title\n// %1 is modifier\n// %2 is modified date\n// %3 is first line\n// %4 is first so many characters\n// %5 is short modified date\n// %6 is short created date\n\n// firefox seems to trim the tooltip if it gets too long...\nconfig.messages.tiddlerLinkTooltip = "%3";\n\nconfig.messages.tiddlerEmpty = "(empty)";\n\nTiddler.prototype.getSubtitle = function()\n{\n var theModifier = this.modifier;\n if(!theModifier)\n theModifier = config.messages.subtitleUnknown;\n var theModified = this.modified;\n if(theModified)\n theModified = theModified.toLocaleString();\n else\n theModified = config.messages.subtitleUnknown;\n\n var m = this.text.match(/\ss*(.*)/);\n var firstLine = (m != null && m.length >= 1) ? m[1] : "";\n\n var contentExcerpt = this.text.prettyTrim(config.TiddlerExcerptTooltip.trimLength);\n if (contentExcerpt == "")\n contentExcerpt = config.messages.tiddlerEmpty;\n\n var shortModified = this.modified.formatString(config.TiddlerExcerptTooltip.dateFormat);\n var shortCreated = this.created.formatString(config.TiddlerExcerptTooltip.dateFormat);\n\n\n return config.messages.tiddlerLinkTooltip.format(\n [this.title,theModifier,theModified,firstLine,contentExcerpt,shortModified,shortCreated]); \n}\n\n// this lifted from TagUtils\nString.prototype.prettyTrim = function(len,prefix,postfix) {\n var result = this.trim().replace(/\sr\sn/g,' ').replace(/[\sn|\st]/g,' ');\n if (result.length > len - 3)\n return result.trim().substr(0,len) + '...';\n else\n return result;\n}\n\n//}}}\n
<<slideShow>>\n\n--s--\n!TiddlyWiki and MicroContent\n[[Dave Garbutt|DaveG]]\n\n[[PD02|http://www.lexjansen.com/phuse/2006/pd/pd02.pdf]] @ PhUSE 2006, Dublin\n--s--\n!Introduction\n*Follow this application up!\n*What is a TiddlyWiki?\n*What can I do with it?\n*Why is it important?\n*Find out more!\n*The WIKIWikiWeb editable web sites\n*A new niche in the paperless office is filled\n--s--\n!MicroContent?\n*A TiddlyWiki keeps 'pages' and visible until you exit or close one. Each 'page' can be opened independently. This piece of genius - to change what seems 'normal' and 'the obvious way to do things'\n*A document that is a single page application\n*Free the paragraph from the prison of context\n*The unit is the called a tiddler\n--s--\n!Problems with MacroContent\n*Documents gets their structure from the closeness of paragraphs\n*Therefore we have to have a reader in mind - an audience\n>> It is an axiom well regarded that a document possessed of an author must be in search of a reader…\n*But MicroContent can break this mould forever\n*By allowing a combination of many audiences (and shared material) in one document\n*Without dazzling the beginner or boring the expert\n\n--s--\n!Personal, nonlinear.extensible, web notebook\n*Personal\n*A single file\n*No server needed\n*Free, open source\n*Web Notebook\n*A TiddlyWiki is a single HTML file containing about 300k of JavaScript\n*which manages the display and addition of tiddlers\n--s--\n!Non-linear\n*there is no fixed order to the tiddlers\n*You determine the order and\n*What is visible\n*Individualized document\n*Structured with\n*Links\n*Tags\n*Lists and summary tables or tabs of tiddlers\n*Grouping tiddlers for opening as a unit\n\n--s--\n!Extensible and customisable\n*CSS dynamic styling\n*Plugin architecture e.g. In-line JavaScript:\n{{{\nconfig.macros.man = {};\nconfig.macros.man.handler= function(place,macroName,params) {\n var key=params[0];\n wikify("[["+key+"|http://unixhelp.ed.ac.uk/CGI/man-cgi?"+key+"]]",place)\n}\n}}}\n1.Copy it in a new tiddler,\n2.tag the tiddler systemConfig,\n3.save the TiddlyWiki,\n4.reload into the browser.\n5.Add this to your tiddler about the awk command: <<man awk>>\n--s--\n!Using TiddlyWiki\n*Adding information\n*Formatting\n*Tables, block quotes, preformatted, headers\n--s--\n!Structuring your information\n*Linking, auto linking\n*AutoLink WikiWords,\n*Tagging\n*Add keywords or phrases to label tiddlers\n*Tagging can create structure content 'free'.\n>For example consider tiddlers with Unix programming tips. \n>> Tag each tip as you create it with the Unix commands used in it.\n>> Then you can look at the autogenerated awk tiddler and see everywhere it is tagging, \n>>> ie all the pages you thought were relevant to awk.\n>> This can include tiddlers where awk is not mentioned in the text\n--s--\n!Structuring your Document\n* Aggregating tiddlers\n* Disaggregating\n* Sequences\n* Adding tags\n* Authoring tools\n--s--\n!Sharing your TiddlyWiki\n* Put on a web server\n* A disk share\n* A USB stick\n* Use a server version\n* Get a hosted TiddlyWiki\n* Automatic sharing and updating is planned : to compete with portals costing millions\n--s--\n!Uses\n* Journal, Diary and Day planner\n* Technical notes\n* Presentations\n* Generating validation reports\n* Construct from custom text files\n* Delivering Documentation\n--s--\n!Creating a Validation document\n{{{\nfind $PWD -type f -print | sort |\n awk -v pwd=$PWD -v date="`date `" '\n {if (NR == 1 ) print "|No.|File | OK? | Notes and comments | re-done OK? |h\sn|>|>|All files in:|" pwd"|"date"|" }\n {sub(pwd,".",$1); print "| "NR"|"$1" | | | |"}'\n}}}\n*prints plain text on the terminal like this:\n{{{\n|No.|File | OK? | Notes and comments | re-done OK? |h\n|>|>|/vob/CMyPROJ/CMyPROJ0103/report|>|Thu Apr 6 17:14:11 DFT 2006|\n| 1|./pgm_a/autoexec.sas | | | |\n| 2|./pgm_a/pops.sas | | | |\n| 3|./pgm_a/subpops.sas | | | |\n| 4|./pgm_a/ds_aevs.sas | | | |\n|>|>|>| and so on...|\n| 21|./pgm_a/mk_trtm.sas | | | |\n}}}\n--s--\n!Validation form…\n*Giving a rendered table like this:\n|No.|File | OK? | Notes and comments | re-done OK? |h\n|>|>|/vob/CMyPROJ/CMyPROJ0103/report|>|Thu Apr 6 17:14:11 DFT 2006|\n| 1|./pgm_a/autoexec.sas | | | |\n| 2|./pgm_a/pops.sas | | | |\n| 3|./pgm_a/subpops.sas | | | |\n| 4|./pgm_a/ds_aevs.sas | | | |\n|>|>|>|>| and so on...|\n| 21|./pgm_a/mk_trtm.sas | | | |\n--s--\n!Demonstration\n*Demo\n*Look and feel\n*Navigating around\n*Adding text\n*Tagging\n*Journals\n*Dcubed\n*My tiddlyspot\n--s--\n!Frequently Posed Worries\n*Scalability\n*Above 2MB response slows down\n*Privacy\n*Not private\n*Encryption available (but big plugin)\n*Safety of typing investment\n*OK\n*Conversion to WORD\n*Not much fun\n*Till someone writes a WORD macro that converts Wiki text to styles / markup\n\n--s--\n!Conclusions\n*For many of the examples I have given it is currently the best solution.\n*Try it yourself:\n*http://mptw.tiddlyspot.com\n*Gnit your own:\n* http://www.tiddlyspot.com\n\n\n--s--\n!Acknowledgements and thanks\n*Jeremy Ruston for creating it\n*and building a great community of developers\n--s--\n!Further Reading\n*See the TiddlyWiki web site http://www.tiddlywiki.com\n*The google groups\n*The public tutorials\n*The plug-in repositories\n*All linked from the main site\n! My [[PhUSE|http://www.lexjansen.com/phuse/2006/pd/pd02.pdf]] 2006 Presentations at Lex Jansen's website\n--s--\n!Questions?\n<<<\nIt is not because things are difficult that we do not dare,\nit is because we do not dare that they are difficult.\n<<<\n>--Seneca\n--s--\n!Contact Information\n* I would value your comments and questions on this paper. \nContact details [[here|DaveG]]\n\n
This is a tutorial for the creation and use of regular expressions (regexes). It is presented in the following chapters:\n*[[Characters]]\n*[[Engines]]\n*[[CharacterClasses]]\n*[[Dot]]\n*[[Anchors]]\n*[[WordBoundaries]]\n*[[Alternation]]\n*[[OptionalItems]]\n*[[Repetition]]\n*[[Grouping]]\n*[[NamedGroups]]\n*[[Unicode]]\n*[[Modifiers]]\n*[[AtomicGrouping]]\n*[[Lookahead]]\n*[[Lookbehind]] \n*[[Lookaround]] \n*[[ContinuingMatches]]\n*[[Conditionals]]\n*[[Comments]]\n\n\n
Useful tools for working... \n\n* Which tools are most useful?\nThis depends what you need to do, but an analysis of my history file shows a distribution like this \n<<sparkline 69 62 52 33 9 9 5 2 1 >> \nfor [[grep]], [[awk]], [[uniq]], [[sed]], [[wc]], [[head]], [[fold]], and [[cut]] .\n(max count is 69 for grep.\nFor first commands it looks a bit different :\n<<sparkline 174 117 72 42 35 34 30 30 29 26 16 15 15 15 12 12 12 11 10 9 9 9 7 7 7 7 6 5 5 5 5>>\nfor [[cleartool]] (174), [[awk]] (117), [[grep]], [[lnv|lnv -an alias to list non-validated SAS programs]], [[sas]],[[more]], [[apply]], [[alias]], [[exit]], [[clearmake]],[[gps_promote_validated.sh]], [[aixterm]], [[mkp]], [[lcm]], [[alst]], [[vs]], [[pico]], [[ps]], [[gps_promote_ready_for_qc.sh]], [[man]], [[cp]], [[atq]], [[cd]], [[chklogs]], [[myps]], [[gcp]], [[whence]], [[lload]], [[lh|lh - an alias to print a modification date histogram]], [[history]]\n\nSeeAlso CommonUnixCommands and [[Unix tutorials]]\n<<tag "Unix commands">>\n
* An excellent guide is [[here || http://www.unh.edu/cis/docs/vms-to-unix/Articles/index.html]]
See [[Learning Unix|http://www.datasavantconsulting.com/roland/spectre/learnunix.html]] \nSite by RolandRashleighBerry
Many on the web.\n\nThis is recommended by JonathanMcCue: [[from Surrey University, UK|http://www.ee.surrey.ac.uk/Teaching/Unix/index.html]]\n\nIn this document I have added an excellent tutorial on [[regular expressions|Tutorial on Regular Expressions]] by StevePike. Thanks
config.macros.man = {};\nconfig.macros.man.handler= function(place,macroName,params) {\n var key=params[0];\n wikify("[["+key+"|http://unixhelp.ed.ac.uk/CGI/man-cgi?"+key+"]]",place)\n}
! UNIX TEXT COMMANDS:\n* This table classifies the commands that can process text (files, or pipes) by the type of operations they can do.\n* This enables you to easily find a command to do what you need. \n* The next step is to refer to the man page, or try the defaults to see if that is enough.\n* If the column marked edit is YES it means there is a way to change the values either of one field, or the whole record. In [[awk]] and [[sed]] this is done with the sub(stitute) functions.\n* Although I have included perl here it is not much used for one-liners, but is a good basis for developing general programs.\n\n!!!! Note: \n* this table is sortable - click the link on the column to re-sort on that column. (one at a time :-)\n* the column type is allocated as follows:\n0 - operates on whole file\n1 - operates on rows only\n2 - operates on columns only\n3 - operates on rows and/or columns\n \n|Program|Type|Select Rows?|Select Cols?|Default field separator|Edit?|Multiple files?|Comments|h\n|[[cut]]|2|NO|YES, by col number or field |-d"\st"|NO|YES||\n|[[join]]|2|NO|YES,by field content |-t"\st"|YES, select any non-key columns|TWO files only|Print the common lines. Files must be sorted on the fields used|\n|[[head]]|1|YES, first -n|NO|-|NO|YES|top of file or pipe|\n|[[tail]]|1|YES, last -n|NO|-|NO|NO (some versions, YES)|bottom of file or pipe, -f option keeps dynamic watch|\n|[[sort]]|1|YES|NO|-t"\st"|NO|YES|Sorts on entire record by default, can drop records with duplicate keys (-u) and merge files (-m)|\n|[[fold]]|0|NO|NO|col number||NO|Wraps long lines|\n|[[paste]]|2|NO|YES|-d"\st"|NO|YES|merges content of files in to one column by column|\n|[[wc]]|0|NO|NO|||YES|Counts characters, words and lines|\n|[[diff]]|0|NO|NO|-|NO|TWO files|prints differences between files|\n|[[comm]]|3|YES|NO whole line is matched|-|NO|TWO files|list lines in common, or in only one of the files|\n|[[col]]|2|NO|YES|||YES|processes reverse line feeds. Does not do what you think! Try [[cut]]|\n|[[colrm]]|2|NO|YES|startcol - endcol|||copy only the given columns to std output|\n|[[print]] [[echo]]|0|NO|NO||||Print the input (KSH Shells) |\n|[[sed]]|4|YES|YES|none|||editing, line selection and substitution|\n|[[spell]]|0|NO|NO|||YES|prints mis-spelled words|\n|[[awk]]|4|YES|YES|-F" "|YES|YES|print matching records; select fields as $1,$2..., programmable|\n|[[perl]]|4|YES|YES|||YES|Power string and data processing tool. OO programming|\n|[[fmt]]|0|NO|NO|-|NO|YES|fill lines to the same length|\n|[[look]]|3|YES|NO|-|NO|YES|Returns lines where start of line matches the sring given. File must be sorted|\n|[[locate]]|3|YES|NO|-|NO|Finds file names|\n|[[diff]]|0|NO|NO|-|NO|TWO|locates differences in the files|\n| The separator is given with the option used to set it. \st means tab. Many awk versions allow a regular expression to be the separator. The separator can also be a non-printable character (e.g. \s015, or ^L, page feed)|c\n----
config.macros.list["untagged"] = {prompt: "Tiddlers that are not tagged"};\n\nconfig.macros.list.untagged.handler = function(params)\n{\n var results = [];\n\n store.forEachTiddler(function (title,tiddler) {\n if(!tiddler.tags || tiddler.tags.length == 0){\n results.push(title);\n }\n });\n results.sort();\n return results;\n}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |\n| 22/6/2006 10:52:43 | DaveGarbutt | [[/|http://tiddlyspot.com/stestphuk/]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 22/6/2006 10:52:57 | DaveGarbutt | [[/|http://tiddlyspot.com/stestphuk/]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 23/6/2006 17:23:3 | DaveGarbutt | [[/|http://tiddlyspot.com/stestphuk/]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 23/6/2006 18:25:13 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 23/6/2006 18:26:31 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 23/6/2006 18:26:48 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 23/6/2006 18:27:5 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 23/6/2006 18:27:42 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . | Ok |\n| 23/6/2006 18:37:28 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 27/6/2006 10:56:27 | DaveGarbutt | [[DaveG-tiddlyspot.html|file:///E:/DaveG-tiddlyspot.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 10/7/2006 19:28:53 | DaveGarbutt | [[DaveG.html|file:///E:/DaveG.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 10/7/2006 19:32:0 | DaveGarbutt | [[DaveG.html|file:///E:/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 10/7/2006 19:38:58 | DaveGarbutt | [[DaveG.html|file:///E:/DaveG.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 10/7/2006 19:39:8 | DaveGarbutt | [[DaveG.html|file:///E:/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 10/7/2006 20:20:3 | DaveGarbutt | [[DaveG.html|file:///E:/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 11/7/2006 10:44:14 | DaveGarbutt | [[DaveG.html|file:///E:/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 16/7/2006 17:40:46 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 16/7/2006 17:41:38 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 16/7/2006 22:33:16 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 20/8/2006 14:10:33 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 20/8/2006 15:8:59 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 20/8/2006 23:33:24 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/stestphuk/store.php]] | . | index.html | . |\n| 20/8/2006 23:39:52 | DaveGarbutt | [[DaveG.html|file:///Volumes/DAVEGARBUTT/DaveG.html]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 23/8/2006 20:25:32 | YourName | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 23/8/2006 20:27:48 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 23/8/2006 20:38:47 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 23/8/2006 20:46:39 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 23/8/2006 21:51:59 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 23/8/2006 22:14:1 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 23/8/2006 22:27:54 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 26/8/2006 19:35:27 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 27/8/2006 11:42:10 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 27/8/2006 15:38:32 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 27/8/2006 17:19:48 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 27/8/2006 18:33:28 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 29/8/2006 16:54:45 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 29/8/2006 18:29:45 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 9:24:6 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 10:6:57 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 30/8/2006 10:57:31 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 30/8/2006 11:15:15 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 30/8/2006 11:30:16 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 30/8/2006 11:46:43 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 14:16:26 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 14:54:23 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 30/8/2006 15:12:0 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 15:28:38 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 30/8/2006 16:10:1 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 17:16:3 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 18:46:7 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 19:52:34 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 19:57:30 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 30/8/2006 22:38:37 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 1/9/2006 12:25:50 | DaveGarbutt | [[/|http://tiddlyspot.com/daveg/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 5/9/2006 17:34:14 | DaveGarbutt | [[/|http://tiddlyspot.com/DaveG/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 8/9/2006 10:30:57 | DaveGarbutt | [[/|http://tiddlyspot.com/DaveG/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 10/9/2006 18:27:43 | DaveGarbutt | [[/|http://tiddlyspot.com/DaveG/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 10/9/2006 18:57:46 | DaveGarbutt | [[/|http://tiddlyspot.com/DaveG/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . | Ok |\n| 10/9/2006 19:1:7 | DaveGarbutt | [[/|http://tiddlyspot.com/DaveG/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 10/9/2006 23:32:57 | DaveGarbutt | [[/|http://daveg.tiddlyspot.com/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 10/9/2006 23:35:42 | DaveGarbutt | [[/|http://daveg.tiddlyspot.com/]] | [[store.php|http://tiddlyspot.com/DaveG/store.php]] | . | index.html | . |\n| 10/9/2006 23:36:56 | DaveGarbutt | [[/|http://daveg.tiddlyspot.com/]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 10/9/2006 23:37:34 | DaveGarbutt | [[/|http://daveg.tiddlyspot.com/]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 10/9/2006 23:47:49 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://tiddlyspot.com/DaveG/store.cgi]] | . | index.html | . | Ok |\n| 10/9/2006 23:50:28 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 11/9/2006 1:52:38 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 11/9/2006 3:5:57 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 11/9/2006 3:29:35 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 11/9/2006 22:31:32 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 15/9/2006 22:59:30 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 15/9/2006 23:57:45 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 16/9/2006 17:59:44 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 16/9/2006 18:2:21 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 16/9/2006 18:25:4 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 17/9/2006 12:1:17 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 17/9/2006 12:13:45 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 17/9/2006 13:10:6 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 17/9/2006 14:12:16 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 17/9/2006 18:28:53 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 18/9/2006 0:17:55 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 18/9/2006 1:14:53 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 18/9/2006 2:16:16 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 20/9/2006 19:16:6 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 4/10/2006 9:10:28 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 4/10/2006 9:10:42 | DaveGarbutt | [[index.html|file:///Users/dave/Documents/BSI/PhUSE%20Papers%202006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 26/10/2006 10:48:6 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 26/10/2006 10:52:14 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 26/10/2006 10:52:33 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 26/10/2006 10:52:58 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 26/10/2006 10:53:54 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 26/10/2006 11:3:36 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 26/10/2006 11:9:57 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 26/10/2006 11:22:35 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 26/10/2006 11:28:11 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 26/10/2006 11:59:44 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 27/10/2006 11:49:24 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 27/10/2006 12:51:48 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 27/10/2006 12:54:28 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 27/10/2006 15:9:22 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 27/10/2006 15:18:5 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 27/10/2006 19:21:50 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 6/11/2006 15:18:29 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 6/11/2006 15:46:4 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 6/11/2006 19:3:42 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 7/11/2006 11:52:40 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 8/11/2006 0:34:38 | DaveGarbutt | [[index.html|file:///Volumes/DAVEGARBUTT/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 8/11/2006 1:15:8 | DaveGarbutt | [[index.html|file:///Volumes/DAVEGARBUTT/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 8/11/2006 15:30:39 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 9/11/2006 16:20:57 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 9/11/2006 16:31:7 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 9/11/2006 19:27:22 | DaveGarbutt | [[index.html|file:///E:/PhUSE%20Dublin%2006/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 28/7/2008 9:6:49 | DaveG | [[index.html|http://daveg.tiddlyspot.com/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 28/7/2008 9:12:27 | DaveG | [[index.html|http://daveg.tiddlyspot.com/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 28/7/2008 9:16:43 | DaveG | [[index.html|http://daveg.tiddlyspot.com/index.html]] | [[store.cgi|http://DaveG.tiddlyspot.com/store.cgi]] | . | index.html | . |
/***\n|''Name:''|UploadPlugin|\n|''Description:''|To save to web a TiddlyWiki|\n|''Version:''|3.4.1|\n|''Date:''|Aug 19, 2006|\n|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|\n|''Documentation:''|http://tiddlywiki.bidix.info/#UploadDoc|\n|''Author:''|BidiX (BidiX (at) bidix (dot) info)|\n|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|\n|''~CoreVersion:''|2.0.0|\n|''Browser:''|Firefox 1.5; InternetExplorer 6.0; Safari|\n|''Include:''|config.lib.file; config.lib.log; config.lib.options; PasswordTweak|\n|''Require:''|[[UploadService|http://tiddlywiki.bidix.info/#UploadService]]|\n***/\n//{{{\nversion.extensions.UploadPlugin = {\n major: 3, minor: 4, revision: 1, \n date: new Date(2006,7,19),\n source: 'http://tiddlywiki.bidix.info/#UploadPlugin',\n documentation: 'http://tiddlywiki.bidix.info/#UploadDoc',\n author: 'BidiX (BidiX (at) bidix (dot) info',\n license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',\n coreVersion: '2.0.0',\n browser: 'Firefox 1.5; InternetExplorer 6.0; Safari'\n};\n//}}}\n\n////+++!![config.lib.file]\n\n//{{{\nif (!config.lib) config.lib = {};\nif (!config.lib.file) config.lib.file= {\n author: 'BidiX',\n version: {major: 0, minor: 1, revision: 0}, \n date: new Date(2006,3,9)\n};\nconfig.lib.file.dirname = function (filePath) {\n var lastpos;\n if ((lastpos = filePath.lastIndexOf("/")) != -1) {\n return filePath.substring(0, lastpos);\n } else {\n return filePath.substring(0, filePath.lastIndexOf("\s\s"));\n }\n};\nconfig.lib.file.basename = function (filePath) {\n var lastpos;\n if ((lastpos = filePath.lastIndexOf("#")) != -1) \n filePath = filePath.substring(0, lastpos);\n if ((lastpos = filePath.lastIndexOf("/")) != -1) {\n return filePath.substring(lastpos + 1);\n } else\n return filePath.substring(filePath.lastIndexOf("\s\s")+1);\n};\nwindow.basename = function() {return "@@deprecated@@";};\n//}}}\n////===\n\n////+++!![config.lib.log]\n\n//{{{\nif (!config.lib) config.lib = {};\nif (!config.lib.log) config.lib.log= {\n author: 'BidiX',\n version: {major: 0, minor: 1, revision: 0}, \n date: new Date(2006,3,9)\n};\nconfig.lib.Log = function(tiddlerTitle, logHeader) {\n if (version.major < 2)\n this.tiddler = store.tiddlers[tiddlerTitle];\n else\n this.tiddler = store.getTiddler(tiddlerTitle);\n if (!this.tiddler) {\n this.tiddler = new Tiddler();\n this.tiddler.title = tiddlerTitle;\n this.tiddler.text = "| !date | !user | !location |" + logHeader;\n this.tiddler.created = new Date();\n this.tiddler.modifier = config.options.txtUserName;\n this.tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers[tiddlerTitle] = this.tiddler;\n else\n store.addTiddler(this.tiddler);\n }\n return this;\n};\n\nconfig.lib.Log.prototype.newLine = function (line) {\n var now = new Date();\n var newText = "| ";\n newText += now.getDate()+"/"+(now.getMonth()+1)+"/"+now.getFullYear() + " ";\n newText += now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+" | ";\n newText += config.options.txtUserName + " | ";\n var location = document.location.toString();\n var filename = config.lib.file.basename(location);\n if (!filename) filename = '/';\n newText += "[["+filename+"|"+location + "]] |";\n this.tiddler.text = this.tiddler.text + "\sn" + newText;\n this.addToLine(line);\n};\n\nconfig.lib.Log.prototype.addToLine = function (text) {\n this.tiddler.text = this.tiddler.text + text;\n this.tiddler.modifier = config.options.txtUserName;\n this.tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers[this.tiddler.tittle] = this.tiddler;\n else {\n store.addTiddler(this.tiddler);\n story.refreshTiddler(this.tiddler.title);\n store.notify(this.tiddler.title, true);\n }\n if (version.major < 2)\n store.notifyAll(); \n};\n//}}}\n////===\n\n////+++!![config.lib.options]\n\n//{{{\nif (!config.lib) config.lib = {};\nif (!config.lib.options) config.lib.options = {\n author: 'BidiX',\n version: {major: 0, minor: 1, revision: 0}, \n date: new Date(2006,3,9)\n};\n\nconfig.lib.options.init = function (name, defaultValue) {\n if (!config.options[name]) {\n config.options[name] = defaultValue;\n saveOptionCookie(name);\n }\n};\n//}}}\n////===\n\n////+++!![PasswordTweak]\n\n//{{{\nversion.extensions.PasswordTweak = {\n major: 1, minor: 0, revision: 2, date: new Date(2006,3,11),\n type: 'tweak',\n source: 'http://tiddlywiki.bidix.info/#PasswordTweak'\n};\n//}}}\n/***\n!!config.macros.option\n***/\n//{{{\nconfig.macros.option.passwordCheckboxLabel = "Save this password on this computer";\nconfig.macros.option.passwordType = "password"; // password | text\n\nconfig.macros.option.onChangeOption = function(e)\n{\n var opt = this.getAttribute("option");\n var elementType,valueField;\n if(opt) {\n switch(opt.substr(0,3)) {\n case "txt":\n elementType = "input";\n valueField = "value";\n break;\n case "pas":\n elementType = "input";\n valueField = "value";\n break;\n case "chk":\n elementType = "input";\n valueField = "checked";\n break;\n }\n config.options[opt] = this[valueField];\n saveOptionCookie(opt);\n var nodes = document.getElementsByTagName(elementType);\n for(var t=0; t<nodes.length; t++) {\n var optNode = nodes[t].getAttribute("option");\n if (opt == optNode) \n nodes[t][valueField] = this[valueField];\n }\n }\n return(true);\n};\n\nconfig.macros.option.handler = function(place,macroName,params)\n{\n var opt = params[0];\n var size = 15;\n if (params[1])\n size = params[1];\n if(config.options[opt] === undefined) {\n return;}\n var c;\n switch(opt.substr(0,3)) {\n case "txt":\n c = document.createElement("input");\n c.onkeyup = this.onChangeOption;\n c.setAttribute ("option",opt);\n c.size = size;\n c.value = config.options[opt];\n place.appendChild(c);\n break;\n case "pas":\n // input password\n c = document.createElement ("input");\n c.setAttribute("type",config.macros.option.passwordType);\n c.onkeyup = this.onChangeOption;\n c.setAttribute("option",opt);\n c.size = size;\n c.value = config.options[opt];\n place.appendChild(c);\n // checkbox link with this password "save this password on this computer"\n c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick = this.onChangeOption;\n c.setAttribute("option","chk"+opt);\n place.appendChild(c);\n c.checked = config.options["chk"+opt];\n // text savePasswordCheckboxLabel\n place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));\n break;\n case "chk":\n c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick = this.onChangeOption;\n c.setAttribute("option",opt);\n place.appendChild(c);\n c.checked = config.options[opt];\n break;\n }\n};\n//}}}\n/***\n!! Option cookie stuff\n***/\n//{{{\nwindow.loadOptionsCookie_orig_PasswordTweak = window.loadOptionsCookie;\nwindow.loadOptionsCookie = function()\n{\n var cookies = document.cookie.split(";");\n for(var c=0; c<cookies.length; c++) {\n var p = cookies[c].indexOf("=");\n if(p != -1) {\n var name = cookies[c].substr(0,p).trim();\n var value = cookies[c].substr(p+1).trim();\n switch(name.substr(0,3)) {\n case "txt":\n config.options[name] = unescape(value);\n break;\n case "pas":\n config.options[name] = unescape(value);\n break;\n case "chk":\n config.options[name] = value == "true";\n break;\n }\n }\n }\n};\n\nwindow.saveOptionCookie_orig_PasswordTweak = window.saveOptionCookie;\nwindow.saveOptionCookie = function(name)\n{\n var c = name + "=";\n switch(name.substr(0,3)) {\n case "txt":\n c += escape(config.options[name].toString());\n break;\n case "chk":\n c += config.options[name] ? "true" : "false";\n // is there an option link with this chk ?\n if (config.options[name.substr(3)]) {\n saveOptionCookie(name.substr(3));\n }\n break;\n case "pas":\n if (config.options["chk"+name]) {\n c += escape(config.options[name].toString());\n } else {\n c += "";\n }\n break;\n }\n c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";\n document.cookie = c;\n};\n//}}}\n/***\n!! Initializations\n***/\n//{{{\n// define config.options.pasPassword\nif (!config.options.pasPassword) {\n config.options.pasPassword = 'defaultPassword';\n window.saveOptionCookie('pasPassword');\n}\n// since loadCookies is first called befor password definition\n// we need to reload cookies\nwindow.loadOptionsCookie();\n//}}}\n////===\n\n////+++!![config.macros.upload]\n\n//{{{\nconfig.macros.upload = {\n accessKey: "U",\n formName: "UploadPlugin",\n contentType: "text/html;charset=UTF-8",\n defaultStoreScript: "store.php"\n};\n\n// only this two configs need to be translated\nconfig.macros.upload.messages = {\n aboutToUpload: "About to upload TiddlyWiki to %0",\n crossDomain: "Certainly a cross-domain isue: access to an other site isn't allowed",\n errorDownloading: "Error downloading",\n errorUploadingContent: "Error uploading content",\n fileLocked: "Files is locked: You are not allowed to Upload",\n fileNotFound: "file to upload not found",\n fileNotUploaded: "File %0 NOT uploaded",\n mainFileUploaded: "Main TiddlyWiki file uploaded to %0",\n urlParamMissing: "url param missing",\n rssFileNotUploaded: "RssFile %0 NOT uploaded",\n rssFileUploaded: "Rss File uploaded to %0"\n};\n\nconfig.macros.upload.label = {\n promptOption: "Save and Upload this TiddlyWiki with UploadOptions",\n promptParamMacro: "Save and Upload this TiddlyWiki in %0",\n saveLabel: "save to web", \n saveToDisk: "save to disk",\n uploadLabel: "upload" \n};\n\nconfig.macros.upload.handler = function(place,macroName,params){\n // parameters initialization\n var storeUrl = params[0];\n var toFilename = params[1];\n var backupDir = params[2];\n var uploadDir = params[3];\n var username = params[4];\n var password; // for security reason no password as macro parameter\n var label;\n if (document.location.toString().substr(0,4) == "http")\n label = this.label.saveLabel;\n else\n label = this.label.uploadLabel;\n var prompt;\n if (storeUrl) {\n prompt = this.label.promptParamMacro.toString().format([this.dirname(storeUrl)]);\n }\n else {\n prompt = this.label.promptOption;\n }\n createTiddlyButton(place, label, prompt, \n function () {\n config.macros.upload.upload(storeUrl, toFilename, uploadDir, backupDir, username, password); \n return false;}, \n null, null, this.accessKey);\n};\nconfig.macros.upload.UploadLog = function() {\n return new config.lib.Log('UploadLog', " !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |" );\n};\nconfig.macros.upload.UploadLog.prototype = config.lib.Log.prototype;\nconfig.macros.upload.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {\n var line = " [[" + config.lib.file.basename(storeUrl) + "|" + storeUrl + "]] | ";\n line += uploadDir + " | " + toFilename + " | " + backupDir + " |";\n this.newLine(line);\n};\nconfig.macros.upload.UploadLog.prototype.endUpload = function() {\n this.addToLine(" Ok |");\n};\nconfig.macros.upload.basename = config.lib.file.basename;\nconfig.macros.upload.dirname = config.lib.file.dirname;\nconfig.macros.upload.upload = function(storeUrl, toFilename, uploadDir, backupDir, username, password)\n{\n // parameters initialization\n storeUrl = (storeUrl ? storeUrl : config.options.txtUploadStoreUrl);\n toFilename = (toFilename ? toFilename : config.options.txtUploadFilename);\n backupDir = (backupDir ? backupDir : config.options.txtUploadBackupDir);\n uploadDir = (uploadDir ? uploadDir : config.options.txtUploadDir);\n username = (username ? username : config.options.txtUploadUserName);\n password = config.options.pasUploadPassword; // for security reason no password as macro parameter\n if (storeUrl === '') {\n storeUrl = config.macros.upload.defaultStoreScript;\n }\n if (config.lib.file.dirname(storeUrl) === '') {\n storeUrl = config.lib.file.dirname(document.location.toString())+'/'+storeUrl;\n }\n if (toFilename === '') {\n toFilename = config.lib.file.basename(document.location.toString());\n }\n\n clearMessage();\n // only for forcing the message to display\n if (version.major < 2)\n store.notifyAll();\n if (!storeUrl) {\n alert(config.macros.upload.messages.urlParamMissing);\n return;\n }\n // Check that file is not locked\n if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {\n if (BidiX.GroupAuthoring.lock.isLocked() && !BidiX.GroupAuthoring.lock.isMyLock()) {\n alert(config.macros.upload.messages.fileLocked);\n return;\n }\n }\n \n var log = new this.UploadLog();\n log.startUpload(storeUrl, toFilename, uploadDir, backupDir);\n if (document.location.toString().substr(0,5) == "file:") {\n saveChanges();\n }\n displayMessage(config.macros.upload.messages.aboutToUpload.format([this.dirname(storeUrl)]), this.dirname(storeUrl));\n this.uploadChanges(storeUrl, toFilename, uploadDir, backupDir, username, password);\n if(config.options.chkGenerateAnRssFeed) {\n //var rssContent = convertUnicodeToUTF8(generateRss());\n var rssContent = generateRss();\n var rssPath = toFilename.substr(0,toFilename.lastIndexOf(".")) + ".xml";\n this.uploadContent(rssContent, storeUrl, rssPath, uploadDir, '', username, password, \n function (responseText) {\n if (responseText.substring(0,1) != '0') {\n displayMessage(config.macros.upload.messages.rssFileNotUploaded.format([rssPath]));\n }\n else {\n if (uploadDir) {\n rssPath = uploadDir + "/" + config.macros.upload.basename(rssPath);\n } else {\n rssPath = config.macros.upload.basename(rssPath);\n }\n displayMessage(config.macros.upload.messages.rssFileUploaded.format(\n [config.macros.upload.dirname(storeUrl)+"/"+rssPath]), config.macros.upload.dirname(storeUrl)+"/"+rssPath);\n }\n // for debugging store.php uncomment last line\n //DEBUG alert(responseText);\n });\n }\n return;\n};\n\nconfig.macros.upload.uploadChanges = function(storeUrl, toFilename, uploadDir, backupDir, \n username, password) {\n var original;\n if (document.location.toString().substr(0,4) == "http") {\n original = this.download(storeUrl, toFilename, uploadDir, backupDir, username, password);\n return;\n }\n else {\n // standard way : Local file\n \n original = loadFile(getLocalPath(document.location.toString()));\n if(window.Components) {\n // it's a mozilla browser\n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]\n .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);\n converter.charset = "UTF-8";\n original = converter.ConvertToUnicode(original);\n }\n catch(e) {\n }\n }\n }\n //DEBUG alert(original);\n this.uploadChangesFrom(original, storeUrl, toFilename, uploadDir, backupDir, \n username, password);\n};\n\nconfig.macros.upload.uploadChangesFrom = function(original, storeUrl, toFilename, uploadDir, backupDir, \n username, password) {\n var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it\n var endSaveArea = '</d' + 'iv>';\n // Locate the storeArea div's\n var posOpeningDiv = original.indexOf(startSaveArea);\n var posClosingDiv = original.lastIndexOf(endSaveArea);\n if((posOpeningDiv == -1) || (posClosingDiv == -1))\n {\n alert(config.messages.invalidFileError.format([document.location.toString()]));\n return;\n }\n var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + \n allTiddlersAsHtml() + "\sn\st\st" +\n original.substr(posClosingDiv);\n var newSiteTitle;\n if(version.major < 2){\n newSiteTitle = (getElementText("siteTitle") + " - " + getElementText("siteSubtitle")).htmlEncode();\n } else {\n newSiteTitle = (wikifyPlain ("SiteTitle") + " - " + wikifyPlain ("SiteSubtitle")).htmlEncode();\n }\n\n revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");\n revised = revised.replaceChunk("<!--PRE-HEAD-START--"+">","<!--PRE-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPreHead","") + "\sn");\n revised = revised.replaceChunk("<!--POST-HEAD-START--"+">","<!--POST-HEAD-END--"+">","\sn" + store.getTiddlerText("MarkupPostHead","") + "\sn");\n revised = revised.replaceChunk("<!--PRE-BODY-START--"+">","<!--PRE-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPreBody","") + "\sn");\n revised = revised.replaceChunk("<!--POST-BODY-START--"+">","<!--POST-BODY-END--"+">","\sn" + store.getTiddlerText("MarkupPostBody","") + "\sn");\n\n var response = this.uploadContent(revised, storeUrl, toFilename, uploadDir, backupDir, \n username, password, function (responseText) {\n if (responseText.substring(0,1) != '0') {\n alert(responseText);\n displayMessage(config.macros.upload.messages.fileNotUploaded.format([getLocalPath(document.location.toString())]));\n }\n else {\n if (uploadDir !== '') {\n toFilename = uploadDir + "/" + config.macros.upload.basename(toFilename);\n } else {\n toFilename = config.macros.upload.basename(toFilename);\n }\n displayMessage(config.macros.upload.messages.mainFileUploaded.format(\n [config.macros.upload.dirname(storeUrl)+"/"+toFilename]), config.macros.upload.dirname(storeUrl)+"/"+toFilename);\n var log = new config.macros.upload.UploadLog();\n log.endUpload();\n store.setDirty(false);\n // erase local lock\n if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {\n BidiX.GroupAuthoring.lock.eraseLock();\n // change mtime with new mtime after upload\n var mtime = responseText.substr(responseText.indexOf("mtime:")+6);\n BidiX.GroupAuthoring.lock.mtime = mtime;\n }\n \n \n }\n // for debugging store.php uncomment last line\n //DEBUG alert(responseText);\n }\n );\n};\n\nconfig.macros.upload.uploadContent = function(content, storeUrl, toFilename, uploadDir, backupDir, \n username, password, callbackFn) {\n var boundary = "---------------------------"+"AaB03x"; \n var request;\n try {\n request = new XMLHttpRequest();\n } \n catch (e) { \n request = new ActiveXObject("Msxml2.XMLHTTP"); \n }\n if (window.netscape){\n try {\n if (document.location.toString().substr(0,4) != "http") {\n netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');}\n }\n catch (e) {}\n } \n //DEBUG alert("user["+config.options.txtUploadUserName+"] password[" + config.options.pasUploadPassword + "]");\n // compose headers data\n var sheader = "";\n sheader += "--" + boundary + "\sr\snContent-disposition: form-data; name=\s"";\n sheader += config.macros.upload.formName +"\s"\sr\sn\sr\sn";\n sheader += "backupDir="+backupDir\n +";user=" + username \n +";password=" + password\n +";uploaddir=" + uploadDir;\n // add lock attributes to sheader\n if (window.BidiX && BidiX.GroupAuthoring && BidiX.GroupAuthoring.lock) {\n var l = BidiX.GroupAuthoring.lock.myLock;\n sheader += ";lockuser=" + l.user\n + ";mtime=" + l.mtime\n + ";locktime=" + l.locktime;\n }\n sheader += ";;\sr\sn"; \n sheader += "\sr\sn" + "--" + boundary + "\sr\sn";\n sheader += "Content-disposition: form-data; name=\s"userfile\s"; filename=\s""+toFilename+"\s"\sr\sn";\n sheader += "Content-Type: " + config.macros.upload.contentType + "\sr\sn";\n sheader += "Content-Length: " + content.length + "\sr\sn\sr\sn";\n // compose trailer data\n var strailer = new String();\n strailer = "\sr\sn--" + boundary + "--\sr\sn";\n var data;\n data = sheader + content + strailer;\n //request.open("POST", storeUrl, true, username, password);\n try {\n request.open("POST", storeUrl, true); \n }\n catch(e) {\n alert(config.macros.upload.messages.crossDomain + "\snError:" +e);\n exit;\n }\n request.onreadystatechange = function () {\n if (request.readyState == 4) {\n if (request.status == 200)\n callbackFn(request.responseText);\n else\n alert(config.macros.upload.messages.errorUploadingContent + "\snStatus: "+request.status.statusText);\n }\n };\n request.setRequestHeader("Content-Length",data.length);\n request.setRequestHeader("Content-Type","multipart/form-data; boundary="+boundary);\n request.send(data); \n};\n\n\nconfig.macros.upload.download = function(uploadUrl, uploadToFilename, uploadDir, uploadBackupDir, \n username, password) {\n var request;\n try {\n request = new XMLHttpRequest();\n } \n catch (e) { \n request = new ActiveXObject("Msxml2.XMLHTTP"); \n }\n try {\n if (uploadUrl.substr(0,4) == "http") {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n }\n else {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n }\n } catch (e) { }\n //request.open("GET", document.location.toString(), true, username, password);\n try {\n request.open("GET", document.location.toString(), true);\n }\n catch(e) {\n alert(config.macros.upload.messages.crossDomain + "\snError:" +e);\n exit;\n }\n \n request.onreadystatechange = function () {\n if (request.readyState == 4) {\n if(request.status == 200) {\n config.macros.upload.uploadChangesFrom(request.responseText, uploadUrl, \n uploadToFilename, uploadDir, uploadBackupDir, username, password);\n }\n else\n alert(config.macros.upload.messages.errorDownloading.format(\n [document.location.toString()]) + "\snStatus: "+request.status.statusText);\n }\n };\n request.send(null);\n};\n\n//}}}\n////===\n\n////+++!![Initializations]\n\n//{{{\nconfig.lib.options.init('txtUploadStoreUrl','store.php');\nconfig.lib.options.init('txtUploadFilename','');\nconfig.lib.options.init('txtUploadDir','');\nconfig.lib.options.init('txtUploadBackupDir','');\nconfig.lib.options.init('txtUploadUserName',config.options.txtUserName);\nconfig.lib.options.init('pasUploadPassword','');\nconfig.shadowTiddlers.UploadDoc = "[[Full Documentation|http://tiddlywiki.bidix.info/l#UploadDoc ]]\sn"; \n\n\n//}}}\n////===\n\n////+++!![Core Hijacking]\n\n//{{{\nconfig.macros.saveChanges.label_orig_UploadPlugin = config.macros.saveChanges.label;\nconfig.macros.saveChanges.label = config.macros.upload.label.saveToDisk;\n\nconfig.macros.saveChanges.handler_orig_UploadPlugin = config.macros.saveChanges.handler;\n\nconfig.macros.saveChanges.handler = function(place)\n{\n if ((!readOnly) && (document.location.toString().substr(0,4) != "http"))\n createTiddlyButton(place,this.label,this.prompt,this.onClick,null,null,this.accessKey);\n};\n\n//}}}\n////===\n
There is a good discussion [[here|http://www.akadia.com/services/unix_tools.html]] of the [[Unix text processing tools]] \n\nThe tools all work on text files and do various common tasks, searching for text being a very common one.\n\nThe tools include:\n\n\n [[find]] [[sed]] [[expr]] [[comm]] [[diff]] [[sort]] [[cut]] [[paste]] [[grep]] [[split]] [[tee]] [[xargs]] [[join]] [[colrm]] [[col]] [[awk and gawk|awk]]\n \nTo see some examples click on a tool in the above list (or in the tags) to see examples in this tiddlywiki.
<!---\n| Name:|~TagglyTaggingViewTemplate |\n| Version:|1.2 (16-Jan-2006)|\n| Source:|http://simonbaird.com/mptw/#TagglyTaggingViewTemplate|\n| Purpose:|See TagglyTagging for more info|\n| Requires:|You need the CSS in TagglyTaggingStyles to make it look right|\n!History\n* 16-Jan-06, version 1.2, added tagglyListWithSort\n* 12-Jan-06, version 1.1, first version\n!Notes\nRemove the miniTag if you don't like it or you don't use QuickOpenTagPlugin\n--->\n<!--{{{-->\n<div class='toolbar' >\n<span macro='toolbar -closeTiddler closeOthers fullscreen +editTiddler permalink references jump'></span>\n</div>\n<div class="tagglyTagged" macro="hideSomeTags"></div>\n<div><span class="title" macro="view title"></span><span class="miniTag" macro="miniTag"></span><div style="font-size:90%;text:right-align;display:inline;padding-left:8.45em;float:right;clear">(<span macro="wordCount"></span> words)</div><!--<span style="padding-left:2.45em;" macro='tagger'></span>--></div>\n<div class="viewer" macro="view text wikified"></div>\n<div class="tagglyTagging" macro="tagglyListWithSort"></div>\n<!--}}}-->\n
* look in two directories and compare the dates\n> {{{ls -l formats.sas ../data/formats.sas7bcat}}}\n* lets make a oneliner to compare the dates:\n* there is a [[test]] command to compare dates of two files - {{{-nt}}} stands for newer than.\n* so we can make an {{{if}}} statement\n> {{{if [[ ../data/formats.sas7bdat -nt ../prog/formats.sas ]] ; then print "catalog out of date run program!"; fi}}}\n** this is not strictly a [[one-liner]] because the {{{;}}} mean end-of-line... \n* this can also be done as a compound command\n> {{{[[ ../data/formats.sas7bdat -ot ../prog/formats.sas ]] && print "catalog out of date run program!"}}}\n* here the [[&&]] means do the second command only if the first command fails, therefore we change the test to //older than//\n* the {{{[[ }}} and {{{]]}}} means make an if test (ie return {{{true}}} or {{{false}}})\n
[[http://groups.google.com/group/comp.soft-sys.sas/browse_thread/thread/b4ff0ff4842f33fd/ccc5c1da4ac32bd6?q=roland+unix&rnum=9#ccc5c1da4ac32bd6]]
* use the date extraction one-liner and adapt it to work on a cross-section of the directories...\n* note the wild card in the directory name - this checks all views\n* $PWD is an EnvironmentVariable (strictly, it is a KornShell SystemVariable) with the path of the current directory in it. This examples assumes you are working in the /vob/... address of your files\n\n{{{\ngawk '/report\s// { ok = match($0,"[0-9]+[A-Z]+[0-9]+"); date=substr($0,RSTART,RLENGTH);if (ok ) print FILENAME":" date, file} ' /view/*_view/$PWD/x8t2_06.lst | sort -t" " | uniq -c\n}}}\n{{{\ngawk: cmd. line:1: warning: escape sequence `\ss' treated as plain `s'\n\n\n 2 /view/garbuda1_view//vob/CLAF237A/CLAF237A2329E1/report/pgm_saf/x8t2_06.lst:12MAY2006 report/pgm_saf/x8t2_06.sas\n 2 /view/gopalde1_view//vob/CLAF237A/CLAF237A2329E1/report/pgm_saf/x8t2_06.lst:14JUL2006 report/pgm_saf/x8t2_06.sas\n[/vob/CLAF237A/CLAF237A2329E1/report/pgm_saf]\n/view/gopalde1_view@ichn21 > \n}}}\n\n!!!!! Note:\n* Insider view:\nthis script looks //inside// the files and finds the last footnote on each page where the program name + date written is put. It does not look at the write date of the file. \nTo do that use [[lh|lh - an alias to print a modification date histogram]] and read [[Where have my dates gone?]] to find out why.\n* It does not print anything for files with no content, or no footer with the address of the program starting with ''report/'' followed by a date in the correct format
<<slideShow>>\n\n--s--\n! Why Safety Reporting IS like Rocket Science\n[[Dave Garbutt|DaveG]]\n\n[[AD13|http://www.lexjansen.com/phuse/2006/ad/ad13.pdf]] @ PhUSE 2006, Dublin\n--s--\n! Introduction\n*I am going to explore ways in which safety reporting (SR) \nIS\nLike, \nRocket Science\n*Along the way we will meet the SEL,\n*Learn what 30 years research on software development has taught \n*Make comparisons to SR\n*And think about where we go next…\n--s--\n! Normal Software development\n1. Requirements\n2. Design\n3. Code\n4.Build\n5.Test (? Go to 3)\n6.Beta release\n7.Final Push\n8.Sales Push , Web Site\n9.Money comes in\n10.Minimal maintenance , given competition\n--s--\n! Software Development for Safety Reporting\n9. Specs made according to 'standards', extended or modified by whim\n8. Coding and checking by programmer\n7. Database changes, additional tables \n6. Modified headers, footers, subset, formatting\n5. Dry run and test (lots of eyeballing and cross checking with specifications)\n4. Checks of code or by re-programming by independent programmer\n3. Data Base Lock\n2. N days for validation and rework.\n1.Ignition - \n0. Lift OFF\n\n--s--\n! Rocket Science? \n*YES, it is , because:\n*No software patches up in Space\n*10,9,8,7….0\n*Bang!\n*Everything has to work\n\n* see [[this|http://today.reuters.com/news/articlenews.aspx?storyID=2006-11-06T191457Z_01_N06275670_RTRUKOC_0_US-SPACE-SHUTTLE.xml]]\nfor a different viewpoint. \n* this 1996 article by [[Charles fishman:|http://www.fastcompany.com/online/06/writestuff_Printer_Friendly.html]] \n--s--\n! SR What is Different?\n*Write once, use once\n*We will run our programs on one set of actual data\n*WE cannot test with exactly that set of data\n*Data Checking or Program Validation?\n*Do we Validate Programs?\n*Or Check Listings?\n*The answer is BOTH\n*This is what makes SR software development different and more like Rocket Science\n--s--\n! The Software Engineering laboratory - it was Rocket Science\n*Existed 1976 till 2001\n*Actually measured performance of many software projects\n*An amazing record of improvement of software quality\n*Compared methodologies by experimentation and by results\n*Defects per thousand lines of code \nThe SEL at NASA\n<<<\n The SEL has achieved productivity comparable to the average MIS or IT system, at the same time achieving quality levels that are at least 10 to 20 times better.\nTo put it a little differently, the average MIS shop would need about 14 calendar months and 110 staff-months to deliver a 100,000 line-of-code MIS system, and it would typically contain about 850 defects when delivered. \nThe NASA SEL would deliver a system of that size with about the same amount of time and effort, but it would contain only about 50 defects. \n<<<\n\nSource: [[http://www.stevemcconnell.com/sgcrib.htm]]\n\n--s--\n! What has / is SE telling us?\n*Software Engineering has been a discipline for over 30 years\n*Methodology matters\n*Select correct methodology for situation\n*Plan, Architect, Test\n*Test: \n*Units\n*Integration\n*Regression \n*Review code\n*Failure rates do not sum together\n--s--\n! SEL's Top Ten ways to reduce defects\n1.Finding and fixing a software problem after delivery is often 100 times more expensive than finding and fixing it during the requirements and design phase.\n2.About 40-50% of the effort on current software projects is spent on avoidable rework.\n3.About 80% of the avoidable rework comes from 20% of the defects.\n4.About 80% of the defects come from 20% of the modules and about half the modules are defect free.\n5.About 90% of the downtime comes from at most 10% of the defects.\n6.Peer reviews catch 60% of the defects.\n7.Perspective-based reviews catch 35% more defects than non-directed reviews.\n8.Disciplined personal practices can reduce defect introduction rates by up to 75%.\n9.All other things being equal, it costs 50% more per source instruction to develop high-dependability software products than to develop low-dependability software products. \nHowever, the investment is more than worth it if significant operations and maintenance costs are involved.\n10.About 40-50% of user programs enter use with nontrivial defects.\n\n--s--\n! Waterfall If \n*- The requirements are knowable in advance,\n*- The requirements have no unresolved, high-risk implications,\n*- The requirements satisfy all the key stakeholders' expectations,\n*- A viable architecture for implementing the requirements is known,\n*- The requirements will be stable during development,\n*- There is enough calendar time to proceed sequentially. (USC)\n--s--\n! Incremental If-\n*- The initial release is good enough to keep the key stakeholders involved,\n*- The architecture is scalable to accommodate needed system growth,\n*- The operational user organizations can adapt to the pace of evolution,\n*- The evolution dimensions are compatible with legacy system replacement,\n*- appropriate management, financial, and incentive structures are in place. (USC)\n\n--s--\n! Measurement and process improvement -SEL Don'ts\n*Don't let team members work in an unsystematic way.\n*Don't set unreasonable goals.\n*Don't implement changes without assessing their impacts and obtaining approval of the change board\n*Don't assume that a schedule slip in the middle of a phase will be made up later.\n*Don't assume that a large amount of documentation ensures success.\n*Don't overstaff, especially early in the project.\n*Don't "gold-plate."\n\n\n--s--\n! Measurement and process improvement -SEL Do's\n*Create and follow a Software Development Plan. \n*Empower project personnel.\n*Minimize the bureaucracy.\n*Define the requirements baseline and manage changes to it.\n*Take periodic snapshots of project health and progress,\n*RE-plan, Re-estimate system size, effort, and schedules periodically\n*Define and manage phase transitions.\n*Start the project with a small senior staff.\n\n--s--\n! Recent trends in methodology\n* The limitations of waterfall development have been widely recognized and\n* Agile development has been born\n* Xtreme programming, pair programming\n* Test-driven Development\n--s--\n! Waterfallen - gather, design, do\n*'Our process begins with requirements' says IT\n*Expecting the user to know their development guidelines and bring a neat set of points and features.\n*Which, with luck exactly fits the latest whizzpopper technology the developers all want to try…\n--s--\n! Waterfallen - blame the requirements \n*This will NEVER happen.\n*Why?\n*Imagine asking a DOS user ca. 1982 for their system requirements for the new faster PCs\n*Would they ask for Norton Commander integration or,\n*Would they sketch this?\n\n--s--\n! The desktop….\n* screenshot of Mac version 1 desktop\n* and the grouch\n--s--\n! Software begins with NEEDS:\n*To do your job more efficiently,\n*More accurately\n*Faster\n*With less tedium\n*In a new way that enables any or all of the above\n*It is always easier to \n*Critique, Suggest based on, or Tweak \n*something than already exists\n*Than it is to create.\n*For this reason building bit by bit with feedback can get you further\n--s--\n! Methodology: test driven development\n*It is becoming more and more accepted that test should be written with the code they test\n*All trivial and other test cases should be done\n*When you are putting software on a Rocket\n*It better be tested before the button is pushed\n*And my perception is that in SR we do not operate like this…\n--s--\n! Test, TEST, and test again\n*When the data changes under the program and \n*The only data that really matters arrives at the critical moment of blast-off\n*Then if…\n*you have validated programs (peer- reviewed, tested)\n*And know they will run on standard testing data - still (to catch unexpected changes) and \n*You can run independent checks on the output\n*You will be a Rocket Scientist, my son!\n--s--\n! Test Oriented Development (I)\n*Independent suite of checks on the output text \n*- Goal - eliminate eyeballing\n*Like Nature and Nurture the quality of deliverables is jointly the data and the transforms\n*Goal - less in-fighting\n*Tools to make individual tailored checking easier \n*Goal - exploit people's brilliance\n*Share code - share tests\n*Goal- re-use of pre validated work\n--s--\n! TOD (II)\n*Measure error and issue rates as well as deadlines \n*Goal - reward accuracy and speed\n*Use process control plots for error rates\n*And for assessing data issues, and programming quality\n*Goal: give statisticians an active QC role\n*Publish the rates on the intranet\n*Reward people that find errors! Do not solely praise staff that deliver on time.\n*Always plot your data. Develop QC plots. Run as data arrives.\n--s--\n! TOD ( III )\n*Make comparisons vs previous versions a routine\n*Goal-> timing of when errors appear is vital for diagnosis\n*If outputs have too much date & time identifiers produce also versions without or build filters\n*Use metadata created from the listings to automate checks of patient counts\n--s--\n! IN SHORT:\n*Integrate testing and quality control into the production process\n--s--\n! Conclusions\n*We need a conversation in the industry about how to move quality forward in SR\n*Comparing ourselves to Rocket Scientists makes more sense than comparing ourselves to Microsoft\n*Goal-> feel good about our craft\n*The combination of our unique needs:\n*Data plus program is the delivery unit\n*No beta phase allowed, no tests after ignition\n*Immense pressure to shorten ignition to lift-off and orbit times \n*Means we need a different methodology & testing strategy from the rest of the software industry\n*TOD or death!\n\n--s--\n! Questions?\n<<<\nIt is not because things are difficult that we do not dare,\nit is because we do not dare that they are difficult.\n<<<\n --Seneca\n--s--\n! Further Reading:\n* this 1996 article by [[Charles fishman:|http://www.fastcompany.com/online/06/writestuff_Printer_Friendly.html]] \n* and [[this|http://today.reuters.com/news/articlenews.aspx?storyID=2006-11-06T191457Z_01_N06275670_RTRUKOC_0_US-SPACE-SHUTTLE.xml]]\nfor a different viewpoint and a slight oversight. \n\n--s--\n! Contact Me\n* I would value your comments and questions on this paper. \n* Please contact me via: DaveG\n* A pdf version of this paper is available at [[Lex Jansen's web site|http://www.lexjansen.com/phuse/2006/ad/ad13.pdf]]\n\n\n\n
* file names (or directories) that start with a dot ([[AKA]] period, decimal point, full stop) are not shown by the default ls command\n* so they are less visible to the user\n* mainly used for configuration files the user does not need to bother with much\n** but also for the synonyms {{{.}}} (the current directory) and\n** {{{.}}}. (the parent directory)\n* to see them with {{{ls}}} use the {{{-a}}} option\n* [[file-name expansion]] also handles a leading dot specially. That is {{{*}}} does not match any filenames starting with a dot.\n** to match them use {{{\s.*}}}\n** * does match filenames containg a dot , e.g. {{{dave.sas}}} will be listed by {{{ls *}}} if it exists\n* [[dot scripts]] are another ([[ksh]]) issue\n
This is part of the [[wikiwikiweb method|http://en.wikipedia.org/wiki/WikiWikiWeb]].\n\nWords with more than one UpperCase letter are automatically made into [[links]]. Click the link, double click the new tiddler and add content. It is therefore very easy to make your web of information grow and keep track of it all.\n\nThere is a tutorial about Tiddlywiki at [[blogjones|http://www.blogjones.com/TiddlyWikiTutorial.html]] and there is also more information [[here|http://www.tiddlywiki.com/#LatestNews%20WikiWord%20WikiWikiWeb%20MainFeatures%20TiddlyWikiAdaptations%20HelloThere]] at the Tiddlywiki.com site. \n\n!!!! NB the version there is the latest major release using different styles etc., this version is running with an older one (from last October, actually) \n\n!!!! If you decide you want to add some content you should read about [[formatting]] in a TiddlyWiki
config.macros.wikipedia = {};\nconfig.macros.wikipedia.handler= function(place,macroName,params) {\n var key=params[0];\n wikify("[["+key+"|http://en.wikipedia.org/wiki/"+key+"]]",place)\n}
/***\n(Almost) as posted by BradleyMeck on the mailing list, 21-Oct-2006. To use put this somewhere in your ViewTemplate:\n{{{<div style="font-size:150%">(<span macro="wordCount"></span> words)</div>}}}\n***/\n//{{{\nmerge(config.macros,{\n wordCount: {\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n createTiddlyText(place,tiddler&&tiddler.text?tiddler.text.match(/\sw+/g).length:"0");\n }\n }\n});\n//}}}\n
!!!! Aix command for simple looping\n* man pages: [[AIX 5.2|http://publib16.boulder.ibm.com/pseries/en_US/cmds/aixcmds1/apply.htm#a167z93f22]]\n!!!! Why use apply?\n* avoids using the (Korn) shell for loop, which is messy to type on one line.\n* it also handles sets of parameters more easily. E.G when you wnat to process the parameters in pairs just use %1 %2 and then the list is processed two at a time.
Command to run a script/command later.\n[[AIX man page|http://www16.boulder.ibm.com/pseries/en_US/cmds/aixcmds1/at.htm#cmw110craw]]
The Unix command for text processing:\n> when written in 1977<<popup 1 "when SAS was also being born">> it was a very original approach to the text processing problem, \n> the concept of matching the text then executing a program (fragment) is simple but //very powerful// because it transcends sequential processing.\n> awk also had one of the first widely available implementations of associative arrays. (Now available in SAS v9 as the hash object)\n> the BEGIN and END patterns are very elegant\n> inevitably it has been widely copied: \n* <<wikipedia XSLT>> processing works similarly\n* SAS A/F has the concept of a BEGIN section, a section for each call, and an END section\n* the SAS datastep also has something similar with the concept of non-executable statements, the {{{if _n_ =1}}} and the {{{end=variable}}} options of set etc. And the implicit loop over datasets that means a SAS program is run on every observation.\n* objects in OO languages have an initialiser, destructor and methods to be used the rest of the time.\nsee also \n* Wikipedia: <<wikipedia awk>>\n* gawk is the GNU project version. It has better diagnostics and error messages. [[with manual here |http://www.lns.cornell.edu/public/COMP/info/gawk/gawk_toc.html]] or [[here at the GNU project | http://www.gnu.org/software/gawk/manual/gawk.html]].\n\n* IBM docs for AIX version [[here|http://www16.boulder.ibm.com/pseries/en_US/cmds/aixcmds1/awk.htm#a1049906]]\nThe AIX awk is like nawk.\nSee also <<man awk>>\n!!!! If gawk is available to you use it because the error messages are much clearer than awk. Not Clear, but clearer :-(\n!!!! You will find much discussion about which awk is fastest, on modern systems this distinction is pretty well dead.
A collection of awk scripts from various application areas:\n*[[FirstPages|ExtractFirstPageOfListing]]: compile the first pages of SAS .lst files into a single file\n*[[GenerateOutputBatch]]: generate a batch file to run outputs, based on a fixed-format delimited file\n*[[GenerateMakefile]]: generate a simple make file, based on a fixed-format delimited text file\n*[[GenerateSASProgram]]: generate a SAS program, based on a fixed-format delimited text file\n*[[GenerateDeleteScript]]: generate a script used to backup and delete automatically generated program files, based on a fixed-format delimited text file\n*[[Lst2rtf]]: convert a SAS output (.lst) file to a basic landscape .rtf file\n*[[RtfReplaceDate]]: replace date fields within .rtf files with arbitrary text (aids version comparison)
Unix command to change the current directory
Script to check all saslogs in a directory for a set of standard errors or warnings.\nCurrently in {{{~garbuda1/chklogs}}}\n!!!! Current Version:\n{{{\n#!/bin/ksh\n# check sas logs for nasty messages that should not exist\n# Thanks to Steve Pike for the greps, I added the count of errors per check type and for file names\n# bugs - this should be an awk or perl program and generate the stats in one go\n# V2 DEc 2005 -reduced number of greps by using regular expressions in the greps\n# Dave Garbutt Nov 2005\n# RE from Vslick log search:\n#^WARNING:.*!([Cc]ompression)|^ERROR:|UNINITIALIZED|converted to|referenced|repeats of|invalid|\n# mathematical operations|converted|NOREPLACE|\s:d+ (?:deleted )*(?:duplicate )*observations|^STLERROR:\n# |^PGM WARNING:|%stlrun\s(|^PGM ERROR:|Physical file does not exist||^NOTE:.*too small|converted|Mathematical operations\n# mod: April added filter to remove extra 'lines' output to log if -ovp is set (error lines are repeated three times)\n# SAS outputs a ^M (oct 015) between each block\n# Also summed a separate category of dataset errors (eg datasets do not exist)\n# added more aggressive judgements about the categories of files.\n# a -v option to call VSlick and RE for deleted or duplicated observation messages\nif [[ -n $1 ]] && [[ $1 != "-v" ]]\nthen\n print "\sn Usage: $0 [-v]\n Checks SASlogs in the current directory for errors, warnings etc. As per the SAS validation guidelines\n Reports how many errors there are, which files they are in and with the\n -v option calls VSlick on the log files with errors (Exceed sessions only)."\n exit\nfi\nrm -f _check.*.txt\nprint "Checking $(ls !(*qc|*mk).log | wc -l) logfiles in $CLEARCASE_ROOT$PWD. "\nprint "\stIgnoring *qc.log and *mk.log\sn"\n# serious do not ignore\ngrep -E '^ERROR[ ]*:|^STLERROR[ ]*:|^[ ]*:[ ]*' !(*qc|*mk).log | gawk -F"[\s015]" '$1 !~ /limit set by errors/ && $1 !~ /Errors printed on page/ {print $1 }' >| _check.error.txt\ngrep -E '^NOTE[ ]*:.*SAS set option OBS=0|Physical file does not exist| NOREPLACE|^ERROR: File [A-Z\s.0-9]+DATA does not exist.' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.dserror.txt\ngrep -i -E '^PGM ERROR' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.pgmerror.txt\n# might be OK... but forbidden by the validation guidelines\ngrep -i -E '^NOTE[ ]*:.*(uninitialized|invalid)' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.nonvalid.txt\n# 'converted to' messages can also appear in ERRORs, but they are caught above anyway\ngrep -i -E '^NOTE[ ]*:.*(repeats of BY|too small|converted|Mathematical operations)' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.repeat.txt\n# warnings still need to be followed up\ngrep -i -E '^DEVELOPER_WARNING[ ]*:' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.developer_warning.txt\ngrep -i -E '^PGM WARNING|^PGM NOTE' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.pgmwarn.txt\n# find warnings but ignore those about compression\ngrep -E '^WARNING[ ]*:.*!([Cc]ompression)' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >| _check.warning.txt\n# check for bad usage of nodupkey etc\ngrep -E 'SORT.*NODUPKEY|^NOTE[ ]*: [0-9]*[1-9]+ (:deleted )?(:duplicate )?observations (:deleted)?(:duplicate)?' !(*qc|*mk).log |gawk -F"[\s015]" '{print $1 }' >> _check.warning.txt\n\n# Summary section\nprint "Number of warnings and errors by type"\nwc -l _check*.txt\nprint "\snNumber of log file lines checked: " $(wc -l !(*qc|*mk).log | tail -1 )\n#print "Log files with errors. (number of errors, filename)"\nprint "\snLog files with data errors or where SAS set OBS=0. Execution very likely failed. "\nawk -F'[:]' '{ print $1 }' _check.dserror.txt | sort | uniq | tee _count-errds.txt\n\nif [[ -z $(<_count-errds.txt) ]]\nthen\n print "\st None."\nfi\nprint "\snLog files with other errors. Validation failed."\n\nawk -F'[:]' '{ print $1 }' _check.error.txt _check.pgmerror.txt | sort | uniq >|_count-err.txt\ncat _count-errds.txt _count-err.txt | sort | uniq >|_count-errall.txt\n#print " with ERROR: " ; cat <_count-err.txt\n#print " with dataset ERROR: " ; cat <_count-errds.txt\n\ncomm -23 _count-err.txt _count-errds.txt\nprint "\snLog files with forbidden warnings or notes only. Validation failed unless reasons can be documented."\nawk -F'[:]' '{ print $1 }' _check.warning.txt _check.developer_warning.txt _check.repeat.txt _check.nonvalid.txt | sort | uniq >| _count-warn.txt\n\n#print " all files with ERROR: " ; cat <_count-errall.txt\nif [[ -z $(<_count-warn.txt) ]]\nthen\n print "\st None."\nelse\n # Now print the list of files names with warnings and not with errors (latter are already listed above)\n comm -23 _count-warn.txt _count-errall.txt | paste - - -\nfi\nprint " Log files with PGM Warnings (number of warnings, filename) these may pass as validated if no other errors or warnings present"\npgmwarn=$(awk -F'[:]' '{ print $1 }' _check.pgmwarn.txt | sort | uniq -c )\nprint "\st${pgmwarn:- None.}"\nprint "\snNote: this script has not been exhaustively checked on every possible SASlog.\n Inform me if you find cases that are missed but should be caught. Dave Garbutt"\nif [[ $1 = -v ]] && [[ -n $DISPLAY ]]\nthen\n editlist=$(<_count-errall.txt)\n print "\sn\stCalling vslick: on $editlist"\n /proj/genesis/adm/it/vslick/bin/vs +new -sua $editlist &\nfi\n# now clear up temporary files\nrm -f _count-warn*.txt _count-err*.txt\n}}}\n\n!!!! Older version:\n{{{\n#!/bin/ksh\n# check sas logs for nasty messages that should not exist\n# Thanks to Steve Pike for the greps, I added the count of errors per check type and for file names\n# bugs - this should be an awk or perl program and generate the stats in one go\n# V2 DEc 2005 -reduced number of greps by using regular expressions in the greps\n# Dave Garbutt Nov 2005\n# RE from Vslick log search:\n# ^WARNING:.*!([Cc]ompression)|^ERROR:|UNINITIALIZED|converted to|referenced|repeats of|invalid|\n# mathematical operations|converted|NOREPLACE|\s:d+ observations|^STLERROR:\n# need to add some of these too\nrm -f _check.*.txt\n# serious do not ignore\ngrep -E '^ERROR:|^STLERROR:' *.log | grep -v -E "limit set by errors|errors printed on pages" >| _check.error.txt\ngrep -E '^NOTE:.*SAS set option OBS=0' *.log >| _check.dserror.txt\ngrep -i -E '^PGM ERROR' *.log >| _check.pgmerror.txt\n# most likely OK... but\ngrep -i -E '^NOTE:.*uninit' *.log >| _check.uninit.txt\ngrep -i -E ^NOTE:.*invalid *.log >| _check.invalid.txt\ngrep -i -E ^NOTE:.*repeat *.log >| _check.repeat.txt\n# warnings still need to be followed up\ngrep -i -E ^DEVELOPER_WARNING: *.log >| _check.developer_warning.txt\ngrep -i -E '^PGM WARNING' *.log >| _check.pgmwarn.txt\ngrep -E '^WARNING:.*!([Cc]ompression)' *.log >| _check.warning.txt\nprint "Number of warnings by type"\nwc -l _check*.txt\nprint "Number of log file lines checked: " $(wc -l *.log | awk '/total/ {print $1} ')\nprint "Log files with errors. (number of errors, filename)"\nawk -F'[:]' '{ print $1 }' _check.error.txt _check.pgmerror.txt _check.dserror.txt | sort | uniq -c | tee _count-err.txt\nprint "Log files with warnings, or worrying notes only"\nawk -F'[:]' '{ print $1 }' _check.warning.txt _check.developer_warning.txt _check.repeat.txt _check.uninit.txt _check.pgmwarn.txt | sort | uniq -c > _count-warn.txt\nprint " Log files with PGM Warnings (number of warnings, filename) "\nawk -F'[:]' '{ print $1 }' _check.pgmwarn.txt | sort | uniq -c\n# strip the count out of file names list and sort on file name\nawk '{print "\st"$2}' _count-err.txt |sort >_count-errsort.txt\nawk '{print "\st"$2}' _count-warn.txt |sort >_count-warnsort.txt\n# Now print the list of files names with warnings and not with errors (latter are already listed above)\nprint " Log files with other warnings"\ncomm -23 _count-warnsort.txt _count-errsort.txt\n# now clear up temporary files\nrm -f _count-warn*.txt _count-err*.txt\n}}}\n !!!! maybe remove the fold for logs with errors\nOrginal version is from StevePike: kshScriptChklogs\n\n\n!!!! example output in CheckSASLogsWithChklogsScript\n
* command to do a byte by byte comparison\n* if the files are the same returns 0 & gives no messages\n* if different returns 1 and pint the number of the first byte that is different.
<<man comm>> get common lines...
<<man cut>>
* code \n{{{\n#/bin/ksh93\ndf -k | awk ' \n BEGIN {gb = 1024 * 1024 } \n$0 ~ /%Used/ { print $0 }\n$1 !~ /.vbs/ { total += $2 ; print $2 / gb"\st " $3 /gb"\st " $4"\st " $5"\st " $6 "\st " $7 }\n END {print "Total : " total / gb " GB"} '\n}}}\n* example output\n{{{\ntec_cla1@aetna>dfgb \nFilesystem 1024-blocks Free %Used Iused %Iused Mounted on\n0.000976562 0 %Used Iused %Iused Mounted\n0.125 0.0825844 34% 3572 6% /\n4.125 0.532532 88% 76556 8% /usr\n2.375 1.60339 33% 9553 2% /var\n1.875 1.64274 13% 5966 2% /tmp\n3.5 0.980824 72% 29268 4% /home\n1.3125 0.0720901 95% 17184 5% /usr/local\n0.0625 0.0372505 41% 364 3% /tivoli\n3.1875 0.281109 92% 6778 1% /ftpsys\n12.75 7.92876 38% 5359 1% /proj/sastmp\n11.75 6.0537 49% 38577 6% /u01/app\n51 13.0994 75% 94139 3% /proj/genesis\n38.5 10.2145 74% 372111 4% /proj/rational\n0 0 - - - /proc\n0.1875 0.114212 40% 712 2% /opt\n1 0.999535 1% 4 1% /proj/gpsII\n6 2.80851 54% 1636 1% /u01/app2\n6.25 3.3149 47% 4019 1% /staging_gps2\n2.5 1.84305 27% 11193 7% /opt/rational\n9.25 5.70012 39% 18729 4% /proj/genesis/data/devl/user\n0.25 0.0867691 66% 11207 18% /appslog\n0.125 0.0825844 34% 3572 6% /view\nTotal : 156.126 GB\n}}}
<<man echo>>
The Shell expands WildcardsInFilenames before calling the command you named.\nThe rules are more flexible than in DOS or VMS.\n See [[IBM docs|http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.doc/aixuser/usrosdev/file_name_subst_korn_shell.htm]]\n\n
<<man fmt>>
Type the text for 'fold'
The content of tiddlers is held in a pure text way. So it is editable with an ordinary browser text-box.\n\nThe tiddlers below are tagged with 'formatting' because they contain information about how to achieve different text effects using the TiddlyWiki conventions
gawk : gnu version of awk\n\nImproved diagnostics:\n{{{\n[/vob/CLAF237A/pool/pool_003/util]\ngarbuda1@ichn21> awk 'BEGIN {RS="[;\sn]"/sasexec/} {print }' cm_output.txt\n syntax error The source line is 1.\n The error context is\n BEGIN >>> {RS="[;\sn]"/sasexec/} <<< \n awk: The statement cannot be correctly parsed.\n The source line is 1.\n[/vob/CLAF237A/pool/pool_003/util]\ngarbuda1@ichn21> gawk 'BEGIN {RS="[;\sn]"/sasexec/} {print }' cm_output.txt\ngawk: cmd. line:1: BEGIN {RS="[;\sn]"/sasexec/} {print }\ngawk: cmd. line:1: ^ parse error\n}}}
find text in files matching a wild card - search a file or pipe\n-v matches files without this text\n-i ignore case \n\nNormally used in a [[pipe]].\n\n
!!! if then else syntax for [[Korn shell]]\nsearch for if in [[Example scripts]] for many examples\n\n!!!! see tagged tiddlers:
short for korn shell - written by DavidKorn\n----\n^^merged from: [[H:\sDATA\sGTD stuff\sunixWiki.html#ksh|H:\sDATA\sGTD stuff\sunixWiki.html#ksh]]^^\n^^Thursday, December 01, 2005 21:39:00 by StevePike^^\nThe korn shell is an interactive command language that provides access to the UNIX system. The ksh language is also a high-level programming language which can be used for prototyping / writing applications.\n\nFurther information concerning the korn shell can be found at the following location:\nhttp://www.kornshell.com\n\nHere is a brief guide to [[Scripting]].\n\nHere is a collection of useful [[Scripts]], and here [[Example scripts]]
Korn Shell - version from 1993, available on AIX since v5\nMade public domain by David Korn in ?2000\n* extra facilities vs [[ksh]] for example hashes and more parameter substitution functions
{{{alias lh='ls -l -H | sed 1d | cut -c 44-51 | sort |uniq -c '}}}\n\nA parametrised version:\n{{{\nalias lh="apply ' ls -l -H %1 | sed 1d | cut -c 44-51 | sort |uniq -c' "\n}}}\n\n{{{\n/view/garbuda1_view@ichn21> lh '*.lst'\n 1 Aug 11 \n 1 Aug 14 \n 2 Aug 17 \n}}}\n* the parameter - most likely with a wild card for [[FileName expansion]]- must be quoted with single quotes\nThis works on systems with the apply command, useful because the [[Korn shell]] does not allow parameters in aliases.\n\n!!!! How about lists of wild card sets?\n{{{\n alias lh="apply -1 'print \s"\snMod dates histogram for %1\s"; ls -l -H %1 | sed 1d | cut -c 44-51 | sort |uniq -c' "\n}}}\nGives:\n{{{\n\nMod dates histogram for *.lst\n 1 Aug 11 \n 1 Aug 14 \n 2 Aug 17 \n\nMod dates histogram for *.rtf\n*.rtf not found\n\nMod dates histogram for *.sas\n 9 Apr 5 \n 17 Apr 6 \n 11 Apr 7 \n 13 Apr 10 \n 1 Apr 19 \n 6 Apr 21 \n 2 Apr 23 \n 1 Apr 24 \n 35 Apr 28 \n 1 Aug 11 \n 2 Aug 14 \n 1 Aug 16 \n 1 Jul 1 \n 3 Jul 5 \n 1 Jul 6 \n 1 Jul 7 \n 2 Jul 17 \n 1 Jul 18 \n 2 Jul 31 \n 2 Jun 2 \n 2 Jun 8 \n 1 Jun 15 \n 1 Jun 21 \n 11 Jun 22 \n 1 Jun 29 \n 3 May 4 \n 2 May 5 \n 2 May 17 \n 1 May 24 \n 1 May 25 \n 1 May 26 \n 1 May 29 \n 1 May 31 \n}}}\n
<<man locate>>
<<man look>>
The new version of awk. Incorporated in the AIX [[awk]]
<<man Perl>>\n\nSee also this introduction to Perl [[one-liners|http://www.builderau.com.au/program/unix/print.htm?TYPE=story&AT=320266188-339024638t-320000993c]]
A special exact syntax for wild-card-type matching of strings used by many Unix programs, and more recently by editors and programming languages (SAS, ruby, perl,JavaScript...)\n\n* the detailed implementation varies slightly across [[Unix commands]]\n* the syntax is similar to the wildcards used for expanding filenames //but it is not the same//, it is more powerful, in fact. \n* see [[awk]] for examples and other tiddlers tagged with ''regular expressions''\n!!!! watch out \n* because the normal [[Unix]] rule of '[[silence means success]]' does not apply when using [[awk]] or [[grep]]. Silence (i.e. no output) can also be because there was an error in your regex that caused it not to match the strings you wanted. \n
|No.|File | OK? | Notes and comments | re-done OK? |h\n|>|>|/vob/CMyPROJ/CMyPROJ0103/report|>|Thu Apr 6 17:14:11 DFT 2006|\n| 1|./pgm_a/autoexec.sas | | | |\n| 2|./pgm_a/pops.sas | | | |\n| 3|./pgm_a/subpops.sas | | | |\n| 4|./pgm_a/ds_aevs.sas | | | |\n…\n| 21|./pgm_a/mk_trtm.sas | | | |\n\n
Type the text for 'sed'
\n\n HANDY ONE-LINERS FOR SED (Unix stream editor) Apr. 28, 2000\n compiled by Eric Pement <epement@jpusa.org> version 5.0\n Latest version of this file is usually at:\n http://www.cornerstonemag.com/sed/sed1line.txt\n \n\n FILE SPACING:\n\n # double space a file\n sed G\n\n # triple space a file\n sed 'G;G'\n\n # undo double-spacing (assumes even-numbered lines are always blank)\n sed 'n;d'\n\n NUMBERING:\n\n # number each line of a file (simple left alignment). Using a tab (see\n # note on '\st' at end of file) instead of space will preserve margins.\n sed = filename | sed 'N;s/\sn/\st/'\n\n # number each line of a file (number on left, right-aligned)\n sed = filename | sed 'N; s/^/ /; s/ *\s(.\s{6,\s}\s)\sn/\s1 /'\n\n # number each line of file, but only print numbers if line is not blank\n sed '/./=' filename | sed '/./N; s/\sn/ /'\n\n # count lines (emulates "wc -l")\n sed -n '$='\n\n TEXT CONVERSION AND SUBSTITUTION:\n\n # IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format\n sed 's/.$//' # assumes that all lines end with CR/LF\n sed 's/^M$//' # in bash/tcsh, press Ctrl-V then Ctrl-M\n sed 's/\sx0D$//' # gsed 3.02.80, but top script is easier\n\n # IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format\n sed "s/$/`echo -e \s\s\sr`/" # command line under ksh\n sed 's/$'"/`echo \s\s\sr`/" # command line under bash\n sed "s/$/`echo \s\s\sr`/" # command line under zsh\n sed 's/$/\sr/' # gsed 3.02.80\n\n # IN DOS ENVIRONMENT: convert Unix newlines (LF) to DOS format\n sed "s/$//" # method 1\n sed -n p # method 2\n\n # IN DOS ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format\n # Cannot be done with DOS versions of sed. Use "tr" instead.\n tr -d \sr <infile >outfile # GNU tr version 1.22 or higher\n\n # delete leading whitespace (spaces, tabs) from front of each line\n # aligns all text flush left\n sed 's/^[ \st]*//' # see note on '\st' at end of file\n\n # delete trailing whitespace (spaces, tabs) from end of each line\n sed 's/[ \st]*$//' # see note on '\st' at end of file\n\n # delete BOTH leading and trailing whitespace from each line\n sed 's/^[ \st]*//;s/[ \st]*$//'\n\n # insert 5 blank spaces at beginning of each line (make page offset)\n sed 's/^/ /'\n\n # align all text flush right on a 79-column width\n sed -e :a -e 's/^.\s{1,78\s}$/ &/;ta' # set at 78 plus 1 space\n\n # center all text in the middle of 79-column width. In method 1,\n # spaces at the beginning of the line are significant, and trailing\n # spaces are appended at the end of the line. In method 2, spaces at\n # the beginning of the line are discarded in centering the line, and\n # no trailing spaces appear at the end of lines.\n sed -e :a -e 's/^.\s{1,77\s}$/ & /;ta' # method 1\n sed -e :a -e 's/^.\s{1,77\s}$/ &/;ta' -e 's/\s( *\s)\s1/\s1/' # method 2\n\n # substitute (find & replace) "foo" with "bar" on each line\n sed 's/foo/bar/' # replaces only 1st instance in a line\n sed 's/foo/bar/4' # replaces only 4th instance in a line\n sed 's/foo/bar/g' # replaces ALL instances in a line\n\n # substitute "foo" with "bar" ONLY for lines which contain "baz"\n sed '/baz/s/foo/bar/g'\n\n # substitute "foo" with "bar" EXCEPT for lines which contain "baz"\n sed '/baz/!s/foo/bar/g'\n\n # change "scarlet" or "ruby" or "puce" to "red"\n sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g' # most seds\n gsed 's/scarlet\s|ruby\s|puce/red/g' # GNU sed only\n\n # reverse order of lines (emulates "tac")\n # bug/feature in HHsed v1.5 causes blank lines to be deleted\n sed '1!G;h;$!d' # method 1\n sed -n '1!G;h;$p' # method 2\n\n # reverse each character on the line (emulates "rev")\n sed '/\sn/!G;s/\s(.\s)\s(.*\sn\s)/&\s2\s1/;//D;s/.//'\n\n # join pairs of lines side-by-side (like "paste")\n sed '$!N;s/\sn/ /'\n\n # if a line ends with a backslash, append the next line to it\n sed -e :a -e '/\s\s$/N; s/\s\s\sn//; ta'\n\n # if a line begins with an equal sign, append it to the previous line\n # and replace the "=" with a single space\n sed -e :a -e '$!N;s/\sn=/ /;ta' -e 'P;D'\n\n # add commas to numeric strings, changing "1234567" to "1,234,567"\n gsed ':a;s/\sB[0-9]\s{3\s}\s>/,&/;ta' # GNU sed\n sed -e :a -e 's/\s(.*[0-9]\s)\s([0-9]\s{3\s}\s)/\s1,\s2/;ta' # other seds\n\n # add commas to numbers with decimal points and minus signs (GNU sed)\n gsed ':a;s/\s(^\s|[^0-9.]\s)\s([0-9]\s+\s)\s([0-9]\s{3\s}\s)/\s1\s2,\s3/g;ta'\n\n # add a blank line every 5 lines (after lines 5, 10, 15, 20, etc.)\n gsed '0~5G' # GNU sed only\n sed 'n;n;n;n;G;' # other seds\n\n SELECTIVE PRINTING OF CERTAIN LINES:\n\n # print first 10 lines of file (emulates behavior of "head")\n sed 10q\n\n # print first line of file (emulates "head -1")\n sed q\n\n # print the last 10 lines of a file (emulates "tail")\n sed -e :a -e '$q;N;11,$D;ba'\n\n # print the last 2 lines of a file (emulates "tail -2")\n sed '$!N;$!D'\n\n # print the last line of a file (emulates "tail -1")\n sed '$!d' # method 1\n sed -n '$p' # method 2\n\n # print only lines which match regular expression (emulates "grep")\n sed -n '/regexp/p' # method 1\n sed '/regexp/!d' # method 2\n\n # print only lines which do NOT match regexp (emulates "grep -v")\n sed -n '/regexp/!p' # method 1, corresponds to above\n sed '/regexp/d' # method 2, simpler syntax\n\n # print 1 line of context before and after regexp, with line number\n # indicating where the regexp occurred (similar to "grep -A1 -B1")\n sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h\n\n # grep for AAA and BBB and CCC (in any order)\n sed '/AAA/!d; /BBB/!d; /CCC/!d'\n\n # grep for AAA and BBB and CCC (in that order)\n sed '/AAA.*BBB.*CCC/!d'\n\n # grep for AAA or BBB or CCC (emulates "egrep")\n sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d # most seds\n gsed '/AAA\s|BBB\s|CCC/!d' # GNU sed only\n\n # print paragraph if it contains AAA (blank lines separate paragraphs)\n # HHsed v1.5 must insert a 'G;' after 'x;' in the next 3 scripts below\n sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'\n\n # print paragraph if it contains AAA and BBB and CCC (in any order)\n sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'\n\n # print paragraph if it contains AAA or BBB or CCC\n sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d\n gsed '/./{H;$!d;};x;/AAA\s|BBB\s|CCC/b;d' # GNU sed only\n\n # print only lines of 65 characters or longer\n sed -n '/^.\s{65\s}/p'\n\n # print only lines of less than 65 characters\n sed -n '/^.\s{65\s}/!p' # method 1, corresponds to above\n sed '/^.\s{65\s}/d' # method 2, simpler syntax\n\n # print section of file from regular expression to end of file\n sed -n '/regexp/,$p'\n\n # print section of file based on line numbers (lines 8-12, inclusive)\n sed -n '8,12p' # method 1\n sed '8,12!d' # method 2\n\n # print line number 52\n sed -n '52p' # method 1\n sed '52!d' # method 2\n sed '52q;d' # method 3, efficient on large files\n\n # beginning at line 3, print every 7th line\n gsed -n '3~7p' # GNU sed only\n sed -n '3,${p;n;n;n;n;n;n;}' # other seds\n\n # print section of file between two regular expressions (inclusive)\n sed -n '/Iowa/,/Montana/p' # case sensitive\n\n SELECTIVE DELETION OF CERTAIN LINES:\n\n # print all of file EXCEPT section between 2 regular expressions\n sed '/Iowa/,/Montana/d'\n\n # delete duplicate, consecutive lines from a file (emulates "uniq").\n # First line in a set of duplicate lines is kept, rest are deleted.\n sed '$!N; /^\s(.*\s)\sn\s1$/!P; D'\n\n # delete duplicate, nonconsecutive lines from a file. Beware not to\n # overflow the buffer size of the hold space, or else use GNU sed.\n sed -n 'G; s/\sn/&&/; /^\s([ -~]*\sn\s).*\sn\s1/d; s/\sn//; h; P'\n\n # delete the first 10 lines of a file\n sed '1,10d'\n\n # delete the last line of a file\n sed '$d'\n\n # delete the last 2 lines of a file\n sed 'N;$!P;$!D;$d'\n\n # delete the last 10 lines of a file\n sed -e :a -e '$d;N;2,10ba' -e 'P;D' # method 1\n sed -n -e :a -e '1,10!{P;N;D;};N;ba' # method 2\n\n # delete every 8th line\n gsed '0~8d' # GNU sed only\n sed 'n;n;n;n;n;n;n;d;' # other seds\n\n # delete ALL blank lines from a file (same as "grep '.' ")\n sed '/^$/d' # method 1\n sed '/./!d' # method 2\n\n # delete all CONSECUTIVE blank lines from file except the first; also\n # deletes all blank lines from top and end of file (emulates "cat -s")\n sed '/./,/^$/!d' # method 1, allows 0 blanks at top, 1 at EOF\n sed '/^$/N;/\sn$/D' # method 2, allows 1 blank at top, 0 at EOF\n\n # delete all CONSECUTIVE blank lines from file except the first 2:\n sed '/^$/N;/\sn$/N;//D'\n\n # delete all leading blank lines at top of file\n sed '/./,$!d'\n\n # delete all trailing blank lines at end of file\n sed -e :a -e '/^\sn*$/N;/\sn$/ba'\n\n # delete the last line of each paragraph\n sed -n '/^$/{p;h;};/./{x;/./p;}'\n\n SPECIAL APPLICATIONS:\n\n # remove nroff overstrikes (char, backspace) from man pages. The 'echo'\n # command may need an -e switch if you use Unix System V or bash shell.\n sed "s/.`echo \s\s\sb`//g" # double quotes required for Unix environment\n sed 's/.^H//g' # in bash/tcsh, press Ctrl-V and then Ctrl-H\n sed 's/.\sx08//g' # hex expression for sed v1.5\n\n # get Usenet/e-mail message header\n sed '/^$/q' # deletes everything after first blank line\n\n # get Usenet/e-mail message body\n sed '1,/^$/d' # deletes everything up to first blank line\n\n # get Subject header, but remove initial "Subject: " portion\n sed '/^Subject: */!d; s///;q'\n\n # get return address header\n sed '/^Reply-To:/q; /^From:/h; /./d;g;q'\n\n # parse out the address proper. Pulls out the e-mail address by itself\n # from the 1-line return address header (see preceding script)\n sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'\n\n # add a leading angle bracket and space to each line (quote a message)\n sed 's/^/> /'\n\n # delete leading angle bracket & space from each line (unquote a message)\n sed 's/^> //'\n\n # remove most HTML tags (accommodates multiple-line tags)\n sed -e :a -e 's/<[^>]*>//g;/</N;//ba'\n\n # extract multi-part uuencoded binaries, removing extraneous header\n # info, so that only the uuencoded portion remains. Files passed to\n # sed must be passed in the proper order. Version 1 can be entered\n # from the command line; version 2 can be made into an executable\n # Unix shell script. (Modified from a script by Rahul Dhesi.)\n sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode # vers. 1\n sed '/^end/,/^begin/d' "$@" | uudecode # vers. 2\n\n # zip up each .TXT file individually, deleting the source file and\n # setting the name of each .ZIP file to the basename of the .TXT file\n # (under DOS: the "dir /b" switch returns bare filenames in all caps).\n echo @echo off >zipup.bat\n dir /b *.txt | sed "s/^\s(.*\s)\s.TXT/pkzip -mo \s1 \s1.TXT/" >>zipup.bat\n\n TYPICAL USE: Sed takes one or more editing commands and applies all of\n them, in sequence, to each line of input. After all the commands have\n been applied to the first input line, that line is output and a second\n input line is taken for processing, and the cycle repeats. The\n preceding examples assume that input comes from the standard input\n device (i.e, the console, normally this will be piped input). One or\n more filenames can be appended to the command line if the input does\n not come from stdin. Output is sent to stdout (the screen). Thus:\n\n cat filename | sed '10q' # uses piped input\n sed '10q' filename # same effect, avoids a useless "cat"\n sed '10q' filename > newfile # redirects output to disk\n\n For additional syntax instructions, including the way to apply editing\n commands from a disk file instead of the command line, consult "sed &\n awk, 2nd Edition," by Dale Dougherty and Arnold Robbins (O'Reilly,\n 1997; http://www.ora.com), "UNIX Text Processing," by Dale Dougherty\n and Tim O'Reilly (Hayden Books, 1987) or the tutorials by Mike Arst\n distributed in U-SEDIT2.ZIP (many sites). To fully exploit the power\n of sed, one must understand "regular expressions." For this, see\n "Mastering Regular Expressions" by Jeffrey Friedl (O'Reilly, 1997).\n The manual ("man") pages on Unix systems may be helpful (try "man\n sed", "man regexp", or the subsection on regular expressions in "man\n ed"), but man pages are notoriously difficult. They are not written to\n teach sed use or regexps to first-time users, but as a reference text\n for those already acquainted with these tools.\n\n QUOTING SYNTAX: The preceding examples use single quotes ('...')\n instead of double quotes ("...") to enclose editing commands, since\n sed is typically used on a Unix platform. Single quotes prevent the\n Unix shell from intrepreting the dollar sign ($) and backquotes\n (`...`), which are expanded by the shell if they are enclosed in\n double quotes. Users of the "csh" shell and derivatives will also need\n to quote the exclamation mark (!) with the backslash (i.e., \s!) to\n properly run the examples listed above, even within single quotes.\n Versions of sed written for DOS invariably require double quotes\n ("...") instead of single quotes to enclose editing commands.\n\n USE OF '\st' IN SED SCRIPTS: For clarity in documentation, we have used\n the expression '\st' to indicate a tab character (0x09) in the scripts.\n However, most versions of sed do not recognize the '\st' abbreviation,\n so when typing these scripts from the command line, you should press\n the TAB key instead. '\st' is supported as a regular expression\n metacharacter in awk, perl, and HHsed, sedmod, and GNU sed v3.02.80.\n\n VERSIONS OF SED: Versions of sed do differ, and some slight syntax\n variation is to be expected. In particular, most do not support the\n use of labels (:name) or branch instructions (b,t) within editing\n commands, except at the end of those commands. We have used the syntax\n which will be portable to most users of sed, even though the popular\n GNU versions of sed allow a more succinct syntax. When the reader sees\n a fairly long command such as this:\n\n sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d\n\n it is heartening to know that GNU sed will let you reduce it to:\n\n sed '/AAA/b;/BBB/b;/CCC/b;d' # or even\n sed '/AAA\s|BBB\s|CCC/b;d'\n\n In addition, remember that while many versions of sed accept a command\n like "/one/ s/RE1/RE2/", some do NOT allow "/one/! s/RE1/RE2/", which\n contains space before the 's'. Omit the space when typing the command.\n\n OPTIMIZING FOR SPEED: If execution speed needs to be increased (due to\n large input files or slow processors or hard disks), substitution will\n be executed more quickly if the "find" expression is specified before\n giving the "s/.../.../" instruction. Thus:\n\n sed 's/foo/bar/g' filename # standard replace command\n sed '/foo/ s/foo/bar/g' filename # executes more quickly\n sed '/foo/ s//bar/g' filename # shorthand sed syntax\n\n On line selection or deletion in which you only need to output lines\n from the first part of the file, a "quit" command (q) in the script\n will drastically reduce processing time for large files. Thus:\n\n sed -n '45,50p' filename # print line nos. 45-50 of a file\n sed -n '51q;45,50p' filename # same, but executes much faster\n\n If you have any additional scripts to contribute or if you find errors\n in this document, please send e-mail to the compiler. Indicate the\n version of sed you used, the operating system it was compiled for, and\n the nature of the problem. Various scripts in this file were written\n or contributed by:\n\n Al Aab <af137@freenet.toronto.on.ca> # "seders" list moderator\n Edgar Allen <era@sky.net> # various\n Yiorgos Adamopoulos <adamo@softlab.ece.ntua.gr>\n Dale Dougherty <dale@songline.com> # author of "sed & awk"\n Carlos Duarte <cdua@algos.inesc.pt> # author of "do it with sed"\n Eric Pement <epement@jpusa.org> # author of this document\n Ken Pizzini <ken@halcyon.com> # author of GNU sed v3.02\n S.G.Ravenhall <S.G.Ravenhall@open.ac.uk> # great de-html script\n Greg Ubben <gsu@romulus.ncsc.mil> # many contributions & much help\n\n Lowecase path filter\n\n #! /bin/sed -f\n\n # remove all trailing /s\n s/\s/*$//\n\n # add ./ if there are no path, only filename\n /\s//!s/^/.\s//\n\n # save path+filename\n h\n\n # remove path\n s/.*\s///\n\n # do conversion only on filename\n y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/\n\n # swap, now line contains original path+file, hold space contains conv filename\n x\n\n # add converted file name to line, which now contains something like\n # path/file-name\snconverted-file-name\n G\n\n # check if converted file name is equal to original file name, if it is, do\n # not print nothing\n /^.*\s/\s(.*\s)\sn\s1/b\n\n # now, transform path/fromfile\sntofile, into mv path/fromfile path/tofile\n # and print it\n s/^\s(.*\s/\s)\s(.*\s)\sn\s(.*\s)$/mv \s1\s2 \s1\s3/p\n\n
sort the input (by default on whole record)\n\n* can specify fields ([[TAB]] is default separator) - \n** use -t" " for space separator\n* other options, \n** -n numeric sort (not text) \n** -r reverse order (largest last, or is it first? ;-)\n** -u delete identical records (as defined by the sort fields). ''NB'' not equal to what [[uniq]] does, which is always matching on the whole record.\n** +n, -n use the listed fields only for the sort. Default is the whole record\n!!! Tip:\n* If you sort a file but it remains unsorted the problem is usually forgetting the separator is tab by default, not space " ".
Type the text for 'tee'
hello world
just one copy of each record of a sorted list
who is logged on?\n\nsee also [[finger]]