abt-cli 0.0.18 → 0.0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/bin/abt +3 -3
  3. data/lib/abt.rb +6 -6
  4. data/lib/abt/ari.rb +20 -0
  5. data/lib/abt/ari_list.rb +13 -0
  6. data/lib/abt/base_command.rb +63 -0
  7. data/lib/abt/cli.rb +51 -52
  8. data/lib/abt/cli/arguments_parser.rb +7 -26
  9. data/lib/abt/cli/global_commands.rb +23 -0
  10. data/lib/abt/cli/global_commands/commands.rb +23 -0
  11. data/lib/abt/cli/global_commands/examples.rb +23 -0
  12. data/lib/abt/cli/global_commands/help.rb +23 -0
  13. data/lib/abt/cli/global_commands/readme.rb +23 -0
  14. data/lib/abt/cli/global_commands/share.rb +36 -0
  15. data/lib/abt/cli/global_commands/version.rb +23 -0
  16. data/lib/abt/cli/prompt.rb +64 -51
  17. data/lib/abt/docs.rb +48 -25
  18. data/lib/abt/docs/cli.rb +3 -3
  19. data/lib/abt/docs/markdown.rb +11 -8
  20. data/lib/abt/git_config.rb +21 -39
  21. data/lib/abt/helpers.rb +26 -8
  22. data/lib/abt/providers/asana/api.rb +9 -9
  23. data/lib/abt/providers/asana/base_command.rb +20 -38
  24. data/lib/abt/providers/asana/commands/add.rb +18 -15
  25. data/lib/abt/providers/asana/commands/branch_name.rb +13 -8
  26. data/lib/abt/providers/asana/commands/clear.rb +8 -7
  27. data/lib/abt/providers/asana/commands/current.rb +22 -38
  28. data/lib/abt/providers/asana/commands/finalize.rb +17 -18
  29. data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +20 -13
  30. data/lib/abt/providers/asana/commands/init.rb +8 -41
  31. data/lib/abt/providers/asana/commands/pick.rb +27 -26
  32. data/lib/abt/providers/asana/commands/projects.rb +5 -5
  33. data/lib/abt/providers/asana/commands/share.rb +6 -8
  34. data/lib/abt/providers/asana/commands/start.rb +33 -24
  35. data/lib/abt/providers/asana/commands/tasks.rb +6 -5
  36. data/lib/abt/providers/asana/configuration.rb +46 -44
  37. data/lib/abt/providers/asana/path.rb +36 -0
  38. data/lib/abt/providers/devops/api.rb +23 -11
  39. data/lib/abt/providers/devops/base_command.rb +22 -43
  40. data/lib/abt/providers/devops/commands/boards.rb +5 -7
  41. data/lib/abt/providers/devops/commands/branch_name.rb +14 -10
  42. data/lib/abt/providers/devops/commands/clear.rb +8 -7
  43. data/lib/abt/providers/devops/commands/current.rb +24 -49
  44. data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +26 -16
  45. data/lib/abt/providers/devops/commands/init.rb +33 -26
  46. data/lib/abt/providers/devops/commands/pick.rb +23 -24
  47. data/lib/abt/providers/devops/commands/share.rb +7 -6
  48. data/lib/abt/providers/devops/commands/{work-items.rb → work_items.rb} +3 -3
  49. data/lib/abt/providers/devops/configuration.rb +27 -56
  50. data/lib/abt/providers/devops/path.rb +51 -0
  51. data/lib/abt/providers/git/commands/branch.rb +25 -19
  52. data/lib/abt/providers/harvest/api.rb +8 -8
  53. data/lib/abt/providers/harvest/base_command.rb +20 -36
  54. data/lib/abt/providers/harvest/commands/clear.rb +8 -7
  55. data/lib/abt/providers/harvest/commands/current.rb +27 -35
  56. data/lib/abt/providers/harvest/commands/init.rb +10 -40
  57. data/lib/abt/providers/harvest/commands/pick.rb +15 -12
  58. data/lib/abt/providers/harvest/commands/projects.rb +5 -5
  59. data/lib/abt/providers/harvest/commands/share.rb +6 -8
  60. data/lib/abt/providers/harvest/commands/start.rb +5 -3
  61. data/lib/abt/providers/harvest/commands/stop.rb +13 -13
  62. data/lib/abt/providers/harvest/commands/tasks.rb +9 -6
  63. data/lib/abt/providers/harvest/commands/track.rb +60 -38
  64. data/lib/abt/providers/harvest/configuration.rb +28 -37
  65. data/lib/abt/providers/harvest/path.rb +36 -0
  66. data/lib/abt/version.rb +1 -1
  67. metadata +18 -6
  68. data/lib/abt/cli/base_command.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df400d04c979d979ab2ead353d68374b8266c0fff678103991cc6443512b703b
