Este script perl realiza un trabajo de hack en él, haciendo algunas suposiciones sobre la estructura del archivo fuente. (Tales como: .hs
archivo (no .lhs
), las firmas están en la línea inmediatamente anterior a las definiciones, las definiciones son de color en el margen izquierdo, etc)
Se trata de manejar (saltar) los comentarios, las definiciones de estilo ecuación (con lados izquierdos repetidos) y tipos que generan salida de varias líneas en ghci
.
Sin duda, muchos casos válidos interesantes no se manejan correctamente. El script no está cerca de respetar la sintaxis real de Haskell.
Es increíblemente lento, ya que inicia una sesión ghci
para cada función que necesita una firma. Hace un archivo de copia de seguridad File.hs.bak
, imprime las funciones que encuentra en stderr, así como las firmas para las funciones que faltan firmas, y escribe el código fuente actualizado en File.hs
. Utiliza un archivo intermedio File.hs.new
y tiene algunas comprobaciones de seguridad para evitar sobrescribir su contenido con basura.
UTILÍCELO BAJO SU PROPIO RIESGO.
Este script puede formatear su disco duro, grabar su casa, inseguroPerformIO, y tener otros efectos secundarios impuros. De hecho, probablemente lo hará.
Me siento tan sucio.
Probado en Mac OS X 10.6 Snow Leopard con un par de mis propios archivos de origen .hs
.
#!/usr/bin/env perl
use warnings;
use strict;
my $sig=0;
my $file;
my %funcs_seen =();
my %keywords =();
for my $kw qw(type newtype data class) { $keywords{$kw} = 1;}
foreach $file (@ARGV)
{
if ($file =~ /\.lhs$/)
{
print STDERR "$file: .lhs is not supported. Skipping.";
next;
}
if ($file !~ /\.hs$/)
{
print STDERR "$file is not a .hs file. Skipping.";
next;
}
my $ghciPreTest = `echo 1 | ghci $file`;
if ($ghciPreTest !~ /Ok, modules loaded: /)
{
print STDERR $ghciPreTest;
print STDERR "$file is not valid Haskell source file. Skipping.";
next;
}
my $module = $file;
$module =~ s/\.hs$//;
my $backup = "$file.bak";
my $new = "$module.New.hs";
-e $backup and die "Backup $backup file exists. Refusing to overwrite. Quitting";
open OLD, $file;
open NEW, ">$new";
print STDERR "Functions in $file:\n";
my $block_comment = 0;
while (<OLD>)
{
my $original_line = $_;
my $line = $_;
my $skip = 0;
$line =~ s/--.*//;
if ($line =~ /{-/) { $block_comment = 1;} # start block comment
$line =~ s/{-.*//;
if ($block_comment and $line =~ /-}/) { $block_comment=0; $skip=1} # end block comment
if ($line =~ /^ *$/) { $skip=1; } # comment/blank
if ($block_comment) { $skip = 1};
if (!$skip)
{
if (/^(('|\w)+)(+(('|\w)+))* *=/)
{
my $object = $1;
if ((! $keywords{$object}) and !($funcs_seen{$object}))
{
$funcs_seen{$object} = 1;
print STDERR "$object\n";
my $dec=`echo ":t $1" | ghci $file | grep -A100 "^[^>]*$module>" | grep -v "Leaving GHCi\." | sed -e "s/^[^>]*$module> //"`;
unless ($sig)
{
print NEW $dec;
print STDERR $dec;
}
}
}
$sig = /^(('|\w)+) *::/;
}
print NEW $original_line;
}
close OLD;
close NEW;
my $ghciPostTest = `echo 1 | ghci $new`;
if ($ghciPostTest !~ /Ok, modules loaded: /)
{
print $ghciPostTest;
print STDERR "$new is not valid Haskell source file. Will not replace original (but you might find it useful)";
next;
} else {
rename ($file, $backup) or die "Could not make backup of $file -> $backup";
rename ($new, $file) or die "Could not make new file $new";
}
}
El comando 'hs-lint' en Emacs se aplicarán automáticamente sugerencias si 'hs-lint-replace-without-ask' está establecido en' t'. No estoy seguro de cómo restringirlo solo a escribir firmas, pero seguramente debe haber una manera. Y solo estoy publicando esto como un comentario porque no es una solución de EclipseFP. –