Skip to content

Commit 37f00cb

Browse files
rkingrking@sharpsaw.org
authored andcommitted
Add clipboard support and tests
We investigated using the clipboard gem but it was deemed to be unnecessarily complicated, and made assumptions that we'd rather not be lumbered with.
1 parent 75a5731 commit 37f00cb

File tree

7 files changed

+112
-1
lines changed

7 files changed

+112
-1
lines changed

.rspec

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--color
2+
--format progress
3+
-r ./spec/spec_helper.rb

Rakefile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
task :default => :test
2+
3+
desc 'run the tests' # that's non-DRY
4+
task :test do
5+
sh 'rspec spec'
6+
end

bin/jist

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ Anonymous gists are not associated with your GitHub account, they can be created
3232
with "-a" even after you have used "jist --login". If you already have an access
3333
token with the "gist" scope, you can pass that with "-t".
3434
35+
To copy the resulting URL to your clipboard you can use the -c option. If you'd
36+
prefer this to be the default behaviour, add `alias jist='jist -c'` to your
37+
shell's rc file.
38+
3539
Instead of creating a new jist, you can update an existing one by passing its ID
3640
or URL with "-u". For this to work, you must be logged in, and have created the
3741
original gist with the same GitHub account.
@@ -68,6 +72,10 @@ original gist with the same GitHub account.
6872
options[:access_token] = token
6973
end
7074

75+
opts.on("-c", "--copy", "Copy the resulting URL to the clipboard") do
76+
options[:copy] = true
77+
end
78+
7179
opts.on_tail("-h","--help", "Show this message.") do
7280
puts opts
7381
exit

jist.gemspec

+3
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ Gem::Specification.new do |s|
1313
s.executables << 'jist'
1414

1515
s.add_dependency 'json'
16+
%w(rake rspec).each do |gem|
17+
s.add_development_dependency gem
18+
end
1619
end

lib/jist.rb

+45-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ module Jist
77

88
VERSION = '0.9.2'
99

10+
# Which clipboard commands do we support?
11+
CLIP_COMMANDS = %w(xclip xsel pbcopy putclip)
12+
1013
# Exception tag for errors raised while gisting.
1114
module Error; end
1215

@@ -22,6 +25,7 @@ module Error; end
2225
# @option options [Boolean] :anonymous (false) is this gist anonymous
2326
# @option options [String] :access_token (`File.read("~/.jist")`) The OAuth2 access token.
2427
# @option options [String] :update the URL or id of a gist to update
28+
# @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
2529
#
2630
# @return [Hash] the decoded JSON response from the server
2731
# @raise [Jist::Error] if something went wrong
@@ -42,6 +46,7 @@ def gist(content, options = {})
4246
# @option options [Boolean] :anonymous (false) is this gist anonymous
4347
# @option options [String] :access_token (`File.read("~/.jist")`) The OAuth2 access token.
4448
# @option options [String] :update the URL or id of a gist to update
49+
# @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
4550
#
4651
# @return [Hash] the decoded JSON response from the server
4752
# @raise [Jist::Error] if something went wrong
@@ -79,7 +84,7 @@ def multi_gist(files, options={})
7984
begin
8085
response = http(request)
8186
if Net::HTTPSuccess === response
82-
JSON.parse(response.body)
87+
on_success(response.body, options)
8388
else
8489
raise "Got #{response.class} from gist: #{response.body}"
8590
end
@@ -152,4 +157,43 @@ def http(request)
152157
rescue Timeout::Error
153158
raise "Could not connect to https://api.github.com/"
154159
end
160+
161+
module_function
162+
163+
# Called after an HTTP response to gist to perform post-processing.
164+
#
165+
# @param [String] body the HTTP-200 response
166+
# @param [Hash] options any options
167+
# @option options [Boolean] :copy copy the URL to the clipboard
168+
# @return [Hash] the parsed JSON response from the server
169+
def on_success(body, options={})
170+
json = JSON.parse(body)
171+
172+
if options[:copy]
173+
Jist.copy(json['html_url'])
174+
end
175+
176+
json
177+
end
178+
179+
# Copy a string to the clipboard.
180+
#
181+
# @param [String] content
182+
# @return content
183+
# @raise [RuntimeError] if no clipboard integration could be found
184+
#
185+
# This method was heavily inspired by defunkt's Gist#copy,
186+
# @see https://github.com/defunkt/gist/blob/bca9b29/lib/gist.rb#L178
187+
def copy(content)
188+
189+
command = CLIP_COMMANDS.detect do |cmd|
190+
system("type #{cmd} >/dev/null 2>&1")
191+
end
192+
193+
unless command
194+
raise "Could not find copy command, tried: #{CLIP_COMMANDS}"
195+
end
196+
197+
IO.popen(copy_cmd.to_s, 'r+') { |clip| clip.print content }
198+
end
155199
end

spec/clipboard_spec.rb

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 )
13+
end
14+
def jist_but_dont_ask_for_copy
15+
Jist.on_success({'html_url' => 'http://example.com/'}.to_json)
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 not copy when not asked to" do
24+
Jist.should_not_receive(:copy).with(@bobo_url)
25+
jist_but_dont_ask_for_copy
26+
end
27+
28+
it "should raise an error if no copying mechanisms are available" do
29+
ENV['PATH'] = ''
30+
lambda{
31+
ask_for_copy
32+
}.should raise_error(/Could not find copy command/)
33+
end
34+
end

spec/spec_helper.rb

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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_relative '../lib/jist'

0 commit comments

Comments
 (0)