4
- data.tar.gz: 0345141c38eae6904d11f40a3045fccd048d8009b70fe9714f5e0986f1779861
3
+ metadata.gz: 0a7665ad954a2011f10df120e0dd6ca13a0ab4ef9e0aea0338be4ec2e6cc62a3
4
+ data.tar.gz: 7c50793f7c8cf9d3d4fb88090dec2803691a4acfc931d39135aed85d0226b00f
5
5
  SHA512:
6
- metadata.gz: 1979110cbd58f0bc71b83ad7211b86e17c5b078e842d4f99ca839c88a88d627ab92506736cd83b6e414cbea2ec2a82592f6e8b3f1effdbd2b57df7decd63793e
7
- data.tar.gz: 6af0e9bb436b304cda9d3acf6c86733050c9a7acffb691017d968e89e3f4e8e51b9fa4cdf5e3a85373ff2f684fa61e41afce0c1b9011d2e6b5551935b40530ea
6
+ metadata.gz: 1db215088d055c4857f37ac01295afa0551d9ed88b11917971ff64ff8b8761db833422b9a52f83751e3b6cf476813fff205160d04443d7a8d7b0af21ce4d755c
7
+ data.tar.gz: 1e89308cc2a26401cfb5e06fd37dc2a80aef260a5bad6c0da0473e61d1469b92457bf14299dc823eca526326c3239ef1b060f0fd747d206ca55eb25a9ad6cf52
data/bin/abt CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative '../lib/abt.rb'
4
+ require_relative "../lib/abt"
5
5
 
6
6
  begin
7
7
  Abt::Cli.new.perform
8
8
  rescue Abt::Cli::Abort => e
9
- abort e.message
9
+ abort(e.message.strip)
10
10
  rescue Interrupt
11
- abort 'Aborted'
11
+ abort("Aborted")
12
12
  end
data/lib/abt.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-inflector'
4
- require 'faraday'
5
- require 'oj'
6
- require 'open3'
7
- require 'stringio'
8
- require 'optparse'
3
+ require "dry-inflector"
4
+ require "faraday"
5
+ require "oj"
6
+ require "open3"
7
+ require "stringio"
8
+ require "optparse"
9
9
 
10
10
  Dir.glob("#{File.dirname(File.absolute_path(__FILE__))}/abt/*.rb").sort.each do |file|
11
11
  require file
data/lib/abt/ari.rb ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ class Ari
5
+ attr_reader :scheme, :path, :flags
6
+
7
+ def initialize(scheme: nil, path: nil, flags: [])
8
+ @scheme = scheme
9
+ @path = path
10
+ @flags = flags
11
+ end
12
+
13
+ def to_s
14
+ str = scheme
15
+ str += ":#{path}" if path
16
+
17
+ [str, *flags].join(" ")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ class AriList < Array
5
+ def to_s
6
+ map(&:to_s).join(" -- ")
7
+ end
8
+
9
+ def -(other)
10
+ AriList.new(to_a - other)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ class BaseCommand
5
+ extend Forwardable
6
+
7
+ def self.usage
8
+ raise NotImplementedError, "Command classes must implement .usage"
9
+ end
10
+
11
+ def self.description
12
+ raise NotImplementedError, "Command classes must implement .description"
13
+ end
14
+
15
+ def self.flags
16
+ []
17
+ end
18
+
19
+ attr_reader :ari, :cli, :flags
20
+
21
+ def_delegators(:@cli, :warn, :puts, :print, :abort, :exit_with_message)
22
+
23
+ def initialize(ari:, cli:)
24
+ @cli = cli
25
+ @ari = ari
26
+ @flags = parse_flags(ari.flags)
27
+ end
28
+
29
+ def perform
30
+ raise NotImplementedError, "Command classes must implement #perform"
31
+ end
32
+
33
+ private
34
+
35
+ def parse_flags(flags)
36
+ result = {}
37
+
38
+ flag_parser.parse!(flags.dup, into: result)
39
+
40
+ exit_with_message(flag_parser.help) if result[:help]
41
+
42
+ result
43
+ rescue OptionParser::InvalidOption => e
44
+ abort(e.message)
45
+ end
46
+
47
+ def flag_parser
48
+ @flag_parser ||= OptionParser.new do |opts|
49
+ opts.banner = <<~TXT
50
+ #{self.class.description.strip}
51
+
52
+ Usage: #{self.class.usage.strip}
53
+ TXT
54
+
55
+ opts.on("-h", "--help", "Display this help")
56
+
57
+ self.class.flags.each do |(*flag)|
58
+ opts.on(*flag)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
data/lib/abt/cli.rb CHANGED
@@ -7,26 +7,31 @@ end
7
7
  module Abt
