Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  helpdef.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Frank Celler / Frank Lübeck.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  The  files  helpdef.g{d,i}  contain  the  `default'  help  book  handler
##  functions, which implement access of GAP's online help to help documents
##  produced  from `gapmacro.tex'-  .tex and  .msk files  using buildman.pe,
##  tex, pdftex and convert.pl.
##
##  The function  which converts the  TeX sources  to text for  the "screen"
##  viewer is outsourced into `helpt2t.g{d,i}'.
##

################ ???????????????????????????? ###############################


#############################################################################
##
#F  GapLibToc2Gap( <tocfile> )  . . . . . . . . . . . . . reading .toc file
##
##  reads a manual.toc file of GAP library book and returns list of entries
##  of form [[chapnr, secnr], pagenr]. Used in `default' ReadSix.
##
##  This allows  to  use     xdvi  and  acroread/xpdf conveniently  as help
##  browser.
##
InstallGlobalFunction(GapLibToc2Gap, function(file)
  local   stream,  str,  getarg,  p,  l,  res,  a,  s,  pos,  r;

  stream := StringStreamInputTextFile(file);
  if stream=fail then
    return fail;
  fi;
  str := ReadAll(stream);
  CloseStream(stream);

  # get next argument in {...} after pos (need to handle nested {}'s)
  getarg := function(str, pos)
    local   l,  level,  p;
    l := Length(str);
    while l >= pos and str[pos] <> '{' do
      pos := pos + 1;
    od;
    level := 0;
    p := pos+1;
    while true do
      if p > l then
        break;
      elif str[p] = '{' then
        level := level+1;
      elif str[p] = '}' then
        if level = 0 then
          break;
        else
          level := level-1;
        fi;
      fi;
      p := p+1;
    od;
    return [pos, p];
  end;

  p := Position(str, '\\');
  l := Length(str);
  res := [];

  while p <> fail do
    # read one .toc entry
    if p+12 < l and (str{[p..p+12]} = "\\chapcontents" or
               str{[p..p+11]} = "\\seccontents") then
      a := [getarg(str, p+12)];
      Add(a, getarg(str, a[1][2]+1));
      Add(a, getarg(str, a[2][2]+1));
      p := Position(str, '\\', a[3][2]);
      s := str{[a[1][1]+1..a[1][2]-1]};
      # bibliography, index,.. are numberless chapters and seem not available
      # in help index for library books
      if Length(s)>0 and ForAll(s, x-> x in "0123456789" or
                 x='.') then
        pos := Position(s, '.');
        if pos=fail then
          # chapter entry
          r := [[Int(s), 0]];
        else
          # chapter and section number
          r := [[Int(s{[1..pos-1]}), Int(s{[pos+1..Length(s)]})]];
        fi;
        # don't need the header again
        ##  Add(r, str{[a[2][1]+1..a[2][2]-1]});
        # page number
        Add(r, Int(str{[a[3][1]+1..a[3][2]-1]}));
        Add(res, r);
      fi;
    else
      p := Position(str, '\\', p);
    fi;
  od;

  return res;
end);

##  here are more functions which are used by the `default' handler
##  functions (see their use below).
#############################################################################
##
#F  HELP_CHAPTER_INFO( <book>, <chapter> )  . . . .  get info about a chapter
##
##  this is a helper function for `HELP_SHOW_SECTIONS'
BindGlobal("HELP_CHAPTER_BEGIN", Immutable("\\Chapter"));
BindGlobal("HELP_SECTION_BEGIN", Immutable("\\Section"));
BindGlobal("HELP_FAKECHAP_BEGIN", Immutable("%\\FakeChapter"));
BindGlobal("HELP_PRELCHAPTER_BEGIN", Immutable("\\PreliminaryChapter"));

