hp12c
18 March 2013

縦書きツイートの時代が来たようなので、わたし、RubyでTermtterで「縦つい。」します

少し前に、"ɹəʇʇɪʍʇ"のような反転文字ツイートが粋だと聞いたわたしは、この流行に乗り遅れまいと直ぐに「flippy」という反転文字を出力するツールをRubyで作りました。そして、愛用のtermtterから時々、"¡ʎqnᴚ ɥʇᴉʍ ɓuᴉʞɔɐH ʎddɐH"などとタイムラインに流して一人悦に入っていたのでした。

"「twitter→ɹəʇʇɪʍʇのように英数字を180度回転して表示する方法」をRubyでやってみた" error

"RubyのコードをFlipして暗号化する?" error

ところが気がつくと反転文字の流行はとうに終わっていて、今度は「縦書きツイート」が流行の兆しを見せているようなのです。

一発で縦書きツイートを作成できる「縦つい。」 : ライフハッカー[日本版]

Ruby使いたる者、流行に乗り遅れるわけにはいきませんよね。「縦つい。」が必要なら「縦つい。」するツールをRubyで作ればいいのです。


そんなわけで...


flippyに縦書きを実現するFlippy#verticalを追加しましたので、お知らせいたします :-)

flippy | RubyGems.org | your community gem host

melborne/flippy · GitHub

Flippyモジュールでの使い方

gem i flippyしてflippyをrequireすると、StringにFlippyモジュールがincludeされますので、文字列に対してverticalメソッドを呼んで下さい。

require "flippy"
str = <<EOS
春はあけぼの、
夏は夜。
秋は夕暮れ、
冬はウィンター。
EOS
puts str.vertical
# >> 冬 秋 夏 春 
# >> は は は は 
# >> ウ 夕 夜。あ 
# >> ィ 暮  け 
# >> ン れ、 ぼ 
# >> タ   の、
# >> |。   

flippyコマンドでの使い方

flippyコマンドに-v(または–vertical)オプションを追加しました。flippy -v [string]のように使います。文字列中の全角または半角スペースが改行として解釈されます。

% flippy -v 春はあけぼの、 夏は夜。 秋は夕暮れ、 冬はウィンター。
冬 秋 夏 春 
は は は は 
ウ 夕 夜。あ 
ィ 暮  け 
ン れ、 ぼ 
タ   の、
|。

これをお使いのTwitterクライアントにコピペすれば「縦つい。」できます。

文字列中の"++"の扱い

version 0.1.0で、文字列中の++以降の文字列を横書きとする仕様を導入しました。

% flippy -v "つまづいたって いいじゃ ないか にんげんだ もの++ みつを #mitsuo"
も に な い つ
の ん い い ま
 げ か じ づ
 ん  ゃ い
 だ   た
    っ
    て みつを #mitsuo

++が複数あるときは最後のもの以降が対象になります。すべての++をエスケープしたいときは文末に++を入れて下さい。

なお、flippyの他の使い方については、以下の記事を参考にしてください。

"RubyのコードをFlipして暗号化する?" error

"flippy gemにKernel#stndを追加しましたので、お知らせします。" error

"flippy consoleで上下反転文字の不思議な感覚を味わってみませんか?" error

Flippy#verticalの実装について

基本的に複数行からなる文字列を二次元配列に入れて転置してjoin-reverseして終わりです。RubyにはArray#transposeというステキなメソッドがあるので転置は一発です。

ただ、前処理がちょっと面倒です。1つは向きの変換が必要な文字群の処理で、これはString#trを使って互換文字に置き換えます。

それから句読点の処理です。「縦つい。」では句読点は直前文字の右側に配置されているのでこれに倣いました。つまり各行の右側は空行になっていて句読点がある場合はここに配置されます。(削除) この処理のため、各行を複製し一方を句読点を除いた行、他方を句読点のみの行に置換する処理をしています。ただし行の先頭文字が句読点の場合はこの限りではないので、先頭文字は対象外とします。 (削除ここまで)(文中の句読点後の空白を除くよう実装を変更しました)

Flippy#verticalの該当コードをここに貼っておきます。(削除) ちなみに今回の実装での個人的TipsはArray.new(size,val).tap{ Array#[nth]=val }です。 (削除ここまで)(String#fillを使う実装に変更しました。thanks to @no6vさん)

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をお使いの方は~/.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をお使いの方はこちら。

vertical.rb


下 思 で ¬ ど

さ う の f う

い 存 縦 l ぞ

ね。分 書 i み

楽 き p な

し を、p さ

ん y ん、

で、 ∟



(追記:2013年03月19日) 実装の変更に伴い記述を変更しました。earthquake.gem用pluginについて追記しました。

(追記:2013年03月20日) 文字列中の"//"の扱いについて追記しました。 (追記:2013年03月23日) Flippy#verticalにおけるデリミタの変更に伴い記述を直しました。


=== Ruby関連電子書籍100円で好評発売中! ===

M’ELBORNE BOOKS

start_ruby ruby_object trivia



Please enable JavaScript to view the comments powered by Disqus. blog comments powered by Disqus
ruby_pack8

100円〜で好評発売中!
M'ELBORNE BOOKS


AltStyle によって変換されたページ (->オリジナル) /