2008/08/29


適当ですが...
show-delicious-comment-if-hatena-bookmark-comment-is-disabled.user.js
これで今日も眠れますね。
しかし名前長いな。
Posted at by




Atompub使うと簡単。
use strict;
use warnings;

use Atompub::Client;
use XML::Atom::Entry;
use utf8;

my $username = 'xxxxxxxxxxxxxxxxxx';
my $password = 'xxxxxxxxxxxxxxxxxx';
my $uri = "http://d.hatena.ne.jp/$username/atom/draft";

my $client = Atompub::Client->new;

$client->username($username);
$client->password($password);

# 下書きを一覧
my @entries = $client->getFeed($uri);
for my $entry (@entries) {
    next if not $entry->id;
    warn $entry->link->href."\n".$entry->title."\n\n";
}

# 新規下書きエントリ
my $entry = XML::Atom::Entry->new;
$entry->title('下書きテスト');
$entry->content('はてダで下書き');
my $entry_uri = $client->createEntry($uri, $entry);
warn $client->errstr||'\n';

# 下書きを上書き
$entry->content('はてダで下書きを上書き');
$client->updateEntry($entry_uri, $entry);

# 下書きを削除
$client->deleteEntry($entry_uri);

# 公開用に新規下書きエントリ
$entry = XML::Atom::Entry->new;
$entry->title('下書き公開テスト');
$entry->content('はてダの下書きを公開してみるテスト');
$entry_uri = $client->createEntry($uri, $entry);
warn $client->errstr||'\n';

# 下書きを公開
$client->ua->default_header('X-HATENA-PUBLISH' => 1);
$client->updateEntry($entry_uri, $entry);
ゴミのエントリは、適当に消して下さい。
ところで1つも下書きエントリがない状態で、getFeedするとルートのlinkが取れてしまうのだけど、これは仕様だろうか。
Posted at by



2008/08/27


ま、ほぼ差異のないソースですが...
windowsでしか動作確認出来てないので、動かなかったら直して下さい。
よかったらもってって下さい。
Posted at by



2008/08/22


APIs for Finding Location

Google launched two APIs for finding the location of a user from a web application. The most simple way, which is also the least precise, is to derive some information about location from the IP. Google AJAX API has an object named google.loader.ClientLocation that includes "metro-level granularity properties": country, region, city, low resolution latitude and longitude. This could be useful if you want to customize a web page for a specific country or to prefill information about location. You probably noticed that google.com automatically redirects to the appropriate international domain and that when you create a Google account your country is already selected.

http://googlesystem.blogspot.com/2008/08/apis-for-finding-location.html

Developer's Guide - Google AJAX APIs - Google Code

When an application makes used of the AJAX API loader, the loader attempts to geo locate the client based on it's IP address. If this process succeeds, the client's location, scoped to the metro level, is made available in the google.loader.ClientLocation property. If the process fails to find a match, this property is set to null.

http://code.google.com/apis/ajax/documentation/#ClientLocation http://code.google.com/apis/gears/api_geolocation.html
試しにやってみたら"google.loader.ClientLocation.address.region"で"「大阪府」って出た。
あと"ClientLocation.latitude"と"ClientLocation.longitude"で緯度経度が得られるので、setCenterで中心位置を変更出来る。
google.load("maps", "2");
google.load("search", "1");
google.setOnLoadCallback(function() {
    var map = new google.maps.Map2(document.getElementById("map"));
    map.setCenter(new google.maps.LatLng(
        google.loader.ClientLocation.latitude,
        google.loader.ClientLocation.longitude), 10);
});
実行結果は以下

続きを読む...

Posted at by




Booで。
class _X:
  s as string

  def constructor():
    s = "ひだまり"

  static def op_LessThan(x as _X, v as string):
    print x.s, v
    return x
 
  static def op_Division(x as _X, v as object):
    if v.GetType() == typeof(int):
      x.s += "スケッチ"
    else:
      x.s += "365"
    return x

X = _X()
_ = 1

X / _ / X < "来週も見てくださいね!"
実行は
C:¥temp> booi yuno.boo
ひだまりスケッチ365 来週も見てくださいね!
でインタプリタ起動するか
C:¥temp> booc yuno.boo
Boo Compiler version 0.8.2.2960 (CLR v2.0.50727.832)

C:¥temp> yuno.exe
ひだまりスケッチ365 来週も見てくださいね!
でコンパイル実行。
boo初めて使ってみたけど、これいいかも。
monoでの実装とかあるのかな?