8
8
  class Cli
9
9
  class Abort < StandardError; end
10
+
10
11
  class Exit < StandardError; end
11
12
 
12
13
  attr_reader :command, :aris, :input, :output, :err_output, :prompt
13
14
 
14
- def initialize(argv: ARGV, input: STDIN, output: STDOUT, err_output: STDERR)
15
+ def initialize(argv: ARGV, input: $stdin, output: $stdout, err_output: $stderr)
15
16
  (@command, *remaining_args) = argv
16
17
  @input = input
17
18
  @output = output
18
19
  @err_output = err_output
19
20
  @prompt = Abt::Cli::Prompt.new(output: err_output)
20
-
21
21
  @aris = ArgumentsParser.new(sanitized_piped_args + remaining_args).parse
22
22
  end
23
23
 
24
24
  def perform
25
- return if handle_global_commands!
26
-
27
- abort('No ARIs') if aris.empty?
25
+ if command.nil?
26
+ warn("No command specified, printing help\n\n")
27
+ @command = "help"
28
+ end
28
29
 
29
- process_aris
30
+ if global_command?
31
+ process_global_command
32
+ else
33
+ process_aris
34
+ end
30
35
  end
31
36
 
32
37
  def print_ari(scheme, path, description = nil)
@@ -57,29 +62,23 @@ module Abt
57
62
 
58
63
  private
59
64
 
60
- def handle_global_commands!
61
- case command
62
- when nil
63
- warn("No command specified\n\n")
64
- puts(Abt::Docs::Cli.help)
65
- true
66
- when '--version', '-v', 'version'
67
- puts(Abt::VERSION)
68
- true
69
- when '--help', '-h', 'help'
70
- puts(Abt::Docs::Cli.help)
71
- true
72
- when 'commands'
73
- puts(Abt::Docs::Cli.commands)
74
- true
75
- when 'examples'
76
- puts(Abt::Docs::Cli.examples)
77
- true
78
- when 'readme'
79
- puts(Abt::Docs::Markdown.readme)
80
- true
81
- else
82
- false
65
+ def global_command?
66
+ return true if aris.empty?
67
+ return true if aris.first.scheme.nil?
68
+
69
+ false
70
+ end
71
+
72
+ def process_global_command
73
+ command_class = GlobalCommands.command_class(command)
74
+
75
+ abort("No such global command: #{command}, perhaps you forgot to add an ARI?") if command_class.nil?
76
+
77
+ begin
78
+ ari = aris.first || Abt::Ari.new
79
+ command_class.new(cli: self, ari: ari).perform
80
+ rescue Exit => e
81
+ puts e.message
83
82
  end
84
83
  end
85
84
 
@@ -89,47 +88,47 @@ module Abt
89
88
  @sanitized_piped_args ||= begin
90
89
  input_string = input.read.strip
91
90
 
92
- abort 'No input from pipe' if input_string.nil? || input_string.empty?
91
+ abort("No input from pipe") if input_string.nil? || input_string.empty?
93
92
 
94
93
  # Exclude comment part of piped input lines
95
- lines_without_comments = input_string.lines.map do |line|
96
- line.split(' # ').first
97
- end
94
+ lines_without_comments = input_string.lines.map { |line| line.split(" # ").first }
98
95
 
99
96
  # Allow multiple ARIs on a single piped input line
100
97
  # TODO: Force the user to pick a single ARI
101
- joined_lines = lines_without_comments.join(' ').strip
98
+ joined_lines = lines_without_comments.join(" ").strip
102
99
  joined_lines.split(/\s+/)
103
100
  end
104
101
  end
105
102
 
106
103
  def process_aris
107
104
  used_schemes = []
108
- aris.each do |ari|
109
- scheme = ari.scheme
110
- path = ari.path
111
105
 
112
- if used_schemes.include?(scheme)
113
- warn "Dropping command for already used scheme: #{ari}"
106
+ aris.each do |ari|
107
+ if used_schemes.include?(ari.scheme)
108
+ warn("Dropping command for already used scheme: #{ari}")
114
109
  next
115
110
  end
116
111
 
