flumtter 5.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/flumtter +5 -0
- data/flumtter.gemspec +31 -0
- data/lib/flumtter.rb +2 -0
- data/lib/flumtter/app/core/account_selector.rb +88 -0
- data/lib/flumtter/app/core/client.rb +148 -0
- data/lib/flumtter/app/core/command.rb +24 -0
- data/lib/flumtter/app/core/command/dm.rb +12 -0
- data/lib/flumtter/app/core/command/tweet.rb +24 -0
- data/lib/flumtter/app/core/command/user.rb +52 -0
- data/lib/flumtter/app/core/command/userlist.rb +8 -0
- data/lib/flumtter/app/core/core.rb +58 -0
- data/lib/flumtter/app/core/curses.rb +90 -0
- data/lib/flumtter/app/core/hash.rb +29 -0
- data/lib/flumtter/app/core/initializer.rb +28 -0
- data/lib/flumtter/app/core/keyboard.rb +54 -0
- data/lib/flumtter/app/core/plugins.rb +27 -0
- data/lib/flumtter/app/core/string.rb +148 -0
- data/lib/flumtter/app/core/terminal.rb +13 -0
- data/lib/flumtter/app/core/thread.rb +29 -0
- data/lib/flumtter/app/core/toast.rb +26 -0
- data/lib/flumtter/app/core/util.rb +107 -0
- data/lib/flumtter/app/core/windows/base.rb +16 -0
- data/lib/flumtter/app/core/windows/buf_window.rb +194 -0
- data/lib/flumtter/app/core/windows/dialog.rb +62 -0
- data/lib/flumtter/app/core/windows/dmbase.rb +28 -0
- data/lib/flumtter/app/core/windows/dynamic_view.rb +43 -0
- data/lib/flumtter/app/core/windows/favorite.rb +31 -0
- data/lib/flumtter/app/core/windows/follower.rb +20 -0
- data/lib/flumtter/app/core/windows/following.rb +20 -0
- data/lib/flumtter/app/core/windows/mention.rb +29 -0
- data/lib/flumtter/app/core/windows/popup.rb +35 -0
- data/lib/flumtter/app/core/windows/tweet.rb +31 -0
- data/lib/flumtter/app/core/windows/tweetbase.rb +24 -0
- data/lib/flumtter/app/core/windows/userbase.rb +43 -0
- data/lib/flumtter/app/main.rb +3 -0
- data/lib/flumtter/app/plugins/commands.rb +15 -0
- data/lib/flumtter/app/plugins/commands/account_changer.rb +9 -0
- data/lib/flumtter/app/plugins/commands/change_profile.rb +69 -0
- data/lib/flumtter/app/plugins/commands/conversation.rb +39 -0
- data/lib/flumtter/app/plugins/commands/delete.rb +26 -0
- data/lib/flumtter/app/plugins/commands/directmessage.rb +35 -0
- data/lib/flumtter/app/plugins/commands/directmessages.rb +33 -0
- data/lib/flumtter/app/plugins/commands/favorite.rb +22 -0
- data/lib/flumtter/app/plugins/commands/mention.rb +7 -0
- data/lib/flumtter/app/plugins/commands/new_tweet.rb +17 -0
- data/lib/flumtter/app/plugins/commands/reply.rb +26 -0
- data/lib/flumtter/app/plugins/commands/retweet.rb +30 -0
- data/lib/flumtter/app/plugins/commands/unfavorite.rb +26 -0
- data/lib/flumtter/app/plugins/commands/user.rb +77 -0
- data/lib/flumtter/app/plugins/commands/utility.rb +17 -0
- data/lib/flumtter/app/plugins/load.rb +16 -0
- data/lib/flumtter/app/plugins/pry.rb +12 -0
- data/lib/flumtter/app/plugins/timeline.rb +42 -0
- data/lib/flumtter/app/plugins/timeline/base.rb +74 -0
- data/lib/flumtter/app/plugins/timeline/deleted_tweet.rb +23 -0
- data/lib/flumtter/app/plugins/timeline/dm.rb +23 -0
- data/lib/flumtter/app/plugins/timeline/event.rb +11 -0
- data/lib/flumtter/app/plugins/timeline/fav.rb +43 -0
- data/lib/flumtter/app/plugins/timeline/tweet.rb +51 -0
- data/lib/flumtter/app/plugins/toast.rb +45 -0
- data/lib/flumtter/version.rb +3 -0
- metadata +213 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module Flumtter
|
2
|
+
class Command
|
3
|
+
attr_reader :name, :command, :help
|
4
|
+
def initialize(command, help="", &blk)
|
5
|
+
@name = command.is_a?(Regexp) ? command.inspect : command
|
6
|
+
@command = command.is_a?(String) ? command.to_reg : command
|
7
|
+
@help = help
|
8
|
+
@blk = blk
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(*args)
|
12
|
+
@blk.call(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.list(commands)
|
16
|
+
char_len = commands.max_by{|c|c.name.size}.name.size + 1 rescue 0
|
17
|
+
commands.map do |c|
|
18
|
+
c.name.ljust(char_len) + c.help
|
19
|
+
end.join("\n")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
sarastire "core/command"
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Flumtter
|
2
|
+
module Command::Tweet
|
3
|
+
def add_command(twitter)
|
4
|
+
command("f", "Favorite") do |m|
|
5
|
+
error_handler do
|
6
|
+
obj, _ = parse_index(m[1])
|
7
|
+
Plugins::Favorite.favorite(obj, twitter)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
command("t", "Retweet") do |m|
|
11
|
+
error_handler do
|
12
|
+
obj, _ = parse_index(m[1])
|
13
|
+
Plugins::Retweet.retweet(obj, twitter)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
command("r", "Reply") do |m|
|
17
|
+
error_handler do
|
18
|
+
obj, m2 = parse_index(m[1])
|
19
|
+
Plugins::Reply.update(obj, m2, twitter)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Flumtter
|
2
|
+
module Command::User
|
3
|
+
include Util
|
4
|
+
|
5
|
+
def add_command(user, twitter)
|
6
|
+
command("tweet", "Tweet List") do
|
7
|
+
error_handler do
|
8
|
+
Window::Tweet.new(user, twitter).show
|
9
|
+
end
|
10
|
+
end
|
11
|
+
command("follower", "Follower List") do
|
12
|
+
error_handler do
|
13
|
+
Window::Follower.new(user, twitter).show
|
14
|
+
end
|
15
|
+
end
|
16
|
+
command("following", "Following List") do
|
17
|
+
error_handler do
|
18
|
+
Window::Following.new(user, twitter).show
|
19
|
+
end
|
20
|
+
end
|
21
|
+
command("favorite", "Favorite List") do
|
22
|
+
error_handler do
|
23
|
+
Window::Favorite.new(user, twitter).show
|
24
|
+
end
|
25
|
+
end
|
26
|
+
command("follow", "Follow") do
|
27
|
+
error_handler do
|
28
|
+
twitter.rest.follow(user.screen_name)
|
29
|
+
Window::Popup::Success.new("follow success").show
|
30
|
+
end
|
31
|
+
end
|
32
|
+
command("unfollow", "Unfollow") do
|
33
|
+
error_handler do
|
34
|
+
twitter.rest.unfollow(user.screen_name)
|
35
|
+
Window::Popup::Success.new("unfollow success").show
|
36
|
+
end
|
37
|
+
end
|
38
|
+
command("block", "Block") do
|
39
|
+
error_handler do
|
40
|
+
twitter.rest.block(user.screen_name)
|
41
|
+
Window::Popup::Success.new("block success").show
|
42
|
+
end
|
43
|
+
end
|
44
|
+
command("unblock", "UnBlock") do
|
45
|
+
error_handler do
|
46
|
+
twitter.rest.unblock(user.screen_name)
|
47
|
+
Window::Popup::Success.new("unblock success").show
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
module Flumtter
|
4
|
+
SourcePath = File.expand_path('../../', __FILE__)
|
5
|
+
UserPath = File.expand_path('~/.flumtter')
|
6
|
+
[SourcePath, UserPath].each do |path|
|
7
|
+
def path.join(*args)
|
8
|
+
File.join(self, *args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
FileUtils.mkdir(UserPath) unless FileTest.exist?(UserPath)
|
12
|
+
|
13
|
+
data_path = UserPath.join("data", "data.bin")
|
14
|
+
Config = Marshal.load(File.read(data_path)) rescue {}
|
15
|
+
at_exit {
|
16
|
+
puts 'data saved'
|
17
|
+
File.write(data_path, Marshal.dump(Config))
|
18
|
+
}
|
19
|
+
|
20
|
+
Thread.abort_on_exception = true
|
21
|
+
|
22
|
+
module_function
|
23
|
+
def sarastire(path, file=nil)
|
24
|
+
path = file.nil? ? SourcePath.join(path, '*.rb') : SourcePath.join(path, file)
|
25
|
+
Dir.glob(path).each{|plugin|require plugin}
|
26
|
+
end
|
27
|
+
|
28
|
+
def sarastire_user(path, file=nil)
|
29
|
+
path = file.nil? ? UserPath.join(path, '*.rb') : UserPath.join(path, file)
|
30
|
+
Dir.glob(path).each{|plugin|require plugin}
|
31
|
+
end
|
32
|
+
|
33
|
+
@events = Hash.new{|h,k|h[k] = []}
|
34
|
+
def on_event(event,&blk)
|
35
|
+
@events[event] << blk
|
36
|
+
end
|
37
|
+
|
38
|
+
def callback(event,object=nil)
|
39
|
+
@events[event].each{|blk|blk.call(object)}
|
40
|
+
end
|
41
|
+
|
42
|
+
TITLE = "Flumtter"
|
43
|
+
|
44
|
+
sarastire 'core', 'util.rb'
|
45
|
+
sarastire_user 'setting'
|
46
|
+
sarastire 'core'
|
47
|
+
sarastire 'plugins'
|
48
|
+
sarastire_user 'plugins'
|
49
|
+
|
50
|
+
TITLE.terminal_title
|
51
|
+
|
52
|
+
def start
|
53
|
+
options = Initializer.optparse
|
54
|
+
Setting.merge!(options)
|
55
|
+
Client.new AccountSelector.select(options)
|
56
|
+
rescue Interrupt
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'dispel'
|
2
|
+
module Dispel
|
3
|
+
class CloseWindow < StandardError; end
|
4
|
+
class NoCommandError < StandardError; end
|
5
|
+
class Recall < StandardError; end
|
6
|
+
|
7
|
+
class Window
|
8
|
+
class << self
|
9
|
+
def open(*args)
|
10
|
+
win = Curses::Window.new(*args)
|
11
|
+
win.keypad(true)
|
12
|
+
yield win
|
13
|
+
rescue CloseWindow
|
14
|
+
ensure
|
15
|
+
win.refresh
|
16
|
+
win.close
|
17
|
+
end
|
18
|
+
|
19
|
+
def close
|
20
|
+
raise CloseWindow
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Util
|
26
|
+
def addstr(win, str)
|
27
|
+
win.setpos(win.cury+1, 1)
|
28
|
+
win.addstr str
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_multiline_str(win, str)
|
32
|
+
str.each_line do |line|
|
33
|
+
addstr(win, line.chomp)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def getstr(win, ex=[])
|
38
|
+
buf = ""
|
39
|
+
x = win.curx
|
40
|
+
loop do
|
41
|
+
input = Dispel::Keyboard.translate_key_to_code(win.getch)
|
42
|
+
ex.each do |k|
|
43
|
+
return input if input == k
|
44
|
+
end
|
45
|
+
|
46
|
+
case input
|
47
|
+
when :"Ctrl+c"
|
48
|
+
raise CloseWindow
|
49
|
+
when :enter
|
50
|
+
return buf
|
51
|
+
when :escape
|
52
|
+
raise CloseWindow
|
53
|
+
when :left
|
54
|
+
if win.curx > x
|
55
|
+
win.setpos(win.cury, win.curx-1)
|
56
|
+
end
|
57
|
+
when :right
|
58
|
+
if win.curx <= buf.size
|
59
|
+
win.setpos(win.cury, win.curx+1)
|
60
|
+
end
|
61
|
+
# TODO: 文字移動して削除入力
|
62
|
+
when :backspace
|
63
|
+
buf.chop!
|
64
|
+
while win.curx > x
|
65
|
+
win.setpos(win.cury, win.curx-1)
|
66
|
+
win.delch()
|
67
|
+
win.insch(" ")
|
68
|
+
end
|
69
|
+
win.addstr(buf)
|
70
|
+
when String
|
71
|
+
buf << input.force_encoding("utf-8")
|
72
|
+
win.setpos(win.cury, win.curx)
|
73
|
+
win.addstr(input)
|
74
|
+
else
|
75
|
+
p input
|
76
|
+
end
|
77
|
+
end
|
78
|
+
rescue NoMethodError => e
|
79
|
+
if e.backtrace.shift =~ /keyboard.rb:210/
|
80
|
+
raise Dispel::Recall
|
81
|
+
else
|
82
|
+
raise e
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
module Flumtter
|
89
|
+
sarastire 'core/windows'
|
90
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Hash
|
2
|
+
def requires(*args)
|
3
|
+
args.each do |arg|
|
4
|
+
raise ArgumentError, "Parameter is missing a value(#{arg})" if self[arg].nil?
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def nest_level(level=0)
|
9
|
+
self.map do |k,v|
|
10
|
+
if v.is_a?(Hash)
|
11
|
+
v.nest_level(level+1)
|
12
|
+
else
|
13
|
+
level+1
|
14
|
+
end
|
15
|
+
end.max
|
16
|
+
end
|
17
|
+
|
18
|
+
def indent(t=0, n=2)
|
19
|
+
self.map do |k,v|
|
20
|
+
if self.nest_level == 1 || !v.is_a?(Hash)
|
21
|
+
between = ": "
|
22
|
+
char_len = self.keys.max_by{|key|key.size}.size + (n * t)
|
23
|
+
k.to_s.shift(t*n).ljust(char_len) + ": " + v.to_s.nshift(char_len + between.size)
|
24
|
+
else
|
25
|
+
[k.to_s.shift(t*n), *v.is_a?(Hash) ? v.indent(t+1, n) : [v.to_s.shift(n*2)]].join("\n")
|
26
|
+
end
|
27
|
+
end.join("\n")
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Initializer
|
4
|
+
@args, @events = [], {}
|
5
|
+
|
6
|
+
module_function
|
7
|
+
def add_opt(&blk)
|
8
|
+
@args << blk
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(sym, &blk)
|
12
|
+
@events[sym] = blk
|
13
|
+
end
|
14
|
+
|
15
|
+
def optparse
|
16
|
+
opt = OptionParser.new
|
17
|
+
options = {}
|
18
|
+
opt.on('-n VALUE', '--name VALUE', 'account name'){|v|options[:name] = v}
|
19
|
+
opt.on('-i VALUE', '--index VALUE', 'account index'){|v|options[:id] = v.to_i}
|
20
|
+
opt.on('-s', '--non_stream', 'without stream'){|v|options[:non_stream] = v}
|
21
|
+
opt.on('-d', '--debug', 'debug mode'){|v|options[:debug] = v}
|
22
|
+
opt.on('--args VALUE'){|v|options[:args] = v}
|
23
|
+
@args.each{|args|args.call(opt, options)}
|
24
|
+
opt.parse!(ARGV)
|
25
|
+
options.each{|k,v|@events[k].call(v,options) unless @events[k].nil?}
|
26
|
+
options
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
|
3
|
+
module Flumtter
|
4
|
+
class Keyboard
|
5
|
+
extend Util
|
6
|
+
|
7
|
+
class << self
|
8
|
+
@@commands = []
|
9
|
+
|
10
|
+
def input(twitter)
|
11
|
+
loop do
|
12
|
+
input = STDIN.noecho(&:gets)
|
13
|
+
next if input.nil?
|
14
|
+
twitter.pause
|
15
|
+
callback(input.chomp, twitter)
|
16
|
+
twitter.resume
|
17
|
+
end
|
18
|
+
rescue Interrupt
|
19
|
+
end
|
20
|
+
|
21
|
+
def callback(input, twitter)
|
22
|
+
if input == "?"
|
23
|
+
Window::Popup.new("Command List", <<~EOF).show
|
24
|
+
#{Command.list(@@commands)}
|
25
|
+
|
26
|
+
For more information, please see the following Home page.
|
27
|
+
http://github.com/flum1025/flumtter3
|
28
|
+
This software is released under the MIT License
|
29
|
+
Copyright © @flum_ 2016
|
30
|
+
EOF
|
31
|
+
else
|
32
|
+
@@commands.each do |command|
|
33
|
+
if m = input.match(command.command)
|
34
|
+
return command.call(m, twitter)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
puts "Command not found".color
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def add(command, help, &blk)
|
42
|
+
@@commands << Command.new(command, help) do |*args|
|
43
|
+
begin
|
44
|
+
blk.call(*args)
|
45
|
+
rescue SystemExit => e
|
46
|
+
raise e
|
47
|
+
rescue Exception => e
|
48
|
+
error e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'Initializer'
|
2
|
+
|
3
|
+
module Flumtter
|
4
|
+
module Plugins
|
5
|
+
module Base
|
6
|
+
def add_opt(&blk)
|
7
|
+
Initializer.add_opt(&blk)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_opt(*args, &blk)
|
11
|
+
Initializer.run(*args, &blk)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module_function
|
16
|
+
def plugin(blk)
|
17
|
+
m = self.const_set(File.basename(blk.source_location[0], '.rb').to_camel.to_sym, Module.new)
|
18
|
+
m.extend(Base)
|
19
|
+
m.extend(Util)
|
20
|
+
m.instance_eval(&blk)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def plugin(&blk)
|
26
|
+
Flumtter::Plugins.plugin(blk)
|
27
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
class String
|
2
|
+
def to_camel
|
3
|
+
self.split(/_/).map(&:capitalize).join
|
4
|
+
end
|
5
|
+
|
6
|
+
def terminal_title
|
7
|
+
print "\033];#{self}\007"
|
8
|
+
at_exit{print "\033];\007"}
|
9
|
+
end
|
10
|
+
|
11
|
+
def title
|
12
|
+
"【#{self}】"
|
13
|
+
end
|
14
|
+
|
15
|
+
def color(color=:red)
|
16
|
+
case color
|
17
|
+
when :white then "\e[1;37m#{self}\e[0m"
|
18
|
+
when :light_gray then "\e[37m#{self}\e[0m"
|
19
|
+
when :gray then "\e[1;30m#{self}\e[0m"
|
20
|
+
when :back then "\e[30m#{self}\e[0m"
|
21
|
+
when :red then "\e[31m#{self}\e[0m"
|
22
|
+
when :light_red then "\e[1;31m#{self}\e[0m"
|
23
|
+
when :green then "\e[32m#{self}\e[0m"
|
24
|
+
when :light_green then "\e[1;32m#{self}\e[0m"
|
25
|
+
when :brown then "\e[33m#{self}\e[0m"
|
26
|
+
when :yellow then "\e[1;33m#{self}\e[0m"
|
27
|
+
when :blue then "\e[34m#{self}\e[0m"
|
28
|
+
when :light_blue then "\e[1;34m#{self}\e[0m"
|
29
|
+
when :purple then "\e[35m#{self}\e[0m"
|
30
|
+
when :pink then "\e[1;35m#{self}\e[0m"
|
31
|
+
when :cyan then "\e[36m#{self}\e[0m"
|
32
|
+
when :light_cyan then "\e[1;36m#{self}\e[0m"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def background_color(color=:red)
|
37
|
+
case color
|
38
|
+
when :black
|
39
|
+
"\e[40m#{self}\e[0m"
|
40
|
+
when :red
|
41
|
+
"\e[41m#{self}\e[0m"
|
42
|
+
when :green
|
43
|
+
"\e[42m#{self}\e[0m"
|
44
|
+
when :yellow
|
45
|
+
"\e[43m#{self}\e[0m"
|
46
|
+
when :blue
|
47
|
+
"\e[44m#{self}\e[0m"
|
48
|
+
when :magenta
|
49
|
+
"\e[45m#{self}\e[0m"
|
50
|
+
when :cyan
|
51
|
+
"\e[46m#{self}\e[0m"
|
52
|
+
when :white
|
53
|
+
"\e[47m#{self}\e[0m"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def exact_size
|
58
|
+
self.each_char.map{|c| c.bytesize == 1 ? 1 : 2}.reduce(0, &:+)
|
59
|
+
end
|
60
|
+
|
61
|
+
def nl(i=1)
|
62
|
+
self + "\n"*i
|
63
|
+
end
|
64
|
+
|
65
|
+
def dnl
|
66
|
+
"\n#{self}\n"
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_mb?
|
70
|
+
self.bytes do |b|
|
71
|
+
return true if (b & 0b10000000) != 0
|
72
|
+
end
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
alias_method :_ljust, :ljust
|
77
|
+
def ljust(length, padstr=nil, rstr="")
|
78
|
+
length -= (exact_size - 1) if has_mb?
|
79
|
+
length -= rstr.exact_size
|
80
|
+
text = padstr.nil? ? _ljust(length) : _ljust(length, padstr)
|
81
|
+
text << rstr
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_em
|
85
|
+
self.tr('0-9a-zA-Z', '0-9a-zA-Z')
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_en
|
89
|
+
self.tr('0-9a-zA-Z', '0-9a-zA-Z')
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_reg
|
93
|
+
reg = Regexp.union(self, self.to_em)
|
94
|
+
/^#{Regexp.new(reg.source, Regexp::IGNORECASE)}[ | ]*(.*)/
|
95
|
+
end
|
96
|
+
|
97
|
+
def shift(n=2)
|
98
|
+
self.each_line.map do |line|
|
99
|
+
" "*n + line.chomp
|
100
|
+
end.join("\n")
|
101
|
+
end
|
102
|
+
|
103
|
+
def nshift(n=2)
|
104
|
+
self.each_line.map.with_index do |line, i|
|
105
|
+
if i.zero?
|
106
|
+
line.chomp
|
107
|
+
else
|
108
|
+
" "*n + line.chomp
|
109
|
+
end
|
110
|
+
end.join("\n")
|
111
|
+
end
|
112
|
+
|
113
|
+
def split_num(n)
|
114
|
+
text = []
|
115
|
+
tmp = ""
|
116
|
+
self.each_char.each do |char|
|
117
|
+
if tmp.exact_size < n
|
118
|
+
tmp << char
|
119
|
+
else
|
120
|
+
text << tmp
|
121
|
+
tmp = char
|
122
|
+
end
|
123
|
+
end
|
124
|
+
text << tmp
|
125
|
+
text.join("\n")
|
126
|
+
end
|
127
|
+
|
128
|
+
def range?(max)
|
129
|
+
unless 1 <= self.size && self.size <= max
|
130
|
+
raise RangeError
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def size_of_lines
|
135
|
+
self.each_line.to_a.size
|
136
|
+
end
|
137
|
+
|
138
|
+
def max_char_of_lines
|
139
|
+
max = self.each_line.max_by{|str|str.size}
|
140
|
+
max.nil? ? 0 : max.size
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
if $0 == __FILE__
|
145
|
+
%i(white light_gray gray black red light_red green light_green brown yellow blue light_blue purple pink cyan light_cyan).each do |c|
|
146
|
+
puts "#{c}".color(c)
|
147
|
+
end
|
148
|
+
end
|