ちなみにpythonに似てるけど、静的型付けです。あとオペレータの判断順番がpythonと違うので、pythonのまま移植すると「ひだまり365スケッチ 来週も見てくださいね!」になるので要注意

Posted at by



2008/08/19


HTML::TreeBuilderは便利だけど、データ構造がロジックになってしまうのが難点。
Perlでブックオフの店舗を検索し、結果をハッシュの配列に格納する - As a Futurist...

HTMLを解析する練習です。Perlの配列とかハッシュの扱いも少し分かりました。 以下のブックオフの検索をPerlでやっただけです。

http://blog.riywo.com/2008/03/31/164327
ってことでWeb::Scraperで。

#!/usr/bin/perl -w

use strict;
use warnings;
use URI;
use Web::Scraper;
use YAML;

my $str = shift || '新宿';
my $uri = URI->new( 'http://www.bookoff.co.jp/shop/shop.php' );
$uri->query_form(
    action => 'search',
    station => $str,
    shop_name => $str,
);

warn Dump scraper {
    process '//tr[td]', 'res[]' => scraper {
        process '//td[1]', name => 'TEXT',
        process '//td[2]', time => 'TEXT',
        process '//td[3]', tel => 'TEXT',
        process '//td[4]', place => 'TEXT',
    };
    result qw/res /;
}->scrape( $uri );
Web::Scraper便利。
process書かずに
name => '//td[1]/text()'
とか書けるシンタックスシュガーあったらなぁ...とか思った。
Posted at by




既に試した方もいらっしゃるようですね。
visual_studio.vimを入れてみた - ampmmnの日記
TaskList : タスクリストの項目をquickfixに表示する。動作未確認。
Output : アウトプットの内容をquickfixに表示。動作未確認。
Solutions : これはVisualStudioを複数走らせている時に、どれと通信するかを選択するものらしい。自分の環境で実行したら、何かエラーメッセージが出力された。でも機能はしているようだ。
Projects : どのプロジェクトをアクティブ(スタートアップ)にするかを選択する。動作未確認。
http://d.hatena.ne.jp/ampmmn/20080809/1218230946
visual_studio.vim,python,unicodeencodeerror - gnarl、技術メモ
visual_studio.vimを導入してみたものの同梱pythonスクリプトのstr(name)のあたりでunicodeencodeerrorが出て困りましたね。
...
projectsメニューの一部がなぜか文字化けしますが
http://d.hatena.ne.jp/gnarl/20071012/1192181729
さまざまな言語のコメントON/OFFに対応した便利プラグイン - Seasons.NET
ただし、日本語版は、日本語エンコードに不具合があるので、アウトプット文字列が表示できないです。
http://d.hatena.ne.jp/Seasons/20070613/1181629449

もったいないので、日本語版Visual Studioでも動作する様に修正してみました。
ポイントは、DDE通信を行ってウィンドウを取得した後、ウィンドウキャプションで目的のサブウィンドウを探している所。
英語版で想定されているので、"Output"は"出力"、"Find Result 1/Find Result 2"は"検索結果 1/検索結果 2"に、"Build"は"ビルド"に修正する必要があります。
せっかくなので、vimに表示されるメニューも修正しました。見栄えはこんな感じ。
visual_studio_vim日本語版
一応、全てのメニューが動作する様にしてあります。
ちなみに、プロジェクト一覧の取得では str(dict)
を使ってvimのDictionaryに引き渡している為、ダブルクォートでないと"\xXX\xXX"なマルチバイトを解釈出来ないvimでは正しく表示されていませんでした。
今回の修正では、simplejsonを使い simplejson.dumps(obj, ensure_ascii=False).decode('utf-8').encode('mbcs')
を使うことでマルチバイトなvimのDictionary形式への変換を行っています。
ソース差分は以下の通り。
diff -cr plugin.orig/visual_studio.py plugin/visual_studio.py
*** plugin.orig/visual_studio.py    Fri Sep 28 20:51:49 2007
--- plugin/visual_studio.py Mon Aug 18 22:59:17 2008
***************
*** 1,3 ****
--- 1,4 ----
+ # -*- coding: ms932 -*-
  '''
  Companion file to visual_studio.vim
  Version 1.2
***************
*** 7,12 ****
--- 8,14 ----
  '''
  
  import os, re, sys, time, pywintypes, win32com.client
+ import simplejson
  
  import logging
  _logging_enabled = False
***************
*** 42,48 ****
          return
      # ExecuteCommand is not synchronous so we have to wait
      _dte_wait_for_build (dte)
