},
],
support => {
- bash => "Y",
- csh => "Y",
- es => "N",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => undef,
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "N",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => undef,
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Aliases",
+ title => 'Aliases',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "Y(1)",
- tcsh => "N",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => {
+ since => 0,
+ },
+ tcsh => undef,
+ zsh => {},
},
- title => "Shell functions",
+ title => 'Shell functions',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "Y",
- tcsh => "N",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => {},
+ tcsh => undef,
+ zsh => {},
},
- title => "\"Sensible\" Input/Output redirection",
+ title => '"Sensible" Input/Output redirection',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "F",
- ksh => "Y",
- rc => "F",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => {
+ alt => 'function',
+ },
+ ksh => {},
+ rc => {
+ alt => 'function',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Directory stack",
+ title => 'Directory stack',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Command history",
+ title => 'Command history',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Command line editing",
+ title => 'Command line editing',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y(3)",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {
+ note => 'emulation is thought by many to be incomplete',
+ partial => 1,
+ },
+ zsh => {},
},
- title => "Vi Command line editing",
+ title => 'Vi Command line editing',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Emacs Command line editing",
+ title => 'Emacs Command line editing',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "L",
- ksh => "N",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => undef,
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Rebindable Command line editing",
+ title => 'Rebindable Command line editing',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "User name look up",
+ title => 'User name look up',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "F",
- ksh => "N",
- rc => "F",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => {
+ alt => 'function',
+ },
+ ksh => undef,
+ rc => {
+ alt => 'function',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Login/Logout watching",
+ title => 'Login/Logout watching',
},
{
support => {
- bash => "Y",
- csh => "Y(1)",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {
+ since => 0,
+ },
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Filename completion",
+ title => 'Filename completion',
},
{
support => {
- bash => "Y",
- csh => "Y(2)",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {
+ since => undef,
+ },
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Username completion",
+ title => 'Username completion',
},
{
support => {
- bash => "Y",
- csh => "Y(2)",
- es => "L",
- ksh => "Y",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {
+ since => undef,
+ },
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => {},
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Hostname completion",
+ title => 'Hostname completion',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "L",
- ksh => "N",
- rc => "L",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {
+ optional => 'requires readline',
+ },
+ ksh => undef,
+ rc => {
+ optional => 'requires readline',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "History completion",
+ title => 'History completion',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "N",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => undef,
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Fully programmable Completion",
+ title => 'Fully programmable Completion',
},
{
support => {
- bash => "N(4)",
- csh => "N",
- es => "N",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "N(6)",
- zsh => "N(6)",
+ bash => {
+ alt => 'patch',
+ note => 'unofficial patches exist to perform this',
+ },
+ csh => undef,
+ es => undef,
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => {
+ alt => 'function',
+ note => 'This can be done via the shells programmable completion mechanism.',
+ },
+ zsh => {
+ alt => 'function',
+ note => 'This can be done via the shells programmable completion mechanism.',
+ },
},
- title => "Mh Mailbox completion",
+ title => 'Mh Mailbox completion',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "N",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "N",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => undef,
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => undef,
+ zsh => {},
},
- title => "Co Processes",
+ title => 'Co Processes',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "N",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => undef,
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Builtin artithmetic evaluation",
+ title => 'Builtin artithmetic evaluation',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "N",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => undef,
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Can follow symbolic links invisibly",
+ title => 'Can follow symbolic links invisibly',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "N",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => undef,
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Periodic command execution",
+ title => 'Periodic command execution',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Custom Prompt (easily)",
+ title => 'Custom Prompt (easily)',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "N",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "N",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => undef,
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => undef,
+ zsh => {},
},
- title => "Sun Keyboard Hack",
+ title => 'Sun Keyboard Hack',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "N",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => undef,
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Spelling Correction",
+ title => 'Spelling Correction',
},
{
support => {
- bash => "Y(2)",
- csh => "N",
- es => "Y",
- ksh => "N",
- rc => "Y",
- sh => "N",
- tcsh => "N",
- zsh => "Y",
+ bash => {
+ since => undef,
+ },
+ csh => undef,
+ es => {},
+ ksh => undef,
+ rc => {},
+ sh => undef,
+ tcsh => undef,
+ zsh => {},
},
- title => "Process Substitution",
+ title => 'Process Substitution',
},
{
support => {
- bash => "sh",
- csh => "csh",
- es => "rc",
- ksh => "sh",
- rc => "rc",
- sh => "sh",
- tcsh => "csh",
- zsh => "sh",
+ bash => 'sh',
+ csh => 'csh',
+ es => 'rc',
+ ksh => 'sh',
+ rc => 'rc',
+ sh => 'sh',
+ tcsh => 'csh',
+ zsh => 'sh',
},
- title => "Underlying Syntax",
+ title => 'Underlying Syntax',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "N(5)",
- rc => "Y",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {
+ alt => 'patch',
+ note => "A version called 'pdksh' is freely available, but does not have the full functionality of the AT&T version.",
+ },
+ rc => {},
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Freely Available",
+ title => 'Freely Available',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "F",
- ksh => "Y",
- rc => "F",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => {
+ alt => 'function',
+ },
+ ksh => {},
+ rc => {
+ alt => 'function',
+ },
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Checks Mailbox",
+ title => 'Checks Mailbox',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "N",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => undef,
+ csh => undef,
+ es => undef,
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Tty Sanity Checking",
+ title => 'Tty Sanity Checking',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "Y",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => {},
+ tcsh => {},
+ zsh => {},
},
- title => "Can cope with large argument lists",
+ title => 'Can cope with large argument lists',
},
{
support => {
- bash => "Y(7)",
- csh => "Y",
- es => "N",
- ksh => "Y(7)",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {
+ alt => 'config',
+ note => 'Only by specifying a file via the ENV environment variable.',
+ },
+ csh => {},
+ es => undef,
+ ksh => {
+ alt => 'config',
+ note => 'Only by specifying a file via the ENV environment variable.',
+ },
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Has non-interactive startup file",
+ title => 'Has non-interactive startup file',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "N",
- ksh => "Y(7)",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => undef,
+ ksh => {
+ alt => 'config',
+ note => 'Only by specifying a file via the ENV environment variable.',
+ },
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "Has non-login startup file",
+ title => 'Has non-login startup file',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "Y",
- ksh => "N",
- rc => "Y",
- sh => "N",
- tcsh => "N",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => {},
+ ksh => undef,
+ rc => {},
+ sh => undef,
+ tcsh => undef,
+ zsh => {},
},
- title => "Can avoid user startup files",
+ title => 'Can avoid user startup files',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "N",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "N",
- zsh => "N",
+ bash => {},
+ csh => undef,
+ es => undef,
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => undef,
+ zsh => undef,
},
- title => "Can specify startup file",
+ title => 'Can specify startup file',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "Y",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "N",
- zsh => "N",
+ bash => undef,
+ csh => undef,
+ es => {},
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => undef,
+ zsh => undef,
},
- title => "Low level command redefinition",
+ title => 'Low level command redefinition',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "Y",
- ksh => "N",
- rc => "Y",
- sh => "N",
- tcsh => "N",
- zsh => "N",
+ bash => undef,
+ csh => undef,
+ es => {},
+ ksh => undef,
+ rc => {},
+ sh => undef,
+ tcsh => undef,
+ zsh => undef,
},
- title => "Has anonymous functions",
+ title => 'Has anonymous functions',
},
{
support => {
- bash => "N",
- csh => "Y",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => undef,
+ csh => {},
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "List Variables",
+ title => 'List Variables',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "Y",
- tcsh => "N",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => {},
+ tcsh => undef,
+ zsh => {},
},
- title => "Full signal trap handling",
+ title => 'Full signal trap handling',
},
{
support => {
- bash => "Y",
- csh => "Y",
- es => "F",
- ksh => "Y",
- rc => "N",
- sh => "N",
- tcsh => "Y",
- zsh => "Y",
+ bash => {},
+ csh => {},
+ es => {
+ alt => 'function',
+ },
+ ksh => {},
+ rc => undef,
+ sh => undef,
+ tcsh => {},
+ zsh => {},
},
- title => "File no clobber ability",
+ title => 'File no clobber ability',
},
{
support => {
- bash => "Y",
- csh => "N",
- es => "Y",
- ksh => "Y",
- rc => "Y",
- sh => "N",
- tcsh => "N",
- zsh => "Y",
+ bash => {},
+ csh => undef,
+ es => {},
+ ksh => {},
+ rc => {},
+ sh => undef,
+ tcsh => undef,
+ zsh => {},
},
- title => "Local variables",
+ title => 'Local variables',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "Y",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "N",
- zsh => "N",
+ bash => undef,
+ csh => undef,
+ es => {},
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => undef,
+ zsh => undef,
},
- title => "Lexically scoped variables",
+ title => 'Lexically scoped variables',
},
{
support => {
- bash => "N",
- csh => "N",
- es => "Y",
- ksh => "N",
- rc => "N",
- sh => "N",
- tcsh => "N",
- zsh => "N",
+ bash => undef,
+ csh => undef,
+ es => {},
+ ksh => undef,
+ rc => undef,
+ sh => undef,
+ tcsh => undef,
+ zsh => undef,
},
- title => "Exceptions",
+ title => 'Exceptions',
},
-
],
}
'<tr>',
'<th>feature',
(map {
- sprintf('<th>%s', Entity($_->{name}))
- } @{ $data->{agents} }{@agents}),
+ sprintf('<th%s>%s',
+ (map {
+ sprintf ' title="%s"', Entity($_)
+ } $data->{agents}->{$_}->{name} // ()),
+ $_
+ )
+ } @agents),
);
print '<thead>', $header;
say '</thead>';
print '<td>', Entity($row->{title});
}
-my %DSTATS = (
- Y => 'feature can be done',
- N => 'feature is not present',
- F => 'feature can only be done by using the shells function mechanism',
- L => 'the readline library must be linked into the shell to enable this feature',
-);
-my %CSTATS = (
- N => 'l1',
- F => 'l2',
- L => 'l4',
- Y => 'l5',
+my %TSTATS = (
+ l5 => '✔',
+ l4 => '✔',
+ l3 => '±',
+ l2 => '*',
+ l1 => '✘',
);
sub saysupportcols {
my ($row, $agent) = @_;
- my $stat = $row->{support}->{$agent};
+ my $support = $row->{support}->{$agent};
+ my $level = (
+ !defined $support ? 'l1' :
+ ref $support ne 'HASH' ? 'l0' :
+ $support->{alt} ? 'l2' :
+ $support->{partial} ? 'l3' :
+ $support->{optional} ? 'l4' :
+ 'l5'
+ );
my $title = join(' ',
- $DSTATS{$stat} // 'unknown support',
- 'in', $agent,
+ defined $support ? 'supported' : 'unsupported',
+ 'in', $data->{agents}->{$agent}->{abbr} // $agent,
);
+ $title .= " ($_)"
+ for ref $support && ($support->{note} // $support->{optional}) || ();
+ my $header = defined $support ? '✔' : '✘';
printf('<td class="%s" title="%s">%s',
- join(' ',
- X => $CSTATS{$stat},
- ),
+ join(' ', X => $level),
$title,
- $stat,
+ $TSTATS{$level} // (ref $support ? '?' : $support),
);
}