abt-cli 0.0.18 → 0.0.23

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.
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