TextMateで(EUC|SJIS|JIS)なファイルを無理矢理扱う

追記

全く使えねぇ




http://thug4dev.com/index.php?/archives/130-TextMateEUC.html

理想形はファイルを開いた時に自動判別してゴニャゴニャするプラグインを書く、みたいな事だと思うんですが…。如何せんCocoaを知る所から始めないといけない。
というわけで力技。


もっと力技と手抜き(開くだけ...)

シンボリックリンクをどかす

$ mv ~/bin/mate ~/bin/mate.org
$ sudo rm /bin/mate 

Usage

$ mate <file>

ソース

~/bin/mate

#!/bin/sh
mate="/Applications/TextMate.app/Contents/Resources/mate -r ";
conv="~/bin/mate_conv_in.pl"
$mate `$conv $1`

~/bin/mate_conv_in.pl

#!/usr/local/bin/perl

use strict;
use warnings;
use lib "$ENV{HOME}/bin";
require 'mate_conv_common.pl';

our ( $TEXTMATE_CHARSET, @CHARSET_MAP, $ORG );

my $path = get_abs_path();

my %map = map { $_ => 1 } @CHARSET_MAP;
my $text = slap( $path );

my $enc = guess_encoding( $text, @CHARSET_MAP );
$enc = ref $enc ? $enc->name : $enc;

if ( $enc =~ /or/ ) {
    error( $enc );
}
if ( exists( $map{$enc} ) ) {
    copy( $path, $path . $ORG ) or error( "$!?n" );
    my $touch_file = get_touch_file_path( $path, $enc );
    ( system( 'touch', $touch_file ) ) == 0 or error( "cannot touch $?" );
    from_to_and_save( $text, $enc, $TEXTMATE_CHARSET, $path );
}

print $path;

__END__

~/bin/mate_conv_common.pl

#!/usr/local/bin/perl

use strict;
use warnings;
use Carp;
use Encode qw/ from_to /;
use Encode::Guess;
use File::Copy;
use File::Basename;
use IO::Dir;
use Cwd qw/ abs_path /;

our $TEXTMATE_CHARSET = 'utf8';
our $TOUCH_FMT        = '_from_%s_%s';
our @CHARSET_MAP      = qw/ euc-jp shiftjis 7bit-jis /;
our $ORG              = '.org';
our $BAK              = '.bak';

sub from_to_and_save {
    my ( $text, $from, $to, $path ) = @_;
    from_to( $text, $from, $to );
    open( OUT, '>', $path ) or croak "$!?n";
    print OUT $text;
    close( OUT );
}

sub slap {
    my $path = shift;
    my $text;
    local ( $/, *FH );
    open( FH, '<', $path ) or croak "$!?n";
    $text = <FH>;
    close( FH );

    return $text;
}

sub get_abs_path {
    if ( $#ARGV == -1 or $#ARGV == 1 ) {
    error( 'hoihoi' );
}
    my $path = abs_path( $ARGV[0] );
    if ( !-f $path ) {
        croak $path . ': No such file.';
    }
    return $path;
}

sub get_touch_file_path {
    my ( $path, $str ) = @_;
    return dirname( $path ) . '/' . get_touch_file_name( $path, $str );
}

sub get_touch_file_name {
    my ( $path, $str ) = @_;
    return sprintf( $TOUCH_FMT, $str, basename( $path ) );
}

sub error {
    croak( shift );
}
1;

とりあえず、保存用...

~/bin/mate_conv_out.pl

#!/usr/local/bin/perl

use strict;
use warnings;
use lib "$ENV{HOME}/bin";
require 'mate_conv_common.pl';

our ( $TEXTMATE_CHARSET, @CHARSET_MAP, $BAK );

my $src  = get_abs_path();
my $dir  = dirname( $src );
my $join = '(' . join( '|', @CHARSET_MAP ) . ')';
my $regx = get_touch_file_name( $src, $join );
my ( $enc, $touch_file );

tie my %dir, 'IO::Dir', $dir;
foreach my $file ( keys %dir ) {
    if ( $file =~ qr{ $regx }xms ) {
        $enc        = $1;
        $touch_file = $file;
        last;
    }
}

if ( $enc ) {
    my $text = slap( $src );
    my $bak  = $src . $BAK;
    move( $src, $bak ) or error( "$!?n" );
    from_to_and_save( $text, $TEXTMATE_CHARSET, $enc, $src );
    unlink( $bak )        or error( "$!?n" );
    unlink( $touch_file ) or error( "$!?n" );
}

__END__

TODO

  • $@の対応?
  • もうちょいスマートにならんか?