Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'optparse'
- require 'stringio'
- require 'rubygems'
- require 'twitter'
- module Twsh
- class Logout < StandardError; end
- class TwshError < StandardError; end
- class Shell
- class << self
- def login(argv, env)
- new argv, env
- end
- end
- def initialize(argv, env)
- username = nil
- password = nil
- OptionParser.new do |opt|
- opt.on('-u VAL') {|v| username = v}
- opt.on('-p VAL') {|v| password = v}
- opt.parse! argv
- end
- fail if username.nil? || password.nil?
- @client = Twitter::Base.new Twitter::HTTPAuth.new username, password
- input = Input.new self
- logged_in = true
- while logged_in
- begin
- output = execute input.read
- puts output if output
- rescue Logout
- logged_in = false
- rescue Interrupt
- puts
- logged_in = false
- rescue TwshError => e
- puts e.message
- end
- end
- end
- attr_reader :client
- def execute(argv)
- return if argv.empty?
- command = argv.shift
- Command.new(self).execute command, argv
- end
- end
- class Command
- @@commands = {}
- class << self
- def setup
- fail unless block_given?
- yield new
- end
- end
- def initialize(twsh = nil)
- @twsh = twsh
- end
- def on(*commands, &process)
- fail unless block_given?
- commands.each {|command| @@commands[command] = process}
- end
- def execute(command, argv)
- process = @@commands[command]
- if process
- args = []
- args << @twsh if process.arity >= 1
- args << argv if process.arity >= 2
- output = nil
- StringIO.open '', 'w' do |io|
- orig = $stdout
- $stdout = io
- process.call *args
- $stdout = orig
- output = io.string unless io.string.empty?
- end
- output
- else
- `#{command} #{argv.join ' '}`.chomp
- end
- end
- end
- class Input
- def initialize(twsh)
- @twsh = twsh
- end
- def read
- read_with_context
- end
- private
- def read_with_context(context = nil, argv = [])
- print context ? "#{context}> " : argv.empty? ? 'twsh% ' : '> '
- context, argv, continue = parse gets, context, argv
- continue ? read_with_context(context, argv) : argv
- end
- def parse(input, context = nil, argv = [])
- escape = false
- continue = false
- v = !argv.empty? ? argv.pop : ''
- new = lambda do
- argv << v unless v.empty?
- v = ''
- end
- input.each_byte do |c|
- if escape
- escape = false
- case c
- when LINE_FEED
- continue = true
- v << c if context
- when ?n
- v << "\n" if quoted? context
- when ?t
- v << "\t" if quoted? context
- when ?f
- v << "\f" if quoted? context
- when ?v
- v << "\v" if quoted? context
- else
- v << c
- end
- else
- case c
- when ?\n
- v << c if context
- when ?\s
- if context
- v << c
- else
- new.call
- end
- when ?'
- if context == :quote
- new.call
- context = nil
- elsif context
- v << c
- else
- context = :quote
- end
- when ?"
- if context == :dquote
- new.call
- context = nil
- elsif context
- v << c
- else
- context = :dquote
- end
- when ?`
- if context == :bquote
- v = @twsh.execute(parse(v)[1])
- context = nil
- elsif context
- v << c
- else
- context = :bquote
- end
- when ?\\
- escape = true
- else
- v << c
- end
- end
- end
- new.call
- [context, argv, continue || !context.nil?]
- end
- def quoted?(context)
- context == :quote || context == :dquote
- end
- end
- end
- Twsh::Command.setup do |c|
- c.on('exit', 'quit', 'logout') { fail Twsh::Logout }
- c.on 'echo' do |twsh, argv|
- twsh.client.update argv.join ' '
- nil
- end
- c.on 'head' do |twsh, argv|
- n = 5
- OptionParser.new do |opt|
- opt.on('-n VAL', Integer) {|v| n = v}
- opt.parse! argv
- end
- screen_name = argv.shift
- iterator = lambda {|status| puts "#{status.user.screen_name}: #{status.text}"}
- if screen_name
- twsh.client.user_timeline(:screen_name => screen_name, :count => n).each &iterator
- else
- twsh.client.home_timeline(:count => n).each &iterator
- end
- nil
- end
- end
- Twsh::Shell.login ARGV, ENV
Add Comment
Please, Sign In to add comment