!     dte_output (vs_pid, fn_quickfix, 'Output')
      _vim_status ('Compile file complete')
      _vim_activate ()
  
--- 44,50 ----
          return
      # ExecuteCommand is not synchronous so we have to wait
      _dte_wait_for_build (dte)
!     dte_output (vs_pid, fn_quickfix, '出力')
      _vim_status ('Compile file complete')
      _vim_activate ()
  
***************
*** 77,83 ****
          _dte_exception (e)
          _vim_activate ()
          return
!     dte_output (vs_pid, fn_quickfix, 'Output')
      _vim_status ('Build solution complete')
      _vim_activate ()
  
--- 79,85 ----
          _dte_exception (e)
          _vim_activate ()
          return
!     dte_output (vs_pid, fn_quickfix, '出力')
      _vim_status ('Build solution complete')
      _vim_activate ()
  
***************
*** 116,122 ****
          _dte_exception (e)
          _vim_activate ()
          return
!     dte_output (vs_pid, fn_quickfix, 'Output')
      _vim_status ('Build project complete')
      _vim_activate ()
  
--- 118,124 ----
          _dte_exception (e)
          _vim_activate ()
          return
!     dte_output (vs_pid, fn_quickfix, '出力')
      _vim_status ('Build project complete')
      _vim_activate ()
  
***************
*** 147,153 ****
      if not dte: return
      task_list = None
      for window in dte.Windows:
!         if str(window.Caption).startswith('Task List'):
              task_list = window
      if not task_list:
          _vim_msg ('Error: Task List window not active')
--- 149,155 ----
      if not dte: return
      task_list = None
      for window in dte.Windows:
!         if window.Caption.encode('mbcs').startswith('タスク一覧'):
              task_list = window
      if not task_list:
          _vim_msg ('Error: Task List window not active')
***************
*** 155,165 ****
      TL = task_list.Object
      for i in range (1, TL.TaskItems.Count+1):
          TLItem = TL.TaskItems.Item(i)
!         try: filename = TLItem.FileName
          except: filename = '<no-filename>'
          try: line = TLItem.Line
          except: line = '<no-line>'
!         try: description = TLItem.Description
          except: description = '<no-description>'
          print >>fp_task_list, '%s(%s) : %s' % (filename, line, description)
      fp_task_list.close ()
--- 157,167 ----
      TL = task_list.Object
      for i in range (1, TL.TaskItems.Count+1):
          TLItem = TL.TaskItems.Item(i)
!         try: filename = TLItem.FileName.encode('mbcs')
          except: filename = '<no-filename>'
          try: line = TLItem.Line
          except: line = '<no-line>'
!         try: description = TLItem.Description.encode('mbcs')
          except: description = '<no-description>'
          print >>fp_task_list, '%s(%s) : %s' % (filename, line, description)
      fp_task_list.close ()
***************
*** 170,176 ****
  
  def dte_output (vs_pid, fn_output, window_caption, notify=None):
      logging.info ('== dte_output %s' % vars())
!     if window_caption not in ['Find Results 1', 'Find Results 2', 'Output']:
          _vim_msg ('Error: unrecognized window (%s)' % window_caption)
          return
      dte = _get_dte(vs_pid)
--- 172,178 ----
  
  def dte_output (vs_pid, fn_output, window_caption, notify=None):
      logging.info ('== dte_output %s' % vars())
!     if window_caption not in ['検索結果 1', '検索結果 2', '出力']:
          _vim_msg ('Error: unrecognized window (%s)' % window_caption)
          return
      dte = _get_dte(vs_pid)
***************
*** 179,191 ****
      if not window:
          _vim_msg ('Error: window not active (%s)' % window_caption)
          return
!     if window_caption == 'Output':
!         owp = window.Object.OutputWindowPanes.Item ('Build')
          sel = owp.TextDocument.Selection
      else:
          sel = window.Selection
      sel.SelectAll()
!     lst_text = str(sel.Text).splitlines()
      lst_text = _fix_filenames (os.path.dirname(dte.Solution.FullName), lst_text)
      sel.Collapse()
      fp_output = file (fn_output, 'w')
--- 181,193 ----
      if not window:
          _vim_msg ('Error: window not active (%s)' % window_caption)
          return
!     if window_caption == '出力':
!         owp = window.Object.OutputWindowPanes.Item ('ビルド')
          sel = owp.TextDocument.Selection
      else:
          sel = window.Selection
      sel.SelectAll()
