snibbets 2.0.28 → 2.0.30

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
  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