File: pager.gi

package info (click to toggle)
gap 4r4p10-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 29,224 kB
  • ctags: 7,084
  • sloc: ansic: 98,591; sh: 3,284; perl: 2,263; makefile: 467; awk: 6
file content (209 lines) | stat: -rw-r--r-- 6,100 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#############################################################################
##  
#W  pager.gi                     GAP Library                     Frank Lbeck
##  
#H  @(#)$Id: pager.gi,v 1.4 2002/05/10 12:56:28 gap Exp $
##  
#Y  Copyright  (C) 2001, Lehrstuhl  D  fuer  Mathematik, RWTH  Aachen, Germany 
#Y (C) 2001 School Math and  Comp. Sci., University of St. Andrews, Scotland
#Y Copyright (C) 2002 The GAP Group
##  
##  The  files  pager.g{d,i}  contain  the `Pager'  utility.  A  rudimentary
##  version of this  was integrated in first versions of  GAP's help system.
##  But this utility is certainly useful for other purposes as well.
##  
Revision.pager_gi := 
  "@(#)$Id: pager.gi,v 1.4 2002/05/10 12:56:28 gap Exp $";
##  
##  There is a builtin pager `PAGER_BUILTIN', but  at least under UNIX one
##  should use an external one.  This can be  set via the variable `PAGER'
##  (e.g., PAGER :=  "less";). Here,  `less'  should be  in the executable
##  PATH of the user and we assume that it supports an argument `+num' for
##  starting display in   line number `num'.   Additional options  can  be
##  assigned to `PAGER_OPTIONS' as list of strings.
##  
##  The user function is `Pager'.
##  
##  The input of `Pager( lines )' can have one the following forms:
##  
##   (1) a string (i.e., lines are separated by '\n')
##   (2) a list of strings (without '\n') interpreted as lines of output 
##   (3) a record with component .lines as in (1) or (2) and optional further
##       components
##  
##  In (3) currently the following components are used:
##  
##   .formatted (true/false) If true, the builtin pager tries to avoid
##                           line breaks by GAP's Print.
##   .start (number)         The display is started with line .start, but 
##                           beginning is available via back scrolling
##  
 
#############################################################################
##
#F  PAGER_BUILTIN( <lines> )	. . . . . . . . . . . . . . . .  format lines
##
# We take  into account a  variable from the  GAPDoc package. If  the text
# contains ANSI color sequences we reset  the terminal before we print the
# last line.
if not IsBound(ANSI_COLORS) then
  ANSI_COLORS := false;
fi;
BindGlobal("PAGER_BUILTIN", function( lines )
  local   formatted,  linepos,  size,  wd,  pl,  count,  i,  stream,  
          halt,  delhaltline,  from,  len,  char, out;
  
  formatted := false;
  linepos := 1;
  # don't print this to LOG files
  out := OutputTextUser();
  
  if IsRecord(lines) then
    if IsBound(lines.formatted) then
      formatted := lines.formatted;
    fi;
    if IsBound(lines.start) then
      linepos := lines.start;
    fi;
    lines := lines.lines;
  fi;
  
  if IsString(lines) then
    lines := SplitString(lines, "\n", "");
  fi;
  
  size   := SizeScreen();
  wd := QuoInt(size[1]+2, 2);
  # really print line without breaking it
  pl := function(l)
    local   r;
    r := 1;
    while r*wd<=Length(l) do
      PrintTo(out, l{[(r-1)*wd+1..r*wd]}, "\c");
      r := r+1;
    od;
    if (r-1)*wd < Length(l) then
      PrintTo(out, l{[(r-1)*wd+1..Length(l)]});
    fi;
    PrintTo(out, "\n");
  end;
  
  if not formatted then
    # cope with overfull lines
    count:=1;
    while count<=Length(lines) do
      if Length(lines[count])>size[1]-2 then
        # find the last blank before this position 
        i:=size[1]-2;
        while i>0 and lines[count][i]<>' ' do
          i:=i-1;
        od;
        if i>0 then
          if not IsBound(lines[count+1]) then
            lines[count+1]:="";
          fi;
          lines[count+1]:=Concatenation(
             lines[count]{[i+1..Length(lines[count])]}," ", lines[count+1]);
          lines[count]:=lines[count]{[1..i-1]};
        fi;
      fi;
      count:=count+1;
    od;
  fi;

  stream := InputTextFile("*errin*");
  count  := 0;
  halt   := 
    "  -- <space> page, <n> next line, <b> back, <p> back line, <q> quit --\c";
  if IsBound(ANSI_COLORS) and ANSI_COLORS = true then
    halt := Concatenation("\033[0m", halt);
  fi;
  delhaltline := function()
    local i;
    for i  in halt  do 
      if i <> '\c' then
        PrintTo(out,  "\b\c \c\b\c" );
      fi;
    od;
  end;
  from := linepos; 
  len := Length(lines);
  repeat
    for i in [from..Minimum(len, from+size[2]-2)] do
      pl(lines[i]);
    od;
    if len = i+1 then
      pl(lines[len]);
      char := 'q';
    elif len = i then
      char := 'q';
    else
      PrintTo(out, halt);
      char := CHAR_INT(ReadByte(stream));
      while not char in " nbpq" do
        char := CHAR_INT(ReadByte(stream));
      od;
      if char = ' ' then
        from := from+size[2]-1;
      elif char = 'n' then
        from := from+1;
      elif char = 'p' and from>1 then
        from := from-1;
      elif char = 'b' then
        from := Maximum(1, from-size[2]+1);
      fi;
      delhaltline();  
    fi;
  until char = 'q';
  
  CloseStream(stream);
end);

# for using `more' or `less' or ... (read from `PAGER')
# we assume that PAGER allows command line option +num for starting
# display in line num
PAGER := "builtin";
PAGER_OPTIONS := [];

BindGlobal("PAGER_EXTERNAL",  function( lines )
  local   path,  pager,  linepos,  str,  i,  cmdargs,  stream;
  path := DirectoriesSystemPrograms();
  pager := Filename(path, PAGER);
  if pager=fail then
    Error("Pager ", PAGER, " not found, change `PAGER'.");
  fi;
  linepos := 1;
  if IsRecord(lines) then
    if IsBound(lines.start) then
      linepos := lines.start;
    fi;
    lines := lines.lines;
  fi;
  
  if not IsString(lines) then
    str:="";
    for i in lines do
      Append(str,i);
      Add(str,'\n');
    od;
    lines := str;
  fi;
  if linepos > 1 then
    cmdargs := [Concatenation("+", String(linepos))];
  else
    cmdargs := [];
  fi;
  stream:=InputTextString(lines);
  Process(path[1], pager, stream, OutputTextUser(),
          Concatenation(PAGER_OPTIONS, cmdargs));
end);

InstallGlobalFunction("Pager",  function(lines)
  if PAGER="builtin" then
    PAGER_BUILTIN(lines);
  else
    PAGER_EXTERNAL(lines);
  fi;
end);