mite.cmd 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.textile +162 -0
- data/Rakefile +33 -0
- data/TODO +4 -0
- data/VERSION +1 -0
- data/bin/mite +13 -0
- data/lib/mite_cmd.rb +34 -0
- data/lib/mite_cmd/application.rb +180 -0
- data/lib/mite_cmd/autocomplete.rb +48 -0
- data/lib/mite_ext.rb +53 -0
- data/lib/string_ext.rb +50 -0
- data/mite.cmd.gemspec +75 -0
- data/spec/mite_cmd/application_spec.rb +532 -0
- data/spec/mite_cmd/autocomplete_spec.rb +106 -0
- data/spec/mite_cmd_spec.rb +51 -0
- data/spec/mite_ext_spec.rb +99 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/string_ext_spec.rb +67 -0
- data/vendor/yolk-mite-rb-0.0.3/CHANGES.txt +11 -0
- data/vendor/yolk-mite-rb-0.0.3/LICENSE +20 -0
- data/vendor/yolk-mite-rb-0.0.3/README.textile +70 -0
- data/vendor/yolk-mite-rb-0.0.3/Rakefile +24 -0
- data/vendor/yolk-mite-rb-0.0.3/VERSION.yml +4 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite-rb.rb +105 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/customer.rb +9 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/project.rb +16 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/service.rb +7 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/time_entry.rb +54 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/time_entry_group.rb +36 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/tracker.rb +34 -0
- data/vendor/yolk-mite-rb-0.0.3/lib/mite/user.rb +19 -0
- metadata +92 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Overbryd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
<pre>
|
2
|
+
|
3
|
+
_ _
|
4
|
+
(_) | | |
|
5
|
+
_ __ ___ _| |_ ___ ___ _ __ ___ __| |
|
6
|
+
| '_ ` _ \| | __/ _ \ / __| '_ ` _ \ / _` |
|
7
|
+
| | | | | | | || __/| (__| | | | | | (_| |
|
8
|
+
|_| |_| |_|_|\__\___(_)___|_| |_| |_|\__,_|
|
9
|
+
|
10
|
+
</pre>
|
11
|
+
A simple command line interface for basic mite tasks.
|
12
|
+
|
13
|
+
* @mite.@ is an ingeniously sleek time tracking tool: http://mite.yo.lk
|
14
|
+
* @mite.cmd@ is a command line interface for it: http://github.com/Overbryd/mite.cmd
|
15
|
+
It provides a system wide command called @mite@.
|
16
|
+
|
17
|
+
h3. Installation instructions:
|
18
|
+
|
19
|
+
$ gem install Overbryd-mite.cmd
|
20
|
+
|
21
|
+
I assume github is in your gem sources. You may need @activesupport@ and @activeresource@ too.
|
22
|
+
|
23
|
+
$ gem install activesupport activeresource
|
24
|
+
|
25
|
+
h3. After installation instructions:
|
26
|
+
|
27
|
+
You'll need to configure the client prior using it.
|
28
|
+
To do this, you can just hammer into your console:
|
29
|
+
|
30
|
+
$ mite configure "Your Account Name" "Your API Key"
|
31
|
+
|
32
|
+
It will then generate a yml file in ~/.mite.yml with your account information.
|
33
|
+
|
34
|
+
The configure command also tries to install the bash auto completion hook into the following files: @~/.bash_completion@, @~/.bash_profile@, @~/.bash_login@, @~/.bashrc@.
|
35
|
+
|
36
|
+
If your system doesn't support one of the files above, install the hook by yourself.
|
37
|
+
In order to work as expected it needs bash to be configured for auto completion.
|
38
|
+
This is actually quite easy, just append this line to your bash config file.
|
39
|
+
|
40
|
+
complete -C "mite auto-complete" mite
|
41
|
+
|
42
|
+
You could use this command as an example (replace .bash_login with your bash configuration file):
|
43
|
+
|
44
|
+
$ echo "complete -C \"mite auto-complete\" mite" >> ~/.bash_login
|
45
|
+
|
46
|
+
h3. Create new time entries with ease:
|
47
|
+
|
48
|
+
$ mite "project name" "service name" "start time" "note"
|
49
|
+
|
50
|
+
$ mite "project name" "service name" "note"
|
51
|
+
|
52
|
+
$ mite "project name" "start time" "note"
|
53
|
+
|
54
|
+
$ mite "start time" "note"
|
55
|
+
|
56
|
+
h4. The magic of the moment err... start_time:
|
57
|
+
|
58
|
+
Append a @+@ to the start time and it will start the tracker.
|
59
|
+
|
60
|
+
The most convenient syntax to set the start time is @h:mm@. So it will accept all these kinds of values: @1:15@, @0:01@, @24:00@.
|
61
|
+
|
62
|
+
Short-hand for hours:
|
63
|
+
* @3+@ will set the start time to 3 hours, and start the tracker
|
64
|
+
* @3.5@ will set it to 3 hours 30 minutes
|
65
|
+
* @0.25+@ will make you look like a floating-point fetish, and start the tracker
|
66
|
+
|
67
|
+
h4. Examples:
|
68
|
+
|
69
|
+
$ mite "World Domination"
|
70
|
+
|
71
|
+
This will start a timer for the project World Domination.
|
72
|
+
|
73
|
+
$ mite HugEveryone 0:15
|
74
|
+
|
75
|
+
The time entry created by this command, is made for the project HugEveryone and is set to 15 minutes. No tracker will be started.
|
76
|
+
|
77
|
+
$ mite HugEveryone Love 1+
|
78
|
+
|
79
|
+
Start a time entry for the project HugEveryone with the service Love and set it to 1 hour. The tracker will be started, because of the @start time@ argument was suffixed with a @+@.
|
80
|
+
|
81
|
+
h4. Note:
|
82
|
+
|
83
|
+
If a project or a service doesn't exist it will be created.
|
84
|
+
You can omit one/some of the arguments, namely: @project name@, @service name@, @note@ or @start time@. But they have to be in order. So you can't set a @service name@ unless you specify a project. This will be fixed in future releases, till then, the arguments rely on their order.
|
85
|
+
|
86
|
+
h3. Amazing auto-completion:
|
87
|
+
|
88
|
+
This is very nifty. (But maybe you should read the After Installation Instructions before.)
|
89
|
+
The client was designed to save keystrokes, so I've baked in a very handy auto-completion feature. It even ignores the typed case.
|
90
|
+
|
91
|
+
Try this:
|
92
|
+
|
93
|
+
$ mite [tab]
|
94
|
+
|
95
|
+
It will try to auto-complete your projects.
|
96
|
+
|
97
|
+
$ mite Project1 [tab]
|
98
|
+
|
99
|
+
It will try to auto-complete your services.
|
100
|
+
|
101
|
+
$ mite Project1 "System Administration" [tab]
|
102
|
+
|
103
|
+
It will try to auto-complete common times!
|
104
|
+
|
105
|
+
$ mite Project1 "System Administration" 0:48 [tab]
|
106
|
+
|
107
|
+
It will try to auto-complete your notes!
|
108
|
+
|
109
|
+
h4. Amazingly fast auto-completion:
|
110
|
+
|
111
|
+
The auto-completion feature creates a cache in ~/.mite.cache, if you want to rebuild this cache just hit:
|
112
|
+
|
113
|
+
$ mite rebuild-cache
|
114
|
+
|
115
|
+
h4. Note: The first run without the cache might be a bit slow.
|
116
|
+
|
117
|
+
h3. Controlling timers:
|
118
|
+
|
119
|
+
$ mite start
|
120
|
+
|
121
|
+
This little cutey will start today's last time entry, if there is one.
|
122
|
+
|
123
|
+
$ mite stop
|
124
|
+
|
125
|
+
This will just stop the current timer. (If you like you can use `mite pause` or `mite lunch` too)
|
126
|
+
|
127
|
+
h3. Simple reports:
|
128
|
+
|
129
|
+
$ mite today
|
130
|
+
|
131
|
+
This will generate a report of today's activity, summarizing your earnings at the bottom.
|
132
|
+
|
133
|
+
$ mite yesterday
|
134
|
+
|
135
|
+
This will generate a report of yesterday's activity, summarizing your earnings and the total time at the bottom.
|
136
|
+
Also works using @this_week@, @last_week@, @this_month@, @last_month@ as argument.
|
137
|
+
|
138
|
+
h3. More simple stuff:
|
139
|
+
|
140
|
+
$ mite
|
141
|
+
|
142
|
+
If there is a running timer, it will output it. Otherwise you should better not listen to it.
|
143
|
+
|
144
|
+
$ mite +
|
145
|
+
|
146
|
+
Just create a new time entry and start tracking it.
|
147
|
+
|
148
|
+
$ mite open
|
149
|
+
|
150
|
+
Opens your mite account in a new browser window (Max OSX only) or prints the url to your account.
|
151
|
+
|
152
|
+
h3. Feature Request? Problems? Found a bug? Your girlfriend broke up with you?
|
153
|
+
|
154
|
+
Your problems are no longer "problems"! They are called issues now, and github has the solution.
|
155
|
+
|
156
|
+
If you want to tell me an idea, I'll happily take care of them in the issues tracker: http://github.com/Overbryd/mite.cmd/issues
|
157
|
+
|
158
|
+
|\3. **All time Highscore of people who were involved** |
|
159
|
+
| who? |\2. what? |
|
160
|
+
| Sebastian Munz (yolk) | 12 issues | found a lot of bugs, did some real use testing. Really cool, thank you! |
|
161
|
+
| Julia Soergel (juliasoergel) | 2 issues | found a bug and `I like your hairstyle!´ |
|
162
|
+
| Michael Bumann (burmi) | 2 issues | found two bugs and mentioned a security issue which is now fixed. Yea baby! |
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "mite.cmd"
|
8
|
+
gem.executables = "mite"
|
9
|
+
gem.summary = "A simple command line interface for basic mite tasks."
|
10
|
+
gem.email = "l.rieder@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/Overbryd/mite.cmd"
|
12
|
+
gem.description = "A simple command line interface for mite, a sleek time tracking webapp."
|
13
|
+
gem.authors = ["Lukas Rieder"]
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :spec do
|
20
|
+
spec_files = Dir.glob('spec/**/*_spec.rb').join(' ')
|
21
|
+
sh "spec #{spec_files} --format specdoc --color"
|
22
|
+
end
|
23
|
+
task :default => :spec
|
24
|
+
|
25
|
+
task :rcov do
|
26
|
+
sh "rake run_rcov && open coverage/index.html"
|
27
|
+
end
|
28
|
+
require 'spec/rake/spectask'
|
29
|
+
Spec::Rake::SpecTask.new(:run_rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
data/TODO
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.10
|
data/bin/mite
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
+
|
5
|
+
require 'mite_cmd'
|
6
|
+
|
7
|
+
begin
|
8
|
+
MiteCmd.calling_script = __FILE__
|
9
|
+
MiteCmd.run(ARGV)
|
10
|
+
rescue MiteCmd::Exception => e
|
11
|
+
puts "#{"Epic fail: #{e.message}".colorize(:color => :red, :background => :black)} Type `mite help` to get help."
|
12
|
+
exit(1)
|
13
|
+
end
|
data/lib/mite_cmd.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
Dir[File.join(File.dirname(__FILE__), *%w[.. vendor * lib])].each do |path|
|
3
|
+
$LOAD_PATH.unshift path
|
4
|
+
end
|
5
|
+
require 'mite-rb'
|
6
|
+
|
7
|
+
require 'string_ext'
|
8
|
+
require 'mite_ext'
|
9
|
+
require 'mite_cmd/application'
|
10
|
+
require 'mite_cmd/autocomplete'
|
11
|
+
|
12
|
+
module MiteCmd
|
13
|
+
BASH_COMPLETION = "complete -C \"mite auto-complete\" mite"
|
14
|
+
|
15
|
+
CONFIG_FILE = File.expand_path '~/.mite.yml'
|
16
|
+
|
17
|
+
mattr_accessor :calling_script
|
18
|
+
|
19
|
+
def self.load_configuration
|
20
|
+
if File.exist?(CONFIG_FILE)
|
21
|
+
configuration = YAML.load(File.read(CONFIG_FILE))
|
22
|
+
Mite.account = configuration[:account]
|
23
|
+
Mite.key = configuration[:apikey]
|
24
|
+
else
|
25
|
+
raise Exception.new("Configuration file is missing.")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.run(args)
|
30
|
+
Application.new(args).run
|
31
|
+
end
|
32
|
+
|
33
|
+
class Exception < StandardError; end
|
34
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'ftools'
|
2
|
+
|
3
|
+
module MiteCmd
|
4
|
+
class Application
|
5
|
+
TIME_FORMAT = /^(\d+(\.\d+)?:?\+?)|(\d+:\d+\+?)|\+$/
|
6
|
+
FLIRTS = [
|
7
|
+
'I like your hairstyle.', 'What a nice console you have.', 'My favorite color is red on black, monospaced.',
|
8
|
+
"What a lovely operation system this #{`uname`} is.", 'What about dinner tonight?', 'Your keystrokes are tingling.'
|
9
|
+
]
|
10
|
+
|
11
|
+
def initialize(arguments=[])
|
12
|
+
@arguments = arguments
|
13
|
+
MiteCmd.load_configuration unless ['configure', 'help'].include?(arguments.first)
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
if @arguments.first == 'open'
|
18
|
+
open_or_echo Mite.account_url
|
19
|
+
|
20
|
+
elsif @arguments.first == 'help'
|
21
|
+
open_or_echo 'http://github.com/Overbryd/mite.cmd'
|
22
|
+
|
23
|
+
elsif @arguments.first == 'configure'
|
24
|
+
raise MiteCmd::Exception.new('mite configure needs two arguments, the account name and the apikey') if @arguments.size < 3 # lol boobs, err... an ice cone!
|
25
|
+
write_configuration({:account => @arguments[1], :apikey => @arguments[2]})
|
26
|
+
tell("Couldn't set up bash completion. I'm terribly frustrated. Maybe 'mite help' helps out.") unless try_to_setup_bash_completion
|
27
|
+
|
28
|
+
elsif @arguments.first == 'auto-complete'
|
29
|
+
autocomplete = MiteCmd::Autocomplete.new(MiteCmd.calling_script)
|
30
|
+
autocomplete.completion_table = if File.exist?(cache_file)
|
31
|
+
Marshal.load File.read(cache_file)
|
32
|
+
else
|
33
|
+
rebuild_completion_table
|
34
|
+
end
|
35
|
+
autocomplete.suggestions.map(&:quote_if_spaced).each { |s| tell s }
|
36
|
+
|
37
|
+
elsif @arguments.first == 'rebuild-cache'
|
38
|
+
File.delete(cache_file) if File.exist? cache_file
|
39
|
+
rebuild_completion_table
|
40
|
+
tell 'The rebuilding of the cache has been done, Master. Your wish is my command.'
|
41
|
+
|
42
|
+
elsif ['today', 'yesterday', 'this_week', 'last_week', 'this_month', 'last_month'].include? @arguments.first
|
43
|
+
total_minutes = 0
|
44
|
+
total_revenue = Mite::TimeEntry.all(:params => {:at => @arguments.first, :user_id => 'current'}).each do |time_entry|
|
45
|
+
total_minutes += time_entry.minutes
|
46
|
+
tell time_entry.inspect
|
47
|
+
end.map(&:revenue).compact.sum
|
48
|
+
tell ("%s:%.2d" % [total_minutes/60, total_minutes-total_minutes/60*60]).colorize(:lightred) + ", " + ("%.2f $" % (total_revenue/100)).colorize(:lightgreen)
|
49
|
+
|
50
|
+
elsif ['stop', 'pause', 'lunch'].include? @arguments.first
|
51
|
+
if current_tracker = (Mite::Tracker.current ? Mite::Tracker.current.stop : nil)
|
52
|
+
tell current_tracker.time_entry.inspect
|
53
|
+
end
|
54
|
+
|
55
|
+
elsif @arguments.first == 'start'
|
56
|
+
if time_entry = Mite::TimeEntry.first(:params => {:at => 'today'})
|
57
|
+
time_entry.start_tracker
|
58
|
+
tell time_entry.inspect
|
59
|
+
else
|
60
|
+
tell "Oh my dear! I tried hard, but I could'nt find any time entry for today."
|
61
|
+
end
|
62
|
+
|
63
|
+
elsif (1..4).include?(@arguments.size)
|
64
|
+
attributes = {}
|
65
|
+
if time_string = @arguments.select { |a| a =~ TIME_FORMAT }.first
|
66
|
+
attributes[:minutes] = parse_minutes(time_string)
|
67
|
+
start_tracker = (time_string =~ /\+$/)
|
68
|
+
end
|
69
|
+
if project = find_or_create_project(@arguments.first)
|
70
|
+
attributes[:project_id] = project.id
|
71
|
+
end
|
72
|
+
if @arguments[1] && service = find_or_create_service(@arguments[1])
|
73
|
+
attributes[:service_id] = service.id
|
74
|
+
end
|
75
|
+
if note = parse_note(@arguments, time_string)
|
76
|
+
attributes[:note] = note
|
77
|
+
end
|
78
|
+
time_entry = Mite::TimeEntry.create attributes
|
79
|
+
time_entry.start_tracker if start_tracker
|
80
|
+
tell time_entry.inspect
|
81
|
+
|
82
|
+
elsif @arguments.size == 0
|
83
|
+
tell Mite::Tracker.current ? Mite::Tracker.current.inspect : flirt
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def say(what)
|
88
|
+
puts what
|
89
|
+
end
|
90
|
+
alias_method :tell, :say
|
91
|
+
|
92
|
+
def flirt
|
93
|
+
FLIRTS[rand(FLIRTS.size)]
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def find_or_create_project(name)
|
99
|
+
project = Mite::Project.first(:params => {:name => name})
|
100
|
+
return nil if name =~ TIME_FORMAT
|
101
|
+
project ? project : Mite::Project.create(:name => name)
|
102
|
+
end
|
103
|
+
|
104
|
+
def find_or_create_service(name)
|
105
|
+
service = Mite::Service.first(:params => {:name => name})
|
106
|
+
return nil if name =~ TIME_FORMAT
|
107
|
+
service ? service : Mite::Service.create(:name => name)
|
108
|
+
end
|
109
|
+
|
110
|
+
def parse_note(args, time_string)
|
111
|
+
if args[3]
|
112
|
+
args[3]
|
113
|
+
elsif time_string.nil? && args[2]
|
114
|
+
args[2]
|
115
|
+
elsif time_string && args[args.index(time_string)+1]
|
116
|
+
args[args.index(time_string)+1]
|
117
|
+
else
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def parse_minutes(string)
|
123
|
+
string = string.sub(/\+$/, '')
|
124
|
+
|
125
|
+
if string.blank?
|
126
|
+
0
|
127
|
+
elsif string =~ /^\d+:\d+$/
|
128
|
+
string.split(':').first.to_i*60 + string.split(':').last.to_i
|
129
|
+
elsif string =~ /^\d+(\.\d+)?:?$/
|
130
|
+
(string.to_f*60).to_i
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def rebuild_completion_table
|
135
|
+
completion_table = {
|
136
|
+
0 => Mite::Project.all.map(&:name),
|
137
|
+
1 => Mite::Service.all.map(&:name),
|
138
|
+
2 => ['0:05', '0:05+', '0:15', '0:15+', '0:30', '0:30+', '1:00', '1:00+'].map(&:quote),
|
139
|
+
3 => Mite::TimeEntry.all.map(&:note).compact
|
140
|
+
}
|
141
|
+
File.open(cache_file, 'w') { |f| Marshal.dump(completion_table, f) }
|
142
|
+
File.chmod(0600, cache_file)
|
143
|
+
completion_table
|
144
|
+
end
|
145
|
+
|
146
|
+
def cache_file
|
147
|
+
File.expand_path('~/.mite.cache')
|
148
|
+
end
|
149
|
+
|
150
|
+
def open_or_echo(open_argument)
|
151
|
+
exec "open '#{open_argument}' || echo '#{open_argument}'"
|
152
|
+
end
|
153
|
+
|
154
|
+
def write_configuration(config)
|
155
|
+
File.open(File.expand_path('~/.mite.yml'), 'w') do |f|
|
156
|
+
YAML.dump(config, f)
|
157
|
+
end
|
158
|
+
File.chmod(0600, File.expand_path('~/.mite.yml'))
|
159
|
+
end
|
160
|
+
|
161
|
+
def try_to_setup_bash_completion
|
162
|
+
bash_code = "\n\n#{MiteCmd::BASH_COMPLETION}"
|
163
|
+
|
164
|
+
['~/.bash_completion', '~/.bash_profile', '~/.bash_login', '~/.bashrc'].each do |file|
|
165
|
+
bash_config_file = File.expand_path file
|
166
|
+
next unless File.file?(bash_config_file)
|
167
|
+
unless File.read(bash_config_file) =~ /#{bash_code}/
|
168
|
+
File.open(bash_config_file, 'a') do |f|
|
169
|
+
f.puts bash_code
|
170
|
+
end
|
171
|
+
return true
|
172
|
+
else
|
173
|
+
return true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
return false
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|