snibbets 2.0.39 → 2.0.40

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