!     lst_text = str(sel.Text.encode('mbcs')).splitlines()
      lst_text = _fix_filenames (os.path.dirname(dte.Solution.FullName), lst_text)
      sel.Collapse()
      fp_output = file (fn_output, 'w')
***************
*** 280,286 ****
              startup_project_index = index
          lst_result.append (_dte_project_tree(project))
          index += 1
!     _vim_command ('let s:visual_studio_lst_project = %s' % lst_result)
      _vim_command ('let s:visual_studio_startup_project_index = %s' % startup_project_index)
  
  def _dte_project_tree (project):
--- 282,288 ----
              startup_project_index = index
          lst_result.append (_dte_project_tree(project))
          index += 1
!     _vim_command ('let s:visual_studio_lst_project = %s' % simplejson.dumps(lst_result, ensure_ascii=False).decode('utf-8').encode('mbcs'))
      _vim_command ('let s:visual_studio_startup_project_index = %s' % startup_project_index)
  
  def _dte_project_tree (project):
***************
*** 290,296 ****
      name = _com_property (project, 'Name')
      if not name:
          return []
!     name = str(name)
      properties = _com_property(project, 'Properties')
      if properties:
          try: full_path = str(properties['FullPath'])
--- 292,298 ----
      name = _com_property (project, 'Name')
      if not name:
          return []
!     name = name.encode('utf-8')
      properties = _com_property(project, 'Properties')
      if properties:
          try: full_path = str(properties['FullPath'])
***************
*** 441,447 ****
  def _dte_output_activate (vs_pid):
      dte = _get_dte(vs_pid)
      if not dte: return
!     window = _dte_get_window(dte, 'Output')
      if not window: return
      window.Activate()
  
--- 443,449 ----
  def _dte_output_activate (vs_pid):
      dte = _get_dte(vs_pid)
      if not dte: return
!     window = _dte_get_window(dte, '出力')
      if not window: return
      window.Activate()
  
diff -cr plugin.orig/visual_studio.vim plugin/visual_studio.vim
*** plugin.orig/visual_studio.vim   Thu Sep 27 05:57:47 2007
--- plugin/visual_studio.vim    Tue Aug 19 09:07:25 2008
***************
*** 226,232 ****
  
  function! DTEOutput()
      let &errorfile = g:visual_studio_output
!     call <Sid>DTEExec ('dte_output', &errorfile, 'Output')
  endfunction
  
  "----------------------------------------------------------------------
--- 226,232 ----
  
  function! DTEOutput()
      let &errorfile = g:visual_studio_output
!     call <Sid>DTEExec ('dte_output', &errorfile, '出力')
  endfunction
  
  "----------------------------------------------------------------------
***************
*** 234,243 ****
  function! DTEFindResults(which)
      if a:which == 1
          let &errorfile = g:visual_studio_find_results_1
!         let window_caption = 'Find Results 1'
      else
          let &errorfile = g:visual_studio_find_results_2
!         let window_caption = 'Find Results 2'
      endif
      call <Sid>DTEExec ('dte_output', &errorfile, window_caption)
  endfunction
--- 234,243 ----
  function! DTEFindResults(which)
      if a:which == 1
          let &errorfile = g:visual_studio_find_results_1
!         let window_caption = '検索結果 1'
      else
          let &errorfile = g:visual_studio_find_results_2
!         let window_caption = '検索結果 2'
      endif
      call <Sid>DTEExec ('dte_output', &errorfile, window_caption)
  endfunction
***************
*** 299,305 ****
      endif
      if gui_menu
          echo 'Found '.len(s:visual_studio_lst_dte).' VisualStudio instance(s)'
!         popup! VisualStudio.Solutions
      else
          call <Sid>DTESolutionTextMenu()
      endif
--- 299,305 ----
      endif
      if gui_menu
          echo 'Found '.len(s:visual_studio_lst_dte).' VisualStudio instance(s)'
!         popup! VisualStudio.ソリューション(&S)
      else
          call <Sid>DTESolutionTextMenu()
      endif
***************
*** 307,313 ****
  
  function! <Sid>DTESolutionGuiMenuCreate()
      try
!         aunmenu VisualStudio.Solutions
      catch
      endtry
      let menu_num = 0
--- 307,313 ----
  
  function! <Sid>DTESolutionGuiMenuCreate()
      try
!         aunmenu VisualStudio.ソリューション(&S)
      catch
      endtry
      let menu_num = 0
***************
*** 320,331 ****
          else
              let leader = '\ \ \ &'.menu_num
          endif
