Skip to content

Commit

Permalink
Add clipboard support and tests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rking authored and rking@sharpsaw.org committed Aug 7, 2012
1 parent 75a5731 commit 37f00cb
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .rspec
@@ -0,0 +1,3 @@
--color
--format progress
-r ./spec/spec_helper.rb
6 changes: 6 additions & 0 deletions Rakefile
@@ -0,0 +1,6 @@
task :default => :test

desc 'run the tests' # that's non-DRY
task :test do
sh 'rspec spec'
end
8 changes: 8 additions & 0 deletions bin/jist
Expand Up @@ -32,6 +32,10 @@ Anonymous gists are not associated with your GitHub account, they can be created
with "-a" even after you have used "jist --login". If you already have an access
token with the "gist" scope, you can pass that with "-t".
To copy the resulting URL to your clipboard you can use the -c option. If you'd
prefer this to be the default behaviour, add `alias jist='jist -c'` to your
shell's rc file.
Instead of creating a new jist, you can update an existing one by passing its ID
or URL with "-u". For this to work, you must be logged in, and have created the
original gist with the same GitHub account.
Expand Down Expand Up @@ -68,6 +72,10 @@ original gist with the same GitHub account.
options[:access_token] = token
end

opts.on("-c", "--copy", "Copy the resulting URL to the clipboard") do
options[:copy] = true
end

opts.on_tail("-h","--help", "Show this message.") do
puts opts
exit
Expand Down
3 changes: 3 additions & 0 deletions jist.gemspec
Expand Up @@ -13,4 +13,7 @@ Gem::Specification.new do |s|
s.executables << 'jist'

s.add_dependency 'json'
%w(rake rspec).each do |gem|
s.add_development_dependency gem
end
end
46 changes: 45 additions & 1 deletion lib/jist.rb
Expand Up @@ -7,6 +7,9 @@ module Jist

VERSION = '0.9.2'

# Which clipboard commands do we support?
CLIP_COMMANDS = %w(xclip xsel pbcopy putclip)

# Exception tag for errors raised while gisting.
module Error; end

Expand All @@ -22,6 +25,7 @@ module Error; end
# @option options [Boolean] :anonymous (false) is this gist anonymous
# @option options [String] :access_token (`File.read("~/.jist")`) The OAuth2 access token.
# @option options [String] :update the URL or id of a gist to update
# @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
#
# @return [Hash] the decoded JSON response from the server
# @raise [Jist::Error] if something went wrong
Expand All @@ -42,6 +46,7 @@ def gist(content, options = {})
# @option options [Boolean] :anonymous (false) is this gist anonymous
# @option options [String] :access_token (`File.read("~/.jist")`) The OAuth2 access token.
# @option options [String] :update the URL or id of a gist to update
# @option options [Boolean] :copy (false) Copy resulting URL to clipboard, if successful.
#
# @return [Hash] the decoded JSON response from the server
# @raise [Jist::Error] if something went wrong
Expand Down Expand Up @@ -79,7 +84,7 @@ def multi_gist(files, options={})
begin
response = http(request)
if Net::HTTPSuccess === response
JSON.parse(response.body)
on_success(response.body, options)
else
raise "Got #{response.class} from gist: #{response.body}"
end
Expand Down Expand Up @@ -152,4 +157,43 @@ def http(request)
rescue Timeout::Error
raise "Could not connect to https://api.github.com/"
end

module_function

# Called after an HTTP response to gist to perform post-processing.
#
# @param [String] body the HTTP-200 response
# @param [Hash] options any options
# @option options [Boolean] :copy copy the URL to the clipboard
# @return [Hash] the parsed JSON response from the server
def on_success(body, options={})
json = JSON.parse(body)

if options[:copy]
Jist.copy(json['html_url'])
end

json
end

# Copy a string to the clipboard.
#
# @param [String] content
# @return content
# @raise [RuntimeError] if no clipboard integration could be found
#
# This method was heavily inspired by defunkt's Gist#copy,
# @see https://github.com/defunkt/gist/blob/bca9b29/lib/gist.rb#L178
def copy(content)

command = CLIP_COMMANDS.detect do |cmd|
system("type #{cmd} >/dev/null 2>&1")
end

unless command
raise "Could not find copy command, tried: #{CLIP_COMMANDS}"
end

IO.popen(copy_cmd.to_s, 'r+') { |clip| clip.print content }
end
end
34 changes: 34 additions & 0 deletions spec/clipboard_spec.rb
@@ -0,0 +1,34 @@
describe '...' do
before do
@saved_path = ENV['PATH']
@bobo_url = 'http://example.com'
end

after do
ENV['PATH'] = @saved_path
end

def ask_for_copy
Jist.on_success({'html_url' => @bobo_url}.to_json, :copy => true )
end
def jist_but_dont_ask_for_copy
Jist.on_success({'html_url' => 'http://example.com/'}.to_json)
end

it 'should try to copy the url when the clipboard option is passed' do
Jist.should_receive(:copy).with(@bobo_url)
ask_for_copy
end

it "should not copy when not asked to" do
Jist.should_not_receive(:copy).with(@bobo_url)
jist_but_dont_ask_for_copy
end

it "should raise an error if no copying mechanisms are available" do
ENV['PATH'] = ''
lambda{
ask_for_copy
}.should raise_error(/Could not find copy command/)
end
end
13 changes: 13 additions & 0 deletions spec/spec_helper.rb
@@ -0,0 +1,13 @@
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# Require this file using `require "spec_helper.rb"` to ensure that it is only
# loaded once.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
config.filter_run :focus
end

require_relative '../lib/jist'

0 comments on commit 37f00cb

Please sign in to comment.