############################################################################ # # File: ibrow.icn # # Subject: Program to browse Icon files for declarations # # Author: Robert J. Alexander # # Date: September 7, 1990 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # Usage: ibrow [...] # # If no source file names are provided on the command line, all *.icn # files in the current directory are browsed. # # The program facilitates browsing of Icon programs. It was originally # written to browse the Icon Program Library, for which purpose it # serves quite well. The user interface is self-explanatory -- just # remember to use "?" for help if you're confused. # ############################################################################ # # Links: colmize # ############################################################################ # # Requires: UNIX # ############################################################################ link colmize procedure main(arg) local p, proctab, doneNames, fn, f, foundNonEmptyLine, block, lineNbr local line, keywd, startLine, proclist, w, i, x, proclines, cmd, b if not (&features == "UNIX") then stop("Runs only under UNIX") if *arg = 0 then { p := open("ls *.icn","rp") while put(arg,read(p)) close(p) } proctab := table() # # Loop to scan all of the specified source files and save their # procedures and records. # doneNames := set() # This set is used to prevent scanning twice if # both a source and a suffixless icode file are # passed as arguments (e.g. mydir/*). write("Icon Browser -- scanning files:") every fn := !arg do { if not (fn[-4:0] == ".icn") then fn ||:= ".icn" if member(doneNames,fn) then next insert(doneNames,fn) f := if fn == "-" then &input else open(fn) | next write(" ",fn) # # Loop to process lines of file (in string scanning mode). # foundNonEmptyLine := &null block := [] lineNbr := 0 while line := read(f) do line ? { lineNbr +:= 1 if not pos(0) then { foundNonEmptyLine := 1 if (tab(many(' \t')) | "")\1 & (keywd := =("end" | "global" | "link")\1) | (keywd := =("procedure" | "record")\1 & tab(many(' \t')) & name := tab(upto(' \t('))\1) then { if keywd == ("procedure" | "record") then startLine := lineNbr if keywd == "record" then { until find(")",line) do { put(block,line) line := read(f) | break lineNbr +:= 1 } } if proctab[name || case keywd of {"end": "()"; "record": "."}] := [block,fn,startLine] then put(block,line) if keywd ~== "procedure" then { foundNonEmptyLine := &null block := [] } } } if \foundNonEmptyLine then put(block,line) } # # Close this file. # close(f) } doneNames := &null # # Reorganize the data. # proctab := sort(proctab) proclist := [] w := **proctab i := 0 every x := !proctab do put(proclist,right(i +:= 1,w) || ". " || x[1]) proclines := [] every put(proclines,colmize(proclist)) proclist := [] every put(proclist,(!proctab)[2]) proctab := &null # # Interact with the user to browse. # repeat { write() every write(!proclines) write() repeat { # # Prompt for, read, and analyze the user's command. # writes("\nq,nn,nn[fmev], (? for help): ") line := read() | exit() case line of { "q": exit() "?": help() & next "": break } if integer(line) then line ||:= "f" if cmd := line[-1] & any('fmev',cmd) & block := proclist[0 < integer(line[1:-1])] then { case cmd of { "f": { # # Write the file name containing the procedure and the # first line of the procedure. # b := block[1] every line := b[1 to *b] do { line ? (if (tab(many(' \t')) | "")\1 & =("procedure" | "record") then break) } write(block[2],": ",line) } "m": { # # List the procedure using "more". # write() p := open("more","pw") | stop("Can't popen") every write(p,!block[1]) close(p) } "e" | "v": { # # Invoke ex or vi positioned at the first line # of procedure or record. # system((if cmd == "e" then "ex" else "vi") || " +" || block[3] || " " || block[2]) } } } } } end procedure help() write( "\nEnter:_ \n q Quit_ \n ? Display help message (this message)_ \n Redisplay the list of procedure and record names_ \n [f] Display the file name and first line of_ \n procedure or record_ \n m Display the procedure or record using \"more\"_ \n e Invoke \"ex\" positioned to procedure or record_ \n v Invoke \"vi\" positioned to procedure or record" ) return end