snibbets 2.0.28 → 2.0.30

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
  SHA256:
3
- metadata.gz: 6f9f01ad7e1ae9656d572bbd502f4b0dc1fa7d344509a6a93f07b765d515ddca
4
- data.tar.gz: 0bc11012e818d56256550af0b3df3fe952307d2f86b8e7da9d91a8a80dfbafee
3
+ metadata.gz: a633139ac4f908c760dc709e91937cfeb6d77c8a3a2aebdfc0e9acec1760a25b
4
+ data.tar.gz: efc77b72771c37c1cda78a6fb66d4af532b9b2c31648e6b7fce4854a2310204e
5
5
  SHA512:
6
- metadata.gz: a8926027efe84785a45414761eab33b66474a819ed394e52e1f638c95e5ae7a3aad857df95728640f3ccf68ad0d471b93039b694bfa0d72886b682afad13c3c5
7
- data.tar.gz: bfc6c99b3178fb1f7cb8dc3b7aad350cca53e6f560ab19357924291346e6bc74583c9755a945363122105840ef66abee960a8aa9ca75547f23b239be088761b1
6
+ metadata.gz: af5ac5a46200ee38bc3fc20daed4bfdc2ca47841cc665883ac7837629436fe42e77a0b953f1d5c3615d0622f2a08e2672771876eb89a86e93afb66d8e89d265d
7
+ data.tar.gz: 89292879a4cd79acb7b30a24a7ed760557b6b26493a3311abbc42eeef097348d36b0b7c2b69475e5aa0d0729d493885647673675cf46b435fabfa7a4d0661fcb
data/CHANGELOG.md CHANGED
@@ -1,75 +1,43 @@
1
- ### 2.0.28
1
+ ### 2.0.30
2
2
 
3
- 2023-04-18 09:18
3
+ 2023-04-19 06:44
4
4
 
5
5
  #### NEW
6
6
 
7
- - `--nvultra` will open the selected snippet in nvUltra
7
+ - Added `--notes` option and accompanying `all_notes` config option to allow display of all notes instead of just code blocks in each snippet
8
8
 
9
9
  #### IMPROVED
10
10
 
11
- - Use Readline for entering info with `--paste`, allows for better editing experience
12
- - Allow `--edit` with `--paste` to open the new snippet in your editor immediately
11
+ - Previously if multiple snippets were output, titles of snippets would go to STDERR so they weren't copied. Now they go to STDOUT as well.
13
12
 
14
- #### FIXED
13
+ ### 2.0.29
15
14
 
16
- - Code indentation with `--paste`
17
- - Nil error when highlighting without extension
18
- - When detecting indented code blocks, require a blank line (or start of file) before them, to avoid picking up lines within indented lists
15
+ 2023-04-18 10:45
19
16
 
20
- ### 2.0.27
17
+ #### IMPROVED
21
18
 
22
- 2023-04-17 15:54
19
+ - Better removal of extra leading/trailing newlines
23
20
 
24
- #### NEW
21
+ #### FIXED
25
22
 
26
- - `--nvultra` will open the selected snippet in nvUltra
23
+ - Selecting 'All snippets' could return blank results in some cases
27
24
 
28
- #### IMPROVED
25
+ ### 2.0.28
29
26
 
30
- - Use Readline for entering info with `--paste`, allows for better editing experience
31
- - Allow `--edit` with `--paste` to open the new snippet in your editor immediately
27
+ 2023-04-18 09:18
32
28
 
33
29
  #### FIXED
34
30
 
35
- - Code indentation with `--paste`
36
- - Nil error when highlighting without extension
31
+ - When detecting indented code blocks, require a blank line (or start of file) before them, to avoid picking up lines within indented lists
37
32
 
38
33
  ### 2.0.26
39
34
 
40
35
  2023-04-16 11:18
41
36
 
42
- #### NEW
43
-
44
- - `--nvultra` will open the selected snippet in nvUltra
45
-
46
- #### IMPROVED
47
-
48
- - Use Readline for entering info with `--paste`, allows for better editing experience
49
- - Allow `--edit` with `--paste` to open the new snippet in your editor immediately
50
-
51
37
  #### FIXED
52
38
 
53
- - Code indentation with `--paste`
54
39
  - Nil error when highlighting without extension
55
40
 
