pincerna 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +77 -0
- data/.travis-gemfile +17 -0
- data/.travis.yml +7 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +23 -0
- data/LICENSE.md +21 -0
- data/README.md +211 -0
- data/Rakefile +45 -0
- data/bin/pincernad +56 -0
- data/docs/Pincerna.html +130 -0
- data/docs/Pincerna/Base.html +3051 -0
- data/docs/Pincerna/Bookmark.html +523 -0
- data/docs/Pincerna/Cache.html +767 -0
- data/docs/Pincerna/ChromeBookmark.html +308 -0
- data/docs/Pincerna/CurrencyConversion.html +589 -0
- data/docs/Pincerna/FirefoxBookmark.html +328 -0
- data/docs/Pincerna/Ip.html +1017 -0
- data/docs/Pincerna/Map.html +399 -0
- data/docs/Pincerna/SafariBookmark.html +308 -0
- data/docs/Pincerna/Server.html +673 -0
- data/docs/Pincerna/Translation.html +517 -0
- data/docs/Pincerna/UnitConversion.html +1042 -0
- data/docs/Pincerna/Version.html +189 -0
- data/docs/Pincerna/Vpn.html +561 -0
- data/docs/Pincerna/Weather.html +837 -0
- data/docs/_index.html +298 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +57 -0
- data/docs/css/style.css +338 -0
- data/docs/file.README.html +327 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +28 -0
- data/docs/index.html +327 -0
- data/docs/js/app.js +214 -0
- data/docs/js/full_list.js +178 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +389 -0
- data/docs/top-level-namespace.html +112 -0
- data/icon.png +0 -0
- data/images/chrome.png +0 -0
- data/images/currency.png +0 -0
- data/images/firefox.png +0 -0
- data/images/map.png +0 -0
- data/images/network.png +0 -0
- data/images/safari.png +0 -0
- data/images/translate.png +0 -0
- data/images/unit.png +0 -0
- data/images/vpn.png +0 -0
- data/images/weather.png +0 -0
- data/info.plist +961 -0
- data/it.cowtech.pincernad.plist +19 -0
- data/lib/pincerna.rb +30 -0
- data/lib/pincerna/base.rb +258 -0
- data/lib/pincerna/bookmark.rb +80 -0
- data/lib/pincerna/cache.rb +61 -0
- data/lib/pincerna/chrome_bookmark.rb +40 -0
- data/lib/pincerna/currency_conversion.rb +134 -0
- data/lib/pincerna/firefox_bookmark.rb +92 -0
- data/lib/pincerna/ip.rb +135 -0
- data/lib/pincerna/map.rb +30 -0
- data/lib/pincerna/safari_bookmark.rb +40 -0
- data/lib/pincerna/server.rb +85 -0
- data/lib/pincerna/translation.rb +67 -0
- data/lib/pincerna/unit_conversion.rb +120 -0
- data/lib/pincerna/version.rb +24 -0
- data/lib/pincerna/vpn.rb +74 -0
- data/lib/pincerna/weather.rb +188 -0
- data/pincerna.alfredworkflow +0 -0
- data/pincerna.gemspec +36 -0
- data/pincerna.sh +9 -0
- data/spec/cassettes/Pincerna_CurrencyConversion/_perform_filtering/should_return_valid_values.yml +38 -0
- data/spec/cassettes/Pincerna_Ip/_get_local_addresses/should_return_a_list_of_addresses.yml +47 -0
- data/spec/cassettes/Pincerna_Ip/_get_public_address/should_return_public_IP_address.yml +44 -0
- data/spec/cassettes/Pincerna_Translation/_perform_filtering/should_default_from_English_to_the_given_language_when_only_one_is_present.yml +124 -0
- data/spec/cassettes/Pincerna_Translation/_perform_filtering/should_query_Google_Translate_for_sentences_returning_no_alternatives.yml +51 -0
- data/spec/cassettes/Pincerna_Translation/_perform_filtering/should_query_Google_Translate_for_single_words.yml +71 -0
- data/spec/cassettes/Pincerna_Weather/_get_forecast/should_append_name.yml +177 -0
- data/spec/cassettes/Pincerna_Weather/_get_forecast/should_get_correct_forecasts.yml +339 -0
- data/spec/cassettes/Pincerna_Weather/_lookup_places/should_return_an_existing_WOEID_without_making_any_request.yml +56 -0
- data/spec/cassettes/Pincerna_Weather/_lookup_places/should_search_for_places.yml +189 -0
- data/spec/cassettes/Pincerna_Weather/_perform_filtering/should_get_forecast.yml +56 -0
- data/spec/coverage_helper.rb +44 -0
- data/spec/pincerna/base_spec.rb +166 -0
- data/spec/pincerna/bookmark_spec.rb +65 -0
- data/spec/pincerna/cache_spec.rb +88 -0
- data/spec/pincerna/chrome_bookmark_spec.rb +114 -0
- data/spec/pincerna/currency_conversion_spec.rb +46 -0
- data/spec/pincerna/firefox_bookmark_spec.rb +46 -0
- data/spec/pincerna/ip_spec.rb +194 -0
- data/spec/pincerna/map_spec.rb +24 -0
- data/spec/pincerna/safari_bookmark_spec.rb +237 -0
- data/spec/pincerna/server_spec.rb +108 -0
- data/spec/pincerna/translation_spec.rb +55 -0
- data/spec/pincerna/unit_conversion_spec.rb +98 -0
- data/spec/pincerna/vpn_spec.rb +68 -0
- data/spec/pincerna/weather_spec.rb +131 -0
- data/spec/spec_helper.rb +48 -0
- metadata +283 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Pincerna
|
8
|
+
# Show the list of Chrome bookmarks.
|
9
|
+
class ChromeBookmark < Bookmark
|
10
|
+
# The icon to show for each feedback item.
|
11
|
+
ICON = Pincerna::Base::ROOT + "/images/chrome.png"
|
12
|
+
|
13
|
+
# The location of the bookmarks data
|
14
|
+
BOOKMARKS_DATA = File.expand_path("~/Library/Application Support/Google/Chrome/Default/Bookmarks")
|
15
|
+
|
16
|
+
# Reads the list of Chrome Bookmarks.
|
17
|
+
def read_bookmarks
|
18
|
+
data = File.read(BOOKMARKS_DATA) rescue nil
|
19
|
+
|
20
|
+
if data then
|
21
|
+
Oj.load(data)["roots"].each do |_, root|
|
22
|
+
scan_folder(root, "") if root.is_a?(Hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
# Scans a folder of bookmarks.
|
29
|
+
#
|
30
|
+
# @param node [Hash] The directory to visit.
|
31
|
+
# @param path [String] The path of this node.
|
32
|
+
def scan_folder(node, path)
|
33
|
+
path += " #{SEPARATOR} #{node["name"]}"
|
34
|
+
|
35
|
+
node["children"].each do |children|
|
36
|
+
children["type"] == "url" ? add_bookmark(children["name"], children["url"], path) : scan_folder(children, path)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Pincerna
|
8
|
+
# Converts a value from a currency to another.
|
9
|
+
class CurrencyConversion < Base
|
10
|
+
# The expression to match.
|
11
|
+
MATCHER = /^
|
12
|
+
(?<value>([+-]?)(\d+)([.,]\d+)?)
|
13
|
+
\s
|
14
|
+
(?<from>\S{1,3})
|
15
|
+
\s+
|
16
|
+
(to\s+)?
|
17
|
+
(?<to>\S{1,3})
|
18
|
+
(?<rate>\swith\srate)?
|
19
|
+
$/mix
|
20
|
+
|
21
|
+
# Relevant groups in the match.
|
22
|
+
RELEVANT_MATCHES = {
|
23
|
+
"value" => ->(context, value){ context.round_float(value.gsub(",", ".").to_f) },
|
24
|
+
"from" => ->(_, value) { value.upcase },
|
25
|
+
"to" => ->(_, value) { value.upcase },
|
26
|
+
"rate" => ->(_, value) { !value.nil? } # If show conversion rate
|
27
|
+
}
|
28
|
+
|
29
|
+
# The icon to show for each feedback item.
|
30
|
+
ICON = Pincerna::Base::ROOT + "/images/currency.png"
|
31
|
+
|
32
|
+
# The URL of the webservice.
|
33
|
+
URL = "http://rate-exchange.appspot.com/currency"
|
34
|
+
|
35
|
+
# A list of symbols and their associated ISO codes
|
36
|
+
SYMBOLS = {
|
37
|
+
"Lek" => "ALL",
|
38
|
+
"؋" => "AFN",
|
39
|
+
"$" => "USD",
|
40
|
+
"ƒ" => "ANG",
|
41
|
+
"ман" => "AZN",
|
42
|
+
"p." => "BYR",
|
43
|
+
"BZ$" => "BZD",
|
44
|
+
"$b" => "BOB",
|
45
|
+
"KM" => "BAM",
|
46
|
+
"P" => "BWP",
|
47
|
+
"лв" => "UZS",
|
48
|
+
"R$" => "BRL",
|
49
|
+
"៛" => "KHR",
|
50
|
+
"¥" => "JPY",
|
51
|
+
"₡" => "CRC",
|
52
|
+
"kn" => "HRK",
|
53
|
+
"₱" => "PHP",
|
54
|
+
"Kč" => "CZK",
|
55
|
+
"kr" => "SEK",
|
56
|
+
"RD$" => "DOP",
|
57
|
+
"£" => "GBP",
|
58
|
+
"€" => "EUR",
|
59
|
+
"¢" => "GHC",
|
60
|
+
"Q" => "GTQ",
|
61
|
+
"L" => "HNL",
|
62
|
+
"Ft" => "HUF",
|
63
|
+
"" => "TRY",
|
64
|
+
"Rp" => "IDR",
|
65
|
+
"﷼" => "YER",
|
66
|
+
"₪" => "ILS",
|
67
|
+
"J$" => "JMD",
|
68
|
+
"₩" => "KRW",
|
69
|
+
"₭" => "LAK",
|
70
|
+
"Ls" => "LVL",
|
71
|
+
"Lt" => "LTL",
|
72
|
+
"ден" => "MKD",
|
73
|
+
"RM" => "MYR",
|
74
|
+
"₨" => "LKR",
|
75
|
+
"₮" => "MNT",
|
76
|
+
"MT" => "MZN",
|
77
|
+
"C$" => "NIO",
|
78
|
+
"₦" => "NGN",
|
79
|
+
"B/." => "PAB",
|
80
|
+
"Gs" => "PYG",
|
81
|
+
"S/." => "PEN",
|
82
|
+
"zł" => "PLN",
|
83
|
+
"lei" => "RON",
|
84
|
+
"руб" => "RUB",
|
85
|
+
"Дин." => "RSD",
|
86
|
+
"S" => "SOS",
|
87
|
+
"R" => "ZAR",
|
88
|
+
"CHF" => "CHF",
|
89
|
+
"NT$" => "TWD",
|
90
|
+
"฿" => "THB",
|
91
|
+
"TT$" => "TTD",
|
92
|
+
"₤" => "TRL",
|
93
|
+
"₴" => "UAH",
|
94
|
+
"$U" => "UYU",
|
95
|
+
"Bs" => "VEF",
|
96
|
+
"₫" => "VND",
|
97
|
+
"Z$" => "ZWD"
|
98
|
+
}
|
99
|
+
|
100
|
+
# Converts a value from a currency to another.
|
101
|
+
#
|
102
|
+
# @param value [Float] The value to convert.
|
103
|
+
# @param from [String] The origin currency.
|
104
|
+
# @param to [String] The target currency.
|
105
|
+
# @param with_rate [Boolean] If to return the conversion rate in the results.
|
106
|
+
# @return [Hash|NilClass] The converted data or `nil` if the conversion failed.
|
107
|
+
def perform_filtering(value, from, to, with_rate)
|
108
|
+
from = replace_symbol(from)
|
109
|
+
to = replace_symbol(to)
|
110
|
+
response = fetch_remote_resource(URL, {q: value, from: from, to: to})
|
111
|
+
{value: value, from: from, to: to, result: round_float(response["v"]), rate: round_float(response["rate"]), with_rate: with_rate}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Processes items to obtain feedback items.
|
115
|
+
#
|
116
|
+
# @param results [Hash] The item to process.
|
117
|
+
# @return [Array] The feedback items.
|
118
|
+
def process_results(results)
|
119
|
+
title = "%s %s = %s %s" % [format_float(results[:value]), results[:from], format_float(results[:result]), results[:to]]
|
120
|
+
title << " (1 %s = %s %s)" % [results[:from], format_float(results[:rate]), results[:to]] if results[:with_rate]
|
121
|
+
|
122
|
+
[{title: title, arg: format_float(results[:value]), subtitle: "Action this item to copy the converted amount on the clipboard.", icon: self.class::ICON}]
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
# Replaces a currency symbol with its corresponding ISO code.
|
127
|
+
#
|
128
|
+
# @param symbol [String] The symbol to replace.
|
129
|
+
# @return [String] The corresponding code. If none is found, the original symbol is returned.
|
130
|
+
def replace_symbol(symbol)
|
131
|
+
SYMBOLS.fetch(symbol, symbol)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Pincerna
|
8
|
+
# Show the list of Firefox bookmarks.
|
9
|
+
class FirefoxBookmark < Bookmark
|
10
|
+
# The icon to show for each feedback item.
|
11
|
+
ICON = Pincerna::Base::ROOT + "/images/firefox.png"
|
12
|
+
|
13
|
+
# A wildcard to searc the default profile
|
14
|
+
PROFILES_SEARCH = File.expand_path("~/Library/Application Support/Firefox/Profiles/*.default")
|
15
|
+
|
16
|
+
# The queries to obtain the bookmarks
|
17
|
+
QUERIES = [
|
18
|
+
"SELECT b.title, p.url, b.parent FROM moz_bookmarks b, moz_places p WHERE b.type=1 AND b.fk=p.id",
|
19
|
+
"SELECT b.title, b.id, b.parent FROM moz_bookmarks b WHERE b.type=2"
|
20
|
+
]
|
21
|
+
|
22
|
+
# Reads the list of Firefox Bookmarks.
|
23
|
+
def read_bookmarks
|
24
|
+
path = Dir.glob(PROFILES_SEARCH).first
|
25
|
+
data = execute_command("/usr/bin/sqlite3", "-echo", "#{path}/places.sqlite", QUERIES.join("; "))
|
26
|
+
|
27
|
+
if data && !data.empty? then
|
28
|
+
@folders = {}
|
29
|
+
parse_bookmarks_data(data)
|
30
|
+
build_paths
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
# Parses bookmarks data.
|
36
|
+
#
|
37
|
+
# @param data [String] The data to parse.
|
38
|
+
def parse_bookmarks_data(data)
|
39
|
+
data = StringScanner.new(data)
|
40
|
+
data.skip_until(/\n/) # Discard the first line
|
41
|
+
|
42
|
+
# While we're still in the first query, look for bookmarks
|
43
|
+
while data.exist?(/#{QUERIES.last}/) do
|
44
|
+
line = data.scan_until(/\n/).strip
|
45
|
+
break if line == QUERIES.last
|
46
|
+
add_bookmark(*restrict_array(line.split("|"), 3))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Now look for folder
|
50
|
+
while !data.eos? do
|
51
|
+
line = data.scan_until(/\n/).strip
|
52
|
+
add_folder(*restrict_array(line.split("|"), 3))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Builds the paths of the bookmarks.
|
57
|
+
def build_paths
|
58
|
+
@bookmarks.map! do |bookmark|
|
59
|
+
bookmark[:path] = " #{SEPARATOR} #{build_path(bookmark[:path].to_i).reverse.join(" #{SEPARATOR} ")}"
|
60
|
+
bookmark
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Builds the full path of a folder.
|
65
|
+
#
|
66
|
+
# @param id [Fixnum] The id of the folder.
|
67
|
+
# @return [String] The path of the folder.
|
68
|
+
def build_path(id)
|
69
|
+
folder = @folders[id]
|
70
|
+
folder ? [folder[0]] + build_path(folder[1]).compact : []
|
71
|
+
end
|
72
|
+
|
73
|
+
# Adds a folder to the list.
|
74
|
+
#
|
75
|
+
# @param title [String] The name of the folder.
|
76
|
+
# @param id [String] The id of the folder.
|
77
|
+
# @param parent [String] The id of the parent folder.
|
78
|
+
def add_folder(title, id, parent)
|
79
|
+
@folders[id.to_i] = [title, parent.to_i] if !title.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
# Restrict array making sure it does not exceed a length.
|
83
|
+
#
|
84
|
+
# @param array [Array] The array to restrict.
|
85
|
+
# @param len [Fixnum] The maximum allowed length.
|
86
|
+
# @return [Array] The restricted array.
|
87
|
+
def restrict_array(array, len)
|
88
|
+
array[0] = "#{array.shift}|#{array[0]}" while array.length > len
|
89
|
+
array
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/pincerna/ip.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Pincerna
|
8
|
+
# Shows the IP addresses of all network interfaces.
|
9
|
+
class Ip < Base
|
10
|
+
# The expression to match.
|
11
|
+
MATCHER = /^(?<all>.*)$/i
|
12
|
+
|
13
|
+
# The icon to show for each feedback item.
|
14
|
+
ICON = Pincerna::Base::ROOT + "/images/network.png"
|
15
|
+
|
16
|
+
# The URL of the webservice.
|
17
|
+
URL = "http://api.externalip.net/ip"
|
18
|
+
|
19
|
+
# Shows the IP addresses of all network interfaces.
|
20
|
+
#
|
21
|
+
# @param query [Array] A query to match against interfaces names.
|
22
|
+
# @return [Array] A list of items to process.
|
23
|
+
def perform_filtering(query)
|
24
|
+
@interface_filter ||= query.empty? ? /.*/ : /#{query}/i
|
25
|
+
|
26
|
+
# Get local addresses
|
27
|
+
rv = get_local_addresses
|
28
|
+
|
29
|
+
# Sort interfaces and address, IPv4 first then IPv6
|
30
|
+
rv.sort! {|left, right|
|
31
|
+
cmp = left[:interface] <=> right[:interface] # Interface name first
|
32
|
+
cmp = compare_ip_classes(left[:address], right[:address]) if cmp == 0 # Now IPv4 first then IPv6
|
33
|
+
cmp = compare_ip_addresses(left[:address], right[:address]) if cmp == 0 # Finally addresses
|
34
|
+
cmp
|
35
|
+
}
|
36
|
+
|
37
|
+
# Add public address
|
38
|
+
rv = rv.insert(0, get_public_address) if @interface_filter.match("public")
|
39
|
+
|
40
|
+
rv
|
41
|
+
end
|
42
|
+
|
43
|
+
# Processes items to obtain feedback items.
|
44
|
+
#
|
45
|
+
# @param results [Array] The items to process.
|
46
|
+
# @return [Array] The feedback items.
|
47
|
+
def process_results(results)
|
48
|
+
results.map do |result|
|
49
|
+
title = "#{result[:interface] ? result[:interface] : "Public"} IP: #{result[:address]}"
|
50
|
+
{title: title, arg: result[:address], subtitle: "Action this item to copy the IP on the clipboard.", icon: ICON}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Gets a list of local IP addresses.
|
55
|
+
#
|
56
|
+
# @return [Array] A list of IPs data.
|
57
|
+
def get_local_addresses
|
58
|
+
rv = []
|
59
|
+
names = get_interfaces_names
|
60
|
+
|
61
|
+
# Split by interfaces
|
62
|
+
interfaces = execute_command("/sbin/ifconfig").split(/(^\S+:\s+)/)
|
63
|
+
interfaces.shift # Discard first whitespace
|
64
|
+
|
65
|
+
# For each interface
|
66
|
+
interfaces.each_slice(2) do |interface, configuration|
|
67
|
+
# See if matches the query and then replace public name
|
68
|
+
interface = interface.gsub(/\s*(.+):\s*/, "\\1")
|
69
|
+
name = names[interface] ? "#{names[interface]} (#{interface})" : interface
|
70
|
+
next if !@interface_filter.match(name)
|
71
|
+
|
72
|
+
# Get addresses
|
73
|
+
addresses = StringScanner.new(configuration)
|
74
|
+
while addresses.scan_until(/inet(6?)\s/) do
|
75
|
+
rv << {interface: name, address: addresses.scan(/\S+/)}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
rv
|
80
|
+
end
|
81
|
+
|
82
|
+
# Gets the public IP address for this machine.
|
83
|
+
#
|
84
|
+
# @return [Hash] The public IP address data.
|
85
|
+
def get_public_address
|
86
|
+
{interface: nil, address: fetch_remote_resource(URL, {}, false)}
|
87
|
+
end
|
88
|
+
|
89
|
+
# Compares two IP classes, giving higher priority to IPv4.
|
90
|
+
#
|
91
|
+
# @param left [String] The first IP to compare.
|
92
|
+
# @param right [String] The second IP to compare.
|
93
|
+
# @return [Fixnum] The result of the comparison.
|
94
|
+
def compare_ip_classes(left, right)
|
95
|
+
(left.index(":") ? 1 : 0) <=> (right.index(":") ? 1 : 0)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Compares to IP addresses, giving higher priority to local address such as 127.0.0.1.
|
99
|
+
#
|
100
|
+
# @param left [String] The first IP to compare.
|
101
|
+
# @param right [String] The second IP to compare.
|
102
|
+
# @return [Fixnum] The result of the comparison.
|
103
|
+
def compare_ip_addresses(left, right)
|
104
|
+
higher_priority = ["::1", "127.0.0.1", "10.0.0.1"]
|
105
|
+
cmp = (higher_priority.include?(left) ? 0 : 1) <=> (higher_priority.include?(right) ? 0 : 1)
|
106
|
+
cmp = left <=> right if cmp == 0
|
107
|
+
cmp
|
108
|
+
end
|
109
|
+
|
110
|
+
# Gets a hash with pair of interfaces and their human names.
|
111
|
+
#
|
112
|
+
# @return [Hash] The hash with interfaces' name.
|
113
|
+
def get_interfaces_names
|
114
|
+
rv = {"lo0" => "Loopback"}
|
115
|
+
|
116
|
+
names = execute_command("/usr/sbin/networksetup", "-listallhardwareports").split(/\n\n/)
|
117
|
+
names.shift # Discard first whitespace
|
118
|
+
|
119
|
+
names.each do |port|
|
120
|
+
port = StringScanner.new(port)
|
121
|
+
name = nil
|
122
|
+
interface = nil
|
123
|
+
|
124
|
+
if port.scan_until(/Hardware Port: /) then
|
125
|
+
name = port.scan_until(/\n/).strip
|
126
|
+
interface = port.scan_until(/\n/).strip if port.scan_until(/Device: /)
|
127
|
+
end
|
128
|
+
|
129
|
+
rv[interface] = name if name && interface
|
130
|
+
end
|
131
|
+
|
132
|
+
rv
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/pincerna/map.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Pincerna
|
8
|
+
# Shows addresses or coordinates on Google Maps.
|
9
|
+
class Map < Base
|
10
|
+
# The icon to show for each feedback item.
|
11
|
+
ICON = Pincerna::Base::ROOT + "/images/map.png"
|
12
|
+
|
13
|
+
# Filters a query.
|
14
|
+
#
|
15
|
+
# @param query [String] An address to show on Google Maps.
|
16
|
+
# @return [Array] A list of items to process.
|
17
|
+
def perform_filtering(query)
|
18
|
+
{query: query}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Processes items to obtain feedback items.
|
22
|
+
#
|
23
|
+
# @param results [Array] The items to process.
|
24
|
+
# @return [Array] The feedback items.
|
25
|
+
def process_results(results)
|
26
|
+
type = results[:query] =~ /((-?)\d+(\.\d+)?)\s*,\s*((-?)\d+(\.\d+)?)/ ? "coordinates" : "location"
|
27
|
+
[{title: "View #{type} on Google Maps", arg: CGI.escape(results[:query]), subtitle: "Action this item to open Google Maps in the browser.", icon: ICON}]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Pincerna
|
8
|
+
# Show the list of Safari bookmarks.
|
9
|
+
class SafariBookmark < Bookmark
|
10
|
+
# The icon to show for each feedback item.
|
11
|
+
ICON = Pincerna::Base::ROOT + "/images/safari.png"
|
12
|
+
|
13
|
+
# The file with bookmarks data.
|
14
|
+
BOOKMARKS_DATA = File.expand_path("~/Library/Safari/Bookmarks.plist")
|
15
|
+
|
16
|
+
# Reads the list of Safari Bookmarks.
|
17
|
+
def read_bookmarks
|
18
|
+
data = execute_command("/usr/bin/plutil", "-convert", "xml1", "-o", "-", BOOKMARKS_DATA)
|
19
|
+
|
20
|
+
if data && !data.empty? then
|
21
|
+
Plist.parse_xml(data)["Children"].each do |children|
|
22
|
+
scan_folder(children, "")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
# Scans a folder of bookmarks.
|
29
|
+
#
|
30
|
+
# @param node [Hash] The directory to visit.
|
31
|
+
# @param path [String] The path of this node.
|
32
|
+
def scan_folder(node, path)
|
33
|
+
path += " #{SEPARATOR} #{node["Title"]}"
|
34
|
+
|
35
|
+
(node["Children"] || []).each do |children|
|
36
|
+
children["WebBookmarkType"] == "WebBookmarkTypeLeaf" ? add_bookmark(children["URIDictionary"]["title"], children["URLString"], path) : scan_folder(children, path)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|