InstallGlobalFunction(HELP_CHAPTER_INFO, function( book, chapter )
    local   info,  filename,  stream,  poss,  secnum,  pos,  line;

    # get the book info
    info := HELP_BOOK_INFO(book);

    # read in a chapter
    if not IsBound(info.secposs[chapter])  then

        filename := Filename( info.directories, info.filenames[chapter] );
        if filename = fail  then
            Error("help file ", info.filenames[chapter], " for help book '", book.bookname, "' not found");
            return fail;
        fi;
        stream := StringStreamInputTextFile(filename);
        if stream = fail then
            Error("help file ", filename, " does not exist or is not readable");
            return fail;
        fi;
        poss   := [];
        secnum := 0;
        repeat
            pos  := PositionStream(stream);
            line := ReadLine(stream);
            if line <> fail  then
                if MATCH_BEGIN( line, HELP_SECTION_BEGIN )  then
                    secnum := secnum + 1;
                    poss[secnum] := pos;
                elif MATCH_BEGIN( line, HELP_CHAPTER_BEGIN ) or
                     MATCH_BEGIN( line, HELP_PRELCHAPTER_BEGIN )  then
                    info.chappos[chapter] := pos;
                elif MATCH_BEGIN( line, HELP_FAKECHAP_BEGIN )  then
                    info.chappos[chapter] := pos;
                fi;
            fi;
        until IsEndOfStream(stream);
        CloseStream(stream);
        info.secposs[chapter] := Immutable(poss);
    fi;

    # return the info
    return [ info.chappos[chapter], info.secposs[chapter] ];

end);

InstallGlobalFunction(HELP_PRINT_SECTION_URL, function(arg)
    local book, hnb, d, pos, chapter, section, fn, path;

    book := HELP_BOOK_INFO(arg[1]);
    if book=fail then
      Error("this book does not exist");
    fi;
    hnb := HELP_KNOWN_BOOKS;
    # the path as string
    book := hnb[2][Position(hnb[1], SIMPLE_STRING(book.bookname))][3];
    if IsDirectory(book) then
      d := book![1];
    else
      d := book;
    fi;
    if Last(d) = '/' then
      d := d{[1..Length(d)-1]};
    fi;

    # find `doc'
    pos:=Length(d)-2;
    while pos>0 and (d[pos]<>'d' or d[pos+1]<>'o' or d[pos+2]<>'c') do
      pos:=pos-1;
    od;
    #see if it is only `doc', if yes skip
    if pos+2=Length(d) then
      # it ends in doc, replace `doc' by `htm'
      d:=Concatenation(d{[1..pos-1]},"htm");
    else
      # insert htm after doc
      d:=Concatenation(d{[1..pos+2]},"/htm",d{[pos+3..Length(d)]});
    fi;

    chapter:=String(arg[2]);
    while Length(chapter)<3 do
      chapter:=Concatenation("0",chapter);
    od;
    section:=arg[3];

    # first try to find a file-per-chapter .htm file
    fn := Concatenation("CHAP", chapter, ".htm");
    if IsDirectory(book) then
      path := Filename([Directory(d)], fn);
    else
      path := Filename(List(GAPInfo.RootPaths, Directory),
                     Concatenation(d, "/", fn));
    fi;
    if path = fail then
      # now try to find a file-per-section .htm file
      section:=String(section);
      while Length(section)<3 do
        section:=Concatenation("0",section);
      od;
      fn := Concatenation("C", chapter, "S", section, ".htm");
      if IsDirectory(book) then
        path := Filename([Directory(d)], fn);
      else
        path := Filename(List(GAPInfo.RootPaths, Directory),
                       Concatenation(d, "/", fn));
      fi;
    fi;
    if path <> fail and not IsString(section) and section>0 then
      # we must have found a file-per-chapter .htm file above
      section:=String(section);
      while Length(section)<3 do
        section:=Concatenation("0",section);
      od;
      path:=Concatenation(path,"#SECT",section);
    fi;
    return path;
end);

# now the handlers

atomic HELP_REGION do # acquire lock for HELP_BOOK_HANDLER

