deadline 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 90c4f0b76dabddd32441f1ea3a77776df2c7e998
4
+ data.tar.gz: 2530f3a91a453b91247322f134ca2297e12359b7
5
+ SHA512:
6
+ metadata.gz: a9e0b6310b22bccb67a780d6701a37b05d9e251c321057b31afffa3c46a3f4fb8a3662c597a81e71f14f207b1ea1cda3197d895a08e82fbb81eb04f4974ddb24
7
+ data.tar.gz: ca9cb53649055637e5ef88bcfcdecd660a484651f5aae26ab9e236ce98d26441b696ea4e3b400c6e90273f0ae752bee4ed72b4974d84b0c8146e0dcc16e0e75c
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -cfs
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in deadline.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 kokubun
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Deadline
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'deadline'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install deadline
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ lib = File.dirname(__FILE__) + '/../lib'
5
+ $:.unshift lib unless $:.include? lib
6
+
7
+ require 'deadline'
8
+
9
+ Deadline::setup
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'deadline/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "deadline"
8
+ spec.version = Deadline::VERSION
9
+ spec.authors = ["ikstrm"]
10
+ spec.email = ["kokubun.t.aa@m.titech.ac.jp"]
11
+ spec.description = %q{Manage deadlines of your tasks and show timer for you}
12
+ spec.summary = %q{Manage deadlines of your tasks}
13
+ spec.homepage = "https://github.com/ikstrm/deadline"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = ["deadline"]
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "active_support"
25
+ spec.add_development_dependency "i18n"
26
+ spec.add_development_dependency "terminal-notifier"
27
+ end
@@ -0,0 +1,34 @@
1
+ require "deadline/version"
2
+ require "deadline/timer"
3
+ require "deadline/task"
4
+
5
+ module Deadline
6
+ def self.setup
7
+ case ARGV[0]
8
+ when "add"
9
+ if ARGV.size < 3
10
+ puts "Usage: deadline add TASK_NAME DEADLINE"
11
+ return
12
+ end
13
+ Task.add(task: ARGV[1], deadline: ARGV[2])
14
+ when "remove"
15
+ if ARGV.size < 2
16
+ puts "Usage: deadline remove (all|TASK_NUMBER)"
17
+ return
18
+ end
19
+ Task.remove(ARGV[1])
20
+ when "tasks"
21
+ Task.print_tasks
22
+ when "track"
23
+ Timer.track
24
+ else
25
+ print(<<-"EOS")
26
+ Usage:
27
+ deadline add TASK_NAME DEADLINE
28
+ deadline remove (all|TASK_NUMBER)
29
+ deadline tasks
30
+ deadline track
31
+ EOS
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,144 @@
1
+ require 'yaml'
2
+ require 'active_support/core_ext'
3
+ require 'terminal-notifier'
4
+
5
+ module Deadline
6
+ class Task
7
+ CONFIG_PATH = File.expand_path('~/.deadline/tasks.yml')
8
+
9
+ def self.all
10
+ conf = load_config
11
+ return unless conf
12
+ conf[:tasks]
13
+ end
14
+
15
+ def self.add(args = {})
16
+ return unless args[:task] && args[:deadline]
17
+
18
+ deadline_time = string_to_time(args[:deadline])
19
+ return unless deadline_time
20
+
21
+ new_task = {
22
+ task: args[:task],
23
+ deadline: deadline_time,
24
+ }
25
+ conf = load_config
26
+ if conf
27
+ conf[:tasks].push(new_task)
28
+ else
29
+ conf = Hash.new
30
+ conf[:tasks] = Array.new.push(new_task)
31
+ end
32
+ save_config(conf)
33
+ puts "New task: #{new_task[:task]}, #{new_task[:deadline]}"
34
+ end
35
+
36
+ def self.remove(target)
37
+ tasks = Task.all
38
+ return unless tasks
39
+
40
+ if target == "all"
41
+ save_config({tasks: []})
42
+ else
43
+ number = target.to_i
44
+ if number < tasks.size
45
+ tasks.delete_at(number)
46
+ conf = {
47
+ tasks: tasks
48
+ }
49
+ save_config(conf)
50
+ end
51
+ end
52
+ end
53
+
54
+ def self.refresh
55
+ tasks = Task.all
56
+ tasks.sort!{ |a, b| a[:deadline] <=> b [:deadline] }
57
+
58
+ new_tasks = Array.new
59
+ tasks.each do |task|
60
+ if task[:deadline] - Time.now > 0
61
+ new_tasks.push(task)
62
+ else
63
+ push_notify(task)
64
+ end
65
+ end
66
+
67
+ save_config({tasks: new_tasks})
68
+ end
69
+
70
+ def self.push_notify(task)
71
+ TerminalNotifier.notify(
72
+ nil,
73
+ title: 'Deadline end',
74
+ subtitle: task[:task]
75
+ )
76
+ end
77
+
78
+ def self.print_tasks
79
+ Task.refresh
80
+ tasks = Task.all
81
+ if tasks == nil || tasks.size == 0
82
+ puts "No task available"
83
+ return
84
+ end
85
+ tasks.each_with_index do |task, idx|
86
+ puts "Task #{idx}: #{task[:task]}, #{task[:deadline]}"
87
+ end
88
+ end
89
+
90
+ def self.load_config
91
+ path = File.expand_path('~/.deadline/')
92
+ if FileTest.exist?(path) == false
93
+ FileUtils.mkdir_p(path)
94
+ return nil
95
+ end
96
+
97
+ if FileTest.exist?(CONFIG_PATH)
98
+ str = nil
99
+ File.open(CONFIG_PATH, 'r') do |f|
100
+ str = f.read
101
+ end
102
+ YAML.load(str)
103
+ else
104
+ nil
105
+ end
106
+ end
107
+
108
+ def self.save_config(conf)
109
+ File.open(CONFIG_PATH, 'w') do |f|
110
+ f << conf.to_yaml
111
+ end
112
+ end
113
+
114
+ def self.string_to_time(string)
115
+ case string
116
+ when /^[0-9]+$/
117
+ Time.now + string.to_i * 60
118
+ when /^(([0-9]|)[0-9]):([0-9][0-9])$/
119
+ today_time = Time.local(
120
+ Date.today.year,
121
+ Date.today.month,
122
+ Date.today.day,
123
+ $1,
124
+ $3,
125
+ 0
126
+ )
127
+ if today_time - Time.now >= 0
128
+ today_time
129
+ else
130
+ tomorrow_time = Time.local(
131
+ Date.tomorrow.year,
132
+ Date.tomorrow.month,
133
+ Date.tomorrow.day,
134
+ $1,
135
+ $3,
136
+ 0
137
+ )
138
+ end
139
+ else
140
+ nil
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'curses'
3
+
4
+ module Deadline
5
+ LABEL_GREEN = 1
6
+ LABEL_RED = 2
7
+ LABEL_WHITE = 3
8
+
9
+ class Timer
10
+ def self.track
11
+ tasks = Task.all
12
+ if tasks == nil || tasks.size == 0
13
+ puts "No task available"
14
+ return
15
+ end
16
+
17
+ Curses.init_screen
18
+ Curses.start_color
19
+ Curses.init_pair LABEL_GREEN, Curses::COLOR_GREEN, Curses::COLOR_BLACK
20
+ Curses.init_pair LABEL_RED, Curses::COLOR_RED, Curses::COLOR_BLACK
21
+ Curses.init_pair LABEL_WHITE, Curses::COLOR_WHITE, Curses::COLOR_BLACK
22
+
23
+ loop do
24
+ Task.refresh
25
+ tasks = Task.all
26
+ if tasks.size == 0
27
+ Curses.close_screen
28
+ break
29
+ end
30
+
31
+ tasks.each_with_index do |task, idx|
32
+ last_time = ""
33
+ line_pos = Curses.lines / 2
34
+ if idx == 0
35
+ last_time = special_last_time_of(task)
36
+ else
37
+ line_pos += idx + 2
38
+ last_time = last_time_of(task)
39
+ end
40
+ task_str = "#{last_time} - #{task[:task]}"
41
+
42
+ Curses.setpos(line_pos, Curses.cols / 2 - (task_str.length / 2))
43
+ Curses.addstr(task_str)
44
+ end
45
+ Curses.attron(Curses.color_pair(LABEL_WHITE))
46
+
47
+ top_label = "【Latest Task】"
48
+ Curses.setpos(Curses.lines / 2 - 1, Curses.cols / 2 - (top_label.length / 2))
49
+ Curses.addstr(top_label)
50
+
51
+ if tasks.size > 1
52
+ top_label = "【Other Tasks】"
53
+ Curses.setpos(Curses.lines / 2 + 2, Curses.cols / 2 - (top_label.length / 2))
54
+ Curses.addstr(top_label)
55
+ end
56
+
57
+ Curses.refresh
58
+ sleep(1)
59
+ end
60
+ end
61
+
62
+ def self.special_last_time_of(task)
63
+ last_time = task[:deadline] - Time.now
64
+ hour = (last_time / 3600).to_i
65
+ min = ((last_time % 3600) / 60).to_i
66
+ sec = (last_time % 60).to_i
67
+ if hour > 0
68
+ Curses.attron(Curses.color_pair(LABEL_GREEN))
69
+ "%dhour %dmin %dsec" % [hour, min, sec]
70
+ elsif min > 10
71
+ Curses.attron(Curses.color_pair(LABEL_GREEN))
72
+ "%dmin %dsec" % [min, sec]
73
+ elsif min > 0
74
+ Curses.attron(Curses.color_pair(LABEL_RED))
75
+ "%dmin %dsec" % [min, sec]
76
+ else
77
+ Curses.attron(Curses.color_pair(LABEL_RED))
78
+ "%dsec" % sec
79
+ end
80
+ end
81
+
82
+ def self.last_time_of(task)
83
+ last_time = task[:deadline] - Time.now
84
+ hour = (last_time / 3600).to_i
85
+ min = ((last_time % 3600) / 60).to_i
86
+ sec = (last_time % 60).to_i
87
+ Curses.attron(Curses.color_pair(LABEL_WHITE))
88
+ "%02d:%02d:%02d" % [hour, min, sec]
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,3 @@
1
+ module Deadline
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ module Deadline
4
+ describe Task do
5
+ describe ".all" do
6
+ describe "given no config file" do
7
+ before do
8
+ path = File.expand_path('~/.deadline/tasks.yml')
9
+ if FileTest.exist?(path)
10
+ FileUtils.rm(path)
11
+ end
12
+ end
13
+
14
+ it "should return nil" do
15
+ tasks = Task.all
16
+ tasks.should == nil
17
+ end
18
+ end
19
+
20
+ describe "when config file exists" do
21
+ before do
22
+ path = File.expand_path('~/.deadline/')
23
+ if FileTest.exist?(path) == false
24
+ FileUtils.mkdir_p(path)
25
+ end
26
+
27
+ File.open(File.expand_path('~/.deadline/tasks.yml'), 'w') do |f|
28
+ f << { tasks: [{task: "test", deadline: "13:30"}] }.to_yaml
29
+ end
30
+ end
31
+
32
+ it "should return array" do
33
+ tasks = Task.all
34
+ tasks.should be_a_kind_of Array
35
+ end
36
+ end
37
+ end
38
+
39
+ describe ".add" do
40
+ before do
41
+ path = File.expand_path('~/.deadline/')
42
+ if FileTest.exist?(path) == false
43
+ FileUtils.mkdir_p(path)
44
+ end
45
+
46
+ File.open(File.expand_path('~/.deadline/tasks.yml'), 'w') do |f|
47
+ f << { tasks: [{task: "test", deadline: "13:30"}] }.to_yaml
48
+ end
49
+ end
50
+
51
+ describe "given a task name and valid time" do
52
+ it "should add a task to deadline" do
53
+ Task.add(task: "new task", deadline: "14:00")
54
+ array = Task.all
55
+ array.size.should == 2
56
+ end
57
+ end
58
+
59
+ describe "given invalid time" do
60
+ it "should not add a task" do
61
+ Task.add(task: "new task", deadline: "hoge")
62
+ array = Task.all
63
+ array.size.should == 1
64
+ end
65
+ end
66
+ end
67
+
68
+ describe ".remove" do
69
+ before do
70
+ path = File.expand_path('~/.deadline/')
71
+ if FileTest.exist?(path) == false
72
+ FileUtils.mkdir_p(path)
73
+ end
74
+
75
+ File.open(File.expand_path('~/.deadline/tasks.yml'), 'w') do |f|
76
+ f << { tasks: [
77
+ {task: "task1", deadline: "13:30"},
78
+ {task: "task2", deadline: "14:30"},
79
+ ] }.to_yaml
80
+ end
81
+ end
82
+
83
+ describe "given a number within range" do
84
+ it "should remove a specific task" do
85
+ Task.remove("1")
86
+ Task.all.size.should == 1
87
+ end
88
+ end
89
+
90
+ describe "given a number out of range" do
91
+ it "should do nothing" do
92
+ Task.remove("2")
93
+ Task.all.size.should == 2
94
+ end
95
+ end
96
+
97
+ describe "given 'all'" do
98
+ it "should remove all tasks" do
99
+ Task.remove("all")
100
+ Task.all.size.should == 0
101
+ end
102
+ end
103
+ end
104
+
105
+ describe ".refresh" do
106
+ describe "given disordered tasks" do
107
+ before do
108
+ Task.remove("all")
109
+ Task.add(task: "test1", deadline: "10")
110
+ Task.add(task: "test3", deadline: "30")
111
+ Task.add(task: "test2", deadline: "20")
112
+ end
113
+
114
+ it "should sort the tasks" do
115
+ Task.refresh
116
+ tasks = Task.all
117
+ tasks[0][:task].should == "test1"
118
+ tasks[1][:task].should == "test2"
119
+ tasks[2][:task].should == "test3"
120
+ end
121
+ end
122
+
123
+ describe "given an expired task" do
124
+ before do
125
+ Task.remove("all")
126
+
127
+ path = File.expand_path('~/.deadline/')
128
+ if FileTest.exist?(path) == false
129
+ FileUtils.mkdir_p(path)
130
+ end
131
+
132
+ File.open(File.expand_path('~/.deadline/tasks.yml'), 'w') do |f|
133
+ f << { tasks: [{
134
+ task: "test",
135
+ deadline: Time.local(2000,1,1,10,0,0)
136
+ }] }.to_yaml
137
+ end
138
+ end
139
+
140
+ it "should remove the task" do
141
+ Task.refresh
142
+ tasks = Task.all
143
+ tasks.size.should == 0
144
+ end
145
+
146
+ it "should push growl notification"
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Deadline
4
+ describe ".track" do
5
+ it "should start timer"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ require 'deadline'
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deadline
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - ikstrm
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: active_support
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: i18n
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: terminal-notifier
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Manage deadlines of your tasks and show timer for you
98
+ email:
99
+ - kokubun.t.aa@m.titech.ac.jp
100
+ executables:
101
+ - deadline
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - .rspec
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/deadline
112
+ - deadline.gemspec
113
+ - lib/deadline.rb
114
+ - lib/deadline/task.rb
115
+ - lib/deadline/timer.rb
116
+ - lib/deadline/version.rb
117
+ - spec/deadline/task_spec.rb
118
+ - spec/deadline/timer_spec.rb
119
+ - spec/spec_helper.rb
120
+ homepage: https://github.com/ikstrm/deadline
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.0.2
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Manage deadlines of your tasks
144
+ test_files:
145
+ - spec/deadline/task_spec.rb
146
+ - spec/deadline/timer_spec.rb
147
+ - spec/spec_helper.rb