!         exe 'amenu <silent> .810 &VisualStudio.&Solutions.'.leader.'\ '.dte_sln.' :call <Sid>DTESolutionMenuChoice('.menu_num.')<cr>'
      endfor
      if len(s:visual_studio_lst_dte) > 0
!         amenu <silent> &VisualStudio.&Solutions.-separator- :
      endif
!     amenu <silent> &VisualStudio.&Solutions.&Refresh :call DTEGetSolutions(1)<cr>
  endfunction
  
  function! <Sid>DTESolutionTextMenu()
--- 320,331 ----
          else
              let leader = '\ \ \ &'.menu_num
          endif
!         exe 'amenu <silent> .810 &VisualStudio.ソリューション(&S).'.leader.'\ '.dte_sln.' :call <Sid>DTESolutionMenuChoice('.menu_num.')<cr>'
      endfor
      if len(s:visual_studio_lst_dte) > 0
!         amenu <silent> &VisualStudio.ソリューション(&S).-separator- :
      endif
!     amenu <silent> &VisualStudio.ソリューション(&S).更新(&R) :call DTEGetSolutions(1)<cr>
  endfunction
  
  function! <Sid>DTESolutionTextMenu()
***************
*** 393,399 ****
      endif
      if gui_menu
          echo 'Found '.len(s:visual_studio_lst_project).' project(s)'
!         popup! VisualStudio.Projects
      else
          call <Sid>DTEProjectTextMenu()
      endif
--- 393,399 ----
      endif
      if gui_menu
          echo 'Found '.len(s:visual_studio_lst_project).' project(s)'
!         popup! VisualStudio.プロジェクト(&J)
      else
          call <Sid>DTEProjectTextMenu()
      endif
***************
*** 401,407 ****
  
  function! <Sid>DTEProjectGuiMenuCreate()
      try
!         aunmenu VisualStudio.Projects
      catch
      endtry
      let menu_num = 0
--- 401,407 ----
  
  function! <Sid>DTEProjectGuiMenuCreate()
      try
!         aunmenu VisualStudio.プロジェクト(&J)
      catch
      endtry
      let menu_num = 0
***************
*** 414,422 ****
          else
              let leader = '\ \ \ &'.menu_num
          endif
!         let project_name_menu = '&VisualStudio.Pro&jects.'.leader.'\ '.escape(project_name, '\. ')
!         exe 'amenu <silent> .820 '.project_name_menu.'.&Build\ Project :call <Sid>DTEProjectMenuBuildChoice('.menu_num.')<cr>'
!         exe 'amenu <silent> .820 '.project_name_menu.'.Set\ Start&up\ Project :call <Sid>DTEProjectMenuStartupChoice('.menu_num.')<cr>'
          exe 'amenu <silent> .820 '.project_name_menu.'.-separator- :<cr>'
          if type(project_children) == type([])
              for child in project_children
--- 414,422 ----
          else
              let leader = '\ \ \ &'.menu_num
          endif
!         let project_name_menu = '&VisualStudio.プロジェクト(&J).'.leader.'\ '.escape(project_name, '\. ')
!         exe 'amenu <silent> .820 '.project_name_menu.'.プロジェクトをビルド(&B) :call <Sid>DTEProjectMenuBuildChoice('.menu_num.')<cr>'
!         exe 'amenu <silent> .820 '.project_name_menu.'.スタートアッププロジェクトに設定(&U) :call <Sid>DTEProjectMenuStartupChoice('.menu_num.')<cr>'
          exe 'amenu <silent> .820 '.project_name_menu.'.-separator- :<cr>'
          if type(project_children) == type([])
              for child in project_children
***************
*** 425,433 ****
          endif
      endfor
      if len(s:visual_studio_lst_project) > 0
!         amenu <silent> .820 &VisualStudio.Pro&jects.-separator- :
      endif
!     amenu <silent> .820 &VisualStudio.Pro&jects.&Refresh :call DTEGetProjects(1, 1)<cr>
  endfunction
  
  function! <Sid>DTEProjectGuiSubMenuCreate(menu, name, value)
--- 425,433 ----
          endif
      endfor
      if len(s:visual_studio_lst_project) > 0
!         amenu <silent> .820 &VisualStudio.プロジェクト(&J).-separator- :
      endif
!     amenu <silent> .820 &VisualStudio.プロジェクト(&J).更新(&R) :call DTEGetProjects(1, 1)<cr>
  endfunction
  
  function! <Sid>DTEProjectGuiSubMenuCreate(menu, name, value)
