home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
qtawk
/
more.exp
< prev
next >
Wrap
Text File
|
1990-10-09
|
20KB
|
535 lines
# QTAwk "more" utility
#
# Display one screen of a file at a time
#
# Command Line Parameters Available: (Note: must precede on command line
# with "--" option to prevent QTAwk from trying to recognize)
# -ppath --> use "path" to locate files to read
# +/r.e.[/] --> read first file until locate match to r.e. regular expression
#
#
# "commands" allow user to:
# [Qq](uit)? -> quit
# [Hh](elp)? -> diplay help
# [Ff](ile)? -> skip to next file
# [Rr](edraw)? -> re-draw last screen
# [Nn](unmbers)? -> turn line numbers on/off
# [Tt](abs)? -> turn tab substitution on/off
# {_d}+ -> go to {_d} line, {_d} > current line number
# {_d}*l -> skip {_d} lines
# {_d}*s -> skip {_d} screens
# {_d}*/r.e./ -> go to {_d} next match of r.e.
# {_d}*m -> go to {_d} next match of last r.e. entered as above
# {_d}*p -> set number of lines prior to match to display
# {_d}*d -> set display line length to {_d}, default 79
# h{_d}/r.e./ -> Highlight text matching r.e.
# if optional {_d}* not entered - default to 1
#
# Use the getdir function to find files matching the patter(s) passed.
# Patterns follow the wildcard syntax of DOS expanded to allow the use
# of character classes, and to allow characters after the '*' wildcard.
# Dos does not recognize characters following the '*'. Must also enclose
# filename specifications in quotes, "fn", to prevent expansion by the QTAwk
# wild card expansion routine. For example the DOS wildcard expression for
# all file names starting with 'c' and ending with 't' or 'p' and with an
# extension of "exp" would be:
# "c*[pt].exp"
# this is translated into the regular expression syntax:
# /^C[!\X001-\X021."\/\\\[\]:|<>+=;,]*[PT]\.EXP$/
#
# Multiple patterns may also be specified:
# QTAwk -fmore.exp -- "[gdh]*.(hlp|txt)" "*(dir|bnc).exp"
#
#
BEGIN {
local p_indx = 1;
local sub_dir = ""; # default to current sub-directory
local fnames;
local ipat;
local i, j;
# set the standard error file
stderr = "stderr";
# set displayed line length
display_length = 79;
def_display_length = 79;
# flag for expanding tabs
sub_tabs = FALSE;
if ( ARGC == 1 ) {
cmd_help;
exit 1;
}
init_sre = FALSE;
# set the regular expressions for recognizing "commands"
Quit = /^{_w}*[Qq](uit)?{_w}*$/;
Help = /^{_w}*[Hh](elp)?{_w}*$/;
Re_display = /^{_w}*[Rr](edraw)?{_w}*$/;
Next_file = /^{_w}*[Ff](ile)?{_w}*$/;
Numbersl = /^{_w}*[Nn](umbers)?{_w}*$/;
Sub_Tabs = /^{_w}*[Tt](abs)?{_w}*$/;
Review_P = /^{_w}*[Cc](ontext)?{_w}*$/;
GoTo_line = /^{_w}*{_d}+{_w}*$/;
Skip_lines = /^{_w}*{_d}*l{_w}*$/;
Skip_scrn = /^{_w}*{_d}*s{_w}*$/;
Match_RE = /^{_w}*{_d}*\/.*\/{_w}*$/;
RE_reset = /^{_w}*{_d}*m{_w}*$/;
Prior_cmd = /^{_w}*{_d}*p{_w}*$/;
Display_L = /^{_w}*{_d}*d{_w}*$/;
High_RE = /^{_w}*h{_w}*{_d}*{_w}*\/.*\/{_w}*$/;
# set regular expressions for command line options
# must precede these on the command line to QTAwk with "--"
# to prevent QTAwk from recognizing
Set_path = /^-[Pp]/;
RE_cmd = /^\+\//;
# set regular expression for recognizing leading digits in a command
ldg_digits = /^{_w}*{_d}+/;
# DOS filename wild card search pattern
wild_cards = /[\*\?\.]/;
# specify legal filename characters by excluding those which are illegal
legal_chars = /[!\x001-\x021."\/\\\[\]:|<>+=;,]/;
for ( i = 1 ; i < ARGC ; i++ ) {
ipat = ARGV[i];
switch ( ipat ) {
case Set_path:
sub(Set_path,"",ipat);
if ( length(ipat) == 0 ) ipat = ARGV[++i];
sub_dir ∩= ipat;
# check for trailing back-slash on path
if ( sub_dir !~ /\\$/ ) sub_dir ∩= '\\';
# print "Sub-directory to Search: " ∩ sub_dir;
break;
case RE_cmd:
sub(/^\+/,"",ipat);
execute_cmd(ipat);
init_sre = TRUE;
break;
default:
#
# convert DOS filename wild card characters to appropriate regular
# expression operators and escape extension period to prevent
# interpretation as r.e. "any character" operator - other r.e.
# operators allowed.
#
ipat = strupr(ipat);
if ( ipat ~~ wild_cards ) {
gsub(/\./,"\\.",ipat);
gsub(/\*/,"{legal_chars}*",ipat);
gsub(/\?/,"{legal_chars}?",ipat);
}
#
# the following line will convert the command line strings
# into regular expressions. This is to prevent the constant
# conversion of a string into a regular expression in the
# "getdir" function.
#
execute("pattern[" ∩ p_indx++ ∩ "] = /^" ∩ ipat ∩ "$/;");
break;
}
}
# if you want to see the r.e. for the files un-comment the following line
# for ( i in pattern ) print "Searching For: " ∩ replace(pattern[i]);
# delete command line arguments - will replace with directory search below
while ( 1 in ARGV ) delete ARGV[1];
i = 1;
fsize_indx = 1; # initialize index into file size array
#
# go find matching files and print names
#
fnames = getdir(sub_dir,pattern);
for ( j in fnames ) {
ARGV[i++] = sub_dir ∩ fnames[j];
}
# check for NO directory entries which match - exit
# If do not exit, then QTAwk will read from Standard Input - with no
# prompt - it will appear as if the machine has hung. a Ctrl-Z will
# input an end-of-file and terminate, but user probably not expecting
# to have to do that
if ( i == 1 ) {
print "No Directory Entries Match filename Specifications";
exit;
}
# set the number of command arguments
ARGC = i;
# initialize index into file size array
fsize_indx = 1;
# set number of lines on screen
screen_size = 25;
# set number of lines to display prior to line matching r.e.
prior_lines = dprior_lines = 2;
# NOTE: use '\x0ff' in ANSI sequences below. The '\x0ff' will get
# translated to '[' before being printed. Use '\x0ff' character
# so that '[' may be used in search and hihgh lighted text regular
# expressions without being substituted for. This assumes that
# the '\x0ff' character will probably not be in a search pattern
# or high lighted text pattern.
# set ANSI strings for text highlighting
High_Text[1] = Red_on_Black = "\x01b\x0ff1;31;40m";
High_Text[2] = Green_on_Black = "\x01b\x0ff1;32;40m";
High_Text[3] = Yellow_on_Black = "\x01b\x0ff1;33;40m";
High_Text[4] = Blue_on_Black = "\x01b\x0ff1;34;40m";
High_Text[5] = Magenta_Black = "\x01b\x0ff1;35;40m";
High_Text[6] = Cyan_Black = "\x01b\x0ff1;36;40m";
High_Text[7] = White_Black = "\x01b\x0ff1;37;40m";
High_Text[8] = Black_on_Red = "\x01b\x0ff1;30;41m";
High_Text[9] = Green_on_Red = "\x01b\x0ff1;32;41m";
# set ANSI sequence for normal text
Normal = "\x01b\x0ff1;31;44m";
}
INITIAL {
line_count = 1;
# matching_re_start = matching_re_length = 0;
searching_re = init_sre;
exit_endfile = init_sre = FALSE;
file_size = file_sizea[fsize_indx++];
amt_read = 0;
cls;
print "=====> " ∩ FILENAME ∩ " : " ∩ file_size ∩ " <=====";
}
{
local i;
local inp;
local hdr = line_numbers ? FNR ∩ ": " : "";
local ol = length; # set to length of input line
local dl;
amt_read += ol + 2; # added 2 to size read to account for CR/LF
dl = hdr ∩ $0;
ol += length(dl); # reset length of displayed line
# set line to be displayed, truncate to keep from overflowing display line
# will still overflow on some lines since tabs are counted as a single
# character here, but expanded by DOS on output to display. Could replace
# tabs with a single blank to prevent this from happening
if ( length(dl) > display_length ) dl = substr(dl,1,display_length);
if ( !searching_re ) {
# here when not searching for regular expression or have found
#
# check if translating horizontal tabs to blanks - do if TRUE
if ( sub_tabs ) dl = stran(dl,' ','\t');
# If a search pattern exists - high-light
if ( Search_pat ) gsub(Search_pat,Red_on_Black ∩ "$$0" ∩ Normal,dl);
# put in high light ansi sequences for high lighted text
for ( i in High_pat ) gsub(High_pat[i],High_Text[i] ∩ "$$0" ∩ Normal,dl);
# translate '\x0ff' character to '[' for ANSI sequences
dl = stran(dl,'[','\x0ff');
print dl;
# store display line
last_screen[row++] = $0;
# check if last line on screen
if ( ++line_count >= screen_size ) {
percent_rd = (int((1000.0 * amt_read)/file_size) + 5)/ 10;
while ( TRUE ) {
printf("%s : %u%%/%lu/%u <-> (Command)? ─┘",FILENAME,percent_rd,file_size,FNR);
fgetline("stdin",inp);
if ( length(inp) > 0 ) {
execute_cmd(inp);
if ( break_loop ) {
break_loop = FALSE;
break;
}
} else break;
}
cls;
line_count = 1;
deletea last_screen;
row = 0;
}
} else if ( $0 ~~ Search_pat ) {
# here if found match in r.e. search
match_found++;
if ( !--searching_re ) {
printf(" \r");
row += line_count += re_draw(match_last);
last_screen = match_last;
cycle;
} else {
printf("%u : Match: %u/%u\r",FNR,match_found,searching_re);
next;
}
} else {
# here if searching for r.e., but current line does not match
# 'rotate' storage array an tack current line on end
printf("%u\r",FNR);
match_last[1] = $0;
rotate(match_last);
}
}
FINAL {
for ( ++line_count ; ++line_count < screen_size ; ) print "";
print "=====> " ∩ FILENAME ∩ " <=====";
if ( !exit_endfile ) {
printf("%s <-> Press Enter",FILENAME);
fgetline("stdin",inp);
}
exit_endfile = FALSE;
}
# function to check for valid command and execute
function execute_cmd(cmd_str) {
local i, j;
local scrn_m = 1;
local digits = FALSE;
# NOTE: If leading digits on command, find
# add 0 to digits to convert to integer. Otherwise if only one
# digit, "substr" function returns a character value. Incrementing
# a character value with '++' operator gives next character in ASCII
# sequence, decrementing with '--' gives previous character.
if ( cmd_str ~~ ldg_digits ) {
digits = substr(cmd_str,MSTART,MLENGTH) + 0;
cmd_str = strim(deletec(cmd_str,MSTART,MLENGTH));
}
switch ( cmd_str ) {
case Numbersl:
# toggle line numbering on/off
line_numbers = !line_numbers;
break;
case Help:
help;
break;
case GoTo_line:
if ( digits > FNR ) skip_ahead(digits - FNR - 1);
break_loop = TRUE;
break;
case Quit:
exit_endfile = TRUE;
exit;
break;
case Re_display:
cls;
re_draw(last_screen);
break;
case Next_file:
deletea last_screen;
exit_endfile = TRUE;
endfile;
break;
case Prior_cmd:
prior_lines = digits ? digits : dprior_lines;
deletea match_last;
break;
case Skip_scrn:
scrn_m = screen_size;
case Skip_lines:
skip_cnt = 1;
if ( digits ) skip_cnt = digits;
skip_ahead(skip_cnt * scrn_m);
break_loop = TRUE;
break;
case Match_RE:
if ( cmd_str !~ /\/$/ ) cmd_str ∩= '/';
execute("Search_pat = " ∩ cmd_str ∩ ";");
case RE_reset:
if ( Search_pat ) {
searching_re = digits ? digits : TRUE;
match_found = 0;
for ( j = prior_lines , i = 1 ; j ; i++ , j-- )
match_last[i] = last_screen[screen_size - j];
}
break_loop = TRUE;
break;
case High_RE:
cmd_str = deletec(cmd_str,1,1);
if ( cmd_str ~~ ldg_digits ) {
digits = substr(cmd_str,MSTART,MLENGTH) + 0;
cmd_str = strim(deletec(cmd_str,MSTART,MLENGTH));
if ( !digits ) digits = 1;
} else digits = 1;
if ( digits < 10 ) {
if ( cmd_str !~ /\/$/ ) cmd_str ∩= '/';
execute("High_pat[digits] = " ∩ cmd_str ∩ ";");
}
break;
case Review_P:
if ( Search_pat ) print "Search Pattern: /" ∩ Search_pat ∩ '/';
for ( i in High_pat ) print "High Lighted Pattern (" ∩ i ∩ "): /" ∩ High_pat[i] ∩ '/';
break;
case Display_L:
if ( digits ) display_length = digits;
else display_length = def_display_length;
break;
case Sub_Tabs:
sub_tabs = !sub_tabs;
break;
}
}
# function to redraw screen
function re_draw(screen) {
local j = 0;
local k = 0;
local i,n;
local cl;
for ( i in screen ) k++;
j = FNR - k + 1;
for ( i in screen ) {
cl = (line_numbers ? j++ ∩ ": " : "") ∩ screen[i];
if ( sub_tabs ) cl = stran(cl," ","\t");
if ( length(cl) > display_length ) cl = substr(cl,1,display_length);
if ( Search_pat ) gsub(Search_pat,Red_on_Black ∩ "$$0" ∩ Normal,cl);
for ( n in High_pat ) gsub(High_pat[n],High_Text[n] ∩ "$$0" ∩ Normal,cl);
cl = stran(cl,'[','\x0ff');
print cl;
}
return k;
}
# function to skip ahead number of lines in current file specified
function skip_ahead(lines) {
local dummy;
cls;
while ( lines-- ) {
# read next line, check for input and not EOF
if ( getline(dummy) <= 0 ) {
exit_endfile = TRUE;
break;
}
# added 2 to size read to account for CR/LF
amt_read += length(dummy) + 2;
printf("%u\r",FNR);
}
}
function help() {
local tabs = sub_tabs ? "ON" : "OFF";
cls;
print "\x01b[1;32;40mMORE\x01b[1;31;44m File Function Commands";
print "Commands:";
print "i below stands for an integer matched by {_d}.";
print "i* means the integer is optional (match {_d}*) - 1 defaults.";
print "i+ means the integer is mandatory (match {_d}+) - no default.\n";
print "[\x01b[1;32;40mQq\x01b[1;31;44m](uit}? -> exit to DOS.";
print "[\x01b[1;32;40mRr\x01b[1;31;44m](edraw)? -> re-display last screen.";
print "[\x01b[1;32;40mFf\x01b[1;31;44m](ile)? -> proceed to next file.";
print "[\x01b[1;32;40mNn\x01b[1;31;44m](umbers)? -> turn line numbers on/off.";
print "[\x01b[1;32;40mTt\x01b[1;31;44m](abs)? -> Sub. Tabs - toggle on/off, starts off, currently:" ∩ tabs;
print " if on, replace tabs with blank";
print "\x01b[1;32;40mi+\x01b[1;31;44m -> Go To Line number i, if i > current line number.";
print "\x01b[1;32;40mi*l\x01b[1;31;44m -> skip forward i Lines.";
print "\x01b[1;32;40mi*s\x01b[1;31;44m -> skip forward i Screens.";
print "\x01b[1;32;40mi*/r.e./\x01b[1;31;44m -> search for ith expression. If found begin";
print " display starting 'p' lines before matching line.";
print "\x01b[1;32;40mi*m\x01b[1;31;44m -> search for next ith Match to previous";
print " regular expression.";
print "\x01b[1;32;40mi*p\x01b[1;31;44m -> set number of lines prior to match to display";
print " defaults to 2 if i not specified.";
print "\x01b[1;32;40mi*d\x01b[1;31;44m -> set display line length to i, 79 default";
print "\x01b[1;32;40mhi*/r.e./\x01b[1;31;44m -> High-light text matching ith expression";
print "[\x01b[1;32;40mCc\x01b[1;31;44m](ontext)? -> Review Search and High Lighted Text Patterns";
}
# function to clear screen and home cursor
# NOTE: MUST have ANSI.SYS device driver installed to work
function cls() {
# clear screen and home cursor string
local _cls_ = "\x01b[2J";
fprintf(stderr,_cls_);
}
# Function to get desired file names and print
# Use DOS "dir" command to list all files to a temporary file
# read temporary file picking up:
# 1) path from third line
# 2) filenames from remainder of lines
# 3) match filenames against filepattern for desired files and print if match
# Could also get file sizes, dates and times if desired
#
# Arguments passed:
# dir ==> path of desired files
# file_template ==> array of string or regular expression patterns
# for filenames
#
function getdir(dir,file_template) {
local tmp_file = "$tmptmp$.dir";
local gdir = "dir " ∩ dir ∩ "*.* > " ∩ tmp_file;
local ddir = "del " ∩ tmp_file;
local tmparr, inline, filename;
local f_indx = 1, f_list;
local i;
system(gdir);
fgetline(tmp_file,inline); # read and discard header lines
fgetline(tmp_file,inline); # read and discard header lines
fgetline(tmp_file,inline); # read and discard header lines
split(inline,tmparr); # split out to get path
drive = substr(tmparr[3],1,2); # set disk drive
path = sustr(tmparr[3],3) ∩ '\\'; # delete drive and set path
# print drive ∩ path; # un-comment to print path
fgetline(tmp_file,inline); # read and discard header lines
while ( fgetline(tmp_file,inline) > 0 ) {
# discard if not a filename line
if ( inline !~ /^[A-Z]/ ) continue;
# discard if a directory name line
if ( inline ~~ /{_w}+<DIR>{_w}+/ ) continue;
# split out file information
nf = split(inline,tmparr);
# form "filename.ext"
filename = tmparr[1] ∩ '.' ∩ tmparr[2];
for ( i in file_template ) {
if ( filename ~~ file_template[i] ) {
f_list[f_indx++] = filename;
# store file size as integer
file_sizea[fsize_indx++] = tmparr[3] + 0;
break;
}
}
}
# delete temporary directory file
close(tmp_file);
system(ddir);
return f_list;
}
#function to display command line help
function cmd_help() {
cls;
print "Usage:";
print "\x01b[1;32;40mQTAwk -fmore.exp -- [-ppath] [+/r.e.[/]] file1 file2 ...\x01b[1;31;44m";
print "Options:";
print " ppath - specifiy path to find files";
print " +/r.e./ - specify regular expression for starting search";
print "Commands:";
print "i below stands for an integer matched by {_d}.";
print "i* means the integer is optional (match {_d}*) - 1 defaults.";
print "i+ means the integer is mandatory (match {_d}+) - no default.";
print "[\x01b[1;32;40mQq\x01b[1;31;44m](uit}? -> exit to DOS.";
print "[\x01b[1;32;40mRr\x01b[1;31;44m](edraw)? -> re-display last screen.";
print "[\x01b[1;32;40mFf\x01b[1;31;44m](ile)? -> proceed to next file.";
print "[\x01b[1;32;40mNn\x01b[1;31;44m](umbers)? -> turn line numbers on/off.";
print "\x01b[1;32;40mi+\x01b[1;31;44m -> Go To Line number i, if i > current line number.";
print "\x01b[1;32;40mi*l\x01b[1;31;44m -> skip forward i Lines.";
print "\x01b[1;32;40mi*s\x01b[1;31;44m -> skip forward i Screens.";
print "\x01b[1;32;40mi*/r.e./\x01b[1;31;44m -> search for ith expression. If found begin";
print " display starting 'p' lines before matching line.";
print "\x01b[1;32;40mi*m\x01b[1;31;44m -> search for next ith Match to previous";
print " regular expression.";
print "\x01b[1;32;40mi*p\x01b[1;31;44m -> set number of lines prior to match to display";
print " defaults to 2 if i not specified.";
print "\x01b[1;32;40mi*d\x01b[1;31;44m -> set display line length to i, 79 default";
print "\x01b[1;32;40mhi*/r.e./\x01b[1;31;44m -> High-light text matching ith expression";
print "[\x01b[1;32;40mCc\x01b[1;31;44m](ontext)? -> Review Search and High Lighted Text Patterns";
}