17830 lines
691 KiB
HTML
17830 lines
691 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||
<head>
|
||
<script id="versionArea" type="text/javascript">
|
||
//<![CDATA[
|
||
var version = {title: "TiddlyWiki", major: 2, minor: 6, revision: 5, date: new Date("October 6, 2011"), extensions: {}};
|
||
//]]>
|
||
</script>
|
||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||
<meta name="copyright" content="
|
||
TiddlyWiki created by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
|
||
|
||
Copyright (c) Jeremy Ruston 2004-2007
|
||
Copyright (c) UnaMesa Association 2007-2011
|
||
|
||
Redistribution and use in source and binary forms, with or without modification,
|
||
are permitted provided that the following conditions are met:
|
||
|
||
Redistributions of source code must retain the above copyright notice, this
|
||
list of conditions and the following disclaimer.
|
||
|
||
Redistributions in binary form must reproduce the above copyright notice, this
|
||
list of conditions and the following disclaimer in the documentation and/or other
|
||
materials provided with the distribution.
|
||
|
||
Neither the name of the UnaMesa Association nor the names of its contributors may be
|
||
used to endorse or promote products derived from this software without specific
|
||
prior written permission.
|
||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY
|
||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||
DAMAGE.
|
||
" />
|
||
<!--PRE-HEAD-START-->
|
||
<!--{{{-->
|
||
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
|
||
<!--}}}-->
|
||
<!--PRE-HEAD-END-->
|
||
<title>
|
||
|
||
</title>
|
||
<style id="styleArea" type="text/css">
|
||
#saveTest {display:none;}
|
||
#messageArea {display:none;}
|
||
#copyright {display:none;}
|
||
#storeArea {display:none;}
|
||
#storeArea div {padding:0.5em; margin:1em 0em 0em 0em; border-color:#fff #666 #444 #ddd; border-style:solid; border-width:2px; overflow:auto;}
|
||
#shadowArea {display:none;}
|
||
#javascriptWarning {width:100%; text-align:center; font-weight:bold; background-color:#dd1100; color:#fff; padding:1em 0em;}
|
||
</style>
|
||
<!--POST-HEAD-START-->
|
||
<!--POST-HEAD-END-->
|
||
</head>
|
||
<body onload="main();" onunload="if(window.unload) unload();">
|
||
<!--PRE-BODY-START-->
|
||
<!--PRE-BODY-END-->
|
||
<div id="copyright">
|
||
Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
|
||
</div>
|
||
<noscript>
|
||
<div id="javascriptWarning">
|
||
This page requires JavaScript to function properly.<br /><br />If you are using Microsoft Internet Explorer you may need to click on the yellow bar above and select 'Allow Blocked Content'. You must then click 'Yes' on the following security warning.
|
||
</div>
|
||
</noscript>
|
||
<div id="saveTest"></div>
|
||
<div id="backstageCloak"></div>
|
||
<div id="backstageButton"></div>
|
||
<div id="backstageArea"><div id="backstageToolbar"></div></div>
|
||
<div id="backstage">
|
||
<div id="backstagePanel"></div>
|
||
</div>
|
||
<div id="contentWrapper"></div>
|
||
<div id="contentStash"></div>
|
||
<div id="shadowArea">
|
||
<div title="MarkupPreHead">
|
||
<pre><!--{{{-->
|
||
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
|
||
<!--}}}-->
|
||
</pre>
|
||
</div>
|
||
<div title="ColorPalette">
|
||
<pre>Background: #fff
|
||
Foreground: #000
|
||
PrimaryPale: #8cf
|
||
PrimaryLight: #18f
|
||
PrimaryMid: #04b
|
||
PrimaryDark: #014
|
||
SecondaryPale: #ffc
|
||
SecondaryLight: #fe8
|
||
SecondaryMid: #db4
|
||
SecondaryDark: #841
|
||
TertiaryPale: #eee
|
||
TertiaryLight: #ccc
|
||
TertiaryMid: #999
|
||
TertiaryDark: #666
|
||
Error: #f88
|
||
</pre>
|
||
</div>
|
||
<div title="StyleSheetColors">
|
||
<pre>/*{{{*/
|
||
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
|
||
|
||
a {color:[[ColorPalette::PrimaryMid]];}
|
||
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
|
||
a img {border:0;}
|
||
|
||
h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
|
||
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
|
||
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}
|
||
|
||
.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
|
||
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
|
||
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}
|
||
|
||
.header {background:[[ColorPalette::PrimaryMid]];}
|
||
.headerShadow {color:[[ColorPalette::Foreground]];}
|
||
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
|
||
.headerForeground {color:[[ColorPalette::Background]];}
|
||
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}
|
||
|
||
.tabSelected {color:[[ColorPalette::PrimaryDark]];
|
||
background:[[ColorPalette::TertiaryPale]];
|
||
border-left:1px solid [[ColorPalette::TertiaryLight]];
|
||
border-top:1px solid [[ColorPalette::TertiaryLight]];
|
||
border-right:1px solid [[ColorPalette::TertiaryLight]];
|
||
}
|
||
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
|
||
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
|
||
.tabContents .button {border:0;}
|
||
|
||
#sidebar {}
|
||
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
|
||
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
|
||
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
|
||
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
|
||
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}
|
||
|
||
.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
|
||
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
|
||
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
|
||
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
|
||
border:1px solid [[ColorPalette::PrimaryMid]];}
|
||
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
|
||
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
|
||
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
|
||
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
|
||
border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
|
||
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
|
||
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
|
||
border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
|
||
|
||
.wizard .notChanged {background:transparent;}
|
||
.wizard .changedLocally {background:#80ff80;}
|
||
.wizard .changedServer {background:#8080ff;}
|
||
.wizard .changedBoth {background:#ff8080;}
|
||
.wizard .notFound {background:#ffff80;}
|
||
.wizard .putToServer {background:#ff80ff;}
|
||
.wizard .gotFromServer {background:#80ffff;}
|
||
|
||
#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
|
||
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}
|
||
|
||
.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}
|
||
|
||
.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
|
||
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
|
||
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
|
||
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
|
||
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
|
||
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
|
||
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
|
||
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}
|
||
|
||
.tiddler .defaultCommand {font-weight:bold;}
|
||
|
||
.shadow .title {color:[[ColorPalette::TertiaryDark]];}
|
||
|
||
.title {color:[[ColorPalette::SecondaryDark]];}
|
||
.subtitle {color:[[ColorPalette::TertiaryDark]];}
|
||
|
||
.toolbar {color:[[ColorPalette::PrimaryMid]];}
|
||
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
|
||
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
|
||
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}
|
||
|
||
.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
|
||
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
|
||
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
|
||
.tagging .button, .tagged .button {border:none;}
|
||
|
||
.footer {color:[[ColorPalette::TertiaryLight]];}
|
||
.selected .footer {color:[[ColorPalette::TertiaryMid]];}
|
||
|
||
.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
|
||
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
|
||
.lowlight {background:[[ColorPalette::TertiaryLight]];}
|
||
|
||
.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}
|
||
|
||
.imageLink, #displayArea .imageLink {background:transparent;}
|
||
|
||
.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}
|
||
|
||
.viewer .listTitle {list-style-type:none; margin-left:-2em;}
|
||
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
|
||
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}
|
||
|
||
.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
|
||
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
|
||
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}
|
||
|
||
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
|
||
.viewer code {color:[[ColorPalette::SecondaryDark]];}
|
||
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}
|
||
|
||
.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}
|
||
|
||
.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
|
||
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
|
||
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
|
||
.readOnly {background:[[ColorPalette::TertiaryPale]];}
|
||
|
||
#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
|
||
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
|
||
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
|
||
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
|
||
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
|
||
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
|
||
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
|
||
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
|
||
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
|
||
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:alpha(opacity=60);}
|
||
/*}}}*/</pre>
|
||
</div>
|
||
<div title="StyleSheetLayout">
|
||
<pre>/*{{{*/
|
||
* html .tiddler {height:1%;}
|
||
|
||
body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}
|
||
|
||
h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
|
||
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
|
||
h4,h5,h6 {margin-top:1em;}
|
||
h1 {font-size:1.35em;}
|
||
h2 {font-size:1.25em;}
|
||
h3 {font-size:1.1em;}
|
||
h4 {font-size:1em;}
|
||
h5 {font-size:.9em;}
|
||
|
||
hr {height:1px;}
|
||
|
||
a {text-decoration:none;}
|
||
|
||
dt {font-weight:bold;}
|
||
|
||
ol {list-style-type:decimal;}
|
||
ol ol {list-style-type:lower-alpha;}
|
||
ol ol ol {list-style-type:lower-roman;}
|
||
ol ol ol ol {list-style-type:decimal;}
|
||
ol ol ol ol ol {list-style-type:lower-alpha;}
|
||
ol ol ol ol ol ol {list-style-type:lower-roman;}
|
||
ol ol ol ol ol ol ol {list-style-type:decimal;}
|
||
|
||
.txtOptionInput {width:11em;}
|
||
|
||
#contentWrapper .chkOptionInput {border:0;}
|
||
|
||
.externalLink {text-decoration:underline;}
|
||
|
||
.indent {margin-left:3em;}
|
||
.outdent {margin-left:3em; text-indent:-3em;}
|
||
code.escaped {white-space:nowrap;}
|
||
|
||
.tiddlyLinkExisting {font-weight:bold;}
|
||
.tiddlyLinkNonExisting {font-style:italic;}
|
||
|
||
/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
|
||
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
|
||
|
||
#mainMenu .tiddlyLinkExisting,
|
||
#mainMenu .tiddlyLinkNonExisting,
|
||
#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
|
||
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
|
||
|
||
.header {position:relative;}
|
||
.header a:hover {background:transparent;}
|
||
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
|
||
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0; top:0;}
|
||
|
||
.siteTitle {font-size:3em;}
|
||
.siteSubtitle {font-size:1.2em;}
|
||
|
||
#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}
|
||
|
||
#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
|
||
#sidebarOptions {padding-top:0.3em;}
|
||
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
|
||
#sidebarOptions input {margin:0.4em 0.5em;}
|
||
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
|
||
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
|
||
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
|
||
#sidebarTabs .tabContents {width:15em; overflow:hidden;}
|
||
|
||
.wizard {padding:0.1em 1em 0 2em;}
|
||
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
|
||
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
|
||
.wizardStep {padding:1em 1em 1em 1em;}
|
||
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
|
||
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
|
||
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
|
||
.wizard .button {padding:0.1em 0.2em;}
|
||
|
||
#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
|
||
.messageToolbar {display:block; text-align:right; padding:0.2em;}
|
||
#messageArea a {text-decoration:underline;}
|
||
|
||
.tiddlerPopupButton {padding:0.2em;}
|
||
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}
|
||
|
||
.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
|
||
.popup .popupMessage {padding:0.4em;}
|
||
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
|
||
.popup li.disabled {padding:0.4em;}
|
||
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
|
||
.listBreak {font-size:1px; line-height:1px;}
|
||
.listBreak div {margin:2px 0;}
|
||
|
||
.tabset {padding:1em 0 0 0.5em;}
|
||
.tab {margin:0 0 0 0.25em; padding:2px;}
|
||
.tabContents {padding:0.5em;}
|
||
.tabContents ul, .tabContents ol {margin:0; padding:0;}
|
||
.txtMainTab .tabContents li {list-style:none;}
|
||
.tabContents li.listLink { margin-left:.75em;}
|
||
|
||
#contentWrapper {display:block;}
|
||
#splashScreen {display:none;}
|
||
|
||
#displayArea {margin:1em 17em 0 14em;}
|
||
|
||
.toolbar {text-align:right; font-size:.9em;}
|
||
|
||
.tiddler {padding:1em 1em 0;}
|
||
|
||
.missing .viewer,.missing .title {font-style:italic;}
|
||
|
||
.title {font-size:1.6em; font-weight:bold;}
|
||
|
||
.missing .subtitle {display:none;}
|
||
.subtitle {font-size:1.1em;}
|
||
|
||
.tiddler .button {padding:0.2em 0.4em;}
|
||
|
||
.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
|
||
.isTag .tagging {display:block;}
|
||
.tagged {margin:0.5em; float:right;}
|
||
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
|
||
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
|
||
.tagClear {clear:both;}
|
||
|
||
.footer {font-size:.9em;}
|
||
.footer li {display:inline;}
|
||
|
||
.annotation {padding:0.5em; margin:0.5em;}
|
||
|
||
* html .viewer pre {width:99%; padding:0 0 1em 0;}
|
||
.viewer {line-height:1.4em; padding-top:0.5em;}
|
||
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
|
||
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
|
||
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
|
||
|
||
.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
|
||
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
|
||
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
|
||
table.listView th, table.listView td, table.listView tr {padding:0 3px 0 3px;}
|
||
|
||
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
|
||
.viewer code {font-size:1.2em; line-height:1.4em;}
|
||
|
||
.editor {font-size:1.1em;}
|
||
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
|
||
.editorFooter {padding:0.25em 0; font-size:.9em;}
|
||
.editorFooter .button {padding-top:0; padding-bottom:0;}
|
||
|
||
.fieldsetFix {border:0; padding:0; margin:1px 0px;}
|
||
|
||
.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
|
||
.zoomer div {padding:1em;}
|
||
|
||
* html #backstage {width:99%;}
|
||
* html #backstageArea {width:99%;}
|
||
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
|
||
#backstageToolbar {position:relative;}
|
||
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
|
||
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
|
||
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
|
||
#backstage {position:relative; width:100%; z-index:50;}
|
||
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
|
||
.backstagePanelFooter {padding-top:0.2em; float:right;}
|
||
.backstagePanelFooter a {padding:0.2em 0.4em;}
|
||
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
|
||
|
||
.whenBackstage {display:none;}
|
||
.backstageVisible .whenBackstage {display:block;}
|
||
/*}}}*/
|
||
</pre>
|
||
</div>
|
||
<div title="StyleSheetLocale">
|
||
<pre>/***
|
||
StyleSheet for use when a translation requires any css style changes.
|
||
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
|
||
***/
|
||
/*{{{*/
|
||
body {font-size:0.8em;}
|
||
#sidebarOptions {font-size:1.05em;}
|
||
#sidebarOptions a {font-style:normal;}
|
||
#sidebarOptions .sliderPanel {font-size:0.95em;}
|
||
.subtitle {font-size:0.8em;}
|
||
.viewer table.listView {font-size:0.95em;}
|
||
/*}}}*/</pre>
|
||
</div>
|
||
<div title="StyleSheetPrint">
|
||
<pre>/*{{{*/
|
||
@media print {
|
||
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
|
||
#displayArea {margin: 1em 1em 0em;}
|
||
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
|
||
}
|
||
/*}}}*/</pre>
|
||
</div>
|
||
<div title="PageTemplate">
|
||
<pre><!--{{{-->
|
||
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
|
||
<div class='headerShadow'>
|
||
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
|
||
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
|
||
</div>
|
||
<div class='headerForeground'>
|
||
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
|
||
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
|
||
</div>
|
||
</div>
|
||
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
|
||
<div id='sidebar'>
|
||
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
|
||
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
|
||
</div>
|
||
<div id='displayArea'>
|
||
<div id='messageArea'></div>
|
||
<div id='tiddlerDisplay'></div>
|
||
</div>
|
||
<!--}}}--></pre>
|
||
</div>
|
||
<div title="ViewTemplate">
|
||
<pre><!--{{{-->
|
||
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
|
||
<div class='title' macro='view title'></div>
|
||
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
|
||
<div class='tagging' macro='tagging'></div>
|
||
<div class='tagged' macro='tags'></div>
|
||
<div class='viewer' macro='view text wikified'></div>
|
||
<div class='tagClear'></div>
|
||
<!--}}}--></pre>
|
||
</div>
|
||
<div title="EditTemplate">
|
||
<pre><!--{{{-->
|
||
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
|
||
<div class='title' macro='view title'></div>
|
||
<div class='editor' macro='edit title'></div>
|
||
<div macro='annotations'></div>
|
||
<div class='editor' macro='edit text'></div>
|
||
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
|
||
<!--}}}--></pre>
|
||
</div>
|
||
<div title="GettingStarted">
|
||
<pre>To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
|
||
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
|
||
* [[MainMenu]]: The menu (usually on the left)
|
||
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
|
||
You'll also need to enter your username for signing your edits: <<option txtUserName>></pre>
|
||
</div>
|
||
<div title="OptionsPanel">
|
||
<pre>These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser
|
||
|
||
Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])
|
||
|
||
<<option txtUserName>>
|
||
<<option chkSaveBackups>> [[SaveBackups]]
|
||
<<option chkAutoSave>> [[AutoSave]]
|
||
<<option chkRegExpSearch>> [[RegExpSearch]]
|
||
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
|
||
<<option chkAnimate>> [[EnableAnimations]]
|
||
|
||
----
|
||
Also see [[AdvancedOptions]]</pre>
|
||
</div>
|
||
<div title="ImportTiddlers">
|
||
<pre><<importTiddlers>></pre>
|
||
</div>
|
||
</div>
|
||
<!--POST-SHADOWAREA-->
|
||
<div id="storeArea">
|
||
<div title="DefaultTiddlers" creator="jclain" modifier="jclain" created="201203090108" modified="201605130537" tags="" changecount="1">
|
||
<pre>[[Main]]</pre>
|
||
</div>
|
||
<div title="EnsureVM" creator="jclain" modifier="jclain" created="201203151819" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
EnsureVM: s'assurer que les services sont lancés pour un type de virtualisation
|
||
|
||
USAGE
|
||
EnsureVM type
|
||
|
||
Les types supportés sont virtualbox et kvm (par défaut)
|
||
}}}</pre>
|
||
</div>
|
||
<div title="Main" creator="jclain" modifier="jclain" created="201203090108" modified="201605130537" tags="" changecount="1">
|
||
<pre>!Présentation
|
||
nutools est un ensemble d'utilitaires pour faciliter l'utililisation des Unixes, en particulier Linux, mais aussi MacOS X et Cygwin.
|
||
C'est aussi une librairie de scripts shell réutilisables ([[ulib]]) et une librairie de modules python réutilisables (pyulib)
|
||
|
||
!Prérequis
|
||
Python >= 2.3 et GNU Awk sont requis pour que toutes les fonctionnalités soient supportées.
|
||
* Sous Linux, lors de l'installation du package, les meilleurs efforts sont fait pour que ces packages soient installés.
|
||
* Sous MacOSX, il faut installer manuellement Fink, DarwinPorts ou Homebrew
|
||
|
||
! Outils
|
||
Chaque outil contient une aide intégrée. Il suffit de lancer l'outil avec l'argument {{{--help}}} pour avoir une aide détaillée.
|
||
* Déploiement d'un répertoire ou d'une archive
|
||
** [[uinst]]: Déploiement local
|
||
** [[mkusfx]]: Faire une archive auto-installable avec uinst
|
||
** [[ruinst]]: Déploiement distant avec uinst
|
||
** [[runs]]: Lancer un script avec le protocole RUNS
|
||
** [[rruns]]: Déploiement distant avec runs
|
||
* Librairie réutilisable de scripts shell
|
||
** [[uinc]]: Dépliage des inclusions dans un fichier
|
||
** [[ulibsync]]: Faire une copie locale pour un projet de ulib et/ou pyulib
|
||
* Autres outils
|
||
** [[udir]]: Gestion des paramètres d'un répertoire. Ces paramètres sont entre autres utilisés par uinst et uinc.</pre>
|
||
</div>
|
||
<div title="MainMenu" creator="jclain" modifier="jclain" created="201203090108" modified="201605130537" tags="" changecount="1">
|
||
<pre>[[GettingStarted]]</pre>
|
||
</div>
|
||
<div title="SKvm" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
SKvm: lancer une machine virtuelle kvm
|
||
|
||
USAGE
|
||
SKvm [options] vmName
|
||
SKvm {-l|-A|-g}
|
||
|
||
OPTIONS
|
||
-n, --check
|
||
Ne rien faire excepté s'assurer que les modules kvm sont chargés
|
||
-u, --user
|
||
Lancer l'opération avec les droits de l'utilisateur courant. Par défaut,
|
||
ce script tente d'acquérir les droits de root.
|
||
-l, --list
|
||
Lister les machines virtuelles
|
||
-s, --start
|
||
Démarrer la machine virtuelle (par défaut)
|
||
Si le nom de la machine virtuelle n'est pas spécifiée, un menu est
|
||
affiché
|
||
-k, --stop
|
||
Arrêter la machine virtuelle
|
||
-H, --destroy
|
||
Arrêter sauvagement la machine virtuelle
|
||
-r, --restart
|
||
Redémarrer la machine virtuelle
|
||
-S, --managed-save
|
||
Enregistrer l'état de la machine virtuelle
|
||
-A, --stop-all
|
||
Arrêter toutes les machines virtuelles qui tournent actuellement
|
||
-g, --gui
|
||
Afficher le gestionnaire de machines virtuelle
|
||
}}}</pre>
|
||
</div>
|
||
<div title="SVirtualBox" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
SVirtualBox: lancer une machine virtuelle VirtualBox
|
||
|
||
USAGE
|
||
SVirtualBox [options] vmName
|
||
|
||
OPTIONS
|
||
-n Ne rien faire excepté s'assurer que les modules VirtualBox sont chargés
|
||
-l Lister les machines virtuelles
|
||
-s Démarrer la machine virtuelle (par défaut)
|
||
Si le nom de la machine virtuelle n'est pas spécifiée, un menu est
|
||
affiché
|
||
-b Démarrer la VM sans interface graphique. Cette option n'est valide
|
||
qu'avec -s
|
||
-k Arrêter la machine virtuelle (par ACPI)
|
||
-p Mettre en veille la machine virtuelle (par ACPI)
|
||
-H Arrêter sauvagement la machine virtuelle
|
||
-R Redémarrer sauvagement la machine virtuelle
|
||
-S Enregistrer l'état de la machine virtuelle
|
||
-g Afficher le gestionnaire de machines virtuelle
|
||
}}}</pre>
|
||
</div>
|
||
<div title="SiteSubtitle" creator="jclain" modifier="jclain" created="201203090108" modified="201605130537" tags="" changecount="1">
|
||
<pre>Outils divers pour linux/macosx, et librairies pour bash</pre>
|
||
</div>
|
||
<div title="SiteTitle" creator="jclain" modifier="jclain" created="201203090108" modified="201605130537" tags="" changecount="1">
|
||
<pre>nutools</pre>
|
||
</div>
|
||
<div title="SiteUrl" creator="jclain" modifier="jclain" created="201203090108" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="_root" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
_root: devenir l'utilisateur root, avec 'sudo' si possible, ou 'su' si
|
||
'sudo' n'est pas installé
|
||
}}}</pre>
|
||
</div>
|
||
<div title="apacheconfig" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
apacheconfig: Gérer la configuration d'un serveur web apache
|
||
|
||
USAGE
|
||
apacheconfig -c
|
||
apacheconfig -t -- args...
|
||
|
||
OPTIONS
|
||
-c, --create
|
||
Créer un nouveau répertoire de configuration pour un hôte
|
||
-d, --destdir DESTDIR[=apacheconfig]
|
||
Nom du répertoire local de configuration.
|
||
|
||
-t, --template [OPT]
|
||
Gérer les fichiers du répertoire local avec templatectl. La valeur de
|
||
cette option est utilisée comme argument court pour l'invocation de
|
||
templatectl, e.g
|
||
apacheconfig -tm args
|
||
est équivalent à
|
||
templatectl -m args
|
||
Les arguments qui restent sont passés tels quels à templatectl
|
||
Les options courantes de templatectl -l, -v, -m, -L sont disponibles
|
||
directement
|
||
--help-template
|
||
Afficher l'aide concernent la gestion des templates.
|
||
Equivalent à -t -- --help
|
||
-h, --host HOST
|
||
Spécifier l'hôte. Equivalent à -v host=HOST
|
||
--sysname SYSNAME
|
||
--sysdist SYSDIST
|
||
-s, --sysver SYSVER
|
||
Spécifier la distribution pour laquelle synchroniser le template. Par
|
||
défaut, choisir les valeurs correspondantes au système courant.
|
||
Les options -7 et -8 sont des aliases respectivement pour -s wheezy et
|
||
-s jessie, parce que les fichiers par défaut ont changé à partir de
|
||
debian jessie.
|
||
|
||
-u, --update, --deploy
|
||
Mettre à jour la configuration système à partir du répertoire local.
|
||
Lors du déploiement de la configuration, les valeurs des variables
|
||
dynamiques sont remplacées dans les fichiers destination.
|
||
Les arguments qui restent sont passés tels quels à apache_autoconf
|
||
-r, --certsdir CERTSDIR
|
||
Spécifier le cas échéant le répertoire contenant les certificats à
|
||
déployer. Cet argument est requis si le répertoire certsconf/ existe.
|
||
|
||
--localhosts
|
||
Créer dans le fichier /etc/hosts tous les noms d'hôte ayant un suffixe
|
||
.local mentionnés dans les fichiers de site. Cette option est utile pour
|
||
le développement et les tests.
|
||
-C, --one-conf CONF
|
||
Ne déployer que le fichier de configuration spécifié. Cette option est
|
||
utilisée avec --deploy et est utile pour le développement et les tests.
|
||
-M, --one-module MODULE
|
||
Ne déployer que le fichier de module spécifié. Cette option est utilisée
|
||
avec --deploy et est utile pour le développement et les tests.
|
||
-S, --one-site SITE
|
||
Ne déployer que le fichier de site spécifié. Cette option est utilisée
|
||
avec --deploy ou --localhosts et est utile pour le développement et les
|
||
tests.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="authftp" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
authftp: Se connecter sur un site FTP authentifié
|
||
Ce script nécessite ncftp. Il est conçu pour faciliter l'accès à des sites FTP
|
||
s'il est requis d'y accéder par un proxy FTP pour les connexion authentifiées.
|
||
|
||
USAGE
|
||
authftp [options] host login password [path]
|
||
|
||
OPTIONS
|
||
-p, --proxy
|
||
-n, --noproxy
|
||
Forcer l'utilisation, resp. ne pas utiliser, le proxy FTP (i.e. faire la
|
||
connexion directement)
|
||
-l, --lftp
|
||
Se connecter avec lftp au lieu de ncftp. Le fonctionnement n'est pas
|
||
garanti si l'on utilise un proxy FTP.
|
||
-o OPTION
|
||
Ajouter une option à la commande lancée. Si l'option prend un argument,
|
||
il faut doubler l'option -o, e.g.
|
||
authftp -l -o -e -o 'mirror remote local' host login pass
|
||
Dans cet exemple, l'option -e de lftp est utilisée pour faire un miroir
|
||
local du répertoire remote.
|
||
--tls
|
||
Indiquer que la connexion se fera en TLS. Implique --lftp puisque ncftp
|
||
ne le supporte pas.
|
||
|
||
note: A cause d'une limitation de lftp, ce n'est pas possible de se connecter
|
||
automatiquement avec lftp si le mot de passe contient une virgule. A cause de la
|
||
façon dont le proxy ftp est configuré, il n'est pas possible de se connecter
|
||
avec un mot de passe qui contient le caractère @
|
||
}}}</pre>
|
||
</div>
|
||
<div title="caturl" creator="jclain" modifier="jclain" created="201605130536" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
caturl: Afficher une url
|
||
|
||
USAGE
|
||
caturl <file.url|file.desktop|URL>
|
||
|
||
OPTIONS
|
||
-c, --check
|
||
Vérifier que le fichier est valide
|
||
-g, --get
|
||
Attaquer l'url spécifiée avec curl
|
||
}}}</pre>
|
||
</div>
|
||
<div title="compileAndGo" creator="jclain" modifier="jclain" created="201203151819" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
compileAndGo: see http://Yost.com/computers/compileAndGo
|
||
}}}</pre>
|
||
</div>
|
||
<div title="cssh" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
cssh: Faire une connexion ssh en lançant automatiquement un screen sur l'hôte distant
|
||
|
||
USAGE
|
||
cssh [user@]host [options]
|
||
|
||
En principe, hormis l'argument user@host, il ne faudrait spécifier que des
|
||
options. Dans le cas où d'autres arguments seraient spécifiés, les meilleurs
|
||
efforts sont faits pour lancer ces commandes avant screen.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="doinplace" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
doinplace: filtrer en place un fichier à travers une suite de commandes
|
||
|
||
USAGE
|
||
doinplace FILE COMMAND [ARGS...]
|
||
|
||
Si on utilise une commande avec des options, penser à utliser '--' pour séparer
|
||
les options de ce script des options de la commande
|
||
|
||
En plus des commandes systèmes, il est possible d'utiliser toute fonction de
|
||
nutools qui effectue des traitement sur un flux comme stripnl, filter_empty,
|
||
merge_contlines, filter_comment, filter_conf, etc. Les fonctions nl2lf, nl2crlf,
|
||
nl2cr, latin1compat et noaccents sont aussi disponibles par convenance.
|
||
|
||
OPTIONS
|
||
-p, --evalp
|
||
Evaluer la commande avec evalp(), ce qui permet de chainer plusieurs
|
||
commandes en les séparant par //. Cette option est automatiquement
|
||
activée si ce script est lancé avec le nom doinplacex
|
||
-g, --ignore-error, --replace-always
|
||
Normalement, le fichier n'est pas remplacé si la commande retourne une
|
||
erreur. Avec cette option, le fichier est remplacé quel que soit le code
|
||
de retour de la commande. A utiliser par exemple avec des commandes
|
||
comme grep qui peuvent retourner FAUX s'ils ne trouvent pas le motif.
|
||
Cette option est automatiquement activée si ce script est lancé avec le
|
||
nom doinplacef
|
||
}}}</pre>
|
||
</div>
|
||
<div title="dumpclients" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
dumpclients: afficher les connexions TCP entrantes sur un port
|
||
|
||
USAGE
|
||
dumpclients [options] port
|
||
|
||
OPTIONS
|
||
-4, --only-tcp
|
||
-6, --only-tcp6
|
||
Se limiter au protocole spécifié. Par défaut, afficher toutes les
|
||
connexions, qu'elles soient en IPv4 ou en IPv6
|
||
-a, --all
|
||
Afficher tous les sockets, y compris les ports d'écoute. Par défaut,
|
||
seules les sockets ouvertes sont affichées.
|
||
-n, --numeric
|
||
Afficher uniquement les adresses IP au lieu du nom d'hôte.
|
||
-z, --allow-no-port
|
||
Ne pas exiger que le port soit spécifié
|
||
--show none,ip,port,state
|
||
Spécifier d'afficher comme informations supplémentaire: rien, l'adresse
|
||
ip, le port et/ou l'état. Par défaut, afficher le port et l'état.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="em" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
Usage: /usr/bin/emacs [OPTION-OR-FILENAME]...
|
||
|
||
Run Emacs, the extensible, customizable, self-documenting real-time
|
||
display editor. The recommended way to start Emacs for normal editing
|
||
is with no options at all.
|
||
|
||
Run M-x info RET m emacs RET m emacs invocation RET inside Emacs to
|
||
read the main documentation for these command-line arguments.
|
||
|
||
Initialization options:
|
||
|
||
--batch do not do interactive display; implies -q
|
||
--daemon start a server in the background
|
||
--debug-init enable Emacs Lisp debugger for init file
|
||
--display, -d DISPLAY use X server DISPLAY
|
||
--no-desktop do not load a saved desktop
|
||
--no-init-file, -q load neither ~/.emacs nor default.el
|
||
--no-shared-memory, -nl do not use shared memory
|
||
--no-site-file do not load site-start.el
|
||
--no-splash do not display a splash screen on startup
|
||
--no-window-system, -nw do not communicate with X, ignoring $DISPLAY
|
||
--quick, -Q equivalent to -q --no-site-file --no-splash
|
||
--script FILE run FILE as an Emacs Lisp script
|
||
--terminal, -t DEVICE use DEVICE for terminal I/O
|
||
--user, -u USER load ~USER/.emacs instead of your own
|
||
|
||
Action options:
|
||
|
||
FILE visit FILE using find-file
|
||
+LINE go to line LINE in next FILE
|
||
+LINE:COLUMN go to line LINE, column COLUMN, in next FILE
|
||
--directory, -L DIR add DIR to variable load-path
|
||
--eval EXPR evaluate Emacs Lisp expression EXPR
|
||
--execute EXPR evaluate Emacs Lisp expression EXPR
|
||
--file FILE visit FILE using find-file
|
||
--find-file FILE visit FILE using find-file
|
||
--funcall, -f FUNC call Emacs Lisp function FUNC with no arguments
|
||
--insert FILE insert contents of FILE into current buffer
|
||
--kill exit without asking for confirmation
|
||
--load, -l FILE load Emacs Lisp FILE using the load function
|
||
--visit FILE visit FILE using find-file
|
||
|
||
Display options:
|
||
|
||
--background-color, -bg COLOR window background color
|
||
--basic-display, -D disable many display features;
|
||
used for debugging Emacs
|
||
--border-color, -bd COLOR main border color
|
||
--border-width, -bw WIDTH width of main border
|
||
--color, --color=MODE override color mode for character terminals;
|
||
MODE defaults to `auto', and can also
|
||
be `never', `auto', `always',
|
||
or a mode name like `ansi8'
|
||
--cursor-color, -cr COLOR color of the Emacs cursor indicating point
|
||
--font, -fn FONT default font; must be fixed-width
|
||
--foreground-color, -fg COLOR window foreground color
|
||
--fullheight, -fh make the first frame high as the screen
|
||
--fullscreen, -fs make first frame fullscreen
|
||
--fullwidth, -fw make the first frame wide as the screen
|
||
--maximized, -mm make the first frame maximized
|
||
--geometry, -g GEOMETRY window geometry
|
||
--no-bitmap-icon, -nbi do not use picture of gnu for Emacs icon
|
||
--iconic start Emacs in iconified state
|
||
--internal-border, -ib WIDTH width between text and main border
|
||
--line-spacing, -lsp PIXELS additional space to put between lines
|
||
--mouse-color, -ms COLOR mouse cursor color in Emacs window
|
||
--name NAME title for initial Emacs frame
|
||
--no-blinking-cursor, -nbc disable blinking cursor
|
||
--reverse-video, -r, -rv switch foreground and background
|
||
--title, -T TITLE title for initial Emacs frame
|
||
--vertical-scroll-bars, -vb enable vertical scroll bars
|
||
--xrm XRESOURCES set additional X resources
|
||
--parent-id XID set parent window
|
||
--help display this help and exit
|
||
--version output version information and exit
|
||
|
||
You can generally also specify long option names with a single -; for
|
||
example, -batch as well as --batch. You can use any unambiguous
|
||
abbreviation for a --option.
|
||
|
||
Various environment variables and window system resources also affect
|
||
Emacs' operation. See the main documentation.
|
||
|
||
Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs
|
||
section of the Emacs manual or the file BUGS.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="fconv" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
fconv: convertir un fichier ou les fichiers d'un répertoire
|
||
|
||
USAGE
|
||
fconv -f FILE [cmds...]
|
||
fconv FILE [cmds...]
|
||
|
||
Une ou plusieurs commandes peuvent être spécifiées, séparées par //
|
||
La commande par défaut est 'lf'
|
||
Si des commandes utilisant des options sont utilisées, penser à séparer les
|
||
options de fconv avec --
|
||
|
||
OPTIONS
|
||
-N, --detect-always
|
||
Pour la commande conv, ne pas optimiser le calcul de l'encoding. Cette
|
||
option n'est valide que si src_enc n'est pas spécifié. On assume que
|
||
tous les fichiers n'ont pas le même encoding: l'encoding src_enc est
|
||
donc recalculé à chaque fois.
|
||
-r, --reverse
|
||
Pour la commande conv, inverser src_enc et dest_enc, qui doivent être
|
||
tous les deux spécifiés.
|
||
-f, --file FILE
|
||
Spécifier le fichier ou le répertoire concerné par la conversion. Les
|
||
aliases -d et --dir sont aussi reconnus.
|
||
Si cette option n'est pas spécifiée, le premier argument est considéré
|
||
comme le nom du fichier ou du répertoire à convertir. Par défaut,
|
||
convertir l'entrée standard.
|
||
Si un répertoire est spécifié, tous les fichiers de ce répertoire et de
|
||
ses sous-répertoires sont recherchés de façon récursive, sans limite de
|
||
profondeur. Ensuite, chacun de ces fichiers est converti.
|
||
--show-cmd
|
||
Afficher la commande qui serait exécutée
|
||
|
||
COMMANDES
|
||
c, conv dest_enc [src_enc]
|
||
Convertir le fichier dans un autre encoding.
|
||
dest_enc est l'encoding destination. Il doit être spécifié.
|
||
src_enc est l'encoding source. S'il n'est pas spécifié ou vaut 'detect',
|
||
il est autodétecté.
|
||
U, utf8 [src_enc]
|
||
Equivalent à conv utf8 src_enc
|
||
L, latin1 [src_enc]
|
||
Equivalent à conv latin1 src_enc
|
||
lf
|
||
crlf
|
||
cr
|
||
Convertir respectivement les caractères de fin de ligne en LF, CR/LF ou CR
|
||
lc, latin1compat
|
||
Transformer certains caratères UTF-8 en équivalents qui existent en Latin1
|
||
na, noaccents
|
||
Transformer les caractères accentués en caractères non accentués
|
||
sort [-u]
|
||
Trier le fichier avec la commande sort. Attention! Il ne faut utiliser
|
||
que les options de sort qui agissent sur un flux e.g. -u pour trier les
|
||
lignes de façon unique.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="fnconv" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
fnconv: renommer un fichier ou les fichiers d'un répertoire
|
||
|
||
USAGE
|
||
fnconv -f FILE [cmds...]
|
||
fnconv FILE [cmds...]
|
||
|
||
Une ou plusieurs commandes peuvent être spécifiées, séparées //
|
||
La commande par défaut est 'fixcase'
|
||
|
||
OPTIONS
|
||
-N, --detect-always
|
||
Pour la commande conv, ne pas optimiser le calcul de l'encoding. Cette
|
||
option n'est valide que si src_enc n'est pas spécifié. On assume que
|
||
tous les fichiers n'ont pas le même encoding: l'encoding src_enc est
|
||
donc recalculé à chaque fois.
|
||
-r, --reverse
|
||
Pour la commande conv, inverser src_enc et dest_enc, qui doivent être
|
||
tous les deux spécifiés.
|
||
-f, --file FILE
|
||
Spécifier le fichier ou le répertoire concerné par le renommage. Les
|
||
aliases -d et --dir sont aussi reconnus.
|
||
Si cette option n'est pas spécifiée, le premier argument est considéré
|
||
comme le nom du fichier ou du répertoire à renommer.
|
||
Si un répertoire est spécifié, le traitement est appliqué à tous les
|
||
fichiers et répertoires de façon récursive, sans limite de profondeur.
|
||
--show-cmd
|
||
Afficher la commande qui serait exécutée
|
||
|
||
COMMANDES
|
||
C, conv dest_enc [src_enc]
|
||
Convertir le nom du fichier dans un autre encoding.
|
||
dest_enc est l'encoding destination. Il doit être spécifié.
|
||
src_enc est l'encoding source. S'il n'est pas spécifié ou vaut 'detect',
|
||
il est autodétecté.
|
||
U, utf8 [src_enc]
|
||
Equivalent à conv utf8 src_enc
|
||
L, latin1 [src_enc]
|
||
Equivalent à conv latin1 src_enc
|
||
lc, latin1compat
|
||
Transformer certains caratères UTF-8 en équivalents qui existent en Latin1
|
||
na, noaccents
|
||
Transformer les caractères accentués en caractères non accentués
|
||
l, lowercase
|
||
Transfomer le nom en minuscule
|
||
u, uppercase
|
||
Transformer le nom en majuscule
|
||
f, fixcase
|
||
Transformer le nom en minuscule s'il est entièrement en majuscule
|
||
}}}</pre>
|
||
</div>
|
||
<div title="geturl" creator="jclain" modifier="jclain" created="201203151819" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
geturl: Télécharger un fichier avec wget ou curl
|
||
|
||
USAGE
|
||
geturl <file.url|file.desktop|URL> [wget options]
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mkRewriteRules" creator="jclain" modifier="jclain" created="201203151819" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mkRewriteRules: Créer un fichier de redirections pour Apache à partir d'un certain
|
||
nombre de règles
|
||
|
||
USAGE
|
||
mkRewriteRules -f rewrite.rules [-o RewriteRules.conf] [-w RewriteRules.html] host
|
||
|
||
OPTIONS
|
||
-p Générer les directives <Proxy...> et tenir compte de proxy_acls
|
||
Par défaut, le champ proxy_acls est ignoré
|
||
|
||
FORMAT des règles de mapping
|
||
============================
|
||
|
||
Les commentaires commencent par le signe "#"
|
||
Les règles sont de la forme:
|
||
src:dest:host:suffix:OPTS:prot:proxy_acls
|
||
^prefix
|
||
=literal
|
||
|
||
prot vaut par défaut http. Il peut valoir aussi https
|
||
|
||
Si dest ou suffix se terminent par $, on est en mode NO_SLASH
|
||
En mode NO_SLASH, si src se termine par $, on est en mode NO_TRAIL
|
||
|
||
* Si dest est de la forme Application.woa
|
||
En mode NO_SLASH, on génère
|
||
RewriteRule ^/src(.*) [prot://host]/cgi-bin/WebObjects/dest[/suffix]$1 [L,OPTS]
|
||
En mode NO_SLASH+NO_TRAIL, on génère
|
||
RewriteRule ^/src [prot://host]/cgi-bin/WebObjects/dest[/suffix] [L,OPTS]
|
||
En mode normal, on génère
|
||
RewriteRule ^/src$ /src/
|
||
RewriteRule ^/src/(.*) [prot://host]/cgi-bin/WebObjects/dest[/suffix]/$1 [L,OPTS]
|
||
|
||
* Si dest n'est pas de la forme Application.woa
|
||
En mode NO_SLASH, on génère
|
||
RewriteRule ^/src(.*) [prot://host]/dest[/suffix]$1 [L,OPTS]
|
||
En mode NO_SLASH+NO_TRAIL, on génère
|
||
RewriteRule ^/src [prot://host]/dest[/suffix] [L,OPTS]
|
||
En mode normal, on génère
|
||
RewriteRule ^/src$ /src/
|
||
RewriteRule ^/src/(.*) /dest[/suffix]/$1 [L,OPTS]
|
||
|
||
Si une règle est précédée d'une ou plusieurs lignes de la forme "^prefix",
|
||
ces lignes sont copiées avant chacune des commandes RewriteRule générées
|
||
pour une règle. Ceci permet d'ajouter des conditions avec RewriteCond pour
|
||
une règle. e.g.
|
||
^RewriteCond %{REMOTE_ADDR} 10\..*
|
||
src:dest.woa
|
||
qui génère:
|
||
RewriteCond %{REMOTE_ADDR} 10\..*
|
||
RewriteRule ^/src$ /src/
|
||
RewriteCond %{REMOTE_ADDR} 10\..*
|
||
RewriteRule ^/src/(.*) /cgi-bin/WebObjects/dest.woa/$1 [L]
|
||
|
||
Une ligne de la forme "=literal" est recopiée sans modifications (sans le "=")
|
||
dans le fichier de sortie.
|
||
|
||
proxy_acls est utilisé si l'option -p est spécifiée et OPTS contient P (comme
|
||
proxy), ou si le mode de réécriture requière l'utilisation d'un proxy.
|
||
|
||
* Avec la valeur "None", aucune directive <Proxy> n'est générée
|
||
* Si aucune valeur n'est spécifiée, la directive suivante est générée:
|
||
<Proxy $URL>
|
||
AddDefaultCharset off
|
||
Order Deny,Allow
|
||
Allow from all
|
||
</Proxy>
|
||
* Si une valeur est spécifiée, la directive suivante est générée:
|
||
<Proxy $URL>
|
||
AddDefaultCharset off
|
||
Order Allow,Deny
|
||
Allow from $proxy_acls
|
||
</Proxy>
|
||
|
||
Dans les exemples donnés ci-dessus, $URL est l'url générée par la réécriture,
|
||
et $proxy_acls la valeur du champ proxy_acls spécifiée ci-dessus.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mkiso" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mkiso: créer une image iso d'un répertoire
|
||
|
||
USAGE
|
||
mkiso [options] srcdir [dest.iso]
|
||
|
||
OPTIONS
|
||
-M, --hfs
|
||
créer une image hybride ISO/HFS
|
||
-V, --volume
|
||
Nom du volume. Par défaut, prendre le nom de base du répertoire
|
||
d'origine. La taille est de 32 caractères max.
|
||
-A, --application
|
||
Description de l'application qui est sur l'image créée. Par défaut,
|
||
prendre le nom de base du répertoire d'origine. La taille est de 128
|
||
caractères max.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mkurl" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mkurl: Enregistrer une url dans un fichier raccourci
|
||
|
||
USAGE
|
||
mkurl <url> [output]
|
||
|
||
OPTIONS
|
||
Par défaut, l'url est enregistrée dans un fichier homepage.url
|
||
Mais il est possible de spécifier un fichier avec l'extension .url pour un
|
||
raccourci utilisable aussi sous Windows, ou avec l'extension .desktop pour
|
||
compatibilité avec le standard XDG
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mkusfx" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mkusfx: Créer une archive auto-extractible qui installe son contenu avec uinst
|
||
|
||
USAGE
|
||
mkusfx [options] [--bare] src cmd...
|
||
mkusfx [options] [--uinst] src
|
||
|
||
OPTIONS
|
||
--bare
|
||
Installer le contenu de l'archive en lançant la commande 'cmd...' avec
|
||
le répertoire courant étant le contenu de l'archive. Typiquement, ce
|
||
sera une commande de forme './script', où script est un fichier situé à
|
||
la racine de l'archive
|
||
Dans ce mode d'installation, l'option --self-contained est ignorée.
|
||
--uinst
|
||
Installer le contenu de l'archive avec uinst (par défaut)
|
||
-o dest
|
||
Spécifier le fichier de sortie. Par défaut, il s'agit de
|
||
${src}-installer.run
|
||
--tmp-archive
|
||
Spécifier qu'il s'agit d'une archive temporaire. Cette archive
|
||
s'auto-détruit après utilisation.
|
||
--self-contained
|
||
Spécifier que l'archive doit pouvoir s'installer même sur un système sur
|
||
lequel nutools n'est pas installé. Cette archive contiendra une copie
|
||
locale de ulib et uinst.sh
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mocifs" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mocifs: Monter un partage Windows/Samba/CIFS
|
||
|
||
USAGE
|
||
mocifs [user@]host[/path] [mountpoint]
|
||
|
||
Par défaut, le répertoire distant est montée sur un répertoire avec le même nom
|
||
de base que l'hôte. Si le répertoire distant est déjà monté, il est démonté.
|
||
Les options -M et -U permettent de modifier le comportement par défaut.
|
||
|
||
OPTIONS
|
||
-M
|
||
Forcer le montage
|
||
-U
|
||
Forcer le démontage
|
||
-o OPTIONS
|
||
Ajouter les options spécifiées à la commande de montage mount.cifs
|
||
-u USERNAME
|
||
-p PASSWORD
|
||
-c USERNAME:PASSWORD
|
||
Spécifier les credentials à utiliser pour la connexion
|
||
}}}</pre>
|
||
</div>
|
||
<div title="modav" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
modav: Monter un répertoire sur un hôte distant avec davfs
|
||
|
||
USAGE
|
||
modav http[s]://host[/path] [mountpoint]
|
||
|
||
Par défaut, le répertoire distant est montée sur un répertoire avec le même nom
|
||
de base que l'hôte. Si le répertoire distant est déjà monté, il est démonté.
|
||
Les options -M et -U permettent de modifier le comportement par défaut.
|
||
|
||
OPTIONS
|
||
-M
|
||
Forcer le montage
|
||
-U
|
||
Forcer le démontage
|
||
-o OPTIONS
|
||
Ajouter les options spécifiées à la commande de montage
|
||
-u USERNAME
|
||
-p PASSWORD
|
||
-c USERNAME:PASSWORD
|
||
Si les credentials à utiliser ne sont pas configuré dans le fichier
|
||
/etc/davfs2/secrets, cette option permet de les spécifier. Si cette
|
||
option est utilisée, il est possible de rajouter
|
||
ask_auth 0
|
||
dans le fichier /etc/davfs2/davfs2.conf pour éviter le conflit qui se
|
||
produit quand des informations sont demandées interactivement. C'est le
|
||
cas par exemple si une connexion en https est faite et que la chaine de
|
||
certification n'est pas configurée. Pour mémoire, cela se fait avec
|
||
servercert myCAs.pem
|
||
dans le fichier /etc/davfs2/davfs2.conf
|
||
Bien entendu, il est préférable de configurer les credentials dans le
|
||
fichier /etc/davfs2/secrets avec la syntaxe
|
||
url username password
|
||
ou
|
||
mountpoint username password
|
||
}}}</pre>
|
||
</div>
|
||
<div title="moiso" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
moiso: Monter une image ISO
|
||
|
||
USAGE
|
||
moiso image.iso [mountpoint]
|
||
|
||
Par défaut, l'image iso est montée sur un répertoire avec le même nom de base.
|
||
Si l'image est déjà montée, elle est démontée. Les options -m et -u permettent
|
||
de modifier le comportement par défaut.
|
||
|
||
OPTIONS
|
||
-m
|
||
Forcer le montage
|
||
-u
|
||
Forcer le démontage
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mossh" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mossh: Monter un répertoire sur un hôte distant avec sshfs
|
||
|
||
USAGE
|
||
mossh [user@]host[:/path] [mountpoint]
|
||
|
||
Par défaut, le répertoire distant est montée sur un répertoire avec le même nom
|
||
de base que l'hôte. Si le répertoire distant est déjà monté, il est démonté.
|
||
Les options -M et -U permettent de modifier le comportement par défaut.
|
||
|
||
OPTIONS
|
||
-M
|
||
Forcer le montage
|
||
-U
|
||
Forcer le démontage
|
||
-o OPTIONS
|
||
Ajouter les options spécifiées à la commande de montage
|
||
-s
|
||
Equivalent à -o allow_other ou -o allow_root selon que l'on est root ou
|
||
non
|
||
-u USER
|
||
Spécifier le user pour la connexion distante, s'il n'est pas possible de
|
||
le spécifier dans l'url. En cas de conflit, la valeur dans l'url est
|
||
prioritaire par rapport à cette option.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mysqlcsv" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mysqlcsv: Faire une requête MySQL et formater la sortie pour traitement avec awkcsv
|
||
|
||
USAGE
|
||
mysqlcsv [query [db]] [-- mysql options]
|
||
|
||
query est la requête sql à exécuter. Si query n'est pas spécifiée, la(les)
|
||
requête(s) sql sont prises sur l'entrée standard, ou depuis un fichier
|
||
si l'option -f est spécifiée.
|
||
db est le nom de la base de données. Cette argument n'est lu que si le nom
|
||
de la base de donnée n'est ni spécifié dans le fichier de configuration,
|
||
ni spécifié avec l'option -D
|
||
|
||
OPTIONS
|
||
-h, --host HOST
|
||
-P, --port PORT
|
||
-u, --user USER
|
||
-pPASSWORD
|
||
-D, --database DATABASE
|
||
Informations de connexion à la base de données
|
||
-C, --config CONFIG
|
||
Prendre les informations de connexion depuis le fichier spécifié.
|
||
Le fichier doit être de la forme
|
||
host=HOST
|
||
#post=3306
|
||
user=USER
|
||
password=PASS
|
||
#database=DB
|
||
#query=QUERY
|
||
Les variables port, database et query sont facultatives.
|
||
Les valeurs définies dans ce fichier sont prioritaires par rapport à
|
||
celles qui auraient été spécifiées sur la ligne de commande.
|
||
Utiliser password=--NOT-SET-- s'il faut se connecter sans mot de passe
|
||
Cette option peut être utilisée plusieurs fois, auquel cas les fichiers
|
||
sont chargés dans l'ordre.
|
||
--profile PROFILE
|
||
La variable $PROFILE est définie avec la valeur spécifiée avant de
|
||
sourcer les fichiers de configuration. Cela permet d'avoir des fichiers
|
||
de configuration qui calculent dynamiquement les paramètres en fonction
|
||
de la valeur du profil.
|
||
-N, --no-headers
|
||
Ne pas afficher les en-têtes
|
||
-c, --force
|
||
Continuer le traitement même en cas d'erreur
|
||
-r, --raw
|
||
Ne pas autoriser mysql à mettre en échappement certaines valeurs
|
||
retournées par le serveur. Par défaut, les transformations suivantes
|
||
sont effectuées:
|
||
newline --> \n
|
||
tab --> \t
|
||
nul --> \0
|
||
\ --> \\
|
||
-n, --nulls
|
||
Transformer dans le flux en sortie les valeurs NULL en chaines vides
|
||
-f, --input INPUT
|
||
Lire la requête depuis le fichier input au lieu de le lire depuis la
|
||
ligne de commande ou l'entrée standard. Ne pas spécifier cette option
|
||
ou utiliser '-' pour lire depuis l'entrée standard.
|
||
Cette option est ignorée si la requête est spécifiée parmi les
|
||
arguments.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="mysqlloadcsv" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
mysqlloadcsv: Charger une table MySQL avec un fichier csv
|
||
|
||
USAGE
|
||
mysqlloadcsv [db.]table [fields...] [-- mysql options]
|
||
|
||
db est le nom de la base de données
|
||
table est le nom de la table à charger
|
||
fields est la liste des colonnes. Si cette valeur est spécifiée, il faudra
|
||
peut-être utiliser l'option -s pour ignorer le cas échéant la ligne des
|
||
en-têtes dans le fichier en entrée. Sinon, les colonnes à utiliser sont
|
||
calculées à partir du fichier en entrée.
|
||
|
||
Dans les données en entrées, qui doivent être en UTF8, les conversions suivantes
|
||
sont effectuées par MySQL:
|
||
|
||
\0 --> <caractère NUL>
|
||
\b --> <backspace>
|
||
\n --> <newline>
|
||
\r --> <carriage return>
|
||
\t --> <tab>
|
||
\Z --> Ctrl+Z
|
||
\N --> NULL
|
||
|
||
OPTIONS
|
||
-h, --host host
|
||
-P, --port port
|
||
-u, --user user
|
||
-ppassword
|
||
Informations de connexion à la base de données
|
||
-C, --config CONFIG
|
||
Prendre les informations de connexion depuis le fichier spécifié.
|
||
Le fichier doit être de la forme
|
||
host=HOST.TLD
|
||
#post=3306
|
||
user=USER
|
||
password=PASS
|
||
#dbtable=DB.TABLE
|
||
#fields=(FIELDS...)
|
||
# Il est possible aussi de spécifier DB et TABLE séparément:
|
||
#database=DB
|
||
#table=TABLE
|
||
Les variables port, dbtable et fields sont facultatives.
|
||
Les valeurs définies dans ce fichier sont prioritaires par rapport à
|
||
celles qui auraient été spécifiées sur la ligne de commande.
|
||
Utiliser password=--NOT-SET-- s'il faut se connecter sans mot de passe
|
||
Cette option peut être utilisée plusieurs fois, auquel cas les fichiers
|
||
sont chargés dans l'ordre.
|
||
--profile PROFILE
|
||
La variable $PROFILE est définie avec la valeur spécifiée avant de
|
||
sourcer les fichiers de configuration. Cela permet d'avoir des fichiers
|
||
de configuration qui calculent dynamiquement les paramètres en fonction
|
||
de la valeur du profil.
|
||
-f, --input INPUT
|
||
Fichier en entrée. Ne pas spécifier cette option ou utiliser '-' pour
|
||
lire depuis l'entrée standard.
|
||
-d, --auto-dbtable DB
|
||
Spécifier la base de données avec laquelle se connecter. De plus, si le
|
||
nom de la table n'est pas spécifié, prendre par défaut le nom de base du
|
||
fichier spécifié avec l'option -f
|
||
-s, --skip-lines NBLINES
|
||
Nombre de lignes à sauter dans le fichier en entrée
|
||
-n, --fake
|
||
Ne pas effectuer l'opération. Afficher simplement la commande SQL.
|
||
--run
|
||
Forcer le lancement de l'opération. Utiliser cette option avec -A pour
|
||
créer la table avec les paramètres analysés.
|
||
-T, --truncate
|
||
Vider la table avant d'effectuer le chargement
|
||
-L, --load-data
|
||
Charger les données avec la commande 'load data local'. C'est l'option
|
||
par défaut. Le fichier est transmis tel quel à MySQL.
|
||
-I, --insert-data
|
||
Charger les données en générant des commandes 'insert into'. L'effet est
|
||
en principe le même avec l'option -L (sauf que certains formats de date
|
||
exotiques seront correctement importés). Cette option peut aussi être
|
||
utilisée avec l'option -n pour générer une liste de commande à corriger
|
||
et/ou adapter.
|
||
-U, -k, --update-data KEY
|
||
Au lieu de charger de nouvelles données, essayer de mettre à jour la
|
||
table. KEY est le nom de la colonne qui est utilisée comme clé. Toutes
|
||
les autres colonnes sont les nouvelles données à mettre à jour. Si
|
||
aucune ligne ne correspond à une clé donnée, la mise à jour pour cette
|
||
ligne est ignorée.
|
||
Note: utiliser les options -T et -U ensemble n'a pas de sens, mais -T
|
||
est quand même honoré.
|
||
-Z, --null-value VALUE
|
||
Avec les options -I et -U, considérer que NULL est représenté par la
|
||
chaine spécifiée. Par défaut, utiliser \N
|
||
-z, --null-is-empty
|
||
Avec les options -I et -U, considérer que NULL est représenté par la
|
||
chaine vide. Cette option est équivalente à -Z ''
|
||
-t, --types [DEFAULT_TYPE,]FIELD:TYPE,...
|
||
Spécifier pour chaque champ mentionné le type de donnée à forcer. Le
|
||
type 'auto' signifie que le type est autodétecté. C'est la valeur par
|
||
défaut. Les autres types valides sont 'str', 'int' et 'date'
|
||
Cette option est ignorée avec l'option -L
|
||
-A, --analyse
|
||
Analyser les données et afficher une requête pour créer une table qui
|
||
pourrait contenir ces données.
|
||
Cette option implique --fake et affiche simplement la commande SQL.
|
||
Pour lancer la commande SQL générée, il faut ajouter l'option --run
|
||
APRES cette option
|
||
}}}</pre>
|
||
</div>
|
||
<div title="noerr" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
noerr: lancer une commande en supprimant la sortie d'erreur
|
||
}}}</pre>
|
||
</div>
|
||
<div title="noerror" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
noerror: lancer une commande en masquant son code de retour. le code de retour est toujours 0
|
||
}}}</pre>
|
||
</div>
|
||
<div title="noout" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
noout: lancer une commande en supprimant la sortie standard
|
||
}}}</pre>
|
||
</div>
|
||
<div title="nutools" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
nutools: configurer ou afficher des informations sur nutools
|
||
|
||
USAGE
|
||
nutools [VERSION]
|
||
|
||
OPTIONS
|
||
-C, --configure
|
||
Faire la configuration pour l'utilisateur courant en appelant uenv -u
|
||
Avec cette option, l'option -l (ou --local-profiles) est aussi reconnue
|
||
et est passée directement à uenv
|
||
-v, --version
|
||
Afficher la version de nutools installée. C'est l'option par défaut
|
||
-c, --check
|
||
Calculer si la version installée correspond à la version spécifiée
|
||
-o, --oper OPERATOR
|
||
Spécifier l'opérateur à utiliser avec l'option --check (par défaut,
|
||
utiliser l'opérateur ge, qui permet de vérifier si la version minimum
|
||
spécifiée est installée)
|
||
--eq
|
||
--ne
|
||
--lt
|
||
--le
|
||
--gt
|
||
--ge
|
||
--same
|
||
--diff
|
||
Ces options sont des raccourcis. L'option '--OP' est équivalente à
|
||
'--check --op OP'
|
||
}}}</pre>
|
||
</div>
|
||
<div title="openurl" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
openurl: Ouvrir une URL dans un navigateur
|
||
|
||
USAGE
|
||
openurl <file.url|file.desktop|URL>
|
||
}}}</pre>
|
||
</div>
|
||
<div title="pdev" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
pdev: basculer sur une branche de développement
|
||
|
||
USAGE
|
||
pdev [FEATURE [SOURCE]]
|
||
pdev -m|-l|-d [FEATURE]
|
||
|
||
- Vérifier l'existence de la branche develop. La créer si nécessaire en la
|
||
basant sur [origin/]master.
|
||
- Vérifier s'il n'y a pas de modifications locales. Sinon, proposer de faire un
|
||
commit ou un stash.
|
||
- Si FEATURE est spécifié, et si on n'est pas déjà sur cette branche, basculer
|
||
vers cette nouvelle branche. S'il s'agit d'une nouvelle branche, la baser sur
|
||
la branche SOURCE, qui vaut par défaut develop
|
||
- Si FEATURE n'est pas spécifié, basculer sur develop s'il s'agit de la seule
|
||
solution, sinon afficher un menu pour choisir la branche de destination.
|
||
|
||
OPTIONS
|
||
-C, --projdir PROJDIR
|
||
Spécifier le répertoire de base du projet qui est dans git. Par défaut,
|
||
on travaille dans le répertoire courant et on laisse git trouver le
|
||
répertoire de base du projet. Avec cette option, le répertoire courant
|
||
est modifié avant de lancer les commandes git.
|
||
-O, --origin ORIGIN
|
||
Spécifier le nom de l'origine. Par défaut, utiliser 'origin'
|
||
-o, --offline
|
||
En cas de création d'une branche, ne pas pousser vers l'origine; ne pas
|
||
tenter le cas échéant de traquer la branche dans l'origine; ne pas
|
||
supprimer une branche dans l'origine. Cette option est automatiquement
|
||
activée si la variable UTOOLS_VCS_OFFLINE est définie.
|
||
--online
|
||
Annuler l'effet de la variable UTOOLS_VCS_OFFLINE: forcer le mode online
|
||
--sync
|
||
Faire un certain nombre d'opération pour 'corriger' le dépôt local: pour
|
||
chacune des branches distantes, vérifier qu'il existe une branche locale
|
||
qui la traque, et pour chaque feature branche locale, vérifier qu'il
|
||
existe une branche distante associée. Cette option nécessite --online
|
||
|
||
-s, --squash COMMIT_MSG
|
||
Si la branche actuelle est une feature branch, la merger comme un seul
|
||
commit avec le message COMMIT_MSG dans develop puis la supprimer. Puis
|
||
basculer sur la branche develop.
|
||
Cette option ne devrait pas être utilisée avec -k, puisque bien que les
|
||
modifications soient mergées, la branche elle-même n'est pas considérée
|
||
comme mergée. Les résultats sont donc indéfinis si la branche est mergée
|
||
à plusieurs reprises.
|
||
-b, --rebase
|
||
Si la branche actuelle est une feature branch, lancer 'git rebase -i'
|
||
sur la feature branch. Cela permet de réordonner les commits pour
|
||
nettoyer l'historique avant de fusionner la branche avec -m
|
||
Cette option devrait le cas échéant être utilisée immédiatement avant -m
|
||
ou alors il faut forcer le push et communiquer avec l'équipe sur le fait
|
||
que la branche de feature a été rebasée.
|
||
-m, --merge
|
||
Si la branche actuelle est une feature branch, la merger dans develop
|
||
puis la supprimer. Puis basculer sur la branche develop.
|
||
--merge-log
|
||
Ajouter un résumé des modifications sur la feature branch en ajoutant le
|
||
log en une ligne de chaque commit dans le message du merge. Cette option
|
||
n'est en principe pas nécessaire puisque 'prel -um' intègre la liste des
|
||
commits dans CHANGES.txt
|
||
-k, --keep
|
||
Avec l'option -m, ne pas supprimer une feature branch après l'avoir
|
||
fusionnée dans develop. Cela permet d'intégrer les modifications petit à
|
||
petit.
|
||
--delete
|
||
Supprimer une feature branch, à condition qu'elle aie déjà été
|
||
entièrement fusionnée dans la branch develop
|
||
--force-delete
|
||
Supprimer une feature branch, même si elle n'a pas encore été fusionnée
|
||
dans la branche develop
|
||
|
||
-l, --log
|
||
-d, --diff
|
||
Afficher les modifications entre deux branches. L'option --log affiche
|
||
les modifications dans l'ordre alors que --diff affiche les différences
|
||
sous forme de diff. Les deux options peuvent être combinées et ont
|
||
l'effet de 'git log -p'
|
||
La branche comparée, s'il elle n'est pas spécifiée, est par défaut la
|
||
branche courante. S'il s'agit d'une feature branch, elle est comparée à
|
||
develop. S'il s'agit de la branche develop, elle est comparée à master.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="prel" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
prel: basculer sur une branche de release
|
||
|
||
USAGE
|
||
prel -u [SOURCE]
|
||
prel -c [RELEASE [SOURCE]]
|
||
prel -m|-l|-d [RELEASE]
|
||
|
||
- Vérifier s'il n'y a pas de modifications locales. Sinon, proposer de faire un
|
||
commit ou un stash.
|
||
- Avec l'option -c, s'il existe une branche de release, proposer de basculer
|
||
vers elle ou sur la branche master. Sinon, basculer sur la branche master.
|
||
- Avec l'option -u, proposer ou fixer une branche de release à créer. Si elle
|
||
existe déjà, basculer vers elle. Sinon, la créer en la basant sur SOURCE, qui
|
||
vaut par défaut develop
|
||
|
||
OPTIONS
|
||
-C, --projdir PROJDIR
|
||
Spécifier le répertoire de base du projet qui est dans git. Par défaut,
|
||
on travaille dans le répertoire courant et on laisse git trouver le
|
||
répertoire de base du projet. Avec cette option, le répertoire courant
|
||
est modifié avant de lancer les commandes git.
|
||
-O, --origin ORIGIN
|
||
Spécifier le nom de l'origine. Par défaut, utiliser 'origin'
|
||
-o, --offline
|
||
En cas de création d'une branche, ne pas pousser vers l'origine; ne pas
|
||
tenter le cas échéant de traquer la branche dans l'origine; ne pas
|
||
supprimer une branche dans l'origine. Cette option est automatiquement
|
||
activée si la variable UTOOLS_VCS_OFFLINE est définie.
|
||
--online
|
||
Annuler l'effet de la variable UTOOLS_VCS_OFFLINE: forcer le mode online
|
||
|
||
-c, --checkout
|
||
Basculer vers une branche de release existante. C'est l'option par
|
||
défaut. Si aucune branche de release n'existe, basculer vers master
|
||
-u, --update
|
||
Préparer une nouvelle release. Utiliser une des options -x, -z ou -p
|
||
pour spécifier le type de release à préparer. Si la branche qui serait
|
||
créée pour le type de release existe déjà, basculer vers cette branche.
|
||
S'il faut la créer, la baser sur la branche SOURCE, qui vaut par défaut
|
||
develop
|
||
--menu
|
||
-x, --major
|
||
-z, --minor
|
||
-p, --patchlevel
|
||
Utilisé avec l'option -u, soit afficher un menu pour choisir la version
|
||
de la nouvelle release (par défaut), soit préparer respectivement une
|
||
release majeure, mineure, ou pour correction de bug.
|
||
-v-OPT
|
||
Avec l'option -u, spécifier une option de pver permettant de choisir la
|
||
version de la nouvelle release. Les options supportées sont -v, -l, -a,
|
||
-b, -r et -R. Par exemple, si la version actuelle sur la branche master
|
||
est 0.2.3, les options '-uz -v-lbeta' permettent de préparer la release
|
||
0.3.0-beta
|
||
En principe, cette option n'a pas à être utilisée, puisque dans une
|
||
branche de release, on peut faire vivre les versions de pré-release
|
||
jusqu'à la release finale. Ainsi, la branche de release est nommée
|
||
d'après la version finale, mais le projet peut recevoir une version de
|
||
pré-release incrémentale.
|
||
-w, --write
|
||
Si une nouvelle branche est créée avec -u, mettre à jour le fichier
|
||
VERSION.txt avec pver. C'est l'option par défaut.
|
||
-n, --no-write
|
||
Si une nouvelle branche est créée avec -u, NE PAS mettre à jour le
|
||
fichier VERSION.txt avec pver. Utiliser cette option si la mise à jour
|
||
du numéro de version doit être faite d'une manière particulière.
|
||
-e, --edit
|
||
Editer le fichier CHANGES.txt autogénéré par -u -w
|
||
Cette option est surtout utile si -m est utilisé avec -u, pour donner la
|
||
possibilité de corriger la liste des modifications avant leur
|
||
enregistrement définitif.
|
||
|
||
-m, --merge
|
||
Si la branche actuelle est une branche de release, ou s'il existe une
|
||
branche de release, la merger dans master, puis dans develop, puis la
|
||
supprimer. Puis basculer sur la branche master.
|
||
S'il n'existe pas de branche de release, proposer de fusionner les
|
||
modifications de la branche develop dans la branche master, sans
|
||
préparer de branche de release au préalable.
|
||
--delete
|
||
Supprimer une branche de release, à condition qu'elle aie déjà été
|
||
entièrement fusionnée dans la branch master
|
||
--force-delete
|
||
Supprimer une branche de release, même si elle n'a pas encore été
|
||
fusionnée dans la branche master
|
||
|
||
-s, --summary
|
||
Afficher la liste des différences entre la branche develop et la branche
|
||
master, comme elle serait générée par les options -u -w pour le fichier
|
||
CHANGES.txt
|
||
-l, --log
|
||
Afficher les modifications actuellement effectuée dans la branche de
|
||
release par rapport à develop.
|
||
-d, --diff
|
||
Afficher les modifications actuellement effectuée dans la branche de
|
||
release par rapport à develop, sous forme de diff.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="pver" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
pver: gérer des numéros de version selon les règles du versionage sémantique v2.0.0 (http://semver.org/)
|
||
|
||
USAGE
|
||
pver [options]
|
||
|
||
OPTIONS
|
||
-f, --file VERSIONFILE
|
||
Gérer le numéro de version se trouvant dans le fichier spécifié. Le
|
||
fichier est créé si nécessaire. C'est l'option par défaut si un fichier
|
||
nommé VERSION.txt se trouve dans le répertoire courant.
|
||
-e, --maven POMFILE
|
||
Gérer le numéro de version se trouvant dans le fichier pom.xml spécifié.
|
||
Le fichier DOIT exister. C'est l'option par défaut si un fichier nommé
|
||
pom.xml se trouve dans le répertoire courant.
|
||
-F, --file-string VERSIONFILE
|
||
Prendre pour valeur de départ le contenu du fichier VERSIONFILE (qui
|
||
vaut par défaut VERSION.txt)
|
||
-g, --git-string [branch:]VERSIONFILE
|
||
Prendre pour valeur de départ le contenu du fichier VERSIONFILE (qui
|
||
vaut par défaut VERSION.txt) dans la branche BRANCH (qui vaut par défaut
|
||
master) du dépôt git situé dans le répertoire courant.
|
||
-s, --string VERSION
|
||
Prendre pour valeur de départ le numéro de version spécifié
|
||
|
||
--show
|
||
Afficher le numéro de version. C'est l'action par défaut
|
||
--allow-empty
|
||
Supporter que la version puisse ne pas être spécifiée ni trouvée. Dans
|
||
ce cas, ne pas assumer que la version effective est 0.0.0
|
||
Avec --show et --update, ne rien afficher si la version est vide.
|
||
--check
|
||
Vérifier que le numéro de version est conforme aux règles du versionage
|
||
sémantique
|
||
--convert
|
||
--no-convert
|
||
Activer (resp. désactiver) la conversion automatique. Par défaut, si la
|
||
version est au format classique 'x.z[.p]-rDD/MM/YYYY', elle est
|
||
convertie automatiquement au format sémantique x.z.p+rYYYYMMDD
|
||
--eq VERSION
|
||
--ne VERSION
|
||
--lt VERSION
|
||
--le VERSION
|
||
--gt VERSION
|
||
--ge VERSION
|
||
--same VERSION
|
||
--diff VERSION
|
||
Comparer avec la version spécifiée. Les opérateurs --eq, --ne, --lt,
|
||
--le, --gt, et --ge ignorent l'identifiant de build (comme le demande la
|
||
règle du versionage sémantique). Les opérateurs --same et --diff
|
||
comparent aussi les identifiants de build.
|
||
-v, --set-version VERSION
|
||
Spécifier un nouveau numéro de version qui écrase la valeur actuelle.
|
||
Cette option ne devrait pas être utilisée en temps normal parce que cela
|
||
va contre les règles du versionage sémantique.
|
||
--prel
|
||
Spécifier un nouveau numéro de version qui écrase la valeur actuelle. Le
|
||
numéro de version est obtenu à partir du nom de la branche git courante,
|
||
qui doit être de la forme release-VERSION
|
||
-u, --update
|
||
Mettre à jour le numéro de version.
|
||
|
||
--menu
|
||
Afficher un menu permettant de choisir le composant de la version à
|
||
incrémenter
|
||
-x, --major
|
||
Augmenter le numéro de version majeure
|
||
-z, --minor
|
||
Augmenter le numéro de version mineure. C'est la valeur par défaut.
|
||
-p, --patchlevel
|
||
Augmenter le numéro de patch
|
||
|
||
-l, --prelease ID
|
||
Spécifier un identifiant de pré-release, à ajouter au numéro de version.
|
||
-a, --alpha
|
||
-b, --beta
|
||
-r, --rc
|
||
Spécifier une pré-release de type alpha, beta, ou rc. Si la version est
|
||
déjà dans ce type, augmenter la dernière valeur numérique des composants
|
||
de l'identifiant, e.g. alpha deviant alpha.1, beta-1.2 devient beta-1.3,
|
||
rc1 devient rc2
|
||
XXX ces fonctions ne sont pas encore implémentées
|
||
-R, --final, --release
|
||
Supprimer l'identifiant de prérelease
|
||
|
||
-m, --metadata ID
|
||
Spécifier un identifiant de build, à ajouter au numéro de version.
|
||
-M, --vcs-metadata
|
||
Spécifier l'identifiant à partir de la révision actuelle dans le
|
||
gestionnaire de version. Note: pour le moment, seul git est supporté.
|
||
--add-metadata ID
|
||
Ajouter l'identifiant spécifié à la valeur actuelle, au lieu de la
|
||
remplacer. Séparer l'identifiant de la valeur précédente avec un '.'
|
||
}}}</pre>
|
||
</div>
|
||
<div title="pz" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
pz: faire une archive du projet
|
||
|
||
USAGE
|
||
pz
|
||
|
||
OPTIONS
|
||
-C, --projdir PROJDIR
|
||
Spécifier le répertoire de base du projet qui est dans git. Par défaut,
|
||
on travaille dans le répertoire courant et on laisse git trouver le
|
||
répertoire de base du projet. Avec cette option, le répertoire courant
|
||
est modifié avant de lancer les commandes git.
|
||
-d, --destdir DESTDIR
|
||
Spécifier le répertoire dans lequel générer l'archive. Par défaut,
|
||
prendre le répertoire parent du répertoire de base du dépôt.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="reptyr.cgo" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
Usage: reptyr [-s] PID
|
||
reptyr -l|-L [COMMAND [ARGS]]
|
||
-l Create a new pty pair and print the name of the slave.
|
||
if there are command-line arguments after -l
|
||
they are executed with REPTYR_PTY set to path of pty.
|
||
-L Like '-l', but also redirect the child's stdio to the slave.
|
||
-s Attach fds 0-2 on the target, even if it is not attached to a tty.
|
||
-h Print this help message and exit.
|
||
-v Print the version number and exit.
|
||
-V Print verbose debug output.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="rmtildes" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
rmtildes: supprimer les fichiers *~ dans le répertoire courant
|
||
|
||
USAGE
|
||
rmtildes [dir [glob]]
|
||
|
||
Par défaut, dir==. et glob==*~
|
||
}}}</pre>
|
||
</div>
|
||
<div title="rruns" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
rruns: Déploiement distant avec runs
|
||
|
||
USAGE
|
||
rruns [-h hosts] [-T tmproot] rscriptname name=value...
|
||
rruns [-h hosts] [-T tmproot] @recipe name=value...
|
||
rruns [-h hosts] [-T tmproot] -f rscript name=value...
|
||
rruns [-h hosts] [-T tmproot] -r recipe name=value...
|
||
|
||
Lancer ce script sans argument (hors options) est équivalent à le lancer avec
|
||
l'argument @default
|
||
|
||
OPTIONS
|
||
-C Ne pas faire le déploiement. Configurer uniquement la connexion par clé
|
||
sur les hôtes distants spécifiés pour le user spécifié. Il faut pouvoir
|
||
se connecter par mot de passe pour configurer la connexion par clé.
|
||
Si l'on veut configurer la connexion par clé pour le user root, mais que
|
||
ce n'est pas possible de se connecter par mot de passe avec le user root
|
||
sur l'hôte distant, et qu'il existe un user sudoer sur l'hôte distant,
|
||
il est possible de faire la configuration avec '--configure root'. La
|
||
commande serait alors
|
||
rruns -h user@host --configure root
|
||
-T tmproot
|
||
Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple
|
||
/var/tmp. Cette option est utile pour les vservers, qui ont par défaut
|
||
un /tmp minuscule de 16 Mo.
|
||
-S ssh
|
||
Spécifier le programme à utiliser pour la connection par ssh.
|
||
-h host
|
||
-h @hostsfile
|
||
Spécifier un ou plusieurs hôtes sur lequels faire le déploiement. Pour
|
||
spécifier plusieurs hôtes, il est possible d'utiliser plusieurs fois
|
||
l'option -h, ou spécifier en une seule fois plusieurs hôtes en les
|
||
séparant par un espace ou le caractère ':', e.g. 'host1 host2' ou
|
||
'host1:host2'. Si la spécification contient les caractères { et },
|
||
l'expansion est effectuée, e.g
|
||
-h 'root@{host1,host2}.univ.run'
|
||
Par défaut, la connexion sur l'hôte distant se fait avec l'utilisateur
|
||
root. Il est possible de spécifier un autre utilisateur avec la syntaxe
|
||
user@host, e.g -h user@host
|
||
La forme @hostsfile permet de lire la liste des hôtes depuis le fichier
|
||
hostsfile, à raison d'un hôte par ligne.
|
||
Si cette option n'est pas spécifiée, et que le répertoire courant est
|
||
dans un des répertoires de $RUNSHOSTSPATH, sélectionner l'hôte
|
||
correspondant. Sinon, l'utilisateur doit saisir l'hôte distant de façon
|
||
interactive.
|
||
-f RSCRIPT
|
||
Lancer le script individuel spécifié au lieu de chercher dans les
|
||
répertoires $RUNS{SCRIPTS,HOSTS}PATH
|
||
-r RECIPE
|
||
Lancer les scripts spécifiés dans le fichier de recettes individuel
|
||
spécifié.
|
||
-z Forcer la réinstallation des scripts qui se basent sur shouldrun/setdone
|
||
-o OUTPUT
|
||
Générer l'archive à lancer sur l'hôte distant au lieu de faire le
|
||
déploiement. Si plusieurs hôtes sont spécifiés, OUTPUT est considéré
|
||
comme un nom de base auquel est ajouté le nom de l'hôte sur lequel
|
||
l'archive doit être déployée.
|
||
--init
|
||
--no-init
|
||
Forcer (resp. empêcher) la création des répertoires d'hôte correspondant
|
||
aux hôtes spécifiés. Par défaut, la création des répertoires d'hôte est
|
||
effectuée uniquement si ce script est lancé sans argument.
|
||
--sysinfos
|
||
Après un déploiement réussi sur l'hôte distant, inscrire si ce n'est
|
||
déjà fait le résultat de la commande usysinfos dans le fichier
|
||
sysinfos.conf du répertoire d'hôte.
|
||
Cette option est automatiquement activée si ce script est lancé sans
|
||
argument (hors options).
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ruinst" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ruinst: Déploiement distant avec uinst
|
||
|
||
USAGE
|
||
ruinst [-h host] [-T tmproot] <file|archive|dir> [-- options de uinst]
|
||
|
||
note: à cause d'une limitation de makeself, les options de uinst ne devraient
|
||
pas contenir d'espaces ni de caractères spéciaux. L'échappement de ces
|
||
caractères n'est pas garanti.
|
||
|
||
OPTIONS
|
||
-C Ne pas faire le déploiement. Configurer uniquement la connexion par clé
|
||
sur les hôtes distants spécifiés pour le user spécifié. Il faut pouvoir
|
||
se connecter par mot de passe pour configurer la connexion par clé.
|
||
Si l'on veut configurer la connexion par clé pour le user root, mais que
|
||
ce n'est pas possible de se connecter par mot de passe avec le user root
|
||
sur l'hôte distant, et qu'il existe un user sudoer sur l'hôte distant,
|
||
il est possible de faire la configuration avec '--configure root'. La
|
||
commande serait alors
|
||
ruinst -h user@host --configure root
|
||
Si l'hôte distant n'a pas sudo ou si sudo n'est pas configuré, il faut
|
||
rajouter l'option --uses-su, e.g:
|
||
ruinst -h user@host --configure root --uses-su
|
||
-T tmproot
|
||
Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple
|
||
/var/tmp. Cette option est utile pour les vservers, qui ont par défaut
|
||
un /tmp minuscule de 16 Mo.
|
||
-S, --ssh ssh
|
||
Spécifier le programme à utiliser pour la connection par ssh.
|
||
-h hosts
|
||
-h @hostsfile
|
||
Spécifier un ou plusieurs hôtes sur lequels faire le déploiement. Pour
|
||
spécifier plusieurs hôtes, il est possible d'utiliser plusieurs fois
|
||
l'option -h, ou spécifier en une seule fois plusieurs hôtes en les
|
||
séparant par un espace ou le caractère ':', e.g. 'host1 host2' ou
|
||
'host1:host2'. Si la spécification contient les caractères { et },
|
||
l'expansion est effectuée, e.g
|
||
-h 'root@{host1,host2}.univ.run'
|
||
Par défaut, la connexion sur l'hôte distant se fait avec l'utilisateur
|
||
root. Il est possible de spécifier un autre utilisateur avec la syntaxe
|
||
user@host, e.g -h user@host
|
||
La forme @hostsfile permet de lire la liste des hôtes depuis le fichier
|
||
hostsfile, à raison d'un hôte par ligne.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="rumount" creator="jclain" modifier="jclain" created="201604262318" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
rumount: démonter un système de fichier récursivement
|
||
|
||
USAGE
|
||
rumount mountpoint
|
||
|
||
Démonter tous les systèmes de fichiers qui sont montés en-dessous de mountpoint
|
||
puis démonter mountpoint. Démonter aussi tous les systèmes de fichiers
|
||
bind-montés à partir d'un sous-répertoire de mountpoint.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="runs" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
runs: Lancer un script avec le protocole runs
|
||
|
||
USAGE
|
||
runs [options] rscriptname name=value...
|
||
runs [options] @recipe name=value...
|
||
runs [options] -f rscript name=value...
|
||
runs [options] -r recipe name=value...
|
||
|
||
OPTIONS
|
||
Configuration
|
||
--init
|
||
--verify
|
||
Vérifier le nom d'hôte et créer si nécessaire le répertoire d'hôte
|
||
correspondant à l'hôte courant ou à l'hôte spécifié avec l'option -h
|
||
Avec --verify, la création du répertoire d'hôte n'est pas effectuée.
|
||
--sysinfos DATA
|
||
Avec l'option --init, initialiser le fichier sysinfos.conf avec DATA, si
|
||
le fichier n'a pas déjà été provisionné. Sans cette option, un fichier
|
||
vide avec des commentaires est créé à la place.
|
||
--create RSCRIPT
|
||
Créer un modèle de script avec le nom donné.
|
||
Avec l'option -h, le script est créé dans le répertoire d'hôte
|
||
correspondant à l'hôte spécifié
|
||
|
||
Gestion des scripts
|
||
-s Forcer l'exécution du script avec l'utilisateur root si ce n'est pas
|
||
déjà le cas
|
||
-f RSCRIPT
|
||
Lancer le script individuel spécifié au lieu de chercher dans les
|
||
répertoires de $RUNSSCRIPTSPATH
|
||
-r RECIPE
|
||
Lancer les scripts spécifiés dans le fichier de recettes individuel
|
||
spécifié.
|
||
-h HOSTNAME[.DOMAIN]
|
||
Spécifier que les scripts sont destinés à être lancés sur l'hôte
|
||
spécifié. Les scripts sont alors aussi cherchés dans les répertoires
|
||
{$RUNSHOSTSPATH}/$hostname.$domain (par défaut) et
|
||
{$RUNSHOSTSPATH}/$domain/$hostname (le cas échéant)
|
||
L'option --host est équivalente, sauf que son argument est facultatif et
|
||
que sa valeur par défaut est l'hôte courant, soit sulfure
|
||
--list
|
||
Afficher la liste des scripts qui sont disponibles. Avec l'option -h,
|
||
inclure aussi les scripts spécifiques à cet hôte.
|
||
Avec cette option, les arguments supplémentaires agissent comme des
|
||
filtres (regexp utilisée avec l'opérateur == de la commande [[). Les
|
||
noms des scripts doivent valider au moins un filtre.
|
||
--info
|
||
Afficher la la description du script et la valeur de chaque variable
|
||
définies
|
||
--desc-only
|
||
Afficher seulement la description du script
|
||
-z Forcer la réinstallation des scripts qui se basent sur shouldrun/setdone
|
||
}}}</pre>
|
||
</div>
|
||
<div title="runsconfig" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
runsconfig: Gérer un répertoire d'hôte de runs
|
||
|
||
USAGE
|
||
runsconfig -c [host [destdir]]
|
||
runsconfig -t -- args...
|
||
|
||
OPTIONS
|
||
-c, --create
|
||
Créer un nouveau répertoire de configuration pour un hôte
|
||
-d, --destdir DESTDIR[=runs]
|
||
Nom du répertoire local de configuration.
|
||
|
||
-t, --template [OPT]
|
||
Gérer les fichiers du répertoire local avec templatectl. La valeur de
|
||
cette option est utilisée comme argument court pour l'invocation de
|
||
templatectl, e.g
|
||
runsconfig -tm args
|
||
est équivalent à
|
||
templatectl -m args
|
||
Les arguments qui restent sont passés tels quels à templatectl
|
||
Les options courantes de templatectl -l, -v, -m, -L sont disponibles
|
||
directement
|
||
--help-template
|
||
Afficher l'aide concernent la gestion des templates.
|
||
Equivalent à -t -- --help
|
||
-h, --host HOST
|
||
Spécifier l'hôte. Equivalent à -v host=HOST
|
||
}}}</pre>
|
||
</div>
|
||
<div title="runsmod" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
runsmod: récupérer des dépôts git à usage de runs
|
||
|
||
USAGE
|
||
runsmod [options] [-h host] [modules...]
|
||
|
||
Tous les dépôts spécifiés dans la configuration sont récupérés. Si des modules
|
||
sont spécifiés, les dépôts correspondants sont récupérés aussi. Avec l'option
|
||
-h, des dépôts spécifiques à l'hôte peuvent éventuellement être récupérés en
|
||
plus.
|
||
|
||
OPTIONS
|
||
-c, --config CONFIG
|
||
Spécifier un fichier de configuration à charger au lieu de la valeur par
|
||
défaut ~/etc/default/runs
|
||
--prod
|
||
--devel
|
||
Forcer un mode de sélection des urls. En mode production, préférer pour
|
||
le clonage les urls de production, qui sont en principe accessibles sans
|
||
authentification et en lecture seule. En mode développement, préférer
|
||
pour le clonage les urls de développement, qui sont en principe
|
||
accessibles par clé ssh et en lecture/écriture
|
||
--no-fetch
|
||
Ne rien récupérer. Utile avec --update-repolist
|
||
-N, --no-host
|
||
-A, --all-hosts
|
||
-H, -h, --host HOST
|
||
-T, --this-host
|
||
Options permettant de spécifier l'hôte pour la récupération de dépôts
|
||
spécifiques.
|
||
--no-host demande explicitement à ce qu'aucun hôte ne soit spécifié
|
||
--all-hosts sélectionne tous les dépôts spécifiques
|
||
--host récupère uniquement les dépôts pour l'hôte spécifié
|
||
--this-host équivaut à --host sulfure
|
||
L'option par défaut est --this-host en mode production et --all-hosts en
|
||
mode développement
|
||
--update-repolist
|
||
Forcer la mise à jour de la liste des dépôts. En principe, cette mise à
|
||
jour n'est pas faite plus d'une fois par période de 24 heures.
|
||
-0, --offline
|
||
-n, --no-pull
|
||
-u, --pull
|
||
Spécifier le mode opératoire pour la récupération des dépôts.
|
||
En mode --offline, ni clone ni pull ne sont autorisés. Le module doit
|
||
avoir déjà été cloné.
|
||
En mode --no-pull, seul le clonage est autorisé, e.g. le dépôt est
|
||
cloné si ce n'est pas déjà le cas.
|
||
En mode --pull, cloner le dépôt si ce n'est pas déjà le cas, ou le
|
||
mettre à jour le dépôt avant de l'utiliser s'il avait déjà été cloné.
|
||
Par défaut, utiliser --pull en mode production et --no-pull en mode
|
||
développement.
|
||
-i, --identity IDENTITY_FILE
|
||
Spécifier le fichier depuis lequel lire la clé privée pour les
|
||
connexions par ssh.
|
||
-o, --output OUTPUT
|
||
Spécifier un fichier dans lequel écrire des définitions de variables,
|
||
notamment REPODIRS qui reçoit la liste des chemins des dépôts qui ont
|
||
été récupérés. De plus, les variables RUNSSCRIPTSPATH, RUNSMODULESPATH
|
||
et RUNSHOSTSPATH sont définies.
|
||
-a, --append-output
|
||
Ajouter au fichier OUTPUT au lieu de l'écraser
|
||
}}}</pre>
|
||
</div>
|
||
<div title="rwoinst" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
rwoinst: Déploiement distant avec woinst
|
||
|
||
USAGE
|
||
rwoinst [-H host] [-T tmproot] <file|archive|dir>... [-- options de woinst]
|
||
|
||
OPTIONS
|
||
-C Ne pas faire le déploiement. Configurer uniquement la connexion par clé
|
||
sur les hôtes distants spécifiés pour le user spécifié. Il faut pouvoir
|
||
se connecter par mot de passe pour configurer la connexion par clé.
|
||
Si l'on veut configurer la connexion par clé pour le user root, mais que
|
||
ce n'est pas possible de se connecter par mot de passe avec le user root
|
||
sur l'hôte distant, et qu'il existe un user sudoer sur l'hôte distant,
|
||
il est possible de faire la configuration avec '--configure root'. La
|
||
commande serait alors
|
||
rwoinst -H user@host --configure root
|
||
-T tmproot
|
||
Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple
|
||
/var/tmp. Cette option est utile pour les vservers, qui ont par défaut
|
||
un /tmp minuscule de 16 Mo.
|
||
-S ssh
|
||
Spécifier le programme à utiliser pour la connection par ssh.
|
||
-H host
|
||
Spécifier un hôte distant sur lequel faire le déploiement. Plusieurs
|
||
options -H peuvent être spécifiées, ou alors on peut séparer plusieurs
|
||
hôtes par ':', e.g. -H host1:host2
|
||
Par défaut, la connexion sur l'hôte distant se fait avec l'utilisateur
|
||
root. Il est possible de spécifier un autre utilisateur avec la syntaxe
|
||
user@host, e.g -H user@host
|
||
}}}</pre>
|
||
</div>
|
||
<div title="sqlcsv" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
USAGE:
|
||
sqlcsv [query]
|
||
|
||
query est la requête SQL à exécuter. Si query n'est pas spécifiée ou si elle
|
||
vaut '-', la requête SQL est lue sur l'entrée standard, ou depuis un
|
||
fichier si l'option -f est spécifiée.
|
||
|
||
DEMARRAGE
|
||
|
||
Au démarrage, les répertoires de configuration (utilisateur ~/.sqlcsv et système
|
||
/etc/sqlcsv) sont analysés. Les fichiers *.jar situés dans ces répertoires sont
|
||
ajoutés au CLASSPATH. La présence de certains fichiers est testée pour activer
|
||
éventuellement les logs détaillés.
|
||
|
||
OPTIONS
|
||
-C, --config CONFIG
|
||
Prendre les informations de connexion depuis le fichier de propriété
|
||
spécifié. Pour l'identifiant CONN, la propriété 'CONN.url' doit exister
|
||
dans ce fichier avec la valeur de l'url jdbc de connexion. De plus, les
|
||
propriétés 'CONN.user' et 'CONN.password' contiennent respectivement si
|
||
nécessaire le nom et le mot de passe de connexion. La propriété
|
||
'loglevel', si elle existe, est utilisée pour configurer le niveau
|
||
d'affichage des logs, comme avec l'option --loglevel
|
||
Si cette option n'est pas spécifiée, un fichier nommé sqlcsv.properties
|
||
est recherché dans l'ordre: dans le répertoire courant, dans le
|
||
répertoire de configuration utilisateur, puis dans le répertoire de
|
||
configuration système. Si le fichier est trouvé, il est chargé
|
||
automatiquement.
|
||
-l, --conn CONN
|
||
Spécifier l'identifiant (ou l'url) de connexion. Cette information est
|
||
obligatoire. Si cette option n'est pas fournie, il faut spécifier un
|
||
fichier de configuration avec l'option -C dans lequel *une seule*
|
||
propriété 'CONN.url' est définie.
|
||
-u, --user USER
|
||
-p, --password PASSWORD
|
||
Spécifier un nom de connexion et un mot de passe si l'url ne le fournit
|
||
pas. Ces valeurs ont la priorité sur les valeurs éventuellement déjà
|
||
présentes dans le fichier de propriété.
|
||
-f, --input INPUT
|
||
Lire la requête depuis le fichier INPUT au lieu de la lire depuis la
|
||
ligne de commande ou l'entrée standard. Ne pas spécifier cette option ou
|
||
utiliser '-' pour lire depuis l'entrée standard. Cette option est
|
||
ignorée si la requête est fournie sur la ligne de commande.
|
||
-o, --output OUTPUT
|
||
Ecrire le résultat dans le fichier OUTPUT. Utiliser '-' pour spécifier
|
||
la sortie standard (c'est la valeur par défaut). S'il y a plusieurs
|
||
requêtes et que le fichier de sortie n'est pas la sortie standard,
|
||
ajouter un numéro incrémental au nom du fichier en sortie pour chaque
|
||
requête. Sinon, il est possible de spécifier plusieurs fois cette option
|
||
pour nommer les fichiers correspondant à chaque requête.
|
||
-t, --autocommit
|
||
Activer le mode autocommit
|
||
-c, --ignore-io-error
|
||
Continuer le traitement même en cas d'erreur du système de fichiers.
|
||
Cependant le traitement s'arrête et la transaction est annulée si une
|
||
autre erreur se produit.
|
||
-y, --ignore-any-error
|
||
Continuer le traitement même en cas d'erreur quelconque.
|
||
-n, --no-headers
|
||
Ne JAMAIS inclure les en-têtes dans la sortie, même avec l'option -h
|
||
-a, --append
|
||
Ajouter le résultat au fichier OUTPUT au lieu de l'écraser.
|
||
-A, --auto-na
|
||
Activer les option -n -a si le fichier OUTPUT existe et qu'il est non
|
||
vide. Le test n'est effectué que pour le premier fichier spécifié.
|
||
-s, --same-output
|
||
Utiliser le même fichier pour écrire le résultat de toutes les requêtes.
|
||
Normalement, un numéro incrémental est ajouté au fichier en sortie si
|
||
plusieurs requêtes sont spécifiées. Si les en-têtes sont les mêmes,
|
||
ajouter le résultat au fichier directement à la suite. Sinon, sauter une
|
||
ligne blanche et afficher les nouveaux en-têtes.
|
||
-h, --force-headers
|
||
En cas d'écriture du résultat de plusieurs requêtes dans un même
|
||
fichier, ne pas tenter de concaténer les résultats même si les en-têtes
|
||
sont les mêmes.
|
||
--uc-output
|
||
Ajouter dans la sortie les résultat de toutes les requêtes, pas
|
||
seulement celles de type DQML
|
||
--loglevel LOGLEVEL
|
||
Spécifier le niveau de logs à afficher. Les valeurs valides sont à
|
||
choisir parmi ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, ERROR
|
||
La présence de certains fichiers dans les répertoires de configuration
|
||
utilisateur ou système configure les logs avant que les options de la
|
||
ligne de commande ne soient analysés: un fichier DEBUG fait démarrer
|
||
l'application avec le niveau de log ALL ce qui permet de voir les logs
|
||
concernant le chargement des jar. Un fichier SQL_DEBUG permet d'activer
|
||
la trace de DriverManager. Exemple:
|
||
mkdir -p ~/.sqlcsv && touch ~/.sqlcsv/{DEBUG,SQL_DEBUG}
|
||
}}}</pre>
|
||
</div>
|
||
<div title="twsync" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
twsync: synchroniser un répertoire de wiki avec un tiddlywiki
|
||
|
||
USAGE
|
||
twsync [options]
|
||
|
||
Un répertoire de wiki est un répertoire où chaque page est contenu dans un
|
||
fichier avec l'extension .twp
|
||
Un tiddlywiki est un fichier html contenant le code de TiddlyWiki et les données
|
||
associées.
|
||
|
||
OPTIONS
|
||
-d wikidir
|
||
-f wikifile
|
||
Spécifier le répertoire de wiki et le tiddlywiki à traiter. Par défaut,
|
||
il s'agit de wiki.html dans le répertoire courant.
|
||
-u Importer les pages de wikidir dans le tiddlywiki. Utiliser cette action
|
||
quand les pages de wikidir sont modifiées et qu'il faut mettre à jour le
|
||
tiddlywiki.
|
||
Il s'agit de l'action par défaut
|
||
--force
|
||
Forcer l'importation des pages même si les tiddlers correspondant sont
|
||
plus récents dans le tiddlywiki
|
||
Forcer aussi la regénération de wikifile même si aucune modification n'a
|
||
été détectée
|
||
-e Exporter les tiddlers du tiddlywiki vers wikidir. Utiliser cette action
|
||
quand le tiddlywiki a été modifié, et qu'il faut synchroniser wikidir
|
||
avec les dernières modifications.
|
||
-U Mettre à jour le fichier wikifile avec la dernière version de tiddlywiki
|
||
située dans ~/wop/modules/nutools/lib/tiddlywiki/empty.html
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uawk" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uawk: wrapper pour des outils implémentés en awk
|
||
|
||
USAGE
|
||
uawk TOOL args...
|
||
|
||
Les noms d'outils valides sont: awkrun awkcsv grepcsv awkfsv2csv mergecsv sortcsv dumpcsv printcsv
|
||
Utiliser l'option --help pour obtenir de l'aide sur chacun des outils
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ubackup" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ubackup: faire une sauvegarde des fichiers
|
||
|
||
USAGE
|
||
ubackup [options]
|
||
|
||
OPTIONS
|
||
-l Lister les profils de sauvegarde disponibles.
|
||
-p Spécifier le profil de sauvegarde à effectuer. Par défaut, toutes les
|
||
sauvegardes sont effectuées.
|
||
-u USER
|
||
Faire le sauvegarde pour l'utilisateur $USER. Cette option n'est valide
|
||
que pour l'utilisateur root.
|
||
-n Afficher ce qui doit être fait plutôt que de le faire
|
||
-H Arrêter la machine après une sauvegarde REUSSIE.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ucalc" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ucalc: Afficher une valeur dans plusieurs unités
|
||
|
||
USAGE
|
||
ucalc value
|
||
|
||
Sans suffixe, la valeur est exprimée en octets. Sinon, elle peut être suffixée
|
||
pour spécifier l'unité dans laquelle est exprimée la valeur:
|
||
K,M,G,T -- Kibi (1024), Mibi (1024^2), Gibi (1024^3), Tebi (1024^4)
|
||
k,m,g,t -- Kilo (1000), Mega (1000^2), Giga (1000^3), Tera (1000^4)
|
||
s -- secteurs de 512 octets
|
||
S -- secteurs de 2048 octets
|
||
p -- pages de 4096 octets
|
||
c -- cylindres (si l'option -c est spécifiée)
|
||
b -- octets
|
||
|
||
OPTIONS
|
||
-u UNIT
|
||
Spécifier l'unité de value. Le suffixe qui est éventuellement sur value
|
||
est ignoré.
|
||
-o UNIT
|
||
Spécifier l'unité en sortie. Par défaut, afficher la valeur dans toutes
|
||
les unités supportées.
|
||
-c VALUE
|
||
Taille d'un cylindre en octets, pour permettre l'affichage des valeurs
|
||
en cylindres
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uconf" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uconf: Activer ou désactiver un paramètre dans un fichier de configuration
|
||
|
||
USAGE
|
||
uconf [options] config name[=value]...
|
||
|
||
OPTIONS
|
||
-e
|
||
Activer le paramètre (par défaut). Si le paramètre existe, mais est
|
||
commenté, il est décommenté. Si une valeur est spécifiée pour le
|
||
paramètre, le paramètre est modifié dans le fichier en conséquence.
|
||
-q
|
||
Cette option s'utilise avec l'option -e et le type shell. Elle permet
|
||
de s'assurer que les valeurs ayant des espaces et/ou des caractères
|
||
spéciaux sont quotées
|
||
-d
|
||
Désactiver le paramètre. Le paramètre est commenté s'il existe dans le
|
||
fichier
|
||
-a
|
||
Ajouter une valeur à la variable, ou un paramètre avec cette valeur
|
||
(suivant le type de fichier de configuration)
|
||
-A
|
||
Ajouter une valeur au tableau, ou un paramètre avec cette valeur
|
||
(suivant le type de fichier de configuration)
|
||
-t TYPE
|
||
Type de fichier de configuration. TYPE peut être sh (par défaut), apache
|
||
ou mysql.
|
||
shell
|
||
les paramètres sont de la forme 'name=value', et les commentaires
|
||
débutent par '#'. Ce type peut être utilisé pour tous les fichiers
|
||
ayant ces caractéristiques, dont les fichiers de script shell
|
||
apache
|
||
les paramètres sont de la forme 'name value', et les commentaires
|
||
débutent par '#'. Ce type peut être utilisé pour tous les fichiers
|
||
ayant ces caractéristiques, dont les fichiers de configuration
|
||
apache
|
||
mysql, php
|
||
les paramètres sont dans des sections nommées de la forme [section],
|
||
sont de la forme 'name=value', et les commentaires débutent par '#'
|
||
ou ';'
|
||
Ce type peut être utilisé pour tous les fichiers ayant ces
|
||
caractéristiques, dont les fichiers de configuration de mysql et de
|
||
php. Avec ce type, la section est obligatoire.
|
||
-s SECTION
|
||
Avec le type mysql, préciser la section dans laquelle inscrire le
|
||
paramètre. Attention! La section DOIT exister, elle n'est pas créée
|
||
automatiquement.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ucrontab" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ucrontab: Ajouter/Supprimer une ligne dans crontab
|
||
|
||
USAGE
|
||
ucrontab [options] ctline
|
||
|
||
OPTIONS
|
||
-a Ajouter la ligne dans le fichier crontab (par défaut)
|
||
-r Enlever la ligne dans le fichier crontab
|
||
-u user
|
||
Spécifier l'utilisateur pour lequel on modifie crontab. Par défaut,
|
||
modifier le crontab de root
|
||
-H host:hosts...
|
||
Modifier le crontab sur les hôtes distants spécifiés. Avec l'hôte '.' ou
|
||
'localhost', la modification est faite sur l'hôte local
|
||
Si l'action est -a, un script 'undo-ucrontab.sh' est créé dans le
|
||
répertoire courant, qui annule la planification. Il est possible de
|
||
lancer ce script le lendemain pour enlever les planifications
|
||
installées.
|
||
ctline
|
||
Ligne de crontab de la forme 'minutes hours days months dows command'
|
||
Si la ligne est de la forme halt[@hh:mm], la commande 'shutdown -h now'
|
||
est planifiée pour le LENDEMAIN à hh:mm. si hh:mm n'est pas spécifié,
|
||
l'arrêt est planifié pour 7:00
|
||
-t hh:mm
|
||
Ignorer la partie 'minutes hours days months dows' de ctline, et la
|
||
remplacer par une planification à hh:mm le LENDEMAIN.
|
||
--dom dayOfMonth
|
||
--month month
|
||
Spécifier respectivement le jour du mois et le mois (1-12) auquel faire
|
||
la planification. Par défaut, les planifications sont effectuées pour le
|
||
LENDEMAIN. Il est conseillé de spécifier les deux arguments si le jour
|
||
doit être fixé.
|
||
-s cmdfile
|
||
Spécifier un fichier, dont le contenu est utilisé pour générer le script
|
||
qui est planifié. Le fichier doit contenir l'ensemble des commandes à
|
||
exécuter. Le script est modifié pour s'autodétruire à la fin de son
|
||
exécution. Si ce comportement n'est pas souhaité, il faut rajouter la
|
||
commande 'exit 0' à la fin.
|
||
-S cmd
|
||
Comme -s, mais spécifier le contenu du fichier directement sur la ligne
|
||
de commande.
|
||
-f hostsfile
|
||
Spécifier un fichier qui contient la liste des hôtes sur lesquels faire
|
||
les planifications.
|
||
Les options -s, -S, -H, -d, -n sont ignorées. L'option --add est valide
|
||
jusqu'au premier @group du fichier. Voici le format de ce fichier:
|
||
|
||
Un groupe d'hôte débute par une ligne de la forme '@group:adelay:gdelay'
|
||
- adelay est le nombre de minutes à laisser passer entre les hôtes du
|
||
groupe (par défaut 1)
|
||
- gdelay est le nombre de minutes à laisser passer après le traitement
|
||
du groupe (par défaut 15)
|
||
Les autres lignes sont des hôtes sur lequels planifier l'opération, de
|
||
la forme 'host:cmd'
|
||
- host est un nom d'hôte pleinement qualifié, sur lequel il est possible
|
||
de se connecter par clé.
|
||
- cmd est une description de la commande à lancer pour effectuer
|
||
l'opération planifiée. Utiliser la syntaxe '<script' pour prendre le
|
||
contenu du fichier de script spécifié. Le script est copié dans un
|
||
fichier temporaire sur l'hôte, et se supprime après son
|
||
lancement. Sinon, la commande spécifiée est utilisée telle quelle. Si
|
||
cmd n'est pas spécifié, prendre la commande par défaut donnée par
|
||
ctline
|
||
Les lignes vides et commençant par '#' sont ignorées
|
||
La commande '@include:file' permet d'inclure un autre fichier
|
||
|
||
-d Activer l'incrémentation automatique des heures de planification entre
|
||
chaque hôte. Ceci permet par exemple de planifier l'arrêt d'un certain
|
||
nombre de machines dans un ordre précis, en horaire décalé.
|
||
Cette option est activée par défaut si ctline==halt[@time]
|
||
-n Désactiver l'incrémentation automatique des heures de planification.
|
||
--add ADELAY
|
||
Spécifier le nombre de minutes entre chaque hôte pour l'incrémentation
|
||
automatique des heures de planification. Par défaut, il y a 1 minute
|
||
entre chaque hôte.
|
||
--us undo-script
|
||
Spécifier le nom du script qui annule la planification. Utiliser ""
|
||
pour désactiver cette fonctionnalité.
|
||
--fake
|
||
Afficher simplement les modifications qui doivent être effectuées.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="udaemon.cgo" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
udaemon.cgo: start a program as a daemon
|
||
|
||
USAGE
|
||
udaemon.cgo /path/to/prog [args...]
|
||
|
||
OPTIONS
|
||
-d DESTDIR
|
||
Change to DESTDIR instead of "/" before starting the program
|
||
}}}</pre>
|
||
</div>
|
||
<div title="udir" creator="jclain" modifier="jclain" created="201605110329" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
udir: gérer les variables de répertoire
|
||
|
||
USAGE
|
||
udir [options] [dir [name=value...]]
|
||
|
||
Par défaut, mettre à jour les variables du répertoire avec les définitions
|
||
données. Attention! Les définitions sont insérées *telles quelles* dans le
|
||
fichier. Par exemple, pour définir une variable qui contient des espaces,
|
||
on pourra faire:
|
||
udir /path/to/dir 'var="value with spaces"'
|
||
pour définir un tableau:
|
||
udir /path/to/dir 'array=(first second)'
|
||
|
||
OPTIONS
|
||
-i, --show-desc
|
||
-n, --show-note
|
||
Afficher la description du répertoire. C'est l'action par défaut si ce
|
||
script est lancé *sans argument*
|
||
-d, --dump
|
||
Afficher toutes les variables définies pour le répertoire 'dir'.
|
||
-x, --eval 'CMDS;...'
|
||
Exécuter les commandes dans le contexte des variables définies pour le
|
||
répertoire.
|
||
-e, --edit
|
||
Editer les variables du répertoire
|
||
--local-vars
|
||
Avec -d, ajouter des directives 'local' aux définitions de variables
|
||
-A, --all-parents
|
||
Avec -d et -x, considérer les variables de tous les répertoires parents
|
||
jusqu'à la racine. Pour ne considérer que les variables du répertoire
|
||
spécifié (par défaut), utiliser --local-only
|
||
--help-vars
|
||
Afficher une descriptions des variables spécifiques aux outils de nutools
|
||
}}}</pre>
|
||
</div>
|
||
<div title="udist" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
udist: gestion d'une distribution upstream
|
||
|
||
Des fichiers de configuration (par exemple) sont distribués par un partenaire,
|
||
et il faut maintenir des modifications locales, tout en acceptant les mises à
|
||
jour provenant de l'upstream. Ce script aide à maintenir un tel scénario.
|
||
|
||
En général, la distribution upstream identifie les fichiers modifiables en leur
|
||
donnant une extension particulière, par exemple 'file.origine' ou 'file.default'
|
||
La liste des extensions reconnues est spécifiée avec l'option -s. Lors de leur
|
||
intégration dans le répertoire local, ces fichiers sont copiés sans cette
|
||
extension.
|
||
|
||
Terminologie: Les fichiers pour lesquels il faut maintenir une version locale
|
||
sont appelés 'fichiers locaux', qu'ils viennent de la distribution upstream ou
|
||
non. Les autres fichiers qui proviennent de la distribution sont appelés
|
||
'fichiers upstream'.
|
||
|
||
USAGE
|
||
udist cmd [options]
|
||
|
||
OPTIONS COMMUNES
|
||
-s .EXT
|
||
Ajouter une extension à la liste des extensions reconnues comme contenu
|
||
original modifiable dans la distribution upstream. Par défaut, les
|
||
extensions suivantes sont reconnues:
|
||
.udist .origine .default
|
||
Cette option peut être utilisée autant de fois que nécessaire.
|
||
--clear-origexts
|
||
Supprimer la liste par défaut des extensions origines. Cette option doit
|
||
être spécifiée avant l'option -s pour construire une nouvelle liste.
|
||
La liste des extensions ne doit pas être vide. Si c'est le cas, elle est
|
||
modifiée pour contenir l'unique élément (.udist)
|
||
-d WORKDIR
|
||
Spécifier le répertoire de travail. Par défaut, la racine du répertoire
|
||
de travail est cherchée à partir du répertoire courant.
|
||
--help
|
||
Afficher l'aide détaillée de la commande spécifiée
|
||
|
||
COMMANDES
|
||
init [WORKDIR [ARCHIVE]]
|
||
Initialiser un répertoire de travail pour contenir une distribution
|
||
upstream
|
||
|
||
upstream-new, new SRCDIR|ARCHIVE [WORKDIR]
|
||
Intégrer une nouvelle distribution upstream.
|
||
Les nouveaux fichiers sont copiés tout de suite dans le répertoire de
|
||
travail. Par contre, les modifications ne sont intégrées qu'avec la
|
||
commande patch
|
||
upstream-clear, clear [WORKDIR]
|
||
Supprimer tous les fichiers non modifiés de l'upstream.
|
||
|
||
local-create, create FILE
|
||
Créer et/ou identifier FILE comme une modification locale par rapport à
|
||
l'upstream.
|
||
local-edit, edit FILE
|
||
S'assurer que local-create a été exécuté si nécessaire pour FILE, puis
|
||
l'éditer avec vim
|
||
|
||
local-copy, cp SRCFILE DESTFILE
|
||
local-move, mv SRCFILE DESTFILE
|
||
local-remove, rm FILE
|
||
Frontend pour respectivement cp, mv et rm. Ces commandes agissent aussi
|
||
sur les fichiers orig et de tag.
|
||
|
||
local-tag, tag FILE TAG
|
||
Faire une copie du fichier local avec le tag spécifié. Si le fichier de
|
||
tag existe déjà, il est écrasé.
|
||
local-switch, switch TAG FILE
|
||
Sélectionner la copie avec le tag spécifié.
|
||
|
||
local-put, put [WORKDIR] DESTDIR
|
||
Copier tous les fichiers locaux dans DESTDIR, par exemple pour faire une
|
||
sauvegarde. Si DESTDIR n'est pas spécifié, prendre la valeur de
|
||
l'origine, affichée par local-list
|
||
local-get, get [-l|-s] SRCDIR [WORKDIR]
|
||
Opération inverse de local-put: intégrer tous les fichiers de SRCDIR
|
||
comme fichiers locaux. Si SRCDIR n'est pas spécifié, prendre la valeur
|
||
de l'origine, affichée par local-list
|
||
local-list, list [WORKDIR]
|
||
Lister tous les fichiers locaux. Les fichiers pour lesquels il faut
|
||
intégrer une modification de l'upstream avec la commande local-patch
|
||
sont identifiés visuellement.
|
||
|
||
upstream-diff, udiff [FILE]
|
||
Après intégration d'une nouvelle distribution upstream, afficher les
|
||
modifications entre la nouvelle distribution upstream et l'ancienne pour
|
||
tous les fichiers modifiables
|
||
local-diff, ldiff [FILE]
|
||
Afficher les modifications locales par rapport à l'upstream pour le(s)
|
||
fichier(s) spécifié(s).
|
||
local-patch, lpatch [FILE]
|
||
Après intégration d'une nouvelle distribution upstream, appliquer au(x)
|
||
le(s) fichier(s) spécifié(s) les modifications disponibles affichées par
|
||
upstream-diff.
|
||
local-forget, lforget [FILE]
|
||
Après intégration d'une nouvelle distribution upstream, oublier les
|
||
modifications disponibles pour le(s) fichier(s) spécifié(s).
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uenv" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uenv: Mettre à jour la configuration de l'environnement
|
||
|
||
USAGE
|
||
uenv [-u [projdirs...]]
|
||
|
||
Cette commande met à jour l'ordre de chargement des fichiers de configuration
|
||
dans ~/etc/{profile.d,bashrc.d}. Elle est donc utile si ces fichiers ont été
|
||
modifiés manuellement, ou si un fichier a été ajouté manuellement.
|
||
|
||
OPTIONS
|
||
HOME=/path/to/homedir
|
||
Spécifier le chemin vers ~
|
||
Cette option doit être placée avant les valeurs projdirs.
|
||
-u, --update
|
||
Installer ou mettre à jour les fichiers de profil des projets spécifiés:
|
||
Les fichiers ~/.profile, ~/.bash_profile et ~/.bashrc sont vérifiés et
|
||
corriger automatiquement pour inclure les fichiers de nutools.
|
||
Ensuite, les fichiers de profil sont copié dans les répertoires
|
||
~/etc/{profile.d,bashrc.d,default}
|
||
Les projets spécifiés *doivent* être configurés avec uinst -C, et
|
||
définir la valeur install_profiles=true dans leur fichier .udir
|
||
Si aucun projet n'est spécifié, prendre les fichiers de profil de
|
||
nutools.
|
||
-l, --local-profiles
|
||
Avec l'option -u, installer les profils locaux comme tels. Pour les
|
||
fichiers de profil qui sont indiqués comme non partagés, les copier dans
|
||
des répertoires spécifiques de la forme {profile,bashrc}.HOSTNAME.d et
|
||
default.HOSTNAME
|
||
-s, --shared-profiles
|
||
Installer les profils locaux comme des profils partagés. C'est l'option
|
||
par défaut.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ufixmod" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ufixmod: forcer le mode d'une liste de fichiers
|
||
|
||
USAGE
|
||
ufixmod [options] [dirs|files....]
|
||
|
||
Le mode forcé pour les répertoires est rwxr-xr-x
|
||
Le mode forcé pour les fichiers est rw-r--r--
|
||
|
||
OPTIONS
|
||
-x, --executable
|
||
Forcer le mode rwX-r-Xr-X pour les fichiers
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ugenpass" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ugenpass: générer un mot de passe au hasard
|
||
|
||
USAGE
|
||
ugenpass [options]
|
||
|
||
OPTIONS
|
||
-l, --len LEN
|
||
Spécifier le nombre de caractères du mot de passe généré
|
||
-U, --upper COUNT
|
||
-L, --lower COUNT
|
||
-A, --alpha COUNT
|
||
-N, --number COUNT
|
||
-S, --symbol COUNT
|
||
-B, --special COUNT
|
||
Spécifier le nombre minimum de chaque classe de caractère
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uinc.sh" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uinc.py: Plier/déplier des inclusions dans un fichier
|
||
|
||
USAGE
|
||
uinc.py [[options] dest...]
|
||
|
||
OPTIONS
|
||
-f Plier les inclusions
|
||
-u Déplier les inclusions (par défaut)
|
||
-@ Forcer le caractère '@' pour le pliage/dépliage
|
||
-* Forcer le caractère '*' pour le pliage/dépliage
|
||
--auto
|
||
Activer la recherche automatique de paramètres (par défaut)
|
||
--noauto
|
||
Désactiver la recherche automatique de paramètres
|
||
-I SPEC
|
||
Spécifier des fichiers à inclure dans les répertoires spécifiés
|
||
-X SPEC
|
||
Spécifier des fichiers à exclure dans les répertoires spécifiés
|
||
--refdir REFDIR
|
||
Spécifier le répertoire de référence. Soit un répertoire DEST spécifié
|
||
dans les arguments. Si un fichier à inclure *n'est pas* un fils du
|
||
répertoire DEST, l'emplacement effectif du fichier est calculé en
|
||
faisant comme si DEST==REFDIR.
|
||
Par exemple, soit DEST=/dest/path et REFDIR=/refdir/path. Si le fichier
|
||
/dest/path/file inclue le fichier ../inc, alors c'est le fichier
|
||
/refdir/inc qui est considéré.
|
||
Ceci permet de traiter les inclusions dans une copie temporaire d'un
|
||
répertoire, dans le cas où les fichier font référence à d'autres
|
||
fichiers situés relativement à l'emplacement original.
|
||
|
||
Les spécifications de fichiers sont de types glob: ils peuvent contenir les
|
||
wildcards * et ?. Ils supportent en plus la chaine '**' qui signifie n'importe
|
||
quelle profondeur de répertoire. 'dir/' est équivalent à 'dir/**' et signifie
|
||
tous les fichiers situés dans l'arborescence à partir de dir.
|
||
|
||
La variable UINCPATH contient une liste de répertoires qui sont consultés pour
|
||
trouver les fichiers à inclure.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uinc" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uinc.py: Plier/déplier des inclusions dans un fichier
|
||
|
||
USAGE
|
||
uinc.py [[options] dest...]
|
||
|
||
OPTIONS
|
||
-f Plier les inclusions
|
||
-u Déplier les inclusions (par défaut)
|
||
-@ Forcer le caractère '@' pour le pliage/dépliage
|
||
-* Forcer le caractère '*' pour le pliage/dépliage
|
||
--auto
|
||
Activer la recherche automatique de paramètres (par défaut)
|
||
--noauto
|
||
Désactiver la recherche automatique de paramètres
|
||
-I SPEC
|
||
Spécifier des fichiers à inclure dans les répertoires spécifiés
|
||
-X SPEC
|
||
Spécifier des fichiers à exclure dans les répertoires spécifiés
|
||
--refdir REFDIR
|
||
Spécifier le répertoire de référence. Soit un répertoire DEST spécifié
|
||
dans les arguments. Si un fichier à inclure *n'est pas* un fils du
|
||
répertoire DEST, l'emplacement effectif du fichier est calculé en
|
||
faisant comme si DEST==REFDIR.
|
||
Par exemple, soit DEST=/dest/path et REFDIR=/refdir/path. Si le fichier
|
||
/dest/path/file inclue le fichier ../inc, alors c'est le fichier
|
||
/refdir/inc qui est considéré.
|
||
Ceci permet de traiter les inclusions dans une copie temporaire d'un
|
||
répertoire, dans le cas où les fichier font référence à d'autres
|
||
fichiers situés relativement à l'emplacement original.
|
||
|
||
Les spécifications de fichiers sont de types glob: ils peuvent contenir les
|
||
wildcards * et ?. Ils supportent en plus la chaine '**' qui signifie n'importe
|
||
quelle profondeur de répertoire. 'dir/' est équivalent à 'dir/**' et signifie
|
||
tous les fichiers situés dans l'arborescence à partir de dir.
|
||
|
||
La variable UINCPATH contient une liste de répertoires qui sont consultés pour
|
||
trouver les fichiers à inclure.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uinst.sh" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uinst.sh: Déployer en local un fichier, une archive, ou un répertoire
|
||
|
||
USAGE
|
||
uinst.sh [options] <file|archive|dir>
|
||
|
||
OPTIONS
|
||
var=value
|
||
Spécifier la valeur d'une variable ou d'un préfixe, plutôt que de
|
||
laisser uprefix l'autodétecter. Utiliser 'uprefix -l' pour avoir une
|
||
liste de préfixes valides. Utiliser 'udir --help-vars' pour avoir une
|
||
liste de variables valides pour uinst.sh.
|
||
-d /path/to/destdir
|
||
Spécifier le répertoire destination, exactement comme si la valeur
|
||
destdir avait été spécifiée, i.e destdir="/path/to/destdir"
|
||
-h, --host [user@]host
|
||
Avec la méthode de déploiement uinst:rsync, permettre de spécifier un
|
||
hôte différent. Cette option est ignorée pour les autres méthodes de
|
||
déploiement. Si host vaut localhost, un déploiement local avec ssh est
|
||
effectué. Si host vaut '.', un déploiement local *sans passer par ssh*
|
||
est effectué, comme si seul le chemin avait été spécifié.
|
||
Cette option initialise la valeur destdir_override_userhost
|
||
-S, --ssh ssh
|
||
Avec la méthode de déploiement uinst:rsync, spécifier le programme à
|
||
utiliser pour la connection par ssh. Cette option initialise la valeur
|
||
destdir_ssh
|
||
--force-remote
|
||
Avec la méthode de déploiement uinst:rsync, si un hôte est spécifié dans
|
||
la valeur de destdir, forcer le déploiement distant avec ssh+rsync, même
|
||
si l'hôte et l'utilisateur correspondent aux valeurs courantes. Cette
|
||
option initialise la valeur destdir_force_remote
|
||
-a, --auto
|
||
Si la source n'est pas spécifiée, déterminer le répertoire à déployer
|
||
automatiquement (c'est la valeur par défaut)
|
||
--no-auto
|
||
Ne pas déterminer automatiquement le répertoire à déployer.
|
||
--prefix
|
||
Corriger les chemins srcdir et destdir qui commencent par des préfixes
|
||
valides (c'est la valeur par défaut). Utiliser 'uprefix -l' pour avoir
|
||
une liste de préfixes valides
|
||
--no-prefix
|
||
Ne jamais corriger un chemin.
|
||
--include-vcs
|
||
Inclure les fichiers de VCS dans les fichiers copiés. Par défaut, les
|
||
fichiers de VCS sont exclus.
|
||
-l, --local-profiles
|
||
Installer les profils locaux comme tels
|
||
--shared-profiles
|
||
Installer les profils locaux comme des profils partagés. C'est la valeur
|
||
par défaut pour compatibilité.
|
||
-C Configurer un répertoire pour le déploiement avec uinst
|
||
Ajouter l'option --force pour forcer la reconfiguration
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uinst" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uinst: Déployer en local un fichier, une archive, ou un répertoire
|
||
|
||
USAGE
|
||
uinst [options] <file|archive|dir>
|
||
|
||
OPTIONS
|
||
var=value
|
||
Spécifier la valeur d'une variable ou d'un préfixe, plutôt que de
|
||
laisser uprefix l'autodétecter. Utiliser 'uprefix -l' pour avoir une
|
||
liste de préfixes valides. Utiliser 'udir --help-vars' pour avoir une
|
||
liste de variables valides pour uinst.
|
||
-d /path/to/destdir
|
||
Spécifier le répertoire destination, exactement comme si la valeur
|
||
destdir avait été spécifiée, i.e destdir="/path/to/destdir"
|
||
-h, --host [user@]host
|
||
Avec la méthode de déploiement uinst:rsync, permettre de spécifier un
|
||
hôte différent. Cette option est ignorée pour les autres méthodes de
|
||
déploiement. Si host vaut localhost, un déploiement local avec ssh est
|
||
effectué. Si host vaut '.', un déploiement local *sans passer par ssh*
|
||
est effectué, comme si seul le chemin avait été spécifié.
|
||
Cette option initialise la valeur destdir_override_userhost
|
||
-S, --ssh ssh
|
||
Avec la méthode de déploiement uinst:rsync, spécifier le programme à
|
||
utiliser pour la connection par ssh. Cette option initialise la valeur
|
||
destdir_ssh
|
||
--force-remote
|
||
Avec la méthode de déploiement uinst:rsync, si un hôte est spécifié dans
|
||
la valeur de destdir, forcer le déploiement distant avec ssh+rsync, même
|
||
si l'hôte et l'utilisateur correspondent aux valeurs courantes. Cette
|
||
option initialise la valeur destdir_force_remote
|
||
-a, --auto
|
||
Si la source n'est pas spécifiée, déterminer le répertoire à déployer
|
||
automatiquement (c'est la valeur par défaut)
|
||
--no-auto
|
||
Ne pas déterminer automatiquement le répertoire à déployer.
|
||
--prefix
|
||
Corriger les chemins srcdir et destdir qui commencent par des préfixes
|
||
valides (c'est la valeur par défaut). Utiliser 'uprefix -l' pour avoir
|
||
une liste de préfixes valides
|
||
--no-prefix
|
||
Ne jamais corriger un chemin.
|
||
--include-vcs
|
||
Inclure les fichiers de VCS dans les fichiers copiés. Par défaut, les
|
||
fichiers de VCS sont exclus.
|
||
-l, --local-profiles
|
||
Installer les profils locaux comme tels
|
||
--shared-profiles
|
||
Installer les profils locaux comme des profils partagés. C'est la valeur
|
||
par défaut pour compatibilité.
|
||
-C Configurer un répertoire pour le déploiement avec uinst
|
||
Ajouter l'option --force pour forcer la reconfiguration
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ujava" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ujava: Lancer un script après avoir sélectionné une version de java
|
||
|
||
USAGE
|
||
ujava [options] version [args...]
|
||
|
||
OPTIONS
|
||
-b, --bits 32|64|auto
|
||
--32
|
||
--64
|
||
Sélectionner une version 32 ou 64 bits de java
|
||
-e, --exact
|
||
Sélectionner la version *exacte* de java demandée, au lieu de la version
|
||
minimum correspondant à la version demandée.
|
||
Si la version requise de java n'est pas trouvée, retourner avec le code
|
||
d'erreur 254.
|
||
|
||
La version de java attendue peut-être exprimée de l'une des façons suivantes:
|
||
1.4 1.4+ 1.5 1.5+ 1.6 1.6+ 1.7 1.7+
|
||
Si args n'est pas spécifié, un shell est lancé dans lequel les variables
|
||
JAVA_HOME, JAVA, JAVAC et PATH sont mis à jour.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uldap" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uldap: Shell pour accéder à un serveur ldap
|
||
|
||
USAGE
|
||
uldap [options]
|
||
|
||
OPTIONS
|
||
-C profile
|
||
Sélectionner un profil de connexion. Par défaut, si l'option -H n'est
|
||
pas spécifiée, le premier profil est sélectionné.
|
||
-x Ne pas tenter de faire une connexion sur le profil par défaut si aucun
|
||
profil n'est sélectionné.
|
||
-f script
|
||
Lire les commandes depuis le script spécifié.
|
||
-n Avec un script donné en ligne de commande ou lu depuis un fichier, ne pas
|
||
ajouter automatiquement la commande print à la fin
|
||
-i Si un script est spécifié, passer en mode interactif après l'exécution
|
||
du script.
|
||
-e Forcer l'arrêt du script si une erreur se produit. C'est l'option par
|
||
défaut pour un script spécifié avec -f.
|
||
-l input.ldif
|
||
Charger le fichier input.ldif comme espace de travail initial
|
||
-H ldapuri
|
||
-D binddn
|
||
-w password
|
||
-b searchbase
|
||
-v var=value
|
||
|
||
COMMANDES
|
||
$ cmd
|
||
Passer directement une commande au shell.
|
||
set [options] [var=value...]
|
||
Changer des options ou des variables. set sans argument affiche la liste
|
||
des variables définies.
|
||
[set] plain
|
||
Passer en mode 'plain': indiquer que l'espace de travail contient des
|
||
données brutes. Les pré-traitements et post-traitements (uncut_on_load,
|
||
decode_on_load, encode_on_save, cut_on_save) ne sont pas appliqués sur
|
||
cet espace de travail
|
||
[set] ldif
|
||
Passer en mode 'ldif': indiquer que l'espace de travail contient des
|
||
données ldif. Les pré-traitements et post-traitements sont appliqués
|
||
normalement sur cet espace de travail
|
||
[set] append
|
||
Pour certaines opérations, spécifier si le résultat de la *prochaine*
|
||
opération remplace le contenu de l'espace de travail courant (par
|
||
défaut), ou si le résultat est ajouté à la fin.
|
||
last
|
||
Afficher en mode édition la dernière commande. Cette commande n'est
|
||
fonctionnelle qu'avec une version de bash >=4.x
|
||
profile name
|
||
Choisir le profil 'name'. Equivalent à 'set profile=name'. Sans
|
||
argument, afficher la liste des profils valides.
|
||
auth anonymous|binddn [password]
|
||
Spécifier le compte à utiliser pour se connecter. Equivalent à
|
||
'set binddn=binddn; set password=password'
|
||
clear [-k]
|
||
Vider l'espace de travail et passer en mode 'plain'.
|
||
Avec l'option -k, supprimer aussi tout l'historique d'annulation.
|
||
load [-k] input
|
||
Charger un fichier dans l'espace de travail. Si l'extension du fichier
|
||
est .ldif, passer en mode 'ldif'
|
||
En mode append, rajouter le contenu du fichier à l'espace de travail,
|
||
puis repasser en mode replace.
|
||
Le code de retour est 0 si le fichier a été chargé, 1 sinon.
|
||
save [-a] output
|
||
Sauvegarder l'espace de travail dans un fichier.
|
||
Avec l'option -a, rajouter au fichier au lieu de l'écraser
|
||
print
|
||
Afficher l'espace de travail
|
||
alias a=rdn...
|
||
Définir un alias pour la commande cd. 'a' est l'alias, 'rdn' est le dn
|
||
correspondant, exprimé par rapport à $suffix. Sans argument, afficher
|
||
la liste des aliases définis.
|
||
cd rdn
|
||
Changer searchbase. Par défaut, il s'agit d'un rdn relatif à $searchbase
|
||
- Certains aliases sont supportés: .. pour l'objet parent, ~ pour
|
||
$suffix, / pour la racine. 'cd' sans argument équivaut à 'cd ~'
|
||
- Si le dn commence par '~/', il s'agit d'un rdn relatif à $suffix.
|
||
- Si le dn commence par /, searchbase reçoit la valeur rdn sans
|
||
modifications (sauf bien sûr enlever le '/' de tête si nécessaire). Il
|
||
faut alors que ce soit un dn absolu.
|
||
ls [-b searchbase] [filter [attrs...]]
|
||
search [-b searchbase] [filter [attrs...]]
|
||
Utiliser ldapsearch pour faire la recherche, et copier le résultat dans
|
||
l'espace de travail. 'ls' est équivalent à 'search -s one'. Si ce n'est
|
||
pas déjà le cas, passer en mode 'ldif'.
|
||
L'option -b prend une valeur avec la même syntaxe que la commande cd,
|
||
sauf que les alias ne sont pas supportés. En particulier, la valeur est
|
||
relative au $searchbase courant. Pour faire une recherche par rapport à
|
||
$suffix, il faut utiliser la syntaxe ~/searchbase.
|
||
En mode append, rajouter le résultat de la recherche à l'espace de
|
||
travail, puis repasser en mode replace.
|
||
Le code de retour est 1 si aucun enregistrement n'a été trouvé, sinon
|
||
le code de retour est celui de la commande ldapsearch.
|
||
cut Couper les lignes trop longues. Cette action est en principe effectuée
|
||
automatiquement lors de la sauvegarde. Il n'est pas conseillé
|
||
d'appliquer des méthodes de transformation après avoir utilisé cette
|
||
action.
|
||
uncut
|
||
Fusionner les lignes coupées. Cette action est en principe effectuée
|
||
automatiquement lors du chargement ou après la recherche.
|
||
encode [attrs...]
|
||
Encoder en base64 les valeurs des attributs mentionnés.
|
||
decode [attrs...]
|
||
Décoder les valeurs des attributs mentionnés si nécessaire (c'est à dire
|
||
s'ils sont encodés en base64)
|
||
keepattr attrs...
|
||
Garder uniquement les lignes des attributs mentionnés. Ensuite,
|
||
supprimer les objets ayant uniquement la ligne dn: (en d'autres termes,
|
||
keepattr sans argument supprime *tout* l'espace de travail)
|
||
keepval attr patterns...
|
||
Pour l'attribut attr, garder uniquement les lignes pour lesquelles les
|
||
valeurs correspondent aux expressions régulières. Les autres attributs
|
||
ne sont pas modifiés. Ensuite, supprimer les objets ayant uniquement la
|
||
ligne dn:
|
||
exclude attrs...
|
||
Supprimer les lignes des attributs mentionnés. Ensuite, supprimer les
|
||
objets ayant uniquement la ligne dn:
|
||
excludeval attr patterns...
|
||
Pour l'attribut attr, supprimer les lignes pour lesquelles les
|
||
valeurs correspondent aux expressions régulières. Les autres attributs
|
||
ne sont pas modifiés. Ensuite, supprimer les objets ayant uniquement la
|
||
ligne dn:
|
||
keepvalentry attr patterns...
|
||
Pour l'attribut attr, vérifier si *au moins une* valeur correspond à
|
||
l'une des expressions régulières. Si c'est le cas, garder l'entrée
|
||
entière, sinon supprimer l'entrée.
|
||
excludevalentry attr patterns...
|
||
Pour l'attribut attr, vérifier si *aucune* des valeurs ne correspond à
|
||
l'une des expressions régulières. Si c'est le cas, garder l'entrée
|
||
entière, sinon supprimer l'entrée.
|
||
setval attr values...
|
||
Remplacer toutes les valeurs de l'attribut attr par les valeurs
|
||
spécifiées.
|
||
addval attr values...
|
||
Ajouter un nouvel attribut avec les valeurs spécifiées. Si l'attribut
|
||
existe déjà, les nouvelles valeurs sont ajoutées à la fin.
|
||
sed args
|
||
Modifier l'espace de travail avec le résultat de la commande sed.
|
||
note: aucun argument n'est filtré, mais il ne faut pas utiliser les
|
||
options de sed qui provoquent la modification en place du fichier,
|
||
comme par exemple l'option -i
|
||
awk args
|
||
Modifier l'espace de travail avec le résultat de la commande awk.
|
||
grep args
|
||
Modifier l'espace de travail avec le résultat de la commande grep.
|
||
format [options] attrs...
|
||
Formater l'espace de travail en données tabulaires, et passer en mode
|
||
'plain'.
|
||
--show-headers
|
||
Afficher les en-têtes
|
||
-F FSEP
|
||
Spécifier le séparateur pour les attributs. Par défaut, il s'agit du
|
||
caractère de tabulation.
|
||
-R VSEP
|
||
Spécifier le séparateur pour les valeurs des attributs. Par défaut, il
|
||
s'agit du point-virgule ';'
|
||
-e Retourner les valeurs comme des variables shell. Les options -F et -R
|
||
sont ignorées. Les attributs multivalués sont écrits sous forme de
|
||
tableaux. Par exemple:
|
||
attributes=('mail' 'givenName')
|
||
index=0
|
||
mail='user@domain.fr'
|
||
givenName=('peter' 'gabriel')
|
||
--bc
|
||
Dans le mode -e, spécifier une commande à insérer avant le premier
|
||
enregistrement. Quand cette commande est lancée, index==-1
|
||
-c Dans le mode -e, spécifier une commande à insérer après chaque
|
||
enregistrement
|
||
--ec
|
||
Dans le mode -e, spécifier une commande à insérer après le dernier
|
||
enregistrement
|
||
sort [args]
|
||
Modifier l'espace de travail avec le résultat de la commande sort.
|
||
edit
|
||
Lancer un éditeur pour modifier l'espace de travail.
|
||
diff [options]
|
||
Afficher les différences entre l'espace de travail et la version
|
||
précédente
|
||
ifok cmd
|
||
iferror cmd
|
||
Si le dernier code de retour est 0 (resp. !=0), lancer la commande cmd
|
||
skip n
|
||
Sauter les n prochaines commandes. A utiliser avec ifok et iferror
|
||
undo
|
||
Annuler la dernière modification effectuée sur l'espace de travail
|
||
|
||
Les directives suivantes prennent le contenu de l'espace de travail, et le
|
||
transforment en une suite de commandes de modifications pour ldapmodify:
|
||
|
||
A Créer un objet de toutes pièces avec les attributs donnés et leurs
|
||
valeurs.
|
||
a Ajouter les valeurs spécifiée à l'attribut
|
||
r Remplacer les valeurs de l'attribut par celles spécifiées
|
||
d Supprimer les valeurs spécifiées de l'attribut
|
||
D Supprimer l'attribut
|
||
delentry
|
||
Supprimer l'objet
|
||
ldapmodify
|
||
Utiliser ldapmodify pour modifier les objets sur le serveur. Il faut
|
||
utiliser au préalable l'une des méthodes de transformation parmi A, a,
|
||
r, d, D, delentry.
|
||
Le code de retour est celui de la commande ldapmodify.
|
||
ldapadd
|
||
Utiliser ldapadd pour créer les objets situés dans l'espace de travail.
|
||
Le code de retour est celui de la commande ldapadd.
|
||
ldapdelete
|
||
Utiliser ldapdelete pour supprimer la liste des dns situés dans l'espace
|
||
de travail.
|
||
Le code de retour est celui de la commande ldapdelete.
|
||
|
||
Notes:
|
||
- les expressions régulières sont celles reconnues par awk.
|
||
- pour spécifier plusieurs actions sur une même ligne, les séparer par //
|
||
- le code de retour est 0 si ok, 255 si une erreur s'est produite (erreur de
|
||
syntaxe, de connexion, de lecture/écriture de fichier, etc.). sinon, les
|
||
opérations ldap{search,modify,delete,add} ont leur code de retour respectifs
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!Liste des librairies de ulib
|
||
* [[ulib/apache]]
|
||
* [[ulib/apache.tools]]
|
||
* [[ulib/auto]]
|
||
* [[ulib/awk]]
|
||
* [[ulib/base]]
|
||
* [[ulib/base.args]]
|
||
* [[ulib/base.array]]
|
||
* [[ulib/base.bool]]
|
||
* [[ulib/base.compat]]
|
||
* [[ulib/base.core]]
|
||
* [[ulib/base.init]]
|
||
* [[ulib/base.num]]
|
||
* [[ulib/base.quote]]
|
||
* [[ulib/base.split]]
|
||
* [[ulib/base.string]]
|
||
* [[ulib/base.tools]]
|
||
* [[ulib/base.ulib]]
|
||
* [[ulib/bash]]
|
||
* [[ulib/cgi]]
|
||
* [[ulib/cgisupport]]
|
||
* [[ulib/compat]]
|
||
* [[ulib/conf]]
|
||
* [[ulib/crontab]]
|
||
* [[ulib/debian]]
|
||
* [[ulib/DEFAULTS]]
|
||
* [[ulib/install]]
|
||
* [[ulib/ipcalc]]
|
||
* [[ulib/java]]
|
||
* [[ulib/javaproperties]]
|
||
* [[ulib/json]]
|
||
* [[ulib/ldap]]
|
||
* [[ulib/ldif]]
|
||
* [[ulib/legacy]]
|
||
* [[ulib/macosx]]
|
||
* [[ulib/mkcrypt]]
|
||
* [[ulib/modeline]]
|
||
* [[ulib/network-manager-service]]
|
||
* [[ulib/password]]
|
||
* [[ulib/prefixes]]
|
||
* [[ulib/PREFIXES-DEFAULTS]]
|
||
* [[ulib/pretty]]
|
||
* [[ulib/ptools]]
|
||
* [[ulib/redhat]]
|
||
* [[ulib/runs]]
|
||
* [[ulib/runsmod]]
|
||
* [[ulib/runsmod.defaults]]
|
||
* [[ulib/semver]]
|
||
* [[ulib/service]]
|
||
* [[ulib/sysinfos]]
|
||
* [[ulib/template]]
|
||
* [[ulib/tiddlywiki]]
|
||
* [[ulib/udir]]
|
||
* [[ulib/uenv]]
|
||
* [[ulib/uenv_update]]
|
||
* [[ulib/uinc]]
|
||
* [[ulib/uinst]]
|
||
* [[ulib/ulib]]
|
||
* [[ulib/ulibsh]]
|
||
* [[ulib/vcs]]
|
||
* [[ulib/virsh]]
|
||
* [[ulib/webobjects]]
|
||
* [[ulib/woinst]]
|
||
* [[ulib/wondermonitor]]
|
||
* [[ulib/wosign]]
|
||
* [[ulib/wotaskd]]</pre>
|
||
</div>
|
||
<div title="ulib/DEFAULTS" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/PREFIXES-DEFAULTS" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{compute_all_prefixes}}}
|
||
!! {{{recompute_all_prefixes}}}</pre>
|
||
</div>
|
||
<div title="ulib/apache.tools" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{apache_resolvecert}}}
|
||
{{{
|
||
Calculer l'emplacement des certificats correspondant aux arguments $1 et
|
||
$2 (qui correspondent aux options --conf et --dir de apache_addcert()),
|
||
puis initialiser les variables $3(=cert), $4(=key) et $5(=ca)
|
||
}}}
|
||
!! {{{apache_addcert}}}
|
||
!! {{{apache_autoconf}}}
|
||
!! {{{apache_autoconf_localhosts}}}</pre>
|
||
</div>
|
||
<div title="ulib/apache" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{get_default_apachebin_prefix}}}
|
||
!! {{{get_default_apacheversion_prefix}}}
|
||
!! {{{get_default_apachectl_prefix}}}
|
||
!! {{{get_default_apachelogdir_prefix}}}
|
||
!! {{{get_default_apachesslcertsdir_prefix}}}
|
||
!! {{{get_default_apachesslkeysdir_prefix}}}
|
||
!! {{{get_default_apacheconfdir_prefix}}}
|
||
!! {{{get_default_apacheconf_prefix}}}
|
||
!! {{{get_default_apacheavsitesdir_prefix}}}
|
||
!! {{{get_default_apachesitesdir_prefix}}}
|
||
!! {{{get_default_htdocsdir_prefix}}}
|
||
!! {{{get_default_cgibindir_prefix}}}
|
||
!! {{{compute_apache_prefixes}}}
|
||
!! {{{recompute_apache_prefixes}}}
|
||
!! {{{get_APACHEBIN_prefix}}}
|
||
!! {{{get_APACHEVERSION_prefix}}}
|
||
!! {{{get_APACHECTL_prefix}}}
|
||
!! {{{get_APACHELOGDIR_prefix}}}
|
||
!! {{{get_APACHESSLCERTSDIR_prefix}}}
|
||
!! {{{get_APACHESSLKEYSDIR_prefix}}}
|
||
!! {{{get_APACHECONFDIR_prefix}}}
|
||
!! {{{get_APACHECONF_prefix}}}
|
||
!! {{{get_APACHEAVSITESDIR_prefix}}}
|
||
!! {{{get_APACHESITESDIR_prefix}}}
|
||
!! {{{get_HTDOCSDIR_prefix}}}
|
||
!! {{{get_CGIBINDIR_prefix}}}</pre>
|
||
</div>
|
||
<div title="ulib/auto" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/awk" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{parseheaders}}}
|
||
!! {{{printheaders}}}
|
||
!! {{{resetheaders}}}
|
||
!! {{{copyall}}}
|
||
!! {{{lawkcsv}}}
|
||
!! {{{cawkcsv}}}
|
||
!! {{{awkcsv}}}
|
||
!! {{{lgrepcsv}}}
|
||
!! {{{cgrepcsv}}}
|
||
!! {{{grepcsv}}}
|
||
!! {{{lawkfsv2csv}}}
|
||
!! {{{cawkfsv2csv}}}
|
||
!! {{{awkfsv2csv}}}
|
||
!! {{{lmergecsv}}}
|
||
{{{
|
||
Fusionner sur la sortie standard les deux fichiers csv $1 et $2. La clé du
|
||
fichier $1 est spécifiée par l'option --lkey et vaut 1 par défaut. La clé
|
||
du fichier $2 est spécifiée par l'option --rkey et vaut 1 par défaut. Les
|
||
valeurs des clés ne doivent pas faire plus de 64 caractères de long.
|
||
}}}
|
||
!! {{{readleft}}}
|
||
!! {{{readright}}}
|
||
!! {{{right2left}}}
|
||
!! {{{cmergecsv}}}
|
||
!! {{{mergecsv}}}
|
||
!! {{{lsortcsv}}}
|
||
{{{
|
||
Trier le fichier csv $1. La clé du tri est spécifiée par l'option -k et
|
||
vaut 1 par défaut. Les valeurs des clés ne doivent pas faire plus de 64
|
||
caractères de long.
|
||
}}}
|
||
!! {{{csortcsv}}}
|
||
!! {{{sortcsv}}}
|
||
!! {{{ldumpcsv}}}
|
||
!! {{{cdumpcsv}}}
|
||
!! {{{dumpcsv}}}
|
||
!! {{{lprintcsv}}}
|
||
!! {{{cprintcsv}}}
|
||
!! {{{printcsv}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.args" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{parse_opts}}}
|
||
{{{
|
||
Analyser des arguments. Cette fonction doit être appelée avec une description
|
||
des options à analyser, suivie des arguments proprement dits. En fonction des
|
||
options rencontrées, certaines variables sont mises à jour.
|
||
Les arguments de cette fonction sont donc de la forme 'optdescs -- args'
|
||
}}}
|
||
!! {{{parse_args_check}}}
|
||
{{{
|
||
Simplifier l'utilisation de parse_opts(). En entrée, le tableau args doit être
|
||
initialisé avec la liste des options. En sortie, ce tableau contient la liste
|
||
des arguments restant sur la ligne de commande. En cas d'erreur, retourner 1.
|
||
Exemple d'utilisation:
|
||
args=(...)
|
||
parse_args_check "$@" || return; set -- "${args[@]}"
|
||
}}}
|
||
!! {{{parse_args}}}
|
||
{{{
|
||
Simplifier l'utilisation de parse_opts(). En entrée, le tableau args doit être
|
||
initialisé avec la liste des options. En sortie, ce tableau contient la liste
|
||
des arguments restant sur la ligne de commande. En cas d'erreur, quitter le
|
||
script avec die()
|
||
Exemple d'utilisation:
|
||
args=(...)
|
||
parse_args_check "$@"; set -- "${args[@]}"
|
||
}}}
|
||
!! {{{genparse}}}
|
||
{{{
|
||
Afficher une ligne de commande à évaluer pour simplifier l'utilisation de
|
||
parse_opts(). Une fonction display_help() par défaut est définie et les
|
||
options appropriées de parse_opts sont utilisées pour reconnaître les options
|
||
spécifiées par les arguments.
|
||
Cette fonction peut être utilisée de cette manière:
|
||
HELP_DESC=...
|
||
HELP_ARG_DESC=... # pour chaque arg
|
||
eval "$(genparse [args...])"
|
||
D'autres variables peuvent être définies: HELP_USAGE, HELP_OPTIONS,
|
||
HELP_ARG_OPTION. Consulter le source pour connaitre leur utilisation
|
||
Les arguments de cette fonction sont de la forme 'sansarg' pour une option
|
||
simple qui ne prend pas d'argument ou 'avecarg=[default-value]' pour une
|
||
option qui prend un argument. Les options générées sont des options
|
||
longues. En l'occurence, les options générées sont respectivement '--sansarg'
|
||
et '--avecarg:'
|
||
Les variables et les options sont toujours en minuscule. Pour les variables,
|
||
le caractère '-' est remplacé par '_'. Si une option contient une lettre en
|
||
majuscule, l'option courte correspondante à cette lettre sera aussi reconnue.
|
||
Par exemple, la commande suivante:
|
||
genparse Force enCoding=utf-8 input= long-Option=
|
||
affichera ceci:
|
||
function display_help() {
|
||
[ -n "$HELP_USAGE" ] || HELP_USAGE="USAGE
|
||
$scriptname [options]"
|
||
[ -n "$HELP_OPTIONS" ] || HELP_OPTIONS="OPTIONS
|
||
${HELP_FORCE_OPTION:- -f, --force${HELP_FORCE_DESC:+
|
||
$HELP_FORCE_DESC}}
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.array" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/base.bool" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{is_yes}}}
|
||
{{{
|
||
retourner vrai si $1 est une valeur "oui"
|
||
}}}
|
||
!! {{{is_no}}}
|
||
{{{
|
||
retourner vrai si $1 est une valeur "non"
|
||
}}}
|
||
!! {{{yesval}}}
|
||
{{{
|
||
normaliser une valeur vraie: si $1 est une valeur "oui", afficher 1, sinon
|
||
afficher une chaine vide
|
||
}}}
|
||
!! {{{setb}}}
|
||
{{{
|
||
Lancer la commande $2..@ en supprimant la sortie standard. Si la commande
|
||
retourne vrai, assigner la valeur 1 à la variable $1. Sinon, lui assigner la
|
||
valeur ""
|
||
note: en principe, la syntaxe est 'setb var cmd args...'. cependant, la
|
||
syntaxe 'setb var=cmd args...' est supportée aussi
|
||
}}}
|
||
!! {{{evalb}}}
|
||
{{{
|
||
Lancer la commande $@ avec evalx() en supprimant la sortie standard. Si la
|
||
commande retourne vrai, afficher 1. Sinon, afficher ""
|
||
}}}
|
||
!! {{{setxb}}}
|
||
{{{
|
||
équivalent à setx $1 evalb $2..@
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.compat" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{setx2}}}
|
||
!! {{{rawecho}}}
|
||
!! {{{rawecho_}}}
|
||
!! {{{quote_arg}}}
|
||
!! {{{quoted_arg}}}
|
||
!! {{{quoted_args}}}
|
||
!! {{{set_var}}}
|
||
!! {{{set_var_cmd}}}
|
||
!! {{{set_var_literal}}}
|
||
!! {{{quote_awk}}}
|
||
!! {{{quoted_awk}}}
|
||
!! {{{quote_seds}}}
|
||
!! {{{quote_form}}}
|
||
!! {{{quoted_form}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.core" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{echo_}}}
|
||
{{{
|
||
afficher la valeur $* sans passer à la ligne
|
||
}}}
|
||
!! {{{recho}}}
|
||
{{{
|
||
afficher une valeur brute. contrairement à la commande echo, ne reconnaitre
|
||
aucune option (i.e. -e, -E, -n ne sont pas signifiants)
|
||
}}}
|
||
!! {{{recho_}}}
|
||
{{{
|
||
afficher une valeur brute, sans passer à la ligne. contrairement à la commande
|
||
echo, ne reconnaitre aucune option (i.e. -e, -E, -n ne sont pas signifiants)
|
||
}}}
|
||
!! {{{should_quote}}}
|
||
{{{
|
||
Tester si la chaine $* doit être mise entre quotes
|
||
}}}
|
||
!! {{{qval}}}
|
||
{{{
|
||
Afficher la chaine $* quotée avec "
|
||
}}}
|
||
!! {{{qvalm}}}
|
||
{{{
|
||
Afficher la chaine $* quotée si nécessaire avec "
|
||
}}}
|
||
!! {{{qvalr}}}
|
||
{{{
|
||
Afficher la chaine $* quotée si nécessaire avec ", sauf si elle est vide
|
||
}}}
|
||
!! {{{qvals}}}
|
||
{{{
|
||
Afficher chaque argument de cette fonction quotée le cas échéant avec "
|
||
Chaque valeur est séparée par un espace.
|
||
}}}
|
||
!! {{{qwc}}}
|
||
{{{
|
||
Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \`, puis
|
||
quoter la chaine avec ", sauf les wildcards * et ?
|
||
Cela permet de quoter une chaine permettant de glober des fichiers, e.g
|
||
eval "ls $(qwc "$value")"
|
||
Note: la protection de ! n'est pas effectuée, parce que le comportement du
|
||
shell est incohérent entre le shell interactif et les scripts. Pour une
|
||
version plus robuste, il est nécessaire d'utiliser un programme externe tel
|
||
que sed ou awk
|
||
}}}
|
||
!! {{{qlines}}}
|
||
{{{
|
||
Traiter chaque ligne de l'entrée standard pour en faire des chaines quotées
|
||
avec '
|
||
}}}
|
||
!! {{{setv}}}
|
||
{{{
|
||
initialiser la variable $1 avec la valeur $2*
|
||
note: en principe, la syntaxe est 'setv var values...'. cependant, la
|
||
syntaxe 'setv var=values...' est supportée aussi
|
||
}}}
|
||
!! {{{echo_setv}}}
|
||
{{{
|
||
Afficher la commande qui serait lancée par setv "$@"
|
||
}}}
|
||
!! {{{setx}}}
|
||
{{{
|
||
syntaxe 1: setx var cmd
|
||
initialiser la variable $1 avec le résultat de la commande "$2..@"
|
||
note: en principe, la syntaxe est 'setx var cmd args...'. cependant, la
|
||
syntaxe 'setx var=cmd args...' est supportée aussi
|
||
syntaxe 2: setx -a array cmd
|
||
initialiser le tableau $1 avec le résultat de la commande "$2..@", chaque
|
||
ligne du résultat étant un élément du tableau
|
||
note: en principe, la syntaxe est 'setx -a array cmd args...'. cependant, la
|
||
syntaxe 'setx -a array=cmd args...' est supportée aussi
|
||
}}}
|
||
!! {{{evalx}}}
|
||
{{{
|
||
Implémenter une syntaxe lisible et naturelle permettant d'enchainer des
|
||
traitements sur une valeur. Par exemple, la commande
|
||
evalx cmd1... // cmd2... // cmd3...
|
||
affiche le résultat de la commande "$(cmd3 $(cmd2 $(cmd1)))"
|
||
Retourner le dernier code d'erreur non nul, ou 0 si toutes les commandes se
|
||
sont exécutées sans erreur.
|
||
}}}
|
||
!! {{{setxx}}}
|
||
{{{
|
||
équivalent à setx $1 evalx $2..@
|
||
}}}
|
||
!! {{{evalp}}}
|
||
{{{
|
||
Implémenter une syntaxe alternative permettant d'enchainer des traitements sur
|
||
un flux de données. Par exemple, la commande
|
||
evalp cmd1... // cmd2... // cmd3...
|
||
affiche le résultat de la commande "$(cmd1 | cmd2 | cmd3)"
|
||
Typiquement, cette fonction permet de faciliter la construction d'un
|
||
enchainement de commandes par programme, ou de faciliter l'utilisation de la
|
||
fonction setx() pour récupérer le résultat d'un enchainement. Dans les autres
|
||
cas, il est plus simple et naturel d'écrire les enchainements avec la syntaxe
|
||
de bash.
|
||
}}}
|
||
!! {{{setxp}}}
|
||
{{{
|
||
équivalent à setx $1 evalp $2..@
|
||
}}}
|
||
!! {{{testx}}}
|
||
{{{
|
||
Faire un test unaire avec la commande [ sur une valeur calculée avec evalx.
|
||
Utiliser la syntaxe 'testx op cmds...' e.g.
|
||
testx -z cmd1 // cmd2
|
||
}}}
|
||
!! {{{test2x}}}
|
||
{{{
|
||
Faire une test binaire avec la commande [ entre une valeur spécifiée et une
|
||
valeur calculée avec evalx. Utiliser la syntaxe 'test2x value op cmds...' e.g.
|
||
test2x value == cmd1 // cmd2
|
||
}}}
|
||
!! {{{testrx}}}
|
||
{{{
|
||
Faire une test binaire avec la commande [[ entre une valeur spécifiée et une
|
||
valeur calculée avec evalx. Utiliser la syntaxe 'testrx value op cmds...' e.g.
|
||
testrx value == cmd1 // cmd2
|
||
}}}
|
||
!! {{{testp}}}
|
||
{{{
|
||
Faire un test unaire avec la commande [ sur une valeur calculée avec evalp.
|
||
Utiliser la syntaxe 'testp op cmds...' e.g.
|
||
testp -z cmd1 // cmd2
|
||
}}}
|
||
!! {{{test2p}}}
|
||
{{{
|
||
Faire une test binaire avec la commande [ entre une valeur spécifiée et une
|
||
valeur calculée avec evalp. Utiliser la syntaxe 'test2p value op cmds...' e.g.
|
||
test2p value == cmd1 // cmd2
|
||
}}}
|
||
!! {{{testrp}}}
|
||
{{{
|
||
Faire une test binaire avec la commande [[ entre une valeur spécifiée et une
|
||
valeur calculée avec evalp. Utiliser la syntaxe 'testrp value op cmds...' e.g.
|
||
testrp value == cmd1 // cmd2
|
||
}}}
|
||
!! {{{err2out}}}
|
||
{{{
|
||
lancer la commande $@ en redirigeant la sortie d'erreur sur la sortie standard
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.init" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/base.num" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{isnum}}}
|
||
{{{
|
||
retourner vrai si $1 est une valeur numérique entière (positive ou négative)
|
||
}}}
|
||
!! {{{ispnum}}}
|
||
{{{
|
||
retourner vrai si $1 est une valeur numérique entière positive
|
||
}}}
|
||
!! {{{isrnum}}}
|
||
{{{
|
||
retourner vrai si $1 est une valeur numérique réelle (positive ou négative)
|
||
le séparateur décimal peut être . ou ,
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.quote" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{qawk}}}
|
||
{{{
|
||
Dans la chaine $*, remplacer \ par \\ et " par \" et afficher la chaine
|
||
entourée de guillemets. Ceci est utile pour quoter des valeur à insérer dans
|
||
un script awk
|
||
}}}
|
||
!! {{{qseds}}}
|
||
{{{
|
||
Quoter la chaine $*, qui doit être utilisée comme chaine de recherche ou de
|
||
remplacement de grep, sed ou awk
|
||
}}}
|
||
!! {{{qform}}}
|
||
{{{
|
||
Dans la chaine $* qui est de la forme "name=value", remplacer dans name et
|
||
dans value '%' par '%25', '+' par '%2B', '&' par '%26', '=' par '%3D', ' ' par
|
||
'+'
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.split" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{splitfsep}}}
|
||
{{{
|
||
Découper $1 de la forme "first[SEPsecond]" entre first, qui est placé dans la
|
||
variable $3(=first) et second, qui est placée dans la variable $4(=second). $2
|
||
est la valeur SEP. Le découpage est faite sur la *première* occurence de SEP.
|
||
}}}
|
||
!! {{{splitfsep2}}}
|
||
{{{
|
||
Découper $1 de la forme "[firstSEP]second" entre first, qui est placé dans la
|
||
variable $3(=first) et second, qui est placée dans la variable $4(=second). $2
|
||
est la valeur SEP. Le découpage est faite sur la *première* occurence de SEP.
|
||
}}}
|
||
!! {{{splitlsep}}}
|
||
{{{
|
||
Découper $1 de la forme "first[SEPsecond]" entre first, qui est placé dans la
|
||
variable $3(=first) et second, qui est placée dans la variable $4(=second). $2
|
||
est la valeur SEP. Le découpage est faite sur la *dernière* occurence de SEP.
|
||
}}}
|
||
!! {{{splitlsep2}}}
|
||
{{{
|
||
Découper $1 de la forme "[firstSEP]second" entre first, qui est placé dans la
|
||
variable $3(=first) et second, qui est placée dans la variable $4(=second). $2
|
||
est la valeur SEP. Le découpage est faite sur la *dernière* occurence de SEP.
|
||
}}}
|
||
!! {{{splitvar}}}
|
||
{{{
|
||
Découper $1 de la forme name[=value] entre le nom, qui est placé dans la
|
||
variable $2(=name) et la valeur, qui est placée dans la variable $3(=value)
|
||
}}}
|
||
!! {{{splitpath}}}
|
||
{{{
|
||
Découper $1 de la forme [dir/]name entre le répertoire, qui est placé dans la
|
||
variable $2(=dir), et le nom du fichier, qui est placé dans la variable
|
||
$3(=name)
|
||
}}}
|
||
!! {{{splitname}}}
|
||
{{{
|
||
Découper $1 de la forme basename[.ext] entre le nom de base du fichier, qui
|
||
est placé dans la variable $2(=basename) et l'extension, qui est placée dans
|
||
la variable $3(=ext)
|
||
Attention, si $1 est un chemin, le résultat risque d'être faussé. Par exemple,
|
||
'splitname a.b/c' ne donne pas le résultat escompté.
|
||
}}}
|
||
!! {{{splithost}}}
|
||
{{{
|
||
Découper $1 de la forme hostname[.domain] entre le nom d'hôte, qui est placé
|
||
dans la variable $2(=hostname) et le domaine, qui est placée dans la variable
|
||
$3(=domain)
|
||
}}}
|
||
!! {{{splituserhost}}}
|
||
{{{
|
||
Découper $1 de la forme [user@]host entre le nom de l'utilisateur, qui est placé
|
||
dans la variable $2(=user) et le nom d'hôte, qui est placée dans la variable
|
||
$3(=host)
|
||
}}}
|
||
!! {{{splitpair}}}
|
||
{{{
|
||
Découper $1 de la forme first[:second] entre la première valeur, qui est placé
|
||
dans la variable $2(=src) et la deuxième valeur, qui est placée dans la variable
|
||
$3(=dest)
|
||
}}}
|
||
!! {{{splitproxy}}}
|
||
{{{
|
||
Découper $1 de la forme http://[user:password@]host[:port]/ entre les valeurs
|
||
$2(=host), $3(=port), $4(=user), $5(=password)
|
||
}}}
|
||
!! {{{spliturl}}}
|
||
{{{
|
||
Découper $1 de la forme scheme://[user:password@]host[:port]/path entre les
|
||
valeurs $2(=scheme), $3(=user), $4(=password), $5(=host), $6(=port), $7(=path)
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.string" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{straddp}}}
|
||
{{{
|
||
ajouter le préfixe $1 à $2*
|
||
}}}
|
||
!! {{{strdelp}}}
|
||
{{{
|
||
enlever le préfixe $1 à $2*
|
||
}}}
|
||
!! {{{strdelp2}}}
|
||
{{{
|
||
enlever le préfixe $1 le plus long à $2*
|
||
}}}
|
||
!! {{{stradds}}}
|
||
{{{
|
||
ajouter le suffixe $1 à $2*
|
||
}}}
|
||
!! {{{strdels}}}
|
||
{{{
|
||
enlever le suffixe $1 à $2*
|
||
}}}
|
||
!! {{{strdels2}}}
|
||
{{{
|
||
enlever le suffixe le plus long $1 à $2*
|
||
}}}
|
||
!! {{{strlower}}}
|
||
{{{
|
||
afficher en minuscule la valeur $*
|
||
}}}
|
||
!! {{{strlower1}}}
|
||
{{{
|
||
afficher la valeur $* après avoir converti la première lettre en minuscule
|
||
}}}
|
||
!! {{{strlowers}}}
|
||
{{{
|
||
afficher les valeurs $1..* après avoir converti leur première lettre en
|
||
minuscule
|
||
}}}
|
||
!! {{{strupper}}}
|
||
{{{
|
||
afficher en majuscule la valeur $*
|
||
}}}
|
||
!! {{{strupper1}}}
|
||
{{{
|
||
afficher la valeur $* après avoir converti la première lettre en majuscule
|
||
}}}
|
||
!! {{{struppers}}}
|
||
{{{
|
||
afficher les valeurs $1..* après avoir converti leur première lettre en
|
||
majuscule
|
||
}}}
|
||
!! {{{strmid}}}
|
||
{{{
|
||
Afficher la plage $1 de la valeur $2*. La plage peut être d'une des formes
|
||
'start', '[start]:length'. Si start est négatif, le compte est effectué à
|
||
partir de la fin de la chaine. Si length est négatif, il est rajouté à la
|
||
longueur de la chaine à partir de start
|
||
}}}
|
||
!! {{{strrepl}}}
|
||
{{{
|
||
Remplacer dans la valeur $3* le motif $1 par la chaine $2. $1 peut commencer
|
||
par l'un des caractères /, #, % pour indiquer le type de recherche
|
||
}}}
|
||
!! {{{first_char}}}
|
||
{{{
|
||
retourner le premier caractère de la chaine $*
|
||
}}}
|
||
!! {{{last_char}}}
|
||
{{{
|
||
retourner le dernier caractère de la chaine $*
|
||
}}}
|
||
!! {{{first_chars}}}
|
||
{{{
|
||
retourner tous les caractères de la chaine $*, excepté le dernier
|
||
}}}
|
||
!! {{{last_chars}}}
|
||
{{{
|
||
retourner tous les caractères de la chaine $*, excepté le premier
|
||
}}}
|
||
!! {{{first_char_is}}}
|
||
{{{
|
||
Tester si le premier caractère de la chaine $1 est $2
|
||
}}}
|
||
!! {{{last_char_is}}}
|
||
{{{
|
||
Tester si le dernier caractère de la chaine $1 est $2
|
||
}}}
|
||
!! {{{beginswith}}}
|
||
{{{
|
||
Tester si la chaine $1 commence par le wildcard $2
|
||
}}}
|
||
!! {{{endswith}}}
|
||
{{{
|
||
Tester si la chaine $1 se termine par le wildcard $2
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.tools" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{base_umove}}}
|
||
{{{
|
||
Outil de haut niveau pour déplacer un fichier ou un lien. Si c'est un lien qui
|
||
est déplacé, la destination du lien est mise à jour si elle est relative.
|
||
l'option '-d UPDATEDIR' permet de spécifier un répertoire dans lequel tous les
|
||
liens qui pointent vers le fichier déplacé sont mis à jour si le déplacement
|
||
du fichier se fait avec succès.
|
||
}}}
|
||
!! {{{base_udelete}}}
|
||
{{{
|
||
Outil de haut niveau pour supprimer un fichier ou un lien. Si on doit
|
||
supprimer un fichier, et que l'option '-d UPDATEDIR' est spécifiée, et que des
|
||
liens du répertoire UPDATEDIR pointent vers le fichier supprimé, ces liens
|
||
sont supprimés aussi.
|
||
}}}
|
||
!! {{{base_ucopy}}}
|
||
{{{
|
||
Outil de haut niveau pour copier un fichier ou un lien. Si c'est un lien qui
|
||
est copié, la destination du lien est mise à jour si elle est relative.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{setyesval}}}
|
||
{{{
|
||
mettre la valeur normalisée de la valeur "oui" de $2 dans la variable $1
|
||
}}}
|
||
!! {{{normyesval}}}
|
||
{{{
|
||
remplacer la valeur de la variable $1 par la valeur normalisée de sa valeur "oui"
|
||
Si $2 est non vide, prendre cette valeur plutôt que la valeur de la variable $1
|
||
}}}
|
||
!! {{{normyesvals}}}
|
||
{{{
|
||
remplacer les valeur des variables $1..* par les valeurs normalisées
|
||
respectives de leur valeur "oui"
|
||
}}}
|
||
!! {{{quote_in}}}
|
||
{{{
|
||
Comme quote_arg pour une chaine lue sur stdin
|
||
}}}
|
||
!! {{{quote_sin}}}
|
||
{{{
|
||
Pour la chaine lue sur stdin, remplacer ' par '\''. Cela permet de protéger une
|
||
chaine à mettre entre quotes
|
||
}}}
|
||
!! {{{quote_sarg}}}
|
||
{{{
|
||
Dans la chaine $1, remplacer ' par '\''. Cette fonction utilise quote_sin,
|
||
puisque le shell a des difficultés à faire le rechercher/remplacer approprié
|
||
}}}
|
||
!! {{{quoted_sarg}}}
|
||
{{{
|
||
Dans la chaine $1, remplacer ' par '\'', et afficher la chaine entourée de
|
||
quotes
|
||
}}}
|
||
!! {{{quoted_sargs}}}
|
||
{{{
|
||
Comme quoted_sarg, mais tous les arguments sont quotés et affichés entourés de
|
||
quotes, ce qui permet de construire des arguments d'une ligne de commande
|
||
}}}
|
||
!! {{{set_array_cmd}}}
|
||
{{{
|
||
Afficher la commande permettant d'initialiser le tableau $1 avec les valeurs:
|
||
soit du tableau $2, soit de $3..$n si $2=="@"
|
||
S'il n'y a que l'argument $1, alors afficher la commande permettant de
|
||
recréer le tableau $1
|
||
}}}
|
||
!! {{{set_array}}}
|
||
{{{
|
||
Soit $1 un tableau à créer. Si $2=="@", créer le tableau $1 avec les valeurs
|
||
$3..$n. Sinon, créer le tableau $1 avec les valeurs du tableau $2.
|
||
Cette fonction n'existe que comme un pendant de set_var(), mais le véritable
|
||
intérêt est la fonction set_array_cmd(). cf array_copy() pour une version plus
|
||
efficace de la copie de tableaux
|
||
}}}
|
||
!! {{{array_count}}}
|
||
{{{
|
||
retourner le nombre d'éléments du tableau $1
|
||
}}}
|
||
!! {{{array_isempty}}}
|
||
{{{
|
||
tester si le tableau $1 est vide
|
||
}}}
|
||
!! {{{array_new}}}
|
||
{{{
|
||
créer un tableau vide dont le nom est $1
|
||
}}}
|
||
!! {{{array_add}}}
|
||
{{{
|
||
ajouter les valeurs $2..@ au tableau dont le nom est $1
|
||
}}}
|
||
!! {{{array_ins}}}
|
||
{{{
|
||
insérer les valeurs $2..@ au début du tableau dont le nom est $1
|
||
}}}
|
||
!! {{{array_del}}}
|
||
{{{
|
||
supprimer *les* valeurs $2 du tableau dont le nom est $1
|
||
}}}
|
||
!! {{{array_addu}}}
|
||
{{{
|
||
ajouter la valeur $2 au tableau dont le nom est $1, si la valeur n'y est pas
|
||
déjà. Retourner vrai si la valeur a été ajoutée
|
||
}}}
|
||
!! {{{array_set}}}
|
||
!! {{{array_insu}}}
|
||
{{{
|
||
insérer la valeur $2 au début du tableau tableau dont le nom est $1, si la
|
||
valeur n'y est pas déjà. Retourner vrai si la valeur a été ajoutée.
|
||
}}}
|
||
!! {{{array_fillrange}}}
|
||
{{{
|
||
Initialiser le tableau $1 avec les nombres de $2(=1) à $3(=10) avec un step de $4(=1)
|
||
}}}
|
||
!! {{{array_eq}}}
|
||
{{{
|
||
tester l'égalité des tableaux $1 et $2
|
||
}}}
|
||
!! {{{array_contains}}}
|
||
{{{
|
||
tester si le tableau dont le nom est $1 contient la valeur $2
|
||
}}}
|
||
!! {{{array_icontains}}}
|
||
{{{
|
||
tester si le tableau dont le nom est $1 contient la valeur $2, sans tenir
|
||
compte de la casse
|
||
}}}
|
||
!! {{{array_find}}}
|
||
{{{
|
||
si le tableau $1 contient la valeur $2, retourner l'index de la valeur. Si le
|
||
tableau $3 est spécifié, retourner la valeur à l'index dans ce tableau
|
||
}}}
|
||
!! {{{array_reverse}}}
|
||
{{{
|
||
Inverser l'ordre des élément du tableau $1
|
||
}}}
|
||
!! {{{array_replace}}}
|
||
{{{
|
||
dans le tableau $1, remplacer toutes les occurences de $2 par $3..*
|
||
}}}
|
||
!! {{{array_each}}}
|
||
{{{
|
||
Pour chacune des valeurs 'v' du tableau $1, appeler la fonction $2 avec les
|
||
arguments '$v $3..$n'
|
||
}}}
|
||
!! {{{array_map}}}
|
||
{{{
|
||
Pour chacune des valeurs 'v' du tableau $1, appeler la fonction $2 avec les
|
||
arguments '$v $3..$n', et remplacer la valeur par le résultat de la fonction
|
||
}}}
|
||
!! {{{first_value}}}
|
||
{{{
|
||
retourner la première valeur du tableau $1
|
||
}}}
|
||
!! {{{last_value}}}
|
||
{{{
|
||
retourner la dernière valeur du tableau $1
|
||
}}}
|
||
!! {{{array_copy}}}
|
||
{{{
|
||
copier le contenu du tableau $2 dans le tableau $1
|
||
}}}
|
||
!! {{{array_copy_firsts}}}
|
||
{{{
|
||
copier tous les valeurs du tableau $2(=$1) dans le tableau $1, excepté la dernière
|
||
}}}
|
||
!! {{{array_del_last}}}
|
||
!! {{{array_copy_lasts}}}
|
||
{{{
|
||
copier tous les valeurs du tableau $2(=$1) dans le tableau $1, excepté la première
|
||
}}}
|
||
!! {{{array_del_first}}}
|
||
!! {{{array_extend}}}
|
||
{{{
|
||
ajouter le contenu du tableau $2 au tableau $1
|
||
}}}
|
||
!! {{{array_extendu}}}
|
||
{{{
|
||
ajouter chacune des valeurs du tableau $2 au tableau $1, si ces valeurs n'y
|
||
sont pas déjà. Retourner vrai si au moins une valeur a été ajoutée
|
||
}}}
|
||
!! {{{array_extend_firsts}}}
|
||
{{{
|
||
ajouter toutes les valeurs du tableau $2 dans le tableau $1, excepté la dernière
|
||
}}}
|
||
!! {{{array_extend_lasts}}}
|
||
{{{
|
||
ajouter toutes les valeurs du tableau $2 dans le tableau $1, excepté la première
|
||
}}}
|
||
!! {{{array_xsplit}}}
|
||
{{{
|
||
créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
|
||
par $3, qui vaut ':' par défaut).
|
||
}}}
|
||
!! {{{array_split}}}
|
||
{{{
|
||
créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
|
||
par $3, qui vaut ':' par défaut). Les éléments vides sont ignorés. par exemple
|
||
"a::b" est équivalent à "a:b"
|
||
}}}
|
||
!! {{{array_from_path}}}
|
||
!! {{{array_from_xlines}}}
|
||
{{{
|
||
créer le tableau $1 avec chaque ligne de $2.
|
||
}}}
|
||
!! {{{array_from_lines}}}
|
||
{{{
|
||
créer le tableau $1 avec chaque ligne de $2. Les lignes vides sont ignorés.
|
||
}}}
|
||
!! {{{array_join}}}
|
||
{{{
|
||
afficher le contenu du tableau dont le nom est $1 sous forme d'une liste de
|
||
valeurs séparées par $2 (par défaut, une virgule)
|
||
Si $1=="@", alors les éléments du tableaux sont les arguments de la fonction à
|
||
partir de $3
|
||
Si $1!="@" et que le tableau est vide, afficher $3
|
||
Si $1!="@", $4 et $5 sont des préfixes et suffixes à rajouter à chaque élément
|
||
}}}
|
||
!! {{{array_mapjoin}}}
|
||
{{{
|
||
map le tableau $1 avec la fonction $2, puis afficher le résultat en séparant
|
||
chaque élément par $3. Les arguments et la sémantique sont les mêmes que pour
|
||
array_join en tenant compte de l'argument supplémentaire $2 qui est la
|
||
fonction pour array_map (les autres arguments sont décalés en conséquence)
|
||
}}}
|
||
!! {{{array_to_lines}}}
|
||
{{{
|
||
afficher le tableau dont le nom est $1 sous forme de lignes
|
||
}}}
|
||
!! {{{array_to_path}}}
|
||
{{{
|
||
afficher le tableau dont le nom est $1 sous forme d'une liste de chemins
|
||
séparés par ':')
|
||
}}}
|
||
!! {{{array_fix_paths}}}
|
||
{{{
|
||
Corriger les valeurs du tableau $1. Les valeurs contenant le séparateur
|
||
$2(=':') sont séparées en plusieurs valeurs. Par exemple avec le tableau
|
||
input=(a b:c), le résultat est input=(a b c)
|
||
}}}
|
||
!! {{{get_date_rfc822}}}
|
||
!! {{{get_date_fr}}}
|
||
!! {{{get_time_fr}}}
|
||
!! {{{parse_date}}}
|
||
!! {{{udelpath}}}
|
||
{{{
|
||
supprimer le chemin $1 de $2(=PATH)
|
||
}}}
|
||
!! {{{uaddpath}}}
|
||
{{{
|
||
Ajouter le chemin $1 à la fin, dans $2(=PATH), s'il n'y existe pas déjà
|
||
}}}
|
||
!! {{{uinspathm}}}
|
||
{{{
|
||
Ajouter le chemin $1 au début, dans $2(=PATH), s'il n'y existe pas déjà
|
||
}}}
|
||
!! {{{uinspath}}}
|
||
{{{
|
||
S'assurer que le chemin $1 soit au début de $2(=PATH)
|
||
}}}
|
||
!! {{{withpath}}}
|
||
{{{
|
||
tester si le chemin est relatif à . ou à .., ou est absolu. i.e 'withpath a/b'
|
||
renvoie faux alors que 'withpath ./a/b' renvoie vrai
|
||
}}}
|
||
!! {{{withext}}}
|
||
{{{
|
||
tester si le fichier a une extension
|
||
}}}
|
||
!! {{{normpath}}}
|
||
{{{
|
||
normaliser le chemin $1, qui est soit absolu, soit relatif à $2 (qui vaut
|
||
$(pwd) par défaut)
|
||
}}}
|
||
!! {{{abspath}}}
|
||
{{{
|
||
Retourner un chemin absolu vers $1. Si $2 est non nul et si $1 est un chemin
|
||
relatif, alors $1 est exprimé par rapport à $2, sinon il est exprimé par
|
||
rapport au répertoire courant.
|
||
Si le chemin n'existe pas, il n'est PAS normalisé. Sinon, les meilleurs
|
||
efforts sont faits pour normaliser le chemin.
|
||
}}}
|
||
!! {{{parentdirs}}}
|
||
{{{
|
||
Obtenir la liste de tous les parents du répertoire $2 dans le tableau $1, du
|
||
répertoire $2 vers la racine. Si $3 commence par 'r' (comme reverse), l'ordre
|
||
est inversé: le tableau contient les répertoire de la racine vers $2.
|
||
}}}
|
||
!! {{{ppath}}}
|
||
{{{
|
||
Dans un chemin *absolu*, remplacer "$HOME" par "~" et "$(pwd)/" par "", afin
|
||
que le chemin soit plus facile à lire. Le répertoire courant est spécifié par
|
||
$2 ou $(pwd) si $2 est vide
|
||
}}}
|
||
!! {{{relpath}}}
|
||
{{{
|
||
Afficher le chemin relatif de $1 par rapport à $2. Si $2 n'est pas spécifié,
|
||
on prend le répertoire courant. Si $1 ou $2 ne sont pas des chemins absolus,
|
||
il sont transformés en chemins absolus par rapport à $3. Si $1==$2, retourner
|
||
une chaine vide
|
||
}}}
|
||
!! {{{relpathx}}}
|
||
{{{
|
||
Comme relpath, mais pour un chemin vers un exécutable qu'il faut lancer:
|
||
s'assurer qu'il y a une spécification de chemin, e.g. ./script
|
||
}}}
|
||
!! {{{withinpath}}}
|
||
{{{
|
||
Tester si le chemin absolu $2 se trouve dans le chemin absolu "$1" (appelée
|
||
barrière). Soit un chemin P, on considère que P est dans P. Si ce comportement
|
||
n'est pas souhaité, $3(=N) doit valoir O, auquel cas P est dans Q implique que
|
||
P != Q.
|
||
}}}
|
||
!! {{{safe_abspath}}}
|
||
{{{
|
||
Afficher le chemin absolu de $1, par rapport à $2, si et seulement si le
|
||
chemin résultat ne se trouve pas en dehors de la barrière $3. Si $2 n'est pas
|
||
spécifié, prendre le répertoire courant. S'il est relatif, l'exprimer par
|
||
rapport au répertoire courant. Si $3 est relatif, l'exprimer par rapport à $2.
|
||
Si le chemin résultat est sité en dehors de la barrière, ne rien afficher et
|
||
retourner un code d'erreur.
|
||
Si le chemin $1 n'existe pas, il n'est PAS normalisé. Sinon, les meilleurs
|
||
efforts sont faits pour normaliser le chemin résultat.
|
||
}}}
|
||
!! {{{safe_relpath}}}
|
||
{{{
|
||
Afficher le chemin relatif de $1 par rapport à $2 si et seulement si le chemin
|
||
résultat ne se trouve pas en dehors de la barrière $3. Si $2 n'est pas
|
||
spécifié, prendre le répertoire courant. S'il est relatif, l'exprimer par
|
||
rapport au répertoire courant. Si $3 est relatif, l'exprimer par rapport à $2.
|
||
Si le chemin résultat est sité en dehors de la barrière, ne rien afficher et
|
||
retourner un code d'erreur.
|
||
}}}
|
||
!! {{{splitwcs}}}
|
||
{{{
|
||
Découper un nom de chemin $1 entre la partie sans wildcards, qui est placée dans
|
||
la variables $2(=basedir), et la partie avec wildcards, qui est placée dans la
|
||
variable $3(=filespec)
|
||
}}}
|
||
!! {{{deref}}}
|
||
{{{
|
||
Retourner un chemin absolu vers le fichier $1, dans lequel toutes les
|
||
composantes "lien symbolique" ont été supprimées.
|
||
DEPRECATED: Cette fonction est dépréciée. Utiliser à la place readlinkm()
|
||
}}}
|
||
!! {{{readlinka}}}
|
||
{{{
|
||
Afficher un chemin absolu vers la destination du fichier $1. Si $1 n'est pas
|
||
un lien, afficher simplement le chemin du fichier
|
||
}}}
|
||
!! {{{readlinkm}}}
|
||
{{{
|
||
Retourner un chemin absolu vers le fichier $1, dans lequel toutes les
|
||
composantes "lien symbolique" ont été supprimées. Il n'est pas requis que les
|
||
composantes du chemin existent.
|
||
}}}
|
||
!! {{{path_if_test}}}
|
||
{{{
|
||
afficher un chemin si le fichier $2 existe (en utilisant l'opérateur $1) dans
|
||
l'un des chemins absolus $4..n. si $3==relative, afficher le chemin relatif,
|
||
sinon le chemin absolu. note: $3 peut être de la forme relative:path, auquel
|
||
cas le chemin affiché est exprimé relativement à path
|
||
}}}
|
||
!! {{{update_link}}}
|
||
{{{
|
||
mettre à jour le lien $2 pour qu'il pointe vers le fichier $1
|
||
}}}
|
||
!! {{{update_links}}}
|
||
{{{
|
||
Mettre à jour les liens $2..@ pour qu'ils pointent vers la nouvelle
|
||
destination $1
|
||
}}}
|
||
!! {{{move_link}}}
|
||
{{{
|
||
Déplacer le lien $1 vers $2, et mettre à jour la destination du lien si
|
||
elle est exprimée de façon relative
|
||
Si $1 n'est pas un lien, le déplacer normalement avec mv
|
||
}}}
|
||
!! {{{copy_link}}}
|
||
{{{
|
||
Copier le lien $1 vers $2, et mettre à jour la destination du lien si
|
||
elle est exprimée de façon relative
|
||
Si $1 n'est pas un lien, le copier normalement avec cp
|
||
}}}
|
||
!! {{{array_find_links}}}
|
||
{{{
|
||
Chercher dans le répertoire $3 (qui est par défaut le répertoire courant)
|
||
les liens vers le fichier $2, et ajouter leurs chemins absolus dans le
|
||
tableau $1
|
||
}}}
|
||
!! {{{list_links}}}
|
||
{{{
|
||
Chercher dans le répertoire $2 les liens vers le fichier $1, et les
|
||
afficher, un par ligne.
|
||
}}}
|
||
!! {{{move_file}}}
|
||
{{{
|
||
Déplacer le fichier $1 vers $2, et mettre à jour les liens $3..@ pour
|
||
qu'ils pointent vers la nouvelle destination
|
||
}}}
|
||
!! {{{get_nblines}}}
|
||
{{{
|
||
Afficher le nombre de lignes d'un fichier
|
||
}}}
|
||
!! {{{mktempf}}}
|
||
{{{
|
||
générer un fichier temporaire et retourner son nom
|
||
}}}
|
||
!! {{{mktempd}}}
|
||
{{{
|
||
générer un répertoire temporaire et retourner son nom
|
||
}}}
|
||
!! {{{mkdirof}}}
|
||
{{{
|
||
Créer le répertoire correspondant à un fichier
|
||
}}}
|
||
!! {{{cp_a}}}
|
||
{{{
|
||
copier des fichiers en gardant le maximum de propriétés
|
||
}}}
|
||
!! {{{cp_R}}}
|
||
{{{
|
||
copier des fichiers récursivement, en suivant les liens symboliques
|
||
}}}
|
||
!! {{{quietgrep}}}
|
||
{{{
|
||
tester la présence d'un pattern dans un fichier
|
||
}}}
|
||
!! {{{quietdiff}}}
|
||
{{{
|
||
tester si deux fichiers sont identiques
|
||
}}}
|
||
!! {{{testsame}}}
|
||
{{{
|
||
tester si deux fichiers sont identiques/différents
|
||
}}}
|
||
!! {{{testdiff}}}
|
||
!! {{{testupdated}}}
|
||
{{{
|
||
test si $2 n'existe pas ou si $1 est différent de $2
|
||
}}}
|
||
!! {{{testnewer}}}
|
||
{{{
|
||
test si $2 n'existe pas ou si $1 est plus récent que $2
|
||
}}}
|
||
!! {{{ps_all}}}
|
||
{{{
|
||
afficher tous les processus avec le maximum d'informations
|
||
}}}
|
||
!! {{{progexists}}}
|
||
{{{
|
||
tester l'existence d'un programme dans le PATH
|
||
}}}
|
||
!! {{{has_python}}}
|
||
{{{
|
||
tester la présence de python
|
||
}}}
|
||
!! {{{has_gawk}}}
|
||
{{{
|
||
tester la présence de gnuawk
|
||
}}}
|
||
!! {{{is_root}}}
|
||
{{{
|
||
tester si on est root
|
||
}}}
|
||
!! {{{source_ifexists}}}
|
||
{{{
|
||
sourcer un fichier s'il existe
|
||
}}}
|
||
!! {{{is_running}}}
|
||
{{{
|
||
tester si un programme dont on donne le PID tourne
|
||
}}}
|
||
!! {{{sedi}}}
|
||
{{{
|
||
Lancer sed sur un fichier en le modifiant en place
|
||
}}}
|
||
!! {{{csort}}}
|
||
{{{
|
||
Lancer sort avec LANG=C pour éviter les problèmes avec la locale. en effet,
|
||
avec LANG!=C, sort utilise les règles de la locale pour le tri, et par
|
||
exemple, avec LANG=fr_FR.UTF-8, la locale indique que les ponctuations doivent
|
||
être ignorées.
|
||
}}}
|
||
!! {{{lsort}}}
|
||
!! {{{cgrep}}}
|
||
{{{
|
||
Lancer grep avec LANG=C pour éviter les problèmes avec la locale. cf csort
|
||
pour une explication.
|
||
}}}
|
||
!! {{{lgrep}}}
|
||
!! {{{csed}}}
|
||
{{{
|
||
Lancer sed avec LANG=C pour éviter les problèmes avec la locale. cf csort pour
|
||
une explication.
|
||
}}}
|
||
!! {{{lsed}}}
|
||
!! {{{cawk}}}
|
||
{{{
|
||
Lancer awk avec LANG=C pour éviter les problèmes avec la locale. cf csort pour
|
||
une explication.
|
||
}}}
|
||
!! {{{lawk}}}
|
||
!! {{{cdiff}}}
|
||
{{{
|
||
Lancer diff avec LANG=C pour éviter les problèmes avec la locale. cf csort
|
||
pour une explication.
|
||
}}}
|
||
!! {{{ldiff}}}
|
||
!! {{{fix_mode}}}
|
||
{{{
|
||
Si le fichier $1 n'est pas writable, le rendre writable temporairement. Si
|
||
nécessaire, le fichier est créé.
|
||
Cette fonction s'utilise de cette façon:
|
||
mode="$(fix_mode file)"
|
||
...
|
||
unfix_mode file "$mode"
|
||
}}}
|
||
!! {{{unfix_mode}}}
|
||
{{{
|
||
Restaurer le mode $2 du fichier $1 traité par fix_mode
|
||
}}}
|
||
!! {{{get_mode}}}
|
||
{{{
|
||
Obtenir le mode du fichier $1, en le créant si nécessaire. A utiliser avec
|
||
unfix_mode pour restaurer le mode d'un fichier qui a été traité avec un
|
||
fichier temporaire intermédiaire
|
||
}}}
|
||
!! {{{rm_maybe}}}
|
||
{{{
|
||
Supprimer les fichiers dont on donne la liste. Si aucun fichier n'est
|
||
spécifié, cette fonction est un NOP
|
||
}}}
|
||
!! {{{cpdir}}}
|
||
{{{
|
||
copier un fichier dans un répertoire, ou le contenu d'un répertoire dans un
|
||
autre répertoire, que le répertoire source soit un lien symbolique ou
|
||
non. Cette fonction existe parce que le comportement de "cp_a src dest" n'est
|
||
pas consistant selon les plateformes, surtout si src est un lien symbolique
|
||
sur un répertoire: parfois on copie le lien, parfois on copie le contenu du
|
||
répertoire, parfois on copie le répertoire...
|
||
La copie est faite avec rsync si possible. Les options du tableau
|
||
__CPDIR_RSYNC_ARGS sont rajoutées aux options standard de rsync.
|
||
}}}
|
||
!! {{{cpnovcs}}}
|
||
{{{
|
||
copier le fichier/répertoire $1 *dans* le *répertoire* $2 avec rsync. Les
|
||
options du tableau __CPNOVCS_RSYNC_ARGS sont rajoutées aux options standard
|
||
de rsync.
|
||
Si $1 est un répertoire, la copie est faite en ignorant les sous-répertoires
|
||
de VCS (.svn, CVS). En ce qui concerne les répertoire de VCS, git aussi est
|
||
supporté, mais uniquement s'il est à la racine du transfert.
|
||
Si $1 se termine par un '/', c'est le contenu du répertoire qui est copié, pas
|
||
le répertoire lui-même. Si rsync n'est pas trouvé sur le système, alors on
|
||
fait une copie standard qui inclue les répertoires de VCS.
|
||
}}}
|
||
!! {{{cpvcs}}}
|
||
{{{
|
||
comme cpnovcs, mais ne pas ignorer les répertoires de VCS
|
||
}}}
|
||
!! {{{cpdirnovcs}}}
|
||
{{{
|
||
Le pendant de cpdir, mais en ignorant les sous-répertoires de VCS: copier le
|
||
contenu du répertoire $1 dans le répertoire $2
|
||
}}}
|
||
!! {{{doinplace}}}
|
||
{{{
|
||
Filtrer le fichier $1 à travers la commande $2..$*, puis remplacer le fichier
|
||
s'il n'y a pas eu d'erreur. Retourner le code d'erreur de la commande. Si $1
|
||
n'est pas spécifié ou vaut -, filtrer l'entrée standard vers la sortie
|
||
standard.
|
||
La variante doinplacef remplace le fichier quelque soit le code de retour de
|
||
la commande. A utiliser avec des commandes comme grep qui peuvent retourner
|
||
FAUX s'ils ne trouvent pas le motif
|
||
}}}
|
||
!! {{{doinplacef}}}
|
||
!! {{{stripnl}}}
|
||
{{{
|
||
Supprimer les caractères de fin de ligne de la chaine en entrée
|
||
}}}
|
||
!! {{{nl2lf}}}
|
||
!! {{{nl2crlf}}}
|
||
!! {{{nl2cr}}}
|
||
!! {{{list_all}}}
|
||
{{{
|
||
Lister les fichiers ou répertoires du répertoire $1, un par ligne
|
||
Les répertoires . et .. sont enlevés de la liste
|
||
$1=un répertoire dont le contenu doit être listé
|
||
$2..@=un ensemble de patterns pour le listage
|
||
}}}
|
||
!! {{{list_files}}}
|
||
{{{
|
||
Lister les fichiers du répertoire $1, un par ligne
|
||
$1=un répertoire dont le contenu doit être listé.
|
||
$2..@=un ensemble de patterns pour le listage
|
||
}}}
|
||
!! {{{list_dirs}}}
|
||
{{{
|
||
Lister les répertoires du répertoire $1, un par ligne
|
||
Les répertoires . et .. sont enlevés de la liste
|
||
$1=un répertoire dont le contenu doit être listé.
|
||
$2..@=un ensemble de patterns pour le listage
|
||
}}}
|
||
!! {{{array_lsall}}}
|
||
{{{
|
||
Lister les fichiers avec `list_all $2 $3...`, et les mettre dans le
|
||
tableau $1. Le tableau contient les chemins complets, par seulement les
|
||
noms comme avec list_all
|
||
}}}
|
||
!! {{{array_lsdirs}}}
|
||
{{{
|
||
Lister les fichiers avec `list_dirs $2 $3...`, et les mettre dans le
|
||
tableau $1. Le tableau contient les chemins complets, par seulement les
|
||
noms comme avec list_dirs
|
||
}}}
|
||
!! {{{array_lsfiles}}}
|
||
{{{
|
||
Lister les fichiers avec `list_files $2 $3...`, et les mettre dans le
|
||
tableau $1. Le tableau contient les chemins complets, par seulement les
|
||
noms comme avec list_files
|
||
}}}
|
||
!! {{{filter_empty}}}
|
||
{{{
|
||
Filtrer l'entrée standard en enlevant les lignes vides
|
||
}}}
|
||
!! {{{filter_vcspath}}}
|
||
{{{
|
||
L'entrée standard étant une liste de chemins, filtrer les fichiers et
|
||
répertoire qui ont un rapport avec subversion ou git
|
||
}}}
|
||
!! {{{merge_contlines}}}
|
||
{{{
|
||
Avec les lignes lues sur stdin, fusionner celles qui se terminent par \ avec
|
||
les suivantes.
|
||
}}}
|
||
!! {{{filter_comment}}}
|
||
{{{
|
||
Filtrer un fichier de configuration lu sur stdin en enlevant les commentaires
|
||
et les lignes vides.
|
||
Avec $1==-m, fusionner les lignes qui se terminent par \ avec les suivantes
|
||
Comme filter_conf(), les commentaires doivent être sur une ligne à part.
|
||
Contrairement à filter_conf, il n'est pas nécessaire que le caractère '#' soit
|
||
en début de ligne: il peut apparaitre après des espaces et des tabulations. De
|
||
même, une ligne qui ne contient que des espaces et des tabulations est
|
||
considérée comme vide.
|
||
}}}
|
||
!! {{{filter_conf}}}
|
||
{{{
|
||
filtrer un fichier de configuration lu sur stdin en enlevant les commentaires
|
||
et les lignes vides. Une ligne n'est considérée commentaire que si '#' est un
|
||
première position. Utiliser filter_comment() si les commentaire peuvent
|
||
commencer par des caractères espace et tabulation.
|
||
Si $1==-m, fusionner les lignes qui se terminent par \ avec les suivantes
|
||
}}}
|
||
!! {{{is_archive}}}
|
||
{{{
|
||
tester si l'extension d'un fichier indique que c'est une archive
|
||
}}}
|
||
!! {{{extract_archive}}}
|
||
{{{
|
||
Extraire le contenu de l'archive $1 dans le répertoire ${2:-.}
|
||
}}}
|
||
!! {{{get_archive_basename}}}
|
||
{{{
|
||
Obtenir le nom de base de l'archive $1
|
||
}}}
|
||
!! {{{get_archive_appname}}}
|
||
{{{
|
||
Obtenir le nom probable de l'application ou du framework contenu dans
|
||
l'archive $1, e.g:
|
||
get_archive_versionsuffix app-0.1.tgz
|
||
--> app
|
||
}}}
|
||
!! {{{get_archive_versionsuffix}}}
|
||
{{{
|
||
Obtenir la valeur probable de la version de l'application ou du framework
|
||
contenu dans l'archive $1, avec le caractère de séparation, e.g:
|
||
get_archive_versionsuffix app-0.1.tgz
|
||
--> -0.1
|
||
}}}
|
||
!! {{{get_archive_version}}}
|
||
{{{
|
||
Obtenir la valeur probable de la version de l'application ou du framework
|
||
contenu dans l'archive $1, e.g:
|
||
get_archive_versionsuffix app-0.1.tgz
|
||
--> 0.1
|
||
}}}
|
||
!! {{{dump_usernames}}}
|
||
{{{
|
||
Placer dans le tableau $1 la liste des utilisateurs du système
|
||
Cette implémentation consulte /etc/passwd et liste tous les utilisateurs dont
|
||
le homedir se trouve dans /home, et dont l'uid est >=500
|
||
}}}
|
||
!! {{{resolv_ips}}}
|
||
{{{
|
||
Placer dans le tableau $1(=ips) la liste des adresses ip correspondant à
|
||
l'hôte $2. La résolution est effectuée avec la commande host.
|
||
}}}
|
||
!! {{{resolv_hosts}}}
|
||
{{{
|
||
Placer dans le tableau $1(=hosts) la liste des hôtes correspondant à
|
||
l'adresse ip $2. La résolution est effectuée avec la commande host.
|
||
}}}
|
||
!! {{{runscript_as}}}
|
||
{{{
|
||
Utiliser bash pour lancer le script $2 avec les arguments $3..$n afin qu'il
|
||
tourne avec les droits d'un autre user $1(=root). Si $2=exec, utiliser exec
|
||
pour lancer le script et ses arguments qui commencent à partir de $3, ce qui
|
||
fait que cette fonction ne retourne pas.
|
||
Attention! cette fonction ne teste pas avec si on est déjà le user $1. Il y a
|
||
donc un risque de boucle infinie si on ne teste pas le user courant.
|
||
}}}
|
||
!! {{{runscript_as_root}}}
|
||
{{{
|
||
Utiliser bash pour lancer le script $1 avec les arguments $2..$* avec les
|
||
droits de root. Si on est déjà en root, le script est simplement lancé. Sinon,
|
||
utiliser runscript_as pour lancer le script avec les droits de root.
|
||
}}}
|
||
!! {{{run_as}}}
|
||
{{{
|
||
Relancer le script courant afin qu'il tourne avec les droits d'un autre user
|
||
$1(=root)
|
||
Attention! cette fonction ne teste pas avec si on est déjà ce user. Il y a
|
||
donc un risque de boucle infinie si on ne teste pas le user courant.
|
||
Il faut lancer cette fonction avec les arguments du script en cours. Par
|
||
exemple::
|
||
run_as root "$@"
|
||
Si $2=--noexec, on n'utilise pas la fonction exec, ce qui fait que la fonction
|
||
retourne. Sinon, on peut considérer que cette fonction ne retourne jamais
|
||
}}}
|
||
!! {{{run_as_root}}}
|
||
{{{
|
||
relancer le script courant afin qu'il tourne en root si on est pas en déjà
|
||
root. Sinon, cette fonction est un nop.
|
||
}}}
|
||
!! {{{check_user}}}
|
||
{{{
|
||
Vérifier si le user courant est l'un des users $1..*
|
||
}}}
|
||
!! {{{ensure_user}}}
|
||
{{{
|
||
Vérifier si le user courant est l'un des users $1..N où N est la position du
|
||
premier "--". Si ce n'est pas le cas et que l'on est root, relancer le script
|
||
avec ce user grâce à la fonction run_as()
|
||
Retourner 1 si ce n'était pas le bon user. Retourner 10 si ce n'était pas le
|
||
bon user et que l'on n'est pas root (donc impossible à priori de relancer le
|
||
script avec le bon user). Retourner 11 si l'utilisateur a choisi de ne pas
|
||
lancer le script avec le bon utilisateur
|
||
A utiliser de cette manière:
|
||
if ensure_user users... -- args; then
|
||
# ... on est avec le bon user; faire les opérations
|
||
else
|
||
# ... ce code n'est exécuté que si une erreur s'est produite, ou si ce
|
||
# n'était pas le bon user et que l'option --noexec est utilisée
|
||
fi
|
||
}}}
|
||
!! {{{check_hostname}}}
|
||
{{{
|
||
Vérifier si le hostname courant est l'un des hôtes $1..*
|
||
localhost matche toujours
|
||
}}}
|
||
!! {{{check_userhostname}}}
|
||
{{{
|
||
Vérifier si le hostname et éventuellement le user courant sont l'un des
|
||
arguments $1..*
|
||
Chaque argument est de la forme [user@]host, mais le test ne tient compte que
|
||
du nom de l'hôte, sans tenir compte du domaine. Si le user n'est pas spécifié,
|
||
le test ne porte que sur hostname.
|
||
}}}
|
||
!! {{{ensure_hostname}}}
|
||
{{{
|
||
Vérifier si le hostname et le user courant sont l'un des arguments $1..*
|
||
Chaque argument est de la forme [user@]host, mais le test ne tient compte que
|
||
du nom de l'hôte, sans tenir compte du domaine.
|
||
Si user est spécifié:
|
||
- Si on est sur le bon hôte mais pas le bon user, ensure_user est lancé avec
|
||
l'argument approprié pour relancer le script
|
||
Si l'argument était de la forme userhost:path, le répertoire courant est
|
||
changé avant de lancer le script avec le bon utilisateur.
|
||
Sinon (si user n'est pas spécifié):
|
||
- Si on n'est pas sur le bon hôte, après confirmation le script est lancé avec
|
||
ssh sur l'hôte distant avec le user spécifié (qui vaut par défaut root). Ce
|
||
script DOIT exister sur l'hôte distant avec le même chemin.
|
||
Si l'argument était de la forme userhost:path, le répertoire courant distant
|
||
est changé avant de lancer le script
|
||
Si on est avec le bon user sur le bon hôte, le répertoire courant n'est jamais
|
||
changé.
|
||
Retourner 1 si ce n'était pas le bon user. Retourner 10 si ce n'était pas le
|
||
bon user et que l'on n'est pas root (donc impossible à priori de relancer le
|
||
script avec le bon user). Retourner 11 si l'utilisateur a choisi de ne pas
|
||
lancer le script sur l'hôte distant. Retourner 12 si une erreur s'est produite
|
||
avec ssh.
|
||
A utiliser de cette manière:
|
||
if ensure_hostname user@host... -- args; then
|
||
# ... on est [avec le bon user] sur le bon hôte; faire les opérations
|
||
else
|
||
# ... ce code n'est exécuté que si une erreur s'est produite, ou si ce
|
||
# n'était pas le bon user et que l'option --noexec est utilisée
|
||
fi
|
||
}}}
|
||
!! {{{sqvals}}}
|
||
!! {{{quoted_values}}}
|
||
!! {{{formatcsv}}}
|
||
!! {{{awkdef}}}
|
||
{{{
|
||
Afficher un script à insérer au début d'un script awk. Ce script définit dans
|
||
une section BEGIN{} les variables donnés en arguments, et avec l'option -f,
|
||
des fonctions utiles. Si une valeur ne ressemble pas à une définition de
|
||
variable, l'analyse des variables s'arrête et le reste des arguments est
|
||
inséré tel quel. Cette fonction peut être utilisée de cette manière:
|
||
awk "$(awkdef -f var=value... 'script awk')"
|
||
Normalement, les variables définies sont scalaires, avec une syntaxe de la
|
||
forme var[:type]=value. type peut valoir str ou int, pour forcer le type de la
|
||
variable créée dans awk.
|
||
Il est possible d'utiliser la syntaxe awk_array[@]=bash_array ou array[@] (qui
|
||
est équivalente à array[@]=array) pour initialiser le tableau awk_array, qui
|
||
contiendra toute les valeurs du tableau nommé bash_array, avec les indices de
|
||
1 à N, N étant le nombre d'éléments du tableau bash_array. La variable
|
||
awk_array_count est aussi initialisée, et contient le nombre d'éléments du
|
||
tableau
|
||
La syntaxe "awk_array[@]=<\n..." permet de spécifier les valeurs du tableau,
|
||
une par ligne, e.g:
|
||
$'values[@]=<\nvalue1\nvalue2'
|
||
pour un tableau values qui contiendra deux valeurs: value1 et value2
|
||
Avec l'option -f, des fonctions supplémentaires sont définies. Elles sont
|
||
décrites dans le module awk.
|
||
}}}
|
||
!! {{{lawkrun}}}
|
||
{{{
|
||
wrapper pour lancer awk avec un script préparé par awkdef. Les définitions et
|
||
les arguments sont séparés par --, e.g.
|
||
awkrun var0=value0 var1=value1 script -- input0 input1
|
||
}}}
|
||
!! {{{cawkrun}}}
|
||
!! {{{awkrun}}}
|
||
!! {{{lf_trylock}}}
|
||
{{{
|
||
USAGE
|
||
lf_trylock [-h max_hours] /path/to/lockfile
|
||
OPTIONS
|
||
lockfile
|
||
fichier qui doit contenir le verrou
|
||
-h max_hours
|
||
Nombre d'heures (par défaut 4) au bout duquel afficher stale
|
||
Sinon, afficher locked
|
||
Retourne 0 si le verrou a été placé correctement. Il ne faut pas oublier de
|
||
supprimer le fichier. Le mieux est de le faire supprimer automatiquement par
|
||
autoclean:
|
||
lockfile=...
|
||
case "$(lf_trylock "$lockfile")" in
|
||
locked) ...;;
|
||
stale) ...;;
|
||
esac
|
||
autoclean "$lockfile"
|
||
Sinon, retourner 1 et afficher l'une des deux valeurs suivantes:
|
||
- stale si le verrou a déjà été placé, depuis au moins max_hours heures
|
||
- locked si le verrou a déjà été placé
|
||
- retry si une erreur s'est produite pendant la pose du verrou ou sa
|
||
lecture. Cela peut se produire si les droits ne sont pas suffisants pour
|
||
écrire dans le répertoire destination, ou si le fichier a été supprimé
|
||
avant sa lecture (race-condition). Dans ce dernier cas, reessayer permettra
|
||
d'acquérir le verrou
|
||
}}}
|
||
!! {{{pidfile_set}}}
|
||
{{{
|
||
USAGE
|
||
pidfile_set [-p pid] /path/to/pidfile
|
||
OPTIONS
|
||
pidfile
|
||
fichier qui doit contenir le pid du script
|
||
-p pid
|
||
spécifier le pid. par défaut, utiliser $$
|
||
-r si pidfile existe mais que le processus ne tourne plus, faire
|
||
comme si le fichier n'existe pas.
|
||
Retourner 0 si le pid a été correctement écrit dans le fichier. Ce fichier
|
||
sera supprimé automatiquement en fin de script
|
||
Retourner 1 si le fichier existe déjà et que le processus est en train de
|
||
tourner.
|
||
Retourner 2 si le fichier existe déjà mais que le processus ne tourne plus.
|
||
Retourner 10 si autre erreur grave s'est produite (par exemple, s'il manque le
|
||
chemin vers pidfile, ou si le fichier n'est pas accessible en écriture.)
|
||
}}}
|
||
!! {{{pidfile_check}}}
|
||
{{{
|
||
USAGE
|
||
pidfile_check /path/to/pidfile
|
||
OPTIONS
|
||
pidfile
|
||
fichier qui doit contenir le pid d'un processus
|
||
Cette fonction permet de vérifier si le processus associé à un fichier de pid
|
||
est en train de tourner.
|
||
Retourner 0 si le fichier de pid existe et que le process du pid spécifié est
|
||
en train de tourner. Retourner 1 sinon.
|
||
Retourner 10 si erreur grave s'est produite (par exemple, s'il manque le
|
||
chemin vers pidfile, ou si le fichier n'est pas accessible en lecture.)
|
||
}}}
|
||
!! {{{page_maybe}}}
|
||
{{{
|
||
Utiliser less, si possible, pour afficher le flux en entrée. Si le terminal
|
||
n'est pas interactif ou si le nombre de lignes en entrée est inférieur au
|
||
nombre de lignes du terminal, afficher simplement le flux.
|
||
Les arguments de cette fonction sont passés à less
|
||
}}}
|
||
!! {{{utools_local}}}
|
||
{{{
|
||
Afficher les commandes pour rendre locales certaines variables en fonction des
|
||
arguments:
|
||
- opts rend locale args, pour utiliser parse_opts() à l'intérieur d'une
|
||
fonction.
|
||
- verbosity et interaction rendent respectivement locales __verbosity et
|
||
__interaction. Ceci est utile pour pouvoir appeler sans risque de pollution
|
||
de l'environnement une fonction qui utilise parse_opts() avec les
|
||
définitions de PRETTYOPTS.
|
||
Si aucun arguments n'est fourni, toutes les définitions sont affichées.
|
||
}}}
|
||
!! {{{stdredir}}}
|
||
{{{
|
||
Lancer la commande $4..@ en redirigeant stdin depuis $1, stdout vers $2,
|
||
stderr vers $3. Si $1 est vide ou vaut /dev/stdin, la redirection n'est
|
||
pas faite. Si $2 est vide ou vaut /dev/stdout, la redirection n'est pas
|
||
faite. Si $3 est vide ou vaut /dev/stderr, la redirection n'est pas faite.
|
||
Cette fonction existe parce que sur certaines versions de bash, il semble
|
||
que les redirections /dev/std* ne sont pas traitées de façon particulière.
|
||
De plus, sur des technologies telles que OpenVZ, les chemins /dev/std* ne
|
||
sont pas créés (parce que /proc/self/fd/* n'est pas accessible). Donc,
|
||
dans de rares cas où le script tourne sur OpenVZ avec une version de bash
|
||
qui est buggée, la redirection n'est pas faite correctement.
|
||
}}}
|
||
!! {{{isatty}}}
|
||
{{{
|
||
tester si STDOUT n'est pas une redirection
|
||
}}}
|
||
!! {{{in_isatty}}}
|
||
{{{
|
||
tester si STDIN n'est pas une redirection
|
||
}}}
|
||
!! {{{out_isatty}}}
|
||
{{{
|
||
tester si STDOUT n'est pas une redirection
|
||
}}}
|
||
!! {{{err_isatty}}}
|
||
{{{
|
||
tester si STDERR n'est pas une redirection
|
||
}}}
|
||
!! {{{die}}}
|
||
!! {{{die_unless}}}
|
||
{{{
|
||
Afficher $-1 et quitter le script avec die() si la commande $1..-2 retourne
|
||
FAUX
|
||
}}}
|
||
!! {{{eerror_unless}}}
|
||
{{{
|
||
Afficher $-1 avec eerror() et retourner $? si la commande $1..-2 retourne FAUX
|
||
}}}
|
||
!! {{{die_if}}}
|
||
{{{
|
||
Afficher $-1 et quitter le script avec die() si la commande $1..-2 retourne
|
||
VRAI
|
||
}}}
|
||
!! {{{eerror_if}}}
|
||
{{{
|
||
Afficher $-1 avec eerror() et retourner le code d'erreur 1 si la commande
|
||
$1..-2 retourne VRAI
|
||
}}}
|
||
!! {{{noerror}}}
|
||
{{{
|
||
lancer la commande "$@" et masquer son code de retour
|
||
}}}
|
||
!! {{{noout}}}
|
||
{{{
|
||
lancer la commande "$@" en supprimant sa sortie standard
|
||
}}}
|
||
!! {{{noerr}}}
|
||
{{{
|
||
lancer la commande "$@" en supprimant sa sortie d'erreur
|
||
}}}
|
||
!! {{{tooenc}}}
|
||
{{{
|
||
Transformer la valeur $1 de l'encoding $2(=$OENC) vers l'encoding de sortie
|
||
$3=($UTOOLS_OUTPUT_ENCODING)
|
||
}}}
|
||
!! {{{uecho}}}
|
||
!! {{{tooenc_}}}
|
||
{{{
|
||
Transformer la valeur $1 de l'encoding $2(=$OENC) vers l'encoding de sortie
|
||
$3=($UTOOLS_OUTPUT_ENCODING)
|
||
}}}
|
||
!! {{{uecho_}}}
|
||
!! {{{toienc}}}
|
||
{{{
|
||
Transformer la valeur $1 de $2(=$IENC) vers l'encoding d'entrée
|
||
$3(=$UTOOLS_INPUT_ENCODING)
|
||
}}}
|
||
!! {{{uread}}}
|
||
{{{
|
||
Lire une valeur sur stdin et la placer dans la variable $1. On assume que la
|
||
valeur en entrée est encodée dans l'encoding d'entrée par défaut
|
||
}}}
|
||
!! {{{stooenc}}}
|
||
{{{
|
||
Transformer la valeur lue sur stdin de $OENC vers l'encoding de sortie par
|
||
défaut ($UTOOLS_OUTPUT_ENCODING)
|
||
}}}
|
||
!! {{{stoienc}}}
|
||
{{{
|
||
Transformer la valeur lue sur stdin de $IENC vers l'encoding d'entrée par
|
||
défaut ($UTOOLS_INPUT_ENCODING)
|
||
}}}
|
||
!! {{{elogto}}}
|
||
{{{
|
||
Activer UTOOLS_EDATE et rediriger STDOUT et STDERR vers le fichier $1
|
||
Si deux fichiers sont spécifiés, rediriger STDOUT vers $1 et STDERR vers $2
|
||
Si aucun fichier n'est spécifié, ne pas faire de redirection
|
||
Si la redirection est activée, forcer l'utilisation de l'encoding UTF8
|
||
Si UTOOLS_ELOG_OVERWRITE=1, alors le fichier en sortie est écrasé. Sinon, les
|
||
lignes en sortie lui sont ajoutées
|
||
}}}
|
||
!! {{{set_verbosity}}}
|
||
!! {{{set_interaction}}}
|
||
!! {{{show_error}}}
|
||
{{{
|
||
tester respectivement si on doit afficher les messages d'erreur,
|
||
d'avertissement, d'information, de debug
|
||
}}}
|
||
!! {{{show_warn}}}
|
||
!! {{{show_info}}}
|
||
!! {{{show_verbose}}}
|
||
!! {{{show_debug}}}
|
||
!! {{{check_verbosity}}}
|
||
!! {{{get_verbosity_option}}}
|
||
!! {{{check_interaction}}}
|
||
!! {{{is_interaction}}}
|
||
!! {{{get_interaction_option}}}
|
||
!! {{{eflush}}}
|
||
{{{
|
||
Afficher les messages en attente
|
||
}}}
|
||
!! {{{eclearp}}}
|
||
{{{
|
||
Supprimer les message en attente
|
||
}}}
|
||
!! {{{eerror}}}
|
||
{{{
|
||
Afficher un message d'erreur
|
||
}}}
|
||
!! {{{ewarn}}}
|
||
{{{
|
||
Afficher un message d'avertissement
|
||
}}}
|
||
!! {{{enote}}}
|
||
{{{
|
||
Afficher un message d'information de même niveau qu'un avertissement
|
||
}}}
|
||
!! {{{ebanner}}}
|
||
{{{
|
||
Afficher un message très important encadré, puis attendre 5 secondes
|
||
}}}
|
||
!! {{{eimportant}}}
|
||
{{{
|
||
Afficher un message très important
|
||
}}}
|
||
!! {{{eattention}}}
|
||
{{{
|
||
Afficher un message important
|
||
}}}
|
||
!! {{{einfo}}}
|
||
{{{
|
||
Afficher un message d'information
|
||
}}}
|
||
!! {{{eecho}}}
|
||
{{{
|
||
Afficher un message d'information sans préfixe
|
||
}}}
|
||
!! {{{eecho_}}}
|
||
!! {{{edebug}}}
|
||
{{{
|
||
Afficher un message de debug
|
||
}}}
|
||
!! {{{trace}}}
|
||
{{{
|
||
Afficher la commande $1..@, la lancer, puis afficher son code d'erreur si une
|
||
erreur se produit
|
||
}}}
|
||
!! {{{trace_error}}}
|
||
{{{
|
||
Lancer la commande $1..@, puis afficher son code d'erreur si une erreur se
|
||
produit. La différence avec trace() est que la commande n'est affichée que si
|
||
une erreur se produit.
|
||
}}}
|
||
!! {{{etitle}}}
|
||
{{{
|
||
Afficher le titre $1, qui est le début éventuel d'une section. Les section
|
||
imbriquées sont affichées indentées. La section n'est pas terminée, et il faut
|
||
la terminer explicitement avec eend, sauf dans certains cas précis:
|
||
- Si $2..$* est spécifié, c'est une commande. Lancer la commande dans le
|
||
contexte de la section. Puis, la section est automatiquement terminée sauf si
|
||
l'option -s est spécifiée, auquel cas la section reste ouverte. Si l'option -p
|
||
est spécifiée, eclearp() est appelé pour purger les messages en attente
|
||
- Dans le cas contraire, l'option -s est ignorée: la section doit toujours
|
||
être terminée explicitement.
|
||
La fonction etitled() est comme etitle(), mais le titre n'est pas affiché
|
||
immédiatement. L'affichage effectif est effectué dès qu'une fonction e* est
|
||
utilisée. Ceci permet, avec la fonction eclearp(), de ne pas afficher de titre
|
||
pour une section vide.
|
||
}}}
|
||
!! {{{etitled}}}
|
||
!! {{{estep}}}
|
||
{{{
|
||
Afficher la description d'une opération. Cette fonction est particulièrement
|
||
appropriée dans le contexte d'un etitle.
|
||
Les variantes e (error), w (warning), n (note), i (info) permettent d'afficher
|
||
des couleurs différentes, mais toutes sont du niveau info.
|
||
}}}
|
||
!! {{{estepe}}}
|
||
!! {{{estepw}}}
|
||
!! {{{estepn}}}
|
||
!! {{{estepi}}}
|
||
!! {{{estep_}}}
|
||
!! {{{estepe_}}}
|
||
!! {{{estepw_}}}
|
||
!! {{{estepn_}}}
|
||
!! {{{estepi_}}}
|
||
!! {{{ebegin}}}
|
||
{{{
|
||
Afficher le message $1, qui décrit le début d'une opération. Cette fonction
|
||
débute une section, qu'il faut terminer avec eend.
|
||
Si $2..$* est spécifié, c'est une commande. Lancer la commande dans le
|
||
contexte de la section. Puis, la section est terminée automatiquement, sauf si
|
||
l'option -s est spécifiée, auquel cas la section reste ouverte.
|
||
}}}
|
||
!! {{{edot}}}
|
||
{{{
|
||
Afficher une étape d'une opération, matérialisée par un point '.' ou une
|
||
croix 'x' en cas de succès ou d'erreur. Cette fonction est particulièrement
|
||
appropriée dans le contexte d'un ebegin.
|
||
}}}
|
||
!! {{{edotw}}}
|
||
{{{
|
||
Afficher un avertissement comme étape d'une opération, matérialisée par une
|
||
lettre 'w' (typiquement de couleur jaune). Cette fonction est particulièrement
|
||
appropriée dans le contexte d'un ebegin.
|
||
}}}
|
||
!! {{{ewait}}}
|
||
{{{
|
||
Afficher les étapes d'une opération qui dure, matérialisées par des '+' toutes
|
||
les secondes tant que le processus $1 tourne.
|
||
A utiliser de cette manière:
|
||
ebegin "msg"
|
||
cmd &
|
||
ewait $!
|
||
eend
|
||
}}}
|
||
!! {{{eend}}}
|
||
{{{
|
||
Terminer une section.
|
||
Avec l'option -c, remettre à zéro toutes les informations de section
|
||
Si la section en cours est un ebegin, afficher la fin de l'opération: [ok] ou
|
||
[error] en fonction du code de retour de la dernière commande (ou de $1 si
|
||
cette valeur est donnée)
|
||
Si la section en cours est un etitle, marquer la fin de la section concernée
|
||
par le titre.
|
||
}}}
|
||
!! {{{elinedots}}}
|
||
{{{
|
||
Afficher un message comme avec ebegin "$1", puis afficher un point '.' pour
|
||
chaque ligne lue sur stdin. Cela permet de suivre une opération. En mode
|
||
DEBUG, afficher la ligne affichée plutôt qu'un point.
|
||
Si $2..$* sont spécifiés, lancer la commande et suivre sa sortie. Ainsi,
|
||
'elinedots msg cmd args' est un raccourci pour 'cmd args | elinedots msg'
|
||
}}}
|
||
!! {{{ask_yesno}}}
|
||
{{{
|
||
Afficher le message $1 suivi de [oN] ou [On] suivant que $2 vaut O ou N, puis
|
||
lire la réponse. Retourner 0 si la réponse est vrai, 1 sinon.
|
||
Si $1 est une option, elle est utilisée avec check_interaction pour savoir si
|
||
on est en mode interactif ou non. A ce moment-là, les valeurs sont décalées
|
||
($2=message, $3=default)
|
||
Si $2 vaut C, la valeur par défaut est N si on est interactif, O sinon
|
||
Si $2 vaut X, la valeur par défaut est O si on est interactif, N sinon
|
||
}}}
|
||
!! {{{read_value}}}
|
||
{{{
|
||
Afficher le message $1 suivi de la valeur par défaut [$3] si elle est non
|
||
vide, puis lire la valeur donnée par l'utilisateur. Cette valeur doit être non
|
||
vide si $4(=O) est vrai. La valeur saisie est placée dans la variable
|
||
$2(=value)
|
||
Si $1 est une option, elle est utilisée avec check_interaction pour savoir si
|
||
on est en mode interactif ou non. A ce moment-là, les valeurs sont décalées
|
||
($2=message, $3=variable, $4=default, $5=required)
|
||
En mode non interactif, c'est la valeur par défaut qui est sélectionnée. Si
|
||
l'utilisateur requière que la valeur soit non vide et que la valeur par défaut
|
||
est vide, afficher un message d'erreur et retourner faux
|
||
read_password() est comme read_value(), mais la valeur saisie n'est pas
|
||
affichée, ce qui la rend appropriée pour la lecture d'un mot de passe.
|
||
}}}
|
||
!! {{{read_password}}}
|
||
!! {{{simple_menu}}}
|
||
{{{
|
||
Afficher un menu simple dont les éléments sont les valeurs du tableau
|
||
$2(=options). L'option choisie est placée dans la variable $1(=option)
|
||
-t TITLE: spécifier le titre du menu
|
||
-m YOUR_CHOICE: spécifier le message d'invite pour la sélection de l'option
|
||
-d DEFAULT: spécifier l'option par défaut. Par défaut, prendre la valeur
|
||
actuelle de la variable $1(=option)
|
||
}}}
|
||
!! {{{actions_menu}}}
|
||
{{{
|
||
Afficher un menu dont les éléments sont les valeurs du tableau $4(=options),
|
||
et une liste d'actions tirées du tableau $3(=actions). L'option choisie est
|
||
placée dans la variable $2(=option). L'action choisie est placée dans la
|
||
variable $1(=action)
|
||
Un choix est saisi sous la forme [action]num_option
|
||
-t TITLE: spécifier le titre du menu
|
||
-m OPT_YOUR_CHOICE: spécifier le message d'invite pour la sélection de
|
||
l'action et de l'option
|
||
-M ACT_YOUR_CHOICE: spécifier le message d'invite dans le cas où aucune option
|
||
n'est disponible. Dans ce cas, seules les actions vides sont possibles.
|
||
-e VOID_ACTION: spécifier qu'une action est vide, c'est à dire qu'elle ne
|
||
requière pas d'être associée à une option. Par défaut, la dernière action
|
||
est classée dans cette catégorie puisque c'est l'action "quitter"
|
||
-d DEFAULT_ACTION: choisir l'action par défaut. par défaut, c'est la première
|
||
action.
|
||
-q QUIT_ACTION: choisir l'option "quitter" qui provoque la sortie du menu sans
|
||
choix. par défaut, c'est la dernière action.
|
||
-o DEFAULT_OPTION: choisir l'option par défaut. par défaut, prendre la valeur
|
||
actuelle de la variable $2(=option)
|
||
}}}
|
||
!! {{{autoclean}}}
|
||
{{{
|
||
Ajouter $1..$n à la liste des fichiers à supprimer à la fin du programme
|
||
}}}
|
||
!! {{{ac_cleanall}}}
|
||
{{{
|
||
Supprimer *tous* les fichiers temporaires gérés par autoclean tout de suite.
|
||
}}}
|
||
!! {{{ac_clean}}}
|
||
{{{
|
||
Supprimer les fichier temporaires $1..$* si et seulement s'ils ont été générés
|
||
par ac_set_tmpfile ou ac_set_tmpdir
|
||
}}}
|
||
!! {{{ac_set_tmpfile}}}
|
||
{{{
|
||
Créer un fichier temporaire avec le motif $2, l'ajouter à la liste des
|
||
fichiers à supprimer en fin de programme, et mettre sa valeur dans la
|
||
variable $1
|
||
En mode debug, si ($5 est vide ou ${!5} est une valeur vraie), et si $3 n'est
|
||
pas vide, prendre ce fichier au lieu de générer un nouveau fichier
|
||
temporaire. Si $4==keep, ne pas écraser le fichier $3 s'il existe.
|
||
}}}
|
||
!! {{{ac_set_tmpdir}}}
|
||
{{{
|
||
Créer un répertoire temporaire avec le motif $2, l'ajouter à la liste des
|
||
fichiers à supprimer en fin de programme, et mettre sa valeur dans la
|
||
variable $1
|
||
En mode debug, si ($4 est vide ou ${!4} est une valeur vraie), et si $3 n'est
|
||
pas vide, prendre ce nom de répertoire au lieu de créer un nouveau répertoire
|
||
temporaire
|
||
}}}
|
||
!! {{{debug_tee}}}
|
||
{{{
|
||
En mode debug, passer le flux à travers la commande 'tee "$@"'. Sinon, le flux
|
||
est passé inchangé.
|
||
}}}
|
||
!! {{{get_user_defaults_file}}}
|
||
{{{
|
||
Afficher le chemin vers le fichier utilisateur à éditer pour qu'il soit chargé
|
||
par 'set_defaults $1'. Ce fichier n'existe pas forcément; il faut peut-être le
|
||
créer.
|
||
}}}
|
||
!! {{{get_defaults_files}}}
|
||
{{{
|
||
Initialiser le tableau $1(=defaults) avec la liste des fichiers qui seraient
|
||
chargés par la commande 'set_defaults $2..N'
|
||
}}}
|
||
!! {{{set_defaults}}}
|
||
{{{
|
||
Pour chaque argument, sourcer /etc/default/$arg *et* (en priorité
|
||
~/etc/default.$HOSTNAME/$arg ou à défaut ~/etc/default/$arg) si ceux-ci
|
||
existent. *Sinon*, lire $scriptdir/lib/default/$arg si ce fichier existe
|
||
}}}
|
||
!! {{{myhost}}}
|
||
{{{
|
||
Afficher le nom d'hôte pleinement qualifié, en faisant appel à la commande
|
||
hostname. Par comparaison, $MYHOST est fourni par bash.
|
||
}}}
|
||
!! {{{myhostname}}}
|
||
{{{
|
||
Afficher le nom d'hôte sans domaine, en faisant appel à la commande
|
||
hostname. Par comparaison, $MYHOSTNAME est fourni par bash.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/base.ulib" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/bash" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/cgi" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{is_cgi}}}
|
||
{{{
|
||
Tester si on est lancé comme un script CGI
|
||
}}}
|
||
!! {{{ctype_header}}}
|
||
{{{
|
||
Générer une en-tête Content-Type: avec la valeur $1[=text/html]
|
||
}}}
|
||
!! {{{cdisp_header}}}
|
||
{{{
|
||
Générer une en-tête Content-Disposition: avec le type $2[=attachment] et
|
||
le nom de fichier $1[=result]
|
||
}}}
|
||
!! {{{nocache_header}}}
|
||
{{{
|
||
Générer des en-têtes qui désactivent la mise en cache du contenu
|
||
}}}
|
||
!! {{{cgicontent}}}
|
||
{{{
|
||
Générer les en-têtes nécessaire avant de servir le contenu.
|
||
$1(=text/html) est le type de contenu. S'il faut servir le contenu avec
|
||
une disposition "attachment", $2 est le nom de fichier à proposer à
|
||
l'utilisateur. Si $3 est spécifié, c'est le chemin vers le fichier dont le
|
||
contenu doit être servi.
|
||
$4..* sont des en-têtes supplémentaires à rajouter
|
||
}}}
|
||
!! {{{cgicontent_nocache}}}
|
||
{{{
|
||
Générer les en-têtes nécessaire avant de servir le contenu. Rajouter les
|
||
entêtes pour désactiver la mise en cache.
|
||
$1(=text/html) est le type de contenu. S'il faut servir le contenu avec
|
||
une disposition "attachment", $2 est le nom de fichier à proposer à
|
||
l'utilisateur. Si $3 est spécifié, c'est le chemin vers le fichier dont le
|
||
contenu doit être servi.
|
||
$4..* sont des en-têtes supplémentaires à rajouter
|
||
}}}
|
||
!! {{{cgierror}}}
|
||
{{{
|
||
Afficher les en-têtes pour désactiver la mise en cache, puis afficher un
|
||
message d'erreur puis arrêter le script
|
||
}}}
|
||
!! {{{cgiredirect}}}
|
||
{{{
|
||
Afficher les en-têtes pour rediriger le client vers la page $1 puis
|
||
arrêter le script
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/cgisupport" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{cgiparams}}}
|
||
!! {{{cgilsxml}}}
|
||
!! {{{cgiupload}}}</pre>
|
||
</div>
|
||
<div title="ulib/compat" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/conf" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{conf_enable}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, activer les paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name[=value]
|
||
Dans tous les cas, toutes les directives de ce nom sont recherchées et
|
||
décommentées. Si value est précisée, les directives sont mises à jour. Si
|
||
la directive ne figure pas dans le fichier, elle y est rajoutée à la fin
|
||
avec la valeur spécifiée.
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{conf_enableq}}}
|
||
{{{
|
||
Comme conf_enable(), mais s'assure que les valeurs sont quotées dans le
|
||
fichier. Ceci permet de stocker des valeurs avec des espaces ou des
|
||
caractères spéciaux.
|
||
}}}
|
||
!! {{{conf_disable}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, désactiver les paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name[=value]
|
||
Toutes les directives de ce noms sont recherchées et commentées. La valeur
|
||
si elle est spécifiée, est ignorée. Si la directive ne figure pas dans le
|
||
fichier, c'est un NOP.
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{conf_append}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, augmenter les valeurs des variables
|
||
correspondant aux paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une variable du fichier de
|
||
configuration, et doit être de la forme name=value
|
||
Une ligne 'name="${name:+$name:}$value"' est générée à la fin du fichier
|
||
de configuration.
|
||
Par défaut, le séparateur CONF_APPEND_SEP vaut ':', mais il est possible
|
||
de changer cette valeur, de façon globale
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{conf_array_append}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, augmenter les valeurs des variables
|
||
de tableau correspondant aux paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une variable du fichier de
|
||
configuration, et doit être de la forme name=value
|
||
Une ligne name=("${name[@]}" "$value") est générée à la fin du fichier de
|
||
configuration
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{conf_check}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, tester si tous les paramètres $2..*
|
||
sont présents.
|
||
Chaque argument de cette fonction correspond à une variable du fichier de
|
||
configuration, et doit être de la forme name[=value]
|
||
Si une valeur est spécifiée, vérifier que le fichier contient la valeur
|
||
correspondante. Sinon, tester uniquement la présence de la directive.
|
||
}}}
|
||
!! {{{aconf_enable}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, activer les paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name[=value]
|
||
Toutes les directives de ce nom sont recherchées et décommentées, et la
|
||
valeur mise à jour. Si la directive ne figure pas dans le fichier, elle y
|
||
est rajoutée à la fin. A cause du mode opératoire, cette fonction ne
|
||
convient pas pour les directives dont le nom peut apparaitre plusieurs
|
||
fois dans le fichier
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{aconf_disable}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, désactiver les paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name[=value]
|
||
Si la valeur est précisée, la directive correspondant à ce nom et cette
|
||
valeur est recherchée et commentée. Sinon, toutes les directives de ce
|
||
noms sont recherchées et commentées. Si la directive ne figure pas dans le
|
||
fichier, c'est un NOP.
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{aconf_append}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, ajouter des directives correspondant
|
||
aux paramètres $2..*
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name=value
|
||
Une ligne '$name $value' est ajoutée à la fin du fichier de configuration
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
}}}
|
||
!! {{{aconf_array_append}}}
|
||
!! {{{aconf_check}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, tester si tous les paramètres $2..*
|
||
sont présents.
|
||
Chaque argument de cette fonction correspond à une variable du fichier de
|
||
configuration, et doit être de la forme name[=value]
|
||
Si une valeur est spécifiée, vérifier que le fichier contient la valeur
|
||
correspondante. Sinon, tester uniquement la présence de la directive.
|
||
}}}
|
||
!! {{{mconf_enable}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, activer les paramètres $3..* de la
|
||
section $2
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name[=value]
|
||
Toutes les directives de ce nom sont recherchées et décommentées, et la
|
||
valeur mise à jour. Si la directive ne figure pas dans le fichier, elle y
|
||
est rajoutée à la fin. A cause du mode opératoire, cette fonction ne
|
||
convient pas pour les directives dont le nom peut apparaitre plusieurs
|
||
fois dans le fichier
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
Cette fonction nécessite gawk et ignore la locale
|
||
}}}
|
||
!! {{{mconf_disable}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, désactiver les paramètres $3..* de la
|
||
section $2.
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name[=value]
|
||
Si la valeur est précisée, la directive correspondant à ce nom et cette
|
||
valeur est recherchée et commentée. Sinon, toutes les directives de ce
|
||
noms sont recherchées et commentées. Si la directive ne figure pas dans le
|
||
fichier, c'est un NOP.
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
Cette fonction nécessite gawk et ignore la locale
|
||
}}}
|
||
!! {{{mconf_append}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, ajouter des directives correspondant
|
||
aux paramètres $3..* dans la section $2
|
||
Chaque argument de cette fonction correspond à une directive du fichier de
|
||
configuration et doit être de la forme name=value
|
||
Une ligne '$name = $value' est ajoutée à la fin de la section, qui est
|
||
créée si nécessaire à la fin du fichier de configuration
|
||
Retourner 0 si une modification a été faite dans le fichier, 1 sinon
|
||
Cette fonction nécessite gawk et ignore la locale
|
||
}}}
|
||
!! {{{mconf_array_append}}}
|
||
!! {{{mconf_check}}}
|
||
{{{
|
||
Dans le fichier de configuration $1, tester si tous les paramètres $3..*
|
||
sont présents dans la section $2
|
||
Chaque argument de cette fonction correspond à une variable du fichier de
|
||
configuration, et doit être de la forme name[=value]
|
||
Si une valeur est spécifiée, vérifier que le fichier contient la valeur
|
||
correspondante. Sinon, tester uniquement la présence de la directive.
|
||
Cette fonction nécessite gawk et ignore la locale
|
||
}}}
|
||
!! {{{gconf_addline}}}
|
||
{{{
|
||
USAGE
|
||
gconf_addline configfile -a BEGIN -z END NEWLINE
|
||
Dans le fichier de configuration $1, ajouter la ligne NEWLINE entre les lignes
|
||
BEGIN et END.
|
||
-a BEGIN
|
||
Spécifier une expression pour matcher une ligne de type BEGIN. Si
|
||
cette option n'est pas spécifiée, on considère que le début de fichier
|
||
matche la ligne BEGIN: la ligne NEWLINE est ajoutée dès que possible.
|
||
Les lignes sont matchées dans l'ordre, i.e. avec '-a 1 -a 2', il faut
|
||
d'abord trouver la ligne 1 puis la ligne 2, sinon, le test n'est pas
|
||
concluant.
|
||
-t LINE
|
||
Si après avoir matché toutes les lignes BEGIN, la ligne LINE est
|
||
rencontrée, alors considérer que la ligne à rajouter existe déjà et
|
||
qu'il ne faut pas la rajouter de nouveau
|
||
-r LINE
|
||
Si après avoir matché toutes les lignes BEGIN, la ligne LINE est
|
||
rencontrée, alors considérer que la ligne à rajouter existe et qu'il
|
||
faut la mettre à jour. Supprimer la ligne existante et la remplacer
|
||
par la nouvelle ligne.
|
||
-z END
|
||
Spécifier une expression pour matcher la ligne de type END. Que cette
|
||
option soit ou non spécifiée, on considère toujours que la fin de
|
||
fichier matche la ligne END. Ainsi, si END n'est pas trouvée, la ligne
|
||
NEWLINE est ajoutée à la fin du fichier.
|
||
Dès que la ligne END est rencontrée, et si aucun des tests -t ou -r
|
||
n'est concluant, alors ajouter la nouvelle ligne avant celle-ci
|
||
-n MAX[=1]
|
||
Ajouter au plus MAX occurences de NEWLINE. Après avoir matché END, le
|
||
cycle recommence, au plus MAX-1 fois. Utiliser MAX=-1 pour désactiver
|
||
la limite
|
||
Cette fonction nécessite gawk et ignore la locale
|
||
Retourner 0 si l'ajout s'est fait correctement. Retourner 1 si BEGIN n'a
|
||
pas été trouvé, et donc aucun ajout n'a été effectué. Retourner 2 si une
|
||
erreur quelconque s'est produite
|
||
}}}
|
||
!! {{{writelines_maybe}}}</pre>
|
||
</div>
|
||
<div title="ulib/crontab" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{add_to_crontab}}}
|
||
!! {{{remove_from_crontab}}}
|
||
!! {{{disable_in_crontab}}}
|
||
!! {{{enable_in_crontab}}}
|
||
!! {{{ctnow}}}
|
||
{{{
|
||
date +"%-M %-H %-d %-m %u"
|
||
}}}
|
||
!! {{{ctresolve}}}
|
||
!! {{{get_default_crontabdir_prefix}}}
|
||
!! {{{compute_crontab_prefixes}}}
|
||
!! {{{recompute_crontab_prefixes}}}
|
||
!! {{{get_CRONTABDIR_prefix}}}</pre>
|
||
</div>
|
||
<div title="ulib/debian" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{pkg_check}}}
|
||
{{{
|
||
Vérifier que les packages sont installés sur le système
|
||
}}}
|
||
!! {{{pkg_update}}}
|
||
{{{
|
||
Mettre à jour la liste des packages silencieusement sans confirmation
|
||
}}}
|
||
!! {{{pkg_upgrade}}}
|
||
{{{
|
||
Mettre à jour la liste des packages silencieusement sans confirmation
|
||
}}}
|
||
!! {{{pkg_install}}}
|
||
{{{
|
||
Installer les packages silencieusement et sans confirmation
|
||
}}}
|
||
!! {{{pkg_installm}}}
|
||
{{{
|
||
Installer les packages silencieusement et sans confirmation
|
||
Retourner 0 si au moins un des packages a été installé. Sinon, les
|
||
packages n'ont pas été installés, soit parce qu'ils sont déjà installé,
|
||
soit parce qu'il y a eu une erreur.
|
||
}}}
|
||
!! {{{pkg_check_install}}}
|
||
{{{
|
||
Si le programme $1 n'existe pas, alors installer les packages $2..$@
|
||
S'il n'y a pas d'arguments $2..$@ utiliser $1 comme nom de package
|
||
Retourner 0 si au moins un des packages a été installé
|
||
}}}
|
||
!! {{{service_disable}}}
|
||
{{{
|
||
Désactiver le service $1 pour qu'il ne se lance pas automatiquement au
|
||
démarrage
|
||
}}}
|
||
!! {{{service_enable}}}
|
||
{{{
|
||
Activer le service $1 pour qu'il se lance automatiquement au démarrage
|
||
}}}
|
||
!! {{{network_parse_confbr}}}
|
||
{{{
|
||
network_parse_confbr "$confbr" br ifaces
|
||
}}}
|
||
!! {{{network_format_confbr}}}
|
||
{{{
|
||
network_format_confbr "$br" ifaces --> "br:ifaces"
|
||
}}}
|
||
!! {{{network_parse_confip}}}
|
||
{{{
|
||
network_parse_confip "$confip" iface gateway ipsuffixes
|
||
}}}
|
||
!! {{{network_parse_ipsuffix}}}
|
||
{{{
|
||
network_parse_ipsuffix "$ipsuffix" ip suffix
|
||
}}}
|
||
!! {{{network_format_confip}}}
|
||
{{{
|
||
network_format_confip "$iface" "$gateway" ipsuffixes --> "iface//gateway:ipsuffixes"
|
||
}}}
|
||
!! {{{network_format_ipsuffix}}}
|
||
{{{
|
||
network_format_ipsuffix "$ip" "$suffix" --> "ip/suffix"
|
||
}}}
|
||
!! {{{network_fix_confbrs}}}
|
||
{{{
|
||
normaliser le tableau $1(=confbrs): fusionner les doublons
|
||
}}}
|
||
!! {{{network_fix_confips}}}
|
||
{{{
|
||
normaliser le tableau $1(=confips): fusionner les doublons, spécifier le
|
||
suffixe /24 par défaut, etc. $2 est le cas échéant l'interface associée
|
||
aux adresses ip non qualifiées
|
||
}}}
|
||
!! {{{network_fix_mainiface}}}
|
||
{{{
|
||
A partir des valeurs des tableaux $1(=confbrs) et $2(=confips), et de
|
||
l'interface principale $3, déterminer l'interface principale. Si $3 est
|
||
spécifié, c'est la valeur sélectionnée. Sinon, si un bridge existe, c'est
|
||
le premier bridge qui est sélectionné. Sinon, la première interface est
|
||
sélectionnée. Sinon, on prend eth0.
|
||
Ensuite, réorganiser les tableaux de façon que confips[0] devienne la
|
||
configuration ip de l'interface principale.
|
||
}}}
|
||
!! {{{network_fix_confs}}}
|
||
!! {{{network_set_confbrs}}}
|
||
{{{
|
||
initialiser $1(=confbrs) avec l'état des bridges sur le système courant
|
||
}}}
|
||
!! {{{network_set_confips}}}
|
||
{{{
|
||
initialiser le tableau $1(=confips) avec l'état des interfaces sur le
|
||
système courant
|
||
}}}
|
||
!! {{{network_interfaces_check_confbr}}}
|
||
{{{
|
||
Vérifier que la configuration du bridge $1, dont les membres sont les
|
||
interfaces du tableau $2(=ifaces) est faite dans le fichier
|
||
$3(=/etc/network/interfaces)
|
||
}}}
|
||
!! {{{network_interfaces_check_confip}}}
|
||
{{{
|
||
Vérifier que la configuration de l'interface $1, avec la passerelle $2,
|
||
avec les adresses IP du tabbleau $3(=ipsuffixes) est faite dans le fichier
|
||
$4(=/etc/network/interfaces)
|
||
}}}
|
||
!! {{{network_interfaces_remove_iface}}}
|
||
{{{
|
||
Supprimer dans le fichier $2(=/etc/network/interfaces) toute la
|
||
configuration qui concerne l'interface $1
|
||
}}}
|
||
!! {{{network_interfaces_remove_ifaces}}}
|
||
{{{
|
||
Supprimer dans le fichier $2(=/etc/network/interfaces) toute la
|
||
configuration qui concerne les interfaces du tableau $1=(ifaces)
|
||
}}}
|
||
!! {{{network_interfaces_remove_confbr}}}
|
||
{{{
|
||
Supprimer dans le fichier $3(=/etc/network/interfaces) toute la
|
||
configuration qui concerne le bridge $1, et dont les interfaces sont
|
||
listées dans le tableau $2(=ifaces)
|
||
}}}
|
||
!! {{{network_interfaces_add_confip}}}
|
||
{{{
|
||
ajouter dans le fichier $4(=/etc/network/interfaces) la configuration pour
|
||
l'interface $1, avec éventuellement la passerelle $2, et les adresses ips
|
||
telles qu'elles sont définies dans le table $3(=ipsuffixes)
|
||
}}}
|
||
!! {{{network_interfaces_add_confbr}}}
|
||
{{{
|
||
ajouter dans le fichier $4(=/etc/network/interfaces) la configuration pour
|
||
le bridge $1, avec la liste des interfaces dans le tableau $2(=ifaces) et
|
||
la liste des configurations des adresses des interfaces dans le tableau
|
||
$3(=confips)
|
||
}}}
|
||
!! {{{network_fix_hostname}}}
|
||
!! {{{network_fix_mailname}}}
|
||
!! {{{network_fix_exim4}}}
|
||
!! {{{network_fix_postfix}}}
|
||
!! {{{network_fix_hosts}}}
|
||
!! {{{network_config}}}
|
||
{{{
|
||
(Re)configurer le réseau sur l'hôte courant.
|
||
$1 (host) est le nom d'hôte.
|
||
$2 (confips) est le nom d'un tableau contenant la configuration des
|
||
adresses ips pour les interfaces.
|
||
$3 (confbrs) est le nom d'un tableau contenant la configuration des
|
||
bridges à créer/mettre à jour.
|
||
$4 (mainiface) est le nom de l'interface principale, c'est à dire
|
||
l'interface qui est sélectionnée si une adresse ip n'est pas préfixée de
|
||
son interface. En principe, l'interface principale est le premier bridge
|
||
défini ou la première interface définie.
|
||
$5 (reset_interfaces) spécifie de ne pas chercher à mettre à jour le
|
||
fichier /etc/network/interfaces, mais de le recréer depuis zéro.
|
||
$6 (oldhost) est le nom d'hôte actuel, avant la modification
|
||
Si un des arguments n'est pas spécifié, il est ignoré.
|
||
Le tableau confips doit contenir des définitions d'une des formes
|
||
suivantes:
|
||
[[iface][//gateway]:]address[/suffix],...
|
||
[iface:]dhcp
|
||
La deuxième forme est pour spécifier qu'une interface est configurée par
|
||
DHCP. iface vaut par défaut eth0, sauf si une définition de bridge
|
||
existe, auquel cas il s'agit du premier bridge défini. Pour chaque
|
||
interface, seule la première spécification d'adresse IP tient compte de
|
||
l'argument gateway. Les autres spécifications définissent des adresses IP
|
||
supplémentaires pour l'interface.
|
||
Le tableau brs doit contenir des définitions de la forme suivante:
|
||
br:ifaces,...
|
||
br est le nom du bridge, e.g. br0. ifaces est une liste d'interfaces
|
||
séparées par une virgule. e.g. br0:eth0,eth1
|
||
Bien que ce soit techniquement possible, ce script interdit que l'on
|
||
définisse une adresse IP pour une interface faisant partie d'un bridge.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/install" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{ensure_exists}}}
|
||
{{{
|
||
Créer le fichier vide "$1" s'il n'existe pas déjà, avec les permissions
|
||
$2(=644). retourner vrai si le fichier a été créé sans erreur
|
||
}}}
|
||
!! {{{copy_replace}}}
|
||
{{{
|
||
Copier de façon inconditionnelle le fichier $1 vers le fichier $2, en
|
||
réinitialisation les permissions à la valeur $3
|
||
}}}
|
||
!! {{{copy_new}}}
|
||
{{{
|
||
Copier le fichier "$1" vers le fichier "$2", avec les permissions $3(=644)
|
||
Ne pas écraser le fichier destination s'il existe déjà
|
||
Retourner vrai si le fichier a été copié sans erreur
|
||
}}}
|
||
!! {{{copy_update}}}
|
||
{{{
|
||
Copier le fichier "$1" vers le fichier "$2", si $2 n'existe pas, ou si $1
|
||
a été modifié par rapport à $2. Réinitialiser le cas échéant les
|
||
permissions à la valeur $3
|
||
Retourner vrai si le fichier a été copié sans erreur.
|
||
}}}
|
||
!! {{{copy_update_ask}}}
|
||
{{{
|
||
Copier ou mettre à jour le fichier $1 vers le fichier $2.
|
||
Si le fichier existe déjà, la différence est affichée, et une confirmation
|
||
est demandée pour l'écrasement du fichier.
|
||
Retourner vrai si le fichier a été copié sans erreur.
|
||
}}}
|
||
!! {{{copy_tree}}}
|
||
{{{
|
||
Copier de façon inconditionnelle l'arborescence $1 dans l'arborescence $2
|
||
}}}
|
||
!! {{{link_new}}}
|
||
{{{
|
||
Si $2 n'existe pas, créer le lien symbolique $2 pointant vers $1
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/ipcalc" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{get_random_kvm_macaddr}}}
|
||
{{{
|
||
Obtenir une adresse mac au hasard commençant par 52:54:00 pour KVM
|
||
}}}
|
||
!! {{{ipcalc_splitipmask}}}
|
||
{{{
|
||
Découper $1 de la forme ip[/mask] entre l'adresse ip, qui est placé dans
|
||
la variable $2(=ip) et le masque, qui est placée dans la variable
|
||
$3(=mask)
|
||
}}}
|
||
!! {{{ipcalc_checkip}}}
|
||
{{{
|
||
Vérifier l'adresse ip $1 pour voir si elle est valide. Si l'adresse est
|
||
valide, l'afficher. Sinon, retourner 1
|
||
}}}
|
||
!! {{{ipcalc_checkmask}}}
|
||
{{{
|
||
vérifier le masque de sous-réseau $1 pour voir si elle est valide. Si oui,
|
||
afficher le suffixe (0, 8, 16, 24, 32) associé. Sinon retourner 1
|
||
}}}
|
||
!! {{{ipcalc_netmask}}}
|
||
{{{
|
||
à partir d'un suffixe (0, 8, 16, 24, 32) ou d'un masque de sous-réseau,
|
||
afficher le masque de sous-réseau. si le suffixe ou le masque ne sont pas
|
||
reconnus, retourner 1
|
||
}}}
|
||
!! {{{ipcalc_broadcast}}}
|
||
{{{
|
||
Calculer l'adresse de broadcast correspondant à l'adresse ip $1. Le masque
|
||
de sous-réseau peut-être indiqué dans l'adresse ip avec le suffixe /n ou
|
||
/x.x.x.x ou donné dans l'argument $2. Seuls les suffixes 0, 8, 16, 24, 32
|
||
sont supportés.
|
||
Retourner 1 si un erreur s'est produite, par exemple si l'adresse ou le
|
||
suffixe sont invalides ou non supportés.
|
||
}}}
|
||
!! {{{ipcalc_gateway}}}
|
||
{{{
|
||
Calculer l'adresse du gateway correspondant à l'adresse ip $1, en
|
||
considérant que le gateway est la première adresse du réseau. Le masque de
|
||
sous-réseau peut-être indiqué dans l'adresse ip avec le suffixe /n ou
|
||
/x.x.x.x ou donné dans l'argument $2. Seuls les suffixes 0, 8, 16, 24, 32
|
||
sont supportés.
|
||
Retourner 1 si un erreur s'est produite, par exemple si l'adresse ou le
|
||
suffixe sont invalides ou non supportés.
|
||
}}}
|
||
!! {{{ipcalc_match}}}
|
||
{{{
|
||
Vérifier si l'adresse $1 correspond au modèle $2, e.g.:
|
||
ipcalc_match 10.75.0.23 10/8 --> TRUE
|
||
ipcalc_match 10.75.0.23 10.75.0.0/24 --> TRUE
|
||
ipcalc_match 10.75.0.23 10.75.0.28 --> FALSE
|
||
}}}
|
||
!! {{{ipcalc_fqdn}}}
|
||
{{{
|
||
Calculer si possible le nom pleinement qualifié correspondant à l'hôte $1.
|
||
Dans tous les cas, afficher l'hôte, mais retourner 1 si la calcul n'a pas
|
||
pu être effectué.
|
||
}}}
|
||
!! {{{ipcalc_fqdn_maybe}}}
|
||
{{{
|
||
Si $1 *semble* déjà être un nom d'hôte pleinement qualifié, l'afficher tel
|
||
quel. Sinon utiliser ipcalc_fqdn() pour afficher le nom d'hôte pleinement
|
||
qualifié correspondant.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/java" creator="jclain" modifier="jclain" created="201605130536" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{select_java}}}
|
||
{{{
|
||
sélectionner la version *minimum* de java correspondant à $1
|
||
$1== 1.3|1.3+|1.4|1.4+|1.5|1.5+|1.6|1.6+|1.7|1.7+|1.8|1.8+
|
||
Si $2 est défini, il peut s'agit de 32 ou 64 selon que l'on requière la
|
||
version 32bits ou 64 bits
|
||
}}}
|
||
!! {{{select_java_exact}}}
|
||
{{{
|
||
sélectionner la version *exacte* de java correspondant à $1
|
||
$1== 1.3|1.4|1.5|1.6|1.7|1.8 pour une correspondance exacte
|
||
$1== 1.3+|1.4+|1.5+|1.6+|1.7+|1.8+ pour une version minimum
|
||
Si $2 est défini, il peut s'agit de 32 ou 64 selon que l'on requière la
|
||
version 32bits ou 64 bits
|
||
}}}
|
||
!! {{{select_java_any}}}
|
||
{{{
|
||
Sélectionner la version exacte de java correspondant aux arguments, dans
|
||
l'ordre, jusqu'à ce qu'un argument corresponde. DEFAULT correspond à la
|
||
valeur actuelle de JAVA_HOME, si elle est définie.
|
||
Si aucun argument n'est défini, on assume "DEFAULT 5 6 7 8 1.4"
|
||
}}}
|
||
!! {{{get_java_version}}}
|
||
{{{
|
||
Afficher la version de java qui installée dans $1(=$JAVA_HOME)
|
||
En cas d'erreur, ne rien afficher.
|
||
}}}
|
||
!! {{{get_default_javahome_prefix}}}
|
||
!! {{{get_javaextensions_prefix}}}
|
||
!! {{{compute_java_prefixes}}}
|
||
!! {{{recompute_java_prefixes}}}
|
||
!! {{{get_JAVA_HOME_prefix}}}
|
||
!! {{{get_JAVAEXTENSIONS_prefix}}}</pre>
|
||
</div>
|
||
<div title="ulib/javaproperties" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{read_property}}}
|
||
{{{
|
||
Lire la propriété $2 dans le fichier $1, et placer la valeur dans la
|
||
variable $3. Si la propriété n'existe pas, prendre la valeur par défaut
|
||
$4. Si $3=="", elle est construite à partir de $2 en remplaçant les '.'
|
||
par '_'
|
||
Retourner 1 si une erreur s'est produite (par exemple si le fichier
|
||
n'existe pas ou n'est pas accessible en lecture)
|
||
}}}
|
||
!! {{{write_property}}}
|
||
{{{
|
||
Ecrire la propriété $2 dans le fichier $1 avec la valeur $3.
|
||
Retourner 1 si une erreur s'est produite (par exemple si le fichier
|
||
n'existe pas ou n'est pas accessible en écriture)
|
||
}}}
|
||
!! {{{write_properties}}}
|
||
{{{
|
||
Ecrire les propriétés $2..* dans le fichier $1. Les propriétés sont de la
|
||
forme "name=value"
|
||
}}}
|
||
!! {{{norm_properties}}}
|
||
{{{
|
||
Normaliser un fichier de propriété: Les commentaires sont supprimés, les
|
||
valeurs sont triées par ordre alphabétique, les caractères accentués sont
|
||
remplacés par des caractères unicode \\uxxxx, les séquences unicodes sont
|
||
transformées en minuscule.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/json" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{json_filter}}}
|
||
{{{
|
||
traiter un flux json pour que chaque valeur soit sur une ligne séparée,
|
||
facilitant le traitement par un script bash
|
||
}}}
|
||
!! {{{awkjson}}}</pre>
|
||
</div>
|
||
<div title="ulib/ldap" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{get_default_ldapconfdir_prefix}}}
|
||
{{{
|
||
Calculer et afficher la valeur par défaut de LDAPCONFDIR, ou une chaine
|
||
vide si l'on n'a pas pu le détecter automatiquement.
|
||
}}}
|
||
!! {{{get_default_ldapowner_prefix}}}
|
||
{{{
|
||
Calculer et afficher la valeur par défaut de LDAPOWNER, ou une chaine
|
||
vide si l'on n'a pas pu le détecter automatiquement.
|
||
}}}
|
||
!! {{{compute_ldap_prefixes}}}
|
||
!! {{{recompute_ldap_prefixes}}}
|
||
!! {{{get_LDAPCONFDIR_prefix}}}
|
||
!! {{{get_LDAPOWNER_prefix}}}
|
||
!! {{{split_ldapuri}}}
|
||
{{{
|
||
spliter le ldapuri $1 en $2(=proto), $3(=host) et $4(=port)
|
||
}}}
|
||
!! {{{get_suffixes}}}
|
||
{{{
|
||
obtenir les suffixes de connexion du serveur avec l'uri $1, un par ligne
|
||
retourner 1 si la valeur n'a pas pu être obtenue
|
||
}}}
|
||
!! {{{get_anysuffix}}}
|
||
{{{
|
||
obtenir le *premier* suffixe du serveur avec l'uri $1
|
||
retourner 1 si la valeur n'a pas pu être obtenue
|
||
}}}
|
||
!! {{{get_dcsuffix}}}
|
||
{{{
|
||
obtenir le *premier* suffixe du serveur avec l'uri $1 qui se termine par
|
||
dc=TLD où TLD est une valeur quelconque. A priori, c'est un suffixe d'une
|
||
base de donnée non administrative.
|
||
retourner 1 si la valeur n'a pas pu être obtenue
|
||
}}}
|
||
!! {{{get_suffix}}}
|
||
{{{
|
||
obtenir le *premier* suffixe du serveur avec l'uri $1 qui se termine si
|
||
possible par dc=TLD où TLD est une valeur quelconque. Dans le cas normal,
|
||
le suffixe affiché est celui d'une base non administrative.
|
||
retourner 1 si la valeur n'a pas pu être obtenue
|
||
}}}
|
||
!! {{{reldn}}}
|
||
!! {{{absdn}}}
|
||
{{{
|
||
obtenir le dn absolu correspondant au dn $1, le dn de base étant
|
||
$2(=$SUFFIX)
|
||
}}}
|
||
!! {{{subof}}}
|
||
{{{
|
||
tester si le dn absolu $1 est $2 ou un enfant de $2
|
||
}}}
|
||
!! {{{rabsdn}}}
|
||
{{{
|
||
comme absdn, mais tient compte de la valeur de $3(=$SEARCHBASE)
|
||
Si le dn commence par "~/", le dn est relatif à $2(=$SUFFIX)
|
||
Si le dn commence par "/", le dn est absolu
|
||
Sinon, le dn est relatif à $3
|
||
}}}
|
||
!! {{{pdn}}}
|
||
{{{
|
||
corriger pour *affichage* un dn *absolu*. pour la racine "", afficher
|
||
'/'. pour $2(=$SUFFIX), afficher '~'. sinon, afficher le dn relativement à
|
||
$2
|
||
}}}
|
||
!! {{{filter_slapdconf}}}
|
||
{{{
|
||
Traiter un fichier de configuration slapd.conf en fusionnant les lignes
|
||
qui sont découpées. Ceci permet de faire des traitements sur le contenu.
|
||
Ce filtre s'utilisera normalement avec filter_conf, e.g.:
|
||
<slapd.conf filter_slapdconf | filter_conf >result.conf
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/ldif" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{def_match_attr}}}
|
||
!! {{{def_match_value}}}
|
||
!! {{{uncut_lines}}}
|
||
{{{
|
||
reformer les lignes qui sont coupées
|
||
}}}
|
||
!! {{{cut_lines}}}
|
||
{{{
|
||
couper les lignes trop longues
|
||
}}}
|
||
!! {{{ensure_complete_objects}}}
|
||
{{{
|
||
S'assurer que le ldif ne contient que des objets complets (éliminant ainsi
|
||
les groupes ayant seulement dn:)
|
||
}}}
|
||
!! {{{delete_marked_objects}}}
|
||
{{{
|
||
Supprimer les objets marqués avec --DELETE--:
|
||
}}}
|
||
!! {{{dump_ldif}}}
|
||
!! {{{tl_addattr}}}
|
||
!! {{{tl_modifyattr}}}
|
||
!! {{{tl_deleteattr}}}
|
||
!! {{{tl_deleteentry}}}
|
||
!! {{{tl_touchentry}}}
|
||
!! {{{tl_keepattr}}}
|
||
!! {{{tl_keepval}}}
|
||
!! {{{tl_excludeattr}}}
|
||
!! {{{tl_excludeval}}}
|
||
!! {{{tl_keepvalentry}}}
|
||
!! {{{tl_excludevalentry}}}
|
||
!! {{{tl_replval}}}
|
||
!! {{{tl_addval}}}
|
||
!! {{{tl_defval}}}
|
||
!! {{{print_values}}}
|
||
!! {{{tl_ensureval}}}
|
||
!! {{{print_ensure_values}}}
|
||
!! {{{tl_decode}}}
|
||
!! {{{tl_encode}}}
|
||
!! {{{tl_format}}}
|
||
!! {{{dump_headers}}}
|
||
!! {{{tl_formatcsv}}}
|
||
!! {{{tl_parsecsv}}}
|
||
!! {{{tl_parsecsvmod}}}
|
||
!! {{{get_transform_cmd}}}
|
||
{{{
|
||
Créer une liste de commandes bash à évaluer en fonction des arguments: une
|
||
suite de commandes séparées par //
|
||
Les variables suivantes peuvent être définies en entrée:
|
||
_T_inputfile:
|
||
Si cette variable est non vide, lire à partir du fichier $_T_inputfile
|
||
au lieu de stdin
|
||
_T_uncut_before:
|
||
faut-il fusionner automatiquement les lignes *avant* de lancer les
|
||
commandes.
|
||
_T_cut_after:
|
||
faut-il découper automatiquement les lignes *après* avoir lancé les
|
||
commandes.
|
||
}}}
|
||
!! {{{transform}}}</pre>
|
||
</div>
|
||
<div title="ulib/legacy" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{file_get_vars}}}
|
||
{{{
|
||
lire les variables dans un fichier
|
||
}}}
|
||
!! {{{file_set_vars}}}
|
||
{{{
|
||
écrire les variables dans un fichier. Le fichier *doit exister*
|
||
}}}
|
||
!! {{{write_all_remaining_vars}}}
|
||
!! {{{file_get_properties}}}
|
||
{{{
|
||
lire les propriétés d'un fichier de propriété java ou xml
|
||
}}}
|
||
!! {{{file_set_properties}}}
|
||
{{{
|
||
écrire les propriétés d'un fichier de propriété java ou xml
|
||
}}}
|
||
!! {{{file_get_java_properties}}}
|
||
{{{
|
||
lire les propriétés d'un fichier de propriétés java. note: les noms de
|
||
propriété java peuvent contenir le caractère "." mais pas les noms de
|
||
variable bash. La conversion est faite automatiquement. Par exemple::
|
||
file_get_properties build.properties path.to.package "default value"
|
||
charge la valeur de la propriété dans la variable path_to_package
|
||
}}}
|
||
!! {{{file_set_java_properties}}}
|
||
{{{
|
||
écrire des propriétés dans un fichier de propriétés java.
|
||
}}}
|
||
!! {{{write_all_remaining_vars}}}
|
||
!! {{{file_get_xml_properties}}}
|
||
{{{
|
||
lire les propriétés d'un fichier de propriétés xml. Limitation: les
|
||
propriétés ne doivent pas être continuées sur plusieurs lignes. Les
|
||
propriétés doivent être écrites sous la forme::
|
||
<propname>propvalue</propname>
|
||
}}}
|
||
!! {{{file_set_xml_properties}}}
|
||
{{{
|
||
écrire des propriétés dans un fichier de propriétés java.
|
||
}}}
|
||
!! {{{write_all_remaining_vars}}}</pre>
|
||
</div>
|
||
<div title="ulib/macosx" creator="jclain" modifier="jclain" created="201206020554" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{local_shellfix}}}
|
||
{{{
|
||
Modifier le compte local $1 pour qu'il utilise bash au lieu de sh
|
||
}}}
|
||
!! {{{local_usercheck}}}
|
||
{{{
|
||
Vérifier si le user local $1 existe
|
||
}}}
|
||
!! {{{local_useradd}}}
|
||
{{{
|
||
Créer le user local $1
|
||
USAGE: local_useradd username [gecos [passwd]]
|
||
OPTIONS
|
||
-s Créer l'utilisateur avec les droits d'administrateur
|
||
-m Créer le home directory
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/mkcrypt" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{mkcrypt}}}</pre>
|
||
</div>
|
||
<div title="ulib/modeline" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{printml}}}
|
||
!! {{{addml}}}</pre>
|
||
</div>
|
||
<div title="ulib/network-manager-service" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{SERVICE_OVERRIDE_network_manager_stopx}}}
|
||
{{{
|
||
désactiver network-manager avant de l'arrêter, ce qui permet de s'assurer
|
||
que chaque chaque connexion est arrêtée proprement
|
||
}}}
|
||
!! {{{SERVICE_OVERRIDE_network_manager_startx}}}
|
||
{{{
|
||
cette fonction est le pendant de stopx: penser à relancer network-manager
|
||
après avoir démarré le service
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/password" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{random_index}}}
|
||
{{{
|
||
Afficher un index au hasard dans le tableau $1
|
||
}}}
|
||
!! {{{random_value}}}
|
||
{{{
|
||
Afficher une valeur au hasard dans le tableau $1
|
||
}}}
|
||
!! {{{random_char}}}
|
||
{{{
|
||
Afficher un caractère au hasard dans la chaine $1
|
||
}}}
|
||
!! {{{genpass}}}
|
||
{{{
|
||
Générer un mot de passe au hasard avec les paramètres GENPASS_*
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/pkg" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{pkg_check}}}
|
||
{{{
|
||
Vérifier que les packages sont installés sur le système
|
||
Retourner 123 si le système n'est pas supporté, et donc qu'aucune commande
|
||
d'installation de package n'est disponible.
|
||
}}}
|
||
!! {{{pkg_install}}}
|
||
{{{
|
||
Installer les packages sans confirmation
|
||
Retourner 123 si le système n'est pas supporté, et donc qu'aucune commande
|
||
d'installation de package n'est disponible.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/prefixes" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{get_USER_prefix}}}
|
||
!! {{{get_HOME_prefix}}}
|
||
!! {{{has_prefix}}}
|
||
!! {{{expand_prefix}}}
|
||
!! {{{list_prefixes}}}
|
||
!! {{{dump_prefixes}}}</pre>
|
||
</div>
|
||
<div title="ulib/pretty" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{get_color}}}
|
||
!! {{{set_verbosity}}}
|
||
!! {{{set_interaction}}}
|
||
!! {{{show_error}}}
|
||
!! {{{show_warn}}}
|
||
!! {{{show_info}}}
|
||
!! {{{show_verbose}}}
|
||
!! {{{show_debug}}}
|
||
!! {{{check_verbosity}}}
|
||
!! {{{get_verbosity_option}}}
|
||
!! {{{check_interaction}}}
|
||
!! {{{is_interaction}}}
|
||
!! {{{get_interaction_option}}}</pre>
|
||
</div>
|
||
<div title="ulib/ptools" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{is_any_branch}}}
|
||
!! {{{is_master_branch}}}
|
||
!! {{{is_develop_branch}}}
|
||
!! {{{is_release_branch}}}
|
||
!! {{{is_hotfix_branch}}}
|
||
!! {{{is_feature_branch}}}
|
||
!! {{{list_release_branches}}}
|
||
!! {{{list_hotfix_branches}}}
|
||
!! {{{list_feature_branches}}}
|
||
!! {{{pver}}}</pre>
|
||
</div>
|
||
<div title="ulib/redhat" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{pkg_check}}}
|
||
{{{
|
||
Vérifier que les packages sont installés sur le système
|
||
}}}
|
||
!! {{{pkg_update}}}
|
||
{{{
|
||
Mettre à jour la liste des packages silencieusement sans confirmation
|
||
}}}
|
||
!! {{{pkg_upgrade}}}
|
||
{{{
|
||
Mettre à jour la liste des packages silencieusement sans confirmation
|
||
}}}
|
||
!! {{{pkg_install}}}
|
||
{{{
|
||
Installer les packages silencieusement et sans confirmation
|
||
}}}
|
||
!! {{{pkg_installm}}}
|
||
{{{
|
||
Installer les packages silencieusement et sans confirmation
|
||
Retourner 0 si au moins un des packages a été installé. Sinon, les
|
||
packages n'ont pas été instllés, soit parce qu'ils sont déjà installé,
|
||
soit parce qu'il y a eu une erreur.
|
||
}}}
|
||
!! {{{service_disable}}}
|
||
{{{
|
||
Désactiver le service $1 pour qu'il ne se lance pas automatiquement au
|
||
démarrage
|
||
}}}
|
||
!! {{{service_enable}}}
|
||
{{{
|
||
Activer le service $1 pour qu'il se lance automatiquement au démarrage
|
||
}}}
|
||
!! {{{create_bridge}}}
|
||
{{{
|
||
Créer un nouveau pont nommé $1 avec les paramètres $2
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/runs" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{runs_initdir}}}
|
||
{{{
|
||
Initialiser le répertoire d'hôte. $1 est un nom d'hôte pleinement
|
||
qualifié, et les fichiers sont créés dans le premier répertoire de
|
||
RUNSHOSTSDIRS qui convient: si un fichier .udir existe avec un tableau
|
||
runs_domains qui contient le domaine de l'hôte spécifié, alors c'est ce
|
||
répertoire qui est sélectionné. Sinon, on prend le premier répertoire de
|
||
RUNSHOSTSDIRS.
|
||
$2 spécifie si le fichier doit être créé avec de l'aide (yes) ou avec le
|
||
script minimum (no)
|
||
$3 est le contenu à placer dans le fichier sysinfos.conf, s'il n'a pas
|
||
déjà été provisionné.
|
||
Il faut lancer __runs_setpath avant d'utiliser cette fonction et
|
||
RUNSHOSTDIRS ne doit pas être vide
|
||
}}}
|
||
!! {{{runs_create_rscript}}}
|
||
{{{
|
||
Créer un modèle de script. Si $2 est spécifié, c'est un nom d'hôte
|
||
pleinement qualifié. Le répertoire d'hôte correspondant *doit* exister.
|
||
$3 spécifie si le fichier doit être créé avec de l'aide (yes) ou avec le
|
||
script minimum (no)
|
||
Si $2!="", il faut lancer __runs_setpath avant d'utiliser cette fonction
|
||
et RUNSHOSTDIRS ne doit pas être vide
|
||
Le chemin du nouveau script est ajouté au tableau new_rscripts
|
||
}}}
|
||
!! {{{runs_unsupported_system}}}
|
||
{{{
|
||
Afficher un message d'erreur indiquant que le système actuel n'est pas
|
||
supporté, et quitter le script
|
||
}}}
|
||
!! {{{runs_require_sysinfos}}}
|
||
{{{
|
||
Vérifier le système actuel avec check_sysinfos(), et afficher un message
|
||
d'erreur avec runs_unsupported_system() s'il ne correspond pas à la
|
||
requête
|
||
}}}
|
||
!! {{{runs_find_host}}}
|
||
!! {{{runs_add_domain}}}
|
||
{{{
|
||
Si $1 est nom d'hôte pleinement qualifié, retourner cette valeur
|
||
Sinon, lui rajouter le domaine RUNSDOMAIN
|
||
}}}
|
||
!! {{{runs_find_hostfile}}}
|
||
{{{
|
||
Trouver et afficher le fichier d'hôte $1 dans les répertoires du tableau
|
||
$3(=RUNSHOSTSDIRS), pour l'hôte $2(=$RUNSHOST). Retourner 0 en cas de
|
||
succès, 1 en cas d'échec.
|
||
Si host=$2 est une valeur non vide, la recherche est effectuée dans
|
||
{$RUNSHOSTSDIRS}/$host et {$RUNSHOSTSDIRS}/$domain/$hostname. Sinon,
|
||
retourner 1, car il faut spécifier un nom d'hôte.
|
||
}}}
|
||
!! {{{runs_find_datafile}}}
|
||
{{{
|
||
Trouver et afficher le fichier de données $1 dans le répertoire $3 s'il
|
||
est non vide puis dans les répertoires des tableaux $4(=RUNSSCRIPTSDIRS),
|
||
$5(=RUNSMODULESDIRS) et $6(=RUNSHOSTSDIRS), pour l'hôte
|
||
$2(=$RUNSHOST). Retourner 0 en cas de succès, 1 en cas d'échec.
|
||
- D'abord, si $1 *n'est pas* de la forme "./path" ou "../path", chercher
|
||
dans $3.
|
||
- Puis si l'hôte est spécifié, chercher dans {$RUNSHOSTSDIRS}/$host et
|
||
{$RUNSHOSTSDIRS}/$domain/$hostname.
|
||
- Puis chercher dans {$RUNSSCRIPTSDIRS} puis {$RUNSMODULESDIRS}.
|
||
- Puis, si $1 est de la forme "./path" ou "../path", chercher dans $3.
|
||
- Sinon, retourner 1
|
||
}}}
|
||
!! {{{runs_initvars}}}
|
||
{{{
|
||
Initialiser les variables RUNSDIR, RUNSSCRIPT, RUNSDIRPATH,
|
||
RUNSSCRIPTPATH, RUNSSCRIPTDIR et RUNSSCRIPTNAME pour le script $1.
|
||
Les valeurs sont initialisées comme suit:
|
||
RUNSSCRIPT="$(abspath "$1")"
|
||
RUNSDIR="$2" (le répertoire de $RUNS*PATH dans lequel a été trouvé le
|
||
script)
|
||
Si $3!="", RUNSDIRPATH="$3" et RUNSSCRIPTPATH="$4"
|
||
Sinon, RUNSDIRPATH="$RUNSSCRIPTDIR" et RUNSSCRIPTPATH="$RUNSSCRIPTNAME"
|
||
}}}
|
||
!! {{{runs_find_scriptfile}}}
|
||
{{{
|
||
Trouver sans l'afficher le script $1 dans les répertoires des tableaux
|
||
$3(=RUNSSCRIPTSDIRS), $4(=RUNSMODULESDIRS) et $5(=RUNSHOSTSDIRS), en
|
||
considérant que le script sera lancé sur l'hôte $2(=$RUNSHOST), et
|
||
initialiser les variables RUNSDIR, RUNSSCRIPT, RUNSSCRIPTDIR,
|
||
RUNSSCRIPTNAME, RUNSDIRPATH et RUNSSCRIPTPATH. Retourner 0 en cas de
|
||
succès, 1 en cas d'échec.
|
||
$6 vaut ".rs" par défaut est c'est une extension à rajouter au nom
|
||
spécifié si le fichier sans l'extension n'existe pas
|
||
RUNSDIR est le répertoire dans lequel a été trouvé le script (parmi les
|
||
valeurs fournies dans les tableaux RUNSSCRIPTSDIRS, RUNSMODULESDIRS,
|
||
RUNSHOSTSDIRS), RUNSDIRPATH est le répertoire à partir duquel est exprimé
|
||
le chemin du script (i.e RUNSDIRPATH + RUNSSCRIPTPATH == RUNSSCRIPT),
|
||
RUNSSCRIPT contient le chemin absolu vers le script, RUNSSCRIPTPATH
|
||
contient le chemin du script dans RUNSDIRPATH, RUNSSCRIPTDIR le répertoire
|
||
du script, et RUNSSCRIPTNAME le nom du script.
|
||
D'abord, si l'hôte est spécifié, chercher dans {$RUNSHOSTSDIRS}/$host et
|
||
{$RUNSHOSTSDIRS}/$domain/$hostname. Puis chercher dans {$RUNSSCRIPTSDIRS}
|
||
}}}
|
||
!! {{{runs_find_scriptfile_reverse}}}
|
||
{{{
|
||
Soit le fichier de script $1, exprimée de façon absolue, trouver le
|
||
fichier parmi les tableaux $3(=RUNSSCRIPTSDIRS), $4(=RUNSMODULESDIRS)
|
||
et $5(=RUNSHOSTSDIRS), en considérant que le script sera lancé sur l'hôte
|
||
$2(=$RUNSHOST), puis initialiser les variables RUNSDIR, RUNSSCRIPT,
|
||
RUNSSCRIPTDIR, RUNSSCRIPTNAME, RUNSDIRPATH et RUNSSCRIPTPATH. Retourner 0
|
||
en cas de succès, 1 en cas d'échec.
|
||
}}}
|
||
!! {{{runs_rscript}}}
|
||
{{{
|
||
Lancer le fichier $1 comme un script avec les arguments $2..$*. Retourner
|
||
la valeur de retour du script.
|
||
}}}
|
||
!! {{{runs_recipe}}}
|
||
{{{
|
||
Lancer les scripts de la recette contenue dans le fichier $1. Arrêter au
|
||
premier script qui est en erreur
|
||
}}}
|
||
!! {{{runs_rscriptpath}}}
|
||
{{{
|
||
Lancer le script $1 avec les arguments $2..$*. Le script est cherché dans
|
||
les répertoires de RUNSSCRIPTSPATH. Retourner 123 si le script n'est pas
|
||
trouvé, sinon retourner la valeur de retour du script.
|
||
}}}
|
||
!! {{{runs_recipepath}}}
|
||
{{{
|
||
Lancer la recette $1. Le fichier de recette est cherché dans les
|
||
répertoires de RUNSSCRIPTSPATH. Retourner 123 si le fichier de recette n'a
|
||
pas été trouvé, sinon retourner la valeur de retour de runs_recipe()
|
||
}}}
|
||
!! {{{runs_init}}}
|
||
!! {{{runs_initdomains}}}
|
||
{{{
|
||
Si ce n'est pas déjà le cas, initialiser RUNSDOMAINS en fonction de
|
||
/etc/resolv.conf
|
||
}}}
|
||
!! {{{runs_inithost}}}
|
||
!! {{{runs_initsysinfos}}}
|
||
!! {{{runs_initworkdir}}}
|
||
!! {{{runs_after_export}}}
|
||
{{{
|
||
après l'export, initialiser varsfile avec les valeurs qu'il faut garder
|
||
entre le déploiement local et le déploiement distant.
|
||
}}}
|
||
!! {{{runs_check_runsscript}}}
|
||
!! {{{runs_var}}}
|
||
{{{
|
||
Initialiser les variables selon les directives données en ligne de
|
||
commande.
|
||
Les arguments peuvent être une suite de définitions de la forme
|
||
'scalar=value', 'scalar!=name', 'array+=value', 'array-=value' ou
|
||
'array@=name'.
|
||
Sinon, le *dernier* argument peut-être de l'une des formes suivantes:
|
||
'array value0 [value1...]' pour initialiser un tableau,
|
||
'array+ value0 [value1...]' pour ajouter des valeurs à un tableau,
|
||
'array- value0 [value1...]' pour enlever des valeurs à un tableau.
|
||
Les formes 'scalar!=value' et 'array@=value' sont des indirections et
|
||
permettent d'initialiser la variable avec la valeur d'une autre
|
||
variable. L'avantage est que la résolution de la valeur est faite
|
||
uniquement lors de l'appel de cette fonction, ce qui est utile avec des
|
||
fonction comme 'after -r'
|
||
}}}
|
||
!! {{{runs_conf}}}
|
||
{{{
|
||
Activer les flags $*
|
||
}}}
|
||
!! {{{runs_indref}}}
|
||
{{{
|
||
fonction de convenance pour créer des références $3..* avec le fichier de
|
||
configuration $1 et les variables $2
|
||
}}}
|
||
!! {{{runs_refcerts}}}
|
||
{{{
|
||
fonction de convenance pour créer une référence à un répertoire contenant
|
||
des certificats mentionnés dans le fichier de configuration $1. Si les
|
||
références $2..* ne sont pas mentionnées, la variable certsdir dans le
|
||
fichier de configuration est utilisée.
|
||
}}}
|
||
!! {{{runs_refapacheconfig}}}
|
||
{{{
|
||
fonction de convenance pour créer les références à un répertoire de
|
||
configuration pour apache.
|
||
USAGE: refapacheconfig autoconfdir=path/to/autoconfdir [certsdir=[path/to/certsdir]]
|
||
- autoconfdir= est requis et permet de définir à la fois la variable qui
|
||
contiendra la référence ainsi que le répertoire à référencer.
|
||
- certsdir= est optionel. Si cet argument est spécifié sous la forme
|
||
certsdir=path/to/certsdir, il permet de définir à la fois la variable qui
|
||
contiendra la référence ainsi que le répertoire à référencer. Si
|
||
l'argument est spécifié sous la forme certsdir=, il permet de définir la
|
||
variable qui contiendra la référence. C'est cette variable qui sera lue
|
||
dans les fichiers de configuration. Si l'argument n'est pas spécifié, on
|
||
considère que l'argument 'certsdir=' a été utilisé.
|
||
}}}
|
||
!! {{{runs_set_lang}}}
|
||
{{{
|
||
Charger la valeur de LANG depuis l'environnement. La variable LANG est
|
||
initialisée
|
||
}}}
|
||
!! {{{runs_set_proxy}}}
|
||
{{{
|
||
Charger la valeur du proxy depuis l'environnement. Les variables
|
||
http_proxy, ftp_proxy et no_proxy sont initialisées
|
||
}}}
|
||
!! {{{runs_check_confs}}}
|
||
{{{
|
||
Vérifier l'état courant par rapport aux flags
|
||
}}}
|
||
!! {{{runs_after}}}
|
||
{{{
|
||
Vérifier que ce script est lancé après le scriptpath $1, par rapport à
|
||
RUNSSTORY
|
||
}}}
|
||
!! {{{runs_clvars}}}
|
||
{{{
|
||
Traiter les spécifications de variables données en ligne de commande ou
|
||
dans un fichier de recettes
|
||
}}}
|
||
!! {{{runs_indvars}}}
|
||
{{{
|
||
Résoudre les valeurs effectives des variables qui sont des indirections
|
||
}}}
|
||
!! {{{runs_clvars_cmd}}}
|
||
{{{
|
||
écrire la ligne de recette correspondant au script $1 et aux variables
|
||
$2..$*
|
||
}}}
|
||
!! {{{runs_loadconfs}}}
|
||
!! {{{runs_clearvars}}}
|
||
!! {{{runs_action_desc}}}
|
||
!! {{{runs_action_dump}}}
|
||
!! {{{runs_action_run}}}
|
||
!! {{{runs_action_export}}}
|
||
!! {{{shouldrun}}}
|
||
!! {{{checkdone}}}
|
||
!! {{{requiredone}}}
|
||
!! {{{setdone}}}
|
||
!! {{{resetdone}}}</pre>
|
||
</div>
|
||
<div title="ulib/runsmod.defaults" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/runsmod" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{runsmod_checkenv}}}
|
||
{{{
|
||
vérifier l'environement. créer les répertoires nécessaires.
|
||
}}}
|
||
!! {{{runsmod_should_update_repolists}}}
|
||
{{{
|
||
tester s'il faut mettre à jour au moins un des fichiers contenant les
|
||
listes des dépôts
|
||
}}}
|
||
!! {{{runsmod_update_repolists}}}
|
||
{{{
|
||
mettre à jour si nécessaire les fichiers contenant les listes des dépôts.
|
||
Si $1 n'est pas vide, forcer la mise à jour de tous les fichiers
|
||
}}}
|
||
!! {{{runsmod_setup_vars}}}
|
||
{{{
|
||
récupérer configuration statique pour la mettre à jour
|
||
}}}
|
||
!! {{{runsmod_clone_or_pull}}}
|
||
{{{
|
||
Chercher les modules $3..@, pour l'hôte $1 qui est le mode d'hôte: none,
|
||
all, self ou one pour un hôte spécifique $2. Ajouter les chemins dans le
|
||
tableau REPO_DIRS. Mettre à jour les tableaux SCRIPTS_DIRS, MODULES_DIRS
|
||
et HOSTS_DIRS
|
||
}}}
|
||
!! {{{runsmod_teardown_vars}}}</pre>
|
||
</div>
|
||
<div title="ulib/semver" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{semver_parse}}}
|
||
!! {{{semver_incmajor}}}
|
||
!! {{{semver_incminor}}}
|
||
!! {{{semver_incpatchlevel}}}
|
||
!! {{{semver_setversion}}}
|
||
!! {{{semver_setprelease}}}
|
||
!! {{{semver_compare_prelease}}}
|
||
!! {{{semver_setmetadata}}}
|
||
!! {{{semver_addmetadata}}}
|
||
!! {{{semver_compare_metadata}}}
|
||
{{{
|
||
même algo que pour prelease
|
||
}}}
|
||
!! {{{semver_copy}}}
|
||
!! {{{semver_build}}}
|
||
!! {{{semver_setvar}}}
|
||
!! {{{psemver_parse}}}
|
||
!! {{{psemver_incmajor}}}
|
||
!! {{{psemver_incminor}}}
|
||
!! {{{psemver_incpatchlevel}}}
|
||
!! {{{psemver_setversion}}}
|
||
!! {{{psemver_setprelease}}}
|
||
!! {{{psemver_compare_prelease}}}
|
||
!! {{{psemver_setmetadata}}}
|
||
!! {{{psemver_addmetadata}}}
|
||
!! {{{psemver_compare_metadata}}}
|
||
!! {{{psemver_copy}}}
|
||
!! {{{psemver_build}}}
|
||
!! {{{psemver_setvar}}}</pre>
|
||
</div>
|
||
<div title="ulib/service" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{service}}}
|
||
!! {{{service_start}}}
|
||
{{{
|
||
démarrer le service $1 de façon inconditionnelle
|
||
}}}
|
||
!! {{{service_startm}}}
|
||
{{{
|
||
démarrer le service $1 s'il n'est pas déjà démarré
|
||
}}}
|
||
!! {{{service_stop}}}
|
||
{{{
|
||
arrêter le service $1 de façon inconditionnelle
|
||
}}}
|
||
!! {{{service_stopm}}}
|
||
{{{
|
||
arrêter le service $1 s'il n'est pas déjà arrêté
|
||
}}}
|
||
!! {{{service_reload}}}
|
||
{{{
|
||
recharger le service $1
|
||
}}}
|
||
!! {{{service_status}}}
|
||
{{{
|
||
tester/afficher le status du service $1
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/sysinfos" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{read_data}}}
|
||
!! {{{dump_data}}}
|
||
!! {{{compute_local_sysinfos}}}
|
||
!! {{{compute_remote_sysinfos}}}
|
||
!! {{{ensure_sysinfos}}}
|
||
{{{
|
||
Essayer de déterminer les valeurs des variables $1(=SYSNAME), $2(=SYSDIST)
|
||
et $3(=SYSVER) en fonction des valeurs des autres. Cette fonction est à
|
||
utiliser quand on récupère cette information de la part de l'utilisateur,
|
||
et qu'il faut compléter
|
||
}}}
|
||
!! {{{get_sysinfos_desc}}}
|
||
{{{
|
||
Afficher une chaine de la forme SYSNAME/SYSDIST/SYSVER qui décrit le
|
||
système actuel
|
||
}}}
|
||
!! {{{check_sysinfos}}}
|
||
{{{
|
||
Tester si le système courant ($MYSYSNAME, $MYSYSDIST, $MYSYSVER, $MYBITS)
|
||
correspond à au moins un des arguments.
|
||
Il est possible de spécifier des variables différentes pour tester le
|
||
système courant avec l'option --vars qui doit être spécifiée en premier:
|
||
check_sysinfos --vars sysname sysdist sysver bits -d debian
|
||
Les options -s, -d, -v, -b permettent respectivement de vérifier le
|
||
système, la distribution, la version et le nombre de bits. Il est possible
|
||
de spécifier plusieurs tests à effectuer, e.g.:
|
||
check_sysinfos -d debian ubuntu -b 64
|
||
pour tester si l'on est sur une distribution debian ou ubuntu *et* sur un
|
||
système 64 bits
|
||
Note: avec l'option --vars, il peut arriver que sysname, sysdist ou sysver
|
||
ne soient pas des tableaux mais des variables scalaires, surtout si elles
|
||
sont fournies par l'utilisateur. Il est conseillé dans ce cas de tester
|
||
toutes les possibilités quand on vérifie une valeur, e.g.:
|
||
check_sysinfos --vars sysname sysdist sysver bits -s linux64 linux32 linux
|
||
pour tester si on est sur un système linux
|
||
Avec l'option -v, il est possible de suffixer la valeur avec + ou - selon
|
||
que l'on veut toutes les versions situées après ou avant la version
|
||
spécifiée. Attention, à cause d'une limitation de l'implémentation, il
|
||
faut alors impérativement filtrer aussi sur la distribution, e.g:
|
||
check_sysinfo -d debian -v lenny+
|
||
pour tester si on est en lenny ou en squeeze.
|
||
De même, l'option -d accepte aussi de suffixer la valeur avec + ou -, mais
|
||
cela n'a actuellement de sens qu'avec les version de MacOS X. Il faut
|
||
aussi impérativement filtrer sur le système, e.g:
|
||
check_sysinfos -s macosx -d 10.5+
|
||
}}}
|
||
!! {{{on_debian}}}
|
||
{{{
|
||
Tester si on est sur debian. charger le module debian si c'est le cas.
|
||
Si une commande $1..@ est spécifiée, la lancer, mais il n'est alors plus
|
||
possible de lancer des tests plus spécifiques avec __on_debian()
|
||
}}}
|
||
!! {{{on_debian:}}}
|
||
!! {{{on_stretch}}}
|
||
!! {{{on_jessie}}}
|
||
!! {{{on_wheezy}}}
|
||
!! {{{on_squeeze}}}
|
||
!! {{{on_default}}}</pre>
|
||
</div>
|
||
<div title="ulib/template" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{template_list}}}
|
||
{{{
|
||
Soit $N le séparateur --, lister les fichiers des répertoires sources
|
||
$2..$(N-1) qui seraient fusionnés avec template_merge() ou supprimés avec
|
||
template_unmerge() du répertoire destination $1. Si des chemins sont spécifiés
|
||
avec les arguments $(N+1)..@, ne traiter que les fichiers qui correspondent à
|
||
ces spécifications. Exemple:
|
||
template_list destdir srcdirs... -- specs...
|
||
}}}
|
||
!! {{{template_merge}}}
|
||
{{{
|
||
Soit $N le séparateur --, copier dans le répertoire destination $1 les
|
||
fichiers des répertoires sources $2..$(N-1) correspondant aux spécifications
|
||
$(N+1)..@, si ces fichiers n'ont pas été modifiés dans le répertoire de
|
||
destination.
|
||
Les fichiers sources ayant l'extension .template sont ignorés par défaut, sauf
|
||
s'ils sonts demandés explicitement. Exemple:
|
||
template_merge destdir srcdirs... -- specs...
|
||
}}}
|
||
!! {{{template_unmerge}}}
|
||
{{{
|
||
Soit $N le séparateur --, supprimer du répertoire destination $1 les fichiers
|
||
provenant des répertoires sources $2..$(N-1) et qui n'ont pas été modifiés. Si
|
||
des chemins sont spécifiés avec les arguments $(N+1)..@, ne traiter que les
|
||
fichiers qui correspondent à ces spécifications. Exemple:
|
||
template_unmerge destdir srcdirs... -- specs...
|
||
}}}
|
||
!! {{{template_cleandest}}}
|
||
{{{
|
||
Supprimer dans le répertoire de destination $1 tous les répertoires vides.
|
||
Cette fonction est habituellement utilisée après template_unmerge()
|
||
Ignorer les chemins qui contiennent .git/ et .svn/
|
||
}}}
|
||
!! {{{template_diff}}}
|
||
{{{
|
||
Afficher les différences entre les fichiers du répertoire de destination $1 et
|
||
les fichiers des répertoires sources $2..@
|
||
}}}
|
||
!! {{{template_srcdir}}}
|
||
{{{
|
||
Obtenir le chemin vers le répertoire source de templates $1, situé dans
|
||
ULIBDIR/templates
|
||
}}}
|
||
!! {{{templatectl_config}}}
|
||
{{{
|
||
Obtenir le chemin vers le fichier de configuration pour le répertoire $1
|
||
Si $2==nohideconfig, utiliser le nom CONFIG.conf, sinon utiliser par défaut
|
||
.CONFIG sauf si le fichier CONFIG.conf existe
|
||
}}}
|
||
!! {{{templatectl_loadvars}}}
|
||
{{{
|
||
Charger les valeurs des variables depuis le fichier $1
|
||
Les variables suivantes doivent être définies:
|
||
- Le tableau TEMPLATECTL_DEFAULTS permet de donner une valeur par défaut aux
|
||
variables mentionnées dans TEMPLATE_STATIC_VARS. C'est une liste de valeurs
|
||
de la forme 'name=value'
|
||
- Le tableau TEMPLATECTL_VARS contient des variables supplémentaires
|
||
spécifiées par l'utilisateur. C'est une liste de valeurs de la forme
|
||
'name=value'
|
||
- TEMPLATE_STATIC_VARS doit contenir une liste de noms de variables qui
|
||
peuvent être remplacés dans les fichiers de template.
|
||
- TEMPLATE_DYNAMIC_VARS contient une liste de noms de variables valides, mais
|
||
qui ne doivent pas être remplacés, en effet, ils sont utilisés pour le
|
||
déploiement des fichiers.
|
||
- TEMPLATE_NOWRITE_VARS contient une liste de noms de variables qui ne
|
||
devraient pas être écrits dans le fichier des variables, sauf si elles
|
||
reçoivent une valeur explicite de la part de l'utilisateur. Ce tableau est
|
||
mis à jour lors de l'analyse du tableau TEMPLATECTL_VARS
|
||
}}}
|
||
!! {{{templatectl_writevars}}}
|
||
{{{
|
||
Ecrire les variables dans le fichier $1
|
||
}}}
|
||
!! {{{templatectl_list_vars}}}
|
||
{{{
|
||
Afficher les valeurs des variables
|
||
}}}
|
||
!! {{{templatectl}}}
|
||
{{{
|
||
Fonction de haut niveau qui facilite l'utilisation des fonctions template_*
|
||
définir la fonction __display_templatectl_help() pour l'affichage de l'aide
|
||
- Le tableau TEMPLATECTL_SRCDIRS doit contenir la liste des répertoires
|
||
sources pour les templates. Alternativement, il est possible de définir la
|
||
variable TEMPLATECTL_SRCDIR s'il n'y a qu'un seul répertoire source pour le
|
||
template
|
||
- TEMPLATECTL_CONFIG est le nom de base du fichier à partir duquel sont
|
||
chargées les variables et dans lequel sont écrites les variables avec
|
||
l'option --write-vars
|
||
Si le nom de base est CONFIG, le fichier s'appelera .CONFIG si l'option
|
||
--hide-config est utilisée (par défaut) ou CONFIG.conf si l'option
|
||
--no-hide-config est utilisée
|
||
Les variables de template_loadvars() sont aussi prises en compte
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/tiddlywiki" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{twget_version}}}
|
||
{{{
|
||
lire le numéro de version dans le fichier $1
|
||
}}}
|
||
!! {{{twdump_header}}}
|
||
{{{
|
||
lire et afficher le contenu avant-storeArea du tiddlywiki $1
|
||
}}}
|
||
!! {{{twdump_footer}}}
|
||
{{{
|
||
lire et afficher le contenu après-storeArea du tiddlywiki $1
|
||
}}}
|
||
!! {{{twdump_storeArea}}}
|
||
{{{
|
||
lire et afficher le storeArea dans le tiddlywiki $1
|
||
}}}
|
||
!! {{{twreplace_storeArea}}}
|
||
{{{
|
||
dans le tiddlywiki $1, remplacer le storeArea par le fichier $2 (par défaut, lu sur stdin)
|
||
}}}
|
||
!! {{{twupgrade}}}
|
||
{{{
|
||
mettre à jour le tiddlywiki $1 sur la base du tiddlywiki plus récent $2
|
||
}}}
|
||
!! {{{twdate_curtwp}}}
|
||
{{{
|
||
obtenir la date courante dans le format "dd/mm/YYYY HH:MM" exprimée dans
|
||
l'heure locale
|
||
$1 est éventuellement la date exprimée en nombre de secondes depuis
|
||
l'epoch, exprimée dans l'heure locale
|
||
}}}
|
||
!! {{{twdate_tid2twp}}}
|
||
{{{
|
||
Transformer $1, une date de la forme "YYYYmmddHHMM" exprimée dans le
|
||
timezone UTC en une chaine "dd/mm/YYYY HH:MM" exprimée dans l'heure locale
|
||
Si $1 n'est pas dans le bon format, ne rien afficher
|
||
}}}
|
||
!! {{{twdate_curtid}}}
|
||
{{{
|
||
obtenir la date courante dans le format "YYYYmmddHHMM" exprimée dans le
|
||
timezone UTC
|
||
$1 est éventuellement la date exprimée en nombre de secondes depuis
|
||
l'epoch, exprimée dans l'heure locale
|
||
}}}
|
||
!! {{{twdate_twp2tid}}}
|
||
{{{
|
||
Transformer $1, une date de la forme "dd/mm/YYYY HH:MM" exprimée en heure
|
||
locale en une chaine "YYYYmmddHHMM" exprimée dans le timezone UTC
|
||
Si $1 n'est pas dans le bon format, ne rien afficher
|
||
}}}
|
||
!! {{{twdump_tiddlers}}}
|
||
{{{
|
||
dumper les tiddlers du fichier $1 généré avec twdump_storeArea() sous
|
||
forme d'une liste d'appel de fonction '__tiddler_data title creator
|
||
modifier created modified tags changecount content'
|
||
Les arguments de la fonction sont les valeurs brutes du tiddler, qui ont
|
||
simplement été corrigées avec unquote_html()
|
||
}}}
|
||
!! {{{dump_tiddler}}}
|
||
!! {{{twdump_twpage}}}
|
||
{{{
|
||
Dumper le contenu de la twpage $1 sous forme d'un appel à une function
|
||
'__twpage_data title creator modifier created modified tags changecount
|
||
content'
|
||
Les arguments de la fonction sont les valeurs brutes de la twpage, sauf
|
||
que le champ modified contient toujours la date de dernière modification
|
||
du fichier.
|
||
}}}
|
||
!! {{{twwrite_tiddler}}}
|
||
{{{
|
||
Ecrire sur STDOUT le tiddler correspondant aux paramètres sont spécifiés
|
||
sur la ligne de commande. Les arguments sont les valeurs brutes prises de
|
||
la twpage, telles qu'elles sont générées par twdump_twpage()
|
||
}}}
|
||
!! {{{twcheck_twpage_modified}}}
|
||
{{{
|
||
Vérifier si la twpage $1 peut être écrasée par un tiddler dont la date de
|
||
modification est $2, de format "YYYYmmddHHMM" exprimée dans le timezone
|
||
UTC
|
||
C'est le cas si le fichier $1 n'existe pas, ou a une date de modification
|
||
antérieure à $2
|
||
}}}
|
||
!! {{{twcheck_twpage_newtwpage}}}
|
||
{{{
|
||
Vérifier si la twpage $1 peut être écrasée par la twpage $2
|
||
C'est le cas si le fichier $1 n'existe pas, ou a une date de modification
|
||
antérieure à $2
|
||
}}}
|
||
!! {{{twwrite_twpage}}}
|
||
{{{
|
||
Ecrire dans le répertoire courant le fichier correspondant au tiddler dont
|
||
les paramètres sont spécifiés sur la ligne de commande. Les arguments sont
|
||
les valeurs brutes prises du tiddler, telles qu'elles sont générées par
|
||
twdump_tiddlers()
|
||
Retourner 0 si le fichier a été écrasé, 1 s'il n'a pas été écrasé parce
|
||
qu'il n'a pas été modifié, 2 s'il n'a pas été écrasé parce qu'il est plus
|
||
récent.
|
||
Si TW_VERBOSE=1, afficher un message informatif lors de l'export
|
||
}}}
|
||
!! {{{export_to_twpages}}}
|
||
{{{
|
||
Exporter tous les tiddlers du tiddlywiki $1 dans le répertoire $2
|
||
}}}
|
||
!! {{{import_from_twpages}}}
|
||
{{{
|
||
Remplacer les tiddlers du tiddlywiki $1 par les twpages du répertoire $2
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/udir" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{udir_check}}}
|
||
{{{
|
||
Vérifier si le fichier $1 existe
|
||
Si $1 est un répertoire, prendre $1/.udir
|
||
}}}
|
||
!! {{{udir_create_maybe}}}
|
||
{{{
|
||
Si le fichier $1 n'existe pas, le créer comme un template .udir
|
||
Si $1 est un répertoire, prendre $1/.udir
|
||
}}}
|
||
!! {{{udir_dump}}}
|
||
{{{
|
||
Dumper toutes les variables définies pour le fichier $1
|
||
Si $1 est un répertoire, prendre $1/.udir
|
||
}}}
|
||
!! {{{udir_eval}}}
|
||
{{{
|
||
Evaluer la commande "$2..$*" dans le contexte des variables définies pour
|
||
le répertoire $1. La commande est évaluée dans un sous-shell pour ne pas
|
||
polluer l'espace de noms courant.
|
||
}}}
|
||
!! {{{udir_dump_all}}}
|
||
{{{
|
||
Dumper toutes les variables définies pour le répertoire $1 et *tous ses
|
||
parents* jusqu'à la racine
|
||
}}}
|
||
!! {{{udir_eval_all}}}
|
||
{{{
|
||
Evaluer la commande "$2..$*" dans le contexte des variables définies pour
|
||
le répertoire $1 et *tous ses parents* jusqu'à la racine
|
||
}}}
|
||
!! {{{udir_parse}}}
|
||
{{{
|
||
Dans le fichier $1, lire les noms des variables
|
||
Si $1 est un répertoire, prendre $1/.udir
|
||
Les noms des variables sont placés dans le tableau $2(=UDIR_VARS), et les noms
|
||
des tableaux sont placés dans le tableau $3(=UDIR_ARRAYS)
|
||
note: les regex qui sont entre "" au lieu de // le sont à cause d'un bug
|
||
de awk sous macosx
|
||
}}}
|
||
!! {{{udir_update}}}
|
||
{{{
|
||
Dans le fichier $1, mettre à jour les variables $2..*
|
||
Si $1 est un répertoire, prendre $1/.udir
|
||
Chaque argument de cette fonction est de la forme name[=value]
|
||
Si value n'est pas précisée, la variable obtient une valeur nulle
|
||
(i.e. var=)
|
||
Si la variable ne figure pas dans le fichier, elle est rajoutée à la fin
|
||
du fichier.
|
||
Cette fonction nécessite gawk.
|
||
}}}
|
||
!! {{{write_unseen}}}
|
||
!! {{{udir_edit}}}</pre>
|
||
</div>
|
||
<div title="ulib/uenv" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre></pre>
|
||
</div>
|
||
<div title="ulib/uenv_update" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{uenv_update_dir}}}
|
||
{{{
|
||
Mettre à jour l'ordre de chargement pour le répertoire $1 qui contient des
|
||
fichiers de profil pour le shell. L'ordre dans lequel le fichiers de
|
||
profil doivent être chargé est écrit dans le fichier $1/.source_in_order
|
||
Si $2 est spécifié, il s'agit d'un fichier temporaire utilisé pour les
|
||
calculs de l'ordre des chargements.
|
||
$3(=$1) est le répertoire de destination. Si $1 est un répertoire de
|
||
préparation temporaire, on peut spécifier grâce à $3 quel est le
|
||
répertoire final après préparation.
|
||
S'ils sont spécifiés, les arguments $4..* sont des répertoires contenant
|
||
des fichiers de profils supplémentaires qu'il faut considérer aussi. Dans
|
||
ce cas, $3 est ignoré.
|
||
}}}
|
||
!! {{{uenv_set_destdirs}}}
|
||
!! {{{uenv_sourced_in}}}
|
||
{{{
|
||
vérifier que l'un des fichiers $2..$* est sourcé dans $1
|
||
}}}
|
||
!! {{{uenv_configure_profiles}}}
|
||
!! {{{uenv_install_profiles}}}</pre>
|
||
</div>
|
||
<div title="ulib/uinc" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{uinc}}}</pre>
|
||
</div>
|
||
<div title="ulib/uinst" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{uinst}}}
|
||
{{{
|
||
lancer uinst en déclarant les variables locales, de façon à ne pas polluer
|
||
l'environnement de l'appelant.
|
||
}}}
|
||
!! {{{uinst_nolocal}}}
|
||
{{{
|
||
Interface en mode ligne de commande pour uinst. Appeler cette fonction
|
||
avec les paramètres de la ligne de commande, e.g.:
|
||
uinst_nolocal "$@"
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/ulib" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{eerror}}}
|
||
!! {{{die}}}
|
||
!! {{{uprovided}}}
|
||
{{{
|
||
Tester si le module $1 a déjà été chargé par urequire
|
||
}}}
|
||
!! {{{uprovide}}}
|
||
{{{
|
||
Spécifier que le module $1 a été sourcée, ou prétendre que c'est le cas.
|
||
Retourner 1 si le module était déjà pourvu, 0 si c'est la première fois
|
||
qu'on le pourvoit
|
||
}}}
|
||
!! {{{urequire}}}
|
||
{{{
|
||
Sourcer un module recherché dans ULIBDIRS
|
||
Le module DEFAULTS est traité de façon particulière: si le fichier associé
|
||
n'est pas trouvé, charger base, pretty, sysinfos et compat à la place
|
||
Si un module n'est pas trouvé, quitter le script avec die()
|
||
}}}
|
||
!! {{{ulibadd}}}
|
||
{{{
|
||
Ajouter $1 au chemin de recherche de urequire
|
||
}}}
|
||
!! {{{ulibsync}}}
|
||
{{{
|
||
Synchroniser les modules de ulib dans le répertoire $1
|
||
}}}
|
||
!! {{{ulibver}}}
|
||
{{{
|
||
Vérifier que la version actuelle de ulib est au moins à la version $1
|
||
(inclue) et éventuellement au plus à la version $2 (exclue)
|
||
}}}
|
||
!! {{{ulibver_require}}}</pre>
|
||
</div>
|
||
<div title="ulib/ulibsh" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{eerror}}}
|
||
!! {{{die}}}
|
||
!! {{{uprovided}}}
|
||
!! {{{uprovide}}}
|
||
!! {{{urequire}}}
|
||
!! {{{ulibadd}}}
|
||
!! {{{ulibsync}}}
|
||
!! {{{ulibver}}}
|
||
!! {{{ulibver_require}}}</pre>
|
||
</div>
|
||
<div title="ulib/vcs" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{vcs_getvcs_help}}}
|
||
!! {{{vcs_getvcs}}}
|
||
!! {{{vcs_getroot_help}}}
|
||
!! {{{vcs_getroot}}}
|
||
!! {{{vcs_getrepos_help}}}
|
||
!! {{{vcs_getrepos}}}
|
||
!! {{{vcs_geturl_help}}}
|
||
!! {{{vcs_geturl}}}
|
||
!! {{{vcs_vcs_help}}}
|
||
!! {{{vcs_vcs}}}
|
||
!! {{{vcs_add_help}}}
|
||
!! {{{vcs_add}}}
|
||
{{{
|
||
le répertoire de référence est le répertoire du premier fichier ajouté
|
||
}}}
|
||
!! {{{vcs_remove_help}}}
|
||
!! {{{vcs_remove}}}
|
||
{{{
|
||
le répertoire de référence est le répertoire du premier fichier supprimé
|
||
}}}
|
||
!! {{{vcs_copy_help}}}
|
||
!! {{{vcs_copy}}}
|
||
{{{
|
||
le répertoire de référence est le répertoire de destination
|
||
}}}
|
||
!! {{{vcs_move_help}}}
|
||
!! {{{vcs_move}}}
|
||
{{{
|
||
le répertoire de référence est le répertoire de destination
|
||
}}}
|
||
!! {{{vcs_mkdir_help}}}
|
||
!! {{{vcs_mkdir}}}
|
||
{{{
|
||
le répertoire de référence est le répertoire du premier répertoire créé
|
||
}}}
|
||
!! {{{vcs_commit_help}}}
|
||
!! {{{vcs_commit}}}
|
||
!! {{{vcs_status_help}}}
|
||
!! {{{vcs_status}}}
|
||
!! {{{vcs_update_help}}}
|
||
!! {{{vcs_update}}}
|
||
!! {{{vcs_push_help}}}
|
||
!! {{{vcs_push}}}
|
||
!! {{{vcs_diff_help}}}
|
||
!! {{{vcs_diff}}}
|
||
!! {{{vcs_tag_help}}}
|
||
!! {{{vcs_tag}}}
|
||
!! {{{git_getrepos}}}
|
||
!! {{{git_geturl}}}
|
||
!! {{{git_have_annex}}}
|
||
!! {{{git_add}}}
|
||
!! {{{git_remove}}}
|
||
!! {{{git_copy}}}
|
||
!! {{{git_move}}}
|
||
!! {{{git_mkdir}}}
|
||
!! {{{git_commit}}}
|
||
!! {{{git_status}}}
|
||
!! {{{git_update}}}
|
||
!! {{{git_push}}}
|
||
!! {{{git_diff}}}
|
||
!! {{{git_tag}}}
|
||
!! {{{git_check_gitvcs}}}
|
||
!! {{{git_ensure_gitvcs}}}
|
||
!! {{{git_list_branches}}}
|
||
!! {{{git_list_rbranches}}}
|
||
!! {{{git_list_pbranches}}}
|
||
{{{
|
||
lister les branches locales et celles qui existent dans l'origine
|
||
$1(=origin) et qui pourraient devenir une branche locale avec la commande
|
||
git checkout -b
|
||
}}}
|
||
!! {{{git_have_branch}}}
|
||
!! {{{git_have_rbranch}}}
|
||
!! {{{git_get_branch}}}
|
||
!! {{{git_get_branch_remote}}}
|
||
!! {{{git_get_branch_merge}}}
|
||
!! {{{git_get_branch_rbranch}}}
|
||
!! {{{git_is_branch}}}
|
||
!! {{{git_have_remote}}}
|
||
!! {{{git_track_branch}}}
|
||
!! {{{git_ensure_branch}}}
|
||
{{{
|
||
retourner 0 si la branche a été créée, 1 si elle existait déjà, 2 en cas d'erreur
|
||
}}}
|
||
!! {{{git_check_cleancheckout}}}
|
||
{{{
|
||
vérifier qu'il n'y a pas de modification locales dans le dépôt
|
||
correspondant au répertoire courant.
|
||
}}}
|
||
!! {{{git_ensure_cleancheckout}}}
|
||
!! {{{git_is_ancestor}}}
|
||
{{{
|
||
vérifier que la branche $1 est un ancêtre direct de la branche $2, qui
|
||
vaut par défaut refs/remotes/${3:-origin}/$1
|
||
note: cette fonction retourne vrai si $1 et $2 identifient le même commit
|
||
}}}
|
||
!! {{{git_should_ff}}}
|
||
{{{
|
||
vérifier si la branche $1 devrait être fast-forwardée à partir de la
|
||
branche d'origine $2, qui vaut par défaut refs/remotes/${3:-origin}/$1
|
||
note: cette fonction est similaire à git_is_ancestor(), mais retourne
|
||
false si $1 et $2 identifient le même commit
|
||
}}}
|
||
!! {{{git_should_push}}}
|
||
{{{
|
||
vérifier si la branche $1 devrait être poussée vers la branche de même nom
|
||
dans l'origine $2(=origin), parce que l'origin peut-être fast-forwardée à
|
||
partir de cette branche.
|
||
}}}
|
||
!! {{{git_fast_forward}}}
|
||
{{{
|
||
vérifier que la branche courante est bien $1, puis tester s'il faut la
|
||
fast-forwarder à partir de la branche d'origine $2, puis le faire si c'est
|
||
nécessaire. la branche d'origine $2 vaut par défaut refs/remotes/origin/$1
|
||
}}}
|
||
!! {{{git_is_merged}}}
|
||
{{{
|
||
vérifier que les branches $1 et $2 ont un ancêtre commun, et que la
|
||
branche $1 a été complètement fusionnée dans la branche destination $2
|
||
}}}
|
||
!! {{{git_annex_initial}}}
|
||
{{{
|
||
sur le dépôt $1 fraichement cloné, vérifier s'il faut faire git annex
|
||
init. Si oui, l'initialiser avec le nom d'hôte, et récupérer tous les
|
||
fichiers annexés
|
||
retourner 1 si une erreur s'est produite
|
||
}}}
|
||
!! {{{svn_getrepos}}}
|
||
!! {{{svn_geturl}}}
|
||
!! {{{svn_add}}}
|
||
!! {{{svn_remove}}}
|
||
!! {{{svn_copy}}}
|
||
!! {{{svn_move}}}
|
||
!! {{{svn_mkdir}}}
|
||
!! {{{svn_commit}}}
|
||
!! {{{svn_status}}}
|
||
!! {{{svn_update}}}
|
||
!! {{{svn_push}}}
|
||
!! {{{svn_diff}}}
|
||
!! {{{svn_tag}}}
|
||
!! {{{cvs_getrepos}}}
|
||
!! {{{cvs_geturl}}}
|
||
!! {{{cvs_add}}}
|
||
!! {{{cvs_remove}}}
|
||
!! {{{cvs_copy}}}
|
||
!! {{{cvs_move}}}
|
||
!! {{{cvs_mkdir}}}
|
||
!! {{{cvs_commit}}}
|
||
!! {{{cvs_status}}}
|
||
!! {{{cvs_update}}}
|
||
!! {{{cvs_push}}}
|
||
!! {{{cvs_diff}}}
|
||
!! {{{cvs_tag}}}</pre>
|
||
</div>
|
||
<div title="ulib/virsh" creator="jclain" modifier="jclain" created="201203300043" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{virsh_filter}}}
|
||
{{{
|
||
filtrer une sortie liste de virsh. En pratique, ne prendre que les lignes
|
||
non vides à partir de la ligne "----*"
|
||
}}}
|
||
!! {{{virsh_list}}}
|
||
!! {{{virsh_pool_list}}}
|
||
!! {{{guess_vm_type}}}
|
||
{{{
|
||
Afficher hn, kvm, vmware, virtualbox ou openvz suivant que l'on est
|
||
*probablement* respectivement sur une machine physique, une machine
|
||
virtuelle kvm, vmware, virtualbox, openvz
|
||
XXX pour le moment, seuls openvz, kvm et hn sont supportés
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/webobjects" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{compute_webobjects_prefixes}}}
|
||
!! {{{recompute_webobjects_prefixes}}}
|
||
!! {{{get_NEXT_ROOT_prefix}}}
|
||
!! {{{get_WOROOT_prefix}}}
|
||
!! {{{get_LOCALROOT_prefix}}}
|
||
!! {{{get_SYSTEMFRAMEWORKS_prefix}}}
|
||
!! {{{get_WOEXTENSIONS_prefix}}}
|
||
!! {{{get_WOFRAMEWORKS_prefix}}}
|
||
!! {{{get_WOAPPLICATIONS_prefix}}}
|
||
!! {{{get_WOCONFIGURATION_prefix}}}
|
||
!! {{{get_WOAUTOSTART_prefix}}}
|
||
!! {{{get_WOLOGS_prefix}}}
|
||
!! {{{get_WOVERSION_prefix}}}
|
||
!! {{{is_wobundle}}}
|
||
{{{
|
||
Tester si $1 a un nom de bundle valide, c'est à dire avec l'extension .woa
|
||
ou .framework
|
||
}}}
|
||
!! {{{is_woappdir}}}
|
||
{{{
|
||
Tester si $1 est un répertoire d'application webobjects. Le test est
|
||
effectué sur le contenu du bundle, pas sur le nom (utiliser is_wobundle()
|
||
pour cela)
|
||
}}}
|
||
!! {{{is_wofwkdir}}}
|
||
{{{
|
||
Tester si $1 est un répertoire de framework webobjects. Le test est
|
||
effectué sur le contenu du bundle, pas sur le nom (utiliser is_wobundle()
|
||
pour cela)
|
||
}}}
|
||
!! {{{get_app_winclspth}}}
|
||
{{{
|
||
calculer la valeur de Contents/Windows/CLSSPATH.txt pour l'application $1
|
||
}}}
|
||
!! {{{get_infofile}}}
|
||
{{{
|
||
Obtenir le chemin vers le fichier Info.plist dans le répertoire de
|
||
resource du bundle $1
|
||
}}}
|
||
!! {{{read_infofile}}}
|
||
{{{
|
||
Lire la version et le numéro de release dans le fichier $1 (chemin vers
|
||
Info.plist) et les placer dans les variables $2(=version) et $3(=release)
|
||
Retourner 1 si un erreur s'est produite, par exemple si le fichier $1
|
||
n'existe pas ou n'est pas accessible en lecture
|
||
}}}
|
||
!! {{{write_infofile}}}
|
||
{{{
|
||
Ecrire $2 (la version) et $3 (le numéro de release) dans le fichier $1
|
||
(chemin vers Info.plist)
|
||
Retourner 1 si un erreur s'est produite, par exemple si le fichier $1
|
||
n'existe pas
|
||
}}}
|
||
!! {{{get_jawotoolsfile}}}
|
||
{{{
|
||
Obtenir le chemin vers le fichier jawotools.properties dans le bundle $1
|
||
}}}
|
||
!! {{{read_jawotoolsfile}}}
|
||
{{{
|
||
lire le fichier de propriété $1 et placer les valeurs dans les variables
|
||
$2(=version), $3(=releaseDate), $4(=description)
|
||
}}}
|
||
!! {{{save_jawotoolsfile}}}
|
||
{{{
|
||
écrire le fichier de propriété $1 avec les valeurs version ($2),
|
||
releaseDate ($3) et description ($4)
|
||
}}}
|
||
!! {{{get_versionfile}}}
|
||
{{{
|
||
Obtenir le chemin vers le fichier VERSION.txt dans le répertoire de
|
||
resource du bundle $1
|
||
}}}
|
||
!! {{{get_configfile}}}
|
||
{{{
|
||
obtenir le chemin vers le fichier de configuration du répertoire de
|
||
resource du bundle
|
||
$1=bundle ou resdir (appdir/Contents/Resources ou fwkdir/Resources)
|
||
}}}
|
||
!! {{{searchreplace_classpath}}}
|
||
{{{
|
||
Dans les fichiers classpath de l'application $1, remplacer $2 par $3. Si
|
||
$3 est vide, la ligne est supprimée
|
||
}}}
|
||
!! {{{dump_jars}}}
|
||
{{{
|
||
Afficher les jars des frameworks utilisés par l'application $1
|
||
}}}
|
||
!! {{{dump_frameworks}}}
|
||
{{{
|
||
Afficher les frameworks utilisés par l'application $1
|
||
}}}
|
||
!! {{{remove_framework}}}
|
||
{{{
|
||
supprimer le framework $2 (nom de base) des fichiers de classpath du
|
||
bundle d'application $1
|
||
}}}
|
||
!! {{{add_framework}}}
|
||
{{{
|
||
s'il n'y existe pas déjà, ajouter le framework $2 (nom de base ou chemin
|
||
absolu) aux fichiers de classpath du bundle d'application $1
|
||
}}}
|
||
!! {{{fix_jars_case}}}
|
||
{{{
|
||
Vérifier que la casse des jars de tous les frameworks utilisés par
|
||
l'application $1 est conforme au système de fichier
|
||
}}}
|
||
!! {{{verifix_bundle}}}
|
||
{{{
|
||
vérifier et corriger le bundle $1. Pour une application, on vérifie que le
|
||
script est exécutable. Pour un framework, on vérifie que le framework est
|
||
conforme au modèle des framework générés par WebObjects.
|
||
}}}
|
||
!! {{{compute_fapps}}}
|
||
{{{
|
||
Placer dans le tableau $1(=fappnames) la liste des noms de bundle
|
||
d'applications qui dépendent du framework $2
|
||
Cette opération est faite à partir des informations sur le système de
|
||
fichier. Elle ne peut donc concerner qu'une installation locale.
|
||
}}}
|
||
!! {{{woraurl}}}
|
||
{{{
|
||
Faire une requête avec la méthode $1 sur l'url $2 avec le payload $3 (par
|
||
exemple pour la méthode POST). la réponse est disponible dans le fichier
|
||
$WORAURL_DATA, $4(=http_code) contient le code de réponse.
|
||
Retourner 0 en cas de succès, ou une valeur différente de zéro si un
|
||
erreur se produit (typiquement, 3 pour une erreur du serveur, 1 pour une
|
||
réponse applicative, comme par exemple si l'application n'existe pas)
|
||
Les codes de réponse 2xx et 417 sont des succès
|
||
Les autres codes (à priori 4xx ou 5xx) sont des erreurs
|
||
note: le code 417 est utilisé par le moniteur pour répondre "Non", par
|
||
opposition à 200 utilisé pour répondre "OUI"
|
||
}}}
|
||
!! {{{wogeturl}}}
|
||
!! {{{splitins}}}
|
||
{{{
|
||
Analyser le nom $1, qui peut être de forme '', 'Name.woa',
|
||
'Name.framework', 'App' ou 'Instance-N' (où N est un nombre), et
|
||
initialiser les variables $2(=type) et $3(=name)
|
||
Si $1=="", type=all et name=""
|
||
Si $1==Name.woa, type=woa et name=Name.woa
|
||
Si $1==Name.framework, type=fwk et name=Name.framework
|
||
Si $1==App, type=app et name=App
|
||
si $1==App-N, type=ins et name=App-N
|
||
}}}
|
||
!! {{{create_wodirs_maybe}}}
|
||
!! {{{check_autostart}}}
|
||
{{{
|
||
vérifier la présence du fichier $WOAUTOSTART. Si ce n'est pas le cas, le
|
||
créer avec le contenu du tableau $1
|
||
}}}
|
||
!! {{{get_autostart_order}}}
|
||
{{{
|
||
Initialiser le tableau $1 avec la liste donnée dans le fichier
|
||
$WOAUTOSTART
|
||
}}}
|
||
!! {{{apply_autostart_order}}}
|
||
{{{
|
||
Réordonner les valeurs $3..* selon la liste donnée dans le tableau $2,
|
||
puis placer le résultat dans le tableau $1. $2 doit être construit avec
|
||
get_autostart_order(). Si $2 n'est pas spécifié, la liste est construite
|
||
localement.
|
||
Si le tableau contient des lignes de délai @N, replacer les délais après
|
||
les applications appropriées
|
||
}}}
|
||
!! {{{wotaskd_stop}}}
|
||
!! {{{wotaskd_start}}}
|
||
!! {{{javamonitor_stop}}}
|
||
!! {{{womonitor_stop}}}
|
||
!! {{{javamonitor_start}}}
|
||
!! {{{womonitor_start}}}
|
||
!! {{{woservices_stop}}}
|
||
!! {{{woservices_start}}}</pre>
|
||
</div>
|
||
<div title="ulib/woinst" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{date2version}}}
|
||
!! {{{woconf}}}
|
||
!! {{{wotag}}}
|
||
!! {{{woinst}}}</pre>
|
||
</div>
|
||
<div title="ulib/wondermonitor" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{wom__statistics}}}
|
||
{{{
|
||
Afficher les statistiques pour le serveur $1, avec éventuellement le mot
|
||
de passe $2
|
||
}}}
|
||
!! {{{wom__info}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et afficher des informations sur l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom__info_filter}}}
|
||
{{{
|
||
filtrer le résultat de wom__info en ne gardant que les tags
|
||
name, state, activeSessions, autoRecover, deaths, host, port
|
||
}}}
|
||
!! {{{wom_info}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $3, avec éventuellement le mot de passe
|
||
$4, et initialiser le tableau $1 avec une liste de valeurs quotés de la
|
||
forme:
|
||
"'name' 'state' 'activeSessions' 'autoRecover' 'deaths' 'host' 'port'"
|
||
concernant l'application $2 (par défaut, toutes les applications). Notez
|
||
qu'il y a une ligne par instance d'application
|
||
Ces valeurs peuvent être utilisées comme arguments d'une fonction. par
|
||
exemple:
|
||
wom_info appinfos "" host pw
|
||
for args in "${appinfos[@]}"; do
|
||
eval "userfunc $args"
|
||
done
|
||
}}}
|
||
!! {{{wom_getValidAndRunning}}}
|
||
{{{
|
||
Placer la liste des applications valides dans le tableau $1(=valid_apps)
|
||
et la liste des applications qui tournent dans le tableau
|
||
$2=(running_apps), en contactant le moniteur sur l'hôte $3, avec
|
||
éventuellement le mot de passe $4.
|
||
}}}
|
||
!! {{{show_appinfo}}}
|
||
{{{
|
||
Afficher des informations sur une application. Les arguments doivent être
|
||
le résultat de la fonction wom_info()
|
||
}}}
|
||
!! {{{wom_running}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et tester si l'application $1 (par défaut, all) tourne actuellement
|
||
}}}
|
||
!! {{{wom_start}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et démarrer l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom_stopped}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et tester si l'application $1 (par défaut, all) est actuellement arrêtée
|
||
}}}
|
||
!! {{{wom_stop}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et arrêter l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom_forceQuit}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et forcer l'arrêt de l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom_turnScheduledOn}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et activer le flag scheduled sur l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom_turnScheduledOff}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et désactiver le flag scheduled sur l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom_turnRefuseNewSessionOn}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et activer le flag refuseNewSession sur l'application $1 (par défaut,
|
||
all)
|
||
}}}
|
||
!! {{{wom_turnRefuseNewSessionOff}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et désactiver le flag refuseNewSession sur l'application $1 (par
|
||
défaut, all)
|
||
}}}
|
||
!! {{{wom_turnAutoRecoverOn}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et activer le flag autoRecover sur l'application $1 (par défaut, all)
|
||
}}}
|
||
!! {{{wom_turnAutoRecoverOff}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et désactiver le flag autoRecover sur l'application $1 (par défaut,
|
||
all)
|
||
}}}
|
||
!! {{{wom_bounce}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et redémarrer l'application $1 (par défaut, all) en mode bounce
|
||
}}}
|
||
!! {{{wom_clearDeaths}}}
|
||
{{{
|
||
Contacter le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3, et effacer le compte des morts suspectes pour l'application $1 (par
|
||
défaut, all)
|
||
}}}
|
||
!! {{{wom__getApplications}}}
|
||
{{{
|
||
Obtenir des information sur la définition de l'application $1 (ou de
|
||
toutes les applications si $1=="") en contactant le moniteur sur l'hôte $2
|
||
avec éventuellement le mot de passe $3. Le résultat est un flux xml,
|
||
chaque application étant défini dans un tag <MApplications>. Si un erreur
|
||
se produit, l'erreur est dans un tag <Strings>
|
||
}}}
|
||
!! {{{wom__getApplications_filter}}}
|
||
{{{
|
||
filtrer le résultat de wom__getApplications en ne gardant que les tags
|
||
name, unixPath, macPath, winPath
|
||
}}}
|
||
!! {{{wom_getApplications}}}
|
||
{{{
|
||
Obtenir la liste des applications définies en contactant le moniteur sur
|
||
l'hôte $3 avec éventuellement le mot de passe $4, et initialiser le
|
||
tableau $1 avec une liste de valeurs quotées de la forme:
|
||
"'name' 'unixPath' 'macPath' 'winPath'"
|
||
concernant l'application $2 (par défaut, toutes les applications)
|
||
Ces valeurs peuvent être utilisées comme arguments d'une fonction. par
|
||
exemple:
|
||
wom_getApplications appinfos "" host pw
|
||
for args in "${appinfos[@]}"; do
|
||
eval "userfunc $args"
|
||
done
|
||
}}}
|
||
!! {{{wom_addApplication}}}
|
||
{{{
|
||
Ajouter une application nommée $1 en contactant le moniteur sur l'hôte $2,
|
||
avec éventuellement le mot de passe $3.
|
||
Soit le nom Name, par défaut l'exécutable se trouve dans
|
||
WOAPPLICATIONS/Name.woa/Name et les logs dans /var/log/WebObjects, et le
|
||
flag autoRecover est activé
|
||
XXX supporter la possibilité de modifier les valeurs par défaut
|
||
}}}
|
||
!! {{{wom_addInstance}}}
|
||
{{{
|
||
Ajouter une instance sur localhost pour l'application nommée $1 en
|
||
contactant le moniteur sur l'hôte $2, avec éventuellement le mot de passe
|
||
$3.
|
||
XXX supporter la possibilité de modifier les valeurs par défaut
|
||
}}}
|
||
!! {{{check_compute_apps_localhost}}}
|
||
{{{
|
||
si les arguments de compute_apps contiennent des bundles de framework, il
|
||
faut avoir accès au système de fichier local. vérifier si l'un des
|
||
arguments $2..* est un framework. si c'est le cas, vérifier que l'hôte $1
|
||
est localhost.
|
||
retourner 0 si c'est ok, 1 s'il y a des frameworks et que host n'est pas
|
||
localhost
|
||
}}}
|
||
!! {{{compute_apps}}}
|
||
{{{
|
||
Remplir le tableau $1(=apps) avec la liste des applications correspondant
|
||
aux arguments $3...*
|
||
Un bundle de framework (Name.framework) est remplacé par la liste des
|
||
bundles d'applications qui dépendent de ce framework. Cette information
|
||
est obtenue en consultant le système de fichier local.
|
||
Un bundle d'application est remplacé par la liste des applications qui
|
||
sont définies pour ce bundle. Cette information est obtenue en consultant
|
||
le tableau généré par wom_getApplications(), dont le nom est $2
|
||
Les arguments de la forme @N sont ignorés, ils correspondent à des délais
|
||
à respecter lors du démarrage de l'application
|
||
}}}
|
||
!! {{{get_error_msg}}}
|
||
!! {{{start_apps}}}
|
||
{{{
|
||
Démarrer les applications $3..$* en contactant le moniteur sur l'hôte $1
|
||
avec le mot de passe éventuel $2
|
||
Les variables globales enable_autorecover et force_enable_autorecover
|
||
permettent respectivement d'activer l'autoRecover après le démarrage de
|
||
l'application et de forcer l'activation de l'autoRecover même si
|
||
l'instance tournait déjà.
|
||
Un argument de la forme @N provoque une attente de N secondes. Ceci permet
|
||
de placer un temps d'attente entre le démarrage de certaines applications.
|
||
}}}
|
||
!! {{{stop_apps}}}
|
||
{{{
|
||
Arrêter les applications $3..$* en contactant le moniteur sur l'hôte $1
|
||
avec le mot de passe éventuel $2
|
||
Les variables globales disable_autorecover et force_disable_autorecover
|
||
permettent respectivement de désactiver l'autoRecover après l'arrêt de
|
||
l'application et de forcer la désactivation de l'autoRecover même si
|
||
l'instance ne tournait pas.
|
||
L'option {-a ARRAY} permet de remplir ARRAY avec la liste des applications
|
||
qui ont été effectivement arrêtées. Cette option si elle est spécifiée
|
||
doit être en premier
|
||
Pour compatibilité avec start_apps, les arguments de la forme @N sont
|
||
ignorés. Il n'y a pas de temps d'attente entre les applications lors de
|
||
l'arrêt.
|
||
}}}
|
||
!! {{{bounce_apps}}}
|
||
{{{
|
||
Redémarrer les applications $3..$* en mode bounce en contactant le
|
||
moniteur sur l'hôte $1 avec le mot de passe éventuel $2
|
||
Pour compatibilité avec start_apps, les arguments de la forme @N sont
|
||
ignorés. Il n'y a pas de temps d'attente entre les applications lors du
|
||
redémarrage.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/wosign" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{wosign_setup_maybe}}}
|
||
!! {{{wosign_jar}}}
|
||
!! {{{wosignable}}}
|
||
!! {{{wosign}}}
|
||
{{{
|
||
Signer un bundle, les jars d'un répertoire, ou un jar
|
||
L'option -f force la resignature des jars d'un répertoire ou d'un
|
||
bundle. Elle force aussi la signature d'un jar, même s'il semble qu'il
|
||
soit la version signée d'un autre jar
|
||
on présuppose que wosignable a retourné true
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulib/wotaskd" creator="jclain" modifier="jclain" created="201203151815" modified="201605130537" tags="" changecount="1">
|
||
<pre>!! {{{wot_config}}}
|
||
{{{
|
||
Afficher la configuration de wotaskd
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulibshell" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ulibshell: Lancer un shell après avoir chargé des modules de ulib
|
||
|
||
USAGE
|
||
ulibshell [options] [args...]
|
||
|
||
OPTIONS
|
||
-r module
|
||
Spécifier un module à charger avec urequire. Plusieurs modules peuvent
|
||
être spécifiés en les séparant par ':'
|
||
|
||
Un shell est lancé dans lequel les modules spécifiés sont chargés. Par défaut,
|
||
seul le module DEFAULTS est chargé. Les arguments sont passés inchangés au
|
||
shell.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulibsync" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ulibsync: Copier les librairies ulib et/ou pyulib
|
||
|
||
USAGE
|
||
ulibsync [options] destdir
|
||
|
||
OPTIONS
|
||
-u Copier ulib
|
||
-p Copier pyulib
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ulink" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ulink: déplacer, supprimer, copier un fichier ou un lien
|
||
|
||
Quand on déplace ou qu'on copie un lien, la destination du lien est mise à jour
|
||
|
||
USAGE
|
||
ulink mv files... dest
|
||
ulink cp files... dest
|
||
ulink rm files...
|
||
|
||
OPTIONS
|
||
-d UPDATEDIR
|
||
Chercher dans UPDATEDIR tous les liens qui pointent vers le fichier
|
||
concerné, et mettre à jour ces liens après avoir déplacé le fichier, ou
|
||
supprimer ces liens si le fichier est supprimé.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="umatch" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
umatch: Afficher le résultat d'une recherche par regexp et compter
|
||
éventuellement leurs occurences
|
||
|
||
USAGE
|
||
umatch [options] [regexp]
|
||
|
||
Chaque ligne *entière* de stdin est mise en correspondance avec l'expression
|
||
regulière qui doit avoir la syntaxe de awk. S'il y a correspondance, afficher
|
||
soit toute l'expression matchée, soit chaque groupe s'il y a des expressions
|
||
parenthésées, chacun des groupes étant séparé par le caractère sep.
|
||
|
||
Si l'expression régulière n'est pas spécifiée, elle vaut par défaut '.*' ce qui
|
||
fait que toutes les lignes correspondent. Ceci peut être utile avec les options
|
||
-s et -c.
|
||
|
||
Certaines expressions régulières sont prédéfinies. regexp peut avoir l'une des
|
||
valeurs prédéfinies suivantes:
|
||
|
||
ip --> [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
|
||
|
||
OPTIONS
|
||
-F sep
|
||
Spécifier le caractère séparateur en sortie s'il faut afficher des
|
||
champs multiples. Par défaut, utiliser le caractère ':'
|
||
Si un séparateur vide est spécifié, le séparateur standard de awk est
|
||
utilisé.
|
||
-s Trier le résultat
|
||
-C FIELDNUM
|
||
-c, --count
|
||
Compter les occurences successives de la valeur du champ FIELDNUM, et
|
||
afficher une ligne de la forme 'count<sep>last_line' pour chaque groupe,
|
||
last_line étant la dernière occurence du groupe. L'option -c correspond
|
||
à '-C 0', c'est à dire compter les occurences successives de toute les
|
||
lignes.
|
||
Le séparateur utilisé pour calculer le numéro de champ est sep, spécifié
|
||
avec l'option -F.
|
||
-a, --all-lines
|
||
Avec les options -c/-C, afficher toutes les lignes des occurences
|
||
successives au lieu de seulement la ligne de la dernière occurence. Ceci
|
||
est utile surtout avec l'option -C, pour voir les différences avec les
|
||
différentes lignes.
|
||
-m, --multiple
|
||
Avec les options -c/-C, n'afficher que les lignes dont le compte est
|
||
supérieur à 1. Avec l'option -a, les groupes contigus sont séparés par
|
||
une ligne '--'
|
||
}}}</pre>
|
||
</div>
|
||
<div title="umirror" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
umirror: faire un miroir d'un site web
|
||
|
||
USAGE
|
||
umirror [options] url [wget_options]
|
||
|
||
OPTIONS
|
||
-l
|
||
Convertir les liens pour consultation locale
|
||
}}}</pre>
|
||
</div>
|
||
<div title="upassword" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
USAGE:
|
||
upassword -p [-f aeskeyfile] [clear [salts...]]
|
||
upassword -p [-f aeskeyfile] -j JKEY codetu [salts...]
|
||
upassword -p -f aeskeyfile -k crypted [salts...]
|
||
upassword -f aeskeyfile -G [password [salt]]
|
||
upassword -f aeskeyfile -s
|
||
upassword -f aeskeyfile -e clear
|
||
upassword -f aeskeyfile -d crypted
|
||
upassword --batch
|
||
|
||
OPTIONS
|
||
-p, --hash-password
|
||
Crypter un mot de passe (option par défaut). Si le mot de passe en clair
|
||
et/ou le salt ne sont pas spécifiés, ils sont choisis au hasard.
|
||
-j, --clear-is-codetu JKEY
|
||
Indiquer que l'argument clear est un numéro d'étudiant, à partir duquel
|
||
il faut générer le mot de passe. Cette option n'est valide qu'avec -p
|
||
-k, --clear-is-crypted
|
||
Indiquer que l'argument clear doit d'abord être décrypté avec la clé AES
|
||
spécifiée avant utilisation. Cette option n'est valide qu'avec -p
|
||
-G, --aes-genkey
|
||
Générer une clé AES pour utilisation avec les options -s, -e, -d
|
||
-s, --aes-showkey
|
||
Afficher encodée en base64 la clé AES contenue dans le fichier spécifié
|
||
-e, --aes-encrypt
|
||
Crypter un mot de passe avec la clé AES spécifiée
|
||
-d, --aes-decrypt
|
||
Décrypter un mot de passe avec la clé AES spécifiée
|
||
-f, --aes-keyfile
|
||
Spécifier le fichier contenant la clé AES. Cette option est obligatoire
|
||
avec les options -G, -s, -e et -d
|
||
--shell
|
||
Afficher les valeurs pour évaluation par le shell
|
||
|
||
MODE BATCH
|
||
Utiliser l'option --batch active le mode batch. Dans ce mode, chaque ligne est
|
||
un ensemble d'arguments, comme si on avait lancé le script à plusieurs reprises.
|
||
L'analyseur est limité: le découpage des arguments est fait sur les espaces.
|
||
Les lignes commençant par # sont ignorées.
|
||
Si une ligne commence par --batch-after, alors cette ligne est affichée après
|
||
chaque résultat. Ceci permet de générer un script qui peut être évalué.
|
||
|
||
Voici un exemple:
|
||
upassword --batch <<EOF
|
||
--batch-after process_password1 args
|
||
--shell
|
||
--shell fixed-password1
|
||
--batch-after process_password2 args
|
||
--shell fixed-password2
|
||
EOF
|
||
Le résultat serait quelque chose comme:
|
||
clear='<random-password>'
|
||
... # toutes les valeurs lm, ntlm, crypt, sha, xsha, ssha, md5, smd5
|
||
process_password1 args
|
||
clear='fixed-password1'
|
||
... # toutes les valeurs lm, ntlm, crypt, sha, xsha, ssha, md5, smd5
|
||
process_password1 args
|
||
clear='fixed-password2'
|
||
... # toutes les valeurs lm, ntlm, crypt, sha, xsha, ssha, md5, smd5
|
||
process_password2 args
|
||
}}}</pre>
|
||
</div>
|
||
<div title="update-nutools" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
update-nutools: mettre à jour nutools
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uprefix" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uprefix: Afficher les préfixes valides pour uinst
|
||
|
||
USAGE
|
||
uprefix -l|--dump|prefix...
|
||
|
||
OPTIONS
|
||
-l
|
||
Afficher la liste des préfixes valides
|
||
--dump
|
||
Afficher la liste des préfixes valides et leurs valeurs
|
||
prefix
|
||
Afficher la valeur du préfixe spécifié
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uproject" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uproject: Outil pour gérer des projets
|
||
|
||
USAGE
|
||
uproject cmd [args]
|
||
|
||
COMMANDS
|
||
getvcs [dir]
|
||
Afficher le type de VCS pour dir.
|
||
getroot [dir]
|
||
Si dir est un répertoire versionné, retourner le répertoire racine du
|
||
projet versionné.
|
||
getrepos [dir]
|
||
Si dir est un répertoire versionné, retourner l'url du repository du
|
||
projet versionné.
|
||
geturl [dir]
|
||
Si dir est un répertoire versionné, retourner son url dans le
|
||
repository.
|
||
fold [dir]
|
||
unfold [dir]
|
||
Utiliser uinc pour défaire (resp. refaire) toutes les inclusions des
|
||
fichiers de dir. Cela nécessite qu'un fichier .udir soit configuré à la
|
||
racine du projet avec uinc=true
|
||
vcs [args]
|
||
Appeler le gestionnaire de gestion approprié avec les arguments donnés.
|
||
add files...
|
||
Ajouter les fichiers files dans le gestionnaire de version.
|
||
remove files...
|
||
Supprimer les fichiers versionnés files.
|
||
copy from to
|
||
Copier le fichier versionné from vers le fichier to.
|
||
move from to
|
||
Renommer le fichier versionné from vers le fichier to.
|
||
mkdir dir
|
||
Créer un nouveau répertoire versionné.
|
||
commit message [files...]
|
||
Enregistrer les modifications (par défaut sur tous les fichiers
|
||
modifiés) avec le commentaire message.
|
||
status
|
||
Afficher l'état des fichiers versionnés et non versionnés.
|
||
update [-x]
|
||
Mettre à jour la copie locale avec la copie sur le serveur.
|
||
-x Ne pas mettre à jour les références externes (si appliquable)
|
||
-n, --no-autoff
|
||
Ne pas faire de fast-forward automatique pour toutes les branches
|
||
traquées. Par défaut, s'il n'y a pas de modifications locales,
|
||
essayer de fast-fowarder toutes les branches locales traquées.
|
||
diff [options]
|
||
Afficher les différences.
|
||
-l Afficher les différences non commitées (par défaut)
|
||
-c Afficher les différences en passe d'être commitées (si appliquable)
|
||
-r REV
|
||
Afficher les différences depuis la révision REV.
|
||
-R Afficher les modifications effectuées depuis la dernière release.
|
||
|
||
clone git@host:path/to/repo [destdir]
|
||
Cloner un dépôt distant. Initialiser git annex si le dépôt contient des
|
||
fichiers annexés. Récupérer aussi ces fichiers avec 'git annex get'
|
||
|
||
crone git@host:path/to/repo [destdir]
|
||
Créer un dépôt distant sur gitolite, puis le cloner
|
||
|
||
develop
|
||
release
|
||
hotfix
|
||
Démarrer le travail sur une branche respectivement de développement, de
|
||
release, ou de correction de bugs. Lancer chaque commande avec --help
|
||
pour les détails. Nécessite git.
|
||
|
||
archive
|
||
Créer une archive du projet courant. Nécessite git.
|
||
|
||
annex [args]
|
||
Lancer git annex avec les arguments spécifiés.
|
||
xadd
|
||
xunlock
|
||
xdrop
|
||
xwhereis
|
||
xwebapp
|
||
Chacune de ces commandes est un raccourci vers la commande
|
||
correspondante de git annex, sans le préfixe 'x'
|
||
xsync
|
||
Sur un dépot où git-annex est activé, lancer 'git annex sync' si on est
|
||
en mode indirect ou 'git annex sync --content' si on est en mode direct.
|
||
Sur un dépôt où git-annex n'est pas activé, faire l'équivalent des
|
||
commandes 'git add -A && git commit && git pull && git push'
|
||
xcopy
|
||
xmove
|
||
xget
|
||
Comme ci-dessus, mais si la commande s'exécute sans erreur, lancer
|
||
aussi 'git annex sync'
|
||
xinitial
|
||
Sur un dépôt fraichement cloné, initialiser le dépôt avec 'annex init'
|
||
s'il contient des fichiers annexés. Récupérer aussi ces fichiers avec
|
||
'annex get'
|
||
xconfig-export [dir]
|
||
Installer des hooks pour qu'un dépôt puisse être utilisé pour servir des
|
||
fichiers, par exemple avec un serveur web. Plus précisément, un hook
|
||
post-receive est créé avec la commande 'git annex merge', et un hook
|
||
post-update est créé avec la commande 'git update-server-info'
|
||
|
||
printml [-t TYPE]
|
||
Afficher le modeline pour un fichier du type spécifié
|
||
addml [-t TYPE] file
|
||
Ajouter un modele pour le fichier spécifié, s'il n'en a pas déjà un.
|
||
Si nécessaire, forcer le type du fichier au lieu de l'autodétecter
|
||
new [options] file [template options]
|
||
Créer un nouveau fichier à partir d'un modèle.
|
||
Avant le nom du fichier, les options suivantes sont valides:
|
||
-t TEMPLATE
|
||
Spécifier le modèle de fichier à utiliser. Par défaut, le modèle
|
||
à utiliser est déduit de l'extension ou du nom du fichier.
|
||
-e Editer le fichier après l'avoir créé.
|
||
Après le nom du fichier, toutes les options sont spécifiques au modèle
|
||
utilisé pour créer le nouveau fichier. Utiliser l'option --help pour
|
||
avoir une description des options disponibles.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uscrontab" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uscrontab: lancer une suite de commande en respectant une planification de type cron
|
||
|
||
USAGE
|
||
uscrontab [options] [/path/to/uscrontab] [var=value...]
|
||
uscrontab -e [/path/to/uscrontab]
|
||
uscrontab -l
|
||
|
||
La première forme du script doit normalement être lancé toutes les minutes par
|
||
une tâche cron. Utiliser l'option --install pour ajouter automatique la ligne
|
||
dans la crontab de l'utilisateur.
|
||
|
||
Avec la première forme du script, le fichier spécifié est traité. Si aucun
|
||
fichier n'est spécifié, fusionner s'il existe le fichier
|
||
/var/local/uscrontab/users/jclain
|
||
avec chacun des fichiers du répertoire
|
||
/var/local/uscrontab/users.d/jclain
|
||
dans un fichier temporaire, puis exécuter le fichier résultat avec le nom
|
||
virtuel
|
||
/var/local/uscrontab/jclain
|
||
note: le nom virtuel est utilisé pour le verrouillage avec --lock
|
||
|
||
A chaque lancement de ce script, le fichier /path/to/uscrontab spécifié est
|
||
examiné pour déterminer quels commandes doivent être exécutées. Ce fichier est
|
||
composé de lignes dans un format particulier, qui sont analysées et traitées
|
||
dans l'ordre.
|
||
|
||
Quelles que soient les lignes qui sont sélectionnées pour l'exécution, elles
|
||
sont garanties de s'exécuter dans l'ordre du fichier, l'une après l'autre.
|
||
|
||
Les définitions var=value mentionnées sur la ligne de commande sont des
|
||
définitions de variables à effectuer avant de lancer les commandes.
|
||
|
||
Les lignes commençant par # sont des commentaires et sont ignorées
|
||
|
||
== Définitions de variables et exécution de commandes ==
|
||
|
||
Les lignes de la forme suivante sont des définitions de variable:
|
||
|
||
[export] var="valeur de la variable"
|
||
|
||
Ces lignes sont des définitions de variable bash qui sont exécutées telles
|
||
quelles. Il n'est donc pas autorisé de mettre des espaces autour de =. Par
|
||
exemple, les lignes suivantes sont des erreurs de syntaxe:
|
||
|
||
var = bad
|
||
var=pas de quotes autour de la valeur
|
||
|
||
alors que celles-ci sont correctes:
|
||
|
||
var=ok
|
||
var="valeur avec des espaces"
|
||
var='on peut utiliser des quotes aussi'
|
||
|
||
Il est possible de manipuler les variables de type PATH avec une syntaxe
|
||
particulière de l'opérateur d'assignation. Les opérateurs += et %= utilisent
|
||
uaddpath(), #= utilise uinspath() et -= utilise udelpath(). Par exemple, les
|
||
lignes suivantes ajoutent respectivement /usr/local/nutools puis enlèvent
|
||
/opt/rogue au PATH:
|
||
|
||
PATH+=/usr/local/nutools
|
||
PATH-=/opt/rogue
|
||
|
||
Bien sûr, il ne faut pas oublier de quoter les espaces:
|
||
|
||
PATH+="/path/to/dir with spaces"
|
||
|
||
La syntaxe ?= permet de définir la valeur d'une variable si elle n'est pas
|
||
déjà définie:
|
||
|
||
var?=default
|
||
|
||
Les lignes de la forme suivante permettent d'exécuter une commande qui est
|
||
exécutée systématiquement et ignore la planification:
|
||
|
||
$one-line-command
|
||
|
||
Une variante permet de spécifier des commandes sur plusieurs lignes.
|
||
ATTENTION! ${ et $} doivent être tous seuls sur la ligne.
|
||
|
||
${
|
||
several
|
||
commands
|
||
...
|
||
$}
|
||
|
||
Ces commandes sont exécutées systématiquement et ignorent la planification.
|
||
On peut s'en servir notamment pour lire un fichier de configuration qui
|
||
définit des variables ou des fonctions:
|
||
|
||
$source path/to/file
|
||
|
||
Le code d'erreur de ces commandes est ignoré, contrairement à ce qui se
|
||
passe pour les commandes qui font l'objet d'une planification.
|
||
|
||
== Planification de commandes ==
|
||
|
||
Les autres lignes doivent être au format d'une ligne de crontab:
|
||
|
||
minutes hours days months dows command-line
|
||
|
||
command-line peut être n'importe quelle ligne de commande bash, pourvu
|
||
qu'elle soit sur une seule ligne.
|
||
|
||
Certaines extensions par rapport à la syntaxe de crontab sont autorisées. Il
|
||
est en particulier possible de spécifier plusieurs planifications pour une
|
||
seule commande. Par exemple, les lignes suivantes permettent d'exécuter
|
||
'command' toutes les heures ET à 1h05:
|
||
|
||
0 * * * *
|
||
5 1 * * * command
|
||
|
||
Il est aussi possible d'utiliser la même planification pour plusieurs
|
||
commandes sans devoir répéter la définition de la planification. Les lignes
|
||
suivantes planifient command1 et command2 toutes les heures:
|
||
|
||
0 * * * * command1
|
||
command2
|
||
|
||
Pour être prise en compte, la ligne command2 doit commencer par au moins un
|
||
espace ou une tabulation. Pour la lisibilité, la syntaxe suivante est
|
||
supportée aussi:
|
||
|
||
0 * * * *
|
||
command1
|
||
command2
|
||
|
||
Les deux formats peuvent être utilisés ensemble. Par exemple les lignes
|
||
suivantes exécutent command1 et command2 toutes les heures ET à 1h05:
|
||
|
||
0 * * * *
|
||
5 1 * * * command1
|
||
command2
|
||
|
||
Par défaut, le script s'arrête à la première commande planifiée qui retourne
|
||
avec un code d'erreur. Il est possible d'ignorer le code d'erreur d'une
|
||
commande avec nostop, e.g:
|
||
|
||
0 * * * * nostop command
|
||
|
||
Cf aussi l'option --continuous pour modifier le comportement par défaut
|
||
|
||
== Fonctions disponibles ==
|
||
|
||
La fonction check_pidfile() est disponible, et permet de vérifier qu'une
|
||
opération n'est pas déjà en cours. Si cette fonction est utilisée, il ne
|
||
faut pas modifier la valeur de -k. Par exemple:
|
||
|
||
0 1 * * *
|
||
check_pidfile /path/to/pid [args]
|
||
long-running-script
|
||
|
||
check_pidfile() doit être utilisée toute seule sur la ligne et s'utilise
|
||
avec les argument suivants:
|
||
|
||
check_pidfile PIDFILE [DESC] [BARRIER]
|
||
|
||
- PIDFILE est le fichier de PID qui est vérifié
|
||
- DESC est la description du traitement qui est effectué. La valeur par
|
||
défaut est "Une synchronisation". Si le fichier de PID est présent, le
|
||
message suivant est affiché:
|
||
DESC est en cours.
|
||
Si vous pensez que c'est une erreur, veuillez vérifier le process de pid PID
|
||
puis supprimez le cas échéant le fichier PIDFILE
|
||
- BARRIER est un fichier qui est créé avec le contenu 'PID' s'il n'existe
|
||
pas encore, et si la vérification du fichier de PID est faite avec succès.
|
||
La présence de ce fichier peut-être vérifiée par un processus externe pour
|
||
empêcher par exemple de mettre à jour les scripts pendant qu'il sont en
|
||
train de tourner.
|
||
Son contenu peut être examiné pour connaître le PID du processus qui l'a
|
||
créé initialement. Le fichier est automatiquement supprimé à la fin de ce
|
||
script.
|
||
Attention: ce fichier n'est pas un verrou, il peut être supprimé à tout
|
||
moment. Notamment, si deux scripts sont configurés pour créer le même
|
||
fichier barrière, le premier script supprimera le fichier barrière avant
|
||
la fin de l'exécution du second script.
|
||
|
||
La fonction remove_pidfile() permet de supprimer un fichier de pid pour
|
||
spécifier qu'une opération est terminée. Considérons l'exemple suivant:
|
||
|
||
0 1 * * *
|
||
check_pidfile /path/to/pid
|
||
script1
|
||
script2
|
||
remove_pidfile /path/to/pid
|
||
script3
|
||
|
||
Dans cet exemple, il ne faut pas qu'une autre occurence de script1 tourne
|
||
pendant que script2 tourne. Par contre, plusieurs occurences de script3
|
||
peuvent tourner en parallèle.
|
||
|
||
La fonction elogto() permet de spécifier un fichier vers lequel toutes les
|
||
sorties sont redirigées.
|
||
|
||
OPTIONS
|
||
-A, --install
|
||
Installer une planification toutes les minutes du script dans la crontab
|
||
de l'utilisateur. Si l'argument /path/to/uscrontab n'est pas spécifié,
|
||
c'est une planification générique qui exécute les fichiers par défaut
|
||
qui est installée.
|
||
-R, --uninstall
|
||
Désinstaller la planification toutes les minutes du script de la crontab
|
||
de l'utilisateur. Si l'argument /path/to/uscrontab est spécifié, cette
|
||
instance est désinstallée. Sinon, ne désinstaller que la planification
|
||
générique.
|
||
-d, --disable-only
|
||
Avec l'option -R, désactiver la planification au lieu de la supprimer.
|
||
-e, --edit
|
||
Lancer un editeur pour modifier l'uscrontab spécifiée. Si aucun fichier
|
||
n'est spécifié, éditer /var/local/uscrontab/users/jclain
|
||
-a, --add
|
||
Installer un script uscrontab dans le répertoire approprié. L'argument
|
||
doit être de la forme [name:]/path/to/uscrontab
|
||
Si name n'est pas spécifié, le nom de base du fichier spécifié est
|
||
utilisé. Si name est vide ou vaut $USER (soit jclain en l'occurence),
|
||
copier le fichier spécifié vers le chemin /var/local/uscrontab/users/jclain
|
||
Sinon, copier le fichier spécifié vers /var/local/uscrontab/users.d/jclain/name
|
||
-r, --remove
|
||
Supprimer le script uscrontab spécifié. L'argument doit être le nom du
|
||
script à supprimer. Si l'argument n'est pas spécifié ou vaut $USER
|
||
(soit jclain en l'occurence), supprimer le fichier /var/local/uscrontab/users/jclain
|
||
s'il existe
|
||
-l, --list
|
||
Si l'argument /path/to/crontab est spécifié, afficher le contenu de ce
|
||
fichier. Sinon, lister les contenus des fichiers crontab qui sont
|
||
exécutés avec la planification actuelle. Si une planification générique
|
||
est installée, ou si aucune planification n'est en cours, afficher le
|
||
contenu du fichier
|
||
/var/local/uscrontab/users/jclain
|
||
et chacun des fichiers du répertoire
|
||
/var/local/uscrontab/users.d/jclain
|
||
-n, --fake
|
||
Afficher au lieu de les exécuter les commandes qui doivent être lancées
|
||
-P, --pause-for NBMINS
|
||
Désactiver les planifications pendant NBMINS minutes. Utiliser -1 pour
|
||
désactiver les planifications sans limite de durée. Pendant la période
|
||
de pause, toutes les invocations de uscrontab n'ont aucun effet, sauf si
|
||
on utilise l'option --force
|
||
-Y, --unpause
|
||
Réactiver les planifications après une mise en pause
|
||
-p, --pause
|
||
Désactiver les planifications pendant 1 journée. Equivalent à -P 1440
|
||
-f, --force
|
||
Forcer l'exécution de la planification, même si elle a été mise en pause
|
||
avec l'option --pause
|
||
|
||
OPTIONS AVANCEES
|
||
--lock LOCKFILE
|
||
Inscrire dans le fichier spécifié des informations permettant d'éviter
|
||
les invocations simultanées de ce script. Si selon ce fichier, le script
|
||
tourne depuis plus de 8 heures, un message d'erreur
|
||
est consigné et un message d'avertissement est affiché au plus une fois.
|
||
Utiliser --lock '' pour désactiver cette fonctionnalité
|
||
Par défaut, si ce script est lancé en root, le fichier utilisé pour le
|
||
verrouillage est de la forme /var/run/uscrontab/abspath/to/crontab
|
||
Si le script est lancé avec un compte utilisateur, aucun verrouillage
|
||
n'est effectué.
|
||
--lockdelay LOCKDELAY[=8]
|
||
Changer le nombre d'heures pendant lesquelles on autorise le script a
|
||
verrouiller l'exécution avant d'afficher un avertissement.
|
||
-c, --continuous
|
||
Par défaut, ce script s'arrête à la première commande planifiée qui
|
||
retourne avec un code d'erreur. Notez que les codes d'erreur des
|
||
commandes sans planification sont toujours ignorés. Avec cette option,
|
||
ce script ne s'arrête jamais, bien qu'il retourne toujours un code
|
||
d'erreur si une erreur s'est produite. Il est possible d'ignorer le
|
||
code d'erreur pour une commande en particulier avec le préfixe nostop
|
||
-k, --stopec EXITCODE[=101]
|
||
Spécifier un code d'erreur spécial qui arrête ce script sans erreur, ou
|
||
'' pour désactiver cette fonctionnalité. Ceci permet en début de script
|
||
de faire des tests par exemple sur l'environnement avant de lancer les
|
||
scripts planifiés. Si l'environnement ne convient pas, il suffit au
|
||
script de contrôle de retourner le code d'erreur spécifique pour arrêter
|
||
le traitement.
|
||
--show-ctnow
|
||
Afficher l'heure de référence au format crontab 'min hou day mon dow'
|
||
Cette valeur peut être utilisée avec l'option --force-ctnow dans des
|
||
tests pour reproduire une condition spécifique.
|
||
--force-ctnow 'min hou day mon dow'
|
||
Pour le développement ou des tests, forcer la valeur de l'heure de
|
||
référence. Il faut respecter le format, sinon les résultats ne sont pas
|
||
garantis. Le mieux est de reprendre le résultat de l'option --show-ctnow
|
||
en le modifiant un peu si nécessaire.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="ussh" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
ussh: se connecter par ssh à un ou plusieurs hôtes
|
||
|
||
USAGE
|
||
ussh [options] hosts
|
||
ussh [options] @hostsfile
|
||
ussh -r hosts
|
||
ussh --parse hosts
|
||
|
||
OPTIONS
|
||
hosts
|
||
@hostsfile
|
||
Spécifier un ou plusieurs hôtes distants sur lequels faire la connexion.
|
||
Pour spécifier plusieurs hôtes, il faut les séparer par un espace ou le
|
||
caractère ':', e.g. 'host1 host2' ou 'host1:host2'. Si la spécification
|
||
contient les caractères { et }, l'expansion est effectuée, e.g
|
||
'root@{host1,host2}.univ.run'
|
||
La forme @hostsfile permet de lire la liste des hôtes depuis le fichier
|
||
hostsfile, à raison d'un hôte par ligne.
|
||
|
||
Toutes les options de ssh sont reconnues. Les options longues suivantes sont
|
||
reconnues comme alias de certaines options courtes de ssh:
|
||
--quiet
|
||
alias de -q, activer le mode non verbeux
|
||
--tty
|
||
alias de -t, forcer l'allocation d'un TTY
|
||
--login USER
|
||
alias de -l, spécifier le user avec lequel se connecter
|
||
--port PORT
|
||
alias de -p, spécifier le port sur lequel se connecter
|
||
|
||
Les options suivantes sont exclusives à ce script:
|
||
-d, --domain DOMAIN
|
||
Spécifier un domaine par défaut pour les hôtes qui sont spécifiés sans
|
||
domaine.
|
||
-z, --ssh SSH
|
||
Spécifier l'exécutable à utiliser pour lancer ssh.
|
||
-r, --remove
|
||
Lancer 'ssh-keygen -R' pour chacun des hôtes spécifiés avant de s'y
|
||
connecter. Par exemple:
|
||
ussh -r host.tld
|
||
est équivalent à:
|
||
ssh-keygen -R host.tld
|
||
ssh-keygen -R host
|
||
ssh-keygen -R 10.10.1.5
|
||
ssh host.tld
|
||
si l'adresse ip de host.tld est 10.10.1.5
|
||
Quand cette option est spécifié, l'option -j est reconnue et permet de
|
||
NE PAS se reconnecter à l'hôte juste après avoir nettoyé les clés. Avec
|
||
l'option -j, TOUS les arguments sont des noms d'hôte puisqu'aucune
|
||
connexion n'est effectuée.
|
||
--exec
|
||
--no-exec
|
||
Avec --exec, si un seul hôte est spécifié, lancer le processus ssh avec
|
||
exec, pour éviter d'encombrer la mémoire. C'est l'option par défaut.
|
||
Avec --no-exec, ne jamais utiliser exec pour lancer ssh.
|
||
--parse
|
||
Afficher la définition des variables ssh, options, hosts et args qui
|
||
permettent d'effectuer la connexion à partir d'un autre script. Exemple:
|
||
eval "$(ussh --parse args...)"
|
||
for host in "${hosts[@]}"; do
|
||
${exec:+exec} "$ssh" "${options[@]}" "$host" "${args[@]}"
|
||
done
|
||
--cc
|
||
Assumer que nutools est installé sur l'hôte distant, et y lancer uwatch
|
||
avec l'option --cc, pour permettre de garder la connexion active dans le
|
||
cadre d'une redirection de port.
|
||
|
||
Si la variable UTOOLS_USSH_RSYNC_SUPPORT contient une valeur non vide, l'analyse
|
||
des arguments s'arrête à la première valeur qui n'est pas une option, afin de
|
||
permettre l'utilisation de ce script avec l'option -e de rsync.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="usysinfos" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
usysinfos: Afficher les informations sur le système
|
||
|
||
USAGE
|
||
usysinfos [query]
|
||
|
||
Si la requête est spécifiée, tester si le système courant correspond à la
|
||
requête. Voir la doc de check_sysinfos() pour le format de la requête.
|
||
|
||
Sinon, afficher les informations sur le système courant.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="utempl" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
utempl: Créer un nouveau fichier à partir d'un modèle
|
||
|
||
USAGE
|
||
utempl [options] file [template options]
|
||
|
||
OPTIONS
|
||
Avant le nom du nouveau fichier, les options suivantes peuvent être utilisées:
|
||
-t TEMPLATE
|
||
Spécifier le modèle de fichier à utiliser. Par défaut, le modèle
|
||
à utiliser est déduit de l'extension ou du nom du fichier.
|
||
-e, --edit
|
||
Editer le fichier après l'avoir créé
|
||
-g, --no-edit
|
||
Ne pas éditer le fichier après l'avoir créé
|
||
|
||
Après le nom du fichier, toutes les options sont spécifiques au modèle
|
||
utilisé pour créer le nouveau fichier. Utiliser l'option --help pour
|
||
avoir une description des options disponibles.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="utrigger" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
utrigger: lancer une commande en différé
|
||
|
||
USAGE
|
||
utrigger [options] -- command [args]
|
||
|
||
La commande est lancée après un certain temps, sauf si ce script est rappelé
|
||
(auquel cas le compte est réinitialisé), ou si l'opération est annulée.
|
||
Attention! La commande est lancée en tâche de fond, et son entrée standard est
|
||
connectée à un fichier qui peut être provisionné avec l'option -a
|
||
|
||
note: ce script ne fonctionne que sous Linux puisqu'il utilise la commande flock
|
||
|
||
OPTIONS
|
||
-n, --name NAME
|
||
Spécifier un nom identifiant la tâche. Par défaut, le nom est généré à
|
||
partir des détails de la tâche à lancer. Ce nom est utilisé pour
|
||
identifier les invocations successives.
|
||
-f, --cmdfile CMDFILE
|
||
Spécifier un fichier contenant les commandes à lancer. Le fichier est
|
||
sourcé dans un sous-shell. Utiliser - pour lire les commandes depuis
|
||
l'entrée standard.
|
||
--rundelay RUNDELAY[=5]
|
||
Nombre de secondes au bout desquelles la commande est lancée. Si ce
|
||
script est relancé avant la fin de ce décompte, le compte est remis à
|
||
zéro.
|
||
Utiliser --rundelay '' pour désactiver cette fonctionnalité, auquel cas
|
||
la commande est lancée immédiatement.
|
||
-s, --sudo
|
||
Forcer l'exécution de la commande avec l'utilisateur root si ce n'est
|
||
pas déjà le cas
|
||
-a, --datafile DATAFILE
|
||
Accumuler des données à fournir à la commande. Les informations du
|
||
fichier DATAFILE (utiliser - pour l'entrée standard) sont ajoutées à un
|
||
fichier temporaires, et sont fournies en une seule fois à la commande
|
||
sur son entrée standard.
|
||
-A, --data DATA
|
||
Variante de --datafile où les données sont fournies sur la ligne de
|
||
commande au lieu d'un fichier externe. Si les deux options -a et -A sont
|
||
spécifiées, les données sont accumulées dans l'ordre --datafile puis
|
||
--data
|
||
-k, --cancel
|
||
Annuler le lancement planifié d'une commande. Si la commande est déjà en
|
||
train de tourner, cette option n'a aucun effet.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="uwatch" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
uwatch: afficher l'heure
|
||
|
||
USAGE
|
||
uwatch [options]
|
||
|
||
OPTIONS
|
||
-t, --time
|
||
Afficher l'heure (par défaut)
|
||
-c, --count
|
||
Afficher le temps écoulé depuis le lancement de ce script
|
||
-u, --units
|
||
Avec l'option --count, afficher l'unité: sec., min. ou heures
|
||
-o, --offset NBSEC
|
||
Avec l'option --count, spécifier un nombre de secondes à partir duquel
|
||
compter
|
||
-s, --step NBSECS[=1]
|
||
Spécifier la période de rafraichissement de l'affichage
|
||
-a, --prefix PREFIX
|
||
Spécifier une chaine à afficher avant l'heure
|
||
-z, --suffix SUFFIX
|
||
Spécifier une chaine à afficher après l'heure
|
||
--cc
|
||
Equivalent à -c -s 5 -a 'Connecté sur $MYHOST depuis ' -z '...'
|
||
Permet de garantir une activité sur une connexion SSH utilisée
|
||
uniquement pour faire une redirection de port
|
||
}}}</pre>
|
||
</div>
|
||
<div title="vzusage" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
vzusage: afficher des informations sur une machine virtuelle OpenVZ
|
||
|
||
USAGE
|
||
vzusage [options] [params...]d
|
||
|
||
OPTIONS
|
||
-b Afficher les informations de /proc/user_beancounters
|
||
-f N'afficher que les valeurs pour lesquelles failcnt > 0.
|
||
Implique -b
|
||
-z coef
|
||
Afficher les instructions à utiliser pour augmenter de coef% les
|
||
valeurs pour lesquelles failcnt > 0. Implique -f
|
||
-c config|veid
|
||
Afficher les informations du fichier de configuration plutôt que les
|
||
beancounters
|
||
}}}</pre>
|
||
</div>
|
||
<div title="woArchive" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
woArchive: créer une archive de la distribution WebObjects en cours
|
||
USAGE
|
||
woArchive [-n name] [-f files]
|
||
|
||
OPTIONS
|
||
-n NAME
|
||
Nom de base de l'archive. Par défaut il s'agit de WebObjects-<version>
|
||
|
||
-f FILES
|
||
Nom de la liste des fichiers de l'archives. Par défaut il s'agit de
|
||
$NAME.files
|
||
}}}</pre>
|
||
</div>
|
||
<div title="woSwitch" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
woSwitch: Changer la version de WebObjects pour le système en cours
|
||
USAGE
|
||
woSwitch [-f from.files] to-archive.tar.gz
|
||
|
||
OPTIONS
|
||
-f from.files
|
||
Spécifier la liste des fichiers pour la version de WebObjects
|
||
installée. Par défaut, il s'agit de WebObjects-<version>.files
|
||
La liste doit correspondre à la version en cours.
|
||
|
||
-F Forcer l'installation, même si la version en cours ne correspond pas à ce
|
||
qui est inscrit dans from.files
|
||
|
||
to-archive.tar.gz
|
||
Nom de l'archive qui contient la version à installer.
|
||
|
||
Ce script ne fonctionne que sur MacOS X
|
||
Le contenu des répertoires suivants est sauvegardé avant le changement:
|
||
/Library/WebObject/Applications
|
||
/Library/WebObject/Configuration
|
||
/Library/WebObject/Extensions
|
||
Ensuite, les répertoires Applications et Configuration sont restaurés. Il faudra
|
||
restaurer Extensions manuellement.
|
||
}}}</pre>
|
||
</div>
|
||
<div title="woctl" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
woctl: Contrôler des applications WebObjects
|
||
|
||
USAGE
|
||
woctl [options] action args
|
||
wostart args...
|
||
wostop args...
|
||
wobounce args...
|
||
worestart args...
|
||
|
||
OPTIONS
|
||
-h HOST
|
||
Spécifier l'hôte qui fait tourner le moniteur sous la forme host[:port]
|
||
-p PASSWORD
|
||
Spécifier le mot de passe pour le moniteur
|
||
|
||
ACTIONS
|
||
Dans les arguments des actions ci-dessous, une application peut être
|
||
spécifiée sous la forme App ou App.woa. Spécifier une application revient à
|
||
spécifier toutes les instances configurées pour cette application.
|
||
Si on spécifie un framework sous la forme Fwk.framework, cela revient à
|
||
spécifier toutes les applications qui dépendent de ce framework.
|
||
Sinon, une instance individuelle est de la forme App-N, où N est un entier
|
||
positif.
|
||
|
||
status
|
||
afficher l'état des instances qui tournent actuellement
|
||
version
|
||
afficher la version de WebObjects installée
|
||
wotaskd
|
||
javamonitor
|
||
woservices
|
||
piloter wotaskd/javamonitor
|
||
_create
|
||
créer une instance par défaut dans javamonitor
|
||
configure
|
||
configurer un bundle
|
||
tag
|
||
ajouter une information de version à un bundle
|
||
run
|
||
lancer une application localement en mode debug
|
||
download
|
||
télécharger une application ou un framework
|
||
start apps...
|
||
démarrer une ou plusieurs applications
|
||
stop apps...
|
||
arrêter une ou plusieurs applications
|
||
restart apps...
|
||
relancer une ou plusieurs applications
|
||
bounce apps...
|
||
relancer une ou plusieurs applications en mode bounce
|
||
}}}</pre>
|
||
</div>
|
||
<div title="woinst" creator="jclain" modifier="jclain" created="201203151820" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
woinst: Déployer un bundle (application ou framework) de WebObjects
|
||
|
||
USAGE
|
||
woinst [options] <file|archive|dir>...
|
||
|
||
OPTIONS
|
||
PREFIX=value
|
||
Spécifier une valeur pour un préfixe, plutôt que de laisser uprefix
|
||
l'autodétecter. Utiliser uprefix -l pour une liste de préfixes valides.
|
||
-b Redémarrer les instances en mode bounce.
|
||
Par défaut, les instances sont arrêtées avant le déploiement, et
|
||
redémarrées après
|
||
-W Ne déployer que les resources web. Implique -n
|
||
-n Ne pas tagger les bundles déployés avec un numéro de version. Par
|
||
défaut, l'utilisateur est invité à compléter des informations telles
|
||
que n° de version et date de release si ces informations ne sont pas
|
||
disponible.
|
||
-x CMD
|
||
Exécuter la commande CMD après avoir effectué le déploiement
|
||
}}}</pre>
|
||
</div>
|
||
<div title="wosign" creator="jclain" modifier="jclain" created="201604262319" modified="201605130537" tags="" changecount="1">
|
||
<pre>{{{
|
||
wosign: signer les jars d'un bundle
|
||
|
||
USAGE
|
||
wosign <app.woa|fwk.framework|file.jar>
|
||
|
||
OPTIONS
|
||
-f Forcer la (re)signature des jars
|
||
-d Enlever la signature des jars originaux
|
||
-s Signer les jar du bundle [PAR DEFAUT]
|
||
--init
|
||
Initialiser les fichiers de configuration pour la signature des bundles.
|
||
--sudo
|
||
Si le répertoire de destination des fichiers de configuration n'est
|
||
accessible en écriture, relancer le script en root.
|
||
}}}</pre>
|
||
</div>
|
||
</div>
|
||
<!--POST-STOREAREA-->
|
||
<!--POST-BODY-START-->
|
||
<!--POST-BODY-END-->
|
||
<script id="jsArea" type="text/javascript">
|
||
//<![CDATA[
|
||
//
|
||
// Please note:
|
||
//
|
||
// * This code is designed to be readable but for compactness it only includes brief comments. You can see fuller comments
|
||
// in the project repository at https://github.com/TiddlyWiki/tiddlywiki
|
||
//
|
||
// * You should never need to modify this source code directly. TiddlyWiki is carefully designed to allow deep customisation
|
||
// without changing the core code. Please consult the development group at http://groups.google.com/group/TiddlyWikiDev
|
||
//
|
||
// JSLint directives
|
||
/*global jQuery:false, version:false */
|
||
/*jslint bitwise:true, browser:true, confusion:true, eqeq:true, evil:true, forin:true, maxerr:100, plusplus:true, regexp:true, sloppy:true, sub:true, undef:true, unparam:true, vars:true, white:true */
|
||
//--
|
||
//-- Configuration repository
|
||
//--
|
||
|
||
// Miscellaneous options
|
||
var config = {
|
||
numRssItems: 20, // Number of items in the RSS feed
|
||
animDuration: 400, // Duration of UI animations in milliseconds
|
||
cascadeFast: 20, // Speed for cascade animations (higher == slower)
|
||
cascadeSlow: 60, // Speed for EasterEgg cascade animations
|
||
cascadeDepth: 5, // Depth of cascade animation
|
||
locale: "en" // W3C language tag
|
||
};
|
||
|
||
// Hashmap of alternative parsers for the wikifier
|
||
config.parsers = {};
|
||
|
||
// Adaptors
|
||
config.adaptors = {};
|
||
config.defaultAdaptor = null;
|
||
|
||
// Backstage tasks
|
||
config.tasks = {};
|
||
|
||
// Annotations
|
||
config.annotations = {};
|
||
|
||
// Custom fields to be automatically added to new tiddlers
|
||
config.defaultCustomFields = {};
|
||
|
||
// Messages
|
||
config.messages = {
|
||
messageClose: {},
|
||
dates: {},
|
||
tiddlerPopup: {}
|
||
};
|
||
|
||
// Options that can be set in the options panel and/or cookies
|
||
config.options = {
|
||
chkRegExpSearch: false,
|
||
chkCaseSensitiveSearch: false,
|
||
chkIncrementalSearch: true,
|
||
chkAnimate: true,
|
||
chkSaveBackups: true,
|
||
chkAutoSave: false,
|
||
chkGenerateAnRssFeed: false,
|
||
chkSaveEmptyTemplate: false,
|
||
chkOpenInNewWindow: true,
|
||
chkToggleLinks: false,
|
||
chkHttpReadOnly: true,
|
||
chkForceMinorUpdate: false,
|
||
chkConfirmDelete: true,
|
||
chkInsertTabs: false,
|
||
chkUsePreForStorage: true, // Whether to use <pre> format for storage
|
||
chkDisplayInstrumentation: false,
|
||
txtBackupFolder: "",
|
||
txtEditorFocus: "text",
|
||
txtMainTab: "tabTimeline",
|
||
txtMoreTab: "moreTabAll",
|
||
txtMaxEditRows: "30",
|
||
txtFileSystemCharSet: "UTF-8",
|
||
txtTheme: ""
|
||
};
|
||
config.optionsDesc = {};
|
||
|
||
config.optionsSource = {};
|
||
|
||
// Default tiddler templates
|
||
var DEFAULT_VIEW_TEMPLATE = 1;
|
||
var DEFAULT_EDIT_TEMPLATE = 2;
|
||
config.tiddlerTemplates = {
|
||
1: "ViewTemplate",
|
||
2: "EditTemplate"
|
||
};
|
||
|
||
// More messages (rather a legacy layout that should not really be like this)
|
||
config.views = {
|
||
wikified: {
|
||
tag: {}
|
||
},
|
||
editor: {
|
||
tagChooser: {}
|
||
}
|
||
};
|
||
|
||
// Backstage tasks
|
||
config.backstageTasks = ["save","sync","importTask","tweak","upgrade","plugins"];
|
||
|
||
// Extensions
|
||
config.extensions = {};
|
||
|
||
// Macros; each has a 'handler' member that is inserted later
|
||
config.macros = {
|
||
today: {},
|
||
version: {},
|
||
search: {sizeTextbox: 15},
|
||
tiddler: {},
|
||
tag: {},
|
||
tags: {},
|
||
tagging: {},
|
||
timeline: {},
|
||
allTags: {},
|
||
list: {
|
||
all: {},
|
||
missing: {},
|
||
orphans: {},
|
||
shadowed: {},
|
||
touched: {},
|
||
filter: {}
|
||
},
|
||
closeAll: {},
|
||
permaview: {},
|
||
saveChanges: {},
|
||
slider: {},
|
||
option: {},
|
||
options: {},
|
||
newTiddler: {},
|
||
newJournal: {},
|
||
tabs: {},
|
||
gradient: {},
|
||
message: {},
|
||
view: {defaultView: "text"},
|
||
edit: {},
|
||
tagChooser: {},
|
||
toolbar: {},
|
||
plugins: {},
|
||
refreshDisplay: {},
|
||
importTiddlers: {},
|
||
upgrade: {
|
||
source: "http://tiddlywiki-releases.tiddlyspace.com/upgrade",
|
||
backupExtension: "pre.core.upgrade"
|
||
},
|
||
sync: {},
|
||
annotations: {}
|
||
};
|
||
|
||
// Commands supported by the toolbar macro
|
||
config.commands = {
|
||
closeTiddler: {},
|
||
closeOthers: {},
|
||
editTiddler: {},
|
||
saveTiddler: {hideReadOnly: true},
|
||
cancelTiddler: {},
|
||
deleteTiddler: {hideReadOnly: true},
|
||
permalink: {},
|
||
references: {type: "popup"},
|
||
jump: {type: "popup"},
|
||
syncing: {type: "popup"},
|
||
fields: {type: "popup"}
|
||
};
|
||
|
||
// Control of macro parameter evaluation
|
||
config.evaluateMacroParameters = "all";
|
||
|
||
// Basic regular expressions
|
||
config.textPrimitives = {
|
||
upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
|
||
lowerLetter: "[a-z0-9_\\-\u00df-\u00ff\u0151\u0171]",
|
||
anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]",
|
||
anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]"
|
||
};
|
||
if(!((new RegExp("[\u0150\u0170]","g")).test("\u0150"))) {
|
||
config.textPrimitives = {
|
||
upperLetter: "[A-Z\u00c0-\u00de]",
|
||
lowerLetter: "[a-z0-9_\\-\u00df-\u00ff]",
|
||
anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff]",
|
||
anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff]"
|
||
};
|
||
}
|
||
config.textPrimitives.sliceSeparator = "::";
|
||
config.textPrimitives.sectionSeparator = "##";
|
||
config.textPrimitives.urlPattern = "(?:file|http|https|mailto|ftp|irc|news|data):[^\\s'\"]+(?:/|\\b)";
|
||
config.textPrimitives.unWikiLink = "~";
|
||
config.textPrimitives.wikiLink = "(?:(?:" + config.textPrimitives.upperLetter + "+" +
|
||
config.textPrimitives.lowerLetter + "+" +
|
||
config.textPrimitives.upperLetter +
|
||
config.textPrimitives.anyLetter + "*)|(?:" +
|
||
config.textPrimitives.upperLetter + "{2,}" +
|
||
config.textPrimitives.lowerLetter + "+))";
|
||
|
||
config.textPrimitives.cssLookahead = "(?:(" + config.textPrimitives.anyLetter + "+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:(" + config.textPrimitives.anyLetter + "+):([^;\\|\\n]+);)";
|
||
config.textPrimitives.cssLookaheadRegExp = new RegExp(config.textPrimitives.cssLookahead,"mg");
|
||
|
||
config.textPrimitives.brackettedLink = "\\[\\[([^\\]]+)\\]\\]";
|
||
config.textPrimitives.titledBrackettedLink = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
|
||
config.textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" + config.textPrimitives.titledBrackettedLink + ")|(?:" +
|
||
config.textPrimitives.brackettedLink + ")|(?:" +
|
||
config.textPrimitives.urlPattern + ")","mg");
|
||
config.textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+ config.textPrimitives.wikiLink + ")|(?:" +
|
||
config.textPrimitives.titledBrackettedLink + ")|(?:" +
|
||
config.textPrimitives.brackettedLink + ")|(?:" +
|
||
config.textPrimitives.urlPattern + ")","mg");
|
||
|
||
config.glyphs = {
|
||
currBrowser: null,
|
||
browsers: [],
|
||
codes: {}
|
||
};
|
||
|
||
//--
|
||
//-- Shadow tiddlers
|
||
//--
|
||
|
||
config.shadowTiddlers = {
|
||
StyleSheet: "",
|
||
MarkupPreHead: "",
|
||
MarkupPostHead: "",
|
||
MarkupPreBody: "",
|
||
MarkupPostBody: "",
|
||
TabTimeline: '<<timeline>>',
|
||
TabAll: '<<list all>>',
|
||
TabTags: '<<allTags excludeLists>>',
|
||
TabMoreMissing: '<<list missing>>',
|
||
TabMoreOrphans: '<<list orphans>>',
|
||
TabMoreShadowed: '<<list shadowed>>',
|
||
AdvancedOptions: '<<options>>',
|
||
PluginManager: '<<plugins>>',
|
||
SystemSettings: '',
|
||
ToolbarCommands: '|~ViewToolbar|closeTiddler closeOthers +editTiddler > fields syncing permalink references jump|\n|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|',
|
||
WindowTitle: '<<tiddler SiteTitle>> - <<tiddler SiteSubtitle>>'
|
||
};
|
||
|
||
// Browser detection... In a very few places, there's nothing else for it but to know what browser we're using.
|
||
config.userAgent = navigator.userAgent.toLowerCase();
|
||
config.browser = {
|
||
isIE: config.userAgent.indexOf("msie") != -1 && config.userAgent.indexOf("opera") == -1,
|
||
isGecko: navigator.product == "Gecko" && config.userAgent.indexOf("WebKit") == -1,
|
||
ieVersion: /MSIE (\d.\d)/i.exec(config.userAgent), // config.browser.ieVersion[1], if it exists, will be the IE version string, eg "6.0"
|
||
isSafari: config.userAgent.indexOf("applewebkit") != -1,
|
||
isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
|
||
firefoxDate: /gecko\/(\d{8})/i.exec(config.userAgent), // config.browser.firefoxDate[1], if it exists, will be Firefox release date as "YYYYMMDD"
|
||
isOpera: config.userAgent.indexOf("opera") != -1,
|
||
isChrome: config.userAgent.indexOf('chrome') > -1,
|
||
isLinux: config.userAgent.indexOf("linux") != -1,
|
||
isUnix: config.userAgent.indexOf("x11") != -1,
|
||
isMac: config.userAgent.indexOf("mac") != -1,
|
||
isWindows: config.userAgent.indexOf("win") != -1
|
||
};
|
||
|
||
merge(config.glyphs,{
|
||
browsers: [
|
||
function() {return config.browser.isIE;},
|
||
function() {return true;}
|
||
],
|
||
codes: {
|
||
downTriangle: ["\u25BC","\u25BE"],
|
||
downArrow: ["\u2193","\u2193"],
|
||
bentArrowLeft: ["\u2190","\u21A9"],
|
||
bentArrowRight: ["\u2192","\u21AA"]
|
||
}
|
||
});
|
||
|
||
//--
|
||
//-- Translateable strings
|
||
//--
|
||
|
||
// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone
|
||
|
||
merge(config.options,{
|
||
txtUserName: "YourName"});
|
||
|
||
merge(config.tasks,{
|
||
save: {text: "save", tooltip: "Save your changes to this TiddlyWiki"},
|
||
sync: {text: "sync", tooltip: "Synchronise changes with other TiddlyWiki files and servers", content: '<<sync>>'},
|
||
importTask: {text: "import", tooltip: "Import tiddlers and plugins from other TiddlyWiki files and servers", content: '<<importTiddlers>>'},
|
||
tweak: {text: "tweak", tooltip: "Tweak the appearance and behaviour of TiddlyWiki", content: '<<options>>'},
|
||
upgrade: {text: "upgrade", tooltip: "Upgrade TiddlyWiki core code", content: '<<upgrade>>'},
|
||
plugins: {text: "plugins", tooltip: "Manage installed plugins", content: '<<plugins>>'}
|
||
});
|
||
|
||
// Options that can be set in the options panel and/or cookies
|
||
merge(config.optionsDesc,{
|
||
txtUserName: "Username for signing your edits",
|
||
chkRegExpSearch: "Enable regular expressions for searches",
|
||
chkCaseSensitiveSearch: "Case-sensitive searching",
|
||
chkIncrementalSearch: "Incremental key-by-key searching",
|
||
chkAnimate: "Enable animations",
|
||
chkSaveBackups: "Keep backup file when saving changes",
|
||
chkAutoSave: "Automatically save changes",
|
||
chkGenerateAnRssFeed: "Generate an RSS feed when saving changes",
|
||
chkSaveEmptyTemplate: "Generate an empty template when saving changes",
|
||
chkOpenInNewWindow: "Open external links in a new window",
|
||
chkToggleLinks: "Clicking on links to open tiddlers causes them to close",
|
||
chkHttpReadOnly: "Hide editing features when viewed over HTTP",
|
||
chkForceMinorUpdate: "Don't update modifier username and date when editing tiddlers",
|
||
chkConfirmDelete: "Require confirmation before deleting tiddlers",
|
||
chkInsertTabs: "Use the tab key to insert tab characters instead of moving between fields",
|
||
txtBackupFolder: "Name of folder to use for backups",
|
||
txtMaxEditRows: "Maximum number of rows in edit boxes",
|
||
txtTheme: "Name of the theme to use",
|
||
txtFileSystemCharSet: "Default character set for saving changes (Firefox/Mozilla only)"});
|
||
|
||
merge(config.messages,{
|
||
customConfigError: "Problems were encountered loading plugins. See PluginManager for details",
|
||
pluginError: "Error: %0",
|
||
pluginDisabled: "Not executed because disabled via 'systemConfigDisable' tag",
|
||
pluginForced: "Executed because forced via 'systemConfigForce' tag",
|
||
pluginVersionError: "Not executed because this plugin needs a newer version of TiddlyWiki",
|
||
nothingSelected: "Nothing is selected. You must select one or more items first",
|
||
savedSnapshotError: "It appears that this TiddlyWiki has been incorrectly saved. Please see http://www.tiddlywiki.com/#Download for details",
|
||
subtitleUnknown: "(unknown)",
|
||
undefinedTiddlerToolTip: "The tiddler '%0' doesn't yet exist",
|
||
shadowedTiddlerToolTip: "The tiddler '%0' doesn't yet exist, but has a pre-defined shadow value",
|
||
tiddlerLinkTooltip: "%0 - %1, %2",
|
||
externalLinkTooltip: "External link to %0",
|
||
noTags: "There are no tagged tiddlers",
|
||
notFileUrlError: "You need to save this TiddlyWiki to a file before you can save changes",
|
||
cantSaveError: "It's not possible to save changes. Possible reasons include:\n- your browser doesn't support saving (Firefox, Internet Explorer, Safari and Opera all work if properly configured)\n- the pathname to your TiddlyWiki file contains illegal characters\n- the TiddlyWiki HTML file has been moved or renamed",
|
||
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
|
||
backupSaved: "Backup saved",
|
||
backupFailed: "Failed to save backup file",
|
||
rssSaved: "RSS feed saved",
|
||
rssFailed: "Failed to save RSS feed file",
|
||
emptySaved: "Empty template saved",
|
||
emptyFailed: "Failed to save empty template file",
|
||
mainSaved: "Main TiddlyWiki file saved",
|
||
mainFailed: "Failed to save main TiddlyWiki file. Your changes have not been saved",
|
||
macroError: "Error in macro <<%0>>",
|
||
macroErrorDetails: "Error while executing macro <<%0>>:\n%1",
|
||
missingMacro: "No such macro",
|
||
overwriteWarning: "A tiddler named '%0' already exists. Choose OK to overwrite it",
|
||
unsavedChangesWarning: "WARNING! There are unsaved changes in TiddlyWiki\n\nChoose OK to save\nChoose CANCEL to discard",
|
||
confirmExit: "--------------------------------\n\nThere are unsaved changes in TiddlyWiki. If you continue you will lose those changes\n\n--------------------------------",
|
||
saveInstructions: "SaveChanges",
|
||
unsupportedTWFormat: "Unsupported TiddlyWiki format '%0'",
|
||
tiddlerSaveError: "Error when saving tiddler '%0'",
|
||
tiddlerLoadError: "Error when loading tiddler '%0'",
|
||
wrongSaveFormat: "Cannot save with storage format '%0'. Using standard format for save.",
|
||
invalidFieldName: "Invalid field name %0",
|
||
fieldCannotBeChanged: "Field '%0' cannot be changed",
|
||
loadingMissingTiddler: "Attempting to retrieve the tiddler '%0' from the '%1' server at:\n\n'%2' in the workspace '%3'",
|
||
upgradeDone: "The upgrade to version %0 is now complete\n\nClick 'OK' to reload the newly upgraded TiddlyWiki",
|
||
invalidCookie: "Invalid cookie '%0'"});
|
||
|
||
merge(config.messages.messageClose,{
|
||
text: "close",
|
||
tooltip: "close this message area"});
|
||
|
||
config.messages.backstage = {
|
||
open: {text: "backstage", tooltip: "Open the backstage area to perform authoring and editing tasks"},
|
||
close: {text: "close", tooltip: "Close the backstage area"},
|
||
prompt: "backstage: ",
|
||
decal: {
|
||
edit: {text: "edit", tooltip: "Edit the tiddler '%0'"}
|
||
}
|
||
};
|
||
|
||
config.messages.listView = {
|
||
tiddlerTooltip: "Click for the full text of this tiddler",
|
||
previewUnavailable: "(preview not available)"
|
||
};
|
||
|
||
config.messages.dates.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"];
|
||
config.messages.dates.days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||
config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||
config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
|
||
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
|
||
"th","th","th","th","th","th","th","th","th","th",
|
||
"st","nd","rd","th","th","th","th","th","th","th",
|
||
"st"];
|
||
config.messages.dates.am = "am";
|
||
config.messages.dates.pm = "pm";
|
||
|
||
merge(config.messages.tiddlerPopup,{
|
||
});
|
||
|
||
merge(config.views.wikified.tag,{
|
||
labelNoTags: "no tags",
|
||
labelTags: "tags: ",
|
||
openTag: "Open tag '%0'",
|
||
tooltip: "Show tiddlers tagged with '%0'",
|
||
openAllText: "Open all",
|
||
openAllTooltip: "Open all of these tiddlers",
|
||
popupNone: "No other tiddlers tagged with '%0'"});
|
||
|
||
merge(config.views.wikified,{
|
||
defaultText: "The tiddler '%0' doesn't yet exist. Double-click to create it",
|
||
defaultModifier: "(missing)",
|
||
shadowModifier: "(built-in shadow tiddler)",
|
||
dateFormat: "DD MMM YYYY",
|
||
createdPrompt: "created"});
|
||
|
||
merge(config.views.editor,{
|
||
tagPrompt: "Type tags separated with spaces, [[use double square brackets]] if necessary, or add existing",
|
||
defaultText: "Type the text for '%0'"});
|
||
|
||
merge(config.views.editor.tagChooser,{
|
||
text: "tags",
|
||
tooltip: "Choose existing tags to add to this tiddler",
|
||
popupNone: "There are no tags defined",
|
||
tagTooltip: "Add the tag '%0'"});
|
||
|
||
merge(config.messages,{
|
||
sizeTemplates:
|
||
[
|
||
{unit: 1024*1024*1024, template: "%0\u00a0GB"},
|
||
{unit: 1024*1024, template: "%0\u00a0MB"},
|
||
{unit: 1024, template: "%0\u00a0KB"},
|
||
{unit: 1, template: "%0\u00a0B"}
|
||
]});
|
||
|
||
merge(config.macros.search,{
|
||
label: "search",
|
||
prompt: "Search this TiddlyWiki",
|
||
placeholder: "",
|
||
accessKey: "F",
|
||
successMsg: "%0 tiddlers found matching %1",
|
||
failureMsg: "No tiddlers found matching %0"});
|
||
|
||
merge(config.macros.tagging,{
|
||
label: "tagging: ",
|
||
labelNotTag: "not tagging",
|
||
tooltip: "List of tiddlers tagged with '%0'"});
|
||
|
||
merge(config.macros.timeline,{
|
||
dateFormat: "DD MMM YYYY"});
|
||
|
||
merge(config.macros.allTags,{
|
||
tooltip: "Show tiddlers tagged with '%0'",
|
||
noTags: "There are no tagged tiddlers"});
|
||
|
||
config.macros.list.all.prompt = "All tiddlers in alphabetical order";
|
||
config.macros.list.missing.prompt = "Tiddlers that have links to them but are not defined";
|
||
config.macros.list.orphans.prompt = "Tiddlers that are not linked to from any other tiddlers";
|
||
config.macros.list.shadowed.prompt = "Tiddlers shadowed with default contents";
|
||
config.macros.list.touched.prompt = "Tiddlers that have been modified locally";
|
||
|
||
merge(config.macros.closeAll,{
|
||
label: "close all",
|
||
prompt: "Close all displayed tiddlers (except any that are being edited)"});
|
||
|
||
merge(config.macros.permaview,{
|
||
label: "permaview",
|
||
prompt: "Link to an URL that retrieves all the currently displayed tiddlers"});
|
||
|
||
merge(config.macros.saveChanges,{
|
||
label: "save changes",
|
||
prompt: "Save all tiddlers to create a new TiddlyWiki",
|
||
accessKey: "S"});
|
||
|
||
merge(config.macros.newTiddler,{
|
||
label: "new tiddler",
|
||
prompt: "Create a new tiddler",
|
||
title: "New Tiddler",
|
||
accessKey: "N"});
|
||
|
||
merge(config.macros.newJournal,{
|
||
label: "new journal",
|
||
prompt: "Create a new tiddler from the current date and time",
|
||
accessKey: "J"});
|
||
|
||
merge(config.macros.options,{
|
||
wizardTitle: "Tweak advanced options",
|
||
step1Title: "These options are saved in cookies in your browser",
|
||
step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>Show unknown options</input>",
|
||
unknownDescription: "//(unknown)//",
|
||
listViewTemplate: {
|
||
columns: [
|
||
{name: 'Option', field: 'option', title: "Option", type: 'String'},
|
||
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
|
||
{name: 'Name', field: 'name', title: "Name", type: 'String'}
|
||
],
|
||
rowClasses: [
|
||
{className: 'lowlight', field: 'lowlight'}
|
||
]}
|
||
});
|
||
|
||
merge(config.macros.plugins,{
|
||
wizardTitle: "Manage plugins",
|
||
step1Title: "Currently loaded plugins",
|
||
step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
|
||
skippedText: "(This plugin has not been executed because it was added since startup)",
|
||
noPluginText: "There are no plugins installed",
|
||
confirmDeleteText: "Are you sure you want to delete these plugins:\n\n%0",
|
||
removeLabel: "remove systemConfig tag",
|
||
removePrompt: "Remove systemConfig tag",
|
||
deleteLabel: "delete",
|
||
deletePrompt: "Delete these tiddlers forever",
|
||
listViewTemplate: {
|
||
columns: [
|
||
{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
|
||
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
|
||
{name: 'Description', field: 'Description', title: "Description", type: 'String'},
|
||
{name: 'Version', field: 'Version', title: "Version", type: 'String'},
|
||
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
|
||
{name: 'Forced', field: 'forced', title: "Forced", tag: 'systemConfigForce', type: 'TagCheckbox'},
|
||
{name: 'Disabled', field: 'disabled', title: "Disabled", tag: 'systemConfigDisable', type: 'TagCheckbox'},
|
||
{name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"},
|
||
{name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'},
|
||
{name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"},
|
||
{name: 'Log', field: 'log', title: "Log", type: 'StringList'}
|
||
],
|
||
rowClasses: [
|
||
{className: 'error', field: 'error'},
|
||
{className: 'warning', field: 'warning'}
|
||
]},
|
||
listViewTemplateReadOnly: {
|
||
columns: [
|
||
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
|
||
{name: 'Description', field: 'Description', title: "Description", type: 'String'},
|
||
{name: 'Version', field: 'Version', title: "Version", type: 'String'},
|
||
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
|
||
{name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"},
|
||
{name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'},
|
||
{name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"},
|
||
{name: 'Log', field: 'log', title: "Log", type: 'StringList'}
|
||
],
|
||
rowClasses: [
|
||
{className: 'error', field: 'error'},
|
||
{className: 'warning', field: 'warning'}
|
||
]}
|
||
});
|
||
|
||
merge(config.macros.toolbar,{
|
||
moreLabel: "more",
|
||
morePrompt: "Show additional commands",
|
||
lessLabel: "less",
|
||
lessPrompt: "Hide additional commands",
|
||
separator: "|"
|
||
});
|
||
|
||
merge(config.macros.refreshDisplay,{
|
||
label: "refresh",
|
||
prompt: "Redraw the entire TiddlyWiki display"
|
||
});
|
||
|
||
merge(config.macros.importTiddlers,{
|
||
readOnlyWarning: "You cannot import into a read-only TiddlyWiki file. Try opening it from a file:// URL",
|
||
wizardTitle: "Import tiddlers from another file or server",
|
||
step1Title: "Step 1: Locate the server or TiddlyWiki file",
|
||
step1Html: "Specify the type of the server: <select name='selTypes'><option value=''>Choose...</option></select><br>Enter the URL or pathname here: <input type='text' size=50 name='txtPath'><br>...or browse for a file: <input type='file' size=50 name='txtBrowse'><br><hr>...or select a pre-defined feed: <select name='selFeeds'><option value=''>Choose...</option></select>",
|
||
openLabel: "open",
|
||
openPrompt: "Open the connection to this file or server",
|
||
statusOpenHost: "Opening the host",
|
||
statusGetWorkspaceList: "Getting the list of available workspaces",
|
||
step2Title: "Step 2: Choose the workspace",
|
||
step2Html: "Enter a workspace name: <input type='text' size=50 name='txtWorkspace'><br>...or select a workspace: <select name='selWorkspace'><option value=''>Choose...</option></select>",
|
||
cancelLabel: "cancel",
|
||
cancelPrompt: "Cancel this import",
|
||
statusOpenWorkspace: "Opening the workspace",
|
||
statusGetTiddlerList: "Getting the list of available tiddlers",
|
||
errorGettingTiddlerList: "Error getting list of tiddlers, click Cancel to try again",
|
||
errorGettingTiddlerListHttp404: "Error retrieving tiddlers from url, please ensure the url exists. Click Cancel to try again.",
|
||
errorGettingTiddlerListHttp: "Error retrieving tiddlers from url, please ensure this url exists and is <a href='http://enable-cors.org/'>CORS</a> enabled",
|
||
errorGettingTiddlerListFile: "Error retrieving tiddlers from local file, please make sure the file is in the same directory as your TiddlyWiki. Click Cancel to try again.",
|
||
step3Title: "Step 3: Choose the tiddlers to import",
|
||
step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>Keep these tiddlers linked to this server so that you can synchronise subsequent changes</input><br><input type='checkbox' name='chkSave'>Save the details of this server in a 'systemServer' tiddler called:</input> <input type='text' size=25 name='txtSaveTiddler'>",
|
||
importLabel: "import",
|
||
importPrompt: "Import these tiddlers",
|
||
confirmOverwriteText: "Are you sure you want to overwrite these tiddlers:\n\n%0",
|
||
step4Title: "Step 4: Importing %0 tiddler(s)",
|
||
step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
|
||
doneLabel: "done",
|
||
donePrompt: "Close this wizard",
|
||
statusDoingImport: "Importing tiddlers",
|
||
statusDoneImport: "All tiddlers imported",
|
||
systemServerNamePattern: "%2 on %1",
|
||
systemServerNamePatternNoWorkspace: "%1",
|
||
confirmOverwriteSaveTiddler: "The tiddler '%0' already exists. Click 'OK' to overwrite it with the details of this server, or 'Cancel' to leave it unchanged",
|
||
serverSaveTemplate: "|''Type:''|%0|\n|''URL:''|%1|\n|''Workspace:''|%2|\n\nThis tiddler was automatically created to record the details of this server",
|
||
serverSaveModifier: "(System)",
|
||
listViewTemplate: {
|
||
columns: [
|
||
{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
|
||
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
|
||
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'},
|
||
{name: 'Tags', field: 'tags', title: "Tags", type: 'Tags'}
|
||
],
|
||
rowClasses: [
|
||
]}
|
||
});
|
||
|
||
merge(config.macros.upgrade,{
|
||
wizardTitle: "Upgrade TiddlyWiki core code",
|
||
step1Title: "Update or repair this TiddlyWiki to the latest release",
|
||
step1Html: "You are about to upgrade to the latest release of the TiddlyWiki core code (from <a href='%0' class='externalLink' target='_blank'>%1</a>). Your content will be preserved across the upgrade.<br><br>Note that core upgrades have been known to interfere with older plugins. If you run into problems with the upgraded file, see <a href='http://www.tiddlywiki.org/wiki/CoreUpgrades' class='externalLink' target='_blank'>http://www.tiddlywiki.org/wiki/CoreUpgrades</a>",
|
||
errorCantUpgrade: "Unable to upgrade this TiddlyWiki. You can only perform upgrades on TiddlyWiki files stored locally",
|
||
errorNotSaved: "You must save changes before you can perform an upgrade",
|
||
step2Title: "Confirm the upgrade details",
|
||
step2Html_downgrade: "You are about to downgrade to TiddlyWiki version %0 from %1.<br><br>Downgrading to an earlier version of the core code is not recommended",
|
||
step2Html_restore: "This TiddlyWiki appears to be already using the latest version of the core code (%0).<br><br>You can continue to upgrade anyway to ensure that the core code hasn't been corrupted or damaged",
|
||
step2Html_upgrade: "You are about to upgrade to TiddlyWiki version %0 from %1",
|
||
upgradeLabel: "upgrade",
|
||
upgradePrompt: "Prepare for the upgrade process",
|
||
statusPreparingBackup: "Preparing backup",
|
||
statusSavingBackup: "Saving backup file",
|
||
errorSavingBackup: "There was a problem saving the backup file",
|
||
statusLoadingCore: "Loading core code",
|
||
errorLoadingCore: "Error loading the core code",
|
||
errorCoreFormat: "Error with the new core code",
|
||
statusSavingCore: "Saving the new core code",
|
||
statusReloadingCore: "Reloading the new core code",
|
||
startLabel: "start",
|
||
startPrompt: "Start the upgrade process",
|
||
cancelLabel: "cancel",
|
||
cancelPrompt: "Cancel the upgrade process",
|
||
step3Title: "Upgrade cancelled",
|
||
step3Html: "You have cancelled the upgrade process"
|
||
});
|
||
|
||
merge(config.macros.sync,{
|
||
listViewTemplate: {
|
||
columns: [
|
||
{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
|
||
{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
|
||
{name: 'Server Type', field: 'serverType', title: "Server type", type: 'String'},
|
||
{name: 'Server Host', field: 'serverHost', title: "Server host", type: 'String'},
|
||
{name: 'Server Workspace', field: 'serverWorkspace', title: "Server workspace", type: 'String'},
|
||
{name: 'Status', field: 'status', title: "Synchronisation status", type: 'String'},
|
||
{name: 'Server URL', field: 'serverUrl', title: "Server URL", text: "View", type: 'Link'}
|
||
],
|
||
rowClasses: [
|
||
],
|
||
buttons: [
|
||
{caption: "Sync these tiddlers", name: 'sync'}
|
||
]},
|
||
wizardTitle: "Synchronize with external servers and files",
|
||
step1Title: "Choose the tiddlers you want to synchronize",
|
||
step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
|
||
syncLabel: "sync",
|
||
syncPrompt: "Sync these tiddlers",
|
||
hasChanged: "Changed while unplugged",
|
||
hasNotChanged: "Unchanged while unplugged",
|
||
syncStatusList: {
|
||
none: {text: "...", display:'none', className:'notChanged'},
|
||
changedServer: {text: "Changed on server", display:null, className:'changedServer'},
|
||
changedLocally: {text: "Changed while unplugged", display:null, className:'changedLocally'},
|
||
changedBoth: {text: "Changed while unplugged and on server", display:null, className:'changedBoth'},
|
||
notFound: {text: "Not found on server", display:null, className:'notFound'},
|
||
putToServer: {text: "Saved update on server", display:null, className:'putToServer'},
|
||
gotFromServer: {text: "Retrieved update from server", display:null, className:'gotFromServer'}
|
||
}
|
||
});
|
||
|
||
merge(config.macros.annotations,{
|
||
});
|
||
|
||
merge(config.commands.closeTiddler,{
|
||
text: "close",
|
||
tooltip: "Close this tiddler"});
|
||
|
||
merge(config.commands.closeOthers,{
|
||
text: "close others",
|
||
tooltip: "Close all other tiddlers"});
|
||
|
||
merge(config.commands.editTiddler,{
|
||
text: "edit",
|
||
tooltip: "Edit this tiddler",
|
||
readOnlyText: "view",
|
||
readOnlyTooltip: "View the source of this tiddler"});
|
||
|
||
merge(config.commands.saveTiddler,{
|
||
text: "done",
|
||
tooltip: "Save changes to this tiddler"});
|
||
|
||
merge(config.commands.cancelTiddler,{
|
||
text: "cancel",
|
||
tooltip: "Undo changes to this tiddler",
|
||
warning: "Are you sure you want to abandon your changes to '%0'?",
|
||
readOnlyText: "done",
|
||
readOnlyTooltip: "View this tiddler normally"});
|
||
|
||
merge(config.commands.deleteTiddler,{
|
||
text: "delete",
|
||
tooltip: "Delete this tiddler",
|
||
warning: "Are you sure you want to delete '%0'?"});
|
||
|
||
merge(config.commands.permalink,{
|
||
text: "permalink",
|
||
tooltip: "Permalink for this tiddler"});
|
||
|
||
merge(config.commands.references,{
|
||
text: "references",
|
||
tooltip: "Show tiddlers that link to this one",
|
||
popupNone: "No references"});
|
||
|
||
merge(config.commands.jump,{
|
||
text: "jump",
|
||
tooltip: "Jump to another open tiddler"});
|
||
|
||
merge(config.commands.syncing,{
|
||
text: "syncing",
|
||
tooltip: "Control synchronisation of this tiddler with a server or external file",
|
||
currentlySyncing: "<div>Currently syncing via <span class='popupHighlight'>'%0'</span> to:</"+"div><div>host: <span class='popupHighlight'>%1</span></"+"div><div>workspace: <span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
|
||
notCurrentlySyncing: "Not currently syncing",
|
||
captionUnSync: "Stop synchronising this tiddler",
|
||
chooseServer: "Synchronise this tiddler with another server:",
|
||
currServerMarker: "\u25cf ",
|
||
notCurrServerMarker: " "});
|
||
|
||
merge(config.commands.fields,{
|
||
text: "fields",
|
||
tooltip: "Show the extended fields of this tiddler",
|
||
emptyText: "There are no extended fields for this tiddler",
|
||
listViewTemplate: {
|
||
columns: [
|
||
{name: 'Field', field: 'field', title: "Field", type: 'String'},
|
||
{name: 'Value', field: 'value', title: "Value", type: 'String'}
|
||
],
|
||
rowClasses: [
|
||
],
|
||
buttons: [
|
||
]}});
|
||
|
||
merge(config.shadowTiddlers,{
|
||
DefaultTiddlers: "[[GettingStarted]]",
|
||
MainMenu: "[[GettingStarted]]",
|
||
SiteTitle: "My TiddlyWiki",
|
||
SiteSubtitle: "a reusable non-linear personal web notebook",
|
||
SiteUrl: "",
|
||
SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options \u00bb" "Change TiddlyWiki advanced options">>',
|
||
SideBarTabs: '<<tabs txtMainTab "Timeline" "Timeline" TabTimeline "All" "All tiddlers" TabAll "Tags" "All tags" TabTags "More" "More lists" TabMore>>',
|
||
TabMore: '<<tabs txtMoreTab "Missing" "Missing tiddlers" TabMoreMissing "Orphans" "Orphaned tiddlers" TabMoreOrphans "Shadowed" "Shadowed tiddlers" TabMoreShadowed>>'
|
||
});
|
||
|
||
merge(config.annotations,{
|
||
AdvancedOptions: "This shadow tiddler provides access to several advanced options",
|
||
ColorPalette: "These values in this shadow tiddler determine the colour scheme of the ~TiddlyWiki user interface",
|
||
DefaultTiddlers: "The tiddlers listed in this shadow tiddler will be automatically displayed when ~TiddlyWiki starts up",
|
||
EditTemplate: "The HTML template in this shadow tiddler determines how tiddlers look while they are being edited",
|
||
GettingStarted: "This shadow tiddler provides basic usage instructions",
|
||
ImportTiddlers: "This shadow tiddler provides access to importing tiddlers",
|
||
MainMenu: "This shadow tiddler is used as the contents of the main menu in the left-hand column of the screen",
|
||
MarkupPreHead: "This tiddler is inserted at the top of the <head> section of the TiddlyWiki HTML file",
|
||
MarkupPostHead: "This tiddler is inserted at the bottom of the <head> section of the TiddlyWiki HTML file",
|
||
MarkupPreBody: "This tiddler is inserted at the top of the <body> section of the TiddlyWiki HTML file",
|
||
MarkupPostBody: "This tiddler is inserted at the end of the <body> section of the TiddlyWiki HTML file immediately after the script block",
|
||
OptionsPanel: "This shadow tiddler is used as the contents of the options panel slider in the right-hand sidebar",
|
||
PageTemplate: "The HTML template in this shadow tiddler determines the overall ~TiddlyWiki layout",
|
||
PluginManager: "This shadow tiddler provides access to the plugin manager",
|
||
SideBarOptions: "This shadow tiddler is used as the contents of the option panel in the right-hand sidebar",
|
||
SideBarTabs: "This shadow tiddler is used as the contents of the tabs panel in the right-hand sidebar",
|
||
SiteSubtitle: "This shadow tiddler is used as the second part of the page title",
|
||
SiteTitle: "This shadow tiddler is used as the first part of the page title",
|
||
SiteUrl: "This shadow tiddler should be set to the full target URL for publication",
|
||
StyleSheetColors: "This shadow tiddler contains CSS definitions related to the color of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler",
|
||
StyleSheet: "This tiddler can contain custom CSS definitions",
|
||
StyleSheetLayout: "This shadow tiddler contains CSS definitions related to the layout of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler",
|
||
StyleSheetLocale: "This shadow tiddler contains CSS definitions related to the translation locale",
|
||
StyleSheetPrint: "This shadow tiddler contains CSS definitions for printing",
|
||
SystemSettings: "This tiddler is used to store configuration options for this TiddlyWiki document",
|
||
TabAll: "This shadow tiddler contains the contents of the 'All' tab in the right-hand sidebar",
|
||
TabMore: "This shadow tiddler contains the contents of the 'More' tab in the right-hand sidebar",
|
||
TabMoreMissing: "This shadow tiddler contains the contents of the 'Missing' tab in the right-hand sidebar",
|
||
TabMoreOrphans: "This shadow tiddler contains the contents of the 'Orphans' tab in the right-hand sidebar",
|
||
TabMoreShadowed: "This shadow tiddler contains the contents of the 'Shadowed' tab in the right-hand sidebar",
|
||
TabTags: "This shadow tiddler contains the contents of the 'Tags' tab in the right-hand sidebar",
|
||
TabTimeline: "This shadow tiddler contains the contents of the 'Timeline' tab in the right-hand sidebar",
|
||
ToolbarCommands: "This shadow tiddler determines which commands are shown in tiddler toolbars",
|
||
ViewTemplate: "The HTML template in this shadow tiddler determines how tiddlers look"
|
||
});
|
||
//--
|
||
//-- Main
|
||
//--
|
||
|
||
var params = null; // Command line parameters
|
||
var store = null; // TiddlyWiki storage
|
||
var story = null; // Main story
|
||
var formatter = null; // Default formatters for the wikifier
|
||
var anim = typeof Animator == "function" ? new Animator() : null; // Animation engine
|
||
var readOnly = false; // Whether we're in readonly mode
|
||
var highlightHack = null; // Embarrassing hack department...
|
||
var hadConfirmExit = false; // Don't warn more than once
|
||
var safeMode = false; // Disable all plugins and cookies
|
||
var showBackstage; // Whether to include the backstage area
|
||
var installedPlugins = []; // Information filled in when plugins are executed
|
||
var startingUp = false; // Whether we're in the process of starting up
|
||
var pluginInfo,tiddler; // Used to pass information to plugins in loadPlugins()
|
||
|
||
// Whether to use the JavaSaver applet
|
||
var useJavaSaver = (config.browser.isSafari || config.browser.isOpera) && (document.location.toString().substr(0,4) != "http");
|
||
|
||
if(!window || !window.console) {
|
||
console = {tiddlywiki:true,log:function(message) {displayMessage(message);}};
|
||
}
|
||
|
||
// Starting up
|
||
function main()
|
||
{
|
||
var t10,t9,t8,t7,t6,t5,t4,t3,t2,t1,t0 = new Date();
|
||
startingUp = true;
|
||
var doc = jQuery(document);
|
||
jQuery.noConflict();
|
||
window.onbeforeunload = function(e) {if(window.confirmExit) return confirmExit();};
|
||
params = getParameters();
|
||
if(params)
|
||
params = params.parseParams("open",null,false);
|
||
store = new TiddlyWiki({config:config});
|
||
invokeParamifier(params,"oninit");
|
||
story = new Story("tiddlerDisplay","tiddler");
|
||
addEvent(document,"click",Popup.onDocumentClick);
|
||
saveTest();
|
||
var s;
|
||
for(s=0; s<config.notifyTiddlers.length; s++)
|
||
store.addNotification(config.notifyTiddlers[s].name,config.notifyTiddlers[s].notify);
|
||
t1 = new Date();
|
||
loadShadowTiddlers();
|
||
doc.trigger("loadShadows");
|
||
t2 = new Date();
|
||
store.loadFromDiv("storeArea","store",true);
|
||
doc.trigger("loadTiddlers");
|
||
loadOptions();
|
||
t3 = new Date();
|
||
invokeParamifier(params,"onload");
|
||
t4 = new Date();
|
||
readOnly = (window.location.protocol == "file:") ? false : config.options.chkHttpReadOnly;
|
||
var pluginProblem = loadPlugins("systemConfig");
|
||
doc.trigger("loadPlugins");
|
||
t5 = new Date();
|
||
formatter = new Formatter(config.formatters);
|
||
invokeParamifier(params,"onconfig");
|
||
story.switchTheme(config.options.txtTheme);
|
||
showBackstage = showBackstage !== undefined ? showBackstage : !readOnly;
|
||
t6 = new Date();
|
||
var m;
|
||
for(m in config.macros) {
|
||
if(config.macros[m].init)
|
||
config.macros[m].init();
|
||
}
|
||
t7 = new Date();
|
||
store.notifyAll();
|
||
t8 = new Date();
|
||
restart();
|
||
refreshDisplay();
|
||
t9 = new Date();
|
||
if(pluginProblem) {
|
||
story.displayTiddler(null,"PluginManager");
|
||
displayMessage(config.messages.customConfigError);
|
||
}
|
||
if(showBackstage)
|
||
backstage.init();
|
||
t10 = new Date();
|
||
if(config.options.chkDisplayInstrumentation) {
|
||
displayMessage("LoadShadows " + (t2-t1) + " ms");
|
||
displayMessage("LoadFromDiv " + (t3-t2) + " ms");
|
||
displayMessage("LoadPlugins " + (t5-t4) + " ms");
|
||
displayMessage("Macro init " + (t7-t6) + " ms");
|
||
displayMessage("Notify " + (t8-t7) + " ms");
|
||
displayMessage("Restart " + (t9-t8) + " ms");
|
||
displayMessage("Total: " + (t10-t0) + " ms");
|
||
}
|
||
startingUp = false;
|
||
doc.trigger("startup");
|
||
}
|
||
|
||
// Called on unload. All functions called conditionally since they themselves may have been unloaded.
|
||
function unload()
|
||
{
|
||
if(window.checkUnsavedChanges)
|
||
checkUnsavedChanges();
|
||
if(window.scrubNodes)
|
||
scrubNodes(document.body);
|
||
}
|
||
|
||
// Restarting
|
||
function restart()
|
||
{
|
||
invokeParamifier(params,"onstart");
|
||
if(story.isEmpty()) {
|
||
story.displayDefaultTiddlers();
|
||
}
|
||
window.scrollTo(0,0);
|
||
}
|
||
|
||
function saveTest()
|
||
{
|
||
var s = document.getElementById("saveTest");
|
||
if(s.hasChildNodes())
|
||
alert(config.messages.savedSnapshotError);
|
||
s.appendChild(document.createTextNode("savetest"));
|
||
}
|
||
|
||
function loadShadowTiddlers()
|
||
{
|
||
var shadows = new TiddlyWiki();
|
||
shadows.loadFromDiv("shadowArea","shadows",true);
|
||
shadows.forEachTiddler(function(title,tiddler){config.shadowTiddlers[title] = tiddler.text;});
|
||
}
|
||
|
||
function loadPlugins(tag)
|
||
{
|
||
if(safeMode)
|
||
return false;
|
||
var tiddlers = store.getTaggedTiddlers(tag);
|
||
tiddlers.sort(function(a,b) {return a.title < b.title ? -1 : (a.title == b.title ? 0 : 1);});
|
||
var toLoad = [];
|
||
var nLoaded = 0;
|
||
var map = {};
|
||
var nPlugins = tiddlers.length;
|
||
installedPlugins = [];
|
||
var i;
|
||
for(i=0; i<nPlugins; i++) {
|
||
var p = getPluginInfo(tiddlers[i]);
|
||
installedPlugins[i] = p;
|
||
var n = p.Name || p.title;
|
||
if(n)
|
||
map[n] = p;
|
||
n = p.Source;
|
||
if(n)
|
||
map[n] = p;
|
||
}
|
||
var visit = function(p) {
|
||
if(!p || p.done)
|
||
return;
|
||
p.done = 1;
|
||
var reqs = p.Requires;
|
||
if(reqs) {
|
||
reqs = reqs.readBracketedList();
|
||
var i;
|
||
for(i=0; i<reqs.length; i++)
|
||
visit(map[reqs[i]]);
|
||
}
|
||
toLoad.push(p);
|
||
};
|
||
for(i=0; i<nPlugins; i++)
|
||
visit(installedPlugins[i]);
|
||
for(i=0; i<toLoad.length; i++) {
|
||
p = toLoad[i];
|
||
pluginInfo = p;
|
||
tiddler = p.tiddler;
|
||
if(isPluginExecutable(p)) {
|
||
if(isPluginEnabled(p)) {
|
||
p.executed = true;
|
||
var startTime = new Date();
|
||
try {
|
||
if(tiddler.text)
|
||
window.eval(tiddler.text);
|
||
nLoaded++;
|
||
} catch(ex) {
|
||
p.log.push(config.messages.pluginError.format([exceptionText(ex)]));
|
||
p.error = true;
|
||
if(!console.tiddlywiki) {
|
||
console.log("error evaluating " + tiddler.title, ex);
|
||
}
|
||
}
|
||
pluginInfo.startupTime = String((new Date()) - startTime) + "ms";
|
||
} else {
|
||
nPlugins--;
|
||
}
|
||
} else {
|
||
p.warning = true;
|
||
}
|
||
}
|
||
return nLoaded != nPlugins;
|
||
}
|
||
|
||
function getPluginInfo(tiddler)
|
||
{
|
||
var p = store.getTiddlerSlices(tiddler.title,["Name","Description","Version","Requires","CoreVersion","Date","Source","Author","License","Browsers"]);
|
||
p.tiddler = tiddler;
|
||
p.title = tiddler.title;
|
||
p.log = [];
|
||
return p;
|
||
}
|
||
|
||
// Check that a particular plugin is valid for execution
|
||
function isPluginExecutable(plugin)
|
||
{
|
||
if(plugin.tiddler.isTagged("systemConfigForce")) {
|
||
plugin.log.push(config.messages.pluginForced);
|
||
return true;
|
||
}
|
||
if(plugin["CoreVersion"]) {
|
||
var coreVersion = plugin["CoreVersion"].split(".");
|
||
var w = parseInt(coreVersion[0],10) - version.major;
|
||
if(w == 0 && coreVersion[1])
|
||
w = parseInt(coreVersion[1],10) - version.minor;
|
||
if(w == 0 && coreVersion[2])
|
||
w = parseInt(coreVersion[2],10) - version.revision;
|
||
if(w > 0) {
|
||
plugin.log.push(config.messages.pluginVersionError);
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function isPluginEnabled(plugin)
|
||
{
|
||
if(plugin.tiddler.isTagged("systemConfigDisable")) {
|
||
plugin.log.push(config.messages.pluginDisabled);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//--
|
||
//-- Paramifiers
|
||
//--
|
||
|
||
function getParameters()
|
||
{
|
||
var p = null;
|
||
if(window.location.hash) {
|
||
p = decodeURIComponent(window.location.hash.substr(1));
|
||
if(config.browser.firefoxDate != null && config.browser.firefoxDate[1] < "20051111")
|
||
p = convertUTF8ToUnicode(p);
|
||
}
|
||
return p;
|
||
}
|
||
|
||
function invokeParamifier(params,handler)
|
||
{
|
||
if(!params || params.length == undefined || params.length <= 1)
|
||
return;
|
||
var i;
|
||
for(i=1; i<params.length; i++) {
|
||
var p = config.paramifiers[params[i].name];
|
||
if(p && p[handler] instanceof Function)
|
||
p[handler](params[i].value);
|
||
else {
|
||
var h = config.optionHandlers[params[i].name.substr(0,3)];
|
||
if(h && h.set instanceof Function)
|
||
h.set(params[i].name,params[i].value);
|
||
}
|
||
}
|
||
}
|
||
|
||
config.paramifiers = {};
|
||
|
||
config.paramifiers.start = {
|
||
oninit: function(v) {
|
||
safeMode = v.toLowerCase() == "safe";
|
||
}
|
||
};
|
||
|
||
config.paramifiers.open = {
|
||
onstart: function(v) {
|
||
if(!readOnly || store.tiddlerExists(v) || store.isShadowTiddler(v))
|
||
story.displayTiddler("bottom",v,null,false,null);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.story = {
|
||
onstart: function(v) {
|
||
var list = store.getTiddlerText(v,"").parseParams("open",null,false);
|
||
invokeParamifier(list,"onstart");
|
||
}
|
||
};
|
||
|
||
config.paramifiers.search = {
|
||
onstart: function(v) {
|
||
story.search(v,false,false);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.searchRegExp = {
|
||
onstart: function(v) {
|
||
story.prototype.search(v,false,true);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.tag = {
|
||
onstart: function(v) {
|
||
story.displayTiddlers(null,store.filterTiddlers("[tag["+v+"]]"),null,false,null);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.newTiddler = {
|
||
onstart: function(v) {
|
||
var args = v.parseParams("anon", null, null)[0];
|
||
var title = args.title ? args.title[0] : v;
|
||
var customFields = args.fields ? args.fields[0] : null;
|
||
if(!readOnly) {
|
||
story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE,false,null,customFields);
|
||
story.focusTiddler(title,"text");
|
||
var i,tags = args.tag || [];
|
||
for(i=0;i<tags.length;i++) {
|
||
story.setTiddlerTag(title,tags[i],+1);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
config.paramifiers.newJournal = {
|
||
onstart: function(v) {
|
||
if(!readOnly) {
|
||
var now = new Date();
|
||
var title = now.formatString(v.trim());
|
||
story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
|
||
story.focusTiddler(title,"text");
|
||
}
|
||
}
|
||
};
|
||
|
||
config.paramifiers.readOnly = {
|
||
onconfig: function(v) {
|
||
var p = v.toLowerCase();
|
||
readOnly = p == "yes" ? true : (p == "no" ? false : readOnly);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.theme = {
|
||
onconfig: function(v) {
|
||
story.switchTheme(v);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.upgrade = {
|
||
onstart: function(v) {
|
||
upgradeFrom(v);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.recent= {
|
||
onstart: function(v) {
|
||
var titles=[];
|
||
var i,tiddlers=store.getTiddlers("modified","excludeLists").reverse();
|
||
for(i=0; i<v && i<tiddlers.length; i++)
|
||
titles.push(tiddlers[i].title);
|
||
story.displayTiddlers(null,titles);
|
||
}
|
||
};
|
||
|
||
config.paramifiers.filter = {
|
||
onstart: function(v) {
|
||
story.displayTiddlers(null,store.filterTiddlers(v),null,false);
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Formatter helpers
|
||
//--
|
||
|
||
function Formatter(formatters)
|
||
{
|
||
var n;
|
||
this.formatters = [];
|
||
var pattern = [];
|
||
for(n=0; n<formatters.length; n++) {
|
||
pattern.push("(" + formatters[n].match + ")");
|
||
this.formatters.push(formatters[n]);
|
||
}
|
||
this.formatterRegExp = new RegExp(pattern.join("|"),"mg");
|
||
}
|
||
|
||
config.formatterHelpers = {
|
||
|
||
createElementAndWikify: function(w)
|
||
{
|
||
w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
|
||
},
|
||
|
||
inlineCssHelper: function(w)
|
||
{
|
||
var styles = [];
|
||
config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
|
||
var lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
|
||
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
|
||
var s,v;
|
||
if(lookaheadMatch[1]) {
|
||
s = lookaheadMatch[1].unDash();
|
||
v = lookaheadMatch[2];
|
||
} else {
|
||
s = lookaheadMatch[3].unDash();
|
||
v = lookaheadMatch[4];
|
||
}
|
||
if(s=="bgcolor")
|
||
s = "backgroundColor";
|
||
if(s=="float")
|
||
s = "cssFloat";
|
||
styles.push({style: s, value: v});
|
||
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
|
||
config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
|
||
lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
|
||
}
|
||
return styles;
|
||
},
|
||
|
||
applyCssHelper: function(e,styles)
|
||
{
|
||
var t;
|
||
for(t=0; t< styles.length; t++) {
|
||
try {
|
||
e.style[styles[t].style] = styles[t].value;
|
||
} catch (ex) {
|
||
}
|
||
}
|
||
},
|
||
|
||
enclosedTextHelper: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
var text = lookaheadMatch[1];
|
||
if(config.browser.isIE)
|
||
text = text.replace(/\n/g,"\r");
|
||
createTiddlyElement(w.output,this.element,null,null,text);
|
||
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
|
||
}
|
||
},
|
||
|
||
isExternalLink: function(link)
|
||
{
|
||
if(store.tiddlerExists(link) || store.isShadowTiddler(link)) {
|
||
return false;
|
||
}
|
||
var urlRegExp = new RegExp(config.textPrimitives.urlPattern,"mg");
|
||
if(urlRegExp.exec(link)) {
|
||
return true;
|
||
}
|
||
if(link.indexOf(".")!=-1 || link.indexOf("\\")!=-1 || link.indexOf("/")!=-1 || link.indexOf("#")!=-1) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
};
|
||
|
||
//--
|
||
//-- Standard formatters
|
||
//--
|
||
|
||
config.formatters = [
|
||
{
|
||
name: "table",
|
||
match: "^\\|(?:[^\\n]*)\\|(?:[fhck]?)$",
|
||
lookaheadRegExp: /^\|([^\n]*)\|([fhck]?)$/mg,
|
||
rowTermRegExp: /(\|(?:[fhck]?)$\n?)/mg,
|
||
cellRegExp: /(?:\|([^\n\|]*)\|)|(\|[fhck]?$\n?)/mg,
|
||
cellTermRegExp: /((?:\x20*)\|)/mg,
|
||
rowTypes: {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
|
||
handler: function(w)
|
||
{
|
||
var table = createTiddlyElement(w.output,"table",null,"twtable");
|
||
var prevColumns = [];
|
||
var currRowType = null;
|
||
var rowContainer;
|
||
var rowCount = 0;
|
||
var onmouseover = function() {jQuery(this).addClass("hoverRow");};
|
||
var onmouseout = function() {jQuery(this).removeClass("hoverRow");};
|
||
w.nextMatch = w.matchStart;
|
||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
|
||
var nextRowType = lookaheadMatch[2];
|
||
if(nextRowType == "k") {
|
||
table.className = lookaheadMatch[1];
|
||
w.nextMatch += lookaheadMatch[0].length+1;
|
||
} else {
|
||
if(nextRowType != currRowType) {
|
||
rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);
|
||
currRowType = nextRowType;
|
||
}
|
||
if(currRowType == "c") {
|
||
// Caption
|
||
w.nextMatch++;
|
||
if(rowContainer != table.firstChild)
|
||
table.insertBefore(rowContainer,table.firstChild);
|
||
rowContainer.setAttribute("align",rowCount == 0?"top":"bottom");
|
||
w.subWikifyTerm(rowContainer,this.rowTermRegExp);
|
||
} else {
|
||
var theRow = createTiddlyElement(rowContainer,"tr",null,rowCount%2?"oddRow":"evenRow");
|
||
theRow.onmouseover = onmouseover;
|
||
theRow.onmouseout = onmouseout;
|
||
this.rowHandler(w,theRow,prevColumns);
|
||
rowCount++;
|
||
}
|
||
}
|
||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
}
|
||
},
|
||
rowHandler: function(w,e,prevColumns)
|
||
{
|
||
var col = 0;
|
||
var colSpanCount = 1;
|
||
var prevCell = null;
|
||
this.cellRegExp.lastIndex = w.nextMatch;
|
||
var cellMatch = this.cellRegExp.exec(w.source);
|
||
while(cellMatch && cellMatch.index == w.nextMatch) {
|
||
if(cellMatch[1] == "~") {
|
||
// Rowspan
|
||
var last = prevColumns[col];
|
||
if(last) {
|
||
last.rowSpanCount++;
|
||
last.element.setAttribute("rowspan",last.rowSpanCount);
|
||
last.element.setAttribute("rowSpan",last.rowSpanCount); // Needed for IE
|
||
last.element.valign = "center";
|
||
if(colSpanCount > 1) {
|
||
last.element.setAttribute("colspan",colSpanCount);
|
||
last.element.setAttribute("colSpan",colSpanCount); // Needed for IE
|
||
colSpanCount = 1;
|
||
}
|
||
}
|
||
w.nextMatch = this.cellRegExp.lastIndex-1;
|
||
} else if(cellMatch[1] == ">") {
|
||
// Colspan
|
||
colSpanCount++;
|
||
w.nextMatch = this.cellRegExp.lastIndex-1;
|
||
} else if(cellMatch[2]) {
|
||
// End of row
|
||
if(prevCell && colSpanCount > 1) {
|
||
prevCell.setAttribute("colspan",colSpanCount);
|
||
prevCell.setAttribute("colSpan",colSpanCount); // Needed for IE
|
||
}
|
||
w.nextMatch = this.cellRegExp.lastIndex;
|
||
break;
|
||
} else {
|
||
// Cell
|
||
w.nextMatch++;
|
||
var styles = config.formatterHelpers.inlineCssHelper(w);
|
||
var spaceLeft = false;
|
||
var chr = w.source.substr(w.nextMatch,1);
|
||
while(chr == " ") {
|
||
spaceLeft = true;
|
||
w.nextMatch++;
|
||
chr = w.source.substr(w.nextMatch,1);
|
||
}
|
||
var cell;
|
||
if(chr == "!") {
|
||
cell = createTiddlyElement(e,"th");
|
||
w.nextMatch++;
|
||
} else {
|
||
cell = createTiddlyElement(e,"td");
|
||
}
|
||
prevCell = cell;
|
||
prevColumns[col] = {rowSpanCount:1,element:cell};
|
||
if(colSpanCount > 1) {
|
||
cell.setAttribute("colspan",colSpanCount);
|
||
cell.setAttribute("colSpan",colSpanCount); // Needed for IE
|
||
colSpanCount = 1;
|
||
}
|
||
config.formatterHelpers.applyCssHelper(cell,styles);
|
||
w.subWikifyTerm(cell,this.cellTermRegExp);
|
||
if(w.matchText.substr(w.matchText.length-2,1) == " ") // spaceRight
|
||
cell.align = spaceLeft ? "center" : "left";
|
||
else if(spaceLeft)
|
||
cell.align = "right";
|
||
w.nextMatch--;
|
||
}
|
||
col++;
|
||
this.cellRegExp.lastIndex = w.nextMatch;
|
||
cellMatch = this.cellRegExp.exec(w.source);
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "heading",
|
||
match: "^!{1,6}",
|
||
termRegExp: /(\n)/mg,
|
||
handler: function(w)
|
||
{
|
||
w.subWikifyTerm(createTiddlyElement(w.output,"h" + w.matchLength),this.termRegExp);
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "list",
|
||
match: "^(?:[\\*#;:]+)",
|
||
lookaheadRegExp: /^(?:(?:(\*)|(#)|(;)|(:))+)/mg,
|
||
termRegExp: /(\n)/mg,
|
||
handler: function(w)
|
||
{
|
||
var stack = [w.output];
|
||
var currLevel = 0, currType = null;
|
||
var listLevel, listType, itemType, baseType;
|
||
w.nextMatch = w.matchStart;
|
||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
|
||
if(lookaheadMatch[1]) {
|
||
listType = "ul";
|
||
itemType = "li";
|
||
} else if(lookaheadMatch[2]) {
|
||
listType = "ol";
|
||
itemType = "li";
|
||
} else if(lookaheadMatch[3]) {
|
||
listType = "dl";
|
||
itemType = "dt";
|
||
} else if(lookaheadMatch[4]) {
|
||
listType = "dl";
|
||
itemType = "dd";
|
||
}
|
||
if(!baseType)
|
||
baseType = listType;
|
||
listLevel = lookaheadMatch[0].length;
|
||
w.nextMatch += lookaheadMatch[0].length;
|
||
var t;
|
||
if(listLevel > currLevel) {
|
||
for(t=currLevel; t<listLevel; t++) {
|
||
var target = (currLevel == 0) ? stack[stack.length-1] : stack[stack.length-1].lastChild;
|
||
stack.push(createTiddlyElement(target,listType));
|
||
}
|
||
} else if(listType!=baseType && listLevel==1) {
|
||
w.nextMatch -= lookaheadMatch[0].length;
|
||
return;
|
||
} else if(listLevel < currLevel) {
|
||
for(t=currLevel; t>listLevel; t--)
|
||
stack.pop();
|
||
} else if(listLevel == currLevel && listType != currType) {
|
||
stack.pop();
|
||
stack.push(createTiddlyElement(stack[stack.length-1].lastChild,listType));
|
||
}
|
||
currLevel = listLevel;
|
||
currType = listType;
|
||
var e = createTiddlyElement(stack[stack.length-1],itemType);
|
||
w.subWikifyTerm(e,this.termRegExp);
|
||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "quoteByBlock",
|
||
match: "^<<<\\n",
|
||
termRegExp: /(^<<<(\n|$))/mg,
|
||
element: "blockquote",
|
||
handler: config.formatterHelpers.createElementAndWikify
|
||
},
|
||
|
||
{
|
||
name: "quoteByLine",
|
||
match: "^>+",
|
||
lookaheadRegExp: /^>+/mg,
|
||
termRegExp: /(\n)/mg,
|
||
element: "blockquote",
|
||
handler: function(w)
|
||
{
|
||
var stack = [w.output];
|
||
var currLevel = 0;
|
||
var newLevel = w.matchLength;
|
||
var t,matched;
|
||
do {
|
||
if(newLevel > currLevel) {
|
||
for(t=currLevel; t<newLevel; t++)
|
||
stack.push(createTiddlyElement(stack[stack.length-1],this.element));
|
||
} else if(newLevel < currLevel) {
|
||
for(t=currLevel; t>newLevel; t--)
|
||
stack.pop();
|
||
}
|
||
currLevel = newLevel;
|
||
w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
|
||
createTiddlyElement(stack[stack.length-1],"br");
|
||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
|
||
if(matched) {
|
||
newLevel = lookaheadMatch[0].length;
|
||
w.nextMatch += lookaheadMatch[0].length;
|
||
}
|
||
} while(matched);
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "rule",
|
||
match: "^----+$\\n?|<hr ?/?>\\n?",
|
||
handler: function(w)
|
||
{
|
||
createTiddlyElement(w.output,"hr");
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "monospacedByLine",
|
||
match: "^(?:/\\*\\{\\{\\{\\*/|\\{\\{\\{|//\\{\\{\\{|<!--\\{\\{\\{-->)\\n",
|
||
element: "pre",
|
||
handler: function(w)
|
||
{
|
||
switch(w.matchText) {
|
||
case "/*{{{*/\n": // CSS
|
||
this.lookaheadRegExp = /\/\*\{\{\{\*\/\n*((?:^[^\n]*\n)+?)(\n*^\f*\/\*\}\}\}\*\/$\n?)/mg;
|
||
break;
|
||
case "{{{\n": // monospaced block
|
||
this.lookaheadRegExp = /^\{\{\{\n((?:^[^\n]*\n)+?)(^\f*\}\}\}$\n?)/mg;
|
||
break;
|
||
case "//{{{\n": // plugin
|
||
this.lookaheadRegExp = /^\/\/\{\{\{\n\n*((?:^[^\n]*\n)+?)(\n*^\f*\/\/\}\}\}$\n?)/mg;
|
||
break;
|
||
case "<!--{{{-->\n": //template
|
||
this.lookaheadRegExp = /<!--\{\{\{-->\n*((?:^[^\n]*\n)+?)(\n*^\f*<!--\}\}\}-->$\n?)/mg;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
config.formatterHelpers.enclosedTextHelper.call(this,w);
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "wikifyComment",
|
||
match: "^(?:/\\*\\*\\*|<!---)\\n",
|
||
handler: function(w)
|
||
{
|
||
var termRegExp = (w.matchText == "/***\n") ? (/(^\*\*\*\/\n)/mg) : (/(^--->\n)/mg);
|
||
w.subWikifyTerm(w.output,termRegExp);
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "macro",
|
||
match: "<<",
|
||
lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
|
||
handler: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
|
||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||
invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "prettyLink",
|
||
match: "\\[\\[",
|
||
lookaheadRegExp: /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg,
|
||
handler: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
var e;
|
||
var text = lookaheadMatch[1];
|
||
if(lookaheadMatch[3]) {
|
||
// Pretty bracketted link
|
||
var link = lookaheadMatch[3];
|
||
e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link)) ?
|
||
createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
|
||
} else {
|
||
// Simple bracketted link
|
||
e = createTiddlyLink(w.output,text,false,null,w.isStatic,w.tiddler);
|
||
}
|
||
createTiddlyText(e,text);
|
||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "wikiLink",
|
||
match: config.textPrimitives.unWikiLink+"?"+config.textPrimitives.wikiLink,
|
||
handler: function(w)
|
||
{
|
||
if(w.matchText.substr(0,1) == config.textPrimitives.unWikiLink) {
|
||
w.outputText(w.output,w.matchStart+1,w.nextMatch);
|
||
return;
|
||
}
|
||
if(w.matchStart > 0) {
|
||
var preRegExp = new RegExp(config.textPrimitives.anyLetterStrict,"mg");
|
||
preRegExp.lastIndex = w.matchStart-1;
|
||
var preMatch = preRegExp.exec(w.source);
|
||
if(preMatch.index == w.matchStart-1) {
|
||
w.outputText(w.output,w.matchStart,w.nextMatch);
|
||
return;
|
||
}
|
||
}
|
||
if(w.autoLinkWikiWords || store.isShadowTiddler(w.matchText)) {
|
||
var link = createTiddlyLink(w.output,w.matchText,false,null,w.isStatic,w.tiddler);
|
||
w.outputText(link,w.matchStart,w.nextMatch);
|
||
} else {
|
||
w.outputText(w.output,w.matchStart,w.nextMatch);
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "urlLink",
|
||
match: config.textPrimitives.urlPattern,
|
||
handler: function(w)
|
||
{
|
||
w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch);
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "image",
|
||
match: "\\[[<>]?[Ii][Mm][Gg]\\[",
|
||
lookaheadRegExp: /\[([<]?)(>?)[Ii][Mm][Gg]\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg,
|
||
handler: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
var e = w.output;
|
||
if(lookaheadMatch[5]) {
|
||
var link = lookaheadMatch[5];
|
||
e = config.formatterHelpers.isExternalLink(link) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
|
||
jQuery(e).addClass("imageLink");
|
||
}
|
||
var img = createTiddlyElement(e,"img");
|
||
if(lookaheadMatch[1])
|
||
img.align = "left";
|
||
else if(lookaheadMatch[2])
|
||
img.align = "right";
|
||
if(lookaheadMatch[3]) {
|
||
img.title = lookaheadMatch[3];
|
||
img.setAttribute("alt",lookaheadMatch[3]);
|
||
}
|
||
img.src = lookaheadMatch[4];
|
||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "html",
|
||
match: "<[Hh][Tt][Mm][Ll]>",
|
||
lookaheadRegExp: /<[Hh][Tt][Mm][Ll]>((?:.|\n)*?)<\/[Hh][Tt][Mm][Ll]>/mg,
|
||
handler: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1];
|
||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "commentByBlock",
|
||
match: "/%",
|
||
lookaheadRegExp: /\/%((?:.|\n)*?)%\//mg,
|
||
handler: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
|
||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "characterFormat",
|
||
match: "''|//|__|\\^\\^|~~|--(?!\\s|$)|\\{\\{\\{",
|
||
handler: function(w)
|
||
{
|
||
switch(w.matchText) {
|
||
case "''":
|
||
w.subWikifyTerm(w.output.appendChild(document.createElement("strong")),/('')/mg);
|
||
break;
|
||
case "//":
|
||
w.subWikifyTerm(createTiddlyElement(w.output,"em"),/(\/\/)/mg);
|
||
break;
|
||
case "__":
|
||
w.subWikifyTerm(createTiddlyElement(w.output,"u"),/(__)/mg);
|
||
break;
|
||
case "^^":
|
||
w.subWikifyTerm(createTiddlyElement(w.output,"sup"),/(\^\^)/mg);
|
||
break;
|
||
case "~~":
|
||
w.subWikifyTerm(createTiddlyElement(w.output,"sub"),/(~~)/mg);
|
||
break;
|
||
case "--":
|
||
w.subWikifyTerm(createTiddlyElement(w.output,"strike"),/(--)/mg);
|
||
break;
|
||
case "{{{":
|
||
var lookaheadRegExp = /\{\{\{((?:.|\n)*?)\}\}\}/mg;
|
||
lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
createTiddlyElement(w.output,"code",null,null,lookaheadMatch[1]);
|
||
w.nextMatch = lookaheadRegExp.lastIndex;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "customFormat",
|
||
match: "@@|\\{\\{",
|
||
handler: function(w)
|
||
{
|
||
switch(w.matchText) {
|
||
case "@@":
|
||
var e = createTiddlyElement(w.output,"span");
|
||
var styles = config.formatterHelpers.inlineCssHelper(w);
|
||
if(styles.length == 0)
|
||
e.className = "marked";
|
||
else
|
||
config.formatterHelpers.applyCssHelper(e,styles);
|
||
w.subWikifyTerm(e,/(@@)/mg);
|
||
break;
|
||
case "{{":
|
||
var lookaheadRegExp = /\{\{[\s]*([\w]+[\s\w]*)[\s]*\{(\n?)/mg;
|
||
lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch) {
|
||
w.nextMatch = lookaheadRegExp.lastIndex;
|
||
e = createTiddlyElement(w.output,lookaheadMatch[2] == "\n" ? "div" : "span",null,lookaheadMatch[1]);
|
||
w.subWikifyTerm(e,/(\}\}\})/mg);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "mdash",
|
||
match: "--",
|
||
handler: function(w)
|
||
{
|
||
createTiddlyElement(w.output,"span").innerHTML = "—";
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "lineBreak",
|
||
match: "\\n|<br ?/?>",
|
||
handler: function(w)
|
||
{
|
||
createTiddlyElement(w.output,"br");
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "rawText",
|
||
match: "\"{3}|<nowiki>",
|
||
lookaheadRegExp: /(?:\"{3}|<nowiki>)((?:.|\n)*?)(?:\"{3}|<\/nowiki>)/mg,
|
||
handler: function(w)
|
||
{
|
||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
createTiddlyElement(w.output,"span",null,null,lookaheadMatch[1]);
|
||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
name: "htmlEntitiesEncoding",
|
||
match: "(?:(?:&#?[a-zA-Z0-9]{2,8};|.)(?:&#?(?:x0*(?:3[0-6][0-9a-fA-F]|1D[c-fC-F][0-9a-fA-F]|20[d-fD-F][0-9a-fA-F]|FE2[0-9a-fA-F])|0*(?:76[89]|7[7-9][0-9]|8[0-7][0-9]|761[6-9]|76[2-7][0-9]|84[0-3][0-9]|844[0-7]|6505[6-9]|6506[0-9]|6507[0-1]));)+|&#?[a-zA-Z0-9]{2,8};)",
|
||
handler: function(w)
|
||
{
|
||
createTiddlyElement(w.output,"span").innerHTML = w.matchText;
|
||
}
|
||
}
|
||
|
||
];
|
||
|
||
//--
|
||
//-- Wikifier
|
||
//--
|
||
|
||
function getParser(tiddler,format)
|
||
{
|
||
if(tiddler) {
|
||
if(!format)
|
||
format = tiddler.fields["wikiformat"];
|
||
var i;
|
||
if(format) {
|
||
for(i in config.parsers) {
|
||
if(format == config.parsers[i].format)
|
||
return config.parsers[i];
|
||
}
|
||
} else {
|
||
for(i in config.parsers) {
|
||
if(tiddler.isTagged(config.parsers[i].formatTag))
|
||
return config.parsers[i];
|
||
}
|
||
}
|
||
}
|
||
return formatter;
|
||
}
|
||
|
||
function Wikifier(source,formatter,highlightRegExp,tiddler)
|
||
{
|
||
this.source = source;
|
||
this.output = null;
|
||
this.formatter = formatter;
|
||
this.nextMatch = 0;
|
||
this.autoLinkWikiWords = tiddler && tiddler.autoLinkWikiWords() == false ? false : true;
|
||
this.highlightRegExp = highlightRegExp;
|
||
this.highlightMatch = null;
|
||
this.isStatic = false;
|
||
if(highlightRegExp) {
|
||
highlightRegExp.lastIndex = 0;
|
||
this.highlightMatch = highlightRegExp.exec(source);
|
||
}
|
||
this.tiddler = tiddler;
|
||
}
|
||
|
||
Wikifier.prototype.wikifyPlain = function()
|
||
{
|
||
var e = createTiddlyElement(document.body,"div");
|
||
e.style.display = "none";
|
||
this.subWikify(e);
|
||
var text = jQuery(e).text();
|
||
jQuery(e).remove();
|
||
return text;
|
||
};
|
||
|
||
Wikifier.prototype.subWikify = function(output,terminator)
|
||
{
|
||
try {
|
||
if(terminator)
|
||
this.subWikifyTerm(output,new RegExp("(" + terminator + ")","mg"));
|
||
else
|
||
this.subWikifyUnterm(output);
|
||
} catch(ex) {
|
||
showException(ex);
|
||
}
|
||
};
|
||
|
||
Wikifier.prototype.subWikifyUnterm = function(output)
|
||
{
|
||
var oldOutput = this.output;
|
||
this.output = output;
|
||
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
|
||
var formatterMatch = this.formatter.formatterRegExp.exec(this.source);
|
||
while(formatterMatch) {
|
||
// Output any text before the match
|
||
if(formatterMatch.index > this.nextMatch)
|
||
this.outputText(this.output,this.nextMatch,formatterMatch.index);
|
||
// Set the match parameters for the handler
|
||
this.matchStart = formatterMatch.index;
|
||
this.matchLength = formatterMatch[0].length;
|
||
this.matchText = formatterMatch[0];
|
||
this.nextMatch = this.formatter.formatterRegExp.lastIndex;
|
||
var t;
|
||
for(t=1; t<formatterMatch.length; t++) {
|
||
if(formatterMatch[t]) {
|
||
this.formatter.formatters[t-1].handler(this);
|
||
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
|
||
break;
|
||
}
|
||
}
|
||
formatterMatch = this.formatter.formatterRegExp.exec(this.source);
|
||
}
|
||
if(this.nextMatch < this.source.length) {
|
||
this.outputText(this.output,this.nextMatch,this.source.length);
|
||
this.nextMatch = this.source.length;
|
||
}
|
||
this.output = oldOutput;
|
||
};
|
||
|
||
Wikifier.prototype.subWikifyTerm = function(output,terminatorRegExp)
|
||
{
|
||
var oldOutput = this.output;
|
||
this.output = output;
|
||
terminatorRegExp.lastIndex = this.nextMatch;
|
||
var terminatorMatch = terminatorRegExp.exec(this.source);
|
||
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
|
||
var formatterMatch = this.formatter.formatterRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
|
||
while(terminatorMatch || formatterMatch) {
|
||
if(terminatorMatch && (!formatterMatch || terminatorMatch.index <= formatterMatch.index)) {
|
||
if(terminatorMatch.index > this.nextMatch)
|
||
this.outputText(this.output,this.nextMatch,terminatorMatch.index);
|
||
this.matchText = terminatorMatch[1];
|
||
this.matchLength = terminatorMatch[1].length;
|
||
this.matchStart = terminatorMatch.index;
|
||
this.nextMatch = this.matchStart + this.matchLength;
|
||
this.output = oldOutput;
|
||
return;
|
||
}
|
||
if(formatterMatch.index > this.nextMatch)
|
||
this.outputText(this.output,this.nextMatch,formatterMatch.index);
|
||
this.matchStart = formatterMatch.index;
|
||
this.matchLength = formatterMatch[0].length;
|
||
this.matchText = formatterMatch[0];
|
||
this.nextMatch = this.formatter.formatterRegExp.lastIndex;
|
||
var t;
|
||
for(t=1; t<formatterMatch.length; t++) {
|
||
if(formatterMatch[t]) {
|
||
this.formatter.formatters[t-1].handler(this);
|
||
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
|
||
break;
|
||
}
|
||
}
|
||
terminatorRegExp.lastIndex = this.nextMatch;
|
||
terminatorMatch = terminatorRegExp.exec(this.source);
|
||
formatterMatch = this.formatter.formatterRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
|
||
}
|
||
if(this.nextMatch < this.source.length) {
|
||
this.outputText(this.output,this.nextMatch,this.source.length);
|
||
this.nextMatch = this.source.length;
|
||
}
|
||
this.output = oldOutput;
|
||
};
|
||
|
||
Wikifier.prototype.outputText = function(place,startPos,endPos)
|
||
{
|
||
while(this.highlightMatch && (this.highlightRegExp.lastIndex > startPos) && (this.highlightMatch.index < endPos) && (startPos < endPos)) {
|
||
if(this.highlightMatch.index > startPos) {
|
||
createTiddlyText(place,this.source.substring(startPos,this.highlightMatch.index));
|
||
startPos = this.highlightMatch.index;
|
||
}
|
||
var highlightEnd = Math.min(this.highlightRegExp.lastIndex,endPos);
|
||
createTiddlyElement(place,"span",null,"highlight",this.source.substring(startPos,highlightEnd));
|
||
startPos = highlightEnd;
|
||
if(startPos >= this.highlightRegExp.lastIndex)
|
||
this.highlightMatch = this.highlightRegExp.exec(this.source);
|
||
}
|
||
if(startPos < endPos) {
|
||
createTiddlyText(place,this.source.substring(startPos,endPos));
|
||
}
|
||
};
|
||
|
||
function wikify(source,output,highlightRegExp,tiddler)
|
||
{
|
||
if(source) {
|
||
var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
|
||
var t0 = new Date();
|
||
wikifier.subWikify(output);
|
||
if(tiddler && config.options.chkDisplayInstrumentation)
|
||
displayMessage("wikify:" +tiddler.title+ " in " + (new Date()-t0) + " ms");
|
||
}
|
||
}
|
||
|
||
function wikifyStatic(source,highlightRegExp,tiddler,format)
|
||
{
|
||
var e = createTiddlyElement(document.body,"pre");
|
||
e.style.display = "none";
|
||
var html = "";
|
||
if(source && source != "") {
|
||
if(!tiddler)
|
||
tiddler = new Tiddler("temp");
|
||
var wikifier = new Wikifier(source,getParser(tiddler,format),highlightRegExp,tiddler);
|
||
wikifier.isStatic = true;
|
||
wikifier.subWikify(e);
|
||
html = e.innerHTML;
|
||
jQuery(e).remove();
|
||
}
|
||
return html;
|
||
}
|
||
|
||
function wikifyPlainText(text,limit,tiddler)
|
||
{
|
||
if(limit > 0)
|
||
text = text.substr(0,limit);
|
||
var wikifier = new Wikifier(text,formatter,null,tiddler);
|
||
return wikifier.wikifyPlain();
|
||
}
|
||
|
||
function highlightify(source,output,highlightRegExp,tiddler)
|
||
{
|
||
if(source) {
|
||
var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler);
|
||
wikifier.outputText(output,0,source.length);
|
||
}
|
||
}
|
||
|
||
//--
|
||
//-- Macro definitions
|
||
//--
|
||
|
||
function invokeMacro(place,macro,params,wikifier,tiddler)
|
||
{
|
||
try {
|
||
var m = config.macros[macro];
|
||
if(m && m.handler) {
|
||
var tiddlerElem = story.findContainingTiddler(place);
|
||
window.tiddler = tiddlerElem ? store.getTiddler(tiddlerElem.getAttribute("tiddler")) : null;
|
||
window.place = place;
|
||
var allowEval = true;
|
||
if(config.evaluateMacroParameters=="system") {
|
||
if(!tiddler || tiddler.tags.indexOf("systemAllowEval") == -1) {
|
||
allowEval = false;
|
||
}
|
||
}
|
||
m.handler(place,macro,m.noPreParse?null:params.readMacroParams(!allowEval),wikifier,params,tiddler);
|
||
} else {
|
||
createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,config.messages.missingMacro]));
|
||
}
|
||
} catch(ex) {
|
||
createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,ex.toString()]));
|
||
}
|
||
}
|
||
|
||
config.macros.version.handler = function(place)
|
||
{
|
||
jQuery("<span/>").text(formatVersion()).appendTo(place);
|
||
};
|
||
|
||
config.macros.today.handler = function(place,macroName,params)
|
||
{
|
||
var now = new Date();
|
||
var text = params[0] ? now.formatString(params[0].trim()) : now.toLocaleString();
|
||
jQuery("<span/>").text(text).appendTo(place);
|
||
};
|
||
|
||
config.macros.list.template = "<<view title link>>";
|
||
config.macros.list.handler = function(place,macroName,params,wikifier,paramString)
|
||
{
|
||
var list = document.createElement("ul");
|
||
jQuery(list).attr({ refresh: "macro", macroName: macroName }).data("params", paramString);
|
||
place.appendChild(list);
|
||
this.refresh(list);
|
||
};
|
||
|
||
config.macros.list.refresh = function(list) {
|
||
var paramString = jQuery(list).data("params");
|
||
var params = paramString.readMacroParams();
|
||
var args = paramString.parseParams("anon", null, null)[0];
|
||
var type = args.anon ? args.anon[0] : "all";
|
||
jQuery(list).empty().addClass("list list-" + type);
|
||
var template = args.template ? store.getTiddlerText(args.template[0]) : false;
|
||
if(!template) {
|
||
template = config.macros.list.template;
|
||
}
|
||
if(this[type].prompt)
|
||
createTiddlyElement(list,"li",null,"listTitle",this[type].prompt);
|
||
var results;
|
||
if(this[type].handler)
|
||
results = this[type].handler(params);
|
||
var t;
|
||
for(t = 0; t < results.length; t++) {
|
||
var li = document.createElement("li");
|
||
list.appendChild(li);
|
||
var tiddler = results[t];
|
||
if(typeof(tiddler) == 'string') { // deal with missing etc..
|
||
tiddler = store.getTiddler(tiddler) || new Tiddler(tiddler);
|
||
}
|
||
wikify(template, li, null, tiddler);
|
||
}
|
||
if(results.length === 0 && args.emptyMessage) {
|
||
jQuery(list).addClass("emptyList");
|
||
jQuery("<li />").text(args.emptyMessage[0]).appendTo(list);
|
||
}
|
||
};
|
||
|
||
config.macros.list.all.handler = function(params)
|
||
{
|
||
return store.reverseLookup("tags","excludeLists",false,"title");
|
||
};
|
||
|
||
config.macros.list.missing.handler = function(params)
|
||
{
|
||
return store.getMissingLinks();
|
||
};
|
||
|
||
config.macros.list.orphans.handler = function(params)
|
||
{
|
||
return store.getOrphans();
|
||
};
|
||
|
||
config.macros.list.shadowed.handler = function(params)
|
||
{
|
||
return store.getShadowed();
|
||
};
|
||
|
||
config.macros.list.touched.handler = function(params)
|
||
{
|
||
return store.getTouched();
|
||
};
|
||
|
||
config.macros.list.filter.handler = function(params)
|
||
{
|
||
var filter = params[1];
|
||
var results = [];
|
||
if(filter) {
|
||
var tiddlers = store.filterTiddlers(filter);
|
||
var t;
|
||
for(t=0; t<tiddlers.length; t++)
|
||
results.push(tiddlers[t].title);
|
||
}
|
||
return results;
|
||
};
|
||
|
||
config.macros.allTags.handler = function(place,macroName,params)
|
||
{
|
||
var tags = store.getTags(params[0]);
|
||
var ul = createTiddlyElement(place,"ul");
|
||
if(tags.length == 0)
|
||
createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
|
||
var t;
|
||
for(t=0; t<tags.length; t++) {
|
||
var title = tags[t][0];
|
||
var info = getTiddlyLinkInfo(title);
|
||
var li = createTiddlyElement(ul,"li");
|
||
var btn = createTiddlyButton(li,title + " (" + tags[t][1] + ")",this.tooltip.format([title]),onClickTag,info.classes);
|
||
btn.setAttribute("tag",title);
|
||
btn.setAttribute("refresh","link");
|
||
btn.setAttribute("tiddlyLink",title);
|
||
if(params[1]) {
|
||
btn.setAttribute("sortby",params[1]);
|
||
}
|
||
}
|
||
};
|
||
|
||
var macro = config.macros.timeline;
|
||
merge(macro, {
|
||
handler: function(place,macroName,params, wikifier, paramString, tiddler) {
|
||
var container = jQuery("<div />").attr("params", paramString).
|
||
attr("macroName", macroName).appendTo(place)[0];
|
||
macro.refresh(container);
|
||
},
|
||
refresh: function(container) {
|
||
jQuery(container).attr("refresh", "macro").empty();
|
||
var paramString = jQuery(container).attr("params");
|
||
var args = paramString.parseParams("anon", null, null)[0];
|
||
var params = args.anon || [];
|
||
|
||
var field = params[0] || "modified";
|
||
var dateFormat = params[2] || this.dateFormat;
|
||
var groupTemplate = macro.groupTemplate.format(field, dateFormat);
|
||
groupTemplate = args.groupTemplate ? store.getTiddlerText(args.groupTemplate[0]) || groupTemplate :
|
||
groupTemplate;
|
||
|
||
var itemTemplate = macro.itemTemplate;
|
||
itemTemplate = args.template ? store.getTiddlerText(args.template[0]) || itemTemplate :
|
||
itemTemplate;
|
||
|
||
var tiddlers = args.filter ? store.sortTiddlers(store.filterTiddlers(args.filter[0]), field) :
|
||
store.reverseLookup("tags", "excludeLists", false, field);
|
||
var lastGroup = "", ul;
|
||
var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1],10)) : 0;
|
||
var t;
|
||
for(t=tiddlers.length-1; t>=last; t--) {
|
||
var tiddler = tiddlers[t];
|
||
var theGroup = wikifyPlainText(groupTemplate,0,tiddler);
|
||
if(typeof(ul) == "undefined" || theGroup != lastGroup) {
|
||
ul = document.createElement("ul");
|
||
jQuery(ul).addClass("timeline");
|
||
container.appendChild(ul);
|
||
createTiddlyElement(ul,"li",null,"listTitle",theGroup);
|
||
lastGroup = theGroup;
|
||
}
|
||
var item = createTiddlyElement(ul,"li",null,"listLink");
|
||
wikify(itemTemplate,item,null,tiddler);
|
||
}
|
||
},
|
||
groupTemplate: "<<view %0 date '%1'>>",
|
||
itemTemplate: "<<view title link>>"
|
||
});
|
||
|
||
config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
var allowEval = true;
|
||
var stack = config.macros.tiddler.tiddlerStack;
|
||
if(stack.length > 0 && config.evaluateMacroParameters == "system") {
|
||
// included tiddler and "system" evaluation required, so check tiddler tagged appropriately
|
||
var title = stack[stack.length-1];
|
||
var pos = title.indexOf(config.textPrimitives.sectionSeparator);
|
||
if(pos != -1) {
|
||
title = title.substr(0,pos); // get the base tiddler title
|
||
}
|
||
var t = store.getTiddler(title);
|
||
if(!t || t.tags.indexOf("systemAllowEval") == -1) {
|
||
allowEval = false;
|
||
}
|
||
}
|
||
params = paramString.parseParams("name",null,allowEval,false,true);
|
||
var names = params[0]["name"];
|
||
var tiddlerName = names[0];
|
||
var className = names[1] || null;
|
||
var args = params[0]["with"];
|
||
var wrapper = createTiddlyElement(place,"span",null,className,null,{
|
||
refresh: "content", tiddler: tiddlerName
|
||
});
|
||
if(args!==undefined)
|
||
wrapper.setAttribute("args","[["+args.join("]] [[")+"]]");
|
||
this.transclude(wrapper,tiddlerName,args);
|
||
};
|
||
|
||
config.macros.tiddler.transclude = function(wrapper,tiddlerName,args)
|
||
{
|
||
var text = store.getTiddlerText(tiddlerName);
|
||
if(!text)
|
||
return;
|
||
var stack = config.macros.tiddler.tiddlerStack;
|
||
if(stack.indexOf(tiddlerName) !== -1)
|
||
return;
|
||
stack.push(tiddlerName);
|
||
try {
|
||
if(typeof args == "string")
|
||
args = args.readBracketedList();
|
||
var n = args ? Math.min(args.length,9) : 0;
|
||
var i;
|
||
for(i=0; i<n; i++) {
|
||
var placeholderRE = new RegExp("\\$" + (i + 1),"mg");
|
||
text = text.replace(placeholderRE,args[i]);
|
||
}
|
||
config.macros.tiddler.renderText(wrapper,text,tiddlerName);
|
||
} finally {
|
||
stack.pop();
|
||
}
|
||
};
|
||
|
||
config.macros.tiddler.renderText = function(place,text,tiddlerName)
|
||
{
|
||
wikify(text,place,null,store.getTiddler(tiddlerName));
|
||
};
|
||
|
||
config.macros.tiddler.tiddlerStack = [];
|
||
|
||
config.macros.tag.handler = function(place,macroName,params)
|
||
{
|
||
var btn = createTagButton(place,params[0],null,params[1],params[2]);
|
||
if(params[3]) {
|
||
btn.setAttribute('sortby',params[3]);
|
||
}
|
||
};
|
||
|
||
config.macros.tags.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
params = paramString.parseParams("anon",null,true,false,false);
|
||
var ul = createTiddlyElement(place,"ul");
|
||
var title = getParam(params,"anon","");
|
||
if(title && store.tiddlerExists(title))
|
||
tiddler = store.getTiddler(title);
|
||
var sep = getParam(params,"sep"," ");
|
||
var lingo = config.views.wikified.tag;
|
||
var label = null;
|
||
var t;
|
||
for(t=0; t<tiddler.tags.length; t++) {
|
||
var tag = store.getTiddler(tiddler.tags[t]);
|
||
if(!tag || !tag.tags.contains("excludeLists")) {
|
||
if(!label)
|
||
label = createTiddlyElement(ul,"li",null,"listTitle",lingo.labelTags.format([tiddler.title]));
|
||
createTagButton(createTiddlyElement(ul,"li"),tiddler.tags[t],tiddler.title);
|
||
if(t<tiddler.tags.length-1)
|
||
createTiddlyText(ul,sep);
|
||
}
|
||
}
|
||
if(!label)
|
||
createTiddlyElement(ul,"li",null,"listTitle",lingo.labelNoTags.format([tiddler.title]));
|
||
};
|
||
|
||
config.macros.tagging.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
params = paramString.parseParams("anon",null,true,false,false);
|
||
var ul = createTiddlyElement(place,"ul");
|
||
var title = getParam(params,"anon","");
|
||
if(title == "" && tiddler instanceof Tiddler)
|
||
title = tiddler.title;
|
||
var sep = getParam(params,"sep"," ");
|
||
ul.setAttribute("title",this.tooltip.format([title]));
|
||
var sortby = getParam(params,"sortBy",false);
|
||
var tagged = store.getTaggedTiddlers(title,sortby);
|
||
var prompt = tagged.length == 0 ? this.labelNotTag : this.label;
|
||
createTiddlyElement(ul,"li",null,"listTitle",prompt.format([title,tagged.length]));
|
||
var t;
|
||
for(t=0; t<tagged.length; t++) {
|
||
createTiddlyLink(createTiddlyElement(ul,"li"),tagged[t].title,true);
|
||
if(t<tagged.length-1)
|
||
createTiddlyText(ul,sep);
|
||
}
|
||
};
|
||
|
||
config.macros.closeAll.handler = function(place)
|
||
{
|
||
createTiddlyButton(place,this.label,this.prompt,this.onClick);
|
||
};
|
||
|
||
config.macros.closeAll.onClick = function(e)
|
||
{
|
||
story.closeAllTiddlers();
|
||
return false;
|
||
};
|
||
|
||
config.macros.permaview.handler = function(place)
|
||
{
|
||
createTiddlyButton(place,this.label,this.prompt,this.onClick);
|
||
};
|
||
|
||
config.macros.permaview.onClick = function(e)
|
||
{
|
||
story.permaView();
|
||
return false;
|
||
};
|
||
|
||
config.macros.saveChanges.handler = function(place,macroName,params)
|
||
{
|
||
if(!readOnly)
|
||
createTiddlyButton(place,params[0] || this.label,params[1] || this.prompt,this.onClick,null,null,this.accessKey);
|
||
};
|
||
|
||
config.macros.saveChanges.onClick = function(e)
|
||
{
|
||
saveChanges();
|
||
return false;
|
||
};
|
||
|
||
config.macros.slider.onClickSlider = function(ev)
|
||
{
|
||
var n = this.nextSibling;
|
||
var cookie = n.getAttribute("cookie");
|
||
var isOpen = n.style.display != "none";
|
||
if(config.options.chkAnimate && anim && typeof Slider == "function")
|
||
anim.startAnimating(new Slider(n,!isOpen,null,"none"));
|
||
else
|
||
n.style.display = isOpen ? "none" : "block";
|
||
config.options[cookie] = !isOpen;
|
||
saveOption(cookie);
|
||
return false;
|
||
};
|
||
|
||
config.macros.slider.createSlider = function(place,cookie,title,tooltip)
|
||
{
|
||
var c = cookie || "";
|
||
createTiddlyButton(place,title,tooltip,this.onClickSlider);
|
||
var panel = createTiddlyElement(null,"div",null,"sliderPanel");
|
||
panel.setAttribute("cookie",c);
|
||
panel.style.display = config.options[c] ? "block" : "none";
|
||
place.appendChild(panel);
|
||
return panel;
|
||
};
|
||
|
||
config.macros.slider.handler = function(place,macroName,params)
|
||
{
|
||
var panel = this.createSlider(place,params[0],params[2],params[3]);
|
||
var text = store.getTiddlerText(params[1]);
|
||
panel.setAttribute("refresh","content");
|
||
panel.setAttribute("tiddler",params[1]);
|
||
if(text)
|
||
wikify(text,panel,null,store.getTiddler(params[1]));
|
||
};
|
||
|
||
// <<gradient [[tiddler name]] vert|horiz rgb rgb rgb rgb... >>
|
||
config.macros.gradient.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
var panel = wikifier ? createTiddlyElement(place,"div",null,"gradient") : place;
|
||
panel.style.position = "relative";
|
||
panel.style.overflow = "hidden";
|
||
panel.style.zIndex = "0";
|
||
if(wikifier) {
|
||
var styles = config.formatterHelpers.inlineCssHelper(wikifier);
|
||
config.formatterHelpers.applyCssHelper(panel,styles);
|
||
}
|
||
params = paramString.parseParams("color");
|
||
var locolors = [], hicolors = [];
|
||
var t;
|
||
for(t=2; t<params.length; t++) {
|
||
var c = params[t].value;
|
||
if(params[t].name == "snap") {
|
||
hicolors[hicolors.length-1] = c;
|
||
} else {
|
||
locolors.push(c);
|
||
hicolors.push(c);
|
||
}
|
||
}
|
||
drawGradient(panel,params[1].value != "vert",locolors,hicolors);
|
||
if(wikifier)
|
||
wikifier.subWikify(panel,">>");
|
||
if(document.all) {
|
||
panel.style.height = "100%";
|
||
panel.style.width = "100%";
|
||
}
|
||
};
|
||
|
||
config.macros.message.handler = function(place,macroName,params)
|
||
{
|
||
if(params[0]) {
|
||
var names = params[0].split(".");
|
||
var lookupMessage = function(root,nameIndex) {
|
||
if(root[names[nameIndex]]) {
|
||
if(nameIndex < names.length-1)
|
||
return (lookupMessage(root[names[nameIndex]],nameIndex+1));
|
||
else
|
||
return root[names[nameIndex]];
|
||
} else
|
||
return null;
|
||
};
|
||
var m = lookupMessage(config,0);
|
||
if(m == null)
|
||
m = lookupMessage(window,0);
|
||
createTiddlyText(place,m.toString().format(params.splice(1)));
|
||
}
|
||
};
|
||
|
||
|
||
config.macros.view.depth = 0;
|
||
config.macros.view.values = [];
|
||
config.macros.view.views = {
|
||
text: function(value,place,params,wikifier,paramString,tiddler) {
|
||
highlightify(value,place,highlightHack,tiddler);
|
||
},
|
||
link: function(value,place,params,wikifier,paramString,tiddler) {
|
||
createTiddlyLink(place,value,true);
|
||
},
|
||
wikified: function(value,place,params,wikifier,paramString,tiddler) {
|
||
if(config.macros.view.depth>50)
|
||
return;
|
||
if(config.macros.view.depth>0) {
|
||
if (value==config.macros.view.values[config.macros.view.depth-1]) {
|
||
return;
|
||
}
|
||
}
|
||
config.macros.view.values[config.macros.view.depth] = value;
|
||
config.macros.view.depth++;
|
||
if(params[2])
|
||
value=params[2].unescapeLineBreaks().format([value]);
|
||
wikify(value,place,highlightHack,tiddler);
|
||
config.macros.view.depth--;
|
||
config.macros.view.values[config.macros.view.depth] = null;
|
||
},
|
||
date: function(value,place,params,wikifier,paramString,tiddler) {
|
||
value = Date.convertFromYYYYMMDDHHMM(value);
|
||
createTiddlyText(place,value.formatString(params[2] || config.views.wikified.dateFormat));
|
||
}
|
||
};
|
||
|
||
config.macros.view.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
if((tiddler instanceof Tiddler) && params[0]) {
|
||
var value = store.getValue(tiddler,params[0]);
|
||
if(value) {
|
||
var type = params[1] || config.macros.view.defaultView;
|
||
var handler = config.macros.view.views[type];
|
||
if(handler)
|
||
handler(value,place,params,wikifier,paramString,tiddler);
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
var field = params[0];
|
||
var rows = params[1] || 0;
|
||
var defVal = params[2] || '';
|
||
if((tiddler instanceof Tiddler) && field) {
|
||
story.setDirty(tiddler.title,true);
|
||
var e,v;
|
||
if(field != "text" && !rows) {
|
||
e = createTiddlyElement(null,"input",null,null,null,{
|
||
type: "text", edit: field, size: "40", autocomplete: "off"
|
||
});
|
||
e.value = store.getValue(tiddler,field) || defVal;
|
||
place.appendChild(e);
|
||
} else {
|
||
var wrapper1 = createTiddlyElement(null,"fieldset",null,"fieldsetFix");
|
||
var wrapper2 = createTiddlyElement(wrapper1,"div");
|
||
e = createTiddlyElement(wrapper2,"textarea");
|
||
e.value = v = store.getValue(tiddler,field) || defVal;
|
||
rows = rows || 10;
|
||
var lines = v.match(/\n/mg);
|
||
var maxLines = Math.max(parseInt(config.options.txtMaxEditRows,10),5);
|
||
if(lines != null && lines.length > rows)
|
||
rows = lines.length + 5;
|
||
rows = Math.min(rows,maxLines);
|
||
e.setAttribute("rows",rows);
|
||
e.setAttribute("edit",field);
|
||
place.appendChild(wrapper1);
|
||
}
|
||
if(tiddler.isReadOnly()) {
|
||
e.setAttribute("readOnly","readOnly");
|
||
jQuery(e).addClass("readOnly");
|
||
}
|
||
return e;
|
||
}
|
||
};
|
||
|
||
config.macros.tagChooser.onClick = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
var lingo = config.views.editor.tagChooser;
|
||
var popup = Popup.create(this);
|
||
var tags = store.getTags(this.getAttribute("tags"));
|
||
if(tags.length == 0)
|
||
jQuery("<li/>").text(lingo.popupNone).appendTo(popup);
|
||
var t;
|
||
for(t=0; t<tags.length; t++) {
|
||
var tag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),config.macros.tagChooser.onTagClick);
|
||
tag.setAttribute("tag",tags[t][0]);
|
||
tag.setAttribute("tiddler",this.getAttribute("tiddler"));
|
||
}
|
||
Popup.show();
|
||
e.cancelBubble = true;
|
||
if(e.stopPropagation) e.stopPropagation();
|
||
return false;
|
||
};
|
||
|
||
config.macros.tagChooser.onTagClick = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
if(e.metaKey || e.ctrlKey) stopEvent(e); //# keep popup open on CTRL-click
|
||
var tag = this.getAttribute("tag");
|
||
var title = this.getAttribute("tiddler");
|
||
if(!readOnly)
|
||
story.setTiddlerTag(title,tag,0);
|
||
return false;
|
||
};
|
||
|
||
config.macros.tagChooser.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
if(tiddler instanceof Tiddler) {
|
||
var lingo = config.views.editor.tagChooser;
|
||
var btn = createTiddlyButton(place,lingo.text,lingo.tooltip,this.onClick);
|
||
btn.setAttribute("tiddler",tiddler.title);
|
||
btn.setAttribute("tags",params[0]);
|
||
}
|
||
};
|
||
|
||
config.macros.refreshDisplay.handler = function(place)
|
||
{
|
||
createTiddlyButton(place,this.label,this.prompt,this.onClick);
|
||
};
|
||
|
||
config.macros.refreshDisplay.onClick = function(e)
|
||
{
|
||
refreshAll();
|
||
return false;
|
||
};
|
||
|
||
config.macros.annotations.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
var title = tiddler ? tiddler.title : null;
|
||
var a = title ? config.annotations[title] : null;
|
||
if(!tiddler || !title || !a)
|
||
return;
|
||
var text = a.format([title]);
|
||
wikify(text,createTiddlyElement(place,"div",null,"annotation"),null,tiddler);
|
||
};
|
||
//--
|
||
//-- NewTiddler and NewJournal macros
|
||
//--
|
||
|
||
config.macros.newTiddler.createNewTiddlerButton = function(place,title,params,label,prompt,accessKey,newFocus,isJournal)
|
||
{
|
||
var tags = [];
|
||
var t;
|
||
for(t=1; t<params.length; t++) {
|
||
if((params[t].name == "anon" && t != 1) || (params[t].name == "tag"))
|
||
tags.push(params[t].value);
|
||
}
|
||
label = getParam(params,"label",label);
|
||
prompt = getParam(params,"prompt",prompt);
|
||
accessKey = getParam(params,"accessKey",accessKey);
|
||
newFocus = getParam(params,"focus",newFocus);
|
||
var customFields = getParam(params,"fields","");
|
||
if(!customFields && !store.isShadowTiddler(title))
|
||
customFields = String.encodeHashMap(config.defaultCustomFields);
|
||
var btn = createTiddlyButton(place,label,prompt,this.onClickNewTiddler,null,null,accessKey);
|
||
btn.setAttribute("newTitle",title);
|
||
btn.setAttribute("isJournal",isJournal ? "true" : "false");
|
||
if(tags.length > 0)
|
||
btn.setAttribute("params",tags.join("|"));
|
||
btn.setAttribute("newFocus",newFocus);
|
||
btn.setAttribute("newTemplate",getParam(params,"template",DEFAULT_EDIT_TEMPLATE));
|
||
if(customFields !== "")
|
||
btn.setAttribute("customFields",customFields);
|
||
var text = getParam(params,"text");
|
||
if(text !== undefined)
|
||
btn.setAttribute("newText",text);
|
||
return btn;
|
||
};
|
||
|
||
config.macros.newTiddler.onClickNewTiddler = function()
|
||
{
|
||
var title = this.getAttribute("newTitle");
|
||
if(this.getAttribute("isJournal") == "true") {
|
||
title = new Date().formatString(title.trim());
|
||
}
|
||
var params = this.getAttribute("params");
|
||
var tags = params ? params.split("|") : [];
|
||
var focus = this.getAttribute("newFocus");
|
||
var template = this.getAttribute("newTemplate");
|
||
var customFields = this.getAttribute("customFields");
|
||
if(!customFields && !store.isShadowTiddler(title))
|
||
customFields = String.encodeHashMap(config.defaultCustomFields);
|
||
story.displayTiddler(null,title,template,false,null,null);
|
||
var tiddlerElem = story.getTiddler(title);
|
||
if(customFields)
|
||
story.addCustomFields(tiddlerElem,customFields);
|
||
var text = this.getAttribute("newText");
|
||
if(typeof text == "string" && story.getTiddlerField(title,"text"))
|
||
story.getTiddlerField(title,"text").value = text.format([title]);
|
||
var t;
|
||
for(t=0;t<tags.length;t++)
|
||
story.setTiddlerTag(title,tags[t],+1);
|
||
story.focusTiddler(title,focus);
|
||
return false;
|
||
};
|
||
|
||
config.macros.newTiddler.handler = function(place,macroName,params,wikifier,paramString)
|
||
{
|
||
if(!readOnly) {
|
||
params = paramString.parseParams("anon",null,true,false,false);
|
||
var title = params[1] && params[1].name == "anon" ? params[1].value : this.title;
|
||
title = getParam(params,"title",title);
|
||
this.createNewTiddlerButton(place,title,params,this.label,this.prompt,this.accessKey,"title",false);
|
||
}
|
||
};
|
||
|
||
config.macros.newJournal.handler = function(place,macroName,params,wikifier,paramString)
|
||
{
|
||
if(!readOnly) {
|
||
params = paramString.parseParams("anon",null,true,false,false);
|
||
var title = params[1] && params[1].name == "anon" ? params[1].value : config.macros.timeline.dateFormat;
|
||
title = getParam(params,"title",title);
|
||
config.macros.newTiddler.createNewTiddlerButton(place,title,params,this.label,this.prompt,this.accessKey,"text",true);
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Search macro
|
||
//--
|
||
|
||
config.macros.search.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
params = paramString.parseParams("anon",null,false,false,false);
|
||
createTiddlyButton(place,this.label,this.prompt,this.onClick,"searchButton");
|
||
var txt = createTiddlyElement(null,"input",null,"txtOptionInput searchField");
|
||
txt.value = getParam(params,"anon","");
|
||
if(config.browser.isSafari) {
|
||
txt.setAttribute("type","search");
|
||
txt.setAttribute("results","5");
|
||
} else {
|
||
txt.setAttribute("type","text");
|
||
}
|
||
place.appendChild(txt);
|
||
txt.onkeyup = this.onKeyPress;
|
||
txt.onfocus = this.onFocus;
|
||
txt.setAttribute("size",this.sizeTextbox);
|
||
txt.setAttribute("accessKey",getParam(params,"accesskey",this.accessKey));
|
||
txt.setAttribute("autocomplete","off");
|
||
txt.setAttribute("lastSearchText","");
|
||
txt.setAttribute("placeholder",getParam(params,"placeholder",this.placeholder));
|
||
};
|
||
|
||
// Global because there's only ever one outstanding incremental search timer
|
||
config.macros.search.timeout = null;
|
||
|
||
config.macros.search.doSearch = function(txt)
|
||
{
|
||
if(txt.value.length > 0) {
|
||
story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);
|
||
txt.setAttribute("lastSearchText",txt.value);
|
||
}
|
||
};
|
||
|
||
config.macros.search.onClick = function(e)
|
||
{
|
||
config.macros.search.doSearch(this.nextSibling);
|
||
return false;
|
||
};
|
||
|
||
config.macros.search.onKeyPress = function(ev)
|
||
{
|
||
var me = config.macros.search;
|
||
var e = ev || window.event;
|
||
switch(e.keyCode) {
|
||
case 9: // Tab
|
||
return;
|
||
case 13: // Ctrl-Enter
|
||
case 10: // Ctrl-Enter on IE PC
|
||
me.doSearch(this);
|
||
break;
|
||
case 27: // Escape
|
||
this.value = "";
|
||
clearMessage();
|
||
break;
|
||
}
|
||
if(config.options.chkIncrementalSearch) {
|
||
if(this.value.length > 2) {
|
||
if(this.value != this.getAttribute("lastSearchText")) {
|
||
if(me.timeout) {
|
||
clearTimeout(me.timeout);
|
||
}
|
||
var txt = this;
|
||
me.timeout = setTimeout(function() {me.doSearch(txt);},500);
|
||
}
|
||
} else {
|
||
if(me.timeout) {
|
||
clearTimeout(me.timeout);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.search.onFocus = function(e)
|
||
{
|
||
this.select();
|
||
};
|
||
|
||
//--
|
||
//-- Tabs macro
|
||
//--
|
||
|
||
config.macros.tabs.handler = function(place,macroName,params)
|
||
{
|
||
var cookie = params[0];
|
||
var numTabs = (params.length-1)/3;
|
||
var wrapper = createTiddlyElement(null,"div",null,"tabsetWrapper " + cookie);
|
||
var tabset = createTiddlyElement(wrapper,"div",null,"tabset");
|
||
tabset.setAttribute("cookie",cookie);
|
||
var validTab = false;
|
||
var t;
|
||
for(t=0; t<numTabs; t++) {
|
||
var label = params[t*3+1];
|
||
var prompt = params[t*3+2];
|
||
var content = params[t*3+3];
|
||
var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,"tab tabUnselected");
|
||
createTiddlyElement(tab,"span",null,null," ",{style:"font-size:0pt;line-height:0px"});
|
||
tab.setAttribute("tab",label);
|
||
tab.setAttribute("content",content);
|
||
tab.title = prompt;
|
||
if(config.options[cookie] == label)
|
||
validTab = true;
|
||
}
|
||
if(!validTab)
|
||
config.options[cookie] = params[1];
|
||
place.appendChild(wrapper);
|
||
this.switchTab(tabset,config.options[cookie]);
|
||
};
|
||
|
||
config.macros.tabs.onClickTab = function(e)
|
||
{
|
||
config.macros.tabs.switchTab(this.parentNode,this.getAttribute("tab"));
|
||
return false;
|
||
};
|
||
|
||
config.macros.tabs.switchTab = function(tabset,tab)
|
||
{
|
||
var cookie = tabset.getAttribute("cookie");
|
||
var theTab = null;
|
||
var nodes = tabset.childNodes;
|
||
var t;
|
||
for(t=0; t<nodes.length; t++) {
|
||
if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab) {
|
||
theTab = nodes[t];
|
||
theTab.className = "tab tabSelected";
|
||
} else {
|
||
nodes[t].className = "tab tabUnselected";
|
||
}
|
||
}
|
||
if(theTab) {
|
||
if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
|
||
jQuery(tabset.nextSibling).remove();
|
||
var tabContent = createTiddlyElement(null,"div",null,"tabContents");
|
||
tabset.parentNode.insertBefore(tabContent,tabset.nextSibling);
|
||
var contentTitle = theTab.getAttribute("content");
|
||
wikify(store.getTiddlerText(contentTitle),tabContent,null,store.getTiddler(contentTitle));
|
||
if(cookie) {
|
||
config.options[cookie] = tab;
|
||
saveOption(cookie);
|
||
}
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Tiddler toolbar
|
||
//--
|
||
|
||
// Create a toolbar command button
|
||
config.macros.toolbar.createCommand = function(place,commandName,tiddler,className)
|
||
{
|
||
if(typeof commandName != "string") {
|
||
var c = null;
|
||
var t;
|
||
for(t in config.commands) {
|
||
if(config.commands[t] == commandName)
|
||
c = t;
|
||
}
|
||
commandName = c;
|
||
}
|
||
if((tiddler instanceof Tiddler) && (typeof commandName == "string")) {
|
||
var command = config.commands[commandName];
|
||
if(command.isEnabled ? command.isEnabled(tiddler) : this.isCommandEnabled(command,tiddler)) {
|
||
var text = command.getText ? command.getText(tiddler) : this.getCommandText(command,tiddler);
|
||
var tooltip = command.getTooltip ? command.getTooltip(tiddler) : this.getCommandTooltip(command,tiddler);
|
||
var cmd = command.type == "popup" ? this.onClickPopup : this.onClickCommand;
|
||
var btn = createTiddlyButton(null,text,tooltip,cmd);
|
||
btn.setAttribute("commandName",commandName);
|
||
btn.setAttribute("tiddler",tiddler.title);
|
||
jQuery(btn).addClass("command_" + commandName);
|
||
if(className)
|
||
jQuery(btn).addClass(className);
|
||
place.appendChild(btn);
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.toolbar.isCommandEnabled = function(command,tiddler)
|
||
{
|
||
var title = tiddler.title;
|
||
var ro = tiddler.isReadOnly();
|
||
var shadow = store.isShadowTiddler(title) && !store.tiddlerExists(title);
|
||
return (!ro || (ro && !command.hideReadOnly)) && !(shadow && command.hideShadow);
|
||
};
|
||
|
||
config.macros.toolbar.getCommandText = function(command,tiddler)
|
||
{
|
||
return (tiddler.isReadOnly() && command.readOnlyText) || command.text;
|
||
};
|
||
|
||
config.macros.toolbar.getCommandTooltip = function(command,tiddler)
|
||
{
|
||
return (tiddler.isReadOnly() && command.readOnlyTooltip) || command.tooltip;
|
||
};
|
||
|
||
config.macros.toolbar.onClickCommand = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
e.cancelBubble = true;
|
||
if(e.stopPropagation) e.stopPropagation();
|
||
var command = config.commands[this.getAttribute("commandName")];
|
||
return command.handler(e,this,this.getAttribute("tiddler"));
|
||
};
|
||
|
||
config.macros.toolbar.onClickPopup = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
e.cancelBubble = true;
|
||
if(e.stopPropagation) e.stopPropagation();
|
||
var popup = Popup.create(this);
|
||
var command = config.commands[this.getAttribute("commandName")];
|
||
var title = this.getAttribute("tiddler");
|
||
popup.setAttribute("tiddler",title);
|
||
command.handlePopup(popup,title);
|
||
Popup.show();
|
||
return false;
|
||
};
|
||
|
||
// Invoke the first command encountered from a given place that is tagged with a specified class
|
||
config.macros.toolbar.invokeCommand = function(place,className,event)
|
||
{
|
||
var children = place.getElementsByTagName("a");
|
||
var t;
|
||
for(t=0; t<children.length; t++) {
|
||
var c = children[t];
|
||
if(jQuery(c).hasClass(className) && c.getAttribute && c.getAttribute("commandName")) {
|
||
if(c.onclick instanceof Function)
|
||
c.onclick.call(c,event);
|
||
break;
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.toolbar.onClickMore = function(ev)
|
||
{
|
||
var e = this.nextSibling;
|
||
e.style.display = "inline";
|
||
this.style.display = "none";
|
||
return false;
|
||
};
|
||
|
||
config.macros.toolbar.onClickLess = function(ev)
|
||
{
|
||
var e = this.parentNode;
|
||
var m = e.previousSibling;
|
||
e.style.display = "none";
|
||
m.style.display = "inline";
|
||
return false;
|
||
};
|
||
|
||
config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
var t;
|
||
for(t=0; t<params.length; t++) {
|
||
var btn;
|
||
var c = params[t];
|
||
switch(c) {
|
||
case "!":
|
||
createTiddlyText(place,this.separator);
|
||
break;
|
||
case "*":
|
||
createTiddlyElement(place,"br");
|
||
break;
|
||
case "<":
|
||
btn = createTiddlyButton(place,this.lessLabel,this.lessPrompt,config.macros.toolbar.onClickLess);
|
||
jQuery(btn).addClass("lessCommand");
|
||
break;
|
||
case ">":
|
||
btn = createTiddlyButton(place,this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore);
|
||
jQuery(btn).addClass("moreCommand");
|
||
var e = createTiddlyElement(place,"span",null,"moreCommand");
|
||
e.style.display = "none";
|
||
place = e;
|
||
break;
|
||
default:
|
||
var className = "";
|
||
switch(c.substr(0,1)) {
|
||
case "+":
|
||
className = "defaultCommand";
|
||
c = c.substr(1);
|
||
break;
|
||
case "-":
|
||
className = "cancelCommand";
|
||
c = c.substr(1);
|
||
break;
|
||
}
|
||
if(config.commands[c]) {
|
||
this.createCommand(place,c,tiddler,className);
|
||
} else {
|
||
this.customCommand(place,c,wikifier,tiddler);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
};
|
||
|
||
// Overrideable function to extend toolbar handler
|
||
config.macros.toolbar.customCommand = function(place,command,wikifier,tiddler)
|
||
{
|
||
};
|
||
|
||
//--
|
||
//-- Menu and toolbar commands
|
||
//--
|
||
|
||
config.commands.closeTiddler.handler = function(event,src,title)
|
||
{
|
||
if(story.isDirty(title) && !readOnly) {
|
||
if(!confirm(config.commands.cancelTiddler.warning.format([title])))
|
||
return false;
|
||
}
|
||
story.setDirty(title,false);
|
||
story.closeTiddler(title,true);
|
||
return false;
|
||
};
|
||
|
||
config.commands.closeOthers.handler = function(event,src,title)
|
||
{
|
||
story.closeAllTiddlers(title);
|
||
return false;
|
||
};
|
||
|
||
config.commands.editTiddler.handler = function(event,src,title)
|
||
{
|
||
clearMessage();
|
||
var tiddlerElem = story.getTiddler(title);
|
||
var fields = tiddlerElem.getAttribute("tiddlyFields");
|
||
story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE,false,null,fields);
|
||
var e = story.getTiddlerField(title,config.options.txtEditorFocus||"text");
|
||
if(e) {
|
||
setCaretPosition(e,0);
|
||
}
|
||
return false;
|
||
};
|
||
|
||
config.commands.saveTiddler.handler = function(event,src,title)
|
||
{
|
||
var newTitle = story.saveTiddler(title,event.shiftKey);
|
||
if(newTitle)
|
||
story.displayTiddler(null,newTitle);
|
||
return false;
|
||
};
|
||
|
||
config.commands.cancelTiddler.handler = function(event,src,title)
|
||
{
|
||
if(story.hasChanges(title) && !readOnly) {
|
||
if(!confirm(this.warning.format([title])))
|
||
return false;
|
||
}
|
||
story.setDirty(title,false);
|
||
story.displayTiddler(null,title);
|
||
return false;
|
||
};
|
||
|
||
config.commands.deleteTiddler.handler = function(event,src,title)
|
||
{
|
||
var deleteIt = true;
|
||
if(config.options.chkConfirmDelete)
|
||
deleteIt = confirm(this.warning.format([title]));
|
||
if(deleteIt) {
|
||
store.removeTiddler(title);
|
||
story.closeTiddler(title,true);
|
||
autoSaveChanges();
|
||
}
|
||
return false;
|
||
};
|
||
|
||
config.commands.permalink.handler = function(event,src,title)
|
||
{
|
||
var t = encodeURIComponent(String.encodeTiddlyLink(title));
|
||
if(window.location.hash != t)
|
||
window.location.hash = t;
|
||
return false;
|
||
};
|
||
|
||
config.commands.references.handlePopup = function(popup,title)
|
||
{
|
||
var references = store.getReferringTiddlers(title);
|
||
var c = false;
|
||
var r;
|
||
for(r=0; r<references.length; r++) {
|
||
if(references[r].title != title && !references[r].isTagged("excludeLists")) {
|
||
createTiddlyLink(createTiddlyElement(popup,"li"),references[r].title,true);
|
||
c = true;
|
||
}
|
||
}
|
||
if(!c)
|
||
createTiddlyElement(popup,"li",null,"disabled",this.popupNone);
|
||
};
|
||
|
||
config.commands.jump.handlePopup = function(popup,title)
|
||
{
|
||
story.forEachTiddler(function(title,element) {
|
||
createTiddlyLink(createTiddlyElement(popup,"li"),title,true,null,false,null,true);
|
||
});
|
||
};
|
||
|
||
config.commands.syncing.handlePopup = function(popup,title)
|
||
{
|
||
var me = config.commands.syncing;
|
||
var tiddler = store.fetchTiddler(title);
|
||
if(!tiddler)
|
||
return;
|
||
var serverType = tiddler.getServerType();
|
||
var serverHost = tiddler.fields["server.host"];
|
||
var serverWorkspace = tiddler.fields["server.workspace"];
|
||
if(!serverWorkspace)
|
||
serverWorkspace = "";
|
||
if(serverType) {
|
||
var e = createTiddlyElement(popup,"li",null,"popupMessage");
|
||
e.innerHTML = me.currentlySyncing.format([serverType,serverHost,serverWorkspace]);
|
||
} else {
|
||
createTiddlyElement(popup,"li",null,"popupMessage",me.notCurrentlySyncing);
|
||
}
|
||
if(serverType) {
|
||
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
|
||
var btn = createTiddlyButton(createTiddlyElement(popup,"li"),this.captionUnSync,null,me.onChooseServer);
|
||
btn.setAttribute("tiddler",title);
|
||
btn.setAttribute("server.type","");
|
||
}
|
||
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
|
||
createTiddlyElement(popup,"li",null,"popupMessage",me.chooseServer);
|
||
var feeds = store.getTaggedTiddlers("systemServer","title");
|
||
var t;
|
||
for(t=0; t<feeds.length; t++) {
|
||
var f = feeds[t];
|
||
var feedServerType = store.getTiddlerSlice(f.title,"Type");
|
||
if(!feedServerType)
|
||
feedServerType = "file";
|
||
var feedServerHost = store.getTiddlerSlice(f.title,"URL");
|
||
if(!feedServerHost)
|
||
feedServerHost = "";
|
||
var feedServerWorkspace = store.getTiddlerSlice(f.title,"Workspace");
|
||
if(!feedServerWorkspace)
|
||
feedServerWorkspace = "";
|
||
var caption = f.title;
|
||
if(serverType == feedServerType && serverHost == feedServerHost && serverWorkspace == feedServerWorkspace) {
|
||
caption = me.currServerMarker + caption;
|
||
} else {
|
||
caption = me.notCurrServerMarker + caption;
|
||
}
|
||
btn = createTiddlyButton(createTiddlyElement(popup,"li"),caption,null,me.onChooseServer);
|
||
btn.setAttribute("tiddler",title);
|
||
btn.setAttribute("server.type",feedServerType);
|
||
btn.setAttribute("server.host",feedServerHost);
|
||
btn.setAttribute("server.workspace",feedServerWorkspace);
|
||
}
|
||
};
|
||
|
||
config.commands.syncing.onChooseServer = function(e)
|
||
{
|
||
var tiddler = this.getAttribute("tiddler");
|
||
var serverType = this.getAttribute("server.type");
|
||
if(serverType) {
|
||
store.addTiddlerFields(tiddler,{
|
||
"server.type": serverType,
|
||
"server.host": this.getAttribute("server.host"),
|
||
"server.workspace": this.getAttribute("server.workspace")
|
||
});
|
||
} else {
|
||
store.setValue(tiddler,"server",null);
|
||
}
|
||
return false;
|
||
};
|
||
|
||
config.commands.fields.handlePopup = function(popup,title)
|
||
{
|
||
var tiddler = store.fetchTiddler(title);
|
||
if(!tiddler)
|
||
return;
|
||
var items = [];
|
||
store.forEachField(tiddler,function(tiddler,fieldName,value){items.push({field:fieldName,value:value});},true);
|
||
items.sort(function(a,b) {return a.field < b.field ? -1 : (a.field == b.field ? 0 : +1);});
|
||
if(items.length > 0)
|
||
ListView.create(popup,items,this.listViewTemplate);
|
||
else
|
||
createTiddlyElement(popup,"div",null,null,this.emptyText);
|
||
};
|
||
|
||
//--
|
||
//-- Tiddler() object
|
||
//--
|
||
|
||
function Tiddler(title)
|
||
{
|
||
this.title = title;
|
||
this.text = "";
|
||
this.creator = null;
|
||
this.modifier = null;
|
||
this.created = new Date();
|
||
this.modified = this.created;
|
||
this.links = [];
|
||
this.linksUpdated = false;
|
||
this.tags = [];
|
||
this.fields = {};
|
||
return this;
|
||
}
|
||
|
||
Tiddler.prototype.getLinks = function()
|
||
{
|
||
if(this.linksUpdated==false)
|
||
this.changed();
|
||
return this.links;
|
||
};
|
||
|
||
// Returns the fields that are inherited in string field:"value" field2:"value2" format
|
||
Tiddler.prototype.getInheritedFields = function()
|
||
{
|
||
var f = {};
|
||
var i;
|
||
for(i in this.fields) {
|
||
if(i=="server.host" || i=="server.workspace" || i=="wikiformat"|| i=="server.type") {
|
||
f[i] = this.fields[i];
|
||
}
|
||
}
|
||
return String.encodeHashMap(f);
|
||
};
|
||
|
||
// Increment the changeCount of a tiddler
|
||
Tiddler.prototype.incChangeCount = function()
|
||
{
|
||
var c = this.fields['changecount'];
|
||
c = c ? parseInt(c,10) : 0;
|
||
this.fields['changecount'] = String(c+1);
|
||
};
|
||
|
||
// Clear the changeCount of a tiddler
|
||
Tiddler.prototype.clearChangeCount = function()
|
||
{
|
||
if(this.fields['changecount']) {
|
||
delete this.fields['changecount'];
|
||
}
|
||
};
|
||
|
||
Tiddler.prototype.doNotSave = function()
|
||
{
|
||
return this.fields['doNotSave'];
|
||
};
|
||
|
||
// Returns true if the tiddler has been updated since the tiddler was created or downloaded
|
||
Tiddler.prototype.isTouched = function()
|
||
{
|
||
var changecount = this.fields.changecount || 0;
|
||
return changecount > 0;
|
||
};
|
||
|
||
// Change the text and other attributes of a tiddler
|
||
Tiddler.prototype.set = function(title,text,modifier,modified,tags,created,fields,creator)
|
||
{
|
||
this.assign(title,text,modifier,modified,tags,created,fields,creator);
|
||
this.changed();
|
||
return this;
|
||
};
|
||
|
||
// Change the text and other attributes of a tiddler without triggered a tiddler.changed() call
|
||
Tiddler.prototype.assign = function(title,text,modifier,modified,tags,created,fields,creator)
|
||
{
|
||
if(title != undefined)
|
||
this.title = title;
|
||
if(text != undefined)
|
||
this.text = text;
|
||
if(modifier != undefined)
|
||
this.modifier = modifier;
|
||
if(modified != undefined)
|
||
this.modified = modified;
|
||
if(creator != undefined)
|
||
this.creator = creator;
|
||
if(created != undefined)
|
||
this.created = created;
|
||
if(fields != undefined)
|
||
this.fields = fields;
|
||
if(tags != undefined)
|
||
this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags;
|
||
else if(this.tags == undefined)
|
||
this.tags = [];
|
||
return this;
|
||
};
|
||
|
||
// Get the tags for a tiddler as a string (space delimited, using [[brackets]] for tags containing spaces)
|
||
Tiddler.prototype.getTags = function()
|
||
{
|
||
return String.encodeTiddlyLinkList(this.tags);
|
||
};
|
||
|
||
// Test if a tiddler carries a tag
|
||
Tiddler.prototype.isTagged = function(tag)
|
||
{
|
||
return this.tags.indexOf(tag) != -1;
|
||
};
|
||
|
||
// Static method to convert "\n" to newlines, "\s" to "\"
|
||
Tiddler.unescapeLineBreaks = function(text)
|
||
{
|
||
return text ? text.unescapeLineBreaks() : "";
|
||
};
|
||
|
||
// Convert newlines to "\n", "\" to "\s"
|
||
Tiddler.prototype.escapeLineBreaks = function()
|
||
{
|
||
return this.text.escapeLineBreaks();
|
||
};
|
||
|
||
// Updates the secondary information (like links[] array) after a change to a tiddler
|
||
Tiddler.prototype.changed = function()
|
||
{
|
||
this.links = [];
|
||
var text = this.text;
|
||
// remove 'quoted' text before scanning tiddler source
|
||
text = text.replace(/\/%((?:.|\n)*?)%\//g,"").
|
||
replace(/\{{3}((?:.|\n)*?)\}{3}/g,"").
|
||
replace(/"""((?:.|\n)*?)"""/g,"").
|
||
replace(/<nowiki\>((?:.|\n)*?)<\/nowiki\>/g,"").
|
||
replace(/<html\>((?:.|\n)*?)<\/html\>/g,"").
|
||
replace(/<script((?:.|\n)*?)<\/script\>/g,"");
|
||
var t = this.autoLinkWikiWords() ? 0 : 1;
|
||
var tiddlerLinkRegExp = t==0 ? config.textPrimitives.tiddlerAnyLinkRegExp : config.textPrimitives.tiddlerForcedLinkRegExp;
|
||
tiddlerLinkRegExp.lastIndex = 0;
|
||
var formatMatch = tiddlerLinkRegExp.exec(text);
|
||
while(formatMatch) {
|
||
var lastIndex = tiddlerLinkRegExp.lastIndex;
|
||
if(t==0 && formatMatch[1] && formatMatch[1] != this.title) {
|
||
// wikiWordLink
|
||
if(formatMatch.index > 0) {
|
||
var preRegExp = new RegExp(config.textPrimitives.unWikiLink+"|"+config.textPrimitives.anyLetter,"mg");
|
||
preRegExp.lastIndex = formatMatch.index-1;
|
||
var preMatch = preRegExp.exec(text);
|
||
if(preMatch.index != formatMatch.index-1)
|
||
this.links.pushUnique(formatMatch[1]);
|
||
} else {
|
||
this.links.pushUnique(formatMatch[1]);
|
||
}
|
||
}
|
||
else if(formatMatch[2-t] && !config.formatterHelpers.isExternalLink(formatMatch[3-t])) // titledBrackettedLink
|
||
this.links.pushUnique(formatMatch[3-t]);
|
||
else if(formatMatch[4-t] && formatMatch[4-t] != this.title) // brackettedLink
|
||
this.links.pushUnique(formatMatch[4-t]);
|
||
tiddlerLinkRegExp.lastIndex = lastIndex;
|
||
formatMatch = tiddlerLinkRegExp.exec(text);
|
||
}
|
||
this.linksUpdated = true;
|
||
};
|
||
|
||
Tiddler.prototype.getSubtitle = function()
|
||
{
|
||
var modifier = this.modifier;
|
||
if(!modifier)
|
||
modifier = config.messages.subtitleUnknown || "";
|
||
var modified = this.modified;
|
||
if(modified)
|
||
modified = modified.toLocaleString();
|
||
else
|
||
modified = config.messages.subtitleUnknown || "";
|
||
var f = config.messages.tiddlerLinkTooltip || "%0 - %1, %2";
|
||
return f.format([this.title,modifier,modified]);
|
||
};
|
||
|
||
Tiddler.prototype.isReadOnly = function()
|
||
{
|
||
return readOnly;
|
||
};
|
||
|
||
Tiddler.prototype.autoLinkWikiWords = function()
|
||
{
|
||
return !(this.isTagged("systemConfig") || this.isTagged("excludeMissing"));
|
||
};
|
||
|
||
Tiddler.prototype.getServerType = function()
|
||
{
|
||
var serverType = null;
|
||
if(this.fields['server.type'])
|
||
serverType = this.fields['server.type'];
|
||
if(!serverType)
|
||
serverType = this.fields['wikiformat'];
|
||
if(serverType && !config.adaptors[serverType])
|
||
serverType = null;
|
||
return serverType;
|
||
};
|
||
|
||
Tiddler.prototype.getAdaptor = function()
|
||
{
|
||
var serverType = this.getServerType();
|
||
return serverType ? new config.adaptors[serverType]() : null;
|
||
};
|
||
|
||
//--
|
||
//-- TiddlyWiki instance contains TiddlerS
|
||
//--
|
||
|
||
function TiddlyWiki(params)
|
||
{
|
||
var tiddlers = {}; // Hashmap by name of tiddlers
|
||
if(params && params.config) {
|
||
this.config = config;
|
||
}
|
||
this.tiddlersUpdated = false;
|
||
this.namedNotifications = []; // Array of {name:,notify:} of notification functions
|
||
this.notificationLevel = 0;
|
||
this.slices = {}; // map tiddlerName->(map sliceName->sliceValue). Lazy.
|
||
this.clear = function() {
|
||
tiddlers = {};
|
||
this.setDirty(false);
|
||
};
|
||
this.fetchTiddler = function(title) {
|
||
var t = tiddlers[title];
|
||
return t instanceof Tiddler ? t : null;
|
||
};
|
||
this.deleteTiddler = function(title) {
|
||
delete this.slices[title];
|
||
delete tiddlers[title];
|
||
};
|
||
this.addTiddler = function(tiddler) {
|
||
delete this.slices[tiddler.title];
|
||
tiddlers[tiddler.title] = tiddler;
|
||
};
|
||
this.forEachTiddler = function(callback) {
|
||
var t;
|
||
for(t in tiddlers) {
|
||
var tiddler = tiddlers[t];
|
||
if(tiddler instanceof Tiddler)
|
||
callback.call(this,t,tiddler);
|
||
}
|
||
};
|
||
}
|
||
|
||
TiddlyWiki.prototype.setDirty = function(dirty)
|
||
{
|
||
this.dirty = dirty;
|
||
};
|
||
|
||
TiddlyWiki.prototype.isDirty = function()
|
||
{
|
||
return this.dirty;
|
||
};
|
||
|
||
TiddlyWiki.prototype.tiddlerExists = function(title)
|
||
{
|
||
var t = this.fetchTiddler(title);
|
||
return t != undefined;
|
||
};
|
||
|
||
TiddlyWiki.prototype.isShadowTiddler = function(title)
|
||
{
|
||
return config.shadowTiddlers[title] === undefined ? false : true;
|
||
};
|
||
|
||
TiddlyWiki.prototype.createTiddler = function(title)
|
||
{
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(!tiddler) {
|
||
tiddler = new Tiddler(title);
|
||
this.addTiddler(tiddler);
|
||
this.setDirty(true);
|
||
}
|
||
return tiddler;
|
||
};
|
||
|
||
TiddlyWiki.prototype.getTiddler = function(title)
|
||
{
|
||
var t = this.fetchTiddler(title);
|
||
if(t != undefined)
|
||
return t;
|
||
else
|
||
return null;
|
||
};
|
||
|
||
TiddlyWiki.prototype.getShadowTiddlerText = function(title)
|
||
{
|
||
if(typeof config.shadowTiddlers[title] == "string")
|
||
return config.shadowTiddlers[title];
|
||
else
|
||
return "";
|
||
};
|
||
|
||
// Retrieve tiddler contents
|
||
TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
|
||
{
|
||
if(!title)
|
||
return defaultText;
|
||
var pos = title.indexOf(config.textPrimitives.sectionSeparator);
|
||
var section = null;
|
||
if(pos != -1) {
|
||
section = title.substr(pos + config.textPrimitives.sectionSeparator.length);
|
||
title = title.substr(0,pos);
|
||
}
|
||
pos = title.indexOf(config.textPrimitives.sliceSeparator);
|
||
if(pos != -1) {
|
||
var slice = this.getTiddlerSlice(title.substr(0,pos),title.substr(pos + config.textPrimitives.sliceSeparator.length));
|
||
if(slice)
|
||
return slice;
|
||
}
|
||
var tiddler = this.fetchTiddler(title);
|
||
var text = tiddler ? tiddler.text : null;
|
||
if(!tiddler && this.isShadowTiddler(title)) {
|
||
text = this.getShadowTiddlerText(title);
|
||
}
|
||
if(text) {
|
||
if(!section)
|
||
return text;
|
||
var re = new RegExp("(^!{1,6}[ \t]*" + section.escapeRegExp() + "[ \t]*\n)","mg");
|
||
re.lastIndex = 0;
|
||
var match = re.exec(text);
|
||
if(match) {
|
||
var t = text.substr(match.index+match[1].length);
|
||
var re2 = /^!/mg;
|
||
re2.lastIndex = 0;
|
||
match = re2.exec(t); //# search for the next heading
|
||
if(match)
|
||
t = t.substr(0,match.index-1);//# don't include final \n
|
||
return t;
|
||
}
|
||
return defaultText;
|
||
}
|
||
if(defaultText != undefined)
|
||
return defaultText;
|
||
return null;
|
||
};
|
||
|
||
TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth)
|
||
{
|
||
var bracketRegExp = new RegExp("(?:\\[\\[([^\\]]+)\\]\\])","mg");
|
||
var text = this.getTiddlerText(title,null);
|
||
if(text == null)
|
||
return defaultText;
|
||
var textOut = [];
|
||
var match,lastPos = 0;
|
||
do {
|
||
match = bracketRegExp.exec(text);
|
||
if(match) {
|
||
textOut.push(text.substr(lastPos,match.index-lastPos));
|
||
if(match[1]) {
|
||
if(depth <= 0)
|
||
textOut.push(match[1]);
|
||
else
|
||
textOut.push(this.getRecursiveTiddlerText(match[1],"",depth-1));
|
||
}
|
||
lastPos = match.index + match[0].length;
|
||
} else {
|
||
textOut.push(text.substr(lastPos));
|
||
}
|
||
} while(match);
|
||
return textOut.join("");
|
||
};
|
||
|
||
//TiddlyWiki.prototype.slicesRE = /(?:^([\'\/]{0,2})~?([\.\w]+)\:\1[\t\x20]*([^\n]+)[\t\x20]*$)|(?:^\|([\'\/]{0,2})~?([\.\w]+)\:?\4\|[\t\x20]*([^\n]+)[\t\x20]*\|$)/gm;
|
||
TiddlyWiki.prototype.slicesRE = /(?:^([\'\/]{0,2})~?([\.\w]+)\:\1[\t\x20]*([^\n]*)[\t\x20]*$)|(?:^\|([\'\/]{0,2})~?([\.\w]+)\:?\4\|[\t\x20]*([^\|\n]*)[\t\x20]*\|$)/gm;
|
||
// @internal
|
||
TiddlyWiki.prototype.calcAllSlices = function(title)
|
||
{
|
||
var slices = {};
|
||
var text = this.getTiddlerText(title,"");
|
||
this.slicesRE.lastIndex = 0;
|
||
var m = this.slicesRE.exec(text);
|
||
while(m) {
|
||
if(m[2])
|
||
slices[m[2]] = m[3];
|
||
else
|
||
slices[m[5]] = m[6];
|
||
m = this.slicesRE.exec(text);
|
||
}
|
||
return slices;
|
||
};
|
||
|
||
// Returns the slice of text of the given name
|
||
TiddlyWiki.prototype.getTiddlerSlice = function(title,sliceName)
|
||
{
|
||
var slices = this.slices[title];
|
||
if(!slices) {
|
||
slices = this.calcAllSlices(title);
|
||
this.slices[title] = slices;
|
||
}
|
||
return slices[sliceName];
|
||
};
|
||
|
||
// Build an hashmap of the specified named slices of a tiddler
|
||
TiddlyWiki.prototype.getTiddlerSlices = function(title,sliceNames)
|
||
{
|
||
var t,r = {};
|
||
for(t=0; t<sliceNames.length; t++) {
|
||
var slice = this.getTiddlerSlice(title,sliceNames[t]);
|
||
if(slice)
|
||
r[sliceNames[t]] = slice;
|
||
}
|
||
return r;
|
||
};
|
||
|
||
TiddlyWiki.prototype.suspendNotifications = function()
|
||
{
|
||
this.notificationLevel--;
|
||
};
|
||
|
||
TiddlyWiki.prototype.resumeNotifications = function()
|
||
{
|
||
this.notificationLevel++;
|
||
};
|
||
|
||
// Invoke the notification handlers for a particular tiddler
|
||
TiddlyWiki.prototype.notify = function(title,doBlanket)
|
||
{
|
||
if(!this.notificationLevel) {
|
||
var t;
|
||
for(t=0; t<this.namedNotifications.length; t++) {
|
||
var n = this.namedNotifications[t];
|
||
if((n.name == null && doBlanket) || (n.name == title))
|
||
n.notify(title);
|
||
}
|
||
}
|
||
};
|
||
|
||
// Invoke the notification handlers for all tiddlers
|
||
TiddlyWiki.prototype.notifyAll = function()
|
||
{
|
||
if(!this.notificationLevel) {
|
||
var t;
|
||
for(t=0; t<this.namedNotifications.length; t++) {
|
||
var n = this.namedNotifications[t];
|
||
if(n.name)
|
||
n.notify(n.name);
|
||
}
|
||
}
|
||
};
|
||
|
||
// Add a notification handler to a tiddler
|
||
TiddlyWiki.prototype.addNotification = function(title,fn)
|
||
{
|
||
var i;
|
||
for(i=0; i<this.namedNotifications.length; i++) {
|
||
if((this.namedNotifications[i].name == title) && (this.namedNotifications[i].notify == fn))
|
||
return this;
|
||
}
|
||
this.namedNotifications.push({name: title, notify: fn});
|
||
return this;
|
||
};
|
||
|
||
TiddlyWiki.prototype.removeTiddler = function(title)
|
||
{
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(tiddler) {
|
||
this.deleteTiddler(title);
|
||
this.notify(title,true);
|
||
this.setDirty(true);
|
||
}
|
||
};
|
||
|
||
// Reset the sync status of a freshly synced tiddler
|
||
TiddlyWiki.prototype.resetTiddler = function(title)
|
||
{
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(tiddler) {
|
||
tiddler.clearChangeCount();
|
||
this.notify(title,true);
|
||
this.setDirty(true);
|
||
}
|
||
};
|
||
|
||
TiddlyWiki.prototype.setTiddlerTag = function(title,status,tag)
|
||
{
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(tiddler) {
|
||
var t = tiddler.tags.indexOf(tag);
|
||
if(t != -1)
|
||
tiddler.tags.splice(t,1);
|
||
if(status)
|
||
tiddler.tags.push(tag);
|
||
tiddler.changed();
|
||
tiddler.incChangeCount();
|
||
this.notify(title,true);
|
||
this.setDirty(true);
|
||
}
|
||
};
|
||
|
||
TiddlyWiki.prototype.addTiddlerFields = function(title,fields)
|
||
{
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(!tiddler)
|
||
return;
|
||
merge(tiddler.fields,fields);
|
||
tiddler.changed();
|
||
tiddler.incChangeCount();
|
||
this.notify(title,true);
|
||
this.setDirty(true);
|
||
};
|
||
|
||
// Store tiddler in TiddlyWiki instance
|
||
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created,creator)
|
||
{
|
||
var tiddler;
|
||
if(title instanceof Tiddler) {
|
||
tiddler = title;
|
||
title = tiddler.title;
|
||
newTitle = title;
|
||
} else {
|
||
tiddler = this.fetchTiddler(title);
|
||
if(tiddler) {
|
||
created = created || tiddler.created; // Preserve created date
|
||
creator = creator || tiddler.creator;
|
||
this.deleteTiddler(title);
|
||
} else {
|
||
created = created || modified;
|
||
tiddler = new Tiddler();
|
||
}
|
||
fields = merge(merge({},fields),config.defaultCustomFields,true);
|
||
tiddler.set(newTitle,newBody,modifier,modified,tags,created,fields,creator);
|
||
}
|
||
this.addTiddler(tiddler);
|
||
if(clearChangeCount)
|
||
tiddler.clearChangeCount();
|
||
else
|
||
tiddler.incChangeCount();
|
||
if(title != newTitle)
|
||
this.notify(title,true);
|
||
this.notify(newTitle,true);
|
||
if(window.location.protocol == "file:")
|
||
this.setDirty(true);
|
||
return tiddler;
|
||
};
|
||
|
||
TiddlyWiki.prototype.incChangeCount = function(title)
|
||
{
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(tiddler)
|
||
tiddler.incChangeCount();
|
||
};
|
||
|
||
TiddlyWiki.prototype.getLoader = function()
|
||
{
|
||
if(!this.loader)
|
||
this.loader = new TW21Loader();
|
||
return this.loader;
|
||
};
|
||
|
||
TiddlyWiki.prototype.getSaver = function()
|
||
{
|
||
if(!this.saver)
|
||
this.saver = new TW21Saver();
|
||
return this.saver;
|
||
};
|
||
|
||
// Return all tiddlers formatted as an HTML string
|
||
TiddlyWiki.prototype.allTiddlersAsHtml = function()
|
||
{
|
||
return this.getSaver().externalize(store);
|
||
};
|
||
|
||
// Load contents of a TiddlyWiki from an HTML DIV
|
||
TiddlyWiki.prototype.loadFromDiv = function(src,idPrefix,noUpdate)
|
||
{
|
||
this.idPrefix = idPrefix;
|
||
var storeElem = (typeof src == "string") ? document.getElementById(src) : src;
|
||
if(!storeElem)
|
||
return;
|
||
var tiddlers = this.getLoader().loadTiddlers(this,storeElem.childNodes);
|
||
this.setDirty(false);
|
||
if(!noUpdate) {
|
||
var i;
|
||
for(i = 0;i<tiddlers.length; i++)
|
||
tiddlers[i].changed();
|
||
}
|
||
jQuery(document).trigger("loadTiddlers");
|
||
};
|
||
|
||
// Load contents of a TiddlyWiki from a string
|
||
// Returns null if there's an error
|
||
TiddlyWiki.prototype.importTiddlyWiki = function(text)
|
||
{
|
||
var posDiv = locateStoreArea(text);
|
||
if(!posDiv)
|
||
return null;
|
||
var content = "<" + "html><" + "body>" + text.substring(posDiv[0],posDiv[1] + endSaveArea.length) + "<" + "/body><" + "/html>";
|
||
// Create the iframe
|
||
var iframe = document.createElement("iframe");
|
||
iframe.style.display = "none";
|
||
document.body.appendChild(iframe);
|
||
var doc = iframe.document;
|
||
if(iframe.contentDocument)
|
||
doc = iframe.contentDocument; // For NS6
|
||
else if(iframe.contentWindow)
|
||
doc = iframe.contentWindow.document; // For IE5.5 and IE6
|
||
// Put the content in the iframe
|
||
doc.open();
|
||
doc.writeln(content);
|
||
doc.close();
|
||
// Load the content into a TiddlyWiki() object
|
||
var storeArea = doc.getElementById("storeArea");
|
||
this.loadFromDiv(storeArea,"store");
|
||
// Get rid of the iframe
|
||
iframe.parentNode.removeChild(iframe);
|
||
return this;
|
||
};
|
||
|
||
TiddlyWiki.prototype.updateTiddlers = function()
|
||
{
|
||
this.tiddlersUpdated = true;
|
||
this.forEachTiddler(function(title,tiddler) {
|
||
tiddler.changed();
|
||
});
|
||
};
|
||
|
||
// Return an array of tiddlers matching a search regular expression
|
||
TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag,match)
|
||
{
|
||
var candidates = this.reverseLookup("tags",excludeTag,!!match);
|
||
var t,results = [];
|
||
for(t=0; t<candidates.length; t++) {
|
||
if((candidates[t].title.search(searchRegExp) != -1) || (candidates[t].text.search(searchRegExp) != -1))
|
||
results.push(candidates[t]);
|
||
}
|
||
if(!sortField)
|
||
sortField = "title";
|
||
results.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
|
||
return results;
|
||
};
|
||
|
||
// Returns a list of all tags in use
|
||
// excludeTag - if present, excludes tags that are themselves tagged with excludeTag
|
||
// Returns an array of arrays where [tag][0] is the name of the tag and [tag][1] is the number of occurances
|
||
TiddlyWiki.prototype.getTags = function(excludeTag)
|
||
{
|
||
var results = [];
|
||
this.forEachTiddler(function(title,tiddler) {
|
||
var g,c;
|
||
for(g=0; g<tiddler.tags.length; g++) {
|
||
var tag = tiddler.tags[g];
|
||
var n = true;
|
||
for(c=0; c<results.length; c++) {
|
||
if(results[c][0] == tag) {
|
||
n = false;
|
||
results[c][1]++;
|
||
}
|
||
}
|
||
if(n && excludeTag) {
|
||
var t = this.fetchTiddler(tag);
|
||
if(t && t.isTagged(excludeTag))
|
||
n = false;
|
||
}
|
||
if(n)
|
||
results.push([tag,1]);
|
||
}
|
||
});
|
||
results.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
|
||
return results;
|
||
};
|
||
|
||
// Return an array of the tiddlers that are tagged with a given tag
|
||
TiddlyWiki.prototype.getTaggedTiddlers = function(tag,sortField)
|
||
{
|
||
return this.reverseLookup("tags",tag,true,sortField);
|
||
};
|
||
|
||
TiddlyWiki.prototype.getValueTiddlers = function(field,value,sortField)
|
||
{
|
||
return this.reverseLookup(field,value,true,sortField);
|
||
};
|
||
|
||
// Return an array of the tiddlers that link to a given tiddler
|
||
TiddlyWiki.prototype.getReferringTiddlers = function(title,unusedParameter,sortField)
|
||
{
|
||
if(!this.tiddlersUpdated)
|
||
this.updateTiddlers();
|
||
return this.reverseLookup("links",title,true,sortField);
|
||
};
|
||
|
||
// Return an array of the tiddlers that do or do not have a specified entry in the specified storage array (ie, "links" or "tags")
|
||
// lookupMatch == true to match tiddlers, false to exclude tiddlers
|
||
TiddlyWiki.prototype.reverseLookup = function(lookupField,lookupValue,lookupMatch,sortField)
|
||
{
|
||
var results = [];
|
||
this.forEachTiddler(function(title,tiddler) {
|
||
var f = !lookupMatch;
|
||
var values;
|
||
if(["links", "tags"].contains(lookupField)) {
|
||
values = tiddler[lookupField];
|
||
} else {
|
||
var accessor = TiddlyWiki.standardFieldAccess[lookupField];
|
||
if(accessor) {
|
||
values = [ accessor.get(tiddler) ];
|
||
} else {
|
||
values = tiddler.fields[lookupField] ? [tiddler.fields[lookupField]] : [];
|
||
}
|
||
}
|
||
var lookup;
|
||
for(lookup=0; lookup<values.length; lookup++) {
|
||
if(values[lookup] == lookupValue)
|
||
f = lookupMatch;
|
||
}
|
||
if(f)
|
||
results.push(tiddler);
|
||
});
|
||
if(!sortField)
|
||
sortField = "title";
|
||
return this.sortTiddlers(results,sortField);
|
||
};
|
||
|
||
// Return the tiddlers as a sorted array
|
||
TiddlyWiki.prototype.getTiddlers = function(field,excludeTag)
|
||
{
|
||
var results = [];
|
||
this.forEachTiddler(function(title,tiddler) {
|
||
if(excludeTag == undefined || !tiddler.isTagged(excludeTag))
|
||
results.push(tiddler);
|
||
});
|
||
if(field)
|
||
results.sort(function(a,b) {return a[field] < b[field] ? -1 : (a[field] == b[field] ? 0 : +1);});
|
||
return results;
|
||
};
|
||
|
||
// Return array of names of tiddlers that are referred to but not defined
|
||
TiddlyWiki.prototype.getMissingLinks = function()
|
||
{
|
||
if(!this.tiddlersUpdated)
|
||
this.updateTiddlers();
|
||
var results = [];
|
||
this.forEachTiddler(function (title,tiddler) {
|
||
if(tiddler.isTagged("excludeMissing") || tiddler.isTagged("systemConfig"))
|
||
return;
|
||
var n;
|
||
for(n=0; n<tiddler.links.length;n++) {
|
||
var link = tiddler.links[n];
|
||
if(this.getTiddlerText(link,null) == null && !this.isShadowTiddler(link) && !config.macros[link])
|
||
results.pushUnique(link);
|
||
}
|
||
});
|
||
results.sort();
|
||
return results;
|
||
};
|
||
|
||
// Return an array of names of tiddlers that are defined but not referred to
|
||
TiddlyWiki.prototype.getOrphans = function()
|
||
{
|
||
var results = [];
|
||
this.forEachTiddler(function (title,tiddler) {
|
||
if(this.getReferringTiddlers(title).length == 0 && !tiddler.isTagged("excludeLists"))
|
||
results.push(title);
|
||
});
|
||
results.sort();
|
||
return results;
|
||
};
|
||
|
||
// Return an array of names of all the shadow tiddlers
|
||
TiddlyWiki.prototype.getShadowed = function()
|
||
{
|
||
var t,results = [];
|
||
for(t in config.shadowTiddlers) {
|
||
if(this.isShadowTiddler(t))
|
||
results.push(t);
|
||
}
|
||
results.sort();
|
||
return results;
|
||
};
|
||
|
||
// Return an array of tiddlers that have been touched since they were downloaded or created
|
||
TiddlyWiki.prototype.getTouched = function()
|
||
{
|
||
var results = [];
|
||
this.forEachTiddler(function(title,tiddler) {
|
||
if(tiddler.isTouched())
|
||
results.push(tiddler);
|
||
});
|
||
results.sort();
|
||
return results;
|
||
};
|
||
|
||
// Resolves a Tiddler reference or tiddler title into a Tiddler object, or null if it doesn't exist
|
||
TiddlyWiki.prototype.resolveTiddler = function(tiddler)
|
||
{
|
||
var t = (typeof tiddler == "string") ? this.getTiddler(tiddler) : tiddler;
|
||
return t instanceof Tiddler ? t : null;
|
||
};
|
||
|
||
// Sort a list of tiddlers
|
||
TiddlyWiki.prototype.sortTiddlers = function(tiddlers,field)
|
||
{
|
||
var asc = +1;
|
||
switch(field.substr(0,1)) {
|
||
case "-":
|
||
asc = -1;
|
||
field = field.substr(1);
|
||
break;
|
||
case "+":
|
||
field = field.substr(1);
|
||
break;
|
||
}
|
||
if(TiddlyWiki.standardFieldAccess[field]) {
|
||
if(field=="title") {
|
||
tiddlers.sort(function(a,b) {return a[field].toLowerCase() < b[field].toLowerCase() ? -asc : (a[field].toLowerCase() == b[field].toLowerCase() ? 0 : asc);});
|
||
} else {
|
||
tiddlers.sort(function(a,b) {return a[field] < b[field] ? -asc : (a[field] == b[field] ? 0 : asc);});
|
||
}
|
||
} else {
|
||
tiddlers.sort(function(a,b) {return a.fields[field] < b.fields[field] ? -asc : (a.fields[field] == b.fields[field] ? 0 : +asc);});
|
||
}
|
||
return tiddlers;
|
||
};
|
||
|
||
//--
|
||
//-- Filter a list of tiddlers
|
||
//--
|
||
|
||
config.filters = {
|
||
tiddler: function(results,match) {
|
||
var title = match[1]||match[4];
|
||
var tiddler = this.fetchTiddler(title);
|
||
if(tiddler) {
|
||
results.pushUnique(tiddler);
|
||
} else if(this.isShadowTiddler(title)) {
|
||
tiddler = new Tiddler();
|
||
tiddler.set(title,this.getTiddlerText(title));
|
||
results.pushUnique(tiddler);
|
||
} else {
|
||
results.pushUnique(new Tiddler(title));
|
||
}
|
||
return results;
|
||
},
|
||
tag: function(results,match) {
|
||
var m,matched = this.getTaggedTiddlers(match[3]);
|
||
for(m=0; m<matched.length; m++) {
|
||
results.pushUnique(matched[m]);
|
||
}
|
||
return results;
|
||
},
|
||
sort: function(results,match) {
|
||
return this.sortTiddlers(results,match[3]);
|
||
},
|
||
limit: function(results,match) {
|
||
return results.slice(0,parseInt(match[3],10));
|
||
},
|
||
field: function(results,match) {
|
||
var m,matched = this.getValueTiddlers(match[2],match[3]);
|
||
for (m = 0; m < matched.length; m++) {
|
||
results.pushUnique(matched[m]);
|
||
}
|
||
return results;
|
||
}
|
||
};
|
||
|
||
// Filter a list of tiddlers
|
||
TiddlyWiki.prototype.filterTiddlers = function(filter)
|
||
{
|
||
var re = /([^\s\[\]]+)|(?:\[([ \w\.\-]+)\[([^\]]+)\]\])|(?:\[\[([^\]]+)\]\])/mg;
|
||
|
||
var results = [];
|
||
if(filter) {
|
||
var match = re.exec(filter);
|
||
while(match) {
|
||
var handler = (match[1]||match[4])?'tiddler':config.filters[match[2]]?match[2]:'field';
|
||
results = config.filters[handler].call(this,results,match);
|
||
match = re.exec(filter);
|
||
}
|
||
}
|
||
return results;
|
||
};
|
||
// Returns true if path is a valid field name (path),
|
||
// i.e. a sequence of identifiers, separated by "."
|
||
TiddlyWiki.isValidFieldName = function(name)
|
||
{
|
||
var match = /[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)*/.exec(name);
|
||
return match && (match[0] == name);
|
||
};
|
||
|
||
// Throws an exception when name is not a valid field name.
|
||
TiddlyWiki.checkFieldName = function(name)
|
||
{
|
||
if(!TiddlyWiki.isValidFieldName(name))
|
||
throw config.messages.invalidFieldName.format([name]);
|
||
};
|
||
|
||
function StringFieldAccess(n,readOnly)
|
||
{
|
||
this.set = readOnly ?
|
||
function(t,v) {if(v != t[n]) throw config.messages.fieldCannotBeChanged.format([n]);} :
|
||
function(t,v) {if(v != t[n]) {t[n] = v; return true;}};
|
||
this.get = function(t) {return t[n];};
|
||
}
|
||
|
||
function DateFieldAccess(n)
|
||
{
|
||
this.set = function(t,v) {
|
||
var d = v instanceof Date ? v : Date.convertFromYYYYMMDDHHMM(v);
|
||
if(d != t[n]) {
|
||
t[n] = d; return true;
|
||
}
|
||
};
|
||
this.get = function(t) {return t[n].convertToYYYYMMDDHHMM();};
|
||
}
|
||
|
||
function LinksFieldAccess(n)
|
||
{
|
||
this.set = function(t,v) {
|
||
var s = (typeof v == "string") ? v.readBracketedList() : v;
|
||
if(s.toString() != t[n].toString()) {
|
||
t[n] = s; return true;
|
||
}
|
||
};
|
||
this.get = function(t) {return String.encodeTiddlyLinkList(t[n]);};
|
||
}
|
||
|
||
TiddlyWiki.standardFieldAccess = {
|
||
// The set functions return true when setting the data has changed the value.
|
||
"title": new StringFieldAccess("title",true),
|
||
// Handle the "tiddler" field name as the title
|
||
"tiddler": new StringFieldAccess("title",true),
|
||
"text": new StringFieldAccess("text"),
|
||
"modifier": new StringFieldAccess("modifier"),
|
||
"modified": new DateFieldAccess("modified"),
|
||
"creator": new StringFieldAccess("creator"),
|
||
"created": new DateFieldAccess("created"),
|
||
"tags": new LinksFieldAccess("tags")
|
||
};
|
||
|
||
TiddlyWiki.isStandardField = function(name)
|
||
{
|
||
return TiddlyWiki.standardFieldAccess[name] != undefined;
|
||
};
|
||
|
||
// Sets the value of the given field of the tiddler to the value.
|
||
// Setting an ExtendedField's value to null or undefined removes the field.
|
||
// Setting a namespace to undefined removes all fields of that namespace.
|
||
// The fieldName is case-insensitive.
|
||
// All values will be converted to a string value.
|
||
TiddlyWiki.prototype.setValue = function(tiddler,fieldName,value)
|
||
{
|
||
TiddlyWiki.checkFieldName(fieldName);
|
||
var t = this.resolveTiddler(tiddler);
|
||
if(!t)
|
||
return;
|
||
fieldName = fieldName.toLowerCase();
|
||
var isRemove = (value === undefined) || (value === null);
|
||
var accessor = TiddlyWiki.standardFieldAccess[fieldName];
|
||
if(accessor) {
|
||
if(isRemove)
|
||
// don't remove StandardFields
|
||
return;
|
||
var h = TiddlyWiki.standardFieldAccess[fieldName];
|
||
if(!h.set(t,value))
|
||
return;
|
||
} else {
|
||
var oldValue = t.fields[fieldName];
|
||
if(isRemove) {
|
||
if(oldValue !== undefined) {
|
||
// deletes a single field
|
||
delete t.fields[fieldName];
|
||
} else {
|
||
// no concrete value is defined for the fieldName
|
||
// so we guess this is a namespace path.
|
||
// delete all fields in a namespace
|
||
var re = new RegExp("^"+fieldName+"\\.");
|
||
var dirty = false;
|
||
var n;
|
||
for(n in t.fields) {
|
||
if(n.match(re)) {
|
||
delete t.fields[n];
|
||
dirty = true;
|
||
}
|
||
}
|
||
if(!dirty)
|
||
return;
|
||
}
|
||
} else {
|
||
// the "normal" set case. value is defined (not null/undefined)
|
||
// For convenience provide a nicer conversion Date->String
|
||
value = value instanceof Date ? value.convertToYYYYMMDDHHMMSSMMM() : String(value);
|
||
if(oldValue == value)
|
||
return;
|
||
t.fields[fieldName] = value;
|
||
}
|
||
}
|
||
// When we are here the tiddler/store really was changed.
|
||
this.notify(t.title,true);
|
||
if(!fieldName.match(/^temp\./))
|
||
this.setDirty(true);
|
||
};
|
||
|
||
// Returns the value of the given field of the tiddler.
|
||
// The fieldName is case-insensitive.
|
||
// Will only return String values (or undefined).
|
||
TiddlyWiki.prototype.getValue = function(tiddler,fieldName)
|
||
{
|
||
var t = this.resolveTiddler(tiddler);
|
||
if(!t)
|
||
return undefined;
|
||
if(fieldName.indexOf(config.textPrimitives.sectionSeparator) === 0 || fieldName.indexOf(config.textPrimitives.sliceSeparator) === 0) {
|
||
var sliceType = fieldName.substr(0, 2);
|
||
var sliceName = fieldName.substring(2);
|
||
return store.getTiddlerText("%0%1%2".format(t.title,sliceType,sliceName));
|
||
} else {
|
||
fieldName = fieldName.toLowerCase();
|
||
var accessor = TiddlyWiki.standardFieldAccess[fieldName];
|
||
if(accessor) {
|
||
return accessor.get(t);
|
||
}
|
||
}
|
||
return t.fields[fieldName];
|
||
};
|
||
|
||
// Calls the callback function for every field in the tiddler.
|
||
// When callback function returns a non-false value the iteration stops
|
||
// and that value is returned.
|
||
// The order of the fields is not defined.
|
||
// @param callback a function(tiddler,fieldName,value).
|
||
TiddlyWiki.prototype.forEachField = function(tiddler,callback,onlyExtendedFields)
|
||
{
|
||
var t = this.resolveTiddler(tiddler);
|
||
if(!t)
|
||
return undefined;
|
||
var n,result;
|
||
for(n in t.fields) {
|
||
result = callback(t,n,t.fields[n]);
|
||
if(result)
|
||
return result;
|
||
}
|
||
if(onlyExtendedFields)
|
||
return undefined;
|
||
for(n in TiddlyWiki.standardFieldAccess) {
|
||
if(n != "tiddler") {
|
||
// even though the "title" field can also be referenced through the name "tiddler"
|
||
// we only visit this field once.
|
||
result = callback(t,n,TiddlyWiki.standardFieldAccess[n].get(t));
|
||
if(result)
|
||
return result;
|
||
}
|
||
}
|
||
return undefined;
|
||
};
|
||
|
||
//--
|
||
//-- Story functions
|
||
//--
|
||
|
||
function Story(containerId,idPrefix)
|
||
{
|
||
this.container = containerId;
|
||
this.idPrefix = idPrefix;
|
||
this.highlightRegExp = null;
|
||
this.tiddlerId = function(title) {
|
||
title = title.replace(/_/g, "__").replace(/ /g, "_");
|
||
var id = this.idPrefix + title;
|
||
return id==this.container ? this.idPrefix + "_" + title : id;
|
||
};
|
||
this.containerId = function() {
|
||
return this.container;
|
||
};
|
||
}
|
||
|
||
Story.prototype.getTiddler = function(title)
|
||
{
|
||
return document.getElementById(this.tiddlerId(title));
|
||
};
|
||
|
||
Story.prototype.getContainer = function()
|
||
{
|
||
return document.getElementById(this.containerId());
|
||
};
|
||
|
||
Story.prototype.forEachTiddler = function(fn)
|
||
{
|
||
var place = this.getContainer();
|
||
if(!place)
|
||
return;
|
||
var e = place.firstChild;
|
||
while(e) {
|
||
var n = e.nextSibling;
|
||
var title = e.getAttribute("tiddler");
|
||
fn.call(this,title,e);
|
||
e = n;
|
||
}
|
||
};
|
||
|
||
Story.prototype.displayDefaultTiddlers = function()
|
||
{
|
||
this.displayTiddlers(null,store.filterTiddlers(store.getTiddlerText("DefaultTiddlers")));
|
||
};
|
||
|
||
Story.prototype.displayTiddlers = function(srcElement,titles,template,animate,unused,customFields,toggle)
|
||
{
|
||
var t;
|
||
for(t = titles.length-1;t>=0;t--)
|
||
this.displayTiddler(srcElement,titles[t],template,animate,unused,customFields);
|
||
};
|
||
|
||
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle,animationSrc)
|
||
{
|
||
var title = (tiddler instanceof Tiddler) ? tiddler.title : tiddler;
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem) {
|
||
if(toggle) {
|
||
if(tiddlerElem.getAttribute("dirty") != "true")
|
||
this.closeTiddler(title,true);
|
||
} else {
|
||
this.refreshTiddler(title,template,false,customFields);
|
||
}
|
||
} else {
|
||
var place = this.getContainer();
|
||
var before = this.positionTiddler(srcElement);
|
||
tiddlerElem = this.createTiddler(place,before,title,template,customFields);
|
||
}
|
||
if(animationSrc && typeof animationSrc !== "string") {
|
||
srcElement = animationSrc;
|
||
}
|
||
if(srcElement && typeof srcElement !== "string") {
|
||
if(config.options.chkAnimate && (animate == undefined || animate == true) && anim && typeof Zoomer == "function" && typeof Scroller == "function")
|
||
anim.startAnimating(new Zoomer(title,srcElement,tiddlerElem),new Scroller(tiddlerElem));
|
||
else
|
||
window.scrollTo(0,ensureVisible(tiddlerElem));
|
||
}
|
||
return tiddlerElem;
|
||
};
|
||
|
||
Story.prototype.positionTiddler = function(srcElement)
|
||
{
|
||
var place = this.getContainer();
|
||
var before = null;
|
||
if(typeof srcElement == "string") {
|
||
switch(srcElement) {
|
||
case "top":
|
||
before = place.firstChild;
|
||
break;
|
||
case "bottom":
|
||
before = null;
|
||
break;
|
||
}
|
||
} else {
|
||
var after = this.findContainingTiddler(srcElement);
|
||
if(after == null) {
|
||
before = place.firstChild;
|
||
} else if(after.nextSibling) {
|
||
before = after.nextSibling;
|
||
if(before.nodeType != 1)
|
||
before = null;
|
||
}
|
||
}
|
||
return before;
|
||
};
|
||
|
||
Story.prototype.createTiddler = function(place,before,title,template,customFields)
|
||
{
|
||
var tiddlerElem = createTiddlyElement(null,"div",this.tiddlerId(title),"tiddler");
|
||
tiddlerElem.setAttribute("refresh","tiddler");
|
||
if(customFields)
|
||
tiddlerElem.setAttribute("tiddlyFields",customFields);
|
||
place.insertBefore(tiddlerElem,before);
|
||
var defaultText = null;
|
||
if(!store.tiddlerExists(title) && !store.isShadowTiddler(title))
|
||
defaultText = this.loadMissingTiddler(title,customFields);
|
||
this.refreshTiddler(title,template,false,customFields,defaultText);
|
||
return tiddlerElem;
|
||
};
|
||
|
||
Story.prototype.loadMissingTiddler = function(title,fields,callback)
|
||
{
|
||
var getTiddlerCallback = function(context)
|
||
{
|
||
if(context.status) {
|
||
var t = context.tiddler;
|
||
if(!t.created)
|
||
t.created = new Date();
|
||
if(!t.modified)
|
||
t.modified = t.created;
|
||
context.tiddler = store.saveTiddler(t.title,t.title,t.text,t.modifier,t.modified,t.tags,t.fields,true,t.created,t.creator);
|
||
autoSaveChanges();
|
||
} else {
|
||
story.refreshTiddler(context.title,null,true);
|
||
}
|
||
context.adaptor.close();
|
||
if(callback) {
|
||
callback(context);
|
||
}
|
||
};
|
||
var tiddler = new Tiddler(title);
|
||
tiddler.fields = typeof fields == "string" ? fields.decodeHashMap() : fields||{};
|
||
var context = {serverType:tiddler.getServerType()};
|
||
if(!context.serverType)
|
||
return "";
|
||
context.host = tiddler.fields['server.host'];
|
||
context.workspace = tiddler.fields['server.workspace'];
|
||
var adaptor = new config.adaptors[context.serverType]();
|
||
adaptor.getTiddler(title,context,null,getTiddlerCallback);
|
||
return config.messages.loadingMissingTiddler.format([title,context.serverType,context.host,context.workspace]);
|
||
};
|
||
|
||
Story.prototype.chooseTemplateForTiddler = function(title,template)
|
||
{
|
||
if(!template)
|
||
template = DEFAULT_VIEW_TEMPLATE;
|
||
if(template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE)
|
||
template = config.tiddlerTemplates[template];
|
||
return template;
|
||
};
|
||
|
||
Story.prototype.getTemplateForTiddler = function(title,template,tiddler)
|
||
{
|
||
return store.getRecursiveTiddlerText(template,null,10);
|
||
};
|
||
|
||
Story.prototype.refreshTiddler = function(title,template,force,customFields,defaultText)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem) {
|
||
if(tiddlerElem.getAttribute("dirty") == "true" && !force)
|
||
return tiddlerElem;
|
||
template = this.chooseTemplateForTiddler(title,template);
|
||
var currTemplate = tiddlerElem.getAttribute("template");
|
||
if((template != currTemplate) || force) {
|
||
var tiddler = store.getTiddler(title);
|
||
if(!tiddler) {
|
||
tiddler = new Tiddler();
|
||
if(store.isShadowTiddler(title)) {
|
||
var tags = [];
|
||
tiddler.set(title,store.getTiddlerText(title),config.views.wikified.shadowModifier,version.date,tags,version.date);
|
||
} else {
|
||
var text = template=="EditTemplate" ?
|
||
config.views.editor.defaultText.format([title]) :
|
||
config.views.wikified.defaultText.format([title]);
|
||
text = defaultText || text;
|
||
var fields = customFields ? customFields.decodeHashMap() : null;
|
||
tiddler.set(title,text,config.views.wikified.defaultModifier,version.date,[],version.date,fields);
|
||
}
|
||
}
|
||
tiddlerElem.setAttribute("tags",tiddler.tags.join(" "));
|
||
tiddlerElem.setAttribute("tiddler",title);
|
||
tiddlerElem.setAttribute("template",template);
|
||
tiddlerElem.onmouseover = this.onTiddlerMouseOver;
|
||
tiddlerElem.onmouseout = this.onTiddlerMouseOut;
|
||
tiddlerElem.ondblclick = this.onTiddlerDblClick;
|
||
tiddlerElem[window.event?"onkeydown":"onkeypress"] = this.onTiddlerKeyPress;
|
||
tiddlerElem.innerHTML = this.getTemplateForTiddler(title,template,tiddler);
|
||
applyHtmlMacros(tiddlerElem,tiddler);
|
||
if(store.getTaggedTiddlers(title).length > 0)
|
||
jQuery(tiddlerElem).addClass("isTag");
|
||
else
|
||
jQuery(tiddlerElem).removeClass("isTag");
|
||
if(store.tiddlerExists(title)) {
|
||
jQuery(tiddlerElem).removeClass("shadow");
|
||
jQuery(tiddlerElem).removeClass("missing");
|
||
} else {
|
||
jQuery(tiddlerElem).addClass(store.isShadowTiddler(title) ? "shadow" : "missing");
|
||
}
|
||
if(customFields)
|
||
this.addCustomFields(tiddlerElem,customFields);
|
||
}
|
||
}
|
||
return tiddlerElem;
|
||
};
|
||
|
||
Story.prototype.addCustomFields = function(place,customFields)
|
||
{
|
||
var fields = customFields.decodeHashMap();
|
||
var w = createTiddlyElement(place,"div",null,"customFields");
|
||
w.style.display = "none";
|
||
var t;
|
||
for(t in fields) {
|
||
var e = document.createElement("input");
|
||
e.setAttribute("type","text");
|
||
e.setAttribute("value",fields[t]);
|
||
w.appendChild(e);
|
||
e.setAttribute("edit",t);
|
||
}
|
||
};
|
||
|
||
Story.prototype.refreshAllTiddlers = function(force)
|
||
{
|
||
var e = this.getContainer().firstChild;
|
||
while(e) {
|
||
var template = e.getAttribute("template");
|
||
if(template && e.getAttribute("dirty") != "true") {
|
||
this.refreshTiddler(e.getAttribute("tiddler"),force ? null : template,true);
|
||
}
|
||
e = e.nextSibling;
|
||
}
|
||
};
|
||
|
||
Story.prototype.onTiddlerMouseOver = function(e)
|
||
{
|
||
jQuery(this).addClass("selected");
|
||
};
|
||
|
||
Story.prototype.onTiddlerMouseOut = function(e)
|
||
{
|
||
jQuery(this).removeClass("selected");
|
||
};
|
||
|
||
Story.prototype.onTiddlerDblClick = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
var target = resolveTarget(e);
|
||
if(target && target.nodeName.toLowerCase() != "input" && target.nodeName.toLowerCase() != "textarea") {
|
||
if(document.selection && document.selection.empty)
|
||
document.selection.empty();
|
||
config.macros.toolbar.invokeCommand(this,"defaultCommand",e);
|
||
e.cancelBubble = true;
|
||
if(e.stopPropagation) e.stopPropagation();
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
Story.prototype.onTiddlerKeyPress = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
clearMessage();
|
||
var consume = false;
|
||
var title = this.getAttribute("tiddler");
|
||
var target = resolveTarget(e);
|
||
switch(e.keyCode) {
|
||
case 9: // Tab
|
||
var ed = story.getTiddlerField(title,"text");
|
||
if(target.tagName.toLowerCase() == "input" && ed.value==config.views.editor.defaultText.format([title])) {
|
||
// moving from input field and editor still contains default text, so select it
|
||
ed.focus();
|
||
ed.select();
|
||
consume = true;
|
||
}
|
||
if(config.options.chkInsertTabs && target.tagName.toLowerCase() == "textarea") {
|
||
replaceSelection(target,String.fromCharCode(9));
|
||
consume = true;
|
||
}
|
||
if(config.isOpera) {
|
||
target.onblur = function() {
|
||
this.focus();
|
||
this.onblur = null;
|
||
};
|
||
}
|
||
break;
|
||
case 13: // Ctrl-Enter
|
||
case 10: // Ctrl-Enter on IE PC
|
||
case 77: // Ctrl-Enter is "M" on some platforms
|
||
if(e.ctrlKey) {
|
||
blurElement(this);
|
||
config.macros.toolbar.invokeCommand(this,"defaultCommand",e);
|
||
consume = true;
|
||
}
|
||
break;
|
||
case 27: // Escape
|
||
blurElement(this);
|
||
config.macros.toolbar.invokeCommand(this,"cancelCommand",e);
|
||
consume = true;
|
||
break;
|
||
}
|
||
e.cancelBubble = consume;
|
||
if(consume) {
|
||
if(e.stopPropagation) e.stopPropagation(); // Stop Propagation
|
||
e.returnValue = true; // Cancel The Event in IE
|
||
if(e.preventDefault ) e.preventDefault(); // Cancel The Event in Moz
|
||
}
|
||
return !consume;
|
||
};
|
||
|
||
Story.prototype.getTiddlerField = function(title,field)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
var e = null;
|
||
if(tiddlerElem) {
|
||
var t,children = tiddlerElem.getElementsByTagName("*");
|
||
for(t=0; t<children.length; t++) {
|
||
var c = children[t];
|
||
if(c.tagName.toLowerCase() == "input" || c.tagName.toLowerCase() == "textarea") {
|
||
if(!e)
|
||
e = c;
|
||
if(c.getAttribute("edit") == field)
|
||
e = c;
|
||
}
|
||
}
|
||
}
|
||
return e;
|
||
};
|
||
|
||
Story.prototype.focusTiddler = function(title,field)
|
||
{
|
||
var e = this.getTiddlerField(title,field);
|
||
if(e) {
|
||
e.focus();
|
||
e.select();
|
||
}
|
||
};
|
||
|
||
Story.prototype.blurTiddler = function(title)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem && tiddlerElem.focus && tiddlerElem.blur) {
|
||
tiddlerElem.focus();
|
||
tiddlerElem.blur();
|
||
}
|
||
};
|
||
|
||
Story.prototype.setTiddlerField = function(title,tag,mode,field)
|
||
{
|
||
var c = this.getTiddlerField(title,field);
|
||
var tags = c.value.readBracketedList();
|
||
tags.setItem(tag,mode);
|
||
c.value = String.encodeTiddlyLinkList(tags);
|
||
};
|
||
|
||
Story.prototype.setTiddlerTag = function(title,tag,mode)
|
||
{
|
||
this.setTiddlerField(title,tag,mode,"tags");
|
||
};
|
||
|
||
Story.prototype.closeTiddler = function(title,animate,unused)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem) {
|
||
clearMessage();
|
||
this.scrubTiddler(tiddlerElem);
|
||
if(config.options.chkAnimate && animate && anim && typeof Slider == "function")
|
||
anim.startAnimating(new Slider(tiddlerElem,false,null,"all"));
|
||
else {
|
||
jQuery(tiddlerElem).remove();
|
||
}
|
||
}
|
||
};
|
||
|
||
Story.prototype.scrubTiddler = function(tiddlerElem)
|
||
{
|
||
tiddlerElem.id = null;
|
||
};
|
||
|
||
Story.prototype.setDirty = function(title,dirty)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem)
|
||
tiddlerElem.setAttribute("dirty",dirty ? "true" : "false");
|
||
};
|
||
|
||
Story.prototype.isDirty = function(title)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem)
|
||
return tiddlerElem.getAttribute("dirty") == "true";
|
||
return null;
|
||
};
|
||
|
||
Story.prototype.areAnyDirty = function()
|
||
{
|
||
var r = false;
|
||
this.forEachTiddler(function(title,element) {
|
||
if(this.isDirty(title))
|
||
r = true;
|
||
});
|
||
return r;
|
||
};
|
||
|
||
Story.prototype.closeAllTiddlers = function(exclude)
|
||
{
|
||
clearMessage();
|
||
this.forEachTiddler(function(title,element) {
|
||
if((title != exclude) && element.getAttribute("dirty") != "true")
|
||
this.closeTiddler(title);
|
||
});
|
||
window.scrollTo(0,ensureVisible(this.container));
|
||
};
|
||
|
||
Story.prototype.isEmpty = function()
|
||
{
|
||
var place = this.getContainer();
|
||
return place && place.firstChild == null;
|
||
};
|
||
|
||
Story.prototype.search = function(text,useCaseSensitive,useRegExp)
|
||
{
|
||
this.closeAllTiddlers();
|
||
highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
|
||
var matches = store.search(highlightHack,"title","excludeSearch");
|
||
this.displayTiddlers(null,matches);
|
||
highlightHack = null;
|
||
var q = useRegExp ? "/" : "'";
|
||
if(matches.length > 0)
|
||
displayMessage(config.macros.search.successMsg.format([matches.length.toString(),q + text + q]));
|
||
else
|
||
displayMessage(config.macros.search.failureMsg.format([q + text + q]));
|
||
};
|
||
|
||
Story.prototype.findContainingTiddler = function(e)
|
||
{
|
||
while(e && !jQuery(e).hasClass("tiddler")) {
|
||
e = jQuery(e).hasClass("popup") && Popup.stack[0] ? Popup.stack[0].root : e.parentNode;
|
||
}
|
||
return e;
|
||
};
|
||
|
||
Story.prototype.gatherSaveFields = function(e,fields)
|
||
{
|
||
if(e && e.getAttribute) {
|
||
var f = e.getAttribute("edit");
|
||
if(f)
|
||
fields[f] = e.value.replace(/\r/mg,"");
|
||
if(e.hasChildNodes()) {
|
||
var t,c = e.childNodes;
|
||
for(t=0; t<c.length; t++)
|
||
this.gatherSaveFields(c[t],fields);
|
||
}
|
||
}
|
||
};
|
||
|
||
Story.prototype.hasChanges = function(title)
|
||
{
|
||
var e = this.getTiddler(title);
|
||
if(e) {
|
||
var fields = {};
|
||
this.gatherSaveFields(e,fields);
|
||
if(store.fetchTiddler(title)) {
|
||
var n;
|
||
for(n in fields) {
|
||
if(store.getValue(title,n) != fields[n]) //# tiddler changed
|
||
return true;
|
||
}
|
||
} else {
|
||
if(store.isShadowTiddler(title) && store.getShadowTiddlerText(title) == fields.text) { //# not checking for title or tags
|
||
return false;
|
||
} else { //# changed shadow or new tiddler
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
Story.prototype.saveTiddler = function(title,minorUpdate)
|
||
{
|
||
var tiddlerElem = this.getTiddler(title);
|
||
if(tiddlerElem) {
|
||
var fields = {};
|
||
this.gatherSaveFields(tiddlerElem,fields);
|
||
var newTitle = fields.title || title;
|
||
if(!store.tiddlerExists(newTitle)) {
|
||
newTitle = newTitle.trim();
|
||
var creator = config.options.txtUserName;
|
||
}
|
||
if(store.tiddlerExists(newTitle) && newTitle != title) {
|
||
if(!confirm(config.messages.overwriteWarning.format([newTitle.toString()])))
|
||
return null;
|
||
title = newTitle;
|
||
}
|
||
if(newTitle != title)
|
||
this.closeTiddler(newTitle,false);
|
||
tiddlerElem.id = this.tiddlerId(newTitle);
|
||
tiddlerElem.setAttribute("tiddler",newTitle);
|
||
tiddlerElem.setAttribute("template",DEFAULT_VIEW_TEMPLATE);
|
||
tiddlerElem.setAttribute("dirty","false");
|
||
if(config.options.chkForceMinorUpdate)
|
||
minorUpdate = !minorUpdate;
|
||
if(!store.tiddlerExists(newTitle))
|
||
minorUpdate = false;
|
||
var newDate = new Date();
|
||
if(store.tiddlerExists(title)) {
|
||
var t = store.fetchTiddler(title);
|
||
var extendedFields = t.fields;
|
||
creator = t.creator;
|
||
} else {
|
||
extendedFields = merge({},config.defaultCustomFields);
|
||
}
|
||
var n;
|
||
for(n in fields) {
|
||
if(!TiddlyWiki.isStandardField(n))
|
||
extendedFields[n] = fields[n];
|
||
}
|
||
var tiddler = store.saveTiddler(title,newTitle,fields.text,minorUpdate ? undefined : config.options.txtUserName,minorUpdate ? undefined : newDate,fields.tags,extendedFields,null,null,creator);
|
||
autoSaveChanges(null,[tiddler]);
|
||
return newTitle;
|
||
}
|
||
return null;
|
||
};
|
||
|
||
Story.prototype.permaView = function()
|
||
{
|
||
var links = [];
|
||
this.forEachTiddler(function(title,element) {
|
||
links.push(String.encodeTiddlyLink(title));
|
||
});
|
||
var t = encodeURIComponent(links.join(" "));
|
||
if(t == "")
|
||
t = "#";
|
||
if(window.location.hash != t)
|
||
window.location.hash = t;
|
||
};
|
||
|
||
Story.prototype.switchTheme = function(theme)
|
||
{
|
||
if(safeMode)
|
||
return;
|
||
|
||
var isAvailable = function(title) {
|
||
var s = title ? title.indexOf(config.textPrimitives.sectionSeparator) : -1;
|
||
if(s!=-1)
|
||
title = title.substr(0,s);
|
||
return store.tiddlerExists(title) || store.isShadowTiddler(title);
|
||
};
|
||
|
||
var getSlice = function(theme,slice) {
|
||
var r;
|
||
if(readOnly)
|
||
r = store.getTiddlerSlice(theme,slice+"ReadOnly") || store.getTiddlerSlice(theme,"Web"+slice);
|
||
r = r || store.getTiddlerSlice(theme,slice);
|
||
if(r && r.indexOf(config.textPrimitives.sectionSeparator)==0)
|
||
r = theme + r;
|
||
return isAvailable(r) ? r : slice;
|
||
};
|
||
|
||
var replaceNotification = function(i,name,theme,slice) {
|
||
var newName = getSlice(theme,slice);
|
||
if(name!=newName && store.namedNotifications[i].name==name) {
|
||
store.namedNotifications[i].name = newName;
|
||
return newName;
|
||
}
|
||
return name;
|
||
};
|
||
|
||
var pt = config.refresherData.pageTemplate;
|
||
var vi = DEFAULT_VIEW_TEMPLATE;
|
||
var vt = config.tiddlerTemplates[vi];
|
||
var ei = DEFAULT_EDIT_TEMPLATE;
|
||
var et = config.tiddlerTemplates[ei];
|
||
|
||
var i;
|
||
for(i=0; i<config.notifyTiddlers.length; i++) {
|
||
var name = config.notifyTiddlers[i].name;
|
||
switch(name) {
|
||
case "PageTemplate":
|
||
config.refresherData.pageTemplate = replaceNotification(i,config.refresherData.pageTemplate,theme,name);
|
||
break;
|
||
case "StyleSheet":
|
||
removeStyleSheet(config.refresherData.styleSheet);
|
||
config.refresherData.styleSheet = replaceNotification(i,config.refresherData.styleSheet,theme,name);
|
||
break;
|
||
case "ColorPalette":
|
||
config.refresherData.colorPalette = replaceNotification(i,config.refresherData.colorPalette,theme,name);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
config.tiddlerTemplates[vi] = getSlice(theme,"ViewTemplate");
|
||
config.tiddlerTemplates[ei] = getSlice(theme,"EditTemplate");
|
||
if(!startingUp) {
|
||
if(config.refresherData.pageTemplate!=pt || config.tiddlerTemplates[vi]!=vt || config.tiddlerTemplates[ei]!=et) {
|
||
refreshAll();
|
||
this.refreshAllTiddlers(true);
|
||
} else {
|
||
setStylesheet(store.getRecursiveTiddlerText(config.refresherData.styleSheet,"",10),config.refreshers.styleSheet);
|
||
}
|
||
config.options.txtTheme = theme;
|
||
saveOption("txtTheme");
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Backstage
|
||
//--
|
||
// Backstage tasks
|
||
config.tasks.save.action = saveChanges;
|
||
|
||
var backstage = {
|
||
area: null,
|
||
toolbar: null,
|
||
button: null,
|
||
showButton: null,
|
||
hideButton: null,
|
||
cloak: null,
|
||
panel: null,
|
||
panelBody: null,
|
||
panelFooter: null,
|
||
currTabName: null,
|
||
currTabElem: null,
|
||
content: null,
|
||
|
||
init: function() {
|
||
var cmb = config.messages.backstage;
|
||
this.area = document.getElementById("backstageArea");
|
||
this.toolbar = jQuery("#backstageToolbar").empty()[0];
|
||
this.button = jQuery("#backstageButton").empty()[0];
|
||
this.button.style.display = "block";
|
||
var t = cmb.open.text + " " + glyph("bentArrowLeft");
|
||
this.showButton = createTiddlyButton(this.button,t,cmb.open.tooltip,
|
||
function(e) {backstage.show(); return false;},null,"backstageShow");
|
||
t = glyph("bentArrowRight") + " " + cmb.close.text;
|
||
this.hideButton = createTiddlyButton(this.button,t,cmb.close.tooltip,
|
||
function(e) {backstage.hide(); return false;},null,"backstageHide");
|
||
this.cloak = document.getElementById("backstageCloak");
|
||
this.panel = document.getElementById("backstagePanel");
|
||
this.panelFooter = createTiddlyElement(this.panel,"div",null,"backstagePanelFooter");
|
||
this.panelBody = createTiddlyElement(this.panel,"div",null,"backstagePanelBody");
|
||
this.cloak.onmousedown = function(e) {backstage.switchTab(null);};
|
||
createTiddlyText(this.toolbar,cmb.prompt);
|
||
for(t=0; t<config.backstageTasks.length; t++) {
|
||
var taskName = config.backstageTasks[t];
|
||
var task = config.tasks[taskName];
|
||
var handler = task.action ? this.onClickCommand : this.onClickTab;
|
||
var text = task.text + (task.action ? "" : glyph("downTriangle"));
|
||
var btn = createTiddlyButton(this.toolbar,text,task.tooltip,handler,"backstageTab");
|
||
jQuery(btn).addClass(task.action ? "backstageAction" : "backstageTask");
|
||
btn.setAttribute("task", taskName);
|
||
}
|
||
this.content = document.getElementById("contentWrapper");
|
||
if(config.options.chkBackstage)
|
||
this.show();
|
||
else
|
||
this.hide();
|
||
},
|
||
|
||
isVisible: function() {
|
||
return this.area ? this.area.style.display == "block" : false;
|
||
},
|
||
|
||
show: function() {
|
||
this.area.style.display = "block";
|
||
if(anim && config.options.chkAnimate) {
|
||
backstage.toolbar.style.left = findWindowWidth() + "px";
|
||
var p = [{style: "left", start: findWindowWidth(), end: 0, template: "%0px"}];
|
||
anim.startAnimating(new Morpher(backstage.toolbar,config.animDuration,p));
|
||
} else {
|
||
backstage.area.style.left = "0px";
|
||
}
|
||
jQuery(this.showButton).hide();
|
||
jQuery(this.hideButton).show();
|
||
config.options.chkBackstage = true;
|
||
saveOption("chkBackstage");
|
||
jQuery(this.content).addClass("backstageVisible");
|
||
},
|
||
|
||
hide: function() {
|
||
if(this.currTabElem) {
|
||
this.switchTab(null);
|
||
} else {
|
||
backstage.toolbar.style.left = "0px";
|
||
if(anim && config.options.chkAnimate) {
|
||
var p = [{style: "left", start: 0, end: findWindowWidth(), template: "%0px"}];
|
||
var c = function(element,properties) {backstage.area.style.display = "none";};
|
||
anim.startAnimating(new Morpher(backstage.toolbar,config.animDuration,p,c));
|
||
} else {
|
||
this.area.style.display = "none";
|
||
}
|
||
this.showButton.style.display = "block";
|
||
this.hideButton.style.display = "none";
|
||
config.options.chkBackstage = false;
|
||
saveOption("chkBackstage");
|
||
jQuery(this.content).removeClass("backstageVisible");
|
||
}
|
||
},
|
||
|
||
onClickCommand: function(e) {
|
||
var task = config.tasks[this.getAttribute("task")];
|
||
if(task.action) {
|
||
backstage.switchTab(null);
|
||
task.action();
|
||
}
|
||
return false;
|
||
},
|
||
|
||
onClickTab: function(e) {
|
||
backstage.switchTab(this.getAttribute("task"));
|
||
return false;
|
||
},
|
||
|
||
// Switch to a given tab, or none if null is passed
|
||
switchTab: function(tabName) {
|
||
var tabElem = null;
|
||
var e = this.toolbar.firstChild;
|
||
while(e) {
|
||
if(e.getAttribute && e.getAttribute("task") == tabName)
|
||
tabElem = e;
|
||
e = e.nextSibling;
|
||
}
|
||
if(tabName == backstage.currTabName) {
|
||
backstage.hidePanel();
|
||
return;
|
||
}
|
||
if(backstage.currTabElem) {
|
||
jQuery(this.currTabElem).removeClass("backstageSelTab");
|
||
}
|
||
if(tabElem && tabName) {
|
||
backstage.preparePanel();
|
||
jQuery(tabElem).addClass("backstageSelTab");
|
||
var task = config.tasks[tabName];
|
||
wikify(task.content,backstage.panelBody,null,null);
|
||
backstage.showPanel();
|
||
} else if(backstage.currTabElem) {
|
||
backstage.hidePanel();
|
||
}
|
||
backstage.currTabName = tabName;
|
||
backstage.currTabElem = tabElem;
|
||
},
|
||
|
||
isPanelVisible: function() {
|
||
return backstage.panel ? backstage.panel.style.display == "block" : false;
|
||
},
|
||
|
||
preparePanel: function() {
|
||
backstage.cloak.style.height = findWindowHeight() + "px";
|
||
backstage.cloak.style.display = "block";
|
||
jQuery(backstage.panelBody).empty();
|
||
return backstage.panelBody;
|
||
},
|
||
|
||
showPanel: function() {
|
||
backstage.panel.style.display = "block";
|
||
if(anim && config.options.chkAnimate) {
|
||
backstage.panel.style.top = (-backstage.panel.offsetHeight) + "px";
|
||
var p = [{style: "top", start: -backstage.panel.offsetHeight, end: 0, template: "%0px"}];
|
||
anim.startAnimating(new Morpher(backstage.panel,config.animDuration,p),new Scroller(backstage.panel,false));
|
||
} else {
|
||
backstage.panel.style.top = "0px";
|
||
}
|
||
return backstage.panelBody;
|
||
},
|
||
|
||
hidePanel: function() {
|
||
if(backstage.currTabElem)
|
||
jQuery(backstage.currTabElem).removeClass("backstageSelTab");
|
||
backstage.currTabElem = null;
|
||
backstage.currTabName = null;
|
||
if(anim && config.options.chkAnimate) {
|
||
var p = [
|
||
{style: "top", start: 0, end: -(backstage.panel.offsetHeight), template: "%0px"},
|
||
{style: "display", atEnd: "none"}
|
||
];
|
||
var c = function(element,properties) {backstage.cloak.style.display = "none";};
|
||
anim.startAnimating(new Morpher(backstage.panel,config.animDuration,p,c));
|
||
} else {
|
||
jQuery([backstage.panel,backstage.cloak]).hide();
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.backstage = {};
|
||
|
||
config.macros.backstage.handler = function(place,macroName,params)
|
||
{
|
||
var backstageTask = config.tasks[params[0]];
|
||
if(backstageTask)
|
||
createTiddlyButton(place,backstageTask.text,backstageTask.tooltip,function(e) {backstage.switchTab(params[0]); return false;});
|
||
};
|
||
|
||
//--
|
||
//-- ImportTiddlers macro
|
||
//--
|
||
|
||
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
if(readOnly) {
|
||
createTiddlyElement(place,"div",null,"marked",this.readOnlyWarning);
|
||
return;
|
||
}
|
||
var w = new Wizard();
|
||
w.createWizard(place,this.wizardTitle);
|
||
this.restart(w);
|
||
};
|
||
|
||
config.macros.importTiddlers.onCancel = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
wizard.clear();
|
||
config.macros.importTiddlers.restart(wizard);
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.onClose = function(e)
|
||
{
|
||
backstage.hidePanel();
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.restart = function(wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
wizard.addStep(this.step1Title,this.step1Html);
|
||
var t,s = wizard.getElement("selTypes");
|
||
for(t in config.adaptors) {
|
||
var e = createTiddlyElement(s,"option",null,null,config.adaptors[t].serverLabel || t);
|
||
e.value = t;
|
||
}
|
||
if(config.defaultAdaptor)
|
||
s.value = config.defaultAdaptor;
|
||
s = wizard.getElement("selFeeds");
|
||
var feeds = this.getFeeds();
|
||
for(t in feeds) {
|
||
e = createTiddlyElement(s,"option",null,null,t);
|
||
e.value = t;
|
||
}
|
||
wizard.setValue("feeds",feeds);
|
||
s.onchange = me.onFeedChange;
|
||
var fileInput = wizard.getElement("txtBrowse");
|
||
fileInput.onchange = me.onBrowseChange;
|
||
fileInput.onkeyup = me.onBrowseChange;
|
||
wizard.setButtons([{caption: this.openLabel, tooltip: this.openPrompt, onClick: me.onOpen}]);
|
||
wizard.formElem.action = "javascript:;";
|
||
wizard.formElem.onsubmit = function() {
|
||
if(!this.txtPath || this.txtPath.value.length) //# check for manually entered path in first step
|
||
this.lastChild.firstChild.onclick();
|
||
};
|
||
};
|
||
|
||
config.macros.importTiddlers.getFeeds = function()
|
||
{
|
||
var feeds = {};
|
||
var t,tagged = store.getTaggedTiddlers("systemServer","title");
|
||
for(t=0; t<tagged.length; t++) {
|
||
var title = tagged[t].title;
|
||
var serverType = store.getTiddlerSlice(title,"Type");
|
||
if(!serverType)
|
||
serverType = "file";
|
||
feeds[title] = {title: title,
|
||
url: store.getTiddlerSlice(title,"URL"),
|
||
workspace: store.getTiddlerSlice(title,"Workspace"),
|
||
workspaceList: store.getTiddlerSlice(title,"WorkspaceList"),
|
||
tiddlerFilter: store.getTiddlerSlice(title,"TiddlerFilter"),
|
||
serverType: serverType,
|
||
description: store.getTiddlerSlice(title,"Description")};
|
||
}
|
||
return feeds;
|
||
};
|
||
|
||
config.macros.importTiddlers.onFeedChange = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
var selTypes = wizard.getElement("selTypes");
|
||
var fileInput = wizard.getElement("txtPath");
|
||
var feeds = wizard.getValue("feeds");
|
||
var f = feeds[this.value];
|
||
if(f) {
|
||
selTypes.value = f.serverType;
|
||
fileInput.value = f.url;
|
||
wizard.setValue("feedName",f.serverType);
|
||
wizard.setValue("feedHost",f.url);
|
||
wizard.setValue("feedWorkspace",f.workspace);
|
||
wizard.setValue("feedWorkspaceList",f.workspaceList);
|
||
wizard.setValue("feedTiddlerFilter",f.tiddlerFilter);
|
||
}
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.onBrowseChange = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
var file = this.value;
|
||
if(this.files && this.files[0]) {
|
||
file = this.files[0].fileName;
|
||
try {
|
||
if(typeof(netscape) !== "undefined") {
|
||
netscape.security.PrivilegeManager.enablePrivilege("UniversalFileRead");
|
||
}
|
||
} catch (ex) {
|
||
showException(ex);
|
||
}
|
||
}
|
||
var fileInput = wizard.getElement("txtPath");
|
||
fileInput.value = config.macros.importTiddlers.getURLFromLocalPath(file);
|
||
var serverType = wizard.getElement("selTypes");
|
||
serverType.value = "file";
|
||
return true;
|
||
};
|
||
|
||
config.macros.importTiddlers.getURLFromLocalPath = function(v)
|
||
{
|
||
if(!v || !v.length)
|
||
return v;
|
||
v = v.replace(/\\/g,"/"); // use "/" for cross-platform consistency
|
||
var u;
|
||
var t = v.split(":");
|
||
var p = t[1] || t[0]; // remove drive letter (if any)
|
||
if(t[1] && (t[0] == "http" || t[0] == "https" || t[0] == "file")) {
|
||
u = v;
|
||
} else if(p.substr(0,1)=="/") {
|
||
u = document.location.protocol + "//" + document.location.hostname + (t[1] ? "/" : "") + v;
|
||
} else {
|
||
var c = document.location.href.replace(/\\/g,"/");
|
||
var pos = c.lastIndexOf("/");
|
||
if(pos!=-1)
|
||
c = c.substr(0,pos); // remove filename
|
||
u = c + "/" + p;
|
||
}
|
||
return u;
|
||
};
|
||
|
||
config.macros.importTiddlers.onOpen = function(e)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
var wizard = new Wizard(this);
|
||
var fileInput = wizard.getElement("txtPath");
|
||
var url = fileInput.value;
|
||
var serverType = wizard.getElement("selTypes").value || config.defaultAdaptor;
|
||
var adaptor = new config.adaptors[serverType]();
|
||
wizard.setValue("adaptor",adaptor);
|
||
wizard.setValue("serverType",serverType);
|
||
wizard.setValue("host",url);
|
||
adaptor.openHost(url,null,wizard,me.onOpenHost);
|
||
wizard.setButtons([{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}],me.statusOpenHost);
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.onOpenHost = function(context,wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
var adaptor = wizard.getValue("adaptor");
|
||
if(context.status !== true)
|
||
displayMessage("Error in importTiddlers.onOpenHost: " + context.statusText);
|
||
adaptor.getWorkspaceList(context,wizard,me.onGetWorkspaceList);
|
||
wizard.setButtons([{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}],me.statusGetWorkspaceList);
|
||
};
|
||
|
||
config.macros.importTiddlers.onGetWorkspaceList = function(context,wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
if(context.status !== true)
|
||
displayMessage("Error in importTiddlers.onGetWorkspaceList: " + context.statusText);
|
||
wizard.setValue("context",context);
|
||
var workspace = wizard.getValue("feedWorkspace");
|
||
if(!workspace && context.workspaces.length==1)
|
||
workspace = context.workspaces[0].title;
|
||
if(workspace) {
|
||
context.adaptor.openWorkspace(workspace,context,wizard,me.onOpenWorkspace);
|
||
wizard.setValue("workspace",workspace);
|
||
wizard.setButtons([{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}],me.statusOpenWorkspace);
|
||
return;
|
||
}
|
||
wizard.addStep(me.step2Title,me.step2Html);
|
||
var t,s = wizard.getElement("selWorkspace");
|
||
s.onchange = me.onWorkspaceChange;
|
||
for(t=0; t<context.workspaces.length; t++) {
|
||
var e = createTiddlyElement(s,"option",null,null,context.workspaces[t].title);
|
||
e.value = context.workspaces[t].title;
|
||
}
|
||
var workspaceList = wizard.getValue("feedWorkspaceList");
|
||
if(workspaceList) {
|
||
var n,list = workspaceList.parseParams("workspace",null,false,true);
|
||
for(n=1; n<list.length; n++) {
|
||
if(context.workspaces.findByField("title",list[n].value) == null) {
|
||
e = createTiddlyElement(s,"option",null,null,list[n].value);
|
||
e.value = list[n].value;
|
||
}
|
||
}
|
||
}
|
||
if(workspace) {
|
||
t = wizard.getElement("txtWorkspace");
|
||
t.value = workspace;
|
||
}
|
||
wizard.setButtons([{caption: me.openLabel, tooltip: me.openPrompt, onClick: me.onChooseWorkspace}]);
|
||
};
|
||
|
||
config.macros.importTiddlers.onWorkspaceChange = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
var t = wizard.getElement("txtWorkspace");
|
||
t.value = this.value;
|
||
this.selectedIndex = 0;
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.onChooseWorkspace = function(e)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
var wizard = new Wizard(this);
|
||
var adaptor = wizard.getValue("adaptor");
|
||
var workspace = wizard.getElement("txtWorkspace").value;
|
||
wizard.setValue("workspace",workspace);
|
||
var context = wizard.getValue("context");
|
||
adaptor.openWorkspace(workspace,context,wizard,me.onOpenWorkspace);
|
||
wizard.setButtons([{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}],me.statusOpenWorkspace);
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.onOpenWorkspace = function(context,wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
if(context.status !== true)
|
||
displayMessage("Error in importTiddlers.onOpenWorkspace: " + context.statusText);
|
||
var adaptor = wizard.getValue("adaptor");
|
||
adaptor.getTiddlerList(context,wizard,me.onGetTiddlerList,wizard.getValue("feedTiddlerFilter"));
|
||
wizard.setButtons([{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}],me.statusGetTiddlerList);
|
||
};
|
||
|
||
config.macros.importTiddlers.onGetTiddlerList = function(context,wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
if(context.status !== true) {
|
||
var error = context.statusText||me.errorGettingTiddlerList;
|
||
if(context.host.indexOf("file://") === 0) {
|
||
error = me.errorGettingTiddlerListFile;
|
||
} else {
|
||
error = context.xhr && context.xhr.status == 404 ? me.errorGettingTiddlerListHttp404 :
|
||
me.errorGettingTiddlerListHttp;
|
||
}
|
||
wizard.setButtons([{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}],"");
|
||
jQuery("span.status", wizard.footerEl).html(error); // so error message can be html
|
||
return;
|
||
}
|
||
// Extract data for the listview
|
||
var listedTiddlers = [];
|
||
if(context.tiddlers) {
|
||
var n;
|
||
for(n=0; n<context.tiddlers.length; n++) {
|
||
var tiddler = context.tiddlers[n];
|
||
listedTiddlers.push({
|
||
title: tiddler.title,
|
||
modified: tiddler.modified,
|
||
modifier: tiddler.modifier,
|
||
text: tiddler.text ? wikifyPlainText(tiddler.text,100) : "",
|
||
tags: tiddler.tags,
|
||
size: tiddler.text ? tiddler.text.length : 0,
|
||
tiddler: tiddler
|
||
});
|
||
}
|
||
}
|
||
listedTiddlers.sort(function(a,b) {return a.title < b.title ? -1 : (a.title == b.title ? 0 : +1);});
|
||
// Display the listview
|
||
wizard.addStep(me.step3Title,me.step3Html);
|
||
var markList = wizard.getElement("markList");
|
||
var listWrapper = document.createElement("div");
|
||
markList.parentNode.insertBefore(listWrapper,markList);
|
||
var listView = ListView.create(listWrapper,listedTiddlers,me.listViewTemplate);
|
||
wizard.setValue("listView",listView);
|
||
wizard.setValue("context",context);
|
||
var txtSaveTiddler = wizard.getElement("txtSaveTiddler");
|
||
txtSaveTiddler.value = me.generateSystemServerName(wizard);
|
||
wizard.setButtons([
|
||
{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel},
|
||
{caption: me.importLabel, tooltip: me.importPrompt, onClick: me.doImport}
|
||
]);
|
||
};
|
||
|
||
config.macros.importTiddlers.generateSystemServerName = function(wizard)
|
||
{
|
||
var serverType = wizard.getValue("serverType");
|
||
var host = wizard.getValue("host");
|
||
var workspace = wizard.getValue("workspace");
|
||
var pattern = config.macros.importTiddlers[workspace ? "systemServerNamePattern" : "systemServerNamePatternNoWorkspace"];
|
||
return pattern.format([serverType,host,workspace]);
|
||
};
|
||
|
||
config.macros.importTiddlers.saveServerTiddler = function(wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
var txtSaveTiddler = wizard.getElement("txtSaveTiddler").value;
|
||
if(store.tiddlerExists(txtSaveTiddler)) {
|
||
if(!confirm(me.confirmOverwriteSaveTiddler.format([txtSaveTiddler])))
|
||
return;
|
||
store.suspendNotifications();
|
||
store.removeTiddler(txtSaveTiddler);
|
||
store.resumeNotifications();
|
||
}
|
||
var serverType = wizard.getValue("serverType");
|
||
var host = wizard.getValue("host");
|
||
var workspace = wizard.getValue("workspace");
|
||
var text = me.serverSaveTemplate.format([serverType,host,workspace]);
|
||
store.saveTiddler(txtSaveTiddler,txtSaveTiddler,text,me.serverSaveModifier,new Date(),["systemServer"]);
|
||
};
|
||
|
||
config.macros.importTiddlers.doImport = function(e)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
var wizard = new Wizard(this);
|
||
if(wizard.getElement("chkSave").checked)
|
||
me.saveServerTiddler(wizard);
|
||
var chkSync = wizard.getElement("chkSync").checked;
|
||
wizard.setValue("sync",chkSync);
|
||
var listView = wizard.getValue("listView");
|
||
var rowNames = ListView.getSelectedRows(listView);
|
||
var adaptor = wizard.getValue("adaptor");
|
||
var overwrite = [];
|
||
var t;
|
||
for(t=0; t<rowNames.length; t++) {
|
||
if(store.tiddlerExists(rowNames[t]))
|
||
overwrite.push(rowNames[t]);
|
||
}
|
||
if(overwrite.length > 0) {
|
||
if(!confirm(me.confirmOverwriteText.format([overwrite.join(", ")])))
|
||
return false;
|
||
}
|
||
wizard.addStep(me.step4Title.format([rowNames.length]),me.step4Html);
|
||
for(t=0; t<rowNames.length; t++) {
|
||
var link = document.createElement("div");
|
||
createTiddlyLink(link,rowNames[t],true);
|
||
var place = wizard.getElement("markReport");
|
||
place.parentNode.insertBefore(link,place);
|
||
}
|
||
wizard.setValue("remainingImports",rowNames.length);
|
||
wizard.setButtons([
|
||
{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}
|
||
],me.statusDoingImport);
|
||
var wizardContext = wizard.getValue("context");
|
||
var tiddlers = wizardContext ? wizardContext.tiddlers : [];
|
||
for(t=0; t<rowNames.length; t++) {
|
||
var context = {
|
||
allowSynchronous:true,
|
||
tiddler:tiddlers[tiddlers.findByField("title",rowNames[t])]
|
||
};
|
||
adaptor.getTiddler(rowNames[t],context,wizard,me.onGetTiddler);
|
||
}
|
||
return false;
|
||
};
|
||
|
||
config.macros.importTiddlers.onGetTiddler = function(context,wizard)
|
||
{
|
||
var me = config.macros.importTiddlers;
|
||
if(!context.status)
|
||
displayMessage("Error in importTiddlers.onGetTiddler: " + context.statusText);
|
||
var tiddler = context.tiddler;
|
||
store.suspendNotifications();
|
||
store.saveTiddler(tiddler.title, tiddler.title, tiddler.text, tiddler.modifier, tiddler.modified, tiddler.tags, tiddler.fields, true, tiddler.created);
|
||
if(!wizard.getValue("sync")) {
|
||
store.setValue(tiddler.title,'server',null);
|
||
}
|
||
store.resumeNotifications();
|
||
if(!context.isSynchronous)
|
||
store.notify(tiddler.title,true);
|
||
var remainingImports = wizard.getValue("remainingImports")-1;
|
||
wizard.setValue("remainingImports",remainingImports);
|
||
if(remainingImports == 0) {
|
||
if(context.isSynchronous) {
|
||
store.notifyAll();
|
||
refreshDisplay();
|
||
}
|
||
wizard.setButtons([
|
||
{caption: me.doneLabel, tooltip: me.donePrompt, onClick: me.onClose}
|
||
],me.statusDoneImport);
|
||
autoSaveChanges();
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Upgrade macro
|
||
//--
|
||
|
||
config.macros.upgrade.handler = function(place)
|
||
{
|
||
var w = new Wizard();
|
||
w.createWizard(place,this.wizardTitle);
|
||
w.addStep(this.step1Title,this.step1Html.format([this.source,this.source]));
|
||
w.setButtons([{caption: this.upgradeLabel, tooltip: this.upgradePrompt, onClick: this.onClickUpgrade}]);
|
||
};
|
||
|
||
config.macros.upgrade.onClickUpgrade = function(e)
|
||
{
|
||
var me = config.macros.upgrade;
|
||
var w = new Wizard(this);
|
||
if(window.location.protocol != "file:") {
|
||
alert(me.errorCantUpgrade);
|
||
return false;
|
||
}
|
||
if(story.areAnyDirty() || store.isDirty()) {
|
||
alert(me.errorNotSaved);
|
||
return false;
|
||
}
|
||
var localPath = getLocalPath(document.location.toString());
|
||
var backupPath = getBackupPath(localPath,me.backupExtension);
|
||
w.setValue("backupPath",backupPath);
|
||
w.setButtons([],me.statusPreparingBackup);
|
||
var original = loadOriginal(localPath);
|
||
w.setButtons([],me.statusSavingBackup);
|
||
var backup = copyFile(backupPath,localPath);
|
||
if(!backup)
|
||
backup = saveFile(backupPath,original);
|
||
if(!backup) {
|
||
w.setButtons([],me.errorSavingBackup);
|
||
alert(me.errorSavingBackup);
|
||
return false;
|
||
}
|
||
w.setButtons([],me.statusLoadingCore);
|
||
var options = {
|
||
type:"GET",
|
||
url:me.source,
|
||
processData:false,
|
||
success:function(data,textStatus,jqXHR) {
|
||
me.onLoadCore(true,w,jqXHR.responseText,me.source,jqXHR);
|
||
},
|
||
error:function(jqXHR,textStatus,errorThrown) {
|
||
me.onLoadCore(false,w,null,me.source,jqXHR);
|
||
}
|
||
};
|
||
ajaxReq(options);
|
||
return false;
|
||
};
|
||
|
||
config.macros.upgrade.onLoadCore = function(status,params,responseText,url,xhr)
|
||
{
|
||
var me = config.macros.upgrade;
|
||
var w = params;
|
||
var errMsg;
|
||
if(!status)
|
||
errMsg = me.errorLoadingCore;
|
||
var newVer = me.extractVersion(responseText);
|
||
if(!newVer)
|
||
errMsg = me.errorCoreFormat;
|
||
if(errMsg) {
|
||
w.setButtons([],errMsg);
|
||
alert(errMsg);
|
||
return;
|
||
}
|
||
var onStartUpgrade = function(e) {
|
||
w.setButtons([],me.statusSavingCore);
|
||
var localPath = getLocalPath(document.location.toString());
|
||
saveFile(localPath,responseText);
|
||
w.setButtons([],me.statusReloadingCore);
|
||
var backupPath = w.getValue("backupPath");
|
||
var newLoc = document.location.toString() + "?time=" + new Date().convertToYYYYMMDDHHMM() + "#upgrade:[[" + encodeURI(backupPath) + "]]";
|
||
window.setTimeout(function () {window.location = newLoc;},10);
|
||
};
|
||
var step2 = [me.step2Html_downgrade,me.step2Html_restore,me.step2Html_upgrade][compareVersions(version,newVer) + 1];
|
||
w.addStep(me.step2Title,step2.format([formatVersion(newVer),formatVersion(version)]));
|
||
w.setButtons([{caption: me.startLabel, tooltip: me.startPrompt, onClick: onStartUpgrade},{caption: me.cancelLabel, tooltip: me.cancelPrompt, onClick: me.onCancel}]);
|
||
};
|
||
|
||
config.macros.upgrade.onCancel = function(e)
|
||
{
|
||
var me = config.macros.upgrade;
|
||
var w = new Wizard(this);
|
||
w.addStep(me.step3Title,me.step3Html);
|
||
w.setButtons([]);
|
||
return false;
|
||
};
|
||
|
||
config.macros.upgrade.extractVersion = function(upgradeFile)
|
||
{
|
||
var re = /^var version = \{title: "([^"]+)", major: (\d+), minor: (\d+), revision: (\d+)(, beta: (\d+)){0,1}, date: new Date\("([^"]+)"\)/mg;
|
||
var m = re.exec(upgradeFile);
|
||
return m ? {title: m[1], major: m[2], minor: m[3], revision: m[4], beta: m[6], date: new Date(m[7])} : null;
|
||
};
|
||
|
||
function upgradeFrom(path)
|
||
{
|
||
var importStore = new TiddlyWiki();
|
||
var tw = loadFile(path);
|
||
if(window.netscape !== undefined)
|
||
tw = convertUTF8ToUnicode(tw);
|
||
importStore.importTiddlyWiki(tw);
|
||
importStore.forEachTiddler(function(title,tiddler) {
|
||
if(!store.getTiddler(title)) {
|
||
store.addTiddler(tiddler);
|
||
}
|
||
});
|
||
refreshDisplay();
|
||
saveChanges(); //# To create appropriate Markup* sections
|
||
alert(config.messages.upgradeDone.format([formatVersion()]));
|
||
window.location = window.location.toString().substr(0,window.location.toString().lastIndexOf("?"));
|
||
}
|
||
|
||
//--
|
||
//-- Sync macro
|
||
//--
|
||
|
||
// Synchronisation handlers
|
||
config.syncers = {};
|
||
|
||
// Sync state.
|
||
var currSync = null;
|
||
|
||
// sync macro
|
||
config.macros.sync.handler = function(place,macroName,params,wikifier,paramString,tiddler)
|
||
{
|
||
if(!wikifier.isStatic)
|
||
this.startSync(place);
|
||
};
|
||
|
||
config.macros.sync.cancelSync = function()
|
||
{
|
||
currSync = null;
|
||
};
|
||
|
||
config.macros.sync.startSync = function(place)
|
||
{
|
||
if(currSync)
|
||
config.macros.sync.cancelSync();
|
||
currSync = {};
|
||
currSync.syncList = this.getSyncableTiddlers();
|
||
currSync.syncTasks = this.createSyncTasks(currSync.syncList);
|
||
this.preProcessSyncableTiddlers(currSync.syncList);
|
||
var wizard = new Wizard();
|
||
currSync.wizard = wizard;
|
||
wizard.createWizard(place,this.wizardTitle);
|
||
wizard.addStep(this.step1Title,this.step1Html);
|
||
var markList = wizard.getElement("markList");
|
||
var listWrapper = document.createElement("div");
|
||
markList.parentNode.insertBefore(listWrapper,markList);
|
||
currSync.listView = ListView.create(listWrapper,currSync.syncList,this.listViewTemplate);
|
||
this.processSyncableTiddlers(currSync.syncList);
|
||
wizard.setButtons([{caption: this.syncLabel, tooltip: this.syncPrompt, onClick: this.doSync}]);
|
||
};
|
||
|
||
config.macros.sync.getSyncableTiddlers = function()
|
||
{
|
||
var list = [];
|
||
store.forEachTiddler(function(title,tiddler) {
|
||
var syncItem = {};
|
||
syncItem.serverType = tiddler.getServerType();
|
||
syncItem.serverHost = tiddler.fields['server.host'];
|
||
if(syncItem.serverType && syncItem.serverHost) {
|
||
syncItem.adaptor = new config.adaptors[syncItem.serverType]();
|
||
syncItem.serverHost = syncItem.adaptor.fullHostName(syncItem.serverHost);
|
||
syncItem.serverWorkspace = tiddler.fields['server.workspace'];
|
||
syncItem.tiddler = tiddler;
|
||
syncItem.title = tiddler.title;
|
||
syncItem.isTouched = tiddler.isTouched();
|
||
syncItem.selected = syncItem.isTouched;
|
||
syncItem.syncStatus = config.macros.sync.syncStatusList[syncItem.isTouched ? "changedLocally" : "none"];
|
||
syncItem.status = syncItem.syncStatus.text;
|
||
list.push(syncItem);
|
||
}
|
||
});
|
||
list.sort(function(a,b) {return a.title < b.title ? -1 : (a.title == b.title ? 0 : +1);});
|
||
return list;
|
||
};
|
||
|
||
config.macros.sync.preProcessSyncableTiddlers = function(syncList)
|
||
{
|
||
var i;
|
||
for(i=0; i<syncList.length; i++) {
|
||
var si = syncList[i];
|
||
si.serverUrl = si.adaptor.generateTiddlerInfo(si.tiddler).uri;
|
||
}
|
||
};
|
||
|
||
config.macros.sync.processSyncableTiddlers = function(syncList)
|
||
{
|
||
var i;
|
||
for(i=0; i<syncList.length; i++) {
|
||
var si = syncList[i];
|
||
if(si.syncStatus.display)
|
||
si.rowElement.style.display = si.syncStatus.display;
|
||
if(si.syncStatus.className)
|
||
si.rowElement.className = si.syncStatus.className;
|
||
}
|
||
};
|
||
|
||
config.macros.sync.createSyncTasks = function(syncList)
|
||
{
|
||
var i,syncTasks = [];
|
||
for(i=0; i<syncList.length; i++) {
|
||
var si = syncList[i];
|
||
var j,r = null;
|
||
for(j=0; j<syncTasks.length; j++) {
|
||
var cst = syncTasks[j];
|
||
if(si.serverType == cst.serverType && si.serverHost == cst.serverHost && si.serverWorkspace == cst.serverWorkspace)
|
||
r = cst;
|
||
}
|
||
if(r) {
|
||
si.syncTask = r;
|
||
r.syncItems.push(si);
|
||
} else {
|
||
si.syncTask = this.createSyncTask(si);
|
||
syncTasks.push(si.syncTask);
|
||
}
|
||
}
|
||
return syncTasks;
|
||
};
|
||
|
||
config.macros.sync.createSyncTask = function(syncItem)
|
||
{
|
||
var st = {};
|
||
st.serverType = syncItem.serverType;
|
||
st.serverHost = syncItem.serverHost;
|
||
st.serverWorkspace = syncItem.serverWorkspace;
|
||
st.syncItems = [syncItem];
|
||
|
||
var getTiddlerListCallback = function(context,sycnItems) {
|
||
var me = config.macros.sync;
|
||
if(!context.status) {
|
||
displayMessage(context.statusText);
|
||
return false;
|
||
}
|
||
syncItems = context.userParams;
|
||
var i,tiddlers = context.tiddlers;
|
||
for(i=0; i<syncItems.length; i++) {
|
||
var si = syncItems[i];
|
||
var f = tiddlers.findByField("title",si.title);
|
||
if(f !== null) {
|
||
if(tiddlers[f].fields['server.page.revision'] > si.tiddler.fields['server.page.revision']) {
|
||
si.syncStatus = me.syncStatusList[si.isTouched ? 'changedBoth' : 'changedServer'];
|
||
}
|
||
} else {
|
||
si.syncStatus = me.syncStatusList.notFound;
|
||
}
|
||
me.updateSyncStatus(si);
|
||
}
|
||
return true;
|
||
};
|
||
|
||
var openWorkspaceCallback = function(context,syncItems) {
|
||
if(context.status) {
|
||
context.adaptor.getTiddlerList(context,syncItems,getTiddlerListCallback);
|
||
return true;
|
||
}
|
||
displayMessage(context.statusText);
|
||
return false;
|
||
};
|
||
|
||
var context = {host:st.serverHost,workspace:st.serverWorkspace};
|
||
syncItem.adaptor.openHost(st.serverHost);
|
||
syncItem.adaptor.openWorkspace(st.serverWorkspace,context,st.syncItems,openWorkspaceCallback);
|
||
return st;
|
||
};
|
||
|
||
config.macros.sync.updateSyncStatus = function(syncItem)
|
||
{
|
||
var e = syncItem.colElements["status"];
|
||
jQuery(e).empty();
|
||
createTiddlyText(e,syncItem.syncStatus.text);
|
||
syncItem.rowElement.style.display = syncItem.syncStatus.display;
|
||
if(syncItem.syncStatus.className)
|
||
syncItem.rowElement.className = syncItem.syncStatus.className;
|
||
};
|
||
|
||
config.macros.sync.doSync = function(e)
|
||
{
|
||
var me = config.macros.sync;
|
||
var getTiddlerCallback = function(context,syncItem) {
|
||
if(syncItem) {
|
||
var tiddler = context.tiddler;
|
||
store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields,true,tiddler.created);
|
||
syncItem.syncStatus = me.syncStatusList.gotFromServer;
|
||
me.updateSyncStatus(syncItem);
|
||
}
|
||
};
|
||
var putTiddlerCallback = function(context,syncItem) {
|
||
if(syncItem) {
|
||
store.resetTiddler(context.title);
|
||
syncItem.syncStatus = me.syncStatusList.putToServer;
|
||
me.updateSyncStatus(syncItem);
|
||
}
|
||
};
|
||
|
||
var rowNames = ListView.getSelectedRows(currSync.listView);
|
||
var i,sl = me.syncStatusList;
|
||
for(i=0; i<currSync.syncList.length; i++) {
|
||
var si = currSync.syncList[i];
|
||
if(rowNames.indexOf(si.title) != -1) {
|
||
var errorMsg = "Error in doSync: ";
|
||
try {
|
||
var r = true;
|
||
switch(si.syncStatus) {
|
||
case sl.changedServer:
|
||
var context = {"workspace": si.serverWorkspace};
|
||
r = si.adaptor.getTiddler(si.title,context,si,getTiddlerCallback);
|
||
break;
|
||
case sl.notFound:
|
||
case sl.changedLocally:
|
||
case sl.changedBoth:
|
||
r = si.adaptor.putTiddler(si.tiddler,null,si,putTiddlerCallback);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if(!r)
|
||
displayMessage(errorMsg + r);
|
||
} catch(ex) {
|
||
if(ex.name == "TypeError")
|
||
displayMessage("sync operation unsupported: " + ex.message);
|
||
else
|
||
displayMessage(errorMsg + ex.message);
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
//--
|
||
//-- Manager UI for groups of tiddlers
|
||
//--
|
||
|
||
config.macros.plugins.handler = function(place,macroName,params,wikifier,paramString)
|
||
{
|
||
var wizard = new Wizard();
|
||
wizard.createWizard(place,this.wizardTitle);
|
||
wizard.addStep(this.step1Title,this.step1Html);
|
||
var markList = wizard.getElement("markList");
|
||
var listWrapper = document.createElement("div");
|
||
markList.parentNode.insertBefore(listWrapper,markList);
|
||
listWrapper.setAttribute("refresh","macro");
|
||
listWrapper.setAttribute("macroName","plugins");
|
||
listWrapper.setAttribute("params",paramString);
|
||
this.refresh(listWrapper,paramString);
|
||
};
|
||
|
||
config.macros.plugins.refresh = function(listWrapper,params)
|
||
{
|
||
var me = config.macros.plugins;
|
||
var wizard = new Wizard(listWrapper);
|
||
var selectedRows = [];
|
||
ListView.forEachSelector(listWrapper,function(e,rowName) {
|
||
if(e.checked)
|
||
selectedRows.push(e.getAttribute("rowName"));
|
||
});
|
||
jQuery(listWrapper).empty();
|
||
params = params.parseParams("anon");
|
||
var plugins = installedPlugins.slice(0);
|
||
var t,tiddler,p;
|
||
var configTiddlers = store.getTaggedTiddlers("systemConfig");
|
||
for(t=0; t<configTiddlers.length; t++) {
|
||
tiddler = configTiddlers[t];
|
||
if(plugins.findByField("title",tiddler.title) == null) {
|
||
p = getPluginInfo(tiddler);
|
||
p.executed = false;
|
||
p.log.splice(0,0,this.skippedText);
|
||
plugins.push(p);
|
||
}
|
||
}
|
||
for(t=0; t<plugins.length; t++) {
|
||
p = plugins[t];
|
||
p.size = p.tiddler.text ? p.tiddler.text.length : 0;
|
||
p.forced = p.tiddler.isTagged("systemConfigForce");
|
||
p.disabled = p.tiddler.isTagged("systemConfigDisable");
|
||
p.Selected = selectedRows.indexOf(plugins[t].title) != -1;
|
||
}
|
||
if(plugins.length == 0) {
|
||
createTiddlyElement(listWrapper,"em",null,null,this.noPluginText);
|
||
wizard.setButtons([]);
|
||
} else {
|
||
var template = readOnly ? this.listViewTemplateReadOnly : this.listViewTemplate;
|
||
var listView = ListView.create(listWrapper,plugins,template,this.onSelectCommand);
|
||
wizard.setValue("listView",listView);
|
||
if(!readOnly) {
|
||
wizard.setButtons([
|
||
{caption: me.removeLabel, tooltip: me.removePrompt, onClick: me.doRemoveTag},
|
||
{caption: me.deleteLabel, tooltip: me.deletePrompt, onClick: me.doDelete}
|
||
]);
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.plugins.doRemoveTag = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
var listView = wizard.getValue("listView");
|
||
var rowNames = ListView.getSelectedRows(listView);
|
||
if(rowNames.length == 0) {
|
||
alert(config.messages.nothingSelected);
|
||
} else {
|
||
var t;
|
||
for(t=0; t<rowNames.length; t++) {
|
||
store.setTiddlerTag(rowNames[t],false,"systemConfig");
|
||
}
|
||
autoSaveChanges();
|
||
}
|
||
};
|
||
|
||
config.macros.plugins.doDelete = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
var listView = wizard.getValue("listView");
|
||
var rowNames = ListView.getSelectedRows(listView);
|
||
if(rowNames.length == 0) {
|
||
alert(config.messages.nothingSelected);
|
||
} else {
|
||
if(confirm(config.macros.plugins.confirmDeleteText.format([rowNames.join(", ")]))) {
|
||
var t;
|
||
for(t=0; t<rowNames.length; t++) {
|
||
store.removeTiddler(rowNames[t]);
|
||
story.closeTiddler(rowNames[t],true);
|
||
}
|
||
}
|
||
autoSaveChanges();
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Message area
|
||
//--
|
||
|
||
function getMessageDiv()
|
||
{
|
||
var msgArea = document.getElementById("messageArea");
|
||
if(!msgArea)
|
||
return null;
|
||
if(!msgArea.hasChildNodes())
|
||
createTiddlyButton(createTiddlyElement(msgArea,"div",null,"messageToolbar"),
|
||
config.messages.messageClose.text,
|
||
config.messages.messageClose.tooltip,
|
||
clearMessage);
|
||
msgArea.style.display = "block";
|
||
return createTiddlyElement(msgArea,"div");
|
||
}
|
||
|
||
function displayMessage(text,linkText)
|
||
{
|
||
var e = getMessageDiv();
|
||
if(!e) {
|
||
alert(text);
|
||
return;
|
||
}
|
||
if(linkText) {
|
||
var link = createTiddlyElement(e,"a",null,null,text);
|
||
link.href = linkText;
|
||
link.target = "_blank";
|
||
} else {
|
||
e.appendChild(document.createTextNode(text));
|
||
}
|
||
}
|
||
|
||
function clearMessage()
|
||
{
|
||
var msgArea = document.getElementById("messageArea");
|
||
if(msgArea) {
|
||
jQuery(msgArea).empty();
|
||
msgArea.style.display = "none";
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//--
|
||
//-- Refresh mechanism
|
||
//--
|
||
|
||
config.notifyTiddlers = [
|
||
{name: "SystemSettings", notify: onSystemSettingsChange},
|
||
{name: "StyleSheetLayout", notify: refreshStyles},
|
||
{name: "StyleSheetColors", notify: refreshStyles},
|
||
{name: "StyleSheet", notify: refreshStyles},
|
||
{name: "StyleSheetPrint", notify: refreshStyles},
|
||
{name: "PageTemplate", notify: refreshPageTemplate},
|
||
{name: "SiteTitle", notify: refreshPageTitle},
|
||
{name: "SiteSubtitle", notify: refreshPageTitle},
|
||
{name: "WindowTitle", notify: refreshPageTitle},
|
||
{name: "ColorPalette", notify: refreshColorPalette},
|
||
{name: null, notify: refreshDisplay}
|
||
];
|
||
|
||
config.refreshers = {
|
||
link: function(e,changeList)
|
||
{
|
||
var title = e.getAttribute("tiddlyLink");
|
||
refreshTiddlyLink(e,title);
|
||
return true;
|
||
},
|
||
|
||
tiddler: function(e,changeList)
|
||
{
|
||
var title = e.getAttribute("tiddler");
|
||
var template = e.getAttribute("template");
|
||
if(changeList && (changeList.indexOf && changeList.indexOf(title) != -1) && !story.isDirty(title))
|
||
story.refreshTiddler(title,template,true);
|
||
else
|
||
refreshElements(e,changeList);
|
||
return true;
|
||
},
|
||
|
||
content: function(e,changeList)
|
||
{
|
||
var title = e.getAttribute("tiddler");
|
||
var force = e.getAttribute("force");
|
||
var args = e.getAttribute("args");
|
||
if(force != null || changeList == null || (changeList.indexOf && changeList.indexOf(title) != -1)) {
|
||
jQuery(e).empty();
|
||
config.macros.tiddler.transclude(e,title,args);
|
||
return true;
|
||
} else
|
||
return false;
|
||
},
|
||
|
||
macro: function(e,changeList)
|
||
{
|
||
var macro = e.getAttribute("macroName");
|
||
var params = e.getAttribute("params");
|
||
if(macro)
|
||
macro = config.macros[macro];
|
||
if(macro && macro.refresh)
|
||
macro.refresh(e,params);
|
||
return true;
|
||
}
|
||
};
|
||
|
||
config.refresherData = {
|
||
styleSheet: "StyleSheet",
|
||
defaultStyleSheet: "StyleSheet",
|
||
pageTemplate: "PageTemplate",
|
||
defaultPageTemplate: "PageTemplate",
|
||
colorPalette: "ColorPalette",
|
||
defaultColorPalette: "ColorPalette"
|
||
};
|
||
|
||
function refreshElements(root,changeList)
|
||
{
|
||
var c,nodes = root.childNodes;
|
||
for(c=0; c<nodes.length; c++) {
|
||
var e = nodes[c], type = null;
|
||
if(e.getAttribute && (e.tagName ? e.tagName != "IFRAME" : true))
|
||
type = e.getAttribute("refresh");
|
||
var refresher = config.refreshers[type];
|
||
var refreshed = false;
|
||
if(refresher != undefined)
|
||
refreshed = refresher(e,changeList);
|
||
if(e.hasChildNodes() && !refreshed)
|
||
refreshElements(e,changeList);
|
||
}
|
||
}
|
||
|
||
function applyHtmlMacros(root,tiddler)
|
||
{
|
||
var e = root.firstChild;
|
||
while(e) {
|
||
var nextChild = e.nextSibling;
|
||
if(e.getAttribute) {
|
||
var macro = e.getAttribute("macro");
|
||
if(macro) {
|
||
e.removeAttribute("macro");
|
||
var params = "";
|
||
var p = macro.indexOf(" ");
|
||
if(p != -1) {
|
||
params = macro.substr(p+1);
|
||
macro = macro.substr(0,p);
|
||
}
|
||
invokeMacro(e,macro,params,null,tiddler);
|
||
}
|
||
}
|
||
if(e.hasChildNodes())
|
||
applyHtmlMacros(e,tiddler);
|
||
e = nextChild;
|
||
}
|
||
}
|
||
|
||
function refreshPageTemplate(title)
|
||
{
|
||
var stash = jQuery("<div/>").appendTo("body").hide()[0];
|
||
var display = story.getContainer();
|
||
var nodes,t;
|
||
if(display) {
|
||
nodes = display.childNodes;
|
||
for(t=nodes.length-1; t>=0; t--)
|
||
stash.appendChild(nodes[t]);
|
||
}
|
||
var wrapper = document.getElementById("contentWrapper");
|
||
|
||
var isAvailable = function(title) {
|
||
var s = title ? title.indexOf(config.textPrimitives.sectionSeparator) : -1;
|
||
if(s!=-1)
|
||
title = title.substr(0,s);
|
||
return store.tiddlerExists(title) || store.isShadowTiddler(title);
|
||
};
|
||
if(!title || !isAvailable(title))
|
||
title = config.refresherData.pageTemplate;
|
||
if(!isAvailable(title))
|
||
title = config.refresherData.defaultPageTemplate; //# this one is always avaialable
|
||
wrapper.innerHTML = store.getRecursiveTiddlerText(title,null,10);
|
||
applyHtmlMacros(wrapper);
|
||
refreshElements(wrapper);
|
||
display = story.getContainer();
|
||
jQuery(display).empty();
|
||
if(!display)
|
||
display = createTiddlyElement(wrapper,"div",story.containerId());
|
||
nodes = stash.childNodes;
|
||
for(t=nodes.length-1; t>=0; t--)
|
||
display.appendChild(nodes[t]);
|
||
jQuery(stash).remove();
|
||
}
|
||
|
||
function refreshDisplay(hint)
|
||
{
|
||
if(typeof hint == "string")
|
||
hint = [hint];
|
||
var e = document.getElementById("contentWrapper");
|
||
refreshElements(e,hint);
|
||
if(backstage.isPanelVisible()) {
|
||
e = document.getElementById("backstage");
|
||
refreshElements(e,hint);
|
||
}
|
||
}
|
||
|
||
function refreshPageTitle()
|
||
{
|
||
document.title = getPageTitle();
|
||
}
|
||
|
||
function getPageTitle()
|
||
{
|
||
return wikifyPlainText(store.getTiddlerText("WindowTitle",""),null,tiddler);
|
||
}
|
||
|
||
function refreshStyles(title,doc)
|
||
{
|
||
setStylesheet(title == null ? "" : store.getRecursiveTiddlerText(title,"",10),title,doc || document);
|
||
}
|
||
|
||
function refreshColorPalette(title)
|
||
{
|
||
if(!startingUp)
|
||
refreshAll();
|
||
}
|
||
|
||
function refreshAll()
|
||
{
|
||
refreshPageTemplate();
|
||
refreshDisplay();
|
||
refreshStyles("StyleSheetLayout");
|
||
refreshStyles("StyleSheetColors");
|
||
refreshStyles(config.refresherData.styleSheet);
|
||
refreshStyles("StyleSheetPrint");
|
||
}
|
||
|
||
//--
|
||
//-- Option handling
|
||
//--
|
||
|
||
config.optionHandlers = {
|
||
'txt': {
|
||
get: function(name) {return encodeCookie(config.options[name].toString());},
|
||
set: function(name,value) {config.options[name] = decodeCookie(value);}
|
||
},
|
||
'chk': {
|
||
get: function(name) {return config.options[name] ? 'true' : 'false';},
|
||
set: function(name,value) {config.options[name] = value == 'true';}
|
||
}
|
||
};
|
||
|
||
function setOption(name,value)
|
||
{
|
||
var optType = name.substr(0,3);
|
||
if(config.optionHandlers[optType] && config.optionHandlers[optType].set)
|
||
config.optionHandlers[optType].set(name,value);
|
||
}
|
||
|
||
// Gets the value of an option as a string. Most code should just read from config.options.* directly
|
||
function getOption(name)
|
||
{
|
||
var optType = name.substr(0,3);
|
||
return config.optionHandlers[optType] && config.optionHandlers[optType].get ? config.optionHandlers[optType].get(name) : null;
|
||
}
|
||
|
||
function loadOptions()
|
||
{
|
||
if(safeMode)
|
||
return;
|
||
loadCookies();
|
||
loadSystemSettings();
|
||
}
|
||
// @Deprecated; retained for backwards compatibility
|
||
var loadOptionsCookie = loadOptions;
|
||
|
||
function getCookies()
|
||
{
|
||
var cookieList = document.cookie.split(';');
|
||
var i,cookies = {};
|
||
for(i=0; i<cookieList.length; i++) {
|
||
var p = cookieList[i].indexOf('=');
|
||
if(p != -1) {
|
||
var name = cookieList[i].substr(0,p).trim();
|
||
var value = cookieList[i].substr(p+1).trim();
|
||
cookies[name] = value;
|
||
}
|
||
}
|
||
return cookies;
|
||
}
|
||
|
||
function loadCookies()
|
||
{
|
||
var i,cookies = getCookies();
|
||
if(cookies['TiddlyWiki']) {
|
||
cookies = cookies['TiddlyWiki'].decodeHashMap();
|
||
}
|
||
for(i in cookies) {
|
||
if(config.optionsSource[i] != 'setting') {
|
||
setOption(i,cookies[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
function loadSystemSettings()
|
||
{
|
||
var key,settings = store.calcAllSlices('SystemSettings');
|
||
config.optionsSource = {};
|
||
for(key in settings) {
|
||
setOption(key,settings[key]);
|
||
config.optionsSource[key] = 'setting';
|
||
}
|
||
}
|
||
|
||
function onSystemSettingsChange()
|
||
{
|
||
if(!startingUp) {
|
||
loadSystemSettings();
|
||
}
|
||
}
|
||
|
||
function saveOption(name)
|
||
{
|
||
if(safeMode)
|
||
return;
|
||
if(name.match(/[()\s]/g, '_')) {
|
||
alert(config.messages.invalidCookie.format([name]));
|
||
return;
|
||
}
|
||
saveCookie(name);
|
||
if(config.optionsSource[name] == 'setting') {
|
||
saveSystemSetting(name,true);
|
||
}
|
||
}
|
||
// @Deprecated; retained for backwards compatibility
|
||
var saveOptionCookie = saveOption;
|
||
|
||
function removeCookie(name)
|
||
{
|
||
document.cookie = name + '=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
|
||
}
|
||
|
||
function saveCookie(name)
|
||
{
|
||
var key,cookies = {};
|
||
for(key in config.options) {
|
||
var value = getOption(key);
|
||
value = value == null ? 'false' : value;
|
||
cookies[key] = value;
|
||
}
|
||
document.cookie = 'TiddlyWiki=' + String.encodeHashMap(cookies) + '; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/';
|
||
cookies = getCookies();
|
||
var c;
|
||
for(c in cookies) {
|
||
var optType = c.substr(0,3);
|
||
if(config.optionHandlers[optType])
|
||
removeCookie(c);
|
||
}
|
||
}
|
||
|
||
var systemSettingSave;
|
||
function commitSystemSettings(storeWasDirty)
|
||
{
|
||
if(systemSettingSave) {
|
||
window.clearTimeout(systemSettingSave);
|
||
}
|
||
systemSettingSave = window.setTimeout(function() {
|
||
var tiddler = store.getTiddler('SystemSettings');
|
||
if(storeWasDirty == false && story.areAnyDirty() == false) {
|
||
saveChanges(null,[tiddler]);
|
||
} else {
|
||
autoSaveChanges(null,[tiddler]);
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
function saveSystemSetting(name,saveFile)
|
||
{
|
||
var title = 'SystemSettings';
|
||
var slice = store.getTiddlerSlice(title,name);
|
||
if(readOnly || slice === getOption(name)) {
|
||
return; //# don't save if read-only or the option hasn't changed
|
||
}
|
||
var slices = store.calcAllSlices(title);
|
||
var key;
|
||
for(key in config.optionsSource) {
|
||
var value = getOption(key) || '';
|
||
if(slices[key] !== value) {
|
||
slices[key] = value;
|
||
}
|
||
}
|
||
var text = [];
|
||
for(key in slices) {
|
||
text.push('%0: %1'.format([key,slices[key]]));
|
||
}
|
||
text = text.sort().join('\n');
|
||
var storeWasDirty = store.isDirty();
|
||
var tiddler = store.getTiddler(title);
|
||
if(tiddler) {
|
||
tiddler.text = text;
|
||
tiddler = store.saveTiddler(tiddler);
|
||
} else {
|
||
tiddler = store.saveTiddler(title,title,text,'System',new Date(),['excludeLists'],config.defaultCustomFields);
|
||
}
|
||
if(saveFile) {
|
||
commitSystemSettings(storeWasDirty);
|
||
}
|
||
}
|
||
|
||
function encodeCookie(s)
|
||
{
|
||
return escape(convertUnicodeToHtmlEntities(s));
|
||
}
|
||
|
||
function decodeCookie(s)
|
||
{
|
||
s = unescape(s);
|
||
var re = /&#[0-9]{1,5};/g;
|
||
return s.replace(re,function($0) {return String.fromCharCode(eval($0.replace(/[&#;]/g,'')));});
|
||
}
|
||
|
||
config.macros.option.genericCreate = function(place,type,opt,className,desc)
|
||
{
|
||
var typeInfo = config.macros.option.types[type];
|
||
var c = document.createElement(typeInfo.elementType);
|
||
if(typeInfo.typeValue)
|
||
c.setAttribute('type',typeInfo.typeValue);
|
||
c[typeInfo.eventName] = typeInfo.onChange;
|
||
c.setAttribute('option',opt);
|
||
c.className = className || typeInfo.className;
|
||
if(config.optionsDesc[opt])
|
||
c.setAttribute('title',config.optionsDesc[opt]);
|
||
place.appendChild(c);
|
||
if(desc != 'no')
|
||
createTiddlyText(place,config.optionsDesc[opt] || opt);
|
||
c[typeInfo.valueField] = config.options[opt];
|
||
return c;
|
||
};
|
||
|
||
config.macros.option.genericOnChange = function(e)
|
||
{
|
||
var opt = this.getAttribute('option');
|
||
if(opt) {
|
||
var optType = opt.substr(0,3);
|
||
var handler = config.macros.option.types[optType];
|
||
if(handler.elementType && handler.valueField)
|
||
config.macros.option.propagateOption(opt,handler.valueField,this[handler.valueField],handler.elementType,this);
|
||
}
|
||
return true;
|
||
};
|
||
|
||
config.macros.option.types = {
|
||
'txt': {
|
||
elementType: 'input',
|
||
valueField: 'value',
|
||
eventName: 'onchange',
|
||
className: 'txtOptionInput',
|
||
create: config.macros.option.genericCreate,
|
||
onChange: config.macros.option.genericOnChange
|
||
},
|
||
'chk': {
|
||
elementType: 'input',
|
||
valueField: 'checked',
|
||
eventName: 'onclick',
|
||
className: 'chkOptionInput',
|
||
typeValue: 'checkbox',
|
||
create: config.macros.option.genericCreate,
|
||
onChange: config.macros.option.genericOnChange
|
||
}
|
||
};
|
||
|
||
config.macros.option.propagateOption = function(opt,valueField,value,elementType,elem)
|
||
{
|
||
config.options[opt] = value;
|
||
saveOption(opt);
|
||
var t,nodes = document.getElementsByTagName(elementType);
|
||
for(t=0; t<nodes.length; t++) {
|
||
var optNode = nodes[t].getAttribute('option');
|
||
if(opt == optNode && nodes[t]!=elem)
|
||
nodes[t][valueField] = value;
|
||
}
|
||
};
|
||
|
||
config.macros.option.handler = function(place,macroName,params,wikifier,paramString)
|
||
{
|
||
params = paramString.parseParams('anon',null,true,false,false);
|
||
var opt = (params[1] && params[1].name == 'anon') ? params[1].value : getParam(params,'name',null);
|
||
var className = (params[2] && params[2].name == 'anon') ? params[2].value : getParam(params,'class',null);
|
||
var desc = getParam(params,'desc','no');
|
||
var type = opt.substr(0,3);
|
||
var h = config.macros.option.types[type];
|
||
if(h && h.create)
|
||
h.create(place,type,opt,className,desc);
|
||
};
|
||
|
||
config.macros.options.handler = function(place,macroName,params,wikifier,paramString)
|
||
{
|
||
params = paramString.parseParams('anon',null,true,false,false);
|
||
var showUnknown = getParam(params,'showUnknown','no');
|
||
var wizard = new Wizard();
|
||
wizard.createWizard(place,this.wizardTitle);
|
||
wizard.addStep(this.step1Title,this.step1Html);
|
||
var markList = wizard.getElement('markList');
|
||
var chkUnknown = wizard.getElement('chkUnknown');
|
||
chkUnknown.checked = showUnknown == 'yes';
|
||
chkUnknown.onchange = this.onChangeUnknown;
|
||
var listWrapper = document.createElement('div');
|
||
markList.parentNode.insertBefore(listWrapper,markList);
|
||
wizard.setValue('listWrapper',listWrapper);
|
||
this.refreshOptions(listWrapper,showUnknown == 'yes');
|
||
};
|
||
|
||
config.macros.options.refreshOptions = function(listWrapper,showUnknown)
|
||
{
|
||
var n,opts = [];
|
||
for(n in config.options) {
|
||
var opt = {};
|
||
opt.option = '';
|
||
opt.name = n;
|
||
opt.lowlight = !config.optionsDesc[n];
|
||
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
|
||
if(!opt.lowlight || showUnknown)
|
||
opts.push(opt);
|
||
}
|
||
opts.sort(function(a,b) {return a.name.substr(3) < b.name.substr(3) ? -1 : (a.name.substr(3) == b.name.substr(3) ? 0 : +1);});
|
||
ListView.create(listWrapper,opts,this.listViewTemplate);
|
||
for(n=0; n<opts.length; n++) {
|
||
var type = opts[n].name.substr(0,3);
|
||
var h = config.macros.option.types[type];
|
||
if(h && h.create) {
|
||
h.create(opts[n].colElements['option'],type,opts[n].name,null,'no');
|
||
}
|
||
}
|
||
};
|
||
|
||
config.macros.options.onChangeUnknown = function(e)
|
||
{
|
||
var wizard = new Wizard(this);
|
||
var listWrapper = wizard.getValue('listWrapper');
|
||
jQuery(listWrapper).empty();
|
||
config.macros.options.refreshOptions(listWrapper,this.checked);
|
||
return false;
|
||
};
|
||
|
||
//--
|
||
//-- Saving
|
||
//--
|
||
|
||
var saveUsingSafari = false;
|
||
|
||
var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it
|
||
var startSaveAreaRE = /<((div)|(DIV)) ((id)|(ID))=["']?storeArea['"]?>/; // Used for IE6
|
||
var endSaveArea = '</d' + 'iv>';
|
||
var endSaveAreaCaps = '</D' + 'IV>';
|
||
|
||
// If there are unsaved changes, force the user to confirm before exitting
|
||
function confirmExit()
|
||
{
|
||
hadConfirmExit = true;
|
||
if((store && store.isDirty && store.isDirty()) || (story && story.areAnyDirty && story.areAnyDirty()))
|
||
return config.messages.confirmExit;
|
||
}
|
||
|
||
// Give the user a chance to save changes before exitting
|
||
function checkUnsavedChanges()
|
||
{
|
||
if(store && store.isDirty && store.isDirty() && window.hadConfirmExit === false) {
|
||
if(confirm(config.messages.unsavedChangesWarning))
|
||
saveChanges();
|
||
}
|
||
}
|
||
|
||
function updateLanguageAttribute(s)
|
||
{
|
||
if(config.locale) {
|
||
var mRE = /(<html(?:.*?)?)(?: xml:lang\="([a-z]+)")?(?: lang\="([a-z]+)")?>/;
|
||
var m = mRE.exec(s);
|
||
if(m) {
|
||
var t = m[1];
|
||
if(m[2])
|
||
t += ' xml:lang="' + config.locale + '"';
|
||
if(m[3])
|
||
t += ' lang="' + config.locale + '"';
|
||
t += ">";
|
||
s = s.substr(0,m.index) + t + s.substr(m.index+m[0].length);
|
||
}
|
||
}
|
||
return s;
|
||
}
|
||
|
||
function updateMarkupBlock(s,blockName,tiddlerName)
|
||
{
|
||
return s.replaceChunk(
|
||
"<!--%0-START-->".format([blockName]),
|
||
"<!--%0-END-->".format([blockName]),
|
||
"\n" + convertUnicodeToFileFormat(store.getRecursiveTiddlerText(tiddlerName,"")) + "\n");
|
||
}
|
||
|
||
function updateOriginal(original,posDiv,localPath)
|
||
{
|
||
if(!posDiv)
|
||
posDiv = locateStoreArea(original);
|
||
if(!posDiv) {
|
||
alert(config.messages.invalidFileError.format([localPath]));
|
||
return null;
|
||
}
|
||
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
|
||
convertUnicodeToFileFormat(store.allTiddlersAsHtml()) + "\n" +
|
||
original.substr(posDiv[1]);
|
||
var newSiteTitle = convertUnicodeToFileFormat(getPageTitle()).htmlEncode();
|
||
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
|
||
revised = updateLanguageAttribute(revised);
|
||
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
|
||
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
|
||
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
|
||
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
|
||
return revised;
|
||
}
|
||
|
||
function locateStoreArea(original)
|
||
{
|
||
// Locate the storeArea divs
|
||
if(!original)
|
||
return null;
|
||
var posOpeningDiv = original.search(startSaveAreaRE);
|
||
var limitClosingDiv = original.indexOf("<"+"!--POST-STOREAREA--"+">");
|
||
if(limitClosingDiv == -1)
|
||
limitClosingDiv = original.indexOf("<"+"!--POST-BODY-START--"+">");
|
||
var start = limitClosingDiv == -1 ? original.length : limitClosingDiv;
|
||
var posClosingDiv = original.lastIndexOf(endSaveArea,start);
|
||
if(posClosingDiv == -1)
|
||
posClosingDiv = original.lastIndexOf(endSaveAreaCaps,start);
|
||
return (posOpeningDiv != -1 && posClosingDiv != -1) ? [posOpeningDiv,posClosingDiv] : null;
|
||
}
|
||
|
||
function autoSaveChanges(onlyIfDirty,tiddlers)
|
||
{
|
||
if(config.options.chkAutoSave)
|
||
saveChanges(onlyIfDirty,tiddlers);
|
||
}
|
||
|
||
function loadOriginal(localPath)
|
||
{
|
||
return loadFile(localPath);
|
||
}
|
||
|
||
// Save this tiddlywiki with the pending changes
|
||
function saveChanges(onlyIfDirty,tiddlers)
|
||
{
|
||
if(onlyIfDirty && !store.isDirty())
|
||
return;
|
||
clearMessage();
|
||
var t0 = new Date();
|
||
var msg = config.messages;
|
||
var originalPath = document.location.toString();
|
||
if(originalPath.substr(0,5) != "file:") {
|
||
alert(msg.notFileUrlError);
|
||
if(store.tiddlerExists(msg.saveInstructions))
|
||
story.displayTiddler(null,msg.saveInstructions);
|
||
return;
|
||
}
|
||
var localPath = getLocalPath(originalPath);
|
||
var original = loadOriginal(localPath);
|
||
if(original == null) {
|
||
alert(msg.cantSaveError);
|
||
if(store.tiddlerExists(msg.saveInstructions))
|
||
story.displayTiddler(null,msg.saveInstructions);
|
||
return;
|
||
}
|
||
var posDiv = locateStoreArea(original);
|
||
if(!posDiv) {
|
||
alert(msg.invalidFileError.format([localPath]));
|
||
return;
|
||
}
|
||
saveMain(localPath,original,posDiv);
|
||
if(config.options.chkSaveBackups)
|
||
saveBackup(localPath,original);
|
||
if(config.options.chkSaveEmptyTemplate)
|
||
saveEmpty(localPath,original,posDiv);
|
||
if(config.options.chkGenerateAnRssFeed && saveRss instanceof Function)
|
||
saveRss(localPath);
|
||
if(config.options.chkDisplayInstrumentation)
|
||
displayMessage("saveChanges " + (new Date()-t0) + " ms");
|
||
}
|
||
|
||
function saveMain(localPath,original,posDiv)
|
||
{
|
||
var save;
|
||
try {
|
||
var revised = updateOriginal(original,posDiv,localPath);
|
||
save = saveFile(localPath,revised);
|
||
} catch (ex) {
|
||
showException(ex);
|
||
}
|
||
if(save) {
|
||
displayMessage(config.messages.mainSaved,"file://" + localPath);
|
||
store.setDirty(false);
|
||
} else {
|
||
alert(config.messages.mainFailed);
|
||
}
|
||
}
|
||
|
||
function saveBackup(localPath,original)
|
||
{
|
||
var backupPath = getBackupPath(localPath);
|
||
var backup = copyFile(backupPath,localPath);
|
||
if(!backup)
|
||
backup = saveFile(backupPath,original);
|
||
if(backup)
|
||
displayMessage(config.messages.backupSaved,"file://" + backupPath);
|
||
else
|
||
alert(config.messages.backupFailed);
|
||
}
|
||
|
||
function saveEmpty(localPath,original,posDiv)
|
||
{
|
||
var emptyPath,p;
|
||
if((p = localPath.lastIndexOf("/")) != -1)
|
||
emptyPath = localPath.substr(0,p) + "/";
|
||
else if((p = localPath.lastIndexOf("\\")) != -1)
|
||
emptyPath = localPath.substr(0,p) + "\\";
|
||
else
|
||
emptyPath = localPath + ".";
|
||
emptyPath += "empty.html";
|
||
var empty = original.substr(0,posDiv[0] + startSaveArea.length) + original.substr(posDiv[1]);
|
||
var emptySave = saveFile(emptyPath,empty);
|
||
if(emptySave)
|
||
displayMessage(config.messages.emptySaved,"file://" + emptyPath);
|
||
else
|
||
alert(config.messages.emptyFailed);
|
||
}
|
||
|
||
function getLocalPath(origPath)
|
||
{
|
||
var originalPath = convertUriToUTF8(origPath,config.options.txtFileSystemCharSet);
|
||
// Remove any location or query part of the URL
|
||
var argPos = originalPath.indexOf("?");
|
||
if(argPos != -1)
|
||
originalPath = originalPath.substr(0,argPos);
|
||
var hashPos = originalPath.indexOf("#");
|
||
if(hashPos != -1)
|
||
originalPath = originalPath.substr(0,hashPos);
|
||
// Convert file://localhost/ to file:///
|
||
if(originalPath.indexOf("file://localhost/") == 0)
|
||
originalPath = "file://" + originalPath.substr(16);
|
||
// Convert to a native file format
|
||
var localPath;
|
||
if(originalPath.charAt(9) == ":") // pc local file
|
||
localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
|
||
else if(originalPath.indexOf("file://///") == 0) // FireFox pc network file
|
||
localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
|
||
else if(originalPath.indexOf("file:///") == 0) // mac/unix local file
|
||
localPath = unescape(originalPath.substr(7));
|
||
else if(originalPath.indexOf("file:/") == 0) // mac/unix local file
|
||
localPath = unescape(originalPath.substr(5));
|
||
else // pc network file
|
||
localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
|
||
return localPath;
|
||
}
|
||
|
||
function getBackupPath(localPath,title,extension)
|
||
{
|
||
var slash = "\\";
|
||
var dirPathPos = localPath.lastIndexOf("\\");
|
||
if(dirPathPos == -1) {
|
||
dirPathPos = localPath.lastIndexOf("/");
|
||
slash = "/";
|
||
}
|
||
var backupFolder = config.options.txtBackupFolder;
|
||
if(!backupFolder || backupFolder == "")
|
||
backupFolder = ".";
|
||
var backupPath = localPath.substr(0,dirPathPos) + slash + backupFolder + localPath.substr(dirPathPos);
|
||
backupPath = backupPath.substr(0,backupPath.lastIndexOf(".")) + ".";
|
||
if(title)
|
||
backupPath += title.replace(/[\\\/\*\?\":<> ]/g,"_") + ".";
|
||
backupPath += (new Date()).convertToYYYYMMDDHHMMSSMMM() + "." + (extension || "html");
|
||
return backupPath;
|
||
}
|
||
|
||
//--
|
||
//-- RSS Saving
|
||
//--
|
||
|
||
function saveRss(localPath)
|
||
{
|
||
var rssPath = localPath.substr(0,localPath.lastIndexOf(".")) + ".xml";
|
||
if(saveFile(rssPath,convertUnicodeToFileFormat(generateRss())))
|
||
displayMessage(config.messages.rssSaved,"file://" + rssPath);
|
||
else
|
||
alert(config.messages.rssFailed);
|
||
}
|
||
|
||
tiddlerToRssItem = function(tiddler,uri)
|
||
{
|
||
var s = "<title" + ">" + tiddler.title.htmlEncode() + "</title" + ">\n";
|
||
s += "<description>" + wikifyStatic(tiddler.text,null,tiddler).htmlEncode() + "</description>\n";
|
||
var i;
|
||
for(i=0; i<tiddler.tags.length; i++)
|
||
s += "<category>" + tiddler.tags[i] + "</category>\n";
|
||
s += "<link>" + uri + "#" + encodeURIComponent(String.encodeTiddlyLink(tiddler.title)) + "</link>\n";
|
||
s +="<pubDate>" + tiddler.modified.toGMTString() + "</pubDate>\n";
|
||
return s;
|
||
};
|
||
|
||
function generateRss()
|
||
{
|
||
var s = [];
|
||
var d = new Date();
|
||
var u = store.getTiddlerText("SiteUrl");
|
||
// Assemble the header
|
||
s.push("<" + "?xml version=\"1.0\"?" + ">");
|
||
s.push("<rss version=\"2.0\">");
|
||
s.push("<channel>");
|
||
s.push("<title" + ">" + wikifyPlainText(store.getTiddlerText("SiteTitle",""),null,tiddler).htmlEncode() + "</title" + ">");
|
||
if(u)
|
||
s.push("<link>" + u.htmlEncode() + "</link>");
|
||
s.push("<description>" + wikifyPlainText(store.getTiddlerText("SiteSubtitle",""),null,tiddler).htmlEncode() + "</description>");
|
||
s.push("<language>" + config.locale + "</language>");
|
||
s.push("<copyright>Copyright " + d.getFullYear() + " " + config.options.txtUserName.htmlEncode() + "</copyright>");
|
||
s.push("<pubDate>" + d.toGMTString() + "</pubDate>");
|
||
s.push("<lastBuildDate>" + d.toGMTString() + "</lastBuildDate>");
|
||
s.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
|
||
s.push("<generator>TiddlyWiki " + formatVersion() + "</generator>");
|
||
// The body
|
||
var tiddlers = store.getTiddlers("modified","excludeLists");
|
||
var i,n = config.numRssItems > tiddlers.length ? 0 : tiddlers.length-config.numRssItems;
|
||
for(i=tiddlers.length-1; i>=n; i--) {
|
||
s.push("<item>\n" + tiddlerToRssItem(tiddlers[i],u) + "\n</item>");
|
||
}
|
||
// And footer
|
||
s.push("</channel>");
|
||
s.push("</rss>");
|
||
// Save it all
|
||
return s.join("\n");
|
||
}
|
||
|
||
//--
|
||
//-- Filesystem code
|
||
//--
|
||
|
||
function convertUTF8ToUnicode(u)
|
||
{
|
||
return config.browser.isOpera || !window.netscape ? manualConvertUTF8ToUnicode(u) : mozConvertUTF8ToUnicode(u);
|
||
}
|
||
|
||
function manualConvertUTF8ToUnicode(utf)
|
||
{
|
||
var uni = utf;
|
||
var src = 0;
|
||
var dst = 0;
|
||
var b1, b2, b3;
|
||
var c;
|
||
while(src < utf.length) {
|
||
b1 = utf.charCodeAt(src++);
|
||
if(b1 < 0x80) {
|
||
dst++;
|
||
} else if(b1 < 0xE0) {
|
||
b2 = utf.charCodeAt(src++);
|
||
c = String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
|
||
uni = uni.substring(0,dst++).concat(c,utf.substr(src));
|
||
} else {
|
||
b2 = utf.charCodeAt(src++);
|
||
b3 = utf.charCodeAt(src++);
|
||
c = String.fromCharCode(((b1 & 0xF) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F));
|
||
uni = uni.substring(0,dst++).concat(c,utf.substr(src));
|
||
}
|
||
}
|
||
return uni;
|
||
}
|
||
|
||
function mozConvertUTF8ToUnicode(u)
|
||
{
|
||
try {
|
||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||
converter.charset = "UTF-8";
|
||
} catch(ex) {
|
||
return manualConvertUTF8ToUnicode(u);
|
||
} // fallback
|
||
var s = converter.ConvertToUnicode(u);
|
||
var fin = converter.Finish();
|
||
return fin.length > 0 ? s+fin : s;
|
||
}
|
||
|
||
function convertUnicodeToFileFormat(s)
|
||
{
|
||
return config.browser.isOpera || !window.netscape ? (config.browser.isIE ? convertUnicodeToHtmlEntities(s) : s) : mozConvertUnicodeToUTF8(s);
|
||
}
|
||
|
||
function convertUnicodeToHtmlEntities(s)
|
||
{
|
||
var re = /[^\u0000-\u007F]/g;
|
||
return s.replace(re,function($0) {return "&#" + $0.charCodeAt(0).toString() + ";";});
|
||
}
|
||
|
||
function convertUnicodeToUTF8(s)
|
||
{
|
||
// return convertUnicodeToFileFormat to allow plugin migration
|
||
return convertUnicodeToFileFormat(s);
|
||
}
|
||
|
||
function manualConvertUnicodeToUTF8(s)
|
||
{
|
||
return unescape(encodeURIComponent(s));
|
||
}
|
||
|
||
function mozConvertUnicodeToUTF8(s)
|
||
{
|
||
try {
|
||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||
converter.charset = "UTF-8";
|
||
} catch(ex) {
|
||
return manualConvertUnicodeToUTF8(s);
|
||
} // fallback
|
||
var u = converter.ConvertFromUnicode(s);
|
||
var fin = converter.Finish();
|
||
return fin.length > 0 ? u + fin : u;
|
||
}
|
||
|
||
function convertUriToUTF8(uri,charSet)
|
||
{
|
||
if(window.netscape == undefined || charSet == undefined || charSet == "")
|
||
return uri;
|
||
try {
|
||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||
var converter = Components.classes["@mozilla.org/intl/utf8converterservice;1"].getService(Components.interfaces.nsIUTF8ConverterService);
|
||
} catch(ex) {
|
||
return uri;
|
||
}
|
||
return converter.convertURISpecToUTF8(uri,charSet);
|
||
}
|
||
|
||
function copyFile(dest,source)
|
||
{
|
||
return config.browser.isIE ? ieCopyFile(dest,source) : false;
|
||
}
|
||
|
||
function saveFile(fileUrl,content)
|
||
{
|
||
var r = mozillaSaveFile(fileUrl,content);
|
||
if(!r)
|
||
r = ieSaveFile(fileUrl,content);
|
||
if(!r)
|
||
r = javaSaveFile(fileUrl,content);
|
||
return r;
|
||
}
|
||
|
||
function loadFile(fileUrl)
|
||
{
|
||
var r = mozillaLoadFile(fileUrl);
|
||
if((r == null) || (r == false))
|
||
r = ieLoadFile(fileUrl);
|
||
if((r == null) || (r == false))
|
||
r = javaLoadFile(fileUrl);
|
||
return r;
|
||
}
|
||
|
||
function ieCreatePath(path)
|
||
{
|
||
try {
|
||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||
} catch(ex) {
|
||
return null;
|
||
}
|
||
|
||
var pos = path.lastIndexOf("\\");
|
||
if(pos==-1)
|
||
pos = path.lastIndexOf("/");
|
||
if(pos!=-1)
|
||
path = path.substring(0,pos+1);
|
||
|
||
var scan = [path];
|
||
var parent = fso.GetParentFolderName(path);
|
||
while(parent && !fso.FolderExists(parent)) {
|
||
scan.push(parent);
|
||
parent = fso.GetParentFolderName(parent);
|
||
}
|
||
|
||
for(i=scan.length-1;i>=0;i--) {
|
||
if(!fso.FolderExists(scan[i])) {
|
||
fso.CreateFolder(scan[i]);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// Returns null if it can't do it, false if there's an error, true if it saved OK
|
||
function ieSaveFile(filePath,content)
|
||
{
|
||
ieCreatePath(filePath);
|
||
try {
|
||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||
} catch(ex) {
|
||
return null;
|
||
}
|
||
var file = fso.OpenTextFile(filePath,2,-1,0);
|
||
file.Write(content);
|
||
file.Close();
|
||
return true;
|
||
}
|
||
|
||
// Returns null if it can't do it, false if there's an error, or a string of the content if successful
|
||
function ieLoadFile(filePath)
|
||
{
|
||
try {
|
||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||
var file = fso.OpenTextFile(filePath,1);
|
||
var content = file.ReadAll();
|
||
file.Close();
|
||
} catch(ex) {
|
||
return null;
|
||
}
|
||
return content;
|
||
}
|
||
|
||
function ieCopyFile(dest,source)
|
||
{
|
||
ieCreatePath(dest);
|
||
try {
|
||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||
fso.GetFile(source).Copy(dest);
|
||
} catch(ex) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// Returns null if it can't do it, false if there's an error, true if it saved OK
|
||
function mozillaSaveFile(filePath,content)
|
||
{
|
||
if(window.Components) {
|
||
try {
|
||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
|
||
file.initWithPath(filePath);
|
||
if(!file.exists())
|
||
file.create(0,0x01B4);// 0x01B4 = 0664
|
||
var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
|
||
out.init(file,0x22,0x04,null);
|
||
out.write(content,content.length);
|
||
out.flush();
|
||
out.close();
|
||
return true;
|
||
} catch(ex) {
|
||
return false;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
// Returns null if it can't do it, false if there's an error, or a string of the content if successful
|
||
function mozillaLoadFile(filePath)
|
||
{
|
||
if(window.Components) {
|
||
try {
|
||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
|
||
file.initWithPath(filePath);
|
||
if(!file.exists())
|
||
return null;
|
||
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
|
||
inputStream.init(file,0x01,0x04,null);
|
||
var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
|
||
sInputStream.init(inputStream);
|
||
var contents = sInputStream.read(sInputStream.available());
|
||
sInputStream.close();
|
||
inputStream.close();
|
||
return contents;
|
||
} catch(ex) {
|
||
return false;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function javaUrlToFilename(url)
|
||
{
|
||
var f = "//localhost";
|
||
if(url.indexOf(f) == 0)
|
||
return url.substring(f.length);
|
||
var i = url.indexOf(":");
|
||
return i > 0 ? url.substring(i-1) : url;
|
||
}
|
||
|
||
function javaSaveFile(filePath,content)
|
||
{
|
||
try {
|
||
if(document.applets["TiddlySaver"])
|
||
return document.applets["TiddlySaver"].saveFile(javaUrlToFilename(filePath),"UTF-8",content);
|
||
} catch(ex) {
|
||
}
|
||
try {
|
||
var s = new java.io.PrintStream(new java.io.FileOutputStream(javaUrlToFilename(filePath)));
|
||
s.print(content);
|
||
s.close();
|
||
} catch(ex2) {
|
||
return null;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function javaLoadFile(filePath)
|
||
{
|
||
try {
|
||
if(document.applets["TiddlySaver"]) {
|
||
var ret = document.applets["TiddlySaver"].loadFile(javaUrlToFilename(filePath),"UTF-8");
|
||
if(!ret)
|
||
return null;
|
||
return String(ret);
|
||
}
|
||
} catch(ex) {
|
||
}
|
||
var content = [];
|
||
try {
|
||
var r = new java.io.BufferedReader(new java.io.FileReader(javaUrlToFilename(filePath)));
|
||
var line;
|
||
while((line = r.readLine()) != null)
|
||
content.push(String(line));
|
||
r.close();
|
||
} catch(ex2) {
|
||
return null;
|
||
}
|
||
return content.join("\n");
|
||
}
|
||
|
||
//--
|
||
//-- Server adaptor base class
|
||
//--
|
||
|
||
function AdaptorBase()
|
||
{
|
||
this.host = null;
|
||
this.store = null;
|
||
return this;
|
||
}
|
||
|
||
AdaptorBase.prototype.close = function()
|
||
{
|
||
return true;
|
||
};
|
||
|
||
AdaptorBase.prototype.fullHostName = function(host)
|
||
{
|
||
if(!host)
|
||
return '';
|
||
host = host.trim();
|
||
if(!host.match(/:\/\//))
|
||
host = 'http://' + host;
|
||
if(host.substr(host.length-1) == '/')
|
||
host = host.substr(0,host.length-1);
|
||
return host;
|
||
};
|
||
|
||
AdaptorBase.minHostName = function(host)
|
||
{
|
||
return host;
|
||
};
|
||
|
||
AdaptorBase.prototype.setContext = function(context,userParams,callback)
|
||
{
|
||
if(!context) context = {};
|
||
context.userParams = userParams;
|
||
if(callback) context.callback = callback;
|
||
context.adaptor = this;
|
||
if(!context.host)
|
||
context.host = this.host;
|
||
context.host = this.fullHostName(context.host);
|
||
if(!context.workspace)
|
||
context.workspace = this.workspace;
|
||
return context;
|
||
};
|
||
|
||
// Open the specified host
|
||
AdaptorBase.prototype.openHost = function(host,context,userParams,callback)
|
||
{
|
||
this.host = host;
|
||
context = this.setContext(context,userParams,callback);
|
||
context.status = true;
|
||
if(callback)
|
||
window.setTimeout(function() {context.callback(context,userParams);},10);
|
||
return true;
|
||
};
|
||
|
||
// Open the specified workspace
|
||
AdaptorBase.prototype.openWorkspace = function(workspace,context,userParams,callback)
|
||
{
|
||
this.workspace = workspace;
|
||
context = this.setContext(context,userParams,callback);
|
||
context.status = true;
|
||
if(callback)
|
||
window.setTimeout(function() {callback(context,userParams);},10);
|
||
return true;
|
||
};
|
||
|
||
//--
|
||
//-- Server adaptor for talking to static TiddlyWiki files
|
||
//--
|
||
|
||
function FileAdaptor()
|
||
{
|
||
}
|
||
|
||
FileAdaptor.prototype = new AdaptorBase();
|
||
|
||
FileAdaptor.serverType = 'file';
|
||
FileAdaptor.serverLabel = 'TiddlyWiki';
|
||
|
||
FileAdaptor.loadTiddlyWikiSuccess = function(context,jqXHR)
|
||
{
|
||
context.status = true;
|
||
context.adaptor.store = new TiddlyWiki();
|
||
if(!context.adaptor.store.importTiddlyWiki(jqXHR.responseText)) {
|
||
context.statusText = config.messages.invalidFileError.format([context.host]);
|
||
context.status = false;
|
||
}
|
||
context.complete(context,context.userParams);
|
||
};
|
||
|
||
FileAdaptor.loadTiddlyWikiError = function(context,jqXHR)
|
||
{
|
||
context.status = false;
|
||
context.statusText = jqXHR.message;
|
||
context.complete(context,context.userParams);
|
||
};
|
||
|
||
// Get the list of workspaces on a given server
|
||
FileAdaptor.prototype.getWorkspaceList = function(context,userParams,callback)
|
||
{
|
||
context = this.setContext(context,userParams,callback);
|
||
context.workspaces = [{title:"(default)"}];
|
||
context.status = true;
|
||
if(callback)
|
||
window.setTimeout(function() {callback(context,userParams);},10);
|
||
return true;
|
||
};
|
||
|
||
// Gets the list of tiddlers within a given workspace
|
||
FileAdaptor.prototype.getTiddlerList = function(context,userParams,callback,filter)
|
||
{
|
||
context = this.setContext(context,userParams,callback);
|
||
if(!context.filter)
|
||
context.filter = filter;
|
||
context.complete = FileAdaptor.getTiddlerListComplete;
|
||
if(this.store) {
|
||
return context.complete(context,context.userParams);
|
||
}
|
||
var options = {
|
||
type:"GET",
|
||
url:context.host,
|
||
processData:false,
|
||
success:function(data,textStatus,jqXHR) {
|
||
FileAdaptor.loadTiddlyWikiSuccess(context,jqXHR);
|
||
},
|
||
error:function(jqXHR,textStatus,errorThrown) {
|
||
context.xhr = jqXHR;
|
||
FileAdaptor.loadTiddlyWikiError(context,jqXHR);
|
||
}
|
||
};
|
||
return ajaxReq(options);
|
||
};
|
||
|
||
FileAdaptor.getTiddlerListComplete = function(context,userParams)
|
||
{
|
||
if(context.status) {
|
||
if(context.filter) {
|
||
context.tiddlers = context.adaptor.store.filterTiddlers(context.filter);
|
||
} else {
|
||
context.tiddlers = [];
|
||
context.adaptor.store.forEachTiddler(function(title,tiddler) {context.tiddlers.push(tiddler);});
|
||
}
|
||
var i;
|
||
for(i=0; i<context.tiddlers.length; i++) {
|
||
context.tiddlers[i].fields['server.type'] = FileAdaptor.serverType;
|
||
context.tiddlers[i].fields['server.host'] = AdaptorBase.minHostName(context.host);
|
||
context.tiddlers[i].fields['server.page.revision'] = context.tiddlers[i].modified.convertToYYYYMMDDHHMM();
|
||
}
|
||
context.status = true;
|
||
}
|
||
if(context.callback) {
|
||
window.setTimeout(function() {context.callback(context,userParams);},10);
|
||
}
|
||
return true;
|
||
};
|
||
|
||
FileAdaptor.prototype.generateTiddlerInfo = function(tiddler)
|
||
{
|
||
var info = {};
|
||
info.uri = tiddler.fields['server.host'] + "#" + tiddler.title;
|
||
return info;
|
||
};
|
||
|
||
// Retrieve a tiddler from a given workspace on a given server
|
||
FileAdaptor.prototype.getTiddler = function(title,context,userParams,callback)
|
||
{
|
||
context = this.setContext(context,userParams,callback);
|
||
context.title = title;
|
||
context.complete = FileAdaptor.getTiddlerComplete;
|
||
if(context.adaptor.store) {
|
||
return context.complete(context,context.userParams);
|
||
}
|
||
var options = {
|
||
type:"GET",
|
||
url:context.host,
|
||
processData:false,
|
||
success:function(data,textStatus,jqXHR) {
|
||
FileAdaptor.loadTiddlyWikiSuccess(context,jqXHR);
|
||
},
|
||
error:function(jqXHR,textStatus,errorThrown) {
|
||
FileAdaptor.loadTiddlyWikiError(context,jqXHR);
|
||
}
|
||
};
|
||
return ajaxReq(options);
|
||
};
|
||
|
||
FileAdaptor.getTiddlerComplete = function(context,userParams)
|
||
{
|
||
var t = context.adaptor.store.fetchTiddler(context.title);
|
||
if(t) {
|
||
t.fields['server.type'] = FileAdaptor.serverType;
|
||
t.fields['server.host'] = AdaptorBase.minHostName(context.host);
|
||
t.fields['server.page.revision'] = t.modified.convertToYYYYMMDDHHMM();
|
||
context.tiddler = t;
|
||
context.status = true;
|
||
} else { //# tiddler does not exist in document
|
||
context.status = false;
|
||
}
|
||
if(context.allowSynchronous) {
|
||
context.isSynchronous = true;
|
||
context.callback(context,userParams);
|
||
} else {
|
||
window.setTimeout(function() {context.callback(context,userParams);},10);
|
||
}
|
||
return true;
|
||
};
|
||
|
||
FileAdaptor.prototype.close = function()
|
||
{
|
||
this.store = null;
|
||
};
|
||
|
||
config.adaptors[FileAdaptor.serverType] = FileAdaptor;
|
||
|
||
config.defaultAdaptor = FileAdaptor.serverType;
|
||
|
||
//--
|
||
//-- HTTP request code
|
||
//--
|
||
|
||
function ajaxReq(args)
|
||
{
|
||
if(window.Components && window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)
|
||
window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
|
||
return jQuery.ajax(args);
|
||
}
|
||
|
||
function httpReq(type,url,callback,params,headers,data,contentType,username,password,allowCache)
|
||
{
|
||
var httpSuccess = function(xhr) {
|
||
try {
|
||
// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
|
||
return (!xhr.status && location.protocol === "file:") ||
|
||
(xhr.status >= 200 && xhr.status < 300) ||
|
||
xhr.status === 304 || xhr.status === 1223;
|
||
} catch(e) {}
|
||
return false;
|
||
};
|
||
|
||
var options = {
|
||
type:type,
|
||
url:url,
|
||
processData:false,
|
||
data:data,
|
||
cache:!!allowCache,
|
||
beforeSend: function(xhr) {
|
||
var i;
|
||
for(i in headers)
|
||
xhr.setRequestHeader(i,headers[i]);
|
||
xhr.setRequestHeader("X-Requested-With", "TiddlyWiki " + formatVersion());
|
||
}
|
||
};
|
||
|
||
if(callback) {
|
||
options.complete = function(xhr,textStatus) {
|
||
if(httpSuccess(xhr))
|
||
callback(true,params,xhr.responseText,url,xhr);
|
||
else
|
||
callback(false,params,null,url,xhr);
|
||
};
|
||
}
|
||
if(contentType)
|
||
options.contentType = contentType;
|
||
if(username)
|
||
options.username = username;
|
||
if(password)
|
||
options.password = password;
|
||
if(window.Components && window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)
|
||
window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
|
||
return jQuery.ajax(options);
|
||
}
|
||
//--
|
||
//-- TiddlyWiki-specific utility functions
|
||
//--
|
||
|
||
// Returns TiddlyWiki version string
|
||
function formatVersion(v)
|
||
{
|
||
v = v || version;
|
||
return v.major + "." + v.minor + "." + v.revision +
|
||
(v.alpha ? " (alpha " + v.alpha + ")" : "") +
|
||
(v.beta ? " (beta " + v.beta + ")" : "");
|
||
}
|
||
|
||
function compareVersions(v1,v2)
|
||
{
|
||
var x1,x2,i,a = ["major","minor","revision"];
|
||
for(i = 0; i<a.length; i++) {
|
||
x1 = v1[a[i]] || 0;
|
||
x2 = v2[a[i]] || 0;
|
||
if(x1<x2)
|
||
return 1;
|
||
if(x1>x2)
|
||
return -1;
|
||
}
|
||
x1 = v1.beta || 9999;
|
||
x2 = v2.beta || 9999;
|
||
if(x1<x2)
|
||
return 1;
|
||
return x1 > x2 ? -1 : 0;
|
||
}
|
||
|
||
function merge(dst,src,preserveExisting)
|
||
{
|
||
var i;
|
||
for(i in src) {
|
||
if(!preserveExisting || dst[i] === undefined)
|
||
dst[i] = src[i];
|
||
}
|
||
return dst;
|
||
}
|
||
|
||
// Resolve the target object of an event
|
||
function resolveTarget(e)
|
||
{
|
||
var obj;
|
||
if(e.target)
|
||
obj = e.target;
|
||
else if(e.srcElement)
|
||
obj = e.srcElement;
|
||
if(obj.nodeType == 3) // defeat Safari bug
|
||
obj = obj.parentNode;
|
||
return obj;
|
||
}
|
||
|
||
// Returns a string containing the description of an exception, optionally prepended by a message
|
||
function exceptionText(e,message)
|
||
{
|
||
var s = e.description || e.toString();
|
||
return message ? "%0:\n%1".format([message,s]) : s;
|
||
}
|
||
|
||
// Displays an alert of an exception description with optional message
|
||
function showException(e,message)
|
||
{
|
||
alert(exceptionText(e,message));
|
||
}
|
||
|
||
function alertAndThrow(m)
|
||
{
|
||
alert(m);
|
||
throw(m);
|
||
}
|
||
|
||
function glyph(name)
|
||
{
|
||
var g = config.glyphs;
|
||
var b = g.currBrowser;
|
||
if(b == null) {
|
||
b = 0;
|
||
while(b < g.browsers.length-1 && !g.browsers[b]())
|
||
b++;
|
||
g.currBrowser = b;
|
||
}
|
||
if(!g.codes[name])
|
||
return "";
|
||
return g.codes[name][b];
|
||
}
|
||
|
||
function createTiddlyText(parent,text)
|
||
{
|
||
return parent.appendChild(document.createTextNode(text));
|
||
}
|
||
|
||
function createTiddlyCheckbox(parent,caption,checked,onChange)
|
||
{
|
||
var cb = document.createElement("input");
|
||
cb.setAttribute("type","checkbox");
|
||
cb.onclick = onChange;
|
||
parent.appendChild(cb);
|
||
cb.checked = checked;
|
||
cb.className = "chkOptionInput";
|
||
if(caption)
|
||
wikify(caption,parent);
|
||
return cb;
|
||
}
|
||
|
||
function createTiddlyElement(parent,element,id,className,text,attribs)
|
||
{
|
||
var n,e = document.createElement(element);
|
||
if(className != null)
|
||
e.className = className;
|
||
if(id != null)
|
||
e.setAttribute("id",id);
|
||
if(text != null)
|
||
e.appendChild(document.createTextNode(text));
|
||
if(attribs) {
|
||
for(n in attribs) {
|
||
e.setAttribute(n,attribs[n]);
|
||
}
|
||
}
|
||
if(parent != null)
|
||
parent.appendChild(e);
|
||
return e;
|
||
}
|
||
|
||
function createTiddlyButton(parent,text,tooltip,action,className,id,accessKey,attribs)
|
||
{
|
||
var i,btn = document.createElement("a");
|
||
btn.setAttribute("href","javascript:;");
|
||
if(action) {
|
||
btn.onclick = action;
|
||
}
|
||
if(tooltip)
|
||
btn.setAttribute("title",tooltip);
|
||
if(text)
|
||
btn.appendChild(document.createTextNode(text));
|
||
btn.className = className || "button";
|
||
if(id)
|
||
btn.id = id;
|
||
if(attribs) {
|
||
for(i in attribs) {
|
||
btn.setAttribute(i,attribs[i]);
|
||
}
|
||
}
|
||
if(parent)
|
||
parent.appendChild(btn);
|
||
if(accessKey)
|
||
btn.setAttribute("accessKey",accessKey);
|
||
return btn;
|
||
}
|
||
|
||
function createExternalLink(place,url,label)
|
||
{
|
||
var link = document.createElement("a");
|
||
link.className = "externalLink";
|
||
link.href = url;
|
||
var f = config.messages.externalLinkTooltip;
|
||
link.title = f ? f.format([url]) : url;
|
||
if(config.options.chkOpenInNewWindow)
|
||
link.target = "_blank";
|
||
place.appendChild(link);
|
||
if(label)
|
||
createTiddlyText(link, label);
|
||
return link;
|
||
}
|
||
|
||
function getTiddlyLinkInfo(title,currClasses)
|
||
{
|
||
var classes = currClasses ? currClasses.split(" ") : [];
|
||
classes.pushUnique("tiddlyLink");
|
||
var tiddler = store.fetchTiddler(title);
|
||
var subTitle;
|
||
if(tiddler) {
|
||
subTitle = tiddler.getSubtitle();
|
||
classes.pushUnique("tiddlyLinkExisting");
|
||
classes.remove("tiddlyLinkNonExisting");
|
||
classes.remove("shadow");
|
||
} else {
|
||
var f;
|
||
classes.remove("tiddlyLinkExisting");
|
||
classes.pushUnique("tiddlyLinkNonExisting");
|
||
if(store.isShadowTiddler(title)) {
|
||
f = config.messages.shadowedTiddlerToolTip;
|
||
classes.pushUnique("shadow");
|
||
} else {
|
||
f = config.messages.undefinedTiddlerToolTip;
|
||
classes.remove("shadow");
|
||
}
|
||
subTitle = f ? f.format([title]) : "";
|
||
}
|
||
if(typeof config.annotations[title]=="string")
|
||
subTitle = config.annotations[title];
|
||
return {classes: classes.join(" "),subTitle: subTitle};
|
||
}
|
||
|
||
// Event handler for clicking on a tiddly link
|
||
function onClickTiddlerLink(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
var target = resolveTarget(e);
|
||
var link = target;
|
||
var title = null;
|
||
var fields = null;
|
||
var noToggle = null;
|
||
do {
|
||
title = link.getAttribute("tiddlyLink");
|
||
fields = link.getAttribute("tiddlyFields");
|
||
noToggle = link.getAttribute("noToggle");
|
||
link = link.parentNode;
|
||
} while(title == null && link != null);
|
||
if(!store.isShadowTiddler(title)) {
|
||
var f = fields ? fields.decodeHashMap() : {};
|
||
fields = String.encodeHashMap(merge(f,config.defaultCustomFields,true));
|
||
}
|
||
if(title) {
|
||
var toggling = e.metaKey || e.ctrlKey;
|
||
if(config.options.chkToggleLinks)
|
||
toggling = !toggling;
|
||
if(noToggle)
|
||
toggling = false;
|
||
if(store.getTiddler(title))
|
||
fields = null;
|
||
story.displayTiddler(target,title,null,true,null,fields,toggling);
|
||
}
|
||
clearMessage();
|
||
return false;
|
||
}
|
||
|
||
function createTiddlyLink(place,title,includeText,className,isStatic,linkedFromTiddler,noToggle)
|
||
{
|
||
var title = jQuery.trim(title);
|
||
var text = includeText ? title : null;
|
||
var i = getTiddlyLinkInfo(title,className);
|
||
var btn = isStatic ? createExternalLink(place,store.getTiddlerText("SiteUrl",null) + "#" + title) : createTiddlyButton(place,text,i.subTitle,onClickTiddlerLink,i.classes);
|
||
if(isStatic)
|
||
btn.className += ' ' + className;
|
||
btn.setAttribute("refresh","link");
|
||
btn.setAttribute("tiddlyLink",title);
|
||
if(noToggle)
|
||
btn.setAttribute("noToggle","true");
|
||
if(linkedFromTiddler) {
|
||
var fields = linkedFromTiddler.getInheritedFields();
|
||
if(fields)
|
||
btn.setAttribute("tiddlyFields",fields);
|
||
}
|
||
return btn;
|
||
}
|
||
|
||
function refreshTiddlyLink(e,title)
|
||
{
|
||
var i = getTiddlyLinkInfo(title,e.className);
|
||
e.className = i.classes;
|
||
e.title = i.subTitle;
|
||
}
|
||
|
||
function createTiddlyDropDown(place,onchange,options,defaultValue)
|
||
{
|
||
var sel = createTiddlyElement(place,"select");
|
||
sel.onchange = onchange;
|
||
var t;
|
||
for(t=0; t<options.length; t++) {
|
||
var e = createTiddlyElement(sel,"option",null,null,options[t].caption);
|
||
e.value = options[t].name;
|
||
if(options[t].name == defaultValue)
|
||
e.selected = true;
|
||
}
|
||
return sel;
|
||
}
|
||
|
||
//--
|
||
//-- TiddlyWiki-specific popup utility functions
|
||
//--
|
||
|
||
// Event handler for 'open all' on a tiddler popup
|
||
function onClickTagOpenAll(ev)
|
||
{
|
||
var tiddlers = store.getTaggedTiddlers(this.getAttribute("tag"));
|
||
var sortby = this.getAttribute("sortby");
|
||
if(sortby&&sortby.length) {
|
||
store.sortTiddlers(tiddlers,sortby);
|
||
}
|
||
story.displayTiddlers(this,tiddlers);
|
||
return false;
|
||
}
|
||
|
||
// Event handler for clicking on a tiddler tag
|
||
function onClickTag(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
var popup = Popup.create(this);
|
||
jQuery(popup).addClass("taggedTiddlerList");
|
||
var tag = this.getAttribute("tag");
|
||
var title = this.getAttribute("tiddler");
|
||
if(popup && tag) {
|
||
var tagged = tag.indexOf("[")==-1 ? store.getTaggedTiddlers(tag) : store.filterTiddlers(tag);
|
||
var sortby = this.getAttribute("sortby");
|
||
if(sortby&&sortby.length) {
|
||
store.sortTiddlers(tagged,sortby);
|
||
}
|
||
var titles = [];
|
||
var r;
|
||
for(r=0;r<tagged.length;r++) {
|
||
if(tagged[r].title != title)
|
||
titles.push(tagged[r].title);
|
||
}
|
||
var lingo = config.views.wikified.tag;
|
||
if(titles.length > 0) {
|
||
var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
|
||
openAll.setAttribute("tag",tag);
|
||
openAll.setAttribute("sortby",sortby);
|
||
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
|
||
for(r=0; r<titles.length; r++) {
|
||
createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);
|
||
}
|
||
} else {
|
||
createTiddlyElement(popup,"li",null,"disabled",lingo.popupNone.format([tag]));
|
||
}
|
||
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
|
||
var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
|
||
createTiddlyText(h,lingo.openTag.format([tag]));
|
||
}
|
||
Popup.show();
|
||
e.cancelBubble = true;
|
||
if(e.stopPropagation) e.stopPropagation();
|
||
return false;
|
||
}
|
||
|
||
// Create a button for a tag with a popup listing all the tiddlers that it tags
|
||
function createTagButton(place,tag,excludeTiddler,title,tooltip)
|
||
{
|
||
var btn = createTiddlyButton(place,title||tag,(tooltip||config.views.wikified.tag.tooltip).format([tag]),onClickTag);
|
||
btn.setAttribute("tag",tag);
|
||
if(excludeTiddler)
|
||
btn.setAttribute("tiddler",excludeTiddler);
|
||
return btn;
|
||
}
|
||
|
||
function onClickTiddlyPopup(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
var tiddler = this.tiddler;
|
||
if(tiddler.text) {
|
||
var popup = Popup.create(this,"div","popupTiddler");
|
||
wikify(tiddler.text,popup,null,tiddler);
|
||
Popup.show();
|
||
}
|
||
if(e) e.cancelBubble = true;
|
||
if(e && e.stopPropagation) e.stopPropagation();
|
||
return false;
|
||
}
|
||
|
||
function createTiddlyPopup(place,caption,tooltip,tiddler)
|
||
{
|
||
if(tiddler.text) {
|
||
createTiddlyLink(place,caption,true);
|
||
var btn = createTiddlyButton(place,glyph("downArrow"),tooltip,onClickTiddlyPopup,"tiddlerPopupButton");
|
||
btn.tiddler = tiddler;
|
||
} else {
|
||
createTiddlyText(place,caption);
|
||
}
|
||
}
|
||
|
||
function onClickError(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
var popup = Popup.create(this);
|
||
var lines = this.getAttribute("errorText").split("\n");
|
||
var t;
|
||
for(t=0; t<lines.length; t++)
|
||
createTiddlyElement(popup,"li",null,null,lines[t]);
|
||
Popup.show();
|
||
e.cancelBubble = true;
|
||
if(e.stopPropagation) e.stopPropagation();
|
||
return false;
|
||
}
|
||
|
||
function createTiddlyError(place,title,text)
|
||
{
|
||
var btn = createTiddlyButton(place,title,null,onClickError,"errorButton");
|
||
if(text) btn.setAttribute("errorText",text);
|
||
}
|
||
//-
|
||
//- Animation engine
|
||
//-
|
||
|
||
function Animator()
|
||
{
|
||
this.running = 0; // Incremented at start of each animation, decremented afterwards. If zero, the interval timer is disabled
|
||
this.timerID = 0; // ID of the timer used for animating
|
||
this.animations = []; // List of animations in progress
|
||
return this;
|
||
}
|
||
|
||
// Start animation engine
|
||
Animator.prototype.startAnimating = function() //# Variable number of arguments
|
||
{
|
||
var t;
|
||
for(t=0; t<arguments.length; t++)
|
||
this.animations.push(arguments[t]);
|
||
if(this.running == 0) {
|
||
var me = this;
|
||
this.timerID = window.setInterval(function() {me.doAnimate(me);},10);
|
||
}
|
||
this.running += arguments.length;
|
||
};
|
||
|
||
// Perform an animation engine tick, calling each of the known animation modules
|
||
Animator.prototype.doAnimate = function(me)
|
||
{
|
||
var a = 0;
|
||
while(a < me.animations.length) {
|
||
var animation = me.animations[a];
|
||
if(animation.tick()) {
|
||
a++;
|
||
} else {
|
||
me.animations.splice(a,1);
|
||
if(--me.running == 0)
|
||
window.clearInterval(me.timerID);
|
||
}
|
||
}
|
||
};
|
||
|
||
Animator.slowInSlowOut = function(progress)
|
||
{
|
||
return(1-((Math.cos(progress * Math.PI)+1)/2));
|
||
};
|
||
|
||
//--
|
||
//-- Morpher animation
|
||
//--
|
||
|
||
// Animate a set of properties of an element
|
||
function Morpher(element,duration,properties,callback)
|
||
{
|
||
this.element = element;
|
||
this.duration = duration;
|
||
this.properties = properties;
|
||
this.startTime = new Date();
|
||
this.endTime = Number(this.startTime) + duration;
|
||
this.callback = callback;
|
||
this.tick();
|
||
return this;
|
||
}
|
||
|
||
Morpher.prototype.assignStyle = function(element,style,value)
|
||
{
|
||
switch(style) {
|
||
case "-tw-vertScroll":
|
||
window.scrollTo(findScrollX(),value);
|
||
break;
|
||
case "-tw-horizScroll":
|
||
window.scrollTo(value,findScrollY());
|
||
break;
|
||
default:
|
||
element.style[style] = value;
|
||
break;
|
||
}
|
||
};
|
||
|
||
Morpher.prototype.stop = function()
|
||
{
|
||
var t;
|
||
for(t=0; t<this.properties.length; t++) {
|
||
var p = this.properties[t];
|
||
if(p.atEnd !== undefined) {
|
||
this.assignStyle(this.element,p.style,p.atEnd);
|
||
}
|
||
}
|
||
if(this.callback)
|
||
this.callback(this.element,this.properties);
|
||
};
|
||
|
||
Morpher.prototype.tick = function()
|
||
{
|
||
var currTime = Number(new Date());
|
||
var t,progress = Animator.slowInSlowOut(Math.min(1,(currTime-this.startTime)/this.duration));
|
||
for(t=0; t<this.properties.length; t++) {
|
||
var p = this.properties[t];
|
||
if(p.start !== undefined && p.end !== undefined) {
|
||
var template = p.template || "%0";
|
||
switch(p.format) {
|
||
case undefined:
|
||
case "style":
|
||
var v = p.start + (p.end-p.start) * progress;
|
||
this.assignStyle(this.element,p.style,template.format([v]));
|
||
break;
|
||
case "color":
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if(currTime >= this.endTime) {
|
||
this.stop();
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
//--
|
||
//-- Zoomer animation
|
||
//--
|
||
|
||
function Zoomer(text,startElement,targetElement,unused)
|
||
{
|
||
var e = createTiddlyElement(document.body,"div",null,"zoomer");
|
||
createTiddlyElement(e,"div",null,null,text);
|
||
var winWidth = findWindowWidth();
|
||
var winHeight = findWindowHeight();
|
||
var p = [
|
||
{style: 'left', start: findPosX(startElement), end: findPosX(targetElement), template: '%0px'},
|
||
{style: 'top', start: findPosY(startElement), end: findPosY(targetElement), template: '%0px'},
|
||
{style: 'width', start: Math.min(startElement.scrollWidth,winWidth), end: Math.min(targetElement.scrollWidth,winWidth), template: '%0px', atEnd: 'auto'},
|
||
{style: 'height', start: Math.min(startElement.scrollHeight,winHeight), end: Math.min(targetElement.scrollHeight,winHeight), template: '%0px', atEnd: 'auto'},
|
||
{style: 'fontSize', start: 8, end: 24, template: '%0pt'}
|
||
];
|
||
var c = function(element,properties) {jQuery(element).remove();};
|
||
return new Morpher(e,config.animDuration,p,c);
|
||
}
|
||
|
||
//--
|
||
//-- Scroller animation
|
||
//--
|
||
|
||
function Scroller(targetElement)
|
||
{
|
||
var p = [{style: '-tw-vertScroll', start: findScrollY(), end: ensureVisible(targetElement)}];
|
||
return new Morpher(targetElement,config.animDuration,p);
|
||
}
|
||
|
||
//--
|
||
//-- Slider animation
|
||
//--
|
||
|
||
// deleteMode - "none", "all" [delete target element and it's children], [only] "children" [but not the target element]
|
||
function Slider(element,opening,unused,deleteMode)
|
||
{
|
||
element.style.overflow = 'hidden';
|
||
if(opening)
|
||
element.style.height = '0px'; // Resolves a Firefox flashing bug
|
||
element.style.display = 'block';
|
||
var height = element.scrollHeight;
|
||
var p = [];
|
||
var c = null;
|
||
if(opening) {
|
||
p.push({style: 'height', start: 0, end: height, template: '%0px', atEnd: 'auto'});
|
||
p.push({style: 'opacity', start: 0, end: 1, template: '%0'});
|
||
p.push({style: 'filter', start: 0, end: 100, template: 'alpha(opacity:%0)'});
|
||
} else {
|
||
p.push({style: 'height', start: height, end: 0, template: '%0px'});
|
||
p.push({style: 'display', atEnd: 'none'});
|
||
p.push({style: 'opacity', start: 1, end: 0, template: '%0'});
|
||
p.push({style: 'filter', start: 100, end: 0, template: 'alpha(opacity:%0)'});
|
||
switch(deleteMode) {
|
||
case "all":
|
||
c = function(element,properties) {jQuery(element).remove();};
|
||
break;
|
||
case "children":
|
||
c = function(element,properties) {jQuery(element).empty();};
|
||
break;
|
||
}
|
||
}
|
||
return new Morpher(element,config.animDuration,p,c);
|
||
}
|
||
|
||
//--
|
||
//-- Popup menu
|
||
//--
|
||
|
||
var Popup = {
|
||
stack: [] // Array of objects with members root: and popup:
|
||
};
|
||
|
||
Popup.create = function(root,elem,className)
|
||
{
|
||
var stackPosition = this.find(root,"popup");
|
||
Popup.remove(stackPosition+1);
|
||
var popup = createTiddlyElement(document.body,elem || "ol","popup",className || "popup");
|
||
popup.stackPosition = stackPosition;
|
||
Popup.stack.push({root: root, popup: popup});
|
||
return popup;
|
||
};
|
||
|
||
Popup.onDocumentClick = function(ev)
|
||
{
|
||
var e = ev || window.event;
|
||
if(e.eventPhase == undefined)
|
||
Popup.remove();
|
||
else if(e.eventPhase == Event.BUBBLING_PHASE || e.eventPhase == Event.AT_TARGET)
|
||
Popup.remove();
|
||
return true;
|
||
};
|
||
|
||
Popup.show = function(valign,halign,offset)
|
||
{
|
||
var curr = Popup.stack[Popup.stack.length-1];
|
||
this.place(curr.root,curr.popup,valign,halign,offset);
|
||
jQuery(curr.root).addClass("highlight");
|
||
if(config.options.chkAnimate && anim && typeof Scroller == "function")
|
||
anim.startAnimating(new Scroller(curr.popup));
|
||
else
|
||
window.scrollTo(0,ensureVisible(curr.popup));
|
||
};
|
||
|
||
Popup.place = function(root,popup,valign,halign,offset)
|
||
{
|
||
if(!offset)
|
||
offset = {x:0,y:0};
|
||
if(popup.stackPosition >= 0 && !valign && !halign) {
|
||
offset.x = offset.x + root.offsetWidth;
|
||
} else {
|
||
offset.x = (halign == "right") ? offset.x + root.offsetWidth : offset.x;
|
||
offset.y = (valign == "top") ? offset.y : offset.y + root.offsetHeight;
|
||
}
|
||
var rootLeft = findPosX(root);
|
||
var rootTop = findPosY(root);
|
||
var popupLeft = rootLeft + offset.x;
|
||
var popupTop = rootTop + offset.y;
|
||
var winWidth = findWindowWidth();
|
||
if(popup.offsetWidth > winWidth*0.75)
|
||
popup.style.width = winWidth*0.75 + "px";
|
||
var popupWidth = popup.offsetWidth;
|
||
var scrollWidth = winWidth - document.body.offsetWidth;
|
||
if(popupLeft + popupWidth > winWidth - scrollWidth - 1) {
|
||
if(halign == "right")
|
||
popupLeft = popupLeft - root.offsetWidth - popupWidth;
|
||
else
|
||
popupLeft = winWidth - popupWidth - scrollWidth - 1;
|
||
}
|
||
popup.style.left = popupLeft + "px";
|
||
popup.style.top = popupTop + "px";
|
||
popup.style.display = "block";
|
||
};
|
||
|
||
Popup.find = function(e)
|
||
{
|
||
var t,pos = -1;
|
||
for(t=this.stack.length-1; t>=0; t--) {
|
||
if(isDescendant(e,this.stack[t].popup))
|
||
pos = t;
|
||
}
|
||
return pos;
|
||
};
|
||
|
||
Popup.remove = function(pos)
|
||
{
|
||
if(!pos) pos = 0;
|
||
if(Popup.stack.length > pos) {
|
||
Popup.removeFrom(pos);
|
||
}
|
||
};
|
||
|
||
Popup.removeFrom = function(from)
|
||
{
|
||
var t;
|
||
for(t=Popup.stack.length-1; t>=from; t--) {
|
||
var p = Popup.stack[t];
|
||
jQuery(p.root).removeClass("highlight");
|
||
jQuery(p.popup).remove();
|
||
}
|
||
Popup.stack = Popup.stack.slice(0,from);
|
||
};
|
||
|
||
//--
|
||
//-- Wizard support
|
||
//--
|
||
|
||
function Wizard(elem)
|
||
{
|
||
if(elem) {
|
||
this.formElem = findRelated(elem,"wizard","className");
|
||
this.bodyElem = findRelated(this.formElem.firstChild,"wizardBody","className","nextSibling");
|
||
this.footElem = findRelated(this.formElem.firstChild,"wizardFooter","className","nextSibling");
|
||
} else {
|
||
this.formElem = null;
|
||
this.bodyElem = null;
|
||
this.footElem = null;
|
||
}
|
||
}
|
||
|
||
Wizard.prototype.setValue = function(name,value)
|
||
{
|
||
jQuery(this.formElem).data(name, value);
|
||
};
|
||
|
||
Wizard.prototype.getValue = function(name)
|
||
{
|
||
return this.formElem ? jQuery(this.formElem).data(name) : null;
|
||
};
|
||
|
||
Wizard.prototype.createWizard = function(place,title)
|
||
{
|
||
this.formElem = createTiddlyElement(place,"form",null,"wizard");
|
||
createTiddlyElement(this.formElem,"h1",null,null,title);
|
||
this.bodyElem = createTiddlyElement(this.formElem,"div",null,"wizardBody");
|
||
this.footElem = createTiddlyElement(this.formElem,"div",null,"wizardFooter");
|
||
return this.formElem;
|
||
};
|
||
|
||
Wizard.prototype.clear = function()
|
||
{
|
||
jQuery(this.bodyElem).empty();
|
||
};
|
||
|
||
Wizard.prototype.setButtons = function(buttonInfo,status)
|
||
{
|
||
jQuery(this.footElem).empty();
|
||
var t;
|
||
for(t=0; t<buttonInfo.length; t++) {
|
||
createTiddlyButton(this.footElem,buttonInfo[t].caption,buttonInfo[t].tooltip,buttonInfo[t].onClick);
|
||
insertSpacer(this.footElem);
|
||
}
|
||
if(typeof status == "string") {
|
||
createTiddlyElement(this.footElem,"span",null,"status",status);
|
||
}
|
||
};
|
||
|
||
Wizard.prototype.addStep = function(stepTitle,html)
|
||
{
|
||
jQuery(this.bodyElem).empty();
|
||
var w = createTiddlyElement(this.bodyElem,"div");
|
||
createTiddlyElement(w,"h2",null,null,stepTitle);
|
||
var step = createTiddlyElement(w,"div",null,"wizardStep");
|
||
step.innerHTML = html;
|
||
applyHtmlMacros(step,tiddler);
|
||
};
|
||
|
||
Wizard.prototype.getElement = function(name)
|
||
{
|
||
return this.formElem.elements[name];
|
||
};
|
||
|
||
//--
|
||
//-- ListView gadget
|
||
//--
|
||
|
||
var ListView = {};
|
||
|
||
// Create a listview
|
||
ListView.create = function(place,listObject,listTemplate,callback,className)
|
||
{
|
||
var table = createTiddlyElement(place,"table",null,className || "listView twtable");
|
||
var thead = createTiddlyElement(table,"thead");
|
||
var t,r = createTiddlyElement(thead,"tr");
|
||
for(t=0; t<listTemplate.columns.length; t++) {
|
||
var columnTemplate = listTemplate.columns[t];
|
||
var c = createTiddlyElement(r,"th");
|
||
var colType = ListView.columnTypes[columnTemplate.type];
|
||
if(colType && colType.createHeader) {
|
||
colType.createHeader(c,columnTemplate,t);
|
||
if(columnTemplate.className)
|
||
jQuery(c).addClass(columnTemplate.className);
|
||
}
|
||
}
|
||
var rc,tbody = createTiddlyElement(table,"tbody");
|
||
for(rc=0; rc<listObject.length; rc++) {
|
||
var rowObject = listObject[rc];
|
||
r = createTiddlyElement(tbody,"tr");
|
||
for(c=0; c<listTemplate.rowClasses.length; c++) {
|
||
if(rowObject[listTemplate.rowClasses[c].field])
|
||
jQuery(r).addClass(listTemplate.rowClasses[c].className);
|
||
}
|
||
rowObject.rowElement = r;
|
||
rowObject.colElements = {};
|
||
var cc;
|
||
for(cc=0; cc<listTemplate.columns.length; cc++) {
|
||
c = createTiddlyElement(r,"td");
|
||
columnTemplate = listTemplate.columns[cc];
|
||
var field = columnTemplate.field;
|
||
colType = ListView.columnTypes[columnTemplate.type];
|
||
if(colType && colType.createItem) {
|
||
colType.createItem(c,rowObject,field,columnTemplate,cc,rc);
|
||
if(columnTemplate.className)
|
||
jQuery(c).addClass(columnTemplate.className);
|
||
}
|
||
rowObject.colElements[field] = c;
|
||
}
|
||
}
|
||
if(callback && listTemplate.actions)
|
||
createTiddlyDropDown(place,ListView.getCommandHandler(callback),listTemplate.actions);
|
||
if(callback && listTemplate.buttons) {
|
||
for(t=0; t<listTemplate.buttons.length; t++) {
|
||
var a = listTemplate.buttons[t];
|
||
if(a && a.name != "")
|
||
createTiddlyButton(place,a.caption,null,ListView.getCommandHandler(callback,a.name,a.allowEmptySelection));
|
||
}
|
||
}
|
||
return table;
|
||
};
|
||
|
||
ListView.getCommandHandler = function(callback,name,allowEmptySelection)
|
||
{
|
||
return function(e) {
|
||
var view = findRelated(this,"TABLE",null,"previousSibling");
|
||
var tiddlers = [];
|
||
ListView.forEachSelector(view,function(e,rowName) {
|
||
if(e.checked)
|
||
tiddlers.push(rowName);
|
||
});
|
||
if(tiddlers.length == 0 && !allowEmptySelection) {
|
||
alert(config.messages.nothingSelected);
|
||
} else {
|
||
if(this.nodeName.toLowerCase() == "select") {
|
||
callback(view,this.value,tiddlers);
|
||
this.selectedIndex = 0;
|
||
} else {
|
||
callback(view,name,tiddlers);
|
||
}
|
||
}
|
||
};
|
||
};
|
||
|
||
// Invoke a callback for each selector checkbox in the listview
|
||
ListView.forEachSelector = function(view,callback)
|
||
{
|
||
var checkboxes = view.getElementsByTagName("input");
|
||
var t,hadOne = false;
|
||
for(t=0; t<checkboxes.length; t++) {
|
||
var cb = checkboxes[t];
|
||
if(cb.getAttribute("type") == "checkbox") {
|
||
var rn = cb.getAttribute("rowName");
|
||
if(rn) {
|
||
callback(cb,rn);
|
||
hadOne = true;
|
||
}
|
||
}
|
||
}
|
||
return hadOne;
|
||
};
|
||
|
||
ListView.getSelectedRows = function(view)
|
||
{
|
||
var rowNames = [];
|
||
ListView.forEachSelector(view,function(e,rowName) {
|
||
if(e.checked)
|
||
rowNames.push(rowName);
|
||
});
|
||
return rowNames;
|
||
};
|
||
|
||
ListView.columnTypes = {};
|
||
|
||
ListView.columnTypes.String = {
|
||
createHeader: function(place,columnTemplate,col)
|
||
{
|
||
createTiddlyText(place,columnTemplate.title);
|
||
},
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
if(v != undefined)
|
||
createTiddlyText(place,v);
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.WikiText = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
if(v != undefined)
|
||
wikify(v,place,null,null);
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Tiddler = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
if(v != undefined && v.title)
|
||
createTiddlyPopup(place,v.title,config.messages.listView.tiddlerTooltip,v);
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Size = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var msg = config.messages.sizeTemplates;
|
||
var v = listObject[field];
|
||
if(v != undefined) {
|
||
var t = 0;
|
||
while(t<msg.length-1 && v<msg[t].unit)
|
||
t++;
|
||
createTiddlyText(place,msg[t].template.format([Math.round(v/msg[t].unit)]));
|
||
}
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Link = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
var c = columnTemplate.text;
|
||
if(v != undefined)
|
||
createExternalLink(place,v,c || v);
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Date = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
if(v != undefined)
|
||
createTiddlyText(place,v.formatString(columnTemplate.dateFormat));
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.StringList = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
if(v != undefined) {
|
||
var t;
|
||
for(t=0; t<v.length; t++) {
|
||
createTiddlyText(place,v[t]);
|
||
createTiddlyElement(place,"br");
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Selector = {
|
||
createHeader: function(place,columnTemplate,col)
|
||
{
|
||
createTiddlyCheckbox(place,null,false,this.onHeaderChange);
|
||
},
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var e = createTiddlyCheckbox(place,null,listObject[field],null);
|
||
e.setAttribute("rowName",listObject[columnTemplate.rowName]);
|
||
},
|
||
onHeaderChange: function(e)
|
||
{
|
||
var state = this.checked;
|
||
var view = findRelated(this,"TABLE");
|
||
if(!view)
|
||
return;
|
||
ListView.forEachSelector(view,function(e,rowName) {
|
||
e.checked = state;
|
||
});
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Tags = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var tags = listObject[field];
|
||
createTiddlyText(place,String.encodeTiddlyLinkList(tags));
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.Boolean = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
if(listObject[field] == true)
|
||
createTiddlyText(place,columnTemplate.trueText);
|
||
if(listObject[field] == false)
|
||
createTiddlyText(place,columnTemplate.falseText);
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.TagCheckbox = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var e = createTiddlyCheckbox(place,null,listObject[field],this.onChange);
|
||
e.setAttribute("tiddler",listObject.title);
|
||
e.setAttribute("tag",columnTemplate.tag);
|
||
},
|
||
onChange : function(e)
|
||
{
|
||
var tag = this.getAttribute("tag");
|
||
var tiddler = this.getAttribute("tiddler");
|
||
store.setTiddlerTag(tiddler,this.checked,tag);
|
||
}
|
||
};
|
||
|
||
ListView.columnTypes.TiddlerLink = {
|
||
createHeader: ListView.columnTypes.String.createHeader,
|
||
createItem: function(place,listObject,field,columnTemplate,col,row)
|
||
{
|
||
var v = listObject[field];
|
||
if(v != undefined) {
|
||
var link = createTiddlyLink(place,listObject[columnTemplate.tiddlerLink],false,null);
|
||
createTiddlyText(link,listObject[field]);
|
||
}
|
||
}
|
||
};
|
||
|
||
//--
|
||
//-- Augmented methods for the JavaScript Array() object
|
||
//--
|
||
|
||
// Add indexOf function if browser does not support it
|
||
if(!Array.indexOf) {
|
||
Array.prototype.indexOf = function(item,from)
|
||
{
|
||
if(!from)
|
||
from = 0;
|
||
var i;
|
||
for(i=from; i<this.length; i++) {
|
||
if(this[i] === item)
|
||
return i;
|
||
}
|
||
return -1;
|
||
};}
|
||
|
||
// Find an entry in a given field of the members of an array
|
||
Array.prototype.findByField = function(field,value)
|
||
{
|
||
var t;
|
||
for(t=0; t<this.length; t++) {
|
||
if(this[t][field] === value)
|
||
return t;
|
||
}
|
||
return null;
|
||
};
|
||
|
||
// Return whether an entry exists in an array
|
||
Array.prototype.contains = function(item)
|
||
{
|
||
return this.indexOf(item) != -1;
|
||
};
|
||
|
||
// Adds, removes or toggles a particular value within an array
|
||
// value - value to add
|
||
// mode - +1 to add value, -1 to remove value, 0 to toggle it
|
||
Array.prototype.setItem = function(value,mode)
|
||
{
|
||
var p = this.indexOf(value);
|
||
if(mode == 0)
|
||
mode = (p == -1) ? +1 : -1;
|
||
if(mode == +1) {
|
||
if(p == -1)
|
||
this.push(value);
|
||
} else if(mode == -1) {
|
||
if(p != -1)
|
||
this.splice(p,1);
|
||
}
|
||
};
|
||
|
||
// Return whether one of a list of values exists in an array
|
||
Array.prototype.containsAny = function(items)
|
||
{
|
||
var i;
|
||
for(i=0; i<items.length; i++) {
|
||
if(this.indexOf(items[i]) != -1)
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
// Return whether all of a list of values exists in an array
|
||
Array.prototype.containsAll = function(items)
|
||
{
|
||
var i;
|
||
for(i = 0; i<items.length; i++) {
|
||
if(this.indexOf(items[i]) == -1)
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
// Push a new value into an array only if it is not already present in the array. If the optional unique parameter is false, it reverts to a normal push
|
||
Array.prototype.pushUnique = function(item,unique)
|
||
{
|
||
if(unique === false) {
|
||
this.push(item);
|
||
} else {
|
||
if(this.indexOf(item) == -1)
|
||
this.push(item);
|
||
}
|
||
};
|
||
|
||
Array.prototype.remove = function(item)
|
||
{
|
||
var p = this.indexOf(item);
|
||
if(p != -1)
|
||
this.splice(p,1);
|
||
};
|
||
|
||
if(!Array.prototype.map) {
|
||
Array.prototype.map = function(fn,thisObj)
|
||
{
|
||
var scope = thisObj || window;
|
||
var i,j,a = [];
|
||
for(i=0, j=this.length; i < j; ++i) {
|
||
a.push(fn.call(scope,this[i],i,this));
|
||
}
|
||
return a;
|
||
};}
|
||
|
||
//--
|
||
//-- Augmented methods for the JavaScript String() object
|
||
//--
|
||
|
||
// Get characters from the right end of a string
|
||
String.prototype.right = function(n)
|
||
{
|
||
return n < this.length ? this.slice(this.length-n) : this;
|
||
};
|
||
|
||
// Trim whitespace from both ends of a string
|
||
String.prototype.trim = function()
|
||
{
|
||
return this.replace(/^\s*|\s*$/g,"");
|
||
};
|
||
|
||
// Convert a string from a CSS style property name to a JavaScript style name ("background-color" -> "backgroundColor")
|
||
String.prototype.unDash = function()
|
||
{
|
||
var t,s = this.split("-");
|
||
if(s.length > 1) {
|
||
for(t=1; t<s.length; t++)
|
||
s[t] = s[t].substr(0,1).toUpperCase() + s[t].substr(1);
|
||
}
|
||
return s.join("");
|
||
};
|
||
|
||
// Substitute substrings from an array into a format string that includes '%1'-type specifiers
|
||
String.prototype.format = function(s)
|
||
{
|
||
var substrings = s && s.constructor == Array ? s : arguments;
|
||
var subRegExp = /(?:%(\d+))/mg;
|
||
var currPos = 0;
|
||
var match,r = [];
|
||
do {
|
||
match = subRegExp.exec(this);
|
||
if(match && match[1]) {
|
||
if(match.index > currPos)
|
||
r.push(this.substring(currPos,match.index));
|
||
r.push(substrings[parseInt(match[1],10)]);
|
||
currPos = subRegExp.lastIndex;
|
||
}
|
||
} while(match);
|
||
if(currPos < this.length)
|
||
r.push(this.substring(currPos,this.length));
|
||
return r.join("");
|
||
};
|
||
|
||
// Escape any special RegExp characters with that character preceded by a backslash
|
||
String.prototype.escapeRegExp = function()
|
||
{
|
||
var s = "\\^$*+?()=!|,{}[].";
|
||
var t,c = this;
|
||
for(t=0; t<s.length; t++)
|
||
c = c.replace(new RegExp("\\" + s.substr(t,1),"g"),"\\" + s.substr(t,1));
|
||
return c;
|
||
};
|
||
|
||
// Convert "\" to "\s", newlines to "\n" (and remove carriage returns)
|
||
String.prototype.escapeLineBreaks = function()
|
||
{
|
||
return this.replace(/\\/mg,"\\s").replace(/\n/mg,"\\n").replace(/\r/mg,"");
|
||
};
|
||
|
||
// Convert "\n" to newlines, "\b" to " ", "\s" to "\" (and remove carriage returns)
|
||
String.prototype.unescapeLineBreaks = function()
|
||
{
|
||
return this.replace(/\\n/mg,"\n").replace(/\\b/mg," ").replace(/\\s/mg,"\\").replace(/\r/mg,"");
|
||
};
|
||
|
||
// Convert & to "&", < to "<", > to ">" and " to """
|
||
String.prototype.htmlEncode = function()
|
||
{
|
||
return this.replace(/&/mg,"&").replace(/</mg,"<").replace(/>/mg,">").replace(/\"/mg,""");
|
||
};
|
||
|
||
// Convert "&" to &, "<" to <, ">" to > and """ to "
|
||
String.prototype.htmlDecode = function()
|
||
{
|
||
return this.replace(/</mg,"<").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
||
};
|
||
|
||
// Parse a space-separated string of name:value parameters
|
||
// The result is an array of objects:
|
||
// result[0] = object with a member for each parameter name, value of that member being an array of values
|
||
// result[1..n] = one object for each parameter, with 'name' and 'value' members
|
||
String.prototype.parseParams = function(defaultName,defaultValue,allowEval,noNames,cascadeDefaults)
|
||
{
|
||
var parseToken = function(match,p) {
|
||
var n;
|
||
if(match[p]) // Double quoted
|
||
n = match[p];
|
||
else if(match[p+1]) // Single quoted
|
||
n = match[p+1];
|
||
else if(match[p+2]) // Double-square-bracket quoted
|
||
n = match[p+2];
|
||
else if(match[p+3]) // Double-brace quoted
|
||
try {
|
||
n = match[p+3];
|
||
if(allowEval && config.evaluateMacroParameters != "none") {
|
||
if(config.evaluateMacroParameters == "restricted") {
|
||
if(window.restrictedEval) {
|
||
n = window.restrictedEval(n);
|
||
}
|
||
} else {
|
||
n = window.eval(n);
|
||
}
|
||
}
|
||
} catch(ex) {
|
||
throw "Unable to evaluate {{" + match[p+3] + "}}: " + exceptionText(ex);
|
||
}
|
||
else if(match[p+4]) // Unquoted
|
||
n = match[p+4];
|
||
else if(match[p+5]) // empty quote
|
||
n = "";
|
||
return n;
|
||
};
|
||
var r = [{}];
|
||
var dblQuote = "(?:\"((?:(?:\\\\\")|[^\"])+)\")";
|
||
var sngQuote = "(?:'((?:(?:\\\\\')|[^'])+)')";
|
||
var dblSquare = "(?:\\[\\[((?:\\s|\\S)*?)\\]\\])";
|
||
var dblBrace = "(?:\\{\\{((?:\\s|\\S)*?)\\}\\})";
|
||
var unQuoted = noNames ? "([^\"'\\s]\\S*)" : "([^\"':\\s][^\\s:]*)";
|
||
var emptyQuote = "((?:\"\")|(?:''))";
|
||
var skipSpace = "(?:\\s*)";
|
||
var token = "(?:" + dblQuote + "|" + sngQuote + "|" + dblSquare + "|" + dblBrace + "|" + unQuoted + "|" + emptyQuote + ")";
|
||
var re = noNames ? new RegExp(token,"mg") : new RegExp(skipSpace + token + skipSpace + "(?:(\\:)" + skipSpace + token + ")?","mg");
|
||
var match;
|
||
do {
|
||
match = re.exec(this);
|
||
if(match) {
|
||
var n = parseToken(match,1);
|
||
if(noNames) {
|
||
r.push({name:"",value:n});
|
||
} else {
|
||
var v = parseToken(match,8);
|
||
if(v == null && defaultName) {
|
||
v = n;
|
||
n = defaultName;
|
||
} else if(v == null && defaultValue) {
|
||
v = defaultValue;
|
||
}
|
||
r.push({name:n,value:v});
|
||
if(cascadeDefaults) {
|
||
defaultName = n;
|
||
defaultValue = v;
|
||
}
|
||
}
|
||
}
|
||
} while(match);
|
||
// Summarise parameters into first element
|
||
var t;
|
||
for(t=1; t<r.length; t++) {
|
||
if(r[0][r[t].name])
|
||
r[0][r[t].name].push(r[t].value);
|
||
else
|
||
r[0][r[t].name] = [r[t].value];
|
||
}
|
||
return r;
|
||
};
|
||
|
||
// Process a string list of macro parameters into an array. Parameters can be quoted with "", '',
|
||
// [[]], {{ }} or left unquoted (and therefore space-separated). Double-braces {{}} results in
|
||
// an *evaluated* parameter: e.g. {{config.options.txtUserName}} results in the current user's name.
|
||
String.prototype.readMacroParams = function(notAllowEval)
|
||
{
|
||
var p = this.parseParams("list",null,!notAllowEval,true);
|
||
var t,n = [];
|
||
for(t=1; t<p.length; t++)
|
||
n.push(p[t].value);
|
||
return n;
|
||
};
|
||
|
||
// Process a string list of unique tiddler names into an array. Tiddler names that have spaces in them must be [[bracketed]]
|
||
String.prototype.readBracketedList = function(unique)
|
||
{
|
||
var p = this.parseParams("list",null,false,true);
|
||
var t,n = [];
|
||
for(t=1; t<p.length; t++) {
|
||
if(p[t].value)
|
||
n.pushUnique(p[t].value,unique);
|
||
}
|
||
return n;
|
||
};
|
||
|
||
// Returns array with start and end index of chunk between given start and end marker, or undefined.
|
||
String.prototype.getChunkRange = function(start,end)
|
||
{
|
||
var s = this.indexOf(start);
|
||
if(s != -1) {
|
||
s += start.length;
|
||
var e = this.indexOf(end,s);
|
||
if(e != -1)
|
||
return [s,e];
|
||
}
|
||
};
|
||
|
||
// Replace a chunk of a string given start and end markers
|
||
String.prototype.replaceChunk = function(start,end,sub)
|
||
{
|
||
var r = this.getChunkRange(start,end);
|
||
return r ? this.substring(0,r[0]) + sub + this.substring(r[1]) : this;
|
||
};
|
||
|
||
// Returns a chunk of a string between start and end markers, or undefined
|
||
String.prototype.getChunk = function(start,end)
|
||
{
|
||
var r = this.getChunkRange(start,end);
|
||
if(r)
|
||
return this.substring(r[0],r[1]);
|
||
};
|
||
|
||
|
||
// Static method to bracket a string with double square brackets if it contains a space
|
||
String.encodeTiddlyLink = function(title)
|
||
{
|
||
return title.indexOf(" ") == -1 ? title : "[[" + title + "]]";
|
||
};
|
||
|
||
// Static method to encodeTiddlyLink for every item in an array and join them with spaces
|
||
String.encodeTiddlyLinkList = function(list)
|
||
{
|
||
if(list) {
|
||
var t,results = [];
|
||
for(t=0; t<list.length; t++)
|
||
results.push(String.encodeTiddlyLink(list[t]));
|
||
return results.join(" ");
|
||
} else {
|
||
return "";
|
||
}
|
||
};
|
||
|
||
// Convert a string as a sequence of name:"value" pairs into a hashmap
|
||
String.prototype.decodeHashMap = function()
|
||
{
|
||
var fields = this.parseParams("anon","",false);
|
||
var t,r = {};
|
||
for(t=1; t<fields.length; t++)
|
||
r[fields[t].name] = fields[t].value;
|
||
return r;
|
||
};
|
||
|
||
// Static method to encode a hashmap into a name:"value"... string
|
||
String.encodeHashMap = function(hashmap)
|
||
{
|
||
var t,r = [];
|
||
for(t in hashmap)
|
||
r.push(t + ':"' + hashmap[t] + '"');
|
||
return r.join(" ");
|
||
};
|
||
|
||
// Static method to left-pad a string with 0s to a certain width
|
||
String.zeroPad = function(n,d)
|
||
{
|
||
var s = n.toString();
|
||
if(s.length < d)
|
||
s = "000000000000000000000000000".substr(0,d-s.length) + s;
|
||
return s;
|
||
};
|
||
|
||
String.prototype.startsWith = function(prefix)
|
||
{
|
||
return !prefix || this.substring(0,prefix.length) == prefix;
|
||
};
|
||
|
||
// Returns the first value of the given named parameter.
|
||
function getParam(params,name,defaultValue)
|
||
{
|
||
if(!params)
|
||
return defaultValue;
|
||
var p = params[0][name];
|
||
return p ? p[0] : defaultValue;
|
||
}
|
||
|
||
// Returns the first value of the given boolean named parameter.
|
||
function getFlag(params,name,defaultValue)
|
||
{
|
||
return !!getParam(params,name,defaultValue);
|
||
}
|
||
|
||
//--
|
||
//-- Augmented methods for the JavaScript Date() object
|
||
//--
|
||
|
||
// Substitute date components into a string
|
||
Date.prototype.formatString = function(template)
|
||
{
|
||
var t = template.replace(/0hh12/g,String.zeroPad(this.getHours12(),2));
|
||
t = t.replace(/hh12/g,this.getHours12());
|
||
t = t.replace(/0hh/g,String.zeroPad(this.getHours(),2));
|
||
t = t.replace(/hh/g,this.getHours());
|
||
t = t.replace(/mmm/g,config.messages.dates.shortMonths[this.getMonth()]);
|
||
t = t.replace(/0mm/g,String.zeroPad(this.getMinutes(),2));
|
||
t = t.replace(/mm/g,this.getMinutes());
|
||
t = t.replace(/0ss/g,String.zeroPad(this.getSeconds(),2));
|
||
t = t.replace(/ss/g,this.getSeconds());
|
||
t = t.replace(/[ap]m/g,this.getAmPm().toLowerCase());
|
||
t = t.replace(/[AP]M/g,this.getAmPm().toUpperCase());
|
||
t = t.replace(/wYYYY/g,this.getYearForWeekNo());
|
||
t = t.replace(/wYY/g,String.zeroPad(this.getYearForWeekNo()-2000,2));
|
||
t = t.replace(/YYYY/g,this.getFullYear());
|
||
t = t.replace(/YY/g,String.zeroPad(this.getFullYear()-2000,2));
|
||
t = t.replace(/MMM/g,config.messages.dates.months[this.getMonth()]);
|
||
t = t.replace(/0MM/g,String.zeroPad(this.getMonth()+1,2));
|
||
t = t.replace(/MM/g,this.getMonth()+1);
|
||
t = t.replace(/0WW/g,String.zeroPad(this.getWeek(),2));
|
||
t = t.replace(/WW/g,this.getWeek());
|
||
t = t.replace(/DDD/g,config.messages.dates.days[this.getDay()]);
|
||
t = t.replace(/ddd/g,config.messages.dates.shortDays[this.getDay()]);
|
||
t = t.replace(/0DD/g,String.zeroPad(this.getDate(),2));
|
||
t = t.replace(/DDth/g,this.getDate()+this.daySuffix());
|
||
t = t.replace(/DD/g,this.getDate());
|
||
var tz = this.getTimezoneOffset();
|
||
var atz = Math.abs(tz);
|
||
t = t.replace(/TZD/g,(tz < 0 ? '+' : '-') + String.zeroPad(Math.floor(atz / 60),2) + ':' + String.zeroPad(atz % 60,2));
|
||
t = t.replace(/\\/g,"");
|
||
return t;
|
||
};
|
||
|
||
Date.prototype.getWeek = function()
|
||
{
|
||
var dt = new Date(this.getTime());
|
||
var d = dt.getDay();
|
||
if(d==0) d=7;// JavaScript Sun=0, ISO Sun=7
|
||
dt.setTime(dt.getTime()+(4-d)*86400000);// shift day to Thurs of same week to calculate weekNo
|
||
var n = Math.floor((dt.getTime()-new Date(dt.getFullYear(),0,1)+3600000)/86400000);
|
||
return Math.floor(n/7)+1;
|
||
};
|
||
|
||
Date.prototype.getYearForWeekNo = function()
|
||
{
|
||
var dt = new Date(this.getTime());
|
||
var d = dt.getDay();
|
||
if(d==0) d=7;// JavaScript Sun=0, ISO Sun=7
|
||
dt.setTime(dt.getTime()+(4-d)*86400000);// shift day to Thurs of same week
|
||
return dt.getFullYear();
|
||
};
|
||
|
||
Date.prototype.getHours12 = function()
|
||
{
|
||
var h = this.getHours();
|
||
return h > 12 ? h-12 : ( h > 0 ? h : 12 );
|
||
};
|
||
|
||
Date.prototype.getAmPm = function()
|
||
{
|
||
return this.getHours() >= 12 ? config.messages.dates.pm : config.messages.dates.am;
|
||
};
|
||
|
||
Date.prototype.daySuffix = function()
|
||
{
|
||
return config.messages.dates.daySuffixes[this.getDate()-1];
|
||
};
|
||
|
||
// Convert a date to local YYYYMMDDHHMM string format
|
||
Date.prototype.convertToLocalYYYYMMDDHHMM = function()
|
||
{
|
||
return this.getFullYear() + String.zeroPad(this.getMonth()+1,2) + String.zeroPad(this.getDate(),2) + String.zeroPad(this.getHours(),2) + String.zeroPad(this.getMinutes(),2);
|
||
};
|
||
|
||
// Convert a date to UTC YYYYMMDDHHMM string format
|
||
Date.prototype.convertToYYYYMMDDHHMM = function()
|
||
{
|
||
return this.getUTCFullYear() + String.zeroPad(this.getUTCMonth()+1,2) + String.zeroPad(this.getUTCDate(),2) + String.zeroPad(this.getUTCHours(),2) + String.zeroPad(this.getUTCMinutes(),2);
|
||
};
|
||
|
||
// Convert a date to UTC YYYYMMDD.HHMMSSMMM string format
|
||
Date.prototype.convertToYYYYMMDDHHMMSSMMM = function()
|
||
{
|
||
return this.getUTCFullYear() + String.zeroPad(this.getUTCMonth()+1,2) + String.zeroPad(this.getUTCDate(),2) + "." + String.zeroPad(this.getUTCHours(),2) + String.zeroPad(this.getUTCMinutes(),2) + String.zeroPad(this.getUTCSeconds(),2) + String.zeroPad(this.getUTCMilliseconds(),3) +"0";
|
||
};
|
||
|
||
// Static method to create a date from a UTC YYYYMMDDHHMM format string
|
||
Date.convertFromYYYYMMDDHHMM = function(d)
|
||
{
|
||
d = d?d.replace(/[^0-9]/g, ""):"";
|
||
return Date.convertFromYYYYMMDDHHMMSSMMM(d.substr(0,12));
|
||
};
|
||
|
||
// Static method to create a date from a UTC YYYYMMDDHHMMSS format string
|
||
Date.convertFromYYYYMMDDHHMMSS = function(d)
|
||
{
|
||
d = d?d.replace(/[^0-9]/g, ""):"";
|
||
return Date.convertFromYYYYMMDDHHMMSSMMM(d.substr(0,14));
|
||
};
|
||
|
||
// Static method to create a date from a UTC YYYYMMDDHHMMSSMMM format string
|
||
Date.convertFromYYYYMMDDHHMMSSMMM = function(d)
|
||
{
|
||
d = d ? d.replace(/[^0-9]/g, "") : "";
|
||
return new Date(Date.UTC(parseInt(d.substr(0,4),10),
|
||
parseInt(d.substr(4,2),10)-1,
|
||
parseInt(d.substr(6,2),10),
|
||
parseInt(d.substr(8,2)||"00",10),
|
||
parseInt(d.substr(10,2)||"00",10),
|
||
parseInt(d.substr(12,2)||"00",10),
|
||
parseInt(d.substr(14,3)||"000",10)));
|
||
};
|
||
|
||
//--
|
||
//-- RGB colour object
|
||
//--
|
||
|
||
// Construct an RGB colour object from a '#rrggbb', '#rgb' or 'rgb(n,n,n)' string or from separate r,g,b values
|
||
function RGB(r,g,b)
|
||
{
|
||
this.r = 0;
|
||
this.g = 0;
|
||
this.b = 0;
|
||
if(typeof r == "string") {
|
||
if(r.substr(0,1) == "#") {
|
||
if(r.length == 7) {
|
||
this.r = parseInt(r.substr(1,2),16)/255;
|
||
this.g = parseInt(r.substr(3,2),16)/255;
|
||
this.b = parseInt(r.substr(5,2),16)/255;
|
||
} else {
|
||
this.r = parseInt(r.substr(1,1),16)/15;
|
||
this.g = parseInt(r.substr(2,1),16)/15;
|
||
this.b = parseInt(r.substr(3,1),16)/15;
|
||
}
|
||
} else {
|
||
var rgbPattern = /rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/;
|
||
var c = r.match(rgbPattern);
|
||
if(c) {
|
||
this.r = parseInt(c[1],10)/255;
|
||
this.g = parseInt(c[2],10)/255;
|
||
this.b = parseInt(c[3],10)/255;
|
||
}
|
||
}
|
||
} else {
|
||
this.r = r;
|
||
this.g = g;
|
||
this.b = b;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
// Mixes this colour with another in a specified proportion
|
||
// c = other colour to mix
|
||
// f = 0..1 where 0 is this colour and 1 is the new colour
|
||
// Returns an RGB object
|
||
RGB.prototype.mix = function(c,f)
|
||
{
|
||
return new RGB(this.r + (c.r-this.r) * f,this.g + (c.g-this.g) * f,this.b + (c.b-this.b) * f);
|
||
};
|
||
|
||
// Return an rgb colour as a #rrggbb format hex string
|
||
RGB.prototype.toString = function()
|
||
{
|
||
var clamp = function(x,min,max) {
|
||
return x < min ? min : (x > max ? max : x);
|
||
};
|
||
return "#" +
|
||
("0" + Math.floor(clamp(this.r,0,1) * 255).toString(16)).right(2) +
|
||
("0" + Math.floor(clamp(this.g,0,1) * 255).toString(16)).right(2) +
|
||
("0" + Math.floor(clamp(this.b,0,1) * 255).toString(16)).right(2);
|
||
};
|
||
|
||
//--
|
||
//-- DOM utilities - many derived from www.quirksmode.org
|
||
//--
|
||
|
||
function drawGradient(place,horiz,locolors,hicolors)
|
||
{
|
||
if(!hicolors)
|
||
hicolors = locolors;
|
||
var t;
|
||
for(t=0; t<= 100; t+=2) {
|
||
var bar = document.createElement("div");
|
||
place.appendChild(bar);
|
||
bar.style.position = "absolute";
|
||
bar.style.left = horiz ? t + "%" : 0;
|
||
bar.style.top = horiz ? 0 : t + "%";
|
||
bar.style.width = horiz ? (101-t) + "%" : "100%";
|
||
bar.style.height = horiz ? "100%" : (101-t) + "%";
|
||
bar.style.zIndex = -1;
|
||
var p = t/100*(locolors.length-1);
|
||
var hc = hicolors[Math.floor(p)];
|
||
if(typeof hc == "string")
|
||
hc = new RGB(hc);
|
||
var lc = locolors[Math.ceil(p)];
|
||
if(typeof lc == "string")
|
||
lc = new RGB(lc);
|
||
bar.style.backgroundColor = hc.mix(lc,p-Math.floor(p)).toString();
|
||
}
|
||
}
|
||
|
||
function addEvent(obj,type,fn)
|
||
{
|
||
if(obj.attachEvent) {
|
||
obj["e"+type+fn] = fn;
|
||
obj[type+fn] = function(){obj["e"+type+fn](window.event);};
|
||
obj.attachEvent("on"+type,obj[type+fn]);
|
||
} else {
|
||
obj.addEventListener(type,fn,false);
|
||
}
|
||
}
|
||
|
||
function removeEvent(obj,type,fn)
|
||
{
|
||
if(obj.detachEvent) {
|
||
obj.detachEvent("on"+type,obj[type+fn]);
|
||
obj[type+fn] = null;
|
||
} else {
|
||
obj.removeEventListener(type,fn,false);
|
||
}
|
||
}
|
||
|
||
// Find the closest relative with a given property value (property defaults to tagName, relative defaults to parentNode)
|
||
function findRelated(e,value,name,relative)
|
||
{
|
||
name = name || "tagName";
|
||
relative = relative || "parentNode";
|
||
if(name == "className") {
|
||
while(e && !jQuery(e).hasClass(value)) {
|
||
e = e[relative];
|
||
}
|
||
} else {
|
||
while(e && e[name] != value) {
|
||
e = e[relative];
|
||
}
|
||
}
|
||
return e;
|
||
}
|
||
|
||
// Get the scroll position for window.scrollTo necessary to scroll a given element into view
|
||
function ensureVisible(e)
|
||
{
|
||
var posTop = findPosY(e);
|
||
var posBot = posTop + e.offsetHeight;
|
||
var winTop = findScrollY();
|
||
var winHeight = findWindowHeight();
|
||
var winBot = winTop + winHeight;
|
||
if(posTop < winTop) {
|
||
return posTop;
|
||
} else if(posBot > winBot) {
|
||
if(e.offsetHeight < winHeight)
|
||
return posTop - (winHeight - e.offsetHeight);
|
||
else
|
||
return posTop;
|
||
} else {
|
||
return winTop;
|
||
}
|
||
}
|
||
|
||
// Get the current width of the display window
|
||
function findWindowWidth()
|
||
{
|
||
return window.innerWidth || document.documentElement.clientWidth;
|
||
}
|
||
|
||
// Get the current height of the display window
|
||
function findWindowHeight()
|
||
{
|
||
return window.innerHeight || document.documentElement.clientHeight;
|
||
}
|
||
|
||
// Get the current horizontal page scroll position
|
||
function findScrollX()
|
||
{
|
||
return window.scrollX || document.documentElement.scrollLeft;
|
||
}
|
||
|
||
// Get the current vertical page scroll position
|
||
function findScrollY()
|
||
{
|
||
return window.scrollY || document.documentElement.scrollTop;
|
||
}
|
||
|
||
function findPosX(obj)
|
||
{
|
||
var curleft = 0;
|
||
while(obj.offsetParent) {
|
||
curleft += obj.offsetLeft;
|
||
obj = obj.offsetParent;
|
||
}
|
||
return curleft;
|
||
}
|
||
|
||
function findPosY(obj)
|
||
{
|
||
var curtop = 0;
|
||
while(obj.offsetParent) {
|
||
curtop += obj.offsetTop;
|
||
obj = obj.offsetParent;
|
||
}
|
||
return curtop;
|
||
}
|
||
|
||
// Blur a particular element
|
||
function blurElement(e)
|
||
{
|
||
if(e && e.focus && e.blur) {
|
||
e.focus();
|
||
e.blur();
|
||
}
|
||
}
|
||
|
||
// Create a non-breaking space
|
||
function insertSpacer(place)
|
||
{
|
||
var e = document.createTextNode(String.fromCharCode(160));
|
||
if(place)
|
||
place.appendChild(e);
|
||
return e;
|
||
}
|
||
|
||
// Replace the current selection of a textarea or text input and scroll it into view
|
||
function replaceSelection(e,text)
|
||
{
|
||
if(e.setSelectionRange) {
|
||
var oldpos = e.selectionStart;
|
||
var isRange = e.selectionEnd > e.selectionStart;
|
||
e.value = e.value.substr(0,e.selectionStart) + text + e.value.substr(e.selectionEnd);
|
||
e.setSelectionRange(isRange ? oldpos : oldpos + text.length,oldpos + text.length);
|
||
var linecount = e.value.split("\n").length;
|
||
var thisline = e.value.substr(0,e.selectionStart).split("\n").length-1;
|
||
e.scrollTop = Math.floor((thisline - e.rows / 2) * e.scrollHeight / linecount);
|
||
} else if(document.selection) {
|
||
var range = document.selection.createRange();
|
||
if(range.parentElement() == e) {
|
||
var isCollapsed = range.text == "";
|
||
range.text = text;
|
||
if(!isCollapsed) {
|
||
range.moveStart("character", -text.length);
|
||
range.select();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Set the caret position in a text area
|
||
function setCaretPosition(e,pos)
|
||
{
|
||
if(e.selectionStart || e.selectionStart == '0') {
|
||
e.selectionStart = pos;
|
||
e.selectionEnd = pos;
|
||
e.focus();
|
||
} else if(document.selection) {
|
||
// IE support
|
||
e.focus ();
|
||
var sel = document.selection.createRange();
|
||
sel.moveStart('character', -e.value.length);
|
||
sel.moveStart('character',pos);
|
||
sel.moveEnd('character',0);
|
||
sel.select();
|
||
}
|
||
}
|
||
|
||
// Returns the text of the given (text) node, possibly merging subsequent text nodes
|
||
function getNodeText(e)
|
||
{
|
||
var t = "";
|
||
while(e && e.nodeName == "#text") {
|
||
t += e.nodeValue;
|
||
e = e.nextSibling;
|
||
}
|
||
return t;
|
||
}
|
||
|
||
// Returns true if the element e has a given ancestor element
|
||
function isDescendant(e,ancestor)
|
||
{
|
||
while(e) {
|
||
if(e === ancestor)
|
||
return true;
|
||
e = e.parentNode;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
// deprecate the following...
|
||
|
||
// Prevent an event from bubbling
|
||
function stopEvent(e)
|
||
{
|
||
var ev = e || window.event;
|
||
ev.cancelBubble = true;
|
||
if(ev.stopPropagation) ev.stopPropagation();
|
||
return false;
|
||
}
|
||
|
||
// Remove any event handlers or non-primitve custom attributes
|
||
function scrubNode(e)
|
||
{
|
||
if(!config.browser.isIE)
|
||
return;
|
||
var att = e.attributes;
|
||
if(att) {
|
||
var t;
|
||
for(t=0; t<att.length; t++) {
|
||
var n = att[t].name;
|
||
if(n !== "style" && (typeof e[n] === "function" || (typeof e[n] === "object" && e[n] != null))) {
|
||
try {
|
||
e[n] = null;
|
||
} catch(ex) {
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var c = e.firstChild;
|
||
while(c) {
|
||
scrubNode(c);
|
||
c = c.nextSibling;
|
||
}
|
||
}
|
||
|
||
function setStylesheet(s,id,doc)
|
||
{
|
||
jQuery.twStylesheet(s,{id:id,doc:doc});
|
||
}
|
||
|
||
function removeStyleSheet(id)
|
||
{
|
||
jQuery.twStylesheet.remove({id:id});
|
||
}
|
||
|
||
//--
|
||
//-- LoaderBase and SaverBase
|
||
//--
|
||
|
||
function LoaderBase() {}
|
||
|
||
LoaderBase.prototype.loadTiddler = function(store,node,tiddlers)
|
||
{
|
||
var title = this.getTitle(store,node);
|
||
if(safeMode && store.isShadowTiddler(title))
|
||
return;
|
||
if(title) {
|
||
var tiddler = store.createTiddler(title);
|
||
this.internalizeTiddler(store,tiddler,title,node);
|
||
tiddlers.push(tiddler);
|
||
}
|
||
};
|
||
|
||
LoaderBase.prototype.loadTiddlers = function(store,nodes)
|
||
{
|
||
var t,tiddlers = [];
|
||
for(t = 0; t < nodes.length; t++) {
|
||
try {
|
||
this.loadTiddler(store,nodes[t],tiddlers);
|
||
} catch(ex) {
|
||
showException(ex,config.messages.tiddlerLoadError.format([this.getTitle(store,nodes[t])]));
|
||
}
|
||
}
|
||
return tiddlers;
|
||
};
|
||
|
||
function SaverBase() {}
|
||
|
||
SaverBase.prototype.externalize = function(store)
|
||
{
|
||
var results = [];
|
||
var t,tiddlers = store.getTiddlers("title");
|
||
for(t = 0; t < tiddlers.length; t++) {
|
||
if(!tiddlers[t].doNotSave())
|
||
results.push(this.externalizeTiddler(store, tiddlers[t]));
|
||
}
|
||
return results.join("\n");
|
||
};
|
||
|
||
//--
|
||
//-- TW21Loader (inherits from LoaderBase)
|
||
//--
|
||
|
||
function TW21Loader() {}
|
||
|
||
TW21Loader.prototype = new LoaderBase();
|
||
|
||
TW21Loader.prototype.getTitle = function(store,node)
|
||
{
|
||
var title = null;
|
||
if(node.getAttribute) {
|
||
title = node.getAttribute("title");
|
||
if(!title)
|
||
title = node.getAttribute("tiddler");
|
||
}
|
||
if(!title && node.id) {
|
||
var lenPrefix = store.idPrefix.length;
|
||
if(node.id.substr(0,lenPrefix) == store.idPrefix)
|
||
title = node.id.substr(lenPrefix);
|
||
}
|
||
return title;
|
||
};
|
||
|
||
TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node)
|
||
{
|
||
var e = node.firstChild;
|
||
var text = null;
|
||
if(node.getAttribute("tiddler")) {
|
||
text = getNodeText(e).unescapeLineBreaks();
|
||
} else {
|
||
while(e.nodeName!="PRE" && e.nodeName!="pre") {
|
||
e = e.nextSibling;
|
||
}
|
||
text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
|
||
}
|
||
var creator = node.getAttribute("creator");
|
||
var modifier = node.getAttribute("modifier");
|
||
var c = node.getAttribute("created");
|
||
var m = node.getAttribute("modified");
|
||
var created = c ? Date.convertFromYYYYMMDDHHMMSS(c) : version.date;
|
||
var modified = m ? Date.convertFromYYYYMMDDHHMMSS(m) : created;
|
||
var tags = node.getAttribute("tags");
|
||
var fields = {};
|
||
var i,attrs = node.attributes;
|
||
for(i = attrs.length-1; i >= 0; i--) {
|
||
var name = attrs[i].name;
|
||
if(attrs[i].specified && !TiddlyWiki.isStandardField(name)) {
|
||
fields[name] = attrs[i].value.unescapeLineBreaks();
|
||
}
|
||
}
|
||
tiddler.assign(title,text,modifier,modified,tags,created,fields,creator);
|
||
return tiddler;
|
||
};
|
||
|
||
//--
|
||
//-- TW21Saver (inherits from SaverBase)
|
||
//--
|
||
|
||
function TW21Saver() {}
|
||
|
||
TW21Saver.prototype = new SaverBase();
|
||
|
||
TW21Saver.prototype.externalizeTiddler = function(store,tiddler)
|
||
{
|
||
try {
|
||
var extendedAttributes = "";
|
||
var usePre = config.options.chkUsePreForStorage;
|
||
store.forEachField(tiddler,
|
||
function(tiddler,fieldName,value) {
|
||
// don't store stuff from the temp namespace
|
||
if(typeof value != "string")
|
||
value = "";
|
||
if(!fieldName.match(/^temp\./))
|
||
extendedAttributes += ' %0="%1"'.format([fieldName,value.escapeLineBreaks().htmlEncode()]);
|
||
},true);
|
||
var created = tiddler.created;
|
||
var modified = tiddler.modified;
|
||
var attributes = tiddler.creator ? ' creator="' + tiddler.creator.htmlEncode() + '"' : "";
|
||
attributes += tiddler.modifier ? ' modifier="' + tiddler.modifier.htmlEncode() + '"' : "";
|
||
attributes += (usePre && created == version.date) ? "" :' created="' + created.convertToYYYYMMDDHHMM() + '"';
|
||
attributes += (usePre && modified == created) ? "" : ' modified="' + modified.convertToYYYYMMDDHHMM() +'"';
|
||
var tags = tiddler.getTags();
|
||
if(!usePre || tags)
|
||
attributes += ' tags="' + tags.htmlEncode() + '"';
|
||
return ('<div %0="%1"%2%3>%4</'+'div>').format([
|
||
usePre ? "title" : "tiddler",
|
||
tiddler.title.htmlEncode(),
|
||
attributes,
|
||
extendedAttributes,
|
||
usePre ? "\n<pre>" + tiddler.text.htmlEncode() + "</pre>\n" : tiddler.text.escapeLineBreaks().htmlEncode()
|
||
]);
|
||
} catch (ex) {
|
||
throw exceptionText(ex,config.messages.tiddlerSaveError.format([tiddler.title]));
|
||
}
|
||
};
|
||
|
||
//]]>
|
||
</script>
|
||
<script id="jsdeprecatedArea" type="text/javascript">
|
||
//<![CDATA[
|
||
//--
|
||
//-- Deprecated Crypto functions and associated conversion routines.
|
||
//-- Use the jQuery.encoding functions directly instead.
|
||
//--
|
||
|
||
// Crypto 'namespace'
|
||
function Crypto() {}
|
||
|
||
// Convert a string to an array of big-endian 32-bit words
|
||
Crypto.strToBe32s = function(str)
|
||
{
|
||
return jQuery.encoding.strToBe32s(str);
|
||
};
|
||
|
||
// Convert an array of big-endian 32-bit words to a string
|
||
Crypto.be32sToStr = function(be)
|
||
{
|
||
return jQuery.encoding.be32sToStr(be);
|
||
};
|
||
|
||
// Convert an array of big-endian 32-bit words to a hex string
|
||
Crypto.be32sToHex = function(be)
|
||
{
|
||
return jQuery.encoding.be32sToHex(be);
|
||
};
|
||
|
||
// Return, in hex, the SHA-1 hash of a string
|
||
Crypto.hexSha1Str = function(str)
|
||
{
|
||
return jQuery.encoding.digests.hexSha1Str(str);
|
||
};
|
||
|
||
// Return the SHA-1 hash of a string
|
||
Crypto.sha1Str = function(str)
|
||
{
|
||
return jQuery.encoding.digests.sha1Str(str);
|
||
};
|
||
|
||
// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
|
||
Crypto.sha1 = function(x,blen)
|
||
{
|
||
return jQuery.encoding.digests.sha1(x,blen);
|
||
};
|
||
|
||
//--
|
||
//-- Deprecated code
|
||
//--
|
||
|
||
// @Deprecated: Use createElementAndWikify and this.termRegExp instead
|
||
config.formatterHelpers.charFormatHelper = function(w)
|
||
{
|
||
w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
|
||
};
|
||
|
||
// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
|
||
config.formatterHelpers.monospacedByLineHelper = function(w)
|
||
{
|
||
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
|
||
lookaheadRegExp.lastIndex = w.matchStart;
|
||
var lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||
var text = lookaheadMatch[1];
|
||
if(config.browser.isIE)
|
||
text = text.replace(/\n/g,"\r");
|
||
createTiddlyElement(w.output,"pre",null,null,text);
|
||
w.nextMatch = lookaheadRegExp.lastIndex;
|
||
}
|
||
};
|
||
|
||
// @Deprecated: Use <br> or <br /> instead of <<br>>
|
||
config.macros.br = {};
|
||
config.macros.br.handler = function(place)
|
||
{
|
||
createTiddlyElement(place,"br");
|
||
};
|
||
|
||
// Find an entry in an array. Returns the array index or null
|
||
// @Deprecated: Use indexOf instead
|
||
Array.prototype.find = function(item)
|
||
{
|
||
var i = this.indexOf(item);
|
||
return i == -1 ? null : i;
|
||
};
|
||
|
||
// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
|
||
// @Deprecated: Use store.getLoader().internalizeTiddler instead
|
||
Tiddler.prototype.loadFromDiv = function(divRef,title)
|
||
{
|
||
return store.getLoader().internalizeTiddler(store,this,title,divRef);
|
||
};
|
||
|
||
// Format the text for storage in an HTML DIV
|
||
// @Deprecated Use store.getSaver().externalizeTiddler instead.
|
||
Tiddler.prototype.saveToDiv = function()
|
||
{
|
||
return store.getSaver().externalizeTiddler(store,this);
|
||
};
|
||
|
||
// @Deprecated: Use store.allTiddlersAsHtml() instead
|
||
function allTiddlersAsHtml()
|
||
{
|
||
return store.allTiddlersAsHtml();
|
||
}
|
||
|
||
// @Deprecated: Use refreshPageTemplate instead
|
||
function applyPageTemplate(title)
|
||
{
|
||
refreshPageTemplate(title);
|
||
}
|
||
|
||
// @Deprecated: Use story.displayTiddlers instead
|
||
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
|
||
{
|
||
story.displayTiddlers(srcElement,titles,template,animate);
|
||
}
|
||
|
||
// @Deprecated: Use story.displayTiddler instead
|
||
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
|
||
{
|
||
story.displayTiddler(srcElement,title,template,animate);
|
||
}
|
||
|
||
// @Deprecated: Use functions on right hand side directly instead
|
||
var createTiddlerPopup = Popup.create;
|
||
var scrollToTiddlerPopup = Popup.show;
|
||
var hideTiddlerPopup = Popup.remove;
|
||
|
||
// @Deprecated: Use right hand side directly instead
|
||
var regexpBackSlashEn = new RegExp("\\\\n","mg");
|
||
var regexpBackSlash = new RegExp("\\\\","mg");
|
||
var regexpBackSlashEss = new RegExp("\\\\s","mg");
|
||
var regexpNewLine = new RegExp("\n","mg");
|
||
var regexpCarriageReturn = new RegExp("\r","mg");
|
||
|
||
//--
|
||
//-- Deprecated FileAdaptor functions
|
||
//--
|
||
|
||
FileAdaptor.loadTiddlyWikiCallback = function(status,context,responseText,url,xhr)
|
||
{
|
||
context.status = status;
|
||
if(!status) {
|
||
context.statusText = "Error reading file";
|
||
} else {
|
||
context.adaptor.store = new TiddlyWiki();
|
||
if(!context.adaptor.store.importTiddlyWiki(responseText)) {
|
||
context.statusText = config.messages.invalidFileError.format([url]);
|
||
context.status = false;
|
||
}
|
||
}
|
||
context.complete(context,context.userParams);
|
||
};
|
||
|
||
//--
|
||
//-- Deprecated HTTP request code
|
||
//-- Use the jQuery ajax functions directly instead
|
||
//--
|
||
|
||
function loadRemoteFile(url,callback,params)
|
||
{
|
||
return httpReq("GET",url,callback,params);
|
||
}
|
||
|
||
function doHttp(type,url,data,contentType,username,password,callback,params,headers,allowCache)
|
||
{
|
||
return httpReq(type,url,callback,params,headers,data,contentType,username,password,allowCache);
|
||
}
|
||
|
||
//--
|
||
//-- Deprecated String functions
|
||
//--
|
||
|
||
// @Deprecated: no direct replacement, since not used in core code
|
||
String.prototype.toJSONString = function()
|
||
{
|
||
// Convert a string to it's JSON representation by encoding control characters, double quotes and backslash. See json.org
|
||
var m = {
|
||
'\b': '\\b',
|
||
'\f': '\\f',
|
||
'\n': '\\n',
|
||
'\r': '\\r',
|
||
'\t': '\\t',
|
||
'"' : '\\"',
|
||
'\\': '\\\\'
|
||
};
|
||
var replaceFn = function(a,b) {
|
||
var c = m[b];
|
||
if(c)
|
||
return c;
|
||
c = b.charCodeAt();
|
||
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
|
||
};
|
||
if(/["\\\x00-\x1f]/.test(this))
|
||
return '"' + this.replace(/([\x00-\x1f\\"])/g,replaceFn) + '"';
|
||
return '"' + this + '"';
|
||
};
|
||
|
||
//--
|
||
//-- Deprecated Tiddler code
|
||
//--
|
||
|
||
// @Deprecated: Use tiddlerToRssItem(tiddler,uri) instead
|
||
Tiddler.prototype.toRssItem = function(uri)
|
||
{
|
||
return tiddlerToRssItem(this,uri);
|
||
};
|
||
|
||
// @Deprecated: Use "<item>\n" + tiddlerToRssItem(tiddler,uri) + "\n</item>" instead
|
||
Tiddler.prototype.saveToRss = function(uri)
|
||
{
|
||
return "<item>\n" + tiddlerToRssItem(this,uri) + "\n</item>";
|
||
};
|
||
|
||
// @Deprecated: Use jQuery.encoding.digests.hexSha1Str instead
|
||
Tiddler.prototype.generateFingerprint = function()
|
||
{
|
||
return "0x" + Crypto.hexSha1Str(this.text);
|
||
};
|
||
|
||
//--
|
||
//-- Deprecated Number functions
|
||
//--
|
||
|
||
// @Deprecated: no direct replacement, since not used in core code
|
||
// Clamp a number to a range
|
||
Number.prototype.clamp = function(min,max)
|
||
{
|
||
var c = this;
|
||
if(c < min)
|
||
c = min;
|
||
if(c > max)
|
||
c = max;
|
||
return Number(c);
|
||
};
|
||
|
||
//--
|
||
//-- Deprecated utility functions
|
||
//-- Use the jQuery functions directly instead
|
||
//--
|
||
|
||
// Remove all children of a node
|
||
function removeChildren(e)
|
||
{
|
||
jQuery(e).empty();
|
||
}
|
||
|
||
// Remove a node and all it's children
|
||
function removeNode(e)
|
||
{
|
||
jQuery(e).remove();
|
||
}
|
||
|
||
// Return the content of an element as plain text with no formatting
|
||
function getPlainText(e)
|
||
{
|
||
return jQuery(e).text();
|
||
}
|
||
|
||
function addClass(e,className)
|
||
{
|
||
jQuery(e).addClass(className);
|
||
}
|
||
|
||
function removeClass(e,className)
|
||
{
|
||
jQuery(e).removeClass(className);
|
||
}
|
||
|
||
function hasClass(e,className)
|
||
{
|
||
return jQuery(e).hasClass(className);
|
||
}
|
||
|
||
//--
|
||
//-- Deprecated Wikifier code
|
||
//--
|
||
|
||
function wikifyPlain(title,theStore,limit)
|
||
{
|
||
if(!theStore)
|
||
theStore = store;
|
||
if(theStore.tiddlerExists(title) || theStore.isShadowTiddler(title)) {
|
||
return wikifyPlainText(theStore.getTiddlerText(title),limit,tiddler);
|
||
} else {
|
||
return "";
|
||
}
|
||
}
|
||
|
||
//]]>
|
||
</script>
|
||
<script id="jslibArea" type="text/javascript">
|
||
//<![CDATA[
|
||
/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */
|
||
(function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bA.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bW(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bP,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bW(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bW(a,c,d,e,"*",g));return l}function bV(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bL),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function by(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bt:bu;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bf(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function V(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(Q.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(w,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(!b)return-1;if(I)return I.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g+"With"](this===b?d:this,[h])}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u,v;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete
|
||
t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,M(a.origType,a.selector),f.extend({},a,{handler:L,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,M(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?D:C):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=D;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=D;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=D,this.stopPropagation()},isDefaultPrevented:C,isPropagationStopped:C,isImmediatePropagationStopped:C};var E=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},F=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?F:E,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?F:E)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="submit"||c==="image")&&f(b).closest("form").length&&J("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&J("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var G,H=function(a){var b=f.nodeName(a,"input")?a.type:"",c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var K={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||C,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=w.exec(h),k="",j&&(k=j[0],h=h.replace(w,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,K[h]?(a.push(K[h]+k),h=h+k):h=(K[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+M(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+M(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var N=/Until$/,O=/^(?:parents|prevUntil|prevAll)/,P=/,/,Q=/^.[^:#\[\.,]*$/,R=Array.prototype.slice,S=f.expr.match.POS,T={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(V(this,a,!1),"not",a)},filter:function(a){return this.pushStack(V(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=S.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|object|embed|option|style)/i,bb=/checked\s*(?:[^=]|=\s*.checked.)/i,bc=/\/(java|ecma)script/i,bd=/^\s*<!(?:\[CDATA\[|\-\-)/,be={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bb.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bf(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bl)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!ba.test(a[0])&&(f.support.checkClone||!bb.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean
|
||
(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bk(k[i]);else bk(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bc.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bm=/alpha\([^)]*\)/i,bn=/opacity=([^)]*)/,bo=/([A-Z]|^ms)/g,bp=/^-?\d+(?:px)?$/i,bq=/^-?\d/,br=/^([\-+])=([\-+.\de]+)/,bs={position:"absolute",visibility:"hidden",display:"block"},bt=["Left","Right"],bu=["Top","Bottom"],bv,bw,bx;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bv(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=br.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bv)return bv(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return by(a,b,d);f.swap(a,bs,function(){e=by(a,b,d)});return e}},set:function(a,b){if(!bp.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cr(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cq("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cq("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cr(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cq("show",1),slideUp:cq("hide",1),slideToggle:cq("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return d.step(a)}var d=this,e=f.fx;this.startTime=cn||co(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&f.timers.push(g)&&!cl&&(cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||co(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cs=/^t(?:able|d|h)$/i,ct=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cu(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cs.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
|
||
//]]>
|
||
</script>
|
||
<script id="jqueryArea" type="text/javascript">
|
||
//<![CDATA[
|
||
/*
|
||
jQuery.encoding.digests.sha1.js
|
||
|
||
SHA-1 digest and associated utility functions
|
||
|
||
Copyright (c) UnaMesa Association 2009
|
||
|
||
Dual licensed under the MIT and GPL licenses:
|
||
http://www.opensource.org/licenses/mit-license.php
|
||
http://www.gnu.org/licenses/gpl.html
|
||
*/
|
||
|
||
(function($) {
|
||
|
||
if(!$.encoding)
|
||
$.encoding = {};
|
||
$.extend($.encoding,{
|
||
strToBe32s: function(str) {
|
||
// Convert a string to an array of big-endian 32-bit words
|
||
var be=[];
|
||
var len=Math.floor(str.length/4);
|
||
var i, j;
|
||
for(i=0, j=0; i<len; i++, j+=4) {
|
||
be[i]=((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
|
||
}
|
||
while(j<str.length) {
|
||
be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
|
||
j++;
|
||
}
|
||
return be;
|
||
},
|
||
be32sToStr: function(be) {
|
||
// Convert an array of big-endian 32-bit words to a string
|
||
var str='';
|
||
for(var i=0;i<be.length*32;i+=8) {
|
||
str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
|
||
}
|
||
return str;
|
||
},
|
||
be32sToHex: function(be) {
|
||
// Convert an array of big-endian 32-bit words to a hex string
|
||
var hex='0123456789ABCDEF';
|
||
var str='';
|
||
for(var i=0;i<be.length*4;i++) {
|
||
str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
|
||
}
|
||
return str;
|
||
}
|
||
});
|
||
})(jQuery);
|
||
|
||
|
||
(function($) {
|
||
|
||
if(!$.encoding.digests)
|
||
$.encoding.digests = {};
|
||
$.extend($.encoding.digests,{
|
||
hexSha1Str: function(str) {
|
||
// Return, in hex, the SHA-1 hash of a string
|
||
return $.encoding.be32sToHex($.encoding.digests.sha1Str(str));
|
||
},
|
||
sha1Str: function(str) {
|
||
// Return the SHA-1 hash of a string
|
||
return sha1($.encoding.strToBe32s(str),str.length);
|
||
},
|
||
sha1: function(x,blen) {
|
||
// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
|
||
return sha1($.encoding.strToBe32s(str),str.length);
|
||
}
|
||
});
|
||
|
||
// Private functions.
|
||
function sha1(x,blen) {
|
||
// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
|
||
function add32(a,b) {
|
||
// Add 32-bit integers, wrapping at 32 bits
|
||
// Uses 16-bit operations internally to work around bugs in some JavaScript interpreters.
|
||
var lsw=(a&0xFFFF)+(b&0xFFFF);
|
||
var msw=(a>>16)+(b>>16)+(lsw>>16);
|
||
return (msw<<16)|(lsw&0xFFFF);
|
||
}
|
||
function AA(a,b,c,d,e) {
|
||
// Cryptographic round helper function. Add five 32-bit integers, wrapping at 32 bits, second parameter is rotated left 5 bits before the addition
|
||
// Uses 16-bit operations internally to work around bugs in some JavaScript interpreters.
|
||
b=(b>>>27)|(b<<5);
|
||
var lsw=(a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
|
||
var msw=(a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
|
||
return (msw<<16)|(lsw&0xFFFF);
|
||
}
|
||
function RR(w,j) {
|
||
// Cryptographic round helper function.
|
||
var n=w[j-3]^w[j-8]^w[j-14]^w[j-16];
|
||
return (n>>>31)|(n<<1);
|
||
}
|
||
|
||
var len=blen*8;
|
||
x[len>>5] |= 0x80 << (24-len%32);
|
||
x[((len+64>>9)<<4)+15]=len;
|
||
var w=new Array(80);
|
||
|
||
var k1=0x5A827999;
|
||
var k2=0x6ED9EBA1;
|
||
var k3=0x8F1BBCDC;
|
||
var k4=0xCA62C1D6;
|
||
|
||
var h0=0x67452301;
|
||
var h1=0xEFCDAB89;
|
||
var h2=0x98BADCFE;
|
||
var h3=0x10325476;
|
||
var h4=0xC3D2E1F0;
|
||
|
||
for(var i=0;i<x.length;i+=16) {
|
||
var j=0;
|
||
var t;
|
||
var a=h0;
|
||
var b=h1;
|
||
var c=h2;
|
||
var d=h3;
|
||
var e=h4;
|
||
while(j<16) {
|
||
w[j]=x[i+j];
|
||
t=AA(e,a,d^(b&(c^d)),w[j],k1);
|
||
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a=t; j++;
|
||
}
|
||
while(j<20) {
|
||
w[j]=RR(w,j);
|
||
t=AA(e,a,d^(b&(c^d)),w[j],k1);
|
||
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a=t; j++;
|
||
}
|
||
while(j<40) {
|
||
w[j]=RR(w,j);
|
||
t=AA(e,a,b^c^d,w[j],k2);
|
||
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a=t; j++;
|
||
}
|
||
while(j<60) {
|
||
w[j]=RR(w,j);
|
||
t=AA(e,a,(b&c)|(d&(b|c)),w[j],k3);
|
||
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a=t; j++;
|
||
}
|
||
while(j<80) {
|
||
w[j]=RR(w,j);
|
||
t=AA(e,a,b^c^d,w[j],k4);
|
||
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a=t; j++;
|
||
}
|
||
h0=add32(h0,a);
|
||
h1=add32(h1,b);
|
||
h2=add32(h2,c);
|
||
h3=add32(h3,d);
|
||
h4=add32(h4,e);
|
||
}
|
||
return [h0,h1,h2,h3,h4];
|
||
}
|
||
})(jQuery);
|
||
/*
|
||
jQuery.twStylesheet.js
|
||
|
||
jQuery plugin to dynamically insert CSS rules into a document
|
||
|
||
Usage:
|
||
jQuery.twStylesheet applies style definitions
|
||
jQuery.twStylesheet.remove neutralizes style definitions
|
||
|
||
Copyright (c) UnaMesa Association 2009
|
||
|
||
Triple licensed under the BSD, MIT and GPL licenses:
|
||
http://www.opensource.org/licenses/bsd-license.php
|
||
http://www.opensource.org/licenses/mit-license.php
|
||
http://www.gnu.org/licenses/gpl.html
|
||
*/
|
||
|
||
(function($) {
|
||
|
||
var defaultId = "customStyleSheet"; // XXX: rename to dynamicStyleSheet?
|
||
|
||
// Add or replace a style sheet
|
||
// css argument is a string of CSS rule sets
|
||
// options.id is an optional name identifying the style sheet
|
||
// options.doc is an optional document reference
|
||
// N.B.: Uses DOM methods instead of jQuery to ensure cross-browser comaptibility.
|
||
$.twStylesheet = function(css, options) {
|
||
options = options || {};
|
||
var id = options.id || defaultId;
|
||
var doc = options.doc || document;
|
||
var el = doc.getElementById(id);
|
||
if(doc.createStyleSheet) { // IE-specific handling
|
||
if(el) {
|
||
el.parentNode.removeChild(el);
|
||
}
|
||
doc.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd",
|
||
' <style id="' + id + '" type="text/css">' + css + '</style>'); // fails without
|
||
} else { // modern browsers
|
||
if(el) {
|
||
el.replaceChild(doc.createTextNode(css), el.firstChild);
|
||
} else {
|
||
el = doc.createElement("style");
|
||
el.type = "text/css";
|
||
el.id = id;
|
||
el.appendChild(doc.createTextNode(css));
|
||
doc.getElementsByTagName("head")[0].appendChild(el);
|
||
}
|
||
}
|
||
};
|
||
|
||
// Remove existing style sheet
|
||
// options.id is an optional name identifying the style sheet
|
||
// options.doc is an optional document reference
|
||
$.twStylesheet.remove = function(options) {
|
||
options = options || {};
|
||
var id = options.id || defaultId;
|
||
var doc = options.doc || document;
|
||
var el = doc.getElementById(id);
|
||
if(el) {
|
||
el.parentNode.removeChild(el);
|
||
}
|
||
};
|
||
|
||
})(jQuery);
|
||
//]]>
|
||
</script>
|
||
<script type="text/javascript">
|
||
//<![CDATA[
|
||
if(useJavaSaver)
|
||
document.write("<applet style='position:absolute;left:-1px' name='TiddlySaver' code='TiddlySaver.class' archive='TiddlySaver.jar' width='1' height='1'></applet>");
|
||
//]]>
|
||
</script>
|
||
<!--POST-SCRIPT-START-->
|
||
<!--POST-SCRIPT-END-->
|
||
</body>
|
||
</html>
|