pinpress 1.5.2 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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