lib/pinpress.rb in pinpress-1.5.2 vs lib/pinpress.rb in pinpress-1.6.0
- old
+ new
@@ -14,10 +14,42 @@
# Stores whether verbose output is turned on.
# @return [Boolean]
attr_accessor :verbose
end
+ # Determines whether an invalid combination of linking options
+ # (auto and manual, via either a switch or a config parameter)
+ # has been given.
+ # @param [Hash] opts
+ # @return [Bool]
+ def conflicting_link_opts?(opts)
+ auto_link_flag = opts[:a]
+ auto_link_conf = configuration.pinpress.auto_link
+ manual_link_flag = opts[:l]
+ manual_link_conf = configuration.pinpress.manual_link
+ ((auto_link_conf && manual_link_conf) || (auto_link_flag && manual_link_flag))
+ end
+
+ # Determines which URL linking options to set. There are some
+ # basic rules:
+ # 1. You can't specify both switches or both config options simultaneously.
+ # 2. Switches will take priority.
+ # 3. Config options are a last resort
+ # @param [Hash] opts_hash
+ # @return [Hash]
+ def determine_link_opts(opts_hash)
+ opts = {}
+ if opts_hash[:a_switch] || opts_hash[:m_switch]
+ opts.merge!(auto_link: true) if opts_hash[:a_switch]
+ opts.merge!(link: true) if opts_hash[:m_switch]
+ else
+ opts.merge!(auto_link: true) if opts_hash[:a_config]
+ opts.merge!(link: true) if opts_hash[:m_config]
+ end
+ opts
+ end
+
# Grabs Pinboard data (passed on passed options) and yields a block that
# allows the user to act upon that returned data.
# @param [Hash] pinboard_opts
# @yield pins
# @raise StandardError if Pinboard client fails
@@ -32,11 +64,11 @@
end
rescue StandardError => e
messenger.debug(e.to_s)
puts e.to_s
raise "Pinboard API failed; are you sure you've run " \
- " `pinpress init` (and that your API key is correct)?"
+ " `pinpress init` (and that your API key is correct)?"
end
end
# Returns a template Hash from the configuration file.
# @param [String] template_name The name of the template to get
@@ -85,10 +117,11 @@
if from_scratch
configuration.reset
# Add initial configuration info.
configuration.add_section(:pinpress)
+ configuration.add_section(:links)
configuration.pinpress = {
config_location: configuration.config_path,
default_pin_template: 'pinpress_default',
default_tag_template: 'pinpress_default',
log_level: 'WARN',
@@ -133,33 +166,82 @@
templates = configuration.tag_templates
end
!templates.find { |t| t.keys[0] == template_name.to_sym }.nil?
end
+ def link_urls_in_desc(name, description, method)
+ fail "Unknown link creation methdo: #{ method.to_s }" unless [:AUTO, :MANUAL].include? method
+ urls = URI.extract(description, ['http', 'https'])
+ urls.each do |u|
+ link_text = nil
+ pin_id = Digest::MD5.hexdigest(description + u)
+
+ # I don't get why, but URL.extract is loose enough to include
+ # weird characters. This is my evolving regex to handle those.
+ u.sub!(/[()\.]+$/, '')
+
+ if configuration.links.send(pin_id)
+ # First, check the configuration file to see if we've stored
+ # this URL before (so that we can grab the saved value).
+ link_text = configuration.links.send(pin_id).link_text
+ else
+ if method == :AUTO
+ # If the configuration file doesn't have an entry for this
+ # link, no worries; create one.
+ link_text = u
+ elsif method == :MANUAL
+ # If the configuration file doesn't have an entry for this
+ # link, no worries; create one.
+ CLIUtils::PrettyIO.wrap = false
+ messenger.section('URL FOUND!')
+ messenger.info("URL:\t\t#{ u }")
+ messenger.info("TITLE:\t#{ name }")
+ messenger.info("POSITION:\t..." + description.scan(/.{0,40}#{ u }.{0,40}/)[0] + '...')
+ until !link_text.nil?
+ link_text = messenger.prompt('What do you want the link text to say?')
+ messenger.warn('Please provide some link text.') if link_text.nil?
+ end
+ CLIUtils::PrettyIO.wrap = true
+ end
+
+ # Store this newly created link info back in the configuration
+ # file.
+ configuration.links.merge!(pin_id => {
+ title: name,
+ url: u,
+ link_text: link_text
+ })
+ end
+ description.sub!(u, "<a href=\"#{ u }\" target=\"_blank\">#{ link_text }</a>")
+ end
+ description
+ end
+
# Present a list of installed templates to the user
# @return [void]
def list_templates
%w(pin tag).each do |type|
templates = configuration.send("#{ type }_templates")
messenger.section("AVAILABLE #{ type.upcase } TEMPLATES:")
if templates
templates.each_with_index do |template, index|
template_name, template = template.first
- puts "#{ index + 1 }.\tName: ".blue + "#{ template_name }"
- puts "Opener:".blue.rjust(22) + "\t#{ template[:opener] }".truncate(80)
- puts "Item:".blue.rjust(22) + "\t#{ template[:item] }".truncate(80)
- puts "Closer:".blue.rjust(22) + "\t#{ template[:closer] }".truncate(80)
+ puts "#{ index + 1 }.\tName: ".blue + "#{ template_name }"
+ puts "Opener:".blue.rjust(22) + "\t#{ template[:opener] }".truncate(80)
+ puts "Item:".blue.rjust(22) + "\t#{ template[:item] }".truncate(80)
+ puts "Closer:".blue.rjust(22) + "\t#{ template[:closer] }".truncate(80)
end
else
messenger.warn('No templates defined...')
end
end
end
# Helper method to merge command line options that are relevant for both pin
# and tag requests.
# @param [Hash] options
+ # @raise StandardError if an invalid combo of linking options is given
# @return [Hash]
def merge_common_options(options, template_name, template_type)
case template_type
when PinPress::Template::TYPE_PIN
section = configuration.pin_templates.find { |t| t.keys[0] == template_name.to_sym}.values[0]
@@ -177,27 +259,53 @@
if options[:t]
opts.merge!(tag: options[:t])
elsif section.default_tags
opts.merge!(tag: section.default_tags.join(','))
end
+
+ # These options are PinPress-related, not necessarily Pinboard-related;
+ # for the sake of convenience, they're included here.
+
+ # Auto-linking and prompting for link text don't go together, so make
+ # sure to let the user know if they include both.
+ if conflicting_link_opts?(options)
+ fail "You can't specify (a) both the `-a` and `-l` switches or " \
+ "(b) both the `auto_link` and `manual_link` configuration options."
+ else
+ link_opts = determine_link_opts({
+ a_switch: options[:a],
+ m_switch: options[:l],
+ a_config: configuration.pinpress.auto_link,
+ m_config: configuration.pinpress.manual_link
+ })
+ opts.merge!(link_opts) if link_opts
+ end
opts
end
# Creates text output from pin data (based upon a passed template).
# @param [Hash] template The template to use
# @param [Hash] opts CLI options to use
# @return [String]
def pin_yield(template, opts)
output = ''
PinPress.execute_template(opts) do |data|
- html_coder = HTMLEntities.new
-
output += template[:opener] if template[:opener]
data.each do |i|
+ name = HTMLEntities.new.encode(i[:description])
+
+ if opts[:link]
+ desc = link_urls_in_desc(name, i[:extended], :MANUAL)
+ elsif opts[:auto_link]
+ desc = link_urls_in_desc(name, i[:extended], :AUTO)
+ else
+ desc = i[:extended]
+ end
+
href = i[:href]
- description = html_coder.encode(i[:description])
- extended = i[:extended]
+ description = name
+ extended = desc
tag = i[:tag]
time = i[:time]
replace = i[:replace]
shared = i[:shared]
toread = i[:toread]
@@ -237,11 +345,11 @@
# Notifies the user that the config file needs to be
# re-done and does it.
# @return [void]
def update_config_file
m = "This version needs to make some config changes. Don't worry; " \
- "when prompted, your current values for existing config options " \
- "will be presented (so it'll be easier to fly through the upgrade)."
+ "when prompted, your current values for existing config options " \
+ "will be presented (so it'll be easier to fly through the upgrade)."
messenger.info(m)
messenger.prompt('Press enter to continue')
PinPress.init(true)
end
end