diff --git a/DEVELOPING.md b/DEVELOPING.md
index 157b91b2e5..5b7f2f2a9f 100644
--- a/DEVELOPING.md
+++ b/DEVELOPING.md
@@ -156,14 +156,12 @@ multiple parts.
- `testinstall`: quick test suite that one can test frequently.
Run via `./gap tst/testinstall.g`
- `teststandard`: slower but more comprehensive test suite.
- Run via `./gap tst/testinstall.g`
+ Run via `./gap tst/teststandard.g`
- `testextra`: very slow test suite that tests even more
Run via `./gap tst/testextra.g`
- `testbugfix`: additional small test files that are created to verify
specific bugfixes work as intended
Run via `./gap tst/testbugfix.g`
-- `testinstall`: quick test suite that one can test frequently.
- Run via `./gap tst/testinstall.g`
## Tracking down regressions
diff --git a/dev/releases/HelpLinks-to-JSON.g b/dev/releases/HelpLinks-to-JSON.g
index d0bc1a6d0b..613bb8c8f9 100644
--- a/dev/releases/HelpLinks-to-JSON.g
+++ b/dev/releases/HelpLinks-to-JSON.g
@@ -65,7 +65,7 @@ for x in NamesOfComponents(HELP_BOOKS_INFO) do
for i in [1 .. Length(book.entries)] do
entry := HELP_BOOK_HANDLER.HelpDataRef(book, i);
- name := StripEscapeSequences(entry[1]);
+ name := _StripEscapeSequences(entry[1]);
name := ReplacedString(name, match, "");
NormalizeWhitespace(name);
diff --git a/doc/ref/files.xml b/doc/ref/files.xml
index 2013360f88..4da8aca5af 100644
--- a/doc/ref/files.xml
+++ b/doc/ref/files.xml
@@ -122,6 +122,7 @@ for more information how to do this.
File Names
<#Include Label="Filename">
+<#Include Label="PathSystemProgram">
diff --git a/hpcgap/lib/helpbase.gi b/hpcgap/lib/helpbase.gi
index c802ca2dc7..921d65a236 100644
--- a/hpcgap/lib/helpbase.gi
+++ b/hpcgap/lib/helpbase.gi
@@ -55,11 +55,6 @@ end);
## This utility will first be used in some debug tools showing what is newly
## installed by loading a package. Can be documented if desired.
##
-# avoid warning for vars from GAPDoc package
-if not IsBound(StripEscapeSequences) then
- StripEscapeSequences := 0;
-fi;
-
BindGlobal( "IsDocumentedWord", function( arg )
local inid, word, case, simple, cword, book, matches, a, match;
@@ -76,7 +71,7 @@ BindGlobal( "IsDocumentedWord", function( arg )
for book in HELP_KNOWN_BOOKS[1] do
matches:= HELP_GET_MATCHES( [ book ], simple, true );
for a in Concatenation( matches ) do
- match:= case( StripEscapeSequences( a[1].entries[ a[2] ][1] ) );
+ match:= case( _StripEscapeSequences( a[1].entries[ a[2] ][1] ) );
if cword in SplitString( match, "", Difference( match, inid ) ) then
return true;
fi;
@@ -285,7 +280,7 @@ for pair in TRANSATL do
for book in HELP_KNOWN_BOOKS[1] do
matches:= HELP_GET_MATCHES( [ book ], word, false );
for a in Concatenation( matches ) do
- match:= StripEscapeSequences( a[1].entries[ a[2] ][1] );
+ match:= _StripEscapeSequences( a[1].entries[ a[2] ][1] );
patterns:=[];
for i in [1..Length(TRANSATL)] do
patterns[i]:=[];
@@ -315,10 +310,6 @@ return report;
od; # end atomic
end);
-if StripEscapeSequences = 0 then
- Unbind(StripEscapeSequences);
-fi;
-
#############################################################################
##
@@ -1061,9 +1052,6 @@ end);
if not IsBound( InitialSubstringUTF8String ) then
InitialSubstringUTF8String:= "dummy";
fi;
-if not IsBound( LETTERS ) then
- LETTERS:= "dummy";
-fi;
if not IsBound( WidthUTF8String ) then
WidthUTF8String:= "dummy";
fi;
@@ -1094,7 +1082,7 @@ BindGlobal( "InitialSubstringUTF8Text", function( str, cols )
fi;
# Now pos points at an ESC character; all escape sequences we
# support are terminated by a letter, so search for one.
- j:= PositionProperty( str, c -> c in LETTERS, pos );
+ j:= PositionProperty( str, c -> c in CHARS_ALPHA, pos );
if j = fail then
Error( "string end inside escape sequence" );
fi;
@@ -1106,9 +1094,6 @@ end );
if not IsReadOnlyGlobal( "InitialSubstringUTF8String" ) then
Unbind( InitialSubstringUTF8String );
fi;
-if not IsReadOnlyGlobal( "LETTERS" ) then
- Unbind( LETTERS );
-fi;
if not IsReadOnlyGlobal( "WidthUTF8String" ) then
Unbind( WidthUTF8String );
fi;
diff --git a/lib/debug.g b/lib/debug.g
index d63ce7baca..802a0c7530 100644
--- a/lib/debug.g
+++ b/lib/debug.g
@@ -89,7 +89,7 @@ Debug := function(arg)
fi;
# Call the editor:
- execpath := Filename(DirectoriesSystemPrograms(),DEBUG.EDITOR.command);
+ execpath := PathSystemProgram(DEBUG.EDITOR.command);
l:= List( DEBUG.EDITOR.args, x -> ReplacedString( x, "###", String( i ) ) );
Add(l,t); # append the temporary filename
Process(DirectoryCurrent(),execpath,InputTextUser(),OutputTextUser(),l);
diff --git a/lib/files.gd b/lib/files.gd
index 38d3a13ad0..5e62bcc54a 100644
--- a/lib/files.gd
+++ b/lib/files.gd
@@ -157,12 +157,10 @@ DeclareGlobalFunction( "DirectoryDesktop" );
##
## For example,
## in order to locate the system program date use
-## together with the second form of
-## .
+## .
##
## path := DirectoriesSystemPrograms();;
-## gap> date := Filename( path, "date" );
+## gap> date := PathSystemProgram( "date" );
## "/bin/date"
## ]]>
##
@@ -431,6 +429,37 @@ BIND_GLOBAL( "DirectoriesSystemPrograms", function()
end );
+#############################################################################
+##
+#F PathSystemProgram( ) . . . . . . . . . . path of a system program
+##
+## <#GAPDoc Label="PathSystemProgram">
+##
+##
+##
+##
+## returns either the path of the first
+## executable file name in one of the directories returned by
+## ,
+## or fail if no such file exists.
+##
+##
+## <#/GAPDoc>
+##
+BIND_GLOBAL( "PathSystemProgram", function( name )
+ local dir, path;
+
+ for dir in DirectoriesSystemPrograms() do
+ path:= Filename( dir, name );
+ if IsExecutableFile( path ) then
+ return path;
+ fi;
+ od;
+
+ return fail;
+end );
+
+
#############################################################################
##
#F DirectoryTemporary() . . . . . . . . . . . . create a temporary directory
@@ -794,16 +823,6 @@ end );
##
DeclareGlobalFunction( "Edit" );
-# the character set definitions might be needed when processing files, thus
-# they must come earlier.
-BIND_GLOBAL("CHARS_DIGITS",Immutable(SSortedList("0123456789")));
-BIND_GLOBAL("CHARS_UALPHA",
- Immutable(SSortedList("ABCDEFGHIJKLMNOPQRSTUVWXYZ")));
-BIND_GLOBAL("CHARS_LALPHA",
- Immutable(SSortedList("abcdefghijklmnopqrstuvwxyz")));
-BIND_GLOBAL("CHARS_SYMBOLS",Immutable(SSortedList(
- " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")));
-
## <#GAPDoc Label="HexSHA256">
##
diff --git a/lib/files.gi b/lib/files.gi
index 936cb71b52..74eccd3305 100644
--- a/lib/files.gi
+++ b/lib/files.gi
@@ -264,7 +264,7 @@ InstallGlobalFunction( Edit, function( name )
local editor, ret;
name := UserHomeExpand(name);
- editor := Filename( DirectoriesSystemPrograms(), UserPreference("Editor") );
+ editor := PathSystemProgram( UserPreference("Editor") );
if editor = fail then
Error( "cannot locate editor `", UserPreference("Editor"),
"' (reset via SetUserPreference(\"Editor\", ...))" );
diff --git a/lib/helpbase.gi b/lib/helpbase.gi
index 4321909730..f3cf5a8f04 100644
--- a/lib/helpbase.gi
+++ b/lib/helpbase.gi
@@ -55,11 +55,6 @@ end);
## This utility will first be used in some debug tools showing what is newly
## installed by loading a package. Can be documented if desired.
##
-# avoid warning for vars from GAPDoc package
-if not IsBound(StripEscapeSequences) then
- StripEscapeSequences := 0;
-fi;
-
BindGlobal( "IsDocumentedWord", function( arg )
local inid, word, case, simple, cword, book, matches, a, match;
@@ -75,7 +70,7 @@ BindGlobal( "IsDocumentedWord", function( arg )
for book in HELP_KNOWN_BOOKS[1] do
matches:= HELP_GET_MATCHES( [ book ], simple, true );
for a in Concatenation( matches ) do
- match:= case( StripEscapeSequences( a[1].entries[ a[2] ][1] ) );
+ match:= case( _StripEscapeSequences( a[1].entries[ a[2] ][1] ) );
if cword in SplitString( match, "", Difference( match, inid ) ) then
return true;
fi;
@@ -279,7 +274,7 @@ for pair in TRANSATL do
for book in HELP_KNOWN_BOOKS[1] do
matches:= HELP_GET_MATCHES( [ book ], word, false );
for a in Concatenation( matches ) do
- match:= StripEscapeSequences( a[1].entries[ a[2] ][1] );
+ match:= _StripEscapeSequences( a[1].entries[ a[2] ][1] );
patterns:=[];
for i in [1..Length(TRANSATL)] do
patterns[i]:=[];
@@ -308,10 +303,6 @@ od;
return report;
end);
-if StripEscapeSequences = 0 then
- Unbind(StripEscapeSequences);
-fi;
-
#############################################################################
##
@@ -1037,9 +1028,6 @@ end);
if not IsBound( InitialSubstringUTF8String ) then
InitialSubstringUTF8String:= "dummy";
fi;
-if not IsBound( LETTERS ) then
- LETTERS:= "dummy";
-fi;
if not IsBound( WidthUTF8String ) then
WidthUTF8String:= "dummy";
fi;
@@ -1070,7 +1058,7 @@ BindGlobal( "InitialSubstringUTF8Text", function( str, cols )
fi;
# Now pos points at an ESC character; all escape sequences we
# support are terminated by a letter, so search for one.
- j:= PositionProperty( str, c -> c in LETTERS, pos );
+ j:= PositionProperty( str, c -> c in CHARS_ALPHA, pos );
if j = fail then
Error( "string end inside escape sequence" );
fi;
@@ -1082,9 +1070,6 @@ end );
if not IsReadOnlyGlobal( "InitialSubstringUTF8String" ) then
Unbind( InitialSubstringUTF8String );
fi;
-if not IsReadOnlyGlobal( "LETTERS" ) then
- Unbind( LETTERS );
-fi;
if not IsReadOnlyGlobal( "WidthUTF8String" ) then
Unbind( WidthUTF8String );
fi;
diff --git a/lib/helpview.gi b/lib/helpview.gi
index cafa286ca0..7d497f73f6 100644
--- a/lib/helpview.gi
+++ b/lib/helpview.gi
@@ -326,7 +326,7 @@ local s,l,a,e,n,c;
FWITF:=Filename(DirectoryTemporary(),"clients");
fi;
if XLSCLIENTSCMD=false then
- XLSCLIENTSCMD:=Filename(DirectoriesSystemPrograms(),"xlsclients");
+ XLSCLIENTSCMD:=PathSystemProgram("xlsclients");
fi;
if XLSCLIENTSCMD=fail then
return fail;
@@ -393,7 +393,7 @@ show := function(file)
file := file.file;
fi;
if XRMTCMD=false then
- XRMTCMD:=Filename(DirectoriesSystemPrograms(),"xrmtcmd");
+ XRMTCMD:=PathSystemProgram("xrmtcmd");
fi;
if XRMTCMD<>fail then
wnum:=FindWindowId("xdvi",file); # get the window ID of a running XDVI
diff --git a/lib/package.gi b/lib/package.gi
index 82573104fa..226dba4014 100644
--- a/lib/package.gi
+++ b/lib/package.gi
@@ -2086,10 +2086,6 @@ InstallGlobalFunction( AutoloadPackages, function()
##
#F GAPDocManualLab() . create manual.lab for package w/ GAPDoc docs
##
-# avoid warning (will be def. in GAPDoc)
-if not IsBound(StripEscapeSequences) then
- StripEscapeSequences := 0;
-fi;
InstallGlobalFunction( GAPDocManualLabFromSixFile,
function( bookname, sixfilepath )
local stream, entries, SecNumber, esctex, file;
@@ -2112,7 +2108,7 @@ InstallGlobalFunction( GAPDocManualLabFromSixFile,
# throw away TeX critical characters here
esctex:= function( str )
- return Filtered( StripEscapeSequences( str ), c -> not c in "%#$&^_~" );
+ return Filtered( _StripEscapeSequences( str ), c -> not c in "%#$&^_~" );
end;
bookname:= LowercaseString( bookname );
@@ -2160,9 +2156,6 @@ InstallGlobalFunction( GAPDocManualLab, function(pkgname)
GAPDocManualLabFromSixFile( book.BookName, file );
od;
end );
-if StripEscapeSequences = 0 then
- Unbind(StripEscapeSequences);
-fi;
#############################################################################
diff --git a/lib/pager.gi b/lib/pager.gi
index 2559ff3be8..7144d48f65 100644
--- a/lib/pager.gi
+++ b/lib/pager.gi
@@ -290,13 +290,12 @@ end);
# +num for starting display in line num
BindGlobal("PAGER_EXTERNAL", function( lines )
- local path, pager, linepos, str, i, cmdargs, stream;
+ local pager, linepos, str, i, cmdargs, stream;
pager := UserPreference("Pager");
if not (Length(pager) > 0 and pager[1] = '/' and IsExecutableFile(pager))
then
- path := DirectoriesSystemPrograms();
- pager := Filename( path, UserPreference("Pager") );
+ pager := PathSystemProgram( UserPreference("Pager") );
fi;
if pager=fail then
Error( "Pager ", UserPreference("Pager"),
diff --git a/lib/polyconw.gi b/lib/polyconw.gi
index 7fe647ca68..2bb620661f 100644
--- a/lib/polyconw.gi
+++ b/lib/polyconw.gi
@@ -133,7 +133,7 @@ end);
## str := "";
## get := OutputTextString(str, false);
## comm := "wget -q ftp://ftp.comlab.ox.ac.uk/pub/Documents/techpapers/Richard.Brent/factors/factors.gz -O - | gzip -dc ";
-## Process(DirectoryCurrent(), Filename(DirectoriesSystemPrograms(),"sh"),
+## Process(DirectoryCurrent(), PathSystemProgram("sh"),
## InputTextUser(), get, ["-c", comm]);
## res := [[],[]];
## n := 0;
diff --git a/lib/process.gd b/lib/process.gd
index 5eb90924cd..c92665ffa9 100644
--- a/lib/process.gd
+++ b/lib/process.gd
@@ -69,10 +69,10 @@
## directory.
##
## path := DirectoriesSystemPrograms();;
-## gap> ls := Filename( path, "ls" );;
+## gap> ls := PathSystemProgram( "ls" );;
## gap> stdin := InputTextUser();;
## gap> stdout := OutputTextUser();;
+## gap> path := DirectoriesSystemPrograms();;
## gap> Process( path[1], ls, stdin, stdout, ["-c"] );;
## awk ls mkdir
## gap> # current directory, here the root directory
@@ -123,12 +123,10 @@
## Note that input/output redirection commands are not allowed as
## options.
##
-## In order to find a system program use
-## together with .
+## In order to find a system program use .
##
## path := DirectoriesSystemPrograms();;
-## gap> date := Filename( path, "date" );
+## gap> date := PathSystemProgram( "date" );
## "/bin/date"
## ]]>
##
diff --git a/lib/process.gi b/lib/process.gi
index 3c2d42a3b7..0253cc13a0 100644
--- a/lib/process.gi
+++ b/lib/process.gi
@@ -247,10 +247,10 @@ InstallGlobalFunction( Exec, function( arg )
# on Windows, we use the native shell such that behaviour does
# not depend on whether cygwin is installed or not.
# cmd.exe is preferable to old-style `command.com'
- shell := Filename( DirectoriesSystemPrograms(), "cmd.exe" );
+ shell := PathSystemProgram( "cmd.exe" );
cs := "/C";
else
- shell := Filename( DirectoriesSystemPrograms(), "sh" );
+ shell := PathSystemProgram( "sh" );
cs := "-c";
fi;
diff --git a/lib/profile.g b/lib/profile.g
index ca7d399c09..fbb52c8236 100644
--- a/lib/profile.g
+++ b/lib/profile.g
@@ -778,7 +778,7 @@ BIND_GLOBAL("ProfileOperationsOff",function()
UnprofileMethods(\+,\-,\*,\/,\^,\mod,\<,\=,\in,
\.,\.\:\=,IsBound\.,Unbind\.,
\[\],\[\]\:\=,IsBound\[\],Unbind\[\]);
-#T Why? These operations are listed in PFOFILED_OPERATIONS!
+#T Why? These operations are listed in PROFILED_OPERATIONS!
end);
BIND_GLOBAL("ProfileOperations",function( arg )
@@ -836,7 +836,7 @@ BIND_GLOBAL("ProfileOperationsAndMethodsOn",function()
ProfileMethods(\+,\-,\*,\/,\^,\mod,\<,\=,\in,
\.,\.\:\=,IsBound\.,Unbind\.,
\[\],\[\]\:\=,IsBound\[\],Unbind\[\]);
-#T Why? These operations are listed in PFOFILED_OPERATIONS!
+#T Why? These operations are listed in PROFILED_OPERATIONS!
end);
ProfileOperationsAndMethodsOff := ProfileOperationsOff;
diff --git a/lib/streams.gd b/lib/streams.gd
index e9b6365227..5551d01efd 100644
--- a/lib/streams.gd
+++ b/lib/streams.gd
@@ -908,7 +908,7 @@ DeclareCategory( "IsInputOutputStream", IsInputStream and
## d := DirectoryCurrent();
## dir("./")
-## gap> f := Filename(DirectoriesSystemPrograms(), "rev");
+## gap> f := PathSystemProgram("rev");
## "/usr/bin/rev"
## gap> s := InputOutputLocalProcess(d,f,[]);
## < input/output stream to rev >
diff --git a/lib/string.g b/lib/string.g
index 536b964759..36ee0f3d4d 100644
--- a/lib/string.g
+++ b/lib/string.g
@@ -349,3 +349,70 @@ BIND_GLOBAL("UserHomeExpand", function(str)
return str;
fi;
end);
+
+
+# the character set definitions might be needed when processing files, thus
+# they must come earlier.
+BIND_GLOBAL("CHARS_DIGITS",MakeImmutable(LIST_SORTED_LIST("0123456789")));
+BIND_GLOBAL("CHARS_UALPHA",
+ MakeImmutable(LIST_SORTED_LIST("ABCDEFGHIJKLMNOPQRSTUVWXYZ")));
+BIND_GLOBAL("CHARS_LALPHA",
+ MakeImmutable(LIST_SORTED_LIST("abcdefghijklmnopqrstuvwxyz")));
+BIND_GLOBAL("CHARS_ALPHA",
+ MakeImmutable(LIST_SORTED_LIST("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")));
+BIND_GLOBAL("CHARS_SYMBOLS",
+ MakeImmutable(LIST_SORTED_LIST(" !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")));
+
+
+#############################################################################
+##
+#F _StripEscapeSequences( ) . . . . . remove escape sequences from str
+##
+## <#GAPDoc Label="_StripEscapeSequences">
+##
+##
+## string without escape sequences
+##
+## This function returns the string one gets from the string str by
+## removing all escape sequences. If str does not contain such a
+## sequence then str itself is returned.
+##
+##
+## <#/GAPDoc>
+##
+BIND_GLOBAL("_StripEscapeSequences", function(str)
+ local esc, res, i, ls, p;
+ esc := CHAR_INT(27);
+ res := "";
+ i := 1;
+ ls := Length(str);
+ while i <= ls do
+ if str[i] = esc then
+ i := i+1;
+ while not str[i] in CHARS_ALPHA do
+ i := i+1;
+ od;
+ # first letter is last character of escape sequence
+ i := i+1;
+ # remove \027 marker of inner escape sequences as well
+ if IsBound(str[i]) and str[i] = '\027' then
+ i := i+1;
+ fi;
+ else
+ p := Position(str, esc, i);
+ if p=fail then
+ if i=1 then
+ # don't copy if no escape there
+ return str;
+ else
+ Append(res, str{[i..ls]});
+ return res;
+ fi;
+ else
+ Append(res, str{[i..p-1]});
+ i := p;
+ fi;
+ fi;
+ od;
+ return res;
+end);
diff --git a/lib/string.gi b/lib/string.gi
index b5cf315b65..aab31a454b 100644
--- a/lib/string.gi
+++ b/lib/string.gi
@@ -40,8 +40,7 @@ InstallGlobalFunction(IsLowerAlphaChar,x->x in CHARS_LALPHA);
##
#F IsAlphaChar()
##
-InstallGlobalFunction(IsAlphaChar,
- x->x in CHARS_LALPHA or x in CHARS_UALPHA);
+InstallGlobalFunction(IsAlphaChar,x->x in CHARS_ALPHA);
#############################################################################
diff --git a/lib/test.gi b/lib/test.gi
index 3de30989a5..dd467eb217 100644
--- a/lib/test.gi
+++ b/lib/test.gi
@@ -807,7 +807,7 @@ end);
##
## The argument inlist must be either a single filename
## or directory name, or a list of filenames and directories.
-## The function will take create a list of files
+## The function will create a list of files
## to be tested by taking any files in inlist, and recursively searching
## any directories in inlist for files ending in .tst.
## Each of these files is then run through , and the results
diff --git a/src/julia_gc.c b/src/julia_gc.c
index 4c9ea0628a..2c13e10d89 100644
--- a/src/julia_gc.c
+++ b/src/julia_gc.c
@@ -421,7 +421,7 @@ static void FindLiveRangeReverse(PtrArray * arr, void * start, void * end)
{
// HACK: the following deals with stacks of 'negative size' exposed by
// Julia -- however, despite us having this code in here for a few years,
- // I know think it may actually be due to a bug on the Julia side. See
+ // I now think it may actually be due to a bug on the Julia side. See
// for details.
if (lt_ptr(end, start)) {
SWAP(void *, start, end);
diff --git a/tst/delegation.g b/tst/delegation.g
index e8dee4758c..9a8fd47747 100644
--- a/tst/delegation.g
+++ b/tst/delegation.g
@@ -53,9 +53,9 @@ for pos in [1..Length(rules)] do
while true do
n := POSITION_SUBSTRING(str, r, n);
if n = fail then break; fi;
- if n > 1 and str[n-1] in LETTERS then continue; fi;
+ if n > 1 and str[n-1] in CHARS_ALPHA then continue; fi;
if Length(str) >= n + Length(r) then
- if not str[n + Length(r)] in LETTERS then
+ if not str[n + Length(r)] in CHARS_ALPHA then
Add( illegal_delegations, r );
break;
fi;
diff --git a/tst/testinstall/testunix/streams.tst b/tst/testinstall/testunix/streams.tst
index 21677f906d..5712ba2517 100644
--- a/tst/testinstall/testunix/streams.tst
+++ b/tst/testinstall/testunix/streams.tst
@@ -5,7 +5,7 @@ gap> START_TEST("streams.tst");
#
gap> d := DirectoryCurrent();;
#@if ARCH_IS_UNIX()
-gap> f := Filename(DirectoriesSystemPrograms(), "cat");;
+gap> f := PathSystemProgram("cat");;
gap> s := InputOutputLocalProcess(d,f,[]);
< input/output stream to cat >
gap> WriteLine(s,"The cat sat on the mat");
diff --git a/tst/teststandard/varnames.tst b/tst/teststandard/varnames.tst
index 3c8d8e28cb..af9f4663b5 100644
--- a/tst/teststandard/varnames.tst
+++ b/tst/teststandard/varnames.tst
@@ -7,7 +7,7 @@ gap> Filtered( NamesSystemGVars(), x -> not x in ALL_KEYWORDS() and
> ( Length(x)=1 or (IsLowerAlphaChar(x[1]) and Length(x) < 5) ) );
[ "*", "+", "-", ".", "/", "<", "=", "E", "X", "Z", "^", "fail", "last",
"time" ]
-gap> Filtered(NamesSystemGVars(),name->IsSubset(LETTERS,name));;
+gap> Filtered(NamesSystemGVars(),name->IsSubset(CHARS_ALPHA,name));;
gap> IsSubset(IDENTS_GVAR(), IDENTS_BOUND_GVARS() );
true
gap> E;