***************
*** 510,526 ****
  " Menu setup
  
  if has('gui') && ( ! exists('g:visual_studio_menu') || g:visual_studio_menu != 0 )
!     amenu <silent> &VisualStudio.&Get\ File :call DTEGetFile()<cr>
!     amenu <silent> &VisualStudio.&Put\ File :call DTEPutFile()<cr>
      amenu <silent> &VisualStudio.-separator1- :
!     amenu <silent> &VisualStudio.&Task\ List :call DTETaskList()<cr>
!     amenu <silent> &VisualStudio.&Output :call DTEOutput()<cr>
!     amenu <silent> &VisualStudio.&Find\ Results\ 1 :call DTEFindResults(1)<cr>
!     amenu <silent> &VisualStudio.Find\ Results\ &2 :call DTEFindResults(2)<cr>
      amenu <silent> &VisualStudio.-separator2- :
!     amenu <silent> &VisualStudio.&Build\ Solution :call DTEBuildSolution()<cr>
!     amenu <silent> &VisualStudio.Build\ Start&up\ Project :call DTEBuildStartupProject()<cr>
!     amenu <silent> &VisualStudio.&Compile\ File :call DTECompileFile()<cr>
      amenu <silent> &VisualStudio.-separator3- :
      call <Sid>DTESolutionGuiMenuCreate()
      call <Sid>DTEProjectGuiMenuCreate()
--- 510,526 ----
  " Menu setup
  
  if has('gui') && ( ! exists('g:visual_studio_menu') || g:visual_studio_menu != 0 )
!     amenu <silent> &VisualStudio.ファイルを取得(&G) :call DTEGetFile()<cr>
!     amenu <silent> &VisualStudio.ファイルを反映(&P) :call DTEPutFile()<cr>
      amenu <silent> &VisualStudio.-separator1- :
!     amenu <silent> &VisualStudio.タスクリスト(&T) :call DTETaskList()<cr>
!     amenu <silent> &VisualStudio.出力(&O) :call DTEOutput()<cr>
!     amenu <silent> &VisualStudio.検索結果\ 1(&F) :call DTEFindResults(1)<cr>
!     amenu <silent> &VisualStudio.検索結果\ 2(&2) :call DTEFindResults(2)<cr>
      amenu <silent> &VisualStudio.-separator2- :
!     amenu <silent> &VisualStudio.ソリューションをビルド(&B) :call DTEBuildSolution()<cr>
!     amenu <silent> &VisualStudio.スタートアッププロジェクトをビルド(&U) :call DTEBuildStartupProject()<cr>
!     amenu <silent> &VisualStudio.ファイルをコンパイル(&C) :call DTECompileFile()<cr>
      amenu <silent> &VisualStudio.-separator3- :
      call <Sid>DTESolutionGuiMenuCreate()
      call <Sid>DTEProjectGuiMenuCreate()
Visual StudioつまりWindows限定なのでファイルの文字コードはms932としました。
動作確認はVisual Studio 2005でしか行っていません。
visual_studio_ja-20080819.zip
よろしければどうぞ。
Posted at by



2008/08/06


以前試した時は出来なかったんですが、今日試したら動く様になっていました。
growl-for-windows - Google Code

A port of the Mac app Growl for use on Windows machines

http://code.google.com/p/growl-for-windows/
バージョンが1.1から1.2に上がったからかな?
Growl for Windows 1.2
以下のコードで動きました。
まずperl
use strict;
use warnings;
use Encode;
use Net::Growl;
register(host => 'localhost',
         application=>"My Perl App",
         password=>'Realy Secure', );
notify(
       application=>"My Perl App",
       title=>'warning',
       description=>decode_utf8('あめんぼ赤いなアイウエオ'),
       priority=>2,
       sticky=>0,
       password=>'Realy Secure',
);
そしてpython
#!/usr/bin/python
#-*- coding:utf-8 -*-
import Growl
g = Growl.GrowlNotifier(
    applicationName='My Python App',
    notifications=["PyGrowl"],
    defaultNotifications=[0],
    hostname="localhost",
    password="Realy Secure")
g.register()
g.notify(
    icon=open('unk.gif').read(),
    noteType="PyGrowl",
    title='wanings',
    description=u"あめんぼ赤いなアイウエオ",
    sticky=False)
あれ?1.1の時にもdecode_utf8とかu""とか試したんですけどねぇ...。やっぱり1.2になったから?