117
- command_class = get_command_class(scheme)
118
- next if command_class.nil?
119
-
120
- print_command(command, ari) if output.isatty
121
- begin
122
- command_class.new(path: path, cli: self, flags: ari.flags).perform
123
- rescue Exit => e
124
- puts e.message
125
- end
126
-
127
- used_schemes << scheme
112
+ used_schemes << ari.scheme if process_ari(ari)
128
113
  end
129
114
 
130
115
  return unless used_schemes.empty? && output.isatty
131
116
 
132
- abort 'No providers found for command and ARI(s)'
117
+ abort("No providers found for command and ARI(s)")
118
+ end
119
+
120
+ def process_ari(ari)
121
+ command_class = get_command_class(ari.scheme)
122
+ return false if command_class.nil?
123
+
124
+ print_command(command, ari) if output.isatty
125
+ begin
126
+ command_class.new(ari: ari, cli: self).perform
127
+ rescue Exit => e
128
+ puts e.message
129
+ end
130
+
131
+ true
133
132
  end
134
133
 
135
134
  def get_command_class(scheme)
@@ -140,7 +139,7 @@ module Abt
140
139
  end
141
140
 
142
141
  def print_command(name, ari)
143
- warn "===== #{name} #{ari} =====".upcase
142
+ warn("===== #{name.upcase} #{ari} =====")
144
143
  end
145
144
  end
146
145
  end
@@ -3,28 +3,6 @@
3
3
  module Abt
4
4
  class Cli
5
5
  class ArgumentsParser
6
- class Ari
7
- attr_reader :scheme, :path, :flags
8
-
9
- def initialize(scheme:, path:, flags:)
10
- @scheme = scheme
11
- @path = path
12
- @flags = flags
13
- end
14
-
15
- def to_s
16
- str = scheme
17
- str += ":#{path}" if path
18
-
19
- [str, *flags].join(' ')
20
- end
21
- end
22
- class Aris < Array
23
- def to_s
24
- map(&:to_s).join(' -- ')
25
- end
26
- end
27
-
28
6
  attr_reader :arguments
29
7
 
30
8
  def initialize(arguments)
@@ -32,11 +10,14 @@ module Abt
32
10
  end
33
11
 
34
12
  def parse
35
- result = Aris.new
13
+ result = AriList.new
36
14
  rest = arguments.dup
37
15
 
16
+ # If the first arg is a flag, it's for a global command
17
+ result << Ari.new(flags: take_flags(rest)) if flag?(rest.first)
18
+
38
19
  until rest.empty?
39
- (scheme, path) = rest.shift.split(':')
20
+ (scheme, path) = rest.shift.split(":")
40
21
  flags = take_flags(rest)
41
22
 
42
23
  result << Ari.new(scheme: scheme, path: path, flags: flags)
@@ -59,11 +40,11 @@ module Abt
59
40
  end
60
41
 
61
42
  def flag?(part)
62
- part && part[0] == '-'
43
+ part && part[0] == "-"
63
44
  end
64
45
 
65
46
  def delimiter?(part)
66
- part == '--'
47
+ part == "--"
67
48
  end
68
49
  end
69
50
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir.glob("#{File.expand_path(__dir__)}/global_commands/*.rb").sort.each { |file| require file }
4
+
5
+ module Abt
6
+ class Cli
7
+ module GlobalCommands
8
+ def self.command_names
9
+ constants.sort.map { |constant_name| Helpers.const_to_command(constant_name) }
10
+ end
11
+
12
+ def self.command_class(name)
13
+ name = "help" if [nil, "-h", "--help"].include?(name)
14
+ name = "version" if ["-v", "--version"].include?(name)
15
+
16
+ const_name = Helpers.command_to_const(name)
17
+ return unless const_defined?(const_name)
18
+
19
+ const_get(const_name)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ class Cli
5
+ module GlobalCommands
6
+ class Commands < Abt::BaseCommand
7
+ def self.usage
8
+ "abt commands"
9
+ end
10
+
11
+ def self.description
12
+ "List all abt commands"
13
+ end
14
+
15
+ attr_reader :cli
16
+
17
+ def perform
18
+ puts(Abt::Docs::Cli.commands)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ class Cli
5
+ module GlobalCommands
6
+ class Examples < Abt::BaseCommand
7
+ def self.usage
8
+ "abt examples"
9
+ end
10
+
11
+ def self.description
12
+ "Print command examples"
13
+ end
14
+
15
+ attr_reader :cli
16
+
17
+ def perform
18
+ puts(Abt::Docs::Cli.examples)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end