##  the default ReadSix function for books in gapmacro format
##  (need to parse a text file in this case, this function still
##  looks pretty long winded)
HELP_BOOK_HANDLER.default.ReadSix := function(stream)
  local   fname,  readNumber, pos,  n,  c,  s,  x,  f,  line,  subline,
          c1,  c2,  i,  name,  num,  s1,  sec,  s2,  j,  x1,
          w,  f1,  res,  toc;

  # name of file
  fname := ShallowCopy(stream![2]);

  # numbers
  readNumber := function( str )
    local   n;

    while pos<=Length(str) and str[pos] = ' '  do
      pos := pos+1;
    od;
    n := 0;
    while pos<=Length(str) and str[pos] <> '.'  do
      n := n * 10 + (Position("0123456789", str[pos])-1);
      pos := pos+1;
    od;
    pos := pos+1;
    return n;
  end;

  c := []; s := []; x := []; f := [];
  repeat
    line := ReadLine(stream);
    if line <> fail  then
      RemoveCharacters(line, "\r");
      subline:=line{[3..Length(line)-1]} ;
      if line[1] = 'C'  then
        Add( c, subline);
      elif line[1] = 'S'  then
        Add( s, subline);
      elif line[1] = 'I'  then
        Add( x, subline);
      elif line[1] = 'F'  then
        if ForAll([Maximum(Length(f)-10, 1)..Length(f)],
                  i-> f[i] <> subline) then
          Add( f, subline);
        fi;
      else
        Print( "#W  corrupted 'manual.six': ", line );
        Print( "#W (in stream: ", stream, ")\n");
        break;
      fi;
    fi;
  until IsEndOfStream(stream);
  CloseStream(stream);

  # parse the chapters information
  c1 := [];
  c2 := [];
  for line  in c  do

    # first the filename
    pos  := Position( line, ' ' );
    name := line{[1..pos-1]};

    # then the chapter number
    num := readNumber(line);

    # then the chapter name
    while pos <= Length(line) and line[pos] = ' '  do pos := pos+1;  od;

    # store that information in <c1> and <c2>
    c1[num] := name;
    c2[num] := line{[pos..Length(line)]};
  od;

  # parse the sections information
  s1 := List( c1, x -> [] );
  for line  in s  do

    # chapter and section number
    pos := 1;
    num := readNumber(line);
    sec := readNumber(line);

    # then the section name
    while pos < Length(line) and line[pos] = ' '  do pos := pos+1;  od;

    # store the information in <s1>
    s1[num][sec] := line{[pos..Length(line)]};
    if pos = Length(line) then
      Print("#W  Empty section name ", num, ".", sec,"\n");
    fi;
  od;

  # convert sections and chapters to lower case
  s2 := [];
  for i  in [ 1 .. Length(s1) ]  do
    for j  in [ 1 .. Length(s1[i]) ]  do
      Add( s2, [ s1[i][j], SIMPLE_STRING(s1[i][j]), "S", i, j ] );
    od;
  od;
  for i  in [ 1 .. Length(c2) ]  do
    Add( s2, [ c2[i], SIMPLE_STRING(c2[i]), "C", i, 0 ] );
  od;

  # parse the index information
  x1 := [];
  for line  in x  do

    # chapter and section number
    pos := 1;
    num := readNumber(line);
    sec := readNumber(line);

    # then the index entry
    while pos <= Length(line) and line[pos] = ' '  do pos := pos+1;  od;

    # store the information in <x1>
    w := line{[pos..Length(line)]};
    Add( x1, [ w, SIMPLE_STRING(w), "I", num, sec ] );
  od;

  # parse the function information
  f1 := [];
  for line  in f  do

    # chapter and section number
    pos := 1;
    num := readNumber(line);
    sec := readNumber(line);

    # then the index entry
    while pos <= Length(line) and line[pos] = ' '  do pos := pos+1;  od;

    # store the information in <x1>
    w := line{[pos..Length(line)]};
    Add( f1, [ w, SIMPLE_STRING(w), "F", num, sec ] );
  od;

  res := rec(
          formats       := ["text", "url"],
          filenames   := Immutable(c1),
# the following three are not made immutable to allow change of names (if it
# is found out that several sections have the same name).
          chapters    := c2,
          sections    := s1,
          secposs     := [],
          chappos     := [],
          entries := Concatenation(s2, x1, f1)
        );

  # trying to read page numbers from manual.toc file
  fname{[Length(fname)-2..Length(fname)]} := "toc";
  toc := GapLibToc2Gap(fname);
  if toc <> fail then
    res.pagenumbers := toc;
    fname{[Length(fname)-2..Length(fname)]} := "dvi";
    if IsExistingFile( fname ) = true then
      res.dvifile := ShallowCopy(fname);
      Add(res.formats, "dvi");
    fi;
    fname{[Length(fname)-2..Length(fname)]} := "pdf";
    if IsExistingFile( fname ) = true then
      res.pdffile := ShallowCopy(fname);
      Add(res.formats, "pdf");
    fi;
  fi;
  res.directories := [ Directory(fname{[1..Length(fname)-10]}) ];
  return res;
end;

HELP_BOOK_HANDLER.default.ShowChapters := function( book )
  local   info,  chap;

  info := HELP_BOOK_INFO(book);
  if info = fail  then
    Print( "Help: unknown book \"", book, "\"\n" );
           return false;
  fi;

  # print the chapters
  chap := ShallowCopy(info.chapters);
  Sort(chap);
  return Concatenation(
            [ FILLED_LINE( "Table of Chapters", info.bookname, '_' ) ],
            chap,
            [ "" ]
        );
end;

HELP_BOOK_HANDLER.default.ShowSections := function( book )
  local   info,  lines,  chap,  sec;

  info := HELP_BOOK_INFO(book);
  if info = fail  then
    Print( "Help: unknown book \"", book, "\"\n" );
           return false;
  fi;

  # print the sections
  lines := [ FILLED_LINE( "Table of Sections", info.bookname, '_' ) ];
  for chap  in [ 1 .. Length(info.chapters) ]  do
    Add( lines, info.chapters[chap] );
    for sec  in [ 1 .. Length(info.sections[chap]) ]  do
      Add(lines,Concatenation("    ",info.sections[chap][sec]));
    od;
  od;
  Add( lines, "" );
  return lines;
end;

HELP_BOOK_HANDLER.default.MatchPrevChap := function(book, entrynr)
  local   info,  chnr,  nr;
  info := HELP_BOOK_INFO(book);
  chnr := info.entries[entrynr][4];
  if info.entries[entrynr][3] <> "C" or chnr = 1 then
    nr :=  First([1..Length(info.entries)], i-> info.entries[i]{[3,4]} =
               ["C", chnr]);
  else
    nr :=  First([1..Length(info.entries)], i-> info.entries[i]{[3,4]} =
               ["C", chnr-1]);
  fi;
  return [info, nr];
end;

HELP_BOOK_HANDLER.default.MatchNextChap := function(book, entrynr)
  local   info,  chnr,  nr;
  info := HELP_BOOK_INFO(book);
  chnr := info.entries[entrynr][4] + 1;
  nr :=  First([1..Length(info.entries)], i-> info.entries[i]{[3,4]} =
               ["C", chnr]);
  return [info, nr];
end;

HELP_BOOK_HANDLER.default.MatchPrev := function(book, entrynr)
  local   info,  entry,  chnr,  secnr,  nr;

  info := HELP_BOOK_INFO(book);
  entry := info.entries[entrynr];
  chnr := entry[4];
  secnr := entry[5];
  if secnr > 1 then
    nr := First([1..Length(info.entries)], i-> info.entries[i]{[3,4,5]}
              = ["S", chnr, secnr-1]);
  elif secnr = 1 then
    nr := First([1..Length(info.entries)], i-> info.entries[i]{[3,4]}
                = ["C", chnr]);
  elif secnr = 0 then
    nr := First(Reversed([1..Length(info.entries)]), i->
                info.entries[i][3] = "S" and
                info.entries[i][4] = chnr-1);
  fi;
  return [info, nr];
