booker 1.2.1 → 2.0.0
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 +4 -4
- data/bin/booker +3 -3
- data/completions/_booker +115 -0
- data/completions/booker.bash +52 -0
- data/completions/booker.fish +49 -0
- data/lib/booker/bookmarks.rb +164 -0
- data/lib/booker/cli.rb +226 -0
- data/lib/booker/config.rb +219 -0
- data/lib/booker/installer.rb +396 -0
- data/lib/booker/output.rb +84 -0
- data/lib/booker/parsers.rb +294 -0
- data/lib/booker/picker.rb +139 -0
- data/lib/booker/version.rb +5 -0
- data/lib/booker.rb +14 -423
- metadata +41 -24
- data/lib/bookmarks.rb +0 -324
- data/lib/config.rb +0 -187
- data/lib/consts.rb +0 -114
data/lib/booker.rb
CHANGED
|
@@ -1,423 +1,14 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
require_relative "
|
|
9
|
-
require_relative "
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class << self
|
|
17
|
-
attr_reader :version
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
include Browser
|
|
21
|
-
|
|
22
|
-
def initialize(args)
|
|
23
|
-
parse args
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def parse(args)
|
|
27
|
-
# no args given, show interactive bookmark selector
|
|
28
|
-
show_bookmarks if args.none?
|
|
29
|
-
|
|
30
|
-
# if arg starts with hyphen, parse option
|
|
31
|
-
parse_opt args if /^-.*/.match?(args.first)
|
|
32
|
-
|
|
33
|
-
# separate bookmark IDs from other args
|
|
34
|
-
bookmark_ids = []
|
|
35
|
-
other_args = []
|
|
36
|
-
|
|
37
|
-
args.each do |arg|
|
|
38
|
-
if /^[0-9_]+$/.match?(arg) # bookmark ID (digits or underscore)
|
|
39
|
-
bookmark_ids << arg
|
|
40
|
-
else
|
|
41
|
-
other_args << arg
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# open all bookmarks first
|
|
46
|
-
unless bookmark_ids.empty?
|
|
47
|
-
open_bookmark bookmark_ids
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# then handle remaining args
|
|
51
|
-
unless other_args.empty?
|
|
52
|
-
if other_args.length == 1 && domain.match(other_args.first)
|
|
53
|
-
# single website URL
|
|
54
|
-
puts "opening website: ".grn + other_args.first
|
|
55
|
-
openweb(prep(other_args.first))
|
|
56
|
-
else
|
|
57
|
-
# search for the rest
|
|
58
|
-
open_search(other_args.join(" ").strip)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def pexit(msg, sig)
|
|
64
|
-
puts msg
|
|
65
|
-
exit sig
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def helper
|
|
69
|
-
pexit HELP_BANNER, 0
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def version
|
|
73
|
-
pexit @@version, 0
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def openweb(url)
|
|
77
|
-
# Pass URL directly to browser without invoking shell
|
|
78
|
-
# This avoids issues with special characters like parentheses
|
|
79
|
-
browser_cmd = browse.strip
|
|
80
|
-
|
|
81
|
-
# Redirect stdout/stderr to suppress GTK warnings
|
|
82
|
-
success = system(browser_cmd, url, out: "/dev/null", err: "/dev/null")
|
|
83
|
-
|
|
84
|
-
unless success
|
|
85
|
-
puts "Warning: ".yel + "Failed to open URL (exit code: #{$?.exitstatus})"
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# an array of ints, as bookmark ids
|
|
90
|
-
def open_bookmark(bm)
|
|
91
|
-
id = bm.shift
|
|
92
|
-
url = Bookmarks.new.bookmark_url(id)
|
|
93
|
-
pexit "Failure:".red + " bookmark #{id} not found", 1 if url.nil?
|
|
94
|
-
puts "opening bookmark ".grn + url
|
|
95
|
-
openweb(url) # No wrap() needed - system() handles it
|
|
96
|
-
open_bookmark bm unless bm.empty?
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def open_search(term)
|
|
100
|
-
puts "searching ".grn + term
|
|
101
|
-
search = BConfig.new.searcher
|
|
102
|
-
term = term.tr(" ", "+")
|
|
103
|
-
openweb(search + term) # No shell escape needed - it's a URL
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def show_bookmarks
|
|
107
|
-
puts "Bookmarks:".grn + " (usage: booker <id> or booker <search>)"
|
|
108
|
-
puts ""
|
|
109
|
-
|
|
110
|
-
bm = Bookmarks.new("") # Get all bookmarks
|
|
111
|
-
allurls = bm.instance_variable_get(:@allurls)
|
|
112
|
-
|
|
113
|
-
if allurls.empty?
|
|
114
|
-
puts "No bookmarks found.".red
|
|
115
|
-
puts "Run: ".yel + "booker --install bookmarks".cyan
|
|
116
|
-
exit 0
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Calculate responsive column widths
|
|
120
|
-
term_width = `tput cols`.to_i
|
|
121
|
-
term_width = 100 if term_width == 0 # fallback
|
|
122
|
-
|
|
123
|
-
id_width = 10
|
|
124
|
-
remaining = term_width - id_width - 3 # 3 spaces between columns
|
|
125
|
-
|
|
126
|
-
folder_width = [remaining * 0.20, 15].max.to_i
|
|
127
|
-
title_width = [remaining * 0.30, 20].max.to_i
|
|
128
|
-
url_width = [remaining * 0.50, 30].max.to_i
|
|
129
|
-
|
|
130
|
-
# Display bookmarks in a readable format
|
|
131
|
-
allurls.each do |bookmark|
|
|
132
|
-
id_str = bookmark.id.to_s.window(id_width).grn
|
|
133
|
-
|
|
134
|
-
# Clean up folder display
|
|
135
|
-
folder = bookmark.folder.gsub(/^\|/, "") # Remove leading |
|
|
136
|
-
folder = (folder == "/") ? "[root]" : folder.chomp("/") # Show [root] for top-level
|
|
137
|
-
folder_str = folder.window(folder_width).blu
|
|
138
|
-
|
|
139
|
-
title_str = bookmark.title.window(title_width).yel
|
|
140
|
-
url_str = bookmark.url.window(url_width)
|
|
141
|
-
|
|
142
|
-
puts "#{id_str} #{folder_str} #{title_str} #{url_str}"
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
puts ""
|
|
146
|
-
puts "Found #{allurls.length} bookmarks".grn
|
|
147
|
-
puts ""
|
|
148
|
-
puts "Examples:".yel
|
|
149
|
-
puts " #{"booker #{allurls.first.id}".ljust(20).cyan} # Open first bookmark"
|
|
150
|
-
puts " #{"booker github".ljust(20).cyan} # Search bookmarks for 'github'"
|
|
151
|
-
puts " #{"booker --help".ljust(20).cyan} # Show help"
|
|
152
|
-
|
|
153
|
-
exit 0
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# parse and execute any command line options
|
|
157
|
-
def parse_opt(args)
|
|
158
|
-
valid_opts = %w[--version -v --install -i --help -h
|
|
159
|
-
--complete -c --bookmark -b --search -s]
|
|
160
|
-
|
|
161
|
-
nextarg = args.shift
|
|
162
|
-
errormsg = "Error: ".red + "unrecognized option #{nextarg}"
|
|
163
|
-
pexit errormsg, 1 if !(valid_opts.include? nextarg)
|
|
164
|
-
|
|
165
|
-
# forced bookmarking
|
|
166
|
-
if nextarg == "--bookmark" || nextarg == "-b"
|
|
167
|
-
if args.first.nil?
|
|
168
|
-
pexit "Error: ".red + "booker --bookmark expects bookmark id", 1
|
|
169
|
-
else
|
|
170
|
-
open_bookmark args
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
# autocompletion
|
|
175
|
-
if nextarg == "--complete" || nextarg == "-c"
|
|
176
|
-
allargs = args.join(" ")
|
|
177
|
-
bm = Bookmarks.new(allargs)
|
|
178
|
-
bm.autocomplete
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# installation
|
|
182
|
-
if nextarg == "--install" || nextarg == "-i"
|
|
183
|
-
if !args.empty?
|
|
184
|
-
install(args)
|
|
185
|
-
else # do everything
|
|
186
|
-
install(%w[completion config bookmarks])
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# forced searching
|
|
191
|
-
if nextarg == "--search" || nextarg == "-s"
|
|
192
|
-
pexit "--search requires an argument", 1 if args.empty?
|
|
193
|
-
allargs = args.join(" ")
|
|
194
|
-
open_search allargs
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
# print version information
|
|
198
|
-
version if nextarg == "--version" || nextarg == "-v"
|
|
199
|
-
|
|
200
|
-
# needs some help
|
|
201
|
-
helper if nextarg == "--help" || nextarg == "-h"
|
|
202
|
-
|
|
203
|
-
exit 0 # dont parse_arg
|
|
204
|
-
end # parse_opt
|
|
205
|
-
|
|
206
|
-
def install(args)
|
|
207
|
-
target = args.shift
|
|
208
|
-
exit 0 if target.nil?
|
|
209
|
-
|
|
210
|
-
if /comp/i.match?(target) # completion installation
|
|
211
|
-
install_completion
|
|
212
|
-
elsif /book/i.match?(target) # bookmarks installation
|
|
213
|
-
install_bookmarks
|
|
214
|
-
elsif /conf/i.match?(target) # default config file generation
|
|
215
|
-
install_config
|
|
216
|
-
else # unknown argument passed into install
|
|
217
|
-
pexit "Failure: ".red + "unknown installation option (#{target})", 1
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
install(args) # recurse til done
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def install_completion
|
|
224
|
-
# check if zsh is even installed for this user
|
|
225
|
-
begin
|
|
226
|
-
fpath = `zsh -c 'echo $fpath'`.split(" ")
|
|
227
|
-
rescue
|
|
228
|
-
pexit "Failure: ".red + "zsh is probably not installed, could not find $fpath", 1
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
# Try user-writable directories first, then system directories
|
|
232
|
-
user_home = ENV["HOME"]
|
|
233
|
-
writable_dirs = fpath.select do |fp|
|
|
234
|
-
fp.start_with?(user_home) && File.directory?(fp) && File.writable?(fp)
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
# If no user-writable directories, try to create one
|
|
238
|
-
if writable_dirs.empty?
|
|
239
|
-
user_completion_dir = File.join(user_home, ".zsh", "completion")
|
|
240
|
-
begin
|
|
241
|
-
FileUtils.mkdir_p(user_completion_dir)
|
|
242
|
-
writable_dirs << user_completion_dir
|
|
243
|
-
puts "Created user completion directory: #{user_completion_dir}".yel
|
|
244
|
-
|
|
245
|
-
# Auto-configure .zshrc if it exists
|
|
246
|
-
zshrc = File.join(user_home, ".zshrc")
|
|
247
|
-
if File.exist?(zshrc)
|
|
248
|
-
zshrc_content = File.read(zshrc)
|
|
249
|
-
if zshrc_content.include?(".zsh/completion")
|
|
250
|
-
puts "~/.zshrc already configured".grn
|
|
251
|
-
else
|
|
252
|
-
File.open(zshrc, "a") do |f|
|
|
253
|
-
f.puts "\n# Booker completion"
|
|
254
|
-
f.puts "fpath=(~/.zsh/completion $fpath)"
|
|
255
|
-
f.puts "autoload -Uz compinit && compinit"
|
|
256
|
-
end
|
|
257
|
-
puts "Added completion to ~/.zshrc".grn
|
|
258
|
-
puts "Run: ".yel + "source ~/.zshrc".cyan + " to activate"
|
|
259
|
-
end
|
|
260
|
-
else
|
|
261
|
-
puts "Add this to your ~/.zshrc: ".yel + "fpath=(~/.zsh/completion $fpath)".cyan
|
|
262
|
-
end
|
|
263
|
-
rescue => e
|
|
264
|
-
# Couldn't create user dir, try system dirs as fallback
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
# Try writable directories first, then all directories as fallback
|
|
269
|
-
dirs_to_try = writable_dirs + fpath.reject { |fp| writable_dirs.include?(fp) }
|
|
270
|
-
|
|
271
|
-
success = false
|
|
272
|
-
dirs_to_try.each do |fp|
|
|
273
|
-
next unless File.directory?(fp)
|
|
274
|
-
|
|
275
|
-
begin
|
|
276
|
-
completion_file = File.join(fp, "_booker")
|
|
277
|
-
File.write(completion_file, COMPLETION)
|
|
278
|
-
system "zsh -c 'autoload -U _booker'"
|
|
279
|
-
puts "Success: ".grn + "installed zsh autocompletion in #{fp}"
|
|
280
|
-
success = true
|
|
281
|
-
break
|
|
282
|
-
rescue => e
|
|
283
|
-
# Try next directory silently
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
unless success
|
|
288
|
-
puts "Warning: ".yel + "Could not install ZSH completion to any directory in $fpath"
|
|
289
|
-
puts "Try manually: ".grn + "mkdir -p ~/.zsh/completion && booker --install completion"
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
def install_bookmarks
|
|
294
|
-
# locate bookmarks file, show user, write to config?
|
|
295
|
-
puts "searching for chrome and firefox bookmarks..."
|
|
296
|
-
begin
|
|
297
|
-
bms = [] # look for bookmarks with type info
|
|
298
|
-
|
|
299
|
-
# Search for Chrome bookmarks
|
|
300
|
-
["Library/Application Support/Google/Chrome",
|
|
301
|
-
"AppData/Local/Google/Chrome/User Data/Default",
|
|
302
|
-
".config/chromium/Default",
|
|
303
|
-
".config/google-chrome/Default",
|
|
304
|
-
"snap/chromium/common/chromium",
|
|
305
|
-
"snap/chromium/current/.config/chromium"].each do |f|
|
|
306
|
-
home = File.join(ENV["HOME"], f)
|
|
307
|
-
next if !FileTest.directory?(home)
|
|
308
|
-
Find.find(home) do |file|
|
|
309
|
-
if /chrom.*bookmarks/i.match?(file)
|
|
310
|
-
bms << {path: file, type: :chrome}
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
# Search for Firefox bookmarks
|
|
316
|
-
firefox_paths = [
|
|
317
|
-
".mozilla/firefox", # Linux
|
|
318
|
-
"snap/firefox/common/.mozilla/firefox", # Linux (snap)
|
|
319
|
-
"Library/Application Support/Firefox", # macOS
|
|
320
|
-
"AppData/Roaming/Mozilla/Firefox" # Windows
|
|
321
|
-
]
|
|
322
|
-
|
|
323
|
-
firefox_paths.each do |f|
|
|
324
|
-
firefox_base = File.join(ENV["HOME"], f)
|
|
325
|
-
next if !FileTest.directory?(firefox_base)
|
|
326
|
-
|
|
327
|
-
profiles_ini = File.join(firefox_base, "profiles.ini")
|
|
328
|
-
next if !File.exist?(profiles_ini)
|
|
329
|
-
|
|
330
|
-
# Parse profiles.ini to find Firefox profiles
|
|
331
|
-
parse_firefox_profiles(profiles_ini, firefox_base).each do |db_path|
|
|
332
|
-
bms << {path: db_path, type: :firefox}
|
|
333
|
-
end
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
if bms.empty? # no bookmarks found
|
|
337
|
-
puts "Failure: ".red + "bookmarks file could not be found."
|
|
338
|
-
raise
|
|
339
|
-
elsif bms.length == 1
|
|
340
|
-
# Auto-select if only one source found
|
|
341
|
-
selected = bms.first[:path]
|
|
342
|
-
type_label = (bms.first[:type] == :chrome) ? "[Chrome]" : "[Firefox]"
|
|
343
|
-
puts "Found bookmark source: #{type_label} #{selected}".yel
|
|
344
|
-
puts "Selected: ".yel + selected
|
|
345
|
-
BConfig.new.write(:bookmarks, selected)
|
|
346
|
-
puts "Success: ".grn + "config file updated with your bookmarks"
|
|
347
|
-
else # have user select a file
|
|
348
|
-
puts "select bookmarks source: "
|
|
349
|
-
|
|
350
|
-
# Offer "ALL" as first option if multiple sources found
|
|
351
|
-
puts "0".grn + " - " + "[ALL SOURCES]".cyan + " (search across all browsers)"
|
|
352
|
-
offset = 1
|
|
353
|
-
|
|
354
|
-
bms.each_with_index do |bm, i|
|
|
355
|
-
type_label = (bm[:type] == :chrome) ? "[Chrome]".yel : "[Firefox]".blu
|
|
356
|
-
puts (i + offset).to_s.grn + " - " + type_label + " " + bm[:path]
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
input = gets
|
|
360
|
-
raise "No input provided" if input.nil?
|
|
361
|
-
selection = input.chomp.to_i
|
|
362
|
-
|
|
363
|
-
if selection == 0
|
|
364
|
-
# User selected "ALL" - save array of all paths
|
|
365
|
-
all_paths = bms.map { |bm| bm[:path] }
|
|
366
|
-
puts "Selected: ".yel + "All sources (#{bms.length} bookmark files)"
|
|
367
|
-
BConfig.new.write(:bookmarks, all_paths)
|
|
368
|
-
puts "Success: ".grn + "config file updated to search all bookmark sources"
|
|
369
|
-
else
|
|
370
|
-
# User selected single source
|
|
371
|
-
actual_index = selection - 1
|
|
372
|
-
selected = bms[actual_index][:path]
|
|
373
|
-
puts "Selected: ".yel + selected
|
|
374
|
-
BConfig.new.write(:bookmarks, selected)
|
|
375
|
-
puts "Success: ".grn + "config file updated with your bookmarks"
|
|
376
|
-
end
|
|
377
|
-
end
|
|
378
|
-
rescue => e
|
|
379
|
-
puts e.message
|
|
380
|
-
pexit "Failure: ".red + "could not add bookmarks to config file ~/.booker", 1
|
|
381
|
-
end
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
def parse_firefox_profiles(ini_path, firefox_base)
|
|
385
|
-
profiles = []
|
|
386
|
-
current_profile = {}
|
|
387
|
-
|
|
388
|
-
File.readlines(ini_path).each do |line|
|
|
389
|
-
line = line.strip
|
|
390
|
-
|
|
391
|
-
# New profile section
|
|
392
|
-
if line.start_with?("[Profile")
|
|
393
|
-
# Save previous profile if it had a path
|
|
394
|
-
if current_profile[:path]
|
|
395
|
-
db_path = File.join(firefox_base, current_profile[:path], "places.sqlite")
|
|
396
|
-
profiles << db_path if File.exist?(db_path)
|
|
397
|
-
end
|
|
398
|
-
current_profile = {}
|
|
399
|
-
|
|
400
|
-
# Parse key=value pairs
|
|
401
|
-
elsif line.include?("=")
|
|
402
|
-
key, value = line.split("=", 2).map(&:strip)
|
|
403
|
-
current_profile[:path] = value if key == "Path"
|
|
404
|
-
current_profile[:name] = value if key == "Name"
|
|
405
|
-
end
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
# Don't forget the last profile
|
|
409
|
-
if current_profile[:path]
|
|
410
|
-
db_path = File.join(firefox_base, current_profile[:path], "places.sqlite")
|
|
411
|
-
profiles << db_path if File.exist?(db_path)
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
profiles
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
def install_config
|
|
418
|
-
BConfig.new.write
|
|
419
|
-
puts "Success: ".grn + "example config file written to ~/.booker"
|
|
420
|
-
rescue
|
|
421
|
-
pexit "Failure: ".red + "could not write example config file to ~/.booker", 1
|
|
422
|
-
end
|
|
423
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# booker - search, browse and open browser bookmarks from the command line
|
|
4
|
+
#
|
|
5
|
+
# Load order matters in one place: Bookmarks::BROWSERS names the parser classes
|
|
6
|
+
# while its class body runs, so parsers has to come first.
|
|
7
|
+
|
|
8
|
+
require_relative "booker/version"
|
|
9
|
+
require_relative "booker/output"
|
|
10
|
+
require_relative "booker/config"
|
|
11
|
+
require_relative "booker/parsers"
|
|
12
|
+
require_relative "booker/bookmarks"
|
|
13
|
+
require_relative "booker/picker"
|
|
14
|
+
require_relative "booker/cli"
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: booker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremy Warner
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: json
|
|
@@ -16,47 +15,55 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '2.
|
|
18
|
+
version: '2.21'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '2.
|
|
25
|
+
version: '2.21'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: sqlite3
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
30
|
- - "~>"
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
32
|
+
version: '2.9'
|
|
33
|
+
- - ">="
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: 2.9.5
|
|
34
36
|
type: :runtime
|
|
35
37
|
prerelease: false
|
|
36
38
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
39
|
requirements:
|
|
38
40
|
- - "~>"
|
|
39
41
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
42
|
+
version: '2.9'
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 2.9.5
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
47
|
+
name: rexml
|
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
|
44
49
|
requirements:
|
|
45
50
|
- - "~>"
|
|
46
51
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '3.
|
|
48
|
-
type: :
|
|
52
|
+
version: '3.4'
|
|
53
|
+
type: :runtime
|
|
49
54
|
prerelease: false
|
|
50
55
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
56
|
requirements:
|
|
52
57
|
- - "~>"
|
|
53
58
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '3.
|
|
59
|
+
version: '3.4'
|
|
55
60
|
description: |2
|
|
56
61
|
Search, browse, and open bookmarks from the command line. Supports Chrome,
|
|
57
|
-
Chromium, and
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
Chromium, Firefox, and Safari. With fzf installed, booker and booker
|
|
63
|
+
<search> open a fuzzy picker over the matches - nothing to install and the
|
|
64
|
+
same in every shell. Zsh, bash, and fish users can also add tab completion
|
|
65
|
+
through bookmark matches. Can open websites directly or search with your
|
|
66
|
+
preferred search engine.
|
|
60
67
|
email: jeremywrnr@gmail.com
|
|
61
68
|
executables:
|
|
62
69
|
- booker
|
|
@@ -64,15 +71,26 @@ extensions: []
|
|
|
64
71
|
extra_rdoc_files: []
|
|
65
72
|
files:
|
|
66
73
|
- bin/booker
|
|
74
|
+
- completions/_booker
|
|
75
|
+
- completions/booker.bash
|
|
76
|
+
- completions/booker.fish
|
|
67
77
|
- lib/booker.rb
|
|
68
|
-
- lib/bookmarks.rb
|
|
69
|
-
- lib/
|
|
70
|
-
- lib/
|
|
71
|
-
|
|
78
|
+
- lib/booker/bookmarks.rb
|
|
79
|
+
- lib/booker/cli.rb
|
|
80
|
+
- lib/booker/config.rb
|
|
81
|
+
- lib/booker/installer.rb
|
|
82
|
+
- lib/booker/output.rb
|
|
83
|
+
- lib/booker/parsers.rb
|
|
84
|
+
- lib/booker/picker.rb
|
|
85
|
+
- lib/booker/version.rb
|
|
86
|
+
homepage: https://github.com/jeremywrnr/booker
|
|
72
87
|
licenses:
|
|
73
88
|
- MIT
|
|
74
|
-
metadata:
|
|
75
|
-
|
|
89
|
+
metadata:
|
|
90
|
+
source_code_uri: https://github.com/jeremywrnr/booker
|
|
91
|
+
bug_tracker_uri: https://github.com/jeremywrnr/booker/issues
|
|
92
|
+
changelog_uri: https://github.com/jeremywrnr/booker/blob/main/CHANGELOG.md
|
|
93
|
+
rubygems_mfa_required: 'true'
|
|
76
94
|
rdoc_options: []
|
|
77
95
|
require_paths:
|
|
78
96
|
- lib
|
|
@@ -80,15 +98,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
80
98
|
requirements:
|
|
81
99
|
- - ">="
|
|
82
100
|
- !ruby/object:Gem::Version
|
|
83
|
-
version: '
|
|
101
|
+
version: '3.2'
|
|
84
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
103
|
requirements:
|
|
86
104
|
- - ">="
|
|
87
105
|
- !ruby/object:Gem::Version
|
|
88
106
|
version: '0'
|
|
89
107
|
requirements: []
|
|
90
|
-
rubygems_version:
|
|
91
|
-
signing_key:
|
|
108
|
+
rubygems_version: 4.0.18
|
|
92
109
|
specification_version: 4
|
|
93
|
-
summary: CLI bookmark manager for Chrome and
|
|
110
|
+
summary: CLI bookmark manager for Chrome, Firefox, and Safari
|
|
94
111
|
test_files: []
|