the_dude 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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