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