Thursday, July 15, 2010

Emeditor with ActivePerl

다음은 EmEditor의 PerlScript를 이용해서 hiveminder에 글을 올리는 post입니다.


#language = "PerlScript"
use utf8;
use Net::Hiveminder;

my $hm = Net::Hiveminder->new(email => 'your@email.com', password => 'yourpassword');
my $text = $Window->prompt('Add Hive Minder Summary', '');
$hm->create_task(Encode::encode("euckr", $text));

$Window->Alert('done');


저는 단축키 alt-v로 이 매크로가 실행되도록 해두었습니다.





이렇게 올린 todo는 바로바로 iphone의 iMinder(무료)로 확인할 수 있고 편집할 수 있습니다.



그런데 hiveminder에 올리는 summary에 한글과 영어이외에 일본어나 중국어등의 utf-8코드를 사용하고 싶다면 이하의 방법을 사용해야 합니다.


#language = "PerlScript"
use encoding "utf8";
use utf8;
use Win32::OLE;
use Net::Hiveminder;

my $vbscript = Win32::OLE->new('ScriptControl');

$vbscript->{Language} = 'JScript';
$vbscript->AddObject("window", $Window); # Emeditor의 DOM의 하나인 윈도우 객체를 넘긴다.
$vbscript->AddCode(<<JScript);
function writeFileAsUTF8WithoutBOM(filepath, content) {
/* ADODB.Stream - SaveOptionsEnum */
var adSaveCreateOverWrite = 2;

/* ADODB.Stream - StreamTypeEnum */
var adTypeBinary = 1, adTypeText = 2;

/* ADODB.Stream - StreamWriteEnum */
var adWriteChar = 0, adWriteLine = 1;

var st = new ActiveXObject("ADODB.Stream");
st.type = adTypeText;
st.charset = "utf-8";
st.open();

st.WriteText( content, adWriteLine );

st.Position = 0;
st.Type = adTypeBinary;
st.Position = 3; // to skip BOM
var bin = st.Read();
st.Close();

var stw = new ActiveXObject("ADODB.Stream");
stw.Type = adTypeBinary;
stw.Open();
stw.Write( bin );
if (filepath == '') {
alert('filepath is empty!');
}
stw.SaveToFile(filepath , adSaveCreateOverWrite );
stw.Close();
}
function saveprompt() {
var str = window.prompt('Add Hive Minder Summary', new Date);
writeFileAsUTF8WithoutBOM('c:\\\\_hiveminder.txt', str);
}
JScript

#$vbscript->Run('saveprompt', null);
$vbscript->Eval('saveprompt()');

my $hm = Net::Hiveminder->new(email => 'your@email.com', password => 'yourpassword', );
open (my $fh, "<:utf8", "c:\\_hiveminder.txt") or $window->alert("Cannot open $file: $!");
my $text = <$fh>;
$hm->create_task($text);

#$window->Alert(Encode::encode("UCS-2LE", $text)); <--- doesn't work
#$window->Alert(Encode::encode("UCS-2BE", $text)); <--- doesn't work
#$window->Alert(Encode::encode("utf8", $text)); <--- doesn't work
#$window->Alert(Encode::encode("utf16", $text)); <--- doesn't work

$Window->Alert('done');







이렇게 해야하는 이유는 Emeditor는 ScriptingControl 이라는 ActiveX를 통해서 ActivePerl의 인스턴스를 만들어 내고
소스 문자열을 그대로 이 ScriptingControl에 건내, Eval이나 Run 인터페이스를 통해 실행하는 방식을 취하고 있는데
ActivePerl에서는 유니코드가 내부적으로 utf16이 아닌 utf-8을 사용하고 있고, 윈도우즈는 유니코드를 내부적으로 utf-16(정확히는 UCS-2)을 사용하고 있는데
이 부분에서 WideChar의 전달이 망가지기 때문입니다.

# 전달받지 않고 Perl안에서 할당하고 처리하는 코드는 잘 문제없습니다.

결국 이런 회피법으로 피해가고 있습니다만, 좀 더 똑똑한 방법이 있는 지는 모르겠습니다.
Python도 내부적으로 UCS-2입니다만, Hiveminder의 Python라이브러리가 없습니다.
# 만들면 되는데, Hiveminder의 Api의 설명문서가 제대로 갱신되어 있지 않습니다. 많은 시간 들여 해봤는데 403 forbidden이 나옵니다.
# 전달해야하는 파라메터는 훨씬 더 많은 것 같습니다.

그런데 위쪽의 방법으로 하면 되는 이유는 OS에서는 어째서인지 명확히 설명할 수는 없지만, 시스템 디폴트코드페이지는 먹히기 때문입니다.
# 실제로는 저는 일본 OS이기 때문에 sjis로 decode하고, 일본어만 사용할 수 있습니다.

좀 더 현명한 방법이 있으면 공유 부탁드립니다. m(_ _)m

No comments: