github_cli 0.4.1 → 0.4.2

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.
data/.travis.yml CHANGED
@@ -4,6 +4,11 @@ branches:
4
4
  only: master
5
5
  notifications:
6
6
  email:false
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: ruby-head
10
+ - jruby
11
+ - rbx-19mode
7
12
  rvm:
8
13
  - 1.9.2
9
14
  - 1.9.3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ 0.4.2 (July 12, 2012)
2
+
3
+ * Add 'did you mean' help for mistyped commands.
4
+ * Add utility function for finding common prefix.
5
+ * Extract command usage and completion classes.
6
+ * Fix bug with all commands listing.
7
+ * Add arguments parser for required and optional arguments.
8
+ * Add non-required argument parsing to repository creation.
9
+ * Add new error type for required arguments.
10
+ * Fix bug with creating authorizations.
11
+
1
12
  0.4.1 (June 28, 2012)
2
13
 
3
14
  * Add search api commands.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- github_cli (0.4.1)
4
+ github_cli (0.4.2)
5
5
  github_api (~> 0.6)
6
6
  thor
7
7
 
data/README.md CHANGED
@@ -41,6 +41,28 @@ This will setup a `.githubrc` configuration file in your home directory with
41
41
  all the global settings. During the install process you will be prompted for your
42
42
  `authentication token`.
43
43
 
44
+ ### Arguments
45
+
46
+ The required arguments come first as per command description, then follow the optional arguments inside a `params` flag.
47
+
48
+ You can create repository by supplying parameters in the following way:
49
+
50
+ ```shell
51
+ ghc repo create octokit --params=description:'Test repo for kitty.'
52
+ ```
53
+
54
+ To create repository inside organization:
55
+
56
+ ```shell
57
+ ghc repo create github/octokit --params=description:'Test repo for kitty.'
58
+ ```
59
+
60
+ To find out which options are required and optional type:
61
+
62
+ ```shell
63
+ ghc repo help create
64
+ ```
65
+
44
66
  ### Getting a list of commands
45
67
 
46
68
  You can list all GitHub APIs comamnds:
@@ -55,6 +77,38 @@ to limit returned results pass `pattern`
55
77
  $ ghc list re* # Returns all commands matching the pattern
56
78
  ```
57
79
 
80
+ ### Output Format
81
+
82
+ The API responses can be formatted as `csv`, `json`, `pretty`, `table`.
83
+
84
+ By default responses are in tabular format. Tables are available in `horizontal` and `vertical` mode. To enforce table display pass `:h` and `:v` respectively. Otherwise a default orientation will be picked depending on the request made and terminal size.
85
+
86
+ ```shell
87
+ ghc user get -u peter-murach --format=table:h
88
+
89
+ ┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳
90
+ ┃ type ┃ login ┃ public_… ┃ blog ┃ hireable ┃ followe… ┃ followi… ┃ location ┃ html_url ┃ name ┃
91
+ ┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋
92
+ ┃ User ┃ peter-m… ┃ 14 ┃ peter-m… ┃ false ┃ 18 ┃ 52 ┃ Sheffie… ┃ https:/… ┃ Piotr M… ┃
93
+ ┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻
94
+ ```
95
+
96
+ To get `csv` formatting for easy command piping do
97
+
98
+ ```shell
99
+ ghc repo ls -u wycats --format=csv
100
+ ```
101
+
102
+ ### Output Paging
103
+
104
+ By default all responses are paged. You can switch off paging by supplying `no-pager` flag.
105
+
106
+ ```shell
107
+ ghc --no-pager user ls -u wycats
108
+ ```
109
+
110
+ Also you can supply you preferred `pager`, otherwise the paging program is taken from environment variable PAGER if defined or defaults to "less".
111
+
58
112
  ### API
59
113
 
60
114
  Interact with git data:
@@ -73,6 +127,7 @@ Interact with issues:
73
127
  $ ghc issue
74
128
  $ ghc label
75
129
  $ ghc milestone
130
+ $ ghc comment
76
131
  ```
77
132
 
78
133
  Interact with repositories:
@@ -80,6 +135,7 @@ Interact with repositories:
80
135
  ```shell
81
136
  $ ghc repo
82
137
  $ ghc collab
138
+ $ ghc content
83
139
  $ ghc download
84
140
  $ ghc fork
85
141
  $ ghc hook
@@ -121,52 +177,6 @@ Interact with search:
121
177
  $ ghc search
122
178
  ```
123
179
 
124
- ### Output Format
125
-
126
- The API responses can be formatted as `csv`, `json`, `pretty`, `table`.
127
-
128
- By default responses are in tabular format. Tables are available in `horizontal` and `vertical` mode. To enforce table display pass `:h` and `:v` respectively. Otherwise a default orientation will be picked depending on the request made and terminal size.
129
-
130
- ```shell
131
- ghc user get -u peter-murach --format=table:h
132
-
133
- ┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳
134
- ┃ type ┃ login ┃ public_… ┃ blog ┃ hireable ┃ followe… ┃ followi… ┃ location ┃ html_url ┃ name ┃
135
- ┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━╋
136
- ┃ User ┃ peter-m… ┃ 14 ┃ peter-m… ┃ false ┃ 18 ┃ 52 ┃ Sheffie… ┃ https:/… ┃ Piotr M… ┃
137
- ┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┻
138
- ```
139
-
140
- To get `csv` formatting for easy command piping do
141
-
142
- ```shell
143
- ghc repo ls -u wycats --format=csv
144
- ```
145
-
146
- ### Output Paging
147
-
148
- By default all responses are paged. You can switch off paging by supplying `no-pager` flag.
149
-
150
- ```shell
151
- ghc --no-pager user ls -u wycats
152
- ```
153
-
154
- Also you can supply you preferred `pager`, otherwise the paging program is taken from environment variable PAGER if defined or defaults to "less".
155
-
156
- ### Examples
157
-
158
- You can create repository by supplying required parameters
159
-
160
- ```shell
161
- ghc repo create --params=name:'octocat' description:'Test repo for kitty.'
162
- ```
163
-
164
- To find out which options are required type
165
-
166
- ```shell
167
- ghc repo help create
168
- ```
169
-
170
180
  ## Contributing
171
181
 
172
182
  1. Fork it
@@ -0,0 +1,32 @@
1
+ Feature: Command Completion
2
+
3
+ Scenario: Suggest alternative
4
+
5
+ When I run `ghc blah`
6
+ Then the exit status should be 0
7
+ And the output should contain:
8
+ """
9
+ Did you mean this?
10
+ blob
11
+ """
12
+
13
+ Scenario: Suggest more than one
14
+
15
+ When I run `ghc convent`
16
+ Then the exit status should be 0
17
+ And the output should contain:
18
+ """
19
+ Did you mean this?
20
+ collab
21
+ commit
22
+ content
23
+ """
24
+
25
+ Scenario: Suggset nothing
26
+
27
+ When I run `ghc xen`
28
+ Then the exit status should be 0
29
+ And the output should not contain:
30
+ """
31
+ Did you mean this?
32
+ """
@@ -18,17 +18,6 @@ Feature: The GHC Executable
18
18
  | |
19
19
  | help |
20
20
 
21
- Scenario: Getting Usage for Commands
22
-
23
- When I run `ghc`
24
- Then the exit status should be 0
25
- And the output should contain "Usage: ghc"
26
- And the output should contain "[--config]"
27
- And the output should contain "[--no-color]"
28
- And the output should contain "[--no-pager]"
29
- And the output should contain "[--version]"
30
- And the output should contain "[--verbose]"
31
-
32
21
  Scenario Outline: Getting Subcommands
33
22
 
34
23
  When I run `ghc <command>`
@@ -1,6 +1,7 @@
1
1
  require 'fileutils'
2
2
 
3
3
  Before do
4
+ @aruba_timeout_seconds = 5
4
5
  @real_home = ENV['HOME']
5
6
  fake_home = File.join('/tmp', 'fakehome')
6
7
  FileUtils.rm_rf fake_home if File.exists? fake_home
@@ -0,0 +1,18 @@
1
+ Feature: Command Usage
2
+
3
+ Scenario: Getting Usage for Commands
4
+
5
+ When I run `ghc`
6
+ Then the exit status should be 0
7
+ And the output should contain "Usage: ghc"
8
+ And the output should contain "[--config]"
9
+ And the output should contain "[--no-color]"
10
+ And the output should contain "[--no-pager]"
11
+ And the output should contain "[--version]"
12
+ And the output should contain "[--verbose]"
13
+
14
+ Scenario: Specific usage for command
15
+
16
+ When I run `ghc repo`
17
+ Then the exit status should be 0
18
+ And the output should contain "repo <subcommand>"
data/github_cli.gemspec CHANGED
@@ -3,7 +3,7 @@ require File.expand_path('../lib/github_cli/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Piotr Murach"]
6
- gem.email = ["pmurach@gmail.com"]
6
+ gem.email = [""]
7
7
  gem.description = %q{CLI-based access to GitHub API v3}
8
8
  gem.summary = %q{github_cli is a set of tools that provide full command line access to GitHub API v3}
9
9
  gem.homepage = "http://github.com/peter-murach/github_cli"
@@ -4,10 +4,14 @@ module GithubCLI
4
4
  # The API class is the main entry point for creating GithubCLI APIs.
5
5
  class API
6
6
 
7
+ ENDPOINT = ''
8
+
7
9
  @@api = nil
8
10
 
9
11
  class << self
10
12
 
13
+ attr_reader :config
14
+
11
15
  def github_api
12
16
  @@api ||= begin
13
17
  @@api = configure_api
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ module GithubCLI
4
+ class Command
5
+ # Makes it easy to parse required and options arguments.
6
+ class Arguments
7
+
8
+ SEPARATOR = '/'
9
+
10
+ attr_reader :args
11
+
12
+ def initialize(args)
13
+ @args = args
14
+ end
15
+
16
+ # Returns seperated arguments
17
+ def parse
18
+ required, non_required = nil, nil
19
+
20
+ if !args.empty?
21
+ required = args
22
+ non_required, required = required.split('/', 2) if required.index('/')
23
+ else
24
+ raise RequiredArgumentMissingError, "No value provided for required argument"
25
+ end
26
+ [non_required, required]
27
+ end
28
+
29
+ # Returns a concise string representation of Arguments instance
30
+ #
31
+ def inspect
32
+ "#<#{self.class.inspect} @args=#{args.inspect}"
33
+ end
34
+
35
+ end # Arguments
36
+ end # Command
37
+ end # GithubCLI
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ module GithubCLI
4
+ # Provides command completion/suggestion for mistyped command or subcommand.
5
+ class Command
6
+ class Completion
7
+ include GithubCLI::Util
8
+
9
+ # Command to be looked up.
10
+ attr_accessor :command
11
+
12
+ def initialize(command)
13
+ @command = command
14
+ end
15
+
16
+ DEFAULT_INDENT = 8
17
+
18
+ # If there is more than one possible alternative, show all of them.
19
+ #
20
+ def find_command_possibilities
21
+ max_length = 1
22
+ commands = Command.all.select do |cmd|
23
+ prefix = Util.longest_common_prefix(command, cmd.namespace)
24
+ if !prefix.empty? && (prefix.length >= max_length)
25
+ max_length = prefix.length
26
+ cmd
27
+ end
28
+ end
29
+ commands.map(&:namespace).uniq.sort
30
+ end
31
+
32
+ # Options
33
+ # indent - Indent suggested commands by specified value.
34
+ #
35
+ def format_command_possibilities(options={})
36
+ possibilities = find_command_possibilities
37
+ string = ""
38
+ indent = options[:indent] || DEFAULT_INDENT
39
+ if possibilities.size >= 1
40
+ string << "\n\nDid you mean this?\n"
41
+ possibilities.each do |possibility|
42
+ string << " " * indent + "#{possibility}\n"
43
+ end
44
+ end
45
+ string
46
+ end
47
+
48
+ # Returns a concise string representation of Completion instance
49
+ #
50
+ def inspect
51
+ "#<#{self.class.inspect} @command=#{command.inspect}"
52
+ end
53
+
54
+ end # Completion
55
+ end # Command
56
+ end # GithubCLI
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ module GithubCLI
4
+ # Responsible for manipulating commands usage string.
5
+ class Command
6
+ class Usage
7
+
8
+ DEFAULT_INDENT = 11
9
+
10
+ # Returns command
11
+ attr_reader :command
12
+
13
+ # Returns command flags
14
+ attr_reader :flags
15
+
16
+ # Initializes an usage instance
17
+ #
18
+ def initialize(command, flags, options={})
19
+ @command = Command.command_to_show(command)
20
+ @flags = flags
21
+ end
22
+
23
+ # Options
24
+ # indent - Indent the line with by indent value. Assumes that the first
25
+ # the first line is already filled in with other padding.
26
+ # length - Line length, otherwise the default terminal width is assumed.
27
+ def format_usage(options={})
28
+ synopsis = "#{flags} #{command} <subcommand> [<args>]"
29
+ indent = options[:indent] || DEFAULT_INDENT
30
+ padding = sprintf("%#{indent}s",'')
31
+ length = options[:length] || Terminal.default_width
32
+ wrap synopsis, length, indent, padding
33
+ end
34
+
35
+ def tokenize_text(text)
36
+ text.split(/\s+/).map(&:chomp).reject(&:empty?)
37
+ end
38
+
39
+ # Wraps text at the given line length using given indent value.
40
+ #
41
+ def wrap(text, length, indent=0, padding=0)
42
+ if text.length > length - indent
43
+ paragraphs = []
44
+ line = ''
45
+ tokenize_text(text).each do |fragment|
46
+ if line.length < length - indent
47
+ line << fragment + ' '
48
+ else
49
+ paragraphs << line
50
+ line = padding + fragment + ' '
51
+ end
52
+ end
53
+ paragraphs << line
54
+ text = paragraphs.join("\n")
55
+ end
56
+ text
57
+ end
58
+
59
+ # Returns a concise string representation of Usage instance
60
+ #
61
+ def inspect
62
+ "#<#{self.class.inspect} @command=#{command.inspect} @flags=#{flags.inspect}"
63
+ end
64
+
65
+ end # Usage
66
+ end # Command
67
+ end # GithubCLI
@@ -29,9 +29,15 @@ module GithubCLI
29
29
  }
30
30
  end
31
31
 
32
- map "ls" => :list,
33
- "all" => :list,
34
- "del" => :delete
32
+ ALIASES = {
33
+ "ls" => :list,
34
+ "all" => :list,
35
+ "del" => :delete,
36
+ "rm" => :delete,
37
+ "c" => :create,
38
+ "e" => :edit
39
+ }
40
+ map ALIASES
35
41
 
36
42
  class_option :params, :type => :hash, :default => {}, :aliases => '-p',
37
43
  :desc => 'Request parameters e.i per_page:100'
@@ -74,6 +80,8 @@ module GithubCLI
74
80
  klass.namespace.split(':').last
75
81
  end
76
82
 
83
+ # Decide whether to show specific command or placeholder
84
+ #
77
85
  def command_to_show(command)
78
86
  command_token = Command.all.find do |cmd|
79
87
  end_index = command.index('<').nil? ? -1 : command.index('<')
@@ -6,29 +6,31 @@ module GithubCLI
6
6
  namespace :auth
7
7
 
8
8
  desc 'list', 'Lists your authorizations'
9
- method_option :params, :type => :hash, :default => {},
10
- :desc => 'Additional request parameters e.i per_page:100'
9
+ long_desc <<-DESC
10
+ You can only list your own tokens, and only through Basic Authentication.
11
+ DESC
11
12
  def list
12
13
  Authorization.all options[:params], options[:formats]
13
14
  end
14
15
 
15
16
  desc 'get <id>', 'Get a single authorization'
16
- method_option :params, :type => :hash, :default => {},
17
- :desc => 'Additional request parameters e.i per_page:100'
17
+ long_desc <<-DESC
18
+ You can only access your own token, and only through Basic Authentication.
19
+ DESC
18
20
  def get(id)
19
21
  Authorization.get id, options[:params], options[:format]
20
22
  end
21
23
 
22
- desc 'create <user> <repo>', 'Create a new authorization'
24
+ desc 'create', 'Create a new authorization'
23
25
  long_desc <<-DESC
26
+ You can only create your own token, and only through Basic Authentication.\n
27
+
24
28
  Inputs
25
29
 
26
30
  scopes - Optional array - A list of scopes that this authorization is in.\n
27
31
  note - Optional string - A note to remind you what the OAuth token is for.\n
28
32
  note_url - Optional string - A URL to remind you what the OAuth token is for.
29
33
  DESC
30
- method_option :params, :type => :hash, :default => {},
31
- :desc => 'Additonal request parameters e.i per_page:100'
32
34
  def create
33
35
  Authorization.create options[:params], options[:format]
34
36
  end
@@ -48,8 +50,6 @@ module GithubCLI
48
50
  end
49
51
 
50
52
  desc 'delete <id>', 'Delete an authorization'
51
- method_option :params, :type => :hash, :default => {},
52
- :desc => 'Additonal request parameters e.i per_page:100'
53
53
  def delete(id)
54
54
  Authorization.delete id, options[:params], options[:format]
55
55
  end
@@ -10,7 +10,7 @@ module GithubCLI
10
10
  Email.all options[:params], options[:format]
11
11
  end
12
12
 
13
- desc 'add <email(s)>', 'Add email address(es) for the authenticated user'
13
+ desc 'add <email(s)>...', 'Add email address(es) for the authenticated user'
14
14
  long_desc <<-DESC
15
15
  You can include a single email address or an array of addresses
16
16
  DESC
@@ -18,7 +18,7 @@ module GithubCLI
18
18
  Email.add emails, options[:params], options[:format]
19
19
  end
20
20
 
21
- desc 'delete <email(s)>', 'Delete email address(es) for the authenticated user'
21
+ desc 'delete <email(s)>...', 'Delete email address(es) for the authenticated user'
22
22
  long_desc <<-DESC
23
23
  You can include a single email address or an array of addresses
24
24
  DESC
@@ -4,8 +4,9 @@ module GithubCLI
4
4
  class Commands::Repositories < Command
5
5
 
6
6
  namespace :repo
7
+ # TODO: format_type options[:format]
7
8
 
8
- desc 'list', 'Lists all repositories'
9
+ desc 'list', 'Lists all repositories for the authenticated user'
9
10
  method_option :org, :type => :string, :aliases => ["-o"],
10
11
  :desc => 'List repositories for <organization>',
11
12
  :banner => '<organization>'
@@ -26,13 +27,12 @@ module GithubCLI
26
27
  Repository.get user, repo, options[:params], options[:format]
27
28
  end
28
29
 
29
- desc 'create', 'Create a new repository for the authenticated user.'
30
+ desc 'create [<org>/]<name>', 'Create a new repository <name> for the authenticated user.'
30
31
  long_desc <<-DESC
31
32
  Create a new repository for the autheticated user.
32
33
 
33
34
  Parameters
34
35
 
35
- name - Required string \n
36
36
  description - Optional string \n
37
37
  homepage - Optional string \n
38
38
  private - Optional boolean - true to create a private repository, false to create a public one \n
@@ -45,10 +45,11 @@ module GithubCLI
45
45
  method_option :org, :type => :string, :aliases => ["-o"],
46
46
  :desc => 'Create repository in <organization>',
47
47
  :banner => '<organization>'
48
- def create
49
- if options[:org]
50
- options[:params]['org'] = options[:org]
51
- end
48
+ def create(args)
49
+ org, options[:params]['name'] = Arguments.new(args).parse
50
+ options[:params]['org'] = org if org
51
+ options[:params]['org'] = options[:org] if options[:org]
52
+
52
53
  Repository.create options[:params], options[:format]
53
54
  end
54
55
 
@@ -2,10 +2,13 @@
2
2
 
3
3
  module GithubCLI
4
4
  class Config
5
- COMMAND_KEY = 'commands'
5
+
6
+ COMMAND_KEY = 'commands'
6
7
  COMMAND_HELP = 'help'
7
8
 
8
- def initialize(root)
9
+ attr_reader :root
10
+
11
+ def initialize(root, options={})
9
12
  @root = root
10
13
  @local_config = local_options_file
11
14
  @global_config = global_options_file
@@ -69,7 +72,7 @@ module GithubCLI
69
72
  private
70
73
 
71
74
  def local_options_file
72
- Pathname.new "#{@root}/.githubrc"
75
+ Pathname.new "#{root}/.githubrc"
73
76
  end
74
77
 
75
78
  def global_options_file
@@ -90,5 +93,9 @@ module GithubCLI
90
93
  value
91
94
  end
92
95
 
96
+ def inspect
97
+ "#{self.class.inspect} @root=#{root}"
98
+ end
99
+
93
100
  end # Config
94
101
  end # GithubCLI
@@ -17,5 +17,12 @@ module GithubCLI
17
17
  def on_error(&block)
18
18
  @@error_block = block
19
19
  end
20
+
21
+ def before(&block)
22
+ end
23
+
24
+ def configure(&block)
25
+ end
26
+
20
27
  end
21
28
  end
@@ -12,6 +12,10 @@ module GithubCLI
12
12
  status_code 5
13
13
  end
14
14
 
15
+ class RequiredArgumentMissingError < GithubCLIError
16
+ status_code 6
17
+ end
18
+
15
19
  # Raised when a configuration file is corrupt or missing.
16
20
  class ConfigFileNotFound < GithubCLIError
17
21
  status_code 10
@@ -3,6 +3,7 @@
3
3
  module GithubCLI
4
4
  # Responsible for display and size detection.
5
5
  class Terminal
6
+
6
7
  DEFAULT_WIDTH = 80
7
8
  DEFAULT_HEIGHT = 40
8
9
 
@@ -38,25 +39,13 @@ module GithubCLI
38
39
  @pager ||= Pager.new
39
40
  end
40
41
 
41
- def print_commands(pattern=nil)
42
- Terminal.line "\n" + GithubCLI.program_name + "\n"
43
- Terminal.newline
44
- GithubCLI.ui.info "Commands:"
45
-
46
- commands = Command.all.select do |cmd|
42
+ def find_commands(pattern=nil)
43
+ Command.all.select do |cmd|
47
44
  cmd if pattern && cmd.namespace =~ pattern
48
- end.map do |cmd|
49
- build_command cmd
50
- end
51
-
52
- if !commands.empty?
53
- GithubCLI.ui.print_table commands, :truncate => true
54
- else
55
- print_command_not_found pattern.to_s.gsub(/\W|/, '')[3..-1]
56
45
  end
57
46
  end
58
47
 
59
- def build_command(cmd, indent=3)
48
+ def build_command_output(cmd, indent=3)
60
49
  prefix = " " * indent
61
50
  if cmd.namespace.empty?
62
51
  ["#{prefix + cmd.usage}", cmd.desc]
@@ -65,6 +54,19 @@ module GithubCLI
65
54
  end
66
55
  end
67
56
 
57
+ def print_commands(pattern=nil)
58
+ Terminal.line "\n" + GithubCLI.program_name + "\n\n"
59
+
60
+ commands = find_commands(pattern).map { |cmd| build_command_output cmd }
61
+
62
+ if !commands.empty?
63
+ GithubCLI.ui.info "Commands:"
64
+ GithubCLI.ui.print_table commands, :truncate => true
65
+ else
66
+ print_command_not_found pattern.to_s.gsub(/\W|/, '')[3..-1]
67
+ end
68
+ end
69
+
68
70
  def print_command_not_found(cmd)
69
71
  GithubCLI.ui.info "ghc: '#{cmd}' is not a ghc command. See 'ghc --help'."
70
72
  end
@@ -74,42 +76,11 @@ module GithubCLI
74
76
 
75
77
  #{GithubCLI.program_name}
76
78
 
77
- Usage: ghc #{format_usage(flags, command, :indent => 11)}
79
+ Usage: ghc #{GithubCLI::Command::Usage.new(command, flags).format_usage }
78
80
 
79
81
  TEXT
80
82
  end
81
83
 
82
- # Options
83
- # indent - Indent the line with by indent value. Assumes that the first
84
- # the first line is already filled in with other padding.
85
- # length - Line length, otherwise the default terminal width is assumed.
86
- def format_usage(flags, command, options={})
87
- synopsis = "#{flags} #{command} <subcommand> [<args>]"
88
- indent = options[:indent] || 0
89
- padding = sprintf("%#{indent}s",'')
90
- length = options[:length] || default_width
91
- wrap synopsis, length, indent, padding
92
- end
93
-
94
- # Wraps text at the given line length using given indent value.
95
- def wrap(text, length, indent=0, padding=0)
96
- if text.length > length - indent
97
- paragraphs = []
98
- line = ''
99
- text.split(/\s+/).map(&:chomp).reject(&:empty?).each do |fragment|
100
- if line.length < length - indent
101
- line << fragment + ' '
102
- else
103
- paragraphs << line
104
- line = padding + fragment + ' '
105
- end
106
- end
107
- paragraphs << line
108
- text = paragraphs.join("\n")
109
- end
110
- text
111
- end
112
-
113
84
  end
114
85
 
115
86
  end # Terminal
@@ -1,3 +1,4 @@
1
+ require 'github_cli'
1
2
  require 'thor'
2
3
 
3
4
  class Thor
@@ -12,7 +13,7 @@ class Thor
12
13
  end
13
14
  list.sort!{ |a,b| a[0] <=> b[0] }
14
15
 
15
- GithubCLI::Terminal.print_usage global_flags, GithubCLI::Command.command_to_show(list[0][0])
16
+ GithubCLI::Terminal.print_usage global_flags, list[0][0]
16
17
 
17
18
  shell.say "Commands:"
18
19
  shell.print_table(list, :indent => 2, :truncate => true)
@@ -39,6 +40,15 @@ class Thor
39
40
  def help(task = nil, subcommand = true); super; end
40
41
  RUBY
41
42
  end
43
+
44
+ def handle_no_task_error(cmd, has_namespace = $thor_runner) #:nodoc:
45
+ possibilities = "#{GithubCLI::Command::Completion.new(cmd).format_command_possibilities}"
46
+ if has_namespace
47
+ raise UndefinedTaskError, "Could not find task #{cmd.inspect} in #{namespace.inspect} namespace. " + possibilities
48
+ else
49
+ raise UndefinedTaskError, "Could not find command #{cmd.inspect}. " + possibilities
50
+ end
51
+ end
42
52
  end
43
53
 
44
54
  desc "help <command>", "Describe available commands or one specific command"
@@ -4,6 +4,8 @@ module GithubCLI
4
4
  module Util
5
5
  extend self
6
6
 
7
+ # Converts deeply nested hash into only one level structure
8
+ #
7
9
  def flatten_hash(prefix=nil, hash)
8
10
  new_hash ||= {}
9
11
  hash.each do |key, val|
@@ -26,6 +28,8 @@ module GithubCLI
26
28
  end
27
29
  end
28
30
 
31
+ # Attempts to convert value object to string
32
+ #
29
33
  def convert_value(value)
30
34
  case value
31
35
  when true then "true"
@@ -38,6 +42,7 @@ module GithubCLI
38
42
 
39
43
  # Shortens string
40
44
  # :trailing - trailing character in place of cutout string
45
+ #
41
46
  def truncate(string, width, options={})
42
47
  trailing = options[:trailing] || '…'
43
48
 
@@ -52,6 +57,7 @@ module GithubCLI
52
57
  # Pads a string
53
58
  # padder - padding character
54
59
  # align - align :left, :right, :center
60
+ #
55
61
  def pad(string, width, options={})
56
62
  supported = [:left, :right, :center]
57
63
  padder = options[:padder] || ' '
@@ -74,5 +80,11 @@ module GithubCLI
74
80
  end
75
81
  string
76
82
  end
83
+
84
+ # Compares two strings to find common prefix
85
+ #
86
+ def longest_common_prefix(string_1, string_2)
87
+ ("#{string_1}\0#{string_2}").match(/^(.*).*\0\1/i).to_a[1]
88
+ end
77
89
  end
78
90
  end # GithubCLI
@@ -1,3 +1,3 @@
1
1
  module GithubCLI
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
data/lib/github_cli.rb CHANGED
@@ -9,6 +9,7 @@ require 'github_cli/thor_ext'
9
9
  require 'github_cli/version'
10
10
  require 'github_cli/errors'
11
11
 
12
+ # Base module which adds Github API to the command line
12
13
  module GithubCLI
13
14
  autoload :DSL, 'github_cli/dsl'
14
15
  autoload :Config, 'github_cli/config'
@@ -26,10 +27,13 @@ module GithubCLI
26
27
  autoload :Util, 'github_cli/util'
27
28
 
28
29
  require 'github_cli/apis'
30
+ require 'github_cli/command/completion'
31
+ require 'github_cli/command/usage'
32
+ require 'github_cli/command/arguments'
29
33
 
30
34
  extend DSL
31
35
 
32
- program_name 'Github CLI client'
36
+ program_name 'GitHub API v3 CLI client'
33
37
 
34
38
  class << self
35
39
  attr_writer :ui, :config
@@ -3,13 +3,8 @@ require 'spec_helper'
3
3
  describe GithubCLI::Pager do
4
4
 
5
5
  context '#pager_command' do
6
- it 'chooses default pagers if none present' do
7
- GithubCLI::System.stub(:command?) { true }
8
- described_class.pager_command.to_s.should =~ /less/
9
- end
10
-
11
6
  it 'permits custom commands' do
12
- cmd = 'mine'
7
+ cmd = 'more'
13
8
  GithubCLI::System.stub(:command?) { true }
14
9
  described_class.pager_command(cmd).should == cmd
15
10
  end
@@ -44,4 +44,16 @@ describe GithubCLI::Util do
44
44
  subject.convert_value(values).should eq(["123", "baz", "2.3"])
45
45
  end
46
46
  end
47
+
48
+ describe '#longest_common_prefix' do
49
+ it 'finds common prefix' do
50
+ a = 'tribe'; b = 'tree'
51
+ subject.longest_common_prefix(a,b).should == "tr"
52
+ end
53
+
54
+ it 'fails to find common prefix' do
55
+ a = 'foo'; b = 'bar'
56
+ subject.longest_common_prefix(a,b).should be_empty
57
+ end
58
+ end
47
59
  end # GithubCLI::Util
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-28 00:00:00.000000000Z
12
+ date: 2012-07-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: github_api
16
- requirement: &2156342420 !ruby/object:Gem::Requirement
16
+ requirement: &2153403460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0.6'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2156342420
24
+ version_requirements: *2153403460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: thor
27
- requirement: &2156342000 !ruby/object:Gem::Requirement
27
+ requirement: &2153403000 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2156342000
35
+ version_requirements: *2153403000
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &2156341520 !ruby/object:Gem::Requirement
38
+ requirement: &2153402520 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2156341520
46
+ version_requirements: *2153402520
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: aruba
49
- requirement: &2156341020 !ruby/object:Gem::Requirement
49
+ requirement: &2153401860 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2156341020
57
+ version_requirements: *2153401860
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &2156340580 !ruby/object:Gem::Requirement
60
+ requirement: &2153401360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2156340580
68
+ version_requirements: *2153401360
69
69
  description: CLI-based access to GitHub API v3
70
70
  email:
71
- - pmurach@gmail.com
71
+ - ''
72
72
  executables:
73
73
  - ghc
74
74
  extensions: []
@@ -88,6 +88,7 @@ files:
88
88
  - features/blob.feature
89
89
  - features/collaborator.feature
90
90
  - features/commit.feature
91
+ - features/completion.feature
91
92
  - features/content.feature
92
93
  - features/download.feature
93
94
  - features/email.feature
@@ -113,9 +114,9 @@ files:
113
114
  - features/tag.feature
114
115
  - features/team.feature
115
116
  - features/tree.feature
117
+ - features/usage.feature
116
118
  - features/user.feature
117
119
  - features/watching.feature
118
- - fixtures/.githubrc
119
120
  - fixtures/simple_config
120
121
  - ghc_logo.png
121
122
  - github_cli.gemspec
@@ -151,6 +152,9 @@ files:
151
152
  - lib/github_cli/apis/watching.rb
152
153
  - lib/github_cli/cli.rb
153
154
  - lib/github_cli/command.rb
155
+ - lib/github_cli/command/arguments.rb
156
+ - lib/github_cli/command/completion.rb
157
+ - lib/github_cli/command/usage.rb
154
158
  - lib/github_cli/commands.rb
155
159
  - lib/github_cli/commands/authorizations.rb
156
160
  - lib/github_cli/commands/blobs.rb
@@ -233,6 +237,7 @@ test_files:
233
237
  - features/blob.feature
234
238
  - features/collaborator.feature
235
239
  - features/commit.feature
240
+ - features/completion.feature
236
241
  - features/content.feature
237
242
  - features/download.feature
238
243
  - features/email.feature
@@ -258,6 +263,7 @@ test_files:
258
263
  - features/tag.feature
259
264
  - features/team.feature
260
265
  - features/tree.feature
266
+ - features/usage.feature
261
267
  - features/user.feature
262
268
  - features/watching.feature
263
269
  - spec/github_cli/api_spec.rb
data/fixtures/.githubrc DELETED
@@ -1,9 +0,0 @@
1
- ---
2
- oauth_token: ad7f9asdf97as98df7as9fd7
3
- basic_auth: 'login:password'
4
- host:
5
- user:
6
- repo:
7
- commands:
8
- issue-list: { inputs: 'ticket' }
9
- issue-get: {}