dude-cli 1.0.0 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +8 -0
- data/.gitignore +0 -1
- data/.travis.yml +4 -3
- data/CHANGELOG.md +25 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +57 -50
- data/README.md +41 -25
- data/bin/dude +3 -2
- data/dude.gemspec +21 -19
- data/lib/dude.rb +14 -0
- data/lib/dude/commands.rb +24 -0
- data/lib/dude/commands/checkout.rb +21 -0
- data/lib/dude/commands/install.rb +57 -0
- data/lib/dude/commands/move.rb +15 -0
- data/lib/dude/commands/start.rb +29 -0
- data/lib/dude/commands/stop.rb +15 -0
- data/lib/dude/commands/tasks.rb +31 -0
- data/lib/dude/commands/track.rb +28 -0
- data/lib/dude/commands/version.rb +11 -0
- data/lib/dude/git.rb +5 -0
- data/lib/dude/git/checkout.rb +2 -16
- data/lib/dude/git/current_branch_name.rb +1 -2
- data/lib/dude/project_management/client.rb +25 -0
- data/lib/dude/project_management/entities/board.rb +9 -0
- data/lib/dude/project_management/entities/issue.rb +37 -0
- data/lib/dude/project_management/jira.rb +9 -0
- data/lib/dude/project_management/jira/client.rb +49 -0
- data/lib/dude/project_management/jira/get_current_tasks.rb +40 -0
- data/lib/dude/project_management/jira/get_task_name_by_id.rb +24 -0
- data/lib/dude/project_management/jira/move_task_to_list.rb +47 -0
- data/lib/dude/project_management/trello.rb +6 -0
- data/lib/dude/project_management/trello/checkout.rb +4 -0
- data/lib/dude/project_management/trello/client.rb +33 -0
- data/lib/dude/project_management/trello/get_current_tasks.rb +24 -0
- data/lib/dude/project_management/trello/get_lists.rb +15 -0
- data/lib/dude/project_management/trello/move_tasks_to_list.rb +14 -0
- data/lib/dude/settings.rb +6 -2
- data/lib/dude/time_trackers/toggl.rb +5 -0
- data/lib/dude/time_trackers/toggl/base.rb +18 -0
- data/lib/dude/{toggl → time_trackers/toggl}/start_time_entry.rb +14 -8
- data/lib/dude/{toggl → time_trackers/toggl}/stop_time_entry.rb +4 -2
- data/lib/dude/version.rb +1 -1
- metadata +72 -89
- data/LICENSE.txt +0 -21
- data/lib/dude/cli.rb +0 -156
- data/lib/dude/gitlab/add_spend_time.rb +0 -36
- data/lib/dude/gitlab/base.rb +0 -38
- data/lib/dude/gitlab/count_spend_time.rb +0 -13
- data/lib/dude/gitlab/estimate.rb +0 -20
- data/lib/dude/gitlab/get_issue_info.rb +0 -9
- data/lib/dude/gitlab/get_issue_time_spent.rb +0 -9
- data/lib/dude/gitlab/get_issue_title.rb +0 -14
- data/lib/dude/gitlab/get_my_issues.rb +0 -31
- data/lib/dude/gitlab/move_issue.rb +0 -37
- data/lib/dude/interface.rb +0 -98
- data/lib/dude/report.rb +0 -38
- data/lib/dude/service.rb +0 -18
- data/lib/dude/toggl.rb +0 -40
- data/lib/dude/toggl/base.rb +0 -28
- data/lib/dude/toggl/issue_spend_time.rb +0 -59
- data/lib/dude/toggl/report.rb +0 -25
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2017 Nikita Pupko
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
data/lib/dude/cli.rb
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
require 'thor'
|
2
|
-
require 'colorize'
|
3
|
-
require 'gitlab'
|
4
|
-
require 'git'
|
5
|
-
require 'rest_client'
|
6
|
-
|
7
|
-
require 'dude/service'
|
8
|
-
require 'dude/settings'
|
9
|
-
require 'dude/interface'
|
10
|
-
require 'dude/report'
|
11
|
-
require 'dude/version'
|
12
|
-
|
13
|
-
require 'dude/git/checkout'
|
14
|
-
require 'dude/git/current_branch_name'
|
15
|
-
|
16
|
-
require 'dude/gitlab/base'
|
17
|
-
require 'dude/gitlab/estimate'
|
18
|
-
require 'dude/gitlab/add_spend_time'
|
19
|
-
require 'dude/gitlab/get_issue_title'
|
20
|
-
require 'dude/gitlab/get_issue_info'
|
21
|
-
require 'dude/gitlab/move_issue'
|
22
|
-
require 'dude/gitlab/get_my_issues'
|
23
|
-
require 'dude/gitlab/count_spend_time'
|
24
|
-
|
25
|
-
require 'dude/toggl/base'
|
26
|
-
require 'dude/toggl/report'
|
27
|
-
require 'dude/toggl/issue_spend_time'
|
28
|
-
require 'dude/toggl/start_time_entry'
|
29
|
-
require 'dude/toggl/stop_time_entry'
|
30
|
-
|
31
|
-
module Dude
|
32
|
-
class CLI < Thor
|
33
|
-
include Settings
|
34
|
-
desc 'install', 'create .duderc file in your home directory'
|
35
|
-
def install
|
36
|
-
path = File.join(Dir.home, Settings::CONFIG_FILE)
|
37
|
-
if File.exist?(path)
|
38
|
-
puts "Config file already exists"
|
39
|
-
else
|
40
|
-
File.open(path, 'w') {|f| f.write(duderc_file_content) }
|
41
|
-
puts ".duderc created in your HOME directory"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
desc 'checkout [ISSUE_ID]', 'checkout to branch with name "ID-issue-title"'
|
46
|
-
def checkout(issue_id, project_title = folder_name)
|
47
|
-
issue_title = get_issue_title(issue_id, project_title)
|
48
|
-
branch_name = branch_name_for_issue(issue_title, issue_id)
|
49
|
-
Dude::Git::Checkout.call(branch_name: branch_name)
|
50
|
-
end
|
51
|
-
|
52
|
-
desc 'start [ISSUE_ID]', 'do checkout, track and move actions'
|
53
|
-
def start(issue_id, project_title = folder_name)
|
54
|
-
checkout(issue_id, project_title)
|
55
|
-
track(issue_id, project_title)
|
56
|
-
move('Doing', issue_id, project_title)
|
57
|
-
end
|
58
|
-
|
59
|
-
desc 'track [ISSUE_ID]', 'start task in Toggl with issue title'
|
60
|
-
def track(issue_id, project_title = folder_name)
|
61
|
-
issue_title = get_issue_title(issue_id, project_title)
|
62
|
-
Dude::Toggl::StartTimeEntry.call(
|
63
|
-
title: "#{issue_title} (##{issue_id})", project_title: project_title
|
64
|
-
)
|
65
|
-
end
|
66
|
-
|
67
|
-
desc 'tasks', 'Show issues in current project assigned to you'
|
68
|
-
def tasks(project_title = folder_name)
|
69
|
-
issues = Dude::Gitlab::GetMyIssues.call(project_title: project_title)
|
70
|
-
Interface.new.issues_list(issues)
|
71
|
-
end
|
72
|
-
|
73
|
-
desc 'estimate [DURATION] [ISSUE_ID]', 'estimate time'
|
74
|
-
def estimate(duration, issue_id = current_issue_id, project_title = folder_name)
|
75
|
-
Dude::Gitlab::Estimate.call(issue_id: issue_id, project_title: project_title, duration: duration)
|
76
|
-
end
|
77
|
-
|
78
|
-
desc 'spend [ISSUE_ID]', 'spend time'
|
79
|
-
def spend(issue_id = current_issue_id, project_title = folder_name)
|
80
|
-
old_data = Dude::Gitlab::CountSpendTime.call(issue_id: issue_id, project_title: project_title)
|
81
|
-
new_data = Dude::Toggl::IssueSpendTime.call(issue_id: issue_id, project_title: project_title)
|
82
|
-
diff = new_data - old_data
|
83
|
-
Dude::Gitlab::AddSpendTime.call(duration: diff, issue_id: issue_id, project_title: project_title)
|
84
|
-
end
|
85
|
-
|
86
|
-
desc 'stop', 'stop current time entry in Toggl, move issue to `To Do`'
|
87
|
-
def stop(issue_id = current_issue_id, project_title = folder_name)
|
88
|
-
Dude::Toggl::StopTimeEntry.call
|
89
|
-
move('To Do', issue_id, project_title)
|
90
|
-
spend(issue_id, project_title)
|
91
|
-
puts 'Work suspended'.colorize(:yellow)
|
92
|
-
end
|
93
|
-
|
94
|
-
desc 'finish', 'stop current time entry in Toggl, move issue to `To Verify`'
|
95
|
-
def finish(issue_id = current_issue_id, project_title = folder_name)
|
96
|
-
Dude::Toggl::StopTimeEntry.call
|
97
|
-
move('To Verify', issue_id, project_title)
|
98
|
-
spend(current_issue_id, project_title)
|
99
|
-
puts "Issue ##{current_issue_id} finished".colorize(:green)
|
100
|
-
end
|
101
|
-
|
102
|
-
desc 'issue [ISSUE_ID]', 'Information about issue'
|
103
|
-
def issue(issue_id = current_issue_id, project_title = folder_name)
|
104
|
-
issue_info = Dude::Gitlab::GetIssueInfo.call(
|
105
|
-
issue_id: issue_id, project_title: project_title
|
106
|
-
)
|
107
|
-
Interface.new.draw_issue_info(issue_info)
|
108
|
-
end
|
109
|
-
|
110
|
-
desc 'stats', 'display your stats from Toggl'
|
111
|
-
def stats
|
112
|
-
report = Dude::Toggl::Report.call
|
113
|
-
Interface.new.draw_report(report)
|
114
|
-
end
|
115
|
-
|
116
|
-
desc 'move [LABEL] [ISSUE_ID]', 'move issue to another column'
|
117
|
-
def move(label, issue_id = current_issue_id, project_title = folder_name)
|
118
|
-
Dude::Gitlab::MoveIssue.call(
|
119
|
-
issue_id: issue_id, project_title: project_title, label: label
|
120
|
-
)
|
121
|
-
end
|
122
|
-
|
123
|
-
desc 'version', 'Show version'
|
124
|
-
def version
|
125
|
-
puts "Dude CLI v#{Dude::VERSION}"
|
126
|
-
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
def git(branch_name)
|
131
|
-
Git.new(branch_name: branch_name)
|
132
|
-
end
|
133
|
-
|
134
|
-
def current_issue_id
|
135
|
-
Dude::Git::CurrentBranchName.call.chomp.split('-').first
|
136
|
-
end
|
137
|
-
|
138
|
-
def get_issue_title(issue_id, project_title)
|
139
|
-
Dude::Gitlab::GetIssueTitle.call(issue_id: issue_id, project_title: project_title)
|
140
|
-
end
|
141
|
-
|
142
|
-
def duderc_file_content
|
143
|
-
"TOGGL_EMAIL=\nTOGGL_TOKEN=\nTOGGL_WORKSPACE_ID=\n" \
|
144
|
-
"GITLAB_ENDPOINT=https://gitlab.yoursite.com/api/v4/\n" \
|
145
|
-
"GITLAB_TOKEN=\nHOURS_PER_DAY=8\nHOURS_PER_WEEK=40"
|
146
|
-
end
|
147
|
-
|
148
|
-
def folder_name
|
149
|
-
@folder_name ||= File.basename(Dir.getwd)
|
150
|
-
end
|
151
|
-
|
152
|
-
def branch_name_for_issue(issue_title, issue_id)
|
153
|
-
issue_title.downcase.gsub(/[^a-z0-9\-_]+/, '-').prepend("#{issue_id}-")
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Dude
|
2
|
-
module Gitlab
|
3
|
-
class AddSpendTime < Dude::Gitlab::Base
|
4
|
-
def call
|
5
|
-
if duration_exists?
|
6
|
-
add_spend_time
|
7
|
-
print_success_message
|
8
|
-
else
|
9
|
-
print_error_message
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def add_spend_time
|
14
|
-
::Gitlab.add_time_spent_on_issue(
|
15
|
-
project_id, options[:issue_id], "#{options[:duration]}s"
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
def duration_exists?
|
20
|
-
options[:duration] > 0
|
21
|
-
end
|
22
|
-
|
23
|
-
def print_success_message
|
24
|
-
puts "Added #{formatted_time} to spent time"
|
25
|
-
end
|
26
|
-
|
27
|
-
def print_error_message
|
28
|
-
puts "Nothing to add".colorize(:yellow)
|
29
|
-
end
|
30
|
-
|
31
|
-
def formatted_time
|
32
|
-
Time.at(options[:duration]).utc.strftime('%H:%M:%S').to_s.colorize(:green)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/dude/gitlab/base.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Dude
|
2
|
-
module Gitlab
|
3
|
-
class Base
|
4
|
-
include Service
|
5
|
-
include Settings
|
6
|
-
|
7
|
-
def initialize(*)
|
8
|
-
super
|
9
|
-
configure_gitlab
|
10
|
-
end
|
11
|
-
|
12
|
-
def check_input_data
|
13
|
-
throw_error if options[:issue_id].to_i.zero? || !issue_exists?
|
14
|
-
end
|
15
|
-
|
16
|
-
def throw_error
|
17
|
-
Interface.new.throw_error(options[:issue_id], options[:project_title])
|
18
|
-
end
|
19
|
-
|
20
|
-
def issue_exists?
|
21
|
-
!::Gitlab.issue(project_id, options[:issue_id]).nil?
|
22
|
-
rescue StandardError
|
23
|
-
nil
|
24
|
-
end
|
25
|
-
|
26
|
-
def project_id
|
27
|
-
@project_id ||= ::Gitlab.project_search(options[:project_title])[0]&.id
|
28
|
-
end
|
29
|
-
|
30
|
-
def configure_gitlab
|
31
|
-
::Gitlab.configure do |config|
|
32
|
-
config.endpoint = settings['GITLAB_ENDPOINT']
|
33
|
-
config.private_token = settings['GITLAB_TOKEN']
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/dude/gitlab/estimate.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Dude
|
2
|
-
module Gitlab
|
3
|
-
class Estimate < Dude::Gitlab::Base
|
4
|
-
def call
|
5
|
-
check_input_data
|
6
|
-
estimate_time
|
7
|
-
end
|
8
|
-
|
9
|
-
def estimate_time
|
10
|
-
::Gitlab.estimate_time_of_issue(project_id, options[:issue_id], options[:duration])
|
11
|
-
Interface.new.draw_time_estimate(options[:duration])
|
12
|
-
end
|
13
|
-
|
14
|
-
# def human_time_estimate
|
15
|
-
# ::Gitlab.issue(project_id, options[:issue_id]).
|
16
|
-
# to_h['time_stats']['human_time_estimate']
|
17
|
-
# end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Dude
|
2
|
-
module Gitlab
|
3
|
-
class GetMyIssues < Dude::Gitlab::Base
|
4
|
-
MAX_ISSUES_PER_PAGE = 300
|
5
|
-
|
6
|
-
def call
|
7
|
-
my_issues
|
8
|
-
end
|
9
|
-
|
10
|
-
def my_issues
|
11
|
-
all_issues_on_project.select {|a| a.last.eql?(user.id) }
|
12
|
-
end
|
13
|
-
|
14
|
-
def all_issues_on_project
|
15
|
-
::Gitlab.issues(project_id, per_page: MAX_ISSUES_PER_PAGE).map do |a|
|
16
|
-
[a.iid, a.title, a.labels, assignees_id(a)]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def user
|
21
|
-
@user ||= ::Gitlab.user
|
22
|
-
end
|
23
|
-
|
24
|
-
def assignees_id(issue)
|
25
|
-
issue&.assignees&.first['id']
|
26
|
-
rescue NoMethodError
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Dude
|
2
|
-
module Gitlab
|
3
|
-
class MoveIssue < Dude::Gitlab::Base
|
4
|
-
DEFAULT_LABELS = ['To Do', 'Doing', 'To Verify'].freeze
|
5
|
-
|
6
|
-
def call
|
7
|
-
check_input_data
|
8
|
-
move_issue
|
9
|
-
print_message
|
10
|
-
end
|
11
|
-
|
12
|
-
def move_issue
|
13
|
-
::Gitlab.edit_issue(project_id, options[:issue_id], labels_options)
|
14
|
-
end
|
15
|
-
|
16
|
-
def labels_options
|
17
|
-
{ labels: new_issue_labels }
|
18
|
-
end
|
19
|
-
|
20
|
-
def all_issue_labels
|
21
|
-
::Gitlab.issue(project_id, options[:issue_id]).labels
|
22
|
-
end
|
23
|
-
|
24
|
-
def default_issue_labels
|
25
|
-
all_issue_labels.reject {|e| DEFAULT_LABELS.include?(e)}
|
26
|
-
end
|
27
|
-
|
28
|
-
def new_issue_labels
|
29
|
-
default_issue_labels.push(options[:label]).join(',')
|
30
|
-
end
|
31
|
-
|
32
|
-
def print_message
|
33
|
-
puts "Issue ##{options[:issue_id]} moved to '#{options[:label]}'".colorize(:green)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/dude/interface.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'colorize'
|
2
|
-
require_relative 'settings'
|
3
|
-
|
4
|
-
module Dude
|
5
|
-
class Interface
|
6
|
-
include Settings
|
7
|
-
|
8
|
-
def draw_report(report)
|
9
|
-
@report = report
|
10
|
-
report_weekly
|
11
|
-
puts ''
|
12
|
-
report_daily
|
13
|
-
end
|
14
|
-
|
15
|
-
def throw_error(issue_id, project_title)
|
16
|
-
puts "Something went wrong. Please, check input data\n".colorize(:red) +
|
17
|
-
"Project: #{project_title.to_s.bold}\n" +
|
18
|
-
"Issue ID: #{issue_id.to_s.bold}"
|
19
|
-
exit
|
20
|
-
end
|
21
|
-
|
22
|
-
def draw_time_estimate(time)
|
23
|
-
puts "Changed time estimate to #{time.colorize(:green)}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def draw_issue_info(info)
|
27
|
-
issue_label = info['labels'].find do |label|
|
28
|
-
['To Do', 'Doing', 'To Verify'].include? label
|
29
|
-
end
|
30
|
-
|
31
|
-
issue_color = case issue_label
|
32
|
-
when 'To Do'
|
33
|
-
:yellow
|
34
|
-
when 'Doing'
|
35
|
-
:green
|
36
|
-
when 'To Verify'
|
37
|
-
:blue
|
38
|
-
end
|
39
|
-
|
40
|
-
puts "#{info['title']} ##{info['iid']}".colorize(issue_color).bold
|
41
|
-
puts "Status: ".colorize(:yellow) + "#{issue_label}"
|
42
|
-
puts "Estimated time: ".colorize(:yellow) +
|
43
|
-
"#{info['time_stats']['human_time_estimate']}"
|
44
|
-
puts "Spent time: ".colorize(:yellow) +
|
45
|
-
"#{info['time_stats']['human_total_time_spent'] || '0h'}"
|
46
|
-
puts "Link: ".colorize(:yellow) + "#{info['web_url']}"
|
47
|
-
end
|
48
|
-
|
49
|
-
def issues_list(issues)
|
50
|
-
[['To Do', :yellow], ['Doing', :green], ['To Verify', :blue]].each do |group, color|
|
51
|
-
puts "#{group}:".colorize(color).bold
|
52
|
-
grouped = issues.select {|i| i[2].include?(group)}
|
53
|
-
if grouped.length.zero?
|
54
|
-
puts 'Nothing'
|
55
|
-
else
|
56
|
-
grouped.each do |id, issue, labels|
|
57
|
-
puts "#{id}:".colorize(color) + " #{issue} #{labels.compact.to_s.gsub('"', "")}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
puts ''
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def report_weekly
|
67
|
-
puts "Week".colorize(:green).bold
|
68
|
-
# puts '-' * 15
|
69
|
-
puts " Worked:".colorize(:yellow).bold +
|
70
|
-
" #{seconds_to_time(@report.week_time_worked)} / " \
|
71
|
-
"#{@report.hours_without_weekends}:00:00 " \
|
72
|
-
"(#{@report.week_time_worked * 100 / 144000}%)"
|
73
|
-
puts " Time left:".colorize(:yellow).bold +
|
74
|
-
" #{seconds_to_time(144000 - @report.week_time_worked)}"
|
75
|
-
end
|
76
|
-
|
77
|
-
def report_daily
|
78
|
-
puts "Today".colorize(:green).bold
|
79
|
-
# puts '-' * 15
|
80
|
-
puts " Worked:".colorize(:yellow).bold +
|
81
|
-
" #{seconds_to_time(@report.today_time_worked)} / " \
|
82
|
-
" #{settings['HOURS_PER_DAY']}:00:00 " \
|
83
|
-
"(#{@report.today_time_worked * 100 / 28800}%)"
|
84
|
-
puts " Time left:".colorize(:yellow).bold +
|
85
|
-
" #{seconds_to_time(@report.seconds_for_today - @report.week_time_worked)}"
|
86
|
-
end
|
87
|
-
|
88
|
-
def seconds_to_time(s)
|
89
|
-
hms = [60,60].reduce([s]) { |m,o| m.unshift(m.shift.divmod(o)).flatten }
|
90
|
-
"#{sprintf '%02d', hms[0]}:#{sprintf '%02d', hms[1]}:#{sprintf '%02d', hms[2]}"
|
91
|
-
end
|
92
|
-
|
93
|
-
def term
|
94
|
-
term_size = IO.console.winsize
|
95
|
-
@terminal = OpenStruct.new(h: term_size[0], w: term_size[1])
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|