jist 0.9.2 → 1.5.0

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/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .rvmrc
2
+ Gemfile.lock
3
+
4
+ # OS X
5
+ .DS_Store
6
+ .yardoc
7
+ doc
8
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ -r ./spec/spec_helper.rb
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE.MIT ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2012 Conrad Irwin <conrad.irwin@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,189 @@
1
+ Jist is a gem that allows you to publish a [gist](https://gist.github.com) from Ruby.
2
+
3
+ # Installation
4
+
5
+ As with all ruby gems, you can install Jist (assuming you have ruby and rubygems) with:
6
+
7
+ ```shell
8
+ $ gem install jist
9
+ ```
10
+
11
+ If you want to use the library in your application, and you're using Bundler. Add the
12
+ following to your Gemfile.
13
+
14
+ ```ruby
15
+ source :rubygems
16
+ gem 'jist'
17
+ ```
18
+
19
+ # Command
20
+
21
+ The jist gem provides a `jist` command that you can use from your terminal to
22
+ upload content to https://gist.github.com/.
23
+
24
+ It's easy to use. To upload the contents of `a.rb` just:
25
+
26
+ ```shell
27
+ $ jist a.rb
28
+ https://gist.github.com/0d07bc98c139810a4075
29
+ ```
30
+
31
+ Upload multiple files :
32
+ ```shell
33
+ $ jist a b c
34
+ $ jist *.rb
35
+ ```
36
+
37
+ By default it reads from STDIN, and you can set a filename with `-f`.
38
+
39
+ ```shell
40
+ $ jist -f test.rb <a.rb
41
+ https://gist.github.com/7db51bb5f4f35c480fc8
42
+ ```
43
+
44
+ Alternatively, you can just paste from the clipboard:
45
+
46
+ ```shell
47
+ $ jist -P
48
+ https://gist.github.com/6a330a11a0db8e52a6ee
49
+ ```
50
+
51
+ Use `-p` to make the gist public and `-d` to add a description.
52
+ ```shell
53
+ $ jist -p -d "Random rbx bug" a.rb
54
+ https://gist.github.com/2977722
55
+ ```
56
+
57
+ You can update existing gists with `-u`:
58
+
59
+ ```shell
60
+ $ jist lib/jist.rb bin/jist -u 42f2c239d2eb57299408
61
+ https://gist.github.com/42f2c239d2eb57299408
62
+ ```
63
+
64
+ If you'd like to copy the resulting URL to your clipboard, use `-c`.
65
+
66
+ ```shell
67
+ $ jist -c <a.rb
68
+ https://gist.github.com/7db51bb5f4f35c480fc8
69
+ ```
70
+
71
+ If you'd like to copy the resulting embeddable URL to your clipboard, use `--copy-js`.
72
+
73
+ ```shell
74
+ $ jist --copy-js <a.rb
75
+ <script src="https://gist.github.com/7db51bb5f4f35c480fc8"></script>
76
+ ```
77
+ And you can just ask jist to open a browser window directly with `-o`.
78
+
79
+ ```shell
80
+ $ jist -o <a.rb
81
+ https://gist.github.com/7db51bb5f4f35c480fc8
82
+ ```
83
+
84
+ See `jist --help` for more detail.
85
+
86
+ ## Login
87
+
88
+ If you want to associate your gists with your github account, you need to login
89
+ with jist. It doesn't store your username and password, it just uses them to get
90
+ an OAuth2 token (with the "gist" permission).
91
+
92
+ ```shell
93
+ jist --login
94
+ Obtaining OAuth2 access_token from github.
95
+ Github username: ConradIrwin
96
+ Github password:
97
+ Success! https://github.com/settings/applications
98
+ ```
99
+
100
+ This token is stored in `~/.jist` and used for all future gisting. If you need to
101
+ you can revoke it from https://github.com/settings/applications, or just delete the
102
+ file.
103
+
104
+ After you've done this, you can still upload gists anonymously with `-a`.
105
+
106
+ ```shell
107
+ jist -a a.rb
108
+ https://gist.github.com/6bf7ec379fc9119b1f15
109
+ ```
110
+
111
+ # Library
112
+
113
+ You can also use Jist as a library from inside your ruby code:
114
+
115
+ ```ruby
116
+ Jist.gist("Look.at(:my => 'awesome').code")
117
+ ```
118
+
119
+ If you need more advanced features you can also pass:
120
+
121
+ * `:access_token` to authenticate using OAuth2 (default is `File.read("~/.jist")).
122
+ * `:filename` to change the syntax highlighting (default is `a.rb`).
123
+ * `:public` if you want your gist to have a guessable url.
124
+ * `:description` to add a description to your gist.
125
+ * `:update` to update an existing gist (can be a URL or an id).
126
+ * `:anonymous` to submit an anonymous gist (default is false).
127
+ * `:copy` to copy the resulting URL to the clipboard (default is false).
128
+ * `:open` to open the resulting URL in a browser (default is false).
129
+
130
+ NOTE: The access_token must have the "gist" scope.
131
+
132
+ If you want to upload multiple files in the same gist, you can:
133
+
134
+ ```ruby
135
+ Jist.multi_gist("a.rb" => "Foo.bar", "a.py" => "Foo.bar")
136
+ ```
137
+
138
+ If you'd rather use jist's builtin access_token, then you can force the user to
139
+ obtain one by calling:
140
+
141
+ ```ruby
142
+ Jist.login!
143
+ ```
144
+
145
+ This will take them through the process of obtaining an OAuth2 token, and storing it
146
+ in `~/.jist`, where it can later be read by `Jist.gist`
147
+
148
+ GitHub enterprise
149
+ ==================
150
+
151
+ If you'd like `jist` to use your locally installed [Github Enterprise](https://enterprise.github.com/),
152
+ you need to export the `GITHUB_URL` environment variable in your `~/.bashrc`.
153
+
154
+ ```bash
155
+ export GITHUB_URL=http://github.internal.example.com/
156
+ ```
157
+
158
+ Once you've done this and restarted your terminal (or run `source ~/.bashrc`), jist will
159
+ automatically use github enterprise instead of the public github.com
160
+
161
+ Configuration
162
+ =============
163
+
164
+ If you'd like `-o` or `-c` to be the default when you use the jist executable, add an
165
+ alias to your `~/.bashrc` (or equivalent). For example:
166
+
167
+ ```ruby
168
+ alias jist='jist -c'
169
+ ```
170
+
171
+ If you'd prefer jist to open a different browser, then you can export the BROWSER
172
+ environment variable:
173
+
174
+ ```ruby
175
+ export BROWSER=google-chrome
176
+ ```
177
+
178
+ If clipboard or browser integration don't work on your platform, please file a bug or
179
+ (more ideally) a pull request.
180
+
181
+ If you need to use an HTTP proxy to access the internet, export the `HTTP_PROXY` or
182
+ `http_proxy` environment variable and jist will use it.
183
+
184
+ Meta-fu
185
+ =======
186
+
187
+ I wrote this because the `gist` gem is out of action, and has been for many months.
188
+
189
+ It's licensed under the MIT license, and bug-reports, and pull requests are welcome.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ task :default => :test
2
+
3
+ desc 'run the tests' # that's non-DRY
4
+ task :test do
5
+ sh 'rspec spec'
6
+ end
7
+
8
+ task :clipfailtest do
9
+ sh 'PATH=/ /usr/bin/ruby -Ilib -S bin/jist -ac < lib/jist.rb'
10
+ end
data/bin/jist CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
-
5
- require 'jist'
4
+ require File.expand_path('../../lib/jist', __FILE__)
6
5
 
7
6
  # For the holdings of options.
8
7
  options = {}
@@ -13,9 +12,6 @@ opts = OptionParser.new do |opts|
13
12
  opts.banner = <<-EOS
14
13
  Jist (v#{Jist::VERSION}) lets you upload to https://gist.github.com/
15
14
 
16
- Usage: #{executable_name} [-p] [-d DESC] [-t TOKEN|-a] [-u URL] [-f NAME]* [FILE]*
17
- #{executable_name} --login
18
-
19
15
  The content to be uploaded can be passed as a list of files, if none are
20
16
  specified STDIN will be read. The default filename for STDIN is "a.rb", and all
21
17
  filenames can be overridden by repeating the "-f" flag. The most useful reason
@@ -32,10 +28,21 @@ Anonymous gists are not associated with your GitHub account, they can be created
32
28
  with "-a" even after you have used "jist --login". If you already have an access
33
29
  token with the "gist" scope, you can pass that with "-t".
34
30
 
31
+ If you would like to shorten the resulting gist URL, use the -s flag. This will
32
+ use GitHub's URL shortener, git.io.
33
+
34
+ To copy the resulting URL to your clipboard you can use the -c option, or to just
35
+ open it directly in your browser, use -o. Using the -e option will copy the embeddable
36
+ URL to the clipboard. You can add `alias jist='jist -c'` to your shell's rc file to configure this
37
+ behaviour by default.
38
+
35
39
  Instead of creating a new jist, you can update an existing one by passing its ID
36
40
  or URL with "-u". For this to work, you must be logged in, and have created the
37
41
  original gist with the same GitHub account.
38
42
 
43
+ Usage: #{executable_name} [-o|-c|-e] [-p] [-s] [-d DESC] [-t TOKEN|-a] [-u URL] [-P] [-f NAME]* FILE*
44
+ #{executable_name} --login
45
+
39
46
  EOS
40
47
 
41
48
  opts.on("--login", "Authenticate jist on this computer.") do
@@ -56,6 +63,10 @@ original gist with the same GitHub account.
56
63
  options[:description] = description
57
64
  end
58
65
 
66
+ opts.on("-s", "--shorten", "Shorten the gist URL using git.io.") do |shorten|
67
+ options[:shorten] = shorten
68
+ end
69
+
59
70
  opts.on("-u", "--update [ URL | ID ]", "Update an existing gist.") do |update|
60
71
  options[:update] = update
61
72
  end
@@ -68,6 +79,22 @@ original gist with the same GitHub account.
68
79
  options[:access_token] = token
69
80
  end
70
81
 
82
+ opts.on("-c", "--copy", "Copy the resulting URL to the clipboard") do
83
+ options[:copy] = true
84
+ end
85
+ opts.on("-e", "--embed", "Copy the embed code for the gist to the clipboard") do
86
+ options[:embed] = true
87
+ options[:copy] = true
88
+ end
89
+
90
+ opts.on("-o", "--open", "Open the resulting URL in a browser") do
91
+ options[:open] = true
92
+ end
93
+
94
+ opts.on("-P", "--paste", "Paste from the clipboard to jist") do
95
+ options[:paste] = true
96
+ end
97
+
71
98
  opts.on_tail("-h","--help", "Show this message.") do
72
99
  puts opts
73
100
  exit
@@ -82,9 +109,21 @@ end
82
109
  opts.parse!
83
110
 
84
111
  begin
85
- if ARGV.size == 0
112
+ options[:output] = if options[:embed] && options[:shorten]
113
+ raise Jist::Error, "--embed does not make sense with --shorten"
114
+ elsif options[:embed]
115
+ :javascript
116
+ elsif options[:shorten]
117
+ :short_url
118
+ else
119
+ :html_url
120
+ end
121
+
122
+ if options[:paste]
123
+ puts Jist.gist(Jist.paste, options)
124
+ elsif ARGV.size == 0
86
125
  $stderr.puts "(type a gist. <ctrl-c> to cancel, <ctrl-d> when done)" if $stdin.tty?
87
- puts Jist.gist(ARGF.read, options)['html_url']
126
+ puts Jist.gist(ARGF.read, options)
88
127
  else
89
128
  files = {}
90
129
  ARGV.zip(filenames).each do |(file, name)|
@@ -95,7 +134,7 @@ begin
95
134
  end
96
135
  end
97
136
 
98
- puts Jist.multi_gist(files, options)['html_url']
137
+ puts Jist.multi_gist(files, options)
99
138
  end
100
139
  rescue Jist::Error => e
101
140
  puts "Error: #{e.message}"
data/jist.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ require './lib/jist'
2
+ Gem::Specification.new do |s|
3
+ s.name = 'jist'
4
+ s.version = Jist::VERSION
5
+ s.summary = 'Just allows you to upload gists'
6
+ s.description = 'Provides a single function (Jist.gist) that uploads a gist.'
7
+ s.homepage = 'https://github.com/ConradIrwin/jist'
8
+ s.email = 'conrad.irwin@gmail.com'
9
+ s.authors = ['Conrad Irwin']
10
+ s.license = 'MIT'
11
+ s.files = `git ls-files`.split("\n")
12
+ s.require_paths = ["lib"]
13
+
14
+ s.executables << 'jist'
15
+
16
+ s.add_dependency 'json'
17
+ %w(rake rspec webmock).each do |gem|
18
+ s.add_development_dependency gem
19
+ end
20
+ end
data/lib/jist.rb CHANGED
@@ -1,30 +1,43 @@
1
1
  require 'net/https'
2
2
  require 'cgi'
3
3
  require 'json'
4
+ require 'uri'
4
5
 
5
6
  # It just gists.
6
7
  module Jist
8
+ extend self
7
9
 
8
- VERSION = '0.9.2'
10
+ VERSION = '1.5.0'
11
+
12
+ # A list of clipboard commands with copy and paste support.
13
+ CLIPBOARD_COMMANDS = {
14
+ 'xclip' => 'xclip -o',
15
+ 'xsel' => 'xsel -o',
16
+ 'pbcopy' => 'pbpaste',
17
+ 'putclip' => 'getclip'
18
+ }
19
+
20
+ GITHUB_API_URL = URI("https://api.github.com/")
21
+ GIT_IO_URL = URI("http://git.io")
22
+
23
+ GITHUB_BASE_PATH = ""
24
+ GHE_BASE_PATH = "/api/v3"
25
+
26
+ URL_ENV_NAME = "GITHUB_URL"
9
27
 
10
28
  # Exception tag for errors raised while gisting.
11
- module Error; end
29
+ module Error;
30
+ def self.exception(*args)
31
+ RuntimeError.new(*args).extend(self)
32
+ end
33
+ end
34
+ class ClipboardError < RuntimeError; include Error end
12
35
 
13
- module_function
14
36
  # Upload a gist to https://gist.github.com
15
37
  #
16
38
  # @param [String] content the code you'd like to gist
17
- # @param [Hash] options more detailed options
18
- #
19
- # @option options [String] :description the description
20
- # @option options [String] :filename ('a.rb') the filename
21
- # @option options [Boolean] :public (false) is this gist public
22
- # @option options [Boolean] :anonymous (false) is this gist anonymous
23
- # @option options [String] :access_token (`File.read("~/.jist")`) The OAuth2 access token.
24
- # @option options [String] :update the URL or id of a gist to update
25
- #
26
- # @return [Hash] the decoded JSON response from the server
27
- # @raise [Jist::Error] if something went wrong
39
+ # @param [Hash] options more detailed options, see
40
+ # the documentation for {multi_gist}
28
41
  #
29
42
  # @see http://developer.github.com/v3/gists/
30
43
  def gist(content, options = {})
@@ -42,8 +55,15 @@ module Jist
42
55
  # @option options [Boolean] :anonymous (false) is this gist anonymous
43
56
  # @option options [String] :access_token (`File.read("~/.jist")`) The OAuth2 access token.
44
57
  # @option options [String] :update the URL or id of a gist to update
58
+ # @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
59
+ # @option options [Boolean] :open (false) Open the resulting URL in a browser.
60
+ # @option options [Symbol] :output (:all) The type of return value you'd like:
61
+ # :html_url gives a String containing the url to the gist in a browser
62
+ # :short_url gives a String contianing a git.io url that redirects to html_url
63
+ # :javascript gives a String containing a script tag suitable for embedding the gist
64
+ # :all gives a Hash containing the parsed json response from the server
45
65
  #
46
- # @return [Hash] the decoded JSON response from the server
66
+ # @return [String, Hash] the return value as configured by options[:output]
47
67
  # @raise [Jist::Error] if something went wrong
48
68
  #
49
69
  # @see http://developer.github.com/v3/gists/
@@ -63,10 +83,10 @@ module Jist
63
83
  if options[:anonymous]
64
84
  access_token = nil
65
85
  else
66
- access_token = (options[:access_token] || File.read(File.expand_path("~/.jist")) rescue nil)
86
+ access_token = (options[:access_token] || File.read(auth_token_file) rescue nil)
67
87
  end
68
88
 
69
- url = "/gists"
89
+ url = "#{base_path}/gists"
70
90
  url << "/" << CGI.escape(existing_gist) if existing_gist.to_s != ''
71
91
  url << "?access_token=" << CGI.escape(access_token) if access_token.to_s != ''
72
92
 
@@ -77,9 +97,9 @@ module Jist
77
97
  retried = false
78
98
 
79
99
  begin
80
- response = http(request)
100
+ response = http(api_url, request)
81
101
  if Net::HTTPSuccess === response
82
- JSON.parse(response.body)
102
+ on_success(response.body, options)
83
103
  else
84
104
  raise "Got #{response.class} from gist: #{response.body}"
85
105
  end
@@ -93,6 +113,22 @@ module Jist
93
113
  raise e.extend Error
94
114
  end
95
115
 
116
+ # Convert long github urls into short git.io ones
117
+ #
118
+ # @param [String] url
119
+ # @return [String] shortened url, or long url if shortening fails
120
+ def shorten(url)
121
+ request = Net::HTTP::Post.new("/")
122
+ request.set_form_data(:url => url)
123
+ response = http(GIT_IO_URL, request)
124
+ case response.code
125
+ when "201"
126
+ response['Location']
127
+ else
128
+ url
129
+ end
130
+ end
131
+
96
132
  # Log the user into jist.
97
133
  #
98
134
  # This method asks the user for a username and password, and tries to obtain
@@ -113,7 +149,7 @@ module Jist
113
149
  end
114
150
  puts ""
115
151
 
116
- request = Net::HTTP::Post.new("/authorizations")
152
+ request = Net::HTTP::Post.new("#{base_path}/authorizations")
117
153
  request.body = JSON.dump({
118
154
  :scopes => [:gist],
119
155
  :note => "The jist gem",
@@ -122,13 +158,13 @@ module Jist
122
158
  request.content_type = 'application/json'
123
159
  request.basic_auth(username, password)
124
160
 
125
- response = http(request)
161
+ response = http(api_url, request)
126
162
 
127
163
  if Net::HTTPCreated === response
128
- File.open(File.expand_path("~/.jist"), 'w') do |f|
164
+ File.open(auth_token_file, 'w') do |f|
129
165
  f.write JSON.parse(response.body)['token']
130
166
  end
131
- puts "Success! https://github.com/settings/applications"
167
+ puts "Success! #{ENV[URL_ENV_NAME] || "https://github.com/"}settings/applications"
132
168
  else
133
169
  raise "Got #{response.class} from gist: #{response.body}"
134
170
  end
@@ -136,20 +172,171 @@ module Jist
136
172
  raise e.extend Error
137
173
  end
138
174
 
139
- # Run an HTTP operation against api.github.com
175
+ # Return HTTP connection
140
176
  #
141
- # @param [Net::HTTPRequest] request
142
- # @return [Net::HTTPResponse]
143
- def http(request)
144
- connection = Net::HTTP.new("api.github.com", 443)
145
- connection.use_ssl = true
146
- connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
177
+ # @param [URI::HTTP] The URI to which to connect
178
+ # @return [Net::HTTP]
179
+ def http_connection(uri)
180
+ env = ENV['http_proxy'] || ENV['HTTP_PROXY']
181
+ connection = if env
182
+ proxy = URI(env)
183
+ Net::HTTP::Proxy(proxy.host, proxy.port).new(uri.host, uri.port)
184
+ else
185
+ Net::HTTP.new(uri.host, uri.port)
186
+ end
187
+ if uri.scheme == "https"
188
+ connection.use_ssl = true
189
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
190
+ end
147
191
  connection.open_timeout = 10
148
192
  connection.read_timeout = 10
149
- connection.start do |http|
193
+ connection
194
+ end
195
+
196
+ # Run an HTTP operation
197
+ #
198
+ # @param [URI::HTTP] The URI to which to connect
199
+ # @param [Net::HTTPRequest] The request to make
200
+ # @return [Net::HTTPResponse]
201
+ def http(url, request)
202
+ http_connection(url).start do |http|
150
203
  http.request request
151
204
  end
152
205
  rescue Timeout::Error
153
- raise "Could not connect to https://api.github.com/"
206
+ raise "Could not connect to #{api_url}"
207
+ end
208
+
209
+ # Called after an HTTP response to gist to perform post-processing.
210
+ #
211
+ # @param [String] body the text body from the github api
212
+ # @param [Hash] options more detailed options, see
213
+ # the documentation for {multi_gist}
214
+ def on_success(body, options={})
215
+ json = JSON.parse(body)
216
+
217
+ output = case options[:output]
218
+ when :javascript
219
+ %Q{<script src="#{json['html_url']}.js"></script>}
220
+ when :html_url
221
+ json['html_url']
222
+ when :short_url
223
+ shorten(json['html_url'])
224
+ else
225
+ json
226
+ end
227
+
228
+ Jist.copy(output.to_s) if options[:copy]
229
+ Jist.open(json['html_url']) if options[:open]
230
+
231
+ output
232
+ end
233
+
234
+ # Copy a string to the clipboard.
235
+ #
236
+ # @param [String] content
237
+ # @raise [Jist::Error] if no clipboard integration could be found
238
+ #
239
+ def copy(content)
240
+ IO.popen(clipboard_command(:copy), 'r+') { |clip| clip.print content }
241
+
242
+ unless paste == content
243
+ message = 'Copying to clipboard failed.'
244
+
245
+ if ENV["TMUX"] && clipboard_command(:copy) == 'pbcopy'
246
+ message << "\nIf you're running tmux on a mac, try http://robots.thoughtbot.com/post/19398560514/how-to-copy-and-paste-with-tmux-on-mac-os-x"
247
+ end
248
+
249
+ raise Error, message
250
+ end
251
+ rescue Error => e
252
+ raise ClipboardError, e.message + "\nAttempted to copy: #{content}"
253
+ end
254
+
255
+ # Get a string from the clipboard.
256
+ #
257
+ # @param [String] content
258
+ # @raise [Jist::Error] if no clipboard integration could be found
259
+ def paste
260
+ `#{clipboard_command(:paste)}`
261
+ end
262
+
263
+ # Find command from PATH environment.
264
+ #
265
+ # @param [String] cmd command name to find
266
+ # @param [String] options PATH environment variable
267
+ # @return [String] the command found
268
+ def which(cmd, path=ENV['PATH'])
269
+ if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin|cygwin/
270
+ path.split(File::PATH_SEPARATOR).each {|dir|
271
+ f = File.join(dir, cmd+".exe")
272
+ return f if File.executable?(f) && !File.directory?(f)
273
+ }
274
+ nil
275
+ else
276
+ return system("which #{cmd} > /dev/null 2>&1")
277
+ end
278
+ end
279
+
280
+ # Get the command to use for the clipboard action.
281
+ #
282
+ # @param [Symbol] action either :copy or :paste
283
+ # @return [String] the command to run
284
+ # @raise [Jist::ClipboardError] if no clipboard integration could be found
285
+ def clipboard_command(action)
286
+ command = CLIPBOARD_COMMANDS.keys.detect do |cmd|
287
+ which cmd
288
+ end
289
+ raise ClipboardError, <<-EOT unless command
290
+ Could not find copy command, tried:
291
+ #{CLIPBOARD_COMMANDS.values.join(' || ')}
292
+ EOT
293
+ action == :copy ? command : CLIPBOARD_COMMANDS[command]
294
+ end
295
+
296
+ # Open a URL in a browser.
297
+ #
298
+ # @param [String] url
299
+ # @raise [RuntimeError] if no browser integration could be found
300
+ #
301
+ # This method was heavily inspired by defunkt's Gist#open,
302
+ # @see https://github.com/defunkt/gist/blob/bca9b29/lib/gist.rb#L157
303
+ def open(url)
304
+ command = if ENV['BROWSER']
305
+ ENV['BROWSER']
306
+ elsif RUBY_PLATFORM =~ /darwin/
307
+ 'open'
308
+ elsif RUBY_PLATFORM =~ /linux/
309
+ %w(
310
+ sensible-browser
311
+ firefox
312
+ firefox-bin
313
+ ).detect do |cmd|
314
+ which cmd
315
+ end
316
+ elsif ENV['OS'] == 'Windows_NT' || RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw|wince/i
317
+ 'start ""'
318
+ else
319
+ raise "Could not work out how to use a browser."
320
+ end
321
+
322
+ `#{command} #{url}`
323
+ end
324
+
325
+ # Get the API base path
326
+ def base_path
327
+ ENV.key?(URL_ENV_NAME) ? GHE_BASE_PATH : GITHUB_BASE_PATH
328
+ end
329
+
330
+ # Get the API URL
331
+ def api_url
332
+ ENV.key?(URL_ENV_NAME) ? URI(ENV[URL_ENV_NAME]) : GITHUB_API_URL
333
+ end
334
+
335
+ def auth_token_file
336
+ if ENV.key?(URL_ENV_NAME)
337
+ File.expand_path "~/.jist.#{ENV[URL_ENV_NAME].gsub(/[^a-z.]/, '')}"
338
+ else
339
+ File.expand_path "~/.jist"
340
+ end
154
341
  end
155
342
  end
@@ -0,0 +1,40 @@
1
+ describe '...' do
2
+ before do
3
+ @saved_path = ENV['PATH']
4
+ @bobo_url = 'http://example.com'
5
+ end
6
+
7
+ after do
8
+ ENV['PATH'] = @saved_path
9
+ end
10
+
11
+ def ask_for_copy
12
+ Jist.on_success({'html_url' => @bobo_url}.to_json, :copy => true, :output => :html_url)
13
+ end
14
+ def jist_but_dont_ask_for_copy
15
+ Jist.on_success({'html_url' => 'http://example.com/'}.to_json, :output => :html_url)
16
+ end
17
+
18
+ it 'should try to copy the url when the clipboard option is passed' do
19
+ Jist.should_receive(:copy).with(@bobo_url)
20
+ ask_for_copy
21
+ end
22
+
23
+ it 'should try to copy the embed url when the clipboard-js option is passed' do
24
+ js_link = %Q{<script src="#{@bobo_url}.js"></script>}
25
+ Jist.should_receive(:copy).with(js_link)
26
+ Jist.on_success({'html_url' => @bobo_url}.to_json, :copy => true, :output => :javascript)
27
+ end
28
+
29
+ it "should not copy when not asked to" do
30
+ Jist.should_not_receive(:copy).with(@bobo_url)
31
+ jist_but_dont_ask_for_copy
32
+ end
33
+
34
+ it "should raise an error if no copying mechanisms are available" do
35
+ ENV['PATH'] = ''
36
+ lambda{
37
+ ask_for_copy
38
+ }.should raise_error(/Could not find copy command.*http/m)
39
+ end
40
+ end
data/spec/ghe_spec.rb ADDED
@@ -0,0 +1,80 @@
1
+ describe '...' do
2
+
3
+ MOCK_GHE_HOST = 'ghe.example.com'
4
+ MOCK_GHE_PROTOCOL = 'http'
5
+ MOCK_USER = 'foo'
6
+ MOCK_PASSWORD = 'bar'
7
+
8
+ MOCK_AUTHZ_GHE_URL = "#{MOCK_GHE_PROTOCOL}://#{MOCK_USER}:#{MOCK_PASSWORD}@#{MOCK_GHE_HOST}/api/v3/"
9
+ MOCK_GHE_URL = "#{MOCK_GHE_PROTOCOL}://#{MOCK_GHE_HOST}/api/v3/"
10
+ MOCK_AUTHZ_GITHUB_URL = "https://#{MOCK_USER}:#{MOCK_PASSWORD}@api.github.com/"
11
+ MOCK_GITHUB_URL = "https://api.github.com/"
12
+
13
+ before do
14
+ @saved_env = ENV[Jist::URL_ENV_NAME]
15
+
16
+ # stub requests for /gists
17
+ stub_request(:post, /#{MOCK_GHE_URL}gists/).to_return(:body => %[{"html_url": "http://#{MOCK_GHE_HOST}"}])
18
+ stub_request(:post, /#{MOCK_GITHUB_URL}gists/).to_return(:body => '{"html_url": "http://github.com/"}')
19
+
20
+ # stub requests for /authorizations
21
+ stub_request(:post, /#{MOCK_AUTHZ_GHE_URL}authorizations/).
22
+ to_return(:status => 201, :body => '{"token": "asdf"}')
23
+ stub_request(:post, /#{MOCK_AUTHZ_GITHUB_URL}authorizations/).
24
+ to_return(:status => 201, :body => '{"token": "asdf"}')
25
+ end
26
+
27
+ after do
28
+ ENV[Jist::URL_ENV_NAME] = @saved_env
29
+ end
30
+
31
+ describe :login! do
32
+ before do
33
+ @saved_stdin = $stdin
34
+
35
+ # stdin emulation
36
+ $stdin = StringIO.new "#{MOCK_USER}\n#{MOCK_PASSWORD}\n"
37
+
38
+ # intercept for updating ~/.jist
39
+ File.stub(:open)
40
+ end
41
+
42
+ after do
43
+ $stdin = @saved_stdin
44
+ end
45
+
46
+ it "should access to api.github.com when $#{Jist::URL_ENV_NAME} wasn't set" do
47
+ ENV.delete Jist::URL_ENV_NAME
48
+
49
+ Jist.login!
50
+
51
+ assert_requested(:post, /#{MOCK_AUTHZ_GITHUB_URL}authorizations/)
52
+ end
53
+
54
+ it "should access to #{MOCK_GHE_HOST} when $#{Jist::URL_ENV_NAME} was set" do
55
+ ENV[Jist::URL_ENV_NAME] = MOCK_GHE_URL
56
+
57
+ Jist.login!
58
+
59
+ assert_requested(:post, /#{MOCK_AUTHZ_GHE_URL}authorizations/)
60
+ end
61
+ end
62
+
63
+ describe :gist do
64
+ it "should access to api.github.com when $#{Jist::URL_ENV_NAME} wasn't set" do
65
+ ENV.delete Jist::URL_ENV_NAME
66
+
67
+ Jist.gist "test gist"
68
+
69
+ assert_requested(:post, /#{MOCK_GITHUB_URL}gists/)
70
+ end
71
+
72
+ it "should access to #{MOCK_GHE_HOST} when $#{Jist::URL_ENV_NAME} was set" do
73
+ ENV[Jist::URL_ENV_NAME] = MOCK_GHE_URL
74
+
75
+ Jist.gist "test gist"
76
+
77
+ assert_requested(:post, /#{MOCK_GHE_URL}gists/)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,21 @@
1
+ describe '...' do
2
+ before do
3
+ @saved_env = ENV['HTTP_PROXY']
4
+ end
5
+
6
+ after do
7
+ ENV['HTTP_PROXY'] = @saved_env
8
+ end
9
+
10
+ FOO_URL = URI('http://ddg.gg/')
11
+
12
+ it "should be Net::HTTP when $HTTP_PROXY wasn't set" do
13
+ ENV['HTTP_PROXY'] = ''
14
+ Jist.http_connection(FOO_URL).should be_an_instance_of(Net::HTTP)
15
+ end
16
+
17
+ it "should be Net::HTTP::Proxy when $HTTP_PROXY was set" do
18
+ ENV['HTTP_PROXY'] = 'http://proxy.example.com:8080'
19
+ Jist.http_connection(FOO_URL).should_not be_an_instance_of(Net::HTTP)
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ describe '...' do
2
+ before do
3
+ stub_request(:post, /api\.github.com\/gists\?access_token=.*/).to_return(:body => '{"html_url": "http://github.com/"}')
4
+ stub_request(:post, "http://git.io/").to_return(:status => 201, :headers => { 'Location' => 'http://git.io/XXXXXX' })
5
+ end
6
+
7
+ it "should return a shortened version of the URL" do
8
+ Jist.gist("Test gist", :output => :short_url).should == "http://git.io/XXXXXX"
9
+ end
10
+ end
11
+
@@ -0,0 +1,15 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
12
+
13
+ require 'webmock/rspec'
14
+ require_relative '../lib/jist'
15
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 1.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,72 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-24 00:00:00.000000000 Z
12
+ date: 2013-04-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
+ type: :runtime
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ none: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ none: false
28
+ prerelease: false
15
29
  name: json
30
+ - !ruby/object:Gem::Dependency
31
+ type: :development
16
32
  requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
17
37
  none: false
38
+ version_requirements: !ruby/object:Gem::Requirement
18
39
  requirements:
19
40
  - - ! '>='
20
41
  - !ruby/object:Gem::Version
21
42
  version: '0'
22
- type: :runtime
43
+ none: false
23
44
  prerelease: false
45
+ name: rake
46
+ - !ruby/object:Gem::Dependency
47
+ type: :development
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ none: false
24
54
  version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
25
59
  none: false
60
+ prerelease: false
61
+ name: rspec
62
+ - !ruby/object:Gem::Dependency
63
+ type: :development
64
+ requirement: !ruby/object:Gem::Requirement
26
65
  requirements:
27
66
  - - ! '>='
28
67
  - !ruby/object:Gem::Version
29
68
  version: '0'
69
+ none: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ none: false
76
+ prerelease: false
77
+ name: webmock
30
78
  description: Provides a single function (Jist.gist) that uploads a gist.
31
79
  email: conrad.irwin@gmail.com
32
80
  executables:
@@ -34,29 +82,42 @@ executables:
34
82
  extensions: []
35
83
  extra_rdoc_files: []
36
84
  files:
37
- - lib/jist.rb
85
+ - .gitignore
86
+ - .rspec
87
+ - Gemfile
88
+ - LICENSE.MIT
89
+ - README.md
90
+ - Rakefile
38
91
  - bin/jist
92
+ - jist.gemspec
93
+ - lib/jist.rb
94
+ - spec/clipboard_spec.rb
95
+ - spec/ghe_spec.rb
96
+ - spec/proxy_spec.rb
97
+ - spec/shorten_spec.rb
98
+ - spec/spec_helper.rb
39
99
  homepage: https://github.com/ConradIrwin/jist
40
- licenses: []
100
+ licenses:
101
+ - MIT
41
102
  post_install_message:
42
103
  rdoc_options: []
43
104
  require_paths:
44
105
  - lib
45
106
  required_ruby_version: !ruby/object:Gem::Requirement
46
- none: false
47
107
  requirements:
48
108
  - - ! '>='
49
109
  - !ruby/object:Gem::Version
50
110
  version: '0'
51
- required_rubygems_version: !ruby/object:Gem::Requirement
52
111
  none: false
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
113
  requirements:
54
114
  - - ! '>='
55
115
  - !ruby/object:Gem::Version
56
116
  version: '0'
117
+ none: false
57
118
  requirements: []
58
119
  rubyforge_project:
59
- rubygems_version: 1.8.24
120
+ rubygems_version: 1.8.25
60
121
  signing_key:
61
122
  specification_version: 3
62
123
  summary: Just allows you to upload gists