56
- ### 2.0.25
57
-
58
- 2023-04-16 11:09
59
-
60
- #### NEW
61
-
62
- - `--nvultra` will open the selected snippet in nvUltra
63
-
64
- #### IMPROVED
65
-
66
- - Use Readline for entering info with `--paste`, allows for better editing experience
67
- - Allow `--edit` with `--paste` to open the new snippet in your editor immediately
68
-
69
- #### FIXED
70
-
71
- - Code indentation with `--paste`
72
-
73
41
  ### 2.0.24
74
42
 
75
43
  2023-04-16 10:49
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- snibbets (2.0.28)
4
+ snibbets (2.0.30)
5
5
  mdless (~> 1.0, >= 1.0.32)
6
6
  tty-reader (~> 0.9, >= 0.9.0)
7
7
  tty-which (~> 0.5, >= 0.5.0)
data/README.md CHANGED
@@ -102,6 +102,8 @@ Set the `source` key to the folder where you keep your Markdown snippets. Option
102
102
 
103
103
  The `all` setting determines how Snibbets handles files containing multiple snippets. If `all` is true, then it will always display every snippet in the selected file. If false, it will offer a menu and let you choose which snippet to display. You can use `--all` on the command line to just enable this once.
104
104
 
105
+ By default, Snibbets displays only the code from each snippet (and optionally block quotes, see below). If you set `all_notes` to true, then the full content of each snippet containing a code block will be returned, allowing you to see additional notes on the command line. This can be toggled at runtime with `--notes` or `--no-notes`.
106
+
105
107
  The `copy` setting determines whether the output is copied to the clipboard in addition to being displayed on STDOUT. This is the equivalent of running `snibbets QUERY | pbcopy` (macOS) or `snibbets QUERY | xclip` (Linux). This can be enabled for just one run with `--copy` on the command line. Setting it to true in the config will copy to the clipboard every time a snippet is displayed. On Mac this will work automatically, on Windows/Linux you may need to [install `xclip` or `xsel`][xclip].
106
108
 
107
109
  [xclip]: https://ostechnix.com/access-clipboard-contents-using-xclip-and-xsel-in-linux/
@@ -157,13 +159,14 @@ Snibbet's implementation of Skylighting has limited but better-looking themes, a
157
159
  ### Usage
158
160
 
159
161
  ```
160
- Snibbets v2.0.28
162
+ Snibbets v2.0.30
161
163
 
162
164
  Usage: snibbets [options] query
163
165
  -a, --all If a file contains multiple snippets, output all of them (no menu)
164
166
  -c, --[no-]copy Copy the output to the clibpoard (also displays on STDOUT)
165
167
  -e, --edit Open the selected snippet in your configured editor
166
168
  -n, --[no-]name-only Only search file names, not content
169
+ --[no-]notes Display the full content of the snippet
167
170
  -o, --output FORMAT Output format (json|launchbar|*raw)
168
171
  -p, --paste, --new Interactively create a new snippet from clipboard contents (Mac only)
169
172
  -q, --quiet Skip menus and display first match
data/bin/snibbets CHANGED
@@ -46,6 +46,10 @@ module Snibbets
46
46
  options[:name_only] = v
47
47
  end
48
48
 
49
+ opts.on('--[no-]notes', 'Display the full content of the snippet') do |v|
50
+ options[:all_notes] = v
51
+ end
52
+
49
53
  opts.on('-o', '--output FORMAT', 'Output format (json|launchbar|*raw)') do |outformat|
50
54
  valid = %w[json launchbar lb raw]
51
55
  if outformat.downcase =~ /(launchbar|lb)/
@@ -17,7 +17,7 @@ module Snibbets
17
17
 
18
18
  in_leader = true
19
19
  each do |line|
20
- if (line =~ /^\s*$/ || line.empty?) && in_leader
20
+ if (line.strip.empty?) && in_leader
21
21
  next
22
22
  else
23
23
  in_leader = false
@@ -14,6 +14,7 @@ module Snibbets
14
14
 
15
15
  DEFAULT_OPTIONS = {
16
16
  all: false,
17
+ all_notes: false,
17
18
  copy: false,
18
19
  editor: nil,
19
20
  extension: 'md',
data/lib/snibbets/menu.rb CHANGED
@@ -14,9 +14,7 @@ module Snibbets
14
14
  def remove_items_without_query(filename, res, query)
15
15
  q = find_query_in_options(filename, res, query).split(/ /)
16
16
  res.delete_if do |opt|
17
- q.none? do |word|
18
- "#{filename} #{opt['title']}" =~ /#{word}/i
19
- end
17
+ q.none? { |word| "#{filename} #{opt['title']}" =~ /#{word}/i }
20
18
  end
21
19
  res
22
20
  end
@@ -28,16 +26,14 @@ module Snibbets
28
26
  end
29
27
 
30
28
  if res.count.zero?
31
- warn 'No matches found'
29
+ warn 'No matches found' if Snibbets.options[:interactive]
32
30
  Process.exit 1
33
31
  end
34
32
 
35
33
  options = res.map { |m| m['title'] }
36
34
 
37
35
  puts title
38
- args = [
39
- "--height=#{options.count}"
40
- ]
36
+ args = ["--height=#{options.count}"]
41
37
  selection = `echo #{Shellwords.escape(options.join("\n"))} | #{executable} filter #{args.join(' ')}`.strip
