abt-cli 0.0.21 → 0.0.26

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 +11 -6
  4. data/lib/abt/ari.rb +1 -1
  5. data/lib/abt/ari_list.rb +1 -1
  6. data/lib/abt/base_command.rb +7 -7
  7. data/lib/abt/cli.rb +55 -49
  8. data/lib/abt/cli/arguments_parser.rb +5 -9
  9. data/lib/abt/cli/global_commands.rb +23 -0
  10. data/lib/abt/cli/global_commands/commands.rb +2 -2
  11. data/lib/abt/cli/global_commands/examples.rb +2 -2
  12. data/lib/abt/cli/global_commands/help.rb +2 -2
  13. data/lib/abt/cli/global_commands/readme.rb +2 -2
  14. data/lib/abt/cli/global_commands/share.rb +6 -6
  15. data/lib/abt/cli/global_commands/version.rb +2 -2
  16. data/lib/abt/cli/prompt.rb +71 -56
  17. data/lib/abt/directory_config.rb +25 -0
  18. data/lib/abt/docs.rb +39 -33
  19. data/lib/abt/docs/cli.rb +3 -3
  20. data/lib/abt/docs/markdown.rb +10 -7
  21. data/lib/abt/git_config.rb +4 -6
  22. data/lib/abt/helpers.rb +26 -8
  23. data/lib/abt/providers/asana/api.rb +9 -9
  24. data/lib/abt/providers/asana/base_command.rb +12 -10
  25. data/lib/abt/providers/asana/commands/add.rb +13 -12
  26. data/lib/abt/providers/asana/commands/branch_name.rb +8 -8
  27. data/lib/abt/providers/asana/commands/clear.rb +7 -8
  28. data/lib/abt/providers/asana/commands/current.rb +14 -15
  29. data/lib/abt/providers/asana/commands/finalize.rb +17 -14
  30. data/lib/abt/providers/asana/commands/harvest_time_entry_data.rb +18 -16
  31. data/lib/abt/providers/asana/commands/init.rb +8 -41
  32. data/lib/abt/providers/asana/commands/pick.rb +22 -26
  33. data/lib/abt/providers/asana/commands/projects.rb +5 -5
  34. data/lib/abt/providers/asana/commands/share.rb +5 -5
  35. data/lib/abt/providers/asana/commands/start.rb +28 -21
  36. data/lib/abt/providers/asana/commands/tasks.rb +6 -6
  37. data/lib/abt/providers/asana/configuration.rb +45 -29
  38. data/lib/abt/providers/asana/path.rb +6 -6
  39. data/lib/abt/providers/devops/api.rb +12 -12
  40. data/lib/abt/providers/devops/base_command.rb +14 -10
  41. data/lib/abt/providers/devops/commands/boards.rb +5 -7
  42. data/lib/abt/providers/devops/commands/branch_name.rb +9 -9
  43. data/lib/abt/providers/devops/commands/clear.rb +7 -8
  44. data/lib/abt/providers/devops/commands/current.rb +17 -18
  45. data/lib/abt/providers/devops/commands/harvest_time_entry_data.rb +21 -19
  46. data/lib/abt/providers/devops/commands/init.rb +21 -14
  47. data/lib/abt/providers/devops/commands/pick.rb +37 -19
  48. data/lib/abt/providers/devops/commands/share.rb +5 -5
  49. data/lib/abt/providers/devops/commands/{work-items.rb → work_items.rb} +3 -3
  50. data/lib/abt/providers/devops/configuration.rb +15 -15
  51. data/lib/abt/providers/devops/path.rb +7 -6
  52. data/lib/abt/providers/git/commands/branch.rb +23 -21
  53. data/lib/abt/providers/harvest/api.rb +8 -8
  54. data/lib/abt/providers/harvest/base_command.rb +10 -8
  55. data/lib/abt/providers/harvest/commands/clear.rb +7 -8
  56. data/lib/abt/providers/harvest/commands/current.rb +13 -14
  57. data/lib/abt/providers/harvest/commands/init.rb +10 -39
  58. data/lib/abt/providers/harvest/commands/pick.rb +15 -11
  59. data/lib/abt/providers/harvest/commands/projects.rb +5 -5
  60. data/lib/abt/providers/harvest/commands/share.rb +5 -5
  61. data/lib/abt/providers/harvest/commands/start.rb +5 -3
  62. data/lib/abt/providers/harvest/commands/stop.rb +12 -12
  63. data/lib/abt/providers/harvest/commands/tasks.rb +7 -7
  64. data/lib/abt/providers/harvest/commands/track.rb +52 -37
  65. data/lib/abt/providers/harvest/configuration.rb +18 -18
  66. data/lib/abt/providers/harvest/path.rb +6 -6
  67. data/lib/abt/version.rb +1 -1
  68. metadata +7 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce59010855d53bf8b8731a680d7adcd21cef4eb93d421174aee893f27350cb1e
4
- data.tar.gz: 8ac30f3ada5fcc7c75f7a9a91110340d579fd79d8c6226dd4f92a24bdf070d88
3
+ metadata.gz: ed527a89749355f223b94daa60d63b91c78ae98ab6976c3470ec6ca42cbcff27
4
+ data.tar.gz: aed24bd58e30bfbbdc574532eb97044cd8e108851c2586ac407c0eb42a2deb28
5
5
  SHA512:
6
- metadata.gz: 0cdbbd886589a06d20281e67a8376b3292cd61e432b7b672c968e2c5730a65707cc60d31d179acdcd7ad2a5eab9ebffe15866e08f5001b1922f291007146038b
7
- data.tar.gz: d0e568a9db4e57207f1cd8d72c789fea3c456f282c6cc1b4a46694767317a0b5c4055d90d53903779c20cd7ecf3c5a0803b07ebafb03b9e07d5ed99f3be14a88
6
+ metadata.gz: 6d615f241ac406df5f89cc79ad36f19b0554602f6eb3e20e2f01ba0143595ea6e748c727ccedfeecd1a826c46e031acc7160a3b0ee7462027157a357d730de35
7
+ data.tar.gz: 2b9e500f77e181f4198ac17939fc1753f9a7105682783b005d780ec4da61c8af43aa3e986bba34e1df4f5173bde47bd0e97e042f293edb713a364d2a9c1c71b6
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
+ exit 130
12
12
  end
data/lib/abt.rb CHANGED
@@ -1,11 +1,12 @@
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
+ require "yaml"
9
10
 
10
11
  Dir.glob("#{File.dirname(File.absolute_path(__FILE__))}/abt/*.rb").sort.each do |file|
11
12
  require file
@@ -22,4 +23,8 @@ module Abt
22
23
  const_name = Helpers.command_to_const(scheme)
23
24
  Providers.const_get(const_name) if Providers.const_defined?(const_name)
24
25
  end
26
+
27
+ def self.directory_config
28
+ @directory_config ||= Abt::DirectoryConfig.new
29
+ end
25
30
  end
data/lib/abt/ari.rb CHANGED
@@ -14,7 +14,7 @@ module Abt
14
14
  str = scheme
15
15
  str += ":#{path}" if path
16
16
 
17
- [str, *flags].join(' ')
17
+ [str, *flags].join(" ")
18
18
  end
19
19
  end
20
20
  end
data/lib/abt/ari_list.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Abt
4
4
  class AriList < Array
5
5
  def to_s
6
- map(&:to_s).join(' -- ')
6
+ map(&:to_s).join(" -- ")
7
7
  end
8
8
 
9
9
  def -(other)
@@ -5,11 +5,11 @@ module Abt
5
5
  extend Forwardable
6
6
 
7
7
  def self.usage
8
- raise NotImplementedError, 'Command classes must implement .usage'
8
+ raise NotImplementedError, "Command classes must implement .usage"
9
9
  end
10
10
 
11
11
  def self.description
12
- raise NotImplementedError, 'Command classes must implement .description'
12
+ raise NotImplementedError, "Command classes must implement .description"
13
13
  end
14
14
 
15
15
  def self.flags
@@ -27,7 +27,7 @@ module Abt
27
27
  end
28
28
 
29
29
  def perform
30
- raise NotImplementedError, 'Command classes must implement #perform'
30
+ raise NotImplementedError, "Command classes must implement #perform"
31
31
  end
32
32
 
33
33
  private
@@ -41,18 +41,18 @@ module Abt
41
41
 
42
42
  result
43
43
  rescue OptionParser::InvalidOption => e
44
- abort e.message
44
+ abort(e.message)
45
45
  end
46
46
 
47
47
  def flag_parser
48
48
  @flag_parser ||= OptionParser.new do |opts|
49
49
  opts.banner = <<~TXT
50
- #{self.class.description}
50
+ #{self.class.description.strip}
51
51
 
52
- Usage: #{self.class.usage}
52
+ Usage: #{self.class.usage.strip}
53
53
  TXT
54
54
 
55
- opts.on('-h', '--help', 'Display this help')
55
+ opts.on("-h", "--help", "Display this help")
56
56
 
57
57
  self.class.flags.each do |(*flag)|
58
58
  opts.on(*flag)
data/lib/abt/cli.rb CHANGED
@@ -1,50 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Dir.glob("#{File.expand_path(__dir__)}/cli/**/*.rb").sort.each do |file|
3
+ Dir.glob("#{File.expand_path(__dir__)}/cli/*.rb").sort.each do |file|
4
4
  require file
5
5
  end
6
6
 
7
7
  module Abt
8
- class Cli
8
+ class Cli # rubocop:disable Metrics/ClassLength
9
9
  class Abort < StandardError; end
10
- class Exit < StandardError; end
11
-
12
- def self.global_command_names
13
- GlobalCommands.constants.sort.map { |constant_name| Helpers.const_to_command(constant_name) }
14
- end
15
-
16
- def self.global_command_class(name)
17
- name = 'help' if [nil, '-h', '--help'].include?(name)
18
- name = 'version' if ['-v', '--version'].include?(name)
19
10
 
20
- const_name = Helpers.command_to_const(name)
21
- return unless GlobalCommands.const_defined?(const_name)
22
-
23
- GlobalCommands.const_get(const_name)
24
- end
11
+ class Exit < StandardError; end
25
12
 
26
- attr_reader :command, :aris, :input, :output, :err_output, :prompt
13
+ attr_reader :command, :remaining_args, :input, :output, :err_output, :prompt
27
14
 
28
- def initialize(argv: ARGV, input: STDIN, output: STDOUT, err_output: STDERR)
29
- (@command, *remaining_args) = argv
15
+ def initialize(argv: ARGV, input: $stdin, output: $stdout, err_output: $stderr)
16
+ (@command, *@remaining_args) = argv
30
17
  @input = input
31
18
  @output = output
32
19
  @err_output = err_output
33
20
  @prompt = Abt::Cli::Prompt.new(output: err_output)
34
- @aris = ArgumentsParser.new(sanitized_piped_args + remaining_args).parse
35
21
  end
36
22
 
37
23
  def perform
38
24
  if command.nil?
39
25
  warn("No command specified, printing help\n\n")
40
- @command = 'help'
26
+ @command = "help"
41
27
  end
42
28
 
43
- if global_command?
44
- process_global_command
45
- else
46
- process_aris
47
- end
29
+ return process_alias if alias?
30
+ return process_global_command if global_command?
31
+
32
+ process_aris
48
33
  end
49
34
 
50
35
  def print_ari(scheme, path, description = nil)
@@ -73,8 +58,29 @@ module Abt
73
58
  raise Exit, message
74
59
  end
75
60
 
61
+ def aris
62
+ @aris ||= ArgumentsParser.new(sanitized_piped_args + remaining_args).parse
63
+ end
64
+
76
65
  private
77
66
 
67
+ def alias?
68
+ command[0] == "@"
69
+ end
70
+
71
+ def process_alias
72
+ matching_alias = Abt.directory_config.dig("aliases", command[1..-1])
73
+
74
+ abort("No such alias #{command}") if matching_alias.nil?
75
+
76
+ with_args = matching_alias.sub("$@", remaining_args.join(" "))
77
+ with_program_name = with_args.gsub("$0", $PROGRAM_NAME).strip
78
+ humanized = with_args.gsub("$0", "abt").strip
79
+
80
+ warn(humanized)
81
+ system(with_program_name)
82
+ end
83
+
78
84
  def global_command?
79
85
  return true if aris.empty?
80
86
  return true if aris.first.scheme.nil?
@@ -83,11 +89,9 @@ module Abt
83
89
  end
84
90
 
85
91
  def process_global_command
86
- command_class = self.class.global_command_class(command)
92
+ command_class = GlobalCommands.command_class(command)
87
93
 
88
- if command_class.nil?
89
- abort "No such global command: #{command}, perhaps you forgot to add an ARI?"
90
- end
94
+ abort("No such global command: #{command}, perhaps you forgot to add an ARI?") if command_class.nil?
91
95
 
92
96
  begin
93
97
  ari = aris.first || Abt::Ari.new
@@ -103,16 +107,14 @@ module Abt
103
107
  @sanitized_piped_args ||= begin
104
108
  input_string = input.read.strip
105
109
 
106
- abort 'No input from pipe' if input_string.nil? || input_string.empty?
110
+ abort("No input from pipe") if input_string.nil? || input_string.empty?
107
111
 
108
112
  # Exclude comment part of piped input lines
109
- lines_without_comments = input_string.lines.map do |line|
110
- line.split(' # ').first
111
- end
113
+ lines_without_comments = input_string.lines.map { |line| line.split(" # ").first }
112
114
 
113
115
  # Allow multiple ARIs on a single piped input line
114
116
  # TODO: Force the user to pick a single ARI
115
- joined_lines = lines_without_comments.join(' ').strip
117
+ joined_lines = lines_without_comments.join(" ").strip
116
118
  joined_lines.split(/\s+/)
117
119
  end
118
120
  end
@@ -122,26 +124,30 @@ module Abt
122
124
 
123
125
  aris.each do |ari|
124
126
  if used_schemes.include?(ari.scheme)
125
- warn "Dropping command for already used scheme: #{ari}"
127
+ warn("Dropping command for already used scheme: #{ari}")
126
128
  next
127
129
  end
128
130
 
129
- command_class = get_command_class(ari.scheme)
130
- next if command_class.nil?
131
-
132
- print_command(command, ari) if output.isatty
133
- begin
134
- command_class.new(ari: ari, cli: self).perform
135
- rescue Exit => e
136
- puts e.message
137
- end
138
-
139
- used_schemes << ari.scheme
131
+ used_schemes << ari.scheme if process_ari(ari)
140
132
  end
141
133
 
142
134
  return unless used_schemes.empty? && output.isatty
143
135
 
144
- abort 'No providers found for command and ARI(s)'
136
+ abort("No providers found for command and ARI(s)")
137
+ end
138
+
139
+ def process_ari(ari)
140
+ command_class = get_command_class(ari.scheme)
141
+ return false if command_class.nil?
142
+
143
+ print_command(command, ari) if output.isatty
144
+ begin
145
+ command_class.new(ari: ari, cli: self).perform
146
+ rescue Exit => e
147
+ puts e.message
148
+ end
149
+
150
+ true
145
151
  end
146
152
 
147
153
  def get_command_class(scheme)
@@ -152,7 +158,7 @@ module Abt
152
158
  end
153
159
 
154
160
  def print_command(name, ari)
155
- warn "===== #{name.upcase} #{ari} ====="
161
+ warn("===== #{name.upcase} #{ari} =====")
156
162
  end
157
163
  end
158
164
  end
@@ -13,15 +13,11 @@ module Abt
13
13
  result = AriList.new
14
14
  rest = arguments.dup
15
15
 
16
- # If the arguments start with "-" it means that we are parsing flags for a global command
17
- if rest.any? && rest.first[0] == '-'
18
- flags = take_flags(rest)
19
-
20
- return [Ari.new(flags: flags)]
21
- end
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)
22
18
 
23
19
  until rest.empty?
24
- (scheme, path) = rest.shift.split(':')
20
+ (scheme, path) = rest.shift.split(":")
25
21
  flags = take_flags(rest)
26
22
 
27
23
  result << Ari.new(scheme: scheme, path: path, flags: flags)
@@ -44,11 +40,11 @@ module Abt
44
40
  end
45
41
 
46
42
  def flag?(part)
47
- part && part[0] == '-'
43
+ part && part[0] == "-"
48
44
  end
49
45
 
50
46
  def delimiter?(part)
51
- part == '--'
47
+ part == "--"
52
48
  end
53
49
  end
54
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
@@ -5,11 +5,11 @@ module Abt
5
5
  module GlobalCommands
6
6
  class Commands < Abt::BaseCommand
7
7
  def self.usage
8
- 'abt commands'
8
+ "abt commands"
9
9
  end
10
10
 
11
11
  def self.description
12
- 'List all abt commands'
12
+ "List all abt commands"
13
13
  end
14
14
 
15
15
  attr_reader :cli
@@ -5,11 +5,11 @@ module Abt
5
5
  module GlobalCommands
6
6
  class Examples < Abt::BaseCommand
7
7
  def self.usage
8
- 'abt examples'
8
+ "abt examples"
9
9
  end
10
10
 
11
11
  def self.description
12
- 'Print command examples'
12
+ "Print command examples"
13
13
  end
14
14
 
15
15
  attr_reader :cli
@@ -5,11 +5,11 @@ module Abt
5
5
  module GlobalCommands
6
6
  class Help < Abt::BaseCommand
7
7
  def self.usage
8
- 'abt help'
8
+ "abt help"
9
9
  end
10
10
 
11
11
  def self.description
12
- 'Print abt usage text'
12
+ "Print abt usage text"
13
13
  end
14
14
 
15
15
  attr_reader :cli
@@ -5,11 +5,11 @@ module Abt
5
5
  module GlobalCommands
6
6
  class Readme < Abt::BaseCommand
7
7
  def self.usage
8
- 'abt readme'
8
+ "abt readme"
9
9
  end
10
10
 
11
11
  def self.description
12
- 'Print markdown readme'
12
+ "Print markdown readme"
13
13
  end
14
14
 
15
15
  attr_reader :cli
@@ -5,29 +5,29 @@ module Abt
5
5
  module GlobalCommands
6
6
  class Share < Abt::BaseCommand
7
7
  def self.usage
8
- 'abt share'
8
+ "abt share"
9
9
  end
10
10
 
11
11
  def self.description
12
- 'Prints all project configuration as a single line of ARIs'
12
+ "Prints all project configuration as a single line of ARIs"
13
13
  end
14
14
 
15
15
  attr_reader :cli
16
16
 
17
17
  def perform
18
- warn 'Printing project configuration'
18
+ warn("Printing project configuration")
19
19
  puts share_string
20
20
  end
21
21
 
22
22
  def share_string
23
23
  @share_string ||= begin
24
- aris = Abt.schemes.join(' ')
24
+ aris = Abt.schemes.join(" ")
25
25
 
26
26
  input = StringIO.new(aris)
27
27
  output = StringIO.new
28
- Abt::Cli.new(argv: ['share'], output: output, input: input).perform
28
+ Abt::Cli.new(argv: ["share"], output: output, input: input).perform
29
29
 
30
- output.string.strip.gsub(/\s+/, ' ')
30
+ output.string.strip.gsub(/\s+/, " ")
31
31
  end
32
32
  end
33
33
  end