snibbets 2.0.39 → 2.0.40

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.
data/lib/snibbets.rb CHANGED
@@ -1,27 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cgi'
4
- require 'erb'
5
- require 'fileutils'
6
- require 'json'
7
- require 'open3'
8
- require 'optparse'
9
- require 'readline'
10
- require 'shellwords'
11
- require 'tty-reader'
12
- require 'tty-which'
13
- require 'yaml'
14
- require_relative 'snibbets/version'
15
- require_relative 'snibbets/colors'
16
- require_relative 'snibbets/config'
17
- require_relative 'snibbets/which'
18
- require_relative 'snibbets/string'
19
- require_relative 'snibbets/hash'
20
- require_relative 'snibbets/array'
21
- require_relative 'snibbets/menu'
22
- require_relative 'snibbets/os'
23
- require_relative 'snibbets/highlight'
24
- require_relative 'snibbets/lexers'
3
+ require "cgi"
4
+ require "erb"
5
+ require "fileutils"
6
+ require "json"
7
+ require "open3"
8
+ require "optparse"
9
+ require "readline"
10
+ require "shellwords"
11
+ require "tty-reader"
12
+ require "tty-which"
13
+ require "yaml"
14
+ require_relative "snibbets/version"
15
+ require_relative "snibbets/colors"
16
+ require_relative "snibbets/config"
17
+ require_relative "snibbets/which"
18
+ require_relative "snibbets/string"
19
+ require_relative "snibbets/hash"
20
+ require_relative "snibbets/array"
21
+ require_relative "snibbets/menu"
22
+ require_relative "snibbets/os"
23
+ require_relative "snibbets/highlight"
24
+ require_relative "snibbets/lexers"
25
25
 
26
26
  # Top level module
27
27
  module Snibbets
@@ -47,78 +47,84 @@ module Snibbets
47
47
  end
48
48
 
49
49
  # Search the snippets directory for query using find and grep
50
- def search(try: 0)
50
+ def search(try: 0, matches: [])
51
51
  folder = File.expand_path(Snibbets.options[:source])
52
- # start by doing a spotlight search, if that fails, start trying:
53
- # First try only search by filenames
54
- # Second try search with grep
55
- ext = Snibbets.options[:extension] || 'md'
52
+ # start by doing a spotlight search with mdfind
53
+ # next try only search by filenames (find)
54
+ # next try search with grep (rg, ag, ack, grep)
55
+ # concatenate results from each search, removing duplicates and sorting
56
+ ext = Snibbets.options[:extension] || "md"
57
+
56
58
  cmd = case try