42
38
  Process.exit 1 if selection.empty?
43
39
 
@@ -82,7 +78,7 @@ module Snibbets
82
78
  end
83
79
 
84
80
  if res.count.zero?
85
- warn 'No matches found'
81
+ warn 'No matches found' if Snibbets.options[:interactive]
86
82
  Process.exit 1
87
83
  end
88
84
 
data/lib/snibbets/os.rb CHANGED
@@ -31,12 +31,12 @@ module Snibbets
31
31
  os = RbConfig::CONFIG['target_os']
32
32
  case os
33
33
  when /darwin.*/i
34
- `pbpaste -pboard general -Prefer txt`
34
+ `pbpaste -pboard general -Prefer txt`.strip_newlines
35
35
  else
36
36
  if TTY::Which.exist?('xclip')
37
- `xclip -o -sel c`
37
+ `xclip -o -sel c`.strip_newlines
38
38
  elsif TTY::Which.exist('xsel')
39
- `xsel -ob`
39
+ `xsel -ob`.strip_newlines
40
40
  else
41
41
  puts 'Paste not supported on this system, please install xclip or xsel.'
42
42
  end
@@ -16,6 +16,10 @@ module Snibbets
16
16
  replace remove_spotlight_tags
17
17
  end
18
18
 
19
+ def strip_empty
20
+ split(/\n/).strip_empty.join("\n")
21
+ end
22
+
19
23
  def remove_meta
20
24
  input = dup
21
25
  lines = input.split(/\n/)
@@ -57,7 +61,7 @@ module Snibbets
57
61
 
58
62
  # if it's a fenced code block, just discard the fence and everything
59
63
  # outside it
