Class: Booker::Bookmarks
- Inherits:
-
Object
- Object
- Booker::Bookmarks
- Defined in:
- lib/booker/bookmarks.rb
Overview
Main Bookmarks facade class
Constant Summary collapse
- BROWSERS =
one row per browser: everything booker knows about a bookmark source lives here, so a fourth browser is an entry rather than a hunt through the parser lookup, the installer's labels and its colors. chrome's file has no extension, so it is the fallback rather than a row to match on
{ firefox: {parser: Parsers::Firefox, ext: ".sqlite", label: "[Firefox]", color: :blu}, safari: {parser: Parsers::Safari, ext: ".plist", label: "[Safari]", color: :cyan}, chrome: {parser: Parsers::Chrome, ext: nil, label: "[Chrome]", color: :yel} }.freeze
Instance Attribute Summary collapse
-
#allurls ⇒ Object
readonly
Returns the value of attribute allurls.
Class Method Summary collapse
-
.source_for(path) ⇒ Object
which browser wrote this file, by name.
Instance Method Summary collapse
-
#autocomplete ⇒ Object
output for zsh autocompetion, print out id, title and cleaned url.
-
#autocomplete_raw ⇒ Object
machine readable feed for the shell completion scripts.
-
#bookmark_url(id) ⇒ Object
get link (from id number).
-
#clean_link(url) ⇒ Object
clean link for completion, remove strange things from any linkurls.
-
#clean_name(url) ⇒ Object
clean title for completion, delete anything not allowed in linktitle.
-
#display_name(url) ⇒ Object
"[source] folder | title", with no width applied.
-
#initialize(search_term = "") ⇒ Bookmarks
constructor
A new instance of Bookmarks.
-
#rows ⇒ Object
one tab separated id/title/url triple per bookmark, shared by the shell completion feed and the picker.
Constructor Details
#initialize(search_term = "") ⇒ Bookmarks
Returns a new instance of Bookmarks.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/booker/bookmarks.rb', line 33 def initialize(search_term = "") @conf = Config.default @allurls = [] seen = Set.new # stat each configured path once, not once to count them and again to # read them. the index is kept: it is the source half of every id sources = @conf.bookmarks.each_with_index.select { |p, _| p && File.exist?(p) } @multi_source = sources.length > 1 sources.each do |file_path, source_index| source = self.class.source_for(file_path) parser = BROWSERS.fetch(source)[:parser].new(file_path, search_term) parser.parse parser.results.each do |bookmark| # add? is nil when the key was already there, so the dedupe check and # the record of having seen it are the same call next unless seen.add?([bookmark.title, bookmark.url]) @allurls << Bookmark.new( folder: bookmark.folder, title: bookmark.title, url: bookmark.url, id: "#{source_index}_#{bookmark.id}", source: source ) end end end |
Instance Attribute Details
#allurls ⇒ Object (readonly)
Returns the value of attribute allurls.
31 32 33 |
# File 'lib/booker/bookmarks.rb', line 31 def allurls @allurls end |
Class Method Details
.source_for(path) ⇒ Object
which browser wrote this file, by name. the installer labels sources with it and the parse loop below picks a parser with it, so the two can never disagree about what a path is
27 28 29 |
# File 'lib/booker/bookmarks.rb', line 27 def self.source_for(path) BROWSERS.find { |_, b| b[:ext] && path&.end_with?(b[:ext]) }&.first || :chrome end |
Instance Method Details
#autocomplete ⇒ Object
output for zsh autocompetion, print out id, title and cleaned url
65 66 67 68 69 70 71 |
# File 'lib/booker/bookmarks.rb', line 65 def autocomplete @allurls.each do |url| name = clean_name(url) link = clean_link(url) puts url.id + ":" + name + ":" + link end end |
#autocomplete_raw ⇒ Object
machine readable feed for the shell completion scripts
86 87 88 |
# File 'lib/booker/bookmarks.rb', line 86 def autocomplete_raw rows.each { |row| puts row } end |
#bookmark_url(id) ⇒ Object
get link (from id number). #each returned @allurls itself when nothing matched, so a bad id reached open_bookmark as an Array and blew up with a TypeError instead of the "bookmark not found" message
122 123 124 |
# File 'lib/booker/bookmarks.rb', line 122 def bookmark_url(id) @allurls.find { |url| id == url.id }&.url end |
#clean_link(url) ⇒ Object
clean link for completion, remove strange things from any linkurls
110 111 112 113 114 115 116 117 |
# File 'lib/booker/bookmarks.rb', line 110 def clean_link(url) link = url.url.gsub(/[,'"&?].*/, "") link.gsub!(/.*:\/+/, "") link.delete!(" ") # Use half terminal width for URL max_width = (Term.width / 2 - CODEWIDTH).clamp(..50) link[0..max_width] end |
#clean_name(url) ⇒ Object
clean title for completion, delete anything not allowed in linktitle
91 92 93 94 |
# File 'lib/booker/bookmarks.rb', line 91 def clean_name(url) # Use half terminal width for name to leave room for URL display_name(url).window((Term.width / 2).clamp(..50)) end |
#display_name(url) ⇒ Object
"[source] folder | title", with no width applied
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/booker/bookmarks.rb', line 97 def display_name(url) # Format: [source] folder | title (source only when multi-source) prefix = (@multi_source && url.source) ? "[#{url.source}] " : "" name = prefix + url.display_folder + " | " + url.title.gsub(/[^a-z0-9\-\/_ ]/i, "") name.squeeze!("-") name.squeeze!(" ") # a top level bookmark has no folder text, which would otherwise leave a # leading space - invisible in the padded #clean_name output, but not in # the raw feed the completion scripts read name.strip end |
#rows ⇒ Object
one tab separated id/title/url triple per bookmark, shared by the shell
completion feed and the picker. never truncated or padded, unlike
#autocomplete: tput cols is unreliable in a completion subshell and a
truncated url opens a broken link. tabs and newlines go from every field,
not just the url - one surviving in a folder name splits that bookmark
into two candidates the picker offers separately, neither openable
79 80 81 82 83 |
# File 'lib/booker/bookmarks.rb', line 79 def rows @allurls.map do |url| [url.id, display_name(url), url.url].map { |f| f.to_s.delete("\t\n") }.join("\t") end end |