pinpress 1.5.2 → 1.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16c3a1261457d78a7a116bca2aa115a42f75f279
4
- data.tar.gz: b3ccd701978f3b4bfdc7c85d76db03d0a423fa38
3
+ metadata.gz: a18271b52fbf91d439eb277c0209d80339d19c8c
4
+ data.tar.gz: 0513753afd1a9279d7d233fa641e9f87841691b7
5
5
  SHA512:
6
- metadata.gz: 77281608528aea4c3945c48a2eea792228b0d2769730226316c04845a7031e7a666c9fb6b707bad172cfd16a62487164b61a99832fb0140becb026239e33a175
7
- data.tar.gz: 9112abaf1f90bf2b5b8da67ea995152a5c37b29d62644e6bdb0ee4a64bfdffdeb4cfb1d74064f1c2468fbc8128a329ec0a2c1c925e0065ed33ae1184c02c913a
6
+ metadata.gz: 56b51a77a71eb554ed33fd00b9b339479e9750cb5ca03cdf9bce5ca821df18dfa7e6dab4b20757062662e5841711708fa7582956d10133503168ac6cacb9158c
7
+ data.tar.gz: b44f2e29926a453d9421a7f2926ea1cd1a330b31138faee87ab37d2537a77e413d4b1e0ef1ad4b4410644ddb3f28dbab4343e7306f44384888d94b3e70568b60
data/HISTORY.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 1.6.0 (2014-09-15)
2
+
3
+ * Added `-a` flag to automatically create hyperlinks from URLs in pin descriptions
4
+ * Added `-l` flag to prompt user to build hyperlinks around URLs in pin descriptions
5
+ * Added `-c` flag to automatically copy output to system clipboard
6
+
1
7
  # 1.5.2 (2014-06-07)
2
8
 
3
9
  * Fixed a small bug with running `tags last`
data/README.md CHANGED
@@ -42,7 +42,7 @@ SYNOPSIS
42
42
  pinpress [global options] command [command options] [arguments...]
43
43
 
44
44
  VERSION
45
- 1.5.2
45
+ 1.6.0
46
46
 
47
47
  GLOBAL OPTIONS
48
48
  --help - Show this message
@@ -68,11 +68,18 @@ SYNOPSIS
68
68
  pinpress [global options] pins [command options]
69
69
 
70
70
  COMMAND OPTIONS
71
+ -a - Auto-links any URLs found in a pin description
72
+ -c - Copy final output to the system clipboard
71
73
  -e arg - The end date to pull pins to (default: none)
74
+ l - Allows the user to create <a> links around detected URLs
72
75
  -m arg - The pin template to use (default: none)
73
76
  -n arg - The number of results to return (default: none)
74
77
  -s arg - The start date to pull pins from (default: none)
75
78
  -t arg - The tags to use (e.g., "ruby,pinboard") (default: none)
79
+
80
+ COMMANDS
81
+ <default> -
82
+ last - Gets all pins from the last run date + 1
76
83
  ```
77
84
 
78
85
  # Initialization
@@ -102,6 +109,9 @@ grab:
102
109
  * `-n`: the number of pins to return (e.g., 20)
103
110
  * `-t`: a CSV list of tags (e.g., "tag1,tag2") that must exist for the returned pins
104
111
 
112
+ By default, pin template text will be output to the terminal; you can use the
113
+ `-c` switch to output it to the system clipboard instead.
114
+
105
115
  ## Getting Pins From a Date Forward
106
116
 
107
117
  ```bash
