Just another Ruby porter,

〜2014年6月中旬〜


<Older(,) | Newer(.)> | Recent(/)>> | RDF

2014-06-11 (Wed)

Ten Count

dcだよなと思ったが、seqで攻めた。最初は

read n;seq $n $[n+9]

としていたが、苦肉の策で1バイト縮めた。

seq $[{n=`dd`,n+9}]

これはzshで動かない。bashは先に{}を展開するがzshはどうも展開しないようで。
つまりbashでは

seq $[n=`dd`] $[n+9]

と書いたのと同じ。一見

seq $[`dd`{,+9}]

でいいんじゃないかと思えるが、これは

seq $[`dd`] $[`dd`+9]

と展開されるのでだめ。``の評価のほうが後になる。

% echo 1 | bash -c 'seq $[{n=`dd`,n+9}]'
0+1 records in
0+1 records out
2 bytes (2 B) copied, 0.000137874 s, 14.5 kB/s
1
2
3
4
5
6
7
8
9
10
% echo 1 | zsh -c 'seq $[{n=`dd`,n+9}]'
0+1 records in
0+1 records out
2 bytes (2 B) copied, 0.000134562 s, 14.9 kB/s
zsh:1: bad math expression: illegal character: {

というわけで、zshのほうが1バイト多い。
dcを使っても?をquoteしなきゃいけなくて1バイト差が出てるのが面白い。


2014-06-12 (Thu)

flip flop

よく見かけるchopとflip flopの組み合わせ。

-chop ${LEFT}x${TOP} -flip -flop \
-chop ${RIGHT}x${BOTTOM} -flip -flop \

同じ-chopなのにこれはどういうことなのか。
flip flopってなんだっけと調べたらflipが上下反転、flopが左右反転。

% convert label:abc -flip x:
% convert label:abc -flop x:

とすると確認できる。つまり意味的には

-chop ${LEFT}x${TOP} \
-flip -flop -chop ${RIGHT}x${BOTTOM} -flip -flop \

なんだな。上下左右を反転させることで左上と右下が入れ替わる。
だから左上しか指定できない-chopが使えると。ということは180度回転でもいいわけだ。

-chop ${LEFT}x${TOP} \
-rotate 180 -chop ${RIGHT}x${BOTTOM} -rotate 180 \

kindlizeは-gravityを使ってるようだ。賢い。

-chop #{LEFT}x#{TOP} \
-gravity SouthEast -chop #{RIGHT}x#{BOTTOM}\
-gravity NorthWest

2014-06-13 (Fri)

optipngでpipe

convertした結果をそのままpipeでoptipngに渡したいなんてことを考えてみたが受けつけてくれない。
むりやり/dev/stdinを使っても

% convert in.jpg png8:- | optipng -out out.png /dev/stdin 
** Processing: /dev/stdin
Error: Can't ftell in input file stream

** Status report
1 file(s) have been processed.
1 error(s) have been encountered.

と言われてしまう。<()を使っても同じだ。

% optipng -out out.png <(convert in.jpg png8:-)
** Processing: /proc/self/fd/11
Error: Can't ftell in input file stream

** Status report
1 file(s) have been processed.
1 error(s) have been encountered.

どっちしてもseekできないとだめってことなので、ファイルにせざるを得ない。

zshなら=()にすればいける。

% optipng -out out.png =(convert in.jpg png8:-)
** Processing: /tmp/zsh1oY1na
200x200 pixels, 8 bits/pixel, 182 colors in palette
Reducing image to 8 bits/pixel, grayscale
Input IDAT size = 2110 bytes
Input file size = 2938 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 1804
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 1723

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 1723

Output file: out.png

Output IDAT size = 1723 bytes (387 bytes decrease)
Output file size = 1994 bytes (944 bytes = 32.13% decrease)

/tmp/zsh1oY1naと表示されているように一時ファイルを作ってくれる。
=()って何のためにあるのかと思ったが、こういうときのためにあるんだな。


2014-06-14 (Sat)

printf %04sの違い

ipv6がどうのこうの。

% zsh -c 'printf "%04s\n" "ab"'
  ab
% bash -c 'printf "%04s\n" "ab"' 
  ab
% /usr/bin/printf "%04s\n" "ab" 
/usr/bin/printf: %04s: 無効な変換指定です
zsh: exit 1     /usr/bin/printf "%04s\n" "ab"
% ruby -e 'printf("%04s\n", "ab")' 
  ab
% ruby -e 'printf("%04s\n", "ab")' 
  ab
% awk 'BEGIN{printf("%04s\n", "ab")}'  
  ab
% python -c 'print "%04s" % "ab"'
  ab
% perl -e 'printf("%04s\n", "ab")' 
00ab

Perlだけ気が利いている。Rubyなら

% ruby -e 'puts "ab".rjust(4, "0")'
00ab

という手もあるが。


2014-06-15 (Sun)

convertのshave

chopを2回しなくてもshaveなんてオプションがあった。
しかしこれは左と右、上と下は同じ量だけ削られる。別々に指定できない。
-shave 20x10と書いた場合、左右は両方とも20、上下は両方とも10削られる。
スキャンした結果だとそんな都合よく対称にはならないのでなかなか使いづらそう。


2014-06-16 (Mon)

古いsqlite3のソース

sqliteのダウンロードページに行っても3.7あたりの古いソースはもう見当たらない。
以前は http://www.sqlite.org/sqlite-3.7.2.tar.gz とすごいところに置いてあったので、
直接指定してみたらまだあった。3.6.23もあった。


2014-06-17 (Tue)

convertで偶数奇数処理

以前横向きでスキャンした画像を 90度回転して元に戻す処理を書いた。
シェルスクリプトなのでwindowsだと使えないが、
convertにはfxがあるのでその処理を吐かせればいいんだと気づいた。

% convert 00?.png -format "convert %f -rotate %[fx:t%2?90:-90] -verbose /tmp/%f" info:
convert 001.png -rotate -90 -verbose /tmp/001.png
convert 002.png -rotate 90 -verbose /tmp/002.png
convert 003.png -rotate -90 -verbose /tmp/003.png
convert 004.png -rotate 90 -verbose /tmp/004.png
convert 005.png -rotate -90 -verbose /tmp/005.png
convert 006.png -rotate 90 -verbose /tmp/006.png
convert 007.png -rotate -90 -verbose /tmp/007.png
convert 008.png -rotate 90 -verbose /tmp/008.png
convert 009.png -rotate -90 -verbose /tmp/009.png

fx内のtは画像リストのインデックス(0から)になっている。
Cでお馴染の?:も使えるので偶数奇数で-90度/90度と回転させればいい。
これをリダイレクトしてバッチにすればwindowsでも実行可能だ。
Linuxでもこのままshに食わせてもいいが、parallelに食わせると時短になる。

% convert 00?.png -format "convert %f -rotate %[fx:t%2?90:-90] -verbose /tmp/%f" info: | parallel
002.png=>/tmp/002.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit DirectClass 41KB 0.090u 0:00.100
003.png=>/tmp/003.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 90.1KB 0.110u 0:00.119
004.png=>/tmp/004.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 41KB 0.170u 0:00.169
005.png=>/tmp/005.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 32.8KB 0.080u 0:00.079
007.png=>/tmp/007.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 41KB 0.090u 0:00.079
006.png=>/tmp/006.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 45.1KB 0.190u 0:00.190
001.png=>/tmp/001.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit DirectClass 1.38MB 0.330u 0:00.339
009.png=>/tmp/009.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 45.1KB 0.080u 0:00.070
008.png=>/tmp/008.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 32.8KB 0.170u 0:00.179

xargsは引数を省略すると/bin/echoを呼ぶが、parallelは実行する。ここが大きな違い。

% convert 00?.png -format "convert %f -rotate %[fx:t%2?90:-90] -verbose /tmp/%f" info: | xargs -P5 -I@ sh -c @
003.png=>/tmp/003.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 90.1KB 0.110u 0:00.150
005.png=>/tmp/005.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 32.8KB 0.080u 0:00.169
002.png=>/tmp/002.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit DirectClass 41KB 0.080u 0:00.159
007.png=>/tmp/007.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 41KB 0.090u 0:00.080
006.png=>/tmp/006.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 45.1KB 0.180u 0:00.219
004.png=>/tmp/004.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 41KB 0.170u 0:00.449
009.png=>/tmp/009.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 45.1KB 0.090u 0:00.119
008.png=>/tmp/008.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit PseudoClass 255c 32.8KB 0.170u 0:00.260
001.png=>/tmp/001.png PNG 1081x714=>714x1081 714x1081+0+0 8-bit DirectClass 1.38MB 0.310u 0:00.519

とすればxargsでもパラで実行可能。


2014-06-18 (Wed)

postfixやめてmsmtpを

使い始めたはいいが、local mailが届かなくなって困った。
SMTP clientなんだから当たり前なんだけど、
そのためにlocalでSMTP server立てるんじゃ意味ないしねえ。
local mailと言ってもcronの結果ぐらいでいいんだけど。
しかたないので~/.msmtprcで

aliases ~/etc/aliases

として、~/etc/aliasesで

eban: gmailアドレス

とした。crontabでなにか吐かれるとそっちに飛ぶ。


2014-06-19 (Thu)

Rainlendar

Rainlendarがicsを読み込んでくれるので、
これをタスクスケジューラで30分おきに動かすといい感じ同期できる。
ただ、場所情報がないのが痛い。これだけのためにoutlookを起動しないといけない。
AppointmentItem Members (Outlook)を見るとLocationで取れそうだし、他にも情報を入れられそう。
ただVBSだけにちょっといじりにくい。
Rubyのwin32oleでいけるのか?


2014-06-20 (Fri)

OutlookからiCalendarを吐くRubyスクリプト

結局Rubyで書いた。

#! /usr/bin/ruby
# -*- coding: utf-8 -*-

require 'win32ole'
require 'date'

olFolderCalendar = 9
WIN32OLE.codepage = WIN32OLE::CP_UTF8
ol =
  begin
    WIN32OLE.connect("Outlook.Application")
  rescue
    WIN32OLE.new("Outlook.Application")
  end

items = ol.Session.GetDefaultFolder(olFolderCalendar).Items
items.Sort "[Start]"
items.IncludeRecurrences = true
now = Time.now
seven = now + 7 * 24 * 60 * 60
body = <<'EOT'
BEGIN:VCALENDAR

BEGIN:VTIMEZONE
TZID:Asia/Tokyo
BEGIN:STANDARD
TZOFFSETFROM:+0900
TZOFFSETTO:+0900
TZNAME:JST
DTSTART:19700101T000000
END:STANDARD
END:VTIMEZONE

EOT
count = 0
STATUS_VALUES = ["CANCELLED", "TENTATIVE", "CONFIRMED"]
filter =
  "[Start] >= '#{now.strftime("%Y/%m/%d %H:%M")}'" +
  " AND [End] <= '#{seven.strftime("%Y/%m/%d")}'" +
  " AND [BusyStatus] > 0"
e = items.Find(filter)
while e
  valarm = 1 < e.BusyStatus && now < e.Start ? <<'EOT' : ""
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER;VALUE=DURATION:-PT5M
END:VALARM
EOT
  body << <<"EOT"
BEGIN:VEVENT
UID:#{count+=1}
SUMMARY:#{e.Subject} [#{STATUS_VALUES[e.BusyStatus][0,2]}]
DTSTART;TZID=Asia/Tokyo:#{e.Start.strftime("%Y%m%dT%H%M%S")}
DTEND;TZID=Asia/Tokyo:#{e.End.strftime("%Y%m%dT%H%M%S")}
LOCATION:#{e.Location}
STATUS:#{STATUS_VALUES[e.BusyStatus]}
#{valarm}END:VEVENT

EOT
  e = items.FindNext
end
body << "END:VCALENDAR\n"
ARGV[0] ? IO.write(ARGV[0], body) : puts(body)

最初はicalendar gemを使ったけど、やたらと遅いのでもう直接展開することにした。
WIN32OLE.codepage = WIN32OLE::CP_UTF8とするとutf-8で処理できる。
これはfilterの中身とかもutf-8で書けるので便利。

  " AND [Subject] <> '昼休み'" +

のようにすれば表示したくない処理も簡単に追加できる。

  " AND [BusyStatus] > 0"

はキャンセルした予定はうっとしいので表示しないという意味。
あと一律5分前にアラーム設定。これで結構いい感じで使えるようになった。


<Older(,) | Newer(.)> | Recent(/)>> | RDF


WWW を検索 jarp.does.notwork.org を検索

わたなべひろふみ
Key fingerprint = C456 1350 085F A320 C6C8 8A36 0F15 9B2E EB12 3885
Valid HTML 4.01!