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