57
- when 1
58
- %(find "#{folder}" -iregex '^#{Regexp.escape(folder)}/#{@query.rx}' -name '*.#{ext}')
59
- when 2
60
- rg = TTY::Which.which('rg')
61
- ag = TTY::Which.which('ag')
62
- ack = TTY::Which.which('ack')
63
- grep = TTY::Which.which('grep')
64
- if !rg.empty?
65
- %(#{rg} -li --color=never --glob='*.#{ext}' '#{@query.rx}' "#{folder}")
66
- elsif !ag.empty?
67
- %(#{ag} -li --nocolor -G '.*.#{ext}' '#{@query.rx}' "#{folder}")
68
- elsif !ack.empty?
69
- %(#{ack} -li --nocolor --markdown '#{@query.rx}' "#{folder}")
70
- elsif !grep.empty?
71
- %(#{grep} -iEl '#{@query.rx}' "#{folder}"/**/*.#{ext})
72
- else
73
- nil
74
- end
75
- else
76
- mdfind = TTY::Which.which('mdfind')
77
- if mdfind.nil? || mdfind.empty?
78
- nil
79
- else
80
- name_only = Snibbets.options[:name_only] ? '-name ' : ''
81
- %(mdfind -onlyin #{folder} #{name_only}'#{@query} name:.#{ext}' 2>/dev/null)
82
- end
83
- end
59
+ when 1
60
+ %(find "#{folder}" -iregex '^#{Regexp.escape(folder)}/#{@query.rx}' -name '*.#{ext}')
61
+ when 2
62
+ rg = TTY::Which.which("rg")
63
+ ag = TTY::Which.which("ag")
64
+ ack = TTY::Which.which("ack")
65
+ grep = TTY::Which.which("grep")
66
+ if !rg.empty?
67
+ %(#{rg} -li --color=never --glob='*.#{ext}' '#{@query.rx}' "#{folder}")
68
+ elsif !ag.empty?
69
+ %(#{ag} -li --nocolor -G '.*.#{ext}' '#{@query.rx}' "#{folder}")
70
+ elsif !ack.empty?
71
+ %(#{ack} -li --nocolor --markdown '#{@query.rx}' "#{folder}")
72
+ elsif !grep.empty?
73
+ %(#{grep} -iEl '#{@query.rx}' "#{folder}"/**/*.#{ext})
74
+ else
75
+ nil
76
+ end
77
+ else
78
+ mdfind = TTY::Which.which("mdfind")
79
+ if mdfind.nil? || mdfind.empty?
80
+ nil
81
+ else
82
+ name_only = Snibbets.options[:name_only] ? "-name " : ""
83
+ %(mdfind -onlyin #{folder} #{name_only}'#{@query} name:.#{ext}' 2>/dev/null)
84
+ end
85
+ end
84
86
 
85
87
  if try == 2
86
88
  if Snibbets.options[:name_only]
87
- puts '{br}No name matches found'.x
89
+ puts "{br}No name matches found".x
88
90
  Process.exit 1
89
91
  elsif cmd.nil?
90
- puts '{br}No search method available on this system. Please install ripgrep, silver surfer, ack, or grep.'.x
92
+ puts "{br}No search method available on this system. Please install ripgrep, silver surfer, ack, or grep.".x
91
93
  Process.exit 1
92
94
  end
93
95
  end
94
96
 
95
- res = cmd.nil? ? '' : `#{cmd}`.strip
96
-
97
- matches = []
97
+ res = cmd.nil? ? "" : `#{cmd}`.strip
98
98
 
99
99
  unless res.empty?
100
100
  lines = res.split(/\n/)
101
101
  lines.each do |l|
102
102
  matches << {
103
- 'title' => File.basename(l, '.*'),
104
- 'path' => l
103
+ "title" => File.basename(l, ".*"),
104
+ "path" => l,
105
105
  }
106
106
  end
107
107
 
108
- matches.sort_by! { |a| a['title'] }.uniq!
108
+ matches.sort_by! { |a| a["title"] }.uniq!
109
+
110
+ # return matches unless matches.empty?
111
+ end
109
112
 
110
- return matches unless matches.empty?
113
+ matches.delete_if do |m|
114
+ content = IO.read(m["path"])
115
+ !content.match_all_tags(@query)
111
116
  end
112
117
 
118
+ # return after 3 cycles
113
119
  return matches if try == 2
114
120
 
115
- # if no results on the first try, try again searching all text
116
- search(try: try + 1) if matches.empty?
121
+ # continue search, appends to current matches
122
+ search(try: try + 1, matches: matches)
117
123
  end
118
124
 
119
125
  def open_snippet_in_nvultra(filepath)
120
- notebook = Snibbets.options[:source].gsub(/ /, '%20')
121
- note = ERB::Util.url_encode(File.basename(filepath, '.md'))
126
+ notebook = Snibbets.options[:source].gsub(/ /, "%20")
127
+ note = ERB::Util.url_encode(File.basename(filepath, ".md"))
122
128
  url = "x-nvultra://open?notebook=#{notebook}&note=#{note}"
123
129
  `open '#{url}'`
124
130
  end
@@ -126,7 +132,7 @@ module Snibbets
126
132
  def open_snippet_in_editor(filepath)
127
133
  editor = Snibbets.options[:editor] || Snibbets::Config.best_editor
128
134
 
129
- os = RbConfig::CONFIG['target_os']
135
+ os = RbConfig::CONFIG["target_os"]
130
136
 
131
137
  if editor.nil?
132
138
  OS.open(filepath)
@@ -158,7 +164,7 @@ module Snibbets
158
164
  def new_snippet_from_clipboard
159
165
  return false unless $stdout.isatty
160
166
 
161
- trap('SIGINT') do
167
+ trap("SIGINT") do
162
168
  Howzit.console.info "\nCancelled"
163
169
  exit!
164
170
  end
@@ -167,10 +173,10 @@ module Snibbets
167
173
  reader = TTY::Reader.new
168
174
 
169
175
  begin
170
- input = reader.read_line('{by}What does this snippet do{bw}? '.x).strip
176
+ input = reader.read_line("{by}What does this snippet do{bw}? ".x).strip
171
177
  title = input unless input.empty?
172
178
 
173
- input = reader.read_line('{by}What language(s) does it use ({xw}separate with spaces, full names or file extensions{by}){bw}? '.x).strip
179
+ input = reader.read_line("{by}What language(s) does it use ({xw}separate with spaces, full names or file extensions{by}){bw}? ".x).strip
174
180
  langs = input.split(/ +/).map(&:strip) unless input.empty?
175
181
  rescue TTY::Reader::InputInterrupt
176
182
  puts "\nCancelled"
@@ -182,10 +188,10 @@ module Snibbets
182
188
 
183
189
  exts = langs if exts.empty?
184
190
 
185
- filename = "#{title}#{exts.map { |x| ".#{x}" }.join('')}.#{Snibbets.options[:extension]}"
191
+ filename = "#{title}#{exts.map { |x| ".#{x}" }.join("")}.#{Snibbets.options[:extension]}"
186
192
  filepath = File.join(File.expand_path(Snibbets.options[:source]), filename.escape_filename)
187
- File.open(filepath, 'w') do |f|
188
- f.puts "tags: #{tags.join(', ')}
193
+ File.open(filepath, "w") do |f|
194
+ f.puts "tags: #{tags.join(", ")}
189
195
 
190
196
  ```
191
197
  #{pb}
@@ -201,20 +207,20 @@ module Snibbets
201
207
  def new_snippet_with_editor(options)
202
208
  return false unless $stdout.isatty
203
209
 
204
- trap('SIGINT') do
210
+ trap("SIGINT") do
205
211
  Howzit.console.info "\nCancelled"
206
212
  exit!
207
213
  end
208
214
 
209
215
  reader = TTY::Reader.new
210
216
  if options[:filename]
211
- title = options[:filename].sub(/(\.#{Snibbets.options[:extension]})$/, '')
217
+ title = options[:filename].sub(/(\.#{Snibbets.options[:extension]})$/, "")
212
218
  extensions = options[:filename].match(/(\.\w+)+$/)
213
219
  langs = extensions ? extensions[0].split(/\./).delete_if(&:empty?) : []
214
- title.sub!(/(\.\w+)+$/, '')
220
+ title.sub!(/(\.\w+)+$/, "")
215
221
  else
216
222
  begin
217
- input = reader.read_line('{by}What does this snippet do{bw}? '.x).strip
223
+ input = reader.read_line("{by}What does this snippet do{bw}? ".x).strip
218
224
  title = input unless input.empty?
219
225
  rescue TTY::Reader::InputInterrupt
220
226
  puts "\nCancelled"
@@ -225,7 +231,7 @@ module Snibbets
225
231
  if langs.nil? || langs.empty?
226
232
  begin
227
233
  # printf 'What language(s) does it use (separate with spaces, full names or file extensions will work)? '
228
- input = reader.read_line('{by}What language(s) does it use ({xw}separate with spaces, full names or file extensions{by}){bw}? '.x).strip
234
+ input = reader.read_line("{by}What language(s) does it use ({xw}separate with spaces, full names or file extensions{by}){bw}? ".x).strip
229
235
  # input = $stdin.gets.chomp
230
236
  langs = input.split(/ +/).map(&:strip) unless input.empty?
231
237
  rescue TTY::Reader::InputInterrupt
@@ -239,11 +245,11 @@ module Snibbets
239
245
 
240
246
  exts = langs if exts.empty?
241
247
 
242
- filename = "#{title}#{exts.map { |x| ".#{x}" }.join('')}.#{Snibbets.options[:extension]}"
248
+ filename = "#{title}#{exts.map { |x| ".#{x}" }.join("")}.#{Snibbets.options[:extension]}"
243
249
  filepath = File.join(File.expand_path(Snibbets.options[:source]), filename.escape_filename)
244
250
 
245
- output =<<~EOOUTPUT
246
- tags: #{tags.join(', ')}
251
+ output = <<~EOOUTPUT
252
+ tags: #{tags.join(", ")}
247
253
 
248
254
  > #{title}
249
255
  EOOUTPUT
@@ -251,11 +257,11 @@ module Snibbets
251
257
  if langs.count.positive?
252
258
  tags.each do |lang|
253
259
  comment = case lang
254
- when /(c|cpp|objectivec|java|javascript|dart|php|golang|typescript|kotlin)/
255
- '// Code'
256
- else
257
- '# Code'
258
- end
260
+ when /(c|cpp|objectivec|java|javascript|dart|php|golang|typescript|kotlin)/
261
+ "// Code"
262
+ else
263
+ "# Code"
264
+ end
259
265
 
260
266
  output << <<~EOLANGS
261
267
 
@@ -271,7 +277,7 @@ module Snibbets
271
277
  EOCODE
272
278
  end
273
279
 
274
- File.open(filepath, 'w') do |f|
280
+ File.open(filepath, "w") do |f|
275
281
  f.puts output
276
282
  end
277
283
 
@@ -290,14 +296,14 @@ module Snibbets
290
296
 
291
297
  if results.empty?
292
298
  out = {
293
- 'title' => 'No matching snippets found'
299
+ "title" => "No matching snippets found",
294
300
  }.to_json
295
301
  puts out
296
302
  Process.exit
297
303
  end
298
304
 
299
305
  results.each do |result|
300
- input = IO.read(result['path'])
306
+ input = IO.read(result["path"])
301
307
  snippets = input.snippets
302
308
  next if snippets.empty?
303
309
 
@@ -305,29 +311,29 @@ module Snibbets
305
311
 
306
312
  if snippets.length == 1
307
313
  output << {
308
- 'title' => result['title'],
309
- 'path' => result['path'],
310
- 'action' => 'copyIt',
311
- 'actionArgument' => snippets[0]['code'],
312
- 'label' => 'Copy'
314
+ "title" => result["title"],
315
+ "path" => result["path"],
316
+ "action" => "copyIt",
317
+ "actionArgument" => snippets[0]["code"],
318
+ "label" => "Copy",
313
319
  }
314
320
  next
315
321
  end
316
322
 
317
323
  snippets.each { |s|
318
324
  children << {
319
- 'title' => s['title'],
320
- 'path' => result['path'],
321
- 'action' => 'copyIt',
322
- 'actionArgument' => s['code'],
323
- 'label' => 'Copy'
325
+ "title" => s["title"],
326
+ "path" => result["path"],
327
+ "action" => "copyIt",
328
+ "actionArgument" => s["code"],
329
+ "label" => "Copy",
324
330
  }
325
331
  }
326
332
 
327
333
  output << {
328
- 'title' => result['title'],
329
- 'path' => result['path'],
330
- 'children' => children
334
+ "title" => result["title"],
335
+ "path" => result["path"],
336
+ "children" => children,
331
337
  }
332
338
  end
333
339
 
@@ -340,14 +346,14 @@ module Snibbets
340
346
  else
341
347
  filepath = nil
342
348
  if results.empty?
343
- warn 'No results' if Snibbets.options[:interactive]
349
+ warn "No results" if Snibbets.options[:interactive]
344
350
  Process.exit 0
345
351
  elsif results.length == 1 || !Snibbets.options[:interactive]
346
- filepath = results[0]['path']
352
+ filepath = results[0]["path"]
347
353
  input = IO.read(filepath)
348
354
  else
349
- answer = Snibbets::Menu.menu(results, title: 'Select a file')
350
- filepath = answer['path']
355
+ answer = Snibbets::Menu.menu(results, title: "Select a file")
356
+ filepath = answer["path"]
351
357
  input = IO.read(filepath)
352
358
  end
353
359
 
@@ -364,21 +370,21 @@ module Snibbets
364
370
  snippets = input.snippets
365
371
 
366
372
  if snippets.empty?
367
- warn 'No snippets found' if Snibbets.options[:interactive]
373
+ warn "No snippets found" if Snibbets.options[:interactive]
368
374
  Process.exit 0
369
375
  elsif snippets.length == 1 || !Snibbets.options[:interactive]
370
- if Snibbets.options[:output] == 'json'
376
+ if Snibbets.options[:output] == "json"
371
377
  print(snippets.to_json, filepath)
372
378
  else
373
379
  snippets.each do |snip|
374
- header = File.basename(filepath, '.md')
380
+ header = File.basename(filepath, ".md")
375
381
  if $stdout.isatty
376
382
  puts "{bw}#{header}{x}".x
377
- puts "{dw}#{'-' * header.length}{x}".x
378
- puts ''
383
+ puts "{dw}#{"-" * header.length}{x}".x
384
+ puts ""
379
385
  end
380
- code = snip['code']
381
- lang = snip['language']
386
+ code = snip["code"]
387
+ lang = snip["language"]
382
388
 
383
389
  print(code, filepath, lang)
384
390
  end
@@ -394,49 +400,48 @@ module Snibbets
394
400
  end
395
401
 
396
402
  def select_snippet(snippets, filepath)
397
- snippets.push({ 'title' => 'All snippets', 'code' => '' })
398
- answer = Menu.menu(snippets.dup, filename: File.basename(filepath, '.md'), title: 'Select snippet', query: @query)
403
+ snippets.push({ "title" => "All snippets", "code" => "" })
404
+ answer = Menu.menu(snippets.dup, filename: File.basename(filepath, ".md"), title: "Select snippet", query: @query)
399
405
 
400
- if answer['title'] == 'All snippets'
401
- snippets.delete_if { |s| s['title'] == 'All snippets' }
402
- if Snibbets.options[:output] == 'json'
406
+ if answer["title"] == "All snippets"
407
+ snippets.delete_if { |s| s["title"] == "All snippets" }
408
+ if Snibbets.options[:output] == "json"
403
409
  print(snippets.to_json, filepath)
404
410
  else
405
411
  if $stdout.isatty
406
- header = File.basename(filepath, '.md')
412
+ header = File.basename(filepath, ".md")
407
413
  warn "{bw}#{header}{x}".x
408
- warn "{dw}#{'=' * header.length}{x}".x
409
- warn ''
414
+ warn "{dw}#{"=" * header.length}{x}".x
415
+ warn ""
410
416
  end
411
417
  print_all(snippets, filepath)
412
418
  end
413
- elsif Snibbets.options[:output] == 'json'
419
+ elsif Snibbets.options[:output] == "json"
414
420
  print(answer.to_json, filepath)
415
421
  else
416
422
  if $stdout.isatty
417
- header = "{bw}#{File.basename(filepath, '.md')}: {c}#{answer['title']}{x}".x
423
+ header = "{bw}#{File.basename(filepath, ".md")}: {c}#{answer["title"]}{x}".x
418
424
  warn header
419
- warn '-' * header.length
420
- warn ''
425
+ warn "-" * header.length
426
+ warn ""
421
427
  end
422
- code = answer['code']
423
- lang = answer['language']
428
+ code = answer["code"]
429
+ lang = answer["language"]
424
430
  print(code, filepath, lang)
425
431
  end
426
432
  end
427
433
 
428
434
  def print_all(snippets, filepath)
429
- if Snibbets.options[:output] == 'json'
435
+ if Snibbets.options[:output] == "json"
430
436
  print(snippets.to_json, filepath)
431
437
  else
432
-
433
438
  snippets.each do |snippet|
434
- lang = snippet['language']
439
+ lang = snippet["language"]
435
440
 
436
- puts "{dw}### {xbw}#{snippet['title']} {xdw}### {x}".x
437
- puts ''
441
+ puts "{dw}### {xbw}#{snippet["title"]} {xdw}### {x}".x
442
+ puts ""
438
443
 
439
- print(snippet['code'], filepath, lang)
444
+ print(snippet["code"], filepath, lang)
440
445
  puts
441
446
  end
442
447
  end
@@ -445,9 +450,9 @@ module Snibbets
445
450
  def print(output, filepath, syntax = nil)
446
451
  if Snibbets.options[:copy]
447
452
  OS.copy(Snibbets.options[:all_notes] ? output : output.clean_code)
448
- warn 'Copied to clipboard'
453
+ warn "Copied to clipboard"
449
454
  end
450
- if Snibbets.options[:highlight] && Snibbets.options[:output] == 'raw'
455
+ if Snibbets.options[:highlight] && Snibbets.options[:output] == "raw"
451
456
  $stdout.puts(Highlight.highlight(output, filepath, syntax))
452
457
  else
453
458
  $stdout.puts(Snibbets.options[:all_notes] ? output : output.clean_code)
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ ruby = "3.3.0"