home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / contrib / menu / menu.S < prev    next >
Text File  |  1993-04-29  |  5KB  |  189 lines

  1. #
  2. # menu.icn
  3. # copyright 1992 Ronald Florence
  4. # @(#) version 1.1 (ron@mlfarm.com, 12 May 1992)
  5. #
  6. # See xmenu.icn for the X-Windows/X-Icon version.
  7. #
  8. # configuration:
  9. #    indexfile := full path of index file
  10. #    data_dir := recipe directory
  11. #    pager := optional external pager (instead of built-in pager)
  12. #    Print_cmd := pretty-printer and/or spooler (for OS with pipes)
  13. #    regexparser := (ms-dos only) findre <or> ReFind
  14.  
  15. # for ms-dos, use:   link iolib, findre <or> link iolib, regexp
  16.  
  17. link iolib
  18. global    Pipes, Print_cmd
  19.  
  20. procedure main(arg)
  21.   local indexfile, data_dir, pager, zcat, hits, online, keys, pchar,
  22.       egrep, meta_keys, egrep_cmd, k, index, m, found, search, putout, 
  23.       out, recipe, rpath, rf, regexparser
  24.  
  25.                 # configuration
  26.   indexfile := getenv("INDEXFILE") | "%INDEXFILE%"
  27.   data_dir := getenv("RECIPEDIR") | "%DATADIR%"
  28.   pager := getenv("PAGER") | "%PAGER%"
  29.   Print_cmd := "%PRINTCMD%"
  30.   regexparser := 
  31.                 # end of configuration
  32.  
  33.   (*arg > 0) | stop("usage: menu keyword [regexp,...]")
  34.   close(open(indexfile)) | stop("can't read index")
  35.   hits := []
  36.   online := []
  37.   keys := []
  38.   pchar := &ascii[32:127]
  39.   Pipes := "pipes" == &features
  40.                 # If we have pipes and egrep (Unix),
  41.                 # separate the keywords into those with
  42.                 # metacharacters and those without.  If
  43.                 # there are none with metacharacters, pop
  44.                 # one off the non-meta list to use with
  45.                 # an egrep search.  
  46.   if \Pipes & close(open("/bin/" | "/usr/bin/" | "/usr/ucb/" || "egrep"))
  47.     then {
  48.       meta_keys := []
  49.       egrep_cmd := "cat " || indexfile 
  50.       regexparser := find
  51.       every k := !arg do put(if metas(k) then meta_keys else keys, map(k))
  52.       \meta_keys[1] | put(meta_keys, pop(keys))
  53.       every k := !meta_keys do egrep_cmd ||:= " | egrep -i '" || k || "'"
  54.       index := open(egrep_cmd || " 2>&1", "rp") 
  55.   }
  56.                 # Without pipes and egrep use findre
  57.                 # or ReFind for the regular expression
  58.                 # search.  S-l-o-w.
  59.   else {
  60.     index := open(indexfile)
  61.     every put(keys, map(!arg))
  62.   }
  63.                 # The search is a generator, breaking
  64.                 # when the find or regexparser fails.  We
  65.                 # then put online recipes in one list
  66.                 # and the reference recipes in another.
  67.   every !index ? {
  68.     \egrep_cmd & find("error"|"grep") & stop("search expression error")
  69.     m := map(&subject)
  70.     found := 1
  71.     every k := !keys do { 
  72.       search := if /egrep & metas(k) then regexparser else find
  73.       search(k, m) | break found := &null 
  74.     }
  75.     \found & {
  76.       put(if ="Comp-" then online else hits, 
  77.       left(tab(many(pchar)), 20) || (tab(upto(pchar)), tab(many(pchar))))
  78.       tab(0)
  79.     }
  80.   }
  81.  
  82.   *hits + *online = 0 & stop("No matching recipes.")
  83.   \hits[1] & more("RECIPES", hits)
  84.   \online[1] & repeat {
  85.     more("ON-LINE RECIPES", online)
  86.     writes("\nEnter recipe numbers(s): ")
  87.     read() ? {
  88.       (*&subject = 0) | upto('qQ') & exit(1)
  89.                 # Print code for the built-in pager.
  90.       putout := if upto('pP') then print else more
  91.       while tab(upto(&digits)) do {
  92.     out := []
  93.     recipe := tab(many(&digits))
  94.      rpath := data_dir || recipe
  95.     if close(open(rpath)) then {
  96.       if *pager > 0 then system(pager || " " || rpath)
  97.                 # Put the recipe in a list, so more
  98.                 # will know how big it is. 
  99.       else rf := open(rpath) & every put(out, !rf)
  100.     }
  101.     else if \Pipes then {
  102.       rpath ||:= ".Z"
  103.       if *pager > 0 then system("zcat " || rpath || " | " || pager)
  104.       else {
  105.         rf := open("zcat " || rpath, "rp")
  106.         every put(out, !rf)
  107.         close(rf)
  108.       } | write("Can't find " || rpath)    
  109.     }
  110.     \out[1] & putout("RECIPE " || recipe, out, "End of Recipe " || recipe)
  111.       }
  112.     }
  113.   }
  114. end 
  115.  
  116.  
  117. procedure print(recipe, head)
  118.   local prn, rp, mode
  119.  
  120.   if \Print_cmd & \Pipes then {
  121.     Print_cmd ? {
  122.       prn := (\tab(find("%s")) || head) | tab(0)
  123.       move(2) & prn ||:= tab(0)
  124.     }
  125.     mode := "wp"
  126.   }
  127.   else if not "MS-DOS" == &features then 
  128.       return write("Sorry, not configured to print.")
  129.   else {
  130.     mode := "w"
  131.     prn := "PRN"
  132.   }
  133.   rp := open(prn, "wp")
  134.   every write(rp, !recipe)
  135.   return close(rp)
  136. end
  137.  
  138.                 # Procedured modified from R.Goerwitz
  139.                 # to detect whether a keyword contains
  140.                 # meta-characters, e.g., whether we
  141.                 # need a regular expression search.
  142. procedure metas(str)
  143.  
  144.   str ? {
  145.     tab(many('*+?|'))    
  146.     while tab(upto('\\*+()|?.$^[')) do {
  147.       if ="\\" then move(1) | stop("badly-formed search string")
  148.       else return .&pos
  149.     }
  150.   }
  151.   fail
  152. end
  153.  
  154.                 # This is kluged to not clear the
  155.                 # screen or show the percentage
  156.                 # after -MORE- for the lists of recipes.
  157. procedure more(header, what, footer)
  158.   static lines
  159.   local ans
  160.  
  161.   initial {
  162.     writes(getval("cl"))
  163.     lines := 0
  164.   }
  165.   /footer | {
  166.     writes(getval("cl"))
  167.     lines := 0
  168.   }
  169.   \header & {
  170.     write(getval("md"|"so") || header || ":" || getval("me"|"se"))
  171.     lines +:= 1
  172.   }
  173.   every !what ? {
  174.     write(tab(0))
  175.     ((lines +:= 1 + *&subject/getval("co")) % (getval("li") - 1) = 0) & {
  176.       writes(getval("so") || "-MORE-")
  177.       \footer & writes("(", (100 > (lines - 2)*100/*what) | 100, "%)")
  178.       writes(getval("se"))
  179.       ans := read() & writes(getval("up") || getval("ce"))
  180.       upto('nNqQ', ans) & fail
  181.     }
  182.   }
  183.   \footer & {
  184.     writes(getval("so") || footer || getval("se")) 
  185.     read() & writes(getval("up") || getval("ce"))
  186.   }
  187. end
  188.  
  189.