少し前に、"ɹəʇʇɪʍʇ"のような反転文字ツイートが粋だと聞いたわたしは、この流行に乗り遅れまいと直ぐに「flippy」という反転文字を出力するツールをRubyで作りました。そして、愛用のtermtterから時々、"¡ʎqnᴚ ɥʇᴉʍ ɓuᴉʞɔɐH ʎddɐH"などとタイムラインに流して一人悦に入っていたのでした。
ところが気がつくと反転文字の流行はとうに終わっていて、今度は「縦書きツイート」が流行の兆しを見せているようなのです。
Ruby使いたる者、流行に乗り遅れるわけにはいきませんよね。「縦つい。」が必要なら「縦つい。」するツールをRubyで作ればいいのです。
そんなわけで...
flippyに縦書きを実現するFlippy#vertical
を追加しましたので、お知らせいたします :-)
gem i flippy
してflippyをrequireすると、StringにFlippyモジュールがincludeされますので、文字列に対してvertical
メソッドを呼んで下さい。
require "flippy"
str = <<EOS
春はあけぼの、
夏は夜。
秋は夕暮れ、
冬はウィンター。
EOS
puts str.vertical
# >> 冬 秋 夏 春
# >> は は は は
# >> ウ 夕 夜。あ
# >> ィ 暮 け
# >> ン れ、 ぼ
# >> タ の、
# >> |。
flippyコマンドに-v
(または–vertical)オプションを追加しました。flippy -v [string]
のように使います。文字列中の全角または半角スペースが改行として解釈されます。
% flippy -v 春はあけぼの、 夏は夜。 秋は夕暮れ、 冬はウィンター。
冬 秋 夏 春
は は は は
ウ 夕 夜。あ
ィ 暮 け
ン れ、 ぼ
タ の、
|。
これをお使いのTwitterクライアントにコピペすれば「縦つい。」できます。
version 0.1.0で、文字列中の++
以降の文字列を横書きとする仕様を導入しました。
% flippy -v "つまづいたって いいじゃ ないか にんげんだ もの++ みつを #mitsuo"
も に な い つ
の ん い い ま
げ か じ づ
ん ゃ い
だ た
っ
て みつを #mitsuo
++
が複数あるときは最後のもの以降が対象になります。すべての++をエスケープしたいときは文末に++を入れて下さい。
なお、flippyの他の使い方については、以下の記事を参考にしてください。
基本的に複数行からなる文字列を二次元配列に入れて転置してjoin-reverseして終わりです。RubyにはArray#transposeというステキなメソッドがあるので転置は一発です。
ただ、前処理がちょっと面倒です。1つは向きの変換が必要な文字群の処理で、これはString#trを使って互換文字に置き換えます。
それから句読点の処理です。「縦つい。」では句読点は直前文字の右側に配置されているのでこれに倣いました。つまり各行の右側は空行になっていて句読点がある場合はここに配置されます。(削除) この処理のため、各行を複製し一方を句読点を除いた行、他方を句読点のみの行に置換する処理をしています。ただし行の先頭文字が句読点の場合はこの限りではないので、先頭文字は対象外とします。 (削除ここまで)(文中の句読点後の空白を除くよう実装を変更しました)
Flippy#verticalの該当コードをここに貼っておきます。(削除) ちなみに今回の実装での個人的Tipsは(String#fillを使う実装に変更しました。thanks to @no6vさん)Array.new(size,val).tap{ Array#[nth]=val }
です。 (削除ここまで)
module Flippy::Vertical
PUNC = ["、","。",",","."]
SYM = {
"ー" => "|",
"「" => "¬",
"」" => "∟",
"→" => "↓",
"↑" => "→",
"←" => "↑",
"↓" => "←",
"=" => "॥",
"..." => ":"
}
SYM1 = (SYM.keys + SYM.values).join
SYM2 = (SYM.values + SYM.keys).join
def vertical
lines = []
self.tr(SYM1, SYM2)
.each_line { |line|
line.chomp!
top = line[0] || ""
rest = line[1..-1] || ""
lines << rest.gsub(/[^#{PUNC.join}]/, ' ')
lines << top + rest.gsub(/#{PUNC.join("|")}/, '')
}
max = lines.map(&:size).max
lines.map { |line|
Array.new(max, ' ').tap { |arr| arr[0, line.size] = line.split(//) }
}.transpose
.map { |line| line.join.reverse }.join("\n")
end
end
termtterをお使いの方は~/.termtter/plugin
以下に以下のコードを配置すればut
コマンドで使えるようになります。プラグインには縦書き以外の変なツイート用コードが含まれていますので、予めご了承下さい。
# -*- coding:utf-8 -*-
# termtter plugin for tweet modifications.
require "flippy"
class String
def mirror(opt)
reversed = RUBY_VERSION < '1.9.0' ? self.split(//).reverse.join : self.reverse
opt.empty? ? self.replace(reversed) : self.replace(self.chop + reversed)
end
def rot13(opt=nil)
from = 'A-Ma-mN-Zn-zあ-なア-ナに-んニ-ン'
to = 'N-Zn-zA-Ma-mに-んニ-ンあ-なア-ナ'
if RUBY_VERSION >= '1.9.0'
from += '一-盒盓-龥'
to += '盓-龥一-盒'
end
self.tr(from, to)
end
def scooch(opt)
opt = opt.to_i.zero? ? 1 : opt.to_i
self.split(//).map { |c| opt.times { c = c.next }; c }.join
end
alias :__flip__ :flip
def flip(opt=nil)
self.__flip__
end
def tate(opt=nil)
self.vertical
end
end
module Termtter::Client
uglies = {
:update_mirror => [[:um], :mirror, 'Mirror message'],
:update_rot13 => [[:u13], :rot13, 'Rot13 message'],
:update_scooch => [[:us], :scooch, 'Scooch message'],
:update_crypt => [[:uc], :crypt, 'Crypt message'],
:update_updown => [[:ufp], :flip, 'Flip message'],
:update_tate => [[:ut], :tate, 'Tate message'],
}
uglies.each do |name, (aliases, meth, help)|
register_command(
:name => name, :aliases => aliases,
:exec_proc => lambda {|arg|
opt = ''
arg.sub!(/^-\s*([\d\w]+)\s+/) { opt = 1ドル; '' }
text =
case name
when :update_tate
"\n" + arg.gsub(/ | /, "\n").send(meth, opt)
when :update_crypt, :update_scooch
"#{arg.send(meth, opt)} ##{meth.to_s} #{opt}"
else
"#{arg.send(meth, opt)} ##{meth.to_s}"
end
Termtter::API::twitter.update(text)
puts "=> #{text}"
},
:help => ["#{name},#{aliases.join(',')} [-VALUE] TEXT", help]
)
end
end
また、@no6vさん作earthquake用pluginもありますので、eqrthquakeをお使いの方はこちら。
下 思 で ¬ ど
さ う の f う
い 存 縦 l ぞ
ね。分 書 i み
楽 き p な
し を、p さ
ん y ん、
で、 ∟
(追記:2013年03月19日) 実装の変更に伴い記述を変更しました。earthquake.gem用pluginについて追記しました。
(追記:2013年03月20日) 文字列中の"//"の扱いについて追記しました。 (追記:2013年03月23日) Flippy#verticalにおけるデリミタの変更に伴い記述を直しました。
=== Ruby関連電子書籍100円で好評発売中! ===