60
- if block.fenced?
64
+ if block.fenced? && !Snibbets.options[:all_notes]
61
65
  code_blocks = block.scan(/(`{3,})(\w+)?\s*\n(.*?)\n\1/m)
62
66
  code_blocks.map! { |b| b[2].strip }
63
67
  return code_blocks.join("\n\n")
@@ -86,29 +90,16 @@ module Snibbets
86
90
 
87
91
  indent = code[0].match(/^( {4,}|\t+)(?=\S)/)
88
92
 
89
- if indent
90
- code.map! { |line| line.sub(/(?mi)^#{indent[1]}/, '') }.join("\n")
91
- else
92
- self
93
- end
94
- end
93
+ return self if indent.nil?
95
94
 
96
- # Returns an array of snippets. Single snippets are returned without a
97
- # title, multiple snippets get titles from header lines
98
- def snippets
99
- content = dup.remove_meta
100
- # If there's only one snippet, just clean it and return
101
- # return [{ 'title' => '', 'code' => content.clean_code.strip }] unless multiple?
95
+ code.map! { |line| line.sub(/(?mi)^#{indent[1]}/, '') }.join("\n")
96
+ end
102
97
 
103
- # Split content by ATX headers. Everything on the line after the #
104
- # becomes the title, code is gleaned from text between that and the
105
- # next ATX header (or end)
106
- sections = []
98
+ def replace_blocks
99
+ sans_blocks = dup
107
100
  counter = 0
108
101
  code_blocks = {}
109
102
 
110
- sans_blocks = content.dup
111
-
112
103
  if Snibbets.options[:include_blockquotes]
113
104
  sans_blocks = sans_blocks.gsub(/(?mi)(^(>.*?)(\n|$))+/) do
114
105
  counter += 1
@@ -133,44 +124,76 @@ module Snibbets
133
124
  "<block#{counter}>\n"
134
125
  end
135
126
 
136
- content = []
137
- if sans_blocks =~ /<block\d+>/
138
- sans_blocks.each_line do |line|
139
- content << line if line =~ /^#/ || line =~ /<block\d+>/
140
- end
127
+ [sans_blocks, code_blocks]
128
+ end
141
129
 
142
- parts = content.join("\n").split(/^#+/)
143
- else
144
- parts = sans_blocks.gsub(/\n{2,}/, "\n\n").split(/^#+/)
130
+ def parse_lang_marker(block)
131
+ lang = nil
132
+ if block =~ /<lang:(.*?)>/
133
+ lang = Regexp.last_match(1)
134
+ block = block.gsub(/<lang:.*?>\n+/, '').strip_empty
145
135
  end
146
136
 
147
- # parts.shift if parts.count > 1
137
+ [lang, block]
138
+ end
139
+
140
+ def restore_blocks(parts, code_blocks)
141
+ sections = []
148
142
 
149
143
  parts.each do |part|
150
144
  lines = part.split(/\n/).strip_empty
151
- next if lines.blocks == 0
145
+ next if lines.blocks.zero?
152
146
 
153
147
  title = lines.count > 1 && lines[0] !~ /<block\d+>/ ? lines.shift.strip.sub(/[.:]$/, '') : 'Default snippet'
154
- block = lines.join("\n").gsub(/<(block\d+)>/) { code_blocks[Regexp.last_match(1)] }
155
148
 
156
- lang = nil
157
- if block =~ /<lang:(.*?)>/
158
- lang = Regexp.last_match(1)
159
- block.gsub!(/<lang:.*?>\n/, '')
160
- end
149
+ block = if Snibbets.options[:all_notes]
150
+ lines.join("\n").gsub(/<(block\d+)>/) { "\n```\n#{code_blocks[Regexp.last_match(1)].strip_empty}\n```" }
151
+ else
152
+ lines.join("\n").gsub(/<(block\d+)>/) { code_blocks[Regexp.last_match(1)].strip_empty }
153
+ end
154
+
155
+ # block = lines.join("\n").gsub(/<(block\d+)>/) { code_blocks[Regexp.last_match(1)] }
161
156
 
157
+ lang, block = parse_lang_marker(block)
162
158
  code = block.clean_code
163
159
 
164
160
  next unless code && !code.empty?
165
161
 
166
162
  sections << {
167
163
  'title' => title,
168
- 'code' => code,
164
+ 'code' => code.strip_empty,
169
165
  'language' => lang
170
166
  }
171
167
  end
172
168
 
173
169
  sections
174
170
  end
171
+
172
+ # Returns an array of snippets. Single snippets are returned without a
173
+ # title, multiple snippets get titles from header lines
174
+ def snippets
175
+ content = dup.remove_meta
176
+ # If there's only one snippet, just clean it and return
177
+ # return [{ 'title' => '', 'code' => content.clean_code.strip }] unless multiple?
178
+
179
+ # Split content by ATX headers. Everything on the line after the #
180
+ # becomes the title, code is gleaned from text between that and the
181
+ # next ATX header (or end)
182
+ sans_blocks, code_blocks = content.replace_blocks
183
+
184
+ parts = if Snibbets.options[:all_notes]
185
+ sans_blocks.split(/^#+/)
186
+ elsif sans_blocks =~ /<block\d+>/
187
+ sans_blocks.split(/\n/).each_with_object([]) do |line, arr|
188
+ arr << line if line =~ /^#/ || line =~ /<block\d+>/
189
+ end.join("\n").split(/^#+/)
190
+ else
191
+ sans_blocks.gsub(/\n{2,}/, "\n\n").split(/^#+/)
192
+ end
193
+
194
+ # parts.shift if parts.count > 1
195
+
196
+ restore_blocks(parts, code_blocks)
197
+ end
175
198
  end
176
199
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snibbets
4
- VERSION = '2.0.28'
4
+ VERSION = '2.0.30'
5
5
  end
data/lib/snibbets.rb CHANGED
@@ -153,7 +153,7 @@ module Snibbets
153
153
  end
154
154
 
155
155
  def new_snippet_from_clipboard
156
- return false unless $stdin.isatty
156
+ return false unless $stdout.isatty
157
157
 
158
158
  trap('SIGINT') do
159
159
  Howzit.console.info "\nCancelled"
@@ -248,7 +248,7 @@ module Snibbets
248
248
  else
249
249
  filepath = nil
250
250
  if results.empty?
251
- warn 'No results'
251
+ warn 'No results' if Snibbets.options[:interactive]
252
252
  Process.exit 0
253
253
  elsif results.length == 1 || !Snibbets.options[:interactive]
254
254
  filepath = results[0]['path']
@@ -272,7 +272,7 @@ module Snibbets
272
272
  snippets = input.snippets
273
273
 
274
274
  if snippets.empty?
275
- warn 'No snippets found'
275
+ warn 'No snippets found' if Snibbets.options[:interactive]
276
276
  Process.exit 0
277
277
  elsif snippets.length == 1 || !Snibbets.options[:interactive]
278
278
  if Snibbets.options[:output] == 'json'
@@ -280,8 +280,11 @@ module Snibbets
280
280
  else
281
281
  snippets.each do |snip|
282
282
  header = File.basename(filepath, '.md')
283
- warn header
284
- warn '-' * header.length
283
+ if $stdout.isatty
284
+ puts header
285
+ puts '-' * header.length
286
+ puts ''
287
+ end
285
288
  code = snip['code']
286
289
  lang = snip['language']
287
290
  print(code, filepath, lang)
@@ -289,52 +292,59 @@ module Snibbets
289
292
  end
290
293
  elsif snippets.length > 1
291
294
  if Snibbets.options[:all]
292
- if Snibbets.options[:output] == 'json'
293
- print(snippets.to_json, filepath)
294
- else
295
-
296
- snippets.each do |snippet|
297
- lang = snippet['language']
298
- warn "### #{snippet['title']} ###"
299
- # warn "# #{'-' * snippet['title'].length}"
300
- print(snippet['code'], filepath, lang)
301
- puts
302
- end
303
- end
295
+ print_all(snippets, filepath)
304
296
  else
305
- snippets.push({ 'title' => 'All snippets', 'code' => '' })
306
-
307
- answer = Menu.menu(snippets, filename: File.basename(filepath, '.md'), title: 'Select snippet', query: @query)
297
+ select_snippet(snippets, filepath)
298
+ end
299
+ end
300
+ end
301
+ end
308
302
 
309
- if answer['title'] == 'All snippets'
310
- snippets.delete_if { |s| s['title'] == 'All snippets' }
311
- if Snibbets.options[:output] == 'json'
312
- print(snippets.to_json, filepath)
313
- else
314
- header = File.basename(filepath, '.md')
315
- warn header
316
- warn '=' * header.length
317
-
318
- snippets.each do |snippet|
319
- lang = snippet['language']
320
- warn "### #{snippet['title']} ###"
321
- # warn "# #{'-' * snippet['title'].length}"
322
- print(snippet['code'], filepath, lang)
323
- puts
324
- end
303
+ def select_snippet(snippets, filepath)
304
+ snippets.push({ 'title' => 'All snippets', 'code' => '' })
305
+ answer = Menu.menu(snippets.dup, filename: File.basename(filepath, '.md'), title: 'Select snippet', query: @query)
325
306
 
326
- end
327
- elsif Snibbets.options[:output] == 'json'
328
- print(answer.to_json, filepath)
329
- else
330
- header = "#{File.basename(filepath, '.md')}: #{answer['title']}"
331
- warn header
332
- warn '-' * header.length
333
- code = answer['code']
334
- lang = answer['language']
335
- print(code, filepath, lang)
336
- end
307
+ if answer['title'] == 'All snippets'
308
+ snippets.delete_if { |s| s['title'] == 'All snippets' }
309
+ if Snibbets.options[:output] == 'json'
310
+ print(snippets.to_json, filepath)
311
+ else
312
+ if $stdout.isatty
313
+ header = File.basename(filepath, '.md')
314
+ warn header
315
+ warn '=' * header.length
316
+ warn ''
337
317
  end
318
+ print_all(snippets, filepath)
319
+ end
320
+ elsif Snibbets.options[:output] == 'json'
321
+ print(answer.to_json, filepath)
322
+ else
323
+ if $stdout.isatty
324
+ header = "#{File.basename(filepath, '.md')}: #{answer['title']}"
325
+ warn header
326
+ warn '-' * header.length
327
+ warn ''
328
+ end
329
+ code = answer['code']
330
+ lang = answer['language']
331
+ print(code, filepath, lang)
332
+ end
333
+ end
334
+
335
+ def print_all(snippets, filepath)
336
+ if Snibbets.options[:output] == 'json'
337
+ print(snippets.to_json, filepath)
338
+ else
339
+
340
+ snippets.each do |snippet|
341
+ lang = snippet['language']
342
+
343
+ puts "### #{snippet['title']} ###"
344
+ puts ''
345
+
346
+ print(snippet['code'], filepath, lang)
347
+ puts
338
348
  end
339
349
  end
340
350
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snibbets
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.28
4
+ version: 2.0.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-18 00:00:00.000000000 Z
11
+ date: 2023-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler