/* * helpinit.sli * * This file is part of NEST. * * Copyright (C) 2004 The NEST Initiative * * NEST is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * NEST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NEST. If not, see <http://www.gnu.org/licenses/>. * */ /* Sli-commands initializing Online-help. */ % Define the root of the help files /HelpRoot statusdict /prgdocdir get (/help) join def /HelpdeskURL statusdict /prgdocdir get (/index.html) join def /HelpExtension (.hlp) def /HtmlExtension (.html) def /TextIndexFilename (helpindex.hlp) def /HtmlIndexFilename (helpindex.html) def % This is where the generated help will go: /HelpSubdirs [(cc) (sli)] def /CPPHelpRoot HelpRoot (/) join (cc) join def /SLIHelpRoot HelpRoot (/) join (sli) join def /HelpSearchPath [CPPHelpRoot SLIHelpRoot] def % regular expressions for help system /SimpleKeyword ((Name:|Synopsis:|Description:|Parameters:|Options:|Examples:|Bugs:|Diagnostics:|Author:|FirstVersion:|Remarks:|Availability:|References:|Source:|Sends:|Receives:|Transmits:)) regcomp def /ReferencingKeyword ((SeeAlso:|Variants:)) regcomp def /InvariantsKeyword ((Examples:)) regcomp def /* BeginDocumentation Name: makehelp - Extracts documentation from a source file Synopsis: string makehelp -> - Description: The function scans the file specified by the argument and generates plain text online help information for all functions documented in this file. A separate file with the extension specified by variable HelpExtension is generated for each function. The help information can be viewed in a terminal by function help. The generated files are the source from which the hypertext online help is generated by an undocumented function in a next step. The start of documentation for a function in the source file is indicated by the string "slash-asterisk [white]BeginDocumentation" (without the quotation marks), where slash-star is the character "/" immediately followed by "*" (with the quotation marks in both cases). The end of the documentation is indicated by the same two characters in reverse order. Thus, the documentation of a function is enclosed in a C-style comment. The help files are created in the directory specified by variable CPPHelpRoot or by variable SLIHelpRoot depending on the type of the source file. The makehelp function recognizes the keyword "name:" in uppercase letters. The rest of the line containing this keyword defines the name of the function the documentation refers to followed by a short characterization of its purpose. The two components are separated by a the three character string " - ". More formally, makehelp extracts help information if the source file matches [any][slash-star[[white]BeginDocumentation[any]\n [white] name: [any][space]-[space][any]\n[any]star-slash]] Function makehelp appends a line to the help file starting with the keyword "source:" in uppercase letters followed by the absolute path to the source file. This backward reference enables the help system of NEST to direct an editor and validation tools to the implementation of the documented function. The generator of hypertext online help operating on the help file recognizes many more keywords for structuring and cross linking the documentation. Parameters: The argument specifies the name of the source file by an absolute path. If no absolute path is provided all directories listed in the variable MakeHelpSearchPath are searched for the file. Examples: (sli-init.sli) makehelp (/home/user/slifunctions/MySli.sli) makehelp Author: Hehl, docu edited by Sirko Straube FirstVersion: 14.4.1999 SeeAlso: help, helpindex, :makeallhelp, :makehelpindex */ /makehelp_s { << >> begin /TheFile Set % save FileName in /TheFile mark % scan for valid extension TheFile (.sli) :searchifend_s { /DestPath SLIHelpRoot def exit} case TheFile (.cpp) :searchifend_s { /DestPath CPPHelpRoot def exit} case TheFile (.cc) :searchifend_s { /DestPath CPPHelpRoot def exit} case TheFile (.h) :searchifend_s { /DestPath CPPHelpRoot def exit} case { TheFile end /makehelp /InvalidSourceExtensionError raiseerror } switchdefault TheFile (/) searchif % Do we have an explicit path? { /SourceLine TheFile def % Yes, remember TheFile ifstream % and try to open } { MakeHelpSearchPath TheFile LocateFileNames % Try all source directories.. dup length 0 eq{ pop false % no file found } { 0 get dup % remember for last .hlp line, e.g. /SourceLine Set % prepare SourceLine ifstream % open the first match } ifelse % filename found } ifelse % direct path or SearchPath { /SourceFile Set % store Source ( Source: ) SourceLine join /SourceLine Set SourceFile { ws % eat white igood not exch ieof 3 -1 roll or {exit} if % file still valid? getc (/) 0 get eq % look for / { igood not exch ieof 3 -1 roll or {exit} if % file still valid? getc (*) 0 get eq % look for * { ws igood not exch ieof 3 -1 roll or {exit} if % file still valid? oldgetline % /* detected (BeginDocumentation) searchif { ws igood not exch ieof 3 -1 roll or { pop TheFile end /makehelp /BeginDocumentationKeyNotContinuedError raiseerror } if oldgetline dup (Name:) search { pop pop ( - ) search { ( ) 2 trim % remove spaces around keyword HelpExtension join % make filename DestPath exch joinpath /HelpFileName Set M_STATUS (makehelp) (creating ) HelpFileName join message HelpFileName (w) file /HelpFile Set pop pop % remaining from search... HelpFile exch <- endl pop SourceFile { igood not exch ieof 3 -1 roll or { HelpFile closeostream pop pop % Source popped twice TheFile end /makehelp /IncompleteDocumentationError raiseerror } if oldgetline dup (*/) searchif { pop % doubled Line popped! HelpFile SourceLine <- endl % add Source to .hlp closeostream exit } if HelpFile exch <- endl pop } loop pop % SourceFile on stack twice here !!! } { 3 npop TheFile end % pop Searchedline, original line, File /makehelp /MissingObligatoryMinusAfterCommandNameError raiseerror }ifelse } { 3 npop TheFile end % pop Searchedline, original line, File /makehelp /KeyName:ExpectedError raiseerror } ifelse } if } { oldgetline pop % no DocText (*) } ifelse } { oldgetline pop % no DocText (/) } ifelse % / found } loop % read source closeistream } { TheFile end /makehelp /FileNotFoundError raiseerror } ifelse % stream open for reading? end } bind def /makehelp trie [/stringtype] /makehelp_s load addtotrie def /* Documentation (not included in helpdesk) Name: :searchifend_s - check wether a substring is the end of another Synopsis: string1 string2 searchif -> bool Description: check wether a substring is the end of another Parameters: string1 : string to search into string2 : endstring to search for Examples: (hallo.h) (.h) :searchifend --> true Bugs: :Function because may be of little use ... Does not work if there's a multiple occurence! Author: Hehl FirstVersion: April 20, 1999 Remarks: if command used by any other person, should be moved to misc_helpers.sli ! SeeAlso: search, searchif */ /:searchifend_s % string string --> bool { search_s { pop pop () eq } { pop false } ifelse } bind def /* BeginDocumentation Name: :makehelpindex - create a list of all commands Synopsis: :makehelpindex -> - Description: :makehelpindex compiles the short descriptions of all commands to a list which is stored in the file index.hlp. This command is executed as part of NEST's installation procedure. You should not need to call this command. Perhaps you were looking for the "helpindex" command? Author: Hehl FirstVersion: April 20, 1999 Remarks: Improved documentation R Kupper, 17-jul-2008 SeeAlso: helpindex, help, makehelp, :makeallhelp */ /:makehelpindex { << >> begin /WorkingDir Directory def /TheIndex [] def HelpSearchPath { dup /ThePath Set SetDirectory pop (.*) FileNames { /currentfile Set currentfile dup HelpExtension search { 4 1 roll % filename without .hlp stored pop pop % other substrings popped ThePath exch joinpath ifstream % was given us by ls, exists! { oldgetline % read first line exch closeistream % and forget about the rest ( - ) search { pop pop ( ) 2 trim exch { % normalize command to 20 characters, ( ) join % but make sure that the command is terminated % by a white-space. dup length 20 gt {exit} if } loop exch join TheIndex exch append /TheIndex Set } { pop pop M_WARNING (:makehelpindex) (Illformed "Name" line in file ) WorkingDir currentfile joinpath join (:) join message M_WARNING (:makehelpindex) ( missing "-" after command name.) message } ifelse } { pop % commandname } ifelse } { % no .hlp filename pop pop % (shouldn't occur, but who knows?) } ifelse } forall } forall HelpRoot TextIndexFilename joinpath (w) {file} stopped { errordict /newerror false put 3 npop end % file with its 2 args popped M_ERROR (:makehelpindex) (Could not write to index file: ) HelpRoot TextIndexFilename joinpath join message /:makehelpindex /IOError raiseerror } { /IndexFile Set TheIndex :sort { IndexFile exch <- endl ; } forall IndexFile closeostream } ifelse WorkingDir SetDirectory pop end } bind def /* BeginDocumentation Name: :hlp2html - Generate HTML-help pages for all existing help files. Synopsis: :hlp2html -> - Description: :hlp2html operator translates .hlp files generated by "makehelp" to HTML. There are two types of keywords: normal and referencing. Referencing Keywords are SeeAlso and Variants, each followed by a colon. The operator will try to set up hyperlinks for every name found after a Referencing Keyword, seperated by commas. A normal Keyword will simply be used for formatting. :hlp2html generates several warnings if it stumbles accross syntactical inccorect documentation files. Normally called by :makeallhelp. Parameters: none Examples: :hlp2html. Normal usage is to call :makeallhelp instead! Bugs: Author: Hehl FirstVersion: Oct 13th, 1999 Remarks: This is not implemented for performance reasons. The regex search probably is not the fastes solution. SeeAlso: :makeallhelp, help */ /:hlp2html { << >> begin %%===================================================== %% Valid documentation keywords. %% %% IF YOU ADD, REMOVE, OR MODIFY ANY OF THESE KEYWORDS, %% YOU MUST ALSO UPDATE THE FILES %% synod2/doc/quickref.html %% AND %% synod2/lib/help/doc_header.txt! %%===================================================== /WorkingDir Directory def HelpSearchPath { dup /CurrentDir Set SetDirectory pop (.*\\) HelpExtension join FileNames % dup == { dup (Translating File ) CurrentDir join exch joinpath M_DEBUG message /in Set /out in dup length 4 sub 4 erase dup /TheCommand Set (.html) join ofstream not {end /:hlp2html /IOError raiseerror} if def out (<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <html> <head> <title>NEST Command Index: ) <- TheCommand <- (</title> <style type="text/css"> body { padding: 0; margin: 0; } a { color: #339; text-decoration: none; } a:visited { color: #339; text-decoration: none; } a:hover { text-decoration: underline; } h1 { padding: 15px 0 0 15px; } p { padding-left: 15px; } table.headerfooter { margin: 20px 0 20px 0; background-color: #eee; width: 100%; height: 30px; border-top: 2px solid #ccc; border-bottom: 2px solid #ccc; text-align: center; } </style> </head> <body bgcolor="white" fgcolor="black"> <h1>Command: ) <- TheCommand <- (</h1> <table class="headerfooter"> <tr> <td width="30%" align=center><a href="../../index.html">NEST HelpDesk</a></td> <td width="30%" align=center><a href="../helpindex.html">Command Index</a></td> <td width="30%" align=center><a href="../../quickref.html">NEST Quick Reference</a></td> </tr> </table> <p> <table>) <- endl ; /TableIsOpen false def % This flag is used to monitor the table. /in in ifstream not {end /HTML /IOError raiseerror} if def { % now we read the file line by line in getline not {pop exit} if /Line Set pop SimpleKeyword Line 1 0 regexec 0 eq { TableIsOpen { out (</pre></td></tr>) <- ; % close the open table row /TableIsOpen false def % and note it. } if 0 get /where Set Line where 0 get dup where 1 get exch sub getinterval dup (<tr><td valign="top"><b>) exch join (</b></td><td valign="top"><pre>) join Line regex_replace out exch <- endl ; /TableIsOpen true def % Make a note that we have opened a table row. It must be closed % when the next keyword has been found, or the file is closed. } { pop %array from regexec doesn't mean anything right here ReferencingKeyword Line 1 0 regexec 0 eq { 0 get /where Set Line where 0 get dup where 1 get exch sub getinterval /ThisKeyword Set out (<tr><td valign="top"><b>) ThisKeyword join (</b></td><td valign="top">) join <- ; Line length where 1 get eq {()} {Line dup length where 1 get sub where 1 get exch getinterval}ifelse ( +) () 3 -1 roll regex_replace dup length 0 eq { pop (Removed empty Reference Keyword ") ThisKeyword join (" in ) join TheCommand join M_DEBUG message } { (,) join /Rest Set { Rest length 0 eq {exit} if Rest (,) search not { % this case should never happen at all! pop TheCommand (: Syntax error while hyperlinking ) join Line join M_WARNING message out (<tr><td></td><td>) Line join (</td></tr>) join <- endl ; exit } { /TheLink Set pop /Rest Set /LinkTo () def HelpSubdirs { (../) exch join TheLink HelpExtension join joinpath dup ifstream {pop /LinkTo Set} {pop} ifelse } forall LinkTo length 0 eq { (Dead Link to ) TheLink join ( in ) join TheCommand join M_WARNING message out TheLink ( ) join <- ; } { out LinkTo dup length 3 sub 3 erase (html) join (<a href=") exch join ("><tt>) join TheLink join (</tt></a> ) join <- ; } ifelse } ifelse } loop } ifelse % Here, the referencing-keyword table row is closed, % so we don't have to use the flag TableIsOpen. out (</td></tr>) <- endl ; } { % Here, we havent't got a keyword. Thus, we just have to % print the line. % At this position, TableIsOpen should be true! pop %array from regexec out Line <- endl ; } ifelse } ifelse } loop out TableIsOpen { (</pre></td></tr>) <- /TableIsOpen false def } if (</table> </p> <table class="headerfooter"> <tr> <td width="30%" align=center><a href="../../index.html">NEST HelpDesk</a></td> <td width="30%" align=center><a href="../helpindex.html">Command Index</a></td> <td width="30%" align=center><a href="../../quickref.html">NEST Quick Reference</a></td> </tr> </table> <p style="text-align:center"> © 2000-2010 <a href="http://www.nest-initiative.org">The NEST Initiative</a> </p> </body>\n</html>) <- endl closeostream } forall } forall WorkingDir SetDirectory pop HelpRoot TextIndexFilename joinpath ifstream not {/HMTL /IOError raiseerror} if /in Set HelpRoot HtmlIndexFilename joinpath ofstream not {/HMTL /IOError raiseerror} if /out Set out (<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <html> <head> <title>NEST Command Index</title> <style type="text/css"> body { padding: 0; margin: 0; } h1 { padding: 15px 0 0 15px; } p { padding-left: 15px; } a { color: #339; text-decoration: none; } a:visited { color: #339; text-decoration: none; } a:hover { text-decoration: underline; } h1 a { color: #000; text-decoration: none; } table.headerfooter { margin: 20px 0 20px 0; background-color: #eee; width: 100%; height: 30px; border-top: 2px solid #ccc; border-bottom: 2px solid #ccc; text-align: center; } table.commands { margin: 15px 0 15px 0; background-color: #eee; width: 90%; border: 2px solid #ccc; border-spacing: 0px; border-collapse: collapse; } table.commands td { border-bottom: 1px solid #ccc; border-right: 1px dotted #ccc; padding: 5px 0 5px 10px; text-align: left; } table.letteridx { margin: 0; background-color: #eee; width: 90%; border: 2px solid #ccc; border-spacing: 0px; border-collapse: collapse; } table.letteridx td { border-right: 1px solid #ccc; padding: 5px; text-align: center; } table.letteridx a { display: block; height: 100%; width: 100%; } </style> </head> <body bgcolor="white" fgcolor="black"> <h1><a name="top">NEST Command Index</a></h1> <table class="headerfooter"> <tr> <td width="50%" align=center><a href="../index.html">NEST HelpDesk</a></td> <td width="50%" align=center><a href="../quickref.html">NEST Quick Reference</a></td> </tr> </table>) <- endl ; /Letters [] def /CommandsByLetter << >> def /ThePath HelpRoot (/) join def { in getline not {pop exit} if /Line Set pop /HtmlLine (<tr><td width="33%">) def Line ( ) search pop /command Set pop /Description Set /LinkTo () def HelpSubdirs { dup HelpRoot exch joinpath command joinpath (.html) join ifstream {exch /LinkTo Set} if pop } forall LinkTo length 0 eq { (Dead Helpindex Link to ) command join M_WARNING message out command <- ; } { % We only collect data here to be printed later /cmdFirstLetter command 0 1 getinterval ToUppercase def % We add a new empty array only for the first occurence of a letter % and if the letter is not known yet CommandsByLetter cmdFirstLetter cvlit known not { /Letters Letters cmdFirstLetter append def CommandsByLetter cmdFirstLetter cvlit [] put } if /HtmlLine HtmlLine (<a href=") join LinkTo command joinpath join (.html">) join command join (</a>) join def } ifelse /HtmlLine HtmlLine (</td><td>) join Description join (</td></tr>) join def CommandsByLetter cmdFirstLetter cvlit get HtmlLine append CommandsByLetter exch cmdFirstLetter cvlit exch put } loop % We want to have the non-letters (:, <, ...) at the end /Letters Letters Sort def Letters {0 get 65 lt} Map [false] search { length /rotation Set } { 0 /rotation Set } ifelse /Letters Letters rotation Rotate def Letters { /LetterQ Set out (<center>\n<a name=") LetterQ join ("><table class="letteridx">\n<tr>) join <- endl ; Letters { /CurrentLetter Set CurrentLetter LetterQ eq { out (<td>) CurrentLetter join (</td>) join <- endl ; } { out (<td><a href="#) CurrentLetter join (">) join CurrentLetter join (</a></td>) join <- endl ; } ifelse } forall out (</tr>\n</table></a>\n</center>\n\n) <- endl ; out (<center><table class="commands">\n) <- endl ; CommandsByLetter LetterQ cvlit get { out exch <- endl ; } forall out (</table></center>) <- endl ; } forall out (<table class="headerfooter"> <tr> <td width="30%" align=center><a href="../index.html">NEST HelpDesk</a></td> <td width="30%" align=center><a href="#top">Top</a></td> <td width="30%" align=center><a href="../quickref.html">NEST Quick Reference</a></td> </tr> </table> <p style="text-align:center"> © 2000-2010 <a href="http://www.nest-initiative.org">The NEST Initiative</a> </p> </body>\n</html>) <- endl ; end } bind def /* BeginDocumentation Name: :makeallhelp - creates/updates all oneline-help texts and the index Synopsis: :makeallhelp -> - Description: :makeallhelp calls makehelp for any file found in one of the directories of MakeHelpSearchPath. Afterwards calls :makehelpindex to update index file. This command is executed as part of NEST's installation procedure. You should not need to call this command. Perhaps you were looking for the "helpindex" command? Author: Hehl FirstVersion: April 20, 1999 Remarks: Should get a 'forced' option where it even tries to continue parsing source files where a corrupt documentation was found. Improved documentation R Kupper 17-jul-2008 SeeAlso: help, makehelp, helpindex, :makehelpindex */ /:makeallhelp { << >> begin /WorkingDir Directory def %save old working dir SLIHelpRoot SetDirectory not {SLIHelpRoot MakeDirectory} if CPPHelpRoot SetDirectory not {CPPHelpRoot MakeDirectory} if (chmod 755 ) SLIHelpRoot join system (chmod 755 ) CPPHelpRoot join system WorkingDir cd MakeHelpSearchPath { /makeallhelp_ThePath Set M_INFO (:makeallhelp) (Processing directory ) makeallhelp_ThePath join message makeallhelp_ThePath SetDirectory pop (.*) FileNames { /makeallhelp_TheFile Set M_STATUS (:makeallhelp) (processing file ) makeallhelp_TheFile join message makeallhelp_ThePath makeallhelp_TheFile joinpath {makehelp} stopped { errordict /errorname get /InvalidSourceExtensionError eq { % this one's not reported pop pop % pop command name and argument errordict /newerror false put } { M_ERROR (:makeallhelp) (Documentation error in file ) makeallhelp_ThePath makeallhelp_TheFile joinpath join message handleerror } ifelse } if } forall } forall WorkingDir SetDirectory pop %restore working dir end :makehelpindex :hlp2html } bind def /*BeginDocumentation Name: ppage - print a file to cout in chunks of 20 lines. Description: This is a "poor man's pager" implemented in SLI. It can be used when no external pager program is available. Synopsis: ifstream ppage -> - (filename) ppage -> - Diagnostics: If a filename is given and does not exist, /FileOpenError is raised. If an ifstream is given, it will be closed by ppage. Author: Marc-Oliver Gewaltig, R Kupper FirstVersion: 27-sep-2007 SeeAlso: page */ /ppage [/istreamtype] { { () = 20 { getline { (> ) =only = } {exit} ifelse } repeat igood not {exit} if () = (Press <RETURN> to continue or "q <RETURN>" to quit. ) readline { 0 get 113 eq {exit} if } if } loop closeistream () = } def /ppage [/stringtype] { dup ifstream not { /ppage /FileOpenError raiseerror } if ppage pop } def /* BeginDocumentation Name: page - Conveniently display contents of a long file Synopsis: (filename) page -> - Description: The "page" command is used by NEST's online-help system to display the help pages. It displays the contents of a file, either through a built-in pager, or an external pager program. The text you are reading right now is displayed using "page". You can customize the display. Type "/page ShowOptions" to show your current settings. Use the "SetOptions" command to customize the pager program. Here are some useful suggestions. You will want to put your favourite into your ~/.nestrc file (see "/nestrc help"): 1. /page << /command (more) % Use more as a pager /wait true >> SetOptions % and wait for termination 2. /page << /command (less -S) % Use less as a pager /wait true >> SetOptions % and wait for termination 3. /page << /command (xterm -e less -S) % Run less in a separate xterm window... /wait false >> SetOptions % ..so we can go on working in parallel. 4. /page << /command (xless) % Use xless as a pager /wait false >> SetOptions % xless opens it's own window. 5. /page << /command (xemacs) % If you like to show helpfiles using xemacs. /wait false >> SetOptions % xemacs opens it's own window. 6. /page << /command false >> SetOptions % use built-in pager. 7. /page ResetOptions % Return to the default configuration ($PAGER or built-in pager). Options: /command - UNIX command to display a file (default: see below) /command can be either false or a string. If /command is set to false, "page" uses the simple built-in pager "ppage" for display. If it is set to the name of a UNIX program, "page" will execute this program as a child process, passing the name of the file as argument. /command defaults to the contents of the $PAGER environment variable. If this variable is not set, it defaults to false. /wait - whether to wait for the UNIX program to finish. (default: true) If /wait is set to true, the "page" command will not return until the UNIX process is terminated. Use this setting for all pager programs that write to stdout. If /wait is set to false, "page" will return immediately after creating the child process. Use this setting for all pager programs that open up their own window. The value of /wait is ignored, if /command is set to false. Examples: The following example displays the license agreement that came with your copy of NEST: "statusdict /prgdatadir get (/LICENSE) join page" Bugs: The string contained in /command is processed by "breakup" to separate the command from its parameters. Be aware that there is a bug in the "breakup"-routine, which makes it impossible to pass a parameter containing blanks by enclosing it in quotation marks. WARNING: Setting the /wait option to false with a pager program that writes to stdout will screw up your SLI prompt. Author: R Kupper FirstVersion: Apr 22 1999, reworked 27-sep-2007 Remarks: If /wait is set to false, the "system"-command is called in no-care-mode. Be aware that this may be an expensive operation depending on the ressources your SLI-process occupies. (see description of "system"). Even if /wait is set to true, creation of a child process may be expensive. To avoid any overhead caused by process creation, set /command to false. SeeAlso: help, helpindex, license, system */ /page << /command (PAGER) getenv not {false} if /wait true >> Options /page [/stringtype] { /page /command GetOption false eq not % Is there a Pager program to use? {%yes, there is a Pager /page /wait GetOption % Shall we wait for its termination? {%yes, we shall wait for termination of pager process /page /command GetOption ( ) breakup exch append 0 system % Spawn Pager Program to display text 2 npop % Wait for Pager process to terminate and clear stack } {%no, we shall not wait for termination of pager process /page /command GetOption ( ) breakup exch append 1 system % Spawn orphaned Pager process to display text } ifelse } {%no, there is no Pager. So use our built-in poor man's pager: ppage } ifelse } def /* BeginDocumentation Name: help - prints help text for a given command Synopsis: /name help -> - Description: help displays the online help file of the command /name. This documantation is created during installation. help uses the command "page" to display its information. Type /page help to learn how to customize the output of this command. Parameters: /name is the command you want to read a help about. Examples: /help help %prints this text. /page help %learn how to customize the output of the help command /ThisIsDefinitelyNoCommand help %raises a NoHelpInformationError. Bugs: Author: Diesmann, Hehl, R Kupper FirstVersion: 26.3.1999 Remarks: help uses the command "page" to display its information. Type /page help to learn how to customize the output of this command. Commented 13 April, 1999 Developers are kindly requested to use our conventional header for commenting any new and all those older commands. SeeAlso: page, helpindex, helpdesk, apropos, which */ /help_l { cvs HelpExtension join HelpSearchPath exch LocateFileNames %Find *.hlp-File in HelpSearchPath dup [] eq not %Was a help file found? {%yes, a helpfile was found 0 get page } {%no, no helpfile was found /help /NoHelpInformationError raiseerror } ifelse } bind def /help_any { /help help_l /help /LiteralExpected raiseerror } def /help_ trie [/literaltype] /help_l load addtotrie [/stringtype] {cvlit help_l} addtotrie [/anytype] /help_any load addtotrie def /help { count 0 eq { :helptext } { help_ } ifelse } def /* BeginDocumentation Name: helpindex - displays a list of all commands Synopsis: helpindex -> - Description: helpindex prints a list of all commands together with a short summary of their usage. helpindex uses the command "page" to display its information. Type /page help to learn how to customize the output of this command. Parameters: none Examples: helpindex --> lists all commands Bugs: Should work with a string parameter giving some letters or keywords, e.g. (ma) helpindex --> list of all commands beginning with ma or (file) helpindex --> list of all commands for filehandling! Author: Hehl FirstVersion: April 20, 1999 Remarks: helpindex uses the command "page" to display its information. Type /page help to learn how to customize the output of this command. SeeAlso: help, apropos, which */ /helpindex { HelpRoot (/) join TextIndexFilename join page } bind def /* Documentation (not included in helpdesk) Name: :sort - dummy sorting via UNIX Synopsis: array :sort -> array Description: alphabetically sorts array via UNIX-sort. Don't know what happens to non-string arrays. Parameters: Examples: Bugs: Author: Hehl FirstVersion: May 19th, 1999 Remarks: Waiting for our real sorting mechanism as discussed on our 17/18 May meeting ... SeeAlso: */ /:sort_a { << >> begin (sort) spawn /i Set /o Set { o exch <- endl ; } forall o closeostream [] i { getline not {exit} if /zeile Set exch zeile append exch } loop closeistream end } bind def /:sort trie [/arraytype] /:sort_a load addtotrie def /* BeginDocumentation Name: helpdesk - Display on-line help in external browser Description: "helpdesk" opens a browser window with the SLI Online help. The browser executable to use must be specified by the user as a command option. (See "SetOptions" on how to do this.) Options: /command - UNIX command to use as browser (default: false) /command is initially set to false. "helpdesk" will issue a message that the user needs to specify the browser. Ths user will usually set /command to his preferred browser in his .nestrc file. Example: /helpdesk << /command (firefox) >> SetOptions If /command is set to the name of a UNIX program, "helpdesk" will execute this program as a child process, and use it to display the HTML-helpdesk. /wait - whether to wait for the UNIX program to finish. (default: false) If /wait is set to true, the "helpdesk" command will not return until the UNIX process is terminated. Use this setting for all browsers that use the terminal exclusively. If /wait is set to false, "helpdesk" will return immediately after creating the child process. Use this setting for all browsers that open up their own window. The value of /wait is ignored if /command is set to false. Author: Gewaltig, Eppler, Kupper SeeAlso: SetOptions, help, helpindex */ /helpdesk << /command false /wait false >> Options /helpdesk { /helpdesk /command GetOption false eq not { /helpdesk /wait GetOption { { /helpdesk /command GetOption ( ) join HelpdeskURL join 0 system 2 npop } stopped } { /helpdesk /command GetOption ( ) join HelpdeskURL join 1 system } ifelse } { M_ERROR (MissingOptionError) (NEST does not know how to connect to your browser. Please see the file ~/.nestrc to learn how to tell NEST about your browser.) message /helpdesk /MissingOptionError raiseerror } ifelse } def /* BeginDocumentation Name: edit - Open a file in an external editor Synopsis: (filename) edit -> - Options: /command - UNIX command to edit a file (default: see below) /command can be either false or a string. If /command is set to false, "edit" will issue a message that informs about how to set the editor If it is set to the name of a UNIX program, "edit" will execute this program as a child process, passing the name of the file as argument. /command defaults to the contents of the $EDITOR environment variable. If this variable is not set, it defaults to false. /wait - whether to wait for the UNIX program to finish. (default: true) If /wait is set to true, the "edit" command will not return until the UNIX process is terminated. Use this setting for all editors that use the terminal exclusively. If /wait is set to false, "edit" will return immediately after creating the child process. Use this setting for all editors that open up their own window. The value of /wait is ignored, if /command is set to false. Description: Opens the file specified by filename. Parameters: The name of a file to be edited (or created, if non-existent). Examples: (helloworld.sli) edit Bugs: Author: Schrader FirstVersion: Remarks: The location of the file is only specified by the parameter; SLISearchPath is not scanned as e.g. in 'run'. SeeAlso: page, run */ /edit << /command (EDITOR) getenv not {false} if /wait true >> Options /edit [/stringtype] { /edit /command GetOption false eq not { % yes, there is an Editor /edit /wait GetOption { % yes, we shall wait for termination of editor process /edit /command GetOption ( ) join exch join 0 system 2 npop } { % no, we shall not wait for termination of editor process /edit /command GetOption ( ) join exch join 1 system } ifelse } { /edit MissingOptionError }ifelse } bind def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % experimental code for invariants and test driven % implementation % /* BeginDocumentation Name: --> - longrightarrow, usually delayed comparison Synopsis: --> -> /--> Description: The symbol --> is used in the example sections of the NEST documentation to indicate the transformation an operator performs to its arguments. The SLI operator --> is defined to just reproduce itself. This enables NEST to evaluate the example sections as regular SLI code. As a result, the arguments of the documented operator and its results are separated by the literaal /-->. A parser for infix notation can then apply the documented operator to the values on the left side of --> and compare the results to the values on the right side of --> Examples: [8 --> 6] --> 8 /--> cvx exec 6 3 arraystore Author: Diesmann FirstVersion: 080506 Remarks: The idea of --> is to contribute to a notation for test driven programming and user documentation which keeps the syntactic clutter at a minimum. SeeAlso: makehelp, helpdesk, EvaluateLiteralInfixes */ /--> /--> def /* BeginDocumentation Name: EvaluateLiteralInfixes - Evaluates an array of infix expressions Synopsis: array -> array Description: The function evaluates an array of expressions assuming that every literal is an infix operator. Inside this function --> is defined as eq, the comparison for equality. Examples: [ 5 /add 6 /sub 2] EvaluateLiteralInfixes --> [9] [ 5 --> 6 true ] EvaluateLiteralInfixes --> [false true] Author: Diesmann FirstVersion: 080506 Remarks: With the further development of test driven programming and unit testing in NEST, the function may develop into a more complete parser for infix notation SeeAlso: makehelp, helpdesk, --> */ /EvaluateLiteralInfixes { << /--> /eq load >> begin % source array with infix expression container % source [] { % loop over source array until empty exch empty {pop exit } if % target source dup First exch Rest % target f source rollu % source target f dup type /literaltype eq % handle literal operators { % source target f % f is a literal exch dup Most exch Last % source f target a 4 -1 roll % f target a source dup Rest exch First % f target a source b exch % f target a b source 5 1 roll % source f target a b 4 -1 roll % source target a b f cvn exec % source target abf append % source target } { % handle all operands % source target f % f is not a literal append % source target } ifelse } loop % target end } def /* BeginDocumentation Name: validate - Check if a function is consistent with all its examples Synopsis: /literal -> boolean Description: The function validate checks whether the examples in the documentation of the function specified by the literal argument work as documented. Every example in the example section is expected to result in a boolean value. validate only returns true if the result of all examples is true. In order to make the documentation of examples more readable validate supports a special (infix) syntax for the examples: a1 ... an --> b1 ...bm is translated to a b eq assuming that the sequence ai collapses to a and the sequence bj to b. Thus, --> has delayed execution time and is only processed after all expressions in the example section have been executed once. The --> expressions can be freely mixed with regular SLI code boolean expressions like a b eq The documentation of function Part contains several examples. Before a function can be validated it needs to be registered with the help system. This is required because in SLI several functions can be defined in the same source file. Thus, only after processing the source file SLI is aware of the functions implemented by this file. The help system of SLI stores the path to the implementing file with the documentation of each function. Therefore, SLI can lookup the source code for each function without searching. The typical workflow in test driven programming in SLI is as follows: 1. create a new file myfunctions.sli 2. write documentation including examples for one or more functions, e.g. /myfunc1 3. call (myfunctions.sli) makehelp 4. implement /myfunc1 5. call /myfunc1 validate 6. continue with 4 (not 3) until validate is successful The algorithm of function validate is as follows: 1. find the help file (.hlp) for the specified function. If not found ask for running makehelp for first time registration of the function 2. obtain the source file implementing the function from the help file 3. update the help file of the function 4. construct target path for test files 5. write some header 6. copy the invariants 7. write some footer 8. run the test file Examples: /Part validate --> true % /validate validate --> true % infinite recursion Author: Diesmann FirstVersion: 080503 Remarks: The function is experimental. It constitutes a first attempt to provide support for test driven programming in NEST. A variant of this function could easily print a detailed report of the test results and the intermediate generation of a test script is not necessary. In the present implementation validate updates the plain text help file (.hlp) but not the hypertext help (.html). SeeAlso: EvaluateLiteralInfixes, -->, Part, makehelp, helpdesk */ /validate [/literaltype] { % string name of function cvs /c Set % file name of test (test_) c join (.sli) join /cf Set % locate the help file c HelpExtension join HelpSearchPath exch LocateFileNames First % if not found print message that documentation % of function is not in data base. Please run % makeallhelp for first time registration of the % new function in the help system /f Set % search for the source file implementing % the command f (r) file { getline not {close exit} if (Source:) search {pop pop exch close exit} {pop} ifelse } loop ( ) () ReplaceOccurrences % update the .hlp file makehelp % here we could also update % the .html file. At present all .html files % are updated simultaneously by function :hlp2html %:makehtmlhelp % construct target path for test files % f (nest/help) search pop /base Set pop pop base (nest/unittests/) join cf join /tf Set % write header to test file tf (w) file /t Set t (true [\n\n) print ; % extract invariants from .hlp file and % write to test file. false /copystate Set f (r) file { getline not {close exit} if /Line Set SimpleKeyword Line 1 0 regexec 0 eq {false /copystate Set } if pop ReferencingKeyword Line 1 0 regexec 0 eq {false /copystate Set } if pop copystate { t Line print (\n) print ; } if InvariantsKeyword Line 1 0 regexec 0 eq {true /copystate Set } if pop } loop % write footer to test file % t (] EvaluateLiteralInfixes {and} Fold\n) print ; t close % execute the new test file tf run } def /* BeginDocumentation Name: apropos - Search the command index for a regular expression. Synopsis: (regexp) apropos -> - /regexp apropos -> - Description: Apropos prints out all lines of the helpindex that match the regular expression. The regular expression can be a simple string. The search is case invariant. Apropos uses extended regular expressions. Parameters: regexp: Regular expression, either as a string or literal. Examples: SLI ] /apropos apropos apropos Search the command index for a regular expression. SLI ] /Apropos apropos apropos Search the command index for a regular expression. SLI ] /Express* apropos apropos Search the command index for a regular expression. EvaluateLiteralInfixes Evaluates an array of infix expressions ExecMath execute a math expression. grep extract lines matching a regular expression pattern regcomp Create a regular expression regexec compare string and regular expression testsuite::test_iaf_psp_peak test of closed form expression for peak ToMathematicaExpression converts SLI data to Mathematica input SLI ] (regular expression) apropos apropos Search the command index for a regular expression. regcomp Create a regular expression regexec compare string and regular expression SLI ] /DoWhatIWant apropos DoWhatIWant: nothing appropriate. Diagnostics: Raises /CannotConvertToRegexp if the expression cannot be converted to a regular expression (see :regerror). Raises /FileNotFound if the help index file cannot be found. Author: R Kupper FirstVersion: 2008-jul-15 SeeAlso: helpindex, help, which, regcomp */ /apropos[/stringtype /e] { /flags regexdict/REG_ICASE :: regexdict/REG_EXTENDED :: add def e flags regcomp /regexp Set % open the helpindex text file: /helpindexfile HelpRoot (/) join TextIndexFilename join def helpindexfile ifstream not { M_ERROR (apropos) (Cannot find the helpindex file. I thought it was here: ) helpindexfile join (. Is your installation broken?) join message funcname /FileNotFound raiseerror } if /found false def { getline not {exit} if /line Set regexp line regex_find { line = /found true def } if } loop pop % the stream found not { e =only (: nothing appropriate.) = } if } SLIFunctionWrapper /apropos[/literaltype] {cvs apropos} def /* BeginDocumentation Name: which - Display the name of a command's source file. Synopsis: /command which -> Description: "which" displays the name of the file containing the documentation header for /command. This is most likely the location, where the command was defined. Parameters: /command - commandname, as listed by "helpindex", including a possible namespace prefix (see examples) Examples: /which which -> Source: /home/kupper/nest2/lib/sli/helpinit.sli /MemoryInfo which -> Source: /home/kupper/nest2/nestkernel/nestmodule.cpp /unittest::pass_or_die which -> Source: /home/kupper/nest2/lib/sli/unittest.sli Diagnostics: Raises /NoHelpInformationError if the command is undocumented. Author: R Kupper FirstVersion: 23-jul-2008 Availability: Standard SLI SeeAlso: helpindex, help, apropos */ /which[/literaltype /c] { /helpfilename c cvs HelpExtension join def helpfilename HelpSearchPath exch LocateFileNames %Find *.hlp-File in HelpSearchPath dup [] eq not %Was a help file found? {%yes, a helpfile was found 0 get (^[[:space:]]*Source: ) grep {=} forall } {%no, no helpfile was found pop funcname /NoHelpInformationError raiseerror } ifelse } SLIFunctionWrapper