それと今日、whineというWindowsで動くGrowlアプリケーションを、某カレー通の方に教えて頂きました。ありがとうございました。
Whine
Growl for Windowsではフォント等、ディスプレイのカスタマイズが出来ないのですがwhineでは出来るので、こちらを使おうかと思います。
猫派の私ですが、これはお勧めです。
Posted at by




家では貧弱なマシンを使っているので、極力重い処理は避けたいと色んな設定を入れています。その一つにperlのファイルを開いた際に"ftplugin/perl.vim"がINCを調べるのに実行する perl -e 'print join(q/,/,@INC)'
というコマンドの抑制。ただ単にperlのモジュールパスを調べるいるだけなんですが、ファイルを開くだけでperlを実行されるのも...という方には以下の設定をvimrcに追加すると実行されなくなります。
let g:perlpath="XXX"
このXXXには上記コマンドの実行結果を設定します。
Windows系ならば perl -e "print join(q/,/,@INC)"
で得られる文字列となります。ActivePerlだとおそらく let g:perlpath = "c:/perl/site/lib,C:/perl/lib"
と設定すれば良いかと思います。

ま、最近の人はリッチなマシン使ってる人多いから、メリット無いかな。
ちなみにUNIX系でperlのバージョン上げたりするとモジュールパスが変りますので再度この設定をし直す必要があります。ご注意を。
Posted at by



2008/08/05


途中まで書いて助けを求めたんですが、結局自分で書きました。
CodeRepos::Share - Trac

mattn誰か後は頼んだ... ゴブッ(吐血)

http://coderepos.org/share/changeset/17104
このリンク先のソースは不完全なソースです。

使い方は
:mixiecho
でエコーの一覧表示
:mixiecho ○○遺跡に落書きした!
でポストです。

これでtwitterの様にmixiを使って、マイミク外される事うけあいですね。
mixiecho.js
よかったらどうぞ。
i love vimperator!
※ teramakoさんからi love vimperatorの画像頂きました。
Posted at by




perl版もあったんですね。
Perl App Engine状況報告、Protocol BufferのPerl対応 | エンタープライズ | マイコミジャーナル

Perl App Engineに関連したコードベースにはおもに次の3つがある。

  • Perl App Engine
  • Perl XS module Sys::Protect
  • Protocol Buffers for Perl
http://journal.mycom.co.jp/news/2008/07/29/042/index.html

protobuf-perl - Google Code

Protocol Buffers for Perl.

http://code.google.com/p/protobuf-perl/
さっそく遊んでみました。
まず、protobuf-perlはオリジナルの改造として作られており、スケルトンクラス生成ツール「protoc」をビルドする所からの導入となります。
通常はprotobufディレクトリで # make -j2 protoc
とすれば出来上がります。ただVisual Studioの場合はlibprotocプロジェクトのソース一覧からperlのgeneratorソースである「perl_generator.cc」が外れてしまっているので、追加してからビルドする必要があります。
出来上がれば、「libprotobuf.dll」と「libprotoc.dll」、「protoc.exe」をパスの通った位置にコピーします。
"main.cc"のソースを見て頂ければ分かりますが、protocol buffersのgeneratorはソースが分離されており、main実行時にプラグインを読み込む様な形で登録されています。 int main(int argc, char* argv[]) {

  google::protobuf::compiler::CommandLineInterface cli;

  // Proto2 C++
  google::protobuf::compiler::cpp::CppGenerator cpp_generator;
  cli.RegisterGenerator("--cpp_out", &cpp_generator,
                        "Generate C++ header and source.");

  // Proto2 Java
  google::protobuf::compiler::java::JavaGenerator java_generator;
  cli.RegisterGenerator("--java_out", &java_generator,
                        "Generate Java source file.");


  // Proto2 Python
  google::protobuf::compiler::python::Generator py_generator;
  cli.RegisterGenerator("--python_out", &py_generator,
                        "Generate Python source file.");


  // Proto2 Perl
  google::protobuf::compiler::perl::Generator perl_generator;
  cli.RegisterGenerator("--perl_out", &perl_generator,
                        "Generate Perl source file.");

  return cli.Run(argc, argv);
}
別の言語でgeneratorを作る場合、"XXX_generator.h"と"XXX_generator.cc"を作り、"main.cc"でincludeとRegisterGeneratorを実行すれば動き出す仕組みになっています。キレイな作りですね。

さて出来上がった"protoc"でperlのラッパクラスを作ります。
先日ご紹介した際に使った"person.proto"を使います。ここで注意しなければならないのが、"--perl_out"オプションを使用する際の引数で指定するファイル名がパッケージ名として使われてしまう点です。
perlパッケージ名称がそれっぽくなる様に以下の様に実行します。
# protoc --perl_out=. Person.proto UNIX系の方は"person.proto"から"Person.proto"にリネームしてから実行して下さい。Windowsならばそのまま実行出来ます。
出来上がった"ProtoBuf::Person"は以下の様になりました。
## Boilerplate:
# Auto-generated code from the protocol buffer compiler.  DO NOT EDIT!

use strict;
use warnings;
#use 5.6.1;
use Protobuf;
package ProtoBuf::Person;


use constant TRUE => 1;
use constant FALSE => 0;
## Top-level enums:

## Top-level extensions:

## All nested enums:
## Message descriptors:

our $_PERSON = Protobuf::Descriptor->new(
  name => 'Person',
  full_name => 'protocol.Person',
  containing_type => undef,
  fields => [
    Protobuf::FieldDescriptor->new(
      name => 'name', index => 0, number => 1,
      type => 9, cpp_type => 9, label => 2,
      default_value => "",
      message_type => undef, enum_type => undef, containing_type => undef,
      is_extension => FALSE, extension_scope => undef),
    Protobuf::FieldDescriptor->new(
      name => 'age', index => 1, number => 2,
      type => 5, cpp_type => 1, label => 2,
      default_value => 0,
      message_type => undef, enum_type => undef, containing_type => undef,
      is_extension => FALSE, extension_scope => undef),
  ],
  extensions => [
  ],
  nested_types => [],  # TODO(bradfitz): Implement.
  enum_types => [
  ],
  options => Protobuf::MessageOptions->new(
  ),
);

## Imports:

## Fix foreign fields:

## Messages:
Protobuf::Message->GenerateClass(__PACKAGE__ . '::Person', $_PERSON);

## Fix foreign fields in extensions:
## Services:
実装はMooseを使っており、アクセサに対する制御も行っています。
次にサンプルコード
use strict;
use warnings;
no warnings qw(deprecated);
use Protobuf::Decoder;
use ProtoBuf::Person;

my $person = ProtoBuf::Person::Person->new;
$person->set_name('mattn');
$person->set_age(18);

open my $out, '>', 'person_perl.txt';
print $out $person->serialize_to_string();
close $out;

my $other = ProtoBuf::Person::Person->new;
open my $in, '<', 'person_perl.txt';
$other->parse_from_string( do { local $/;<$in> } );
close $in;

printf "name:%s\nage:%d\n", $other->name(), $other->age();
前回と同様にファイルに書き出し、ファイルから読み込んでparse_from_stringで実体化します。結果は前回と同様です。

cppは別として、pythonの場合はpickleが、javaの場合はSerializableがあり、Google Protocol Buffersの使い所が難しい気もしましたが、色々な言語がサポートされてくると言語をまたいだデータ共有という形で使えそうな気がして来ました。特にmemcachedを使ったダイナミックインスタンスエクスポートとか面白いかもしれませんね。
またperl版がMooseと絡んでいる所がとても通ぽくて良いですね。:-)
どうせなら、PerlIOでシリアライズ出来たらな...と思ってしまいましたが、もしかしたら今後サポートされるかもしれませんね。

他にもprotocol buffersはいろんな言語でインプリメンツされているので、皆さんもお好きな言語で遊んでみてはいかがでしょうか。
Posted at by



2008/08/04


vimではコマンドモード時に、<c-x>で現在のディレクトリを補完するようにしているので、これがvimperatorでもやれると便利と思った。
twitter.jsでは「%URL%」とか「%TITLE%」で現在のURLが置き換えられる様になってるけど、他のコマンドでも使いたい場合もある。
例えば、そろそろ誰かが「mixiecho」ってコマンド作ったとして :mixiecho ちょっwwwコレ http://example.jp/ とかやりたい時には、またtwitter.jsと同じ実装しなきゃいけない。
ま、こんなので困るのは私だけかも。
(function() {
    liberator.mappings.addUserMap([liberator.modes.COMMAND_LINE], ['<c-x>'],
        "insert current URL to command line",
        function () {
            var cmdline = liberator.CommandLine();
            var curcmd = ':' + cmdline.getCommand();
            if (!curcmd.match(/ $/)) curcmd += ' ';
            cmdline.open(curcmd, liberator.buffer.URL);
        }
    );
})();
コマンドラインのコントロール名は決まっているので、そこにkeyEventをdispatchEventしても良かったけど、まっいいや。
Posted at by