the_dude 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ results.html
2
+ tmp
3
+ pkg
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format d --color
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create 1.9.3@dude
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ the_dude (0.0.2)
5
+ colored
6
+ hirb
7
+ nokogiri
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ aruba (0.5.2)
13
+ childprocess (~> 0.3.6)
14
+ cucumber (>= 1.1.1)
15
+ rspec-expectations (>= 2.7.0)
16
+ builder (3.0.4)
17
+ childprocess (0.3.9)
18
+ ffi (~> 1.0, >= 1.0.11)
19
+ colored (1.2)
20
+ cucumber (1.3.1)
21
+ builder (>= 2.1.2)
22
+ diff-lcs (>= 1.1.3)
23
+ gherkin (~> 2.12.0)
24
+ multi_json (~> 1.3)
25
+ diff-lcs (1.2.4)
26
+ fakeweb (1.3.0)
27
+ ffi (1.8.1)
28
+ gherkin (2.12.0)
29
+ multi_json (~> 1.3)
30
+ hirb (0.7.1)
31
+ json (1.7.7)
32
+ multi_json (1.7.3)
33
+ nokogiri (1.5.9)
34
+ rake (10.0.4)
35
+ rdoc (4.0.1)
36
+ json (~> 1.4)
37
+ rspec (2.13.0)
38
+ rspec-core (~> 2.13.0)
39
+ rspec-expectations (~> 2.13.0)
40
+ rspec-mocks (~> 2.13.0)
41
+ rspec-core (2.13.1)
42
+ rspec-expectations (2.13.0)
43
+ diff-lcs (>= 1.1.3, < 2.0)
44
+ rspec-mocks (2.13.1)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ aruba
51
+ fakeweb
52
+ rake
53
+ rdoc
54
+ rspec
55
+ the_dude!
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # The Dude
2
+
3
+ [![Code Climate](https://codeclimate.com/github/adamphillips/the_dude.png)](https://codeclimate.com/github/adamphillips/the\_dude)
4
+
5
+ The Dude is here to make your terminal life more chilled.
6
+
7
+ You preload The Dude with your commonly used commands. Then you run them.
8
+ Alternatively, The Dude already knows how to do a bunch of stuff for you.
9
+
10
+ For example:
11
+
12
+ $ dude fetch google.co.uk # opens a google.co.uk in lynx
13
+ $ dude show me pictures of cool stuff # opens a browser with a google images search for 'cool stuff'
14
+ $ dude wassup # starts top
15
+
16
+ If this sounds like fancypants bash aliases, you'd be about right. So what's the point?
17
+
18
+ Well, there's a few reasons
19
+ - a single dude command can trigger a bunch of other commands. Sure you
20
+ could write a shell script and run that using an alias but that assumes
21
+ you're happy writing shell scripts.
22
+ - for the command-line phobic, dude provides a friendly interface to the
23
+ command line.
24
+ - for those who are happy on the command line, there can still be a benefit
25
+ in reducing the cognitive overhead required to run scripts
26
+
27
+ ## Talking to The Dude
28
+
29
+ The Dude is still very young and not on rubygems quite yet. For the mean
30
+ time, you will need to checkout the repo and build the gem.
31
+
32
+ The Dude comes with a 'dude' binary so you can use this to run commands
33
+
34
+ dude why? # will output 'because'
35
+
36
+ Alternatively, you can start the dude inteactively with
37
+
38
+ dude -i
39
+
40
+ Then you get a dude prompt you can enter commands straight into.
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ require 'rake/clean'
2
+ require 'rubygems'
3
+ require 'rubygems/package_task'
4
+ require 'rdoc/task'
5
+ require 'cucumber'
6
+ require 'cucumber/rake/task'
7
+ Rake::RDocTask.new do |rd|
8
+ rd.main = "README.rdoc"
9
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
10
+ rd.title = 'Your application title'
11
+ end
12
+
13
+ spec = eval(File.read('the_dude.gemspec'))
14
+
15
+ Gem::PackageTask.new(spec) do |pkg|
16
+ end
17
+ CUKE_RESULTS = 'results.html'
18
+ CLEAN << CUKE_RESULTS
19
+ desc 'Run features'
20
+ Cucumber::Rake::Task.new(:features) do |t|
21
+ opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
22
+ opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
23
+ t.cucumber_opts = opts
24
+ t.fork = false
25
+ end
26
+
27
+ desc 'Run features tagged as work-in-progress (@wip)'
28
+ Cucumber::Rake::Task.new('features:wip') do |t|
29
+ tag_opts = ' --tags ~@pending'
30
+ tag_opts = ' --tags @wip'
31
+ t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}"
32
+ t.fork = false
33
+ end
34
+
35
+ task :cucumber => :features
36
+ task 'cucumber:wip' => 'features:wip'
37
+ task :wip => 'features:wip'
38
+ require 'rake/testtask'
39
+ Rake::TestTask.new do |t|
40
+ t.libs << "test"
41
+ t.test_files = FileList['test/*_test.rb']
42
+ end
43
+
44
+ task :default => [:test,:features]
data/bin/dude ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require 'the_dude'
3
+
4
+ include TheDude::Dsl
5
+
6
+ DUDERC_PATH = "#{ENV['HOME']}/.duderc"
7
+ load DUDERC_PATH if File.exists? DUDERC_PATH
8
+
9
+ # Setup rlwrap for readline support
10
+ if ARGV.include? '-i'
11
+ interactive_mode = true
12
+ if !ENV['__REPL_WRAPPED'] && system("which rlwrap > /dev/null 2> /dev/null")
13
+ ENV['__REPL_WRAPPED'] = '0'
14
+
15
+ exec "rlwrap #{Shellwords.escape(__FILE__)} #{ARGV.join(' ')}"
16
+ end
17
+ end
18
+
19
+ question = ARGV.join(' ')
20
+
21
+ if interactive_mode
22
+ loop do
23
+ print "dude, "
24
+ begin
25
+ question = $stdin.gets.chomp
26
+ rescue NoMethodError, Interrupt
27
+ exit
28
+ end
29
+
30
+ puts TheDude.ask question
31
+ puts ''
32
+ end
33
+ else
34
+ puts TheDude.ask question
35
+ end
@@ -0,0 +1,13 @@
1
+ Feature: Basic interaction with the Dude
2
+
3
+ Scenario: App just runs
4
+ When I get help for "dude"
5
+ Then the exit status should be 0
6
+
7
+ Scenario: Asking a question
8
+ When I run `dude why?`
9
+ Then the output should contain "because"
10
+
11
+ Scenario: Asking a question that requires running another command
12
+ When I run `dude date`
13
+ Then the output should contain today's date
@@ -0,0 +1,27 @@
1
+ Feature: Reading from ~/.duderc
2
+ It should be possible to configure the dude from a duderc file
3
+
4
+ Scenario: File doesn't exist should still work
5
+ When I run `dude`
6
+ Then the exit status should be 0
7
+
8
+ #Scenario: File containing a question definition
9
+ #Given a file named "~/.duderc" with:
10
+ #"""
11
+ #command "another question" do
12
+ #"another answer"
13
+ #end
14
+ #"""
15
+ #When I run `dude another question`
16
+ #Then the output should contain "another answer"
17
+
18
+ #Scenario: File containing a question definition
19
+ #Given a file named "~/.duderc" with:
20
+ #"""
21
+ #command "say something" do
22
+ #`echo "hello"`
23
+ #end
24
+ #"""
25
+ #When I run `dude another question`
26
+ #Then the output should contain exactly "hello"
27
+
@@ -0,0 +1,8 @@
1
+ When /^I get help for "([^"]*)"$/ do |app_name|
2
+ @app_name = app_name
3
+ step %(I run `#{app_name} help`)
4
+ end
5
+
6
+ Then /^the output should contain today's date$/ do
7
+ step "the output should contain \"#{Date.today.to_s}\""
8
+ end
@@ -0,0 +1,15 @@
1
+ require 'aruba/cucumber'
2
+
3
+ ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
4
+ LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
5
+
6
+ Before do
7
+ # Using "announce" causes massive warnings on 1.9.2
8
+ @puts = true
9
+ @original_rubylib = ENV['RUBYLIB']
10
+ ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
11
+ end
12
+
13
+ After do
14
+ ENV['RUBYLIB'] = @original_rubylib
15
+ end
data/lib/the_dude.rb ADDED
@@ -0,0 +1,128 @@
1
+ require 'date'
2
+ require 'shellwords'
3
+
4
+ require 'hirb'
5
+ require 'colored'
6
+
7
+ require 'the_dude/command'
8
+ require 'the_dude/config'
9
+ require 'the_dude/dsl'
10
+ require 'the_dude/expression'
11
+ require 'the_dude/http'
12
+ require 'the_dude/variable'
13
+ require 'the_dude/version'
14
+
15
+ module TheDude
16
+
17
+ class << self
18
+ # Asks the dude a question
19
+ def ask question
20
+ command = find_command_for question
21
+ return "Wtf? What do you mean #{question}" unless command
22
+ arguments = arguments_for question, command
23
+
24
+ # this is a nasty way of dealing with the fact that we get question
25
+ # returned if it exactly matches the command
26
+ arguments = nil if arguments == question
27
+
28
+ command.ask *arguments
29
+ end
30
+
31
+ # @return [Hash] Returns the commands the dude knows about
32
+ def commands
33
+ @commands || {}
34
+ end
35
+
36
+ # Outputs something using angry-dude-formatting
37
+ def complain something
38
+ puts angry_dude_format something
39
+ end
40
+
41
+ # @return [Hash] Returns the variables the dude knows about
42
+ def variables
43
+ @variables || {}
44
+ end
45
+
46
+ # Registers a new command with the dude
47
+ #
48
+ # @param [TheDude::Command] command The command to register
49
+ def register_command command
50
+ @commands ||= {}
51
+ @commands[command.question] = command
52
+ end
53
+
54
+ # Registers a new variable with the dude
55
+ #
56
+ # @param [TheDude::Variable] variable The variable to register
57
+ def register_variable variable
58
+ @variables ||= {}
59
+ @variables[variable.name] = variable
60
+ end
61
+
62
+ # Resets the dude
63
+ def reset
64
+ reset_commands
65
+ reset_variables
66
+ end
67
+
68
+ # Outputs something use dude-formatting
69
+ def say something
70
+ puts dude_format something
71
+ end
72
+
73
+ private
74
+
75
+ # @return [String] Applies angry dude formatting for error messages
76
+ def angry_dude_format string
77
+ string
78
+ end
79
+
80
+ # Returns the arguments for a question based on the specified command
81
+ #
82
+ # @param [String] question The question
83
+ # @param [TheDude::Command] command The command
84
+ #
85
+ # @return [Array] An array of arguments
86
+ def arguments_for question, command
87
+ question.scan(command.question)[0]
88
+ end
89
+
90
+ # @return [String] Applies dude formatting
91
+ def dude_format string
92
+ string
93
+ end
94
+
95
+ # Returns the command for answering the specified question
96
+ #
97
+ # @param [String] question The question asked
98
+ #
99
+ # @return [TheDude::Command]
100
+ def find_command_for question
101
+ # if there's an exact match return that first
102
+ return commands[question] if commands[question]
103
+
104
+ commands.each do |key, val|
105
+ if key.kind_of? Regexp
106
+ return val if key =~ question
107
+ end
108
+ end
109
+
110
+ return false
111
+ end
112
+
113
+ # Resets the collection of commands
114
+ def reset_commands
115
+ @commands = {}
116
+ end
117
+
118
+ # Resets the collection of commands
119
+ def reset_variables
120
+ @variables = {}
121
+ end
122
+
123
+ end
124
+
125
+ class UndefinedVariableError < Exception; end
126
+ end
127
+
128
+ require 'the_dude/setup' # Load default commands and variables
@@ -0,0 +1,61 @@
1
+ module TheDude
2
+ class Command
3
+ # [String | Regexp] The question for this command
4
+ attr_reader :question
5
+
6
+ # [String | Proc | Block] The answer for this command
7
+ attr_accessor :answer
8
+
9
+ # Initializes a new command.
10
+ #
11
+ # An instance is created to hold the details of the command and the command
12
+ # is registered in TheDude.commands using the provided key. The answer can
13
+ # be a string, proc or block. If both a string/proc and block are passed,
14
+ # the block will take precedence.
15
+ #
16
+ # @example
17
+ #
18
+ # command = TheDude::Command.new 'hello', 'hello'
19
+ # TheDude.commands['hello'] == command # true
20
+ #
21
+ # TheDude::Command.new 'hello' do
22
+ # puts 'hello'
23
+ # puts 'how are you?'
24
+ # end
25
+ #
26
+ # @param [String | Regexp] question the question to ask
27
+ # @param [String | Proc] answer the answer to the question
28
+ #
29
+ # @return [TheDude::Command]
30
+ def initialize question, answer=nil, &block_answer
31
+ @question = Expression.new(question).to_regex
32
+ @answer = block_answer || answer
33
+
34
+ TheDude.register_command self
35
+ end
36
+
37
+ # Asks the question with the specified arguments. If the answer is a string
38
+ # it is returned. If it is a proc or block it is evaluated with the passed
39
+ # parameters.
40
+ def ask *args
41
+ begin
42
+ if answer.kind_of? Proc
43
+ instance_exec(*args, &answer)
44
+ else
45
+ answer
46
+ end
47
+ rescue SystemExit
48
+ exit
49
+ rescue Interrupt
50
+ TheDude.say 'Fine, i\'ll leave it then'
51
+ rescue Exception => e
52
+ TheDude.complain "Man, what are you doing? Look what you just did\n
53
+ #{e.class}
54
+ #{e.message}
55
+ #{e.backtrace}
56
+ At least you didn't pee on my rug I guess
57
+ "
58
+ end
59
+ end
60
+ end
61
+ end