perl

hshong's blog

Subscribe to RSS feed

ctags 로 perl 소스분석

,

perl -V

하면 젤 밑에 나의 @INC 가 나온다.
  @INC:
    /home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/site_perl/5.12.0/i686-linux-thread-multi
    /home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/site_perl/5.12.0
    /home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/5.12.0/i686-linux-thread-multi
    /home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/5.12.0

i686-linux-thread-multi 요거는 뭔지 모르겠고,
site_perl 밑에 있는건 cpan 을 통해 내가 추가로 설치한 모듈저장소이고,
5.12.0 밑에 있는건 5.12.0 의 코어+기본 모듈이다.

vim 에서 'Ctrl + ]' 을 눌러서 tag 로 원하는 tag로 점프하려면, tags 를 맨들어야 한다.
ubuntu 기본 패키지에 들어있는 ctags 는 내가 알던 ctags 랑 좀 달라서, 걍 다시 설치

sudo apt-get install ctags


cd /home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/5.12.0
ctags -R --languages=Perl

cd /home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/site_perl/5.12.0
ctags -R --languages=Perl


ctags 옵션 조띠 많음. 위처럼 하면 pm, pl 인 파일을 recursive 하게 하위 디렉터리까지 털어서 tags 라는 이름의 파일로 저장한다.

.vimrc 에 기본 tags 위치 지정
set tags=/home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/5.12.0/tags,/home/hshong/perl5/perlbrew/perls/perl-5.12.0/lib/site_perl/5.12.0/tags


어떻게 하면 cpan 모듈받을때마다 tags 갱신해주고 여차저차 활용할지는 아직 몰겟음.
주위에 tags 활용 잘하는 사람 있으면 보고 주서와야징

gnome-term 황홀경

,

한개의 터미널세션에서 screen 을 사용해서 여러개의 창을 띄우고 작업하고 싶었으나,
key map 하는 방법을 몰라서 안쓰고 있다.

Ctrl + a

눌르고 a

Ctrl + a

눌르고 c
같은 키조합이 bash shell 을 쓰는 나에겐 중복되어서 커서 이동이 불편했기 때문이다.
bash shell 에서 Ctrl + a 는 커서를 명령행 젤 앞으로 보내준다.

예전엔 모르는 함수는 perldoc 으로 찾지 뭐 라는 생각이 있엇는데, 요샌 eclipse 쓰다보니께,

.

눌르면 뭐든 해결되는 편리함을 느껴서 ctags 를 좀 파보자는 생각으로
tags 이전 스택으로 돌아오는 명령어

Ctrl + T

를 보고

Ctrl + Shift + t

를 눌렀다.
tab 이 생겼다. 하나 주웠다.

요약하면, gnome-term 에서

Ctrl + Shift + t

눌러보자

초간단 웹서버로 파일 보내기

, , ,

otfile

민간인 친구들은 네이트온을 파일 전송용으로 자주 쓴다.
나한테도 가끔 나쁜 파일들을 보내달라고 하는데, 집 PC, 회사 PC 모두 우분투를 쓰기 때문에 보내줄 수가 없다.

예전에 keedi 님의 트윗을 보고 생각난게 있어서 슥샥 해봤다.

HTTP::Server::Simple 을 사용한 간단한 스크립트인데,

1. 초간단 웹서버를 띄운다.
2. public 링크를 만들어준다.
3. 한번의 요청만 수락하고 웹서버는 죽는다.

OTF

위에꺼에서 포트번호 바꿔주고, 공유기 설정 - 포트포워딩에서 내가 사용할 OTF 전용 포트 rule 한개 추가하면 끝
IT강국에 사는 나는 xpeed 를 쓰기 때문에 거칠 것 없이 빠른 전송속도를 보여준다.

사용예

요렇게 파일 걸어주면
hshong@hshong-laptop:~/tmp$ otfile badfile 
I: serving 'badfile' as 'badfile', size 10, type text/plain
I: url is: http://내아이피:3000/8c3e50a2-cabb-4b50-b552-5adc20254452/badfile


요렇게 민간인이 HTTP 클라이언트(웹브라우저)를 이용해서 받을 수 있다.
hshong@hshong-laptop:~$ wget http://내아이피:3000/8c3e50a2-cabb-4b50-b552-5adc20254452/badfile
--2010-07-17 22:27:59--  http://내아이피:3000/8c3e50a2-cabb-4b50-b552-5adc20254452/badfile
Connecting to 내아이피:3000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10 [text/plain]
Saving to: `badfile'

100%[==================================================================================================================================>] 10          --.-K/s   in 0.009s  

2010-07-17 22:27:59 (1.08 KB/s) - `badfile' saved [10/10]


전송상태 Progress bar 도 표시되서 편리하다
I: request from 클라이언트아이피
badfile: 100% [==================================================================================================================================================]D 0h00m00s

터미널(tty) 에서 이메일(email) 보내기

, , , ...

email

diff 한 결과라던지, log를 바로 메일로 쏘고 싶은데, 브라우저로 할려니깐 귀찮아서
검색해봤더니 이미 perl-kr 의 jeen++ 님이 슥샥 해놓으신게 있어서 한개 주웠음

INSTALL
            sudo apt-get install ssmtp

    /etc/ssmtp/ssmtp.conf

            root=your.email@gmail.com
            mailhub=smtp.gmail.com:587
            useSTARTTLS=YES
            AuthUser=your.email@gmail.com
            AuthPass=your.password
            rewriteDomain=gmail.com
            FromLineOverride=YES
            hostname=blah

    MIME::Lite

            cpanm MIME::Lite

SYNOPSIS
            email [-h|--help] [-f|--from] <SENDER> [-t|--to] <RECEIVER> [-s|--subject] <SUBJECT> [-c|--contents] <CONTENT or File>

            e.g.
            echo "export EMAIL_FROM=sender@example.com" >> $HOME/.bashrc && source $HOME/.bashrc
            email -t receiver@example.com -s Subject -c Content
            echo content | email -t receiver@example.com -s subject

            or

            email -f sender@example.com -t receiver@example.com -s Subject -c Content
            email -f sender@example.com -t receiver@example.com -s Subject -c /path/to/foo.file -c Content          # multiple
            email -from="sender@example.com" --to="receiver@example.com" --subject="Subject" --contents="Content"


사용예
echo "export EMAIL_FROM=내꺼@gmail.com" >> /home/hshong/.bashrc && source /home/hshong/.bashrc
email -h | email -t 내꺼@gmail.com -s "email usage"

터미널용(tty) 영한사전, 한영사전

App-eng2kor-1.0006.tar.gz

SYNOPSIS
            eng2kor --help

            eng2kor "english"                                          # eng2kor
            eng2kor some thing "something"                             # multiple
            eng2kor "this is sentence"                                 # sentence
            eng2kor --lang='ko|en' 한쿡말                               # kor2eng
            eng2kor --file=eng.txt                                     # file
            echo "word" | eng2kor                                      # pipe input
            export DAUM_ENDIC_KEY=e4208a9e48744c40f2b7459162062313ed9878f6      # note: just sample, invalid key


INSTALL
            tar xfz App-eng2kor-VERSION.tar.gz
            cd App-eng2kor-VERSION
            perl Makefile.PL
            make
            make test
            make install


PRE REQUIRED MODULES
    'Encode' => '0',
    'File::Slurp' => '0',
    'Getopt::Long' => '0',
    'HTTP::Request' => '0',
    'HTTP::Response' => '0',
    'JSON' => '0',
    'LWP::UserAgent' => '0',
    'Pod::Usage' => '0',
    'Term::ANSIColor' => '0',
    'constant' => '0',
    'utf8' => '0'


결과 예
hshong@ubuntu:~$ eng2kor perl
perl
perl
	펄
hshong@ubuntu:~$ eng2kor --lang='ko|en' 펄
펄
펄
	Pearl
pearl
	→purl(펄, 소용돌이, 넘어뜨리다, 졸졸 흐르다)
펄
	1. a wide expanse of land 2. slime along the bank of an inlet 3. a vast plain
purl
	1. 장식 단을 달다, 가두리를 달다 2. 단 감침, 가두리


* miyagawa의 gistp 보고 베꼇음

local::lib 를 왜 사용할까?

, , ,

Best way - local::lib 를 참고하면 된다.
의존성 모듈의 위치지정 이라든가, man page 를 설치할 것인가 에 대한 다양한 옵션에 대한 설명도 있을 뿐더러 모듈 Author가 직접 작성하였고 아래 내용의 대부분은 위의 링크의 일부를 가져온 것이다.

root 또는 관리자 계정이 아닌 일반사용자라면, 마음껏 cpan을 활용할 수가 없다.
서버 관리자가 특정 모듈을 설치해 주지 않는다면?
홈디렉토리에 펄을 새로 설치해서 쓰면되지만..
근데 이미 global 하게 설정된 수많은 non-core 모듈들은 어쩌고?
이럴때에 local::lib 를 써서 자신만의 @INC를 추가로 가질 수 있다면 유용하다.
local::lib 를 사용한다면, 기존의 편리함을 이용하면서 나만을 위한 새로운
모듈 저장소를 확보할 수 있다.

나만의 공간이기 때문에 git repository로 관리할 수도 있고, 신경 쓸 부분이 줄어들기 때문에 여러모로 편리하게 사용할 수 있다.

사용방법은 perl-kr 의 aero님 이 이미 blog 에 posting 하신 좋은 예가 있다. (cpanm 까지 한방에 굳)
aero's blog

% wget -O - http://cpanmin.us/ | perl - local::lib App::cpanminus && echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >> ~/.bashrc && . ~/.bashrc


확인은?
% perl -le 'print join "\n", @INC'


$HOME/perl5/lib/perl5
$HOME/perl5/lib/perl5/i686-linux

이렇게 디렉토리가 생겻다면 LWP 모듈을 시험삼아 설치해보자.

% cpanm LWP
% ls -l $HOME/perl5/lib/perl5/LWP.pm


@INC, PERL5LIB와 같은 용어 설명은 아래 링크를 참고
Perl Module 수동 설치

catalyst로 제작한 web application을 apache web server로 띄우는 방법?

, , , ...

일단은 나도 몰름.
이 post를 update 해가면서 완성시킬 예정임

현재의 의문점.

<project_root>/script/<project>_server.pl

에서 보면 여러 환경변수를 가지고 선행 처리후에
my $runner = sub { <project>->run({ ... }); };
하는데,
이건 Plack::Server 로(처럼?) 구현된 것인가?

그렇다면 <project>_server.pl 자체가 Plack::Server의 구현물?

용어부터가 정리가 안되고 잇음

apache conf에서 <Location> 또는 <Directory> 를 어디로 정해야 할것이며, 원하는 페이지 접근을 위해선
URL을 어떻게 입력해야 하나?

일단 PSGI::Plack 부터 공부하자

mod_perl, Catalyst::Manual::Cookbook

KBO 일정 - google calendar

, , , ...

두산 베어스 LG 트윈스 넥센 히어로즈 SK 와이번스 한화 이글스 ㅠ.ㅠ KIA 타이거즈 삼성 라이온스 롯데 자이언츠 sports schedule 에서 보면 메이져리그나 일본리그는 있는데, 국내 프로야구일정은 없어서 KBO에 메일도 보내고 트윗도 날려봤는데 반응이 없어서 직접 만들어봤다. 한국야구위원회 의 html을 파싱해서 미리 만들어놓은 calendar에 API를 사용해서 넣는다. CPAN 만 잇다면야 뭐.. 갠적으론 내가 만들어 놓은 팀별 calendar를 KBO 관리자한테 수정권한을 주고 KBO 에서는 해당 calendar를 사용하면 좋을 거 같은데.. * 문제가 있는게, 일정이 바뀔때마다 수정권한 있는 '내가' 해야 된다는거..
#!/usr/env/perl
use strict;
use warnings;
use utf8;
use LWP::Simple;
use List::Util qw/first/;
use Net::Google::Calendar;
my $DEBUG=1;
my $year = 2010;
my @months = map { sprintf "%02d", $_; } (3..8);
#------------------
# google calendar
#------------------
my ($username, $password) = ('googleID', 'password');
my $cal = Net::Google::Calendar->new;
$cal->login($username, $password);
my @cs;
for($cal->get_calendars) {
    #print $_->title."\n";
    #print $_->id."\n\n";
    push @cs, $_;
}
#------------------
foreach my $month (@months) {
    #my $html = get("http://www.koreabaseball.com/schedule/schedule.asp?cyear=$year&cmonth=$month"); # session problem
    open(my $fh, '<', "html/schedule.$month.html") or die "couldn't open html/shcedule.$month.html $!\n";
    my $html = do { local $/; <$fh> };
    if($html) {
        my @tags = $html =~ m{<td bgcolor="#\w+" valign=top><table width="\d+" border="\d+" cellspacing="\d+" cellpadding="\d+">.*?</table></td>}sg;
        for my $tag (@tags) {
            my @days = $tag =~ m{<td width="\d+" height="\d+" align="right" class="style\d+">(\d+)</td>}sg;
            my ($day) = @days;
            my @home_score_away_time = $tag =~ m{<td width=\d+ align=center>(.*?)</td>}sig;
            while (my ($home, $score, $away, $time) = splice @home_score_away_time, 0, 4) {
                my ($hour, $min) = $time =~ m/(\d+):(\d+)/sg;
                unless ($hour) {
                    $hour = 14;
                    $min = 0;
                }
                #------------------
                # google calendar
                #------------------
                my $entry = Net::Google::Calendar::Entry->new();
                $entry->title("$home vs $away");
                $entry->content("$home vs $away");
                $entry->location('');
                $entry->transparency('transparent');
                $entry->status('confirmed');
                my $start = DateTime->new(year=>$year, month=>$month, day=>$day, hour=>$hour, minute=>$min, time_zone => 'Asia/Seoul');
                $entry->when($start, $start + DateTime::Duration->new( hours => 4 ));
                my $author = Net::Google::Calendar::Person->new();
                $author->name('hshong');
                $author->email($username);
                $entry->author($author);
                my $c = first { $_->title =~ m/^$home/ } @cs;
                $cal->set_calendar($c);
                $cal->add_entry($entry);
                $c = first { $_->title =~ m/^$away/ } @cs;
                $cal->set_calendar($c);
                $cal->add_entry($entry);
                #------------------
                print "$year $month $day $hour $min $home $away\n";
            }
        }
    }
}