@@ -162,6 +172,9 @@ grab:
162
172
  * `-s`: the start date to use (uses [Chronic](https://github.com/mojombo/chronic "Chronic"), which allows dates like "last Tuesday")
163
173
  * `-e`: the end date to use (also uses [Chronic](https://github.com/mojombo/chronic "Chronic"))
164
174
 
175
+ By default, pin template text will be output to the terminal; you can use the
176
+ `-c` switch to output it to the system clipboard instead.
177
+
165
178
  ## Getting Tags From a Date Forward
166
179
 
167
180
  ```bash
@@ -376,6 +389,105 @@ $ pinpress tags -m pinpress_default
376
389
  link-mash (15),app (2),ios (3),productivity (1),launch-center-pro (1),drafts (2),
377
390
  ```
378
391
 
392
+ # URL Linking
393
+
394
+ I often run into the situation where I want to take a URL from a pin's description
395
+ and add an `<a>` tag around it (since Pinboard doesn't allow you to embed the HTML
396
+ within the pin description itself). PinPress provides two mechanisms to accomplish
397
+ this: automatic linking and manual linking.
398
+
399
+ ## Automatic URL Linking
400
+
401
+ ### Using It
402
+
403
+ To use automatic linking, simply use the `-a` switch when running PinPress.
404
+
405
+ Alternatively, to always use automatic linking, include a `auto_link` key/value
406
+ in `~/.pinpress`:
407
+
408
+ ```yaml
409
+ pinpress:
410
+ auto_link: true
411
+ ```
412
+
413
+ Note that the `auto_link` configuration key can be overridden by using a different
414
+ URL linking switch (such as `-l`).
415
+
416
+ ### How It Works
417
+
418
+ Using this method, PinPress will scan each pin that is being requested for URLs.
419
+ Upon finding a URL, PinPress will automatically wrap it in an `<a>` tag.
420
+
421
+ For example, given a description that looks like this:
422
+
423
+ ```html
424
+ ...this is some text with a URL: http://www.google.com.
425
+ ```
426
+
427
+ ...PinPress will modify the description such that the following is output
428
+ instead:
429
+
430
+ ```html
431
+ ...this is some text with a URL: <a href="http://www.google.com" target="_blank">http://www.google.com</a>.
432
+ ```
433
+
434
+ Finally, this link gets stored in `~/.pinpress`:
435
+
436
+ ```yaml
437
+ links:
438
+ # This ID is a combination of the URL
439
+ # and the pin in which it is found.
440
+ 853d65b7e76a57955040e97902fc2b3c:
441
+ title: Pin with Google
442
+ url: http://www.google.com
443
+ link_text: http://www.google.com
444
+ ```
445
+
446
+ This happens for two reasons:
447
+
448
+ 1. Going forward, any request that returns this pin will use the data found
449
+ in `~/.pinpress` (so that it doesn't have to be recalculated).
450
+ 2. If you want to modify the text that gets used for this link in this pin,
451
+ you can do it here.
452
+
453
+ ## Manual URL Linking
454
+
455
+ ### Using It
456
+
457
+ To use automatic linking, simply use the `-l` switch when running PinPress.
458
+
459
+ Alternatively, to always use automatic linking, include a `manual_link` key/value
460
+ in `~/.pinpress`:
461
+
462
+ ```yaml
463
+ pinpress:
464
+ manual_link: true
465
+ ```
466
+
467
+ Note that the `manual_link` configuration key can be overridden by using a different
468
+ URL linking switch (such as `-a`).
469
+
470
+ ### How It Works
471
+
472
+ This method is similar to automatic linking in that it will search each pin in the
473
+ output for URLs in its description. When found, the user is prompted to enter the
474
+ text that will create the link.
475
+
476
+ For example, given a description that looks like this:
477
+
478
+ ```html
479
+ Check out https://gifyoutube.com/!
480
+ ```
481
+
482
+ ...imagine that the user types in `GIF Youtube`; the result will look like this:
483
+
484
+ ```html
485
+ Check out <a href="https://gifyoutube.com/" target="_blank">GIF Youtube</a>!
486
+ ```
487
+
488
+ Like automatic linking, the results of this URL/pin combo are stored in
489
+ `~/.pinpress` for easy lookup and future editing.
490
+
379
491
  # Other Configuration Options
380
492
 
381
493
  ## Global Keys
@@ -388,10 +500,20 @@ pinpress:
388
500
  # ...other keys...
389
501
 
390
502
  # The default pins template to use
391
- default_pin_template
503
+ default_pin_template: template_name
392
504
 
393
505
  # The default tags template to use
394
- default_tag_template
506
+ default_tag_template: template_name
507
+
508
+ # Automatic URL linking; note that this
509
+ # cannot exist eat the same time as manual
510
+ # URL linking
511
+ auto_link: true
512
+
513
+ # Manual URL linking; note that this
514
+ # cannot exist eat the same time as auto
515
+ # URL linking
516
+ manual_link: true
395
517
 
396
518
  # ...other keys...
397
519
  ```
@@ -434,8 +556,9 @@ pinpress:
434
556
  default_pin_template: pinpress_default
435
557
  default_tag_template: pinpress_default
436
558
  log_level: WARN
437
- version: 1.5.0
559
+ version: 1.6.0
438
560
  api_token: bachya:1234567890987654321
561
+ manual_link: true
439
562
  pin_templates:
440
563
  - pinpress_default:
441
564
  opener: |
@@ -32,10 +32,13 @@
32
32
  #--------------------------------------------------------------------
33
33
  require 'chronic'
34
34
  require 'cliutils'
35
+ require 'digest/md5'
35
36
  require 'gli'
36
37
  require 'htmlentities'
38
+ require 'pbcopy'
37
39
  require 'pinboard'
38
40
  require 'pinpress'
41
+ require 'uri'
39
42
 
40
43
  include CLIUtils::Configuration
41
44
  include CLIUtils::Messaging
@@ -135,6 +138,10 @@ command :pins do |c|
135
138
  c.flag([:s], desc: 'The start date to pull pins from')
136
139
  c.flag([:t], desc: 'The tags to use (e.g., "ruby,pinboard")')
137
140
 
141
+ c.switch([:a], desc: 'Auto-links any URLs found in a pin description')
142
+ c.switch([:c], desc: 'Copy final output to the system clipboard')
143
+ c.switch([:l], desc: 'Allows the user to create <a> links around detected URLs')
144
+
138
145
  c.desc 'Gets pins from Pinboard'
139
146
  c.action do |global_options, options, args|
140
147
  PinPress.verbose = global_options[:v]
@@ -152,7 +159,17 @@ command :pins do |c|
152
159
 
153
160
  # Request pin data from Pinboard and output the return data.
154
161
  output = PinPress.pin_yield(template, opts)
155
- puts output if output
162
+
163
+ # If the `-c` switch is used, copy the output to the system clipboard;
164
+ # otherwise, simply output it to the termianl.
165
+ # puts output if output
166
+ if output
167
+ if options[:c]
168
+ output | pbcopy
169
+ else
170
+ puts output
171
+ end
172
+ end
156
173
 
157
174
  # Save the last-run date to the configuration file.
158
175
  configuration.pin_templates.find { |t| t.keys[0] == template_name.to_sym}.values[0].last_run = Time.now.utc.iso8601
@@ -181,7 +198,17 @@ command :pins do |c|
181
198
 
182
199
  # Request pin data from Pinboard and output the return data.
183
200
  output = PinPress.pin_yield(template, opts)
184
- puts output if output
201
+
202
+ # If the `-c` switch is used, copy the output to the system clipboard;
203
+ # otherwise, simply output it to the termianl.
204
+ # puts output if output
205
+ if output
206
+ if options[:c]
207
+ output | pbcopy
208
+ else
209
+ puts output
210
+ end
211
+ end
185
212
 
186
213
  # Save the last-run date to the configuration file.
187
214
  configuration.pin_templates.find { |t| t.keys[0] == template_name.to_sym}.values[0].last_run = Time.now.utc.iso8601
@@ -219,7 +246,17 @@ command :tags do |c|
219
246
 
220
247
  # Request tag data from Pinboard and output the return data.
221
248
  output = PinPress.tag_yield(template, opts)
222
- puts output if output
249
+
250
+ # If the `-c` switch is used, copy the output to the system clipboard;
251
+ # otherwise, simply output it to the termianl.
252
+ # puts output if output
253
+ if output
254
+ if options[:c]
255
+ output | pbcopy
256
+ else
257
+ puts output
258
+ end
259
+ end
223
260
 
224
261
  # Save the last-run date to the configuration file.
225
262
  t_config = configuration.tag_templates.find { |t| t.keys[0] == template_name.to_sym}.values[0]
@@ -249,7 +286,17 @@ command :tags do |c|
249
286
 
250
287
  # Request tag data from Pinboard and output the return data.
251
288
  output = PinPress.tag_yield(template, opts)
252
- puts output if output
289
+
290
+ # If the `-c` switch is used, copy the output to the system clipboard;
291
+ # otherwise, simply output it to the termianl.
292
+ # puts output if output
293
+ if output
294
+ if options[:c]
295
+ output | pbcopy
296
+ else
297
+ puts output
298
+ end
299
+ end
253
300
 
254
301
  # Save the last-run date to the configuration file.
255
302
  t_config = configuration.tag_templates.find { |t| t.keys[0] == template_name.to_sym}.values[0]
@@ -16,6 +16,38 @@ module PinPress
16
16
  attr_accessor :verbose
17
17
  end
18
18
 
19
+ # Determines whether an invalid combination of linking options
20
+ # (auto and manual, via either a switch or a config parameter)
21
+ # has been given.
22
+ # @param [Hash] opts
23
+ # @return [Bool]
24
+ def conflicting_link_opts?(opts)
25
+ auto_link_flag = opts[:a]
26
+ auto_link_conf = configuration.pinpress.auto_link
27
+ manual_link_flag = opts[:l]
28
+ manual_link_conf = configuration.pinpress.manual_link
29
+ ((auto_link_conf && manual_link_conf) || (auto_link_flag && manual_link_flag))
30
+ end
31
+
32
+ # Determines which URL linking options to set. There are some
33
+ # basic rules:
34
+ # 1. You can't specify both switches or both config options simultaneously.
35
+ # 2. Switches will take priority.
36
+ # 3. Config options are a last resort
37
+ # @param [Hash] opts_hash
38
+ # @return [Hash]
39
+ def determine_link_opts(opts_hash)
40
+ opts = {}
41
+ if opts_hash[:a_switch] || opts_hash[:m_switch]
42
+ opts.merge!(auto_link: true) if opts_hash[:a_switch]
43
+ opts.merge!(link: true) if opts_hash[:m_switch]
44
+ else
45
+ opts.merge!(auto_link: true) if opts_hash[:a_config]
46
+ opts.merge!(link: true) if opts_hash[:m_config]
47
+ end
48
+ opts
49
+ end
50
+
19
51
  # Grabs Pinboard data (passed on passed options) and yields a block that
20
52
  # allows the user to act upon that returned data.
21
53
  # @param [Hash] pinboard_opts
@@ -34,7 +66,7 @@ module PinPress
34
66
  messenger.debug(e.to_s)
35
67
  puts e.to_s
36
68
  raise "Pinboard API failed; are you sure you've run " \
37
- " `pinpress init` (and that your API key is correct)?"
69
+ " `pinpress init` (and that your API key is correct)?"
38
70
  end
39
71
  end
40
72
 
@@ -87,6 +119,7 @@ module PinPress
87
119
 
88
120
  # Add initial configuration info.
89
121
  configuration.add_section(:pinpress)
122
+ configuration.add_section(:links)
90
123
  configuration.pinpress = {
91
124
  config_location: configuration.config_path,
92
125
  default_pin_template: 'pinpress_default',
@@ -135,6 +168,54 @@ module PinPress
135
168
  !templates.find { |t| t.keys[0] == template_name.to_sym }.nil?
136
169
  end
137
170
 
171
+ def link_urls_in_desc(name, description, method)
172
+ fail "Unknown link creation methdo: #{ method.to_s }" unless [:AUTO, :MANUAL].include? method
173
+ urls = URI.extract(description, ['http', 'https'])
174
+ urls.each do |u|
175
+ link_text = nil
176
+ pin_id = Digest::MD5.hexdigest(description + u)
177
+
178
+ # I don't get why, but URL.extract is loose enough to include
179
+ # weird characters. This is my evolving regex to handle those.
180
+ u.sub!(/[()\.]+$/, '')
181
+
182
+ if configuration.links.send(pin_id)
183
+ # First, check the configuration file to see if we've stored
184
+ # this URL before (so that we can grab the saved value).
185
+ link_text = configuration.links.send(pin_id).link_text
186
+ else
187
+ if method == :AUTO
188
+ # If the configuration file doesn't have an entry for this
189
+ # link, no worries; create one.
190
+ link_text = u
191
+ elsif method == :MANUAL
192
+ # If the configuration file doesn't have an entry for this
193
+ # link, no worries; create one.
194
+ CLIUtils::PrettyIO.wrap = false
195
+ messenger.section('URL FOUND!')
196
+ messenger.info("URL:\t\t#{ u }")
197
+ messenger.info("TITLE:\t#{ name }")
198
+ messenger.info("POSITION:\t..." + description.scan(/.{0,40}#{ u }.{0,40}/)[0] + '...')
199
+ until !link_text.nil?
200
+ link_text = messenger.prompt('What do you want the link text to say?')
201
+ messenger.warn('Please provide some link text.') if link_text.nil?
202
+ end
203
+ CLIUtils::PrettyIO.wrap = true
204
+ end
205
+
206
+ # Store this newly created link info back in the configuration
207
+ # file.
208
+ configuration.links.merge!(pin_id => {
209
+ title: name,
210
+ url: u,
211
+ link_text: link_text
212
+ })
213
+ end
214
+ description.sub!(u, "<a href=\"#{ u }\" target=\"_blank\">#{ link_text }</a>")
215
+ end
216
+ description
217
+ end
218
+
138
219
  # Present a list of installed templates to the user
139
220
  # @return [void]
140
221
  def list_templates
@@ -144,10 +225,10 @@ module PinPress
144
225
  if templates
145
226
  templates.each_with_index do |template, index|
146
227
  template_name, template = template.first
147
- puts "#{ index + 1 }.\tName: ".blue + "#{ template_name }"
148
- puts "Opener:".blue.rjust(22) + "\t#{ template[:opener] }".truncate(80)
149
- puts "Item:".blue.rjust(22) + "\t#{ template[:item] }".truncate(80)
150
- puts "Closer:".blue.rjust(22) + "\t#{ template[:closer] }".truncate(80)
228
+ puts "#{ index + 1 }.\tName: ".blue + "#{ template_name }"
229
+ puts "Opener:".blue.rjust(22) + "\t#{ template[:opener] }".truncate(80)
230
+ puts "Item:".blue.rjust(22) + "\t#{ template[:item] }".truncate(80)
231
+ puts "Closer:".blue.rjust(22) + "\t#{ template[:closer] }".truncate(80)
151
232
  end
152
233
  else
153
234
  messenger.warn('No templates defined...')
@@ -158,6 +239,7 @@ module PinPress
158
239
  # Helper method to merge command line options that are relevant for both pin
159
240
  # and tag requests.
160
241
  # @param [Hash] options
242
+ # @raise StandardError if an invalid combo of linking options is given
161
243
  # @return [Hash]
162
244
  def merge_common_options(options, template_name, template_type)
163
245
  case template_type
@@ -179,6 +261,24 @@ module PinPress
179
261
  elsif section.default_tags
180
262
  opts.merge!(tag: section.default_tags.join(','))
181
263
  end
264
+
265
+ # These options are PinPress-related, not necessarily Pinboard-related;
266
+ # for the sake of convenience, they're included here.
267
+
268
+ # Auto-linking and prompting for link text don't go together, so make
269
+ # sure to let the user know if they include both.
270
+ if conflicting_link_opts?(options)
271
+ fail "You can't specify (a) both the `-a` and `-l` switches or " \
272
+ "(b) both the `auto_link` and `manual_link` configuration options."
273
+ else
274
+ link_opts = determine_link_opts({
275
+ a_switch: options[:a],
276
+ m_switch: options[:l],
277
+ a_config: configuration.pinpress.auto_link,
278
+ m_config: configuration.pinpress.manual_link
279
+ })
280
+ opts.merge!(link_opts) if link_opts
281
+ end
182
282
  opts
183
283
  end
184
284
 
@@ -189,13 +289,21 @@ module PinPress
189
289
  def pin_yield(template, opts)
190
290
  output = ''
191
291
  PinPress.execute_template(opts) do |data|
192
- html_coder = HTMLEntities.new
193
-
194
292
  output += template[:opener] if template[:opener]
195
293
  data.each do |i|
294
+ name = HTMLEntities.new.encode(i[:description])
295
+
296
+ if opts[:link]
297
+ desc = link_urls_in_desc(name, i[:extended], :MANUAL)
298
+ elsif opts[:auto_link]
299
+ desc = link_urls_in_desc(name, i[:extended], :AUTO)
300
+ else
301
+ desc = i[:extended]
302
+ end
303
+
196
304
  href = i[:href]
197
- description = html_coder.encode(i[:description])
198
- extended = i[:extended]
305
+ description = name
306
+ extended = desc
199
307
  tag = i[:tag]
200
308
  time = i[:time]
201
309
  replace = i[:replace]
@@ -239,8 +347,8 @@ module PinPress
239
347
  # @return [void]
240
348
  def update_config_file
241
349
  m = "This version needs to make some config changes. Don't worry; " \
242
- "when prompted, your current values for existing config options " \
243
- "will be presented (so it'll be easier to fly through the upgrade)."
350
+ "when prompted, your current values for existing config options " \
351
+ "will be presented (so it'll be easier to fly through the upgrade)."
244
352
  messenger.info(m)
245
353
  messenger.prompt('Press enter to continue')
246
354
  PinPress.init(true)
@@ -28,5 +28,5 @@ module PinPress
28
28
  SUMMARY = 'A simple CLI to create HTML templates of Pinboard data.'
29
29
 
30
30
  # The Gem's version
31
- VERSION = '1.5.2'
31
+ VERSION = '1.6.0'
32
32
  end
@@ -22,5 +22,6 @@ Gem::Specification.new do |spec|
22
22
  spec.add_runtime_dependency('cliutils', '~> 2')
23
23
  spec.add_runtime_dependency('gli', '2.9.0')
24
24
  spec.add_runtime_dependency('htmlentities', '4.3.1')
25
+ spec.add_runtime_dependency('pbcopy', '1.0.1')
25
26
  spec.add_runtime_dependency('pinboard', '0.1.1')
26
27
  end
@@ -13,3 +13,4 @@ pin_templates:
13
13
  tag_templates:
14
14
  - name: pinpress_default
15
15
  item: "<%= tag %> (<%= count %>),"
16
+ links: {}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pinpress
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Bach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-07 00:00:00.000000000 Z
11
+ date: 2014-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aruba
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
124
  version: 4.3.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: pbcopy
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 1.0.1
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 1.0.1
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: pinboard
127
141
  requirement: !ruby/object:Gem::Requirement