pereira@sri-unix.UUCP (08/15/83)
% File: Mec:Helper.Pl Author: R.A.O'Keefe Updated: 12 October 82 % Modified for TOPS-20 Fernando Pereira % This file contains two utilities: % try_hard_to_see(FileName, DeviceDefaults, ExtensionDefaults) % -- tries all the Extension and Device defaults (varying the % -- extensions first) until it succeeds in 'see'ing the file, % -- and fails if the file cannot be found. % give_help(Area, Topic) % -- looks for an assertion help_file(Area, FileName, Delimiter) % -- which you must supply. It then tries hard to open the file % -- with default extensions "", "HLP", and "PL" and with device % -- defaults "DSK", "MEC", "UTIL", and "PLL". If the file can't % -- be found, or if there is no help_file assertion, it gives an % -- apology. Otherwise it searches the file for the sequence % -- Delimiter Topic ".", e.g. #help. % It defines append, but its definition is the same as that in UTIL. %----------------------------------------------------------------------% :- public try_hard_to_see/3. :- public append/3. :- mode try_hard_to_see(+, +, +), expand_file(+, +, +, -), parse_file(-, -, -, -, ?, ?), file_component(-, ?, ?), letter_or_digit(+, -), normalise_file_component(+, +, -), supply_file_default(+, +, +, -), supply_file_default(+, +, -), pack_file_title(+, +, +, +, -), append(+, +, -). try_hard_to_see(Title, DeviceDefaults, ExtensionDefaults) :- nofileerrors, expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle), see(FullTitle), !, fileerrors. try_hard_to_see(Title, _, _) :- fileerrors, write('** Can''t see '), writeq(Title), nl, fail. expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle) :- atomic(Title), name(Title, TitleName), !, expand_file(TitleName, DeviceDefaults, ExtensionDefaults, FullTitle). expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle) :- parse_file(Device, Directory, FileName, Extension, Title, []), normalise_file_component(Directory, 99999, TryDirectory), normalise_file_component(FileName, 99999, TryFileName), !, supply_file_default(Device, DeviceDefaults, 99999, TryDevice), supply_file_default(Extension, ExtensionDefaults, 99999, TryExtension), pack_file_title(TryDevice, TryDirectory, TryFileName, TryExtension, TryTitle), name(FullTitle, TryTitle). parse_file(Device, Directory, FileName, Extension) --> ( file_component(Device), ":" | { Device = "" } ), !, ( "<", file_component(Directory), ">" | { Directory = "" } ), !, file_component(FileName), ( ".", file_component(Extension) | { Extension = "" } ), !. file_component([LetDig|Rest]) --> [Char], { letter_or_digit(Char, LetDig) | [Char] = "-", LetDig = Char }, !, file_component(Rest). file_component([]) --> []. letter_or_digit(C, C) :- C >= "0", C =< "9", !. letter_or_digit(C, C) :- C >= "a", C =< "z", !. letter_or_digit(C, D) :- C >= "A", C =< "Z", D is C+("a"-"A"). normalise_file_component([], _, []) :- !. normalise_file_component(Default, Length, TryThis) :- atomic(Default), name(Default, DefaultName), !, normalise_file_component(DefaultName, Length, TryThis). normalise_file_component(_, 0, []) :- !. normalise_file_component([C|Rest], Length, [LetDig|More]) :- letter_or_digit(C, LetDig), !, Left is Length-1, normalise_file_component(Rest, Left, More). normalise_file_component([_|Rest], Length, TryThis) :- normalise_file_component(Rest, Length, TryThis). supply_file_default(Given, _, Length, TryThis) :- normalise_file_component(Given, Length, TryThis). supply_file_default([], Defaults, Length, TryThis) :- supply_file_default(Defaults, Length, TryThis). supply_file_default([Default|_], Length, TryThis) :- normalise_file_component(Default, Length, TryThis). supply_file_default([_|Defaults], Length, TryThis) :- !, supply_file_default(Defaults, Length, TryThis). pack_file_title([], [], FileName, Extension, Title) :- !, append(FileName, [46|Extension], Title). % 46 is "." pack_file_title([], Directory, FileName, Extension, Title) :- !, pack_file_title([], [], FileName, Extension, Tail), append([60|Directory],[62|Tail],Title). % 60 is "<" % 62 is ">" pack_file_title(Device, Directory, FileName, Extension, Title) :- pack_file_title([], Directory, FileName, Extension, Tail), append(Device, [58|Tail], Title). % 58 is ":" append([Head|Tail], List, [Head|More]) :- append(Tail, List, More). append([], List, List). %----------------------------------------------------------------------% :- public give_help/0, give_help/1, give_help/2. :- mode give_help, % list of areas. give_help(+), % list of topics in an area. give_help(+, +), % help on a specific topic. find_help(+, +), % find and type a topic of list read_after_delimiter(+), % find "#" or return end_of_file find_help(+, +, +), % check a list of topics among(+, +), % member on commas instead of dots type_until_delimiter(+). % display body of a Note. give_help :- write('Help is available in the following areas:'), nl, help_file(Area, _, _), tab(4), writeq(Area), nl, fail. give_help :- write('Call give_help(Area) for a list of topics in an Area.'), nl, write('Call give_help('), write('Area'), write(',Topic) for help about a specific topic.'), nl. give_help(Area) :- write('The topics in '), writeq(Area), write(' for which help is available are:'), nl, give_help(Area, Topic), write('Call give_help('), writeq(Area), write(',Topic) for help about a specific topic.'), nl. give_help(Area, Topic) :- ( help_file(Area, HelpName, Delimiter), call(Delim is Delimiter) | atom(Area), Delim is "#", HelpName = Area ), seeing(Old), ( try_hard_to_see(HelpName, [dsk,mec,util,pll], [hlp,pl]), !, find_help(Delim, Topic), seen, see(Old) | write('** No help is available on '), writeq(Topic), write(' in '), writeq(Area), nl ), !. find_help(Delimiter, Topic) :- var(Topic), !, read_after_delimiter(Delimiter, Topics), ( Topics = end_of_file | tab(4), write(Topics), nl, fail ). find_help(Delimiter, Topic) :- read_after_delimiter(Delimiter, Topics), find_help(Topics, Topic, Delimiter). find_help(end_of_file, Topic, _) :- !, seeing(HelpFile), write('** No help is available on '), writeq(Topic), write(' in file '), writeq(HelpFile), nl. find_help(Topics, Topic, Delimiter) :- among(Topic, Topics), type_until_delimiter(Delimiter). among(Topic, (Topics1,Topics2)) :- !, ( among(Topic, Topics1) | among(Topic, Topics2) ). among(Topic, (Topics1;Topics2)) :- !, ( among(Topic, Topics1) | among(Topic, Topics2) ). among(Topic, Topic). read_after_delimiter(Delimiter, Topics) :- repeat, get0(Character), ( Character = 26, !, Topics = end_of_file | Character = Delimiter, read(Topics) ). type_until_delimiter(Delimiter) :- get0(C), C =\= 26, C =\= Delimiter, put(C), !, type_until_delimiter(Delimiter). type_until_delimiter(Delimiter). /* DEBUGGING CODE is_string(X) :- var(X), !, fail. is_string([]) :- !. is_string([H|_]) :- \+ integer(H), !, fail. is_string([9|T]) :- is_string(T). is_string([H|T]) :- 32 =< H, H < 127, is_string(T). portray_string([]) :- put(34). portray_string([34|T]) :- put(34), put(34), !, portray_string(T). portray_string([H|T]) :- put(H), !, portray_string(T). portray(X) :- is_string(X), put(34), portray_string(X). try(T) :- expand_file(T, [dsk, mec, util, pll], [hlp, txt], Title), writeq(Title), nl, fail. /* DEBUGGING CODE */