android style & theme

, , , ...

android 에선 style과 theme를 상속할 수 있다.

style의 계층구조를 파악해두면 내가 상속해서 쓸때 도움이 될 것 같아서 정리해봤다.
원본은 android namespace - res/values/style.xml

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Simple;
use Data::Dump qw/dump/;

my $config = XMLin('style.xml');
my $style={};
foreach my $key (keys %{$config->{style}}) {
    my @names = split /\./, $key;
    my $tmp='$style->{';
    $tmp .= join '}->{', @names;
    $tmp.='}={}';
    eval $tmp;
}

print dump($style);


해쉬 레퍼런스를 재귀적으로 연결해야 하는데 여려워잉..그래서 eval을 사용

output
{
  AlertDialog             => {},
  Animation               => {
                               Dialog              => {},
                               DropDownDown        => {},
                               InputMethod         => {},
                               InputMethodFancy    => {},
                               LockScreen          => {},
                               OptionsPanel        => {},
                               SearchBar           => {},
                               StatusBar           => {},
                               SubMenuPanel        => {},
                               Toast               => {},
                               Translucent         => {},
                               TypingFilter        => {},
                               TypingFilterRestore => {},
                             },
  ButtonBar               => {},
  DialogWindowTitle       => {},
  MediaButton             => { Previous => {}, Rew => {} },
  Preference              => { CheckBoxPreference => {}, DialogPreference => {} },
  TextAppearance          => {
                               Inverse     => {},
                               Large       => {},
                               Medium      => { Inverse => {} },
                               Widget      => { DropDownHint => {}, TextView => { PopupMenu => {} } },
                               WindowTitle => {},
                             },
  Widget                  => {
                               AbsListView          => {},
                               AutoCompleteTextView => {},
                               Button               => { Small => {}, Toggle => {} },
                               CompoundButton       => { CheckBox => {}, RadioButton => {} },
                               DropDownItem         => { Spinner => {} },
                               EditText             => {},
                               ExpandableListView   => {},
                               Gallery              => {},
                               HorizontalScrollView => {},
                               ImageButton          => {},
                               ImageWell            => {},
                               ListView             => { DropDown => {}, Menu => {}, White => {} },
                               PopupWindow          => {},
                               ProgressBar          => { Horizontal => {}, Small => { Title => {} } },
                               RatingBar            => { Small => {} },
                               ScrollView           => {},
                               Spinner              => {},
                               TabWidget            => {},
                               TextView             => { ListSeparator => { White => {} } },
                               WebView              => {},
                             },
  WindowTitle             => {},
  "WindowTitleBackground" => {},
  ZoomControls            => {},


요 밑에껀 theme
{
  Theme => {
        Black        => { NoTitleBar => { Fullscreen => {} } },
        Dialog       => { AppError => {} },
        ExpandedMenu => {},
        InputMethod  => {},
        Light        => { NoTitleBar => {}, Panel => {} },
        NoDisplay    => {},
        NoTitleBar   => { Fullscreen => {} },
        Panel        => {},
        SearchBar    => {},
        Translucent  => {},
      },
}


@am0c, @keedi 님들의 도움으로 eval을 사용하지 않고 더 멋지게..

@am0c++, @keedi++
#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dump qw/dump/;

my %styles;
while (my $line = <DATA>) {
    chomp $line;
    my @objects = split /\./, $line;
    my $ref = \%styles;
    for my $object ( @objects ) {
        $ref->{$object} = {} unless $ref->{$object};
        $ref = $ref->{$object};
    }
}

print dump(\%styles);

__DATA__
Widget.GridView
Widget.GestureOverlayView.White
TextAppearance.DialogWindowTitle
Widget.SeekBar
Widget.QuickContactBadgeSmall.WindowSmall
Widget.RatingBar.Indicator
Animation.Activity
Animation.DropDownUp
Widget
Widget.ExpandableListView
Preference.Category
Widget.TextView.SpinnerItem
Animation.ZoomButtons
Widget.CompoundButton
TextAppearance.SearchResult.Subtitle
Widget.QuickContactBadgeSmall.WindowLarge
Widget.Button.Inset
Widget.ProgressBar.Large.Inverse
Animation
Widget.ScrollView
Widget.ProgressBar.Inverse
Widget.EditText
Widget.Button.Transparent
Widget.ListView
WindowTitleBackground
Animation.TypingFilter
Widget.TextView.PopupMenu
Widget.CompoundButton.CheckBox
Widget.ProgressBar
MediaButton.Ffwd
TextAppearance.Theme.Dialog.AppError
WindowTitle
TextAppearance.Small
TextAppearance.Large.Inverse
Animation.Toast
Animation.Dialog
MediaButton
TextAppearance.Medium.Inverse
Widget.Gallery
TextAppearance.Large
Animation.StatusBar
Widget.QuickContactBadge.WindowLarge
Widget.QuickContactBadgeSmall
Widget.ImageWell
MediaButton.Previous
Widget.ImageButton
TextAppearance.Inverse
Animation.DropDownDown
Widget.RatingBar
Widget.RatingBar.Small
ZoomControls
Preference.DialogPreference.EditTextPreference
Widget.TextView.ListSeparator.White
Animation.LockScreen
Animation.Wallpaper
Animation.Translucent
Widget.DropDownItem.Spinner
Animation.OptionsPanel
Widget.CompoundButton.RadioButton
Animation.RecentApplications
MediaButton.Rew
TextAppearance.Widget.TextView.PopupMenu
Widget.CompoundButton.Star
Preference.RingtonePreference
TextAppearance.Widget.TextView.SpinnerItem
Widget.KeyboardView
MediaButton.Play
AlertDialog
TextAppearance.StatusBarTitle
TextAppearance.Theme.Dialog
MediaButton.Pause
Widget.ProgressBar.Small
Widget.AutoCompleteTextView
TextAppearance.Widget.IconMenu.Item
Widget.Button
Preference.PreferenceScreen
TextAppearance.Widget.EditText
Widget.ProgressBar.Large
Widget.Spinner
TextAppearance.Widget.TabWidget
Widget.Button.Small
Widget.AbsListView
TextAppearance.Medium
TextAppearance.Theme
Preference.Information
Widget.ProgressBar.Small.Inverse
Widget.TabWidget
TextAppearance.Widget.DropDownItem
TextAppearance.SearchResult
Animation.InputMethod
Widget.DropDownItem
Animation.InputMethodFancy
DialogWindowTitle
Widget.TextView
Widget.TextView.ListSeparator
Preference.DialogPreference.YesNoPreference
MediaButton.Next
Widget.HorizontalScrollView
Widget.ListView.White
Widget.QuickContactBadge.WindowSmall
TextAppearance.Small.Inverse
TextAppearance
Widget.QuickContactBadge
Preference
Animation.SlidingCard
TextAppearance.SearchResult.Title
TextAppearance.Widget.Button
Widget.QuickContactBadge.WindowMedium
Widget.Button.Toggle
Animation.TypingFilterRestore
Widget.PopupWindow
TextAppearance.Widget.TextView
Widget.ListView.Menu
Animation.SearchBar
Widget.ProgressBar.Small.Title
TextAppearance.Widget
ButtonBar
Widget.QuickContactBadgeSmall.WindowMedium
Widget.GestureOverlayView
Widget.WebView
TextAppearance.Widget.DropDownHint
TextAppearance.SlidingTabActive
Preference.CheckBoxPreference
Widget.ListView.DropDown
Preference.DialogPreference
Animation.SubMenuPanel
Widget.ProgressBar.Horizontal
TextAppearance.WindowTitle
TextAppearance.SlidingTabNormal

unique line by perl

,

#!/usr/env/perl -w
use strict;
die "Usage: $0 file\n" unless @ARGV;
open(my $f, "<", $ARGV[0]) or die "$ARGV[0] open failed $!\n";
my %seen;
while(<$f>) {
    #chomp;
    $seen{$_}++;
}
close($f);
foreach my $key (sort keys %seen) {
    #print "$key\n";
    print "$key";
}