end;

HELP_BOOK_HANDLER.default.MatchNext := function(book, entrynr)
  local   info,  entry,  chnr,  secnr,  nr;

  info := HELP_BOOK_INFO(book);
  entry := info.entries[entrynr];
  chnr := entry[4];
  secnr := entry[5];
  nr := First([1..Length(info.entries)], i-> info.entries[i]{[3,4,5]}
              = ["S", chnr, secnr+1]);
  if nr = fail then
    nr := First([1..Length(info.entries)], i-> info.entries[i]{[3,4,5]}
                = ["C", chnr+1, 0]);
  fi;

  return [info, nr];
end;

##
##  The default search for matches is easy, just MATCH_BEGIN (if frombegin
##  = true), resp.  IS_SUBSTRING is used for content of second position in
##  .entries. The topic is assumed to be normalized already.
##
HELP_BOOK_HANDLER.default.SearchMatches := function (book, topic, frombegin)
  local info, exact, match, rank, m, i;
  info := HELP_BOOK_INFO(book);
  exact := [];
  match := [];
  rank := [];
  for i in [1..Length(info.entries)] do
    if topic=info.entries[i][2] then
      Add(exact, i);
    elif frombegin = true then
      m := MATCH_BEGIN_COUNT(info.entries[i][2], topic);
      if m >= 0 then
        Add(match, i);
        Add(rank, -m);
      fi;
    else
      if IS_SUBSTRING(info.entries[i][2], topic) then
        Add(match, i);
      fi;
    fi;
  od;

  # sort by rank if applicable
  if frombegin = true then
    SortParallel(rank, match);
  fi;

  return [exact, match];
end;

##  the `default' handler for HelpData delegates to functions from above
HELP_BOOK_HANDLER.default.HelpData := function(book, entrynr, type)
  local   info,  entry,  chnr,  secnr,  pos,  r;

  info := HELP_BOOK_INFO(book);
  entry := info.entries[entrynr];
  chnr := entry[4];
  secnr := entry[5];

  # we handle the special type "ref" for cross references first
  if type = "ref" then
    return HELP_BOOK_HANDLER.HelpDataRef(info, entrynr);
  fi;

  if type = "secnr" then
    r := "";
    Append(r, String(chnr));
    if secnr <> 0 then
      Add(r, '.');
      Append(r, String(secnr));
    fi;
    return [[chnr, secnr, 0], r];
  fi;

  if not type in info.formats then
    return fail;
  fi;

  if type = "text" then
    if entry[3] = "F" then
      return HELP_PRINT_SECTION_TEXT(info, chnr, secnr, entry[1]);
    else
      return HELP_PRINT_SECTION_TEXT(info, chnr, secnr);
    fi;
  fi;

  if type = "url" then
    return HELP_PRINT_SECTION_URL(info, chnr, secnr);
  fi;

  if type = "dvi" then
    pos := PositionSorted(info.pagenumbers, [[chnr, secnr],-1]);
    if IsBound(info.pagenumbers[pos]) and info.pagenumbers[pos][1] =
       [chnr, secnr] then
      return rec(file := info.dvifile, page := info.pagenumbers[pos][2]);
    fi;
  fi;

  if type = "pdf" then
    pos := PositionSorted(info.pagenumbers, [[chnr, secnr],-1]);
    if IsBound(info.pagenumbers[pos]) and info.pagenumbers[pos][1] =
       [chnr, secnr] then
      return rec(file := info.pdffile, page := info.pagenumbers[pos][2]);
    fi;
  fi;

  return fail;
end;

HELP_BOOK_HANDLER.default.SubsectionNumber := function(info, entrynr)
  return info.entries[entrynr]{[4,5]};
end;

od; # end of atomic HELP_REGION

[ Dauer der Verarbeitung: 0.7 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge